2024-10-13 08:38:11 +00:00
|
|
|
# Defines
|
|
|
|
define wardrobe.outfit_schedule = ("day", "night", "cloudy", "rainy", "snowy")
|
|
|
|
define wardrobe.subcategories = {
|
2022-05-16 23:48:22 +00:00
|
|
|
"hair": 5, "shirts": 5, "skirts": 5, "pantyhose": 5, "slot1": 5, "panties": 5, "save": 5,
|
|
|
|
"earrings": 4, "sweaters": 4, "trousers": 4, "stockings": 4, "bikini panties": 4, "load": 4,
|
|
|
|
"neckwear": 3, "dresses": 3, "shorts": 3, "socks": 3, "schedule": 3,
|
|
|
|
"one-piece suits": 2, "import": 2,
|
|
|
|
"robes": 1, "export": 1,
|
|
|
|
"gloves": 0, "pubes": 0, "delete": 0,
|
|
|
|
"other": -1,
|
|
|
|
}
|
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
# Settings
|
2024-10-18 19:29:04 +00:00
|
|
|
default wardrobe.music = True
|
2024-10-13 08:38:11 +00:00
|
|
|
default wardrobe.chitchats = True
|
|
|
|
default wardrobe.autosave = False
|
|
|
|
default wardrobe.suppress_warnings = False
|
|
|
|
default wardrobe.randomize_color = False
|
|
|
|
default wardrobe.global_color = False
|
2024-10-18 19:29:04 +00:00
|
|
|
default wardrobe.allow_opacity = False
|
2023-07-11 21:57:49 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
# Functions
|
|
|
|
init python in wardrobe:
|
2024-10-29 14:06:38 +00:00
|
|
|
import functools
|
2024-11-06 21:13:12 +00:00
|
|
|
import os
|
2024-10-13 08:38:11 +00:00
|
|
|
from collections import OrderedDict
|
2023-07-11 21:57:49 +00:00
|
|
|
|
2024-10-18 19:29:04 +00:00
|
|
|
_last_track = None
|
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
def get_subcategories(d):
|
|
|
|
return OrderedDict(
|
2023-07-13 23:59:26 +00:00
|
|
|
sorted(
|
|
|
|
[
|
|
|
|
(subcat, [item for item in items if item.unlocked])
|
2024-10-13 08:38:11 +00:00
|
|
|
for subcat, items in subcategories.get(d, {}).items()
|
2023-07-13 23:59:26 +00:00
|
|
|
],
|
2024-10-13 08:38:11 +00:00
|
|
|
key=lambda x: subcategories.get(x[0], 0),
|
2023-07-13 23:59:26 +00:00
|
|
|
reverse=True
|
|
|
|
)
|
|
|
|
)
|
2023-02-10 23:12:16 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
def get_icon(category):
|
|
|
|
fp = f"gui/creamy_pumpkin_pie/icons/{category}.png"
|
|
|
|
if renpy.loadable(fp):
|
|
|
|
return renpy.store.Image(fp, oversample=4)
|
|
|
|
return renpy.store.Image("gui/creamy_pumpkin_pie/icons/noicon.png", oversample=4)
|
|
|
|
|
2024-10-18 19:29:04 +00:00
|
|
|
def change_section(section):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
2024-10-29 11:57:39 +00:00
|
|
|
character = scope["character"]
|
2024-10-18 19:29:04 +00:00
|
|
|
if scope["selected_section"] == section:
|
|
|
|
return
|
|
|
|
scope["selected_section"] = section
|
2024-10-29 11:57:39 +00:00
|
|
|
|
|
|
|
if section == "outfits":
|
2024-11-06 21:13:12 +00:00
|
|
|
scope["selected_item"] = None
|
|
|
|
import_outfits()
|
|
|
|
if section == "clothing":
|
2024-10-29 11:57:39 +00:00
|
|
|
scope["selected_category"] = "head"
|
|
|
|
scope["selected_subcategory"] = "hair"
|
|
|
|
scope["selected_item"] = None
|
|
|
|
elif section == "color_picker":
|
|
|
|
scope["selected_item"] = next((item[0] for item in character.states.values() if item[0]), None)
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
def change_category(category):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
2024-11-07 08:44:09 +00:00
|
|
|
character = scope["character"]
|
2024-10-18 19:29:04 +00:00
|
|
|
if scope["selected_category"] == category:
|
|
|
|
return
|
|
|
|
scope["selected_category"] = category
|
2024-11-07 08:44:09 +00:00
|
|
|
scope["selected_subcategory"] = next((subcat for subcat in character.wardrobe[category]), None)
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
def change_subcategory(subcategory):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
if scope["selected_subcategory"] == subcategory:
|
|
|
|
return
|
|
|
|
scope["selected_subcategory"] = subcategory
|
|
|
|
|
|
|
|
def change_item(item):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
scope["selected_layer"] = 0
|
|
|
|
scope["layers"] = item.color
|
|
|
|
scope["selected_item"] = item
|
|
|
|
|
|
|
|
renpy.store.colorpicker.set_layer(item, 0)
|
|
|
|
|
|
|
|
renpy.restart_interaction()
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
def jump_to_item(item, section="clothing"):
|
2024-10-29 11:57:39 +00:00
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
cat, subcat = item.categories
|
|
|
|
scope["selected_section"] = section
|
|
|
|
scope["selected_category"] = cat
|
|
|
|
scope["selected_subcategory"] = subcat
|
|
|
|
scope["selected_item"] = item
|
|
|
|
|
|
|
|
if section == "color_picker":
|
|
|
|
renpy.store.colorpicker.set_layer(item, 0)
|
|
|
|
|
|
|
|
renpy.restart_interaction()
|
|
|
|
|
2024-10-18 19:29:04 +00:00
|
|
|
def toggle_setting(setting):
|
|
|
|
if setting == "music":
|
|
|
|
if renpy.store.wardrobe.music == False:
|
|
|
|
renpy.store.wardrobe.music = True
|
|
|
|
renpy.music.play("music/Spring_In_My_Step.ogg")
|
|
|
|
else:
|
|
|
|
renpy.store.wardrobe.music = False
|
|
|
|
renpy.music.play(_last_track, fadein=1)
|
|
|
|
else:
|
|
|
|
# StoreModule is a bit of a hack, but it's the only way to do this.
|
|
|
|
renpy.store.wardrobe.__dict__[setting] = not renpy.store.wardrobe.__dict__[setting]
|
|
|
|
renpy.restart_interaction()
|
|
|
|
|
2024-10-15 16:22:38 +00:00
|
|
|
def equip(item):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
if isinstance(item, renpy.store.DollCloth):
|
|
|
|
# Check if the item is hair and already equipped
|
|
|
|
if item.type == "hair" and character.is_equipped_item(item):
|
|
|
|
# If so, play a sound and display a notification to indicate that hair cannot be removed
|
|
|
|
renpy.play("sounds/fail.ogg")
|
|
|
|
renpy.notify("Hair cannot be removed.")
|
|
|
|
else:
|
|
|
|
# Check if the item is already equipped
|
|
|
|
if character.is_equipped_item(item):
|
|
|
|
# If so, check if it's possible to unequip the item
|
|
|
|
if wardrobe_check_unequip(item):
|
|
|
|
# If so, play a reaction and then remove the item from the character's equipment
|
|
|
|
wardrobe_react("unequip", item)
|
|
|
|
character.unequip(item)
|
|
|
|
else:
|
|
|
|
# Otherwise, play a failed unequip reaction
|
|
|
|
wardrobe_react("unequip_fail", item)
|
2024-10-15 16:22:38 +00:00
|
|
|
else:
|
2024-11-06 21:13:12 +00:00
|
|
|
# If the item is not already equipped, check if it's possible to equip the item
|
|
|
|
if wardrobe_check_equip(item):
|
|
|
|
# If so, play a reaction and then add the item to the character's equipment
|
|
|
|
wardrobe_react("equip", item)
|
|
|
|
|
|
|
|
# Check if the item is on the blacklist
|
|
|
|
if not wardrobe_check_blacklist(item):
|
|
|
|
# If so, play a blacklist reaction
|
|
|
|
wardrobe_react("blacklist", item)
|
|
|
|
|
|
|
|
# Mark the item as seen and equip it to the character
|
|
|
|
item.mark_as_seen()
|
|
|
|
character.equip(item)
|
|
|
|
|
|
|
|
# Check if a fallback response is required for the item
|
|
|
|
if wardrobe_fallback_required(item):
|
|
|
|
# If so, call the fallback response function
|
|
|
|
renpy.call(get_character_response(states.active_girl, "fallback"), item)
|
|
|
|
else:
|
|
|
|
# Otherwise, play a failed equip reaction
|
|
|
|
wardrobe_react("equip_fail", item)
|
|
|
|
renpy.restart_interaction()
|
|
|
|
else:
|
|
|
|
outfit = character.create_outfit(temp=True)
|
|
|
|
|
|
|
|
if outfit == item:
|
|
|
|
renpy.notify("Load failed: Outfit already equipped.")
|
2024-10-15 16:22:38 +00:00
|
|
|
else:
|
2024-11-06 21:13:12 +00:00
|
|
|
if wardrobe_check_equip_outfit(item):
|
|
|
|
|
|
|
|
if not outfit.exists():
|
|
|
|
# confirm = suppress_warnings or renpy.show_screen("confirm", "Discard unsaved changes and load this outfit?")
|
|
|
|
|
|
|
|
wardrobe_react("equip_outfit", item)
|
|
|
|
character.equip(item)
|
|
|
|
else:
|
|
|
|
wardrobe_react("equip_outfit", item)
|
|
|
|
character.equip(item)
|
2024-10-15 16:22:38 +00:00
|
|
|
else:
|
2024-11-06 21:13:12 +00:00
|
|
|
wardrobe_react("equip_outfit_fail", item)
|
|
|
|
|
2024-10-15 16:22:38 +00:00
|
|
|
|
|
|
|
def strip():
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
state = scope.get("__character_strip", 0)
|
|
|
|
character = scope["character"]
|
|
|
|
|
|
|
|
if state == 0: # Strip to underwear
|
|
|
|
character.strip("clothes")
|
|
|
|
character.wear("bra", "panties")
|
|
|
|
scope["__character_strip"] = 1
|
|
|
|
elif state == 1: # Strip naked
|
|
|
|
character.strip("bra", "panties")
|
|
|
|
scope["__character_strip"] = 2
|
|
|
|
elif state == 2: # Wear everything
|
|
|
|
character.wear("all")
|
|
|
|
scope["__character_strip"] = 0
|
|
|
|
renpy.restart_interaction()
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
def save():
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
|
|
|
outfit = character.create_outfit(temp=True)
|
|
|
|
|
|
|
|
if outfit.exists():
|
|
|
|
renpy.notify("Save failed: Outfit already exists.")
|
|
|
|
else:
|
|
|
|
outfit = character.create_outfit()
|
|
|
|
outfit.build_button()
|
|
|
|
renpy.notify("Outfit Saved.")
|
|
|
|
|
2024-10-29 11:57:39 +00:00
|
|
|
def toggle_item(slot):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
|
|
|
|
|
|
|
if character.is_worn(slot):
|
|
|
|
character.strip(slot)
|
|
|
|
else:
|
|
|
|
character.wear(slot)
|
|
|
|
|
2024-10-15 16:22:38 +00:00
|
|
|
def exit():
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
|
|
|
|
|
|
|
# Handle exit animation
|
|
|
|
scope["navigation_last_frame_atl"] = renpy.store.navigation_last_frame_hide
|
|
|
|
scope["navigation_atl"] = renpy.store.navigation_hide
|
|
|
|
scope["navigation_exit"] = True
|
|
|
|
|
|
|
|
# Save the outfit
|
|
|
|
outfit = renpy.store.get_character_outfit(renpy.store.states.active_girl, typ="last")
|
|
|
|
outfit.save()
|
|
|
|
|
|
|
|
# Reset states
|
|
|
|
character.wear("all")
|
|
|
|
renpy.restart_interaction()
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
def wheelmenu(item, section="clothing"):
|
2024-10-29 11:57:39 +00:00
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
2024-11-06 21:13:12 +00:00
|
|
|
submenu_pos = renpy.get_mouse_pos()
|
2024-10-29 11:57:39 +00:00
|
|
|
|
|
|
|
exit_action = renpy.store.Function(renpy.hide_screen, "wheelmenu")
|
|
|
|
equip_action = renpy.store.Function(equip, item)
|
|
|
|
color_action = renpy.store.Function(jump_to_item, item, "color_picker") if character.is_equipped_item(item) else [equip_action, renpy.store.Function(jump_to_item, item, "color_picker")]
|
|
|
|
select_action = renpy.store.Function(change_item, item)
|
|
|
|
jump_action = renpy.store.Function(jump_to_item, item)
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
if isinstance(item, renpy.store.DollCloth):
|
|
|
|
hide_action = renpy.store.Function(toggle_item, item.type)
|
|
|
|
|
|
|
|
def _overwrite_outfit(character, item):
|
|
|
|
selected_outfit_index = character.outfits.index(item)
|
|
|
|
selected_outfit_schedule = character.outfits[selected_outfit_index].schedule.copy()
|
|
|
|
|
|
|
|
current_outfit = character.create_outfit()
|
|
|
|
current_outfit.delete() # Removes from list only
|
|
|
|
current_outfit.schedule = selected_outfit_schedule
|
|
|
|
|
|
|
|
character.outfits[selected_outfit_index] = current_outfit
|
|
|
|
|
|
|
|
def schedule_action():
|
|
|
|
btns = renpy.store.create_wheelmenu({
|
|
|
|
_("Day"): (renpy.store.Text("🌞", align=(0.5, 0.5)), renpy.store.Function(toggle_schedule_action, "day"), "True", str(not item.schedule["day"])),
|
|
|
|
_("Night"): (renpy.store.Text("🌙", align=(0.5, 0.5)), renpy.store.Function(toggle_schedule_action, "night"), "True", str(not item.schedule["night"])),
|
|
|
|
_("Rainy"): (renpy.store.Text("🌧️", align=(0.5, 0.5)), renpy.store.Function(toggle_schedule_action, "rainy"), "True", str(not item.schedule["rainy"])),
|
|
|
|
_("Snowy"): (renpy.store.Text("🌨️", align=(0.5, 0.5)), renpy.store.Function(toggle_schedule_action, "snowy"), "True", str(not item.schedule["snowy"])),
|
|
|
|
_("Cloudy"): (renpy.store.Text("☁️", align=(0.5, 0.5)), renpy.store.Function(toggle_schedule_action, "cloudy"), "True", str(not item.schedule["cloudy"])),
|
|
|
|
})
|
|
|
|
|
|
|
|
renpy.show_screen("wheelmenu", btns, pos=submenu_pos, close_action=exit_action)
|
|
|
|
|
|
|
|
def toggle_schedule_action(schedule):
|
|
|
|
item.schedule[schedule] = not item.schedule[schedule]
|
|
|
|
schedule_action()
|
|
|
|
|
2024-10-29 11:57:39 +00:00
|
|
|
d = {}
|
|
|
|
if section == "outfits":
|
2024-11-06 21:13:12 +00:00
|
|
|
delete_action = item.delete
|
2024-11-07 08:44:09 +00:00
|
|
|
export_action = renpy.store.Function(item.export_data, f"{item._hash}.png")
|
2024-11-06 21:13:12 +00:00
|
|
|
overwrite_action = renpy.store.Function(_overwrite_outfit, character, item)
|
|
|
|
|
|
|
|
d[_("Equip")] = (renpy.store.Text("👗", align=(0.5, 0.5)), [exit_action, equip_action])
|
|
|
|
d[_("Overwrite")] = (renpy.store.Text("💾", align=(0.5, 0.5)), [exit_action, overwrite_action])
|
|
|
|
d[_("Delete")] = (renpy.store.Text("❌", align=(0.5, 0.5)), [exit_action, delete_action])
|
|
|
|
d[_("Export")] = (renpy.store.Text("📤", align=(0.5, 0.5)), [exit_action, export_action])
|
|
|
|
d[_("Schedule")] = (renpy.store.Text("🗓️", align=(0.5, 0.5)), [exit_action, schedule_action])
|
|
|
|
elif section == "clothing":
|
2024-10-29 11:57:39 +00:00
|
|
|
if not character.is_equipped_item(item):
|
|
|
|
d[_("Equip")] = (renpy.store.Text("👗", align=(0.5, 0.5)), [exit_action, equip_action])
|
|
|
|
else:
|
|
|
|
d[_("Unequip")] = (renpy.store.Text("👙", align=(0.5, 0.5)), [exit_action, equip_action])
|
|
|
|
|
|
|
|
if item.color:
|
|
|
|
d[_("Colourize")] = (renpy.store.Text("🎨", align=(0.5, 0.5)), [exit_action, color_action])
|
|
|
|
elif section == "color_picker":
|
|
|
|
if not character.is_worn(item.type):
|
|
|
|
d[_("Show")] = (renpy.store.Text("👁️", align=(0.5, 0.5)), [exit_action, hide_action])
|
|
|
|
else:
|
|
|
|
d[_("Hide")] = (renpy.store.Text("👁️", align=(0.5, 0.5)), [exit_action, hide_action])
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
d[_("Select")] = (renpy.store.Text("✅", align=(0.5, 0.5)), [exit_action, select_action])
|
|
|
|
d[_("Jump to wardrobe")] = (renpy.store.Text("🚪", align=(0.5, 0.5)), [exit_action, jump_action])
|
2024-10-29 11:57:39 +00:00
|
|
|
|
|
|
|
btns = renpy.store.create_wheelmenu(d)
|
|
|
|
|
|
|
|
renpy.play("sounds/qubodup-click1.ogg")
|
|
|
|
renpy.show_screen("wheelmenu", btns, pos=None, close_action=exit_action)
|
|
|
|
|
|
|
|
def color_picker_item_icon(item):
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
|
|
|
|
|
|
|
if character.is_worn(item.type):
|
|
|
|
return renpy.store.AlphaMask(renpy.store.Transform(item.icon, xysize=(48, 48)), renpy.store.Transform("wheelmenu_button_opaque", xysize=(48, 48)))
|
|
|
|
return renpy.store.Transform(renpy.store.AlphaMask(renpy.store.Transform(item.icon, xysize=(48, 48)), renpy.store.Transform("wheelmenu_button_opaque", xysize=(48, 48))), matrixcolor=renpy.store.SaturationMatrix(0)*renpy.store.BrightnessMatrix(-0.25)*renpy.store.OpacityMatrix(0.5))
|
2024-10-29 14:06:38 +00:00
|
|
|
|
|
|
|
@functools.cache
|
|
|
|
def easteregg(character_name):
|
|
|
|
head_action = renpy.store.Function(wardrobe_react,"touch", "head")
|
|
|
|
breasts_action = renpy.store.Function(wardrobe_react, "touch", "breasts")
|
|
|
|
vagina_action = renpy.store.Function(wardrobe_react, "touch", "vagina")
|
|
|
|
|
|
|
|
# Positions (hardcoded)
|
|
|
|
if character_name == "tonks":
|
|
|
|
head_box = (763, 31, 882, 160)
|
|
|
|
breasts_box = (735, 232, 890, 310)
|
|
|
|
vagina_box = (765, 405, 834, 466)
|
|
|
|
elif character_name == "hermione":
|
|
|
|
head_box = (760, 14, 882, 170)
|
|
|
|
breasts_box = (735, 232, 880, 320)
|
|
|
|
vagina_box = (770, 387, 834, 440)
|
|
|
|
elif character_name == "cho":
|
|
|
|
head_box = (756, 71, 863, 193)
|
|
|
|
breasts_box = (751, 247, 856, 318)
|
|
|
|
vagina_box = (768, 405, 826, 457)
|
|
|
|
elif character_name == "luna":
|
|
|
|
head_box = (763, 31, 885, 165)
|
|
|
|
breasts_box = (740, 220, 872, 310)
|
|
|
|
vagina_box = (771, 391, 834, 444)
|
|
|
|
elif character_name == "astoria":
|
|
|
|
head_box = (757, 64, 863, 194)
|
|
|
|
breasts_box = (755, 254, 863, 318)
|
|
|
|
vagina_box = (775, 410, 824, 457)
|
|
|
|
else: # Susan + fallback
|
|
|
|
head_box = (771, 56, 871, 184)
|
|
|
|
breasts_box = (724, 230, 882, 342)
|
|
|
|
vagina_box = (770, 405, 850, 464)
|
|
|
|
|
|
|
|
head_xysize = (head_box[2] - head_box[0], head_box[3] - head_box[1])
|
|
|
|
breasts_xysize = (breasts_box[2] - breasts_box[0], breasts_box[3] - breasts_box[1])
|
|
|
|
vagina_xysize = (vagina_box[2] - vagina_box[0], vagina_box[3] - vagina_box[1])
|
|
|
|
|
|
|
|
head_pos = (head_box[0], head_box[1])
|
|
|
|
breasts_pos = (breasts_box[0], breasts_box[1])
|
|
|
|
vagina_pos = (vagina_box[0], vagina_box[1])
|
|
|
|
|
|
|
|
# Buttons
|
|
|
|
head_btn = renpy.store.Button(child=renpy.store.Null(), style="wardrobe_secret", xysize=head_xysize, action=head_action)
|
|
|
|
breasts_btn = renpy.store.Button(child=renpy.store.Null(*breasts_xysize), style="wardrobe_secret", xysize=breasts_xysize, action=breasts_action)
|
|
|
|
vagina_btn = renpy.store.Button(child=renpy.store.Null(*vagina_xysize), style="wardrobe_secret", xysize=vagina_xysize, action=vagina_action)
|
|
|
|
|
|
|
|
return [(head_btn, head_pos), (breasts_btn, breasts_pos), (vagina_btn, vagina_pos)]
|
|
|
|
|
2024-11-06 21:13:12 +00:00
|
|
|
def import_outfits():
|
|
|
|
scope = renpy.get_screen("wardrobe").scope
|
|
|
|
character = scope["character"]
|
|
|
|
path = f"{renpy.config.gamedir}/outfits/"
|
|
|
|
|
|
|
|
if not os.path.exists(path):
|
|
|
|
os.makedirs(path)
|
|
|
|
|
|
|
|
files = []
|
|
|
|
for f in os.listdir(path):
|
|
|
|
fp = os.path.join(path, f)
|
|
|
|
rp = os.path.relpath(fp, renpy.config.gamedir).replace("\\", "/")
|
|
|
|
|
|
|
|
if os.path.isfile(os.path.join(path, f)) and f.endswith(".png"):
|
|
|
|
character.import_outfit(rp)
|
|
|
|
|
2024-10-18 19:29:04 +00:00
|
|
|
# Context
|
2024-10-13 08:38:11 +00:00
|
|
|
label wardrobe(inter_pause=True):
|
|
|
|
$ disable_game_menu()
|
2024-10-18 19:29:04 +00:00
|
|
|
$ wardrobe._last_track = renpy.music.get_playing()
|
|
|
|
if wardrobe.music:
|
|
|
|
play music "music/Spring_In_My_Step.ogg"
|
2024-10-13 08:38:11 +00:00
|
|
|
if inter_pause:
|
|
|
|
# Ensures all irrelevant screens are hidden before capturing the surface tree
|
|
|
|
with Pause(0.2)
|
|
|
|
call screen wardrobe
|
|
|
|
$ enable_game_menu()
|
|
|
|
jump main_room_menu
|
|
|
|
|
2024-10-18 19:29:04 +00:00
|
|
|
# Interface
|
2024-10-13 08:38:11 +00:00
|
|
|
screen wardrobe():
|
|
|
|
layer "interface"
|
|
|
|
zorder 0
|
2022-05-16 23:48:22 +00:00
|
|
|
style_prefix "wardrobe"
|
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
default navigation_atl = navigation_show
|
|
|
|
default last_frame = (screenshot.capture() or screenshot.image)
|
|
|
|
default navigation_last_frame_atl = navigation_last_frame_show
|
|
|
|
default navigation_exit = False
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
default character = get_character_object(states.active_girl)
|
2024-10-18 19:29:04 +00:00
|
|
|
default selected_section = None
|
2024-10-13 08:38:11 +00:00
|
|
|
default selected_category = None
|
|
|
|
default selected_subcategory = None
|
2024-10-18 19:29:04 +00:00
|
|
|
default selected_item = None
|
|
|
|
default selected_layer = 0
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
add last_frame at navigation_last_frame_atl
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
add "gui_fade_both" at gui_fade
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
if navigation_exit:
|
|
|
|
timer 0.4 action Return()
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
frame:
|
|
|
|
at navigation_atl
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
vbox:
|
2024-10-18 19:29:04 +00:00
|
|
|
# Sections
|
2022-05-16 23:48:22 +00:00
|
|
|
hbox:
|
|
|
|
spacing 0
|
2024-10-13 08:38:11 +00:00
|
|
|
|
2024-10-18 19:29:04 +00:00
|
|
|
button:
|
|
|
|
add wardrobe.get_icon("outfits") xysize (64, 64)
|
2024-11-06 21:13:12 +00:00
|
|
|
tooltip _("Outfits")
|
2024-10-18 19:29:04 +00:00
|
|
|
action Function(wardrobe.change_section, "outfits") selected (selected_section == "outfits")
|
2024-11-06 21:13:12 +00:00
|
|
|
button:
|
|
|
|
add wardrobe.get_icon("clothing") xysize (64, 64)
|
|
|
|
tooltip _("Clothing")
|
|
|
|
action Function(wardrobe.change_section, "clothing") selected (selected_section == "clothing")
|
2024-10-18 19:29:04 +00:00
|
|
|
button:
|
|
|
|
add wardrobe.get_icon("color_picker") xysize (64, 64)
|
2024-11-06 21:13:12 +00:00
|
|
|
tooltip _("Colour Picker")
|
2024-10-18 19:29:04 +00:00
|
|
|
action Function(wardrobe.change_section, "color_picker") selected (selected_section == "color_picker")
|
|
|
|
button:
|
2024-11-06 21:13:12 +00:00
|
|
|
add wardrobe.get_icon("clothing") xysize (64, 64)
|
|
|
|
tooltip _("Settings")
|
2024-10-18 19:29:04 +00:00
|
|
|
action Function(wardrobe.change_section, "settings") selected (selected_section == "settings")
|
|
|
|
|
|
|
|
null height 3
|
2024-10-13 08:38:11 +00:00
|
|
|
add "frame_spacer" xsize 500 xalign 0.5
|
2024-10-18 19:29:04 +00:00
|
|
|
null height 3
|
|
|
|
|
|
|
|
if selected_section == "outfits":
|
2024-11-06 21:13:12 +00:00
|
|
|
# Outfit List
|
|
|
|
vpgrid:
|
|
|
|
cols 5
|
|
|
|
spacing 5
|
|
|
|
mousewheel True
|
|
|
|
scrollbars "vertical"
|
|
|
|
|
|
|
|
textbutton "Save":
|
|
|
|
focus_mask None
|
|
|
|
xysize (96, 168)
|
|
|
|
insensitive_background "#0000001A"
|
|
|
|
idle_background "#00000033"
|
|
|
|
text_align (0.5, 0.5)
|
|
|
|
sensitive (not bool(DollThread._count))
|
|
|
|
action wardrobe.save
|
|
|
|
|
|
|
|
for outfit in reversed(character.outfits):
|
|
|
|
add outfit.button
|
|
|
|
|
|
|
|
elif selected_section == "clothing":
|
2024-10-18 19:29:04 +00:00
|
|
|
# Categories
|
|
|
|
hbox:
|
|
|
|
spacing 0
|
|
|
|
for category in character.wardrobe:
|
|
|
|
if category == "hidden":
|
|
|
|
continue
|
|
|
|
|
|
|
|
button:
|
|
|
|
add wardrobe.get_icon(category) xysize (64, 64)
|
|
|
|
tooltip category
|
|
|
|
action Function(wardrobe.change_category, category) selected (selected_category == category)
|
|
|
|
|
|
|
|
null height 3
|
2024-10-13 08:38:11 +00:00
|
|
|
add "frame_spacer" xsize 500 xalign 0.5
|
2024-10-18 19:29:04 +00:00
|
|
|
null height 3
|
|
|
|
|
|
|
|
# Subcategories
|
|
|
|
if selected_category:
|
|
|
|
viewport:
|
|
|
|
ysize 28
|
|
|
|
edgescroll (60, 50)
|
|
|
|
mousewheel "horizontal"
|
|
|
|
hbox:
|
|
|
|
for subcategory in character.wardrobe[selected_category]:
|
|
|
|
button:
|
2024-10-22 14:26:41 +00:00
|
|
|
text subcategory
|
2024-10-18 19:29:04 +00:00
|
|
|
action Function(wardrobe.change_subcategory, subcategory) selected (selected_subcategory == subcategory)
|
|
|
|
|
|
|
|
add "frame_spacer" xsize 500 xalign 0.5
|
|
|
|
null height 5
|
|
|
|
|
|
|
|
# Items
|
|
|
|
if selected_subcategory:
|
|
|
|
vpgrid:
|
|
|
|
cols 5
|
|
|
|
ysize 399
|
|
|
|
xspacing 5
|
|
|
|
yspacing 5
|
|
|
|
mousewheel True
|
|
|
|
scrollbars "vertical"
|
|
|
|
for item in character.wardrobe[selected_category][selected_subcategory]:
|
|
|
|
add item.button
|
|
|
|
elif selected_section == "color_picker":
|
|
|
|
# Included in a single screen because local screen scopes don't work as they should with functions.
|
|
|
|
hbox:
|
|
|
|
# Item list
|
|
|
|
vpgrid:
|
|
|
|
cols 1
|
|
|
|
ysize 520
|
|
|
|
yspacing 4
|
|
|
|
scrollbars "vertical"
|
|
|
|
mousewheel True
|
|
|
|
for state in character.states.values():
|
|
|
|
$ item = state[0]
|
|
|
|
|
|
|
|
if item and item.color:
|
|
|
|
button:
|
2024-10-29 11:57:39 +00:00
|
|
|
add wardrobe.color_picker_item_icon(item)
|
|
|
|
action Function(wardrobe.wheelmenu, item, "color_picker") selected (selected_item == item)
|
|
|
|
alternate Function(wardrobe.jump_to_item, item)
|
2024-10-22 14:26:41 +00:00
|
|
|
style "wardrobe_item_small_button"
|
2024-10-18 19:29:04 +00:00
|
|
|
if selected_item:
|
|
|
|
$ is_blacklisted = selected_item.type.startswith(tuple(selected_item.blacklist_unequip))
|
|
|
|
$ is_allowed = selected_item.type.startswith(("makeup", "tattoo"))
|
2024-10-22 14:26:41 +00:00
|
|
|
$ accents = colorpicker.generate_colors(selected_item.color[0], len(selected_item.color))
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
vbox:
|
2024-10-22 14:26:41 +00:00
|
|
|
label _("Colour Picker") xalign 0.5
|
|
|
|
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
hbox:
|
2024-10-22 14:26:41 +00:00
|
|
|
xfill True
|
|
|
|
text _("Layers") xalign 0
|
|
|
|
frame:
|
|
|
|
style "empty"
|
|
|
|
xalign 1.0
|
|
|
|
xysize (255, 32)
|
|
|
|
hbox:
|
|
|
|
for n, col in enumerate(selected_item.color):
|
|
|
|
button:
|
|
|
|
xysize (32, 32)
|
|
|
|
style "wardrobe_swatch"
|
|
|
|
background Transform(Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_swatch_circular.png", oversample=4), xysize=(32, 32), matrixcolor=SepiaMatrix(col, desat=(0.3333, 0.3333, 0.3333)))
|
|
|
|
action Function(colorpicker.set_layer, selected_item, n)
|
|
|
|
selected (n == selected_layer)
|
|
|
|
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
|
|
|
|
|
|
|
hbox:
|
|
|
|
xfill True
|
|
|
|
text _("Hue") xalign 0
|
|
|
|
frame:
|
|
|
|
xysize (255, 32)
|
|
|
|
xalign 1.0
|
|
|
|
style "empty"
|
|
|
|
add AlphaMask(colorpicker.cp.cph, Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_bar.png", oversample=4))
|
|
|
|
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
hbox:
|
2024-10-22 14:26:41 +00:00
|
|
|
xfill True
|
|
|
|
text _("Saturation") xalign 0
|
|
|
|
frame:
|
|
|
|
xysize (255, 32)
|
|
|
|
xalign 1.0
|
|
|
|
style "empty"
|
|
|
|
add AlphaMask(colorpicker.cp.cps, Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_bar.png", oversample=4))
|
|
|
|
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
|
|
|
|
|
|
|
hbox:
|
|
|
|
xfill True
|
2024-10-29 14:06:38 +00:00
|
|
|
text _("Brightness") xalign 0 # HSV calls it value, but brightness is more user friendly
|
2024-10-22 14:26:41 +00:00
|
|
|
frame:
|
|
|
|
xysize (255, 32)
|
|
|
|
xalign 1.0
|
|
|
|
style "empty"
|
|
|
|
add AlphaMask(colorpicker.cp.cpv, Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_bar.png", oversample=4))
|
|
|
|
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
if not is_blacklisted and (is_allowed or wardrobe.allow_opacity):
|
2024-10-22 14:26:41 +00:00
|
|
|
hbox:
|
|
|
|
xfill True
|
|
|
|
text _("Alpha") xalign 0
|
|
|
|
frame:
|
|
|
|
xysize (255, 32)
|
|
|
|
xalign 1.0
|
|
|
|
style "empty"
|
|
|
|
add AlphaMask(colorpicker.cp.cpa, Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_bar.png", oversample=4))
|
|
|
|
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
|
|
|
|
|
|
|
hbox:
|
|
|
|
xfill True
|
|
|
|
text _("History") xalign 0
|
|
|
|
frame:
|
|
|
|
xysize (255, 32)
|
|
|
|
xalign 1.0
|
|
|
|
style "empty"
|
|
|
|
|
|
|
|
hbox:
|
|
|
|
for col in colorpicker.history:
|
|
|
|
button:
|
|
|
|
xysize (32, 32)
|
|
|
|
style "wardrobe_swatch"
|
|
|
|
background Transform(Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_swatch_circular.png", oversample=4), xysize=(32, 32), matrixcolor=SepiaMatrix(col, desat=(0.3333, 0.3333, 0.3333)))
|
|
|
|
action Function(colorpicker.set_color, value=col)
|
|
|
|
selected (col == colorpicker.cp.live_color)
|
|
|
|
|
|
|
|
label _("Swatches") xalign 0.5
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
|
|
|
|
|
|
|
grid 14 4:
|
|
|
|
for i, col in enumerate(colorpicker.favorites):
|
|
|
|
button:
|
|
|
|
xysize (32, 32)
|
|
|
|
style "wardrobe_swatch"
|
|
|
|
background (Transform(Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_swatch.png", oversample=4), xysize=(32, 32), matrixcolor=SepiaMatrix(col, desat=(0.3333, 0.3333, 0.3333))) if col else Transform(Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_swatch_empty.png", oversample=4), xysize=(32, 32)))
|
|
|
|
action (Function(colorpicker.set_color, value=col) if col else NullAction())
|
|
|
|
alternate Function(colorpicker.cp.add_favorite, i, colorpicker.cp.live_color)
|
|
|
|
selected (col == colorpicker.cp.live_color)
|
|
|
|
|
|
|
|
label _("Layer Adjustments") xalign 0.5
|
|
|
|
add "frame_spacer" xalign 0.5 xsize 420
|
|
|
|
|
|
|
|
textbutton _("Reset current layer") action [Function(selected_item.reset_color, selected_layer), Function(colorpicker.cp.live_replace, selected_item.color_default[selected_layer]), renpy.restart_interaction] style "wardrobe_button"
|
|
|
|
textbutton _("Reset all layers") action [selected_item.reset_color, Function(colorpicker.cp.live_replace, selected_item.color_default[selected_layer]), renpy.restart_interaction] style "wardrobe_button"
|
|
|
|
textbutton _("Auto generate accents") action [Function(selected_item.set_color, accents), renpy.restart_interaction] style "wardrobe_button"
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
elif selected_section == "settings":
|
|
|
|
textbutton _("Special Music") action Function(wardrobe.toggle_setting, "music") selected wardrobe.music style "wardrobe_checkbox_button"
|
|
|
|
textbutton _("Chitchats") action Function(wardrobe.toggle_setting, "chitchats") selected wardrobe.chitchats style "wardrobe_checkbox_button"
|
|
|
|
textbutton _("Autosave") action Function(wardrobe.toggle_setting, "autosave") selected wardrobe.autosave style "wardrobe_checkbox_button"
|
|
|
|
textbutton _("Suppress Warnings") action Function(wardrobe.toggle_setting, "suppress_warnings") selected wardrobe.suppress_warnings style "wardrobe_checkbox_button"
|
|
|
|
textbutton _("Randomize Colours") action Function(wardrobe.toggle_setting, "randomize_color") selected wardrobe.randomize_color style "wardrobe_checkbox_button"
|
|
|
|
textbutton _("Global Colours") action Function(wardrobe.toggle_setting, "global_color") selected wardrobe.global_color style "wardrobe_checkbox_button"
|
|
|
|
textbutton _("Allow Opacity Slider") action Function(wardrobe.toggle_setting, "allow_opacity") selected wardrobe.allow_opacity style "wardrobe_checkbox_button"
|
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
add character.image align (1.0, 1.0) zoom 0.6
|
2024-10-15 16:22:38 +00:00
|
|
|
|
|
|
|
vbox:
|
|
|
|
align (0.5, 1.0)
|
|
|
|
textbutton "Strip" action wardrobe.strip
|
2024-10-22 14:26:41 +00:00
|
|
|
textbutton "Return" action wardrobe.exit keysym "K_ESCAPE"
|
2024-10-13 08:38:11 +00:00
|
|
|
|
2024-10-29 14:06:38 +00:00
|
|
|
for i, j in wardrobe.easteregg(character.name):
|
|
|
|
add i pos j
|
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
style wardrobe_item_button is empty:
|
|
|
|
background Transform("wheelmenu_button", xysize=(96,96))
|
|
|
|
hover_background At(Transform("wheelmenu_button_opaque", xysize=(96,96)), wheelmenu_hover_anim)
|
2024-10-18 19:29:04 +00:00
|
|
|
selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(24, 24))
|
2024-04-18 15:57:31 +00:00
|
|
|
hover_sound "sounds/qubodup-hover1.ogg"
|
2024-10-13 08:38:11 +00:00
|
|
|
activate_sound "sounds/qubodup-click2.ogg"
|
2022-05-16 23:48:22 +00:00
|
|
|
|
2024-10-13 08:38:11 +00:00
|
|
|
style wardrobe_item_button_inadequate is empty:
|
2024-10-15 16:22:38 +00:00
|
|
|
background Transform("wheelmenu_button", xysize=(96,96))
|
|
|
|
hover_background At(Transform("wheelmenu_button_opaque", xysize=(96,96), matrixcolor=TintMatrix("#ff0000")), wheelmenu_hover_anim)
|
2024-10-13 08:38:11 +00:00
|
|
|
hover_sound "sounds/qubodup-hover1.ogg"
|
|
|
|
activate_sound "sounds/qubodup-click2.ogg"
|
2024-10-22 14:26:41 +00:00
|
|
|
|
|
|
|
style wardrobe_item_small_button is wardrobe_item_button:
|
|
|
|
background Transform("wheelmenu_button", xysize=(48,48))
|
|
|
|
hover_background At(Transform("wheelmenu_button_opaque", xysize=(48,48)), wheelmenu_hover_anim)
|
|
|
|
selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(24, 24))
|
|
|
|
|
2024-11-07 08:44:09 +00:00
|
|
|
style wardrobe_item_rectangular_button is wardrobe_item_button:
|
|
|
|
background Transform("wheelmenu_button", xysize=(96,168))
|
|
|
|
hover_background At(Transform("wheelmenu_button_opaque", xysize=(96,168)), wheelmenu_hover_anim)
|
|
|
|
selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(24, 24))
|
|
|
|
|
2024-10-22 14:26:41 +00:00
|
|
|
style wardrobe_outline:
|
|
|
|
padding (2, 2)
|
|
|
|
foreground Frame(Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_outline.png"), 2, 0, 2, 0, tile=False)
|
|
|
|
|
|
|
|
style wardrobe_swatch:
|
|
|
|
selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(12, 12))
|
2024-10-13 08:38:11 +00:00
|
|
|
|
|
|
|
style wardrobe_frame is empty:
|
|
|
|
xsize 540
|
|
|
|
yfill True
|
|
|
|
padding (10, 10)
|
|
|
|
background Frame(Image("gui/creamy_pumpkin_pie/side_frame.png", oversample=4), 0, 100, 9, 75, tile=False)
|
2024-10-15 16:22:38 +00:00
|
|
|
|
|
|
|
style wardrobe_button is frame_button:
|
|
|
|
xpadding 0
|
|
|
|
style wardrobe_button_text is frame_button_text:
|
|
|
|
size 18
|
|
|
|
style wardrobe_label:
|
|
|
|
xpadding 5
|
2024-10-18 19:29:04 +00:00
|
|
|
ypadding 2
|
2024-10-22 14:26:41 +00:00
|
|
|
style wardrobe_label_text is wardrobe_button_text:
|
|
|
|
size 32
|
|
|
|
style wardrobe_text is wardrobe_button_text
|
2024-10-15 16:22:38 +00:00
|
|
|
style wardrobe_viewport:
|
|
|
|
fit_first True
|
|
|
|
xsize 500
|
2024-10-18 19:29:04 +00:00
|
|
|
|
|
|
|
style wardrobe_checkbox_button:
|
|
|
|
padding (6, 4)
|
|
|
|
hover_background Frame(Image("gui/creamy_pumpkin_pie/book/book_select.png", oversample=4), 20, 0, 20, 0, tile=False)
|
|
|
|
foreground Transform(Image("gui/creamy_pumpkin_pie/book/book_button_check_empty.png", oversample=4), xpos=6, yalign=0.5)
|
|
|
|
selected_foreground Transform(Image("gui/creamy_pumpkin_pie/book/book_button_check_checked.png", oversample=4), xpos=6, yalign=0.5)
|
|
|
|
insensitive_foreground Transform(Image("gui/creamy_pumpkin_pie/book/book_button_check_empty.png", oversample=4), alpha=0.5, xpos=6, yalign=0.5)
|
|
|
|
|
|
|
|
style wardrobe_checkbox_button_text is wardrobe_button_text:
|
|
|
|
first_indent 24
|
2024-10-29 14:06:38 +00:00
|
|
|
|
|
|
|
# Debug only
|
|
|
|
style wardrobe_secret:
|
2024-11-06 21:13:12 +00:00
|
|
|
#background "#ff000025"
|
|
|
|
background None
|