Outfit import/export

* Re-implemented image payload injection using Python3-compliant methods
* Added sanity checks for image importing and exporting
* Added compression for the payload
* Added user input for exported image file names
* Removed redundant layer for Tonks' ribbon bra
* Updated MyMod clothing definition example.
* Fixed regression in outfit clone functions
This commit is contained in:
LoafyLemon 2023-02-10 23:12:16 +00:00
parent 5fdf1e87fe
commit fb8e3aab0f
9 changed files with 132 additions and 116 deletions

Binary file not shown.

View File

@ -1,13 +1,19 @@
# Add new hairstyle for character as an instance of DollCloth,
# make sure the variable name is unique, preferably starting with mod name.
default MyMod_ponytail = DollCloth(
modpath="mods/mymod/", # shortened filepath to this file
modpath="MyMod", # File path; Usually a mod folder name. (case insensitive)
name="hermione", # Character name (case sensitive)
categories=("head","hair"), # Main category and subcategory of the item
type="hair", # Item type
id="ponytail", # Item identificator
categories=("head","hair"), # Main category and subcategory of the item (case sensitive)
type="hair", # Item type (case sensitive)
id="ponytail", # Item identifier (case sensitive)
unlocked=True, # True=Item is unlocked by default, False=Item is a part of the outfit and requries to be bought
level=0, # Character whoring/friendship level required to wear this cloth. (Optional)
armfix=False, # If cloth images intersect with arm layers, set to True. (Optional)
color=[[152, 89, 48, 255], [195, 137, 89, 255]] # Python list with default colours in RGBA format applicable for each colourable file layer
color=["#985930", "#c38959"], # Python list with default colours in one of the formats listed down below.
zorder=None # Item zorder number, or None, if None default zorder for the slot will be used.
)
# Example valid colour formats:
# RGB: [(255, 255, 255), (255, 255, 255)]
# RGBA: [(255, 255, 255, 255), (255, 255, 255, 255)]
# HEX: [("#985930", "#c38959")]
# HEXA: [("#985930FF", "#c38959FF")]

View File

@ -252,8 +252,6 @@ init python:
def clone(self):
"""Creates a clone of this cloth object. Since it requires a parent object it should be used internally only to avoid object depth issue."""
if self.parent:
return self
return DollCloth(self.name, self.categories, self.type, self.id, [x for x in self.color] if self.color else None, self.zorder, self.unlocked, self.level, self.blacklist, self.modpath, self)
def is_modded(self):

View File

@ -183,6 +183,4 @@ init python:
def clone(self):
"""Creates a clone of this cloth object. Since it requires a parent object it should be used internally only to avoid object depth issue."""
if self.parent:
return self
return DollClothDynamic(self.name, self.categories, self.type, self.id, [x for x in self.color] if self.color else None, self.zorder, self.unlocked, self.level, self.blacklist, self.modpath, self._tracking, self)

View File

@ -505,11 +505,11 @@ init python:
# Grab data
if fromfile:
try:
imported = image_payload.decode(path)
except:
if image_payload._file:
image_payload._file.close()
imported = ImagePayload().extract(path)
except Exception as e:
renpy.notify("Import failed: Corrupted file.")
print(e)
renpy.block_rollback()
return None
else:
imported = get_clipboard()
@ -518,8 +518,9 @@ init python:
if imported:
try:
imported = make_revertable(evaluate(imported))
except:
except Exception as e:
renpy.notify("Import failed: Corrupted outfit data.")
print(e)
renpy.block_rollback()
return None

View File

@ -86,16 +86,21 @@ init python:
def export_data(self, filename, tofile=True):
"""Exports outfit to .png file or clipboard text."""
exported = [self.group[0].name]
exported.extend([x.id, x.color] for x in self.group)
for i in self.group:
if i.color:
color = [j.hexcode for j in i.color]
exported.append([i.id, color])
# Encode data
if tofile:
path = "{}/game/outfits/".format(config.basedir)
fn = "{}.png".format(filename)
path = os.path.join(config.gamedir, "outfits")
if not os.path.exists(path):
os.makedirs(path)
path = os.path.join(path, "_temp.png")
d = Transform(self.image, crop=(210, 200, 700, 1000), anchor=(0.5, 1.0), align=(0.5, 1.0), xsize=310, ysize=470, fit="contain")
d = Fixed(
"interface/wardrobe/export_background.webp",
@ -105,8 +110,9 @@ init python:
Text("Ver. {}".format(config.version), size=10, align=(0.99, 0.99))
)
displayable_to_file(d, path+fn, size=(310, 470) )
image_payload.encode(filename, str(exported))
displayable_to_file(d, path, size=(310, 470) )
ImagePayload().inject("_temp.png", filename, str(exported))
os.remove(path)
else:
set_clipboard(exported)
renpy.notify("Export successful!")

View File

@ -97,7 +97,7 @@ init -1 python:
try:
return __import__('ast').literal_eval(txt)
except Exception as e:
print("Error evaluating clipboard data:")
print("Error evaluating data:")
print(e)
def reset_variables(*args):

File diff suppressed because it is too large Load Diff

View File

@ -266,7 +266,12 @@ label wardrobe_menu():
elif _choice[0] == "export":
python:
_choice[1].export_data(datetime.datetime.now().strftime("%d %b %Y-%H%M%S"))
filename = renpy.input("Save as:", datetime.datetime.now().strftime("%d %b %Y-%H%M%S"))
if not filename.endswith(".png"):
filename += ".png"
_choice[1].export_data(filename)
achievements.unlock("export")
elif _choice[0] == "import":