fix issues
- fix Sector group no-successive issue when saving as nmo - add nong ventilator adder. - use copy.copy to write some code to reduce the calling of get/set_raw_vt_mtl() - keep texture when apply virtools mtl preset.
This commit is contained in:
parent
03e8feac67
commit
50b7eb0bce
@ -235,6 +235,74 @@ class BBP_OT_add_nong_extra_point(bpy.types.Operator, ComponentSectorParam, Comp
|
||||
)
|
||||
)
|
||||
|
||||
class BBP_OT_add_nong_ventilator(bpy.types.Operator, ComponentSectorParam, ComponentCountParam):
|
||||
"""Add Nong Ventilator"""
|
||||
bl_idname = "bbp.add_nong_ventilator"
|
||||
bl_label = "Nong Ventilator"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
ventilator_count_source: bpy.props.EnumProperty(
|
||||
name = "Ventilator Count Source",
|
||||
items = (
|
||||
('DEFINED', "Predefined", "Pre-defined ventilator count."),
|
||||
('CUSTOM', "Custom", "User specified ventilator count."),
|
||||
),
|
||||
)
|
||||
|
||||
preset_vetilator_count: bpy.props.EnumProperty(
|
||||
name = "Preset Count",
|
||||
description = "Pick preset ventilator count.",
|
||||
items = (
|
||||
# (token, display name, descriptions, icon, index)
|
||||
('PAPER', 'Paper', 'The ventilator count (1) can push paper ball up.'),
|
||||
('WOOD', 'Wood', 'The ventilator count (6) can push wood ball up.'),
|
||||
('STONE', 'Stone', 'The ventilator count (32) can push stone ball up.'),
|
||||
),
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
# draw sector settings
|
||||
self.draw_component_sector_params(layout)
|
||||
|
||||
# draw count settings by different source
|
||||
layout.label(text = 'Count')
|
||||
layout.prop(self, 'ventilator_count_source', expand = True)
|
||||
if (self.ventilator_count_source == 'CUSTOM'):
|
||||
self.draw_component_count_params(layout)
|
||||
else:
|
||||
layout.prop(self, 'preset_vetilator_count')
|
||||
|
||||
def execute(self, context):
|
||||
# get ventilator count
|
||||
count: int = 0
|
||||
if (self.ventilator_count_source == 'CUSTOM'):
|
||||
count = self.general_get_component_count()
|
||||
else:
|
||||
match(self.preset_vetilator_count):
|
||||
case 'PAPER': count = 1
|
||||
case 'WOOD': count = 6
|
||||
case 'STONE': count = 32
|
||||
case _: raise UTIL_functions.BBPException('invalid enumprop data')
|
||||
|
||||
# create elements without any move
|
||||
_general_create_component(
|
||||
PROP_ballance_element.BallanceElementType.P_Modul_18,
|
||||
self.general_get_component_sector(),
|
||||
count,
|
||||
lambda _: mathutils.Matrix.Identity(4)
|
||||
)
|
||||
return {'FINISHED'}
|
||||
|
||||
@staticmethod
|
||||
def draw_blc_menu(layout: bpy.types.UILayout):
|
||||
layout.operator(
|
||||
BBP_OT_add_nong_ventilator.bl_idname,
|
||||
icon_value = UTIL_icons_manager.get_component_icon(
|
||||
PROP_ballance_element.get_ballance_element_name(PROP_ballance_element.BallanceElementType.P_Modul_18)
|
||||
)
|
||||
)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Series Comp Adder
|
||||
@ -412,6 +480,7 @@ class BBP_OT_add_sector_component_pair(bpy.types.Operator, ComponentSectorParam)
|
||||
def register():
|
||||
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_nong_ventilator)
|
||||
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)
|
||||
@ -420,5 +489,6 @@ 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_ventilator)
|
||||
bpy.utils.unregister_class(BBP_OT_add_nong_extra_point)
|
||||
bpy.utils.unregister_class(BBP_OT_add_component)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import bpy
|
||||
from bpy_extras.wm_utils.progress_report import ProgressReport
|
||||
import tempfile, os, typing
|
||||
import tempfile, os, typing, re
|
||||
from . import PROP_preferences, UTIL_ioport_shared
|
||||
from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture, UTIL_icons_manager
|
||||
from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture
|
||||
@ -164,15 +164,18 @@ def _export_virtools_groups(
|
||||
# start saving
|
||||
progress.enter_substeps(len(obj3d_crets), "Saving Groups")
|
||||
|
||||
# create group exporting helper
|
||||
group_cret_guard: VirtoolsGroupCreationGuard = VirtoolsGroupCreationGuard(writer)
|
||||
|
||||
for obj3d, vtobj3d in obj3d_crets:
|
||||
# open group visitor
|
||||
with PROP_virtools_group.VirtoolsGroupsHelper(obj3d) as gp_visitor:
|
||||
for gp_name in gp_visitor.iterate_groups():
|
||||
# get group or create new group
|
||||
# get group or create new group from guard
|
||||
vtgroup: bmap.BMGroup | None = group_cret_map.get(gp_name, None)
|
||||
if vtgroup is None:
|
||||
vtgroup = writer.create_group()
|
||||
vtgroup.set_name(gp_name)
|
||||
# note: no need to set name, guard has set it.
|
||||
vtgroup = group_cret_guard.create_group(gp_name)
|
||||
group_cret_map[gp_name] = vtgroup
|
||||
|
||||
# group this object
|
||||
@ -462,6 +465,72 @@ def _save_virtools_document(
|
||||
progress.step()
|
||||
progress.leave_substeps()
|
||||
|
||||
class VirtoolsGroupCreationGuard():
|
||||
"""
|
||||
This class is designed for ensure that the created sector group is successive.
|
||||
|
||||
Due to the design of Ballance, Ballance rely on checking the existance of Sector_XX to get how many sectors this map have.
|
||||
Thus if there are no component in a sector, it still need to create a empty Sector_XX group, otherwise the game will crash
|
||||
or be ended at a accident sector.
|
||||
|
||||
This class hook the operation of Virtools group creation and check all Sector group creation.
|
||||
Create essential group to make Sector_XX group successive.
|
||||
Thus all group creation in this module should be passed by this class.
|
||||
"""
|
||||
cRegexGroupSector: typing.ClassVar[re.Pattern] = re.compile('^Sector_(0[1-8]|[1-9][0-9]{1,2}|9)$')
|
||||
|
||||
@staticmethod
|
||||
def __get_group_index(group_name: str) -> int | None:
|
||||
"""
|
||||
Return the sector index of group name if it is. Otherwise None.
|
||||
"""
|
||||
regex_result = VirtoolsGroupCreationGuard.cRegexGroupSector.match(group_name)
|
||||
if regex_result is not None:
|
||||
return int(regex_result.group(1))
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def __get_group_name(group_index: int) -> str:
|
||||
"""
|
||||
Output Sector group name by given sector index
|
||||
"""
|
||||
if group_index == 9:
|
||||
return 'Sector_9'
|
||||
else:
|
||||
return f'Sector_{group_index:0>2d}'
|
||||
|
||||
__mWriter: bmap.BMFileWriter
|
||||
__mSectors: list[bmap.BMGroup]
|
||||
|
||||
def __init__(self, assoc_writer: bmap.BMFileWriter):
|
||||
self.__mWriter = assoc_writer
|
||||
self.__mSectors = []
|
||||
|
||||
def create_group(self, group_name: str) -> bmap.BMGroup:
|
||||
"""
|
||||
The hooked group creation function.
|
||||
|
||||
Please note the passed group name argument is just for name checking.
|
||||
This function will set group name for you, not like BMFileWriter.create_group() operated.
|
||||
"""
|
||||
# check whether it is sector group
|
||||
# note: the return sector index is 1 based, not 0
|
||||
sector_idx: int | None = VirtoolsGroupCreationGuard.__get_group_index(group_name)
|
||||
# if it is regular group, return normal creation
|
||||
if sector_idx is None:
|
||||
gp: bmap.BMGroup = self.__mWriter.create_group()
|
||||
gp.set_name(group_name)
|
||||
return gp
|
||||
|
||||
# get from sector cahce list
|
||||
# enlarge sector cache list if it is not fulfilled given sector index
|
||||
while sector_idx > len(self.__mSectors):
|
||||
gp: bmap.BMGroup = self.__mWriter.create_group()
|
||||
self.__mSectors.append(gp)
|
||||
gp.set_name(self.__get_group_name(len(self.__mSectors)))
|
||||
# return ordered sector from sector caches
|
||||
return self.__mSectors[sector_idx - 1]
|
||||
|
||||
def register() -> None:
|
||||
bpy.utils.register_class(BBP_OT_export_virtools)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import bpy
|
||||
import typing, enum
|
||||
import typing, enum, copy
|
||||
from . import PROP_virtools_material, PROP_virtools_texture
|
||||
from . import UTIL_ballance_texture, UTIL_functions
|
||||
|
||||
@ -91,21 +91,19 @@ def _load_bme_material_preset(mtl: bpy.types.Material, preset_name: str) -> None
|
||||
# get preset first
|
||||
preset: _BMEMaterialPreset = _g_BMEMaterialPresets[preset_name]
|
||||
|
||||
# apply raw data first
|
||||
PROP_virtools_material.set_raw_virtools_material(mtl, preset.mRawMtl)
|
||||
# get raw mtl and do a shallow copy
|
||||
# because we will change something later. but do not want to affect preset self.
|
||||
raw_mtl: PROP_virtools_material.RawVirtoolsMaterial = copy.copy(preset.mRawMtl)
|
||||
|
||||
# load ballance texture
|
||||
blctex: bpy.types.Image = UTIL_ballance_texture.load_ballance_texture(preset.mTexName)
|
||||
# apply texture props
|
||||
PROP_virtools_texture.set_raw_virtools_texture(blctex, PROP_virtools_texture.get_ballance_texture_preset(preset.mTexName))
|
||||
# set loaded texture to shallow copied raw mtl
|
||||
raw_mtl.mTexture = blctex
|
||||
|
||||
# because preset's rawmtl is const, we can not change it directly
|
||||
# so we need change its texture by triving it again as a new rawmtl
|
||||
# after we got ballance texture
|
||||
newrawmtl: PROP_virtools_material.RawVirtoolsMaterial = PROP_virtools_material.get_raw_virtools_material(mtl)
|
||||
newrawmtl.mTexture = blctex
|
||||
PROP_virtools_material.set_raw_virtools_material(mtl, newrawmtl)
|
||||
|
||||
# set raw mtl
|
||||
PROP_virtools_material.set_raw_virtools_material(mtl, raw_mtl)
|
||||
# apply vt mtl to blender mtl
|
||||
PROP_virtools_material.apply_to_blender_material(mtl)
|
||||
|
||||
|
@ -270,7 +270,7 @@ class SharedGroupNameInputProperties():
|
||||
)
|
||||
|
||||
def draw_group_name_input(self, layout: bpy.types.UILayout) -> None:
|
||||
layout.prop(self, 'group_name_source', expand=True)
|
||||
layout.prop(self, 'group_name_source', expand = True)
|
||||
if (self.group_name_source == 'CUSTOM'):
|
||||
layout.prop(self, 'custom_group_name')
|
||||
else:
|
||||
|
@ -1,5 +1,5 @@
|
||||
import bpy
|
||||
import typing, enum
|
||||
import typing, enum, copy
|
||||
from . import UTIL_virtools_types, UTIL_functions, UTIL_ballance_texture, UTIL_file_browser
|
||||
from . import PROP_virtools_texture, PROP_preferences
|
||||
|
||||
@ -515,8 +515,17 @@ def get_virtools_material_preset(preset_type: MaterialPresetType) -> MaterialPre
|
||||
return _g_MaterialPresets[preset_type]
|
||||
|
||||
def preset_virtools_material(mtl: bpy.types.Material, preset_type: MaterialPresetType) -> None:
|
||||
preset_data: MaterialPresetData = _g_MaterialPresets[preset_type]
|
||||
set_raw_virtools_material(mtl, preset_data.mData)
|
||||
# get preset raw mtl member first
|
||||
# but we need create a shallow copy for it first.
|
||||
preset_data: RawVirtoolsMaterial = copy.copy(_g_MaterialPresets[preset_type].mData)
|
||||
# the we get texture setting from now texture
|
||||
now_data: RawVirtoolsMaterial = get_raw_virtools_material(mtl)
|
||||
# change preset texture to current texture
|
||||
# because we do not want to change texture by preset.
|
||||
# also this is the reason why i need do a shallow copy for preset data
|
||||
preset_data.mTexture = now_data.mTexture
|
||||
# apply preset
|
||||
set_raw_virtools_material(mtl, preset_data)
|
||||
|
||||
# create preset enum blender helper
|
||||
_g_Helper_MtlPreset: UTIL_functions.EnumPropHelper = UTIL_functions.EnumPropHelper(
|
||||
|
@ -68,7 +68,7 @@ _g_BMEPrototypes: list[dict[str, typing.Any]] = []
|
||||
_g_BMEPrototypeIndexMap: dict[str, int] = {}
|
||||
|
||||
# the core loader
|
||||
for walk_root, walk_dirs, walk_files in os.walk(os.path.join(os.path.dirname(__file__), 'json')):
|
||||
for walk_root, walk_dirs, walk_files in os.walk(os.path.join(os.path.dirname(__file__), 'jsons')):
|
||||
for relfile in walk_files:
|
||||
if not relfile.endswith('.json'): continue
|
||||
with open(os.path.join(walk_root, relfile), 'r', encoding = 'utf-8') as fp:
|
||||
|
@ -78,6 +78,7 @@ class BBP_MT_AddComponentsMenu(bpy.types.Menu):
|
||||
layout.separator()
|
||||
layout.label(text="Nong Components")
|
||||
OP_ADDS_component.BBP_OT_add_nong_extra_point.draw_blc_menu(layout)
|
||||
OP_ADDS_component.BBP_OT_add_nong_ventilator.draw_blc_menu(layout)
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Series Components")
|
||||
|
Loading…
Reference in New Issue
Block a user