@things-factory/figure-ui 10.1.271 → 10.1.273
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/canvas.ts +4 -2
- package/client/modeller/clips.ts +74 -4
- package/client/modeller/data-interface.ts +30 -18
- package/client/modeller/editor-styles.ts +17 -6
- package/client/modeller/editor.ts +2 -0
- package/client/modeller/fasten-form.ts +81 -6
- package/client/modeller/fasten-geometry.ts +5 -3
- package/client/modeller/figure-cavity-drawing.ts +1 -3
- package/client/modeller/figure-clips.ts +101 -8
- package/client/modeller/figure-data-panel.ts +384 -200
- package/client/modeller/figure-fasten-dialog.ts +41 -30
- package/client/modeller/figure-fasten-drawing.ts +24 -14
- package/client/modeller/figure-first-save.ts +4 -3
- package/client/modeller/figure-links.ts +109 -37
- package/client/modeller/figure-parts.ts +7 -11
- package/client/modeller/figure-preview.ts +299 -79
- package/client/modeller/figure-size-editor.ts +7 -2
- package/client/modeller/first-save.ts +8 -0
- package/client/modeller/focus-on-render.ts +4 -0
- package/client/modeller/pivot.ts +76 -0
- package/client/modeller/size-response.ts +14 -0
- package/client/modeller/stage-model.ts +50 -6
- package/dist-client/modeller/canvas.d.ts +1 -0
- package/dist-client/modeller/canvas.js +3 -2
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/clips.d.ts +17 -3
- package/dist-client/modeller/clips.js +69 -4
- package/dist-client/modeller/clips.js.map +1 -1
- package/dist-client/modeller/data-interface.d.ts +11 -8
- package/dist-client/modeller/data-interface.js +27 -17
- package/dist-client/modeller/data-interface.js.map +1 -1
- package/dist-client/modeller/editor-styles.js +17 -6
- package/dist-client/modeller/editor-styles.js.map +1 -1
- package/dist-client/modeller/editor.js +2 -0
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/fasten-form.d.ts +13 -0
- package/dist-client/modeller/fasten-form.js +72 -7
- package/dist-client/modeller/fasten-form.js.map +1 -1
- package/dist-client/modeller/fasten-geometry.d.ts +3 -2
- package/dist-client/modeller/fasten-geometry.js +5 -3
- package/dist-client/modeller/fasten-geometry.js.map +1 -1
- package/dist-client/modeller/figure-cavity-drawing.js +1 -3
- package/dist-client/modeller/figure-cavity-drawing.js.map +1 -1
- package/dist-client/modeller/figure-clips.d.ts +9 -0
- package/dist-client/modeller/figure-clips.js +104 -8
- package/dist-client/modeller/figure-clips.js.map +1 -1
- package/dist-client/modeller/figure-data-panel.d.ts +10 -19
- package/dist-client/modeller/figure-data-panel.js +382 -190
- package/dist-client/modeller/figure-data-panel.js.map +1 -1
- package/dist-client/modeller/figure-fasten-dialog.js +39 -24
- package/dist-client/modeller/figure-fasten-dialog.js.map +1 -1
- package/dist-client/modeller/figure-fasten-drawing.js +24 -14
- package/dist-client/modeller/figure-fasten-drawing.js.map +1 -1
- package/dist-client/modeller/figure-first-save.js +4 -3
- package/dist-client/modeller/figure-first-save.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +9 -0
- package/dist-client/modeller/figure-links.js +120 -51
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-parts.js +7 -11
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +13 -0
- package/dist-client/modeller/figure-preview.js +296 -80
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-size-editor.js +7 -3
- package/dist-client/modeller/figure-size-editor.js.map +1 -1
- package/dist-client/modeller/first-save.d.ts +5 -0
- package/dist-client/modeller/first-save.js +7 -0
- package/dist-client/modeller/first-save.js.map +1 -1
- package/dist-client/modeller/focus-on-render.d.ts +2 -0
- package/dist-client/modeller/focus-on-render.js +4 -0
- package/dist-client/modeller/focus-on-render.js.map +1 -0
- package/dist-client/modeller/pivot.d.ts +12 -0
- package/dist-client/modeller/pivot.js +59 -0
- package/dist-client/modeller/pivot.js.map +1 -0
- package/dist-client/modeller/size-response.d.ts +6 -0
- package/dist-client/modeller/size-response.js +14 -0
- package/dist-client/modeller/size-response.js.map +1 -1
- package/dist-client/modeller/stage-model.d.ts +17 -3
- package/dist-client/modeller/stage-model.js +44 -6
- package/dist-client/modeller/stage-model.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
- package/test/browser/editing-page.js +1 -1
- package/test/browser/editing.check.mjs +6 -5
- package/test/browser/links.check.mjs +30 -0
- package/test/browser/modeller.check.mjs +2 -2
- package/test/browser/parts-page.js +4 -0
- package/test/browser/parts.check.mjs +16 -10
- package/test/browser/screen-page.js +12 -1
- package/test/browser/screen.check.mjs +142 -11
- package/test/browser/section.check.mjs +21 -0
- package/test/browser/serve-response.mjs +5 -2
- package/test/browser/side-panel-sweep.check.mjs +171 -10
- package/test/clips.test.ts +49 -4
- package/test/data-motion.test.ts +39 -8
- package/test/fasten-form.test.ts +69 -0
- package/test/fasten-geometry.test.ts +13 -0
- package/test/first-save.test.ts +11 -1
- package/test/pivot.test.ts +57 -0
- package/test/size-response.test.ts +10 -2
- package/test/stage-model.test.ts +23 -1
- package/translations/en.json +31 -11
- package/translations/es.json +30 -10
- package/translations/ja.json +30 -10
- package/translations/ko.json +32 -12
- package/translations/ms.json +30 -10
- package/translations/zh.json +30 -10
- package/tutorial/humanoid/README.md +22 -0
- package/tutorial/humanoid/chapters.mjs +247 -0
- package/tutorial/humanoid/encode.mjs +26 -0
- package/tutorial/humanoid/lib.mjs +197 -0
- package/tutorial/humanoid/record.mjs +65 -0
|
@@ -9,15 +9,26 @@ import { i18next, localize } from '@operato/i18n';
|
|
|
9
9
|
import { unitWord } from './unit-words.js';
|
|
10
10
|
import { figureFaceOverhangOf, figureMotionsOf, motionIdOf } from '@hatiolab/figure-model';
|
|
11
11
|
import { acceptsOf, AXES, canFasten, canFollow, positionIsShare, heldBy, shownWhenOf, visibilityControlsOf, fasteningOf, hasInstanceSize, holdsThings, leadersFor, motionOf, motionFormOf, motionFormRefusalOf, endPlaceKeyOf, motionJoint, controlIdFor, withoutAxis, placeFacesOf, placeIdFor, placesOn, rowAxesOf, rowBlockOf, fixedJointOf, rowOf, positionsWorkedOut, followOf, followableAxes, measureNow, freshStateSize, stateSizeIdFor, stateSizeCommandOf, stateSizeFixedOf } from './links.js';
|
|
12
|
-
import { measureFactor } from './size-response.js';
|
|
12
|
+
import { measureFactor, sizeAxisWord } from './size-response.js';
|
|
13
13
|
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js';
|
|
14
14
|
import { insideAlignmentOf } from './fasten-geometry.js';
|
|
15
15
|
import { fastenFormOf, fastenPlanOf, fastenSentenceOf } from './fasten-form.js';
|
|
16
16
|
import { HelpToggles } from './help.js';
|
|
17
17
|
import { groupMenu, GroupMenuStyles } from './group-menu.js';
|
|
18
18
|
import { jointAxisWord } from './joint-axis.js';
|
|
19
|
+
import { PIVOT_POINTS, pivotPointOf, pivotPointsOf } from './pivot.js';
|
|
19
20
|
import { placeTerms } from '@things-factory/figure-viewer/dist-client/detail-facts.js';
|
|
20
21
|
const freshMotion = () => ({ kind: 'slide', axis: 'x', id: '', min: 0, max: 500, follow: '', multiplier: 1, offset: 0, travel: '', travelPlus: 0 });
|
|
22
|
+
/**
|
|
23
|
+
* The motion a part's form starts from: a part hung on another part most often turns there -- a thigh at the hip, a door
|
|
24
|
+
* at its frame -- so it starts as a turn; a part on the plane, or on nothing, as a slide (review 2026-11-11: eight
|
|
25
|
+
* joints of a humanoid, each changed from slide to turn by hand).
|
|
26
|
+
*/
|
|
27
|
+
export function motionStartOf(revision, part) {
|
|
28
|
+
const own = revision ? fasteningOf(revision, part) : undefined;
|
|
29
|
+
return own && !own.toPlane && own.target ? { ...freshMotion(), kind: 'turn', min: -90, max: 90 } : freshMotion();
|
|
30
|
+
}
|
|
31
|
+
const sameMotion = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
21
32
|
const freshRow = () => ({ axis: '', pitch: 200, fills: true, count: 5 });
|
|
22
33
|
const freshPlace = () => ({ role: 'grip', face: 'top', label: '', accepts: '', capacity: 1 });
|
|
23
34
|
/**
|
|
@@ -76,9 +87,31 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
76
87
|
this.motionAxis = 0;
|
|
77
88
|
}
|
|
78
89
|
static { this.styles = [SidePanelStyles, GroupMenuStyles, css `
|
|
90
|
+
/* A motion's delete and edit as icons at the line's end, their words in their titles: two word buttons took the line (user 2026-11-12). */
|
|
91
|
+
div[pair] > button[act][icon] {
|
|
92
|
+
flex: none;
|
|
93
|
+
width: var(--figure-control-height, 28px);
|
|
94
|
+
padding: 0;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
}
|
|
97
|
+
/* The size-by-state form folded under its summary, opened to add one. */
|
|
98
|
+
details[state-size-add][open] > summary {
|
|
99
|
+
margin-bottom: 6px;
|
|
100
|
+
}
|
|
79
101
|
:host {
|
|
80
102
|
display: block;
|
|
81
103
|
}
|
|
104
|
+
/* The turn's axis through the part's top, middle or bottom, by name, under the numbers it fills in. */
|
|
105
|
+
div[pivot-points] {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
gap: 8px;
|
|
109
|
+
margin: 4px 0 8px;
|
|
110
|
+
}
|
|
111
|
+
div[pivot-points] > span {
|
|
112
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
113
|
+
font-size: var(--ui-t-small, 11.5px);
|
|
114
|
+
}
|
|
82
115
|
/* A group's sub-question, under its title: quieter than the title, as a label is. */
|
|
83
116
|
p[group-question] {
|
|
84
117
|
margin: 4px 0 0;
|
|
@@ -155,7 +188,7 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
155
188
|
this.fixNote = '';
|
|
156
189
|
if (this.asset && this.partId && this.partId !== this.loadedFor) {
|
|
157
190
|
this.loadedFor = this.partId;
|
|
158
|
-
this.motion =
|
|
191
|
+
this.motion = motionStartOf(this.revision, this.partId);
|
|
159
192
|
this.place = freshPlace();
|
|
160
193
|
this.placeEditing = null;
|
|
161
194
|
this.row = freshRow();
|
|
@@ -164,6 +197,12 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
164
197
|
this.editingMotion = false;
|
|
165
198
|
this.motionAxis = 0;
|
|
166
199
|
}
|
|
200
|
+
else if (changed.has('revision') && this.partId && !this.editingMotion) {
|
|
201
|
+
/* Fastened since the form was loaded, a form nobody has touched starts as that part's motion now does. */
|
|
202
|
+
const was = motionStartOf(changed.get('revision'), this.partId);
|
|
203
|
+
if (sameMotion(this.motion, was))
|
|
204
|
+
this.motion = motionStartOf(this.revision, this.partId);
|
|
205
|
+
}
|
|
167
206
|
}
|
|
168
207
|
updated() {
|
|
169
208
|
/* Only the sections that hold a form speak of what it would do, and only while their tab is shown: the panel has
|
|
@@ -555,7 +594,7 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
555
594
|
const axes = followableAxes(asset, part);
|
|
556
595
|
if (!axes.length)
|
|
557
596
|
return nothing;
|
|
558
|
-
const word = (axis) =>
|
|
597
|
+
const word = (axis) => sizeAxisWord(asset, part, axis, i18next.t('figure.label.size-diameter'));
|
|
559
598
|
const sized = axes.flatMap(axis => {
|
|
560
599
|
const f = followOf(asset, part, axis);
|
|
561
600
|
return f.of === 'state' ? [{ axis, f }] : [];
|
|
@@ -576,7 +615,7 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
576
615
|
: { ...form, id: value };
|
|
577
616
|
};
|
|
578
617
|
const number = (key) => (e) => (this.stateSize = { ...form, axis, [key]: e.target.valueAsNumber });
|
|
579
|
-
return html `<h4 state-size>${i18next.t('figure.label.state-size')}</h4
|
|
618
|
+
return html `${sized.length ? html `<h4 state-size>${i18next.t('figure.label.state-size')}</h4>` : nothing}
|
|
580
619
|
${sized.map(({ axis: one, f }) => {
|
|
581
620
|
const k = measureFactor(asset, part, one);
|
|
582
621
|
const input = controls.find(c => c.id === f.input);
|
|
@@ -599,7 +638,10 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
599
638
|
</div>`;
|
|
600
639
|
})}
|
|
601
640
|
${free.length
|
|
602
|
-
?
|
|
641
|
+
? /* Folded until asked for: six lines of a form few parts use pushed the controls below it down (user 2026-11-12). */
|
|
642
|
+
html `<details state-size-add>
|
|
643
|
+
<summary>${i18next.t('figure.button.add-state-size')}</summary>
|
|
644
|
+
<div form state-size-form>
|
|
603
645
|
<span>${i18next.t('figure.label.state-size-measure')}</span>
|
|
604
646
|
<select ?disabled=${this.locked} @change=${(e) => (this.stateSize = { ...form, axis: e.target.value, atMax: NaN })}>
|
|
605
647
|
${free.map(one => html `<option value=${one} ?selected=${one === axis}>${word(one)}</option>`)}
|
|
@@ -609,9 +651,9 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
609
651
|
<datalist id="state-size-controls">${controls.map(c => html `<option value=${c.id}>${c.label}</option>`)}</datalist>
|
|
610
652
|
<span>${i18next.t('figure.label.state-size-unit')}</span>
|
|
611
653
|
<select ?disabled=${this.locked} @change=${(e) => {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
654
|
+
const unit = e.target.value;
|
|
655
|
+
this.stateSize = { ...form, axis, unit, ...(unit === 'percent' ? { min: 0, max: 100 } : unit === 'ratio' ? { min: 0, max: 1 } : {}) };
|
|
656
|
+
}}>
|
|
615
657
|
${['percent', 'ratio', 'mm'].map(u => html `<option value=${u} ?selected=${u === form.unit}>${unitWord(u)}</option>`)}
|
|
616
658
|
</select>
|
|
617
659
|
<span>${i18next.t('figure.label.control-range')} (${unitWord(form.unit)})</span>
|
|
@@ -625,11 +667,12 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
625
667
|
<input type="number" step="any" min="0" state-size-at-max .value=${Number.isFinite(atMax) ? String(atMax) : ''} ?disabled=${this.locked} @change=${number('atMax')} />
|
|
626
668
|
</div>
|
|
627
669
|
<button act add-state-size ?disabled=${this.locked || !command} @click=${() => {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
670
|
+
if (!command)
|
|
671
|
+
return;
|
|
672
|
+
this.command(command);
|
|
673
|
+
this.stateSize = freshStateSize();
|
|
674
|
+
}}><md-icon>add</md-icon>${i18next.t('figure.button.add')}</button>
|
|
675
|
+
</details>`
|
|
633
676
|
: nothing}`;
|
|
634
677
|
}
|
|
635
678
|
renderShown(asset) {
|
|
@@ -690,7 +733,30 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
690
733
|
<input type="number" step="any" aria-label=${`${i18next.t('figure.label.motion-through')} ${axis.toUpperCase()}`} .value=${String(m.through?.[axis] ?? 0)} @change=${typed(axis)} />
|
|
691
734
|
</div>`)}
|
|
692
735
|
</div>
|
|
693
|
-
</div
|
|
736
|
+
</div>
|
|
737
|
+
${this.renderPivotPoints(m)}`;
|
|
738
|
+
}
|
|
739
|
+
renderPivotPoints(m) {
|
|
740
|
+
if (!this.revision || m.throughFollows)
|
|
741
|
+
return nothing;
|
|
742
|
+
const key = `${this.revision.revision}:${this.partId}:${m.axis}`;
|
|
743
|
+
if (this.pivotCache?.key !== key)
|
|
744
|
+
this.pivotCache = { key, points: pivotPointsOf(this.revision, this.partId, m.axis) };
|
|
745
|
+
const points = this.pivotCache.points;
|
|
746
|
+
if (!points)
|
|
747
|
+
return nothing;
|
|
748
|
+
return html `<div pivot-points>
|
|
749
|
+
<span>${i18next.t('figure.label.pivot-at')}</span>
|
|
750
|
+
<ox-input-select-buttons
|
|
751
|
+
.value=${pivotPointOf(points, m.through, m.axis) ?? ''}
|
|
752
|
+
.options=${PIVOT_POINTS.map(p => ({ value: p, display: i18next.t(`figure.label.pivot-${p}`) }))}
|
|
753
|
+
@change=${(e) => {
|
|
754
|
+
const at = points[e.detail];
|
|
755
|
+
if (at)
|
|
756
|
+
this.motion = { ...m, through: { ...at } };
|
|
757
|
+
}}
|
|
758
|
+
></ox-input-select-buttons>
|
|
759
|
+
</div>`;
|
|
694
760
|
}
|
|
695
761
|
renderMotion(asset) {
|
|
696
762
|
const now = motionOf(asset, this.partId);
|
|
@@ -727,14 +793,14 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
727
793
|
: nothing}
|
|
728
794
|
</span>
|
|
729
795
|
${count > 1
|
|
730
|
-
? html `<button act remove-axis ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: withoutAxis(joint, k) })}>
|
|
731
|
-
<md-icon>
|
|
796
|
+
? html `<button act icon remove-axis title=${i18next.t('figure.button.remove-axis')} aria-label=${i18next.t('figure.button.remove-axis')} ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: withoutAxis(joint, k) })}>
|
|
797
|
+
<md-icon>delete</md-icon>
|
|
732
798
|
</button>`
|
|
733
|
-
: html `<button act ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: fixedJointOf(joint) })}>
|
|
734
|
-
<md-icon>
|
|
799
|
+
: html `<button act icon title=${i18next.t('figure.button.remove-motion')} aria-label=${i18next.t('figure.button.remove-motion')} ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: fixedJointOf(joint) })}>
|
|
800
|
+
<md-icon>delete</md-icon>
|
|
735
801
|
</button>`}
|
|
736
|
-
<button act ?disabled=${this.locked || !joint} @click=${() => edit(k)}>
|
|
737
|
-
<md-icon>edit</md-icon
|
|
802
|
+
<button act icon title=${i18next.t('figure.button.change-motion')} aria-label=${i18next.t('figure.button.change-motion')} ?disabled=${this.locked || !joint} @click=${() => edit(k)}>
|
|
803
|
+
<md-icon>edit</md-icon>
|
|
738
804
|
</button>
|
|
739
805
|
</div>`;
|
|
740
806
|
};
|
|
@@ -775,6 +841,8 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
775
841
|
const adding = k > 0 && k >= figureMotionsOf(joint).length;
|
|
776
842
|
const follow = leaders.some(j => j.id === m.follow) ? m.follow : '';
|
|
777
843
|
const refusal = motionFormRefusalOf(m, follow);
|
|
844
|
+
/* Following another joint is offered after the part's own control: a row above it moved every field down a row, and
|
|
845
|
+
a name typed there chose a joint to follow (review 2026-11-11). */
|
|
778
846
|
return html `
|
|
779
847
|
${k > 0 ? html `<p motion-axis-heading><b>${i18next.t('figure.label.motion-axis-n', { n: k + 1 })}</b></p>` : nothing}
|
|
780
848
|
<div pair>
|
|
@@ -789,6 +857,35 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
789
857
|
${AXES.map(a => html `<option value=${a} ?selected=${a === m.axis}>${i18next.t('figure.label.motion-axis')} ${a.toUpperCase()}</option>`)}
|
|
790
858
|
</select>`}
|
|
791
859
|
</div>
|
|
860
|
+
${m.followSum || follow
|
|
861
|
+
? nothing
|
|
862
|
+
: html `<div form>
|
|
863
|
+
${m.kind === 'slide'
|
|
864
|
+
? html `<span>${i18next.t('figure.label.motion-travel')}</span>
|
|
865
|
+
<select @change=${(e) => (this.motion = { ...m, travel: e.target.value })}>
|
|
866
|
+
${m.travelSum
|
|
867
|
+
? html `<option value="" ?selected=${!m.travel}>${m.travelSum.sum.map(t => `${t.from.of === 'input' ? t.from.input : `${t.from.of === 'part' ? t.from.part : i18next.t('figure.label.motion-travel')} · ${t.from.axis.toUpperCase()}`}${t.times !== undefined && t.times !== 1 ? ` × ${t.times}` : ''}`).join(' + ')}</option>`
|
|
868
|
+
: html `<option value="" ?selected=${!m.travel}>${i18next.t('figure.label.motion-travel-mm')}</option>`}
|
|
869
|
+
${asset.appearance
|
|
870
|
+
.map(look => look.target)
|
|
871
|
+
.filter(one => canFollow(asset, one))
|
|
872
|
+
.flatMap(one => AXES.map(a => html `<option value=${`${one}:${a}`} ?selected=${m.travel === `${one}:${a}`}>${one} · ${a.toUpperCase()}</option>`))}
|
|
873
|
+
</select>
|
|
874
|
+
${m.travel
|
|
875
|
+
? html `<span>${i18next.t('figure.label.follows-plus')}</span>
|
|
876
|
+
<input type="number" step="any" .value=${String(m.travelPlus ?? 0)} @change=${(e) => (this.motion = { ...m, travelPlus: Number(e.target.value) || 0 })} />`
|
|
877
|
+
: nothing}`
|
|
878
|
+
: nothing}
|
|
879
|
+
<span>${i18next.t('figure.label.control-id')}</span>
|
|
880
|
+
<input .value=${m.id} placeholder=${controlIdFor(this.partId, m.kind, k)} @change=${(e) => (this.motion = { ...m, id: e.target.value.trim() })} />
|
|
881
|
+
${m.kind === 'continuous' || (m.kind === 'slide' && (m.travel || m.travelSum))
|
|
882
|
+
? nothing
|
|
883
|
+
: html `<span>${i18next.t('figure.label.control-range')} (${unit})</span>
|
|
884
|
+
<div pair>
|
|
885
|
+
<input type="number" step="any" .value=${String(m.min)} @change=${(e) => (this.motion = { ...m, min: Number(e.target.value) })} />
|
|
886
|
+
<input type="number" step="any" .value=${String(m.max)} @change=${(e) => (this.motion = { ...m, max: Number(e.target.value) })} />
|
|
887
|
+
</div>`}
|
|
888
|
+
</div>`}
|
|
792
889
|
${m.followSum
|
|
793
890
|
? html `<div form>
|
|
794
891
|
<span>${i18next.t('figure.label.motion-follow')}</span>
|
|
@@ -805,42 +902,14 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
805
902
|
</select>
|
|
806
903
|
</div>`
|
|
807
904
|
: nothing}
|
|
808
|
-
${m.followSum
|
|
809
|
-
?
|
|
810
|
-
: follow
|
|
811
|
-
? html `<div form>
|
|
905
|
+
${!m.followSum && follow
|
|
906
|
+
? html `<div form>
|
|
812
907
|
<span>${i18next.t('figure.label.motion-multiplier')}</span>
|
|
813
908
|
<input type="number" step="any" .value=${String(m.multiplier)} @change=${(e) => (this.motion = { ...m, multiplier: Number(e.target.value) })} />
|
|
814
909
|
<span>${i18next.t('figure.label.motion-offset')} (${unit})</span>
|
|
815
910
|
<input type="number" step="any" .value=${String(m.offset)} @change=${(e) => (this.motion = { ...m, offset: Number(e.target.value) || 0 })} />
|
|
816
911
|
</div>`
|
|
817
|
-
|
|
818
|
-
${m.kind === 'slide'
|
|
819
|
-
? html `<span>${i18next.t('figure.label.motion-travel')}</span>
|
|
820
|
-
<select @change=${(e) => (this.motion = { ...m, travel: e.target.value })}>
|
|
821
|
-
${m.travelSum
|
|
822
|
-
? html `<option value="" ?selected=${!m.travel}>${m.travelSum.sum.map(t => `${t.from.of === 'input' ? t.from.input : `${t.from.of === 'part' ? t.from.part : i18next.t('figure.label.motion-travel')} · ${t.from.axis.toUpperCase()}`}${t.times !== undefined && t.times !== 1 ? ` × ${t.times}` : ''}`).join(' + ')}</option>`
|
|
823
|
-
: html `<option value="" ?selected=${!m.travel}>${i18next.t('figure.label.motion-travel-mm')}</option>`}
|
|
824
|
-
${asset.appearance
|
|
825
|
-
.map(look => look.target)
|
|
826
|
-
.filter(one => canFollow(asset, one))
|
|
827
|
-
.flatMap(one => AXES.map(a => html `<option value=${`${one}:${a}`} ?selected=${m.travel === `${one}:${a}`}>${one} · ${a.toUpperCase()}</option>`))}
|
|
828
|
-
</select>
|
|
829
|
-
${m.travel
|
|
830
|
-
? html `<span>${i18next.t('figure.label.follows-plus')}</span>
|
|
831
|
-
<input type="number" step="any" .value=${String(m.travelPlus ?? 0)} @change=${(e) => (this.motion = { ...m, travelPlus: Number(e.target.value) || 0 })} />`
|
|
832
|
-
: nothing}`
|
|
833
|
-
: nothing}
|
|
834
|
-
<span>${i18next.t('figure.label.control-id')}</span>
|
|
835
|
-
<input .value=${m.id} placeholder=${controlIdFor(this.partId, m.kind, k)} @change=${(e) => (this.motion = { ...m, id: e.target.value.trim() })} />
|
|
836
|
-
${m.kind === 'continuous' || (m.kind === 'slide' && (m.travel || m.travelSum))
|
|
837
|
-
? nothing
|
|
838
|
-
: html `<span>${i18next.t('figure.label.control-range')} (${unit})</span>
|
|
839
|
-
<div pair>
|
|
840
|
-
<input type="number" step="any" .value=${String(m.min)} @change=${(e) => (this.motion = { ...m, min: Number(e.target.value) })} />
|
|
841
|
-
<input type="number" step="any" .value=${String(m.max)} @change=${(e) => (this.motion = { ...m, max: Number(e.target.value) })} />
|
|
842
|
-
</div>`}
|
|
843
|
-
</div>`}
|
|
912
|
+
: nothing}
|
|
844
913
|
${m.kind === 'slide' ? nothing : this.renderThrough(m)}
|
|
845
914
|
<button
|
|
846
915
|
act
|