finish bme

This commit is contained in:
yyc12345 2023-12-18 10:30:32 +08:00
parent 6bc3933291
commit 35f2c4a389
4 changed files with 212 additions and 9 deletions

View File

@ -156,7 +156,30 @@ class BBP_OT_add_bme_struct(bpy.types.Operator):
return self.execute(context) return self.execute(context)
def execute(self, context): def execute(self, context):
# todo: call general creator # collect cfgs data
cfgs: dict[str, typing.Any] = {}
for (cfg, cfg_index) in self.bme_struct_cfg_index_cache:
match(cfg.get_type()):
case UTIL_bme.PrototypeShowcaseCfgsTypes.Integer:
cfgs[cfg.get_field()] = self.bme_struct_cfgs[cfg_index].prop_int
case UTIL_bme.PrototypeShowcaseCfgsTypes.Float:
cfgs[cfg.get_field()] = self.bme_struct_cfgs[cfg_index].prop_float
case UTIL_bme.PrototypeShowcaseCfgsTypes.Boolean:
cfgs[cfg.get_field()] = self.bme_struct_cfgs[cfg_index].prop_bool
case UTIL_bme.PrototypeShowcaseCfgsTypes.Face:
# face is just 6 bool tuple
cfgs[cfg.get_field()] = tuple(
self.bme_struct_cfgs[cfg_index + i].prop_bool for i in range(6)
)
# call general creator
obj: bpy.types.Object = UTIL_bme.create_bme_struct_wrapper(
_g_EnumHelper_BmeStructType.get_selection(self.bme_struct_type),
cfgs
)
# move to cursor
UTIL_functions.add_into_scene_and_move_to_cursor(obj)
return {'FINISHED'} return {'FINISHED'}
def draw(self, context): def draw(self, context):

View File

@ -106,6 +106,9 @@ def _load_bme_material_preset(mtl: bpy.types.Material, preset_name: str) -> None
newrawmtl.mTexture = blctex newrawmtl.mTexture = blctex
PROP_virtools_material.set_raw_virtools_material(mtl, newrawmtl) PROP_virtools_material.set_raw_virtools_material(mtl, newrawmtl)
# apply vt mtl to blender mtl
PROP_virtools_material.apply_to_blender_material(mtl)
#endregion #endregion
#region BME Material Operation Help Class & Functions #region BME Material Operation Help Class & Functions

View File

@ -1,7 +1,7 @@
import bpy, mathutils import bpy, mathutils
import os, json, enum, typing, math import os, json, enum, typing, math
from . import PROP_virtools_group, PROP_bme_material from . import PROP_virtools_group, PROP_bme_material
from . import UTIL_functions, UTIL_icons_manager, UTIL_blender_mesh from . import UTIL_functions, UTIL_icons_manager, UTIL_blender_mesh, UTIL_virtools_types, UTIL_naming_convension
## NOTE: Outside caller should use BME struct's unique indetifier to visit each prototype ## NOTE: Outside caller should use BME struct's unique indetifier to visit each prototype
# and drive this class' functions to work. # and drive this class' functions to work.
@ -130,7 +130,7 @@ def _eval_params(strl: str, cfgs_data: dict[str, typing.Any]) -> typing.Any:
def _eval_vars(strl: str, params_data: dict[str, typing.Any]) -> typing.Any: def _eval_vars(strl: str, params_data: dict[str, typing.Any]) -> typing.Any:
return eval(strl, _g_ProgFieldGlobals, params_data) return eval(strl, _g_ProgFieldGlobals, params_data)
def _eval_others(strl, str, params_vars_data: dict[str, typing.Any]) -> typing.Any: def _eval_others(strl: str, params_vars_data: dict[str, typing.Any]) -> typing.Any:
return eval(strl, _g_ProgFieldGlobals, params_vars_data) return eval(strl, _g_ProgFieldGlobals, params_vars_data)
#endregion #endregion
@ -216,13 +216,182 @@ class EnumPropHelper(UTIL_functions.EnumPropHelper):
#region Core Creator #region Core Creator
def get_bme_struct_cfgs(): def create_bme_struct_wrapper(ident: str, cfgs: dict[str, typing.Any]) -> bpy.types.Object:
pass # get prototype first
proto: dict[str, typing.Any] = _get_prototype_by_identifier(ident)
def create_bme_struct_wrapper(): # analyse params by given cfgs
pass params: dict[str, typing.Any] = {}
for proto_param in proto[TOKEN_PARAMS]:
params[proto_param[TOKEN_PARAMS_FIELD]] = _eval_params(proto_param[TOKEN_PARAMS_DATA], cfgs)
def create_bme_struct(): # create used mesh
pass mesh: bpy.types.Mesh = bpy.data.meshes.new('BMEStruct')
# create mesh writer and bme mtl helper
# recursively calling underlying creation function
with UTIL_blender_mesh.MeshWriter(mesh) as writer:
with PROP_bme_material.BMEMaterialsHelper(bpy.context.scene) as bmemtl:
create_bme_struct(
ident,
writer,
bmemtl,
mathutils.Matrix.Identity(4),
params
)
# create object and assign prop
# get obj info first
obj_info: UTIL_naming_convension.BallanceObjectInfo
match(PrototypeShowcaseTypes(proto[TOKEN_SHOWCASE][TOKEN_SHOWCASE_TYPE])):
case PrototypeShowcaseTypes.No:
obj_info = UTIL_naming_convension.BallanceObjectInfo.create_from_others(UTIL_naming_convension.BallanceObjectType.DECORATION)
case PrototypeShowcaseTypes.Floor:
obj_info = UTIL_naming_convension.BallanceObjectInfo.create_from_others(UTIL_naming_convension.BallanceObjectType.FLOOR)
case PrototypeShowcaseTypes.Rail:
obj_info = UTIL_naming_convension.BallanceObjectInfo.create_from_others(UTIL_naming_convension.BallanceObjectType.RAIL)
case PrototypeShowcaseTypes.Wood:
obj_info = UTIL_naming_convension.BallanceObjectInfo.create_from_others(UTIL_naming_convension.BallanceObjectType.WOOD)
# then get object name
obj_name: str | None = UTIL_naming_convension.YYCToolchainConvention.set_to_name(obj_info, None)
if obj_name is None: raise UTIL_functions.BBPException('impossible null name')
# create object by name
obj: bpy.types.Object = bpy.data.objects.new(obj_name, mesh)
# assign virtools groups
UTIL_naming_convension.VirtoolsGroupConvention.set_to_object(obj, obj_info, None)
# return object
return obj
def create_bme_struct(
ident: str,
writer: UTIL_blender_mesh.MeshWriter,
bmemtl: PROP_bme_material.BMEMaterialsHelper,
transform: mathutils.Matrix,
params: dict[str, typing.Any]) -> None:
# get prototype first
proto: dict[str, typing.Any] = _get_prototype_by_identifier(ident)
# calc vars by given params
# please note i will add entries directly into params dict
# but the params dict will not used independently later,
# all following use is the union of params and vars dict.
# so it is safe.
for proto_var in proto[TOKEN_VARS]:
params[proto_var[TOKEN_VARS_FIELD]] = _eval_vars(proto_var[TOKEN_VARS_DATA], params)
# collect valid face and vertices data for following using.
# if NOT skip, add into valid list
valid_vec_idx: list[int] = []
for vec_idx, proto_vec in enumerate(proto[TOKEN_VERTICES]):
if not _eval_others(proto_vec[TOKEN_VERTICES_SKIP], params):
valid_vec_idx.append(vec_idx)
valid_face_idx: list[int] = []
for face_idx, proto_face in enumerate(proto[TOKEN_FACES]):
if not _eval_others(proto_face[TOKEN_FACES_SKIP], params):
valid_face_idx.append(face_idx)
# create mtl slot remap to help following mesh adding
# because mesh writer do not accept string format mtl slot visiting,
# it only accept int based mtl slot index.
# NOTE: since Python 3.6, the item of builtin dict is ordered by inserting order.
# we rely on this to implement following features
mtl_remap: dict[str, int] = {}
for face_idx in valid_face_idx:
# eval mtl name
mtl_name: str = _eval_others(proto[TOKEN_FACES][face_idx][TOKEN_FACES_TEXTURE], params)
# add into remap if not exist
if mtl_name not in mtl_remap:
mtl_remap[mtl_name] = len(mtl_remap)
# prepare mesh part data
mesh_part: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient()
def vpos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3()
for vec_idx in valid_vec_idx:
# BME no need to convert co system
v.x, v.y, v.z = _eval_others(proto[TOKEN_VERTICES][vec_idx][TOKEN_VERTICES_DATA], params)
yield v
mesh_part.mVertexPosition = vpos_iterator()
def vnml_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3()
for face_idx in valid_face_idx:
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
for i in range(len(face_data[TOKEN_FACES_INDICES])):
v.x, v.y, v.z = _eval_others(face_data[TOKEN_FACES_NORMALS][i], params)
# BME normals need normalize
UTIL_virtools_types.vxvector3_normalize(v)
yield v
mesh_part.mVertexNormal = vnml_iterator()
def vuv_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector2]:
v: UTIL_virtools_types.VxVector2 = UTIL_virtools_types.VxVector2()
for face_idx in valid_face_idx:
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
for i in range(len(face_data[TOKEN_FACES_INDICES])):
v.x, v.y = _eval_others(face_data[TOKEN_FACES_UVS][i], params)
yield v
mesh_part.mVertexUV = vuv_iterator()
def mtl_iterator() -> typing.Iterator[bpy.types.Material | None]:
for mtl_name in mtl_remap.keys():
yield bmemtl.get_material(mtl_name)
mesh_part.mMaterial = mtl_iterator()
def face_iterator() -> typing.Iterator[UTIL_blender_mesh.FaceData]:
# create face data with 3 placeholder
f: UTIL_blender_mesh.FaceData = UTIL_blender_mesh.FaceData(
[UTIL_blender_mesh.FaceVertexData() for i in range(3)]
)
# create a internal counter to count how many indices has been processed
# this counter will be used to calc uv and normal index
# because these are based on face, not vertex position index.
face_counter: int = 0
# iterate valid face
for face_idx in valid_face_idx:
# get face data
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
# calc indices count
face_indices: list[int] = face_data[TOKEN_FACES_INDICES]
indices_count: int = len(face_indices)
# resize face data to fulfill req
while len(f.mIndices) > indices_count:
f.mIndices.pop()
while len(f.mIndices) < indices_count:
f.mIndices.append(UTIL_blender_mesh.FaceVertexData())
# fill the data
for i in range(indices_count):
# fill vertex position data by indices
f.mIndices[i].mPosIdx = face_indices[i]
# fill nml and uv based on face index
f.mIndices[i].mNmlIdx = face_counter + i
f.mIndices[i].mUvIdx = face_counter + i
# add current face indices count to internal counter
face_counter += indices_count
# return data once
yield f
mesh_part.mFace = face_iterator()
# add part to writer
writer.add_ingredient(mesh_part)
# then we incursively process instance creation
for proto_instance in proto[TOKEN_INSTANCES]:
# calc instance params
instance_params: dict[str, typing.Any] = {}
proto_instance_params: dict[str, str] = proto_instance[TOKEN_INSTANCES_PARAMS]
for proto_inst_param_field, proto_inst_param_data in proto_instance_params.items():
instance_params[proto_inst_param_field] = _eval_others(proto_inst_param_data, params)
# call recursively
create_bme_struct(
proto_instance[TOKEN_INSTANCES_IDENTIFIER],
writer,
bmemtl,
_eval_others(proto_instance[TOKEN_INSTANCES_TRANSFORM], params),
instance_params
)
#endregion #endregion

View File

@ -27,6 +27,14 @@ def vxvector3_conv_co(self: VxVector3) -> None:
""" """
self.y, self.z = self.z, self.y self.y, self.z = self.z, self.y
def vxvector3_normalize(self: VxVector3) -> None:
"""
Normalize given Vector
"""
cache: mathutils.Vector = mathutils.Vector((self.x, self.y, self.z))
cache.normalize()
self.x, self.y, self.z = cache.x, cache.y, cache.z
#endregion #endregion
#region VxMatrix Patch #region VxMatrix Patch