basically finish framework of ballance_element

This commit is contained in:
yyc12345 2023-10-25 21:35:26 +08:00
parent 2896602e6a
commit c1f92c7244

View File

@ -1,60 +1,70 @@
import bpy
import os, typing
import os, typing, enum
from . import UTIL_functions, UTIL_blender_mesh
#region Raw Elements Operations
_g_AllElementsName: tuple[str] = (
"P_Extra_Life",
"P_Extra_Point",
"P_Trafo_Paper",
"P_Trafo_Stone",
"P_Trafo_Wood",
"P_Ball_Paper",
"P_Ball_Stone",
"P_Ball_Wood",
"P_Box",
"P_Dome",
"P_Modul_01",
"P_Modul_03",
"P_Modul_08",
"P_Modul_17",
"P_Modul_18",
"P_Modul_19",
"P_Modul_25",
"P_Modul_26",
"P_Modul_29",
"P_Modul_30",
"P_Modul_34",
"P_Modul_37",
"P_Modul_41",
"PC_TwoFlames",
"PE_Balloon",
"PR_Resetpoint",
"PS_FourFlames",
)
class BallanceElementType(enum.IntEnum):
P_Extra_Life = 0
P_Extra_Point = 1
P_Trafo_Paper = 2
P_Trafo_Stone = 3
P_Trafo_Wood = 4
P_Ball_Paper = 5
P_Ball_Stone = 6
P_Ball_Wood = 7
P_Box = 8
P_Dome = 9
P_Modul_01 = 10
P_Modul_03 = 11
P_Modul_08 = 12
P_Modul_17 = 13
P_Modul_18 = 14
P_Modul_19 = 15
P_Modul_25 = 16
P_Modul_26 = 17
P_Modul_29 = 18
P_Modul_30 = 19
P_Modul_34 = 20
P_Modul_37 = 21
P_Modul_41 = 22
PC_TwoFlames = 23
PE_Balloon = 24
PR_Resetpoint = 25
PS_FourFlames = 26
_g_ElementIndexMap: dict[str, int] = dict((val, idx) for idx, val in enumerate(_g_AllElementsName))
_g_ElementCount: int = len(BallanceElementType)
_g_ElementNameIdMap: dict[str, int] = dict((entry.name, entry.value) for entry in BallanceElementType)
_g_ElementIdNameMap: dict[str, int] = dict((entry.value, entry.name) for entry in BallanceElementType)
def get_ballance_element_index(name: str) -> int | None:
def get_ballance_element_id(name: str) -> int | None:
"""
Get Ballance element index by its name.
Get Ballance element ID by its name.
@param name[in] The name of element
@return the index of this Ballance element name distributed by this plugin. or None if providing name is invalid.
@return the ID of this Ballance element name distributed by this plugin. or None if providing name is invalid.
"""
return _g_ElementIndexMap.get(name, None)
return _g_ElementNameIdMap.get(name, None)
def get_ballance_element_name(id: int) -> int | None:
"""
Get Ballance element name by its ID
@param id[in] The ID of element
@return the name of this Ballance element, or None if ID is invalid.
"""
return _g_ElementIdNameMap.get(id, None)
def is_ballance_element(name: str) -> bool:
"""
Check whether providing name is Ballance element.
Just a wrapper of get_ballance_element_index
Just a wrapper of get_ballance_element_id
@param name[in] The name of element
@return True if providing name is Ballance element name.
"""
return get_ballance_element_index(name) is not None
return get_ballance_element_id(name) is not None
#endregion
@ -76,15 +86,42 @@ def get_ballance_elements() -> bpy.types.CollectionProperty:
#endregion
#region Ballance Elements Operation Help Class
#region
def load_element(mesh: bpy.types.Mesh, element_id: int) -> None:
pass
#endregion
#region Ballance Elements Operation Help Class & Functions
class BallanceElementsHelper():
__mSingletonOccupation: typing.ClassVar[bool] = False
"""
The helper of Ballance elements processing.
All element operations, including getting or setting, must be manipulated by this class.
You should NOT operate Ballance Elements property (in Scene) directly.
This class should only have 1 instance at the same time. This class support `with` syntax to achieve this.
This class frequently used in importing stage to create element placeholder.
"""
__mSingletonMutex: typing.ClassVar[bool] = False
__mIsValid: bool
__mElementMap: dict[int, bpy.types.Mesh]
def __init__():
pass
def __init__(self):
self.__mElementMap = {}
# check singleton
if BallanceElementsHelper.__mSingletonMutex:
self.__mIsValid = False
raise UTIL_functions.BBPException('BallanceElementsHelper is mutex.')
# set validation and read ballance elements property
BallanceElementsHelper.__mSingletonMutex = True
self.__mIsValid = True
self.__read_from_ballance_element()
def is_valid(self) -> bool:
return self.__mIsValid
@ -97,16 +134,80 @@ class BallanceElementsHelper():
def dispose(self) -> None:
if self.is_valid():
pass
# write to ballance elements property and reset validation
self.__write_to_ballance_elements()
self.__mIsValid = False
self.__mSingletonMutex = False
def load_element(self, element_idx: int) -> bpy.types.Mesh:
pass
def get_element(self, element_id: int) -> 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)
if mesh is not None:
return mesh
# if no existing one, create new one
new_mesh_name: str | None = get_ballance_element_id(element_id)
if new_mesh_name is None:
raise UTIL_functions.BBPException('invalid element id')
new_mesh: bpy.types.Mesh = bpy.data.meshes.new(get_ballance_element_name(element_id))
load_element(new_mesh, element_id)
self.__mElementMap[element_id] = new_mesh
return new_mesh
def __write_to_ballance_elements(self) -> None:
pass
elements: bpy.types.CollectionProperty = get_ballance_elements()
elements.clear()
for eleid, elemesh in self.__mElementMap.items():
name: str | None = get_ballance_element_name(eleid)
if name is None:
continue
item: BBP_PG_ballance_element = elements.add()
item.element_name = name
item.mesh_ptr = elemesh
def __read_from_ballance_element(self) -> None:
pass
elements: bpy.types.CollectionProperty = get_ballance_elements()
self.__mElementMap.clear()
item: BBP_PG_ballance_element
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
# add into map
self.__mElementMap[mesh_id] = item.mesh_ptr
def reset_ballance_elements() -> None:
invalid_idx: list[int] = []
elements: bpy.types.CollectionProperty = get_ballance_elements()
# re-load all elements
index: int = 0
item: BBP_PG_ballance_element
for item in elements:
eleid: int | None = get_ballance_element_id(item.element_name)
# load or record invalid entry
if eleid is None or item.mesh_ptr is None:
invalid_idx.append(index)
else:
load_element(item.mesh_ptr, eleid)
# inc counter
index += 1
# remove invalid one with reversed order
invalid_idx.reverse()
for idx in invalid_idx:
elements.remove(idx)
#endregion
@ -129,8 +230,7 @@ class BBP_OT_reset_ballance_elements(bpy.types.Operator):
return context.scene is not None
def execute(self, context):
scene: bpy.types.Scene = context.scene
reset_ballance_elements()
return {'FINISHED'}
class BBP_PT_ballance_elements(bpy.types.Panel):
@ -163,8 +263,8 @@ class BBP_PT_ballance_elements(bpy.types.Panel):
target, "active_ballance_elements",
# default row height is a half of the count of all elements
# limit the max row height to the the count of all elements
rows = len(_g_AllElementsName) // 2,
maxrows = len(_g_AllElementsName),
rows = _g_ElementCount // 2,
maxrows = _g_ElementCount,
)
#endregion