Skip to content
This repository has been archived by the owner on Jul 21, 2024. It is now read-only.

Character Library Tools (WIP) #251

Merged
merged 1 commit into from
Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 63 additions & 13 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3232,6 +3232,7 @@ def draw(self, context):
if hasattr(obj, prop) and not prop.startswith("Expressions_"):
box_fast_creators.prop(obj, prop)
box_fast_creators.operator("mbast.reset_categoryonly", icon="RECOVER_LAST")
#----------
box_fast_creators.separator(factor=0.5)
box_fast_creators.label(text="Phenotype Creator", icon='SORT_ASC')
body_type = morphcreator.get_body_type()
Expand All @@ -3244,11 +3245,31 @@ def draw(self, context):
box_fast_creators.label(text="Name : " + pheno_name, icon='INFO')
if morphcreator.is_phenotype_exists(body_type, pheno_name):
box_fast_creators.label(text="File already exists !", icon='ERROR')
else :
box_fast_creators.operator('mbcrea.button_save_phenotype', icon="FREEZE")
box_fast_creators.operator('mbcrea.button_save_phenotype', icon="FREEZE")
#----------
box_fast_creators.separator(factor=0.5)
box_fast_creators.label(text="Preset Creator", icon='SORT_ASC')
preset_folder = mblab_humanoid.presets_data_folder
path = os.path.join("data", "presets", preset_folder)
box_fast_creators.label(text="File saved under " + path, icon='INFO')
box_fast_creators.label(text="(age, mass & tone are used here)", icon='FORWARD')
box_fast_creators.prop(scn, 'mbcrea_preset_name_filter')
if len(scn.mbcrea_preset_name_filter) > 0:
box_fast_creators.prop(scn, 'mbcrea_special_preset') # Common or Special ?
preset_name = ""
if scn.mbcrea_special_preset:
preset_name = "special"
tmp = algorithms.split_name(scn.mbcrea_preset_name_filter, '-²&=¨^$£%µ,?;!§+*/').lower()
if not tmp.startswith("type_"):
preset_name += "type_"
preset_name += tmp
box_fast_creators.label(text="Name : " + preset_name, icon='INFO')
if morphcreator.is_preset_exists(preset_folder, preset_name):
box_fast_creators.label(text="File already exists !", icon='ERROR')
box_fast_creators.operator('mbcrea.button_save_preset', icon="FREEZE")
else:
box_combinexpression.label(text="! NO COMPATIBLE MODEL !", icon='ERROR')
box_combinexpression.enabled = False
box_fast_creators.label(text="! NO COMPATIBLE MODEL !", icon='ERROR')
box_fast_creators.enabled = False
#----------------------------------
box_adaptation_tools.separator(factor=0.5)

Expand Down Expand Up @@ -3548,7 +3569,17 @@ def morphs_items_minmax(box, items_str, minmax_str):
maxlen=1024,
subtype='FILE_NAME')

bpy.types.Scene.mbcrea_preset_name_filter = bpy.props.StringProperty(
name="Name",
description="The name for the file.\nStarting with type_ is automatic",
default="",
maxlen=1024,
subtype='FILE_NAME')

bpy.types.Scene.mbcrea_special_preset = bpy.props.BoolProperty(
name="Special",
description="If the preset is special or common")

class FinalizeExpression(bpy.types.Operator):
"""
Working like FinalizeMorph
Expand Down Expand Up @@ -3649,17 +3680,35 @@ def execute(self, context):
scn = bpy.context.scene
#-------File name----------
pheno_name = algorithms.split_name(scn.mbcrea_phenotype_name_filter, '-²&=¨^$£%µ,?;!§+*/').lower()
#--expression path + name--
#---phenotype path + name--
path = os.path.join(file_ops.get_data_path(), "phenotypes", morphcreator.get_body_type() + "_ptypes", pheno_name+".json")
#--------Saving file-------
morphcreator.save_phenotype(path, mblab_humanoid)
return {'FINISHED'}

def ShowMessageBox(self, message = "", title = "Message Box", icon = 'INFO'):
class FinalizePreset(bpy.types.Operator):
"""
Working like Save character
"""
bl_label = 'Finalize the preset'
bl_idname = 'mbcrea.button_save_preset'
filename_ext = ".json"
bl_description = 'Finalize the preset'
bl_context = 'objectmode'
bl_options = {'REGISTER', 'INTERNAL'}

def execute(self, context):
scn = bpy.context.scene
#-------File name----------
preset_name = algorithms.split_name(scn.mbcrea_preset_name_filter, '-²&=¨^$£%µ,?;!§+*/').lower()
if not preset_name.startswith("type_"):
preset_name = "type_" + preset_name
#----preset path + name----
path = os.path.join(file_ops.get_data_path(), "presets", mblab_humanoid.presets_data_folder, preset_name+".json")
#--------Saving file-------
morphcreator.save_preset(path, mblab_humanoid)
return {'FINISHED'}

def draw(self, context):
self.layout.label(text=message)
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)

class ButtonCompatToolsDir(bpy.types.Operator):
#just for quick tests
Expand Down Expand Up @@ -4002,9 +4051,9 @@ def execute(self, context):
return {'FINISHED'}

class ButtonFastCreationsON(bpy.types.Operator):
bl_label = 'Fast Creation Tools'
bl_label = 'Character Library Creation'
bl_idname = 'mbcrea.button_fastcreators_on'
bl_description = 'Quick tools to create :\n- Phenotypes\n- Presets'
bl_description = 'Quick tools to create :\n- Phenotypes\n- Presets\nfor Character Library'
bl_context = 'objectmode'
bl_options = {'REGISTER', 'INTERNAL'}

Expand All @@ -4015,9 +4064,9 @@ def execute(self, context):
return {'FINISHED'}

class ButtonFastCreationsOFF(bpy.types.Operator):
bl_label = 'Fast Creation Tools'
bl_label = 'Character Library Creation'
bl_idname = 'mbcrea.button_fastcreators_off'
bl_description = 'Quick tools to create :\n- Phenotypes\n- Presets'
bl_description = 'Quick tools to create :\n- Phenotypes\n- Presets\nfor Character Library'
bl_context = 'objectmode'
bl_options = {'REGISTER', 'INTERNAL'}

Expand Down Expand Up @@ -4409,6 +4458,7 @@ def execute(self, context):
FinalizeExpression,
FinalizeCombExpression,
FinalizePhenotype,
FinalizePreset,
ButtonUpdateCombMorphs,
FinalizeCombMorph,
Reset_expression_category,
Expand Down
7 changes: 3 additions & 4 deletions expressionscreator.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,9 @@ def save_face_expression(self, filepath):
for prop in self.humanoid.character_data.keys():
if self.humanoid.character_data[prop] != 0.5 and prop.startswith("Expressions_"):
char_data["structural"][prop] = round(self.humanoid.character_data[prop], 4)

output_file = open(filepath, 'w')
json.dump(char_data, output_file)
output_file.close()
with open(filepath, "w") as j_file:
json.dump(char_data, j_file, indent=2)
j_file.close()

# data_source can be a filepath but also the data themselves.
def load_face_expression(self, data_source, reset_unassigned=True):
Expand Down
35 changes: 35 additions & 0 deletions morphcreator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import bpy
import numpy
from . import algorithms
from . import file_ops


body_parts = [("AB", "Abdomen", ""),
Expand Down Expand Up @@ -291,5 +292,39 @@ def is_phenotype_exists(body_type, name):
return False
return False

def save_phenotype(path, humanoid):
# Save all expression morphs as a new face expression
# in its dedicated file.
# If file already exists, it's replaced.
logger.info("Exporting character to {0}".format(file_ops.simple_path(path)))
obj = humanoid.get_object()
char_data = {"structural": dict()}

if obj:
for prop in humanoid.character_data.keys():
if humanoid.character_data[prop] != 0.5 and not prop.startswith("Expressions_"):
char_data["structural"][prop] = round(humanoid.character_data[prop], 2)

with open(path, "w") as j_file:
json.dump(char_data, j_file, indent=2)
j_file.close()

# ------------------------------------------------------------------------
# All methods/classes to help creating presets
# ------------------------------------------------------------------------

def is_preset_exists(preset_folder, name):
if len(preset_folder) < 1 or len(name) < 1:
return False
try:
path = os.path.join(file_ops.get_data_path(), "presets", preset_folder)
for database_file in os.listdir(path):
the_item, extension = os.path.splitext(database_file)
if the_item == name:
return True
except:
return False
return False

def save_phenotype(path, humanoid):
return None