7 Commits

Author SHA1 Message Date
684567777f feat: add virtools camera support 2026-03-06 16:10:05 +08:00
5e94d7db85 fix: change the default length of flat and sink street from 2.5 to 5
- this feature is requested by Lee623
2026-03-06 14:40:50 +08:00
8a7e3306a7 feat: allow exporting object in virtools file which has geometry.
- allow exporting object without apply modifier.
- allow exporting any objects which can be mesh (has geometry).
- due to this change, add virtools mesh properties for metaball, font, curve, surface.
- due to this change, remove the virtools group warning for metaball, font, curve and surface.
2026-03-05 21:45:36 +08:00
68fbffad54 feat: update pybmap to the latest version 2026-03-05 12:45:25 +08:00
dd6e557f39 refactor: rename PyBMap to pybmap due to the change of libcmo21 2026-03-04 21:56:11 +08:00
e4a4eae88e fix: fix fatal error when exporting virtools file
- fix fatal error that user only can export virtools file into existing file, rather than any new file.
2025-09-23 21:45:56 +08:00
f920cdcaf5 i18n: fix translation 2025-09-04 10:01:41 +08:00
18 changed files with 919 additions and 583 deletions

View File

@@ -1,324 +1,324 @@
[ [
{ {
"identifier": "floor_normal_straight", "identifier": "floor_normal_straight",
"showcase": { "showcase": {
"title": "Normal Floor", "title": "Normal Floor",
"category": "Floors", "category": "Floors",
"icon": "NormalFloor", "icon": "NormalFloor",
"type": "floor", "type": "floor",
"cfgs": [ "cfgs": [
{ {
"field": "height_", "field": "height_",
"type": "float", "type": "float",
"title": "Height", "title": "Height",
"desc": "The height of block.", "desc": "The height of block.",
"default": "5.0" "default": "5.0"
}, },
{ {
"field": "length_", "field": "length_",
"type": "float", "type": "float",
"title": "Length", "title": "Length",
"desc": "The length of block.", "desc": "The length of block.",
"default": "2.5" "default": "5.0"
}, },
{ {
"field": "face_", "field": "face_",
"type": "face", "type": "face",
"title": "Face", "title": "Face",
"desc": "Whether has some faces.", "desc": "Whether has some faces.",
"default": "(True, False, False, False, True, True)" "default": "(True, False, False, False, True, True)"
} }
] ]
}, },
"params": [ "params": [
{ {
"field": "height", "field": "height",
"data": "height_" "data": "height_"
}, },
{ {
"field": "length", "field": "length",
"data": "length_" "data": "length_"
}, },
{ {
"field": "face", "field": "face",
"data": "face_" "data": "face_"
} }
], ],
"skip": "length == 0", "skip": "length == 0",
"vars": [ "vars": [
{ {
"field": "length_uv", "field": "length_uv",
"data": "length / 5.0" "data": "length / 5.0"
} }
], ],
"vertices": [ "vertices": [
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(0, 0, 0)" "data": "(0, 0, 0)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(length, 0, 0)" "data": "(length, 0, 0)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(length, 5, 0)" "data": "(length, 5, 0)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(0, 5, 0)" "data": "(0, 5, 0)"
} }
], ],
"faces": [ "faces": [
{ {
"skip": "not face[0]", "skip": "not face[0]",
"texture": "\"FloorTopFlat\"", "texture": "\"FloorTopFlat\"",
"indices": [0, 1, 2, 3], "indices": [0, 1, 2, 3],
"uvs": [ "uvs": [
"(0, 0)", "(0, 0)",
"(0, length_uv)", "(0, length_uv)",
"(1, length_uv)", "(1, length_uv)",
"(1, 0)" "(1, 0)"
], ],
"normals": null "normals": null
} }
], ],
"instances": [ "instances": [
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[2]", "skip": "not face[2]",
"params": { "params": {
"height": "height", "height": "height",
"length": "5", "length": "5",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "rot(0, 0, 90) @ scale(1, -1, 1)" "transform": "rot(0, 0, 90) @ scale(1, -1, 1)"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[3]", "skip": "not face[3]",
"params": { "params": {
"height": "height", "height": "height",
"length": "5", "length": "5",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "move(length, 0, 0) @ rot(0, 0, 90)" "transform": "move(length, 0, 0) @ rot(0, 0, 90)"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[4]", "skip": "not face[4]",
"params": { "params": {
"height": "height", "height": "height",
"length": "length", "length": "length",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "ident()" "transform": "ident()"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[5]", "skip": "not face[5]",
"params": { "params": {
"height": "height", "height": "height",
"length": "length", "length": "length",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "move(0, 5, 0) @ scale(1, -1, 1)" "transform": "move(0, 5, 0) @ scale(1, -1, 1)"
}, },
{ {
"identifier": "floor_rectangle_bottom", "identifier": "floor_rectangle_bottom",
"skip": "not face[1]", "skip": "not face[1]",
"params": { "params": {
"length": "length", "length": "length",
"width": "5" "width": "5"
}, },
"transform": "move(0, 0, -height)" "transform": "move(0, 0, -height)"
} }
] ]
}, },
{ {
"identifier": "floor_sink_straight", "identifier": "floor_sink_straight",
"showcase": { "showcase": {
"title": "Sink Floor", "title": "Sink Floor",
"category": "Floors", "category": "Floors",
"icon": "SinkFloor", "icon": "SinkFloor",
"type": "floor", "type": "floor",
"cfgs": [ "cfgs": [
{ {
"field": "height_", "field": "height_",
"type": "float", "type": "float",
"title": "Height", "title": "Height",
"desc": "The height of block.", "desc": "The height of block.",
"default": "5.0" "default": "5.0"
}, },
{ {
"field": "length_", "field": "length_",
"type": "float", "type": "float",
"title": "Length", "title": "Length",
"desc": "The length of block.", "desc": "The length of block.",
"default": "2.5" "default": "5.0"
}, },
{ {
"field": "face_", "field": "face_",
"type": "face", "type": "face",
"title": "Face", "title": "Face",
"desc": "Whether has some faces.", "desc": "Whether has some faces.",
"default": "(True, False, False, False, True, True)" "default": "(True, False, False, False, True, True)"
} }
] ]
}, },
"params": [ "params": [
{ {
"field": "height", "field": "height",
"data": "height_" "data": "height_"
}, },
{ {
"field": "length", "field": "length",
"data": "length_" "data": "length_"
}, },
{ {
"field": "face", "field": "face",
"data": "face_" "data": "face_"
} }
], ],
"skip": "length == 0", "skip": "length == 0",
"vars": [ "vars": [
{ {
"field": "length_uv", "field": "length_uv",
"data": "length / 5.0" "data": "length / 5.0"
} }
], ],
"vertices": [ "vertices": [
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(0, 0, 0)" "data": "(0, 0, 0)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(length, 0, 0)" "data": "(length, 0, 0)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(length, 2.5, -0.7)" "data": "(length, 2.5, -0.7)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(0, 2.5, -0.7)" "data": "(0, 2.5, -0.7)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(length, 5, 0)" "data": "(length, 5, 0)"
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"data": "(0, 5, 0)" "data": "(0, 5, 0)"
} }
], ],
"faces": [ "faces": [
{ {
"skip": "not face[0]", "skip": "not face[0]",
"texture": "\"FloorTopProfil\"", "texture": "\"FloorTopProfil\"",
"indices": [0, 1, 2, 3], "indices": [0, 1, 2, 3],
"uvs": [ "uvs": [
"(0, 0)", "(0, 0)",
"(0, length_uv)", "(0, length_uv)",
"(0.5, length_uv)", "(0.5, length_uv)",
"(0.5, 0)" "(0.5, 0)"
], ],
"normals": null "normals": null
}, },
{ {
"skip": "not face[0]", "skip": "not face[0]",
"texture": "\"FloorTopProfil\"", "texture": "\"FloorTopProfil\"",
"indices": [3, 2, 4, 5], "indices": [3, 2, 4, 5],
"uvs": [ "uvs": [
"(0.5, 0)", "(0.5, 0)",
"(0.5, length_uv)", "(0.5, length_uv)",
"(1, length_uv)", "(1, length_uv)",
"(1, 0)" "(1, 0)"
], ],
"normals": null "normals": null
} }
], ],
"instances": [ "instances": [
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[2]", "skip": "not face[2]",
"params": { "params": {
"height": "height", "height": "height",
"length": "2.5", "length": "2.5",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "True" "is_right_sink": "True"
}, },
"transform": "rot(0, 0, 90) @ scale(1, -1, 1)" "transform": "rot(0, 0, 90) @ scale(1, -1, 1)"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[2]", "skip": "not face[2]",
"params": { "params": {
"height": "height", "height": "height",
"length": "2.5", "length": "2.5",
"is_left_sink": "True", "is_left_sink": "True",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "move(0, 2.5, 0) @ rot(0, 0, 90) @ scale(1, -1, 1)" "transform": "move(0, 2.5, 0) @ rot(0, 0, 90) @ scale(1, -1, 1)"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[3]", "skip": "not face[3]",
"params": { "params": {
"height": "height", "height": "height",
"length": "2.5", "length": "2.5",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "True" "is_right_sink": "True"
}, },
"transform": "move(length, 0, 0) @ rot(0, 0, 90)" "transform": "move(length, 0, 0) @ rot(0, 0, 90)"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[3]", "skip": "not face[3]",
"params": { "params": {
"height": "height", "height": "height",
"length": "2.5", "length": "2.5",
"is_left_sink": "True", "is_left_sink": "True",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "move(length, 2.5, 0) @ rot(0, 0, 90)" "transform": "move(length, 2.5, 0) @ rot(0, 0, 90)"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[4]", "skip": "not face[4]",
"params": { "params": {
"height": "height", "height": "height",
"length": "length", "length": "length",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "ident()" "transform": "ident()"
}, },
{ {
"identifier": "raw_floor_side", "identifier": "raw_floor_side",
"skip": "not face[5]", "skip": "not face[5]",
"params": { "params": {
"height": "height", "height": "height",
"length": "length", "length": "length",
"is_left_sink": "False", "is_left_sink": "False",
"is_right_sink": "False" "is_right_sink": "False"
}, },
"transform": "move(0, 5, 0) @ scale(1, -1, 1)" "transform": "move(0, 5, 0) @ scale(1, -1, 1)"
}, },
{ {
"identifier": "floor_rectangle_bottom", "identifier": "floor_rectangle_bottom",
"skip": "not face[1]", "skip": "not face[1]",
"params": { "params": {
"length": "length", "length": "length",
"width": "5" "width": "5"
}, },
"transform": "move(0, 0, -height)" "transform": "move(0, 0, -height)"
} }
] ]
} }
] ]

4
bbp_ng/.gitignore vendored
View File

@@ -1,7 +1,7 @@
## ===== Personal ===== ## ===== Personal =====
# Do not include PyBMap in this repository. # Do not include pybmap in this repository.
# Order user build and fetch it manually. # Order user build and fetch it manually.
PyBMap/ pybmap/
# Disable generated assets but keep the directory hierarchy. # Disable generated assets but keep the directory hierarchy.
icons/* icons/*

View File

@@ -4,7 +4,7 @@ import tempfile, os, typing
from . import PROP_preferences, UTIL_ioport_shared, UTIL_naming_convention from . import PROP_preferences, UTIL_ioport_shared, UTIL_naming_convention
from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture
from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_virtools_light from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_virtools_light
from .PyBMap import bmap_wrapper as bmap from .pybmap import bmap_wrapper as bmap
class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtoolsFile, UTIL_ioport_shared.ExportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams): class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtoolsFile, UTIL_ioport_shared.ExportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams):
"""Export Virtools File""" """Export Virtools File"""
@@ -44,9 +44,18 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
self.report({'ERROR'}, 'You must specify at least one encoding for file saving (e.g. cp1252, gbk)!') self.report({'ERROR'}, 'You must specify at least one encoding for file saving (e.g. cp1252, gbk)!')
return {'CANCELLED'} return {'CANCELLED'}
# check file name # check file name, but has slightly difference with importer.
# when exporting, file can be inexisting in file system, so we can't check it directly.
filename = self.general_get_filename() filename = self.general_get_filename()
if not os.path.isfile(filename): bad_filename: bool = False
# for filename, at first, it should not be empty surely.
if len(filename) == 0:
bad_filename = True
# then, if it is existing, it should be a file, otherwise everything is okey.
if os.path.exists(filename) and (not os.path.isfile(filename)):
bad_filename = True
# now, show message and exit if we have bad file name
if bad_filename:
self.report({'ERROR'}, 'No file was selected!') self.report({'ERROR'}, 'No file was selected!')
return {'CANCELLED'} return {'CANCELLED'}
@@ -150,28 +159,33 @@ def _prepare_virtools_3dobjects(
# iterate exported object list # iterate exported object list
for obj3d in export_objects: for obj3d in export_objects:
# only accept mesh object and light object # only accept mesh-like object, camera and light object
# all of other objects will be discard. # all of other objects will be discard.
match(obj3d.type): if UTIL_blender_mesh.TemporaryMesh.has_geometry(obj3d):
case 'MESH': # mesh-like object
# mesh object if obj3d not in obj3d_cret_set:
if obj3d not in obj3d_cret_set: # add into set
# add into set obj3d_cret_set.add(obj3d)
obj3d_cret_set.add(obj3d) # create virtools instance
# create virtools instance vtobj3d: bmap.BM3dObject = writer.create_3dobject()
vtobj3d: bmap.BM3dObject = writer.create_3dobject() # add into result list
# add into result list obj3d_crets.append((obj3d, vtobj3d))
obj3d_crets.append((obj3d, vtobj3d)) else:
case 'LIGHT': match(obj3d.type):
# light object case 'CAMERA':
if obj3d not in light_cret_set: # camera object
# add into set # TODO
light_cret_set.add(obj3d) pass
# create virtools instance case 'LIGHT':
vtlight: bmap.BMTargetLight = writer.create_target_light() # light object
# add into result list if obj3d not in light_cret_set:
light_crets.append((obj3d, typing.cast(bpy.types.Light, obj3d.data), vtlight)) # add into set
light_cret_set.add(obj3d)
# create virtools instance
vtlight: bmap.BMTargetLight = writer.create_target_light()
# add into result list
light_crets.append((obj3d, typing.cast(bpy.types.Light, obj3d.data), vtlight))
# step progress no matter whether create new one # step progress no matter whether create new one
progress.step() progress.step()

View File

@@ -4,7 +4,7 @@ import tempfile, os, typing
from . import PROP_preferences, UTIL_ioport_shared, UTIL_naming_convention from . import PROP_preferences, UTIL_ioport_shared, UTIL_naming_convention
from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture
from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_virtools_light, PROP_ballance_map_info from . import PROP_virtools_group, PROP_virtools_material, PROP_virtools_mesh, PROP_virtools_texture, PROP_virtools_light, PROP_ballance_map_info
from .PyBMap import bmap_wrapper as bmap from .pybmap import bmap_wrapper as bmap
class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtoolsFile, UTIL_ioport_shared.ImportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams): class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtoolsFile, UTIL_ioport_shared.ImportParams, UTIL_ioport_shared.VirtoolsParams, UTIL_ioport_shared.BallanceParams):
"""Import Virtools File""" """Import Virtools File"""

View File

@@ -191,6 +191,9 @@ class BBP_OT_game_camera(bpy.types.Operator):
) # type: ignore ) # type: ignore
rotation_kind: bpy.props.EnumProperty( rotation_kind: bpy.props.EnumProperty(
# YYC MAKR:
# This property is not shown on UI layout,
# but it should be translated because it is not PURE assistant property.
name = "Rotation Angle Kind", name = "Rotation Angle Kind",
description = "", description = "",
items = _g_EnumHelper_RotationKind.generate_items(), items = _g_EnumHelper_RotationKind.generate_items(),
@@ -198,9 +201,9 @@ class BBP_OT_game_camera(bpy.types.Operator):
translation_context = 'BBP_OT_game_camera/property' translation_context = 'BBP_OT_game_camera/property'
) # type: ignore ) # type: ignore
preset_rotation_angle: bpy.props.EnumProperty( preset_rotation_angle: bpy.props.EnumProperty(
# I18N: Property not showen should not have name and desc. name = "Preset Rotation Angle",
# name = "Preset Rotation Angle", description = "",
# description = "", translation_context = 'BBP_OT_game_camera/property',
options = {'HIDDEN'}, options = {'HIDDEN'},
items = _g_EnumHelper_RotationAngle.generate_items(), items = _g_EnumHelper_RotationAngle.generate_items(),
default = _g_EnumHelper_RotationAngle.to_selection(RotationAngle.Deg0), default = _g_EnumHelper_RotationAngle.to_selection(RotationAngle.Deg0),

View File

@@ -202,7 +202,7 @@ class PropsVisitor():
""" """
encodings = get_ioport_encodings(self.__mAssocScene) encodings = get_ioport_encodings(self.__mAssocScene)
encodings.clear() encodings.clear()
for default_enc in UTIL_virtools_types.g_PyBMapDefaultEncodings: for default_enc in UTIL_virtools_types.g_PybmapDefaultEncodings:
item = encodings.add() item = encodings.add()
item.encoding = default_enc item.encoding = default_enc
def draw_ioport_encodings(self, layout: bpy.types.UILayout) -> None: def draw_ioport_encodings(self, layout: bpy.types.UILayout) -> None:

View File

@@ -0,0 +1,292 @@
import bpy
import typing, math
from . import UTIL_functions, UTIL_virtools_types
# Raw Data
class RawVirtoolsCamera():
# Class Member
mProjectionType: UTIL_virtools_types.CK_CAMERA_PROJECTION
mOrthographicZoom: float
mFrontPlane: float
mBackPlane: float
mFov: float
mAspectRatio: tuple[int, int]
# Class member default value
cDefaultProjectionType: typing.ClassVar[UTIL_virtools_types.CK_CAMERA_PROJECTION] = UTIL_virtools_types.CK_CAMERA_PROJECTION.CK_PERSPECTIVEPROJECTION
cDefaultOrthographicZoom: typing.ClassVar[float] = 1.0
cDefaultFrontPlane: typing.ClassVar[float] = 1.0
cDefaultBackPlane: typing.ClassVar[float] = 4000.0
cDefaultFov: typing.ClassVar[float] = 0.5
cDefaultAspectRatio: typing.ClassVar[tuple[int, int]] = (4, 3)
def __init__(self, **kwargs):
# assign default value for each component
self.mProjectionType = kwargs.get("mProjectionType", RawVirtoolsCamera.cDefaultProjectionType)
self.mOrthographicZoom = kwargs.get("mOrthographicZoom", RawVirtoolsCamera.cDefaultOrthographicZoom)
self.mFrontPlane = kwargs.get("mFrontPlane", RawVirtoolsCamera.cDefaultFrontPlane)
self.mBackPlane = kwargs.get("mBackPlane", RawVirtoolsCamera.cDefaultBackPlane)
self.mFov = kwargs.get("mFov", RawVirtoolsCamera.cDefaultFov)
self.mAspectRatio = kwargs.get("mAspectRatio", RawVirtoolsCamera.cDefaultAspectRatio)
def regulate(self) -> None:
# everything should be positive
self.mOrthographicZoom = max(0.0, self.mOrthographicZoom)
self.mFrontPlane = max(0.0, self.mFrontPlane)
self.mBackPlane = max(0.0, self.mBackPlane)
self.mFov = max(0.0, self.mFov)
# aspect ratio should be positive and at least 1
(w, h) = self.mAspectRatio
w = max(1, w)
h = max(1, h)
self.mAspectRatio = (w, h)
# Blender Property Group
_g_Helper_CK_CAMERA_PROJECTION = UTIL_virtools_types.EnumPropHelper(UTIL_virtools_types.CK_CAMERA_PROJECTION)
class BBP_PG_virtools_camera(bpy.types.PropertyGroup):
projection_type: bpy.props.EnumProperty(
name = "Type",
description = "The type of this camera.",
items = _g_Helper_CK_CAMERA_PROJECTION.generate_items(),
default = _g_Helper_CK_CAMERA_PROJECTION.to_selection(RawVirtoolsCamera.cDefaultProjectionType),
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
orthographic_zoom: bpy.props.FloatProperty(
name = "Orthographic Zoom",
description = "Defines the orthographic zoom.",
min = 0.0,
soft_min = 0.0,
soft_max = 0.5,
step = 5,
default = RawVirtoolsCamera.cDefaultOrthographicZoom,
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
front_plane: bpy.props.FloatProperty(
name = "Front Plane",
description = "Defines the front plane.",
min = 0.0,
soft_min = 0.0,
soft_max = 5000.0,
step = 100,
default = RawVirtoolsCamera.cDefaultFrontPlane,
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
back_plane: bpy.props.FloatProperty(
name = "Back Plane",
description = "Defines the back plane.",
min = 0.0,
soft_min = 0.0,
soft_max = 5000.0,
step = 100,
default = RawVirtoolsCamera.cDefaultBackPlane,
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
fov: bpy.props.FloatProperty(
name = "Field of View",
description = "Defines the field of view.",
subtype = 'ANGLE',
min = 0.0,
max = math.radians(180.0),
step = 100,
precision = 100,
default = RawVirtoolsCamera.cDefaultFov,
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
aspect_ratio_w: bpy.props.IntProperty(
name = "Aspect Ratio Width",
description = "Defines the width of aspect ratio.",
min = 1,
soft_min = 1,
soft_max = 40,
step = 1,
default = RawVirtoolsCamera.cDefaultAspectRatio[0],
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
aspect_ratio_h: bpy.props.IntProperty(
name = "Aspect Ratio Height",
description = "Defines the height of aspect ratio.",
min = 1,
soft_min = 1,
soft_max = 40,
step = 1,
default = RawVirtoolsCamera.cDefaultAspectRatio[1],
translation_context = 'BBP_PG_virtools_camera/property'
) # type: ignore
# Getter Setter and Applyer
def get_virtools_camera(cam: bpy.types.Camera) -> BBP_PG_virtools_camera:
return cam.virtools_camera
def get_raw_virtools_camera(cam: bpy.types.Camera) -> RawVirtoolsCamera:
props: BBP_PG_virtools_camera = get_virtools_camera(cam)
rawdata: RawVirtoolsCamera = RawVirtoolsCamera()
rawdata.mProjectionType = _g_Helper_CK_CAMERA_PROJECTION.get_selection(props.projection_type)
rawdata.mOrthographicZoom = props.orthographic_zoom
rawdata.mFrontPlane = props.front_plane
rawdata.mBackPlane = props.back_plane
rawdata.mFov = props.fov
rawdata.mAspectRatio = (props.aspect_ratio_w, props.aspect_ratio_h)
rawdata.regulate()
return rawdata
def set_raw_virtools_camera(cam: bpy.types.Camera, rawdata: RawVirtoolsCamera) -> None:
props: BBP_PG_virtools_camera = get_virtools_camera(cam)
props.projection_type = _g_Helper_CK_CAMERA_PROJECTION.to_selection(rawdata.mProjectionType)
props.orthographic_zoom = rawdata.mOrthographicZoom
props.front_plane = rawdata.mFrontPlane
props.back_plane = rawdata.mBackPlane
props.fov = rawdata.mFov
(props.aspect_ratio_w, props.aspect_ratio_h) = rawdata.mAspectRatio
def apply_to_blender_camera(cam: bpy.types.Camera) -> None:
# get raw data first
rawdata: RawVirtoolsCamera = get_raw_virtools_camera(cam)
# set camera type
match(rawdata.mProjectionType):
case UTIL_virtools_types.CK_CAMERA_PROJECTION.CK_PERSPECTIVEPROJECTION:
cam.type = 'PERSP'
case UTIL_virtools_types.CK_CAMERA_PROJECTION.CK_ORTHOGRAPHICPROJECTION:
cam.type = 'ORTHO'
# set orthographic zoom
cam.ortho_scale = rawdata.mOrthographicZoom
# front and back plane
cam.clip_start = rawdata.mFrontPlane
cam.clip_end = rawdata.mBackPlane
# fov
cam.lens_unit = 'FOV'
cam.angle = rawdata.mFov
# Operators
class BBP_OT_apply_virtools_camera(bpy.types.Operator):
"""Apply Virtools Camera to Blender Camera."""
bl_idname = "bbp.apply_virtools_camera"
bl_label = "Apply to Blender Camera"
bl_options = {'UNDO'}
bl_translation_context = 'BBP_OT_apply_virtools_camera'
@classmethod
def poll(cls, context):
return context.camera is not None
def execute(self, context):
cam: bpy.types.Camera = context.camera
apply_to_blender_camera(cam)
return {'FINISHED'}
# Display Panel
class BBP_PT_virtools_camera(bpy.types.Panel):
"""Show Virtools Camera Properties"""
bl_label = "Virtools Camera"
bl_idname = "BBP_PT_virtools_camera"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data" # idk why blender use `data` as the camera tab same as mesh.
bl_translation_context = 'BBP_PT_virtools_camera'
@classmethod
def poll(cls, context):
return context.camera is not None
def draw(self, context):
# get layout and target
layout = self.layout
cam: bpy.types.Camera = context.camera
props: BBP_PG_virtools_camera = get_virtools_camera(cam)
rawdata: RawVirtoolsCamera = get_raw_virtools_camera(cam)
# draw operator
layout.operator(
BBP_OT_apply_virtools_camera.bl_idname, text='Apply', icon='NODETREE',
text_ctxt='BBP_PT_virtools_camera/draw')
# draw data
layout.separator()
# show camera type first
layout.prop(props, 'projection_type')
# all camera has front and back plane
layout.label(text='Clipping', text_ctxt='BBP_PT_virtools_camera/draw')
sublayout = layout.column()
sublayout.use_property_split = True
sublayout.prop(props, 'front_plane')
sublayout.prop(props, 'back_plane')
# only perspective camera has fov setting
if rawdata.mProjectionType == UTIL_virtools_types.CK_CAMERA_PROJECTION.CK_PERSPECTIVEPROJECTION:
layout.separator()
layout.label(text='Perspective Parameters', text_ctxt='BBP_PT_virtools_camera/draw')
sublayout = layout.column()
sublayout.use_property_split = True
sublayout.prop(props, 'fov')
# only orthographic camera has orthographic zoom setting
if rawdata.mProjectionType == UTIL_virtools_types.CK_CAMERA_PROJECTION.CK_ORTHOGRAPHICPROJECTION:
layout.separator()
layout.label(text='Orthographic Parameters', text_ctxt='BBP_PT_virtools_camera/draw')
sublayout = layout.column()
sublayout.use_property_split = True
sublayout.prop(props, 'orthographic_zoom')
# aspect ratio
layout.separator()
layout.label(text='Aspect Ratio', text_ctxt='BBP_PT_virtools_camera/draw')
sublayout = layout.row()
sublayout.use_property_split = False
sublayout.prop(props, 'aspect_ratio_w', text = '', expand = True)
sublayout.prop(props, 'aspect_ratio_h', text = '', expand = True)
# Register
def register() -> None:
bpy.utils.register_class(BBP_PG_virtools_camera)
bpy.utils.register_class(BBP_OT_apply_virtools_camera)
bpy.utils.register_class(BBP_PT_virtools_camera)
# add into camera metadata
bpy.types.Camera.virtools_camera = bpy.props.PointerProperty(type = BBP_PG_virtools_camera)
def unregister() -> None:
# remove from metadata
del bpy.types.Camera.virtools_camera
bpy.utils.unregister_class(BBP_PT_virtools_camera)
bpy.utils.unregister_class(BBP_OT_apply_virtools_camera)
bpy.utils.unregister_class(BBP_PG_virtools_camera)

View File

@@ -1,6 +1,6 @@
import bpy import bpy
import typing, enum import typing, enum
from . import UTIL_functions, UTIL_icons_manager from . import UTIL_functions, UTIL_icons_manager, UTIL_blender_mesh
#region Virtools Groups Define & Help Class #region Virtools Groups Define & Help Class
@@ -387,9 +387,9 @@ class BBP_PT_virtools_groups(bpy.types.Panel):
target = typing.cast(bpy.types.Object, context.active_object) target = typing.cast(bpy.types.Object, context.active_object)
# notify on non-mesh object # notify on non-mesh object
if target.type != 'MESH': if not UTIL_blender_mesh.TemporaryMesh.has_geometry(target):
layout.label( layout.label(
text='Virtools Group is invalid on non-mesh object!', icon='ERROR', text='Virtools Group is invalid on non-mesh-like object!', icon='ERROR',
text_ctxt='BBP_PT_virtools_groups/draw') text_ctxt='BBP_PT_virtools_groups/draw')
# draw main body # draw main body

View File

@@ -1,5 +1,4 @@
import bpy, mathutils import bpy
from bpy.types import Context
import typing, math import typing, math
from . import UTIL_functions, UTIL_virtools_types from . import UTIL_functions, UTIL_virtools_types

View File

@@ -1,6 +1,6 @@
import bpy import bpy
import typing, enum import typing, enum
from . import UTIL_functions, UTIL_virtools_types from . import UTIL_functions, UTIL_blender_mesh, UTIL_virtools_types
# Raw Data # Raw Data
@@ -30,19 +30,21 @@ class BBP_PG_virtools_mesh(bpy.types.PropertyGroup):
# Getter Setter # Getter Setter
def get_virtools_mesh(mesh: bpy.types.Mesh) -> BBP_PG_virtools_mesh: CanToMesh = bpy.types.Mesh | bpy.types.Curve | bpy.types.SurfaceCurve | bpy.types.TextCurve | bpy.types.MetaBall
return mesh.virtools_mesh
def get_raw_virtools_mesh(mesh: bpy.types.Mesh) -> RawVirtoolsMesh: def get_virtools_mesh(meshlike: CanToMesh) -> BBP_PG_virtools_mesh:
props: BBP_PG_virtools_mesh = get_virtools_mesh(mesh) return meshlike.virtools_mesh
def get_raw_virtools_mesh(meshlike: CanToMesh) -> RawVirtoolsMesh:
props: BBP_PG_virtools_mesh = get_virtools_mesh(meshlike)
rawdata: RawVirtoolsMesh = RawVirtoolsMesh() rawdata: RawVirtoolsMesh = RawVirtoolsMesh()
rawdata.mLitMode = _g_Helper_VXMESH_LITMODE.get_selection(props.lit_mode) rawdata.mLitMode = _g_Helper_VXMESH_LITMODE.get_selection(props.lit_mode)
return rawdata return rawdata
def set_raw_virtools_mesh(mesh: bpy.types.Mesh, rawdata: RawVirtoolsMesh) -> None: def set_raw_virtools_mesh(meshlike: CanToMesh, rawdata: RawVirtoolsMesh) -> None:
props: BBP_PG_virtools_mesh = get_virtools_mesh(mesh) props: BBP_PG_virtools_mesh = get_virtools_mesh(meshlike)
props.lit_mode = _g_Helper_VXMESH_LITMODE.to_selection(rawdata.mLitMode) props.lit_mode = _g_Helper_VXMESH_LITMODE.to_selection(rawdata.mLitMode)
@@ -59,12 +61,22 @@ class BBP_PT_virtools_mesh(bpy.types.Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return context.mesh is not None if context.mesh is not None: return True
if context.curve is not None: return True
if context.meta_ball is not None: return True
return False
def draw(self, context): def draw(self, context):
# get layout and target # get layout
layout = self.layout layout = self.layout
props: BBP_PG_virtools_mesh = get_virtools_mesh(context.mesh) # get target
datablock: typing.Any
if context.mesh is not None: datablock = context.mesh
elif context.curve is not None: datablock = context.curve
elif context.meta_ball is not None: datablock = context.meta_ball
else: datablock = None
# get mesh properties
props: BBP_PG_virtools_mesh = get_virtools_mesh(datablock)
# draw data # draw data
layout.prop(props, 'lit_mode') layout.prop(props, 'lit_mode')
@@ -75,11 +87,21 @@ def register() -> None:
bpy.utils.register_class(BBP_PG_virtools_mesh) bpy.utils.register_class(BBP_PG_virtools_mesh)
bpy.utils.register_class(BBP_PT_virtools_mesh) bpy.utils.register_class(BBP_PT_virtools_mesh)
# add into mesh metadata # Add metadata into mesh-like data block.
# according to TemporaryMesh, we need add it into:
# mesh, curve, surface, font, and metaball.
bpy.types.Mesh.virtools_mesh = bpy.props.PointerProperty(type = BBP_PG_virtools_mesh) bpy.types.Mesh.virtools_mesh = bpy.props.PointerProperty(type = BBP_PG_virtools_mesh)
bpy.types.Curve.virtools_mesh = bpy.props.PointerProperty(type = BBP_PG_virtools_mesh)
bpy.types.SurfaceCurve.virtools_mesh = bpy.props.PointerProperty(type = BBP_PG_virtools_mesh)
bpy.types.TextCurve.virtools_mesh = bpy.props.PointerProperty(type = BBP_PG_virtools_mesh)
bpy.types.MetaBall.virtools_mesh = bpy.props.PointerProperty(type = BBP_PG_virtools_mesh)
def unregister() -> None: def unregister() -> None:
# remove from metadata # remove from metadata
del bpy.types.MetaBall.virtools_mesh
del bpy.types.TextCurve.virtools_mesh
del bpy.types.SurfaceCurve.virtools_mesh
del bpy.types.Curve.virtools_mesh
del bpy.types.Mesh.virtools_mesh del bpy.types.Mesh.virtools_mesh
bpy.utils.unregister_class(BBP_PT_virtools_mesh) bpy.utils.unregister_class(BBP_PT_virtools_mesh)

View File

@@ -105,22 +105,37 @@ def _nest_custom_split_normal(nml_array: array.array) -> typing.Iterator[UTIL_vi
class TemporaryMesh(): class TemporaryMesh():
""" """
Create a temporary mesh for convenient exporting. Create a temporary mesh for convenient exporting.
When exporting mesh, we need triangulate it first. When exporting mesh, we need evaluate it first, then triangulate it.
We create a temporary mesh to hold the triangulated mesh result. We create a temporary mesh to hold the evaluated and triangulated mesh result.
So that original object will not be affected and keep its original geometry. So that original object will not be affected and keep its original geometry.
Please note passed bpy.types.Object must be Mesh Object. Please note passed bpy.types.Object must be an object which can be converted into mesh.
You can use this class provided static method to check it.
""" """
__cAllowedObjectType: typing.ClassVar[set[str]] = {
'MESH', 'CURVE', 'SURFACE', 'FONT', 'META'
}
@staticmethod
def has_geometry(obj: bpy.types.Object):
"""
Check whether given Blender object has geometry.
If it has, it can safely utilize this class for visiting mesh.
"""
return obj.type in TemporaryMesh.__cAllowedObjectType
__mBindingObject: bpy.types.Object __mBindingObject: bpy.types.Object
__mEvaluatedObject: bpy.types.Object
__mTempMesh: bpy.types.Mesh __mTempMesh: bpy.types.Mesh
def __init__(self, binding_obj: bpy.types.Object): def __init__(self, binding_obj: bpy.types.Object):
depsgraph = bpy.context.evaluated_depsgraph_get()
self.__mBindingObject = binding_obj self.__mBindingObject = binding_obj
self.__mTempMesh = None self.__mEvaluatedObject = self.__mBindingObject.evaluated_get(depsgraph)
self.__mTempMesh = self.__mEvaluatedObject.to_mesh()
if self.__mBindingObject.data is None: if self.__mTempMesh is None:
raise UTIL_functions.BBPException('try getting mesh from an object without mesh.') raise UTIL_functions.BBPException('try getting mesh from an object without mesh.')
self.__mTempMesh = self.__mBindingObject.to_mesh()
def __enter__(self): def __enter__(self):
return self return self
@@ -129,6 +144,7 @@ class TemporaryMesh():
self.dispose() self.dispose()
def is_valid(self) -> bool: def is_valid(self) -> bool:
if self.__mBindingObject is None: return False
if self.__mBindingObject is None: return False if self.__mBindingObject is None: return False
if self.__mTempMesh is None: return False if self.__mTempMesh is None: return False
return True return True
@@ -136,7 +152,8 @@ class TemporaryMesh():
def dispose(self) -> None: def dispose(self) -> None:
if self.is_valid(): if self.is_valid():
self.__mTempMesh = None self.__mTempMesh = None
self.__mBindingObject.to_mesh_clear() self.__mEvaluatedObject.to_mesh_clear()
self.__mEvaluatedObject = None
self.__mBindingObject = None self.__mBindingObject = None
def get_temp_mesh(self) -> bpy.types.Mesh: def get_temp_mesh(self) -> bpy.types.Mesh:

View File

@@ -1,9 +1,10 @@
import bpy, mathutils import bpy, mathutils
import typing, math import typing, math
from dataclasses import dataclass
from . import UTIL_functions from . import UTIL_functions
# extract all declarations in PyBMap # extract all declarations in pybmap
from .PyBMap.virtools_types import * from .pybmap.virtools_types import *
# and add some patches for them # and add some patches for them
# mainly patch them with functions exchanging data with blender # mainly patch them with functions exchanging data with blender
# and the convertion between differnet coordinate system. # and the convertion between differnet coordinate system.
@@ -112,126 +113,130 @@ def bldmatrix_restore_light_obj(data: mathutils.Matrix) -> mathutils.Matrix:
#region Blender EnumProperty Creation #region Blender EnumProperty Creation
class EnumAnnotation(): @dataclass(frozen=True)
mDisplayName: str class EnumDocstring():
mDescription: str display_name: str
def __init__(self, display_name: str, description: str): """The name of this enum entry."""
self.mDisplayName = display_name description: str
self.mDescription = description """The description of this enum entry."""
_g_Annotation: dict[type, dict[int, EnumAnnotation]] = { _g_Docstring: dict[type, dict[int, EnumDocstring]] = {
VXTEXTURE_BLENDMODE: { VXTEXTURE_BLENDMODE: {
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DECAL.value: EnumAnnotation("Decal", "Texture replace any material information "), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DECAL.value: EnumDocstring("Decal", "Texture replace any material information "),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MODULATE.value: EnumAnnotation("Modulate", "Texture and material are combine. Alpha information of the texture replace material alpha component. "), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MODULATE.value: EnumDocstring("Modulate", "Texture and material are combine. Alpha information of the texture replace material alpha component. "),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DECALALPHA.value: EnumAnnotation("Decal Alpha", "Alpha information in the texture specify how material and texture are combined. Alpha information of the texture replace material alpha component. "), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DECALALPHA.value: EnumDocstring("Decal Alpha", "Alpha information in the texture specify how material and texture are combined. Alpha information of the texture replace material alpha component. "),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MODULATEALPHA.value: EnumAnnotation("Modulate Alpha", "Alpha information in the texture specify how material and texture are combined "), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MODULATEALPHA.value: EnumDocstring("Modulate Alpha", "Alpha information in the texture specify how material and texture are combined "),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DECALMASK.value: EnumAnnotation("Decal Mask", ""), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DECALMASK.value: EnumDocstring("Decal Mask", ""),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MODULATEMASK.value: EnumAnnotation("Modulate Mask", ""), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MODULATEMASK.value: EnumDocstring("Modulate Mask", ""),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_COPY.value: EnumAnnotation("Copy", "Equivalent to DECAL "), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_COPY.value: EnumDocstring("Copy", "Equivalent to DECAL "),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_ADD.value: EnumAnnotation("Add", ""), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_ADD.value: EnumDocstring("Add", ""),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DOTPRODUCT3.value: EnumAnnotation("Dot Product 3", "Perform a Dot Product 3 between texture (normal map) and a referential vector given in VXRENDERSTATE_TEXTUREFACTOR. "), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_DOTPRODUCT3.value: EnumDocstring("Dot Product 3", "Perform a Dot Product 3 between texture (normal map) and a referential vector given in VXRENDERSTATE_TEXTUREFACTOR. "),
VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MAX.value: EnumAnnotation("Max", ""), VXTEXTURE_BLENDMODE.VXTEXTUREBLEND_MAX.value: EnumDocstring("Max", ""),
}, },
VXTEXTURE_FILTERMODE: { VXTEXTURE_FILTERMODE: {
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_NEAREST.value: EnumAnnotation("Nearest", "No Filter "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_NEAREST.value: EnumDocstring("Nearest", "No Filter "),
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_LINEAR.value: EnumAnnotation("Linear", "Bilinear Interpolation "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_LINEAR.value: EnumDocstring("Linear", "Bilinear Interpolation "),
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_MIPNEAREST.value: EnumAnnotation("Mip Nearest", "Mip mapping "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_MIPNEAREST.value: EnumDocstring("Mip Nearest", "Mip mapping "),
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_MIPLINEAR.value: EnumAnnotation("Mip Linear", "Mip Mapping with Bilinear interpolation "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_MIPLINEAR.value: EnumDocstring("Mip Linear", "Mip Mapping with Bilinear interpolation "),
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_LINEARMIPNEAREST.value: EnumAnnotation("Linear Mip Nearest", "Mip Mapping with Bilinear interpolation between mipmap levels. "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_LINEARMIPNEAREST.value: EnumDocstring("Linear Mip Nearest", "Mip Mapping with Bilinear interpolation between mipmap levels. "),
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_LINEARMIPLINEAR.value: EnumAnnotation("Linear Mip Linear", "Trilinear Filtering "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_LINEARMIPLINEAR.value: EnumDocstring("Linear Mip Linear", "Trilinear Filtering "),
VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_ANISOTROPIC.value: EnumAnnotation("Anisotropic", "Anisotropic filtering "), VXTEXTURE_FILTERMODE.VXTEXTUREFILTER_ANISOTROPIC.value: EnumDocstring("Anisotropic", "Anisotropic filtering "),
}, },
VXBLEND_MODE: { VXBLEND_MODE: {
VXBLEND_MODE.VXBLEND_ZERO.value: EnumAnnotation("Zero", "Blend factor is (0, 0, 0, 0). "), VXBLEND_MODE.VXBLEND_ZERO.value: EnumDocstring("Zero", "Blend factor is (0, 0, 0, 0). "),
VXBLEND_MODE.VXBLEND_ONE.value: EnumAnnotation("One", "Blend factor is (1, 1, 1, 1). "), VXBLEND_MODE.VXBLEND_ONE.value: EnumDocstring("One", "Blend factor is (1, 1, 1, 1). "),
VXBLEND_MODE.VXBLEND_SRCCOLOR.value: EnumAnnotation("Src Color", "Blend factor is (Rs, Gs, Bs, As). "), VXBLEND_MODE.VXBLEND_SRCCOLOR.value: EnumDocstring("Src Color", "Blend factor is (Rs, Gs, Bs, As). "),
VXBLEND_MODE.VXBLEND_INVSRCCOLOR.value: EnumAnnotation("Inv Src Color", "Blend factor is (1-Rs, 1-Gs, 1-Bs, 1-As). "), VXBLEND_MODE.VXBLEND_INVSRCCOLOR.value: EnumDocstring("Inv Src Color", "Blend factor is (1-Rs, 1-Gs, 1-Bs, 1-As). "),
VXBLEND_MODE.VXBLEND_SRCALPHA.value: EnumAnnotation("Src Alpha", "Blend factor is (As, As, As, As). "), VXBLEND_MODE.VXBLEND_SRCALPHA.value: EnumDocstring("Src Alpha", "Blend factor is (As, As, As, As). "),
VXBLEND_MODE.VXBLEND_INVSRCALPHA.value: EnumAnnotation("Inv Src Alpha", "Blend factor is (1-As, 1-As, 1-As, 1-As). "), VXBLEND_MODE.VXBLEND_INVSRCALPHA.value: EnumDocstring("Inv Src Alpha", "Blend factor is (1-As, 1-As, 1-As, 1-As). "),
VXBLEND_MODE.VXBLEND_DESTALPHA.value: EnumAnnotation("Dest Alpha", "Blend factor is (Ad, Ad, Ad, Ad). "), VXBLEND_MODE.VXBLEND_DESTALPHA.value: EnumDocstring("Dest Alpha", "Blend factor is (Ad, Ad, Ad, Ad). "),
VXBLEND_MODE.VXBLEND_INVDESTALPHA.value: EnumAnnotation("Inv Dest Alpha", "Blend factor is (1-Ad, 1-Ad, 1-Ad, 1-Ad). "), VXBLEND_MODE.VXBLEND_INVDESTALPHA.value: EnumDocstring("Inv Dest Alpha", "Blend factor is (1-Ad, 1-Ad, 1-Ad, 1-Ad). "),
VXBLEND_MODE.VXBLEND_DESTCOLOR.value: EnumAnnotation("Dest Color", "Blend factor is (Rd, Gd, Bd, Ad). "), VXBLEND_MODE.VXBLEND_DESTCOLOR.value: EnumDocstring("Dest Color", "Blend factor is (Rd, Gd, Bd, Ad). "),
VXBLEND_MODE.VXBLEND_INVDESTCOLOR.value: EnumAnnotation("Inv Dest Color", "Blend factor is (1-Rd, 1-Gd, 1-Bd, 1-Ad). "), VXBLEND_MODE.VXBLEND_INVDESTCOLOR.value: EnumDocstring("Inv Dest Color", "Blend factor is (1-Rd, 1-Gd, 1-Bd, 1-Ad). "),
VXBLEND_MODE.VXBLEND_SRCALPHASAT.value: EnumAnnotation("Src Alpha Sat", "Blend factor is (f, f, f, 1); f = min(As, 1-Ad). "), VXBLEND_MODE.VXBLEND_SRCALPHASAT.value: EnumDocstring("Src Alpha Sat", "Blend factor is (f, f, f, 1); f = min(As, 1-Ad). "),
#VXBLEND_MODE.VXBLEND_BOTHSRCALPHA.value: EnumAnnotation("Both Src Alpha", "Source blend factor is (As, As, As, As) and destination blend factor is (1-As, 1-As, 1-As, 1-As) "), #VXBLEND_MODE.VXBLEND_BOTHSRCALPHA.value: EnumDocstring("Both Src Alpha", "Source blend factor is (As, As, As, As) and destination blend factor is (1-As, 1-As, 1-As, 1-As) "),
#VXBLEND_MODE.VXBLEND_BOTHINVSRCALPHA.value: EnumAnnotation("Both Inv Src Alpha", "Source blend factor is (1-As, 1-As, 1-As, 1-As) and destination blend factor is (As, As, As, As) "), #VXBLEND_MODE.VXBLEND_BOTHINVSRCALPHA.value: EnumDocstring("Both Inv Src Alpha", "Source blend factor is (1-As, 1-As, 1-As, 1-As) and destination blend factor is (As, As, As, As) "),
}, },
VXTEXTURE_ADDRESSMODE: { VXTEXTURE_ADDRESSMODE: {
VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSWRAP.value: EnumAnnotation("Wrap", "Default mesh wrap mode is used (see CKMesh::SetWrapMode) "), VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSWRAP.value: EnumDocstring("Wrap", "Default mesh wrap mode is used (see CKMesh::SetWrapMode) "),
VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSMIRROR.value: EnumAnnotation("Mirror", "Texture coordinates outside the range [0..1] are flipped evenly. "), VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSMIRROR.value: EnumDocstring("Mirror", "Texture coordinates outside the range [0..1] are flipped evenly. "),
VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSCLAMP.value: EnumAnnotation("Clamp", "Texture coordinates greater than 1.0 are set to 1.0, and values less than 0.0 are set to 0.0. "), VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSCLAMP.value: EnumDocstring("Clamp", "Texture coordinates greater than 1.0 are set to 1.0, and values less than 0.0 are set to 0.0. "),
VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSBORDER.value: EnumAnnotation("Border", "When texture coordinates are greater than 1.0 or less than 0.0 texture is set to a color defined in CKMaterial::SetTextureBorderColor. "), VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSBORDER.value: EnumDocstring("Border", "When texture coordinates are greater than 1.0 or less than 0.0 texture is set to a color defined in CKMaterial::SetTextureBorderColor. "),
VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSMIRRORONCE.value: EnumAnnotation("Mirror Once", " "), VXTEXTURE_ADDRESSMODE.VXTEXTURE_ADDRESSMIRRORONCE.value: EnumDocstring("Mirror Once", " "),
}, },
VXFILL_MODE: { VXFILL_MODE: {
VXFILL_MODE.VXFILL_POINT.value: EnumAnnotation("Point", "Vertices rendering "), VXFILL_MODE.VXFILL_POINT.value: EnumDocstring("Point", "Vertices rendering "),
VXFILL_MODE.VXFILL_WIREFRAME.value: EnumAnnotation("Wireframe", "Edges rendering "), VXFILL_MODE.VXFILL_WIREFRAME.value: EnumDocstring("Wireframe", "Edges rendering "),
VXFILL_MODE.VXFILL_SOLID.value: EnumAnnotation("Solid", "Face rendering "), VXFILL_MODE.VXFILL_SOLID.value: EnumDocstring("Solid", "Face rendering "),
}, },
VXSHADE_MODE: { VXSHADE_MODE: {
VXSHADE_MODE.VXSHADE_FLAT.value: EnumAnnotation("Flat", "Flat Shading "), VXSHADE_MODE.VXSHADE_FLAT.value: EnumDocstring("Flat", "Flat Shading "),
VXSHADE_MODE.VXSHADE_GOURAUD.value: EnumAnnotation("Gouraud", "Gouraud Shading "), VXSHADE_MODE.VXSHADE_GOURAUD.value: EnumDocstring("Gouraud", "Gouraud Shading "),
VXSHADE_MODE.VXSHADE_PHONG.value: EnumAnnotation("Phong", "Phong Shading (Not yet supported by most implementation) "), VXSHADE_MODE.VXSHADE_PHONG.value: EnumDocstring("Phong", "Phong Shading (Not yet supported by most implementation) "),
}, },
VXCMPFUNC: { VXCMPFUNC: {
VXCMPFUNC.VXCMP_NEVER.value: EnumAnnotation("Never", "Always fail the test. "), VXCMPFUNC.VXCMP_NEVER.value: EnumDocstring("Never", "Always fail the test. "),
VXCMPFUNC.VXCMP_LESS.value: EnumAnnotation("Less", "Accept if value if less than current value. "), VXCMPFUNC.VXCMP_LESS.value: EnumDocstring("Less", "Accept if value if less than current value. "),
VXCMPFUNC.VXCMP_EQUAL.value: EnumAnnotation("Equal", "Accept if value if equal than current value. "), VXCMPFUNC.VXCMP_EQUAL.value: EnumDocstring("Equal", "Accept if value if equal than current value. "),
VXCMPFUNC.VXCMP_LESSEQUAL.value: EnumAnnotation("Less Equal", "Accept if value if less or equal than current value. "), VXCMPFUNC.VXCMP_LESSEQUAL.value: EnumDocstring("Less Equal", "Accept if value if less or equal than current value. "),
VXCMPFUNC.VXCMP_GREATER.value: EnumAnnotation("Greater", "Accept if value if greater than current value. "), VXCMPFUNC.VXCMP_GREATER.value: EnumDocstring("Greater", "Accept if value if greater than current value. "),
VXCMPFUNC.VXCMP_NOTEQUAL.value: EnumAnnotation("Not Equal", "Accept if value if different than current value. "), VXCMPFUNC.VXCMP_NOTEQUAL.value: EnumDocstring("Not Equal", "Accept if value if different than current value. "),
VXCMPFUNC.VXCMP_GREATEREQUAL.value: EnumAnnotation("Greater Equal", "Accept if value if greater or equal current value. "), VXCMPFUNC.VXCMP_GREATEREQUAL.value: EnumDocstring("Greater Equal", "Accept if value if greater or equal current value. "),
VXCMPFUNC.VXCMP_ALWAYS.value: EnumAnnotation("Always", "Always accept the test. "), VXCMPFUNC.VXCMP_ALWAYS.value: EnumDocstring("Always", "Always accept the test. "),
}, },
CK_TEXTURE_SAVEOPTIONS: { CK_TEXTURE_SAVEOPTIONS: {
CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_RAWDATA.value: EnumAnnotation("Raw Data", "Save raw data inside file. The bitmap is saved in a raw 32 bit per pixel format. "), CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_RAWDATA.value: EnumDocstring("Raw Data", "Save raw data inside file. The bitmap is saved in a raw 32 bit per pixel format. "),
CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL.value: EnumAnnotation("External", "Store only the file name for the texture. The bitmap file must be present in the bitmap paths when loading the composition. "), CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL.value: EnumDocstring("External", "Store only the file name for the texture. The bitmap file must be present in the bitmap paths when loading the composition. "),
CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_IMAGEFORMAT.value: EnumAnnotation("Image Format", "Save using format specified. The bitmap data will be converted to the specified format by the correspondant bitmap plugin and saved inside file. "), CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_IMAGEFORMAT.value: EnumDocstring("Image Format", "Save using format specified. The bitmap data will be converted to the specified format by the correspondant bitmap plugin and saved inside file. "),
CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_USEGLOBAL.value: EnumAnnotation("Use Global", "Use Global settings, that is the settings given with CKContext::SetGlobalImagesSaveOptions. (Not valid when using CKContext::SetImagesSaveOptions). "), CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_USEGLOBAL.value: EnumDocstring("Use Global", "Use Global settings, that is the settings given with CKContext::SetGlobalImagesSaveOptions. (Not valid when using CKContext::SetImagesSaveOptions). "),
CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_INCLUDEORIGINALFILE.value: EnumAnnotation("Include Original File", "Insert original image file inside CMO file. The bitmap file that was used originally for the texture or sprite will be append to the composition file and extracted when the file is loaded. "), CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_INCLUDEORIGINALFILE.value: EnumDocstring("Include Original File", "Insert original image file inside CMO file. The bitmap file that was used originally for the texture or sprite will be append to the composition file and extracted when the file is loaded. "),
}, },
VX_PIXELFORMAT: { VX_PIXELFORMAT: {
VX_PIXELFORMAT._32_ARGB8888.value: EnumAnnotation("32 Bits ARGB8888", "32-bit ARGB pixel format with alpha "), VX_PIXELFORMAT._32_ARGB8888.value: EnumDocstring("32 Bits ARGB8888", "32-bit ARGB pixel format with alpha "),
VX_PIXELFORMAT._32_RGB888.value: EnumAnnotation("32 Bits RGB888", "32-bit RGB pixel format without alpha "), VX_PIXELFORMAT._32_RGB888.value: EnumDocstring("32 Bits RGB888", "32-bit RGB pixel format without alpha "),
VX_PIXELFORMAT._24_RGB888.value: EnumAnnotation("24 Bits RGB888", "24-bit RGB pixel format "), VX_PIXELFORMAT._24_RGB888.value: EnumDocstring("24 Bits RGB888", "24-bit RGB pixel format "),
VX_PIXELFORMAT._16_RGB565.value: EnumAnnotation("16 Bits RGB565", "16-bit RGB pixel format "), VX_PIXELFORMAT._16_RGB565.value: EnumDocstring("16 Bits RGB565", "16-bit RGB pixel format "),
VX_PIXELFORMAT._16_RGB555.value: EnumAnnotation("16 Bits RGB555", "16-bit RGB pixel format (5 bits per color) "), VX_PIXELFORMAT._16_RGB555.value: EnumDocstring("16 Bits RGB555", "16-bit RGB pixel format (5 bits per color) "),
VX_PIXELFORMAT._16_ARGB1555.value: EnumAnnotation("16 Bits ARGB1555", "16-bit ARGB pixel format (5 bits per color + 1 bit for alpha) "), VX_PIXELFORMAT._16_ARGB1555.value: EnumDocstring("16 Bits ARGB1555", "16-bit ARGB pixel format (5 bits per color + 1 bit for alpha) "),
VX_PIXELFORMAT._16_ARGB4444.value: EnumAnnotation("16 Bits ARGB4444", "16-bit ARGB pixel format (4 bits per color) "), VX_PIXELFORMAT._16_ARGB4444.value: EnumDocstring("16 Bits ARGB4444", "16-bit ARGB pixel format (4 bits per color) "),
VX_PIXELFORMAT._8_RGB332.value: EnumAnnotation("8 Bits RGB332", "8-bit RGB pixel format "), VX_PIXELFORMAT._8_RGB332.value: EnumDocstring("8 Bits RGB332", "8-bit RGB pixel format "),
VX_PIXELFORMAT._8_ARGB2222.value: EnumAnnotation("8 Bits ARGB2222", "8-bit ARGB pixel format "), VX_PIXELFORMAT._8_ARGB2222.value: EnumDocstring("8 Bits ARGB2222", "8-bit ARGB pixel format "),
VX_PIXELFORMAT._32_ABGR8888.value: EnumAnnotation("32 Bits ABGR8888", "32-bit ABGR pixel format "), VX_PIXELFORMAT._32_ABGR8888.value: EnumDocstring("32 Bits ABGR8888", "32-bit ABGR pixel format "),
VX_PIXELFORMAT._32_RGBA8888.value: EnumAnnotation("32 Bits RGBA8888", "32-bit RGBA pixel format "), VX_PIXELFORMAT._32_RGBA8888.value: EnumDocstring("32 Bits RGBA8888", "32-bit RGBA pixel format "),
VX_PIXELFORMAT._32_BGRA8888.value: EnumAnnotation("32 Bits BGRA8888", "32-bit BGRA pixel format "), VX_PIXELFORMAT._32_BGRA8888.value: EnumDocstring("32 Bits BGRA8888", "32-bit BGRA pixel format "),
VX_PIXELFORMAT._32_BGR888.value: EnumAnnotation("32 Bits BGR888", "32-bit BGR pixel format "), VX_PIXELFORMAT._32_BGR888.value: EnumDocstring("32 Bits BGR888", "32-bit BGR pixel format "),
VX_PIXELFORMAT._24_BGR888.value: EnumAnnotation("24 Bits BGR888", "24-bit BGR pixel format "), VX_PIXELFORMAT._24_BGR888.value: EnumDocstring("24 Bits BGR888", "24-bit BGR pixel format "),
VX_PIXELFORMAT._16_BGR565.value: EnumAnnotation("16 Bits BGR565", "16-bit BGR pixel format "), VX_PIXELFORMAT._16_BGR565.value: EnumDocstring("16 Bits BGR565", "16-bit BGR pixel format "),
VX_PIXELFORMAT._16_BGR555.value: EnumAnnotation("16 Bits BGR555", "16-bit BGR pixel format (5 bits per color) "), VX_PIXELFORMAT._16_BGR555.value: EnumDocstring("16 Bits BGR555", "16-bit BGR pixel format (5 bits per color) "),
VX_PIXELFORMAT._16_ABGR1555.value: EnumAnnotation("16 Bits ABGR1555", "16-bit ABGR pixel format (5 bits per color + 1 bit for alpha) "), VX_PIXELFORMAT._16_ABGR1555.value: EnumDocstring("16 Bits ABGR1555", "16-bit ABGR pixel format (5 bits per color + 1 bit for alpha) "),
VX_PIXELFORMAT._16_ABGR4444.value: EnumAnnotation("16 Bits ABGR4444", "16-bit ABGR pixel format (4 bits per color) "), VX_PIXELFORMAT._16_ABGR4444.value: EnumDocstring("16 Bits ABGR4444", "16-bit ABGR pixel format (4 bits per color) "),
VX_PIXELFORMAT._DXT1.value: EnumAnnotation("DXT1", "S3/DirectX Texture Compression 1 "), VX_PIXELFORMAT._DXT1.value: EnumDocstring("DXT1", "S3/DirectX Texture Compression 1 "),
VX_PIXELFORMAT._DXT2.value: EnumAnnotation("DXT2", "S3/DirectX Texture Compression 2 "), VX_PIXELFORMAT._DXT2.value: EnumDocstring("DXT2", "S3/DirectX Texture Compression 2 "),
VX_PIXELFORMAT._DXT3.value: EnumAnnotation("DXT3", "S3/DirectX Texture Compression 3 "), VX_PIXELFORMAT._DXT3.value: EnumDocstring("DXT3", "S3/DirectX Texture Compression 3 "),
VX_PIXELFORMAT._DXT4.value: EnumAnnotation("DXT4", "S3/DirectX Texture Compression 4 "), VX_PIXELFORMAT._DXT4.value: EnumDocstring("DXT4", "S3/DirectX Texture Compression 4 "),
VX_PIXELFORMAT._DXT5.value: EnumAnnotation("DXT5", "S3/DirectX Texture Compression 5 "), VX_PIXELFORMAT._DXT5.value: EnumDocstring("DXT5", "S3/DirectX Texture Compression 5 "),
VX_PIXELFORMAT._16_V8U8.value: EnumAnnotation("16 Bits V8U8", "16-bit Bump Map format format (8 bits per color) "), VX_PIXELFORMAT._16_V8U8.value: EnumDocstring("16 Bits V8U8", "16-bit Bump Map format format (8 bits per color) "),
VX_PIXELFORMAT._32_V16U16.value: EnumAnnotation("32 Bits V16U16", "32-bit Bump Map format format (16 bits per color) "), VX_PIXELFORMAT._32_V16U16.value: EnumDocstring("32 Bits V16U16", "32-bit Bump Map format format (16 bits per color) "),
VX_PIXELFORMAT._16_L6V5U5.value: EnumAnnotation("16 Bits L6V5U5", "16-bit Bump Map format format with luminance "), VX_PIXELFORMAT._16_L6V5U5.value: EnumDocstring("16 Bits L6V5U5", "16-bit Bump Map format format with luminance "),
VX_PIXELFORMAT._32_X8L8V8U8.value: EnumAnnotation("32 Bits X8L8V8U8", "32-bit Bump Map format format with luminance "), VX_PIXELFORMAT._32_X8L8V8U8.value: EnumDocstring("32 Bits X8L8V8U8", "32-bit Bump Map format format with luminance "),
VX_PIXELFORMAT._8_ABGR8888_CLUT.value: EnumAnnotation("8 Bits ABGR8888 CLUT", "8 bits indexed CLUT (ABGR) "), VX_PIXELFORMAT._8_ABGR8888_CLUT.value: EnumDocstring("8 Bits ABGR8888 CLUT", "8 bits indexed CLUT (ABGR) "),
VX_PIXELFORMAT._8_ARGB8888_CLUT.value: EnumAnnotation("8 Bits ARGB8888 CLUT", "8 bits indexed CLUT (ARGB) "), VX_PIXELFORMAT._8_ARGB8888_CLUT.value: EnumDocstring("8 Bits ARGB8888 CLUT", "8 bits indexed CLUT (ARGB) "),
VX_PIXELFORMAT._4_ABGR8888_CLUT.value: EnumAnnotation("4 Bits ABGR8888 CLUT", "4 bits indexed CLUT (ABGR) "), VX_PIXELFORMAT._4_ABGR8888_CLUT.value: EnumDocstring("4 Bits ABGR8888 CLUT", "4 bits indexed CLUT (ABGR) "),
VX_PIXELFORMAT._4_ARGB8888_CLUT.value: EnumAnnotation("4 Bits ARGB8888 CLUT", "4 bits indexed CLUT (ARGB) "), VX_PIXELFORMAT._4_ARGB8888_CLUT.value: EnumDocstring("4 Bits ARGB8888 CLUT", "4 bits indexed CLUT (ARGB) "),
}, },
VXLIGHT_TYPE: { VXLIGHT_TYPE: {
VXLIGHT_TYPE.VX_LIGHTPOINT.value: EnumAnnotation("Point", "The Light is a point of light "), VXLIGHT_TYPE.VX_LIGHTPOINT.value: EnumDocstring("Point", "The Light is a point of light "),
VXLIGHT_TYPE.VX_LIGHTSPOT.value: EnumAnnotation("Spot", "The light is a spotlight "), VXLIGHT_TYPE.VX_LIGHTSPOT.value: EnumDocstring("Spot", "The light is a spotlight "),
VXLIGHT_TYPE.VX_LIGHTDIREC.value: EnumAnnotation("Directional", "The light is directional light : Lights comes from an infinite point so only direction of light can be given "), VXLIGHT_TYPE.VX_LIGHTDIREC.value: EnumDocstring("Directional", "The light is directional light : Lights comes from an infinite point so only direction of light can be given "),
#VXLIGHT_TYPE.VX_LIGHTPARA.value: EnumAnnotation("Lightpara", "Obsolete, do not use "), #VXLIGHT_TYPE.VX_LIGHTPARA.value: EnumDocstring("Lightpara", "Obsolete, do not use "),
}, },
VXMESH_LITMODE: { VXMESH_LITMODE: {
VXMESH_LITMODE.VX_PRELITMESH.value: EnumAnnotation("Prelit", "Lighting use color information store with vertices "), VXMESH_LITMODE.VX_PRELITMESH.value: EnumDocstring("Prelit", "Lighting use color information store with vertices "),
VXMESH_LITMODE.VX_LITMESH.value: EnumAnnotation("Lit", "Lighting is done by renderer using normals and face material information. "), VXMESH_LITMODE.VX_LITMESH.value: EnumDocstring("Lit", "Lighting is done by renderer using normals and face material information. "),
},
CK_CAMERA_PROJECTION: {
CK_CAMERA_PROJECTION.CK_PERSPECTIVEPROJECTION.value: EnumDocstring("Perspective projection", ""),
CK_CAMERA_PROJECTION.CK_ORTHOGRAPHICPROJECTION.value: EnumDocstring("Orthographic projection", ""),
} }
} }
@@ -241,13 +246,13 @@ class EnumPropHelper(UTIL_functions.EnumPropHelper[_TRawEnum]):
""" """
Virtools type specified Blender EnumProp helper. Virtools type specified Blender EnumProp helper.
""" """
__mAnnotationDict: dict[int, EnumAnnotation] __mDocstringDict: dict[int, EnumDocstring]
__mEnumTy: type[_TRawEnum] __mEnumTy: type[_TRawEnum]
def __init__(self, ty: type[_TRawEnum]): def __init__(self, ty: type[_TRawEnum]):
# set enum type and annotation ref first # set enum type and docstring ref first
self.__mEnumTy = ty self.__mEnumTy = ty
self.__mAnnotationDict = _g_Annotation[ty] self.__mDocstringDict = _g_Docstring[ty]
# YYC MARK: # YYC MARK:
# It seems that Pylance has bad generic analyse ability in there. # It seems that Pylance has bad generic analyse ability in there.
@@ -259,8 +264,8 @@ class EnumPropHelper(UTIL_functions.EnumPropHelper[_TRawEnum]):
self.__mEnumTy, # enum.Enum its self is iterable self.__mEnumTy, # enum.Enum its self is iterable
lambda x: str(x.value), # convert enum.Enum's value to string lambda x: str(x.value), # convert enum.Enum's value to string
lambda x: self.__mEnumTy(int(x)), # use stored enum type and int() to get enum member lambda x: self.__mEnumTy(int(x)), # use stored enum type and int() to get enum member
lambda x: self.__mAnnotationDict[x.value].mDisplayName, lambda x: self.__mDocstringDict[x.value].display_name,
lambda x: self.__mAnnotationDict[x.value].mDescription, lambda x: self.__mDocstringDict[x.value].description,
lambda _: '' lambda _: ''
) )
@@ -273,11 +278,11 @@ def virtools_name_regulator(name: str | None) -> str:
else: return bpy.app.translations.pgettext_data('annoymous', 'BME/UTIL_virtools_types.virtools_name_regulator()') else: return bpy.app.translations.pgettext_data('annoymous', 'BME/UTIL_virtools_types.virtools_name_regulator()')
# YYC MARK: # YYC MARK:
# There are default encodings for PyBMap. We support Western European and Simplified Chinese in default. # There are default encodings for pybmap. We support Western European and Simplified Chinese in default.
# Since LibCmo 0.2, the encoding name of LibCmo become universal encoding which is platfoorm independent. # Since LibCmo 0.2, the encoding name of LibCmo become universal encoding which is platfoorm independent.
# So no need set it according to different platform. # So no need set it according to different platform.
# Use universal encoding name (like Python). # Use universal encoding name (like Python).
g_PyBMapDefaultEncodings: tuple[str, ...] = ( g_PybmapDefaultEncodings: tuple[str, ...] = (
'cp1252', 'cp1252',
'gbk' 'gbk'
) )

View File

@@ -17,7 +17,7 @@ UTIL_icons_manager.register()
# then load other modules # then load other modules
from . import UTIL_translation from . import UTIL_translation
from . import PROP_preferences, PROP_ptrprop_resolver, PROP_virtools_material, PROP_virtools_texture, PROP_virtools_mesh, PROP_virtools_light, PROP_virtools_group from . import PROP_preferences, PROP_ptrprop_resolver, PROP_virtools_material, PROP_virtools_texture, PROP_virtools_mesh, PROP_virtools_light, PROP_virtools_camera, PROP_virtools_group
from . import PROP_ballance_element, PROP_bme_material, PROP_ballance_map_info from . import PROP_ballance_element, PROP_bme_material, PROP_ballance_map_info
from . import OP_IMPORT_bmfile, OP_EXPORT_bmfile, OP_IMPORT_virtools, OP_EXPORT_virtools from . import OP_IMPORT_bmfile, OP_EXPORT_bmfile, OP_IMPORT_virtools, OP_EXPORT_virtools
from . import OP_UV_flatten_uv, OP_UV_rail_uv from . import OP_UV_flatten_uv, OP_UV_rail_uv
@@ -327,6 +327,7 @@ def register() -> None:
PROP_virtools_texture.register() PROP_virtools_texture.register()
PROP_virtools_mesh.register() PROP_virtools_mesh.register()
PROP_virtools_light.register() PROP_virtools_light.register()
PROP_virtools_camera.register()
PROP_virtools_group.register() PROP_virtools_group.register()
PROP_ballance_element.register() PROP_ballance_element.register()
PROP_bme_material.register() PROP_bme_material.register()
@@ -397,6 +398,7 @@ def unregister() -> None:
PROP_bme_material.unregister() PROP_bme_material.unregister()
PROP_ballance_element.unregister() PROP_ballance_element.unregister()
PROP_virtools_group.unregister() PROP_virtools_group.unregister()
PROP_virtools_camera.unregister()
PROP_virtools_light.unregister() PROP_virtools_light.unregister()
PROP_virtools_mesh.unregister() PROP_virtools_mesh.unregister()
PROP_virtools_texture.unregister() PROP_virtools_texture.unregister()

View File

@@ -6,7 +6,7 @@ schema_version = "1.0.0"
# Example of manifest file for a Blender extension # Example of manifest file for a Blender extension
# Change the values according to your extension # Change the values according to your extension
id = "bbp_ng" id = "bbp_ng"
version = "4.3.0" version = "4.3.1"
name = "Ballance Blender Plugin" name = "Ballance Blender Plugin"
tagline = "The specialized add-on served for creating game map of Ballance" tagline = "The specialized add-on served for creating game map of Ballance"
maintainer = "yyc12345 <yyc12321@outlook.com>" maintainer = "yyc12345 <yyc12321@outlook.com>"

View File

@@ -4,13 +4,13 @@ This page will guide you in compiling the plugin as well as distributing it.
## Compiling LibCmo with BMap ## Compiling LibCmo with BMap
BBP's Virtools file native import/export functionality relies on BMap and its Python binding PyBMap. In order to distribute the plugin, we need to first compile BMap and its predecessor LibCmo, and before doing so, you need to check the version of BMap you need. Because BBP doesn't always use the latest version of BMap, e.g. if you're compiling an older version of BBP, it's obviously not possible to rely on the latest version of BMap. BMap is constantly being upgraded, and the functionality it provides is constantly changing, and different versions of BMap are incompatible. BBP usually states the version of BMap it uses at the time of release, but if BBP doesn't point it out, you may need to look for the most recent version of BMap that compiles with the version of BBP at the time of its release. BBP's Virtools file native import/export functionality relies on BMap and its Python binding pybmap. In order to distribute the plugin, we need to first compile BMap and its predecessor LibCmo, and before doing so, you need to check the version of BMap you need. Because BBP doesn't always use the latest version of BMap, e.g. if you're compiling an older version of BBP, it's obviously not possible to rely on the latest version of BMap. BMap is constantly being upgraded, and the functionality it provides is constantly changing, and different versions of BMap are incompatible. BBP usually states the version of BMap it uses at the time of release, but if BBP doesn't point it out, you may need to look for the most recent version of BMap that compiles with the version of BBP at the time of its release.
After specifying the version, you need to visit [LibCmo GitHub repository](https://github.com/yyc12345/libcmo21). Then clone the project and use the Git command to go to the corresponding version (or just download the source code of the corresponding version). Then follow LibCmo's compilation manual to compile to get BMap. on Windows, you'll usually get the files `BMap.dll` and `BMap.pdb`. On Linux, it will be `BMap.so`. After specifying the version, you need to visit [LibCmo GitHub repository](https://github.com/yyc12345/libcmo21). Then clone the project and use the Git command to go to the corresponding version (or just download the source code of the corresponding version). Then follow LibCmo's compilation manual to compile to get BMap. on Windows, you'll usually get the files `BMap.dll` and `BMap.pdb`. On Linux, it will be `BMap.so`.
Then we need to configure PyBMap, which comes with LibCmo. Please follow the manual of PyBMap to combine the compiled binary BMap library with PyBMap. That is to complete the PyBMap configuration. Then we need to configure pybmap, which comes with LibCmo. Please follow the manual of pybmap to combine the compiled binary BMap library with pybmap. That is to complete the pybmap configuration.
Then we need to copy the configured PyBMap to our project under `bbp_ng/PyBMap` to complete this step. Then we need to copy the configured pybmap to our project under `bbp_ng/pybmap` to complete this step.
## Generate Resources ## Generate Resources

View File

@@ -4,13 +4,13 @@
## 编译LibCmo与BMap ## 编译LibCmo与BMap
BBP的Virtools文件原生导入导出功能依赖BMap以及其Python绑定PyBMap来实现。为了分发插件我们需要首先编译BMap及其前置LibCmo。而在编译前你需要先确认你需要的BMap版本。因为BBP并不总是使用最新的BMap例如你正在编译一个旧版的BBP其显然不可能依赖最新的BMap。BMap也在不断升级中其提供的功能也在不断变化不同版本的BMap是不兼容的。BBP通常会在发布时写明其所用的BMap版本如果BBP没有指出你可能需要寻找与BBP发布时最近的BMap版本来编译。 BBP的Virtools文件原生导入导出功能依赖BMap以及其Python绑定pybmap来实现。为了分发插件我们需要首先编译BMap及其前置LibCmo。而在编译前你需要先确认你需要的BMap版本。因为BBP并不总是使用最新的BMap例如你正在编译一个旧版的BBP其显然不可能依赖最新的BMap。BMap也在不断升级中其提供的功能也在不断变化不同版本的BMap是不兼容的。BBP通常会在发布时写明其所用的BMap版本如果BBP没有指出你可能需要寻找与BBP发布时最近的BMap版本来编译。
在明确版本后,你需要访问[LibCmo位于GitHub的存储库](https://github.com/yyc12345/libcmo21)。然后克隆项目使用Git命令转到对应版本或者直接下载对应版本的源码。然后按照LibCmo的编译手册编译得到BMap。在Windows上你通常会得到`BMap.dll``BMap.pdb`这两个文件。而在Linux上则会是`BMap.so` 在明确版本后,你需要访问[LibCmo位于GitHub的存储库](https://github.com/yyc12345/libcmo21)。然后克隆项目使用Git命令转到对应版本或者直接下载对应版本的源码。然后按照LibCmo的编译手册编译得到BMap。在Windows上你通常会得到`BMap.dll``BMap.pdb`这两个文件。而在Linux上则会是`BMap.so`
然后我们需要配置PyBMap。PyBMap是随LibCmo一起提供的。请按照PyBMap的手册将编译得到的二进制BMap库PyBMap结合在一起。即完成PyBMap配置。 然后我们需要配置pybmap。pybmap是随LibCmo一起提供的。请按照pybmap的手册将编译得到的二进制BMap库pybmap结合在一起。即完成pybmap配置。
然后我们需要将配置好的PyBMap拷贝到本项目的根目录下即可完成此步即存在`bbp_ng/PyBMap`文件夹,为配置好的PyBMap 然后我们需要将配置好的pybmap拷贝到本项目的根目录下即可完成此步即存在`bbp_ng/pybmap`文件夹,为配置好的pybmap
## 生成资源 ## 生成资源

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-03 09:48+0800\n" "POT-Creation-Date: 2025-09-04 09:55+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -1642,7 +1642,14 @@ msgstr ""
msgid "A very close view to player ball in game." msgid "A very close view to player ball in game."
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle
msgctxt "BBP_OT_game_camera/property"
msgid "Preset Rotation Angle"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'1' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'1'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg0
msgctxt "BBP_OT_game_camera/property"
msgid "0 Degree" msgid "0 Degree"
msgstr "" msgstr ""
@@ -1651,6 +1658,8 @@ msgid "0 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'2' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'2'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg45
msgctxt "BBP_OT_game_camera/property"
msgid "45 Degree" msgid "45 Degree"
msgstr "" msgstr ""
@@ -1659,6 +1668,8 @@ msgid "45 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'3' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'3'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg90
msgctxt "BBP_OT_game_camera/property"
msgid "90 Degree" msgid "90 Degree"
msgstr "" msgstr ""
@@ -1667,6 +1678,8 @@ msgid "90 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'4' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'4'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg135
msgctxt "BBP_OT_game_camera/property"
msgid "135 Degree" msgid "135 Degree"
msgstr "" msgstr ""
@@ -1675,6 +1688,8 @@ msgid "135 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'5' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'5'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg180
msgctxt "BBP_OT_game_camera/property"
msgid "180 Degree" msgid "180 Degree"
msgstr "" msgstr ""
@@ -1683,6 +1698,8 @@ msgid "180 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'6' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'6'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg225
msgctxt "BBP_OT_game_camera/property"
msgid "225 Degree" msgid "225 Degree"
msgstr "" msgstr ""
@@ -1691,6 +1708,8 @@ msgid "225 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'7' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'7'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg270
msgctxt "BBP_OT_game_camera/property"
msgid "270 Degree" msgid "270 Degree"
msgstr "" msgstr ""
@@ -1699,51 +1718,13 @@ msgid "270 degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'8' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'8'
msgid "315 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'8'
msgid "315 degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg0
msgctxt "BBP_OT_game_camera/property"
msgid "0 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg135
msgctxt "BBP_OT_game_camera/property"
msgid "135 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg180
msgctxt "BBP_OT_game_camera/property"
msgid "180 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg225
msgctxt "BBP_OT_game_camera/property"
msgid "225 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg270
msgctxt "BBP_OT_game_camera/property"
msgid "270 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg315 #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg315
msgctxt "BBP_OT_game_camera/property" msgctxt "BBP_OT_game_camera/property"
msgid "315 Degree" msgid "315 Degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg45 #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'8'
msgctxt "BBP_OT_game_camera/property" msgid "315 degree"
msgid "45 Degree"
msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg90
msgctxt "BBP_OT_game_camera/property"
msgid "90 Degree"
msgstr "" msgstr ""
#. :src: bpy.types.BBP_OT_game_camera.rotation_kind:'1' #. :src: bpy.types.BBP_OT_game_camera.rotation_kind:'1'
@@ -3735,17 +3716,17 @@ msgctxt "BBP_OT_fix_all_materials/draw"
msgid "Fix {0}/{1} materials." msgid "Fix {0}/{1} materials."
msgstr "" msgstr ""
#: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:302 #: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:305
msgctxt "BBP_OT_game_camera/draw" msgctxt "BBP_OT_game_camera/draw"
msgid "Target" msgid "Target"
msgstr "" msgstr ""
#: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:307 #: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:310
msgctxt "BBP_OT_game_camera/draw" msgctxt "BBP_OT_game_camera/draw"
msgid "Rotation" msgid "Rotation"
msgstr "" msgstr ""
#: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:330 #: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:333
msgctxt "BBP_OT_game_camera/draw" msgctxt "BBP_OT_game_camera/draw"
msgid "Perspective" msgid "Perspective"
msgstr "" msgstr ""

View File

@@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Ballance Blender Plugin 4.2.0 (0)\n" "Project-Id-Version: Ballance Blender Plugin 4.2.0 (0)\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-03 09:48+0800\n" "POT-Creation-Date: 2025-09-04 09:55+0800\n"
"PO-Revision-Date: \n" "PO-Revision-Date: \n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
@@ -1661,7 +1661,14 @@ msgstr "彩蛋"
msgid "A very close view to player ball in game." msgid "A very close view to player ball in game."
msgstr "游戏中一种非常贴近玩家球的视角。" msgstr "游戏中一种非常贴近玩家球的视角。"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle
msgctxt "BBP_OT_game_camera/property"
msgid "Preset Rotation Angle"
msgstr "预设旋转角度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'1' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'1'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg0
msgctxt "BBP_OT_game_camera/property"
msgid "0 Degree" msgid "0 Degree"
msgstr "0 度" msgstr "0 度"
@@ -1670,6 +1677,8 @@ msgid "0 degree"
msgstr "0 度" msgstr "0 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'2' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'2'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg45
msgctxt "BBP_OT_game_camera/property"
msgid "45 Degree" msgid "45 Degree"
msgstr "45 度" msgstr "45 度"
@@ -1678,6 +1687,8 @@ msgid "45 degree"
msgstr "45 度" msgstr "45 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'3' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'3'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg90
msgctxt "BBP_OT_game_camera/property"
msgid "90 Degree" msgid "90 Degree"
msgstr "90 度" msgstr "90 度"
@@ -1686,6 +1697,8 @@ msgid "90 degree"
msgstr "90 度" msgstr "90 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'4' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'4'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg135
msgctxt "BBP_OT_game_camera/property"
msgid "135 Degree" msgid "135 Degree"
msgstr "135 度" msgstr "135 度"
@@ -1694,6 +1707,8 @@ msgid "135 degree"
msgstr "135 度" msgstr "135 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'5' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'5'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg180
msgctxt "BBP_OT_game_camera/property"
msgid "180 Degree" msgid "180 Degree"
msgstr "180 度" msgstr "180 度"
@@ -1702,6 +1717,8 @@ msgid "180 degree"
msgstr "180 度" msgstr "180 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'6' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'6'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg225
msgctxt "BBP_OT_game_camera/property"
msgid "225 Degree" msgid "225 Degree"
msgstr "225 度" msgstr "225 度"
@@ -1710,6 +1727,8 @@ msgid "225 degree"
msgstr "225 度" msgstr "225 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'7' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'7'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg270
msgctxt "BBP_OT_game_camera/property"
msgid "270 Degree" msgid "270 Degree"
msgstr "270 度" msgstr "270 度"
@@ -1718,6 +1737,8 @@ msgid "270 degree"
msgstr "270 度" msgstr "270 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'8' #. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle:'8'
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg315
msgctxt "BBP_OT_game_camera/property"
msgid "315 Degree" msgid "315 Degree"
msgstr "315 度" msgstr "315 度"
@@ -1725,46 +1746,6 @@ msgstr "315 度"
msgid "315 degree" msgid "315 degree"
msgstr "315 度" msgstr "315 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg0
msgctxt "BBP_OT_game_camera/property"
msgid "0 Degree"
msgstr "0 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg135
msgctxt "BBP_OT_game_camera/property"
msgid "135 Degree"
msgstr "135 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg180
msgctxt "BBP_OT_game_camera/property"
msgid "180 Degree"
msgstr "180 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg225
msgctxt "BBP_OT_game_camera/property"
msgid "225 Degree"
msgstr "225 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg270
msgctxt "BBP_OT_game_camera/property"
msgid "270 Degree"
msgstr "270 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg315
msgctxt "BBP_OT_game_camera/property"
msgid "315 Degree"
msgstr "315 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg45
msgctxt "BBP_OT_game_camera/property"
msgid "45 Degree"
msgstr "45 度"
#. :src: bpy.types.BBP_OT_game_camera.preset_rotation_angle_deg90
msgctxt "BBP_OT_game_camera/property"
msgid "90 Degree"
msgstr "90 度"
#. :src: bpy.types.BBP_OT_game_camera.rotation_kind:'1' #. :src: bpy.types.BBP_OT_game_camera.rotation_kind:'1'
msgctxt "BBP_OT_game_camera/property" msgctxt "BBP_OT_game_camera/property"
msgid "Preset" msgid "Preset"
@@ -3769,17 +3750,17 @@ msgctxt "BBP_OT_fix_all_materials/draw"
msgid "Fix {0}/{1} materials." msgid "Fix {0}/{1} materials."
msgstr "修复 {0}/{1} 材质。" msgstr "修复 {0}/{1} 材质。"
#: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:302 #: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:305
msgctxt "BBP_OT_game_camera/draw" msgctxt "BBP_OT_game_camera/draw"
msgid "Target" msgid "Target"
msgstr "目标" msgstr "目标"
#: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:307 #: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:310
msgctxt "BBP_OT_game_camera/draw" msgctxt "BBP_OT_game_camera/draw"
msgid "Rotation" msgid "Rotation"
msgstr "旋转" msgstr "旋转"
#: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:330 #: extensions/user_default/bbp_ng/OP_OBJECT_game_view.py:333
msgctxt "BBP_OT_game_camera/draw" msgctxt "BBP_OT_game_camera/draw"
msgid "Perspective" msgid "Perspective"
msgstr "视角" msgstr "视角"
@@ -5214,9 +5195,29 @@ msgctxt "BBP/BME/Proto/floor_wide_x_crossing/[3]"
msgid "Whether has some faces." msgid "Whether has some faces."
msgstr "是否生成某些面。" msgstr "是否生成某些面。"
#~ msgctxt "BBP_OT_game_camera/property" #~ msgid "0 Degree"
#~ msgid "Preset Rotation Angle" #~ msgstr "0 度"
#~ msgstr "预设旋转角度"
#~ msgid "45 Degree"
#~ msgstr "45 度"
#~ msgid "90 Degree"
#~ msgstr "90 度"
#~ msgid "135 Degree"
#~ msgstr "135 度"
#~ msgid "180 Degree"
#~ msgstr "180 度"
#~ msgid "225 Degree"
#~ msgstr "225 度"
#~ msgid "270 Degree"
#~ msgstr "270 度"
#~ msgid "315 Degree"
#~ msgstr "315 度"
#~ msgctxt "BBP_PG_legacy_align_history/property" #~ msgctxt "BBP_PG_legacy_align_history/property"
#~ msgid "Target Objects (Selected Objects)" #~ msgid "Target Objects (Selected Objects)"