Compare commits
3 Commits
feat/appea
...
fix/angled
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04f9df75cb | ||
|
|
2132c4e64c | ||
|
|
12e332240a |
@@ -66,13 +66,8 @@ class ZToolsWorkbench(Gui.Workbench):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
from ztools.commands import (
|
||||
assembly_pattern_commands,
|
||||
datum_commands,
|
||||
pattern_commands,
|
||||
pocket_commands,
|
||||
spreadsheet_commands,
|
||||
)
|
||||
# Command imports moved to module scope (after Gui.addWorkbench) so they
|
||||
# are available before Initialize() runs. See end of file.
|
||||
|
||||
# =====================================================================
|
||||
# PartDesign Structure Tools
|
||||
@@ -306,12 +301,6 @@ class ZToolsWorkbench(Gui.Workbench):
|
||||
+ self.ztools_spreadsheet_tools,
|
||||
)
|
||||
|
||||
# Register the PartDesign manipulator now that commands exist.
|
||||
# Guard so it only registers once even if Initialize is called again.
|
||||
if not getattr(ZToolsWorkbench, "_manipulator_installed", False):
|
||||
ZToolsWorkbench._manipulator_installed = True
|
||||
Gui.addWorkbenchManipulator(_ZToolsPartDesignManipulator())
|
||||
|
||||
App.Console.PrintMessage("ztools workbench initialized\n")
|
||||
|
||||
def Activated(self):
|
||||
@@ -337,11 +326,24 @@ class ZToolsWorkbench(Gui.Workbench):
|
||||
Gui.addWorkbench(ZToolsWorkbench())
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Eager command registration
|
||||
# ---------------------------------------------------------------------------
|
||||
# Import command modules at module scope so Gui.addCommand() calls run before
|
||||
# any workbench activates. This ensures the PartDesign manipulator can
|
||||
# reference them regardless of workbench activation order (#52).
|
||||
|
||||
from ztools.commands import (
|
||||
assembly_pattern_commands,
|
||||
datum_commands,
|
||||
pattern_commands,
|
||||
pocket_commands,
|
||||
spreadsheet_commands,
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# WorkbenchManipulator: inject ZTools commands into PartDesign workbench
|
||||
# ---------------------------------------------------------------------------
|
||||
# Registered in ZToolsWorkbench.Initialize() after commands are imported,
|
||||
# so the commands exist before the manipulator references them.
|
||||
|
||||
|
||||
class _ZToolsPartDesignManipulator:
|
||||
@@ -363,24 +365,11 @@ class _ZToolsPartDesignManipulator:
|
||||
|
||||
def modifyMenuBar(self):
|
||||
return [
|
||||
{
|
||||
"insert": "ZTools_DatumCreator",
|
||||
"menuItem": "PartDesign_Boolean",
|
||||
"after": "",
|
||||
},
|
||||
{
|
||||
"insert": "ZTools_DatumManager",
|
||||
"menuItem": "ZTools_DatumCreator",
|
||||
"after": "",
|
||||
},
|
||||
{
|
||||
"insert": "ZTools_EnhancedPocket",
|
||||
"menuItem": "ZTools_DatumManager",
|
||||
"after": "",
|
||||
},
|
||||
{
|
||||
"insert": "ZTools_RotatedLinearPattern",
|
||||
"menuItem": "ZTools_EnhancedPocket",
|
||||
"after": "",
|
||||
},
|
||||
{"append": "ZTools_DatumCreator", "menuItem": "PartDesign_Body"},
|
||||
{"append": "ZTools_DatumManager", "menuItem": "PartDesign_Body"},
|
||||
{"append": "ZTools_EnhancedPocket", "menuItem": "PartDesign_Body"},
|
||||
{"append": "ZTools_RotatedLinearPattern", "menuItem": "PartDesign_Body"},
|
||||
]
|
||||
|
||||
|
||||
Gui.addWorkbenchManipulator(_ZToolsPartDesignManipulator())
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Custom ViewProvider for ZTools datum objects
|
||||
|
||||
import json
|
||||
import math
|
||||
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
@@ -141,6 +142,23 @@ class ZToolsDatumViewProvider:
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_source_refs(datum_obj):
|
||||
"""Parse ZTools_SourceRefs and resolve to (object, subname, shape) tuples."""
|
||||
refs_json = getattr(datum_obj, "ZTools_SourceRefs", "[]")
|
||||
try:
|
||||
refs = json.loads(refs_json)
|
||||
except json.JSONDecodeError:
|
||||
return []
|
||||
doc = datum_obj.Document
|
||||
resolved = []
|
||||
for ref in refs:
|
||||
obj = doc.getObject(ref.get("object", ""))
|
||||
sub = ref.get("subname", "")
|
||||
shape = obj.getSubObject(sub) if obj and sub else None
|
||||
resolved.append((obj, sub, shape))
|
||||
return resolved
|
||||
|
||||
|
||||
class DatumEditTaskPanel:
|
||||
"""
|
||||
Task panel for editing existing ZTools datum objects.
|
||||
@@ -364,8 +382,45 @@ class DatumEditTaskPanel:
|
||||
self.datum_obj.AttachmentOffset = new_offset
|
||||
self._update_params({"distance": distance})
|
||||
|
||||
elif ztools_type in ("angled", "tangent_cylinder"):
|
||||
self._update_params({"angle": self.angle_spin.value()})
|
||||
elif ztools_type == "angled":
|
||||
angle = self.angle_spin.value()
|
||||
if self._has_attachment():
|
||||
refs = _resolve_source_refs(self.datum_obj)
|
||||
if len(refs) >= 2 and refs[0][2] and refs[1][2]:
|
||||
face_normal = refs[0][2].normalAt(0, 0)
|
||||
edge_shape = refs[1][2]
|
||||
edge_dir = (
|
||||
edge_shape.Vertexes[-1].Point - edge_shape.Vertexes[0].Point
|
||||
).normalize()
|
||||
face_rot = App.Rotation(App.Vector(0, 0, 1), face_normal)
|
||||
local_edge_dir = face_rot.inverted().multVec(edge_dir)
|
||||
angle_rot = App.Rotation(local_edge_dir, angle)
|
||||
self.datum_obj.AttachmentOffset = App.Placement(
|
||||
App.Vector(0, 0, 0), angle_rot
|
||||
)
|
||||
self._update_params({"angle": angle})
|
||||
|
||||
elif ztools_type == "tangent_cylinder":
|
||||
angle = self.angle_spin.value()
|
||||
refs = _resolve_source_refs(self.datum_obj)
|
||||
if refs and refs[0][2]:
|
||||
face = refs[0][2]
|
||||
if isinstance(face.Surface, Part.Cylinder):
|
||||
cyl = face.Surface
|
||||
axis = cyl.Axis
|
||||
center = cyl.Center
|
||||
radius = cyl.Radius
|
||||
rad = math.radians(angle)
|
||||
if abs(axis.dot(App.Vector(1, 0, 0))) < 0.99:
|
||||
local_x = axis.cross(App.Vector(1, 0, 0)).normalize()
|
||||
else:
|
||||
local_x = axis.cross(App.Vector(0, 1, 0)).normalize()
|
||||
local_y = axis.cross(local_x)
|
||||
radial = local_x * math.cos(rad) + local_y * math.sin(rad)
|
||||
tangent_point = center + radial * radius
|
||||
rot = App.Rotation(App.Vector(0, 0, 1), radial)
|
||||
self.datum_obj.Placement = App.Placement(tangent_point, rot)
|
||||
self._update_params({"angle": angle})
|
||||
|
||||
elif ztools_type in ("normal_to_edge", "on_edge"):
|
||||
parameter = self.param_spin.value()
|
||||
|
||||
Reference in New Issue
Block a user