first receive attempts
This commit is contained in:
@@ -0,0 +1,459 @@
|
||||
import bpy
|
||||
import bmesh
|
||||
from bpy.types import Object
|
||||
from mathutils import Vector
|
||||
from typing import Any, List, Optional, Tuple, Iterable
|
||||
from specklepy.objects.base import Base
|
||||
from specklepy.objects.geometry.line import Line
|
||||
from specklepy.objects.geometry.mesh import Mesh
|
||||
from specklepy.objects.geometry.polyline import Polyline
|
||||
|
||||
# Constants for naming and conversion
|
||||
OBJECT_NAME_MAX_LENGTH = 62
|
||||
OBJECT_NAME_SPECKLE_SEPARATOR = "::"
|
||||
OBJECT_NAME_NUMERAL_SEPARATOR = "."
|
||||
|
||||
# Property aliases for finding geometry in various Speckle object types
|
||||
DISPLAY_VALUE_PROPERTY_ALIASES = ["displayValue", "displayMesh", "displayStyle"]
|
||||
ELEMENTS_PROPERTY_ALIASES = ["elements", "Elements", "@elements"]
|
||||
|
||||
def _has_native_conversion(speckle_object: Base) -> bool:
|
||||
"""Check if object has a direct conversion method."""
|
||||
return isinstance(speckle_object, (Line, Mesh, Polyline))
|
||||
|
||||
def _has_fallback_conversion(speckle_object: Base) -> bool:
|
||||
"""Check if object has displayValue properties that can be converted."""
|
||||
return any(getattr(speckle_object, alias, None) for alias in DISPLAY_VALUE_PROPERTY_ALIASES)
|
||||
|
||||
def can_convert_to_native(speckle_object: Base) -> bool:
|
||||
"""Check if a Speckle object can be converted to Blender.
|
||||
|
||||
Args:
|
||||
speckle_object: The Speckle object to check
|
||||
|
||||
Returns:
|
||||
True if the object can be converted, False otherwise
|
||||
"""
|
||||
return _has_native_conversion(speckle_object) or _has_fallback_conversion(speckle_object)
|
||||
|
||||
def convert_to_native(speckle_object: Base) -> Object:
|
||||
"""Convert a Speckle object to a Blender object.
|
||||
|
||||
Args:
|
||||
speckle_object: The Speckle object to convert
|
||||
|
||||
Returns:
|
||||
A Blender object
|
||||
"""
|
||||
# Generate a name for the object
|
||||
object_name = _generate_object_name(speckle_object)
|
||||
|
||||
converted = None
|
||||
children = []
|
||||
|
||||
# First try native conversion if available
|
||||
if isinstance(speckle_object, Line):
|
||||
converted = line_to_native(speckle_object, object_name)
|
||||
elif isinstance(speckle_object, Mesh):
|
||||
converted = mesh_to_native(speckle_object, object_name, 1.0) # Using 1.0 as default scale
|
||||
elif isinstance(speckle_object, Polyline):
|
||||
converted = polyline_to_native(speckle_object, object_name)
|
||||
|
||||
# If no native conversion was possible, try displayValue conversion
|
||||
if not converted:
|
||||
(converted, children) = display_value_to_native(
|
||||
speckle_object, object_name, 1.0 # Using 1.0 as default scale
|
||||
)
|
||||
if not converted and not children:
|
||||
raise ValueError(f"Failed to convert object: {speckle_object.speckle_type}")
|
||||
|
||||
# Create a Blender object if the converter returned data instead of an object
|
||||
if not isinstance(converted, Object):
|
||||
blender_object = create_new_object(converted, object_name)
|
||||
else:
|
||||
blender_object = converted
|
||||
|
||||
# Store Speckle ID
|
||||
if hasattr(blender_object, "speckle"):
|
||||
blender_object.speckle.object_id = str(speckle_object.id)
|
||||
blender_object.speckle.enabled = True
|
||||
|
||||
# Parent children to the main object if any were created
|
||||
for child in children:
|
||||
child.parent = blender_object
|
||||
|
||||
return blender_object
|
||||
|
||||
def line_to_native(speckle_line: Line, name: str) -> bpy.types.Curve:
|
||||
"""Convert a Speckle line to a Blender curve.
|
||||
|
||||
Args:
|
||||
speckle_line: The Speckle line to convert
|
||||
name: The name for the new Blender curve
|
||||
|
||||
Returns:
|
||||
A Blender curve data block
|
||||
"""
|
||||
# Check if the line has valid start and end points
|
||||
if not speckle_line.start or not speckle_line.end:
|
||||
raise ValueError("Line is missing start or end point")
|
||||
|
||||
# Create a new curve data block
|
||||
blender_curve = bpy.data.curves.new(name, type="CURVE")
|
||||
blender_curve.dimensions = "3D"
|
||||
|
||||
# Create a new spline in the curve
|
||||
spline = blender_curve.splines.new("POLY")
|
||||
spline.points.add(1) # Add one point (default has 1, so total will be 2)
|
||||
|
||||
# Set the coordinates
|
||||
# Note: Blender curve points are 4D (x, y, z, w) where w is weight
|
||||
spline.points[0].co = (
|
||||
float(speckle_line.start.x),
|
||||
float(speckle_line.start.y),
|
||||
float(speckle_line.start.z),
|
||||
1.0,
|
||||
)
|
||||
|
||||
spline.points[1].co = (
|
||||
float(speckle_line.end.x),
|
||||
float(speckle_line.end.y),
|
||||
float(speckle_line.end.z),
|
||||
1.0,
|
||||
)
|
||||
|
||||
return blender_curve
|
||||
|
||||
def mesh_to_native(speckle_mesh: Mesh, name: str, scale: float) -> bpy.types.Mesh:
|
||||
"""Convert a Speckle mesh to a Blender mesh.
|
||||
|
||||
Args:
|
||||
speckle_mesh: The Speckle mesh to convert
|
||||
name: The name for the new Blender mesh
|
||||
scale: The scale factor to apply
|
||||
|
||||
Returns:
|
||||
A Blender mesh data block
|
||||
"""
|
||||
# Check if mesh already exists with this name
|
||||
if name in bpy.data.meshes.keys():
|
||||
return bpy.data.meshes[name]
|
||||
|
||||
# Create a new mesh data block
|
||||
blender_mesh = bpy.data.meshes.new(name=name)
|
||||
|
||||
# Create a BMesh for easier manipulation
|
||||
bm = bmesh.new()
|
||||
|
||||
# Add vertices
|
||||
add_vertices(speckle_mesh, bm, scale)
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
||||
# Add faces
|
||||
add_faces(speckle_mesh, bm, 0, 0)
|
||||
bm.faces.ensure_lookup_table()
|
||||
|
||||
# Finalize and cleanup
|
||||
bm.to_mesh(blender_mesh)
|
||||
bm.free()
|
||||
|
||||
return blender_mesh
|
||||
|
||||
def add_vertices(mesh: Mesh, bm: bmesh.types.BMesh, scale: float) -> None:
|
||||
"""Add vertices from a Speckle mesh to a Blender BMesh.
|
||||
|
||||
Args:
|
||||
mesh: The Speckle mesh containing vertices
|
||||
bm: The Blender BMesh to add vertices to
|
||||
scale: The scale factor to apply
|
||||
"""
|
||||
if not mesh.vertices:
|
||||
return
|
||||
|
||||
# Add vertices
|
||||
for i in range(0, len(mesh.vertices), 3):
|
||||
x = float(mesh.vertices[i]) * scale
|
||||
y = float(mesh.vertices[i + 1]) * scale
|
||||
z = float(mesh.vertices[i + 2]) * scale
|
||||
bm.verts.new(Vector((x, y, z)))
|
||||
|
||||
def add_faces(mesh: Mesh, bm: bmesh.types.BMesh, vertex_offset: int, material_index: int) -> None:
|
||||
"""Add faces from a Speckle mesh to a Blender BMesh.
|
||||
|
||||
Args:
|
||||
mesh: The Speckle mesh containing faces
|
||||
bm: The Blender BMesh to add faces to
|
||||
vertex_offset: Offset to apply to vertex indices
|
||||
material_index: Material index to assign to faces
|
||||
"""
|
||||
if not mesh.faces:
|
||||
return
|
||||
|
||||
# Ensure lookup table is up to date
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
||||
i = 0
|
||||
while i < len(mesh.faces):
|
||||
face_size = mesh.faces[i]
|
||||
i += 1
|
||||
|
||||
# Skip invalid faces
|
||||
if face_size < 3:
|
||||
continue
|
||||
|
||||
# Get vertices for this face
|
||||
verts = []
|
||||
for j in range(face_size):
|
||||
if i >= len(mesh.faces):
|
||||
break
|
||||
|
||||
vert_idx = mesh.faces[i] + vertex_offset
|
||||
i += 1
|
||||
|
||||
if vert_idx >= len(bm.verts):
|
||||
continue
|
||||
|
||||
verts.append(bm.verts[vert_idx])
|
||||
|
||||
# Create the face if we have enough valid vertices
|
||||
if len(verts) >= 3:
|
||||
try:
|
||||
face = bm.faces.new(verts)
|
||||
face.material_index = material_index
|
||||
except Exception as e:
|
||||
print(f"Failed to create face: {e}")
|
||||
|
||||
def polyline_to_native(speckle_polyline: Polyline, name: str) -> bpy.types.Curve:
|
||||
"""Convert a Speckle polyline to a Blender curve.
|
||||
|
||||
Args:
|
||||
speckle_polyline: The Speckle polyline to convert
|
||||
name: The name for the new Blender curve
|
||||
|
||||
Returns:
|
||||
A Blender curve data block
|
||||
"""
|
||||
# Get points from the polyline
|
||||
points = speckle_polyline.get_points()
|
||||
if not points:
|
||||
raise ValueError("Polyline has no points")
|
||||
|
||||
# Create a new curve data block
|
||||
blender_curve = bpy.data.curves.new(name, type="CURVE")
|
||||
blender_curve.dimensions = "3D"
|
||||
|
||||
# Create a new spline in the curve
|
||||
spline = blender_curve.splines.new("POLY")
|
||||
spline.points.add(len(points) - 1) # Add points (default has 1, so add n-1 more)
|
||||
|
||||
# Set the coordinates for each point
|
||||
# Note: Blender curve points are 4D (x, y, z, w) where w is weight
|
||||
for i, point in enumerate(points):
|
||||
spline.points[i].co = (
|
||||
float(point.x),
|
||||
float(point.y),
|
||||
float(point.z),
|
||||
1.0,
|
||||
)
|
||||
|
||||
# If the polyline is closed, set the spline to be cyclic
|
||||
if speckle_polyline.is_closed():
|
||||
spline.use_cyclic_u = True
|
||||
|
||||
return blender_curve
|
||||
|
||||
def display_value_to_native(
|
||||
speckle_object: Base, name: str, scale: float
|
||||
) -> Tuple[Optional[bpy.types.Mesh], List[Object]]:
|
||||
"""Convert displayValue properties to Blender objects.
|
||||
|
||||
Args:
|
||||
speckle_object: The Speckle object to convert
|
||||
name: The name for the new Blender objects
|
||||
scale: The scale factor to apply
|
||||
|
||||
Returns:
|
||||
Tuple of (converted mesh, list of child objects)
|
||||
"""
|
||||
return _members_to_native(
|
||||
speckle_object, name, scale, DISPLAY_VALUE_PROPERTY_ALIASES, True
|
||||
)
|
||||
|
||||
def _members_to_native(
|
||||
speckle_object: Base,
|
||||
name: str,
|
||||
scale: float,
|
||||
members: Iterable[str],
|
||||
combineMeshes: bool,
|
||||
) -> Tuple[Optional[bpy.types.Mesh], List[Object]]:
|
||||
"""Convert specific members of a Speckle object to Blender objects.
|
||||
|
||||
Args:
|
||||
speckle_object: The Speckle object to convert
|
||||
name: The name for the new Blender objects
|
||||
scale: The scale factor to apply
|
||||
members: The member properties to look for
|
||||
combineMeshes: Whether to combine meshes into one
|
||||
|
||||
Returns:
|
||||
Tuple of (combined mesh, list of child objects)
|
||||
"""
|
||||
meshes: List[Mesh] = []
|
||||
others: List[Base] = []
|
||||
|
||||
for alias in members:
|
||||
display = getattr(speckle_object, alias, None)
|
||||
|
||||
count = 0
|
||||
MAX_DEPTH = 255 # Prevent infinite recursion
|
||||
|
||||
def separate(value: Any) -> bool:
|
||||
nonlocal meshes, others, count, MAX_DEPTH
|
||||
|
||||
if combineMeshes and isinstance(value, Mesh):
|
||||
meshes.append(value)
|
||||
elif isinstance(value, Base):
|
||||
others.append(value)
|
||||
elif isinstance(value, list):
|
||||
count += 1
|
||||
if count > MAX_DEPTH:
|
||||
return True
|
||||
for x in value:
|
||||
separate(x)
|
||||
|
||||
return False
|
||||
|
||||
did_halt = separate(display)
|
||||
|
||||
if did_halt:
|
||||
print(f"Traversal halted after exceeding depth {MAX_DEPTH}")
|
||||
|
||||
# Convert meshes and other objects
|
||||
children: List[Object] = []
|
||||
mesh = None
|
||||
|
||||
if meshes:
|
||||
mesh = meshes_to_native(speckle_object, meshes, name, scale)
|
||||
|
||||
for item in others:
|
||||
try:
|
||||
blender_object = convert_to_native(item)
|
||||
children.append(blender_object)
|
||||
except Exception as ex:
|
||||
print(f"Failed to convert display value {item}: {ex}")
|
||||
|
||||
return (mesh, children)
|
||||
|
||||
def meshes_to_native(element: Base, meshes: List[Mesh], name: str, scale: float) -> bpy.types.Mesh:
|
||||
"""Convert multiple Speckle meshes to a single Blender mesh.
|
||||
|
||||
Args:
|
||||
element: The parent Speckle object
|
||||
meshes: The Speckle meshes to convert
|
||||
name: The name for the new Blender mesh
|
||||
scale: The scale factor to apply
|
||||
|
||||
Returns:
|
||||
A Blender mesh
|
||||
"""
|
||||
if name in bpy.data.meshes.keys():
|
||||
return bpy.data.meshes[name]
|
||||
|
||||
blender_mesh = bpy.data.meshes.new(name=name)
|
||||
|
||||
bm = bmesh.new()
|
||||
|
||||
# First pass: add vertices
|
||||
for mesh in meshes:
|
||||
add_vertices(mesh, bm, scale)
|
||||
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
||||
# Second pass: add faces
|
||||
offset = 0
|
||||
for i, mesh in enumerate(meshes):
|
||||
if not mesh.vertices:
|
||||
continue
|
||||
|
||||
add_faces(mesh, bm, offset, i)
|
||||
|
||||
offset += len(mesh.vertices) // 3
|
||||
|
||||
# Finalize and cleanup
|
||||
bm.to_mesh(blender_mesh)
|
||||
bm.free()
|
||||
|
||||
return blender_mesh
|
||||
|
||||
def create_new_object(obj_data, desired_name: str) -> bpy.types.Object:
|
||||
"""Create a new Blender object with a unique name.
|
||||
|
||||
Args:
|
||||
obj_data: The data to use for the object (e.g., mesh, curve)
|
||||
desired_name: The desired name for the object
|
||||
|
||||
Returns:
|
||||
A new Blender object
|
||||
"""
|
||||
# Make sure the name is unique
|
||||
name = _make_unique_name(desired_name, bpy.data.objects.keys())
|
||||
|
||||
# Create the object
|
||||
blender_object = bpy.data.objects.new(name, obj_data)
|
||||
|
||||
# Link it to the active collection if possible
|
||||
if bpy.context.collection:
|
||||
bpy.context.collection.objects.link(blender_object)
|
||||
else:
|
||||
# If no active collection, link to scene collection
|
||||
bpy.context.scene.collection.objects.link(blender_object)
|
||||
|
||||
return blender_object
|
||||
|
||||
def _make_unique_name(desired_name: str, existing_names) -> str:
|
||||
"""Create a unique name by appending a number if necessary.
|
||||
|
||||
Args:
|
||||
desired_name: The desired name
|
||||
existing_names: Collection of existing names to avoid duplicates
|
||||
|
||||
Returns:
|
||||
A unique name
|
||||
"""
|
||||
if desired_name not in existing_names:
|
||||
return desired_name
|
||||
|
||||
# If name exists, append numbers until we find a unique one
|
||||
counter = 1
|
||||
while True:
|
||||
new_name = f"{desired_name}.{counter:03d}"
|
||||
if new_name not in existing_names:
|
||||
return new_name
|
||||
counter += 1
|
||||
|
||||
def _generate_object_name(speckle_object: Base) -> str:
|
||||
"""Generate a name for a Blender object based on a Speckle object.
|
||||
|
||||
Args:
|
||||
speckle_object: The Speckle object
|
||||
|
||||
Returns:
|
||||
A name for the object
|
||||
"""
|
||||
# Try to get a meaningful name
|
||||
name = getattr(speckle_object, "name", None)
|
||||
|
||||
if not name:
|
||||
# Use the object type as a fallback
|
||||
speckle_type = speckle_object.speckle_type
|
||||
name = speckle_type.split(".")[-1] # Get the last part of the type name
|
||||
|
||||
# Truncate if necessary
|
||||
if len(name) > OBJECT_NAME_MAX_LENGTH - 10: # Leave room for speckle ID
|
||||
name = name[:OBJECT_NAME_MAX_LENGTH - 10]
|
||||
|
||||
# Add the Speckle ID for uniqueness
|
||||
if hasattr(speckle_object, "id") and speckle_object.id:
|
||||
return f"{name}{OBJECT_NAME_SPECKLE_SEPARATOR}{speckle_object.id[:8]}"
|
||||
else:
|
||||
return name
|
||||
@@ -1,5 +1,11 @@
|
||||
import bpy
|
||||
from typing import Set
|
||||
from specklepy.api.credentials import get_local_accounts
|
||||
from specklepy.transports.server import ServerTransport
|
||||
from specklepy.api import operations
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.objects.base import Base
|
||||
from ..converter.to_native import can_convert_to_native, convert_to_native
|
||||
|
||||
class SPECKLE_OT_load(bpy.types.Operator):
|
||||
bl_idname = "speckle.load"
|
||||
@@ -18,4 +24,112 @@ class SPECKLE_OT_load(bpy.types.Operator):
|
||||
self.report({'INFO'}, f"Load button clicked at {context.scene.speckle_state.mouse_position[0], context.scene.speckle_state.mouse_position[1]}")
|
||||
# Opens project_selection_dialog
|
||||
bpy.ops.speckle.project_selection_dialog("INVOKE_DEFAULT")
|
||||
return {'FINISHED'}
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@classmethod
|
||||
def load(cls, context: bpy.types.Context, model_card) -> None:
|
||||
|
||||
print("Load process started")
|
||||
print(f"Loading project: {model_card.project_name}, model: {model_card.model_name}")
|
||||
print(f"Project ID: {model_card.project_id}")
|
||||
print(f"Version ID: {model_card.version_id}")
|
||||
|
||||
try:
|
||||
# get the account from local accounts
|
||||
account = next((acc for acc in get_local_accounts() if acc.id == context.window_manager.selected_account_id), None)
|
||||
if not account:
|
||||
raise Exception("No Speckle account found")
|
||||
|
||||
# initialize the Speckle client
|
||||
client = SpeckleClient(host=account.serverInfo.url)
|
||||
# authenticate with account
|
||||
client.authenticate_with_account(account)
|
||||
|
||||
# now we need a transport
|
||||
transport = ServerTransport(
|
||||
stream_id=model_card.project_id,
|
||||
client=client
|
||||
)
|
||||
|
||||
# get the version
|
||||
version = client.version.get(model_card.version_id, model_card.project_id)
|
||||
obj_id = version.referenced_object
|
||||
|
||||
# receive the data
|
||||
version_data = operations.receive(
|
||||
obj_id,
|
||||
transport
|
||||
)
|
||||
|
||||
# TO DISCUSS
|
||||
# create a root collection in Blender to hold all imported objects
|
||||
root_collection_name = f"{model_card.model_name} - {model_card.version_id[:8]}"
|
||||
root_collection = bpy.data.collections.new(root_collection_name)
|
||||
context.scene.collection.children.link(root_collection)
|
||||
|
||||
# start conversion process
|
||||
context.window_manager.progress_begin(0, 100)
|
||||
|
||||
# process and convert the received data to Blender objects
|
||||
converted_objects = {}
|
||||
traversal_queue = [version_data]
|
||||
converted_count = 0
|
||||
total_count = getattr(version_data, "totalChildrenCount", 100) or 100
|
||||
|
||||
while traversal_queue:
|
||||
current_object = traversal_queue.pop(0)
|
||||
|
||||
# Skip if already processed
|
||||
if hasattr(current_object, "id") and current_object.id in converted_objects:
|
||||
continue
|
||||
|
||||
try:
|
||||
# check if this object can be converted
|
||||
if can_convert_to_native(current_object):
|
||||
# convert the object to Blender
|
||||
blender_obj = convert_to_native(current_object)
|
||||
|
||||
# store the converted object
|
||||
if hasattr(current_object, "id"):
|
||||
converted_objects[current_object.id] = blender_obj
|
||||
|
||||
# link to the root collection if not already in a collection
|
||||
if blender_obj.name not in root_collection.objects:
|
||||
try:
|
||||
root_collection.objects.link(blender_obj)
|
||||
except RuntimeError:
|
||||
# Object might already be linked to another collection
|
||||
pass
|
||||
|
||||
print(f"Successfully converted: {current_object.speckle_type}")
|
||||
|
||||
# check for children/elements to process
|
||||
children = []
|
||||
# look for common element properties
|
||||
for prop_name in ["elements", "Elements", "@elements"]:
|
||||
if hasattr(current_object, prop_name):
|
||||
elements = getattr(current_object, prop_name)
|
||||
if isinstance(elements, list):
|
||||
children.extend(elements)
|
||||
elif isinstance(elements, Base):
|
||||
children.append(elements)
|
||||
|
||||
# add all children to the traversal queue
|
||||
traversal_queue.extend(children)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error converting object: {str(e)}")
|
||||
|
||||
# update progress
|
||||
converted_count += 1
|
||||
progress = int((converted_count / total_count) * 100)
|
||||
context.window_manager.progress_update(min(progress, 100))
|
||||
|
||||
context.window_manager.progress_end()
|
||||
print(f"Conversion completed. Converted {converted_count} objects.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error loading from Speckle: {str(e)}")
|
||||
context.window_manager.progress_end()
|
||||
return
|
||||
@@ -15,6 +15,7 @@ class speckle_model_card(bpy.types.PropertyGroup):
|
||||
version_id (StringProperty): Unique identifier of the selected version.
|
||||
"""
|
||||
project_name: bpy.props.StringProperty(name="Project Name", description="Name of the project", default="") # type: ignore
|
||||
project_id: bpy.props.StringProperty(name="Project ID", description="ID of the selected project", default="") # type: ignore
|
||||
model_name: bpy.props.StringProperty(name="Model Name", description="Name of the model", default="") # type: ignore
|
||||
is_publish: bpy.props.BoolProperty(name="Publish/Load", description="If the model is published or loaded", default=False) # type: ignore
|
||||
selection_summary: bpy.props.StringProperty(name="Selection Summary", description="Summary of the selection", default="") # type: ignore
|
||||
@@ -28,6 +29,7 @@ class speckle_model_card(bpy.types.PropertyGroup):
|
||||
"""
|
||||
return {
|
||||
"project_name": self.project_name,
|
||||
"project_id": self.project_id,
|
||||
"model_name": self.model_name,
|
||||
"is_publish": self.is_publish,
|
||||
"selection_summary": self.selection_summary,
|
||||
@@ -46,6 +48,7 @@ class speckle_model_card(bpy.types.PropertyGroup):
|
||||
"""
|
||||
item = cls()
|
||||
item.project_name = data["project_name"]
|
||||
item.project_id = data["project_id"]
|
||||
item.model_name = data["model_name"]
|
||||
item.is_publish = data["is_publish"]
|
||||
item.selection_summary = data["selection_summary"]
|
||||
|
||||
@@ -7,6 +7,7 @@ import bpy
|
||||
from bpy.types import WindowManager, UILayout, Context, PropertyGroup, Event
|
||||
from .mouse_position_mixin import MousePositionMixin
|
||||
from ..utils.version_manager import get_versions_for_model
|
||||
from ..operators.load import SPECKLE_OT_load
|
||||
|
||||
class speckle_version(bpy.types.PropertyGroup):
|
||||
"""PropertyGroup for storing version information.
|
||||
@@ -132,11 +133,16 @@ class SPECKLE_OT_version_selection_dialog(MousePositionMixin, bpy.types.Operator
|
||||
def execute(self, context: Context) -> set[str]:
|
||||
model_card = context.scene.speckle_state.model_cards.add()
|
||||
model_card.project_name = self.project_name
|
||||
model_card.project_id = self.project_id
|
||||
model_card.model_name = self.model_name
|
||||
model_card.is_publish = False
|
||||
# Store the selected version ID
|
||||
selected_version = context.window_manager.speckle_versions[self.version_index]
|
||||
model_card.version_id = selected_version.id
|
||||
|
||||
# Call the load process class method
|
||||
SPECKLE_OT_load.load(context, model_card)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context: Context, event: Event) -> set[str]:
|
||||
|
||||
@@ -60,7 +60,7 @@ def get_models_for_project(account_id: str, project_id: str, search: Optional[st
|
||||
# Get models
|
||||
models: List[Model] = client.model.get_models(project_id=project_id, models_limit=10, models_filter=filter).items
|
||||
|
||||
return [(model.name, model.id, format_relative_time(model.createdAt)) for model in models]
|
||||
return [(model.name, model.id, format_relative_time(model.created_at)) for model in models]
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error fetching models: {str(e)}")
|
||||
|
||||
@@ -45,7 +45,7 @@ def get_projects_for_account(account_id: str, search: Optional[str] = None) -> L
|
||||
# Fetch projects
|
||||
projects = client.active_user.get_projects(limit=10, filter=filter).items
|
||||
|
||||
return [(project.name, format_role(project.role), format_relative_time(project.updatedAt), project.id) for project in projects]
|
||||
return [(project.name, format_role(project.role), format_relative_time(project.updated_at), project.id) for project in projects]
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
@@ -53,7 +53,7 @@ def get_versions_for_model(account_id: str, project_id: str, model_id: str, sear
|
||||
# Get versions
|
||||
versions: List[Version] = client.version.get_versions(project_id=project_id, model_id=model_id, limit=10, filter=filter).items
|
||||
|
||||
return [(version.id, version.message or "No message", format_relative_time(version.createdAt)) for version in versions]
|
||||
return [(version.id, version.message or "No message", format_relative_time(version.created_at)) for version in versions]
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error fetching versions: {str(e)}")
|
||||
|
||||
+2
-3
@@ -2,11 +2,10 @@
|
||||
name = "speckle-blender"
|
||||
version = "3.0.0"
|
||||
description = "Next-Gen Speckle connector for Blender!"
|
||||
requires-python = ">=3.8, <4.0.0"
|
||||
requires-python = ">=3.11.9, <4.0.0"
|
||||
license = "Apache-2.0"
|
||||
dependencies = [
|
||||
"specklepy>=2.21.1,<3",
|
||||
"attrs>=23.1.0,<24",
|
||||
"specklepy>=3.0.0a3"
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
|
||||
Reference in New Issue
Block a user