@rslsp1/fa-app-tools 10.3.2 → 10.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/StageEngine-O5I654LD.js +1243 -0
- package/dist/StageEngine-PYWITIIY.mjs +1243 -0
- package/dist/{chunk-ACB2543O.js → chunk-DDH2SGZM.js} +113 -20
- package/dist/{chunk-TFWIMFNF.mjs → chunk-GKLCL2VQ.mjs} +111 -18
- package/dist/{chunk-HFX6D53W.js → chunk-VSHSZEGV.js} +1810 -606
- package/dist/{chunk-JP7LIWDR.mjs → chunk-XLNA2BD6.mjs} +1448 -244
- package/dist/index.d.mts +53 -2
- package/dist/index.d.ts +53 -2
- package/dist/index.js +265 -106
- package/dist/index.mjs +531 -372
- package/dist/szenen.d.mts +610 -279
- package/dist/szenen.d.ts +610 -279
- package/dist/szenen.js +75 -29
- package/dist/szenen.mjs +48 -2
- package/package.json +1 -1
- package/dist/StageEngine-3MOBM2WX.mjs +0 -590
- package/dist/StageEngine-5VR3KEZB.js +0 -590
|
@@ -8,14 +8,19 @@ import {
|
|
|
8
8
|
CAMERA_ASPECT_RATIOS,
|
|
9
9
|
STAGE_CATALOGUE,
|
|
10
10
|
checkCameraAspectRatioChanges,
|
|
11
|
+
distinctPreviewColor,
|
|
12
|
+
facingRotationZ,
|
|
11
13
|
frozenCameraAspectRatio,
|
|
14
|
+
normalizePreviewColor,
|
|
15
|
+
previewColorConflicts,
|
|
16
|
+
previewColorLegibility,
|
|
12
17
|
roundMeters,
|
|
13
18
|
stageColor,
|
|
14
19
|
stageColors,
|
|
15
20
|
stageFrame,
|
|
16
21
|
stageTypeLabel,
|
|
17
22
|
withStagePositions
|
|
18
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GKLCL2VQ.mjs";
|
|
19
24
|
|
|
20
25
|
// src/lib/szenen/szenenSnapshot.ts
|
|
21
26
|
var SZENEN_SNAPSHOT_SCHEMA_VERSION = 1;
|
|
@@ -442,6 +447,98 @@ async function hfLoadImageAsBase64(id, token, namespace, filename, on404, mimeTy
|
|
|
442
447
|
return result === "ABORT" ? null : result;
|
|
443
448
|
}
|
|
444
449
|
|
|
450
|
+
// src/lib/szenen/stageMigration.ts
|
|
451
|
+
var STAGE_MIGRATION_ID = "stage_floor_center_v1";
|
|
452
|
+
var STAGE_MIGRATION_EVENT = "szenen.stage_convention_migrated";
|
|
453
|
+
function migrateNode(node, report, source) {
|
|
454
|
+
if (!node.proxy_3d || node.proxy_3d.origin === "floor_center") return structuredClone(node);
|
|
455
|
+
const proxy = node.proxy_3d, d = proxy.dimensions;
|
|
456
|
+
if (!Array.isArray(d) || d.length !== 3 || d.some((v) => !Number.isFinite(v) || v <= 0)) throw new Error(`${source}/${node.node_id}: ung\xFCltige Proxy-Ma\xDFe.`);
|
|
457
|
+
let shape;
|
|
458
|
+
if (node.label === "Mensch" || node.type === "subject") shape = { primitive: "humanoid_proxy", pose_ref: "standing", morph: { build: 0.5, gender: 0.5 } };
|
|
459
|
+
else if (node.label === "Stuhl") shape = { primitive: "furniture_proxy", variant: "chair" };
|
|
460
|
+
else if (node.label === "Tisch" || node.type === "surface") shape = { primitive: "furniture_proxy", variant: "table" };
|
|
461
|
+
else if (node.label === "Lampe" || node.type === "light") shape = { primitive: "furniture_proxy", variant: "floor_lamp" };
|
|
462
|
+
else {
|
|
463
|
+
shape = { primitive: "box" };
|
|
464
|
+
report.remaining_boxes.push(`${source}/${node.node_id}`);
|
|
465
|
+
}
|
|
466
|
+
const anchors = node.anchors && Object.fromEntries(Object.entries(node.anchors).map(([key, value2]) => {
|
|
467
|
+
const a = value2;
|
|
468
|
+
return [key, [a[0], a[1], a[2] + d[2] / 2]];
|
|
469
|
+
}));
|
|
470
|
+
return { ...node, proxy_3d: { ...proxy, dimensions: [...d], ...shape, origin: "floor_center" }, ...anchors ? { anchors } : {} };
|
|
471
|
+
}
|
|
472
|
+
function prepareStageMigration(state) {
|
|
473
|
+
const report = { remaining_boxes: [], changed_camera_views: [], placements: 0 };
|
|
474
|
+
const entries = [];
|
|
475
|
+
const records = (snapshot) => [
|
|
476
|
+
...snapshot.versions.map((v) => ({ element_id: v.element_id, version_id: v.version_id, before: v.payload })),
|
|
477
|
+
...snapshot.draft ? [{
|
|
478
|
+
element_id: snapshot.element.element_id,
|
|
479
|
+
draft_id: snapshot.draft.draft_id,
|
|
480
|
+
revision: snapshot.draft.revision,
|
|
481
|
+
before: snapshot.draft.payload
|
|
482
|
+
}] : []
|
|
483
|
+
];
|
|
484
|
+
for (const snapshot of state.elements.values()) {
|
|
485
|
+
if (!["scene", "scene_setup"].includes(snapshot.element.type)) continue;
|
|
486
|
+
if (snapshot.draftFork) throw new Error(`Migration: Entwurfskonflikt an ${snapshot.element.element_id} zuerst aufl\xF6sen.`);
|
|
487
|
+
for (const record of records(snapshot)) {
|
|
488
|
+
const source = record.element_id + "/" + ("version_id" in record ? record.version_id : record.draft_id);
|
|
489
|
+
let after;
|
|
490
|
+
if (snapshot.element.type === "scene") {
|
|
491
|
+
if (record.before.nodes === void 0) continue;
|
|
492
|
+
if (!Array.isArray(record.before.nodes)) throw new Error(`${source}: nodes ist keine Liste.`);
|
|
493
|
+
after = { ...record.before, nodes: record.before.nodes.map((n) => migrateNode(n, report, source)) };
|
|
494
|
+
} else {
|
|
495
|
+
const p = record.before;
|
|
496
|
+
const scene = state.elements.get(p.scene_ref?.element_id);
|
|
497
|
+
const link = "draft_id" in record && snapshot.draft?.chain?.links.find((l) => l.field === "scene_ref");
|
|
498
|
+
const scenePayload = link && scene?.draft?.draft_id === link.target_draft_id ? scene.draft.payload : scene?.versions.find((v) => v.version_id === p.scene_ref?.version_id)?.payload;
|
|
499
|
+
if (!scenePayload && (p.placements?.length || p.node_overrides?.some((n) => n.proxy_3d))) throw new Error(`${source}: referenzierte Szene fehlt.`);
|
|
500
|
+
const placements = (p.placements ?? []).map((placement) => {
|
|
501
|
+
const raw = scenePayload?.nodes.find((n) => n.node_id === placement.node_id);
|
|
502
|
+
const override = p.node_overrides?.find((n) => n.node_id === placement.node_id);
|
|
503
|
+
const proxy = override?.proxy_3d ?? raw?.proxy_3d;
|
|
504
|
+
if (!proxy || proxy.origin === "floor_center") return placement;
|
|
505
|
+
if (!Number.isFinite(proxy.dimensions?.[2]) || proxy.dimensions[2] <= 0) throw new Error(`${source}/${placement.node_id}: H\xF6he fehlt.`);
|
|
506
|
+
report.placements++;
|
|
507
|
+
return { ...placement, position: [placement.position[0], placement.position[1], placement.position[2] - proxy.dimensions[2] / 2] };
|
|
508
|
+
});
|
|
509
|
+
for (const camera of p.camera_rig?.cameras ?? []) {
|
|
510
|
+
if (camera.orientation?.mode === "explicit" && camera.orientation.rotation_euler_deg.filter((n) => n !== 0).length >= 2)
|
|
511
|
+
report.changed_camera_views.push(`${source}/${camera.camera_id}`);
|
|
512
|
+
}
|
|
513
|
+
after = {
|
|
514
|
+
...p,
|
|
515
|
+
...p.placements ? { placements } : {},
|
|
516
|
+
...p.node_overrides ? { node_overrides: p.node_overrides.map((n) => {
|
|
517
|
+
const raw = scenePayload?.nodes.find((x) => x.node_id === n.node_id);
|
|
518
|
+
return n.proxy_3d ? { ...n, proxy_3d: migrateNode({ ...raw, ...n }, report, source).proxy_3d } : n;
|
|
519
|
+
}) } : {}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
if (JSON.stringify(after) !== JSON.stringify(record.before)) entries.push({ ...record, after });
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return { migration_id: STAGE_MIGRATION_ID, entries, report };
|
|
526
|
+
}
|
|
527
|
+
function applyStageMigration(state, migration) {
|
|
528
|
+
if (migration.migration_id !== STAGE_MIGRATION_ID) throw new Error("Unbekannte B\xFChnenmigration.");
|
|
529
|
+
for (const entry of migration.entries) {
|
|
530
|
+
const snapshot = state.elements.get(entry.element_id);
|
|
531
|
+
if (!snapshot) throw new Error(`B\xFChnenmigration: Element ${entry.element_id} fehlt.`);
|
|
532
|
+
if (entry.version_id) {
|
|
533
|
+
const version = snapshot.versions.find((v) => v.version_id === entry.version_id);
|
|
534
|
+
if (!version) throw new Error(`B\xFChnenmigration: Version ${entry.version_id} fehlt.`);
|
|
535
|
+
if (JSON.stringify(version.payload) === JSON.stringify(entry.before)) version.payload = structuredClone(entry.after);
|
|
536
|
+
} else if (snapshot.draft && snapshot.draft.draft_id === entry.draft_id && snapshot.draft.revision === entry.revision && JSON.stringify(snapshot.draft.payload) === JSON.stringify(entry.before)) {
|
|
537
|
+
snapshot.draft = { ...snapshot.draft, payload: structuredClone(entry.after), revision: snapshot.draft.revision + 1 };
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
445
542
|
// src/lib/szenen/elementEvents.ts
|
|
446
543
|
var SZENEN_EVENT_PREFIX = "szenen.";
|
|
447
544
|
var SZENEN_EVENT_TYPES = {
|
|
@@ -827,7 +924,9 @@ function reduceElementEvents(events) {
|
|
|
827
924
|
for (const [elementId, snapshot] of snapshots) {
|
|
828
925
|
elements.set(elementId, finalize(elementId, snapshot));
|
|
829
926
|
}
|
|
830
|
-
|
|
927
|
+
const state = { elements, findings };
|
|
928
|
+
for (const event of ordered) if (event.type === STAGE_MIGRATION_EVENT) applyStageMigration(state, event.payload);
|
|
929
|
+
return state;
|
|
831
930
|
}
|
|
832
931
|
var highestRevision = (byRevision) => [...byRevision.keys()].reduce((max, revision) => revision > max ? revision : max, 0);
|
|
833
932
|
function finalize(elementId, snapshot) {
|
|
@@ -2021,7 +2120,7 @@ function applySchema(schema, instance, path, baseId, ctx) {
|
|
|
2021
2120
|
}
|
|
2022
2121
|
function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
2023
2122
|
let valid = true;
|
|
2024
|
-
const
|
|
2123
|
+
const fail4 = (keyword, message) => {
|
|
2025
2124
|
ctx.errors.push({ instancePath: path, message, keyword });
|
|
2026
2125
|
valid = false;
|
|
2027
2126
|
};
|
|
@@ -2032,24 +2131,24 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2032
2131
|
if ("type" in schema) {
|
|
2033
2132
|
const expected = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
2034
2133
|
if (!expected.some((t) => matchesType(instance, t))) {
|
|
2035
|
-
|
|
2134
|
+
fail4("type", `muss ${expected.join(" oder ")} sein, ist ${jsonTypeOf(instance)}`);
|
|
2036
2135
|
}
|
|
2037
2136
|
}
|
|
2038
2137
|
if ("const" in schema && !deepEqual(instance, schema.const)) {
|
|
2039
|
-
|
|
2138
|
+
fail4("const", `muss gleich ${JSON.stringify(schema.const)} sein`);
|
|
2040
2139
|
}
|
|
2041
2140
|
if (Array.isArray(schema.enum) && !schema.enum.some((option) => deepEqual(instance, option))) {
|
|
2042
|
-
|
|
2141
|
+
fail4("enum", `muss einer der erlaubten Werte sein: ${schema.enum.map((v) => JSON.stringify(v)).join(", ")}`);
|
|
2043
2142
|
}
|
|
2044
2143
|
if (typeof instance === "string") {
|
|
2045
2144
|
if (typeof schema.minLength === "number" && instance.length < schema.minLength) {
|
|
2046
|
-
|
|
2145
|
+
fail4("minLength", `muss mindestens ${schema.minLength} Zeichen haben`);
|
|
2047
2146
|
}
|
|
2048
2147
|
if (typeof schema.maxLength === "number" && instance.length > schema.maxLength) {
|
|
2049
|
-
|
|
2148
|
+
fail4("maxLength", `darf hoechstens ${schema.maxLength} Zeichen haben`);
|
|
2050
2149
|
}
|
|
2051
2150
|
if (typeof schema.pattern === "string" && !new RegExp(schema.pattern, "u").test(instance)) {
|
|
2052
|
-
|
|
2151
|
+
fail4("pattern", `muss dem Muster ${schema.pattern} entsprechen`);
|
|
2053
2152
|
}
|
|
2054
2153
|
if (typeof schema.format === "string") {
|
|
2055
2154
|
const check = FORMATS[schema.format];
|
|
@@ -2058,40 +2157,40 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2058
2157
|
`Format "${schema.format}" ist in jsonSchema.ts nicht implementiert.`
|
|
2059
2158
|
);
|
|
2060
2159
|
}
|
|
2061
|
-
if (!check(instance))
|
|
2160
|
+
if (!check(instance)) fail4("format", `muss dem Format ${schema.format} entsprechen`);
|
|
2062
2161
|
}
|
|
2063
2162
|
}
|
|
2064
2163
|
if (typeof instance === "number") {
|
|
2065
2164
|
if (typeof schema.minimum === "number" && instance < schema.minimum) {
|
|
2066
|
-
|
|
2165
|
+
fail4("minimum", `muss >= ${schema.minimum} sein`);
|
|
2067
2166
|
}
|
|
2068
2167
|
if (typeof schema.maximum === "number" && instance > schema.maximum) {
|
|
2069
|
-
|
|
2168
|
+
fail4("maximum", `muss <= ${schema.maximum} sein`);
|
|
2070
2169
|
}
|
|
2071
2170
|
if (typeof schema.exclusiveMinimum === "number" && instance <= schema.exclusiveMinimum) {
|
|
2072
|
-
|
|
2171
|
+
fail4("exclusiveMinimum", `muss > ${schema.exclusiveMinimum} sein`);
|
|
2073
2172
|
}
|
|
2074
2173
|
if (typeof schema.exclusiveMaximum === "number" && instance >= schema.exclusiveMaximum) {
|
|
2075
|
-
|
|
2174
|
+
fail4("exclusiveMaximum", `muss < ${schema.exclusiveMaximum} sein`);
|
|
2076
2175
|
}
|
|
2077
2176
|
if (typeof schema.multipleOf === "number" && schema.multipleOf > 0) {
|
|
2078
2177
|
const quotient = instance / schema.multipleOf;
|
|
2079
|
-
if (!Number.isInteger(quotient))
|
|
2178
|
+
if (!Number.isInteger(quotient)) fail4("multipleOf", `muss ein Vielfaches von ${schema.multipleOf} sein`);
|
|
2080
2179
|
}
|
|
2081
2180
|
}
|
|
2082
2181
|
if (Array.isArray(instance)) {
|
|
2083
2182
|
if (typeof schema.minItems === "number" && instance.length < schema.minItems) {
|
|
2084
|
-
|
|
2183
|
+
fail4("minItems", `muss mindestens ${schema.minItems} Eintraege haben`);
|
|
2085
2184
|
}
|
|
2086
2185
|
if (typeof schema.maxItems === "number" && instance.length > schema.maxItems) {
|
|
2087
|
-
|
|
2186
|
+
fail4("maxItems", `darf hoechstens ${schema.maxItems} Eintraege haben`);
|
|
2088
2187
|
}
|
|
2089
2188
|
if (schema.uniqueItems === true) {
|
|
2090
2189
|
const gesehen = /* @__PURE__ */ new Set();
|
|
2091
2190
|
for (const eintrag of instance) {
|
|
2092
2191
|
const schluessel = canonicalJson(eintrag);
|
|
2093
2192
|
if (gesehen.has(schluessel)) {
|
|
2094
|
-
|
|
2193
|
+
fail4("uniqueItems", "darf keine doppelten Eintraege enthalten");
|
|
2095
2194
|
break;
|
|
2096
2195
|
}
|
|
2097
2196
|
gesehen.add(schluessel);
|
|
@@ -2102,7 +2201,7 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2102
2201
|
const trifft = instance.some(
|
|
2103
2202
|
(eintrag, i) => applySchema(schema.contains, eintrag, `${path}/${i}`, baseId, { ...ctx, errors: probe })
|
|
2104
2203
|
);
|
|
2105
|
-
if (!trifft)
|
|
2204
|
+
if (!trifft) fail4("contains", "muss mindestens einen passenden Eintrag enthalten");
|
|
2106
2205
|
}
|
|
2107
2206
|
if ("items" in schema) {
|
|
2108
2207
|
for (let i = 0; i < instance.length; i++) {
|
|
@@ -2115,10 +2214,10 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2115
2214
|
if (isObject2(instance)) {
|
|
2116
2215
|
const keys = Object.keys(instance);
|
|
2117
2216
|
if (typeof schema.minProperties === "number" && keys.length < schema.minProperties) {
|
|
2118
|
-
|
|
2217
|
+
fail4("minProperties", `muss mindestens ${schema.minProperties} Eigenschaften haben`);
|
|
2119
2218
|
}
|
|
2120
2219
|
if (typeof schema.maxProperties === "number" && keys.length > schema.maxProperties) {
|
|
2121
|
-
|
|
2220
|
+
fail4("maxProperties", `darf hoechstens ${schema.maxProperties} Eigenschaften haben`);
|
|
2122
2221
|
}
|
|
2123
2222
|
if (Array.isArray(schema.required)) {
|
|
2124
2223
|
for (const name of schema.required) {
|
|
@@ -2148,7 +2247,7 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2148
2247
|
if (known.has(name)) continue;
|
|
2149
2248
|
const childPath = `${path}/${escapePointer(name)}`;
|
|
2150
2249
|
if (schema.additionalProperties === false) {
|
|
2151
|
-
|
|
2250
|
+
fail4("additionalProperties", `unbekannte Eigenschaft "${name}"`);
|
|
2152
2251
|
} else if (schema.additionalProperties !== true) {
|
|
2153
2252
|
if (!applySchema(schema.additionalProperties, instance[name], childPath, baseId, ctx)) {
|
|
2154
2253
|
valid = false;
|
|
@@ -2167,7 +2266,7 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2167
2266
|
const anyValid = schema.anyOf.some(
|
|
2168
2267
|
(branch) => applySchema(branch, instance, path, baseId, { ...ctx, errors: probe })
|
|
2169
2268
|
);
|
|
2170
|
-
if (!anyValid)
|
|
2269
|
+
if (!anyValid) fail4("anyOf", "passt auf keine der erlaubten Varianten");
|
|
2171
2270
|
}
|
|
2172
2271
|
if (Array.isArray(schema.oneOf)) {
|
|
2173
2272
|
const probe = [];
|
|
@@ -2175,7 +2274,7 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2175
2274
|
(branch) => applySchema(branch, instance, path, baseId, { ...ctx, errors: probe })
|
|
2176
2275
|
).length;
|
|
2177
2276
|
if (matches !== 1) {
|
|
2178
|
-
|
|
2277
|
+
fail4(
|
|
2179
2278
|
"oneOf",
|
|
2180
2279
|
matches === 0 ? "passt auf keine der erlaubten Varianten" : `passt auf ${matches} Varianten, erlaubt ist genau eine`
|
|
2181
2280
|
);
|
|
@@ -2184,7 +2283,7 @@ function applyKeywords(schema, instance, path, baseId, ctx) {
|
|
|
2184
2283
|
if ("not" in schema) {
|
|
2185
2284
|
const probe = [];
|
|
2186
2285
|
if (applySchema(schema.not, instance, path, baseId, { ...ctx, errors: probe })) {
|
|
2187
|
-
|
|
2286
|
+
fail4("not", "darf hier nicht zutreffen");
|
|
2188
2287
|
}
|
|
2189
2288
|
}
|
|
2190
2289
|
if ("if" in schema) {
|
|
@@ -2711,6 +2810,34 @@ var SZENEN_SCHEMAS = {
|
|
|
2711
2810
|
"string",
|
|
2712
2811
|
"null"
|
|
2713
2812
|
]
|
|
2813
|
+
},
|
|
2814
|
+
"variant": {
|
|
2815
|
+
"type": "string"
|
|
2816
|
+
},
|
|
2817
|
+
"origin": {
|
|
2818
|
+
"type": "string",
|
|
2819
|
+
"const": "floor_center"
|
|
2820
|
+
},
|
|
2821
|
+
"morph": {
|
|
2822
|
+
"type": "object",
|
|
2823
|
+
"properties": {
|
|
2824
|
+
"build": {
|
|
2825
|
+
"type": "number",
|
|
2826
|
+
"minimum": 0,
|
|
2827
|
+
"maximum": 1
|
|
2828
|
+
},
|
|
2829
|
+
"gender": {
|
|
2830
|
+
"type": "number",
|
|
2831
|
+
"minimum": 0,
|
|
2832
|
+
"maximum": 1
|
|
2833
|
+
}
|
|
2834
|
+
},
|
|
2835
|
+
"additionalProperties": false
|
|
2836
|
+
},
|
|
2837
|
+
"preview_color": {
|
|
2838
|
+
"description": "Feste Markerfarbe des Proxys in Editor und Kamera-Preview (#rrggbb). Reiner Kompositionsmarker zur Zuordnung von Proxy und Objekt \u2014 KEINE Angabe zur realen Farbe oder zum Material des Objekts. Fehlt sie, vergibt der Editor eine unterscheidbare Ersatzfarbe.",
|
|
2839
|
+
"type": "string",
|
|
2840
|
+
"pattern": "^#[0-9a-f]{6}$"
|
|
2714
2841
|
}
|
|
2715
2842
|
},
|
|
2716
2843
|
"required": [
|
|
@@ -8509,6 +8636,219 @@ function sameResponseAs(run, response) {
|
|
|
8509
8636
|
return (run.raw_output ?? "") === response;
|
|
8510
8637
|
}
|
|
8511
8638
|
|
|
8639
|
+
// src/lib/szenen/promptRunVariant.ts
|
|
8640
|
+
var CAMERA_PREVIEW_ASSET_ROLE = "camera_preview";
|
|
8641
|
+
var VARIANT_VISIBILITY_BASIS = "variant_unassessed";
|
|
8642
|
+
var VARIANT_NODE_STATE = "unassessed";
|
|
8643
|
+
var VARIANT_SYSTEM_PROMPT = "Promptvariante eines bestehenden Laufs. Es wurde keine Renderer-Anweisung ausgefuehrt und kein Modell vom Server gerufen; der Prompttext stammt unveraendert vom MCP-Aufrufer. Eingefrorener Stand und Eingangsbilder sind die des Quelllaufs.";
|
|
8644
|
+
var VARIANT_ASSUMPTION = "Die Sichtbarkeit der Szenenknoten wurde fuer diesen Prompttext nicht beurteilt.";
|
|
8645
|
+
var istText7 = (wert) => typeof wert === "string" && wert.trim().length > 0;
|
|
8646
|
+
var isObject12 = (wert) => typeof wert === "object" && wert !== null && !Array.isArray(wert);
|
|
8647
|
+
function unbeurteilteKnoten(input) {
|
|
8648
|
+
return input.scene.nodes.map((node) => ({
|
|
8649
|
+
node_id: node.node_id,
|
|
8650
|
+
state: VARIANT_NODE_STATE,
|
|
8651
|
+
reason: "Promptvariante \u2014 keine Sichtbarkeitsbeurteilung fuer diesen Text.",
|
|
8652
|
+
assumption: true
|
|
8653
|
+
}));
|
|
8654
|
+
}
|
|
8655
|
+
function checkVariantInputAssets(assets, cameraPreview) {
|
|
8656
|
+
if (!Array.isArray(assets)) {
|
|
8657
|
+
return { ok: false, message: '"variant_of.input_assets" muss eine Liste sein.' };
|
|
8658
|
+
}
|
|
8659
|
+
const gesehen = /* @__PURE__ */ new Set();
|
|
8660
|
+
for (const [index, asset] of assets.entries()) {
|
|
8661
|
+
if (!isObject12(asset)) {
|
|
8662
|
+
return { ok: false, message: `"variant_of.input_assets[${index}]" ist kein Objekt.` };
|
|
8663
|
+
}
|
|
8664
|
+
if (!istText7(asset.asset_id)) {
|
|
8665
|
+
return { ok: false, message: `"variant_of.input_assets[${index}].asset_id" fehlt.` };
|
|
8666
|
+
}
|
|
8667
|
+
if (asset.role !== CAMERA_PREVIEW_ASSET_ROLE) {
|
|
8668
|
+
return {
|
|
8669
|
+
ok: false,
|
|
8670
|
+
message: `"variant_of.input_assets[${index}].role" ist unbekannt: ${JSON.stringify(asset.role)}. Erlaubt: ${CAMERA_PREVIEW_ASSET_ROLE}.`
|
|
8671
|
+
};
|
|
8672
|
+
}
|
|
8673
|
+
if (asset.position !== index) {
|
|
8674
|
+
return {
|
|
8675
|
+
ok: false,
|
|
8676
|
+
message: `"variant_of.input_assets[${index}].position" ist ${JSON.stringify(asset.position)}; die Eingangsbilder sind lueckenlos ab 0 geordnet.`
|
|
8677
|
+
};
|
|
8678
|
+
}
|
|
8679
|
+
if (asset.prompt_token !== null && !istText7(asset.prompt_token)) {
|
|
8680
|
+
return {
|
|
8681
|
+
ok: false,
|
|
8682
|
+
message: `"variant_of.input_assets[${index}].prompt_token" muss Text oder null sein.`
|
|
8683
|
+
};
|
|
8684
|
+
}
|
|
8685
|
+
if (typeof asset.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(asset.sha256)) {
|
|
8686
|
+
return { ok: false, message: `"variant_of.input_assets[${index}].sha256" ist ungueltig.` };
|
|
8687
|
+
}
|
|
8688
|
+
const herkunft = asset.origin;
|
|
8689
|
+
if (!isObject12(herkunft) || !istText7(herkunft.run_id) || !istText7(herkunft.item_id)) {
|
|
8690
|
+
return {
|
|
8691
|
+
ok: false,
|
|
8692
|
+
message: `"variant_of.input_assets[${index}].origin" braucht run_id und item_id.`
|
|
8693
|
+
};
|
|
8694
|
+
}
|
|
8695
|
+
if (gesehen.has(asset.asset_id)) {
|
|
8696
|
+
return {
|
|
8697
|
+
ok: false,
|
|
8698
|
+
message: `Asset ${asset.asset_id} steht mehrfach in "variant_of.input_assets".`
|
|
8699
|
+
};
|
|
8700
|
+
}
|
|
8701
|
+
gesehen.add(asset.asset_id);
|
|
8702
|
+
}
|
|
8703
|
+
const previews = assets.filter((asset) => asset.role === CAMERA_PREVIEW_ASSET_ROLE);
|
|
8704
|
+
if (cameraPreview) {
|
|
8705
|
+
if (previews.length !== 1) {
|
|
8706
|
+
return {
|
|
8707
|
+
ok: false,
|
|
8708
|
+
message: `Der Lauf traegt ein Kamera-Preview, die Eingangsbilder nennen aber ${previews.length} davon. Erwartet ist genau das eingefrorene Preview.`
|
|
8709
|
+
};
|
|
8710
|
+
}
|
|
8711
|
+
if (previews[0].sha256 !== cameraPreview.sha256) {
|
|
8712
|
+
return {
|
|
8713
|
+
ok: false,
|
|
8714
|
+
message: "Das Eingangsbild passt nicht zum eingefrorenen Kamera-Preview (sha256 weicht ab)."
|
|
8715
|
+
};
|
|
8716
|
+
}
|
|
8717
|
+
} else if (previews.length > 0) {
|
|
8718
|
+
return {
|
|
8719
|
+
ok: false,
|
|
8720
|
+
message: "Die Eingangsbilder nennen ein Kamera-Preview, der Lauf traegt aber keines."
|
|
8721
|
+
};
|
|
8722
|
+
}
|
|
8723
|
+
return { ok: true };
|
|
8724
|
+
}
|
|
8725
|
+
function checkVariantBlock(record) {
|
|
8726
|
+
const block = record.variant_of;
|
|
8727
|
+
if (block === void 0) return { ok: true };
|
|
8728
|
+
if (!isObject12(block)) return { ok: false, message: '"variant_of" muss ein Objekt sein.' };
|
|
8729
|
+
if (!istText7(block.source_run_id)) {
|
|
8730
|
+
return { ok: false, message: '"variant_of.source_run_id" fehlt oder ist leer.' };
|
|
8731
|
+
}
|
|
8732
|
+
if (block.source_run_id === record.run_id) {
|
|
8733
|
+
return { ok: false, message: "Ein Lauf kann nicht Variante seiner selbst sein." };
|
|
8734
|
+
}
|
|
8735
|
+
if (!istText7(block.operation_id) || block.operation_id !== record.operation_id) {
|
|
8736
|
+
return {
|
|
8737
|
+
ok: false,
|
|
8738
|
+
message: '"variant_of.operation_id" fehlt oder widerspricht "operation_id" des Laufs.'
|
|
8739
|
+
};
|
|
8740
|
+
}
|
|
8741
|
+
if (record.provider !== MCP_CLIENT_PROVIDER || record.status !== "succeeded") {
|
|
8742
|
+
return {
|
|
8743
|
+
ok: false,
|
|
8744
|
+
message: `Ein Variantenlauf ist ein erfolgreicher Lauf mit provider "${MCP_CLIENT_PROVIDER}".`
|
|
8745
|
+
};
|
|
8746
|
+
}
|
|
8747
|
+
return checkVariantInputAssets(
|
|
8748
|
+
block.input_assets,
|
|
8749
|
+
record.camera_preview
|
|
8750
|
+
);
|
|
8751
|
+
}
|
|
8752
|
+
function buildPromptRunVariantRecord(eingabe) {
|
|
8753
|
+
const now = eingabe.now ?? (() => /* @__PURE__ */ new Date());
|
|
8754
|
+
const quelle = eingabe.source;
|
|
8755
|
+
if (!istText7(eingabe.runId) || !istText7(eingabe.operationId)) {
|
|
8756
|
+
return { kind: "rejected", message: "Ein Variantenlauf braucht run_id und operation_id." };
|
|
8757
|
+
}
|
|
8758
|
+
if (!quelle || quelle.status !== "succeeded" || !quelle.output || !quelle.input_payload) {
|
|
8759
|
+
return {
|
|
8760
|
+
kind: "rejected",
|
|
8761
|
+
message: "Nur ein erfolgreicher Lauf mit eingefrorener Eingabe kann Quelle einer Variante sein."
|
|
8762
|
+
};
|
|
8763
|
+
}
|
|
8764
|
+
if (quelle.run_id === eingabe.runId) {
|
|
8765
|
+
return { kind: "rejected", message: "Die Variante braucht eine eigene run_id." };
|
|
8766
|
+
}
|
|
8767
|
+
const eingabeSnapshot = structuredClone(quelle.input_payload);
|
|
8768
|
+
const modell = eingabeSnapshot.target_model ?? {};
|
|
8769
|
+
if (typeof modell.max_prompt_chars === "number" && eingabe.positive.length > modell.max_prompt_chars) {
|
|
8770
|
+
return {
|
|
8771
|
+
kind: "rejected",
|
|
8772
|
+
message: `Der Prompt hat ${eingabe.positive.length} Zeichen; das eingefrorene Zielmodell erlaubt hoechstens ${modell.max_prompt_chars}.`
|
|
8773
|
+
};
|
|
8774
|
+
}
|
|
8775
|
+
const assets = checkVariantInputAssets(eingabe.inputAssets, quelle.camera_preview);
|
|
8776
|
+
if (!assets.ok) return { kind: "rejected", message: assets.message };
|
|
8777
|
+
const notiz = istText7(eingabe.note) ? eingabe.note.trim() : null;
|
|
8778
|
+
const geprueft = checkRunResponse({
|
|
8779
|
+
positive: eingabe.positive,
|
|
8780
|
+
negative: eingabe.negative ?? null,
|
|
8781
|
+
feedback: `Promptvariante von Lauf ${quelle.run_id}; Snapshot und Eingangsbilder unveraendert uebernommen.`,
|
|
8782
|
+
visibility: {
|
|
8783
|
+
basis: VARIANT_VISIBILITY_BASIS,
|
|
8784
|
+
nodes: unbeurteilteKnoten(eingabeSnapshot),
|
|
8785
|
+
assumptions: [VARIANT_ASSUMPTION]
|
|
8786
|
+
},
|
|
8787
|
+
notes: notiz === null ? [] : [`Notiz zur Variante: ${notiz}`]
|
|
8788
|
+
}, eingabeSnapshot);
|
|
8789
|
+
if (!geprueft.ok) return { kind: "rejected", message: geprueft.message };
|
|
8790
|
+
const output = {
|
|
8791
|
+
...geprueft.output,
|
|
8792
|
+
// **Unveraendert** — `checkRunResponse` liefert den Text ohnehin woertlich.
|
|
8793
|
+
positive: eingabe.positive
|
|
8794
|
+
};
|
|
8795
|
+
const origin = {
|
|
8796
|
+
host: "mcp",
|
|
8797
|
+
...istText7(eingabe.declaredModelId) ? { declared_model_id: eingabe.declaredModelId } : {},
|
|
8798
|
+
renderer_instruction_was_system_prompt: false
|
|
8799
|
+
};
|
|
8800
|
+
const record = {
|
|
8801
|
+
run_id: eingabe.runId,
|
|
8802
|
+
// Woertlich aus dem Quelllauf: dieselbe Herkunft, dieselben Kennungen.
|
|
8803
|
+
shot_version_id: quelle.shot_version_id,
|
|
8804
|
+
shot_element_id: quelle.shot_element_id,
|
|
8805
|
+
scene_setup_version_id: quelle.scene_setup_version_id,
|
|
8806
|
+
camera_id: quelle.camera_id,
|
|
8807
|
+
target_model_version_id: quelle.target_model_version_id,
|
|
8808
|
+
provider: MCP_CLIENT_PROVIDER,
|
|
8809
|
+
model_id: UNVERIFIED_MODEL_ID,
|
|
8810
|
+
system_prompt: VARIANT_SYSTEM_PROMPT,
|
|
8811
|
+
input_payload: eingabeSnapshot,
|
|
8812
|
+
status: "succeeded",
|
|
8813
|
+
failure: null,
|
|
8814
|
+
output,
|
|
8815
|
+
raw_output: JSON.stringify({
|
|
8816
|
+
positive: eingabe.positive,
|
|
8817
|
+
negative: output.negative,
|
|
8818
|
+
note: notiz
|
|
8819
|
+
}),
|
|
8820
|
+
...quelle.source ? { source: structuredClone(quelle.source) } : {},
|
|
8821
|
+
...quelle.camera_preview ? { camera_preview: structuredClone(quelle.camera_preview) } : {},
|
|
8822
|
+
operation_id: eingabe.operationId,
|
|
8823
|
+
execution_origin: origin,
|
|
8824
|
+
variant_of: {
|
|
8825
|
+
source_run_id: quelle.run_id,
|
|
8826
|
+
operation_id: eingabe.operationId,
|
|
8827
|
+
input_assets: eingabe.inputAssets.map((asset) => structuredClone(asset))
|
|
8828
|
+
},
|
|
8829
|
+
created_at: now().toISOString()
|
|
8830
|
+
};
|
|
8831
|
+
return { kind: "ok", record };
|
|
8832
|
+
}
|
|
8833
|
+
function variantOf(run) {
|
|
8834
|
+
const block = run.variant_of;
|
|
8835
|
+
if (!isObject12(block) || !istText7(block.source_run_id)) return null;
|
|
8836
|
+
return block;
|
|
8837
|
+
}
|
|
8838
|
+
function sameVariantRequest(run, anfrage) {
|
|
8839
|
+
const block = variantOf(run);
|
|
8840
|
+
if (!block || block.source_run_id !== anfrage.sourceRunId || !run.output) return false;
|
|
8841
|
+
const negativ = istText7(anfrage.negative) ? anfrage.negative : null;
|
|
8842
|
+
const notiz = istText7(anfrage.note) ? anfrage.note.trim() : null;
|
|
8843
|
+
let gespeichert = {};
|
|
8844
|
+
try {
|
|
8845
|
+
gespeichert = JSON.parse(run.raw_output ?? "{}");
|
|
8846
|
+
} catch {
|
|
8847
|
+
return false;
|
|
8848
|
+
}
|
|
8849
|
+
return run.output.positive === anfrage.positive && (run.output.negative ?? null) === negativ && (gespeichert.note ?? null) === notiz;
|
|
8850
|
+
}
|
|
8851
|
+
|
|
8512
8852
|
// src/lib/szenen/seedListe.ts
|
|
8513
8853
|
var DEFAULT_SEED_VORLAGE = {
|
|
8514
8854
|
name: "Default",
|
|
@@ -8636,6 +8976,398 @@ async function leseBilderAusZip(datei) {
|
|
|
8636
8976
|
return bilder;
|
|
8637
8977
|
}
|
|
8638
8978
|
|
|
8979
|
+
// src/lib/szenen/stageOperations.ts
|
|
8980
|
+
var NODE_TYPES = ["subject", "object", "surface", "light", "camera_target", "group", "other"];
|
|
8981
|
+
var PROXY_PRIMITIVES = ["humanoid_proxy", "box", "cylinder", "sphere", "plane", "room_shell", "furniture_proxy"];
|
|
8982
|
+
var SLUG = /^[a-z][a-z0-9_]{0,62}$/;
|
|
8983
|
+
var Abgelehnt = class extends Error {
|
|
8984
|
+
};
|
|
8985
|
+
var fail2 = (message) => {
|
|
8986
|
+
throw new Abgelehnt(message);
|
|
8987
|
+
};
|
|
8988
|
+
function vec3(value2, label, positive = false) {
|
|
8989
|
+
if (!Array.isArray(value2) || value2.length !== 3 || value2.some((n) => typeof n !== "number" || !Number.isFinite(n))) {
|
|
8990
|
+
fail2(`${label}: drei endliche Zahlen erforderlich.`);
|
|
8991
|
+
}
|
|
8992
|
+
if (positive && value2.some((n) => n <= 0)) fail2(`${label}: alle Werte m\xFCssen positiv sein.`);
|
|
8993
|
+
return [...value2];
|
|
8994
|
+
}
|
|
8995
|
+
function farbe(value2, label) {
|
|
8996
|
+
const hex = normalizePreviewColor(value2);
|
|
8997
|
+
if (!hex) fail2(`${label}: Farbe als RGB-Hexwert #rrggbb angeben, angekommen ist ${JSON.stringify(value2)}.`);
|
|
8998
|
+
return hex;
|
|
8999
|
+
}
|
|
9000
|
+
function checkProxyShape(proxy) {
|
|
9001
|
+
if (proxy.primitive === "furniture_proxy" && !["chair", "table", "floor_lamp"].includes(proxy.variant)) fail2("M\xF6bel ben\xF6tigen variant: chair, table oder floor_lamp.");
|
|
9002
|
+
if (proxy.pose_ref != null && !["standing", "sitting", "walking", "arms_crossed", "hand_on_chin"].includes(proxy.pose_ref)) fail2("Unbekannte Personenpose.");
|
|
9003
|
+
if (proxy.morph && Object.entries(proxy.morph).some(([key, v]) => !["build", "gender"].includes(key) || typeof v !== "number" || !Number.isFinite(v) || v < 0 || v > 1)) fail2("Morph-Regler ben\xF6tigen endliche Werte zwischen 0 und 1.");
|
|
9004
|
+
}
|
|
9005
|
+
var hiddenOf = (shot) => new Set(Array.isArray(shot?.overrides?.hidden_nodes) ? shot.overrides.hidden_nodes : []);
|
|
9006
|
+
function previewColorNodes(scene, setup, shot) {
|
|
9007
|
+
const hidden = hiddenOf(shot);
|
|
9008
|
+
const overrides = new Map((setup?.node_overrides ?? []).map((o) => [o.node_id, o]));
|
|
9009
|
+
return (Array.isArray(scene.nodes) ? scene.nodes : []).filter((n) => !hidden.has(n.node_id)).map((n) => {
|
|
9010
|
+
const o = overrides.get(n.node_id);
|
|
9011
|
+
return { node_id: n.node_id, type: n.type, proxy_3d: (o && o.proxy_3d !== void 0 ? o.proxy_3d : n.proxy_3d) ?? null };
|
|
9012
|
+
});
|
|
9013
|
+
}
|
|
9014
|
+
function pinPreviewColors(scene, setup, shot) {
|
|
9015
|
+
const nodes = Array.isArray(scene.nodes) ? scene.nodes : [];
|
|
9016
|
+
const colors = stageColors(previewColorNodes(scene, setup, shot));
|
|
9017
|
+
const taken = Object.values(colors).map((c) => c.hex);
|
|
9018
|
+
return {
|
|
9019
|
+
...scene,
|
|
9020
|
+
nodes: nodes.map((n) => {
|
|
9021
|
+
if (!n.proxy_3d || normalizePreviewColor(n.proxy_3d.preview_color) || setup && proxyUeberschrieben(setup, n.node_id)) return n;
|
|
9022
|
+
let hex = colors[n.node_id]?.hex;
|
|
9023
|
+
if (!hex) {
|
|
9024
|
+
hex = distinctPreviewColor(n.type, taken);
|
|
9025
|
+
taken.push(hex);
|
|
9026
|
+
}
|
|
9027
|
+
return { ...n, proxy_3d: { ...n.proxy_3d, preview_color: hex } };
|
|
9028
|
+
})
|
|
9029
|
+
};
|
|
9030
|
+
}
|
|
9031
|
+
function fremdeVerweise(nodeId, setup, shot) {
|
|
9032
|
+
const out = [];
|
|
9033
|
+
for (const c of setup.camera_rig?.cameras ?? []) {
|
|
9034
|
+
if (c.orientation?.target?.node_ref === nodeId) out.push(`Kamera ${c.camera_id} blickt auf ihn`);
|
|
9035
|
+
if (c.framing?.target?.node_ref === nodeId) out.push(`Kamera ${c.camera_id} rahmt ihn`);
|
|
9036
|
+
if (c.focus?.node_ref === nodeId) out.push(`Kamera ${c.camera_id} fokussiert ihn`);
|
|
9037
|
+
}
|
|
9038
|
+
if (shot) {
|
|
9039
|
+
if (shot.overrides?.focus?.node_ref === nodeId) out.push("der Shot fokussiert ihn");
|
|
9040
|
+
if (shot.overrides?.framing?.target?.node_ref === nodeId) out.push("der Shot rahmt ihn");
|
|
9041
|
+
if (hiddenOf(shot).has(nodeId)) out.push("der Shot blendet ihn aus");
|
|
9042
|
+
}
|
|
9043
|
+
return out;
|
|
9044
|
+
}
|
|
9045
|
+
function proxyUeberschrieben(setup, nodeId) {
|
|
9046
|
+
return (setup.node_overrides ?? []).some((o) => o.node_id === nodeId && o.proxy_3d !== void 0);
|
|
9047
|
+
}
|
|
9048
|
+
function neueNodeId(nodes, type) {
|
|
9049
|
+
const basis = SLUG.test(type) ? type : "node";
|
|
9050
|
+
for (let i = 1; ; i++) {
|
|
9051
|
+
const id = `${basis}_${i}`;
|
|
9052
|
+
if (!nodes.some((n) => n.node_id === id)) return id;
|
|
9053
|
+
}
|
|
9054
|
+
}
|
|
9055
|
+
function applyStageOperations(input, operations) {
|
|
9056
|
+
let scene = structuredClone(input.scene);
|
|
9057
|
+
let setup = structuredClone(input.setup);
|
|
9058
|
+
let shot = input.shot ? structuredClone(input.shot) : null;
|
|
9059
|
+
const changed = { scene: false, setup: false, shot: false };
|
|
9060
|
+
const created = [];
|
|
9061
|
+
let adds = 0, removes = 0;
|
|
9062
|
+
let index = null;
|
|
9063
|
+
try {
|
|
9064
|
+
if (!Array.isArray(scene.nodes)) fail2("Die Szene hat keine Node-Liste.");
|
|
9065
|
+
if (!Array.isArray(setup.camera_rig?.cameras)) fail2("Der Aufbau hat kein Kamera-Rig.");
|
|
9066
|
+
if (!Array.isArray(operations) || operations.length === 0) fail2("Mindestens eine Operation angeben.");
|
|
9067
|
+
const vorher = JSON.stringify(scene);
|
|
9068
|
+
scene = pinPreviewColors(scene, setup, shot);
|
|
9069
|
+
if (JSON.stringify(scene) !== vorher) changed.scene = true;
|
|
9070
|
+
for (const [i, operation] of operations.entries()) {
|
|
9071
|
+
index = i;
|
|
9072
|
+
const nodes = scene.nodes;
|
|
9073
|
+
const findNode = (id) => {
|
|
9074
|
+
const node = nodes.find((n) => n.node_id === id);
|
|
9075
|
+
if (!node) fail2(`Node ${JSON.stringify(id)} gibt es in der Szene nicht.`);
|
|
9076
|
+
return node;
|
|
9077
|
+
};
|
|
9078
|
+
switch (operation.op) {
|
|
9079
|
+
case "add_node": {
|
|
9080
|
+
adds++;
|
|
9081
|
+
if (!NODE_TYPES.includes(operation.type)) fail2(`Unbekannter Node-Typ ${JSON.stringify(operation.type)}.`);
|
|
9082
|
+
if (typeof operation.description !== "string" || !operation.description.trim()) fail2("add_node braucht eine semantische Beschreibung (description).");
|
|
9083
|
+
const id = operation.node_id ?? neueNodeId(nodes, operation.type);
|
|
9084
|
+
if (!SLUG.test(id)) fail2(`node_id ${JSON.stringify(id)} ist kein g\xFCltiger Bezeichner (Kleinbuchstaben, Ziffern, Unterstrich).`);
|
|
9085
|
+
if (nodes.some((n) => n.node_id === id)) fail2(`node_id ${id} ist bereits vergeben.`);
|
|
9086
|
+
const catalogueLabel = operation.label?.replace(/\s+\d+$/, "");
|
|
9087
|
+
const vorlage = STAGE_CATALOGUE.find((e) => e.label === catalogueLabel && e.type === operation.type) ?? (operation.label && operation.type === "object" ? void 0 : STAGE_CATALOGUE.find((e) => e.type === operation.type));
|
|
9088
|
+
const dimensions = operation.dimensions ? vec3(operation.dimensions, "dimensions", true) : [...vorlage?.dimensions ?? [0.5, 0.5, 0.5]];
|
|
9089
|
+
const primitive = operation.primitive ?? vorlage?.primitive ?? "box";
|
|
9090
|
+
if (!PROXY_PRIMITIVES.includes(primitive)) fail2(`Unbekanntes Primitive ${JSON.stringify(primitive)}.`);
|
|
9091
|
+
scene = pinPreviewColors(scene, setup, shot);
|
|
9092
|
+
const taken = Object.values(stageColors(previewColorNodes(scene, setup, shot))).map((c) => c.hex);
|
|
9093
|
+
const color = operation.preview_color !== void 0 ? farbe(operation.preview_color, "preview_color") : distinctPreviewColor(operation.type, taken);
|
|
9094
|
+
const node = {
|
|
9095
|
+
node_id: id,
|
|
9096
|
+
type: operation.type,
|
|
9097
|
+
...operation.label ? { label: operation.label } : {},
|
|
9098
|
+
semantic: { description: operation.description, ...operation.properties ? { properties: operation.properties } : {} },
|
|
9099
|
+
proxy_3d: {
|
|
9100
|
+
primitive,
|
|
9101
|
+
dimensions,
|
|
9102
|
+
preview_color: color,
|
|
9103
|
+
origin: "floor_center",
|
|
9104
|
+
...primitive === "furniture_proxy" ? { variant: operation.variant ?? (vorlage && "variant" in vorlage ? vorlage.variant : void 0) } : {},
|
|
9105
|
+
...primitive === "humanoid_proxy" ? { pose_ref: operation.pose_ref ?? "standing", morph: operation.morph ?? { build: 0.5, gender: 0.5 } } : {}
|
|
9106
|
+
}
|
|
9107
|
+
};
|
|
9108
|
+
scene = { ...scene, unit_system: "blender_z_up_meters", nodes: [...scene.nodes, node] };
|
|
9109
|
+
checkProxyShape(node.proxy_3d);
|
|
9110
|
+
const position = operation.position ? vec3(operation.position, "position") : [0, 0, 0];
|
|
9111
|
+
setup = {
|
|
9112
|
+
...setup,
|
|
9113
|
+
coordinate_system: "blender_z_up_meters",
|
|
9114
|
+
placements: [...setup.placements ?? [], {
|
|
9115
|
+
node_id: id,
|
|
9116
|
+
position,
|
|
9117
|
+
...operation.rotation_euler_deg ? { rotation_euler_deg: vec3(operation.rotation_euler_deg, "rotation_euler_deg") } : {},
|
|
9118
|
+
...operation.scale ? { scale: vec3(operation.scale, "scale", true) } : {}
|
|
9119
|
+
}]
|
|
9120
|
+
};
|
|
9121
|
+
changed.scene = changed.setup = true;
|
|
9122
|
+
created.push(id);
|
|
9123
|
+
break;
|
|
9124
|
+
}
|
|
9125
|
+
case "update_node": {
|
|
9126
|
+
const node = findNode(operation.node_id);
|
|
9127
|
+
const next = { ...node };
|
|
9128
|
+
if (operation.type !== void 0) {
|
|
9129
|
+
if (!NODE_TYPES.includes(operation.type)) fail2(`Unbekannter Node-Typ ${JSON.stringify(operation.type)}.`);
|
|
9130
|
+
next.type = operation.type;
|
|
9131
|
+
}
|
|
9132
|
+
if (operation.label !== void 0) {
|
|
9133
|
+
if (operation.label === null || operation.label === "") delete next.label;
|
|
9134
|
+
else next.label = operation.label;
|
|
9135
|
+
}
|
|
9136
|
+
if (operation.description !== void 0 || operation.properties !== void 0) {
|
|
9137
|
+
if (operation.description !== void 0 && !String(operation.description).trim()) fail2("description darf nicht leer sein.");
|
|
9138
|
+
next.semantic = {
|
|
9139
|
+
...node.semantic,
|
|
9140
|
+
...operation.description !== void 0 ? { description: operation.description } : {},
|
|
9141
|
+
...operation.properties !== void 0 ? { properties: operation.properties } : {}
|
|
9142
|
+
};
|
|
9143
|
+
}
|
|
9144
|
+
if (operation.primitive !== void 0 || operation.dimensions !== void 0 || operation.preview_color !== void 0 || operation.variant !== void 0 || operation.pose_ref !== void 0 || operation.morph !== void 0) {
|
|
9145
|
+
if (proxyUeberschrieben(setup, node.node_id)) {
|
|
9146
|
+
fail2(`Node ${node.node_id} hat im Aufbau eine proxy_3d-\xDCberschreibung; Geometrie und Farbe wirken dort, nicht in der Szene.`);
|
|
9147
|
+
}
|
|
9148
|
+
const proxy = { ...node.proxy_3d ?? {} };
|
|
9149
|
+
if (!node.proxy_3d && operation.dimensions === void 0) fail2(`Node ${node.node_id} hat keine Proxy-Geometrie; zuerst dimensions setzen.`);
|
|
9150
|
+
if (operation.primitive !== void 0) {
|
|
9151
|
+
if (!PROXY_PRIMITIVES.includes(operation.primitive)) fail2(`Unbekanntes Primitive ${JSON.stringify(operation.primitive)}.`);
|
|
9152
|
+
proxy.primitive = operation.primitive;
|
|
9153
|
+
}
|
|
9154
|
+
proxy.primitive ?? (proxy.primitive = "box");
|
|
9155
|
+
if (operation.dimensions !== void 0) proxy.dimensions = vec3(operation.dimensions, "dimensions", true);
|
|
9156
|
+
if (operation.variant !== void 0) proxy.variant = operation.variant;
|
|
9157
|
+
if (operation.pose_ref !== void 0) proxy.pose_ref = operation.pose_ref;
|
|
9158
|
+
if (operation.morph !== void 0) proxy.morph = { ...proxy.morph, ...operation.morph };
|
|
9159
|
+
if (operation.preview_color === null) delete proxy.preview_color;
|
|
9160
|
+
else if (operation.preview_color !== void 0) proxy.preview_color = farbe(operation.preview_color, "preview_color");
|
|
9161
|
+
checkProxyShape(proxy);
|
|
9162
|
+
next.proxy_3d = proxy;
|
|
9163
|
+
}
|
|
9164
|
+
scene = { ...scene, nodes: nodes.map((n) => n === node ? next : n) };
|
|
9165
|
+
changed.scene = true;
|
|
9166
|
+
break;
|
|
9167
|
+
}
|
|
9168
|
+
case "place_node": {
|
|
9169
|
+
findNode(operation.node_id);
|
|
9170
|
+
const placements = setup.placements ?? [];
|
|
9171
|
+
const vorhanden = placements.find((p) => p.node_id === operation.node_id);
|
|
9172
|
+
if (!vorhanden && !operation.position) fail2(`Node ${operation.node_id} ist noch nicht platziert; position angeben.`);
|
|
9173
|
+
const next = {
|
|
9174
|
+
...vorhanden ?? { node_id: operation.node_id },
|
|
9175
|
+
...operation.position ? { position: vec3(operation.position, "position") } : {},
|
|
9176
|
+
...operation.rotation_euler_deg ? { rotation_euler_deg: vec3(operation.rotation_euler_deg, "rotation_euler_deg") } : {},
|
|
9177
|
+
...operation.scale ? { scale: vec3(operation.scale, "scale", true) } : {}
|
|
9178
|
+
};
|
|
9179
|
+
setup = {
|
|
9180
|
+
...setup,
|
|
9181
|
+
coordinate_system: setup.coordinate_system ?? "blender_z_up_meters",
|
|
9182
|
+
placements: vorhanden ? placements.map((p) => p === vorhanden ? next : p) : [...placements, next]
|
|
9183
|
+
};
|
|
9184
|
+
changed.setup = true;
|
|
9185
|
+
break;
|
|
9186
|
+
}
|
|
9187
|
+
case "remove_node": {
|
|
9188
|
+
removes++;
|
|
9189
|
+
findNode(operation.node_id);
|
|
9190
|
+
const verweise = fremdeVerweise(operation.node_id, setup, shot);
|
|
9191
|
+
if (verweise.length) fail2(`Node ${operation.node_id} wird noch verwendet: ${verweise.join("; ")}. Zuerst diese Bez\xFCge \xE4ndern.`);
|
|
9192
|
+
scene = pinPreviewColors(scene, setup, shot);
|
|
9193
|
+
scene = {
|
|
9194
|
+
...scene,
|
|
9195
|
+
nodes: scene.nodes.filter((n) => n.node_id !== operation.node_id),
|
|
9196
|
+
relations: (scene.relations ?? []).filter((r) => r.from !== operation.node_id && r.to !== operation.node_id)
|
|
9197
|
+
};
|
|
9198
|
+
setup = {
|
|
9199
|
+
...setup,
|
|
9200
|
+
...setup.placements ? { placements: setup.placements.filter((p) => p.node_id !== operation.node_id) } : {},
|
|
9201
|
+
...setup.node_overrides ? { node_overrides: setup.node_overrides.filter((o) => o.node_id !== operation.node_id) } : {}
|
|
9202
|
+
};
|
|
9203
|
+
changed.scene = changed.setup = true;
|
|
9204
|
+
break;
|
|
9205
|
+
}
|
|
9206
|
+
case "add_camera": {
|
|
9207
|
+
const camera = operation.camera;
|
|
9208
|
+
if (!camera || typeof camera !== "object" || !SLUG.test(camera.camera_id)) fail2("add_camera braucht ein Kameraobjekt mit g\xFCltiger camera_id.");
|
|
9209
|
+
if (setup.camera_rig.cameras.some((c) => c.camera_id === camera.camera_id)) fail2(`camera_id ${camera.camera_id} ist bereits vergeben.`);
|
|
9210
|
+
if (typeof camera.aspect_ratio !== "string") fail2("Eine neue Kamera braucht ein explizites aspect_ratio.");
|
|
9211
|
+
for (const ref of [camera.orientation?.target?.node_ref, camera.framing?.target?.node_ref, camera.focus?.node_ref]) {
|
|
9212
|
+
if (ref !== void 0) findNode(ref);
|
|
9213
|
+
}
|
|
9214
|
+
setup = { ...setup, camera_rig: { ...setup.camera_rig, cameras: [...setup.camera_rig.cameras, structuredClone(camera)] } };
|
|
9215
|
+
changed.setup = true;
|
|
9216
|
+
break;
|
|
9217
|
+
}
|
|
9218
|
+
case "update_camera": {
|
|
9219
|
+
const cameras = setup.camera_rig.cameras;
|
|
9220
|
+
const camera = cameras.find((c) => c.camera_id === operation.camera_id);
|
|
9221
|
+
if (!camera) fail2(`Kamera ${operation.camera_id} gibt es im Aufbau nicht.`);
|
|
9222
|
+
if (!operation.changes || typeof operation.changes !== "object") fail2("update_camera braucht changes.");
|
|
9223
|
+
if ("camera_id" in operation.changes && operation.changes.camera_id !== operation.camera_id) fail2("camera_id ist unver\xE4nderlich.");
|
|
9224
|
+
const next = { ...camera, ...structuredClone(operation.changes) };
|
|
9225
|
+
for (const ref of [next.orientation?.target?.node_ref, next.framing?.target?.node_ref, next.focus?.node_ref]) {
|
|
9226
|
+
if (ref !== void 0) findNode(ref);
|
|
9227
|
+
}
|
|
9228
|
+
setup = { ...setup, camera_rig: { ...setup.camera_rig, cameras: cameras.map((c) => c === camera ? next : c) } };
|
|
9229
|
+
changed.setup = true;
|
|
9230
|
+
break;
|
|
9231
|
+
}
|
|
9232
|
+
case "set_shot_camera": {
|
|
9233
|
+
if (!shot) fail2("Ohne Shot-Entwurf gibt es keine aktive Kamera zu setzen.");
|
|
9234
|
+
if (!setup.camera_rig.cameras.some((c) => c.camera_id === operation.camera_id)) fail2(`Kamera ${operation.camera_id} gibt es im Aufbau nicht.`);
|
|
9235
|
+
shot = { ...shot, camera_id: operation.camera_id };
|
|
9236
|
+
changed.shot = true;
|
|
9237
|
+
break;
|
|
9238
|
+
}
|
|
9239
|
+
default:
|
|
9240
|
+
fail2(`Unbekannte Operation ${JSON.stringify(operation.op)}.`);
|
|
9241
|
+
}
|
|
9242
|
+
}
|
|
9243
|
+
index = null;
|
|
9244
|
+
if (adds && removes) fail2("Hinzuf\xFCgen und Entfernen bitte in getrennten Aufrufen: F\xFCr beides zugleich gibt es keine Schreibreihenfolge ohne verwaisten Zwischenstand.");
|
|
9245
|
+
const ids = new Set(scene.nodes.map((n) => n.node_id));
|
|
9246
|
+
const waise = (setup.placements ?? []).filter((p) => !ids.has(p.node_id)).map((p) => p.node_id);
|
|
9247
|
+
if (waise.length) fail2(`Placements ohne Node: ${waise.join(", ")}.`);
|
|
9248
|
+
if (shot && !setup.camera_rig.cameras.some((c) => c.camera_id === shot.camera_id)) fail2(`Die aktive Kamera ${shot.camera_id} fehlt im Aufbau.`);
|
|
9249
|
+
} catch (e) {
|
|
9250
|
+
if (e instanceof Abgelehnt) return { kind: "rejected", message: e.message, operation_index: index };
|
|
9251
|
+
throw e;
|
|
9252
|
+
}
|
|
9253
|
+
const order = removes ? ["setup", "scene", "shot"] : ["scene", "setup", "shot"];
|
|
9254
|
+
return {
|
|
9255
|
+
kind: "ok",
|
|
9256
|
+
payloads: { scene, setup, shot },
|
|
9257
|
+
changed,
|
|
9258
|
+
created_node_ids: created,
|
|
9259
|
+
write_order: order.filter((k) => changed[k]),
|
|
9260
|
+
color_conflicts: previewColorConflicts(previewColorNodes(scene, setup, shot))
|
|
9261
|
+
};
|
|
9262
|
+
}
|
|
9263
|
+
|
|
9264
|
+
// src/lib/szenen/stageChain.ts
|
|
9265
|
+
function stageValue(r) {
|
|
9266
|
+
if (r.kind !== "ok" || r.value == null) {
|
|
9267
|
+
throw new Error(r.message ?? (r.kind === "conflict" ? "Der Entwurf wurde parallel ge\xE4ndert; die letzte \xC4nderung wurde nicht gespeichert." : `Operation fehlgeschlagen: ${r.kind}`));
|
|
9268
|
+
}
|
|
9269
|
+
return r.value;
|
|
9270
|
+
}
|
|
9271
|
+
async function lies(elements, id) {
|
|
9272
|
+
const gelesen = stageValue(await elements.getElement(id));
|
|
9273
|
+
return gelesen;
|
|
9274
|
+
}
|
|
9275
|
+
async function mitKette(elements, type, chainId) {
|
|
9276
|
+
const liste = stageValue(await elements.listElements({ type }));
|
|
9277
|
+
const treffer = [];
|
|
9278
|
+
for (const eintrag of liste) {
|
|
9279
|
+
const s = await lies(elements, eintrag.element_id);
|
|
9280
|
+
if (s.draft?.chain?.chain_id === chainId) treffer.push(s);
|
|
9281
|
+
}
|
|
9282
|
+
return treffer;
|
|
9283
|
+
}
|
|
9284
|
+
async function findStageDraftChain(elements, sceneElementId) {
|
|
9285
|
+
const scene = await lies(elements, sceneElementId);
|
|
9286
|
+
if (scene.element.type !== "scene") throw new Error(`Element ${sceneElementId} ist keine Szene.`);
|
|
9287
|
+
if (scene.draftFork) throw new Error("Die Szene hat konkurrierende Entw\xFCrfe. Bitte zuerst aufl\xF6sen.");
|
|
9288
|
+
const chainId = scene.draft?.chain?.chain_id;
|
|
9289
|
+
if (!chainId) return null;
|
|
9290
|
+
const setups = await mitKette(elements, "scene_setup", chainId);
|
|
9291
|
+
const shots = await mitKette(elements, "shot", chainId);
|
|
9292
|
+
if (setups.length !== 1 || shots.length !== 1) {
|
|
9293
|
+
throw new Error(`Die Draft-Kette ${chainId} ist unvollst\xE4ndig oder mehrdeutig (${setups.length} Aufbau-, ${shots.length} Shot-Entw\xFCrfe).`);
|
|
9294
|
+
}
|
|
9295
|
+
const link = setups[0].draft.chain.links.find((l) => l.field === "scene_ref");
|
|
9296
|
+
if (link?.target_draft_id !== scene.draft.draft_id) throw new Error("Die gespeicherte Draft-Kette passt nicht zur Szene.");
|
|
9297
|
+
const shotLink = shots[0].draft.chain.links.find((l) => l.field === "scene_setup_ref");
|
|
9298
|
+
if (shotLink?.target_draft_id !== setups[0].draft.draft_id) throw new Error("Der Shot-Entwurf zeigt nicht auf den Aufbau dieser Kette.");
|
|
9299
|
+
return { chain_id: chainId, scene, setup: setups[0], shot: shots[0] };
|
|
9300
|
+
}
|
|
9301
|
+
async function openStageDraftChain(elements, input) {
|
|
9302
|
+
const { sceneElementId, setupVersionId, contextId } = input;
|
|
9303
|
+
const setup = await lies(elements, input.setupElementId);
|
|
9304
|
+
if (setup.element.type !== "scene_setup") throw new Error(`Element ${input.setupElementId} ist kein Scene Setup.`);
|
|
9305
|
+
if (setup.draftFork) throw new Error("Der Aufbau hat konkurrierende Entw\xFCrfe. Bitte zuerst aufl\xF6sen.");
|
|
9306
|
+
if (setupVersionId && setup.draft) throw new Error("F\xFCr diesen Aufbau existiert bereits ein Entwurf. Bitte diesen explizit ausw\xE4hlen.");
|
|
9307
|
+
const setupPayload = setupVersionId ? setup.versions.find((v) => v.version_id === setupVersionId)?.payload : setup.draft?.payload;
|
|
9308
|
+
if (!setupPayload) throw new Error("Der gew\xE4hlte Stand ist nicht mehr vorhanden.");
|
|
9309
|
+
const scene = await lies(elements, sceneElementId);
|
|
9310
|
+
if (scene.draftFork) throw new Error("Die Szene hat konkurrierende Entw\xFCrfe.");
|
|
9311
|
+
const existingChain = setup.draft?.chain;
|
|
9312
|
+
if (existingChain) {
|
|
9313
|
+
const link = existingChain.links.find((l) => l.field === "scene_ref");
|
|
9314
|
+
if (link?.target_draft_id !== scene.draft?.draft_id || scene.draft?.chain?.chain_id !== existingChain.chain_id) {
|
|
9315
|
+
throw new Error("Die gespeicherte Draft-Kette passt nicht zur Szene.");
|
|
9316
|
+
}
|
|
9317
|
+
} else if (scene.draft?.chain) {
|
|
9318
|
+
throw new Error("Die Szene geh\xF6rt bereits zu einer anderen Draft-Kette.");
|
|
9319
|
+
}
|
|
9320
|
+
const ref = setupPayload.scene_ref;
|
|
9321
|
+
if (!existingChain && ref?.element_id && ref.element_id !== sceneElementId) {
|
|
9322
|
+
throw new Error("Der Aufbau geh\xF6rt zu einer anderen Szene.");
|
|
9323
|
+
}
|
|
9324
|
+
const scenePayload = scene.draft?.payload ?? scene.versions.find((v) => v.version_id === ref?.version_id)?.payload;
|
|
9325
|
+
if (!scenePayload) throw new Error("Die referenzierte Szene ist nicht vorhanden.");
|
|
9326
|
+
const chainId = existingChain?.chain_id ?? (input.newChainId ?? (() => crypto.randomUUID()))();
|
|
9327
|
+
const chain = existingChain ?? { chain_id: chainId, origin: "stage", links: [] };
|
|
9328
|
+
let sceneDraft = scene.draft;
|
|
9329
|
+
if (!existingChain) {
|
|
9330
|
+
sceneDraft = stageValue(await elements.writeDraft({
|
|
9331
|
+
elementId: sceneElementId,
|
|
9332
|
+
payload: scenePayload,
|
|
9333
|
+
expectedRevision: scene.draft?.revision ?? 0,
|
|
9334
|
+
baseVersionId: scene.draft?.base_version_id ?? ref?.version_id ?? null,
|
|
9335
|
+
chain: { ...chain, links: [] }
|
|
9336
|
+
}));
|
|
9337
|
+
}
|
|
9338
|
+
let setupDraft = setup.draft;
|
|
9339
|
+
if (!existingChain) {
|
|
9340
|
+
setupDraft = stageValue(await elements.writeDraft({
|
|
9341
|
+
elementId: setup.element.element_id,
|
|
9342
|
+
payload: setupPayload,
|
|
9343
|
+
expectedRevision: setup.draft?.revision ?? 0,
|
|
9344
|
+
baseVersionId: setupVersionId,
|
|
9345
|
+
chain: { ...chain, links: [{ field: "scene_ref", target_element_id: sceneElementId, target_draft_id: sceneDraft.draft_id }] }
|
|
9346
|
+
}));
|
|
9347
|
+
}
|
|
9348
|
+
const shots = await mitKette(elements, "shot", chainId);
|
|
9349
|
+
let shot = shots[0] ?? null;
|
|
9350
|
+
if (!shot) {
|
|
9351
|
+
const created = stageValue(await elements.createElement({ type: "shot", contextId, title: "3D-Kameraansicht" }));
|
|
9352
|
+
const cameraId = setupPayload.camera_rig?.cameras?.[0]?.camera_id;
|
|
9353
|
+
if (!cameraId) throw new Error("Der Aufbau hat keine Kamera.");
|
|
9354
|
+
const shotPayload = { camera_id: cameraId, ...input.targetModelId ? { prompt_render_settings: { target_model_id: input.targetModelId } } : {} };
|
|
9355
|
+
stageValue(await elements.writeDraft({
|
|
9356
|
+
elementId: created.element_id,
|
|
9357
|
+
payload: shotPayload,
|
|
9358
|
+
expectedRevision: 0,
|
|
9359
|
+
chain: { ...chain, links: [{ field: "scene_setup_ref", target_element_id: setup.element.element_id, target_draft_id: setupDraft.draft_id }] }
|
|
9360
|
+
}));
|
|
9361
|
+
shot = await lies(elements, created.element_id);
|
|
9362
|
+
}
|
|
9363
|
+
return {
|
|
9364
|
+
chain_id: chainId,
|
|
9365
|
+
scene: await lies(elements, sceneElementId),
|
|
9366
|
+
setup: await lies(elements, setup.element.element_id),
|
|
9367
|
+
shot
|
|
9368
|
+
};
|
|
9369
|
+
}
|
|
9370
|
+
|
|
8639
9371
|
// src/lib/szenen/textGenerationPort.ts
|
|
8640
9372
|
function simulatedAnswerFor(request) {
|
|
8641
9373
|
let input;
|
|
@@ -9140,7 +9872,7 @@ function validateDerivationInput(input) {
|
|
|
9140
9872
|
if (input.policy.produces.length === 0) return "Die Regel erzeugt keinen einzigen Vorschlag.";
|
|
9141
9873
|
return null;
|
|
9142
9874
|
}
|
|
9143
|
-
var
|
|
9875
|
+
var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
9144
9876
|
var MAX_PROPOSAL_TITLE_LENGTH = 120;
|
|
9145
9877
|
function fallbackProposalTitle(type) {
|
|
9146
9878
|
return `Rekonstruktion ${type}`;
|
|
@@ -9157,7 +9889,7 @@ function pruefeNodeLabels(payload) {
|
|
|
9157
9889
|
if (!Array.isArray(payload.nodes)) return { payload, hinweise: [] };
|
|
9158
9890
|
const hinweise = [];
|
|
9159
9891
|
const nodes = payload.nodes.map((node, i) => {
|
|
9160
|
-
if (!
|
|
9892
|
+
if (!isObject13(node) || typeof node.node_id !== "string") return node;
|
|
9161
9893
|
const abgeleitet = kurznameAusNodeId(node.node_id);
|
|
9162
9894
|
if (!("label" in node)) {
|
|
9163
9895
|
hinweise.push({
|
|
@@ -9190,7 +9922,7 @@ function resolveJsonPointer(wurzel, pointer) {
|
|
|
9190
9922
|
aktuell = aktuell[index];
|
|
9191
9923
|
continue;
|
|
9192
9924
|
}
|
|
9193
|
-
if (!
|
|
9925
|
+
if (!isObject13(aktuell) || !(schluessel in aktuell)) {
|
|
9194
9926
|
return { found: false, value: void 0 };
|
|
9195
9927
|
}
|
|
9196
9928
|
aktuell = aktuell[schluessel];
|
|
@@ -9204,7 +9936,7 @@ function collectVersionRefs2(value2) {
|
|
|
9204
9936
|
knoten.forEach(besuchen);
|
|
9205
9937
|
return;
|
|
9206
9938
|
}
|
|
9207
|
-
if (!
|
|
9939
|
+
if (!isObject13(knoten)) return;
|
|
9208
9940
|
if (typeof knoten.element_id === "string" && typeof knoten.version_id === "string") {
|
|
9209
9941
|
gefunden.push({ element_id: knoten.element_id, version_id: knoten.version_id });
|
|
9210
9942
|
}
|
|
@@ -9270,7 +10002,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9270
10002
|
envelope: null,
|
|
9271
10003
|
contract_ok: false
|
|
9272
10004
|
});
|
|
9273
|
-
if (!
|
|
10005
|
+
if (!isObject13(value2)) {
|
|
9274
10006
|
befund({
|
|
9275
10007
|
code: "response.not_object",
|
|
9276
10008
|
severity: "error",
|
|
@@ -9288,7 +10020,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9288
10020
|
});
|
|
9289
10021
|
}
|
|
9290
10022
|
const rohProposals = value2.proposals;
|
|
9291
|
-
const proposalsLesbar =
|
|
10023
|
+
const proposalsLesbar = isObject13(rohProposals);
|
|
9292
10024
|
if (!proposalsLesbar) {
|
|
9293
10025
|
befund({
|
|
9294
10026
|
code: "envelope.proposals_missing",
|
|
@@ -9298,7 +10030,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9298
10030
|
});
|
|
9299
10031
|
}
|
|
9300
10032
|
const roh = proposalsLesbar ? rohProposals : {};
|
|
9301
|
-
const rohGaps =
|
|
10033
|
+
const rohGaps = isObject13(value2.gaps) ? value2.gaps : {};
|
|
9302
10034
|
const gapsUngefragt = Object.keys(rohGaps).filter(
|
|
9303
10035
|
(t) => !input.policy.produces.includes(t)
|
|
9304
10036
|
);
|
|
@@ -9310,7 +10042,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9310
10042
|
pointer: "/gaps"
|
|
9311
10043
|
});
|
|
9312
10044
|
}
|
|
9313
|
-
const fehlend = input.policy.produces.filter((t) => !
|
|
10045
|
+
const fehlend = input.policy.produces.filter((t) => !isObject13(roh[t]));
|
|
9314
10046
|
if (fehlend.length > 0 && proposalsLesbar) {
|
|
9315
10047
|
const d = befund({
|
|
9316
10048
|
code: "envelope.proposals_missing_types",
|
|
@@ -9331,11 +10063,11 @@ function assessDerivationResponse(value2, input) {
|
|
|
9331
10063
|
pointer: "/proposals"
|
|
9332
10064
|
});
|
|
9333
10065
|
}
|
|
9334
|
-
const rohTitles =
|
|
10066
|
+
const rohTitles = isObject13(value2.titles) ? value2.titles : {};
|
|
9335
10067
|
const umgebucht = [];
|
|
9336
10068
|
const ohneLabel = [];
|
|
9337
10069
|
for (const type of input.policy.produces) {
|
|
9338
|
-
if (!
|
|
10070
|
+
if (!isObject13(roh[type])) continue;
|
|
9339
10071
|
const labelPruefung = type === "scene" ? pruefeNodeLabels(roh[type]) : { payload: roh[type], hinweise: [] };
|
|
9340
10072
|
const payload = labelPruefung.payload;
|
|
9341
10073
|
const eigene = [];
|
|
@@ -9372,7 +10104,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9372
10104
|
const bezugPointer = bezug ? `/${bezug.field}` : null;
|
|
9373
10105
|
let gapFehler = false;
|
|
9374
10106
|
for (const eintrag of benannt) {
|
|
9375
|
-
if (!
|
|
10107
|
+
if (!isObject13(eintrag) || typeof eintrag.pointer !== "string" || typeof eintrag.reason !== "string" || !eintrag.reason.trim()) {
|
|
9376
10108
|
eigene.push(befund({
|
|
9377
10109
|
code: "proposal.gap_entry_invalid",
|
|
9378
10110
|
severity: "error",
|
|
@@ -9449,7 +10181,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9449
10181
|
});
|
|
9450
10182
|
} else {
|
|
9451
10183
|
for (const eintrag of value2.not_derivable) {
|
|
9452
|
-
if (!
|
|
10184
|
+
if (!isObject13(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.reason !== "string") {
|
|
9453
10185
|
befund({
|
|
9454
10186
|
code: "envelope.not_derivable_entry_invalid",
|
|
9455
10187
|
severity: "error",
|
|
@@ -9474,7 +10206,7 @@ function assessDerivationResponse(value2, input) {
|
|
|
9474
10206
|
});
|
|
9475
10207
|
} else {
|
|
9476
10208
|
for (const eintrag of value2.conflicts) {
|
|
9477
|
-
if (!
|
|
10209
|
+
if (!isObject13(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.from_image !== "string" || typeof eintrag.from_prompt !== "string") {
|
|
9478
10210
|
befund({
|
|
9479
10211
|
code: "envelope.conflicts_entry_invalid",
|
|
9480
10212
|
severity: "error",
|
|
@@ -10314,9 +11046,46 @@ function usePagedPortQuery(seite, abhaengigkeiten, limit = LOAD_MORE_PAGE_SIZE)
|
|
|
10314
11046
|
const [mehrFehler, setMehrFehler] = useState6(null);
|
|
10315
11047
|
const [token, setToken] = useState6(0);
|
|
10316
11048
|
const sequenz = useRef4(0);
|
|
11049
|
+
const seitenRef = useRef4([]);
|
|
11050
|
+
seitenRef.current = seiten;
|
|
11051
|
+
const zuletzt = useRef4(null);
|
|
10317
11052
|
useEffect5(() => {
|
|
10318
11053
|
const meine = sequenz.current += 1;
|
|
10319
11054
|
let abgemeldet = false;
|
|
11055
|
+
const vorher = zuletzt.current;
|
|
11056
|
+
zuletzt.current = { deps: abhaengigkeiten, token, limit };
|
|
11057
|
+
const nurNeuLaden = vorher !== null && vorher.token !== token && vorher.limit === limit && vorher.deps.length === abhaengigkeiten.length && vorher.deps.every((d, i) => Object.is(d, abhaengigkeiten[i])) && seitenRef.current.length > 0;
|
|
11058
|
+
const fehler5 = (e) => e instanceof Error ? e.message : String(e);
|
|
11059
|
+
if (nurNeuLaden) {
|
|
11060
|
+
const anzahl = seitenRef.current.length;
|
|
11061
|
+
setMehrFehler(null);
|
|
11062
|
+
void (async () => {
|
|
11063
|
+
const neu = [];
|
|
11064
|
+
let cursor = null;
|
|
11065
|
+
try {
|
|
11066
|
+
while (neu.length < anzahl) {
|
|
11067
|
+
const ergebnis = await seite(cursor, limit);
|
|
11068
|
+
if (abgemeldet || meine !== sequenz.current) return;
|
|
11069
|
+
if (ergebnis.kind !== "ok") {
|
|
11070
|
+
setMehrFehler(ergebnis.message);
|
|
11071
|
+
return;
|
|
11072
|
+
}
|
|
11073
|
+
neu.push(ergebnis.value);
|
|
11074
|
+
if (!ergebnis.value.hasMore) break;
|
|
11075
|
+
cursor = ergebnis.value.nextCursor;
|
|
11076
|
+
}
|
|
11077
|
+
} catch (e) {
|
|
11078
|
+
if (!abgemeldet && meine === sequenz.current) setMehrFehler(fehler5(e));
|
|
11079
|
+
return;
|
|
11080
|
+
}
|
|
11081
|
+
setLaedtMehr(false);
|
|
11082
|
+
setPhase({ status: "ready", value: neu[0] });
|
|
11083
|
+
setSeiten(neu);
|
|
11084
|
+
})();
|
|
11085
|
+
return () => {
|
|
11086
|
+
abgemeldet = true;
|
|
11087
|
+
};
|
|
11088
|
+
}
|
|
10320
11089
|
setPhase({ status: "loading" });
|
|
10321
11090
|
setSeiten([]);
|
|
10322
11091
|
setLaedtMehr(false);
|
|
@@ -10337,7 +11106,7 @@ function usePagedPortQuery(seite, abhaengigkeiten, limit = LOAD_MORE_PAGE_SIZE)
|
|
|
10337
11106
|
if (abgemeldet || meine !== sequenz.current) return;
|
|
10338
11107
|
setPhase({
|
|
10339
11108
|
status: "error",
|
|
10340
|
-
message:
|
|
11109
|
+
message: fehler5(e),
|
|
10341
11110
|
retryable: true
|
|
10342
11111
|
});
|
|
10343
11112
|
});
|
|
@@ -10655,7 +11424,7 @@ function ortVon(instanz) {
|
|
|
10655
11424
|
|
|
10656
11425
|
// src/features/szenen/areas/SceneEditor.tsx
|
|
10657
11426
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
10658
|
-
var
|
|
11427
|
+
var NODE_TYPES2 = [
|
|
10659
11428
|
"subject",
|
|
10660
11429
|
"object",
|
|
10661
11430
|
"surface",
|
|
@@ -10807,7 +11576,7 @@ var SceneEditor = ({
|
|
|
10807
11576
|
"data-testid": "neuer-node-typ",
|
|
10808
11577
|
value: neuerTyp,
|
|
10809
11578
|
onChange: (e) => setNeuerTyp(e.target.value),
|
|
10810
|
-
children:
|
|
11579
|
+
children: NODE_TYPES2.map((t) => /* @__PURE__ */ jsx6("option", { value: t, children: NODE_TYPE_LABELS[t] }, t))
|
|
10811
11580
|
}
|
|
10812
11581
|
),
|
|
10813
11582
|
/* @__PURE__ */ jsx6(
|
|
@@ -10961,7 +11730,7 @@ var NodeFormular = ({
|
|
|
10961
11730
|
value: node.type,
|
|
10962
11731
|
disabled: readOnly,
|
|
10963
11732
|
onChange: (e) => aendere({ ...node, type: e.target.value }),
|
|
10964
|
-
children:
|
|
11733
|
+
children: NODE_TYPES2.map((t) => /* @__PURE__ */ jsx6("option", { value: t, children: NODE_TYPE_LABELS[t] }, t))
|
|
10965
11734
|
}
|
|
10966
11735
|
)
|
|
10967
11736
|
] }),
|
|
@@ -11997,8 +12766,8 @@ function feldLabel(type, pfad, name) {
|
|
|
11997
12766
|
|
|
11998
12767
|
// src/features/szenen/areas/SchemaFields.tsx
|
|
11999
12768
|
import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
12000
|
-
var
|
|
12001
|
-
var istVersionRef = (v) =>
|
|
12769
|
+
var isObject14 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
12770
|
+
var istVersionRef = (v) => isObject14(v) && typeof v.element_id === "string" && typeof v.version_id === "string";
|
|
12002
12771
|
function leseJson(wert) {
|
|
12003
12772
|
if (!wert || wert === NULL_MARKER) return null;
|
|
12004
12773
|
try {
|
|
@@ -12226,13 +12995,13 @@ var VersionRefListeFeld = ({ port, kontextkette, feld: feld2, wert, onChange, re
|
|
|
12226
12995
|
}
|
|
12227
12996
|
const schreiben = (neu) => onChange(
|
|
12228
12997
|
feld2.path,
|
|
12229
|
-
schreibListe(neu.map((eintrag, i) =>
|
|
12998
|
+
schreibListe(neu.map((eintrag, i) => isObject14(eintrag) && mitRolle2 ? { ...eintrag, rank: i } : eintrag))
|
|
12230
12999
|
);
|
|
12231
13000
|
return /* @__PURE__ */ jsxs10("div", { className: "szenen-feld__reflist", "data-testid": `reflist-${feld2.path}`, children: [
|
|
12232
13001
|
liste.length === 0 && /* @__PURE__ */ jsx11("p", { "data-testid": `reflist-${feld2.path}-leer`, children: "Keine Eintr\xE4ge." }),
|
|
12233
13002
|
/* @__PURE__ */ jsx11("ol", { children: liste.map((eintrag, index) => /* @__PURE__ */ jsxs10("li", { "data-testid": `reflist-${feld2.path}-${index}`, children: [
|
|
12234
13003
|
istVersionRef(eintrag) ? /* @__PURE__ */ jsx11(RefAnzeige, { port, ref_: eintrag, testId: `reflist-${feld2.path}-${index}-ref` }) : /* @__PURE__ */ jsx11("code", { children: JSON.stringify(eintrag) }),
|
|
12235
|
-
mitRolle2 === "styleRole" &&
|
|
13004
|
+
mitRolle2 === "styleRole" && isObject14(eintrag) && /* @__PURE__ */ jsxs10(
|
|
12236
13005
|
"select",
|
|
12237
13006
|
{
|
|
12238
13007
|
"data-testid": `reflist-${feld2.path}-${index}-role`,
|
|
@@ -12245,7 +13014,7 @@ var VersionRefListeFeld = ({ port, kontextkette, feld: feld2, wert, onChange, re
|
|
|
12245
13014
|
]
|
|
12246
13015
|
}
|
|
12247
13016
|
),
|
|
12248
|
-
mitRolle2 === "frei" &&
|
|
13017
|
+
mitRolle2 === "frei" && isObject14(eintrag) && /* @__PURE__ */ jsx11(
|
|
12249
13018
|
"input",
|
|
12250
13019
|
{
|
|
12251
13020
|
"data-testid": `reflist-${feld2.path}-${index}-role`,
|
|
@@ -12255,7 +13024,7 @@ var VersionRefListeFeld = ({ port, kontextkette, feld: feld2, wert, onChange, re
|
|
|
12255
13024
|
onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...x, role: e.target.value } : x))
|
|
12256
13025
|
}
|
|
12257
13026
|
),
|
|
12258
|
-
mitGewicht &&
|
|
13027
|
+
mitGewicht && isObject14(eintrag) && /* @__PURE__ */ jsx11(
|
|
12259
13028
|
"input",
|
|
12260
13029
|
{
|
|
12261
13030
|
"data-testid": `reflist-${feld2.path}-${index}-weight`,
|
|
@@ -12453,7 +13222,7 @@ var KameraFeld = ({
|
|
|
12453
13222
|
if (phase.status !== "ready" || !phase.value) return [];
|
|
12454
13223
|
const cameras = valueAtPath(phase.value.payload, "camera_rig.cameras");
|
|
12455
13224
|
if (!Array.isArray(cameras)) return [];
|
|
12456
|
-
return cameras.filter(
|
|
13225
|
+
return cameras.filter(isObject14).map((c) => ({
|
|
12457
13226
|
id: typeof c.camera_id === "string" ? c.camera_id : null,
|
|
12458
13227
|
name: typeof c.name === "string" ? c.name : null
|
|
12459
13228
|
})).filter((c) => c.id !== null);
|
|
@@ -12598,11 +13367,11 @@ var MediaRefListeFeld = ({ feld: feld2, wert, onChange, readOnly }) => {
|
|
|
12598
13367
|
}
|
|
12599
13368
|
const schreiben = (neu) => onChange(
|
|
12600
13369
|
feld2.path,
|
|
12601
|
-
schreibListe(neu.map((e, i) =>
|
|
13370
|
+
schreibListe(neu.map((e, i) => isObject14(e) ? { ...e, position: i } : e))
|
|
12602
13371
|
);
|
|
12603
13372
|
return /* @__PURE__ */ jsxs10("div", { className: "szenen-feld__liste", "data-testid": `feld-${feld2.path}`, children: [
|
|
12604
13373
|
liste.map((eintrag, index) => {
|
|
12605
|
-
const objekt =
|
|
13374
|
+
const objekt = isObject14(eintrag) ? eintrag : {};
|
|
12606
13375
|
return /* @__PURE__ */ jsxs10("div", { className: "szenen-feld__liste-zeile", children: [
|
|
12607
13376
|
/* @__PURE__ */ jsx11(
|
|
12608
13377
|
"input",
|
|
@@ -12611,7 +13380,7 @@ var MediaRefListeFeld = ({ feld: feld2, wert, onChange, readOnly }) => {
|
|
|
12611
13380
|
value: typeof objekt.asset_id === "string" ? objekt.asset_id : "",
|
|
12612
13381
|
readOnly,
|
|
12613
13382
|
placeholder: "asset_id (UUID)",
|
|
12614
|
-
onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...
|
|
13383
|
+
onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject14(x) ? x : {}, asset_id: e.target.value } : x))
|
|
12615
13384
|
}
|
|
12616
13385
|
),
|
|
12617
13386
|
/* @__PURE__ */ jsxs10(
|
|
@@ -12620,7 +13389,7 @@ var MediaRefListeFeld = ({ feld: feld2, wert, onChange, readOnly }) => {
|
|
|
12620
13389
|
"data-testid": `feld-${feld2.path}-${index}-rolle`,
|
|
12621
13390
|
value: typeof objekt.role === "string" ? objekt.role : "",
|
|
12622
13391
|
disabled: readOnly,
|
|
12623
|
-
onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...
|
|
13392
|
+
onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject14(x) ? x : {}, role: e.target.value } : x)),
|
|
12624
13393
|
children: [
|
|
12625
13394
|
/* @__PURE__ */ jsx11("option", { value: "", children: "(Rolle w\xE4hlen)" }),
|
|
12626
13395
|
rollen.map((r) => /* @__PURE__ */ jsx11("option", { value: r, children: r }, r))
|
|
@@ -12663,7 +13432,7 @@ var LEERES_PROFIL = {
|
|
|
12663
13432
|
var listeAus = (text2) => text2.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
12664
13433
|
var AusfuehrungsprofileFeld = ({ feld: feld2, wert, onChange, readOnly }) => {
|
|
12665
13434
|
const gelesen = leseListe(wert);
|
|
12666
|
-
const profile = (gelesen ?? []).filter(
|
|
13435
|
+
const profile = (gelesen ?? []).filter(isObject14);
|
|
12667
13436
|
const unlesbar = gelesen === null;
|
|
12668
13437
|
const schreibe = (neu) => onChange(feld2.path, schreibListe(neu));
|
|
12669
13438
|
const alleBefunde = checkImageExecutionProfiles(profile);
|
|
@@ -15419,6 +16188,7 @@ var STATUS_TEXT = {
|
|
|
15419
16188
|
failed: "fehlgeschlagen"
|
|
15420
16189
|
};
|
|
15421
16190
|
function herkunftChip(lauf) {
|
|
16191
|
+
if (variantOf(lauf)) return "Variante \xFCber MCP";
|
|
15422
16192
|
if (lauf.provider === MANUAL_PROVIDER) return "manuell eingetragen";
|
|
15423
16193
|
if (lauf.provider === MCP_CLIENT_PROVIDER) return "\xFCber MCP";
|
|
15424
16194
|
return lauf.model_id;
|
|
@@ -15464,6 +16234,7 @@ var LaufInhalt = ({
|
|
|
15464
16234
|
onItemGespeichert();
|
|
15465
16235
|
};
|
|
15466
16236
|
const handeingabe = manualEntryOf(lauf);
|
|
16237
|
+
const variante = variantOf(lauf);
|
|
15467
16238
|
const id = lauf.run_id;
|
|
15468
16239
|
const promptUndTags = /* @__PURE__ */ jsxs18(Fragment9, { children: [
|
|
15469
16240
|
lauf.status === "succeeded" && lauf.output && /* @__PURE__ */ jsx20(
|
|
@@ -15530,6 +16301,23 @@ var LaufInhalt = ({
|
|
|
15530
16301
|
/* @__PURE__ */ jsx20("summary", { children: "Erl\xE4uterung des Modells" }),
|
|
15531
16302
|
/* @__PURE__ */ jsx20("p", { "data-testid": `feedback-${id}`, children: lauf.output.feedback })
|
|
15532
16303
|
] }),
|
|
16304
|
+
variante && /* @__PURE__ */ jsxs18("section", { className: "szenen-lauf__handeingabe", "data-testid": `variante-${id}`, children: [
|
|
16305
|
+
/* @__PURE__ */ jsx20("h5", { children: "Promptvariante" }),
|
|
16306
|
+
/* @__PURE__ */ jsxs18("p", { children: [
|
|
16307
|
+
"Snapshot und Eingangsbilder aus Lauf",
|
|
16308
|
+
" ",
|
|
16309
|
+
/* @__PURE__ */ jsx20("code", { children: variante.source_run_id }),
|
|
16310
|
+
"; der Prompttext stammt unver\xE4ndert vom MCP-Aufrufer."
|
|
16311
|
+
] }),
|
|
16312
|
+
variante.input_assets.map((asset) => /* @__PURE__ */ jsxs18("p", { "data-testid": `variante-asset-${id}-${asset.position}`, children: [
|
|
16313
|
+
"Eingang ",
|
|
16314
|
+
asset.position + 1,
|
|
16315
|
+
asset.prompt_token ? ` (${asset.prompt_token})` : "",
|
|
16316
|
+
":",
|
|
16317
|
+
" ",
|
|
16318
|
+
/* @__PURE__ */ jsx20("code", { children: asset.asset_id })
|
|
16319
|
+
] }, asset.asset_id))
|
|
16320
|
+
] }),
|
|
15533
16321
|
handeingabe && /* @__PURE__ */ jsxs18("section", { className: "szenen-lauf__handeingabe", "data-testid": `handeingabe-${id}`, children: [
|
|
15534
16322
|
/* @__PURE__ */ jsx20("h5", { children: "Manuell erfasst" }),
|
|
15535
16323
|
/* @__PURE__ */ jsxs18("p", { "data-testid": `handeingabe-von-${id}`, children: [
|
|
@@ -16658,12 +17446,12 @@ var ElementSheet = ({
|
|
|
16658
17446
|
import { useEffect as useEffect15, useMemo as useMemo6, useRef as useRef11, useState as useState21 } from "react";
|
|
16659
17447
|
|
|
16660
17448
|
// src/lib/szenen/bausteinKatalog.ts
|
|
16661
|
-
var
|
|
17449
|
+
var isObject15 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
16662
17450
|
var text = (v) => typeof v === "string" && v.trim() !== "" ? v : null;
|
|
16663
17451
|
function kachelAssetId(payload) {
|
|
16664
|
-
const refs =
|
|
17452
|
+
const refs = isObject15(payload) && Array.isArray(payload.media_refs) ? payload.media_refs : [];
|
|
16665
17453
|
for (const rolle of ["example", "reference"]) {
|
|
16666
|
-
const treffer = refs.find((r) =>
|
|
17454
|
+
const treffer = refs.find((r) => isObject15(r) && r.role === rolle && typeof r.asset_id === "string");
|
|
16667
17455
|
if (treffer) return treffer.asset_id;
|
|
16668
17456
|
}
|
|
16669
17457
|
return null;
|
|
@@ -16706,7 +17494,7 @@ async function bausteinKatalog(queries, kette) {
|
|
|
16706
17494
|
katalog.push({ ...basis, titel, zustand: { art: "fork" } });
|
|
16707
17495
|
continue;
|
|
16708
17496
|
}
|
|
16709
|
-
const payload =
|
|
17497
|
+
const payload = isObject15(version.payload) ? version.payload : {};
|
|
16710
17498
|
katalog.push({
|
|
16711
17499
|
element_id: stammsatz.element_id,
|
|
16712
17500
|
titel,
|
|
@@ -17037,7 +17825,7 @@ var BausteinSheet = ({
|
|
|
17037
17825
|
import React21, { useEffect as useEffect17, useState as useState23, useRef as useRef12, useReducer } from "react";
|
|
17038
17826
|
|
|
17039
17827
|
// src/features/szenen/areas/loadStageEngine.ts
|
|
17040
|
-
var loadStageEngine = () => import("./StageEngine-
|
|
17828
|
+
var loadStageEngine = () => import("./StageEngine-PYWITIIY.mjs");
|
|
17041
17829
|
|
|
17042
17830
|
// src/features/szenen/areas/StagePromptSettings.tsx
|
|
17043
17831
|
import { useEffect as useEffect16, useState as useState22 } from "react";
|
|
@@ -17050,9 +17838,13 @@ function StagePromptSettings({ port, contextId, forElementId, target, settings,
|
|
|
17050
17838
|
const [inspection, setInspection] = useState22(null);
|
|
17051
17839
|
const [inspectionError, setInspectionError] = useState22("");
|
|
17052
17840
|
const [previewImage, setPreviewImage] = useState22("");
|
|
17841
|
+
const [request, setRequest] = useState22(0);
|
|
17842
|
+
const [rendering, setRendering] = useState22(false);
|
|
17843
|
+
const [renderedBasis, setRenderedBasis] = useState22(null);
|
|
17053
17844
|
const inputFingerprint = JSON.stringify(input);
|
|
17054
17845
|
const settingsFingerprint = JSON.stringify(settings);
|
|
17055
17846
|
const [instruction, setInstruction] = useState22(settings.user_instruction ?? "");
|
|
17847
|
+
const basis = JSON.stringify([inputFingerprint, settingsFingerprint, instruction, target, forElementId, contextId, tags]);
|
|
17056
17848
|
useEffect16(() => setInstruction(settings.user_instruction ?? ""), [settings.user_instruction]);
|
|
17057
17849
|
useEffect16(() => {
|
|
17058
17850
|
let live = true;
|
|
@@ -17110,10 +17902,10 @@ function StagePromptSettings({ port, contextId, forElementId, target, settings,
|
|
|
17110
17902
|
};
|
|
17111
17903
|
}, [port, contextId, forElementId, target, settings.reference_sentence_tag, tags]);
|
|
17112
17904
|
useEffect16(() => {
|
|
17905
|
+
if (!request) return;
|
|
17113
17906
|
let live = true;
|
|
17114
|
-
setInspection(null);
|
|
17115
|
-
setPreviewImage("");
|
|
17116
17907
|
setInspectionError("");
|
|
17908
|
+
setRendering(true);
|
|
17117
17909
|
const timer = setTimeout(() => {
|
|
17118
17910
|
void (async () => {
|
|
17119
17911
|
try {
|
|
@@ -17152,17 +17944,22 @@ function StagePromptSettings({ port, contextId, forElementId, target, settings,
|
|
|
17152
17944
|
if (live) {
|
|
17153
17945
|
setInspection(prepared);
|
|
17154
17946
|
setPreviewImage(`data:${preview.mime_type};base64,${preview.data}`);
|
|
17947
|
+
setRenderedBasis(basis);
|
|
17155
17948
|
}
|
|
17156
17949
|
} catch (e) {
|
|
17157
17950
|
if (live) setInspectionError(String(e));
|
|
17951
|
+
} finally {
|
|
17952
|
+
if (live) setRendering(false);
|
|
17158
17953
|
}
|
|
17159
17954
|
})();
|
|
17160
|
-
},
|
|
17955
|
+
}, 50);
|
|
17161
17956
|
return () => {
|
|
17162
17957
|
live = false;
|
|
17163
17958
|
clearTimeout(timer);
|
|
17959
|
+
setRendering(false);
|
|
17164
17960
|
};
|
|
17165
|
-
}, [
|
|
17961
|
+
}, [request]);
|
|
17962
|
+
const stale = !!inspection && renderedBasis !== basis;
|
|
17166
17963
|
const selected = settings.prompt_tags ?? [];
|
|
17167
17964
|
const groups = ["Inhalt", "Stil", "Regeln", "Anweisungen"];
|
|
17168
17965
|
const missing = selected.filter((s) => !tags.some((t) => same(t, s)));
|
|
@@ -17243,8 +18040,11 @@ function StagePromptSettings({ port, contextId, forElementId, target, settings,
|
|
|
17243
18040
|
/* @__PURE__ */ jsx27("p", { className: "szenen-3d__referenz", "aria-live": "polite", children: reference }),
|
|
17244
18041
|
/* @__PURE__ */ jsxs25("div", { className: "szenen-3d__gemini", "aria-label": "Gemini-Eingabe vor der Erzeugung", children: [
|
|
17245
18042
|
/* @__PURE__ */ jsx27("h5", { children: "Das erh\xE4lt Gemini" }),
|
|
18043
|
+
/* @__PURE__ */ jsx27("button", { type: "button", disabled: rendering || !input || !previewRenderer, onClick: () => setRequest((n) => n + 1), children: inspection ? "Preview aktualisieren" : "Preview erzeugen" }),
|
|
18044
|
+
rendering && /* @__PURE__ */ jsx27("p", { role: "status", children: "Preview wird gerendert \u2026" }),
|
|
17246
18045
|
inspectionError && /* @__PURE__ */ jsx27("p", { role: "alert", children: inspectionError }),
|
|
17247
|
-
!inspection && !inspectionError && /* @__PURE__ */ jsx27("p", { children: "
|
|
18046
|
+
!inspection && !inspectionError && !rendering && /* @__PURE__ */ jsx27("p", { className: "szenen-3d__hinweis", children: "Noch kein Preview. Das Rendern dauert auf dem Handy einige Sekunden; beim Ableiten des Prompts wird es ohnehin neu erzeugt." }),
|
|
18047
|
+
stale && !rendering && /* @__PURE__ */ jsx27("p", { role: "status", className: "szenen-3d__hinweis", children: "Veraltet: B\xFChne oder Einstellungen haben sich seit diesem Preview ge\xE4ndert." }),
|
|
17248
18048
|
inspection && /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
17249
18049
|
previewImage && /* @__PURE__ */ jsx27("img", { src: previewImage, alt: "Referenzbild f\xFCr Gemini" }),
|
|
17250
18050
|
/* @__PURE__ */ jsx27("p", { children: "Gemini erh\xE4lt dieses Preview und die folgende Objektzuordnung. Bildverweise sind derzeit Asset-Kennungen; Objektbilder werden noch nicht mitgesendet." }),
|
|
@@ -17285,7 +18085,9 @@ var value = (r) => {
|
|
|
17285
18085
|
return r.value;
|
|
17286
18086
|
};
|
|
17287
18087
|
var errorText = (e) => e instanceof Error ? e.message : String(e);
|
|
17288
|
-
var VIEWS = [["top", "Draufsicht"], ["side", "Seitenansicht"], ["camera", "Kamera"]];
|
|
18088
|
+
var VIEWS = [["top", "Draufsicht"], ["side", "Seitenansicht"], ["camera", "Kamera"], ["free", "Freie Ansicht"]];
|
|
18089
|
+
var ANCHORS_BASIC = [["center", "Mitte"], ["base", "Boden"]];
|
|
18090
|
+
var ANCHORS_HUMAN = [...ANCHORS_BASIC, ["head", "Kopf"], ["eyes", "Augen"], ["face", "Gesicht"], ["hands", "H\xE4nde"], ["left_shoulder", "Linke Schulter"], ["right_shoulder", "Rechte Schulter"]];
|
|
17289
18091
|
var StageBoundary = class extends React21.Component {
|
|
17290
18092
|
constructor() {
|
|
17291
18093
|
super(...arguments);
|
|
@@ -17333,17 +18135,122 @@ function MeterField({ label, axis, value: current, min, step, disabled, onCommit
|
|
|
17333
18135
|
)
|
|
17334
18136
|
] });
|
|
17335
18137
|
}
|
|
18138
|
+
function MorphField({ label, value: stored, onCommit }) {
|
|
18139
|
+
const [pending, setPending] = useState23(stored), last = useRef12(stored);
|
|
18140
|
+
useEffect17(() => {
|
|
18141
|
+
setPending(stored);
|
|
18142
|
+
last.current = stored;
|
|
18143
|
+
}, [stored]);
|
|
18144
|
+
const commit = (value2) => {
|
|
18145
|
+
if (value2 !== last.current) {
|
|
18146
|
+
last.current = value2;
|
|
18147
|
+
onCommit(value2);
|
|
18148
|
+
}
|
|
18149
|
+
};
|
|
18150
|
+
return /* @__PURE__ */ jsxs26("label", { className: "szenen-3d__morph", children: [
|
|
18151
|
+
label,
|
|
18152
|
+
/* @__PURE__ */ jsx28(
|
|
18153
|
+
"input",
|
|
18154
|
+
{
|
|
18155
|
+
"aria-label": label,
|
|
18156
|
+
type: "range",
|
|
18157
|
+
min: "0",
|
|
18158
|
+
max: "1",
|
|
18159
|
+
step: ".01",
|
|
18160
|
+
value: pending,
|
|
18161
|
+
onChange: (e) => setPending(Number(e.currentTarget.value)),
|
|
18162
|
+
onPointerUp: (e) => commit(Number(e.currentTarget.value)),
|
|
18163
|
+
onPointerCancel: () => setPending(stored),
|
|
18164
|
+
onKeyUp: (e) => commit(Number(e.currentTarget.value)),
|
|
18165
|
+
onBlur: (e) => commit(Number(e.currentTarget.value))
|
|
18166
|
+
}
|
|
18167
|
+
)
|
|
18168
|
+
] });
|
|
18169
|
+
}
|
|
18170
|
+
function ColorField({ hex, explicit, disabled, onCommit, onReset }) {
|
|
18171
|
+
const [pending, setPending] = useState23(hex);
|
|
18172
|
+
const [text2, setText] = useState23(hex);
|
|
18173
|
+
useEffect17(() => {
|
|
18174
|
+
setPending(hex);
|
|
18175
|
+
setText(hex);
|
|
18176
|
+
}, [hex]);
|
|
18177
|
+
const changed = pending !== hex;
|
|
18178
|
+
const discard = () => {
|
|
18179
|
+
setPending(hex);
|
|
18180
|
+
setText(hex);
|
|
18181
|
+
};
|
|
18182
|
+
const commit = () => {
|
|
18183
|
+
if (changed) onCommit(pending);
|
|
18184
|
+
};
|
|
18185
|
+
return /* @__PURE__ */ jsxs26("div", { className: "szenen-3d__farbe", children: [
|
|
18186
|
+
/* @__PURE__ */ jsx28(
|
|
18187
|
+
"input",
|
|
18188
|
+
{
|
|
18189
|
+
type: "color",
|
|
18190
|
+
value: pending,
|
|
18191
|
+
disabled,
|
|
18192
|
+
"aria-label": "Markerfarbe w\xE4hlen",
|
|
18193
|
+
onChange: (e) => {
|
|
18194
|
+
const next = normalizePreviewColor(e.currentTarget.value);
|
|
18195
|
+
if (next) {
|
|
18196
|
+
setPending(next);
|
|
18197
|
+
setText(next);
|
|
18198
|
+
}
|
|
18199
|
+
}
|
|
18200
|
+
}
|
|
18201
|
+
),
|
|
18202
|
+
/* @__PURE__ */ jsx28(
|
|
18203
|
+
"input",
|
|
18204
|
+
{
|
|
18205
|
+
type: "text",
|
|
18206
|
+
value: text2,
|
|
18207
|
+
disabled,
|
|
18208
|
+
inputMode: "text",
|
|
18209
|
+
autoComplete: "off",
|
|
18210
|
+
spellCheck: false,
|
|
18211
|
+
maxLength: 7,
|
|
18212
|
+
"aria-label": "Markerfarbe als Hexwert",
|
|
18213
|
+
onChange: (e) => {
|
|
18214
|
+
const raw = e.currentTarget.value;
|
|
18215
|
+
setText(raw);
|
|
18216
|
+
const next = normalizePreviewColor(raw.startsWith("#") ? raw : `#${raw}`);
|
|
18217
|
+
if (next) setPending(next);
|
|
18218
|
+
},
|
|
18219
|
+
onKeyDown: (e) => {
|
|
18220
|
+
if (e.key === "Enter") {
|
|
18221
|
+
e.preventDefault();
|
|
18222
|
+
commit();
|
|
18223
|
+
} else if (e.key === "Escape") discard();
|
|
18224
|
+
}
|
|
18225
|
+
}
|
|
18226
|
+
),
|
|
18227
|
+
changed ? /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18228
|
+
/* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__farbe-uebernehmen", disabled, onClick: commit, children: "Farbe \xFCbernehmen" }),
|
|
18229
|
+
/* @__PURE__ */ jsx28("button", { type: "button", disabled, onClick: discard, children: "Verwerfen" })
|
|
18230
|
+
] }) : explicit ? /* @__PURE__ */ jsx28("button", { type: "button", disabled, onClick: onReset, children: "Standardfarbe" }) : /* @__PURE__ */ jsx28("span", { className: "szenen-3d__farbe-auto", children: "automatisch" })
|
|
18231
|
+
] });
|
|
18232
|
+
}
|
|
17336
18233
|
function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, embedded = false }) {
|
|
17337
18234
|
const [engine, setEngine] = useState23(null);
|
|
17338
18235
|
const [choices, setChoices] = useState23([]);
|
|
17339
18236
|
const [choice, setChoice] = useState23("");
|
|
17340
18237
|
const [working, setWorking] = useState23(null);
|
|
17341
18238
|
const [shown, setShown] = useState23(null);
|
|
18239
|
+
const shownRef = useRef12(null);
|
|
17342
18240
|
const previewRef = useRef12(null);
|
|
17343
18241
|
const [input, setInput] = useState23(null);
|
|
18242
|
+
const resolvedRef = useRef12(null), exportSources = useRef12(null);
|
|
17344
18243
|
const [view, setView] = useState23("top");
|
|
17345
18244
|
const [selected, setSelected] = useState23(null);
|
|
18245
|
+
const [objectTarget, setObjectTarget] = useState23("");
|
|
18246
|
+
const [sichtbar, setSichtbar] = useState23({ nodes: /* @__PURE__ */ new Set(), walls: /* @__PURE__ */ new Set(), floors: /* @__PURE__ */ new Set(), ground: true, camera: true });
|
|
18247
|
+
const [blatt, setBlatt] = useState23(false);
|
|
18248
|
+
const [vollbild, setVollbild] = useState23(false);
|
|
18249
|
+
const [kameraBlatt, setKameraBlatt] = useState23(false);
|
|
18250
|
+
const buehne = useRef12(null);
|
|
18251
|
+
const [entfernen, setEntfernen] = useState23(null);
|
|
17346
18252
|
const [message, setMessage] = useState23("B\xFChne wird geladen \u2026");
|
|
18253
|
+
const [vorab, setVorab] = useState23([]);
|
|
17347
18254
|
const [busy, setBusy] = useState23(false);
|
|
17348
18255
|
const [pending, setPending] = useState23(0);
|
|
17349
18256
|
const [targets, setTargets] = useState23([]);
|
|
@@ -17373,12 +18280,16 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17373
18280
|
chain: { scene: { element_id: w.scene.element.element_id, version_id: "", payload: w.scenePayload }, setup: { element_id: w.setup.element.element_id, version_id: "", payload: w.setupPayload } }
|
|
17374
18281
|
});
|
|
17375
18282
|
if (result.kind !== "resolved") throw new Error(result.failure.message);
|
|
17376
|
-
|
|
18283
|
+
const resolved = withCameraPreviewMetadata(result.input, w.scenePayload);
|
|
18284
|
+
resolvedRef.current = resolved;
|
|
18285
|
+
exportSources.current = Object.fromEntries(["scene", "setup", "shot"].map((key) => [key, { element_id: w[key].element.element_id, version_id: null, draft: { draft_id: w[key].draft.draft_id, revision: w[key].draft.revision } }]));
|
|
18286
|
+
setInput(resolved);
|
|
18287
|
+
return resolved;
|
|
17377
18288
|
}
|
|
17378
18289
|
async function reload(w) {
|
|
17379
18290
|
const [scene, setup, shot] = await Promise.all([read(w.scene.element.element_id), read(w.setup.element.element_id), read(w.shot.element.element_id)]);
|
|
17380
18291
|
if (!scene.draft || !setup.draft || !shot.draft) throw new Error("Ein B\xFChnenentwurf fehlt. Bitte den Aufbau erneut \xF6ffnen.");
|
|
17381
|
-
|
|
18292
|
+
return resolve({ scene, setup, shot, scenePayload: scene.draft.payload, setupPayload: setup.draft.payload, shotPayload: shot.draft.payload });
|
|
17382
18293
|
}
|
|
17383
18294
|
async function act(operation) {
|
|
17384
18295
|
if (busy) return;
|
|
@@ -17398,8 +18309,8 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17398
18309
|
setPending((n) => n + 1);
|
|
17399
18310
|
setMessage("");
|
|
17400
18311
|
queue.current = queue.current.then(async () => {
|
|
17401
|
-
if (generation !== epoch.current) return;
|
|
17402
18312
|
try {
|
|
18313
|
+
if (generation !== epoch.current) return;
|
|
17403
18314
|
if (!workingRef.current && previewRef.current) await open(previewRef.current);
|
|
17404
18315
|
const w = workingRef.current;
|
|
17405
18316
|
if (!w) return;
|
|
@@ -17424,6 +18335,10 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17424
18335
|
});
|
|
17425
18336
|
}
|
|
17426
18337
|
async function write(w, which, payload) {
|
|
18338
|
+
const pinned = pinPreviewColors(which === "scene" ? payload : w.scenePayload, w.setupPayload, w.shotPayload);
|
|
18339
|
+
if (which === "scene") payload = pinned;
|
|
18340
|
+
else if (JSON.stringify(pinned) !== JSON.stringify(w.scenePayload))
|
|
18341
|
+
value(await port.elements.writeDraft({ elementId: w.scene.element.element_id, payload: pinned, expectedRevision: w.scene.draft.revision }));
|
|
17427
18342
|
const s = w[which];
|
|
17428
18343
|
value(await port.elements.writeDraft({ elementId: s.element.element_id, payload, expectedRevision: s.draft.revision }));
|
|
17429
18344
|
await reload(w);
|
|
@@ -17452,7 +18367,11 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17452
18367
|
let live = true;
|
|
17453
18368
|
void (async () => {
|
|
17454
18369
|
try {
|
|
17455
|
-
const
|
|
18370
|
+
const engineLaden = loadStageEngine();
|
|
18371
|
+
const szeneFrueh = await read(sceneElementId);
|
|
18372
|
+
const szenePayloadFrueh = szeneFrueh.draft?.payload ?? szeneFrueh.versions[szeneFrueh.versions.length - 1]?.payload;
|
|
18373
|
+
if (live && Array.isArray(szenePayloadFrueh?.nodes)) setVorab(szenePayloadFrueh.nodes);
|
|
18374
|
+
const loaded = await engineLaden;
|
|
17456
18375
|
const chain = value(await port.context.chainFor(contextId));
|
|
17457
18376
|
const list = value(await port.elements.listElements({ type: "scene_setup" })).filter((e) => chain.includes(e.context_id));
|
|
17458
18377
|
const snapshots = await Promise.all(list.map((e) => read(e.element_id)));
|
|
@@ -17496,6 +18415,32 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17496
18415
|
live = false;
|
|
17497
18416
|
};
|
|
17498
18417
|
}, [port, sceneElementId, contextId]);
|
|
18418
|
+
useEffect17(() => {
|
|
18419
|
+
if (selected && blatt) setKameraBlatt(false);
|
|
18420
|
+
}, [selected, blatt]);
|
|
18421
|
+
useEffect17(() => {
|
|
18422
|
+
if (selected && (sichtbar.nodes.has(selected) || sichtbar.walls.has(selected) && sichtbar.floors.has(selected))) setSelected(null);
|
|
18423
|
+
}, [selected, sichtbar]);
|
|
18424
|
+
useEffect17(() => {
|
|
18425
|
+
if (!vollbild) return;
|
|
18426
|
+
const el = buehne.current, root = document.documentElement, overflow = root.style.overflow;
|
|
18427
|
+
root.style.overflow = "hidden";
|
|
18428
|
+
let api = false;
|
|
18429
|
+
const left = () => {
|
|
18430
|
+
if (api && !document.fullscreenElement) setVollbild(false);
|
|
18431
|
+
};
|
|
18432
|
+
document.addEventListener("fullscreenchange", left);
|
|
18433
|
+
if (el?.requestFullscreen && !document.fullscreenElement) el.requestFullscreen({ navigationUI: "hide" }).then(() => {
|
|
18434
|
+
api = true;
|
|
18435
|
+
}, () => {
|
|
18436
|
+
});
|
|
18437
|
+
return () => {
|
|
18438
|
+
document.removeEventListener("fullscreenchange", left);
|
|
18439
|
+
root.style.overflow = overflow;
|
|
18440
|
+
if (document.fullscreenElement === el) void document.exitFullscreen().catch(() => {
|
|
18441
|
+
});
|
|
18442
|
+
};
|
|
18443
|
+
}, [vollbild]);
|
|
17499
18444
|
async function preview(c) {
|
|
17500
18445
|
const scene = await read(sceneElementId);
|
|
17501
18446
|
const scenePayload = scene.draft?.payload ?? scene.versions.find((v) => v.version_id === c.payload.scene_ref?.version_id)?.payload;
|
|
@@ -17513,53 +18458,49 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17513
18458
|
chain: { scene: { element_id: sceneElementId, version_id: "", payload: scenePayload }, setup: { element_id: c.setup.element.element_id, version_id: c.versionId ?? "", payload: c.payload } }
|
|
17514
18459
|
});
|
|
17515
18460
|
if (result.kind !== "resolved") throw new Error(result.failure.message);
|
|
18461
|
+
resolvedRef.current = withCameraPreviewMetadata(result.input, scenePayload);
|
|
18462
|
+
exportSources.current = {
|
|
18463
|
+
scene: { element_id: sceneElementId, version_id: scene.draft ? null : c.payload.scene_ref.version_id, draft: scene.draft ? { draft_id: scene.draft.draft_id, revision: scene.draft.revision } : null },
|
|
18464
|
+
setup: { element_id: c.setup.element.element_id, version_id: c.versionId, draft: c.versionId ? null : { draft_id: c.setup.draft.draft_id, revision: c.setup.draft.revision } },
|
|
18465
|
+
shot: { element_id: null, version_id: null, synthetic: true }
|
|
18466
|
+
};
|
|
18467
|
+
shownRef.current = { scenePayload, setupPayload: c.payload, shotPayload };
|
|
17516
18468
|
previewRef.current = c;
|
|
17517
18469
|
setChoice(c.key);
|
|
17518
|
-
setShown(
|
|
18470
|
+
setShown(shownRef.current);
|
|
17519
18471
|
setInput(withCameraPreviewMetadata(result.input, scenePayload));
|
|
17520
18472
|
}
|
|
17521
18473
|
async function open(c) {
|
|
17522
|
-
const
|
|
17523
|
-
|
|
17524
|
-
if (c.versionId && setup.draft) throw new Error("F\xFCr diesen Aufbau existiert bereits ein Entwurf. Bitte diesen explizit ausw\xE4hlen.");
|
|
17525
|
-
const setupPayload = c.versionId ? setup.versions.find((v) => v.version_id === c.versionId)?.payload : setup.draft?.payload;
|
|
17526
|
-
if (!setupPayload) throw new Error("Der gew\xE4hlte Stand ist nicht mehr vorhanden.");
|
|
17527
|
-
const scene = await read(sceneElementId);
|
|
17528
|
-
if (scene.draftFork) throw new Error("Die Szene hat konkurrierende Entw\xFCrfe.");
|
|
17529
|
-
const existingChain = setup.draft?.chain;
|
|
17530
|
-
if (existingChain) {
|
|
17531
|
-
const link = existingChain.links.find((l) => l.field === "scene_ref");
|
|
17532
|
-
if (link?.target_draft_id !== scene.draft?.draft_id || scene.draft?.chain?.chain_id !== existingChain.chain_id) throw new Error("Die gespeicherte Draft-Kette passt nicht zur Szene.");
|
|
17533
|
-
} else if (scene.draft?.chain) throw new Error("Die Szene geh\xF6rt bereits zu einer anderen Draft-Kette.");
|
|
17534
|
-
const ref = setupPayload.scene_ref;
|
|
17535
|
-
const scenePayload = scene.draft?.payload ?? scene.versions.find((v) => v.version_id === ref?.version_id)?.payload;
|
|
17536
|
-
if (!scenePayload) throw new Error("Die referenzierte Szene ist nicht vorhanden.");
|
|
17537
|
-
const chainId = existingChain?.chain_id ?? crypto.randomUUID();
|
|
17538
|
-
const chain = existingChain ?? { chain_id: chainId, origin: "stage", links: [] };
|
|
17539
|
-
let sceneDraft = scene.draft;
|
|
17540
|
-
if (!existingChain) sceneDraft = value(await port.elements.writeDraft({ elementId: sceneElementId, payload: scenePayload, expectedRevision: scene.draft?.revision ?? 0, baseVersionId: scene.draft?.base_version_id ?? ref?.version_id ?? null, chain: { ...chain, links: [] } }));
|
|
17541
|
-
let setupDraft = setup.draft;
|
|
17542
|
-
if (!existingChain) setupDraft = value(await port.elements.writeDraft({ elementId: setup.element.element_id, payload: setupPayload, expectedRevision: setup.draft?.revision ?? 0, baseVersionId: c.versionId, chain: { ...chain, links: [{ field: "scene_ref", target_element_id: sceneElementId, target_draft_id: sceneDraft.draft_id }] } }));
|
|
17543
|
-
const shots = value(await port.elements.listElements({ type: "shot" }));
|
|
17544
|
-
let shot = null;
|
|
17545
|
-
for (const entry of shots) {
|
|
17546
|
-
const s = await read(entry.element_id);
|
|
17547
|
-
if (s.draft?.chain?.chain_id === chainId) {
|
|
17548
|
-
shot = s;
|
|
17549
|
-
break;
|
|
17550
|
-
}
|
|
17551
|
-
}
|
|
17552
|
-
if (!shot) {
|
|
17553
|
-
const created = value(await port.elements.createElement({ type: "shot", contextId, title: "3D-Kameraansicht" }));
|
|
17554
|
-
const cameraId = setupPayload.camera_rig?.cameras?.[0]?.camera_id;
|
|
17555
|
-
if (!cameraId) throw new Error("Der Aufbau hat keine Kamera.");
|
|
17556
|
-
const shotPayload = { camera_id: cameraId, ...target ? { prompt_render_settings: { target_model_id: target } } : {} };
|
|
17557
|
-
value(await port.elements.writeDraft({ elementId: created.element_id, payload: shotPayload, expectedRevision: 0, chain: { ...chain, links: [{ field: "scene_setup_ref", target_element_id: setup.element.element_id, target_draft_id: setupDraft.draft_id }] } }));
|
|
17558
|
-
shot = await read(created.element_id);
|
|
17559
|
-
}
|
|
17560
|
-
await reload({ scene, setup, shot, scenePayload, setupPayload, shotPayload: shot.draft.payload });
|
|
18474
|
+
const state = await openStageDraftChain(port.elements, { sceneElementId, setupElementId: c.setup.element.element_id, setupVersionId: c.versionId, contextId, targetModelId: target || null });
|
|
18475
|
+
await reload({ scene: state.scene, setup: state.setup, shot: state.shot, scenePayload: state.scene.draft.payload, setupPayload: state.setup.draft.payload, shotPayload: state.shot.draft.payload });
|
|
17561
18476
|
previewRef.current = null;
|
|
17562
18477
|
}
|
|
18478
|
+
async function apply(w, operations) {
|
|
18479
|
+
const result = applyStageOperations({ scene: w.scenePayload, setup: w.setupPayload, shot: w.shotPayload }, operations);
|
|
18480
|
+
if (result.kind !== "ok") throw new Error(result.message);
|
|
18481
|
+
for (const which of result.write_order) {
|
|
18482
|
+
const s = w[which];
|
|
18483
|
+
value(await port.elements.writeDraft({ elementId: s.element.element_id, payload: result.payloads[which], expectedRevision: s.draft.revision }));
|
|
18484
|
+
}
|
|
18485
|
+
await reload(w);
|
|
18486
|
+
return result;
|
|
18487
|
+
}
|
|
18488
|
+
const rotate = (id, rotation) => enqueue(async (w) => {
|
|
18489
|
+
await apply(w, [{ op: "place_node", node_id: id, rotation_euler_deg: rotation }]);
|
|
18490
|
+
});
|
|
18491
|
+
const face = (id, targetId) => enqueue(async (w) => {
|
|
18492
|
+
const saved = await resolve(w), source = saved.scene.nodes.find((n) => n.node_id === id)?.placement;
|
|
18493
|
+
const targetPosition = targetId ? saved.scene.nodes.find((n) => n.node_id === targetId)?.placement?.position : saved.camera?.placement?.position;
|
|
18494
|
+
if (!source || !targetPosition) throw new Error("Quelle oder Ziel ist nicht platziert.");
|
|
18495
|
+
const rotation = [...source.rotation_euler_deg ?? [0, 0, 0]];
|
|
18496
|
+
rotation[2] = facingRotationZ(source.position, targetPosition);
|
|
18497
|
+
await apply(w, [{ op: "place_node", node_id: id, rotation_euler_deg: rotation }]);
|
|
18498
|
+
});
|
|
18499
|
+
const support = (id, targetId) => enqueue(async (w) => {
|
|
18500
|
+
if (!engine) throw new Error("B\xFChne ist noch nicht geladen.");
|
|
18501
|
+
const saved = await resolve(w), position = await engine.stageSupportPosition(saved, id, targetId);
|
|
18502
|
+
await apply(w, [{ op: "place_node", node_id: id, position }]);
|
|
18503
|
+
});
|
|
17563
18504
|
const display = input && withStagePositions(input, overlay.current.nodes, overlay.current.camera && overlay.current.camera.id === input.camera?.camera_id ? overlay.current.camera.position : null);
|
|
17564
18505
|
const base = working ?? shown;
|
|
17565
18506
|
const nodes = base?.scenePayload.nodes ?? [];
|
|
@@ -17571,6 +18512,200 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17571
18512
|
const cameraPosition = (display?.camera?.camera_id === camera?.camera_id ? display?.camera?.placement?.position : null) ?? camera?.placement?.position;
|
|
17572
18513
|
const lookAt = camera?.orientation?.mode === "look_at" ? camera.orientation.target?.node_ref : null;
|
|
17573
18514
|
const title = choices.find((c) => c.key === choice)?.title;
|
|
18515
|
+
const visibleNodes = display?.scene.nodes.filter((n) => !n.hidden) ?? [];
|
|
18516
|
+
const colors = stageColors(visibleNodes);
|
|
18517
|
+
const conflicts = previewColorConflicts(visibleNodes);
|
|
18518
|
+
const umschalten = (key, id) => setSichtbar((v) => {
|
|
18519
|
+
const next = new Set(v[key]);
|
|
18520
|
+
if (!next.delete(id)) next.add(id);
|
|
18521
|
+
return { ...v, [key]: next };
|
|
18522
|
+
});
|
|
18523
|
+
const ausgeblendet = (sichtbar.ground ? 0 : 1) + (sichtbar.camera ? 0 : 1) + nodes.reduce((sum, n) => sum + [sichtbar.nodes, sichtbar.walls, sichtbar.floors].filter((set) => set.has(n.node_id)).length, 0);
|
|
18524
|
+
const anchorsFor = (n) => n?.proxy_3d?.primitive === "humanoid_proxy" ? ANCHORS_HUMAN : ANCHORS_BASIC;
|
|
18525
|
+
const lookNode = lookAt ? nodes.find((n) => n.node_id === lookAt) : void 0;
|
|
18526
|
+
const setLook = (nodeRef, anchor) => edit("setup", (p) => withCamera(p, camera.camera_id, (c) => ({ ...c, orientation: {
|
|
18527
|
+
...c.orientation?.mode === "look_at" ? c.orientation : {},
|
|
18528
|
+
mode: "look_at",
|
|
18529
|
+
target: { node_ref: nodeRef, anchor }
|
|
18530
|
+
} })));
|
|
18531
|
+
const cameraFields = base ? /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18532
|
+
/* @__PURE__ */ jsxs26("label", { children: [
|
|
18533
|
+
"Kamera",
|
|
18534
|
+
/* @__PURE__ */ jsx28("select", { disabled: busy, value: base.shotPayload.camera_id ?? "", onChange: (e) => {
|
|
18535
|
+
const id = e.target.value;
|
|
18536
|
+
edit("shot", (p) => ({ ...p, camera_id: id }));
|
|
18537
|
+
}, children: base.setupPayload.camera_rig.cameras.map((c) => /* @__PURE__ */ jsx28("option", { value: c.camera_id, children: c.name ?? c.camera_id }, c.camera_id)) })
|
|
18538
|
+
] }),
|
|
18539
|
+
camera && /* @__PURE__ */ jsxs26("label", { children: [
|
|
18540
|
+
"Kameraformat",
|
|
18541
|
+
/* @__PURE__ */ jsxs26("select", { disabled: busy, value: camera.aspect_ratio ?? "", onChange: (e) => {
|
|
18542
|
+
const ratio = e.target.value;
|
|
18543
|
+
edit("setup", (p) => withCamera(p, camera.camera_id, (c) => ({ ...c, aspect_ratio: ratio })));
|
|
18544
|
+
}, children: [
|
|
18545
|
+
/* @__PURE__ */ jsx28("option", { value: "", children: "Explizit w\xE4hlen \u2026" }),
|
|
18546
|
+
CAMERA_ASPECT_RATIOS.map((r) => /* @__PURE__ */ jsx28("option", { children: r }, r)),
|
|
18547
|
+
camera.aspect_ratio && !CAMERA_ASPECT_RATIOS.includes(camera.aspect_ratio) && /* @__PURE__ */ jsx28("option", { children: camera.aspect_ratio })
|
|
18548
|
+
] })
|
|
18549
|
+
] }),
|
|
18550
|
+
camera?.placement?.mode === "absolute" && /* @__PURE__ */ jsxs26("fieldset", { disabled: busy, className: "szenen-3d__werte", children: [
|
|
18551
|
+
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Position (m)" }),
|
|
18552
|
+
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Kameraposition", axis, step: ".1", value: cameraPosition?.[index], onCommit: (n) => edit("setup", (p) => withCamera(p, camera.camera_id, (c) => {
|
|
18553
|
+
const position = [...c.placement.position];
|
|
18554
|
+
position[index] = n;
|
|
18555
|
+
return { ...c, placement: { mode: "absolute", position } };
|
|
18556
|
+
})) }, axis)),
|
|
18557
|
+
camera.orientation?.mode === "explicit" && /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18558
|
+
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Drehung (\xB0)" }),
|
|
18559
|
+
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Kameraausrichtung", axis, step: "1", value: camera.orientation.rotation_euler_deg[index], onCommit: (n) => edit("setup", (p) => withCamera(p, camera.camera_id, (c) => {
|
|
18560
|
+
const rotation_euler_deg = [...c.orientation.rotation_euler_deg];
|
|
18561
|
+
rotation_euler_deg[index] = n;
|
|
18562
|
+
return { ...c, orientation: { mode: "explicit", rotation_euler_deg } };
|
|
18563
|
+
})) }, axis))
|
|
18564
|
+
] })
|
|
18565
|
+
] }),
|
|
18566
|
+
camera && /* @__PURE__ */ jsxs26("label", { children: [
|
|
18567
|
+
"Blickziel",
|
|
18568
|
+
/* @__PURE__ */ jsxs26("select", { "aria-label": "Blickziel", disabled: busy, value: lookAt ?? "", onChange: (e) => {
|
|
18569
|
+
const id = e.target.value;
|
|
18570
|
+
if (!id) return;
|
|
18571
|
+
const keep = camera.orientation?.target?.anchor;
|
|
18572
|
+
setLook(id, anchorsFor(nodes.find((n) => n.node_id === id)).some(([k]) => k === keep) ? keep : "center");
|
|
18573
|
+
}, children: [
|
|
18574
|
+
!lookAt && /* @__PURE__ */ jsx28("option", { value: "", children: camera.orientation?.mode === "explicit" ? "Feste Drehung (unten)" : "Ausw\xE4hlen \u2026" }),
|
|
18575
|
+
visibleNodes.filter((n) => n.placement).map((n) => /* @__PURE__ */ jsx28("option", { value: n.node_id, children: labels[n.node_id] }, n.node_id))
|
|
18576
|
+
] })
|
|
18577
|
+
] }),
|
|
18578
|
+
camera && lookAt && /* @__PURE__ */ jsxs26("label", { children: [
|
|
18579
|
+
"Blickpunkt",
|
|
18580
|
+
/* @__PURE__ */ jsx28("select", { "aria-label": "Blickpunkt", disabled: busy, value: camera.orientation.target?.anchor ?? "center", onChange: (e) => setLook(lookAt, e.target.value), children: anchorsFor(lookNode).map(([key, title2]) => /* @__PURE__ */ jsx28("option", { value: key, children: title2 }, key)) })
|
|
18581
|
+
] }),
|
|
18582
|
+
lookAt && /* @__PURE__ */ jsxs26("p", { className: "szenen-3d__hinweis", children: [
|
|
18583
|
+
"Blickt auf ",
|
|
18584
|
+
labels[lookAt] ?? lookAt,
|
|
18585
|
+
". Kamera in Drauf- oder Seitenansicht ziehen, um sie zu versetzen; antippen \xF6ffnet diese Einstellungen."
|
|
18586
|
+
] })
|
|
18587
|
+
] }) : null;
|
|
18588
|
+
const objectSheet = node ? /* @__PURE__ */ jsxs26("div", { className: `szenen-3d__objektblatt${blatt ? "" : " is-zu"}`, role: "region", "aria-label": "Gew\xE4hltes Objekt", children: [
|
|
18589
|
+
/* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__blatt-schliessen", onClick: () => setSelected(null), children: "Objektblatt schlie\xDFen" }),
|
|
18590
|
+
/* @__PURE__ */ jsxs26("fieldset", { disabled: busy, className: "szenen-3d__werte", children: [
|
|
18591
|
+
/* @__PURE__ */ jsxs26("legend", { children: [
|
|
18592
|
+
labels[node.node_id],
|
|
18593
|
+
" ",
|
|
18594
|
+
/* @__PURE__ */ jsx28("span", { children: stageTypeLabel(node.type) })
|
|
18595
|
+
] }),
|
|
18596
|
+
colors[node.node_id] && /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18597
|
+
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Markerfarbe" }),
|
|
18598
|
+
/* @__PURE__ */ jsx28(
|
|
18599
|
+
ColorField,
|
|
18600
|
+
{
|
|
18601
|
+
hex: colors[node.node_id].hex,
|
|
18602
|
+
explicit: colors[node.node_id].explicit,
|
|
18603
|
+
disabled: busy,
|
|
18604
|
+
onCommit: (hex) => enqueue(async (w) => {
|
|
18605
|
+
await apply(w, [{ op: "update_node", node_id: node.node_id, preview_color: hex }]);
|
|
18606
|
+
}),
|
|
18607
|
+
onReset: () => enqueue(async (w) => {
|
|
18608
|
+
await apply(w, [{ op: "update_node", node_id: node.node_id, preview_color: null }]);
|
|
18609
|
+
})
|
|
18610
|
+
}
|
|
18611
|
+
),
|
|
18612
|
+
previewColorLegibility(colors[node.node_id].hex) && /* @__PURE__ */ jsx28("p", { role: "status", className: "szenen-3d__farbe-hinweis", children: previewColorLegibility(colors[node.node_id].hex) === "too_dark" ? "Sehr dunkle Markerfarbe: Das Bildmodell kann den Block als Schatten oder dunkle Kleidung lesen. Eine kr\xE4ftige, mittelhelle Farbe ist eindeutiger." : "Sehr helle Markerfarbe: Der Block hebt sich kaum vom hellen Preview-Hintergrund ab." }),
|
|
18613
|
+
conflicts.filter((c) => c.node_ids.includes(node.node_id)).map((c) => {
|
|
18614
|
+
const other = c.node_ids[0] === node.node_id ? c.node_ids[1] : c.node_ids[0];
|
|
18615
|
+
return /* @__PURE__ */ jsxs26("p", { role: "status", className: "szenen-3d__farbe-hinweis", children: [
|
|
18616
|
+
c.identical ? "Gleiche Farbe wie" : "Schwer unterscheidbar von",
|
|
18617
|
+
" ",
|
|
18618
|
+
labels[other] ?? other,
|
|
18619
|
+
" (",
|
|
18620
|
+
colors[other]?.hex,
|
|
18621
|
+
")."
|
|
18622
|
+
] }, other);
|
|
18623
|
+
})
|
|
18624
|
+
] }),
|
|
18625
|
+
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Gr\xF6\xDFe (m)" }),
|
|
18626
|
+
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Gr\xF6\xDFe", axis, step: ".05", min: 0.01, value: node.proxy_3d?.dimensions?.[index], onCommit: (n) => edit("scene", (p) => ({ ...p, nodes: p.nodes.map((x) => {
|
|
18627
|
+
if (x.node_id !== node.node_id) return x;
|
|
18628
|
+
const d = [...x.proxy_3d?.dimensions ?? [1, 1, 1]];
|
|
18629
|
+
d[index] = n;
|
|
18630
|
+
return { ...x, proxy_3d: { ...x.proxy_3d, primitive: x.proxy_3d?.primitive ?? "box", dimensions: d } };
|
|
18631
|
+
}) })) }, axis)),
|
|
18632
|
+
placement ? /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18633
|
+
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Position (m)" }),
|
|
18634
|
+
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Position", axis, step: ".05", value: nodePosition?.[index], onCommit: (n) => edit("setup", (p) => ({ ...p, placements: p.placements.map((x) => {
|
|
18635
|
+
if (x.node_id !== node.node_id) return x;
|
|
18636
|
+
const q = [...x.position];
|
|
18637
|
+
q[index] = n;
|
|
18638
|
+
return { ...x, position: q };
|
|
18639
|
+
}) })) }, axis))
|
|
18640
|
+
] }) : /* @__PURE__ */ jsx28("button", { type: "button", onClick: () => edit("setup", (p) => ({ ...p, coordinate_system: "blender_z_up_meters", placements: [...p.placements ?? [], { node_id: node.node_id, position: [0, 0, 0] }] })), children: "Am Ursprung platzieren" }),
|
|
18641
|
+
placement && /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18642
|
+
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Drehung (\xB0)" }),
|
|
18643
|
+
/* @__PURE__ */ jsx28(
|
|
18644
|
+
MeterField,
|
|
18645
|
+
{
|
|
18646
|
+
label: "Objektdrehung",
|
|
18647
|
+
axis: "Z",
|
|
18648
|
+
step: "15",
|
|
18649
|
+
value: placement.rotation_euler_deg?.[2] ?? 0,
|
|
18650
|
+
onCommit: (z) => enqueue(async (w) => {
|
|
18651
|
+
const q = w.setupPayload.placements.find((p) => p.node_id === node.node_id);
|
|
18652
|
+
if (!q) throw new Error("Objekt ist nicht mehr platziert.");
|
|
18653
|
+
await apply(w, [{ op: "place_node", node_id: node.node_id, rotation_euler_deg: [q.rotation_euler_deg?.[0] ?? 0, q.rotation_euler_deg?.[1] ?? 0, z] }]);
|
|
18654
|
+
})
|
|
18655
|
+
}
|
|
18656
|
+
),
|
|
18657
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__objekt-aktionen", children: [
|
|
18658
|
+
/* @__PURE__ */ jsx28("button", { type: "button", onClick: () => face(node.node_id), children: "Zur Kamera drehen" }),
|
|
18659
|
+
/* @__PURE__ */ jsx28("button", { type: "button", onClick: () => support(node.node_id), children: "Auf Boden" })
|
|
18660
|
+
] }),
|
|
18661
|
+
/* @__PURE__ */ jsxs26("label", { className: "szenen-3d__zeilenkopf", children: [
|
|
18662
|
+
"Zielobjekt",
|
|
18663
|
+
/* @__PURE__ */ jsxs26("select", { "aria-label": "Zielobjekt", value: objectTarget, onChange: (e) => setObjectTarget(e.target.value), children: [
|
|
18664
|
+
/* @__PURE__ */ jsx28("option", { value: "", children: "Ausw\xE4hlen \u2026" }),
|
|
18665
|
+
visibleNodes.filter((n) => n.node_id !== node.node_id && n.placement).map((n) => /* @__PURE__ */ jsx28("option", { value: n.node_id, children: labels[n.node_id] }, n.node_id))
|
|
18666
|
+
] })
|
|
18667
|
+
] }),
|
|
18668
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__objekt-aktionen", children: [
|
|
18669
|
+
/* @__PURE__ */ jsx28("button", { type: "button", disabled: !objectTarget || objectTarget === node.node_id, onClick: () => face(node.node_id, objectTarget), children: "Zu Objekt drehen" }),
|
|
18670
|
+
/* @__PURE__ */ jsx28("button", { type: "button", disabled: !objectTarget || objectTarget === node.node_id, onClick: () => support(node.node_id, objectTarget), children: "Auf Objekt setzen" })
|
|
18671
|
+
] })
|
|
18672
|
+
] }),
|
|
18673
|
+
node.proxy_3d?.primitive === "humanoid_proxy" && /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18674
|
+
/* @__PURE__ */ jsx28("div", { className: "szenen-3d__pose", role: "group", "aria-label": "Pose", children: [["standing", "Stehen"], ["sitting", "Sitzen"], ["walking", "Gehen"], ["arms_crossed", "Arme verschr\xE4nkt"], ["hand_on_chin", "Hand am Kinn"]].map(([pose, label]) => /* @__PURE__ */ jsx28("button", { type: "button", "aria-pressed": (node.proxy_3d.pose_ref ?? "standing") === pose, onClick: () => enqueue(async (w) => {
|
|
18675
|
+
await apply(w, [{ op: "update_node", node_id: node.node_id, pose_ref: pose }]);
|
|
18676
|
+
}), children: label }, pose)) }),
|
|
18677
|
+
["build", "gender"].map((key) => /* @__PURE__ */ jsx28(
|
|
18678
|
+
MorphField,
|
|
18679
|
+
{
|
|
18680
|
+
label: key === "build" ? "Statur" : "Geschlecht",
|
|
18681
|
+
value: node.proxy_3d.morph?.[key] ?? 0.5,
|
|
18682
|
+
onCommit: (v) => enqueue(async (w) => {
|
|
18683
|
+
const current = w.scenePayload.nodes.find((n) => n.node_id === node.node_id);
|
|
18684
|
+
if (!current) throw new Error("Person fehlt.");
|
|
18685
|
+
await apply(w, [{ op: "update_node", node_id: node.node_id, morph: { ...current.proxy_3d.morph, [key]: v } }]);
|
|
18686
|
+
})
|
|
18687
|
+
},
|
|
18688
|
+
key
|
|
18689
|
+
))
|
|
18690
|
+
] }),
|
|
18691
|
+
entfernen === node.node_id ? /* @__PURE__ */ jsxs26("div", { className: "szenen-3d__entfernen", role: "group", "aria-label": "Entfernen best\xE4tigen", children: [
|
|
18692
|
+
/* @__PURE__ */ jsxs26("span", { children: [
|
|
18693
|
+
"\u201E",
|
|
18694
|
+
labels[node.node_id],
|
|
18695
|
+
"\u201C aus der Szene entfernen?"
|
|
18696
|
+
] }),
|
|
18697
|
+
/* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__gefahr", onClick: () => {
|
|
18698
|
+
const id = node.node_id;
|
|
18699
|
+
setEntfernen(null);
|
|
18700
|
+
enqueue(async (w) => {
|
|
18701
|
+
await apply(w, [{ op: "remove_node", node_id: id }]);
|
|
18702
|
+
setSelected(null);
|
|
18703
|
+
});
|
|
18704
|
+
}, children: "Entfernen" }),
|
|
18705
|
+
/* @__PURE__ */ jsx28("button", { type: "button", onClick: () => setEntfernen(null), children: "Abbrechen" })
|
|
18706
|
+
] }) : /* @__PURE__ */ jsx28("button", { type: "button", onClick: () => setEntfernen(node.node_id), children: "Objekt entfernen" })
|
|
18707
|
+
] })
|
|
18708
|
+
] }) : null;
|
|
17574
18709
|
return /* @__PURE__ */ jsxs26("section", { className: `szenen-3d${embedded ? " szenen-3d--eingebettet" : ""}`, "aria-label": "3D-B\xFChne", "data-testid": "szenen-3d", children: [
|
|
17575
18710
|
/* @__PURE__ */ jsxs26("header", { className: "szenen-3d__kopf", children: [
|
|
17576
18711
|
!embedded && /* @__PURE__ */ jsx28("h4", { children: "3D-B\xFChne" }),
|
|
@@ -17589,120 +18724,171 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17589
18724
|
title.replace(/ · (Entwurf|Version \S+)$/, "")
|
|
17590
18725
|
] }),
|
|
17591
18726
|
base && /* @__PURE__ */ jsx28("span", { className: "szenen-3d__sync", "data-state": pending ? "speichert" : working ? "gespeichert" : "ansicht", "aria-live": "polite", children: pending ? "Speichert \u2026" : working ? "Gespeichert" : "Erste \xC4nderung legt Entwurf an" }),
|
|
18727
|
+
base && engine && /* @__PURE__ */ jsx28("button", { type: "button", disabled: busy, onClick: () => void act(async () => {
|
|
18728
|
+
await queue.current;
|
|
18729
|
+
let payloads;
|
|
18730
|
+
if (workingRef.current) {
|
|
18731
|
+
await reload(workingRef.current);
|
|
18732
|
+
const w = workingRef.current;
|
|
18733
|
+
payloads = w;
|
|
18734
|
+
} else {
|
|
18735
|
+
const c = previewRef.current;
|
|
18736
|
+
if (!c) throw new Error("Bitte einen Aufbau w\xE4hlen.");
|
|
18737
|
+
const setup = await read(c.setup.element.element_id), payload = c.versionId ? setup.versions.find((v) => v.version_id === c.versionId)?.payload : setup.draft?.payload;
|
|
18738
|
+
if (!payload) throw new Error("Der gew\xE4hlte Aufbau fehlt.");
|
|
18739
|
+
await preview({ ...c, setup, payload });
|
|
18740
|
+
payloads = shownRef.current;
|
|
18741
|
+
}
|
|
18742
|
+
if (!resolvedRef.current || !exportSources.current) throw new Error("Der gespeicherte Exportstand fehlt.");
|
|
18743
|
+
const result = await engine.exportStageScene(resolvedRef.current, { payloads: { scene: payloads.scenePayload, setup: payloads.setupPayload, shot: payloads.shotPayload }, sources: exportSources.current }, workingRef.current?.shot.element.title ?? `scene_${resolvedRef.current.camera.camera_id}`);
|
|
18744
|
+
const bytes = new Uint8Array(result.data), url = URL.createObjectURL(new Blob([bytes], { type: "application/zip" }));
|
|
18745
|
+
const link = document.createElement("a");
|
|
18746
|
+
link.href = url;
|
|
18747
|
+
link.download = result.filename;
|
|
18748
|
+
document.body.appendChild(link);
|
|
18749
|
+
link.click();
|
|
18750
|
+
link.remove();
|
|
18751
|
+
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
18752
|
+
setMessage("Szene f\xFCr Blender exportiert.");
|
|
18753
|
+
}), children: "Szene exportieren" }),
|
|
17592
18754
|
onClose && /* @__PURE__ */ jsx28("button", { type: "button", disabled: busy, onClick: onClose, children: "Schlie\xDFen" })
|
|
17593
18755
|
] }),
|
|
17594
18756
|
message && /* @__PURE__ */ jsx28("p", { role: "status", className: "szenen-3d__meldung", children: message }),
|
|
17595
|
-
!base ?
|
|
18757
|
+
!base ? /* @__PURE__ */ jsxs26("div", { className: "szenen-3d__geruest", "aria-hidden": "true", children: [
|
|
17596
18758
|
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__leiste", children: [
|
|
17597
|
-
/* @__PURE__ */ jsx28("div", { className: "szenen-studio__umschalter",
|
|
17598
|
-
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__katalog",
|
|
18759
|
+
/* @__PURE__ */ jsx28("div", { className: "szenen-studio__umschalter", children: VIEWS.map(([v, title2]) => /* @__PURE__ */ jsx28("button", { type: "button", disabled: true, tabIndex: -1, children: title2 }, v)) }),
|
|
18760
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__katalog", children: [
|
|
17599
18761
|
/* @__PURE__ */ jsx28("span", { children: "Hinzuf\xFCgen" }),
|
|
17600
|
-
STAGE_CATALOGUE.map((entry) => /* @__PURE__ */ jsxs26("button", { type: "button", disabled:
|
|
17601
|
-
|
|
17602
|
-
await write(w, "scene", { ...w.scenePayload, unit_system: "blender_z_up_meters", nodes: [...w.scenePayload.nodes, { node_id: id, label: entry.label, type: entry.type, semantic: { description: entry.label }, proxy_3d: { primitive: "box", dimensions: [...entry.dimensions] } }] });
|
|
17603
|
-
const setup = await read(w.setup.element.element_id);
|
|
17604
|
-
const p = setup.draft.payload;
|
|
17605
|
-
value(await port.elements.writeDraft({ elementId: setup.element.element_id, expectedRevision: setup.draft.revision, payload: { ...p, coordinate_system: "blender_z_up_meters", placements: [...p.placements ?? [], { node_id: id, position: [0, 0, entry.dimensions[2] / 2] }] } }));
|
|
17606
|
-
await reload(workingRef.current);
|
|
17607
|
-
setSelected(id);
|
|
17608
|
-
}), children: [
|
|
17609
|
-
/* @__PURE__ */ jsx28("i", { style: { background: stageColor(entry.type) }, "aria-hidden": "true" }),
|
|
18762
|
+
STAGE_CATALOGUE.map((entry) => /* @__PURE__ */ jsxs26("button", { type: "button", disabled: true, tabIndex: -1, children: [
|
|
18763
|
+
/* @__PURE__ */ jsx28("i", { style: { background: stageColor(entry.type) } }),
|
|
17610
18764
|
"+ ",
|
|
17611
18765
|
entry.label
|
|
17612
18766
|
] }, entry.label))
|
|
17613
18767
|
] })
|
|
17614
18768
|
] }),
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
{
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
|
|
17621
|
-
|
|
17622
|
-
|
|
17623
|
-
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
18769
|
+
/* @__PURE__ */ jsx28("div", { className: "szenen-3d__viewport szenen-3d__viewport--laden" }),
|
|
18770
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__inspektor", children: [
|
|
18771
|
+
/* @__PURE__ */ jsxs26("section", { className: "szenen-3d__karte", children: [
|
|
18772
|
+
/* @__PURE__ */ jsx28("h5", { children: "Elemente" }),
|
|
18773
|
+
/* @__PURE__ */ jsx28("div", { className: "szenen-3d__elemente", children: vorab.map((n) => /* @__PURE__ */ jsxs26("button", { type: "button", disabled: true, tabIndex: -1, children: [
|
|
18774
|
+
/* @__PURE__ */ jsx28("i", { style: { background: stageColors(vorab)[n.node_id]?.hex ?? stageColor(n.type) } }),
|
|
18775
|
+
n.label ?? n.semantic?.description ?? n.node_id
|
|
18776
|
+
] }, n.node_id)) }),
|
|
18777
|
+
/* @__PURE__ */ jsx28("p", { className: "szenen-3d__hinweis", children: "Element in der B\xFChne oder hier ausw\xE4hlen." })
|
|
18778
|
+
] }),
|
|
18779
|
+
/* @__PURE__ */ jsxs26("section", { className: "szenen-3d__karte", children: [
|
|
18780
|
+
/* @__PURE__ */ jsx28("h5", { children: "Aktive Kamera" }),
|
|
18781
|
+
/* @__PURE__ */ jsx28("p", { className: "szenen-3d__hinweis", children: "Kamera wird geladen \u2026" })
|
|
18782
|
+
] })
|
|
18783
|
+
] })
|
|
18784
|
+
] }) : /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
18785
|
+
/* @__PURE__ */ jsxs26("div", { ref: buehne, className: `szenen-3d__buehne${vollbild ? " is-vollbild" : ""}`, children: [
|
|
18786
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__leiste", children: [
|
|
18787
|
+
/* @__PURE__ */ jsx28("div", { className: "szenen-studio__umschalter", role: "group", "aria-label": "3D-Ansicht", children: VIEWS.map(([v, title2]) => /* @__PURE__ */ jsx28("button", { type: "button", "aria-pressed": view === v, onClick: () => setView(v), children: title2 }, v)) }),
|
|
18788
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__katalog", role: "group", "aria-label": "Objektkatalog", children: [
|
|
18789
|
+
/* @__PURE__ */ jsx28("span", { children: "Hinzuf\xFCgen" }),
|
|
18790
|
+
STAGE_CATALOGUE.map((entry) => /* @__PURE__ */ jsxs26("button", { type: "button", disabled: busy, onClick: () => enqueue(async (w) => {
|
|
18791
|
+
const result = await apply(w, [{ op: "add_node", type: entry.type, label: entry.label, description: entry.label, dimensions: [...entry.dimensions] }]);
|
|
18792
|
+
setSelected(result.created_node_ids[0]);
|
|
18793
|
+
}), children: [
|
|
18794
|
+
/* @__PURE__ */ jsx28("i", { style: { background: stageColor(entry.type) }, "aria-hidden": "true" }),
|
|
18795
|
+
"+ ",
|
|
18796
|
+
entry.label
|
|
18797
|
+
] }, entry.label))
|
|
18798
|
+
] }),
|
|
18799
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__ansichtsoptionen", role: "group", "aria-label": "Anzeige", children: [
|
|
18800
|
+
/* @__PURE__ */ jsxs26("details", { className: "szenen-3d__sichtbar", children: [
|
|
18801
|
+
/* @__PURE__ */ jsxs26("summary", { children: [
|
|
18802
|
+
"Sichtbarkeit",
|
|
18803
|
+
ausgeblendet ? ` \xB7 ${ausgeblendet} aus` : ""
|
|
18804
|
+
] }),
|
|
18805
|
+
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__sichtbar-liste", role: "group", "aria-label": "Sichtbarkeit", children: [
|
|
18806
|
+
/* @__PURE__ */ jsxs26("label", { children: [
|
|
18807
|
+
/* @__PURE__ */ jsx28("input", { type: "checkbox", checked: sichtbar.ground, onChange: () => setSichtbar((v) => ({ ...v, ground: !v.ground })) }),
|
|
18808
|
+
"Grundfl\xE4che"
|
|
18809
|
+
] }),
|
|
18810
|
+
/* @__PURE__ */ jsxs26("label", { children: [
|
|
18811
|
+
/* @__PURE__ */ jsx28("input", { type: "checkbox", checked: sichtbar.camera, onChange: () => setSichtbar((v) => ({ ...v, camera: !v.camera })) }),
|
|
18812
|
+
"Kamerasymbol"
|
|
18813
|
+
] }),
|
|
18814
|
+
nodes.map((n) => n.proxy_3d?.primitive === "room_shell" ? /* @__PURE__ */ jsxs26(React21.Fragment, { children: [
|
|
18815
|
+
/* @__PURE__ */ jsxs26("label", { children: [
|
|
18816
|
+
/* @__PURE__ */ jsx28("input", { type: "checkbox", checked: !sichtbar.floors.has(n.node_id), onChange: () => umschalten("floors", n.node_id) }),
|
|
18817
|
+
/* @__PURE__ */ jsx28("i", { style: { background: colors[n.node_id]?.hex ?? stageColor(n.type) }, "aria-hidden": "true" }),
|
|
18818
|
+
labels[n.node_id],
|
|
18819
|
+
" \xB7 Boden"
|
|
18820
|
+
] }),
|
|
18821
|
+
/* @__PURE__ */ jsxs26("label", { children: [
|
|
18822
|
+
/* @__PURE__ */ jsx28("input", { type: "checkbox", checked: !sichtbar.walls.has(n.node_id), onChange: () => umschalten("walls", n.node_id) }),
|
|
18823
|
+
/* @__PURE__ */ jsx28("i", { style: { background: colors[n.node_id]?.hex ?? stageColor(n.type) }, "aria-hidden": "true" }),
|
|
18824
|
+
labels[n.node_id],
|
|
18825
|
+
" \xB7 W\xE4nde"
|
|
18826
|
+
] })
|
|
18827
|
+
] }, n.node_id) : /* @__PURE__ */ jsxs26("label", { children: [
|
|
18828
|
+
/* @__PURE__ */ jsx28("input", { type: "checkbox", checked: !sichtbar.nodes.has(n.node_id), onChange: () => umschalten("nodes", n.node_id) }),
|
|
18829
|
+
/* @__PURE__ */ jsx28("i", { style: { background: colors[n.node_id]?.hex ?? stageColor(n.type) }, "aria-hidden": "true" }),
|
|
18830
|
+
labels[n.node_id]
|
|
18831
|
+
] }, n.node_id)),
|
|
18832
|
+
/* @__PURE__ */ jsx28("button", { type: "button", disabled: !ausgeblendet, onClick: () => setSichtbar({ nodes: /* @__PURE__ */ new Set(), walls: /* @__PURE__ */ new Set(), floors: /* @__PURE__ */ new Set(), ground: true, camera: true }), children: "Alle einblenden" })
|
|
18833
|
+
] })
|
|
18834
|
+
] }),
|
|
18835
|
+
/* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__blatt-schalter", "aria-pressed": blatt, onClick: () => setBlatt((b) => !b), children: "Objektblatt" }),
|
|
18836
|
+
vollbild && /* @__PURE__ */ jsx28("button", { type: "button", "aria-pressed": kameraBlatt, onClick: () => {
|
|
18837
|
+
setSelected(null);
|
|
18838
|
+
setKameraBlatt((k) => !k);
|
|
18839
|
+
}, children: "Kamera" }),
|
|
18840
|
+
/* @__PURE__ */ jsx28("button", { type: "button", "aria-pressed": vollbild, onClick: () => {
|
|
18841
|
+
setVollbild((v) => !v);
|
|
18842
|
+
setKameraBlatt(false);
|
|
18843
|
+
}, children: vollbild ? "Vollbild beenden" : "Vollbild" })
|
|
18844
|
+
] })
|
|
18845
|
+
] }),
|
|
18846
|
+
engine && display ? /* @__PURE__ */ jsx28(StageBoundary, { resetKey: input, children: /* @__PURE__ */ jsx28(
|
|
18847
|
+
engine.StageEngine,
|
|
18848
|
+
{
|
|
18849
|
+
input: display,
|
|
18850
|
+
view,
|
|
18851
|
+
selected,
|
|
18852
|
+
labels,
|
|
18853
|
+
onSelect: setSelected,
|
|
18854
|
+
onMove: (id, p) => move((o) => {
|
|
18855
|
+
o.nodes.set(id, p);
|
|
18856
|
+
}),
|
|
18857
|
+
onRotate: rotate,
|
|
18858
|
+
onMoveCamera: camera?.placement?.mode === "absolute" ? (p) => move((o) => {
|
|
18859
|
+
o.camera = { id: camera.camera_id, position: p };
|
|
18860
|
+
}) : void 0,
|
|
18861
|
+
visibility: sichtbar,
|
|
18862
|
+
onSelectCamera: blatt ? () => {
|
|
18863
|
+
setSelected(null);
|
|
18864
|
+
setKameraBlatt(true);
|
|
18865
|
+
} : void 0
|
|
18866
|
+
}
|
|
18867
|
+
) }) : /* @__PURE__ */ jsx28("div", { className: "szenen-3d__viewport szenen-3d__viewport--laden", "aria-hidden": "true" }),
|
|
18868
|
+
vollbild && blatt && objectSheet,
|
|
18869
|
+
vollbild && kameraBlatt && !(blatt && objectSheet) && /* @__PURE__ */ jsxs26("div", { className: "szenen-3d__objektblatt szenen-3d__kamerablatt", role: "region", "aria-label": "Kamera", children: [
|
|
18870
|
+
/* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__blatt-schliessen", onClick: () => setKameraBlatt(false), children: "Kamerablatt schlie\xDFen" }),
|
|
18871
|
+
/* @__PURE__ */ jsxs26("fieldset", { disabled: busy, className: "szenen-3d__werte", children: [
|
|
18872
|
+
/* @__PURE__ */ jsx28("legend", { children: "Kamera" }),
|
|
18873
|
+
cameraFields
|
|
18874
|
+
] })
|
|
18875
|
+
] })
|
|
18876
|
+
] }),
|
|
17631
18877
|
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__inspektor", children: [
|
|
17632
18878
|
/* @__PURE__ */ jsxs26("section", { className: "szenen-3d__karte", children: [
|
|
17633
18879
|
/* @__PURE__ */ jsx28("h5", { children: "Elemente" }),
|
|
17634
18880
|
/* @__PURE__ */ jsx28("div", { className: "szenen-3d__elemente", role: "group", "aria-label": "Element w\xE4hlen", children: nodes.map((n) => /* @__PURE__ */ jsxs26("button", { type: "button", "aria-pressed": n.node_id === selected, onClick: () => setSelected(n.node_id === selected ? null : n.node_id), children: [
|
|
17635
|
-
/* @__PURE__ */ jsx28("i", { style: { background:
|
|
18881
|
+
/* @__PURE__ */ jsx28("i", { style: { background: colors[n.node_id]?.hex ?? stageColor(n.type) }, "aria-hidden": "true" }),
|
|
17636
18882
|
labels[n.node_id]
|
|
17637
18883
|
] }, n.node_id)) }),
|
|
17638
|
-
|
|
17639
|
-
/* @__PURE__ */ jsxs26("legend", { children: [
|
|
17640
|
-
labels[node.node_id],
|
|
17641
|
-
" ",
|
|
17642
|
-
/* @__PURE__ */ jsx28("span", { children: stageTypeLabel(node.type) })
|
|
17643
|
-
] }),
|
|
17644
|
-
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Gr\xF6\xDFe (m)" }),
|
|
17645
|
-
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Gr\xF6\xDFe", axis, step: ".05", min: 0.01, value: node.proxy_3d?.dimensions?.[index], onCommit: (n) => edit("scene", (p) => ({ ...p, nodes: p.nodes.map((x) => {
|
|
17646
|
-
if (x.node_id !== node.node_id) return x;
|
|
17647
|
-
const d = [...x.proxy_3d?.dimensions ?? [1, 1, 1]];
|
|
17648
|
-
d[index] = n;
|
|
17649
|
-
return { ...x, proxy_3d: { primitive: x.proxy_3d?.primitive ?? "box", dimensions: d } };
|
|
17650
|
-
}) })) }, axis)),
|
|
17651
|
-
placement ? /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
17652
|
-
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Position (m)" }),
|
|
17653
|
-
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Position", axis, step: ".05", value: nodePosition?.[index], onCommit: (n) => edit("setup", (p) => ({ ...p, placements: p.placements.map((x) => {
|
|
17654
|
-
if (x.node_id !== node.node_id) return x;
|
|
17655
|
-
const q = [...x.position];
|
|
17656
|
-
q[index] = n;
|
|
17657
|
-
return { ...x, position: q };
|
|
17658
|
-
}) })) }, axis))
|
|
17659
|
-
] }) : /* @__PURE__ */ jsx28("button", { type: "button", onClick: () => edit("setup", (p) => ({ ...p, coordinate_system: "blender_z_up_meters", placements: [...p.placements ?? [], { node_id: node.node_id, position: [0, 0, 0] }] })), children: "Am Ursprung platzieren" })
|
|
17660
|
-
] }) : /* @__PURE__ */ jsxs26("p", { className: "szenen-3d__hinweis", children: [
|
|
18884
|
+
objectSheet && !vollbild ? objectSheet : /* @__PURE__ */ jsxs26("p", { className: "szenen-3d__hinweis", children: [
|
|
17661
18885
|
"Element in der B\xFChne oder hier ausw\xE4hlen.",
|
|
17662
18886
|
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__nur-maus", children: " Pfeiltasten verschieben in 5-cm-Schritten, mit Shift in 50 cm." })
|
|
17663
18887
|
] })
|
|
17664
18888
|
] }),
|
|
17665
18889
|
/* @__PURE__ */ jsxs26("section", { className: "szenen-3d__karte", children: [
|
|
17666
18890
|
/* @__PURE__ */ jsx28("h5", { children: "Aktive Kamera" }),
|
|
17667
|
-
|
|
17668
|
-
"Kamera",
|
|
17669
|
-
/* @__PURE__ */ jsx28("select", { disabled: busy, value: base.shotPayload.camera_id ?? "", onChange: (e) => {
|
|
17670
|
-
const id = e.target.value;
|
|
17671
|
-
edit("shot", (p) => ({ ...p, camera_id: id }));
|
|
17672
|
-
}, children: base.setupPayload.camera_rig.cameras.map((c) => /* @__PURE__ */ jsx28("option", { value: c.camera_id, children: c.name ?? c.camera_id }, c.camera_id)) })
|
|
17673
|
-
] }),
|
|
17674
|
-
camera && /* @__PURE__ */ jsxs26("label", { children: [
|
|
17675
|
-
"Kameraformat",
|
|
17676
|
-
/* @__PURE__ */ jsxs26("select", { disabled: busy, value: camera.aspect_ratio ?? "", onChange: (e) => {
|
|
17677
|
-
const ratio = e.target.value;
|
|
17678
|
-
edit("setup", (p) => withCamera(p, camera.camera_id, (c) => ({ ...c, aspect_ratio: ratio })));
|
|
17679
|
-
}, children: [
|
|
17680
|
-
/* @__PURE__ */ jsx28("option", { value: "", children: "Explizit w\xE4hlen \u2026" }),
|
|
17681
|
-
CAMERA_ASPECT_RATIOS.map((r) => /* @__PURE__ */ jsx28("option", { children: r }, r)),
|
|
17682
|
-
camera.aspect_ratio && !CAMERA_ASPECT_RATIOS.includes(camera.aspect_ratio) && /* @__PURE__ */ jsx28("option", { children: camera.aspect_ratio })
|
|
17683
|
-
] })
|
|
17684
|
-
] }),
|
|
17685
|
-
camera?.placement?.mode === "absolute" && /* @__PURE__ */ jsxs26("fieldset", { disabled: busy, className: "szenen-3d__werte", children: [
|
|
17686
|
-
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Position (m)" }),
|
|
17687
|
-
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Kameraposition", axis, step: ".1", value: cameraPosition?.[index], onCommit: (n) => edit("setup", (p) => withCamera(p, camera.camera_id, (c) => {
|
|
17688
|
-
const position = [...c.placement.position];
|
|
17689
|
-
position[index] = n;
|
|
17690
|
-
return { ...c, placement: { mode: "absolute", position } };
|
|
17691
|
-
})) }, axis)),
|
|
17692
|
-
camera.orientation?.mode === "explicit" && /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
17693
|
-
/* @__PURE__ */ jsx28("span", { className: "szenen-3d__zeilenkopf", children: "Drehung (\xB0)" }),
|
|
17694
|
-
["X", "Y", "Z"].map((axis, index) => /* @__PURE__ */ jsx28(MeterField, { label: "Kameraausrichtung", axis, step: "1", value: camera.orientation.rotation_euler_deg[index], onCommit: (n) => edit("setup", (p) => withCamera(p, camera.camera_id, (c) => {
|
|
17695
|
-
const rotation_euler_deg = [...c.orientation.rotation_euler_deg];
|
|
17696
|
-
rotation_euler_deg[index] = n;
|
|
17697
|
-
return { ...c, orientation: { mode: "explicit", rotation_euler_deg } };
|
|
17698
|
-
})) }, axis))
|
|
17699
|
-
] })
|
|
17700
|
-
] }),
|
|
17701
|
-
lookAt && /* @__PURE__ */ jsxs26("p", { className: "szenen-3d__hinweis", children: [
|
|
17702
|
-
"Blickt auf ",
|
|
17703
|
-
labels[lookAt] ?? lookAt,
|
|
17704
|
-
". Kamera in Drauf- oder Seitenansicht ziehen, um sie zu versetzen."
|
|
17705
|
-
] })
|
|
18891
|
+
vollbild && kameraBlatt ? null : cameraFields
|
|
17706
18892
|
] })
|
|
17707
18893
|
] }),
|
|
17708
18894
|
/* @__PURE__ */ jsxs26("div", { className: "szenen-3d__abschluss", children: [
|
|
@@ -17760,7 +18946,9 @@ function StageWorkspace({ port, sceneElementId, contextId, onClose, onChanged, e
|
|
|
17760
18946
|
setRefresh((r) => r + 1);
|
|
17761
18947
|
}), children: "Kamera-Preview nachspeichern" }),
|
|
17762
18948
|
!port.runs.supportsCameraPreview && /* @__PURE__ */ jsx28("p", { className: "szenen-3d__hinweis", children: "Dieser Host kann das Kamera-Preview noch nicht am Run-Item speichern." }),
|
|
17763
|
-
working && /* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__nebenaktion", disabled: busy, onClick: () => enqueue((w) =>
|
|
18949
|
+
working && /* @__PURE__ */ jsx28("button", { type: "button", className: "szenen-3d__nebenaktion", disabled: busy, onClick: () => enqueue(async (w) => {
|
|
18950
|
+
await reload(w);
|
|
18951
|
+
}), children: "Gespeicherten Stand neu laden" })
|
|
17764
18952
|
] }),
|
|
17765
18953
|
working && /* @__PURE__ */ jsx28(RunsPanel, { port, contextId, source: { kind: "draft_chain", chainId: working.shot.draft.chain.chain_id } }, refresh)
|
|
17766
18954
|
] })
|
|
@@ -17915,7 +19103,7 @@ var ElementDetail = ({
|
|
|
17915
19103
|
const setzeFeld = (pfad, wert) => setEntwurf((vorher) => ({ ...vorher, [pfad]: wert }));
|
|
17916
19104
|
const payloadAusFormular = () => payloadFromForm(felder, entwurf);
|
|
17917
19105
|
const strukturPayload = useMemo7(() => {
|
|
17918
|
-
const
|
|
19106
|
+
const lies2 = (name) => {
|
|
17919
19107
|
try {
|
|
17920
19108
|
const roh = JSON.parse(entwurf[name] || "[]");
|
|
17921
19109
|
return Array.isArray(roh) ? roh : [];
|
|
@@ -17923,7 +19111,7 @@ var ElementDetail = ({
|
|
|
17923
19111
|
return [];
|
|
17924
19112
|
}
|
|
17925
19113
|
};
|
|
17926
|
-
return { nodes:
|
|
19114
|
+
return { nodes: lies2("nodes"), relations: lies2("relations") };
|
|
17927
19115
|
}, [entwurf.nodes, entwurf.relations]);
|
|
17928
19116
|
const umgebungsRefs = useMemo7(() => {
|
|
17929
19117
|
try {
|
|
@@ -22465,11 +23653,11 @@ function createClientDerivationPort(options) {
|
|
|
22465
23653
|
}
|
|
22466
23654
|
|
|
22467
23655
|
// src/lib/szenen/inputChecks.ts
|
|
22468
|
-
var
|
|
23656
|
+
var fail3 = (message) => ({ kind: "error", message, retryable: false });
|
|
22469
23657
|
var KNOWN_TYPES = new Set(SZENEN_ELEMENT_TYPES);
|
|
22470
23658
|
function checkRevision(value2, field) {
|
|
22471
23659
|
if (typeof value2 !== "number" || !Number.isInteger(value2) || value2 < 0) {
|
|
22472
|
-
return
|
|
23660
|
+
return fail3(
|
|
22473
23661
|
`${field} muss eine ganze Zahl >= 0 sein, war ${JSON.stringify(value2)}. Ohne belastbare Revision ist die Konfliktregel (\xA73.1) nicht anwendbar.`
|
|
22474
23662
|
);
|
|
22475
23663
|
}
|
|
@@ -22477,7 +23665,7 @@ function checkRevision(value2, field) {
|
|
|
22477
23665
|
}
|
|
22478
23666
|
function checkElementType(value2) {
|
|
22479
23667
|
if (typeof value2 !== "string" || !KNOWN_TYPES.has(value2)) {
|
|
22480
|
-
return
|
|
23668
|
+
return fail3(
|
|
22481
23669
|
`Unbekannter Elementtyp ${JSON.stringify(value2)}. Erlaubt: ${SZENEN_ELEMENT_TYPES.join(", ")}. Der Typ ist nach Anlage unveraenderlich (D-02) \u2014 ein falsch angelegtes Element laesst sich nur noch stilllegen.`
|
|
22482
23670
|
);
|
|
22483
23671
|
}
|
|
@@ -22485,20 +23673,20 @@ function checkElementType(value2) {
|
|
|
22485
23673
|
}
|
|
22486
23674
|
function checkTitle(value2) {
|
|
22487
23675
|
if (typeof value2 !== "string" || value2.trim().length === 0) {
|
|
22488
|
-
return
|
|
23676
|
+
return fail3("title muss ein nicht leerer Text sein.");
|
|
22489
23677
|
}
|
|
22490
23678
|
return null;
|
|
22491
23679
|
}
|
|
22492
23680
|
function checkOptionalId(value2, field) {
|
|
22493
23681
|
if (value2 === null || value2 === void 0) return null;
|
|
22494
23682
|
if (typeof value2 !== "string" || value2.trim().length === 0) {
|
|
22495
|
-
return
|
|
23683
|
+
return fail3(`${field} muss ein nicht leerer Text sein, wenn es gesetzt ist.`);
|
|
22496
23684
|
}
|
|
22497
23685
|
return null;
|
|
22498
23686
|
}
|
|
22499
23687
|
function checkRequiredId(value2, field) {
|
|
22500
23688
|
if (typeof value2 !== "string" || value2.trim().length === 0) {
|
|
22501
|
-
return
|
|
23689
|
+
return fail3(`${field} ist erforderlich.`);
|
|
22502
23690
|
}
|
|
22503
23691
|
return null;
|
|
22504
23692
|
}
|
|
@@ -22506,17 +23694,17 @@ var RELATIONS = /* @__PURE__ */ new Set(["derived_from", "merged_from"]);
|
|
|
22506
23694
|
function checkParents(value2) {
|
|
22507
23695
|
if (value2 === void 0 || value2 === null) return null;
|
|
22508
23696
|
if (!Array.isArray(value2)) {
|
|
22509
|
-
return
|
|
23697
|
+
return fail3(`parents muss ein Array sein, war ${typeof value2}.`);
|
|
22510
23698
|
}
|
|
22511
23699
|
for (const [i, entry] of value2.entries()) {
|
|
22512
23700
|
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
22513
|
-
return
|
|
23701
|
+
return fail3(`parents[${i}] muss ein Objekt sein.`);
|
|
22514
23702
|
}
|
|
22515
23703
|
const parent = entry;
|
|
22516
23704
|
const idError = checkRequiredId(parent.parent_version_id, `parents[${i}].parent_version_id`);
|
|
22517
23705
|
if (idError) return idError;
|
|
22518
23706
|
if (typeof parent.relation !== "string" || !RELATIONS.has(parent.relation)) {
|
|
22519
|
-
return
|
|
23707
|
+
return fail3(
|
|
22520
23708
|
`parents[${i}].relation muss "derived_from" oder "merged_from" sein, war ${JSON.stringify(parent.relation)}.`
|
|
22521
23709
|
);
|
|
22522
23710
|
}
|
|
@@ -22524,7 +23712,7 @@ function checkParents(value2) {
|
|
|
22524
23712
|
return null;
|
|
22525
23713
|
}
|
|
22526
23714
|
function checkPayloadPresent(value2) {
|
|
22527
|
-
if (value2 === void 0) return
|
|
23715
|
+
if (value2 === void 0) return fail3("payload ist erforderlich.");
|
|
22528
23716
|
return null;
|
|
22529
23717
|
}
|
|
22530
23718
|
function firstError(...checks) {
|
|
@@ -22568,7 +23756,7 @@ function checkSetPreferredHeadInput(input) {
|
|
|
22568
23756
|
}
|
|
22569
23757
|
function checkCoverLength(value2) {
|
|
22570
23758
|
if (typeof value2 === "string" && value2.length > 512) {
|
|
22571
|
-
return
|
|
23759
|
+
return fail3("cover_media_ref darf hoechstens 512 Zeichen lang sein.");
|
|
22572
23760
|
}
|
|
22573
23761
|
return null;
|
|
22574
23762
|
}
|
|
@@ -24147,7 +25335,7 @@ function createFlowImageProvider(generateImage) {
|
|
|
24147
25335
|
}
|
|
24148
25336
|
|
|
24149
25337
|
// src/lib/szenen/imageGenerationOrderStore.ts
|
|
24150
|
-
function
|
|
25338
|
+
function istText8(wert) {
|
|
24151
25339
|
return typeof wert === "string" && wert.trim().length > 0;
|
|
24152
25340
|
}
|
|
24153
25341
|
function collectImageGenerationOrders(events) {
|
|
@@ -24155,7 +25343,7 @@ function collectImageGenerationOrders(events) {
|
|
|
24155
25343
|
for (const event of events) {
|
|
24156
25344
|
if (event.type !== SZENEN_EVENT_TYPES.imageGenerationStarted) continue;
|
|
24157
25345
|
const payload = event.payload;
|
|
24158
|
-
if (!payload || !
|
|
25346
|
+
if (!payload || !istText8(payload.generation_batch_id) || !istText8(payload.prompt_run_id)) continue;
|
|
24159
25347
|
if (byBatchId.has(payload.generation_batch_id)) continue;
|
|
24160
25348
|
byBatchId.set(payload.generation_batch_id, {
|
|
24161
25349
|
generation_batch_id: payload.generation_batch_id,
|
|
@@ -24169,7 +25357,7 @@ function collectImageGenerationOrders(events) {
|
|
|
24169
25357
|
for (const event of events) {
|
|
24170
25358
|
if (event.type !== SZENEN_EVENT_TYPES.imageGenerationFinished) continue;
|
|
24171
25359
|
const payload = event.payload;
|
|
24172
|
-
if (!payload || !
|
|
25360
|
+
if (!payload || !istText8(payload.generation_batch_id)) continue;
|
|
24173
25361
|
const auftrag = byBatchId.get(payload.generation_batch_id);
|
|
24174
25362
|
if (!auftrag) continue;
|
|
24175
25363
|
if (auftrag.status !== "started") continue;
|
|
@@ -24239,13 +25427,13 @@ function isSzenenItemId(itemId) {
|
|
|
24239
25427
|
return itemId.startsWith(SZENEN_ITEM_PREFIX);
|
|
24240
25428
|
}
|
|
24241
25429
|
function checkSzenenBatchOrigin(candidate) {
|
|
24242
|
-
if (!
|
|
25430
|
+
if (!istText9(candidate.prompt_run_id)) {
|
|
24243
25431
|
return {
|
|
24244
25432
|
kind: "rejected",
|
|
24245
25433
|
failure: { field: "prompt_run_id", message: '"prompt_run_id" fehlt oder ist leer.' }
|
|
24246
25434
|
};
|
|
24247
25435
|
}
|
|
24248
|
-
if (!
|
|
25436
|
+
if (!istText9(candidate.generation_batch_id)) {
|
|
24249
25437
|
return {
|
|
24250
25438
|
kind: "rejected",
|
|
24251
25439
|
failure: {
|
|
@@ -24288,7 +25476,7 @@ function mergeSzenenBatchOrigin(bestehend, neu) {
|
|
|
24288
25476
|
};
|
|
24289
25477
|
}
|
|
24290
25478
|
var DEFAULT_FSK_LEVEL = "FSK16";
|
|
24291
|
-
var
|
|
25479
|
+
var istText9 = (v) => typeof v === "string" && v.trim().length > 0;
|
|
24292
25480
|
function roundOfRun(run, runsOfShot) {
|
|
24293
25481
|
return runsOfShot.findIndex((kandidat) => kandidat.run_id === run.run_id) + 1;
|
|
24294
25482
|
}
|
|
@@ -24324,7 +25512,7 @@ function deriveItemFromRun(input) {
|
|
|
24324
25512
|
}
|
|
24325
25513
|
};
|
|
24326
25514
|
}
|
|
24327
|
-
if (!run.output || !
|
|
25515
|
+
if (!run.output || !istText9(run.output.positive)) {
|
|
24328
25516
|
return {
|
|
24329
25517
|
kind: "rejected",
|
|
24330
25518
|
failure: {
|
|
@@ -24348,8 +25536,8 @@ function deriveItemFromRun(input) {
|
|
|
24348
25536
|
}
|
|
24349
25537
|
const item_id = itemIdForRun(run.run_id);
|
|
24350
25538
|
const lineage = deriveLineage(item_id, round, existingItems);
|
|
24351
|
-
const negative =
|
|
24352
|
-
const title =
|
|
25539
|
+
const negative = istText9(run.output.negative) ? run.output.negative : null;
|
|
25540
|
+
const title = istText9(input.title) ? input.title : istText9(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
|
|
24353
25541
|
return {
|
|
24354
25542
|
kind: "ok",
|
|
24355
25543
|
value: {
|
|
@@ -24359,9 +25547,9 @@ function deriveItemFromRun(input) {
|
|
|
24359
25547
|
negative_prompt: negative,
|
|
24360
25548
|
// `feedback` ist Pflicht (D-55) und ist genau die Erlaeuterung fuer den
|
|
24361
25549
|
// Menschen — also gehoert sie in das Feld fuer Notizen.
|
|
24362
|
-
notes:
|
|
25550
|
+
notes: istText9(input.notes) ? input.notes : run.output.feedback,
|
|
24363
25551
|
rating: typeof input.rating === "number" ? input.rating : 0,
|
|
24364
|
-
fsk_level:
|
|
25552
|
+
fsk_level: istText9(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
|
|
24365
25553
|
tags: [],
|
|
24366
25554
|
szenen: {
|
|
24367
25555
|
prompt_run_id: run.run_id,
|
|
@@ -24783,14 +25971,14 @@ function createImageGenerationPort(options) {
|
|
|
24783
25971
|
}
|
|
24784
25972
|
|
|
24785
25973
|
// src/lib/szenen/imageJobStore.ts
|
|
24786
|
-
var
|
|
25974
|
+
var istText10 = (wert) => typeof wert === "string" && wert.trim().length > 0;
|
|
24787
25975
|
var SETTLED_STATUS = ["succeeded", "partial", "failed", "rejected"];
|
|
24788
25976
|
function collectImageJobs(events) {
|
|
24789
25977
|
const nachId = /* @__PURE__ */ new Map();
|
|
24790
25978
|
for (const event of events) {
|
|
24791
25979
|
if (event.type !== SZENEN_EVENT_TYPES.imageJobRequested) continue;
|
|
24792
25980
|
const payload = event.payload;
|
|
24793
|
-
if (!payload || !
|
|
25981
|
+
if (!payload || !istText10(payload.job_id) || !istText10(payload.prompt_run_id)) continue;
|
|
24794
25982
|
if (nachId.has(payload.job_id)) continue;
|
|
24795
25983
|
nachId.set(payload.job_id, {
|
|
24796
25984
|
job_id: payload.job_id,
|
|
@@ -24809,7 +25997,7 @@ function collectImageJobs(events) {
|
|
|
24809
25997
|
for (const event of events) {
|
|
24810
25998
|
if (event.type !== SZENEN_EVENT_TYPES.imageJobClaimed) continue;
|
|
24811
25999
|
const payload = event.payload;
|
|
24812
|
-
if (!payload || !
|
|
26000
|
+
if (!payload || !istText10(payload.job_id) || !istText10(payload.claim_id)) continue;
|
|
24813
26001
|
const auftrag = nachId.get(payload.job_id);
|
|
24814
26002
|
if (!auftrag) continue;
|
|
24815
26003
|
const anspruch = {
|
|
@@ -24828,7 +26016,7 @@ function collectImageJobs(events) {
|
|
|
24828
26016
|
for (const event of events) {
|
|
24829
26017
|
if (event.type !== SZENEN_EVENT_TYPES.imageJobSettled) continue;
|
|
24830
26018
|
const payload = event.payload;
|
|
24831
|
-
if (!payload || !
|
|
26019
|
+
if (!payload || !istText10(payload.job_id)) continue;
|
|
24832
26020
|
const auftrag = nachId.get(payload.job_id);
|
|
24833
26021
|
if (!auftrag) continue;
|
|
24834
26022
|
if (!auftrag.claim || auftrag.claim.claim_id !== payload.claim_id) continue;
|
|
@@ -24870,33 +26058,33 @@ function istOffen(job) {
|
|
|
24870
26058
|
return job.status === "pending";
|
|
24871
26059
|
}
|
|
24872
26060
|
var PROMPT_AUSZUG_ZEICHEN = 160;
|
|
24873
|
-
var
|
|
26061
|
+
var istText11 = (wert) => typeof wert === "string" && wert.trim().length > 0;
|
|
24874
26062
|
function titelJeElement(events) {
|
|
24875
26063
|
const titel = /* @__PURE__ */ new Map();
|
|
24876
26064
|
for (const event of events) {
|
|
24877
26065
|
if (event.type === SZENEN_EVENT_TYPES.elementCreated) {
|
|
24878
26066
|
const p = event.payload;
|
|
24879
|
-
if (p &&
|
|
26067
|
+
if (p && istText11(p.element_id) && istText11(p.title)) titel.set(p.element_id, p.title);
|
|
24880
26068
|
} else if (event.type === SZENEN_EVENT_TYPES.metadataRevised) {
|
|
24881
26069
|
const p = event.payload;
|
|
24882
|
-
if (p &&
|
|
26070
|
+
if (p && istText11(p.element_id) && istText11(p.title)) titel.set(p.element_id, p.title);
|
|
24883
26071
|
}
|
|
24884
26072
|
}
|
|
24885
26073
|
return titel;
|
|
24886
26074
|
}
|
|
24887
26075
|
function benennendesElement(run) {
|
|
24888
26076
|
const quelle = run.source;
|
|
24889
|
-
if (quelle?.kind === "scene_direct" &&
|
|
26077
|
+
if (quelle?.kind === "scene_direct" && istText11(quelle.scene?.element_id)) {
|
|
24890
26078
|
return quelle.scene.element_id;
|
|
24891
26079
|
}
|
|
24892
26080
|
if (quelle?.kind === "draft_chain") {
|
|
24893
26081
|
const knoten = quelle.nodes ?? [];
|
|
24894
|
-
const szene = knoten.find((k) => k?.type === "scene" &&
|
|
26082
|
+
const szene = knoten.find((k) => k?.type === "scene" && istText11(k.element_id));
|
|
24895
26083
|
if (szene) return szene.element_id;
|
|
24896
|
-
const shot = knoten.find((k) => k?.type === "shot" &&
|
|
26084
|
+
const shot = knoten.find((k) => k?.type === "shot" && istText11(k.element_id));
|
|
24897
26085
|
if (shot) return shot.element_id;
|
|
24898
26086
|
}
|
|
24899
|
-
return
|
|
26087
|
+
return istText11(run.shot_element_id) ? run.shot_element_id : null;
|
|
24900
26088
|
}
|
|
24901
26089
|
function kuerze(text2, zeichen) {
|
|
24902
26090
|
const sauber = text2.replace(/\s+/g, " ").trim();
|
|
@@ -24921,7 +26109,7 @@ function herkunftFuer(job, laeufe, elementTitel, bilderJeLauf2) {
|
|
|
24921
26109
|
run_id: job.prompt_run_id,
|
|
24922
26110
|
szene_titel: elementId ? elementTitel.get(elementId) ?? null : null,
|
|
24923
26111
|
szene_element_id: elementId,
|
|
24924
|
-
prompt_auszug:
|
|
26112
|
+
prompt_auszug: istText11(positiv) ? kuerze(positiv, PROMPT_AUSZUG_ZEICHEN) : null,
|
|
24925
26113
|
lauf_gefunden: true,
|
|
24926
26114
|
bilder_im_lauf
|
|
24927
26115
|
};
|
|
@@ -24943,7 +26131,7 @@ function selectImageJobs(events, storeId, query = {}) {
|
|
|
24943
26131
|
const getroffen = status === "all" ? alle : alle.filter((j) => GRUPPEN[status].includes(j.status));
|
|
24944
26132
|
const geordnet = sortiere(getroffen, logIndex, status === "pending");
|
|
24945
26133
|
let ab = 0;
|
|
24946
|
-
if (
|
|
26134
|
+
if (istText11(query.cursor)) {
|
|
24947
26135
|
const stelle = geordnet.findIndex((j) => j.job_id === query.cursor);
|
|
24948
26136
|
if (stelle < 0) {
|
|
24949
26137
|
throw new Error(
|
|
@@ -24972,8 +26160,8 @@ function bildRefAus(roh, batchId) {
|
|
|
24972
26160
|
media_ref: roh.media_ref,
|
|
24973
26161
|
position: roh.position,
|
|
24974
26162
|
generation_batch_id: batchId,
|
|
24975
|
-
...
|
|
24976
|
-
...
|
|
26163
|
+
...istText11(roh.asset_id) ? { asset_id: roh.asset_id } : {},
|
|
26164
|
+
...istText11(roh.mime_type) ? { mime_type: roh.mime_type } : {},
|
|
24977
26165
|
model: roh.model ?? null,
|
|
24978
26166
|
seed: roh.seed ?? null,
|
|
24979
26167
|
width: roh.width ?? null,
|
|
@@ -24988,10 +26176,10 @@ function bilderJeLauf(events, jobs) {
|
|
|
24988
26176
|
for (const event of events) {
|
|
24989
26177
|
if (event.type !== SZENEN_EVENT_TYPES.imageBatchPersisted) continue;
|
|
24990
26178
|
const p = event.payload;
|
|
24991
|
-
if (!p || !
|
|
26179
|
+
if (!p || !istText11(p.item_id) || !istText11(p.prompt_run_id) || !istText11(p.generation_batch_id)) continue;
|
|
24992
26180
|
if (gesehen.has(p.generation_batch_id)) continue;
|
|
24993
26181
|
gesehen.add(p.generation_batch_id);
|
|
24994
|
-
const roh = (Array.isArray(p.images) ? p.images : []).filter((b) => !!b &&
|
|
26182
|
+
const roh = (Array.isArray(p.images) ? p.images : []).filter((b) => !!b && istText11(b.media_ref) && typeof b.position === "number").sort((a, b) => a.position - b.position);
|
|
24995
26183
|
if (roh.length === 0) continue;
|
|
24996
26184
|
const job = jobJeBatch.get(p.generation_batch_id) ?? null;
|
|
24997
26185
|
const liste = jeLauf.get(p.prompt_run_id) ?? [];
|
|
@@ -25004,7 +26192,7 @@ function bilderJeLauf(events, jobs) {
|
|
|
25004
26192
|
job_id: job?.job_id ?? null,
|
|
25005
26193
|
position_im_batch: einzeln.position + 1,
|
|
25006
26194
|
anzahl_im_batch: roh.length,
|
|
25007
|
-
gespeichert_am:
|
|
26195
|
+
gespeichert_am: istText11(p.created_at) ? p.created_at : null,
|
|
25008
26196
|
execution_target_model_key: job?.execution_target_model_key ?? null
|
|
25009
26197
|
});
|
|
25010
26198
|
}
|
|
@@ -25494,6 +26682,9 @@ export {
|
|
|
25494
26682
|
hfUploadImage,
|
|
25495
26683
|
hfLoadImageAsBase64,
|
|
25496
26684
|
applyEvents,
|
|
26685
|
+
STAGE_MIGRATION_ID,
|
|
26686
|
+
STAGE_MIGRATION_EVENT,
|
|
26687
|
+
prepareStageMigration,
|
|
25497
26688
|
SZENEN_EVENT_PREFIX,
|
|
25498
26689
|
SZENEN_EVENT_TYPES,
|
|
25499
26690
|
reduceElementEvents,
|
|
@@ -25621,6 +26812,12 @@ export {
|
|
|
25621
26812
|
completePromptOperation,
|
|
25622
26813
|
runOfOperation,
|
|
25623
26814
|
sameResponseAs,
|
|
26815
|
+
CAMERA_PREVIEW_ASSET_ROLE,
|
|
26816
|
+
checkVariantInputAssets,
|
|
26817
|
+
checkVariantBlock,
|
|
26818
|
+
buildPromptRunVariantRecord,
|
|
26819
|
+
variantOf,
|
|
26820
|
+
sameVariantRequest,
|
|
25624
26821
|
DEFAULT_SEED_VORLAGE,
|
|
25625
26822
|
parseSeedListe,
|
|
25626
26823
|
formatSeedListe,
|
|
@@ -25630,6 +26827,13 @@ export {
|
|
|
25630
26827
|
UPLOAD_MAX_BYTES,
|
|
25631
26828
|
istZipDatei,
|
|
25632
26829
|
leseBilderAusZip,
|
|
26830
|
+
NODE_TYPES,
|
|
26831
|
+
PROXY_PRIMITIVES,
|
|
26832
|
+
previewColorNodes,
|
|
26833
|
+
pinPreviewColors,
|
|
26834
|
+
applyStageOperations,
|
|
26835
|
+
findStageDraftChain,
|
|
26836
|
+
openStageDraftChain,
|
|
25633
26837
|
simulatedAnswerFor,
|
|
25634
26838
|
SIMULATION_PROVIDER,
|
|
25635
26839
|
createSimulationTextGenerationPort,
|