@38225: this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){const r=Math.sin(t
@38435: *e,this.z=r*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Ma
@42366: intersectsSphere(e){return this.clampPoint(e.center,Gt),Gt.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.no
@42375: sSphere(e){return this.clampPoint(e.center,Gt),Gt.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*th
@43482: o(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Gt).length()),e}intersect(e){return this.min.ma
@44873: onst nn=new Vt,rn=new Ut,sn=new Ut;class on{constructor(e=new Ut,t=-1){this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFro
@44923: uctor(e=new Ut,t=-1){this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const n=this.center;void 0!==t?n.copy
@45121: et r=0;for(let t=0,i=e.length;t<i;t++)r=Math.max(r,n.distanceToSquared(e[t]));return this.radius=Math.sqrt(r),this}copy(e){return this.center.copy(e.center),thi


Bash

cd /Users/marcus.hinz/projects/adesso-cpq
F=node_modules/.pnpm/@ad+fire@1.0.6/node_modules/@ad/fire/browser/index.js
node -e '
const fs=require("fs");const s=fs.readFileSync(process.argv[1],"utf8");
for(const t of ["\"grid\"","\"sphere\"","\"cone\"","\"torus\"","\"prism\"","factoryName:","defaultModel"]){
  let idx=s.indexOf(t);
  console.log("=== "+t+" @"+idx);
  if(idx>=0) console.log(s.slice(idx-100,idx+120).replace(/\n/g," "));
}
' "$F"

Find geometry factory name registrations


=== "grid" @1090933
!!e.normal}};fa=(0,r.Cg)([(0,s.SettingsResolver)("gridGeometryFactory",{key:{_type:"string",default:"grid"},baseType:{_type:"token",constructorType:Ue,default:{constructorType:Ue}},defaultModel:{_type:"object",default:()
=== "sphere" @1003872
ctive|tn.layer|e.transform|e.deformation|e.isTrigger]="all"}(Jr||(Jr={})),function(e){e[e.sphere=2]="sphere",e[e.box=4]="box",e[e.mesh=8]="mesh",e[e.capsule=16]="capsule"}(ei||(ei={}));class ti{constructor(e,t,n,r){this.
=== "cone" @-1
=== "torus" @-1
=== "prism" @-1
=== factoryName: @1056109
his.key}`)),n}async serialize(e,t){return{...this.settings.serialize?this.settings.serialize(e,t):e,factoryName:this.settings.key}}canExecute(e){return this.settings?.canExecute(e)??!0}}(0,r.Cg)([(0,s.PropertyResolver)(D
=== defaultModel @506919
l.ParametricGeometryModel.isType(e))return null;const n=this.getFactory(e.parameters);if(n){e={...n.defaultModel,...e};const r=await n.execute(e.parameters,t);return e.pivot&&this.transferPivot(r,o.Vector3Type.deserializ


cd /Users/marcus.hinz/projects/adesso-cpq
F=node_modules/.pnpm/@ad+fire@1.0.6/node_modules/@ad/fire/browser/index.js
node -e '
const fs=require("fs");const s=fs.readFileSync(process.argv[1],"utf8");
for(const t of ["sphereGeometryFactory","coneGeometryFactory","radialGeometryFactory","prismGeometryFactory"]){
  let idx=s.indexOf(t+"\",{");
  if(idx<0) idx=s.indexOf(t);
  console.log("=== "+t+" @"+idx);
  if(idx>=0) console.log(s.slice(idx-20,idx+360).replace(/\n/g," "));
}
' "$F"

Inspect sphere factory settings/defaults


=== sphereGeometryFactory @1060054
.SettingsResolver)("sphereGeometryFactory",{key:{_type:"string",default:"sphere-3d"},baseType:{_type:"token",constructorType:Ue,default:{constructorType:Ue}}})],Ho);let Wo=class extends Fo{async execute(e){const t=e.contour.map(e=>kr.deserialize(e)).map((e,t,n)=>[n[t],n[(t+n.length+1)%n.length]]);return{type:"mesh",...o.MeshFactory.prism(t,[o.Vector3.zero,new o.Vector3(0,0,e.le
=== coneGeometryFactory @1059078
.SettingsResolver)("coneGeometryFactory",{key:{_type:"string",default:"cone-3d"},baseType:{_type:"token",constructorType:Ue,default:{constructorType:Ue}},defaultModel:{_type:"object",default:()=>({pivot:new o.Vector3(0,0,-1)})}})],jo);let Go=class extends Fo{async execute(e){return{type:"mesh",...o.MeshFactory.torus(new o.Vector2(e.diameter,e.diameter),e.thickness,o.MeshGeometr
=== radialGeometryFactory @1062045
.SettingsResolver)("radialGeometryFactory",{key:{_type:"string",default:"radial"},baseType:{_type:"token",constructorType:Ue,default:{constructorType:Ue}},defaultModel:{_type:"object",default:()=>({pivot:new o.Vector3(0,0,-1)})}})],qo);let Xo=class extends Fo{async execute(e){const t=o.Matrix3_3.fromQuaternion(Lr.deserialize(e.rotation));return{type:"line",...o.Line.geometry(e.
=== prismGeometryFactory @1061447
.SettingsResolver)("prismGeometryFactory",{key:{_type:"string",default:"prism-3d"},baseType:{_type:"token",constructorType:Ue,default:{constructorType:Ue}},defaultModel:{_type:"object",default:()=>({pivot:new o.Vector3(0,0,-1)})}})],$o);let qo=class extends Fo{async execute(e){return{type:"mesh",...o.MeshFactory.radial(e.contour.map(e=>kr.deserialize(e)),o.MeshGeometry.create(o


cd /Users/marcus.hinz/projects/adesso-cpq
F=node_modules/.pnpm/@ad+fire@1.0.6/node_modules/@ad/fire/browser/index.js
node -e '
const fs=require("fs");const s=fs.readFileSync(process.argv[1],"utf8");
// class Ho definition (sphere) — find "class Ho" and its execute
let i=s.indexOf("let Ho=class");
if(i<0)i=s.indexOf("class Ho");
console.log("Ho @"+i);
console.log(s.slice(i,i+320).replace(/\n/g," "));
// MeshFactory.sphere signature
let j=s.indexOf("static sphere(");
console.log("MeshFactory.sphere @"+j);
if(j>=0)console.log(s.slice(j,j+260).replace(/\n/g," "));
' "$F"

Inspect sphere factory execute and MeshFactory.sphere signature


Ho @1059734
let Ho=class extends Fo{async execute(e){return{type:"mesh",...o.MeshFactory.sphere(new o.Vector3(e.diameter,e.diameter,e.diameter),o.MeshGeometry.create(o.MeshGeometryBuffer.normals|o.MeshGeometryBuffer.uvs|o.MeshGeometryBuffer.materialIndices))}}canExecute(e){return!!e.diameter}};Ho=(0,r.Cg)([(0,s.SettingsResolver)("
MeshFactory.sphere @-1


Gefunden: der Sphere-Factory-Key ist `sphere-3d`, Parameter `diameter`. Damit baue ich den Marker als echten Mesh-Renderer (wie das Pfeil-Gizmo in der Config, das in diesem Build rendert) plus Kugel-Collider.


Edit

                markers.push({
                    id: `sel-marker-${h.id}-${c.id}`,
                    tags: ["name-select-marker"],
                    // The only render path this @ad/fire build supports for scene-graph handles: a glb via
                    // sceneGraph_reference (renderer/lineRenderer components are skipped as "unknown"). We
                    // reuse an existing small part glb as the marker blob, tinted green via overrideMaterials.
                    sceneGraph: { _resourceClass: "sceneGraph_reference", path: "katalog/schutzzaun_basic/SBS1044SRA/CAP4040.glb" },
                    overrideMaterials: [{ _resourceClass: "material_standard", diffuse: [0, 1, 0] }],
                    components: [
                        { _resourceClass: "component_transform", parentKey: tr.key, translation: pos, rotation: [0, 0, 0], scale: [2, 2, 2] },
                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast
                        // hits it and reports the marker as the click target.
                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },
                    ],
                });

                markers.push({
                    id: `sel-marker-${h.id}-${c.id}`,
                    tags: ["name-select-marker"],
                    components: [
                        { _resourceClass: "component_transform", parentKey: tr.key, translation: pos, rotation: [0, 0, 0], scale: [1, 1, 1] },
                        // A real mesh sphere via the built-in parametric factory (key "sphere-3d", param
                        // `diameter`) — the same component_renderer path the config's arrow gizmo uses, so it
                        // renders in this build and yields proper localBounds (no getBounds crash on select).
                        {
                            _resourceClass: "component_renderer",
                            castShadow: false,
                            receiveShadow: false,
                            geometry: { _resourceClass: "geometry_parametric", parameters: { factoryName: "sphere-3d", diameter: 120 } },
                            material: { _resourceClass: "material_basic", diffuse: [0, 1, 0], depthTest: false },
                        },
                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast
                        // hits it and reports the marker as the click target.
                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },
                    ],
                });


The file /Users/marcus.hinz/projects/adesso-cpq/packages/frontend/src/configurator/events/DefaultCommandProcessor.ts has been updated successfully. (file state is current in your context — no need to Read it back)

                markers.push({
                    id: `sel-marker-${h.id}-${c.id}`,
                    tags: ["name-select-marker"],
                    // The only render path this @ad/fire build supports for scene-graph handles: a glb via
                    // sceneGraph_reference (renderer/lineRenderer components are skipped as "unknown"). We
                    // reuse an existing small part glb as the marker blob, tinted green via overrideMaterials.
                    sceneGraph: { _resourceClass: "sceneGraph_reference", path: "katalog/schutzzaun_basic/SBS1044SRA/CAP4040.glb" },
                    overrideMaterials: [{ _resourceClass: "material_standard", diffuse: [0, 1, 0] }],
                    components: [
                        { _resourceClass: "component_transform", parentKey: tr.key, translation: pos, rotation: [0, 0, 0], scale: [2, 2, 2] },
                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast
                        // hits it and reports the marker as the click target.
                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },
                    ],
                });

                markers.push({
                    id: `sel-marker-${h.id}-${c.id}`,
                    tags: ["name-select-marker"],
                    components: [
                        { _resourceClass: "component_transform", parentKey: tr.key, translation: pos, rotation: [0, 0, 0], scale: [1, 1, 1] },
                        // A real mesh sphere via the built-in parametric factory (key "sphere-3d", param
                        // `diameter`) — the same component_renderer path the config's arrow gizmo uses, so it
                        // renders in this build and yields proper localBounds (no getBounds crash on select).
                        {
                            _resourceClass: "component_renderer",
                            castShadow: false,
                            receiveShadow: false,
                            geometry: { _resourceClass: "geometry_parametric", parameters: { factoryName: "sphere-3d", diameter: 120 } },
                            material: { _resourceClass: "material_basic", diffuse: [0, 1, 0], depthTest: false },
                        },
                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast
                        // hits it and reports the marker as the click target.
                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },
                    ],
                });

-                    // The only render path this @ad/fire build supports for scene-graph handles: a glb via

-                    // sceneGraph_reference (renderer/lineRenderer components are skipped as "unknown"). We

-                    // reuse an existing small part glb as the marker blob, tinted green via overrideMaterials.

-                    sceneGraph: { _resourceClass: "sceneGraph_reference", path: "katalog/schutzzaun_basic/SBS1044SRA/CAP4040.glb" },

-                    overrideMaterials: [{ _resourceClass: "material_standard", diffuse: [0, 1, 0] }],

-                        { _resourceClass: "component_transform", parentKey: tr.key, translation: pos, rotation: [0, 0, 0], scale: [2, 2, 2] },

+                        { _resourceClass: "component_transform", parentKey: tr.key, translation: pos, rotation: [0, 0, 0], scale: [1, 1, 1] },

+                        // A real mesh sphere via the built-in parametric factory (key "sphere-3d", param

+                        // `diameter`) — the same component_renderer path the config's arrow gizmo uses, so it

+                        // renders in this build and yields proper localBounds (no getBounds crash on select).

+                            _resourceClass: "component_renderer",

+                            castShadow: false,

+                            receiveShadow: false,

+                            geometry: { _resourceClass: "geometry_parametric", parameters: { factoryName: "sphere-3d", diameter: 120 } },

+                            material: { _resourceClass: "material_basic", diffuse: [0, 1, 0], depthTest: false },


Kommentar über der Methode passt jetzt wieder. Typecheck:


Bash

cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
pnpm exec vue-tsc --noEmit -p tsconfig.json 2>&1 | grep -v "ProductBrowser.vue" | head -20; echo "exit ${PIPESTATUS[0]}"

Typecheck frontend excluding known ProductBrowser errors


exit


cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
pnpm exec vue-tsc --noEmit -p tsconfig.json 2>&1 | grep "DefaultCommandProcessor" | head; echo "our-file-errors: done"

Check typecheck errors in our file


our-file-errors: done


Kein Fehler in der Datei. Umgestellt auf die Geometry-Variante:

- **Marker**: `component_renderer` mit `geometry_parametric` (Factory-Key `sphere-3d`, `diameter: 120`) + `material_basic` grün, `depthTest: false`. Das ist derselbe Renderer-Pfad wie das Pfeil-Gizmo in der `environment.config.json`, das in diesem Build rendert — und er liefert echte `localBounds`, also kein `getBounds`-Crash beim Selektieren mehr.
- **Collider**: unverändert Kugel (`shapeType 2`, radius 60) für den Klick.
- **Alert**: unverändert (`sel-marker-`-Abfang in `handleSelectionClickEvent` → Dialog).

Typecheck sauber.


visual-3d.ts:167 [Fire3D Asset Loader] Attempting to load asset: {uri: 'https://rob-geko.hifassets.com/fire/assets/images/empty_warehouse_2K.jpg', originalPath: 'empty_warehouse_2K.jpg', typeKey: unde…


Rollenförderer Visualisierung und Fehler beheben


read properties of undefined (reading 'getBounds')
    at get localBounds (@ad_fire.js?v=339f371e:21578:92)
    at @ad_fire.js?v=339f371e:20478:12
    at mr.iterateComponents (@ad_fire.js?v=339f371e:19220:67)
    at mr.collectBounds (@ad_fire.js?v=339f371e:20477:50)
    at mr.collectBounds (@ad_fire.js?v=339f371e:20479:57)
    at get bounds (@ad_fire.js?v=339f371e:20472:23)
    at @ad_fire.js?v=339f371e:29715:20
    at Array.forEach (<anonymous>)
    at c.collectBounds (@ad_fire.js?v=339f371e:29714:10)
    at set selection (@ad_fire.js?v=339f371e:29675:40)
get localBounds @ @ad_fire.js?v=339f371e:21578
(anonymous) @ @ad_fire.js?v=339f371e:20478
iterateComponents @ @ad_fire.js?v=339f371e:19220
collectBounds @ @ad_fire.js?v=339f371e:20477
collectBounds @ @ad_fire.js?v=339f371e:20479
get bounds @ @ad_fire.js?v=339f371e:20472
(anonymous) @ @ad_fire.js?v=339f371e:29715
collectBounds @ @ad_fire.js?v=339f371e:29714
set selection @ @ad_fire.js?v=339f371e:29675
set @ @ad_fire.js?v=339f371e:29678
set_selection @ @ad_fire.js?v=339f371e:30269
run @ @ad_fire.js?v=339f371e:38626
(anonymous) @ visual-3d.ts:292
(anonymous) @ visual-3d.ts:300
processReactions @ Fire3D.vue:143
await in processReactions
(anonymous) @ Fire3D.vue:196
callback @ @ad_fire.js?v=339f371e:38295
call @ @ad_fire.js?v=339f371e:38300
emit @ @ad_fire.js?v=339f371e:38345
(anonymous) @ @ad_fire.js?v=339f371e:20933
(anonymous) @ @ad_fire.js?v=339f371e:20933
callback @ @ad_fire.js?v=339f371e:38276
processEvent @ @ad_fire.js?v=339f371e:38387
dispatchEvent @ @ad_fire.js?v=339f371e:38379
dispatchEvent @ @ad_fire.js?v=339f371e:38418
callback @ @ad_fire.js?v=339f371e:38276
processEvent @ @ad_fire.js?v=339f371e:38387
dispatchEvent @ @ad_fire.js?v=339f371e:38379
dispatchEvent @ @ad_fire.js?v=339f371e:38418
callback @ @ad_fire.js?v=339f371e:38276
processEvent @ @ad_fire.js?v=339f371e:38387
dispatchEvent @ @ad_fire.js?v=339f371e:38379
dispatchEvent @ @ad_fire.js?v=339f371e:38418
callback @ @ad_fire.js?v=339f371e:38276
processEvent @ @ad_fire.js?v=339f371e:38387
dispatchEvent @ @ad_fire.js?v=339f371e:38379
dispatchEvent @ @ad_fire.js?v=339f371e:38418
(anonymous) @ @ad_fire.js?v=339f371e:29765
Promise.then
processInput @ @ad_fire.js?v=339f371e:29764
processInput @ @ad_fire.js?v=339f371e:30227
(anonymous) @ @ad_fire.js?v=339f371e:30224
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
frame @ @ad_fire.js?v=339f371e:17426
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
requestAnimationFrame
frameAutomatic @ @ad_fire.js?v=339f371e:17415
executeCallbacks @ @ad_fire.js?v=339f371e:17433
processPhase @ @ad_fire.js?v=339f371e:17429
(anonymous) @ @ad_fire.js?v=339f371e:17415
@ad_fire.js?v=339f371e:21578 Uncaught TypeError: Cannot read properties of undefined (reading 'getBounds')
    at get localBounds (@ad_fire.js?v=339f371e:21578:92)
    at @ad_fire.js?v=339f371e:20478:12
    at mr.iterateComponents (@ad_fire.js?v=339f371e:19220:67)
    at mr.collectBounds (@ad_fire.js?v=339f371e:20477:50)
    at mr.collectBounds (@ad_fire.js?v=339f371e:20479:57)
    at get bounds (@ad_fire.js?v=339f371e:20472:23)
    at @ad_fire.js?v=339f371e:29715:20
    at Array.forEach (<anonymous>)
    at c.collectBounds (@ad_fire.js?v=339f371e:29714:10)
    at c.onSelectableUpdated (@ad_fire.js?v=339f371e:29690:36)


read properties of undefined (reading 'getBounds')     at get localBounds (@ad_fire.js?v=339f371e:21578:92)     at @ad_fire.js?v=339f371e:20478:12     at mr.iterateComponents (@ad_fire.js?v=339f371e:1…


Der Crash bleibt — er kommt beim Bounds-Sammeln des selektierten Elements, das in den Marker (sein Kind) hineinläuft. Ich schaue nach, welche Komponente in `localBounds` das `undefined` liefert.


cd /Users/marcus.hinz/projects/adesso-cpq
F=node_modules/.pnpm/@ad+fire@1.0.6/node_modules/@ad/fire/browser/index.js
node -e '
const fs=require("fs");const s=fs.readFileSync(process.argv[1],"utf8");
// find all "get localBounds" occurrences with context
let i=0,c=0;
while((i=s.indexOf("get localBounds",i+1))>=0 && c<12){
  console.log("=== @"+i);
  console.log(s.slice(i-140,i+140).replace(/\n/g," "));
  c++;
}
' "$F"

Find localBounds getters and their component classes


=== @490859
s._settings.selectable!=e&&(this._settings.selectable=e,this.sync(x.selectable))}isSelectionClickable(){return this.active&&this.selectable}get localBounds(){return l.Bounds.createFromVertices(...w(.1))}get bounds(){return this.localBounds.transform(this.LTW)}getTransformationPro
=== @496285
erial",`input must be of renderingType '${o.RenderTypeMask[o.RenderTypeMask.mesh]}'`))}),this._settings.materials=e,this.sync(b.materials))}get localBounds(){return this._localBounds}validateSettings(e){if(!(e=super.validateSettings(e)).geometry)throw new Error((0,c.notDefined)(t
=== @958336
s.receiveShadow}set receiveShadow(e){null!=e&&e!=this._settings.receiveShadow&&(this._settings.receiveShadow=e,this.sync(rn.receiveShadow))}get localBounds(){return this._settings.geometry?this._settings.geometry.bounds:o.Bounds.zero}constructor(e){super(e)}initSynchronizable(){s
=== @961508
s.receiveShadow}set receiveShadow(e){null!=e&&e!=this._settings.receiveShadow&&(this._settings.receiveShadow=e,this.sync(rn.receiveShadow))}get localBounds(){return this._settings.geometry?this._settings.geometry.bounds:o.Bounds.zero}constructor(e){super(e)}initSynchronizable(){s
=== @1015489
turn this.settings.handleIndex}get bounds(){return this._bounds||(this._bounds=this.descriptor.getBounds(this.shape,this.ltw)),this._bounds}get localBounds(){return this.shapeDescriptorManager.get(this.shape.shapeType).getLocalBounds(this.shape,this.ltw)}get geometry(){return[thi
=== @1020555
triggersSelection}set triggersSelection(e){this._settings.triggersSelection=e}get name(){return`${this.handle.name}|${this.tags.join("-")}`}get localBounds(){return o.Bounds.createFromBoundArray(this.shapeDescriptorManager.get(this.shapeType).getBounds(this.shape,o.Matrix4_4.iden
=== @1657241
gs.selectable!==e&&(this._settings.selectable=e,this.sync(i.selectable))}get childIndex(){return this.handle.getComponents(o).indexOf(this)}get localBounds(){const e=this.diameter/2;switch(this.type){case r.point:case r.adapter:return new u.Bounds(this.localPosition,new u.Vector3


Der Crash sitzt im Collider-`localBounds`: `shapeDescriptorManager.get(shapeType).getBounds(...)` — der Descriptor ist `undefined`, unser Collider-Spec passt nicht. Ich schaue, wie ein echter Collider in den Szenen-JSONs aussieht.


cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
grep -rln "component_collider" .storybook src public 2>/dev/null | head
echo "=== example ==="
node -e '
const fs=require("fs");
const {execSync}=require("child_process");
const files=execSync("grep -rl component_collider .storybook src public 2>/dev/null").toString().trim().split("\n").filter(Boolean);
for(const f of files.slice(0,3)){
  const s=fs.readFileSync(f,"utf8");
  const i=s.indexOf("component_collider");
  console.log("### "+f);
  console.log(s.slice(i-40,i+300));
}
'

Find real collider serialization examples


Error: Exit code 1
.storybook/products/schutzzaun_basic/SBE0389SNA.json
.storybook/products/schutzzaun_basic/SBE1034PNA.json
.storybook/products/schutzzaun_basic/SBE0518PNA.json
.storybook/products/schutzzaun_basic/SBE1120SNA.json
.storybook/products/schutzzaun_basic/SBF0872PRA.json
.storybook/products/schutzzaun_basic/SBE0604PNA.json
.storybook/products/schutzzaun_basic/SBE0819PNA.json
.storybook/products/schutzzaun_basic/SBS1044PRA.json
.storybook/products/schutzzaun_basic/SBE1249PNA.json
.storybook/products/schutzzaun_basic/SBE0475SNA.json
=== example ===
node:child_process:1001
    throw err;
    ^

Error: Command failed: grep -rl component_collider .storybook src public 2>/dev/null
    at genericNodeError (node:internal/errors:998:15)
    at wrappedFn (node:internal/errors:543:14)
    at checkExecSyncError (node:child_process:926:11)
    at execSync (node:child_process:998:15)
    at [eval]:4:13
    at runScriptInThisContext (node:internal/vm:219:10)
    at node:internal/process/execution:483:12
    at [eval]-wrapper:6:24
    at runScriptInContext (node:internal/process/execution:481:60)
    at evalFunction (node:internal/process/execution:315:30) {
  status: 2,
  signal: null,
  output: [
    null,
    Buffer(33470) [Uint8Array] [
       46, 115, 116, 111, 114, 121,  98, 111, 111, 107,  47, 112,
      114, 111, 100, 117,  99, 116, 115,  47, 115,  99, 104, 117,
      116, 122, 122,  97, 117, 110,  95,  98,  97, 115, 105,  99,
       47,  83,  66,  83,  49,  48,  52,  52,  80,  82,  65,  46,
      106, 115, 111, 110,  10,  46, 115, 116, 111, 114, 121,  98,
      111, 111, 107,  47, 112, 114, 111, 100, 117,  99, 116, 115,
       47, 115,  99, 104, 117, 116, 122, 122,  97, 117, 110,  95,
       98,  97, 115, 105,  99,  47,  83,  66,  69,  49,  49,  54,
       51,  80,  78,  65,
      ... 33370 more items
    ],
    Buffer(0) [Uint8Array] []
  ],
  pid: 36508,
  stdout: Buffer(33470) [Uint8Array] [
     46, 115, 116, 111, 114, 121,  98, 111, 111, 107,  47, 112,
    114, 111, 100, 117,  99, 116, 115,  47, 115,  99, 104, 117,
    116, 122, 122,  97, 117, 110,  95,  98,  97, 115, 105,  99,
     47,  83,  66,  83,  49,  48,  52,  52,  80,  82,  65,  46,
    106, 115, 111, 110,  10,  46, 115, 116, 111, 114, 121,  98,
    111, 111, 107,  47, 112, 114, 111, 100, 117,  99, 116, 115,
     47, 115,  99, 104, 117, 116, 122, 122,  97, 117, 110,  95,
     98,  97, 115, 105,  99,  47,  83,  66,  69,  49,  49,  54,
     51,  80,  78,  65,
    ... 33370 more items
  ],
  stderr: Buffer(0) [Uint8Array] []
}

Node.js v26.4.0


cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
python3 -c "
import json
f='.storybook/products/schutzzaun_basic/SBS1044PRA.json'
d=json.load(open(f))
import re
s=json.dumps(d)
i=s.find('component_collider')
print(s[i-20:i+400])
"

Show real collider spec from part JSON


{"_resourceClass": "component_collider", "type": 2, "shapeType": 4, "center": [-248.432807922, -168.384811401, -95.0], "dimension": [-79.9999847412, -40.0, -10]}]}, {"id": "X-e7e9d979-2121-426b-9d3a-1949704c8b15", "properties": {"custom-selection": {"type": "string", "value": "parent"}}, "tags": ["name-generic", "pmi-STEHERPROFIL_LINKS"], "components": [{"_resourceClass": "component_transform", "parentKey": "node_EIN


Echte Collider nutzen `shapeType: 4` (Box) mit `dimension`, kein `radius`. Ich prüfe, ob der Sphere-Descriptor (shapeType 2) in diesem Build überhaupt registriert ist.


cd /Users/marcus.hinz/projects/adesso-cpq
F=node_modules/.pnpm/@ad+fire@1.0.6/node_modules/@ad/fire/browser/index.js
node -e '
const fs=require("fs");const s=fs.readFileSync(process.argv[1],"utf8");
for(const t of ["shapeDescriptorManager","ShapeDescriptor","SphereShape","BoxShape","getLocalBounds","shapeType"]){
  let i=s.indexOf(t);
  console.log("=== "+t+" @"+i);
}
// registration of descriptors
let i=0,c=0;
while((i=s.indexOf("ShapeDescriptor",i+1))>=0 && c<10){console.log("@"+i+": "+s.slice(i-60,i+60).replace(/\n/g," "));c++;}
' "$F"

Find shape descriptor registrations


=== shapeDescriptorManager @1015519
=== ShapeDescriptor @608913
=== SphereShape @-1
=== BoxShape @-1
=== getLocalBounds @1006075
=== shapeType @518495
@608913: sitory:()=>qp,ShaderSerializer:()=>ig,ShaderSyncMask:()=>Oe,ShapeDescriptorManager:()=>di,ShapeType:()=>ei,SkyboxConfigu
@610732: Qo,WrapType:()=>pt,WritableTransformationProvider:()=>$n,boxShapeDescriptor:()=>oi,capsuleShapeDescriptor:()=>li,isTypeS
@610762: nsformationProvider:()=>$n,boxShapeDescriptor:()=>oi,capsuleShapeDescriptor:()=>li,isTypeSelectable:()=>hf,meshShapeDesc
@610813: i,capsuleShapeDescriptor:()=>li,isTypeSelectable:()=>hf,meshShapeDescriptor:()=>ii,polyfills:()=>p,resourceClass:()=>ho,
@1013305: riptors[e.shapeType])throw new Error((0,i.logMessage)(this,"ShapeDescriptorManager.register",`'${ei[e.shapeType]}' alrea


Bestätigt: dieser Build registriert nur `boxShapeDescriptor`, `capsuleShapeDescriptor`, `meshShapeDescriptor` — **keinen Sphere-Descriptor**. Ein runder Collider (shapeType 2) existiert nicht, deshalb ist `shapeDescriptorManager.get(2)` undefined und `getBounds` crasht. Das ist der Grund, warum glb- und Geometry-Variante identisch abstürzen: beide hatten den Sphere-Collider.

Ich stelle den Collider auf Box um (shapeType 4 mit `dimension`, exakt wie die echten Bauteile — bewährt, kein Crash). Die sichtbare Kugel bleibt der grüne Sphere-Mesh.


Edit

                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast
                        // hits it and reports the marker as the click target.
                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },

                        // Box collider (shapeType 4) around the PMI — this @ad/fire build registers only
                        // box/capsule/mesh shape descriptors (no sphere), so shapeType 2 has no descriptor and
                        // crashes selection-bounds. triggersSelection defaults true → the raycast hits it and
                        // reports the marker as the click target. The visible marker stays the round mesh above.
                        { _resourceClass: "component_collider", type: 2, shapeType: 4, center: [0, 0, 0], dimension: [80, 80, 80] },


                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast
                        // hits it and reports the marker as the click target.
                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },

                        // Box collider (shapeType 4) around the PMI — this @ad/fire build registers only
                        // box/capsule/mesh shape descriptors (no sphere), so shapeType 2 has no descriptor and
                        // crashes selection-bounds. triggersSelection defaults true → the raycast hits it and
                        // reports the marker as the click target. The visible marker stays the round mesh above.
                        { _resourceClass: "component_collider", type: 2, shapeType: 4, center: [0, 0, 0], dimension: [80, 80, 80] },

geometry: { _resourceClass: "geometry_parametric", parameters: { factoryName: "sphere-3d", diameter: 120 } },

material: { _resourceClass: "material_basic", diffuse: [0, 1, 0], depthTest: false },

-                        // Round collider (shapeType 2 = sphere), triggersSelection defaults true → the raycast

-                        // hits it and reports the marker as the click target.

-                        { _resourceClass: "component_collider", type: 2, shapeType: 2, center: [0, 0, 0], radius: 60 },

+                        // Box collider (shapeType 4) around the PMI — this @ad/fire build registers only

+                        // box/capsule/mesh shape descriptors (no sphere), so shapeType 2 has no descriptor and

+                        // crashes selection-bounds. triggersSelection defaults true → the raycast hits it and

+                        // reports the marker as the click target. The visible marker stays the round mesh above.

+                        { _resourceClass: "component_collider", type: 2, shapeType: 4, center: [0, 0, 0], dimension: [80, 80, 80] },


    // under the element root's transform (PMI positions are element-local), rendered via an inline
    // parametric sphere + basic material, with a round collider so it's clickable. Tagged
    // `name-select-marker`. No selection → scene unchanged.

    // under the element root's transform (PMI positions are element-local), rendered via an inline
    // parametric sphere + basic material, with a box collider so it's clickable (this build has no
    // sphere collider). Tagged `name-select-marker`. No selection → scene unchanged.


    // under the element root's transform (PMI positions are element-local), rendered via an inline
    // parametric sphere + basic material, with a round collider so it's clickable. Tagged
    // `name-select-marker`. No selection → scene unchanged.

    // under the element root's transform (PMI positions are element-local), rendered via an inline
    // parametric sphere + basic material, with a box collider so it's clickable (this build has no
    // sphere collider). Tagged `name-select-marker`. No selection → scene unchanged.

// On selection, drop a small green sphere at every PMI of the selected element(s). The marker hangs

-    // parametric sphere + basic material, with a round collider so it's clickable. Tagged

-    // `name-select-marker`. No selection → scene unchanged.

+    // parametric sphere + basic material, with a box collider so it's clickable (this build has no

+    // sphere collider). Tagged `name-select-marker`. No selection → scene unchanged.

private withSelectionMarkers(scene: any): any {

const roots = new Set(this.selectionElementRoots());


Bash

cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
pnpm exec vue-tsc --noEmit -p tsconfig.json 2>&1 | grep "DefaultCommandProcessor" | head; echo "done"

Typecheck our file


done


Ursache gefunden und behoben.

**Warum beide Varianten identisch crashten:** Der Crash liegt nicht am glb oder an der Geometry, sondern am **Collider**. `localBounds` des Colliders ruft `shapeDescriptorManager.get(shapeType).getBounds(...)`. Dieser `@ad/fire`-Build registriert nur `boxShapeDescriptor`, `capsuleShapeDescriptor`, `meshShapeDescriptor` — **keinen Sphere-Descriptor**. Bei `shapeType: 2` liefert `get(2)` also `undefined`, und `.getBounds` auf `undefined` wirft. Beim Selektieren läuft das Bounds-Sammeln in den Marker (Kind des Elements) und trifft genau diesen Collider.

**Fix:**
- Collider auf `shapeType: 4` (Box) mit `dimension: [80,80,80]` — exakt wie die echten Bauteile, bewährt, kein Crash.
- Sichtbarer Marker bleibt der grüne Sphere-Mesh (`geometry_parametric` `sphere-3d`), also weiterhin rund.
- Alert-Abfang unverändert.

Typecheck sauber.

Einschränkung: einen *runden* Collider gibt dieser Build nicht her (nur Box/Capsule/Mesh). Der Klickbereich ist damit ein Würfel um das PMI; optisch bleibt die Kugel rund. Ein wirklich runder Trefferbereich ginge nur über Capsule (shapeType 16) — anderes Parameter-Schema, das ich bei Bedarf teste.


perfekt
jetzt schränke den Einbau auf die PMIs ein, die mit select beginnen


cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
python3 -c "
import json
d=json.load(open('.storybook/products/schutzzaun_basic/SBS1044PRA.json'))
def walk(o):
    out=[]
    if isinstance(o,dict):
        if o.get('_resourceClass')=='component_pmi': out.append(o)
        for v in o.values(): out+=walk(v)
    elif isinstance(o,list):
        for v in o: out+=walk(v)
    return out
pmis=walk(d)
print('count',len(pmis))
for p in pmis[:6]:
    print(json.dumps(p)[:300])
"

Inspect component_pmi structure in a part


count 23
{"_resourceClass": "component_pmi", "id": "CS_EIN", "tags": ["name-CS_EIN"], "type": "point", "properties": {"position": {"type": "vector3", "value": [-40, -33, 0], "usage": "position"}, "rotation": {"type": "quaternion", "value": [0.0, 4.71238898038469, 0.0], "usage": "rotation"}}}
{"_resourceClass": "component_pmi", "id": "CS_BASE_PRE", "tags": ["name-CS_BASE_PRE"], "type": "point", "properties": {"position": {"type": "vector3", "value": [-40.0, -33.0, 0.0], "usage": "position"}, "rotation": {"type": "quaternion", "value": [1.5707963267948966, -1.5707963267948966, 0.0], "usag
{"_resourceClass": "component_pmi", "id": "CS_BASE", "tags": ["name-CS_BASE"], "type": "point", "properties": {"position": {"type": "vector3", "value": [-40.0, -33.0, 0.0], "usage": "position"}, "rotation": {"type": "quaternion", "value": [-1.5707963267948966, -6.123233995741237e-17, 1.5707963267948
{"_resourceClass": "component_pmi", "id": "CS_EIN_L", "tags": ["name-CS_EIN_L"], "type": "point", "properties": {"position": {"type": "vector3", "value": [-20.0, 1067.0, -20.0], "usage": "position"}, "rotation": {"type": "quaternion", "value": [-0.0, -1.5707963267948966, 0.0], "usage": "rotation"}}}
{"_resourceClass": "component_pmi", "id": "CS_EIN_R", "tags": ["name-CS_EIN_R"], "type": "point", "properties": {"position": {"type": "vector3", "value": [1064.0, 1067.0, -20.0], "usage": "position"}, "rotation": {"type": "quaternion", "value": [-0.0, 1.5707963267948966, 0.0], "usage": "rotation"}}}
{"_resourceClass": "component_pmi", "id": "CS_EIN_START_L", "tags": ["name-CS_EIN_START_L"], "type": "point", "properties": {"position": {"type": "vector3", "value": [-40.0, -33.0, -20.0], "usage": "position"}, "rotation": {"type": "quaternion", "value": [-0.0, -1.5707963267948966, 0.0], "usage": "r


cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
python3 -c "
import json
d=json.load(open('.storybook/products/schutzzaun_basic/SBS1044PRA.json'))
def walk(o):
    out=[]
    if isinstance(o,dict):
        if o.get('_resourceClass')=='component_pmi': out.append(o.get('id'))
        for v in o.values(): out+=walk(v)
    elif isinstance(o,list):
        for v in o: out+=walk(v)
    return out
print([p for p in walk(d)])
"

List all PMI ids to see SELECT naming


['CS_EIN', 'CS_BASE_PRE', 'CS_BASE', 'CS_EIN_L', 'CS_EIN_R', 'CS_EIN_START_L', 'CS_EIN_START_R', 'CS_OUT_R_0', 'CS_OUT_L_0', 'CS_OUT_R_90', 'CS_OUT_L_90', 'CS_OUT_R_90_B', 'CS_OUT_L_90_B', 'CS_OUT_R_270', 'CS_OUT_L_270', 'CS_OUT_R_270_B', 'CS_OUT_L_270_B', 'CS_SELECT_L_0', 'CS_SELECT_R_0', 'CS_SELECT_L_90', 'CS_SELECT_R_90', 'CS_SELECT_L_270', 'CS_SELECT_R_270']


Die Select-PMIs heißen `CS_SELECT_*`. Ich filtere darauf.


Edit

            for (const c of h.components ?? []) {
                if (c._resourceClass !== "component_pmi") continue;
                const pos = c.properties?.position?.value ?? [0, 0, 0];

            for (const c of h.components ?? []) {
                if (c._resourceClass !== "component_pmi") continue;
                // Only the select PMIs (CS_SELECT_*) get a marker, not the docking/base points.
                if (!String(c.id).startsWith("CS_SELECT")) continue;
                const pos = c.properties?.position?.value ?? [0, 0, 0];


            for (const c of h.components ?? []) {
                if (c._resourceClass !== "component_pmi") continue;
                const pos = c.properties?.position?.value ?? [0, 0, 0];

            for (const c of h.components ?? []) {
                if (c._resourceClass !== "component_pmi") continue;
                // Only the select PMIs (CS_SELECT_*) get a marker, not the docking/base points.
                if (!String(c.id).startsWith("CS_SELECT")) continue;
                const pos = c.properties?.position?.value ?? [0, 0, 0];

+                // Only the select PMIs (CS_SELECT_*) get a marker, not the docking/base points.

+                if (!String(c.id).startsWith("CS_SELECT")) continue;


Marker werden jetzt nur noch an den `CS_SELECT_*`-PMIs gesetzt.


abhängig vom gelickten pmi
kopiere die komponente und baue die Kopie in entsprechender orintierung an die Komonente an


Ich schaue mir die vorhandene Dock-Logik (`buildCreateEvent`, `group-merge`, `dockRotation`, `sceneOfElement`) an, um die Kopie korrekt anzubauen.


Bash

cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
grep -n "buildCreateEvent\|sceneOfElement\|dockRotation\|groupIdOfElement\|elementRootOf\|occupiedPmis\|rootHandleId\b" src/configurator/model/GroupProcessor.ts | head -40

Locate GroupProcessor dock helpers


36:// one place identity is minted — buildCreateEvent (which both product-add and copy funnel through)
38:export function instantiateScene(scene: Scene): { handles: Handle[]; rootHandleId: string } {
53:    let rootHandleId = "";
62:                rootHandleId = handle.id;
66:    return { handles: src.handles, rootHandleId };
94:    rootHandleId: string; // the element root among `handles`
170:    buildCreateEvent(productScene: Scene, position: Vec3): GroupCreateEvent {
171:        const { handles, rootHandleId } = instantiateScene(productScene);
177:            rootHandleId,
184:    groupIdOfElement(rootHandleId: string): string | null {
185:        return this.elementToGroup.get(rootHandleId) ?? null;
203:    occupiedPmis(): { element: string; pmi: string }[] {
223:    // element root's parentKey is stripped so buildCreateEvent (via instantiateScene) treats it as a
225:    sceneOfElement(elementRoot: string): { _resourceClass: string; handles: Handle[] } | null {
386:    elementRootOf(handleId: string): string | null {
433:                this.elementHandles.set(event.rootHandleId, cloned);
437:                    members: [event.rootHandleId],
441:                this.elementToGroup.set(event.rootHandleId, event.groupId);
451:                const occupied = this.occupiedPmis();
660:    private pmiLocal(rootHandleId: string, pmiId: string): Vec3 {
661:        const handle = this.handles.get(rootHandleId);
673:    private pmiRotation(rootHandleId: string, pmiId: string): Quat {
674:        const handle = this.handles.get(rootHandleId);
687:    dockRotation(anchorRoot: string, anchorPmi: string, joinRoot: string, joinPmi: string): Quat {


abhängig vom gelickten pmi kopiere die komponente und baue die Kopie in entsprechender orintierung an die Komonente an


160	    // valid CSS identifier — a bare UUID can start with a digit, which breaks the "#id" selector.
161	    private nextId(prefix: string): string {
162	        return `${prefix}-${crypto.randomUUID()}`;
163	    }
164
165	    // ---- record-time -------------------------------------------------------
166
167	    // Build a create event from a product scene (or a copied subtree): re-identify it via
168	    // instantiateScene (source ids repeat across instances), find the element root, and bake the
169	    // prepared subtree into the event so replay is deterministic.
170	    buildCreateEvent(productScene: Scene, position: Vec3): GroupCreateEvent {
171	        const { handles, rootHandleId } = instantiateScene(productScene);
172	        return {
173	            type: "group-create",
174	            timestamp: Date.now(),
175	            groupId: this.nextId("g"),
176	            groupKey: this.nextId("gk"),
177	            rootHandleId,
178	            handles,
179	            position,
180	            rotation: IDENTITY_QUAT,
181	        };
182	    }
183
184	    groupIdOfElement(rootHandleId: string): string | null {
185	        return this.elementToGroup.get(rootHandleId) ?? null;
186	    }
187
188	    groupByKey(key: string): string | null {
189	        for (const g of this.groups.values()) if (g.key === key) return g.id;
190	        return null;
191	    }
192
193	    groupKeyOf(groupId: string): string | null {
194	        return this.groups.get(groupId)?.key ?? null;
195	    }
196
197	    transformOf(groupId: string): Transform | null {
198	        return this.groups.get(groupId)?.transform ?? null;
199	    }
200
201	    // Docking points already in use, derived purely from the edges (no stored state). Each edge
202	    // occupies its `fromPmi` on `from` and its `toPmi` on `to`. Open ends are everything else.
203	    occupiedPmis(): { element: string; pmi: string }[] {
204	        const out: { element: string; pmi: string }[] = [];
205	        for (const g of this.groups.values()) {
206	            for (const e of g.edges) {
207	                out.push({ element: e.from, pmi: e.fromPmi });
208	                out.push({ element: e.to, pmi: e.toPmi });
209	            }

    // valid CSS identifier — a bare UUID can start with a digit, which breaks the "#id" selector.
    private nextId(prefix: string): string {
        return `${prefix}-${crypto.randomUUID()}`;
    }

    // ---- record-time -------------------------------------------------------

    // Build a create event from a product scene (or a copied subtree): re-identify it via
    // instantiateScene (source ids repeat across instances), find the element root, and bake the
    // prepared subtree into the event so replay is deterministic.
    buildCreateEvent(productScene: Scene, position: Vec3): GroupCreateEvent {
        const { handles, rootHandleId } = instantiateScene(productScene);
        return {
            type: "group-create",
            timestamp: Date.now(),
            groupId: this.nextId("g"),
            groupKey: this.nextId("gk"),
            rootHandleId,
            handles,
            position,
            rotation: IDENTITY_QUAT,
        };
    }

    groupIdOfElement(rootHandleId: string): string | null {
        return this.elementToGroup.get(rootHandleId) ?? null;
    }

    groupByKey(key: string): string | null {
        for (const g of this.groups.values()) if (g.key === key) return g.id;
        return null;
    }

    groupKeyOf(groupId: string): string | null {
        return this.groups.get(groupId)?.key ?? null;
    }

    transformOf(groupId: string): Transform | null {
        return this.groups.get(groupId)?.transform ?? null;
    }

    // Docking points already in use, derived purely from the edges (no stored state). Each edge
    // occupies its `fromPmi` on `from` and its `toPmi` on `to`. Open ends are everything else.
    occupiedPmis(): { element: string; pmi: string }[] {
        const out: { element: string; pmi: string }[] = [];
        for (const g of this.groups.values()) {
            for (const e of g.edges) {
                out.push({ element: e.from, pmi: e.fromPmi });
                out.push({ element: e.to, pmi: e.toPmi });
            }


Ich ersetze den Alert durch das Anbauen der Kopie. Mapping: `CS_SELECT_<Seite>_<Winkel>` → Anker `CS_OUT_<Seite>_<Winkel>`, Join `CS_EIN_L` (Seite R) bzw. `CS_EIN_R` (Seite L); Orientierung über `dockRotation` aus den PMI-Frames.


Edit

        const stop: UIReaction = { type: "sendCommand", cmd: "stop_interaction_mode", args: [] };
        // Intercept a click on one of our PMI marker spheres — pop an alert with the hit PMI.
        const targetId: unknown = event.target?.id;
        if (typeof targetId === "string" && targetId.startsWith("sel-marker-")) {
            const pmi = targetId.slice(targetId.lastIndexOf("-") + 1);
            const element = targetId.slice("sel-marker-".length, targetId.lastIndexOf("-"));
            return [{ type: "dialog", title: "PMI-Marker", message: `Klick auf PMI ${pmi}\nElement ${element}` }];
        }

        const stop: UIReaction = { type: "sendCommand", cmd: "stop_interaction_mode", args: [] };
        // Intercept a click on one of our select-PMI marker spheres — dock a copy of the element there.
        const targetId: unknown = event.target?.id;
        if (typeof targetId === "string" && targetId.startsWith("sel-marker-")) {
            const pmi = targetId.slice(targetId.lastIndexOf("-") + 1);
            const element = targetId.slice("sel-marker-".length, targetId.lastIndexOf("-"));
            return this.handleMarkerBuild(element, pmi, stop);
        }


        const stop: UIReaction = { type: "sendCommand", cmd: "stop_interaction_mode", args: [] };
        // Intercept a click on one of our PMI marker spheres — pop an alert with the hit PMI.
        const targetId: unknown = event.target?.id;
        if (typeof targetId === "string" && targetId.startsWith("sel-marker-")) {
            const pmi = targetId.slice(targetId.lastIndexOf("-") + 1);
            const element = targetId.slice("sel-marker-".length, targetId.lastIndexOf("-"));
            return [{ type: "dialog", title: "PMI-Marker", message: `Klick auf PMI ${pmi}\nElement ${element}` }];
        }

        const stop: UIReaction = { type: "sendCommand", cmd: "stop_interaction_mode", args: [] };
        // Intercept a click on one of our select-PMI marker spheres — dock a copy of the element there.
        const targetId: unknown = event.target?.id;
        if (typeof targetId === "string" && targetId.startsWith("sel-marker-")) {
            const pmi = targetId.slice(targetId.lastIndexOf("-") + 1);
            const element = targetId.slice("sel-marker-".length, targetId.lastIndexOf("-"));
            return this.handleMarkerBuild(element, pmi, stop);
        }

// the set, or toggles it off if already in. fire is driven with the full set via set_selection.

private handleSelectionClickEvent(event: any): UIReaction[] {

-        // Intercept a click on one of our PMI marker spheres — pop an alert with the hit PMI.

+        // Intercept a click on one of our select-PMI marker spheres — dock a copy of the element there.

-            return [{ type: "dialog", title: "PMI-Marker", message: `Klick auf PMI ${pmi}\nElement ${element}` }];

+            return this.handleMarkerBuild(element, pmi, stop);

const additive = event.selectionAction === "add";


Jetzt die Methode. Ich platziere sie direkt nach `handleSelectionClickEvent`:


    // Right-click escalation: only meaningful for a single selected pick; bump it one level.
    private handleEscalateSelection(event: any): UIReaction[] {

    // A clicked select marker (CS_SELECT_<side>_<angle>) docks a copy of its element onto the matching
    // open end: the anchor is the corresponding CS_OUT point, the copy joins with CS_EIN_L (right side)
    // or CS_EIN_R (left side), and the branch orientation (0/90/270) follows from the PMI frames via
    // dockRotation. Occupied ends do nothing. Selection stays on the original so its markers re-render.
    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {
        this.replay();
        const anchorPmi = pmi.replace("CS_SELECT_", "CS_OUT_");
        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";
        const groupId = this.groups.groupIdOfElement(element);
        const scene = this.groups.sceneOfElement(element);
        if (!groupId || !scene) return [stop];
        if (this.groups.occupiedPmis().some((o) => o.element === element && o.pmi === anchorPmi)) {
            return [stop]; // that end is already taken
        }
        const createEvent = this.groups.buildCreateEvent(scene as never, [0, 0, 0]);
        this.eventStore.push(createEvent);
        this.eventStore.push({
            type: "group-merge",
            timestamp: Date.now(),
            targetGroupId: groupId,
            movingGroupId: createEvent.groupId,
            anchorRootId: element,
            joinRootId: createEvent.rootHandleId,
            anchorPmiId: anchorPmi,
            joinPmiId: joinPmi,
            rot: this.groups.dockRotation(element, anchorPmi, createEvent.rootHandleId, joinPmi),
        } as GroupEvent);
        return this.selectionReactions(stop);
    }

    // Right-click escalation: only meaningful for a single selected pick; bump it one level.
    private handleEscalateSelection(event: any): UIReaction[] {


    // A clicked select marker (CS_SELECT_<side>_<angle>) docks a copy of its element onto the matching
    // open end: the anchor is the corresponding CS_OUT point, the copy joins with CS_EIN_L (right side)
    // or CS_EIN_R (left side), and the branch orientation (0/90/270) follows from the PMI frames via
    // dockRotation. Occupied ends do nothing. Selection stays on the original so its markers re-render.
    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {
        this.replay();
        const anchorPmi = pmi.replace("CS_SELECT_", "CS_OUT_");
        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";
        const groupId = this.groups.groupIdOfElement(element);
        const scene = this.groups.sceneOfElement(element);
        if (!groupId || !scene) return [stop];
        if (this.groups.occupiedPmis().some((o) => o.element === element && o.pmi === anchorPmi)) {
            return [stop]; // that end is already taken
        }
        const createEvent = this.groups.buildCreateEvent(scene as never, [0, 0, 0]);
        this.eventStore.push(createEvent);
        this.eventStore.push({
            type: "group-merge",
            timestamp: Date.now(),
            targetGroupId: groupId,
            movingGroupId: createEvent.groupId,
            anchorRootId: element,
            joinRootId: createEvent.rootHandleId,
            anchorPmiId: anchorPmi,
            joinPmiId: joinPmi,
            rot: this.groups.dockRotation(element, anchorPmi, createEvent.rootHandleId, joinPmi),
        } as GroupEvent);
        return this.selectionReactions(stop);
    }

    // Right-click escalation: only meaningful for a single selected pick; bump it one level.
    private handleEscalateSelection(event: any): UIReaction[] {

+    // A clicked select marker (CS_SELECT_<side>_<angle>) docks a copy of its element onto the matching

+    // open end: the anchor is the corresponding CS_OUT point, the copy joins with CS_EIN_L (right side)

+    // or CS_EIN_R (left side), and the branch orientation (0/90/270) follows from the PMI frames via

+    // dockRotation. Occupied ends do nothing. Selection stays on the original so its markers re-render.

+    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {

+        const anchorPmi = pmi.replace("CS_SELECT_", "CS_OUT_");

+        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";

+        const groupId = this.groups.groupIdOfElement(element);

+        const scene = this.groups.sceneOfElement(element);

+        if (!groupId || !scene) return [stop];

+        if (this.groups.occupiedPmis().some((o) => o.element === element && o.pmi === anchorPmi)) {

+            return [stop]; // that end is already taken

+        const createEvent = this.groups.buildCreateEvent(scene as never, [0, 0, 0]);

+        this.eventStore.push(createEvent);

+            movingGroupId: createEvent.groupId,

+            joinRootId: createEvent.rootHandleId,

+            rot: this.groups.dockRotation(element, anchorPmi, createEvent.rootHandleId, joinPmi),

+        return this.selectionReactions(stop);


Bash

cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
pnpm exec vue-tsc --noEmit -p tsconfig.json 2>&1 | grep "DefaultCommandProcessor" | head; echo "done"

Typecheck our file


done


Umgesetzt. Klick auf einen `CS_SELECT_*`-Marker:

- Anker = `CS_OUT_*` (gleiche Seite/Winkel, z. B. `CS_SELECT_R_90` → `CS_OUT_R_90`).
- Join der Kopie = `CS_EIN_L` bei Seite R, `CS_EIN_R` bei Seite L.
- Orientierung (0/90/270) kommt aus `dockRotation` über die PMI-Frames.
- Bereits belegtes Ende → nichts.
- Kopie via `buildCreateEvent` (frische IDs) + `group-merge`; Original bleibt selektiert, Marker werden neu gesetzt.

Typecheck sauber.


Die Winkel zuornung passt glaube ich nicht


cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
python3 -c "
import json
d=json.load(open('.storybook/products/schutzzaun_basic/SBS1044PRA.json'))
def walk(o):
    out=[]
    if isinstance(o,dict):
        if o.get('_resourceClass')=='component_pmi': out.append(o)
        for v in o.values(): out+=walk(v)
    elif isinstance(o,list):
        for v in o: out+=walk(v)
    return out
for p in walk(d):
    i=p['id']
    if i.startswith('CS_OUT') or i.startswith('CS_SELECT') or i.startswith('CS_EIN'):
        pos=p['properties']['position']['value']
        rot=p['properties'].get('rotation',{}).get('value')
        print(f'{i:20} pos={pos} rot={rot}')
"

Dump OUT/SELECT/EIN positions and rotations


CS_EIN               pos=[-40, -33, 0] rot=[0.0, 4.71238898038469, 0.0]
CS_EIN_L             pos=[-20.0, 1067.0, -20.0] rot=[-0.0, -1.5707963267948966, 0.0]
CS_EIN_R             pos=[1064.0, 1067.0, -20.0] rot=[-0.0, 1.5707963267948966, 0.0]
CS_EIN_START_L       pos=[-40.0, -33.0, -20.0] rot=[-0.0, -1.5707963267948966, 0.0]
CS_EIN_START_R       pos=[1084.0, -33.0, -20.0] rot=[-0.0, 1.5707963267948966, 0.0]
CS_OUT_R_0           pos=[1114.0, 1067.0, -20.0] rot=[-0.0, -1.5707963267948966, 0.0]
CS_OUT_L_0           pos=[-70.0, 1067.0, -20.0] rot=[-0.0, 1.5707963267948966, 0.0]
CS_OUT_R_90          pos=[1064.0, 1067.0, -110.0] rot=[0.0, -2.449293598299986e-16, 0.0]
CS_OUT_L_90          pos=[-20.0, 1067.0, -110.0] rot=[0.0, -2.449293598299986e-16, 0.0]
CS_OUT_R_90_B        pos=[1114.0, 1067.0, -20.0] rot=[0.0, -2.449293598299986e-16, 0.0]
CS_OUT_L_90_B        pos=[-70.0, 1067.0, -20.0] rot=[0.0, -2.449293598299986e-16, 0.0]
CS_OUT_R_270         pos=[1064.0, 1067.0, 30.0] rot=[3.141592653589793, 3.673940397441252e-16, 3.141592653589793]
CS_OUT_L_270         pos=[-20.0, 1067.0, 30.0] rot=[3.141592653589793, 3.673940397441252e-16, 3.141592653589793]
CS_OUT_R_270_B       pos=[1114.0, 1067.0, -20.0] rot=[3.141592653589793, 3.673940397441252e-16, 3.141592653589793]
CS_OUT_L_270_B       pos=[-70.0, 1067.0, -20.0] rot=[3.141592653589793, 3.673940397441252e-16, 3.141592653589793]
CS_SELECT_L_0        pos=[-340.0, 1067.0, -20.0] rot=[-0.0, -1.5707963267948966, 0.0]
CS_SELECT_R_0        pos=[1384.0, 1067.0, -20.0] rot=[-0.0, 1.5707963267948966, 0.0]
CS_SELECT_L_90       pos=[-40.0, 1067.0, -340.0] rot=[3.141592653589793, 3.673940397441252e-16, 3.141592653589793]
CS_SELECT_R_90       pos=[1084.0, 1067.0, -340.0] rot=[3.141592653589793, 3.673940397441252e-16, 3.141592653589793]
CS_SELECT_L_270      pos=[-40.0, 1067.0, 300.0] rot=[0.0, -2.449293598299986e-16, 0.0]
CS_SELECT_R_270      pos=[1084.0, 1067.0, 300.0] rot=[0.0, -2.449293598299986e-16, 0.0]


Ich sehe es in den PMI-Daten. Die Rotationen:

- `CS_SELECT_*_90` rot = `[π, 0, π]` → das ist die Rotation von `CS_OUT_*_270`, **nicht** von `CS_OUT_*_90` (die ist `[0, 0, 0]`).
- `CS_SELECT_*_270` rot = `[0, 0, 0]` → das ist die Rotation von `CS_OUT_*_90`.

Die 90/270-Frames sind zwischen SELECT und OUT vertauscht. Da `dockRotation` die Kopie am Anker-Frame ausrichtet, muss ein `_90`-Marker auf `CS_OUT_*_270` docken und umgekehrt. `_0` bleibt.


Edit

    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {
        this.replay();
        const anchorPmi = pmi.replace("CS_SELECT_", "CS_OUT_");
        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";

    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {
        this.replay();
        // Map the select marker to its dock anchor. The 90/270 branch frames are swapped between the
        // CS_SELECT points and the CS_OUT points (a CS_SELECT_*_90 carries the CS_OUT_*_270 frame and
        // vice versa), so swap the angle suffix; _0 stays. dockRotation then orients the copy.
        const base = pmi.replace("CS_SELECT_", "CS_OUT_");
        const anchorPmi = base.endsWith("_90") ? base.slice(0, -3) + "_270"
            : base.endsWith("_270") ? base.slice(0, -4) + "_90"
            : base;
        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";


    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {
        this.replay();
        const anchorPmi = pmi.replace("CS_SELECT_", "CS_OUT_");
        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";

    private handleMarkerBuild(element: string, pmi: string, stop: UIReaction): UIReaction[] {
        this.replay();
        // Map the select marker to its dock anchor. The 90/270 branch frames are swapped between the
        // CS_SELECT points and the CS_OUT points (a CS_SELECT_*_90 carries the CS_OUT_*_270 frame and
        // vice versa), so swap the angle suffix; _0 stays. dockRotation then orients the copy.
        const base = pmi.replace("CS_SELECT_", "CS_OUT_");
        const anchorPmi = base.endsWith("_90") ? base.slice(0, -3) + "_270"
            : base.endsWith("_270") ? base.slice(0, -4) + "_90"
            : base;
        const joinPmi = pmi.includes("_R_") ? "CS_EIN_L" : "CS_EIN_R";

// dockRotation. Occupied ends do nothing. Selection stays on the original so its markers re-render.

-        const anchorPmi = pmi.replace("CS_SELECT_", "CS_OUT_");

+        // Map the select marker to its dock anchor. The 90/270 branch frames are swapped between the

+        // CS_SELECT points and the CS_OUT points (a CS_SELECT_*_90 carries the CS_OUT_*_270 frame and

+        // vice versa), so swap the angle suffix; _0 stays. dockRotation then orients the copy.

+        const base = pmi.replace("CS_SELECT_", "CS_OUT_");

+        const anchorPmi = base.endsWith("_90") ? base.slice(0, -3) + "_270"

const groupId = this.groups.groupIdOfElement(element);

const scene = this.groups.sceneOfElement(element);


Bash

cd /Users/marcus.hinz/projects/adesso-cpq/packages/frontend
pnpm exec vue-tsc --noEmit -p tsconfig.json 2>&1 | grep "DefaultCommandProcessor" | head; echo "done"

Typecheck our file


Angezogen: `_90` dockt jetzt auf `CS_OUT_*_270`, `_270` auf `CS_OUT_*_90`, `_0` unverändert. Grund ist die vertauschte Frame-Zuordnung in den PMI-Rotationen. Typecheck sauber — bitte visuell prüfen.


Wenn ich auf _0 klicke, baout er nach vorn


`_0` baut nach vorn statt gerade — also stimmt auch die 0-Zuordnung bzw. die Rotation nicht. Ich schaue mir `dockRotation` und die Merge-Anwendung genau an, statt weiter zu raten.