update component creation
This commit is contained in:
parent
ebb22c9ec1
commit
f6569313bf
@ -1,12 +1,47 @@
|
||||
import bpy
|
||||
import bpy, mathutils
|
||||
import math, typing
|
||||
from . import UTIL_functions, UTIL_icons_manager, UTIL_naming_convension
|
||||
from . import PROP_ballance_element, PROP_virtools_group
|
||||
|
||||
#region Param Help Classes
|
||||
|
||||
class ComponentSectorParam():
|
||||
component_sector: bpy.props.IntProperty(
|
||||
name = "Sector",
|
||||
description = "Define which sector the object will be grouped in",
|
||||
min = 1, max = 999,
|
||||
soft_min = 1, soft_max = 8,
|
||||
default = 1,
|
||||
)
|
||||
|
||||
def general_get_component_sector(self) -> int:
|
||||
return self.component_sector
|
||||
|
||||
def draw_component_sector_params(self, layout: bpy.types.UILayout) -> None:
|
||||
layout.prop(self, 'component_sector')
|
||||
|
||||
class ComponentCountParam():
|
||||
component_count: bpy.props.IntProperty(
|
||||
name = "Count",
|
||||
description = "The count of components you want to generate",
|
||||
min = 1, max = 64,
|
||||
soft_min = 1, soft_max = 32,
|
||||
default = 1,
|
||||
)
|
||||
|
||||
def general_get_component_count(self) -> int:
|
||||
return self.component_count
|
||||
|
||||
def draw_component_count_params(self, layout: bpy.types.UILayout) -> None:
|
||||
layout.prop(self, 'component_count')
|
||||
|
||||
#endregion
|
||||
|
||||
#region Help Classes & Functions
|
||||
|
||||
def _get_component_info(comp_type: PROP_ballance_element.BallanceElementType, comp_sector: int) -> UTIL_naming_convension.BallanceObjectInfo:
|
||||
match(comp_type):
|
||||
# process special for 2 unique components
|
||||
# process for 2 special unique components
|
||||
case PROP_ballance_element.BallanceElementType.PS_FourFlames:
|
||||
return UTIL_naming_convension.BallanceObjectInfo.create_from_others(UTIL_naming_convension.BallanceObjectType.LEVEL_START)
|
||||
case PROP_ballance_element.BallanceElementType.PE_Balloon:
|
||||
@ -18,7 +53,10 @@ def _get_component_info(comp_type: PROP_ballance_element.BallanceElementType, co
|
||||
return UTIL_naming_convension.BallanceObjectInfo.create_from_resetpoint(comp_sector)
|
||||
# process for other components
|
||||
case _:
|
||||
return UTIL_naming_convension.BallanceObjectInfo.create_from_component(comp_type.name, comp_sector)
|
||||
return UTIL_naming_convension.BallanceObjectInfo.create_from_component(
|
||||
PROP_ballance_element.get_ballance_element_name(comp_type),
|
||||
comp_sector
|
||||
)
|
||||
|
||||
def _set_component_by_info(obj: bpy.types.Object, info: UTIL_naming_convension.BallanceObjectInfo) -> None:
|
||||
# set component name and grouping it into virtools group at the same time
|
||||
@ -56,6 +94,33 @@ def _check_component_existance(comp_type: PROP_ballance_element.BallanceElementT
|
||||
if expect_name in bpy.data.objects: return expect_name
|
||||
else: return None
|
||||
|
||||
def _general_create_component(comp_type: PROP_ballance_element.BallanceElementType, comp_sector: int, comp_count: int, comp_offset: typing.Callable[[int], mathutils.Matrix]) -> None:
|
||||
"""
|
||||
General component creation function.
|
||||
|
||||
@param comp_type[in] The component type created.
|
||||
@param comp_sector[in] The sector param which passed to other functions. For non-sector component, pass any number.
|
||||
@param comp_count[in] The count of created component. For single component creation, please pass 1.
|
||||
@param comp_offset[in] The function pointer which receive 1 argument indicating the index of object which we want to get its offset.
|
||||
You can pass `lambda _: mathutils.Matrix.Identity(4)` to get zero offset for every items.
|
||||
You can pass `lambda _: mathutils.Matrix( xxx )` to get same offset for every items.
|
||||
You can pass `lambda i: mathutils.Matrix( func(i) )` to get index based offset for each items.
|
||||
The offset is the offset to the origin point, not the previous object.
|
||||
"""
|
||||
# get element info first
|
||||
ele_info: UTIL_naming_convension.BallanceObjectInfo = _get_component_info(comp_type, comp_sector)
|
||||
# create blc element context
|
||||
with PROP_ballance_element.BallanceElementsHelper(bpy.context.scene) as creator:
|
||||
# object creation counter
|
||||
for i in range(comp_count):
|
||||
# get mesh from element context, and create with empty name first. we assign name later.
|
||||
obj: bpy.types.Object = bpy.data.objects.new('', creator.get_element(comp_type))
|
||||
# assign virtools group, object name by we gotten element info.
|
||||
_set_component_by_info(obj, ele_info)
|
||||
# add into scene and move to cursor
|
||||
UTIL_functions.add_into_scene_and_move_to_cursor(obj)
|
||||
# move with extra offset by calling offset getter
|
||||
obj.matrix_world = obj.matrix_world @ comp_offset(i)
|
||||
|
||||
class EnumPropHelper():
|
||||
"""
|
||||
@ -69,7 +134,7 @@ class EnumPropHelper():
|
||||
str(item.value),
|
||||
item.name,
|
||||
"",
|
||||
UTIL_icons_manager.get_element_icon(item.name),
|
||||
UTIL_icons_manager.get_element_icon(PROP_ballance_element.get_ballance_element_name(item)),
|
||||
item.value
|
||||
) for item in PROP_ballance_element.BallanceElementType
|
||||
)
|
||||
@ -88,20 +153,14 @@ class EnumPropHelper():
|
||||
|
||||
#endregion
|
||||
|
||||
class BBP_OT_add_component(bpy.types.Operator):
|
||||
#region Noemal Component Adder
|
||||
|
||||
class BBP_OT_add_component(bpy.types.Operator, ComponentSectorParam):
|
||||
"""Add Component"""
|
||||
bl_idname = "bbp.add_component"
|
||||
bl_label = "Add Component"
|
||||
bl_options = {'UNDO'}
|
||||
|
||||
component_sector: bpy.props.IntProperty(
|
||||
name = "Sector",
|
||||
description = "Define which sector the object will be grouped in",
|
||||
min = 1, max = 999,
|
||||
soft_min = 1, soft_max = 8,
|
||||
default = 1,
|
||||
)
|
||||
|
||||
component_type: bpy.props.EnumProperty(
|
||||
name = "Type",
|
||||
description = "This component type",
|
||||
@ -120,39 +179,255 @@ class BBP_OT_add_component(bpy.types.Operator):
|
||||
# only show sector for non-PE/PS component
|
||||
eletype: PROP_ballance_element.BallanceElementType = EnumPropHelper.get_selection(self.component_type)
|
||||
if eletype != PROP_ballance_element.BallanceElementType.PS_FourFlames and eletype != PROP_ballance_element.BallanceElementType.PE_Balloon:
|
||||
layout.prop(self, "component_sector")
|
||||
self.draw_component_sector_params(layout)
|
||||
|
||||
# check for some special components and show warning
|
||||
elename: str | None = _check_component_existance(EnumPropHelper.get_selection(self.component_type), self.component_sector)
|
||||
elename: str | None = _check_component_existance(EnumPropHelper.get_selection(self.component_type), self.general_get_component_sector())
|
||||
if elename is not None:
|
||||
layout.label(text = f'Warning: {elename} already exist.')
|
||||
|
||||
def execute(self, context):
|
||||
# create by ballance components
|
||||
eletype: PROP_ballance_element.BallanceElementType = EnumPropHelper.get_selection(self.component_type)
|
||||
eleinfo: UTIL_naming_convension.BallanceObjectInfo = _get_component_info(eletype, self.component_sector)
|
||||
|
||||
with PROP_ballance_element.BallanceElementsHelper(bpy.context.scene) as creator:
|
||||
# create with empty name first
|
||||
obj = bpy.data.objects.new('', creator.get_element(eletype.value))
|
||||
# assign its props, including name
|
||||
_set_component_by_info(obj, eleinfo)
|
||||
# scene cursor
|
||||
UTIL_functions.add_into_scene_and_move_to_cursor(obj)
|
||||
|
||||
# call general creator
|
||||
_general_create_component(
|
||||
EnumPropHelper.get_selection(self.component_type),
|
||||
self.general_get_component_sector(),
|
||||
1, # only create one
|
||||
lambda _: mathutils.Matrix.Identity(4)
|
||||
)
|
||||
return {'FINISHED'}
|
||||
|
||||
@classmethod
|
||||
def draw_blc_menu(self, layout: bpy.types.UILayout):
|
||||
for item in PROP_ballance_element.BallanceElementType:
|
||||
item_name: str = PROP_ballance_element.get_ballance_element_name(item)
|
||||
|
||||
cop = layout.operator(
|
||||
self.bl_idname, text = item.name,
|
||||
icon_value = UTIL_icons_manager.get_element_icon(item.name))
|
||||
self.bl_idname, text = item_name,
|
||||
icon_value = UTIL_icons_manager.get_element_icon(item_name)
|
||||
)
|
||||
cop.component_type = EnumPropHelper.to_selection(item)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nong Comp Adder
|
||||
|
||||
class BBP_OT_add_nong_extra_point(bpy.types.Operator, ComponentSectorParam, ComponentCountParam):
|
||||
"""Add Nong Extra Point"""
|
||||
bl_idname = "bbp.add_nong_extra_point"
|
||||
bl_label = "Nong Extra Point"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
self.draw_component_sector_params(layout)
|
||||
self.draw_component_count_params(layout)
|
||||
|
||||
def execute(self, context):
|
||||
# create objects and rotate it by a certain degree calculated by its index
|
||||
# calc percent first
|
||||
percent: float = 1.0 / self.general_get_component_count()
|
||||
# create elements
|
||||
_general_create_component(
|
||||
PROP_ballance_element.BallanceElementType.P_Extra_Point,
|
||||
self.general_get_component_sector(),
|
||||
self.general_get_component_count(),
|
||||
lambda i: mathutils.Matrix.Rotation(percent * i * math.pi * 2, 4, 'Z')
|
||||
)
|
||||
return {'FINISHED'}
|
||||
|
||||
@classmethod
|
||||
def draw_blc_menu(self, layout: bpy.types.UILayout):
|
||||
layout.operator(
|
||||
BBP_OT_add_nong_extra_point.bl_idname,
|
||||
icon_value = UTIL_icons_manager.get_element_icon(
|
||||
PROP_ballance_element.get_ballance_element_name(PROP_ballance_element.BallanceElementType.P_Extra_Point)
|
||||
)
|
||||
)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Series Comp Adder
|
||||
|
||||
class BBP_OT_add_tilting_block_series(bpy.types.Operator, ComponentSectorParam, ComponentCountParam):
|
||||
"""Add Tilting Block Series"""
|
||||
bl_idname = "bbp.add_tilting_block_series"
|
||||
bl_label = "Tilting Block Series"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
component_span: bpy.props.FloatProperty(
|
||||
name = "Span",
|
||||
description = "The distance between each titling blocks",
|
||||
min = 0.0, max = 100.0,
|
||||
soft_min = 0.0, soft_max = 12.0,
|
||||
default = 6.0022,
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
self.draw_component_sector_params(layout)
|
||||
self.draw_component_count_params(layout)
|
||||
layout.prop(self, 'component_span')
|
||||
|
||||
def execute(self, context):
|
||||
# create objects and move it by delta
|
||||
# get span first
|
||||
span: float = self.component_span
|
||||
# create elements
|
||||
_general_create_component(
|
||||
PROP_ballance_element.BallanceElementType.P_Modul_41,
|
||||
self.general_get_component_sector(),
|
||||
self.general_get_component_count(),
|
||||
lambda i: mathutils.Matrix.Translation(mathutils.Vector((span * i, 0.0, 0.0))) # move with extra delta in x axis
|
||||
)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@classmethod
|
||||
def draw_blc_menu(self, layout: bpy.types.UILayout):
|
||||
layout.operator(
|
||||
BBP_OT_add_tilting_block_series.bl_idname,
|
||||
icon_value = UTIL_icons_manager.get_element_icon(
|
||||
PROP_ballance_element.get_ballance_element_name(PROP_ballance_element.BallanceElementType.P_Modul_41)
|
||||
)
|
||||
)
|
||||
|
||||
class BBP_OT_add_ventilator_series(bpy.types.Operator, ComponentSectorParam, ComponentCountParam):
|
||||
"""Add Ventilator Series"""
|
||||
bl_idname = "bbp.add_ventilator_series"
|
||||
bl_label = "Ventilator Series"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
component_translation: bpy.props.FloatVectorProperty(
|
||||
name = "Delta Vector",
|
||||
description = "The translation between each ventilators. You can use this property to implement vertical or horizontal ventilator series. Set all factors to zero can get Nong ventilator.",
|
||||
size = 3, subtype = 'TRANSLATION',
|
||||
min = 0.0, max = 100.0,
|
||||
soft_min = 0.0, soft_max = 50.0,
|
||||
default = (0.0, 0.0, 15.0),
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
self.draw_component_sector_params(layout)
|
||||
self.draw_component_count_params(layout)
|
||||
layout.prop(self, 'component_translation')
|
||||
|
||||
def execute(self, context):
|
||||
# create objects and move it by delta
|
||||
# get translation first
|
||||
translation: mathutils.Vector = mathutils.Vector(self.component_translation)
|
||||
# create elements
|
||||
_general_create_component(
|
||||
PROP_ballance_element.BallanceElementType.P_Modul_18,
|
||||
self.general_get_component_sector(),
|
||||
self.general_get_component_count(),
|
||||
lambda i: mathutils.Matrix.Translation(i * translation) # move with extra translation
|
||||
)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@classmethod
|
||||
def draw_blc_menu(self, layout: bpy.types.UILayout):
|
||||
layout.operator(
|
||||
BBP_OT_add_ventilator_series.bl_idname,
|
||||
icon_value = UTIL_icons_manager.get_element_icon(
|
||||
PROP_ballance_element.get_ballance_element_name(PROP_ballance_element.BallanceElementType.P_Modul_18)
|
||||
)
|
||||
)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Comp Pair Adder
|
||||
|
||||
class BBP_OT_add_sector_component_pair(bpy.types.Operator, ComponentSectorParam):
|
||||
"""Add Sector Pair, both check point and reset point."""
|
||||
bl_idname = "bbp.add_sector_component_pair"
|
||||
bl_label = "Sector Pair"
|
||||
bl_options = {'UNDO'}
|
||||
|
||||
def __get_checkpoint(self) -> tuple[PROP_ballance_element.BallanceElementType, int]:
|
||||
if self.general_get_component_sector() == 1:
|
||||
return (PROP_ballance_element.BallanceElementType.PS_FourFlames, 1)
|
||||
else:
|
||||
# the sector of two flames should be `sector - 1` because first one was occupied by FourFlams
|
||||
return (PROP_ballance_element.BallanceElementType.PC_TwoFlames, self.general_get_component_sector() - 1)
|
||||
|
||||
def __get_resetpoint(self) -> tuple[PROP_ballance_element.BallanceElementType, int]:
|
||||
# resetpoint's sector is just sector it self.
|
||||
return (PROP_ballance_element.BallanceElementType.PR_Resetpoint, self.general_get_component_sector())
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
self.draw_component_sector_params(layout)
|
||||
|
||||
# check checkpoint and resetpoint name conflict and show warnings
|
||||
(checkp_ty, checkp_sector) = self.__get_checkpoint()
|
||||
elename: str | None = _check_component_existance(checkp_ty, checkp_sector)
|
||||
if elename is not None:
|
||||
layout.label(text = f'Warning: {elename} already exist.')
|
||||
|
||||
(resetp_ty, resetp_sector) = self.__get_resetpoint()
|
||||
elename = _check_component_existance(resetp_ty, resetp_sector)
|
||||
if elename is not None:
|
||||
layout.label(text = f'Warning: {elename} already exist.')
|
||||
|
||||
def execute(self, context):
|
||||
# create checkpoint and resetpoint individually in element context
|
||||
# get type and sector data first
|
||||
(checkp_ty, checkp_sector) = self.__get_checkpoint()
|
||||
(resetp_ty, resetp_sector) = self.__get_resetpoint()
|
||||
# calc resetpoint offset
|
||||
# resetpoint need a extra offset between checkpoint
|
||||
# but it is different in FourFlams and TwoFlams
|
||||
resetp_offset: float
|
||||
if checkp_ty == PROP_ballance_element.BallanceElementType.PS_FourFlames:
|
||||
resetp_offset = 3.25
|
||||
else:
|
||||
resetp_offset = 2.0
|
||||
|
||||
# add elements
|
||||
# create checkpoint
|
||||
_general_create_component(
|
||||
checkp_ty,
|
||||
checkp_sector,
|
||||
1, # only create one
|
||||
lambda _: mathutils.Matrix.Identity(4)
|
||||
)
|
||||
# create resetpoint
|
||||
_general_create_component(
|
||||
resetp_ty,
|
||||
resetp_sector,
|
||||
1, # only create one
|
||||
lambda _: mathutils.Matrix.Translation(mathutils.Vector((0.0, 0.0, resetp_offset))) # apply resetpoint offset
|
||||
)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@classmethod
|
||||
def draw_blc_menu(self, layout: bpy.types.UILayout):
|
||||
layout.operator(
|
||||
BBP_OT_add_sector_component_pair.bl_idname,
|
||||
icon_value = UTIL_icons_manager.get_element_icon(
|
||||
PROP_ballance_element.get_ballance_element_name(PROP_ballance_element.BallanceElementType.PR_Resetpoint)
|
||||
)
|
||||
)
|
||||
|
||||
#endregion
|
||||
|
||||
def register():
|
||||
# register all classes
|
||||
bpy.utils.register_class(BBP_OT_add_component)
|
||||
bpy.utils.register_class(BBP_OT_add_nong_extra_point)
|
||||
bpy.utils.register_class(BBP_OT_add_tilting_block_series)
|
||||
bpy.utils.register_class(BBP_OT_add_ventilator_series)
|
||||
bpy.utils.register_class(BBP_OT_add_sector_component_pair)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(BBP_OT_add_sector_component_pair)
|
||||
bpy.utils.unregister_class(BBP_OT_add_ventilator_series)
|
||||
bpy.utils.unregister_class(BBP_OT_add_tilting_block_series)
|
||||
bpy.utils.unregister_class(BBP_OT_add_nong_extra_point)
|
||||
bpy.utils.unregister_class(BBP_OT_add_component)
|
||||
|
@ -35,26 +35,48 @@ class BallanceElementType(enum.IntEnum):
|
||||
PS_FourFlames = 26
|
||||
|
||||
_g_ElementCount: int = len(BallanceElementType)
|
||||
_g_ElementNameIdMap: dict[str, int] = dict((entry.name, entry.value) for entry in BallanceElementType)
|
||||
_g_ElementIdNameMap: dict[int, str] = dict((entry.value, entry.name) for entry in BallanceElementType)
|
||||
|
||||
def get_ballance_element_id(name: str) -> int | None:
|
||||
def get_ballance_element_type_from_id(id: int) -> BallanceElementType | None:
|
||||
"""
|
||||
Get Ballance element ID by its name.
|
||||
Get Ballance element type by its id.
|
||||
|
||||
@param id[in] The id of element
|
||||
@return the type of this Ballance element name distributed by this plugin. or None if providing id is invalid.
|
||||
"""
|
||||
try:
|
||||
return BallanceElementType(id) # https://docs.python.org/zh-cn/3/library/enum.html#enum.EnumType.__call__
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def get_ballance_element_type_from_name(name: str) -> BallanceElementType | None:
|
||||
"""
|
||||
Get Ballance element type by its name.
|
||||
|
||||
@param name[in] The name of element
|
||||
@return the ID of this Ballance element name distributed by this plugin. or None if providing name is invalid.
|
||||
@return the type of this Ballance element name distributed by this plugin. or None if providing name is invalid.
|
||||
"""
|
||||
return _g_ElementNameIdMap.get(name, None)
|
||||
try:
|
||||
return BallanceElementType[name] # https://docs.python.org/zh-cn/3/library/enum.html#enum.EnumType.__getitem__
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def get_ballance_element_name(id: int) -> str | None:
|
||||
def get_ballance_element_id(ty: BallanceElementType) -> int:
|
||||
"""
|
||||
Get Ballance element name by its ID
|
||||
Get Ballance element id by its type
|
||||
|
||||
@param id[in] The ID of element
|
||||
@return the name of this Ballance element, or None if ID is invalid.
|
||||
@param ty[in] The type of element
|
||||
@return the id of this Ballance element.
|
||||
"""
|
||||
return _g_ElementIdNameMap.get(id, None)
|
||||
return ty.value
|
||||
|
||||
def get_ballance_element_name(ty: BallanceElementType) -> str:
|
||||
"""
|
||||
Get Ballance element name by its type
|
||||
|
||||
@param ty[in] The type of element
|
||||
@return the name of this Ballance element.
|
||||
"""
|
||||
return ty.name
|
||||
|
||||
def is_ballance_element(name: str) -> bool:
|
||||
"""
|
||||
@ -65,16 +87,16 @@ def is_ballance_element(name: str) -> bool:
|
||||
@param name[in] The name of element
|
||||
@return True if providing name is Ballance element name.
|
||||
"""
|
||||
return get_ballance_element_id(name) is not None
|
||||
return get_ballance_element_type_from_name(name) is not None
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ballance Elements Define & Visitor
|
||||
|
||||
class BBP_PG_ballance_element(bpy.types.PropertyGroup):
|
||||
element_name: bpy.props.StringProperty(
|
||||
name = "Element Name",
|
||||
default = ""
|
||||
element_id: bpy.props.IntProperty(
|
||||
name = "Element Id",
|
||||
default = 0
|
||||
)
|
||||
|
||||
mesh_ptr: bpy.props.PointerProperty(
|
||||
@ -94,12 +116,9 @@ def _save_element(mesh: bpy.types.Mesh, filename: str) -> None:
|
||||
# write this function and call this function in operator.
|
||||
pass
|
||||
|
||||
def _load_element(mesh: bpy.types.Mesh, element_id: int) -> None:
|
||||
def _load_element(mesh: bpy.types.Mesh, element_type: BallanceElementType) -> None:
|
||||
# resolve mesh path
|
||||
element_name: str | None = get_ballance_element_name(element_id)
|
||||
if element_name is None:
|
||||
raise UTIL_functions.BBPException('invalid element id in _load_element()')
|
||||
|
||||
element_name: str = get_ballance_element_name(element_type)
|
||||
element_filename: str = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"meshes",
|
||||
@ -208,7 +227,7 @@ class BallanceElementsHelper():
|
||||
__mSingletonMutex: typing.ClassVar[bool] = False
|
||||
__mIsValid: bool
|
||||
__mAssocScene: bpy.types.Scene
|
||||
__mElementMap: dict[int, bpy.types.Mesh]
|
||||
__mElementMap: dict[BallanceElementType, bpy.types.Mesh]
|
||||
|
||||
def __init__(self, assoc: bpy.types.Scene):
|
||||
self.__mElementMap = {}
|
||||
@ -240,36 +259,30 @@ class BallanceElementsHelper():
|
||||
self.__mIsValid = False
|
||||
BallanceElementsHelper.__mSingletonMutex = False
|
||||
|
||||
def get_element(self, element_id: int) -> bpy.types.Mesh:
|
||||
def get_element(self, element_type: BallanceElementType) -> bpy.types.Mesh:
|
||||
if not self.is_valid():
|
||||
raise UTIL_functions.BBPException('calling invalid BallanceElementsHelper')
|
||||
|
||||
# get exist one
|
||||
mesh: bpy.types.Mesh | None = self.__mElementMap.get(element_id, None)
|
||||
mesh: bpy.types.Mesh | None = self.__mElementMap.get(element_type, None)
|
||||
if mesh is not None:
|
||||
return mesh
|
||||
|
||||
# if no existing one, create new one
|
||||
new_mesh_name: str | None = get_ballance_element_name(element_id)
|
||||
if new_mesh_name is None:
|
||||
raise UTIL_functions.BBPException('invalid element id')
|
||||
new_mesh_name: str = get_ballance_element_name(element_type)
|
||||
new_mesh: bpy.types.Mesh = bpy.data.meshes.new(new_mesh_name)
|
||||
|
||||
_load_element(new_mesh, element_id)
|
||||
self.__mElementMap[element_id] = new_mesh
|
||||
_load_element(new_mesh, element_type)
|
||||
self.__mElementMap[element_type] = new_mesh
|
||||
return new_mesh
|
||||
|
||||
def __write_to_ballance_elements(self) -> None:
|
||||
elements: bpy.types.CollectionProperty = get_ballance_elements(self.__mAssocScene)
|
||||
elements.clear()
|
||||
|
||||
for eleid, elemesh in self.__mElementMap.items():
|
||||
name: str | None = get_ballance_element_name(eleid)
|
||||
if name is None:
|
||||
continue
|
||||
|
||||
for elety, elemesh in self.__mElementMap.items():
|
||||
item: BBP_PG_ballance_element = elements.add()
|
||||
item.element_name = name
|
||||
item.element_id = get_ballance_element_id(elety)
|
||||
item.mesh_ptr = elemesh
|
||||
|
||||
def __read_from_ballance_element(self) -> None:
|
||||
@ -280,11 +293,11 @@ class BallanceElementsHelper():
|
||||
for item in elements:
|
||||
# check requirements
|
||||
if item.mesh_ptr is None: continue
|
||||
mesh_id: int | None = get_ballance_element_id(item.element_name)
|
||||
if mesh_id is None: continue
|
||||
element_type: BallanceElementType | None = get_ballance_element_type_from_id(item.element_id)
|
||||
if element_type is None: continue
|
||||
|
||||
# add into map
|
||||
self.__mElementMap[mesh_id] = item.mesh_ptr
|
||||
self.__mElementMap[element_type] = item.mesh_ptr
|
||||
|
||||
def reset_ballance_elements(scene: bpy.types.Scene) -> None:
|
||||
invalid_idx: list[int] = []
|
||||
@ -294,13 +307,13 @@ def reset_ballance_elements(scene: bpy.types.Scene) -> None:
|
||||
index: int = 0
|
||||
item: BBP_PG_ballance_element
|
||||
for item in elements:
|
||||
eleid: int | None = get_ballance_element_id(item.element_name)
|
||||
elety: BallanceElementType | None = get_ballance_element_type_from_id(item.element_id)
|
||||
|
||||
# load or record invalid entry
|
||||
if eleid is None or item.mesh_ptr is None:
|
||||
if elety is None or item.mesh_ptr is None:
|
||||
invalid_idx.append(index)
|
||||
else:
|
||||
_load_element(item.mesh_ptr, eleid)
|
||||
_load_element(item.mesh_ptr, elety)
|
||||
|
||||
# inc counter
|
||||
index += 1
|
||||
@ -316,8 +329,12 @@ def reset_ballance_elements(scene: bpy.types.Scene) -> None:
|
||||
|
||||
class BBP_UL_ballance_elements(bpy.types.UIList):
|
||||
def draw_item(self, context, layout: bpy.types.UILayout, data, item: BBP_PG_ballance_element, icon, active_data, active_propname):
|
||||
if item.element_name != "" and item.mesh_ptr is not None:
|
||||
layout.label(text = item.element_name, translate = False)
|
||||
# check requirements
|
||||
elety: BallanceElementType | None = get_ballance_element_type_from_id(item.element_id)
|
||||
if elety is None or item.mesh_ptr is None: return
|
||||
|
||||
# draw list item
|
||||
layout.label(text = get_ballance_element_name(elety), translate = False)
|
||||
layout.label(text = item.mesh_ptr.name, translate = False, icon = 'MESH_DATA')
|
||||
|
||||
class BBP_OT_reset_ballance_elements(bpy.types.Operator):
|
||||
|
@ -1,4 +1,4 @@
|
||||
import bpy
|
||||
import bpy, mathutils
|
||||
import math, typing, enum, sys
|
||||
|
||||
class BBPException(Exception):
|
||||
@ -53,11 +53,17 @@ def message_box(message: tuple[str, ...], title: str, icon: str):
|
||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
||||
|
||||
def move_to_cursor(obj: bpy.types.Object):
|
||||
obj.location = bpy.context.scene.cursor.location
|
||||
# use obj.matrix_world to move, not obj.location because this bug:
|
||||
# https://blender.stackexchange.com/questions/27667/incorrect-matrix-world-after-transformation
|
||||
# the update of matrix_world after setting location is not immediately.
|
||||
# and calling update() function for view_layer for the translation of each object is not suit for too much objects.
|
||||
|
||||
# obj.location = bpy.context.scene.cursor.location
|
||||
obj.matrix_world = obj.matrix_world @ mathutils.Matrix.Translation(bpy.context.scene.cursor.location - obj.location)
|
||||
|
||||
def add_into_scene_and_move_to_cursor(obj: bpy.types.Object):
|
||||
move_to_cursor(obj)
|
||||
|
||||
view_layer = bpy.context.view_layer
|
||||
collection = view_layer.active_layer_collection.collection
|
||||
collection.objects.link(obj)
|
||||
|
||||
move_to_cursor(obj)
|
||||
|
@ -67,23 +67,28 @@ class BBP_MT_AddRailMenu(bpy.types.Menu):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
class BBP_MT_AddElementsMenu(bpy.types.Menu):
|
||||
"""Add Ballance Elements"""
|
||||
bl_idname = "BBP_MT_AddElementsMenu"
|
||||
bl_label = "Elements"
|
||||
class BBP_MT_AddComponentsMenu(bpy.types.Menu):
|
||||
"""Add Ballance Components"""
|
||||
bl_idname = "BBP_MT_AddComponentsMenu"
|
||||
bl_label = "Components"
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.label(text="Basic Elements")
|
||||
layout.label(text="Basic Components")
|
||||
OP_ADDS_component.BBP_OT_add_component.draw_blc_menu(layout)
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Duplicated Elements")
|
||||
#OBJS_add_components.BBP_OT_add_components_dup.draw_blc_menu(layout)
|
||||
layout.label(text="Nong Components")
|
||||
OP_ADDS_component.BBP_OT_add_nong_extra_point.draw_blc_menu(layout)
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Elements Pair")
|
||||
#OBJS_add_components.BBP_OT_add_components_series.draw_blc_menu(layout)
|
||||
layout.label(text="Series Components")
|
||||
OP_ADDS_component.BBP_OT_add_tilting_block_series.draw_blc_menu(layout)
|
||||
OP_ADDS_component.BBP_OT_add_ventilator_series.draw_blc_menu(layout)
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Components Pair")
|
||||
OP_ADDS_component.BBP_OT_add_sector_component_pair.draw_blc_menu(layout)
|
||||
|
||||
# ===== Menu Drawer =====
|
||||
|
||||
@ -109,10 +114,10 @@ def menu_drawer_add(self, context):
|
||||
layout.label(text="Ballance")
|
||||
layout.menu(BBP_MT_AddFloorMenu.bl_idname, icon='MESH_CUBE')
|
||||
layout.menu(BBP_MT_AddRailMenu.bl_idname, icon='MESH_CIRCLE')
|
||||
layout.menu(BBP_MT_AddElementsMenu.bl_idname, icon='MESH_ICOSPHERE')
|
||||
layout.menu(BBP_MT_AddComponentsMenu.bl_idname, icon='MESH_ICOSPHERE')
|
||||
#layout.operator_menu_enum(
|
||||
# OBJS_add_components.BALLANCE_OT_add_components.bl_idname,
|
||||
# "elements_type", icon='MESH_ICOSPHERE', text="Elements")
|
||||
# "Components_type", icon='MESH_ICOSPHERE', text="Components")
|
||||
#endregion
|
||||
|
||||
#region Register and Unregister.
|
||||
@ -121,7 +126,7 @@ g_BldClasses: tuple[typing.Any, ...] = (
|
||||
BBP_MT_View3DMenu,
|
||||
BBP_MT_AddFloorMenu,
|
||||
BBP_MT_AddRailMenu,
|
||||
BBP_MT_AddElementsMenu
|
||||
BBP_MT_AddComponentsMenu
|
||||
)
|
||||
|
||||
class MenuEntry():
|
||||
|
Loading…
Reference in New Issue
Block a user