@reekon-tools/boldr-cad 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -4
- package/dist/app/edit.d.ts +3 -3
- package/dist/app/edit.js +26 -1
- package/dist/app/edit.js.map +1 -1
- package/dist/app/state.d.ts +3 -5
- package/dist/app/state.js +0 -1
- package/dist/app/state.js.map +1 -1
- package/dist/data/sync.d.ts +1 -1
- package/dist/data/sync.js +7 -2
- package/dist/data/sync.js.map +1 -1
- package/dist/editor/actions.d.ts +8 -0
- package/dist/editor/actions.js +149 -169
- package/dist/editor/actions.js.map +1 -1
- package/dist/editor/elevation.d.ts +4 -1
- package/dist/editor/elevation.js +16 -17
- package/dist/editor/elevation.js.map +1 -1
- package/dist/editor/gestures.d.ts +21 -0
- package/dist/editor/gestures.js +92 -14
- package/dist/editor/gestures.js.map +1 -1
- package/dist/editor/keys.js +2 -2
- package/dist/editor/keys.js.map +1 -1
- package/dist/editor/linkActions.d.ts +22 -3
- package/dist/editor/linkActions.js +95 -13
- package/dist/editor/linkActions.js.map +1 -1
- package/dist/editor/mode.js +4 -3
- package/dist/editor/mode.js.map +1 -1
- package/dist/editor/project.js +1 -2
- package/dist/editor/project.js.map +1 -1
- package/dist/editor/scaleGate.d.ts +13 -0
- package/dist/editor/scaleGate.js +27 -0
- package/dist/editor/scaleGate.js.map +1 -0
- package/dist/editor/selection.js +13 -9
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/tooltips.js +9 -0
- package/dist/editor/tooltips.js.map +1 -1
- package/dist/editor/view3d.d.ts +4 -1
- package/dist/editor/view3d.js +6 -2
- package/dist/editor/view3d.js.map +1 -1
- package/dist/export/pdf.d.ts +5 -2
- package/dist/export/pdf.js +12 -8
- package/dist/export/pdf.js.map +1 -1
- package/dist/export/plan.d.ts +1 -1
- package/dist/export/plan.js +14 -9
- package/dist/export/plan.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model/demo.d.ts +1 -0
- package/dist/model/demo.js +2 -1
- package/dist/model/demo.js.map +1 -1
- package/dist/model/elevation.d.ts +1 -1
- package/dist/model/elevation.js +3 -3
- package/dist/model/elevation.js.map +1 -1
- package/dist/model/history.js +4 -1
- package/dist/model/history.js.map +1 -1
- package/dist/model/links.d.ts +4 -1
- package/dist/model/links.js +9 -2
- package/dist/model/links.js.map +1 -1
- package/dist/model/measurement.d.ts +2 -2
- package/dist/model/measurement.js +3 -3
- package/dist/model/measurement.js.map +1 -1
- package/dist/model/openings.d.ts +10 -0
- package/dist/model/openings.js +18 -0
- package/dist/model/openings.js.map +1 -1
- package/dist/model/planGeom.d.ts +37 -2
- package/dist/model/planGeom.js +72 -9
- package/dist/model/planGeom.js.map +1 -1
- package/dist/model/project.js +5 -2
- package/dist/model/project.js.map +1 -1
- package/dist/model/rooms.d.ts +18 -5
- package/dist/model/rooms.js +178 -73
- package/dist/model/rooms.js.map +1 -1
- package/dist/model/scale.d.ts +30 -0
- package/dist/model/scale.js +120 -0
- package/dist/model/scale.js.map +1 -0
- package/dist/model/settings.d.ts +0 -1
- package/dist/model/settings.js +1 -1
- package/dist/model/settings.js.map +1 -1
- package/dist/model/sketch.d.ts +21 -1
- package/dist/model/sketch.js +58 -4
- package/dist/model/sketch.js.map +1 -1
- package/dist/model/stroke.js +2 -2
- package/dist/model/types.d.ts +38 -7
- package/dist/react/BottomBar.d.ts +2 -1
- package/dist/react/BottomBar.js +94 -25
- package/dist/react/BottomBar.js.map +1 -1
- package/dist/react/Drawer.js +3 -2
- package/dist/react/Drawer.js.map +1 -1
- package/dist/react/Duck.js.map +1 -1
- package/dist/react/KeypadSheet.js.map +1 -1
- package/dist/react/MarkupPanel.js +1 -1
- package/dist/react/PlanCanvas.native.js +54 -7
- package/dist/react/PlanCanvas.native.js.map +1 -1
- package/dist/react/Popovers.js +14 -3
- package/dist/react/Popovers.js.map +1 -1
- package/dist/react/Rail.js +1 -1
- package/dist/react/Sheet.d.ts +2 -2
- package/dist/react/Sheet.js.map +1 -1
- package/dist/react/barScroll.d.ts +23 -0
- package/dist/react/barScroll.js +47 -0
- package/dist/react/barScroll.js.map +1 -0
- package/dist/react/corners.d.ts +6 -2
- package/dist/react/corners.js.map +1 -1
- package/dist/react/host.d.ts +7 -0
- package/dist/react/host.js +14 -1
- package/dist/react/host.js.map +1 -1
- package/dist/react/motion.d.ts +1 -1
- package/dist/react/motion.js +1 -1
- package/dist/react/motion.js.map +1 -1
- package/dist/render/draw.d.ts +21 -4
- package/dist/render/draw.js +184 -149
- package/dist/render/draw.js.map +1 -1
- package/dist/render/elevation.js +3 -3
- package/dist/render/elevation.js.map +1 -1
- package/dist/render/figmaIcons.d.ts +6 -0
- package/dist/render/figmaIcons.js +16 -1
- package/dist/render/figmaIcons.js.map +1 -1
- package/dist/render/hit.d.ts +8 -1
- package/dist/render/hit.js +23 -4
- package/dist/render/hit.js.map +1 -1
- package/dist/render/icons.js +27 -20
- package/dist/render/icons.js.map +1 -1
- package/dist/render/lens.d.ts +27 -0
- package/dist/render/lens.js +41 -0
- package/dist/render/lens.js.map +1 -0
- package/dist/render/linkTile.d.ts +20 -2
- package/dist/render/linkTile.js +476 -246
- package/dist/render/linkTile.js.map +1 -1
- package/dist/render/snap.d.ts +5 -1
- package/dist/render/snap.js +3 -1
- package/dist/render/snap.js.map +1 -1
- package/dist/render/svgPath.d.ts +29 -0
- package/dist/render/svgPath.js +114 -0
- package/dist/render/svgPath.js.map +1 -0
- package/dist/render/tileIcons.d.ts +18 -0
- package/dist/render/tileIcons.js +67 -0
- package/dist/render/tileIcons.js.map +1 -0
- package/dist/render/view.d.ts +18 -1
- package/dist/render/view.js +31 -4
- package/dist/render/view.js.map +1 -1
- package/dist/skia/SkiaDrawCtx.d.ts +8 -0
- package/dist/skia/SkiaDrawCtx.js +27 -5
- package/dist/skia/SkiaDrawCtx.js.map +1 -1
- package/dist/solver/equations.d.ts +6 -0
- package/dist/solver/equations.js +23 -6
- package/dist/solver/equations.js.map +1 -1
- package/dist/solver/gauss-newton.js +6 -1
- package/dist/solver/gauss-newton.js.map +1 -1
- package/dist/tools/annotate.d.ts +0 -2
- package/dist/tools/annotate.js +1 -22
- package/dist/tools/annotate.js.map +1 -1
- package/dist/tools/chamfer.js +4 -0
- package/dist/tools/chamfer.js.map +1 -1
- package/dist/tools/dim.d.ts +3 -3
- package/dist/tools/dim.js +26 -65
- package/dist/tools/dim.js.map +1 -1
- package/dist/tools/fillet.js +4 -0
- package/dist/tools/fillet.js.map +1 -1
- package/dist/tools/freehand.js +1 -4
- package/dist/tools/freehand.js.map +1 -1
- package/dist/tools/line.js +15 -11
- package/dist/tools/line.js.map +1 -1
- package/dist/tools/modify.js +6 -1
- package/dist/tools/modify.js.map +1 -1
- package/dist/tools/registry.d.ts +5 -0
- package/dist/tools/registry.js +6 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/select.d.ts +19 -0
- package/dist/tools/select.js +116 -17
- package/dist/tools/select.js.map +1 -1
- package/dist/tools/shapes.d.ts +1 -1
- package/dist/tools/shapes.js +12 -5
- package/dist/tools/shapes.js.map +1 -1
- package/dist/tools/survey.d.ts +6 -0
- package/dist/tools/survey.js +28 -0
- package/dist/tools/survey.js.map +1 -1
- package/dist/view3d/build.js +9 -8
- package/dist/view3d/build.js.map +1 -1
- package/package.json +9 -9
- package/src/app/edit.ts +25 -1
- package/src/app/state.ts +3 -5
- package/src/data/sync.ts +7 -2
- package/src/editor/actions.ts +126 -112
- package/src/editor/elevation.ts +13 -16
- package/src/editor/gestures.ts +83 -13
- package/src/editor/keys.ts +2 -2
- package/src/editor/linkActions.ts +90 -13
- package/src/editor/mode.ts +4 -3
- package/src/editor/project.ts +1 -2
- package/src/editor/scaleGate.ts +32 -0
- package/src/editor/selection.ts +13 -7
- package/src/editor/tooltips.ts +8 -0
- package/src/editor/view3d.ts +6 -2
- package/src/export/pdf.ts +7 -4
- package/src/export/plan.ts +14 -10
- package/src/index.ts +1 -1
- package/src/model/demo.ts +2 -1
- package/src/model/elevation.ts +4 -4
- package/src/model/history.ts +4 -1
- package/src/model/links.ts +8 -2
- package/src/model/measurement.ts +3 -3
- package/src/model/openings.ts +18 -0
- package/src/model/planGeom.ts +70 -10
- package/src/model/project.ts +6 -2
- package/src/model/rooms.ts +151 -63
- package/src/model/scale.ts +105 -0
- package/src/model/settings.ts +1 -2
- package/src/model/sketch.ts +48 -4
- package/src/model/stroke.ts +2 -2
- package/src/model/types.ts +38 -7
- package/src/react/BottomBar.tsx +114 -29
- package/src/react/Drawer.tsx +14 -10
- package/src/react/Duck.tsx +3 -3
- package/src/react/KeypadSheet.tsx +2 -2
- package/src/react/MarkupPanel.tsx +1 -1
- package/src/react/PlanCanvas.native.tsx +60 -6
- package/src/react/Popovers.tsx +24 -9
- package/src/react/Rail.tsx +1 -1
- package/src/react/Sheet.tsx +3 -3
- package/src/react/barScroll.ts +57 -0
- package/src/react/corners.ts +6 -3
- package/src/react/host.ts +14 -1
- package/src/react/motion.tsx +6 -6
- package/src/render/draw.ts +156 -116
- package/src/render/elevation.ts +5 -4
- package/src/render/figmaIcons.ts +17 -1
- package/src/render/hit.ts +21 -4
- package/src/render/icons.ts +27 -20
- package/src/render/lens.ts +52 -0
- package/src/render/linkTile.ts +436 -190
- package/src/render/snap.ts +7 -2
- package/src/render/svgPath.ts +95 -0
- package/src/render/tileIcons.ts +75 -0
- package/src/render/view.ts +37 -5
- package/src/skia/SkiaDrawCtx.ts +26 -4
- package/src/solver/equations.ts +22 -6
- package/src/solver/gauss-newton.ts +4 -1
- package/src/styles.css +3 -2
- package/src/tools/annotate.ts +1 -18
- package/src/tools/chamfer.ts +3 -0
- package/src/tools/dim.ts +26 -52
- package/src/tools/fillet.ts +3 -0
- package/src/tools/freehand.ts +1 -3
- package/src/tools/line.ts +12 -11
- package/src/tools/modify.ts +5 -1
- package/src/tools/registry.ts +10 -1
- package/src/tools/select.ts +99 -18
- package/src/tools/shapes.ts +9 -4
- package/src/tools/survey.ts +21 -0
- package/src/ui/ctx.ts +4 -3
- package/src/ui/drawer.ts +8 -2
- package/src/view3d/build.ts +11 -10
package/dist/render/draw.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ed, isSel } from '../app/state';
|
|
2
2
|
import { consPoints, curveDefined, isDim, lineDefined, measure } from '../model/constraints';
|
|
3
3
|
import { hyp, norm2, normAng, projT } from '../model/geom';
|
|
4
|
-
import { drivingDim, edgePoint, measureOpeningDim, refPoint, refS, widthEntered } from '../model/openings';
|
|
5
|
-
import { arcAngles, curveFrame, dimEnds, dimRadius, edgeOf, gridSteps, OPENING_TICK_EXT, openingFrame, outsideSide, wallThick } from '../model/planGeom';
|
|
4
|
+
import { drivingDim, edgePoint, hingeEdge, measureOpeningDim, refPoint, refS, widthEntered } from '../model/openings';
|
|
5
|
+
import { angleCorner, angleLabel, arcAngles, curveFrame, dimEnds, dimRadius, edgeOf, gridSteps, OPENING_TICK_EXT, openingFrame, outsideSide, wallThick } from '../model/planGeom';
|
|
6
6
|
import { faceCorner } from '../model/wallfaces';
|
|
7
7
|
import { roomGeom } from '../model/rooms';
|
|
8
8
|
import { wallPieces } from '../model/wallshape';
|
|
@@ -15,12 +15,14 @@ import { cabPoints } from '../model/faces';
|
|
|
15
15
|
import { drawKeyPlan, drawWallBackdrop, drawWallChips, drawWallSelection } from './elevation';
|
|
16
16
|
import { fmtAng, fmtArea, fmtLen } from '../units';
|
|
17
17
|
import { FONT, TH } from './theme';
|
|
18
|
-
import { cvs, imgCache, keyPlanSize, mainT, nextThumbFrame, noteFont, noteHandles, noteTextBox, S, sketchBounds, underlayH, underlayHandles, underlayMid } from './view';
|
|
18
|
+
import { cvs, imageLinkBadge, imgCache, keyPlanSize, mainT, nextThumbFrame, noteFont, noteHandles, noteTextBox, S, sketchBounds, underlayH, underlayHandles, underlayMid, underlaySrc } from './view';
|
|
19
19
|
import { dashFor, isSegment, NOTE_TEXT_SIZE, noteLook, shapeOutline } from '../model/markup';
|
|
20
20
|
import { strokeMarkup, strokeOutline } from './markup';
|
|
21
21
|
import { drawLink } from './linkTile';
|
|
22
22
|
import { isLink, linkInfoOf } from '../model/links';
|
|
23
23
|
import { smoothRectPath } from './squircle';
|
|
24
|
+
import { LINK_SVG } from './figmaIcons';
|
|
25
|
+
import { drawSvgIcon, svgIcon } from './svgPath';
|
|
24
26
|
/** Tap targets registered while drawPlan() paints (null outside it: thumbnails and the elevation register none). */
|
|
25
27
|
let hits = null;
|
|
26
28
|
const addHit = (h) => { if (hits)
|
|
@@ -39,26 +41,29 @@ export function linkBlue() {
|
|
|
39
41
|
const dark = !!m && (parseInt(m[1], 16) * 299 + parseInt(m[2], 16) * 587 + parseInt(m[3], 16) * 114) / 1000 < 128;
|
|
40
42
|
return dark ? TH.lblue : TH.blue;
|
|
41
43
|
}
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
c
|
|
47
|
-
c.strokeStyle = color;
|
|
48
|
-
c.lineWidth = 1.4;
|
|
49
|
-
c.beginPath();
|
|
50
|
-
c.roundRect(-6.5, -2.25, 7.5, 4.5, 2.25);
|
|
51
|
-
c.roundRect(-1, -2.25, 7.5, 4.5, 2.25);
|
|
52
|
-
c.stroke();
|
|
53
|
-
c.restore();
|
|
44
|
+
/** Figma's link icon (render/figmaIcons.ts), read once. */
|
|
45
|
+
const LINK_ICON = svgIcon(LINK_SVG);
|
|
46
|
+
/** The link icon, `size` across, centred on (x, y): in its own dark grey, or `color`. */
|
|
47
|
+
export function linkIcon(c, x, y, size, color) {
|
|
48
|
+
drawSvgIcon(c, LINK_ICON, 'link', x - size / 2, y - size / 2, size, color);
|
|
54
49
|
}
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
/**
|
|
51
|
+
* A linked measurement's badge, as the frame draws it on its 30 px chip (Figma 2795:77149): 5 in from the chip's edges,
|
|
52
|
+
* 20 across with the 12 px link icon in its middle, 10 before the value, and the value 5 from the chip's end. A linked
|
|
53
|
+
* chip is the size of a plain one (the user's call, 2026-10-25: "the same size as the regular measurement tiles"), so
|
|
54
|
+
* the badge is drawn at the chip's own height: all of it scaled by h / 30.
|
|
55
|
+
*/
|
|
56
|
+
const LINKED = { h: 30, pad: 5, badge: 20, badgeR: 3.826, icon: 12, gap: 10 };
|
|
57
|
+
/** The width and height chip() draws `text` at (and its font, set on `c`). */
|
|
58
|
+
export function chipSize(c, text, { font = '600 12px', pad = 7, h = 22, minW = 0, mark }) {
|
|
59
59
|
c.font = font + ' ' + FONT;
|
|
60
|
-
const
|
|
61
|
-
|
|
60
|
+
const room = mark ? (LINKED.pad * 2 + LINKED.badge + LINKED.gap) * (h / LINKED.h) : pad * 2;
|
|
61
|
+
return { w: Math.max(minW, c.measureText(text).width + room), h };
|
|
62
|
+
}
|
|
63
|
+
/** Rounded label on the canvas; registers a hit region when `kind` is given. */
|
|
64
|
+
export function chip(c, text, cx, cy, opts) {
|
|
65
|
+
const { bg, fg, border, kind, id, rot = 0, mark } = opts;
|
|
66
|
+
const { w, h } = chipSize(c, text, opts), x = cx - w / 2, y = cy - h / 2;
|
|
62
67
|
c.save();
|
|
63
68
|
if (rot) {
|
|
64
69
|
c.translate(cx, cy);
|
|
@@ -76,9 +81,16 @@ export function chip(c, text, cx, cy, { bg, fg, border, font = '600 12px', pad =
|
|
|
76
81
|
c.fillStyle = fg;
|
|
77
82
|
c.textAlign = 'center';
|
|
78
83
|
c.textBaseline = 'middle';
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
if (mark) {
|
|
85
|
+
const k = h / LINKED.h, inset = LINKED.pad * k, bw = LINKED.badge * k, bx = x + inset, tx = bx + bw + LINKED.gap * k;
|
|
86
|
+
c.fillText(text, (tx + x + w - inset) / 2, cy + 0.5);
|
|
87
|
+
rr(c, bx, cy - bw / 2, bw, bw, LINKED.badgeR * k);
|
|
88
|
+
c.fillStyle = '#FFFFFF';
|
|
89
|
+
c.fill();
|
|
90
|
+
linkIcon(c, bx + bw / 2, cy, LINKED.icon * k);
|
|
91
|
+
}
|
|
92
|
+
else
|
|
93
|
+
c.fillText(text, cx, cy + 0.5);
|
|
82
94
|
c.restore();
|
|
83
95
|
if (kind) {
|
|
84
96
|
const ext = rot ? Math.max(w, h) / 2 : 0;
|
|
@@ -118,8 +130,9 @@ function drawUnderlay(c, T) {
|
|
|
118
130
|
if (!settings.layers.underlay)
|
|
119
131
|
return;
|
|
120
132
|
for (const u of page().underlays) {
|
|
121
|
-
const im = imgCache(u.
|
|
122
|
-
|
|
133
|
+
const im = imgCache(underlaySrc(u)), ready = !!im && im.complete && !!im.naturalWidth;
|
|
134
|
+
// (an expanded photo whose picture hasn't come yet, or is gone: where it is, as its tile's card)
|
|
135
|
+
if (!ready && !u.link)
|
|
123
136
|
continue;
|
|
124
137
|
// drawn about its middle, turned as it's set (clockwise as seen: the canvas turns that way)
|
|
125
138
|
const h = underlayH(u), m = underlayMid(u), [x, y] = S(T, m.x, m.y), w = u.w * T.s, hh = h * T.s;
|
|
@@ -128,7 +141,48 @@ function drawUnderlay(c, T) {
|
|
|
128
141
|
c.translate(x, y);
|
|
129
142
|
if (u.rot)
|
|
130
143
|
c.rotate((u.rot * Math.PI) / 180);
|
|
131
|
-
|
|
144
|
+
if (ready)
|
|
145
|
+
c.drawImage(im, -w / 2, -hh / 2, w, hh);
|
|
146
|
+
else {
|
|
147
|
+
c.fillStyle = '#2B2C2E';
|
|
148
|
+
c.fillRect(-w / 2, -hh / 2, w, hh);
|
|
149
|
+
if (linkInfoOf(u.link)?.exists === false) {
|
|
150
|
+
c.font = '500 13px ' + FONT;
|
|
151
|
+
c.fillStyle = '#9FA0A2';
|
|
152
|
+
c.textAlign = 'center';
|
|
153
|
+
c.textBaseline = 'middle';
|
|
154
|
+
c.fillText('Removed', 0, 0);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
c.restore();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Each expanded photo's badge: its link icon in a white disc in its top-right corner (imageLinkBadge), over the drawing
|
|
162
|
+
* — always, as Skia's, selected or not, locked or not: it says the photo is the job's, and a tap on it opens it.
|
|
163
|
+
*/
|
|
164
|
+
function drawImageLinks(c, T) {
|
|
165
|
+
if (!settings.layers.underlay)
|
|
166
|
+
return;
|
|
167
|
+
const { W, H } = cvs;
|
|
168
|
+
for (const u of page().underlays) {
|
|
169
|
+
const b = imageLinkBadge(T, u);
|
|
170
|
+
if (!b || b.x < -b.r || b.y < -b.r || b.x > W + b.r || b.y > H + b.r)
|
|
171
|
+
continue;
|
|
172
|
+
const r = b.r, disc = (cc, X, Y) => { cc.beginPath(); cc.arc(X + r, Y + r, r, 0, Math.PI * 2); };
|
|
173
|
+
c.save();
|
|
174
|
+
if (ed.mode === 'draft')
|
|
175
|
+
c.globalAlpha = 0.75;
|
|
176
|
+
if (c.shape)
|
|
177
|
+
c.shape('image link ' + r, b.x - r, b.y - r, disc);
|
|
178
|
+
else
|
|
179
|
+
disc(c, b.x - r, b.y - r);
|
|
180
|
+
c.fillStyle = '#FFFFFF';
|
|
181
|
+
c.fill();
|
|
182
|
+
c.lineWidth = 1;
|
|
183
|
+
c.strokeStyle = 'rgba(24,26,28,.2)';
|
|
184
|
+
c.stroke();
|
|
185
|
+
linkIcon(c, b.x, b.y, r * 1.2, '#181A1C');
|
|
132
186
|
c.restore();
|
|
133
187
|
}
|
|
134
188
|
}
|
|
@@ -147,20 +201,49 @@ function drawRooms(c, T, sk, thumb) {
|
|
|
147
201
|
if (thumb)
|
|
148
202
|
continue;
|
|
149
203
|
const [cx, cy] = S(T, g.c.x, g.c.y);
|
|
204
|
+
// (its area and perimeter once the drawing has its scale: before, only placeholders — just its name)
|
|
205
|
+
const nm = r.name, info = sk.unscaled ? '' : fmtArea(g.area) + ' · ' + fmtLen(g.per) + ' perim.';
|
|
206
|
+
c.font = '600 14px ' + FONT;
|
|
207
|
+
const nw = c.measureText(nm).width;
|
|
208
|
+
c.font = '500 12px ' + FONT;
|
|
209
|
+
const iw = info ? c.measureText(info).width : 0;
|
|
210
|
+
const show = spaceLabel(T, g.inner, nw, iw);
|
|
211
|
+
if (!show.name)
|
|
212
|
+
continue;
|
|
150
213
|
c.textAlign = 'center';
|
|
151
214
|
c.textBaseline = 'middle';
|
|
152
215
|
c.fillStyle = TH.label;
|
|
153
216
|
c.font = '600 14px ' + FONT;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const w = Math.max(
|
|
217
|
+
c.fillText(nm, cx, show.info ? cy - 9 : cy);
|
|
218
|
+
if (show.info) {
|
|
219
|
+
c.font = '500 12px ' + FONT;
|
|
220
|
+
c.fillStyle = TH.ink2;
|
|
221
|
+
c.fillText(info, cx, cy + 9);
|
|
222
|
+
}
|
|
223
|
+
const w = Math.max(nw, 140);
|
|
161
224
|
addHit({ kind: 'room', id, x: cx - w / 2, y: cy - 20, w, h: 40 });
|
|
162
225
|
}
|
|
163
226
|
}
|
|
227
|
+
/** Room left round a space's label on the screen, each side, points. */
|
|
228
|
+
const SPACE_LABEL_PAD = 8;
|
|
229
|
+
/**
|
|
230
|
+
* Which of a space's label shows: only what fits inside the space on the screen, so zoomed out it goes rather than
|
|
231
|
+
* cluttering the drawing (the user's call, 2026-10-29, as a tile's name goes: LINK_FULL_PX) — its area and perimeter
|
|
232
|
+
* first, then its name. `nameW`, `infoW`: their widths (no area line: 0).
|
|
233
|
+
*/
|
|
234
|
+
export function spaceLabel(T, inner, nameW, infoW) {
|
|
235
|
+
let x0 = Infinity, x1 = -Infinity, y0 = Infinity, y1 = -Infinity;
|
|
236
|
+
for (const p of inner) {
|
|
237
|
+
x0 = Math.min(x0, p.x);
|
|
238
|
+
x1 = Math.max(x1, p.x);
|
|
239
|
+
y0 = Math.min(y0, p.y);
|
|
240
|
+
y1 = Math.max(y1, p.y);
|
|
241
|
+
}
|
|
242
|
+
const w = (x1 - x0) * T.s, h = (y1 - y0) * T.s, pad = 2 * SPACE_LABEL_PAD;
|
|
243
|
+
// (one line of 14 pt; two, 18 apart, of 14 and 12)
|
|
244
|
+
const name = w >= nameW + pad && h >= 18 + pad;
|
|
245
|
+
return { name, info: name && infoW > 0 && w >= infoW + pad && h >= 36 + pad };
|
|
246
|
+
}
|
|
164
247
|
function curveWalls(sk) {
|
|
165
248
|
const out = [];
|
|
166
249
|
const show = (constr) => !(constr && !settings.layers.construction);
|
|
@@ -443,14 +526,16 @@ function drawOpenings(c, T, sk) {
|
|
|
443
526
|
c.stroke();
|
|
444
527
|
}
|
|
445
528
|
else {
|
|
446
|
-
|
|
529
|
+
// the leaf, open square to the wall from the jamb it hangs on, and its swing back to the other
|
|
530
|
+
const [hs, ls] = hingeEdge(o) === 's1' ? [s1, s0] : [s0, s1];
|
|
531
|
+
const hinge = P(hs, (f * t) / 2), leaf = P(hs, f * (t / 2 + w));
|
|
447
532
|
c.beginPath();
|
|
448
533
|
c.moveTo(hinge[0], hinge[1]);
|
|
449
534
|
c.lineTo(leaf[0], leaf[1]);
|
|
450
535
|
c.stroke();
|
|
451
536
|
const [hx, hy] = hinge, r = w * T.s;
|
|
452
537
|
const a0 = Math.atan2(leaf[1] - hy, leaf[0] - hx);
|
|
453
|
-
const end = P(
|
|
538
|
+
const end = P(ls, (f * t) / 2);
|
|
454
539
|
const a1 = Math.atan2(end[1] - hy, end[0] - hx);
|
|
455
540
|
c.beginPath();
|
|
456
541
|
c.setLineDash([4, 3]);
|
|
@@ -578,12 +663,31 @@ function drawLock(c, x, y) {
|
|
|
578
663
|
c.fillRect(x - 3.3, y - 1.2, 6.6, 4.6);
|
|
579
664
|
c.restore();
|
|
580
665
|
}
|
|
666
|
+
/** The selected points and the selected lines' ends: what a constraint's icon still shows for with the icons off. */
|
|
667
|
+
function selPoints(sk) {
|
|
668
|
+
const out = new Set();
|
|
669
|
+
for (const s of ed.sel) {
|
|
670
|
+
if (s.type === 'line') {
|
|
671
|
+
const l = sk.lines[s.id];
|
|
672
|
+
if (l) {
|
|
673
|
+
out.add(l.a);
|
|
674
|
+
out.add(l.b);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (s.type === 'point')
|
|
678
|
+
out.add(s.id);
|
|
679
|
+
}
|
|
680
|
+
return out;
|
|
681
|
+
}
|
|
581
682
|
/** Points: filled = fully defined, hollow = still free (shape cue paired with color). */
|
|
582
683
|
function drawPoints(c, T, sk) {
|
|
583
684
|
const { W, H } = cvs;
|
|
584
685
|
const touch = ed.lastPointerTouch;
|
|
585
686
|
// a cabinet's corners aren't grab points: it moves as one, like a door or window
|
|
586
687
|
const cabCorners = new Set(Object.values(sk.cabs ?? {}).flatMap(cabPoints));
|
|
688
|
+
// a locked point's padlock is a constraint icon: with the icons off, it shows only as the badges do, on what's
|
|
689
|
+
// selected (the user's call, 2026-10-26)
|
|
690
|
+
const locks = settings.showCons ? null : selPoints(sk);
|
|
587
691
|
for (const id in sk.points) {
|
|
588
692
|
const p = sk.points[id];
|
|
589
693
|
const [x, y] = S(T, p.x, p.y);
|
|
@@ -626,14 +730,14 @@ function drawPoints(c, T, sk) {
|
|
|
626
730
|
c.strokeStyle = TH.ink;
|
|
627
731
|
c.stroke();
|
|
628
732
|
}
|
|
629
|
-
if (p.fixed && !p.origin && !p.anchor)
|
|
733
|
+
if (p.fixed && !p.origin && !p.anchor && (!locks || locks.has(id) || ed.highlight.has(id)))
|
|
630
734
|
drawLock(c, x + 9, y - 14);
|
|
631
735
|
}
|
|
632
736
|
}
|
|
633
737
|
function dimAnchor(sk, c) {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
//
|
|
738
|
+
if (c.type === 'dist' || c.type === 'pldist') {
|
|
739
|
+
// (a length measured on a wall's face: from its corner to corner, the label off the face on that side. Between
|
|
740
|
+
// parallel lines or walls: from face to face, slid along them.)
|
|
637
741
|
const e = dimEnds(sk, c);
|
|
638
742
|
if (!e)
|
|
639
743
|
return null;
|
|
@@ -641,29 +745,13 @@ function dimAnchor(sk, c) {
|
|
|
641
745
|
const dx = b.x - a.x, dy = b.y - a.y, L = hyp(dx, dy) || 1e-9, nx = -dy / L, ny = dx / L, off = c.off || 0;
|
|
642
746
|
return { m: { x: (a.x + b.x) / 2 + nx * off, y: (a.y + b.y) / 2 + ny * off }, a, b, nx, ny, L };
|
|
643
747
|
}
|
|
644
|
-
if (c.type === 'pldist') {
|
|
645
|
-
// (between walls' faces: from face to face)
|
|
646
|
-
const e = dimEnds(sk, c);
|
|
647
|
-
if (!e)
|
|
648
|
-
return null;
|
|
649
|
-
return { m: { x: (e.a.x + e.b.x) / 2, y: (e.a.y + e.b.y) / 2 }, a: e.a, b: e.b };
|
|
650
|
-
}
|
|
651
748
|
if (c.type === 'diam') {
|
|
652
749
|
// (across a curved wall's face: its arrows on that face)
|
|
653
750
|
const g = dimRadius(sk, c);
|
|
654
751
|
return g ? { m: { x: g.o.x, y: g.o.y }, o: g.o, r: g.r } : null;
|
|
655
752
|
}
|
|
656
|
-
if (c.type === 'angle')
|
|
657
|
-
|
|
658
|
-
const sh = [l1.a, l1.b].find(p => p === l2.a || p === l2.b);
|
|
659
|
-
if (sh) {
|
|
660
|
-
const s = P(sh), o1 = P(l1.a === sh ? l1.b : l1.a), o2 = P(l2.a === sh ? l2.b : l2.a);
|
|
661
|
-
const u1 = norm2(o1.x - s.x, o1.y - s.y), u2 = norm2(o2.x - s.x, o2.y - s.y);
|
|
662
|
-
return { vtx: s, bis: norm2(u1[0] + u2[0], u1[1] + u2[1]), u1, u2 };
|
|
663
|
-
}
|
|
664
|
-
const a = P(l1.a), b = P(l1.b);
|
|
665
|
-
return { vtx: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 }, bis: [0, 1] };
|
|
666
|
-
}
|
|
753
|
+
if (c.type === 'angle')
|
|
754
|
+
return angleCorner(sk, c);
|
|
667
755
|
return null;
|
|
668
756
|
}
|
|
669
757
|
/** Whether a dimension, or something it measures (its lines, points or curves), is selected or hovered. */
|
|
@@ -683,7 +771,7 @@ function drawDims(c, T, sk) {
|
|
|
683
771
|
return;
|
|
684
772
|
for (const id in sk.cons) {
|
|
685
773
|
const d = sk.cons[id];
|
|
686
|
-
if (!isDim(d) || d.
|
|
774
|
+
if (!isDim(d) || d.elev)
|
|
687
775
|
continue; // the wall view's own dimensions are its chips
|
|
688
776
|
const A = dimAnchor(sk, d);
|
|
689
777
|
if (!A)
|
|
@@ -693,22 +781,22 @@ function drawDims(c, T, sk) {
|
|
|
693
781
|
const bad = ed.highlight.has(id) || ed.ana.bad.has(id);
|
|
694
782
|
if (ref && !bad && !dimLive(sk, id, d))
|
|
695
783
|
continue;
|
|
696
|
-
// a measurement of the job sets it:
|
|
784
|
+
// a measurement of the job sets it: the link badge before its value (chip()), on the chip's own colour — red once
|
|
785
|
+
// the job's measurement is gone
|
|
697
786
|
const linked = !!d.measurementRef && !ref && !bad, gone = linked && linkInfoOf(d.measurementRef)?.exists === false;
|
|
698
787
|
let bg = ref ? TH.ref : TH.blue, fg = ref ? TH.reftext : '#fff';
|
|
699
|
-
if (bad) {
|
|
788
|
+
if (bad || gone) {
|
|
700
789
|
bg = TH.red;
|
|
701
790
|
fg = '#fff';
|
|
702
791
|
}
|
|
703
|
-
|
|
704
|
-
bg = TH.bg;
|
|
705
|
-
fg = gone ? TH.red : d.type === 'angle' ? TH.purple : linkBlue();
|
|
706
|
-
}
|
|
707
|
-
const border = selected ? [TH.yellow, 2.5] : linked ? [fg, 1.5] : null;
|
|
792
|
+
const border = selected ? [TH.yellow, 2.5] : null;
|
|
708
793
|
const mark = linked ? 'link' : undefined;
|
|
709
794
|
const wrap = (s) => (ref ? '(' : '') + s + (ref ? ')' : '');
|
|
710
795
|
if (d.type === 'angle' && 'vtx' in A) {
|
|
711
796
|
const [vx, vy] = S(T, A.vtx.x, A.vtx.y);
|
|
797
|
+
// pulled off its corner: its arc out where the label is, the label riding on it; else a little arc at the
|
|
798
|
+
// corner, the label out along the bisector
|
|
799
|
+
const moved = angleLabel(sk, d), R = moved ? moved.r * T.s : 22;
|
|
712
800
|
if (A.u1 && A.u2) {
|
|
713
801
|
// arc between the two lines, so the angle reads as belonging to that corner
|
|
714
802
|
const t1 = Math.atan2(-A.u1[1], A.u1[0]), t2 = Math.atan2(-A.u2[1], A.u2[0]);
|
|
@@ -717,18 +805,34 @@ function drawDims(c, T, sk) {
|
|
|
717
805
|
sweep -= 2 * Math.PI;
|
|
718
806
|
while (sweep < -Math.PI)
|
|
719
807
|
sweep += 2 * Math.PI;
|
|
808
|
+
// (blue, as every other dimension is — the user's call, 2026-10-29; purple is the inference guides')
|
|
720
809
|
c.save();
|
|
721
|
-
c.strokeStyle = bad ? TH.red : ref ? TH.chipline : TH.
|
|
810
|
+
c.strokeStyle = bad ? TH.red : ref ? TH.chipline : TH.blue;
|
|
722
811
|
c.lineWidth = 1.2;
|
|
723
812
|
if (ref)
|
|
724
813
|
c.setLineDash([3, 3]);
|
|
725
814
|
c.beginPath();
|
|
726
|
-
c.arc(vx, vy,
|
|
815
|
+
c.arc(vx, vy, R, t1, t1 + sweep, sweep < 0);
|
|
727
816
|
c.stroke();
|
|
817
|
+
// (pulled out past where a line ends: an extension line along it, out to the arc)
|
|
818
|
+
c.lineWidth = 1;
|
|
819
|
+
for (const [u, len] of [[A.u1, A.len1], [A.u2, A.len2]]) {
|
|
820
|
+
const from = (len ?? 0) * T.s;
|
|
821
|
+
if (moved && R > from + 2) {
|
|
822
|
+
c.beginPath();
|
|
823
|
+
c.moveTo(vx + u[0] * from, vy - u[1] * from);
|
|
824
|
+
c.lineTo(vx + u[0] * (R + 4), vy - u[1] * (R + 4));
|
|
825
|
+
c.stroke();
|
|
826
|
+
}
|
|
827
|
+
}
|
|
728
828
|
c.restore();
|
|
729
829
|
}
|
|
730
|
-
|
|
731
|
-
|
|
830
|
+
const text = wrap(fmtAng(val)), opts = { bg, fg, border, kind: 'dim', id, mark };
|
|
831
|
+
// (left where it was drawn: 50 px out along the bisector, or as far as its corners stay clear of the corner — a
|
|
832
|
+
// linked chip is wider)
|
|
833
|
+
const sz = chipSize(c, text, opts), out = Math.max(50, Math.hypot(sz.w, sz.h) / 2 + 28);
|
|
834
|
+
const [lx, ly] = moved ? [vx + Math.cos(moved.ang) * R, vy - Math.sin(moved.ang) * R] : [vx + A.bis[0] * out, vy - A.bis[1] * out];
|
|
835
|
+
chip(c, text, lx, ly, opts);
|
|
732
836
|
continue;
|
|
733
837
|
}
|
|
734
838
|
if (d.type === 'diam' && 'o' in A) {
|
|
@@ -739,7 +843,7 @@ function drawDims(c, T, sk) {
|
|
|
739
843
|
continue;
|
|
740
844
|
const [mx, my] = S(T, A.m.x, A.m.y);
|
|
741
845
|
const lineColor = bad ? TH.red : ref ? TH.chipline : TH.blue;
|
|
742
|
-
if (d.type === 'dist' && A.nx != null && Math.abs((d.off || 0) * T.s) > 10) {
|
|
846
|
+
if ((d.type === 'dist' || d.type === 'pldist') && A.nx != null && Math.abs((d.off || 0) * T.s) > 10) {
|
|
743
847
|
drawDimLeaders(c, T, A.a, A.b, A.nx, A.ny, d.off, lineColor, ref);
|
|
744
848
|
}
|
|
745
849
|
else if (d.type === 'pldist' || !d.line) {
|
|
@@ -999,7 +1103,8 @@ export function drawRubberBand(c, T, from, to, snapped) {
|
|
|
999
1103
|
endRing(c, x2, y2, TH.blue);
|
|
1000
1104
|
c.restore();
|
|
1001
1105
|
const L = hyp(to.x - from.x, to.y - from.y);
|
|
1002
|
-
|
|
1106
|
+
// (no distance on a drawing without its scale yet: it's only a placeholder)
|
|
1107
|
+
if (L * T.s > 24 && !planSK().unscaled)
|
|
1003
1108
|
chip(c, fmtLen(L), (x1 + x2) / 2, (y1 + y2) / 2 - 16, { bg: '#fff', fg: TH.blue, border: [TH.blue, 1.5] });
|
|
1004
1109
|
}
|
|
1005
1110
|
/**
|
|
@@ -1047,7 +1152,9 @@ export function drawPendingDim(c, T, p) {
|
|
|
1047
1152
|
}
|
|
1048
1153
|
c.restore();
|
|
1049
1154
|
const [mx, my] = S(T, (p.a.x + p.b.x) / 2 + p.nx * p.off, (p.a.y + p.b.y) / 2 + p.ny * p.off);
|
|
1050
|
-
|
|
1155
|
+
// (no label until one's typed, on a page whose sizes are still placeholders)
|
|
1156
|
+
if (p.label)
|
|
1157
|
+
chip(c, p.label, mx, my - (Math.abs(p.off * T.s) > 1 ? 0 : 16), { bg: TH.blue, fg: '#fff', border: [TH.yellow, 2] });
|
|
1051
1158
|
}
|
|
1052
1159
|
/**
|
|
1053
1160
|
* A linear dimension pulled off its line: extension lines from both ends out to a dimension line with
|
|
@@ -1112,70 +1219,9 @@ function drawDiameter(c, T, o, r, d, text, color, chipOpts, dashed = false) {
|
|
|
1112
1219
|
if (!d.rad)
|
|
1113
1220
|
arrowHead(c, p2, -sx, -sy);
|
|
1114
1221
|
c.restore();
|
|
1115
|
-
|
|
1116
|
-
const w = c.measureText(text).width + 14 + (chipOpts.mark ? MARK_W : 0);
|
|
1222
|
+
const { w } = chipSize(c, text, chipOpts);
|
|
1117
1223
|
chip(c, text, end[0] + side * (w / 2 + 2), end[1], chipOpts);
|
|
1118
1224
|
}
|
|
1119
|
-
/** Architectural dimension strings on the Print dimensions layer (reference-only). */
|
|
1120
|
-
function drawPrintDims(c, T, sk) {
|
|
1121
|
-
if (!settings.layers.print)
|
|
1122
|
-
return;
|
|
1123
|
-
for (const id in sk.cons) {
|
|
1124
|
-
const d = sk.cons[id];
|
|
1125
|
-
if (d.layer !== 'print' || d.type !== 'dist')
|
|
1126
|
-
continue;
|
|
1127
|
-
const a = sk.points[d.a], b = sk.points[d.b];
|
|
1128
|
-
if (!a || !b)
|
|
1129
|
-
continue;
|
|
1130
|
-
const dx = b.x - a.x, dy = b.y - a.y, L = hyp(dx, dy);
|
|
1131
|
-
if (L < 1e-6)
|
|
1132
|
-
continue;
|
|
1133
|
-
const nx = -dy / L, ny = dx / L, off = d.off || 24;
|
|
1134
|
-
const pa = { x: a.x + nx * off, y: a.y + ny * off }, pb = { x: b.x + nx * off, y: b.y + ny * off };
|
|
1135
|
-
const [ax, ay] = S(T, a.x, a.y), [bx, by] = S(T, b.x, b.y), [qax, qay] = S(T, pa.x, pa.y), [qbx, qby] = S(T, pb.x, pb.y);
|
|
1136
|
-
const sgn = Math.sign(off) || 1, ex = nx * sgn * 6, ey = -ny * sgn * 6;
|
|
1137
|
-
const selected = isSel('dim', id);
|
|
1138
|
-
c.strokeStyle = selected ? TH.yellow : TH.ink;
|
|
1139
|
-
c.lineWidth = 1;
|
|
1140
|
-
c.beginPath();
|
|
1141
|
-
const gap = ax - qax || ay - qay ? 4 : 0, ga = norm2(qax - ax, qay - ay);
|
|
1142
|
-
c.moveTo(ax + ga[0] * gap, ay + ga[1] * gap);
|
|
1143
|
-
c.lineTo(qax + ex, qay + ey);
|
|
1144
|
-
c.moveTo(bx + ga[0] * gap, by + ga[1] * gap);
|
|
1145
|
-
c.lineTo(qbx + ex, qby + ey);
|
|
1146
|
-
c.moveTo(qax, qay);
|
|
1147
|
-
c.lineTo(qbx, qby);
|
|
1148
|
-
c.stroke();
|
|
1149
|
-
const u = norm2(qbx - qax, qby - qay);
|
|
1150
|
-
c.lineWidth = 1.8;
|
|
1151
|
-
c.beginPath();
|
|
1152
|
-
for (const [x, y] of [[qax, qay], [qbx, qby]]) {
|
|
1153
|
-
const tx = ((u[0] - u[1]) * 5) / Math.SQRT2, ty = ((u[1] + u[0]) * 5) / Math.SQRT2;
|
|
1154
|
-
c.moveTo(x - tx, y - ty);
|
|
1155
|
-
c.lineTo(x + tx, y + ty);
|
|
1156
|
-
}
|
|
1157
|
-
c.stroke();
|
|
1158
|
-
let ang = Math.atan2(qby - qay, qbx - qax);
|
|
1159
|
-
if (ang > Math.PI / 2)
|
|
1160
|
-
ang -= Math.PI;
|
|
1161
|
-
if (ang < -Math.PI / 2)
|
|
1162
|
-
ang += Math.PI;
|
|
1163
|
-
const mx = (qax + qbx) / 2, my = (qay + qby) / 2, txt = fmtLen(L);
|
|
1164
|
-
c.save();
|
|
1165
|
-
c.translate(mx, my);
|
|
1166
|
-
c.rotate(ang);
|
|
1167
|
-
c.font = '600 12px ' + FONT;
|
|
1168
|
-
const w = c.measureText(txt).width + 8;
|
|
1169
|
-
c.fillStyle = TH.bg;
|
|
1170
|
-
c.fillRect(-w / 2, -17, w, 14);
|
|
1171
|
-
c.fillStyle = selected ? TH.yellow : TH.ink;
|
|
1172
|
-
c.textAlign = 'center';
|
|
1173
|
-
c.textBaseline = 'alphabetic';
|
|
1174
|
-
c.fillText(txt, 0, -6);
|
|
1175
|
-
c.restore();
|
|
1176
|
-
addHit({ kind: 'pdim', id, x: mx - w / 2 - 4, y: my - 18, w: w + 8, h: 24 });
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
1225
|
/**
|
|
1180
1226
|
* A badge's symbol drawn as lines rather than a character: ∥ ⊥ ∘ ◎ aren't in every typeface — on a device the
|
|
1181
1227
|
* app's own (Inter) lacks them and Skia has nothing to fall back on, so they came out as the font's "missing glyph"
|
|
@@ -1275,18 +1321,7 @@ function badgeSpots(T, sk, c) {
|
|
|
1275
1321
|
}
|
|
1276
1322
|
function drawBadges(c, T, sk) {
|
|
1277
1323
|
const { W, H } = cvs;
|
|
1278
|
-
const selIds = new Set(ed.sel.map(s => s.id)), selPts =
|
|
1279
|
-
for (const s of ed.sel) {
|
|
1280
|
-
if (s.type === 'line') {
|
|
1281
|
-
const l = sk.lines[s.id];
|
|
1282
|
-
if (l) {
|
|
1283
|
-
selPts.add(l.a);
|
|
1284
|
-
selPts.add(l.b);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
if (s.type === 'point')
|
|
1288
|
-
selPts.add(s.id);
|
|
1289
|
-
}
|
|
1324
|
+
const selIds = new Set(ed.sel.map(s => s.id)), selPts = selPoints(sk);
|
|
1290
1325
|
for (const id in sk.cons) {
|
|
1291
1326
|
const k = sk.cons[id];
|
|
1292
1327
|
if (isDim(k) || k.elev)
|
|
@@ -1633,7 +1668,6 @@ function paintPlanView(ctx, sk, m, under = true) {
|
|
|
1633
1668
|
drawOpenings(ctx, T, sk);
|
|
1634
1669
|
drawLines(ctx, T, sk);
|
|
1635
1670
|
drawCurves(ctx, T, sk);
|
|
1636
|
-
drawPrintDims(ctx, T, sk);
|
|
1637
1671
|
if (ed.mode === 'draft')
|
|
1638
1672
|
drawBadges(ctx, T, sk);
|
|
1639
1673
|
// (the drawing's points only in Draft: Annotate can't move them, and shouldn't look as if it could — the user's
|
|
@@ -1643,6 +1677,8 @@ function paintPlanView(ctx, sk, m, under = true) {
|
|
|
1643
1677
|
drawOpeningAnchors(ctx, T, sk);
|
|
1644
1678
|
drawDims(ctx, T, sk);
|
|
1645
1679
|
drawOpeningDims(ctx, T, sk);
|
|
1680
|
+
// (an expanded photo's badge over the drawing, under the markup: as it's tapped)
|
|
1681
|
+
drawImageLinks(ctx, T);
|
|
1646
1682
|
drawNotes(ctx, T, sk);
|
|
1647
1683
|
drawNoteSelection(ctx, T);
|
|
1648
1684
|
}
|
|
@@ -1665,7 +1701,6 @@ function paintWall(ctx, W, fixed) {
|
|
|
1665
1701
|
drawCurves(ctx, T, sk);
|
|
1666
1702
|
// (over the edges — its own and its neighbours' — so a selected cabinet's outline shows all the way round)
|
|
1667
1703
|
drawWallSelection(ctx, T, plan, f, sk);
|
|
1668
|
-
drawPrintDims(ctx, T, sk);
|
|
1669
1704
|
drawBadges(ctx, T, sk);
|
|
1670
1705
|
if (ed.mode === 'draft')
|
|
1671
1706
|
drawPoints(ctx, T, sk);
|