mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
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:
parent
878764f79d
commit
70f500a087
4 changed files with 110 additions and 5 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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 = []
|
||||
|
|
Loading…
Reference in a new issue