diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index 01e6c8c77..5ba5cf58c 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -40,14 +40,46 @@ if "bpy" in locals(): import imp if "import_mdl" in locals(): imp.reload(import_mdl) - #if "export_mdl" in locals(): - # imp.reload(export_mdl) + if "export_mdl" in locals(): + imp.reload(export_mdl) import bpy from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty +from bpy.props import FloatVectorProperty from bpy_extras.io_utils import ExportHelper, ImportHelper, path_reference_mode, axis_conversion +SYNCTYPE=( + ('ST_SYNC', "Syncronized", "Automatic animations are all together"), + ('ST_RAND', "Random", "Automatic animations have random offsets"), +) + +EFFECTS=( + ('EF_NONE', "None", "No effects"), + ('EF_ROCKET', "Rocket", "Leave a rocket trail"), + ('EF_GRENADE', "Grenade", "Leave a grenade trail"), + ('EF_GIB', "Gib", "Leave a trail of blood"), + ('EF_TRACER', "Tracer", "Green split trail"), + ('EF_ZOMGIB', "Zombie Gib", "Leave a smaller blood trail"), + ('EF_TRACER2', "Tracer 2", "Orange split trail + rotate"), + ('EF_TRACER3', "Tracer 3", "Purple split trail"), +) + +class QFMDLSettings(bpy.types.PropertyGroup): + eyeposition = FloatVectorProperty( + name="Eye Position", + description="View possion relative to object origin") + synctype = EnumProperty( + items=SYNCTYPE, + name="Sync Type", + description="Add random time offset for automatic animations") + rotate = BoolProperty( + name="Rotate", + description="Rotate automatically (for pickup items)") + effects = EnumProperty( + items=EFFECTS, + name="Effects", + description="Particle trail effects") class ImportMDL6(bpy.types.Operator, ImportHelper): '''Load a Quake MDL (v6) File''' @@ -81,6 +113,24 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): keywords = self.as_keywords (ignore=("check_existing", "filter_glob")) return export_mdl.export_mdl(self, context, **keywords) +class MDLPanel(bpy.types.Panel): + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = 'object' + bl_label = 'QF MDL' + + @classmethod + def poll(cls, context): + obj = context.active_object + return obj and obj.type == 'MESH' + + def draw(self, context): + layout = self.layout + obj = context.active_object + layout.prop(obj.qfmdl, "eyeposition") + layout.prop(obj.qfmdl, "synctype") + layout.prop(obj.qfmdl, "rotate") + layout.prop(obj.qfmdl, "effects") def menu_func_import(self, context): self.layout.operator(ImportMDL6.bl_idname, text="Quake MDL (.mdl)") @@ -93,6 +143,8 @@ def menu_func_export(self, context): def register(): bpy.utils.register_module(__name__) + bpy.types.Object.qfmdl = bpy.props.PointerProperty(type=QFMDLSettings) + bpy.types.INFO_MT_file_import.append(menu_func_import) bpy.types.INFO_MT_file_export.append(menu_func_export) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 0cd0b6fac..f75c17012 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -161,6 +161,12 @@ def calc_average_area(mdl): totalarea += (c * c) ** 0.5 / 2.0 return totalarea / len(mdl.tris) +def get_properties(mdl, obj): + mdl.eyeposition = tuple (obj.qfmdl.eyeposition) + mdl.synctype = MDL.SYNCTYPE[obj.qfmdl.synctype] + mdl.flags = ((obj.qfmdl.synctype and MDL.EF_ROTATE or 0) + | MDL.EFFECTS[obj.qfmdl.effects]) + def export_mdl(operator, context, filepath): obj = context.active_object mesh = obj.to_mesh (context.scene, True, 'PREVIEW') #wysiwyg? @@ -179,5 +185,6 @@ def export_mdl(operator, context, filepath): mdl.frames.append(make_frame(mesh, vertmap)) mdl.size = calc_average_area(mdl) scale_verts(mdl) + get_properties(mdl, obj) mdl.write(filepath) return {'FINISHED'} diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 303a0e8c6..4dbd96d50 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -235,6 +235,35 @@ def write_text(mdl): txt.from_string(string) return txt.name +def parse_flags(flags): + #NOTE these are in QuakeForge priority order; a little different to id. + # id has rocket and grenate between tracer2 and tracer3 + if flags & MDL.EF_ROCKET: + return 'EF_ROCKET' + elif flags & MDL.EF_GRENADE: + return 'EF_GRENADE' + elif flags & MDL.EF_GIB: + return 'EF_GIB' + elif flags & MDL.EF_ZOMGIB: + return 'EF_ZOMGIB' + elif flags & MDL.EF_TRACER: + return 'EF_TRACER' + elif flags & MDL.EF_TRACER2: + return 'EF_TRACER2' + elif flags & MDL.EF_TRACER3: + return 'EF_TRACER3' + else: + return 'EF_NONE' + +def set_properties(mdl): + mdl.obj.qfmdl.eyeposition = mdl.eyeposition + try: + mdl.obj.qfmdl.synctype = MDL.SYNCTYPE[mdl.synctype] + except IndexError: + mdl.obj.qfmdl.synctype = 'ST_SYNC' + mdl.obj.qfmdl.rotate = (mdl.flags & MDL.EF_ROTATE) and True or False + mdl.obj.qfmdl.effects = parse_flags(mdl.flags) + def import_mdl(operator, context, filepath): bpy.context.user_preferences.edit.use_global_undo = False @@ -264,8 +293,9 @@ def import_mdl(operator, context, filepath): merge_frames(mdl) build_actions(mdl) - operator.report({'INFO'}, - "Extra settings saved in the %s text block." % write_text(mdl)) + #operator.report({'INFO'}, + # "Extra settings saved in the %s text block." % write_text(mdl)) + set_properties(mdl) mdl.mesh.update() diff --git a/tools/io_mesh_qfmdl/mdl.py b/tools/io_mesh_qfmdl/mdl.py index 6526fd462..521b6bf03 100644 --- a/tools/io_mesh_qfmdl/mdl.py +++ b/tools/io_mesh_qfmdl/mdl.py @@ -22,6 +22,22 @@ from struct import unpack, pack class MDL: + ST_SYNC = 0 + ST_RAND = 1 + SYNCTYPE={'ST_SYNC':ST_SYNC, 'ST_RAND':ST_RAND, + ST_SYNC:'ST_SYNC', ST_RAND:'ST_RAND'} + EF_ROCKET = 1 + EF_GRENADE = 2 + EF_GIB = 4 + EF_ROTATE = 8 + EF_TRACER = 16 + EF_ZOMGIB = 32 + EF_TRACER2 = 64 + EF_TRACER3 = 128 + EFFECTS={'EF_NONE':0, 'EF_ROCKET':EF_ROCKET, 'EF_GRENADE':EF_GRENADE, + 'EF_GIB':EF_GIB, 'EF_TRACER':EF_TRACER, 'EF_ZOMGIB':EF_ZOMGIB, + 'EF_TRACER2':EF_TRACER2, 'EF_TRACER3':EF_TRACER3} + class Skin: def __init__(self): pass @@ -271,7 +287,7 @@ class MDL: self.scale_origin = (0.0, 0.0, 0.0) #FIXME self.boundingradius = 1.0 #FIXME self.eyeposition = (0.0, 0.0, 0.0) #FIXME - self.synctype = 0 #FIXME config (right default?) + self.synctype = MDL.ST_SYNC self.flags = 0 #FIXME config self.size = 0 #FIXME ??? self.skins = []