BIM: rename ArchWindow's Sill property to SillHeight and handle one-w… (#26277)

* BIM: rename ArchWindow's Sill property to SillHeight and handle one-way migration

* BIM: properly remove the locked "Sill" property
This commit is contained in:
Furgo
2025-12-20 22:26:52 +01:00
committed by GitHub
parent 9b827c0436
commit ab16aa0161
4 changed files with 38 additions and 32 deletions

View File

@@ -308,11 +308,11 @@ class _Window(ArchComponent.Component):
obj.setEditorMode("HorizontalArea", 2)
obj.setEditorMode("PerimeterLength", 2)
# Sill change related properties
# SillHeight change related properties
self.setSillProperties(obj)
def setSillProperties(self, orgObj, linkObj=None):
"""Set properties which support Sill change.
"""Set properties which support SillHeight change.
Support both Arch Window and Link of Arch Window.
"""
@@ -324,10 +324,10 @@ class _Window(ArchComponent.Component):
prop = obj.PropertiesList
# 'Sill' support
if not "Sill" in prop:
if not "SillHeight" in prop:
obj.addProperty(
"App::PropertyLength",
"Sill",
"SillHeight",
"Window",
QT_TRANSLATE_NOOP("App::Property", "The height of this window's sill"),
locked=True,
@@ -347,14 +347,20 @@ class _Window(ArchComponent.Component):
# Add features in the SketchArch External Add-on
self.addSketchArchFeatures(obj, mode="ODR")
# TODO 2025.6.27 : Seems Sill already triggered onChanged() upon document restored - NO need codes below in onDocumentRestored()
# TODO 2025.6.27 : Seems SillHeight already triggered onChanged() upon document restored - NO need codes below in onDocumentRestored()
# Need to restore 'initial' settings as corresponding codes in onChanged() does upon object creation
# self.baseSill = obj.Sill.Value
# self.baseSill = obj.SillHeight.Value
# self.basePos = obj.Base.Placement.Base
# self.atthOff = None
# if hasattr(obj, 'AttachmentOffsetXyzAndRotation'):
# self.atthOff = obj.AttachmentOffsetXyzAndRotation.Base
# Sill -> SillHeight property rename migration
if hasattr(obj, "Sill"):
obj.SillHeight = obj.Sill
obj.setPropertyStatus(prop, "-LockDynamic")
obj.removeProperty("Sill")
def loads(self, state):
self.Type = "Window"
@@ -369,9 +375,9 @@ class _Window(ArchComponent.Component):
def onChanged(self, obj, prop):
self.hideSubobjects(obj, prop)
if prop == "Sill":
if prop == "SillHeight":
self.setSillProperties(obj) # Can't wait until onDocumentRestored
self.onSillChanged(obj)
self.onSillHeightChanged(obj)
elif not "Restore" in obj.State:
if prop in [
"Base",
@@ -728,7 +734,7 @@ class _Window(ArchComponent.Component):
@realthunder added support to Links to run Linked Scripted Object's methods()
"""
# Sill change support
# SillHeight change support
self.setSillProperties(obj, linkObj)
# Add features in the SketchArch External Add-on
@@ -737,17 +743,17 @@ class _Window(ArchComponent.Component):
# Execute features in the SketchArch External Add-on
self.executeSketchArchFeatures(obj, linkObj)
# Sill change feature
self.onSillChanged(obj, linkObj)
# SillHeight change feature
self.onSillHeightChanged(obj, linkObj)
def onSillChanged(self, orgObj, linkObj=None, index=None, linkElement=None):
def onSillHeightChanged(self, orgObj, linkObj=None, index=None, linkElement=None):
if linkObj:
obj = linkObj
else:
obj = orgObj
val = getattr(obj, "Sill").Value
val = getattr(obj, "SillHeight").Value
if (
getattr(obj, "baseSill", None) is None
and getattr(obj, "basePosZ", None) is None
@@ -787,12 +793,12 @@ class _Window(ArchComponent.Component):
# SketchArch or Not
if hasattr(obj, "AttachmentOffsetXyzAndRotation"):
objAttOff = obj.AttachmentOffsetXyzAndRotation
objAttOff.Base.z = obj.atthOffZ + (obj.Sill.Value - obj.baseSill)
objAttOff.Base.z = obj.atthOffZ + (obj.SillHeight.Value - obj.baseSill)
obj.AttachmentOffsetXyzAndRotation = objAttOff
if not SketchArch:
# Not to change Base's Placement
# obj.Base.Placement.Base.z = self.basePos.z + (obj.Sill.Value - self.baseSill)
obj.Placement.Base.z = obj.basePosZ + (obj.Sill.Value - obj.baseSill)
obj.Placement.Base.z = obj.basePosZ + (obj.SillHeight.Value - obj.baseSill)
def getSubFace(self):
"returns a subface for creation of subvolume for cutting in a base object"

View File

@@ -550,13 +550,13 @@ def makeWindowPreset(
obj.Frame = w2
obj.Offset = o1
obj.Placement = FreeCAD.Placement() # unable to find where this bug comes from...
# If window_sill is provided, set obj.Sill (and trigger onChanged()
# If window_sill is provided, set obj.SillHeight (and trigger onChanged()
# codes to track and adjust disposition of the Window object).
# Do not set the property (to 0) and not trigger onChanged()
# if otherwise.
# obj.Sill = window_sill if window_sill is not None else 0
# obj.SillHeight = window_sill if window_sill is not None else 0
if window_sill is not None:
obj.Sill = window_sill
obj.SillHeight = window_sill
if "door" in windowtype.lower():
obj.IfcType = "Door"
obj.Label = translate("Arch", "Door")

View File

@@ -79,7 +79,7 @@ class Arch_Window:
self.RemoveExternal = params.get_param_arch("archRemoveExternal")
self.Preset = 0
self.LibraryPreset = 0
self.Sill = 0
self.SillHeight = 0
self.Include = True
self.baseFace = None
self.wparams = ["Width", "Height", "H1", "H2", "H3", "W1", "W2", "O1", "O2"]
@@ -187,7 +187,7 @@ class Arch_Window:
# if something was selected, override the underlying object
if self.sel:
obj = self.sel[0]
point = point.add(FreeCAD.Vector(0, 0, self.Sill))
point = point.add(FreeCAD.Vector(0, 0, self.SillHeight))
self.doc.openTransaction(translate("Arch", "Create Window"))
FreeCADGui.doCommand("import FreeCAD, Arch, DraftGeomUtils, WorkingPlane")
@@ -286,10 +286,10 @@ class Arch_Window:
# placement = FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(1,0,0),90))
# TODO 2025.11.1 : To improve the algorithm to be more robust to allow the Base Sketch in any orientation but without problem
#
# Window object triggers onChanged() upon setting/changing Window.Sill to move Window's z position
# Window object triggers onChanged() upon setting/changing Window.SillHeight to move Window's z position
# For Window with SketchArch add-on, attachToHost() is to be run below to set the 'initial' Window's placement prior to triggering onChanged() below,
# so window_sill parameter is not used here at the moment, see 'if self.Include' below.
# FreeCADGui.doCommand("win = Arch.makeWindowPreset('" + WindowPresets[self.Preset] + "' " + wp + ", window_sill=" + str(self.Sill.Value) + ")")
# FreeCADGui.doCommand("win = Arch.makeWindowPreset('" + WindowPresets[self.Preset] + "' " + wp + ", window_sill=" + str(self.SillHeight.Value) + ")")
FreeCADGui.doCommand(
"pl90 = FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(1,0,0),90))"
)
@@ -309,7 +309,7 @@ class Arch_Window:
+ "' "
+ wp
+ ", placement=pl, window_sill="
+ str(self.Sill.Value)
+ str(self.SillHeight.Value)
+ ")"
)
FreeCADGui.doCommand("win.AttachToAxisOrSketch = 'None'")
@@ -325,7 +325,7 @@ class Arch_Window:
+ "' "
+ wp
+ ", placement=pl, window_sill="
+ str(self.Sill.Value)
+ str(self.SillHeight.Value)
+ ")"
)
SketchArch = False
@@ -340,8 +340,8 @@ class Arch_Window:
)
if SketchArch:
ArchSketchObject.attachToHost(w, target=host, pl=wPl)
# Trigger onChanged() in the window object by setting Window.Sill, after setting the Window's 'initial' placement by attachToHost() above
FreeCADGui.doCommand("win.Sill = " + str(self.Sill.Value))
# Trigger onChanged() in the window object by setting Window.SillHeight, after setting the Window's 'initial' placement by attachToHost() above
FreeCADGui.doCommand("win.SillHeight = " + str(self.SillHeight.Value))
self.doc.commitTransaction()
self.doc.recompute()
@@ -353,7 +353,7 @@ class Arch_Window:
"this function is called by the Snapper when the mouse is moved"
delta = FreeCAD.Vector(self.Width / 2, self.W1 / 2, self.Height / 2)
delta = delta.add(FreeCAD.Vector(0, 0, self.Sill))
delta = delta.add(FreeCAD.Vector(0, 0, self.SillHeight))
if self.baseFace is None:
rot = FreeCAD.Rotation(self.wp.u, self.wp.v, -self.wp.axis, "XZY")
@@ -402,7 +402,7 @@ class Arch_Window:
values = ui.createWidget("Gui::InputField")
grid.addWidget(labels, 1, 0, 1, 1)
grid.addWidget(values, 1, 1, 1, 1)
values.valueChanged.connect(self.setSill)
values.valueChanged.connect(self.setSillHeight)
# check for Parts library and Arch presets
@@ -503,11 +503,11 @@ class Arch_Window:
return lambda d: self.setParams(p, d)
def setSill(self, d):
def setSillHeight(self, d):
from draftutils import params
self.Sill = d
self.SillHeight = d
if self.doormode:
params.set_param_arch("DoorSill", d)
else:

View File

@@ -343,7 +343,7 @@ class TestArchWindow(TestArchBase.TestArchBase):
Notes:
- The clone's name is automatically generated, the `name` argument is ignored.
- The clone's WindowParts, Sill and other properties are always empty, despite the original having them.
- The clone's WindowParts, SillHeight and other properties are always empty, despite the original having them.
"""
sketch = self._create_sketch_with_wires("OriginalSketch", [(0, 0, 600, 800)])
@@ -352,7 +352,7 @@ class TestArchWindow(TestArchBase.TestArchBase):
baseobj=sketch, parts=original_parts, name="OriginalWindow"
)
original_window.Frame = 60.0
original_window.Sill = 100.0
original_window.SillHeight = 100.0
self.document.recompute()
self.assertEqual(original_window.Label, "OriginalWindow")