@things-factory/figure-ui 10.1.150 → 10.1.151
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/editor.ts +14 -6
- package/dist-client/modeller/editor.d.ts +6 -0
- package/dist-client/modeller/editor.js +14 -6
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/test/browser/part-ids.check.mjs +86 -0
|
@@ -750,6 +750,14 @@ export class FigureEditor extends LitElement {
|
|
|
750
750
|
private shown(): FigureRevision | undefined {
|
|
751
751
|
return this.session?.revisionNow()
|
|
752
752
|
}
|
|
753
|
+
/**
|
|
754
|
+
* The figure's parts by id, one per authored part as the parts list shows them. Not the drawn bodies: a row's copies
|
|
755
|
+
* are drawn under ids of their own, so a part made into a row was missing from those and its id was offered to the
|
|
756
|
+
* next part, which figure-model refused (DUPLICATE_PART).
|
|
757
|
+
*/
|
|
758
|
+
private partIds(): Set<string> {
|
|
759
|
+
return new Set(this.session?.revisionNow()?.asset.appearance.map(look => look.target) ?? [])
|
|
760
|
+
}
|
|
753
761
|
/** A value in hand: an input's value (design or pose) or a part edit. Nothing is recorded. */
|
|
754
762
|
private hold(values: Record<string, number>, edit?: FigurePartEdit) {
|
|
755
763
|
this.live = { values: { ...this.live.values, ...values }, ...(edit ? { edit } : this.live.edit ? { edit: this.live.edit } : {}) }
|
|
@@ -803,7 +811,7 @@ export class FigureEditor extends LitElement {
|
|
|
803
811
|
private add(kind: FigurePaletteKind) {
|
|
804
812
|
if (!this.session) return
|
|
805
813
|
this.run(() => {
|
|
806
|
-
const ids =
|
|
814
|
+
const ids = this.partIds()
|
|
807
815
|
let n = 1
|
|
808
816
|
while (ids.has(`${kind}-${n}`)) n++
|
|
809
817
|
const part = paletteRecipe(kind, `${kind}-${n}`)
|
|
@@ -838,7 +846,7 @@ export class FigureEditor extends LitElement {
|
|
|
838
846
|
if (!choice) return
|
|
839
847
|
const node = upload.summary.nodes.find(n => n.index === (choice as { node?: number }).node)
|
|
840
848
|
this.run(() => {
|
|
841
|
-
const taken =
|
|
849
|
+
const taken = this.partIds()
|
|
842
850
|
const id = meshPartIdOf(node?.name ?? file.name.replace(/\.glb$/i, ''), taken)
|
|
843
851
|
this.session!.add(meshPartOf(upload, choice as { node?: number }, id))
|
|
844
852
|
this.selected = id
|
|
@@ -850,9 +858,9 @@ export class FigureEditor extends LitElement {
|
|
|
850
858
|
*/
|
|
851
859
|
private duplicatePart(id: string) {
|
|
852
860
|
this.run(() => {
|
|
853
|
-
const before =
|
|
861
|
+
const before = this.partIds()
|
|
854
862
|
this.session!.edit({ kind: 'duplicate-part', target: id })
|
|
855
|
-
this.selected = this.
|
|
863
|
+
this.selected = [...this.partIds()].find(part => !before.has(part)) ?? id
|
|
856
864
|
})
|
|
857
865
|
}
|
|
858
866
|
private movePart(id: string, to: number) {
|
|
@@ -1032,9 +1040,9 @@ export class FigureEditor extends LitElement {
|
|
|
1032
1040
|
private mirror(axis: 'x' | 'z') {
|
|
1033
1041
|
this.run(() => {
|
|
1034
1042
|
const id = this.selected
|
|
1035
|
-
const before =
|
|
1043
|
+
const before = this.partIds()
|
|
1036
1044
|
this.session!.edit({ kind: 'duplicate-part', target: id })
|
|
1037
|
-
const copy = this.
|
|
1045
|
+
const copy = [...this.partIds()].find(part => !before.has(part))
|
|
1038
1046
|
if (!copy) return
|
|
1039
1047
|
this.session!.apply(mirrorChanges(this.shown()!, id, copy, axis))
|
|
1040
1048
|
this.selected = copy
|
|
@@ -146,6 +146,12 @@ export declare class FigureEditor extends LitElement {
|
|
|
146
146
|
* defaults put every other joint back to its saved angle while one slider moved (user, 2026-09-24).
|
|
147
147
|
*/
|
|
148
148
|
private shown;
|
|
149
|
+
/**
|
|
150
|
+
* The figure's parts by id, one per authored part as the parts list shows them. Not the drawn bodies: a row's copies
|
|
151
|
+
* are drawn under ids of their own, so a part made into a row was missing from those and its id was offered to the
|
|
152
|
+
* next part, which figure-model refused (DUPLICATE_PART).
|
|
153
|
+
*/
|
|
154
|
+
private partIds;
|
|
149
155
|
/** A value in hand: an input's value (design or pose) or a part edit. Nothing is recorded. */
|
|
150
156
|
private hold;
|
|
151
157
|
private closeSectionEditor;
|
|
@@ -737,6 +737,14 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
737
737
|
shown() {
|
|
738
738
|
return this.session?.revisionNow();
|
|
739
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* The figure's parts by id, one per authored part as the parts list shows them. Not the drawn bodies: a row's copies
|
|
742
|
+
* are drawn under ids of their own, so a part made into a row was missing from those and its id was offered to the
|
|
743
|
+
* next part, which figure-model refused (DUPLICATE_PART).
|
|
744
|
+
*/
|
|
745
|
+
partIds() {
|
|
746
|
+
return new Set(this.session?.revisionNow()?.asset.appearance.map(look => look.target) ?? []);
|
|
747
|
+
}
|
|
740
748
|
/** A value in hand: an input's value (design or pose) or a part edit. Nothing is recorded. */
|
|
741
749
|
hold(values, edit) {
|
|
742
750
|
this.live = { values: { ...this.live.values, ...values }, ...(edit ? { edit } : this.live.edit ? { edit: this.live.edit } : {}) };
|
|
@@ -794,7 +802,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
794
802
|
if (!this.session)
|
|
795
803
|
return;
|
|
796
804
|
this.run(() => {
|
|
797
|
-
const ids =
|
|
805
|
+
const ids = this.partIds();
|
|
798
806
|
let n = 1;
|
|
799
807
|
while (ids.has(`${kind}-${n}`))
|
|
800
808
|
n++;
|
|
@@ -832,7 +840,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
832
840
|
return;
|
|
833
841
|
const node = upload.summary.nodes.find(n => n.index === choice.node);
|
|
834
842
|
this.run(() => {
|
|
835
|
-
const taken =
|
|
843
|
+
const taken = this.partIds();
|
|
836
844
|
const id = meshPartIdOf(node?.name ?? file.name.replace(/\.glb$/i, ''), taken);
|
|
837
845
|
this.session.add(meshPartOf(upload, choice, id));
|
|
838
846
|
this.selected = id;
|
|
@@ -844,9 +852,9 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
844
852
|
*/
|
|
845
853
|
duplicatePart(id) {
|
|
846
854
|
this.run(() => {
|
|
847
|
-
const before =
|
|
855
|
+
const before = this.partIds();
|
|
848
856
|
this.session.edit({ kind: 'duplicate-part', target: id });
|
|
849
|
-
this.selected = this.
|
|
857
|
+
this.selected = [...this.partIds()].find(part => !before.has(part)) ?? id;
|
|
850
858
|
});
|
|
851
859
|
}
|
|
852
860
|
movePart(id, to) {
|
|
@@ -1045,9 +1053,9 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1045
1053
|
mirror(axis) {
|
|
1046
1054
|
this.run(() => {
|
|
1047
1055
|
const id = this.selected;
|
|
1048
|
-
const before =
|
|
1056
|
+
const before = this.partIds();
|
|
1049
1057
|
this.session.edit({ kind: 'duplicate-part', target: id });
|
|
1050
|
-
const copy = this.
|
|
1058
|
+
const copy = [...this.partIds()].find(part => !before.has(part));
|
|
1051
1059
|
if (!copy)
|
|
1052
1060
|
return;
|
|
1053
1061
|
this.session.apply(mirrorChanges(this.shown(), id, copy, axis));
|