Use custom properties for model flags etc.

Eye position, auto rotation, sync type and particle effects can now all be
edited in blender: both import and export do the right thing. The settings
can be found in the "QF MDL" panel of the "Object" tab of the properties
view.
This commit is contained in:
Bill Currie 2012-04-15 21:55:23 +09:00
parent 878764f79d
commit 70f500a087
4 changed files with 110 additions and 5 deletions

View file

@ -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)

View file

@ -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'}

View file

@ -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()

View file

@ -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 = []