@things-factory/figure-ui 10.1.265 → 10.1.266
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/client/modeller/align.ts +13 -1
- package/client/modeller/clips.ts +90 -1
- package/client/modeller/editor-styles.ts +36 -0
- package/client/modeller/editor.ts +53 -6
- package/client/modeller/figure-clips.ts +82 -34
- package/client/modeller/joint-drag.ts +32 -2
- package/dist-client/modeller/align.d.ts +5 -0
- package/dist-client/modeller/align.js +10 -1
- package/dist-client/modeller/align.js.map +1 -1
- package/dist-client/modeller/clips.d.ts +56 -4
- package/dist-client/modeller/clips.js +89 -0
- package/dist-client/modeller/clips.js.map +1 -1
- package/dist-client/modeller/editor-styles.js +36 -0
- package/dist-client/modeller/editor-styles.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +7 -0
- package/dist-client/modeller/editor.js +58 -5
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-clips.d.ts +13 -1
- package/dist-client/modeller/figure-clips.js +87 -34
- package/dist-client/modeller/figure-clips.js.map +1 -1
- package/dist-client/modeller/joint-drag.d.ts +21 -2
- package/dist-client/modeller/joint-drag.js +20 -1
- package/dist-client/modeller/joint-drag.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/test/align.test.ts +18 -0
- package/test/clips.test.ts +83 -0
- package/test/joint-drag.test.ts +49 -0
- package/test/joint-frames.test.ts +3 -2
- package/translations/en.json +22 -2
- package/translations/es.json +22 -2
- package/translations/ja.json +22 -2
- package/translations/ko.json +22 -2
- package/translations/ms.json +22 -2
- package/translations/zh.json +22 -2
|
@@ -43,7 +43,7 @@ import { groupFields, ownerOf, partLabelOf, repeatOf } from './fields.js';
|
|
|
43
43
|
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js';
|
|
44
44
|
import { EditorStyles } from './editor-styles.js';
|
|
45
45
|
import { ScrollbarStyles } from '@operato/styles';
|
|
46
|
-
import { alignChanges, canMirror, mirrorEditOf, mirrorPlanOf } from './align.js';
|
|
46
|
+
import { alignChanges, canMirror, mirrorEditOf, mirroredClipsOf, mirrorPlanOf } from './align.js';
|
|
47
47
|
import { paletteRecipe } from './palette.js';
|
|
48
48
|
import { meshChoicesOf, meshPartOf } from './mesh-import.js';
|
|
49
49
|
import './figure-mesh-choice.js';
|
|
@@ -60,7 +60,7 @@ import { sizeInputOf } from './size-response.js';
|
|
|
60
60
|
import { canFollow, followableAxes, endPlaceKeyOf, followOf, sizeFollowersOf, measureNow, partSummaryOf, instanceRangeOf, instanceSizeToDeclare, proportionToFollow, rangeWith, turnsAboutAJoint, valueNow } from './links.js';
|
|
61
61
|
import { jointFanOf } from './joint-fan.js';
|
|
62
62
|
import { derivedOf } from './revision.js';
|
|
63
|
-
import { jointDragOf } from './joint-drag.js';
|
|
63
|
+
import { jointDragOf, jointHandleOf } from './joint-drag.js';
|
|
64
64
|
import { liveOverSession, NOTHING_LIVE, scrubLabel } from './live.js';
|
|
65
65
|
import { startingShapeKindOfBody } from './starting-shape.js';
|
|
66
66
|
import { GroupMenuStyles } from './group-menu.js';
|
|
@@ -108,6 +108,8 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
108
108
|
this.moreOpen = FigureEditor_1.storedMoreOpen();
|
|
109
109
|
/** What the middle shows: the parts being edited, or the figure placed on a board at eight sizes. */
|
|
110
110
|
this.middle = 'edit';
|
|
111
|
+
/** 「관절 위치 편집」: while on, a drag on a part that hangs from a joint that moves moves where the joint sits, not its pose. Off on each new selection. */
|
|
112
|
+
this.jointPlacing = false;
|
|
111
113
|
/** A line saying what a command did besides what was asked; gone at the next command. */
|
|
112
114
|
this.notice = '';
|
|
113
115
|
/**
|
|
@@ -296,8 +298,10 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
296
298
|
}
|
|
297
299
|
if (view && !view.geometry.some(g => ownerOf(g.id) === this.selected))
|
|
298
300
|
this.selected = '';
|
|
299
|
-
if (_changed.has('selected'))
|
|
301
|
+
if (_changed.has('selected')) {
|
|
300
302
|
this.gizmoMode = undefined;
|
|
303
|
+
this.jointPlacing = false;
|
|
304
|
+
}
|
|
301
305
|
/* The window is about the part chosen on the properties tab, being edited: it does not follow anywhere else. */
|
|
302
306
|
if (this.fastening && (_changed.has('selected') || !this.selected || this.tab !== 'properties' || this.middle !== 'edit'))
|
|
303
307
|
this.closeFastening();
|
|
@@ -328,6 +332,30 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
328
332
|
this.selected = next;
|
|
329
333
|
});
|
|
330
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* On a part that hangs from a joint that moves, what a drag does, before it is dragged (review 2026-11-09): the handle
|
|
337
|
+
* that poses it, or why none does and where it is moved from -- and 「관절 위치 편집」 to move where the joint sits.
|
|
338
|
+
*/
|
|
339
|
+
renderJointHandle(unavailable) {
|
|
340
|
+
const asset = this.asset();
|
|
341
|
+
if (unavailable || this.gizmoMode === 'scale' || !this.selected || !asset)
|
|
342
|
+
return nothing;
|
|
343
|
+
const handle = jointHandleOf(asset, this.selected);
|
|
344
|
+
if (!handle)
|
|
345
|
+
return nothing;
|
|
346
|
+
if (this.jointPlacing)
|
|
347
|
+
return html `<p joint-handle role="status">${i18next.t('figure.text.joint-placing', { joint: handle.joint })}
|
|
348
|
+
<button act @click=${() => (this.jointPlacing = false)}>${i18next.t('figure.button.joint-place-off')}</button></p>`;
|
|
349
|
+
const said = handle.kind === 'mimic'
|
|
350
|
+
? i18next.t('figure.text.gizmo-joint-mimic', { joint: handle.joint, leader: handle.leader })
|
|
351
|
+
: handle.kind === 'several-axes'
|
|
352
|
+
? i18next.t('figure.text.gizmo-joint-several-axes', { joint: handle.joint })
|
|
353
|
+
: i18next.t(`figure.text.joint-handle-${handle.kind}`, { joint: handle.joint });
|
|
354
|
+
const leaderPart = handle.kind === 'mimic' ? handle.leaderPart : undefined;
|
|
355
|
+
return html `<p joint-handle role="status">${said}
|
|
356
|
+
${leaderPart ? html `<button act @click=${() => this.choose(leaderPart)}>${i18next.t('figure.button.select-leader', { leader: handle.leader })}</button>` : nothing}
|
|
357
|
+
<button act @click=${() => (this.jointPlacing = true)}>${i18next.t('figure.button.joint-place-on')}</button></p>`;
|
|
358
|
+
}
|
|
331
359
|
/** While the size tool is on a round part: which of its handles change the one diameter (ADR-0140 4.1). */
|
|
332
360
|
renderSameMeasure(unavailable) {
|
|
333
361
|
if (unavailable || this.gizmoMode !== 'scale' || !this.selected)
|
|
@@ -697,12 +725,31 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
697
725
|
const shown = this.shown();
|
|
698
726
|
const asset = shown.asset;
|
|
699
727
|
const drawn = view.geometry.find(g => g.id === id);
|
|
700
|
-
const drag = drawn ? jointDragOf(asset, ownerOf(id), drawn, result, shown.inputs) : null;
|
|
728
|
+
const drag = drawn ? jointDragOf(asset, ownerOf(id), drawn, result, shown.inputs, { place: this.jointPlacing }) : null;
|
|
701
729
|
if (drag) {
|
|
702
730
|
if (drag.kind === 'value')
|
|
703
731
|
this.run(() => this.session.apply([{ kind: 'set-state', input: drag.input, unit: drag.unit, value: drag.value }]));
|
|
704
732
|
else if (drag.kind === 'joint')
|
|
705
733
|
this.run(() => this.session.command({ kind: 'set-joint', joint: drag.joint }));
|
|
734
|
+
else if (drag.reason === 'place-off') {
|
|
735
|
+
/* A pose drag that would have moved the joint: nothing is written, and the way to move it is offered. */
|
|
736
|
+
this.refusals.point(i18next.t('figure.text.gizmo-joint-place-off', { joint: drag.joint }), {
|
|
737
|
+
label: i18next.t('figure.button.joint-place-on'),
|
|
738
|
+
run: () => (this.jointPlacing = true)
|
|
739
|
+
});
|
|
740
|
+
this.requestUpdate();
|
|
741
|
+
}
|
|
742
|
+
else if (drag.reason === 'mimic') {
|
|
743
|
+
/* A joint that follows another: the one it follows is a click away. */
|
|
744
|
+
const leader = jointHandleOf(asset, ownerOf(id));
|
|
745
|
+
const leaderPart = leader?.kind === 'mimic' ? leader.leaderPart : undefined;
|
|
746
|
+
const message = i18next.t('figure.text.gizmo-joint-mimic', { joint: drag.joint, leader: drag.leader ?? '' });
|
|
747
|
+
if (leaderPart)
|
|
748
|
+
this.refusals.point(message, { label: i18next.t('figure.button.select-leader', { leader: drag.leader ?? '' }), run: () => this.choose(leaderPart) });
|
|
749
|
+
else
|
|
750
|
+
this.refusals.say(message);
|
|
751
|
+
this.requestUpdate();
|
|
752
|
+
}
|
|
706
753
|
else {
|
|
707
754
|
this.error = i18next.t(`figure.text.gizmo-joint-${drag.reason}`, { joint: drag.joint, leader: drag.leader ?? '', axis: drag.axis ?? '' });
|
|
708
755
|
this.requestUpdate();
|
|
@@ -825,6 +872,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
825
872
|
${i18next.t('figure.label.mirror-keep-motion')}
|
|
826
873
|
</label>`
|
|
827
874
|
: nothing}
|
|
875
|
+
${(clips => (clips.length ? html `<p hint mirror-clips>${i18next.t('figure.text.mirror-copies-clips', { clips: clips.join(', ') })}</p>` : nothing))(mirroredClipsOf(this.shown().asset, m.part, m.form.chain))}
|
|
828
876
|
<div pair>
|
|
829
877
|
<button act ?disabled=${unavailable} @click=${() => this.mirrorWith(m.part, m.form)}>${i18next.t('figure.button.mirror-' + m.form.axis)}</button>
|
|
830
878
|
<button act @click=${() => (this.mirroring = undefined)}>${i18next.t('figure.button.cancel')}</button>
|
|
@@ -1122,6 +1170,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1122
1170
|
@states=${(e) => this.run(() => this.session.apply(e.detail.changes))}
|
|
1123
1171
|
@states-live=${(e) => this.hold(e.detail.values)}
|
|
1124
1172
|
@part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
1173
|
+
@part-edits=${(e) => this.run(() => this.session.applyRecipe(e.detail.edits))}
|
|
1125
1174
|
></figure-clips>`;
|
|
1126
1175
|
}
|
|
1127
1176
|
/** One command, one step of the history. A refusal a person can meet here is said in their words. */
|
|
@@ -2096,7 +2145,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
2096
2145
|
@render-error=${(e) => {
|
|
2097
2146
|
this.error = e.detail.message;
|
|
2098
2147
|
}}
|
|
2099
|
-
></figure-canvas>${this.renderSameMeasure(unavailable)}</div>
|
|
2148
|
+
></figure-canvas>${this.renderSameMeasure(unavailable)}${this.renderJointHandle(unavailable)}</div>
|
|
2100
2149
|
<aside slot="end">
|
|
2101
2150
|
<div tabs>
|
|
2102
2151
|
${this.renderTab('properties', 'tune', i18next.t('figure.label.properties'))}
|
|
@@ -2399,6 +2448,10 @@ __decorate([
|
|
|
2399
2448
|
state(),
|
|
2400
2449
|
__metadata("design:type", String)
|
|
2401
2450
|
], FigureEditor.prototype, "gizmoMode", void 0);
|
|
2451
|
+
__decorate([
|
|
2452
|
+
state(),
|
|
2453
|
+
__metadata("design:type", Object)
|
|
2454
|
+
], FigureEditor.prototype, "jointPlacing", void 0);
|
|
2402
2455
|
__decorate([
|
|
2403
2456
|
state(),
|
|
2404
2457
|
__metadata("design:type", Object)
|