- assembly draft
This commit is contained in:
Generated
+14
-4
@@ -4,11 +4,12 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="8f0bafd6-58a0-4b20-aa2b-ddc3ba278873" name="Changes" comment="- sketch enhacements">
|
||||
<list default="true" id="8f0bafd6-58a0-4b20-aa2b-ddc3ba278873" name="Changes" comment="- UI refinement, button position ui file as source no dirty drafting anymore">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui.ui" beforeDir="false" afterPath="$PROJECT_DIR$/gui.ui" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui_ui.py" beforeDir="false" afterPath="$PROJECT_DIR$/gui_ui.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/fluency/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/main.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/fluency/rendering/occ_renderer.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/rendering/occ_renderer.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/fluency/models/data_model.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/models/data_model.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -313,7 +314,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1783159860774</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="26" />
|
||||
<task id="LOCAL-00026" summary="- UI refinement, button position ui file as source no dirty drafting anymore">
|
||||
<option name="closed" value="true" />
|
||||
<created>1783174566362</created>
|
||||
<option name="number" value="00026" />
|
||||
<option name="presentableId" value="LOCAL-00026" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1783174566362</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="27" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@@ -355,6 +364,7 @@
|
||||
<MESSAGE value="- Basic operations" />
|
||||
<MESSAGE value="- removed cadquery deoendency" />
|
||||
<MESSAGE value="- sketch enhacements" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="- sketch enhacements" />
|
||||
<MESSAGE value="- UI refinement, button position ui file as source no dirty drafting anymore" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="- UI refinement, button position ui file as source no dirty drafting anymore" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -15,72 +15,6 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="12" column="2">
|
||||
<widget class="QGroupBox" name="compos_in_assembly_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Components in Assembly</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="3">
|
||||
<widget class="QGroupBox" name="joint_tools">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Joint Tools</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="pb_add_connector">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+ Cnct</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pb_remove_connector">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>- Cnct</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="sizePolicy">
|
||||
@@ -695,19 +629,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QGroupBox" name="assembly_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Assembly</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="11">
|
||||
<widget class="QTabWidget" name="InputTab">
|
||||
<property name="sizePolicy">
|
||||
@@ -1031,7 +952,7 @@
|
||||
<property name="title">
|
||||
<string>Drawing</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0,0,0">
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0,0">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
@@ -1149,6 +1070,110 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="assembly_box">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Assembly</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="3" rowspan="2">
|
||||
<widget class="QGroupBox" name="joint_tools">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Joint Tools</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pb_remove_connector">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>- Cnct</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pb_add_connector">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+ Cnct</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pb_add_connector_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+Jnt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pb_add_connector_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-Jnt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
|
||||
@@ -37,34 +37,6 @@ class Ui_fluencyCAD(object):
|
||||
self.centralwidget.setObjectName(u"centralwidget")
|
||||
self.gridLayout = QGridLayout(self.centralwidget)
|
||||
self.gridLayout.setObjectName(u"gridLayout")
|
||||
self.compos_in_assembly_box = QGroupBox(self.centralwidget)
|
||||
self.compos_in_assembly_box.setObjectName(u"compos_in_assembly_box")
|
||||
self.compos_in_assembly_box.setMinimumSize(QSize(0, 50))
|
||||
|
||||
self.gridLayout.addWidget(self.compos_in_assembly_box, 12, 2, 1, 1)
|
||||
|
||||
self.joint_tools = QGroupBox(self.centralwidget)
|
||||
self.joint_tools.setObjectName(u"joint_tools")
|
||||
self.joint_tools.setMinimumSize(QSize(0, 50))
|
||||
self.gridLayout_10 = QGridLayout(self.joint_tools)
|
||||
self.gridLayout_10.setObjectName(u"gridLayout_10")
|
||||
self.pb_add_connector = QPushButton(self.joint_tools)
|
||||
self.pb_add_connector.setObjectName(u"pb_add_connector")
|
||||
self.pb_add_connector.setMinimumSize(QSize(50, 50))
|
||||
self.pb_add_connector.setMaximumSize(QSize(50, 50))
|
||||
|
||||
self.gridLayout_10.addWidget(self.pb_add_connector, 0, 0, 1, 1)
|
||||
|
||||
self.pb_remove_connector = QPushButton(self.joint_tools)
|
||||
self.pb_remove_connector.setObjectName(u"pb_remove_connector")
|
||||
self.pb_remove_connector.setMinimumSize(QSize(50, 50))
|
||||
self.pb_remove_connector.setMaximumSize(QSize(50, 50))
|
||||
|
||||
self.gridLayout_10.addWidget(self.pb_remove_connector, 0, 1, 1, 1)
|
||||
|
||||
|
||||
self.gridLayout.addWidget(self.joint_tools, 12, 3, 1, 1)
|
||||
|
||||
self.groupBox_5 = QGroupBox(self.centralwidget)
|
||||
self.groupBox_5.setObjectName(u"groupBox_5")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred)
|
||||
@@ -384,12 +356,6 @@ class Ui_fluencyCAD(object):
|
||||
|
||||
self.gridLayout.addWidget(self.groupBox_4, 2, 3, 1, 1)
|
||||
|
||||
self.assembly_box = QGroupBox(self.centralwidget)
|
||||
self.assembly_box.setObjectName(u"assembly_box")
|
||||
self.assembly_box.setMinimumSize(QSize(0, 50))
|
||||
|
||||
self.gridLayout.addWidget(self.assembly_box, 12, 1, 1, 1)
|
||||
|
||||
self.InputTab = QTabWidget(self.centralwidget)
|
||||
self.InputTab.setObjectName(u"InputTab")
|
||||
sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
|
||||
@@ -625,6 +591,48 @@ class Ui_fluencyCAD(object):
|
||||
|
||||
self.gridLayout.addWidget(self.groupBox_2, 2, 0, 1, 1)
|
||||
|
||||
self.assembly_box = QGroupBox(self.centralwidget)
|
||||
self.assembly_box.setObjectName(u"assembly_box")
|
||||
self.assembly_box.setMinimumSize(QSize(0, 50))
|
||||
|
||||
self.gridLayout.addWidget(self.assembly_box, 12, 1, 1, 2)
|
||||
|
||||
self.joint_tools = QGroupBox(self.centralwidget)
|
||||
self.joint_tools.setObjectName(u"joint_tools")
|
||||
self.joint_tools.setMinimumSize(QSize(0, 50))
|
||||
self.gridLayout_10 = QGridLayout(self.joint_tools)
|
||||
self.gridLayout_10.setObjectName(u"gridLayout_10")
|
||||
self.pb_remove_connector = QPushButton(self.joint_tools)
|
||||
self.pb_remove_connector.setObjectName(u"pb_remove_connector")
|
||||
self.pb_remove_connector.setMinimumSize(QSize(50, 50))
|
||||
self.pb_remove_connector.setMaximumSize(QSize(50, 50))
|
||||
|
||||
self.gridLayout_10.addWidget(self.pb_remove_connector, 0, 2, 1, 1)
|
||||
|
||||
self.pb_add_connector = QPushButton(self.joint_tools)
|
||||
self.pb_add_connector.setObjectName(u"pb_add_connector")
|
||||
self.pb_add_connector.setMinimumSize(QSize(50, 50))
|
||||
self.pb_add_connector.setMaximumSize(QSize(50, 50))
|
||||
|
||||
self.gridLayout_10.addWidget(self.pb_add_connector, 0, 1, 1, 1)
|
||||
|
||||
self.pb_add_connector_2 = QPushButton(self.joint_tools)
|
||||
self.pb_add_connector_2.setObjectName(u"pb_add_connector_2")
|
||||
self.pb_add_connector_2.setMinimumSize(QSize(50, 50))
|
||||
self.pb_add_connector_2.setMaximumSize(QSize(50, 50))
|
||||
|
||||
self.gridLayout_10.addWidget(self.pb_add_connector_2, 1, 1, 1, 1)
|
||||
|
||||
self.pb_add_connector_3 = QPushButton(self.joint_tools)
|
||||
self.pb_add_connector_3.setObjectName(u"pb_add_connector_3")
|
||||
self.pb_add_connector_3.setMinimumSize(QSize(50, 50))
|
||||
self.pb_add_connector_3.setMaximumSize(QSize(50, 50))
|
||||
|
||||
self.gridLayout_10.addWidget(self.pb_add_connector_3, 1, 2, 1, 1)
|
||||
|
||||
|
||||
self.gridLayout.addWidget(self.joint_tools, 11, 3, 2, 1)
|
||||
|
||||
fluencyCAD.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QMenuBar(fluencyCAD)
|
||||
self.menubar.setObjectName(u"menubar")
|
||||
@@ -658,10 +666,6 @@ class Ui_fluencyCAD(object):
|
||||
self.actionNew_Project.setText(QCoreApplication.translate("fluencyCAD", u"New", None))
|
||||
self.actionLoad_Project.setText(QCoreApplication.translate("fluencyCAD", u"Load", None))
|
||||
self.actionRecent.setText(QCoreApplication.translate("fluencyCAD", u"Recent", None))
|
||||
self.compos_in_assembly_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Components in Assembly", None))
|
||||
self.joint_tools.setTitle(QCoreApplication.translate("fluencyCAD", u"Joint Tools", None))
|
||||
self.pb_add_connector.setText(QCoreApplication.translate("fluencyCAD", u"+ Cnct", None))
|
||||
self.pb_remove_connector.setText(QCoreApplication.translate("fluencyCAD", u"- Cnct", None))
|
||||
self.groupBox_5.setTitle(QCoreApplication.translate("fluencyCAD", u"Snapping Points", None))
|
||||
self.label.setText(QCoreApplication.translate("fluencyCAD", u"Snp Dst", None))
|
||||
self.pb_snap_vert.setText(QCoreApplication.translate("fluencyCAD", u"Vert", None))
|
||||
@@ -739,7 +743,6 @@ class Ui_fluencyCAD(object):
|
||||
self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"STL", None))
|
||||
self.pb_export_step.setText(QCoreApplication.translate("fluencyCAD", u"STEP", None))
|
||||
self.pb_export_iges.setText(QCoreApplication.translate("fluencyCAD", u"IGES", None))
|
||||
self.assembly_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Assembly", None))
|
||||
self.InputTab.setTabText(self.InputTab.indexOf(self.sketch_tab), QCoreApplication.translate("fluencyCAD", u"Sketch", None))
|
||||
self.groupBox_7.setTitle(QCoreApplication.translate("fluencyCAD", u"Executive", None))
|
||||
self.pushButton_5.setText(QCoreApplication.translate("fluencyCAD", u"Load Code", None))
|
||||
@@ -796,6 +799,12 @@ class Ui_fluencyCAD(object):
|
||||
self.pb_offset_tool.setToolTip(QCoreApplication.translate("fluencyCAD", u"Offset selected sketch face (duplicate + offset boundary)", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.pb_offset_tool.setText(QCoreApplication.translate("fluencyCAD", u"Offst", None))
|
||||
self.assembly_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Assembly", None))
|
||||
self.joint_tools.setTitle(QCoreApplication.translate("fluencyCAD", u"Joint Tools", None))
|
||||
self.pb_remove_connector.setText(QCoreApplication.translate("fluencyCAD", u"- Cnct", None))
|
||||
self.pb_add_connector.setText(QCoreApplication.translate("fluencyCAD", u"+ Cnct", None))
|
||||
self.pb_add_connector_2.setText(QCoreApplication.translate("fluencyCAD", u"+Jnt", None))
|
||||
self.pb_add_connector_3.setText(QCoreApplication.translate("fluencyCAD", u"-Jnt", None))
|
||||
self.menuFile.setTitle(QCoreApplication.translate("fluencyCAD", u"File", None))
|
||||
self.menuSettings.setTitle(QCoreApplication.translate("fluencyCAD", u"Settings", None))
|
||||
# retranslateUi
|
||||
|
||||
+941
-3
File diff suppressed because it is too large
Load Diff
@@ -336,6 +336,160 @@ class Component:
|
||||
self.modified_at = datetime.now()
|
||||
|
||||
|
||||
@dataclass
|
||||
class Connector:
|
||||
"""
|
||||
A connection point on an assembly component instance.
|
||||
|
||||
Stores the position and orientation of a connection point
|
||||
(e.g. a hole center, face midpoint, or edge point) that will
|
||||
later be used by the SolveSpace solver to mate components.
|
||||
The *normal* defines the connection axis direction (e.g. the
|
||||
hole axis for a screw connection).
|
||||
"""
|
||||
|
||||
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
||||
name: str = "Untitled Connector"
|
||||
|
||||
# 3D position of the connection point (world coords).
|
||||
position: Tuple[float, float, float] = (0.0, 0.0, 0.0)
|
||||
# Normal direction of the connection (e.g. hole axis).
|
||||
normal: Tuple[float, float, float] = (0.0, 0.0, 1.0)
|
||||
# In-plane X direction for defining the reference frame.
|
||||
x_dir: Tuple[float, float, float] = (1.0, 0.0, 0.0)
|
||||
|
||||
# Rotation around the normal axis (degrees).
|
||||
axis_rotation: float = 0.0
|
||||
# Offset distance along the normal.
|
||||
offset: float = 0.0
|
||||
|
||||
# Which AssemblyComponent this connector belongs to.
|
||||
assembly_component_id: str = ""
|
||||
# Which body/face this connector was placed on (renderer obj_id).
|
||||
source_obj_id: str = ""
|
||||
|
||||
# Future: connected to another Connector's id.
|
||||
# connected_to: Optional[str] = None
|
||||
|
||||
created_at: datetime = field(default_factory=datetime.now)
|
||||
modified_at: datetime = field(default_factory=datetime.now)
|
||||
|
||||
|
||||
@dataclass
|
||||
class AssemblyComponent:
|
||||
"""
|
||||
An instance of a component within an assembly.
|
||||
|
||||
References a component in the project and stores its relative
|
||||
position and rotation for placement within the assembly.
|
||||
Holds connectors that define connection points for the
|
||||
SolveSpace solver.
|
||||
"""
|
||||
|
||||
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
||||
component_id: str = ""
|
||||
name: str = "Untitled Instance"
|
||||
|
||||
# Position and orientation relative to the assembly origin.
|
||||
position: np.ndarray = field(default_factory=lambda: np.array([0.0, 0.0, 0.0]))
|
||||
rotation: np.ndarray = field(default_factory=lambda: np.eye(3))
|
||||
|
||||
# Connectors defined on this component instance.
|
||||
connectors: Dict[str, Connector] = field(default_factory=dict)
|
||||
|
||||
created_at: datetime = field(default_factory=datetime.now)
|
||||
modified_at: datetime = field(default_factory=datetime.now)
|
||||
|
||||
def add_connector(
|
||||
self,
|
||||
position: Tuple[float, float, float],
|
||||
normal: Tuple[float, float, float],
|
||||
x_dir: Tuple[float, float, float],
|
||||
source_obj_id: str = "",
|
||||
name: Optional[str] = None,
|
||||
) -> Connector:
|
||||
"""Add a connector to this component instance."""
|
||||
conn = Connector(
|
||||
name=name or f"Connector {len(self.connectors) + 1}",
|
||||
position=position,
|
||||
normal=normal,
|
||||
x_dir=x_dir,
|
||||
assembly_component_id=self.id,
|
||||
source_obj_id=source_obj_id,
|
||||
)
|
||||
self.connectors[conn.id] = conn
|
||||
self.modified_at = datetime.now()
|
||||
return conn
|
||||
|
||||
def remove_connector(self, connector_id: str) -> bool:
|
||||
"""Remove a connector from this component instance."""
|
||||
if connector_id in self.connectors:
|
||||
del self.connectors[connector_id]
|
||||
self.modified_at = datetime.now()
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@dataclass
|
||||
class Assembly:
|
||||
"""
|
||||
An assembly of multiple component instances.
|
||||
|
||||
An assembly groups component instances with relative positions,
|
||||
ready for constraint solving and joint definition between them.
|
||||
Components can be instanced multiple times, each at a different
|
||||
position and rotation.
|
||||
"""
|
||||
|
||||
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
||||
name: str = "Untitled Assembly"
|
||||
|
||||
components: Dict[str, AssemblyComponent] = field(default_factory=dict)
|
||||
active_assembly_component: Optional[str] = None
|
||||
|
||||
created_at: datetime = field(default_factory=datetime.now)
|
||||
modified_at: datetime = field(default_factory=datetime.now)
|
||||
|
||||
def add_component_instance(
|
||||
self, component_id: str, name: Optional[str] = None
|
||||
) -> AssemblyComponent:
|
||||
"""Add a component instance to the assembly.
|
||||
|
||||
Returns the newly created AssemblyComponent. The same
|
||||
component can be added multiple times (multiple instances).
|
||||
"""
|
||||
ac = AssemblyComponent(
|
||||
component_id=component_id,
|
||||
name=name or f"Instance {len(self.components) + 1}",
|
||||
)
|
||||
self.components[ac.id] = ac
|
||||
if self.active_assembly_component is None:
|
||||
self.active_assembly_component = ac.id
|
||||
self.modified_at = datetime.now()
|
||||
return ac
|
||||
|
||||
def remove_component_instance(self, assembly_component_id: str) -> bool:
|
||||
"""Remove a component instance from the assembly."""
|
||||
if assembly_component_id in self.components:
|
||||
del self.components[assembly_component_id]
|
||||
if self.active_assembly_component == assembly_component_id:
|
||||
self.active_assembly_component = next(
|
||||
iter(self.components.keys()), None
|
||||
)
|
||||
self.modified_at = datetime.now()
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_active_instance(self) -> Optional[AssemblyComponent]:
|
||||
"""Get the currently active assembly component instance."""
|
||||
if (
|
||||
self.active_assembly_component
|
||||
and self.active_assembly_component in self.components
|
||||
):
|
||||
return self.components[self.active_assembly_component]
|
||||
return None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Project:
|
||||
"""
|
||||
@@ -351,12 +505,85 @@ class Project:
|
||||
components: Dict[str, Component] = field(default_factory=dict)
|
||||
active_component: Optional[str] = None
|
||||
|
||||
assemblies: Dict[str, Assembly] = field(default_factory=dict)
|
||||
active_assembly: Optional[str] = None
|
||||
|
||||
kernel: OCGeometryKernel = field(default_factory=OCGeometryKernel)
|
||||
|
||||
created_at: datetime = field(default_factory=datetime.now)
|
||||
modified_at: datetime = field(default_factory=datetime.now)
|
||||
file_path: Optional[str] = None
|
||||
|
||||
# ── Component helpers ──
|
||||
|
||||
def add_component(self, component: Optional[Component] = None) -> Component:
|
||||
"""Add a component to the project."""
|
||||
if component is None:
|
||||
component = Component(name=f"Component {len(self.components) + 1}")
|
||||
self.components[component.id] = component
|
||||
if self.active_component is None:
|
||||
self.active_component = component.id
|
||||
self.modified_at = datetime.now()
|
||||
return component
|
||||
|
||||
def remove_component(self, component_id: str) -> bool:
|
||||
"""Remove a component from the project."""
|
||||
if component_id in self.components:
|
||||
del self.components[component_id]
|
||||
if self.active_component == component_id:
|
||||
self.active_component = next(iter(self.components.keys()), None)
|
||||
self.modified_at = datetime.now()
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_active_component(self) -> Optional[Component]:
|
||||
"""Get the currently active component."""
|
||||
if self.active_component and self.active_component in self.components:
|
||||
return self.components[self.active_component]
|
||||
return None
|
||||
|
||||
def set_active_component(self, component_id: Optional[str]) -> None:
|
||||
"""Set the active component."""
|
||||
self.active_component = component_id
|
||||
self.modified_at = datetime.now()
|
||||
|
||||
# ── Assembly helpers ──
|
||||
|
||||
def add_assembly(self, assembly: Optional[Assembly] = None) -> Assembly:
|
||||
"""Add an assembly to the project."""
|
||||
if assembly is None:
|
||||
assembly = Assembly(name=f"Assembly {len(self.assemblies) + 1}")
|
||||
self.assemblies[assembly.id] = assembly
|
||||
if self.active_assembly is None:
|
||||
self.active_assembly = assembly.id
|
||||
self.modified_at = datetime.now()
|
||||
return assembly
|
||||
|
||||
def remove_assembly(self, assembly_id: str) -> bool:
|
||||
"""Remove an assembly from the project."""
|
||||
if assembly_id in self.assemblies:
|
||||
del self.assemblies[assembly_id]
|
||||
if self.active_assembly == assembly_id:
|
||||
self.active_assembly = next(iter(self.assemblies.keys()), None)
|
||||
self.modified_at = datetime.now()
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_active_assembly(self) -> Optional[Assembly]:
|
||||
"""Get the currently active assembly."""
|
||||
if self.active_assembly and self.active_assembly in self.assemblies:
|
||||
return self.assemblies[self.active_assembly]
|
||||
return None
|
||||
|
||||
def set_active_assembly(self, assembly_id: Optional[str]) -> None:
|
||||
"""Set the active assembly."""
|
||||
self.active_assembly = assembly_id
|
||||
self.modified_at = datetime.now()
|
||||
|
||||
def get_component_by_id(self, component_id: str) -> Optional[Component]:
|
||||
"""Look up a component by id across all project components."""
|
||||
return self.components.get(component_id)
|
||||
|
||||
def add_component(self, component: Optional[Component] = None) -> Component:
|
||||
"""Add a component to the project."""
|
||||
if component is None:
|
||||
|
||||
Reference in New Issue
Block a user