@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.
@@ -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 = new Set(this.session!.read().geometry.map(g => g.id))
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 = new Set(this.session!.read().geometry.map(g => g.id))
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 = new Set(this.session!.read().geometry.map(g => g.id))
861
+ const before = this.partIds()
854
862
  this.session!.edit({ kind: 'duplicate-part', target: id })
855
- this.selected = this.session!.read().geometry.find(g => !before.has(g.id))?.id ?? id
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 = new Set(this.session!.read().geometry.map(g => g.id))
1043
+ const before = this.partIds()
1036
1044
  this.session!.edit({ kind: 'duplicate-part', target: id })
1037
- const copy = this.session!.read().geometry.find(g => !before.has(g.id))?.id
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 = new Set(this.session.read().geometry.map(g => g.id));
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 = new Set(this.session.read().geometry.map(g => g.id));
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 = new Set(this.session.read().geometry.map(g => g.id));
855
+ const before = this.partIds();
848
856
  this.session.edit({ kind: 'duplicate-part', target: id });
849
- this.selected = this.session.read().geometry.find(g => !before.has(g.id))?.id ?? id;
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 = new Set(this.session.read().geometry.map(g => g.id));
1056
+ const before = this.partIds();
1049
1057
  this.session.edit({ kind: 'duplicate-part', target: id });
1050
- const copy = this.session.read().geometry.find(g => !before.has(g.id))?.id;
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));