Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd3d08aa68 | |||
| d3d4d44227 | |||
| e50421d223 | |||
| fb7a1d93f8 | |||
| a8b367d243 | |||
| db24ea7def |
@@ -1,5 +1,5 @@
|
||||
import bpy
|
||||
from typing import List
|
||||
from typing import List, Dict
|
||||
from bpy.types import Operator, Context, Object
|
||||
from bpy.props import EnumProperty
|
||||
from ..utils.model_card_utils import update_model_card_objects
|
||||
@@ -89,7 +89,7 @@ class SPECKLE_OT_selection_filter_dialog(Operator):
|
||||
row.label(text="Selection Summary", icon="OUTLINER_OB_GROUP_INSTANCE")
|
||||
row.label(text=f"Total: {total_selected}", icon="OBJECT_DATA")
|
||||
|
||||
object_types: dict[str, int] = {}
|
||||
object_types: Dict[str, int] = {}
|
||||
for obj in selected_objects:
|
||||
if obj.type not in object_types:
|
||||
object_types[obj.type] = 1
|
||||
@@ -113,7 +113,7 @@ class SPECKLE_OT_selection_filter_dialog(Operator):
|
||||
)
|
||||
|
||||
def get_icon_for_type(self, obj_type: str) -> str:
|
||||
icon_map: dict[str, str] = {
|
||||
icon_map: Dict[str, str] = {
|
||||
"MESH": "OUTLINER_OB_MESH",
|
||||
"CURVE": "OUTLINER_OB_CURVE",
|
||||
"SURFACE": "OUTLINER_OB_SURFACE",
|
||||
|
||||
@@ -5,7 +5,7 @@ from specklepy.objects.primitive import Interval
|
||||
from specklepy.objects.base import Base
|
||||
from mathutils import Matrix
|
||||
from mathutils.geometry import interpolate_bezier
|
||||
from .utils import nurb_make_curve, make_knots
|
||||
from .utils import nurb_make_curve, make_knots, apply_cached_properties, extract_custom_properties
|
||||
|
||||
|
||||
def curve_to_speckle(
|
||||
@@ -21,15 +21,22 @@ def curve_to_speckle(
|
||||
base = Base()
|
||||
curves = []
|
||||
|
||||
# Extract custom properties once for all curves (shared curve data)
|
||||
curve_properties = extract_custom_properties(curve_data)
|
||||
|
||||
for spline in curve_data.splines:
|
||||
if spline.type == "BEZIER":
|
||||
curves.append(
|
||||
bezier_to_speckle(matrix, spline, blender_obj.name, scale_factor, units)
|
||||
curve = bezier_to_speckle(
|
||||
matrix, spline, blender_obj.name, scale_factor, units
|
||||
)
|
||||
apply_cached_properties(curve, curve_properties)
|
||||
curves.append(curve)
|
||||
elif spline.type == "NURBS":
|
||||
curves.append(
|
||||
nurbs_to_speckle(matrix, spline, blender_obj.name, scale_factor, units)
|
||||
curve = nurbs_to_speckle(
|
||||
matrix, spline, blender_obj.name, scale_factor, units
|
||||
)
|
||||
apply_cached_properties(curve, curve_properties)
|
||||
curves.append(curve)
|
||||
|
||||
if curves:
|
||||
base["@elements"] = curves
|
||||
|
||||
@@ -8,7 +8,7 @@ from mathutils import Vector as MVector
|
||||
|
||||
from specklepy.objects.base import Base
|
||||
from specklepy.objects.geometry.mesh import Mesh
|
||||
from .utils import get_submesh_id
|
||||
from .utils import get_submesh_id, apply_cached_properties, extract_custom_properties
|
||||
|
||||
|
||||
def mesh_to_speckle(
|
||||
@@ -42,6 +42,9 @@ def mesh_to_speckle_meshes(
|
||||
|
||||
submeshes = []
|
||||
|
||||
# Extract custom properties once for all submeshes (shared mesh data)
|
||||
mesh_properties = extract_custom_properties(data)
|
||||
|
||||
# sort material indices to ensure consistent ordering
|
||||
for material_index in sorted(submesh_data.keys()):
|
||||
mesh_area = 0
|
||||
@@ -107,6 +110,9 @@ def mesh_to_speckle_meshes(
|
||||
|
||||
speckle_mesh.applicationId = get_submesh_id(blender_object, material_index)
|
||||
|
||||
# Add custom properties from the mesh data
|
||||
apply_cached_properties(speckle_mesh, mesh_properties)
|
||||
|
||||
submeshes.append(speckle_mesh)
|
||||
|
||||
return submeshes
|
||||
|
||||
@@ -3,7 +3,7 @@ from typing import Optional
|
||||
from specklepy.objects.data_objects import BlenderObject
|
||||
from .curve_to_speckle import curve_to_speckle
|
||||
from .mesh_to_speckle import mesh_to_speckle_meshes
|
||||
from .utils import get_object_id, get_curve_element_id
|
||||
from .utils import get_object_id, get_curve_element_id, extract_custom_properties
|
||||
|
||||
|
||||
def convert_to_speckle(
|
||||
@@ -13,7 +13,7 @@ def convert_to_speckle(
|
||||
apply_modifiers: bool = True,
|
||||
) -> Optional[BlenderObject]:
|
||||
display_value = []
|
||||
properties = {}
|
||||
properties = extract_custom_properties(blender_object)
|
||||
|
||||
if blender_object.type == "CURVE":
|
||||
# handle curve modifiers apply_modifiers is True
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
from bpy.types import ID, Object
|
||||
import math
|
||||
from typing import Tuple, Optional
|
||||
from typing import Tuple, Optional, Dict, Any
|
||||
|
||||
OBJECT_NAME_SPECKLE_SEPARATOR = " -- "
|
||||
SPECKLE_ID_LENGTH = 32
|
||||
@@ -240,3 +240,62 @@ def get_curve_element_id(blender_object: Object, curve_index: int = 0) -> str:
|
||||
|
||||
def get_object_id(blender_object: Object) -> str:
|
||||
return get_unique_id(blender_object)
|
||||
|
||||
|
||||
def extract_custom_properties(blender_id: ID) -> Dict[str, Any]:
|
||||
"""
|
||||
Extract custom user-defined properties from a Blender ID datablock.
|
||||
"""
|
||||
properties = {}
|
||||
|
||||
# Get all custom property keys
|
||||
for key in blender_id.keys():
|
||||
# Skip system properties that start with underscore
|
||||
if key.startswith("_"):
|
||||
continue
|
||||
|
||||
try:
|
||||
value = blender_id[key]
|
||||
|
||||
# Handle basic data types that Speckle can handle
|
||||
if isinstance(value, (str, int, float, bool)):
|
||||
properties[key] = value
|
||||
elif isinstance(value, (list, tuple)):
|
||||
# Handle arrays of basic types
|
||||
if all(isinstance(item, (str, int, float, bool)) for item in value):
|
||||
properties[key] = list(value)
|
||||
elif type(value).__name__ == "IDPropertyArray":
|
||||
# Handle Blender IDPropertyArray types (BoolArray, IntArray, FloatArray)
|
||||
try:
|
||||
# Convert to list using to_list() method if available, otherwise use list()
|
||||
if hasattr(value, "to_list"):
|
||||
array_list = value.to_list()
|
||||
else:
|
||||
array_list = list(value)
|
||||
|
||||
# Verify all items are basic types
|
||||
if all(
|
||||
isinstance(item, (str, int, float, bool)) for item in array_list
|
||||
):
|
||||
properties[key] = array_list
|
||||
except (TypeError, ValueError):
|
||||
# Skip arrays that can't be converted
|
||||
continue
|
||||
except (KeyError, TypeError):
|
||||
# Skip properties that can't be accessed or have unsupported types
|
||||
continue
|
||||
|
||||
return properties
|
||||
|
||||
|
||||
def apply_custom_properties(speckle_obj, blender_data: ID) -> None:
|
||||
"""Apply custom properties to a Speckle object if they exist."""
|
||||
properties = extract_custom_properties(blender_data)
|
||||
if properties:
|
||||
speckle_obj.properties = properties
|
||||
|
||||
|
||||
def apply_cached_properties(speckle_obj, properties: Dict[str, Any]) -> None:
|
||||
"""Apply pre-extracted custom properties to a Speckle object if they exist."""
|
||||
if properties:
|
||||
speckle_obj.properties = properties
|
||||
|
||||
Reference in New Issue
Block a user