fix issues
- disable bmx import/export temporaryly - optimize the ui display of importing/exporting. (use box to organize props) - place button horizontally, not vertically in virtools material. - disallow apply in legacy align if no axis selected. - add applied step counter in legacy alignment. - add feedback for reseting bme material/component. (add a message box to show success)
This commit is contained in:
parent
318d661ac1
commit
680f367a42
@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
from . import PROP_preferences, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh
|
||||
from . import PROP_preferences, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_icons_manager, UTIL_ioport_shared
|
||||
|
||||
class BBP_OT_export_bmfile(bpy.types.Operator, UTIL_file_browser.ExportBmxFile):
|
||||
class BBP_OT_export_bmfile(bpy.types.Operator, UTIL_file_browser.ExportBmxFile, UTIL_ioport_shared.ExportParams):
|
||||
"""Save a Ballance Map File (BM File Spec 1.4)"""
|
||||
bl_idname = "bbp.export_bmfile"
|
||||
bl_label = "Export BM (Ballance Map) File"
|
||||
@ -12,12 +12,18 @@ class BBP_OT_export_bmfile(bpy.types.Operator, UTIL_file_browser.ExportBmxFile):
|
||||
return PROP_preferences.get_raw_preferences().has_valid_blc_tex_folder()
|
||||
|
||||
def execute(self, context):
|
||||
UTIL_functions.message_box((self.general_get_filename(), ), 'Export BM File Path', 'INFO')
|
||||
UTIL_functions.message_box(
|
||||
('This function not supported yet.', ),
|
||||
'No Implement',
|
||||
UTIL_icons_manager.BlenderPresetIcons.Error.value
|
||||
)
|
||||
self.report({'INFO'}, "BM File Exporting Finished.")
|
||||
return {'FINISHED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text = 'Export Target')
|
||||
self.draw_export_params(layout.box())
|
||||
|
||||
def register() -> None:
|
||||
bpy.utils.register_class(BBP_OT_export_bmfile)
|
||||
|
@ -68,15 +68,21 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text = 'Export Target')
|
||||
self.draw_export_params(layout)
|
||||
self.draw_export_params(layout.box())
|
||||
|
||||
layout.separator()
|
||||
layout.label(text = 'Virtools Params')
|
||||
self.draw_virtools_params(layout)
|
||||
layout.label(text = 'Global Texture Save Option')
|
||||
layout.prop(self, 'texture_save_opt', text = '')
|
||||
layout.prop(self, 'use_compress')
|
||||
box = layout.box()
|
||||
self.draw_virtools_params(box)
|
||||
|
||||
box.separator()
|
||||
box.label(text = 'Global Texture Save Option')
|
||||
box.prop(self, 'texture_save_opt', text = '')
|
||||
|
||||
box.separator()
|
||||
box.prop(self, 'use_compress')
|
||||
if self.use_compress:
|
||||
layout.prop(self, 'compress_level')
|
||||
box.prop(self, 'compress_level')
|
||||
|
||||
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
|
||||
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
|
||||
|
@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
from . import PROP_preferences, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh
|
||||
from . import PROP_preferences, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_icons_manager, UTIL_ioport_shared
|
||||
|
||||
class BBP_OT_import_bmfile(bpy.types.Operator, UTIL_file_browser.ImportBmxFile):
|
||||
class BBP_OT_import_bmfile(bpy.types.Operator, UTIL_file_browser.ImportBmxFile, UTIL_ioport_shared.ImportParams):
|
||||
"""Load a Ballance Map File (BM File Spec 1.4)"""
|
||||
bl_idname = "bbp.import_bmfile"
|
||||
bl_label = "Import BM (Ballance Map) File"
|
||||
@ -12,12 +12,18 @@ class BBP_OT_import_bmfile(bpy.types.Operator, UTIL_file_browser.ImportBmxFile):
|
||||
return PROP_preferences.get_raw_preferences().has_valid_blc_tex_folder()
|
||||
|
||||
def execute(self, context):
|
||||
UTIL_functions.message_box((self.general_get_filename(), ), 'Import BM File Path', 'INFO')
|
||||
UTIL_functions.message_box(
|
||||
('This function not supported yet.', ),
|
||||
'No Implement',
|
||||
UTIL_icons_manager.BlenderPresetIcons.Error.value
|
||||
)
|
||||
self.report({'INFO'}, "BM File Importing Finished.")
|
||||
return {'FINISHED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text = 'Conflict Options')
|
||||
self.draw_import_params(layout.box())
|
||||
|
||||
def register() -> None:
|
||||
bpy.utils.register_class(BBP_OT_import_bmfile)
|
||||
|
@ -29,10 +29,10 @@ class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtool
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text = 'Conflict Options')
|
||||
self.draw_import_params(layout)
|
||||
self.draw_import_params(layout.box())
|
||||
layout.separator()
|
||||
layout.label(text = 'Virtools Params')
|
||||
self.draw_virtools_params(layout)
|
||||
self.draw_virtools_params(layout.box())
|
||||
|
||||
def _import_virtools(file_name_: str, encodings_: tuple[str]) -> None:
|
||||
# create temp folder
|
||||
|
@ -82,8 +82,21 @@ class BBP_OT_legacy_align(bpy.types.Operator):
|
||||
if self.apply_flag == True: return
|
||||
self.apply_flag = True
|
||||
|
||||
# add a new entry in history
|
||||
self.align_history.add()
|
||||
# check whether add new entry
|
||||
# if no selected axis, this alignment is invalid
|
||||
entry: BBP_PG_legacy_align_history = self.align_history[-1]
|
||||
if entry.align_x == True or entry.align_y == True or entry.align_z == True:
|
||||
# valid one
|
||||
# add a new entry in history
|
||||
self.align_history.add()
|
||||
else:
|
||||
# invalid one
|
||||
# reset all data to default
|
||||
entry.align_x = False
|
||||
entry.align_y = False
|
||||
entry.align_z = False
|
||||
entry.current_align_mode = _g_EnumHelper_AlignMode.to_selection(AlignMode.AxisCenter)
|
||||
entry.target_align_mode = _g_EnumHelper_AlignMode.to_selection(AlignMode.AxisCenter)
|
||||
|
||||
# reset hinder
|
||||
self.recursive_hinder = False
|
||||
@ -142,7 +155,7 @@ class BBP_OT_legacy_align(bpy.types.Operator):
|
||||
col = layout.column()
|
||||
|
||||
# show axis
|
||||
col.label(text="Align Axis")
|
||||
col.label(text="Align Axis (Multi-selection)")
|
||||
row = col.row()
|
||||
row.prop(entry, "align_x", toggle = 1)
|
||||
row.prop(entry, "align_y", toggle = 1)
|
||||
@ -152,12 +165,17 @@ class BBP_OT_legacy_align(bpy.types.Operator):
|
||||
col.separator()
|
||||
col.label(text = 'Current Object (Active Object)')
|
||||
col.prop(entry, "current_align_mode", expand = True)
|
||||
col.label(text = 'Target Objects (Other Objects)')
|
||||
col.label(text = 'Target Objects (Selected Objects)')
|
||||
col.prop(entry, "target_align_mode", expand = True)
|
||||
|
||||
# show apply button
|
||||
col.separator()
|
||||
col.prop(self, 'apply_flag', text = 'Apply', icon = 'CHECKMARK', toggle = 1)
|
||||
conditional_disable_area = col.column()
|
||||
# only allow Apply when there is a selected axis
|
||||
conditional_disable_area.enabled = entry.align_x == True or entry.align_y == True or entry.align_z == True
|
||||
# show apply and counter
|
||||
conditional_disable_area.prop(self, 'apply_flag', text = 'Apply', icon = 'CHECKMARK', toggle = 1)
|
||||
conditional_disable_area.label(text = f'Total {len(self.align_history) - 1} applied alignments')
|
||||
|
||||
#region Core Functions
|
||||
|
||||
|
@ -54,7 +54,8 @@ class BBP_OT_select_object_by_virtools_group(bpy.types.Operator, PROP_virtools_g
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text='Selection Mode')
|
||||
layout.prop(self, 'selection_mode', expand = True)
|
||||
sublayout = layout.column() # make selection expand vertically, not horizontal.
|
||||
sublayout.prop(self, 'selection_mode', expand = True)
|
||||
|
||||
layout.separator()
|
||||
layout.label(text='Group Parameters')
|
||||
|
@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
import os, typing, enum, array
|
||||
from . import PROP_virtools_mesh
|
||||
from . import UTIL_functions, UTIL_file_io, UTIL_blender_mesh, UTIL_virtools_types
|
||||
from . import UTIL_functions, UTIL_file_io, UTIL_blender_mesh, UTIL_virtools_types, UTIL_icons_manager
|
||||
|
||||
#region Raw Elements Operations
|
||||
|
||||
@ -349,6 +349,12 @@ class BBP_OT_reset_ballance_elements(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
reset_ballance_elements(context.scene)
|
||||
# show a window to let user know, not silence
|
||||
UTIL_functions.message_box(
|
||||
('Reset OK.', ),
|
||||
"Reset Result",
|
||||
UTIL_icons_manager.BlenderPresetIcons.Info.value
|
||||
)
|
||||
return {'FINISHED'}
|
||||
|
||||
class BBP_PT_ballance_elements(bpy.types.Panel):
|
||||
|
@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
import typing, enum, copy
|
||||
from . import PROP_virtools_material, PROP_virtools_texture
|
||||
from . import UTIL_ballance_texture, UTIL_functions
|
||||
from . import UTIL_ballance_texture, UTIL_functions, UTIL_icons_manager
|
||||
|
||||
#region BME Material Presets
|
||||
|
||||
@ -239,6 +239,12 @@ class BBP_OT_reset_bme_materials(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
reset_bme_materials(context.scene)
|
||||
# show a window to let user know, not silence
|
||||
UTIL_functions.message_box(
|
||||
('Reset OK.', ),
|
||||
"Reset Result",
|
||||
UTIL_icons_manager.BlenderPresetIcons.Info.value
|
||||
)
|
||||
return {'FINISHED'}
|
||||
|
||||
class BBP_PT_bme_materials(bpy.types.Panel):
|
||||
|
@ -656,8 +656,9 @@ class BBP_PT_virtools_material(bpy.types.Panel):
|
||||
props: BBP_PG_virtools_material = get_virtools_material(context.material)
|
||||
|
||||
# draw operator
|
||||
layout.operator(BBP_OT_preset_virtools_material.bl_idname, icon="PRESET")
|
||||
layout.operator(BBP_OT_apply_virtools_material.bl_idname, icon="NODETREE")
|
||||
row = layout.row()
|
||||
row.operator(BBP_OT_preset_virtools_material.bl_idname, text = 'Preset', icon = "PRESET")
|
||||
row.operator(BBP_OT_apply_virtools_material.bl_idname, text = 'Apply', icon = "NODETREE")
|
||||
|
||||
# draw data
|
||||
layout.label(text="Color Parameters")
|
||||
|
@ -1,6 +1,6 @@
|
||||
import bpy
|
||||
import enum
|
||||
from . import UTIL_virtools_types
|
||||
from . import UTIL_virtools_types, UTIL_functions
|
||||
from . import PROP_ptrprop_resolver
|
||||
|
||||
## Intent
|
||||
@ -9,65 +9,90 @@ from . import PROP_ptrprop_resolver
|
||||
# and call general getter to get user selected data.
|
||||
# Also provide draw function thus caller do not need draw the params themselves.
|
||||
|
||||
class ConflictStrategy(enum.IntEnum):
|
||||
Rename = enum.auto()
|
||||
Current = enum.auto()
|
||||
Replace = enum.auto()
|
||||
_g_ConflictStrategyDesc: dict[ConflictStrategy, tuple[str, str]] = {
|
||||
ConflictStrategy.Rename: ('Rename', 'Rename the new one'),
|
||||
ConflictStrategy.Current: ('Use Current', 'Use current one'),
|
||||
ConflictStrategy.Replace: ('Replace', 'Replace the old one with new one'),
|
||||
}
|
||||
_g_EnumHelper_ConflictStrategy: UTIL_functions.EnumPropHelper = UTIL_functions.EnumPropHelper(
|
||||
ConflictStrategy,
|
||||
lambda x: str(x.value),
|
||||
lambda x: ConflictStrategy(int(x)),
|
||||
lambda x: _g_ConflictStrategyDesc[x][0],
|
||||
lambda x: _g_ConflictStrategyDesc[x][1],
|
||||
lambda _: ''
|
||||
)
|
||||
|
||||
class ImportParams():
|
||||
texture_conflict_strategy: bpy.props.EnumProperty(
|
||||
name = "Texture name conflict",
|
||||
items = (
|
||||
('NEW', "New Instance", "Create a new instance"),
|
||||
('CURRENT', "Use Current", "Use current one"),
|
||||
),
|
||||
name = "Texture Name Conflict",
|
||||
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
||||
description = "Define how to process texture name conflict",
|
||||
default = 'CURRENT',
|
||||
)
|
||||
default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Current),
|
||||
)
|
||||
|
||||
material_conflict_strategy: bpy.props.EnumProperty(
|
||||
name = "Material name conflict",
|
||||
items = (
|
||||
('RENAME', "Rename", "Rename the new one"),
|
||||
('CURRENT', "Use Current", "Use current one"),
|
||||
),
|
||||
name = "Material Name Conflict",
|
||||
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
||||
description = "Define how to process material name conflict",
|
||||
default = 'RENAME',
|
||||
)
|
||||
default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename),
|
||||
)
|
||||
|
||||
mesh_conflict_strategy: bpy.props.EnumProperty(
|
||||
name = "Mesh name conflict",
|
||||
items = (
|
||||
('RENAME', "Rename", "Rename the new one"),
|
||||
('CURRENT', "Use Current", "Use current one"),
|
||||
),
|
||||
name = "Mesh Name Conflict",
|
||||
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
||||
description = "Define how to process mesh name conflict",
|
||||
default = 'RENAME',
|
||||
)
|
||||
default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename),
|
||||
)
|
||||
|
||||
object_conflict_strategy: bpy.props.EnumProperty(
|
||||
name = "Object name conflict",
|
||||
items = (
|
||||
('RENAME', "Rename", "Rename the new one"),
|
||||
('CURRENT', "Use Current", "Use current one"),
|
||||
),
|
||||
name = "Object Name Conflict",
|
||||
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
||||
description = "Define how to process object name conflict",
|
||||
default = 'RENAME',
|
||||
)
|
||||
default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename),
|
||||
)
|
||||
|
||||
def draw_import_params(self, layout: bpy.types.UILayout) -> None:
|
||||
layout.prop(self, 'object_conflict_strategy')
|
||||
layout.prop(self, 'mesh_conflict_strategy')
|
||||
layout.prop(self, 'material_conflict_strategy')
|
||||
layout.prop(self, 'texture_conflict_strategy')
|
||||
layout.label(text = 'Object Name Conflict')
|
||||
layout.prop(self, 'object_conflict_strategy', text = '')
|
||||
layout.label(text = 'Mesh Name Conflict')
|
||||
layout.prop(self, 'mesh_conflict_strategy', text = '')
|
||||
layout.label(text = 'Material Name Conflict')
|
||||
layout.prop(self, 'material_conflict_strategy', text = '')
|
||||
layout.label(text = 'Texture Name Conflict')
|
||||
layout.prop(self, 'texture_conflict_strategy', text = '')
|
||||
|
||||
def general_get_texture_conflict_strategy(self) -> ConflictStrategy:
|
||||
return _g_EnumHelper_ConflictStrategy.get_selection(self.texture_conflict_strategy)
|
||||
|
||||
def general_get_material_conflict_strategy(self) -> ConflictStrategy:
|
||||
return _g_EnumHelper_ConflictStrategy.get_selection(self.material_conflict_strategy)
|
||||
|
||||
def general_get_mesh_conflict_strategy(self) -> ConflictStrategy:
|
||||
return _g_EnumHelper_ConflictStrategy.get_selection(self.mesh_conflict_strategy)
|
||||
|
||||
def general_get_object_conflict_strategy(self) -> ConflictStrategy:
|
||||
return _g_EnumHelper_ConflictStrategy.get_selection(self.object_conflict_strategy)
|
||||
|
||||
class ExportParams():
|
||||
export_mode: bpy.props.EnumProperty(
|
||||
name = "Export Mode",
|
||||
items = (
|
||||
('COLLECTION', "Collection", "Export a collection"),
|
||||
('OBJECT', "Object", "Export an object"),
|
||||
('COLLECTION', "Collection", "Export a collection", 'OUTLINER_COLLECTION', 0),
|
||||
('OBJECT', "Object", "Export an object", 'OBJECT_DATA', 1),
|
||||
),
|
||||
)
|
||||
|
||||
def draw_export_params(self, layout: bpy.types.UILayout) -> None:
|
||||
# make prop expand horizontaly, not vertical.
|
||||
sublayout = layout.row()
|
||||
# draw switch
|
||||
layout.prop(self, "export_mode", expand = True)
|
||||
sublayout.prop(self, "export_mode", expand = True)
|
||||
|
||||
# draw picker
|
||||
if self.export_mode == 'COLLECTION':
|
||||
PROP_ptrprop_resolver.draw_export_collection(layout)
|
||||
@ -96,7 +121,8 @@ class VirtoolsParams():
|
||||
)
|
||||
|
||||
def draw_virtools_params(self, layout: bpy.types.UILayout) -> None:
|
||||
layout.prop(self, 'vt_encodings')
|
||||
layout.label(text = 'Encodings')
|
||||
layout.prop(self, 'vt_encodings', text = '')
|
||||
|
||||
def general_get_vt_encodings(self) -> tuple[str]:
|
||||
# get encoding, split it by `;` and strip blank chars.
|
||||
@ -108,6 +134,13 @@ class ExportEditModeBackup():
|
||||
The class which save Edit Mode when exporting and restore it after exporting.
|
||||
Because edit mode is not allowed when exporting.
|
||||
Support `with` statement.
|
||||
|
||||
```
|
||||
with ExportEditModeBackup():
|
||||
# do some exporting work
|
||||
blabla()
|
||||
# restore automatically when exiting "with"
|
||||
```
|
||||
"""
|
||||
mInEditMode: bool
|
||||
|
||||
@ -127,4 +160,28 @@ class ExportEditModeBackup():
|
||||
bpy.ops.object.editmode_toggle()
|
||||
self.mInEditMode = False
|
||||
|
||||
class ConflictResolver():
|
||||
"""
|
||||
This class frequently used when importing objects.
|
||||
This class accept 4 conflict strategies for object, mesh, material and texture,
|
||||
and provide 4 general creation functions to handle these strategies.
|
||||
Each general creation functions will return an instance and a bool indicating whether this instance need be initialized.
|
||||
|
||||
This class also provide 3 static common creation functions without considering conflict.
|
||||
They just a redirect calling to `bpy.data.xxx.new()`.
|
||||
No static texture (Image) creation function because texture is not created from `bpy.data.images`.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def create_object(name: str, data: bpy.types.Mesh) -> bpy.types.Object:
|
||||
return bpy.data.objects.new(name, data)
|
||||
|
||||
@staticmethod
|
||||
def create_mesh(name: str) -> bpy.types.Mesh:
|
||||
return bpy.data.meshes.new(name)
|
||||
|
||||
@staticmethod
|
||||
def create_material(name: str) -> bpy.types.Material:
|
||||
return bpy.data.materials.new(name)
|
||||
|
||||
|
||||
|
@ -373,7 +373,8 @@ class VirtoolsGroupConvention():
|
||||
|
||||
case BallanceObjectType.COMPONENT:
|
||||
# group into component type
|
||||
gp.add_group(info.mComponentType)
|
||||
# use typing.cast() to force linter accept it because None is impossible
|
||||
gp.add_group(typing.cast(str, info.mComponentType))
|
||||
|
||||
# group to sector
|
||||
if info.mSector == 9:
|
||||
|
@ -103,12 +103,12 @@ MenuDrawer_t = typing.Callable[[typing.Any, typing.Any], None]
|
||||
|
||||
def menu_drawer_import(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.operator(OP_IMPORT_bmfile.BBP_OT_import_bmfile.bl_idname, text = "Ballance Map (.bmx)")
|
||||
#layout.operator(OP_IMPORT_bmfile.BBP_OT_import_bmfile.bl_idname, text = "Ballance Map (.bmx)")
|
||||
layout.operator(OP_IMPORT_virtools.BBP_OT_import_virtools.bl_idname, text = "Virtools File (.nmo/.cmo/.vmo) (experimental)")
|
||||
|
||||
def menu_drawer_export(self, context) -> None:
|
||||
layout: bpy.types.UILayout = self.layout
|
||||
layout.operator(OP_EXPORT_bmfile.BBP_OT_export_bmfile.bl_idname, text = "Ballance Map (.bmx)")
|
||||
#layout.operator(OP_EXPORT_bmfile.BBP_OT_export_bmfile.bl_idname, text = "Ballance Map (.bmx)")
|
||||
layout.operator(OP_EXPORT_virtools.BBP_OT_export_virtools.bl_idname, text = "Virtools File (.nmo/.cmo/.vmo) (experimental)")
|
||||
|
||||
def menu_drawer_view3d(self, context) -> None:
|
||||
|
Loading…
Reference in New Issue
Block a user