Adds first and final frame setting

Adds preview of mdl mins / maxs bbox
Adds author
This commit is contained in:
blubs 2023-01-21 13:41:59 -08:00
parent 2bd94d2b7a
commit 9b8f9b8077
2 changed files with 150 additions and 10 deletions

View File

@ -23,7 +23,7 @@
bl_info = { bl_info = {
"name": "Quake MDL format", "name": "Quake MDL format",
"author": "Bill Currie, Aleksander Marhall", "author": "Bill Currie, Aleksander Marhall, Luis Gutierrez",
"version": (0, 7, 0), "version": (0, 7, 0),
"blender": (2, 80, 0), "blender": (2, 80, 0),
"api": 35622, "api": 35622,
@ -47,7 +47,7 @@ if "bpy" in locals():
import bpy import bpy
from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty
from bpy.props import FloatVectorProperty, PointerProperty from bpy.props import FloatVectorProperty, PointerProperty, IntProperty, BoolProperty, PointerProperty
from bpy_extras.io_utils import ExportHelper, ImportHelper, path_reference_mode, axis_conversion from bpy_extras.io_utils import ExportHelper, ImportHelper, path_reference_mode, axis_conversion
PALETTE=( PALETTE=(
@ -72,6 +72,94 @@ EFFECTS=(
('EF_TRACER3', "Tracer 3", "Purple split trail"), ('EF_TRACER3', "Tracer 3", "Purple split trail"),
) )
import bgl
import gpu
import mathutils
from gpu_extras.batch import batch_for_shader
def mdl_draw_bbox_callback(self, context):
def draw_line(start, end, color):
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
batch = batch_for_shader(shader, 'LINES', {'pos': [start,end]})
shader.bind()
shader.uniform_float('color', color)
batch.draw(shader)
bbox_mins = context.view_layer.objects.active.qfmdl.mdl_scale_mins
bbox_maxs = context.view_layer.objects.active.qfmdl.mdl_scale_maxs
if not context.view_layer.objects.active.qfmdl.mdl_draw_bbox:
return
bbox_corners = {
'left_front_lower': mathutils.Vector((bbox_mins[0], bbox_mins[1], bbox_mins[2])),
'right_front_lower': mathutils.Vector((bbox_maxs[0], bbox_mins[1], bbox_mins[2])),
'right_back_lower': mathutils.Vector((bbox_maxs[0], bbox_maxs[1], bbox_mins[2])),
'left_back_lower': mathutils.Vector((bbox_mins[0], bbox_maxs[1], bbox_mins[2])),
'left_front_upper': mathutils.Vector((bbox_mins[0], bbox_mins[1], bbox_maxs[2])),
'right_front_upper': mathutils.Vector((bbox_maxs[0], bbox_mins[1], bbox_maxs[2])),
'right_back_upper': mathutils.Vector((bbox_maxs[0], bbox_maxs[1], bbox_maxs[2])),
'left_back_upper': mathutils.Vector((bbox_mins[0], bbox_maxs[1], bbox_maxs[2])),
}
color_red = (1.0, 0.0, 0.0, 0.7)
color_green = (0.0, 1.0, 0.0, 0.7)
color_blue = (0.0, 0.0, 1.0, 0.7)
bgl.glEnable(bgl.GL_BLEND)
bgl.glEnable(bgl.GL_LINE_SMOOTH)
bgl.glDisable(bgl.GL_DEPTH_TEST)
draw_line(bbox_corners['left_front_lower'], bbox_corners['right_front_lower'], color_red)
draw_line(bbox_corners['left_back_lower'], bbox_corners['right_back_lower'], color_red)
draw_line(bbox_corners['left_front_upper'], bbox_corners['right_front_upper'], color_red)
draw_line(bbox_corners['left_back_upper'], bbox_corners['right_back_upper'], color_red)
draw_line(bbox_corners['left_front_lower'], bbox_corners['left_back_lower'], color_green)
draw_line(bbox_corners['right_front_lower'], bbox_corners['right_back_lower'], color_green)
draw_line(bbox_corners['left_front_upper'], bbox_corners['left_back_upper'], color_green)
draw_line(bbox_corners['right_front_upper'], bbox_corners['right_back_upper'], color_green)
draw_line(bbox_corners['left_front_lower'], bbox_corners['left_front_upper'], color_blue)
draw_line(bbox_corners['right_front_lower'], bbox_corners['right_front_upper'], color_blue)
draw_line(bbox_corners['left_back_lower'], bbox_corners['left_back_upper'], color_blue)
draw_line(bbox_corners['right_back_lower'], bbox_corners['right_back_upper'], color_blue)
# bgl.glEnd()
bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_BLEND)
bgl.glDisable(bgl.GL_LINE_SMOOTH)
bgl.glEnable(bgl.GL_DEPTH_TEST)
# This dictionary is used to store bbox preview handlers
# Keys: object names
# Values: registered handlers
draw_bbox_handlers = {
}
def mdl_draw_bbox_updated(self, context):
global draw_bbox_handlers
# Disable all existing handlers:
while len(draw_bbox_handlers) > 0:
k = list(draw_bbox_handlers.keys())[0]
v = draw_bbox_handlers.pop(k)
bpy.types.SpaceView3D.draw_handler_remove(v, 'WINDOW')
# Add a new handler for this object name:
if self.mdl_draw_bbox:
obj_name = context.view_layer.objects.active.name
handler = bpy.types.SpaceView3D.draw_handler_add(mdl_draw_bbox_callback, (self,context), 'WINDOW', 'POST_VIEW')
# Store the handler to later remove it
draw_bbox_handlers[obj_name] = handler
class QFMDLSettings(bpy.types.PropertyGroup): class QFMDLSettings(bpy.types.PropertyGroup):
palette : EnumProperty( palette : EnumProperty(
items=PALETTE, items=PALETTE,
@ -79,7 +167,7 @@ class QFMDLSettings(bpy.types.PropertyGroup):
description="Palette") description="Palette")
eyeposition : FloatVectorProperty( eyeposition : FloatVectorProperty(
name="Eye Position", name="Eye Position",
description="View possion relative to object origin") description="View position relative to object origin")
synctype : EnumProperty( synctype : EnumProperty(
items=SYNCTYPE, items=SYNCTYPE,
name="Sync Type", name="Sync Type",
@ -116,15 +204,31 @@ class QFMDLSettings(bpy.types.PropertyGroup):
# name="Script", # name="Script",
# description="Script for animating frames and skins") # description="Script for animating frames and skins")
mdl_first_frame : IntProperty(
name="First Frame",
default=0,
description="First animation frame to export."
)
mdl_last_frame : IntProperty(
name="Last Frame",
default=0,
description="Final animation frame to export. (Inclusive)"
)
mdl_scale_mins : FloatVectorProperty( mdl_scale_mins : FloatVectorProperty(
name="MDL Mins", name="MDL Mins",
default=(-400.0,-100.0,-100.0), default=(-100.0,-100.0,-100.0),
description="Minimum allowed vertex coordinates") description="Minimum allowed vertex coordinates")
mdl_scale_maxs : FloatVectorProperty( mdl_scale_maxs : FloatVectorProperty(
name="MDL Maxs", name="MDL Maxs",
default=(100.0,100.0,100.0), default=(100.0,100.0,100.0),
description="Maximum allowed vertex coordinates") description="Maximum allowed vertex coordinates")
mdl_draw_bbox : BoolProperty(
name="Show MDL bounding box",
default=False,
description="Draw the specified MDL bounding box in the blender 3D viewport.",
update=mdl_draw_bbox_updated,
)
class ImportMDL6(bpy.types.Operator, ImportHelper): class ImportMDL6(bpy.types.Operator, ImportHelper):
@ -146,6 +250,9 @@ class ImportMDL6(bpy.types.Operator, ImportHelper):
keywords = self.as_keywords (ignore=("filter_glob",)) keywords = self.as_keywords (ignore=("filter_glob",))
return import_mdl.import_mdl(self, context, **keywords) return import_mdl.import_mdl(self, context, **keywords)
class ExportMDL6(bpy.types.Operator, ExportHelper): class ExportMDL6(bpy.types.Operator, ExportHelper):
'''Save a Quake MDL (v6) File''' '''Save a Quake MDL (v6) File'''
@ -183,16 +290,32 @@ class ExportMDL6(bpy.types.Operator, ExportHelper):
md16 : BoolProperty( md16 : BoolProperty(
name="16-bit", name="16-bit",
description="16 bit vertex coordinates: QuakeForge only") description="16 bit vertex coordinates: QuakeForge only")
mdl_first_frame : IntProperty(
name="Start Frame",
default=0,
description="First animation frame to export."
)
mdl_last_frame : IntProperty(
name="End Frame",
default=0,
description="Final animation frame to export. (Inclusive)"
)
mdl_scale_mins : FloatVectorProperty( mdl_scale_mins : FloatVectorProperty(
name="MDL Mins", name="MDL Mins",
default=(-100.0,-100.0,-100.0), default=(-100.0,-100.0,-100.0),
# default = bpy.context.active_object.qfmdl.mdl_scale_mins,
description="Minimum allowed vertex coordinates") description="Minimum allowed vertex coordinates")
mdl_scale_maxs : FloatVectorProperty( mdl_scale_maxs : FloatVectorProperty(
name="MDL Maxs", name="MDL Maxs",
default=(100.0,100.0,100.0), default=(100.0,100.0,100.0),
# default = bpy.context.active_object.qfmdl.mdl_scale_maxs,
description="Maximum allowed vertex coordinates") description="Maximum allowed vertex coordinates")
mdl_draw_bbox : BoolProperty(
name="Show MDL bounding box",
default=False,
description="Draw the specified MDL bounding box in the blender 3D viewport.",
update=mdl_draw_bbox_updated,
)
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@ -208,6 +331,8 @@ class ExportMDL6(bpy.types.Operator, ExportHelper):
# self.eyeposition = bpy.context.active_object.qfmdl.eyeposition # self.eyeposition = bpy.context.active_object.qfmdl.eyeposition
self.mdl_scale_mins = bpy.context.active_object.qfmdl.mdl_scale_mins self.mdl_scale_mins = bpy.context.active_object.qfmdl.mdl_scale_mins
self.mdl_scale_maxs = bpy.context.active_object.qfmdl.mdl_scale_maxs self.mdl_scale_maxs = bpy.context.active_object.qfmdl.mdl_scale_maxs
self.mdl_first_frame = bpy.context.active_object.qfmdl.mdl_first_frame
self.mdl_last_frame = bpy.context.active_object.qfmdl.mdl_last_frame
return ExportHelper.invoke(self,context,event) return ExportHelper.invoke(self,context,event)
# return {"RUNNING_MODAL"} # return {"RUNNING_MODAL"}
# return {'FINISHED'} # return {'FINISHED'}
@ -240,8 +365,13 @@ class OBJECT_PT_MDLPanel(bpy.types.Panel):
# layout.prop(obj.qfmdl, "script") # layout.prop(obj.qfmdl, "script")
layout.prop(obj.qfmdl, "xform") layout.prop(obj.qfmdl, "xform")
layout.prop(obj.qfmdl, "md16") layout.prop(obj.qfmdl, "md16")
layout.prop(obj.qfmdl, "mdl_first_frame")
layout.prop(obj.qfmdl, "mdl_last_frame")
layout.prop(obj.qfmdl, "mdl_scale_mins") layout.prop(obj.qfmdl, "mdl_scale_mins")
layout.prop(obj.qfmdl, "mdl_scale_maxs") layout.prop(obj.qfmdl, "mdl_scale_maxs")
layout.prop(obj.qfmdl, "mdl_draw_bbox")
def menu_func_import(self, context): def menu_func_import(self, context):
self.layout.operator(ImportMDL6.bl_idname, text="Quake MDL (.mdl)") self.layout.operator(ImportMDL6.bl_idname, text="Quake MDL (.mdl)")

View File

@ -247,8 +247,11 @@ def get_properties(
effects, effects,
xform, xform,
md16, md16,
mdl_first_frame,
mdl_last_frame,
mdl_scale_mins, mdl_scale_mins,
mdl_scale_maxs): mdl_scale_maxs,
mdl_draw_bbox,):
mdl.palette = MDL.PALETTE[palette] mdl.palette = MDL.PALETTE[palette]
mdl.eyeposition = eyeposition mdl.eyeposition = eyeposition
mdl.synctype = MDL.SYNCTYPE[synctype] mdl.synctype = MDL.SYNCTYPE[synctype]
@ -357,8 +360,11 @@ def export_mdl(
effects = EFFECTS[1], effects = EFFECTS[1],
xform = True, xform = True,
md16 = False, md16 = False,
mdl_first_frame=0,
mdl_last_frame=10,
mdl_scale_mins=(-100,-100,-100), mdl_scale_mins=(-100,-100,-100),
mdl_scale_maxs=(100,100,100), mdl_scale_maxs=(100,100,100),
mdl_draw_bbox=False,
): ):
obj = context.active_object obj = context.active_object
@ -382,8 +388,11 @@ def export_mdl(
effects, effects,
xform, xform,
md16, md16,
mdl_first_frame,
mdl_last_frame,
mdl_scale_mins, mdl_scale_mins,
mdl_scale_maxs): mdl_scale_maxs,
mdl_draw_bbox,):
return {'CANCELLED'} return {'CANCELLED'}
mdl.tris, mdl.stverts, vertmap = build_tris(mesh) mdl.tris, mdl.stverts, vertmap = build_tris(mesh)
@ -401,7 +410,8 @@ def export_mdl(
# Export up to the last scene frame: # Export up to the last scene frame:
# for fno in range(context.scene.frame_start, context.scene.frame_end + 1): # for fno in range(context.scene.frame_start, context.scene.frame_end + 1):
# Only export up to current frame: # Only export up to current frame:
for fno in range(context.scene.frame_start, context.scene.frame_current + 1): # for fno in range(context.scene.frame_start, context.scene.frame_current + 1):
for fno in range(mdl_first_frame, mdl_last_frame + 1):
context.scene.frame_set(fno) context.scene.frame_set(fno)
obj.update_from_editmode() obj.update_from_editmode()
depsgraph = context.evaluated_depsgraph_get() depsgraph = context.evaluated_depsgraph_get()