feat: support virtools camera import and export
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import bpy, mathutils
|
import bpy, mathutils
|
||||||
from bpy_extras.wm_utils.progress_report import ProgressReport
|
from bpy_extras.wm_utils.progress_report import ProgressReport
|
||||||
import tempfile, os, typing
|
import tempfile, os, typing
|
||||||
|
from dataclasses import dataclass
|
||||||
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, PROP_virtools_camera
|
||||||
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):
|
||||||
@@ -83,10 +84,17 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
|
|||||||
|
|
||||||
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
|
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
|
||||||
_TLightPair = tuple[bpy.types.Object, bpy.types.Light, bmap.BMTargetLight]
|
_TLightPair = tuple[bpy.types.Object, bpy.types.Light, bmap.BMTargetLight]
|
||||||
|
_TCameraPair = tuple[bpy.types.Object, bpy.types.Camera, bmap.BMTargetCamera]
|
||||||
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
|
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
|
||||||
_TMaterialPair = tuple[bpy.types.Material, bmap.BMMaterial]
|
_TMaterialPair = tuple[bpy.types.Material, bmap.BMMaterial]
|
||||||
_TTexturePair = tuple[bpy.types.Image, bmap.BMTexture]
|
_TTexturePair = tuple[bpy.types.Image, bmap.BMTexture]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class _PreparedCrets:
|
||||||
|
obj3d_crets: tuple[_TObj3dPair, ...]
|
||||||
|
light_crets: tuple[_TLightPair, ...]
|
||||||
|
camera_crets: tuple[_TCameraPair, ...]
|
||||||
|
|
||||||
def _export_virtools(
|
def _export_virtools(
|
||||||
file_name_: str,
|
file_name_: str,
|
||||||
encodings_: tuple[str, ...],
|
encodings_: tuple[str, ...],
|
||||||
@@ -112,17 +120,16 @@ def _export_virtools(
|
|||||||
|
|
||||||
# prepare progress reporter
|
# prepare progress reporter
|
||||||
with ProgressReport(wm = bpy.context.window_manager) as progress:
|
with ProgressReport(wm = bpy.context.window_manager) as progress:
|
||||||
# prepare 3dobject and light
|
# prepare 3dobject, light and camera
|
||||||
obj3d_crets: tuple[_TObj3dPair, ...]
|
prep_crets = _prepare_virtools_3dobjects(writer, progress, export_objects)
|
||||||
light_crets: tuple[_TLightPair, ...]
|
|
||||||
(obj3d_crets, light_crets) = _prepare_virtools_3dobjects(writer, progress, export_objects)
|
|
||||||
# export group according to prepared 3dobject
|
# export group according to prepared 3dobject
|
||||||
_export_virtools_groups(writer, progress, successive_sector_, successive_sector_count_, obj3d_crets)
|
_export_virtools_groups(writer, progress, successive_sector_, successive_sector_count_, prep_crets.obj3d_crets)
|
||||||
# export prepared light
|
# export prepared light and camera
|
||||||
_export_virtools_light(writer, progress, light_crets)
|
_export_virtools_light(writer, progress, prep_crets.light_crets)
|
||||||
|
_export_virtools_camera(writer, progress, prep_crets.camera_crets)
|
||||||
# export prepared 3dobject
|
# export prepared 3dobject
|
||||||
mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects(
|
mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects(
|
||||||
writer, progress, obj3d_crets)
|
writer, progress, prep_crets.obj3d_crets)
|
||||||
# export mesh
|
# export mesh
|
||||||
material_crets: tuple[_TMaterialPair, ...] = _export_virtools_meshes(
|
material_crets: tuple[_TMaterialPair, ...] = _export_virtools_meshes(
|
||||||
writer, progress, mesh_crets)
|
writer, progress, mesh_crets)
|
||||||
@@ -140,7 +147,7 @@ def _prepare_virtools_3dobjects(
|
|||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
export_objects: tuple[bpy.types.Object, ...]
|
export_objects: tuple[bpy.types.Object, ...]
|
||||||
) -> tuple[tuple[_TObj3dPair, ...], tuple[_TLightPair, ...]]:
|
) -> _PreparedCrets:
|
||||||
# this function only create equvalent entries in virtools engine and do not export anything
|
# this function only create equvalent entries in virtools engine and do not export anything
|
||||||
# because _export_virtools_3dobjects() and _export_virtools_groups() are need use the return value of this function
|
# because _export_virtools_3dobjects() and _export_virtools_groups() are need use the return value of this function
|
||||||
#
|
#
|
||||||
@@ -153,6 +160,9 @@ def _prepare_virtools_3dobjects(
|
|||||||
# create light hashset and result
|
# create light hashset and result
|
||||||
light_crets: list[_TLightPair] = []
|
light_crets: list[_TLightPair] = []
|
||||||
light_cret_set: set[bpy.types.Object] = set()
|
light_cret_set: set[bpy.types.Object] = set()
|
||||||
|
# create camera hashset and result
|
||||||
|
camera_crets: list[_TCameraPair] = []
|
||||||
|
camera_cret_set: set[bpy.types.Object] = set()
|
||||||
# start saving
|
# start saving
|
||||||
tr_text: str = bpy.app.translations.pgettext_rpt('Creating 3dObjects and Lights', 'BBP_OT_export_virtools/execute')
|
tr_text: str = bpy.app.translations.pgettext_rpt('Creating 3dObjects and Lights', 'BBP_OT_export_virtools/execute')
|
||||||
progress.enter_substeps(len(export_objects), tr_text)
|
progress.enter_substeps(len(export_objects), tr_text)
|
||||||
@@ -174,8 +184,13 @@ def _prepare_virtools_3dobjects(
|
|||||||
match(obj3d.type):
|
match(obj3d.type):
|
||||||
case 'CAMERA':
|
case 'CAMERA':
|
||||||
# camera object
|
# camera object
|
||||||
# TODO
|
if obj3d not in camera_cret_set:
|
||||||
pass
|
# add into set
|
||||||
|
camera_cret_set.add(obj3d)
|
||||||
|
# create virtools instance
|
||||||
|
vtcamera: bmap.BMTargetCamera = writer.create_target_camera()
|
||||||
|
# add into result list
|
||||||
|
camera_crets.append((obj3d, typing.cast(bpy.types.Camera, obj3d.data), vtcamera))
|
||||||
case 'LIGHT':
|
case 'LIGHT':
|
||||||
# light object
|
# light object
|
||||||
if obj3d not in light_cret_set:
|
if obj3d not in light_cret_set:
|
||||||
@@ -191,7 +206,7 @@ def _prepare_virtools_3dobjects(
|
|||||||
|
|
||||||
# leave progress and return
|
# leave progress and return
|
||||||
progress.leave_substeps()
|
progress.leave_substeps()
|
||||||
return (tuple(obj3d_crets), tuple(light_crets))
|
return _PreparedCrets(tuple(obj3d_crets), tuple(light_crets), tuple(camera_crets))
|
||||||
|
|
||||||
def _export_virtools_groups(
|
def _export_virtools_groups(
|
||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
@@ -288,6 +303,49 @@ def _export_virtools_light(
|
|||||||
# leave progress and return
|
# leave progress and return
|
||||||
progress.leave_substeps()
|
progress.leave_substeps()
|
||||||
|
|
||||||
|
def _export_virtools_camera(
|
||||||
|
writer: bmap.BMFileWriter,
|
||||||
|
progress: ProgressReport,
|
||||||
|
camera_crets: tuple[_TCameraPair, ...]
|
||||||
|
) -> None:
|
||||||
|
# start saving
|
||||||
|
tr_text: str = bpy.app.translations.pgettext_rpt('Saving Cameras', 'BBP_OT_export_virtools/execute')
|
||||||
|
progress.enter_substeps(len(camera_crets), tr_text)
|
||||||
|
|
||||||
|
for obj3d, camera, vtcamera in camera_crets:
|
||||||
|
# set name
|
||||||
|
vtcamera.set_name(obj3d.name)
|
||||||
|
|
||||||
|
# setup 3d entity parts
|
||||||
|
# set world matrix
|
||||||
|
vtmat: UTIL_virtools_types.VxMatrix = UTIL_virtools_types.VxMatrix()
|
||||||
|
bldmat: mathutils.Matrix = UTIL_virtools_types.bldmatrix_restore_camera_obj(obj3d.matrix_world)
|
||||||
|
UTIL_virtools_types.vxmatrix_from_blender(vtmat, bldmat)
|
||||||
|
UTIL_virtools_types.vxmatrix_conv_co(vtmat)
|
||||||
|
vtcamera.set_world_matrix(vtmat)
|
||||||
|
# set visibility
|
||||||
|
vtcamera.set_visibility(not obj3d.hide_get())
|
||||||
|
|
||||||
|
# setup camera data
|
||||||
|
rawcamera: PROP_virtools_camera.RawVirtoolsCamera = PROP_virtools_camera.get_raw_virtools_camera(camera)
|
||||||
|
|
||||||
|
vtcamera.set_projection_type(rawcamera.mProjectionType)
|
||||||
|
|
||||||
|
vtcamera.set_orthographic_zoom(rawcamera.mOrthographicZoom)
|
||||||
|
|
||||||
|
vtcamera.set_front_plane(rawcamera.mFrontPlane)
|
||||||
|
vtcamera.set_back_plane(rawcamera.mBackPlane)
|
||||||
|
vtcamera.set_fov(rawcamera.mFov)
|
||||||
|
|
||||||
|
(w, h) = rawcamera.mAspectRatio
|
||||||
|
vtcamera.set_aspect_ratio(w, h)
|
||||||
|
|
||||||
|
# step
|
||||||
|
progress.step()
|
||||||
|
|
||||||
|
# leave progress and return
|
||||||
|
progress.leave_substeps()
|
||||||
|
|
||||||
def _export_virtools_3dobjects(
|
def _export_virtools_3dobjects(
|
||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from bpy_extras.wm_utils.progress_report import ProgressReport
|
|||||||
import tempfile, os, typing
|
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_virtools_camera, 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):
|
||||||
@@ -80,8 +80,9 @@ def _import_virtools(file_name_: str, encodings_: tuple[str, ...], resolver: UTI
|
|||||||
# import 3dobjects
|
# import 3dobjects
|
||||||
obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] = _import_virtools_3dobjects(
|
obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] = _import_virtools_3dobjects(
|
||||||
reader, progress, resolver, mesh_cret_map)
|
reader, progress, resolver, mesh_cret_map)
|
||||||
# import light
|
# import light and camera
|
||||||
_import_virtools_lights(reader, progress, resolver)
|
_import_virtools_lights(reader, progress, resolver)
|
||||||
|
_import_virtools_cameras(reader, progress, resolver)
|
||||||
# import groups
|
# import groups
|
||||||
_import_virtools_groups(reader, progress, obj3d_cret_map)
|
_import_virtools_groups(reader, progress, obj3d_cret_map)
|
||||||
|
|
||||||
@@ -423,6 +424,53 @@ def _import_virtools_lights(
|
|||||||
# leave progress
|
# leave progress
|
||||||
progress.leave_substeps()
|
progress.leave_substeps()
|
||||||
|
|
||||||
|
def _import_virtools_cameras(
|
||||||
|
reader: bmap.BMFileReader,
|
||||||
|
progress: ProgressReport,
|
||||||
|
resolver: UTIL_ioport_shared.ConflictResolver
|
||||||
|
) -> None:
|
||||||
|
# prepare progress
|
||||||
|
tr_text: str = bpy.app.translations.pgettext_rpt('Loading Cameras', 'BBP_OT_import_virtools/execute')
|
||||||
|
progress.enter_substeps(reader.get_target_camera_count(), tr_text)
|
||||||
|
|
||||||
|
# same creation notes like light
|
||||||
|
for vtcamera in reader.get_target_cameras():
|
||||||
|
# create camera data block and 3d object together
|
||||||
|
(camera_3dobj, camera, init_camera) = resolver.create_camera(
|
||||||
|
UTIL_virtools_types.virtools_name_regulator(vtcamera.get_name())
|
||||||
|
)
|
||||||
|
|
||||||
|
if init_camera:
|
||||||
|
# setup camera data block
|
||||||
|
rawcamera: PROP_virtools_camera.RawVirtoolsCamera = PROP_virtools_camera.RawVirtoolsCamera()
|
||||||
|
|
||||||
|
rawcamera.mProjectionType = vtcamera.get_projection_type()
|
||||||
|
|
||||||
|
rawcamera.mOrthographicZoom = vtcamera.get_orthographic_zoom()
|
||||||
|
|
||||||
|
rawcamera.mFrontPlane = vtcamera.get_front_plane()
|
||||||
|
rawcamera.mBackPlane = vtcamera.get_back_plane()
|
||||||
|
rawcamera.mFov = vtcamera.get_fov()
|
||||||
|
|
||||||
|
rawcamera.mAspectRatio = vtcamera.get_aspect_ratio()
|
||||||
|
|
||||||
|
PROP_virtools_camera.set_raw_virtools_camera(camera, rawcamera)
|
||||||
|
PROP_virtools_camera.apply_to_blender_camera(camera)
|
||||||
|
|
||||||
|
# setup camera associated 3d object
|
||||||
|
# add into scene
|
||||||
|
UTIL_functions.add_into_scene(camera_3dobj)
|
||||||
|
# set world matrix
|
||||||
|
vtmat: UTIL_virtools_types.VxMatrix = vtcamera.get_world_matrix()
|
||||||
|
UTIL_virtools_types.vxmatrix_conv_co(vtmat)
|
||||||
|
bldmat: mathutils.Matrix = UTIL_virtools_types.vxmatrix_to_blender(vtmat)
|
||||||
|
camera_3dobj.matrix_world = UTIL_virtools_types.bldmatrix_patch_camera_obj(bldmat)
|
||||||
|
# set visibility
|
||||||
|
camera_3dobj.hide_set(not vtcamera.get_visibility())
|
||||||
|
|
||||||
|
# leave progress
|
||||||
|
progress.leave_substeps()
|
||||||
|
|
||||||
def _import_virtools_groups(
|
def _import_virtools_groups(
|
||||||
reader: bmap.BMFileReader,
|
reader: bmap.BMFileReader,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
|
|||||||
@@ -191,10 +191,39 @@ def apply_to_blender_camera(cam: bpy.types.Camera) -> None:
|
|||||||
cam.lens_unit = 'FOV'
|
cam.lens_unit = 'FOV'
|
||||||
cam.angle = rawdata.mFov
|
cam.angle = rawdata.mFov
|
||||||
|
|
||||||
|
def apply_to_blender_scene_resolution(cam: bpy.types.Camera) -> None:
|
||||||
|
# get raw data first
|
||||||
|
rawdata: RawVirtoolsCamera = get_raw_virtools_camera(cam)
|
||||||
|
|
||||||
|
# fetch width and height
|
||||||
|
(w, h) = rawdata.mAspectRatio
|
||||||
|
|
||||||
|
# compute a proper resolution from this aspect ratio
|
||||||
|
# calculate their lcm first
|
||||||
|
hw_lcm = math.lcm(w, h)
|
||||||
|
# get the first number which is greater than 1000 (1000 is a proper resolution size)
|
||||||
|
# and can be integrally divided by this lcm.
|
||||||
|
HW_MIN: int = 1000
|
||||||
|
min_edge = ((HW_MIN // hw_lcm) + 1) * hw_lcm
|
||||||
|
# calculate the final resolution
|
||||||
|
if w < h:
|
||||||
|
# width is shorter than height, set width as min edge
|
||||||
|
width = min_edge
|
||||||
|
height = width // w * h
|
||||||
|
else:
|
||||||
|
# opposite case
|
||||||
|
height = min_edge
|
||||||
|
width = height // h * w
|
||||||
|
|
||||||
|
# setup resolution
|
||||||
|
render_settings = bpy.context.scene.render
|
||||||
|
render_settings.resolution_x = width
|
||||||
|
render_settings.resolution_y = height
|
||||||
|
|
||||||
# Operators
|
# Operators
|
||||||
|
|
||||||
class BBP_OT_apply_virtools_camera(bpy.types.Operator):
|
class BBP_OT_apply_virtools_camera(bpy.types.Operator):
|
||||||
"""Apply Virtools Camera to Blender Camera."""
|
"""Apply Virtools Camera to Blender Camera except Resolution."""
|
||||||
bl_idname = "bbp.apply_virtools_camera"
|
bl_idname = "bbp.apply_virtools_camera"
|
||||||
bl_label = "Apply to Blender Camera"
|
bl_label = "Apply to Blender Camera"
|
||||||
bl_options = {'UNDO'}
|
bl_options = {'UNDO'}
|
||||||
@@ -209,6 +238,22 @@ class BBP_OT_apply_virtools_camera(bpy.types.Operator):
|
|||||||
apply_to_blender_camera(cam)
|
apply_to_blender_camera(cam)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class BBP_OT_apply_virtools_camera_resolution(bpy.types.Operator):
|
||||||
|
"""Apply Virtools Camera Resolution to Blender Scene."""
|
||||||
|
bl_idname = "bbp.apply_virtools_camera_resolution"
|
||||||
|
bl_label = "Apply to Blender Scene Resolution"
|
||||||
|
bl_options = {'UNDO'}
|
||||||
|
bl_translation_context = 'BBP_OT_apply_virtools_camera_resolution'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.camera is not None
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
cam: bpy.types.Camera = context.camera
|
||||||
|
apply_to_blender_scene_resolution(cam)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
# Display Panel
|
# Display Panel
|
||||||
|
|
||||||
class BBP_PT_virtools_camera(bpy.types.Panel):
|
class BBP_PT_virtools_camera(bpy.types.Panel):
|
||||||
@@ -232,9 +277,13 @@ class BBP_PT_virtools_camera(bpy.types.Panel):
|
|||||||
rawdata: RawVirtoolsCamera = get_raw_virtools_camera(cam)
|
rawdata: RawVirtoolsCamera = get_raw_virtools_camera(cam)
|
||||||
|
|
||||||
# draw operator
|
# draw operator
|
||||||
layout.operator(
|
row = layout.row()
|
||||||
|
row.operator(
|
||||||
BBP_OT_apply_virtools_camera.bl_idname, text='Apply', icon='NODETREE',
|
BBP_OT_apply_virtools_camera.bl_idname, text='Apply', icon='NODETREE',
|
||||||
text_ctxt='BBP_PT_virtools_camera/draw')
|
text_ctxt='BBP_PT_virtools_camera/draw')
|
||||||
|
row.operator(
|
||||||
|
BBP_OT_apply_virtools_camera_resolution.bl_idname, text='Apply Resolution', icon='SCENE',
|
||||||
|
text_ctxt='BBP_PT_virtools_camera/draw')
|
||||||
|
|
||||||
# draw data
|
# draw data
|
||||||
layout.separator()
|
layout.separator()
|
||||||
@@ -276,6 +325,7 @@ class BBP_PT_virtools_camera(bpy.types.Panel):
|
|||||||
def register() -> None:
|
def register() -> None:
|
||||||
bpy.utils.register_class(BBP_PG_virtools_camera)
|
bpy.utils.register_class(BBP_PG_virtools_camera)
|
||||||
bpy.utils.register_class(BBP_OT_apply_virtools_camera)
|
bpy.utils.register_class(BBP_OT_apply_virtools_camera)
|
||||||
|
bpy.utils.register_class(BBP_OT_apply_virtools_camera_resolution)
|
||||||
bpy.utils.register_class(BBP_PT_virtools_camera)
|
bpy.utils.register_class(BBP_PT_virtools_camera)
|
||||||
|
|
||||||
# add into camera metadata
|
# add into camera metadata
|
||||||
@@ -286,6 +336,7 @@ def unregister() -> None:
|
|||||||
del bpy.types.Camera.virtools_camera
|
del bpy.types.Camera.virtools_camera
|
||||||
|
|
||||||
bpy.utils.unregister_class(BBP_PT_virtools_camera)
|
bpy.utils.unregister_class(BBP_PT_virtools_camera)
|
||||||
|
bpy.utils.unregister_class(BBP_OT_apply_virtools_camera_resolution)
|
||||||
bpy.utils.unregister_class(BBP_OT_apply_virtools_camera)
|
bpy.utils.unregister_class(BBP_OT_apply_virtools_camera)
|
||||||
bpy.utils.unregister_class(BBP_PG_virtools_camera)
|
bpy.utils.unregister_class(BBP_PG_virtools_camera)
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class ConflictResolver():
|
|||||||
|
|
||||||
__mObjectStrategy: ConflictStrategy
|
__mObjectStrategy: ConflictStrategy
|
||||||
__mLightStrategy: ConflictStrategy
|
__mLightStrategy: ConflictStrategy
|
||||||
|
__mCameraStrategy: ConflictStrategy
|
||||||
__mMeshStrategy: ConflictStrategy
|
__mMeshStrategy: ConflictStrategy
|
||||||
__mMaterialStrategy: ConflictStrategy
|
__mMaterialStrategy: ConflictStrategy
|
||||||
__mTextureStrategy: ConflictStrategy
|
__mTextureStrategy: ConflictStrategy
|
||||||
@@ -44,11 +45,13 @@ class ConflictResolver():
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
obj_strategy: ConflictStrategy,
|
obj_strategy: ConflictStrategy,
|
||||||
light_strategy: ConflictStrategy,
|
light_strategy: ConflictStrategy,
|
||||||
|
camera_strategy: ConflictStrategy,
|
||||||
mesh_strategy: ConflictStrategy,
|
mesh_strategy: ConflictStrategy,
|
||||||
mtl_strategy: ConflictStrategy,
|
mtl_strategy: ConflictStrategy,
|
||||||
tex_strategy: ConflictStrategy):
|
tex_strategy: ConflictStrategy):
|
||||||
self.__mObjectStrategy = obj_strategy
|
self.__mObjectStrategy = obj_strategy
|
||||||
self.__mLightStrategy = light_strategy
|
self.__mLightStrategy = light_strategy
|
||||||
|
self.__mCameraStrategy = camera_strategy
|
||||||
self.__mMeshStrategy = mesh_strategy
|
self.__mMeshStrategy = mesh_strategy
|
||||||
self.__mMaterialStrategy = mtl_strategy
|
self.__mMaterialStrategy = mtl_strategy
|
||||||
self.__mTextureStrategy = tex_strategy
|
self.__mTextureStrategy = tex_strategy
|
||||||
@@ -88,6 +91,22 @@ class ConflictResolver():
|
|||||||
new_obj: bpy.types.Object = bpy.data.objects.new(name, new_light)
|
new_obj: bpy.types.Object = bpy.data.objects.new(name, new_light)
|
||||||
return (new_obj, new_light, True)
|
return (new_obj, new_light, True)
|
||||||
|
|
||||||
|
def create_camera(self, name: str) -> tuple[bpy.types.Object, bpy.types.Camera, bool]:
|
||||||
|
"""
|
||||||
|
Create camera data block and associated 3d object.
|
||||||
|
|
||||||
|
Same execution pattern with light creation.
|
||||||
|
"""
|
||||||
|
if self.__mCameraStrategy == ConflictStrategy.Current:
|
||||||
|
old_obj: bpy.types.Object | None = bpy.data.objects.get(name, None)
|
||||||
|
if old_obj is not None and old_obj.type == 'CAMERA':
|
||||||
|
return (old_obj, typing.cast(bpy.types.Camera, old_obj.data), False)
|
||||||
|
# create new object.
|
||||||
|
# if object or camera name is conflict, rename it directly without considering conflict strategy
|
||||||
|
new_camera: bpy.types.Camera = bpy.data.cameras.new(name)
|
||||||
|
new_obj: bpy.types.Object = bpy.data.objects.new(name, new_camera)
|
||||||
|
return (new_obj, new_camera, True)
|
||||||
|
|
||||||
def create_mesh(self, name: str) -> tuple[bpy.types.Mesh, bool]:
|
def create_mesh(self, name: str) -> tuple[bpy.types.Mesh, bool]:
|
||||||
if self.__mMeshStrategy == ConflictStrategy.Current:
|
if self.__mMeshStrategy == ConflictStrategy.Current:
|
||||||
old: bpy.types.Mesh | None = bpy.data.meshes.get(name, None)
|
old: bpy.types.Mesh | None = bpy.data.meshes.get(name, None)
|
||||||
@@ -153,6 +172,14 @@ class ImportParams():
|
|||||||
translation_context = 'BBP/UTIL_ioport_shared.ImportParams/property'
|
translation_context = 'BBP/UTIL_ioport_shared.ImportParams/property'
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
camera_conflict_strategy: bpy.props.EnumProperty(
|
||||||
|
name = "Camera Name Conflict",
|
||||||
|
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
||||||
|
description = "Define how to process camera name conflict",
|
||||||
|
default = _g_EnumHelper_ConflictStrategy.to_selection(ConflictStrategy.Rename),
|
||||||
|
translation_context = 'BBP/UTIL_ioport_shared.ImportParams/property'
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
object_conflict_strategy: bpy.props.EnumProperty(
|
object_conflict_strategy: bpy.props.EnumProperty(
|
||||||
name = "Object Name Conflict",
|
name = "Object Name Conflict",
|
||||||
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
items = _g_EnumHelper_ConflictStrategy.generate_items(),
|
||||||
@@ -173,11 +200,13 @@ class ImportParams():
|
|||||||
grid = body.grid_flow(row_major=False, columns=2)
|
grid = body.grid_flow(row_major=False, columns=2)
|
||||||
grid.label(text='Object', icon='CUBE', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
grid.label(text='Object', icon='CUBE', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
||||||
grid.label(text='Light', icon='LIGHT', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
grid.label(text='Light', icon='LIGHT', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
||||||
|
grid.label(text='Camera', icon='CAMERA_DATA', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
||||||
grid.label(text='Mesh', icon='MESH_DATA', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
grid.label(text='Mesh', icon='MESH_DATA', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
||||||
grid.label(text='Material', icon='MATERIAL', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
grid.label(text='Material', icon='MATERIAL', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
||||||
grid.label(text='Texture', icon='TEXTURE', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
grid.label(text='Texture', icon='TEXTURE', text_ctxt='BBP/UTIL_ioport_shared.ImportParams/draw')
|
||||||
grid.prop(self, 'object_conflict_strategy', text='')
|
grid.prop(self, 'object_conflict_strategy', text='')
|
||||||
grid.prop(self, 'light_conflict_strategy', text='')
|
grid.prop(self, 'light_conflict_strategy', text='')
|
||||||
|
grid.prop(self, 'camera_conflict_strategy', text='')
|
||||||
grid.prop(self, 'mesh_conflict_strategy', text='')
|
grid.prop(self, 'mesh_conflict_strategy', text='')
|
||||||
grid.prop(self, 'material_conflict_strategy', text='')
|
grid.prop(self, 'material_conflict_strategy', text='')
|
||||||
grid.prop(self, 'texture_conflict_strategy', text='')
|
grid.prop(self, 'texture_conflict_strategy', text='')
|
||||||
@@ -194,6 +223,9 @@ class ImportParams():
|
|||||||
def general_get_light_conflict_strategy(self) -> ConflictStrategy:
|
def general_get_light_conflict_strategy(self) -> ConflictStrategy:
|
||||||
return _g_EnumHelper_ConflictStrategy.get_selection(self.light_conflict_strategy)
|
return _g_EnumHelper_ConflictStrategy.get_selection(self.light_conflict_strategy)
|
||||||
|
|
||||||
|
def general_get_camera_conflict_strategy(self) -> ConflictStrategy:
|
||||||
|
return _g_EnumHelper_ConflictStrategy.get_selection(self.camera_conflict_strategy)
|
||||||
|
|
||||||
def general_get_object_conflict_strategy(self) -> ConflictStrategy:
|
def general_get_object_conflict_strategy(self) -> ConflictStrategy:
|
||||||
return _g_EnumHelper_ConflictStrategy.get_selection(self.object_conflict_strategy)
|
return _g_EnumHelper_ConflictStrategy.get_selection(self.object_conflict_strategy)
|
||||||
|
|
||||||
@@ -201,6 +233,7 @@ class ImportParams():
|
|||||||
return ConflictResolver(
|
return ConflictResolver(
|
||||||
self.general_get_object_conflict_strategy(),
|
self.general_get_object_conflict_strategy(),
|
||||||
self.general_get_light_conflict_strategy(),
|
self.general_get_light_conflict_strategy(),
|
||||||
|
self.general_get_camera_conflict_strategy(),
|
||||||
self.general_get_mesh_conflict_strategy(),
|
self.general_get_mesh_conflict_strategy(),
|
||||||
self.general_get_material_conflict_strategy(),
|
self.general_get_material_conflict_strategy(),
|
||||||
self.general_get_texture_conflict_strategy()
|
self.general_get_texture_conflict_strategy()
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ def vxmatrix_to_blender(self: VxMatrix) -> mathutils.Matrix:
|
|||||||
## Hints about Light Matrix
|
## Hints about Light Matrix
|
||||||
# There is a slight difference between Virtools and Blender.
|
# There is a slight difference between Virtools and Blender.
|
||||||
# In blender, the default direction of all directional light (spot and sun) are Down (-Z).
|
# In blender, the default direction of all directional light (spot and sun) are Down (-Z).
|
||||||
# Hoewver, in Virtools, the default direction of all directional light (spot and directional) are Forward (+Z).
|
# However, in Virtools, the default direction of all directional light (spot and directional) are Forward (+Z).
|
||||||
#
|
#
|
||||||
# As brief view, in Blender coordinate system, you can see that we got Blender default light direction
|
# As brief view, in Blender coordinate system, you can see that we got Blender default light direction
|
||||||
# from Virtools default light direction by rotating it around X-axis with -90 degree
|
# from Virtools default light direction by rotating it around X-axis with -90 degree
|
||||||
@@ -109,6 +109,31 @@ def bldmatrix_restore_light_obj(data: mathutils.Matrix) -> mathutils.Matrix:
|
|||||||
# so we simply right multiple it.
|
# so we simply right multiple it.
|
||||||
return data @ mathutils.Matrix.Rotation(math.radians(-90), 4, 'X')
|
return data @ mathutils.Matrix.Rotation(math.radians(-90), 4, 'X')
|
||||||
|
|
||||||
|
## Hints about Camera Matrix
|
||||||
|
# Just like light, camera is also different between Virtools and Blender.
|
||||||
|
# In Blender, the default camera orientation is looking at -Z and +Y up.
|
||||||
|
# Oppositely, Virtools camera is looking at +Z and +Y up.
|
||||||
|
#
|
||||||
|
# These direction is based on their own coordinate system respectively.
|
||||||
|
# Accidently this difference is same like light.
|
||||||
|
# So we can simply copy light strategy in there.
|
||||||
|
|
||||||
|
def bldmatrix_patch_camera_obj(data: mathutils.Matrix) -> mathutils.Matrix:
|
||||||
|
"""
|
||||||
|
Add patch for camera world matrix to correct its direction.
|
||||||
|
This function is usually used when importing camera.
|
||||||
|
"""
|
||||||
|
# same operation like light matrix patch
|
||||||
|
return data @ mathutils.Matrix.Rotation(math.radians(90), 4, 'X')
|
||||||
|
|
||||||
|
def bldmatrix_restore_camera_obj(data: mathutils.Matrix) -> mathutils.Matrix:
|
||||||
|
"""
|
||||||
|
The reverse operation of bldmatrix_patch_camera_mat().
|
||||||
|
This function is usually used when exporting camera.
|
||||||
|
"""
|
||||||
|
# same operation like light matrix patch
|
||||||
|
return data @ mathutils.Matrix.Rotation(math.radians(-90), 4, 'X')
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Blender EnumProperty Creation
|
#region Blender EnumProperty Creation
|
||||||
|
|||||||
Reference in New Issue
Block a user