[feat] improve element adder
- fix ambiguous default side setter for floor adder. use "update" field of EnumProperty instead. also applied for dup element with span adder. - divide component adder into 3 different adder, to process different add strategies. - update elements placeholder adder. this change will force all element placeholder share a single mesh in the whole map. - add series element adder.
This commit is contained in:
parent
d292ce389a
commit
e153e51abd
@ -1,12 +1,34 @@
|
|||||||
import bpy, mathutils
|
import bpy, mathutils
|
||||||
from . import UTILS_constants, UTILS_functions, UTILS_icons_manager
|
from . import UTILS_constants, UTILS_functions, UTILS_icons_manager
|
||||||
|
|
||||||
# ================================================= actual add
|
# =============== Common Class ================
|
||||||
|
class common_add_component_props(bpy.types.Operator):
|
||||||
|
attentionElements = ("PC_TwoFlames", "PR_Resetpoint")
|
||||||
|
uniqueElements = ("PS_FourFlames", "PE_Balloon")
|
||||||
|
|
||||||
class BALLANCE_OT_add_components(bpy.types.Operator):
|
elements_sector: bpy.props.IntProperty(
|
||||||
"""Add sector related elements"""
|
name="Sector",
|
||||||
|
description="Define which sector the object will be grouped in",
|
||||||
|
min=1, max=8,
|
||||||
|
default=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_component_name(self, raw_comp_name):
|
||||||
|
if raw_comp_name in self.uniqueElements:
|
||||||
|
return raw_comp_name + "_01"
|
||||||
|
elif raw_comp_name in self.attentionElements:
|
||||||
|
return raw_comp_name + "_0" + str(self.elements_sector)
|
||||||
|
else:
|
||||||
|
return raw_comp_name + "_0" + str(self.elements_sector) + "_"
|
||||||
|
|
||||||
|
def parent_draw(self, parent_layout, raw_comp_name):
|
||||||
|
if raw_comp_name not in self.uniqueElements:
|
||||||
|
parent_layout.prop(self, 'elements_sector')
|
||||||
|
|
||||||
|
class BALLANCE_OT_add_components(common_add_component_props):
|
||||||
|
"""Add Elements"""
|
||||||
bl_idname = "ballance.add_components"
|
bl_idname = "ballance.add_components"
|
||||||
bl_label = "Add elements"
|
bl_label = "Add Elements"
|
||||||
bl_options = {'UNDO'}
|
bl_options = {'UNDO'}
|
||||||
|
|
||||||
elements_type: bpy.props.EnumProperty(
|
elements_type: bpy.props.EnumProperty(
|
||||||
@ -20,52 +42,17 @@ class BALLANCE_OT_add_components(bpy.types.Operator):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
attentionElements = ("PC_TwoFlames", "PR_Resetpoint")
|
|
||||||
uniqueElements = ("PS_FourFlames", "PE_Balloon")
|
|
||||||
canDuplicatedElements = ('P_Extra_Point', 'P_Modul_18', 'P_Modul_26')
|
|
||||||
|
|
||||||
elements_sector: bpy.props.IntProperty(
|
|
||||||
name="Sector",
|
|
||||||
description="Define which sector the object will be grouped in",
|
|
||||||
min=1, max=8,
|
|
||||||
default=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
elements_duplicated: bpy.props.BoolProperty(
|
|
||||||
name="Duplicated",
|
|
||||||
description="Whether duplicate elements (Nong xxx / 脓xxx)",
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
elements_dup_times: bpy.props.IntProperty(
|
|
||||||
name="Duplication Times",
|
|
||||||
description="How many this element should be duplicated.",
|
|
||||||
min=1, max=64,
|
|
||||||
soft_min=1, soft_max=32,
|
|
||||||
default=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
# get name
|
# get name
|
||||||
if self.elements_type in self.uniqueElements:
|
finalObjectName = self.get_component_name(self.elements_type)
|
||||||
finalObjectName = self.elements_type + "_01"
|
|
||||||
elif self.elements_type in self.attentionElements:
|
|
||||||
finalObjectName = self.elements_type + "_0" + str(self.elements_sector)
|
|
||||||
else:
|
|
||||||
finalObjectName = self.elements_type + "_0" + str(self.elements_sector) + "_"
|
|
||||||
|
|
||||||
# create object
|
# create object
|
||||||
loadedMesh = UTILS_functions.load_component(
|
loadedMesh = UTILS_functions.load_component(
|
||||||
UTILS_constants.bmfile_componentList.index(self.elements_type))
|
UTILS_constants.bmfile_componentList.index(self.elements_type)
|
||||||
|
)
|
||||||
obj = bpy.data.objects.new(finalObjectName, loadedMesh)
|
obj = bpy.data.objects.new(finalObjectName, loadedMesh)
|
||||||
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
||||||
|
|
||||||
# extra duplication
|
|
||||||
if (self.elements_type in self.canDuplicatedElements) and self.elements_duplicated:
|
|
||||||
for i in range(self.elements_dup_times - 1):
|
|
||||||
obj = bpy.data.objects.new(finalObjectName, loadedMesh)
|
|
||||||
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
|
||||||
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
@ -76,16 +63,148 @@ class BALLANCE_OT_add_components(bpy.types.Operator):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
# attension notice
|
# attension notice
|
||||||
if self.elements_type in self.attentionElements:
|
if self.elements_type in self.attentionElements:
|
||||||
layout.label(text="Please note that sector is suffix.")
|
layout.label(text="NOTE: Check Sector ID carefully.")
|
||||||
if self.elements_type in self.canDuplicatedElements:
|
if self.elements_type in self.uniqueElements:
|
||||||
layout.label(text="This element can use duplication feature.")
|
layout.label(text="NOTE: This element have unique name.")
|
||||||
|
|
||||||
# cfg
|
# cfg
|
||||||
layout.prop(self, "elements_type")
|
layout.prop(self, "elements_type")
|
||||||
if self.elements_type not in self.uniqueElements:
|
self.parent_draw(layout, self.elements_type)
|
||||||
layout.prop(self, "elements_sector")
|
|
||||||
|
|
||||||
if self.elements_type in self.canDuplicatedElements:
|
|
||||||
layout.separator()
|
|
||||||
layout.prop(self, "elements_duplicated")
|
class BALLANCE_OT_add_components_dup(common_add_component_props):
|
||||||
layout.prop(self, "elements_dup_times")
|
"""Add Duplicated Elements"""
|
||||||
|
bl_idname = "ballance.add_components_dup"
|
||||||
|
bl_label = "Add Duplicated Elements"
|
||||||
|
bl_options = {'UNDO'}
|
||||||
|
|
||||||
|
elements_type: bpy.props.EnumProperty(
|
||||||
|
name="Type",
|
||||||
|
description="This element type",
|
||||||
|
#items=tuple(map(lambda x: (x, x, ""), UTILS_constants.bmfile_componentList)),
|
||||||
|
items=tuple(
|
||||||
|
# token, display name, descriptions, icon, index
|
||||||
|
(blk, blk, "", UTILS_icons_manager.get_element_icon(blk), idx)
|
||||||
|
for idx, blk in enumerate(
|
||||||
|
('P_Extra_Point', 'P_Modul_18', 'P_Modul_26')
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
elements_dup_times: bpy.props.IntProperty(
|
||||||
|
name="Duplication Count",
|
||||||
|
description="How many this element should be duplicated.",
|
||||||
|
min=2, max=64,
|
||||||
|
soft_min=2, soft_max=32,
|
||||||
|
default=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# get name
|
||||||
|
finalObjectName = self.get_component_name(self.elements_type)
|
||||||
|
|
||||||
|
# load mesh
|
||||||
|
loadedMesh = UTILS_functions.load_component(
|
||||||
|
UTILS_constants.bmfile_componentList.index(self.elements_type)
|
||||||
|
)
|
||||||
|
# create object
|
||||||
|
for i in range(self.elements_dup_times):
|
||||||
|
obj = bpy.data.objects.new(finalObjectName, loadedMesh)
|
||||||
|
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
wm = context.window_manager
|
||||||
|
return wm.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, "elements_type")
|
||||||
|
self.parent_draw(layout, self.elements_type)
|
||||||
|
layout.prop(self, "elements_dup_times")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class BALLANCE_OT_add_components_series(common_add_component_props):
|
||||||
|
"""Add Elements with a Series."""
|
||||||
|
bl_idname = "ballance.add_components_series"
|
||||||
|
bl_label = "Add Series Elements"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
supported_series = {
|
||||||
|
# format: key: (description: str, real_component: str, unit_transition: mathutils.Vector, default_span: float)
|
||||||
|
# key will become enum property's identifier
|
||||||
|
"MODUL_41": ('Tilting Block Series', 'P_Modul_41', mathutils.Vector((1.0, 0.0, 0.0)), 6.0022),
|
||||||
|
"MODUL_18_V": ('Fan Vertical Series', 'P_Modul_18', mathutils.Vector((0.0, 0.0, 1.0)), 15),
|
||||||
|
"MODUL_18_H": ('Fan Horizonal Series', 'P_Modul_18', mathutils.Vector((1.0, 0.0, 0.0)), 30),
|
||||||
|
}
|
||||||
|
|
||||||
|
# the updator for default span
|
||||||
|
def element_type_updated(self, context):
|
||||||
|
# set span
|
||||||
|
self.elements_span = BALLANCE_OT_add_components_series.supported_series[self.elements_type][3]
|
||||||
|
|
||||||
|
# blender required
|
||||||
|
return None
|
||||||
|
|
||||||
|
elements_type: bpy.props.EnumProperty(
|
||||||
|
name="Type",
|
||||||
|
description="This element type",
|
||||||
|
#items=tuple(map(lambda x: (x, x, ""), UTILS_constants.bmfile_componentList)),
|
||||||
|
items=tuple(
|
||||||
|
# token, display name, descriptions, icon, index
|
||||||
|
(skey, sitem[0], "", UTILS_icons_manager.get_element_icon(sitem[1]), idx)
|
||||||
|
for (idx, (skey, sitem)) in enumerate(supported_series.items())
|
||||||
|
),
|
||||||
|
default=0,
|
||||||
|
update=element_type_updated
|
||||||
|
)
|
||||||
|
|
||||||
|
elements_dup_times: bpy.props.IntProperty(
|
||||||
|
name="Duplication Count",
|
||||||
|
description="How many this element should be duplicated.",
|
||||||
|
min=2, max=64,
|
||||||
|
soft_min=2, soft_max=32,
|
||||||
|
default=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
elements_span: bpy.props.FloatProperty(
|
||||||
|
name="Elements Span",
|
||||||
|
description="The span between each elements.",
|
||||||
|
min=0.0,
|
||||||
|
default=0.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
# force trigger span update once to treat span normally
|
||||||
|
self.element_type_updated(context)
|
||||||
|
|
||||||
|
return self.execute(context)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
# get unit span and real element name for loading mesh and creating name
|
||||||
|
(_, real_element_name, unit_span, _) = self.supported_series[self.elements_type]
|
||||||
|
|
||||||
|
# get name
|
||||||
|
finalObjectName = self.get_component_name(real_element_name)
|
||||||
|
# load mesh
|
||||||
|
loadedMesh = UTILS_functions.load_component(
|
||||||
|
UTILS_constants.bmfile_componentList.index(real_element_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
# create object
|
||||||
|
for i in range(self.elements_dup_times):
|
||||||
|
obj = bpy.data.objects.new(finalObjectName, loadedMesh)
|
||||||
|
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
||||||
|
obj.matrix_world.translation += unit_span * (self.elements_span * i)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, "elements_type")
|
||||||
|
self.parent_draw(layout, self.elements_type)
|
||||||
|
layout.prop(self, "elements_dup_times")
|
||||||
|
layout.prop(self, "elements_span")
|
||||||
|
@ -12,6 +12,23 @@ class BALLANCE_OT_add_floors(bpy.types.Operator):
|
|||||||
bl_label = "Add floor"
|
bl_label = "Add floor"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
# the updator for default side value
|
||||||
|
def floor_type_updated(self, context):
|
||||||
|
# get floor prototype
|
||||||
|
floor_prototype = UTILS_constants.floor_blockDict[self.floor_type]
|
||||||
|
|
||||||
|
# try sync default value
|
||||||
|
default_sides = floor_prototype['DefaultSideConfig']
|
||||||
|
self.use_2d_top = default_sides['UseTwoDTop']
|
||||||
|
self.use_2d_right = default_sides['UseTwoDRight']
|
||||||
|
self.use_2d_bottom = default_sides['UseTwoDBottom']
|
||||||
|
self.use_2d_left = default_sides['UseTwoDLeft']
|
||||||
|
self.use_3d_top = default_sides['UseThreeDTop']
|
||||||
|
self.use_3d_bottom = default_sides['UseThreeDBottom']
|
||||||
|
|
||||||
|
# blender required
|
||||||
|
return None
|
||||||
|
|
||||||
floor_type: bpy.props.EnumProperty(
|
floor_type: bpy.props.EnumProperty(
|
||||||
name="Type",
|
name="Type",
|
||||||
description="Floor type",
|
description="Floor type",
|
||||||
@ -25,7 +42,7 @@ class BALLANCE_OT_add_floors(bpy.types.Operator):
|
|||||||
(blk, blk, "", UTILS_icons_manager.get_floor_icon(blk), idx)
|
(blk, blk, "", UTILS_icons_manager.get_floor_icon(blk), idx)
|
||||||
for idx, blk in enumerate(UTILS_constants.floor_blockDict.keys())
|
for idx, blk in enumerate(UTILS_constants.floor_blockDict.keys())
|
||||||
),
|
),
|
||||||
|
update=floor_type_updated
|
||||||
)
|
)
|
||||||
|
|
||||||
expand_length_1 : bpy.props.IntProperty(
|
expand_length_1 : bpy.props.IntProperty(
|
||||||
@ -74,8 +91,6 @@ class BALLANCE_OT_add_floors(bpy.types.Operator):
|
|||||||
default=True
|
default=True
|
||||||
)
|
)
|
||||||
|
|
||||||
previous_floor_type = ''
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(self, context):
|
def poll(self, context):
|
||||||
prefs = bpy.context.preferences.addons[__package__].preferences
|
prefs = bpy.context.preferences.addons[__package__].preferences
|
||||||
@ -130,27 +145,15 @@ class BALLANCE_OT_add_floors(bpy.types.Operator):
|
|||||||
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
UTILS_functions.add_into_scene_and_move_to_cursor(obj)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
# yyc marked. Blumia reported.
|
# yyc marked. Blumia reported.
|
||||||
# prepare settings before registing
|
# prepare settings before registing
|
||||||
# otherwise the mesh will not be created when first run.
|
# otherwise the mesh will not be created when first run.
|
||||||
# (do not change any properties)
|
# (do not change any properties)
|
||||||
|
|
||||||
# get floor prototype
|
# yyc marked again.
|
||||||
floor_prototype = UTILS_constants.floor_blockDict[self.floor_type]
|
# now I migrate default side value setter to updator of enum property.
|
||||||
|
# nothing need to process in here now.
|
||||||
# try sync default value
|
|
||||||
if self.previous_floor_type != self.floor_type:
|
|
||||||
self.previous_floor_type = self.floor_type
|
|
||||||
|
|
||||||
default_sides = floor_prototype['DefaultSideConfig']
|
|
||||||
self.use_2d_top = default_sides['UseTwoDTop']
|
|
||||||
self.use_2d_right = default_sides['UseTwoDRight']
|
|
||||||
self.use_2d_bottom = default_sides['UseTwoDBottom']
|
|
||||||
self.use_2d_left = default_sides['UseTwoDLeft']
|
|
||||||
self.use_3d_top = default_sides['UseThreeDTop']
|
|
||||||
self.use_3d_bottom = default_sides['UseThreeDBottom']
|
|
||||||
|
|
||||||
return self.execute(context)
|
return self.execute(context)
|
||||||
|
|
||||||
|
@ -116,8 +116,21 @@ def parse_material_nodes(mtl):
|
|||||||
# load component
|
# load component
|
||||||
|
|
||||||
def load_component(component_id):
|
def load_component(component_id):
|
||||||
# get file first
|
# get component name from id
|
||||||
component_name = UTILS_constants.bmfile_componentList[component_id]
|
component_name = UTILS_constants.bmfile_componentList[component_id]
|
||||||
|
|
||||||
|
# create real mesh.
|
||||||
|
# if component mesh is existed, use existed one.
|
||||||
|
(mesh, skip_init) = create_instance_with_option(
|
||||||
|
UTILS_constants.BmfileInfoType.MESH,
|
||||||
|
"BlcBldPlg_EleMesh_" + component_name,
|
||||||
|
'CURRENT'
|
||||||
|
)
|
||||||
|
if skip_init:
|
||||||
|
return mesh
|
||||||
|
|
||||||
|
# mesh is not existing. start to load mesh
|
||||||
|
# get file first
|
||||||
selected_file = os.path.join(
|
selected_file = os.path.join(
|
||||||
os.path.dirname(__file__),
|
os.path.dirname(__file__),
|
||||||
'meshes',
|
'meshes',
|
||||||
@ -126,9 +139,6 @@ def load_component(component_id):
|
|||||||
|
|
||||||
# read file. please note this sector is sync with import_bm's mesh's code. when something change, please change each other.
|
# read file. please note this sector is sync with import_bm's mesh's code. when something change, please change each other.
|
||||||
fmesh = open(selected_file, 'rb')
|
fmesh = open(selected_file, 'rb')
|
||||||
|
|
||||||
# create real mesh, we don't need to consider name. blender will solve duplicated name
|
|
||||||
mesh = bpy.data.meshes.new('mesh_' + component_name)
|
|
||||||
|
|
||||||
vList = []
|
vList = []
|
||||||
vnList = []
|
vnList = []
|
||||||
@ -204,6 +214,10 @@ def create_instance_with_option(instance_type, instance_name, instance_opt,
|
|||||||
For object, you should provide `extra_mesh`.
|
For object, you should provide `extra_mesh`.
|
||||||
For texture, you should provide `extra_texture_path` and `extra_texture_filename`.
|
For texture, you should provide `extra_texture_path` and `extra_texture_filename`.
|
||||||
|
|
||||||
|
Value type:
|
||||||
|
`instance_type`: one integer in UTILS_constants.BmfileInfoType
|
||||||
|
`instance_name`: a string of new data block name
|
||||||
|
`instance_opt`: 'RENAME' or 'CURRENT'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_instance():
|
def get_instance():
|
||||||
|
@ -127,11 +127,16 @@ class BALLANCE_MT_AddElementsMenu(bpy.types.Menu):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
|
layout.label(text="Basic Elements")
|
||||||
for item in UTILS_constants.bmfile_componentList:
|
for item in UTILS_constants.bmfile_componentList:
|
||||||
cop = layout.operator(
|
cop = layout.operator(
|
||||||
OBJS_add_components.BALLANCE_OT_add_components.bl_idname,
|
OBJS_add_components.BALLANCE_OT_add_components.bl_idname,
|
||||||
text=item, icon_value = UTILS_icons_manager.get_element_icon(item))
|
text=item, icon_value = UTILS_icons_manager.get_element_icon(item))
|
||||||
cop.elements_type = item
|
cop.elements_type = item
|
||||||
|
|
||||||
|
layout.label(text="Special Elements")
|
||||||
|
layout.operator(OBJS_add_components.BALLANCE_OT_add_components_dup.bl_idname, text="Dup Elements")
|
||||||
|
layout.operator(OBJS_add_components.BALLANCE_OT_add_components_series.bl_idname, text="Elements Series")
|
||||||
|
|
||||||
# =============================================
|
# =============================================
|
||||||
# blender call system
|
# blender call system
|
||||||
@ -149,6 +154,8 @@ classes = (
|
|||||||
BALLANCE_MT_ThreeDViewerMenu,
|
BALLANCE_MT_ThreeDViewerMenu,
|
||||||
|
|
||||||
OBJS_add_components.BALLANCE_OT_add_components,
|
OBJS_add_components.BALLANCE_OT_add_components,
|
||||||
|
OBJS_add_components.BALLANCE_OT_add_components_dup,
|
||||||
|
OBJS_add_components.BALLANCE_OT_add_components_series,
|
||||||
OBJS_add_rails.BALLANCE_OT_add_rails,
|
OBJS_add_rails.BALLANCE_OT_add_rails,
|
||||||
OBJS_add_rails.BALLANCE_OT_add_tunnels,
|
OBJS_add_rails.BALLANCE_OT_add_tunnels,
|
||||||
OBJS_add_floors.BALLANCE_OT_add_floors,
|
OBJS_add_floors.BALLANCE_OT_add_floors,
|
||||||
|
Loading…
Reference in New Issue
Block a user