@fps-games/editor 0.1.4-beta.5 → 0.1.5-beta.1
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/build-info.json +16 -16
- package/dist/local-editor-harness.d.ts +24 -5
- package/dist/local-editor-harness.d.ts.map +1 -1
- package/dist/local-editor-harness.js +456 -90
- package/dist/local-editor-harness.js.map +1 -1
- package/dist/local-editor-performance-stats.d.ts +12 -0
- package/dist/local-editor-performance-stats.d.ts.map +1 -0
- package/dist/local-editor-performance-stats.js +46 -0
- package/dist/local-editor-performance-stats.js.map +1 -0
- package/dist/playable-babylon-facade.d.ts +2 -2
- package/dist/playable-babylon-facade.d.ts.map +1 -1
- package/dist/playable-babylon-facade.js +1 -1
- package/dist/playable-babylon-facade.js.map +1 -1
- package/dist/playable-babylon-rendering.d.ts +57 -12
- package/dist/playable-babylon-rendering.d.ts.map +1 -1
- package/dist/playable-babylon-rendering.js +529 -20
- package/dist/playable-babylon-rendering.js.map +1 -1
- package/dist/playable-local-editor-host.d.ts +10 -9
- package/dist/playable-local-editor-host.d.ts.map +1 -1
- package/dist/playable-local-editor-host.js.map +1 -1
- package/dist/playable-sdk.d.ts +5 -3
- package/dist/playable-sdk.d.ts.map +1 -1
- package/dist/playable-sdk.js +3 -2
- package/dist/playable-sdk.js.map +1 -1
- package/dist/static-shadow-cpu-worker.d.ts +7 -0
- package/dist/static-shadow-cpu-worker.d.ts.map +1 -0
- package/dist/static-shadow-cpu-worker.js +221 -0
- package/dist/static-shadow-cpu-worker.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts +3 -1
- package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/index.js +3 -1
- package/node_modules/@fps-games/babylon-renderer/dist/index.js.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts +4 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js +584 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts +61 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js +382 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts +47 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js +285 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts +88 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js +813 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts +27 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js +220 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts +35 -3
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js +65 -609
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts +169 -14
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js +9 -3
- package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +2 -0
- package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/index.js +2 -0
- package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts +34 -0
- package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js +272 -0
- package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +6 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js +65 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts +19 -0
- package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/rendering.js +66 -0
- package/node_modules/@fps-games/editor-babylon/dist/rendering.js.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts +5 -2
- package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js +65 -32
- package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +19 -2
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/package.json +5 -5
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts +1 -1
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts +8 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js +14 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +10 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +17 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +466 -42
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +70 -5
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +595 -5
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/package.json +3 -3
- package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +14 -1
- package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-session.js +34 -10
- package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/inspector.d.ts +2 -1
- package/node_modules/@fps-games/editor-core/dist/inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/inspector.js +11 -1
- package/node_modules/@fps-games/editor-core/dist/inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts +7 -0
- package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/serialized-object.js +1 -0
- package/node_modules/@fps-games/editor-core/dist/serialized-object.js.map +1 -1
- package/node_modules/@fps-games/editor-core/package.json +2 -2
- package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +10 -5
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js +3 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +4 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +29 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +10 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +3 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/index.js +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts +33 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js +232 -16
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts +12 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +153 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts +4 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js +4 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts +19 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js +57 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts +7 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js +620 -36
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts +8 -3
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js +258 -10
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts +110 -3
- package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +25 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +4 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts +9 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js +12 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +75 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts +17 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +262 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -3
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts +6 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js +31 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js +21 -9
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts +151 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js +445 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
- package/node_modules/@fps-games/editor-protocol/package.json +1 -1
- package/package.json +8 -8
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
const SHADOW_RENDERING_GROUP_BLOB = {
|
|
2
|
+
id: 'shadow-group-moving-object',
|
|
3
|
+
label: 'Moving Object Shadows',
|
|
4
|
+
summary: 'Blob: lightweight for moving objects and project-default fallback.',
|
|
5
|
+
};
|
|
6
|
+
const SHADOW_RENDERING_GROUP_STATIC = {
|
|
7
|
+
id: 'shadow-group-static-scene',
|
|
8
|
+
label: 'Static Scene Shadows',
|
|
9
|
+
summary: 'Consumes baked artifacts; update during authoring/build, runtime only displays results.',
|
|
10
|
+
};
|
|
11
|
+
const SHADOW_RENDERING_GROUP_PLANAR = {
|
|
12
|
+
id: 'shadow-group-directional-planar',
|
|
13
|
+
label: 'Directional Planar Shadows',
|
|
14
|
+
summary: 'Real-time planar projection following the directional light.',
|
|
15
|
+
};
|
|
16
|
+
const SHADOW_RENDERING_GROUP_COMPAT = {
|
|
17
|
+
id: 'shadow-group-compatibility',
|
|
18
|
+
label: 'Compatibility Shadows',
|
|
19
|
+
summary: 'Legacy ShadowGenerator / CSM read-only compatibility paths.',
|
|
20
|
+
};
|
|
1
21
|
export function createEditorSceneRenderingPanelState(profile, state = {}, options = {}) {
|
|
2
22
|
const blob = profile.shadows.blob;
|
|
3
23
|
const staticProjected = profile.shadows.staticProjected;
|
|
@@ -6,6 +26,10 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
6
26
|
const postProcess = profile.postProcess;
|
|
7
27
|
const dirty = state.dirty === true;
|
|
8
28
|
const lastError = state.lastError ?? null;
|
|
29
|
+
const language = options.language ?? 'en';
|
|
30
|
+
const staticShadowBake = resolveStaticShadowBakeLifecycleState(state.staticShadowBake, staticProjected.enabled);
|
|
31
|
+
const staticShadowStatus = formatStaticShadowBakeLifecycleStatus(staticShadowBake, language);
|
|
32
|
+
const staticShadowBakeInProgress = staticShadowBake.status === 'baking';
|
|
9
33
|
const panel = {
|
|
10
34
|
title: 'Rendering',
|
|
11
35
|
summary: 'Project-level rendering settings shared by editor preview and runtime.',
|
|
@@ -21,7 +45,7 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
21
45
|
? 'Revert rendering settings to the last saved rendering settings.'
|
|
22
46
|
: 'Rendering settings already match the last saved rendering settings.',
|
|
23
47
|
}],
|
|
24
|
-
sections: [{
|
|
48
|
+
sections: [createRenderingGroupsSection(profile.renderingGroups.slots), {
|
|
25
49
|
id: 'environment',
|
|
26
50
|
title: 'Environment / IBL',
|
|
27
51
|
summary: 'World environment texture and reflection lighting shared by editor preview and runtime.',
|
|
@@ -223,11 +247,13 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
223
247
|
title: 'Shadows',
|
|
224
248
|
summary: 'Global shadow systems for editor preview and runtime.',
|
|
225
249
|
layout: 'list',
|
|
250
|
+
systemsCollapsible: true,
|
|
226
251
|
systems: [
|
|
227
252
|
{
|
|
228
253
|
id: 'blob-shadow',
|
|
229
254
|
label: 'Blob Shadow',
|
|
230
255
|
kind: 'blob-shadow',
|
|
256
|
+
group: { ...SHADOW_RENDERING_GROUP_BLOB },
|
|
231
257
|
active: blob.enabled,
|
|
232
258
|
summary: 'Default object shadow',
|
|
233
259
|
properties: [
|
|
@@ -345,10 +371,25 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
345
371
|
},
|
|
346
372
|
{
|
|
347
373
|
id: 'static-projected-shadow',
|
|
348
|
-
label: 'Static
|
|
374
|
+
label: 'Static Baked Shadow',
|
|
349
375
|
kind: 'static-projected-shadow',
|
|
376
|
+
group: { ...SHADOW_RENDERING_GROUP_STATIC },
|
|
350
377
|
active: staticProjected.enabled,
|
|
351
|
-
summary:
|
|
378
|
+
summary: staticShadowStatus.summary,
|
|
379
|
+
status: staticShadowStatus.status,
|
|
380
|
+
details: createStaticShadowBakeDetails(staticShadowBake, language),
|
|
381
|
+
progress: staticShadowStatus.progress,
|
|
382
|
+
actions: [{
|
|
383
|
+
id: 'bake-static-shadows',
|
|
384
|
+
label: 'Bake Static Shadows',
|
|
385
|
+
icon: 'save',
|
|
386
|
+
disabled: !staticProjected.enabled || staticShadowBakeInProgress,
|
|
387
|
+
tooltip: staticShadowBakeInProgress
|
|
388
|
+
? 'Static shadow bake is already running.'
|
|
389
|
+
: staticProjected.enabled
|
|
390
|
+
? 'Bake static shadow chunks for objects authored as Static Baked Shadow.'
|
|
391
|
+
: 'Enable Static Baked Shadow before baking.',
|
|
392
|
+
}],
|
|
352
393
|
properties: [
|
|
353
394
|
{
|
|
354
395
|
path: 'shadows.staticProjected.enabled',
|
|
@@ -404,14 +445,47 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
404
445
|
commitMode: 'live',
|
|
405
446
|
},
|
|
406
447
|
{
|
|
407
|
-
path: 'shadows.staticProjected.bake.
|
|
408
|
-
label: '
|
|
448
|
+
path: 'shadows.staticProjected.bake.texelsPerMeter',
|
|
449
|
+
label: 'Texels per Meter',
|
|
409
450
|
valueType: 'number',
|
|
410
451
|
control: 'number',
|
|
411
|
-
value: staticProjected.bake.
|
|
452
|
+
value: staticProjected.bake.texelsPerMeter,
|
|
453
|
+
min: 1,
|
|
454
|
+
step: 1,
|
|
455
|
+
tooltip: 'Target SDF atlas texel density for baked static shadows.',
|
|
456
|
+
commitMode: 'blur',
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
path: 'shadows.staticProjected.bake.atlasSize',
|
|
460
|
+
label: 'Atlas Size',
|
|
461
|
+
valueType: 'number',
|
|
462
|
+
control: 'number',
|
|
463
|
+
value: staticProjected.bake.atlasSize,
|
|
412
464
|
min: 16,
|
|
413
465
|
step: 1,
|
|
414
|
-
tooltip: '
|
|
466
|
+
tooltip: 'Maximum width and height for each static shadow atlas page.',
|
|
467
|
+
commitMode: 'blur',
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
path: 'shadows.staticProjected.bake.maxAtlasPages',
|
|
471
|
+
label: 'Page Budget',
|
|
472
|
+
valueType: 'number',
|
|
473
|
+
control: 'number',
|
|
474
|
+
value: staticProjected.bake.maxAtlasPages,
|
|
475
|
+
min: 1,
|
|
476
|
+
step: 1,
|
|
477
|
+
tooltip: 'Maximum atlas pages allowed before bake lowers the effective texel density.',
|
|
478
|
+
commitMode: 'blur',
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
path: 'shadows.staticProjected.bake.sdfRadiusPx',
|
|
482
|
+
label: 'SDF Radius',
|
|
483
|
+
valueType: 'number',
|
|
484
|
+
control: 'number',
|
|
485
|
+
value: staticProjected.bake.sdfRadiusPx,
|
|
486
|
+
min: 0,
|
|
487
|
+
step: 1,
|
|
488
|
+
tooltip: 'Signed-distance radius in pixels used to preserve crisp controllable edges.',
|
|
415
489
|
commitMode: 'blur',
|
|
416
490
|
},
|
|
417
491
|
{
|
|
@@ -437,23 +511,35 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
437
511
|
commitMode: 'live',
|
|
438
512
|
},
|
|
439
513
|
{
|
|
440
|
-
path: 'shadows.staticProjected.bake.
|
|
441
|
-
label: '
|
|
514
|
+
path: 'shadows.staticProjected.bake.spatialChunkSize',
|
|
515
|
+
label: 'Spatial Chunk Size',
|
|
442
516
|
valueType: 'number',
|
|
443
517
|
control: 'number',
|
|
444
|
-
value: staticProjected.bake.
|
|
518
|
+
value: staticProjected.bake.spatialChunkSize,
|
|
445
519
|
min: 0.01,
|
|
446
520
|
step: 0.01,
|
|
447
521
|
unit: 'm',
|
|
448
|
-
tooltip: '
|
|
522
|
+
tooltip: 'World size of each spatial bake chunk before atlas packing.',
|
|
449
523
|
commitMode: 'live',
|
|
450
524
|
},
|
|
525
|
+
{
|
|
526
|
+
path: 'shadows.staticProjected.bake.targetChunkCount',
|
|
527
|
+
label: 'Target Chunks',
|
|
528
|
+
valueType: 'number',
|
|
529
|
+
control: 'number',
|
|
530
|
+
value: staticProjected.bake.targetChunkCount,
|
|
531
|
+
min: 1,
|
|
532
|
+
step: 1,
|
|
533
|
+
tooltip: 'Soft chunk-count budget. Large scenes automatically enlarge spatial chunks to stay near this target.',
|
|
534
|
+
commitMode: 'blur',
|
|
535
|
+
},
|
|
451
536
|
],
|
|
452
537
|
},
|
|
453
538
|
{
|
|
454
539
|
id: 'planar-main',
|
|
455
540
|
label: 'Planar Main',
|
|
456
541
|
kind: 'planar-shadow',
|
|
542
|
+
group: { ...SHADOW_RENDERING_GROUP_PLANAR },
|
|
457
543
|
active: planar.enabled,
|
|
458
544
|
summary: 'Follow Directional Light',
|
|
459
545
|
properties: [
|
|
@@ -584,6 +670,7 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
584
670
|
id: 'legacy-shadow',
|
|
585
671
|
label: 'Legacy Shadow',
|
|
586
672
|
kind: 'legacy-shadow',
|
|
673
|
+
group: { ...SHADOW_RENDERING_GROUP_COMPAT },
|
|
587
674
|
active: profile.shadows.enabled && !planar.enabled,
|
|
588
675
|
readOnly: true,
|
|
589
676
|
summary: profile.shadows.enabled ? 'Compatibility path' : 'Disabled',
|
|
@@ -597,6 +684,7 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
597
684
|
id: 'csm-shadow',
|
|
598
685
|
label: 'CSM',
|
|
599
686
|
kind: 'csm-shadow',
|
|
687
|
+
group: { ...SHADOW_RENDERING_GROUP_COMPAT },
|
|
600
688
|
active: profile.shadows.enabled && profile.shadows.useCsm && !planar.enabled,
|
|
601
689
|
readOnly: true,
|
|
602
690
|
summary: profile.shadows.useCsm ? 'Compatibility path' : 'Disabled',
|
|
@@ -609,7 +697,382 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
|
|
|
609
697
|
],
|
|
610
698
|
}],
|
|
611
699
|
};
|
|
612
|
-
return localizeRenderingPanelState(panel,
|
|
700
|
+
return localizeRenderingPanelState(panel, language, dirty);
|
|
701
|
+
}
|
|
702
|
+
function resolveStaticShadowBakeLifecycleState(state, enabled) {
|
|
703
|
+
if (!enabled) {
|
|
704
|
+
return {
|
|
705
|
+
status: 'disabled',
|
|
706
|
+
chunkCount: 0,
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
return state ?? {
|
|
710
|
+
status: 'missing',
|
|
711
|
+
chunkCount: 0,
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function formatStaticShadowBakeLifecycleStatus(state, language) {
|
|
715
|
+
const chunkCount = Math.max(0, Math.trunc(state.chunkCount ?? 0));
|
|
716
|
+
const chunkText = language === 'zh'
|
|
717
|
+
? `${chunkCount} 个分块`
|
|
718
|
+
: `${chunkCount} chunk${chunkCount === 1 ? '' : 's'}`;
|
|
719
|
+
if (state.status === 'baking') {
|
|
720
|
+
const progress = state.progress ?? {
|
|
721
|
+
label: language === 'zh' ? '正在烘焙静态阴影' : 'Baking static shadows',
|
|
722
|
+
indeterminate: true,
|
|
723
|
+
};
|
|
724
|
+
return {
|
|
725
|
+
summary: language === 'zh' ? '正在烘焙' : 'Baking',
|
|
726
|
+
status: language === 'zh'
|
|
727
|
+
? formatChineseStaticShadowBakingStatus(state)
|
|
728
|
+
: state.reason ?? 'Baking static shadow artifact.',
|
|
729
|
+
progress: {
|
|
730
|
+
...progress,
|
|
731
|
+
label: language === 'zh' ? formatChineseStaticShadowProgressLabel(state) : progress.label,
|
|
732
|
+
},
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
if (state.status === 'disabled') {
|
|
736
|
+
const fallback = 'Static Baked Shadow is disabled.';
|
|
737
|
+
return {
|
|
738
|
+
summary: language === 'zh' ? '已禁用' : 'Disabled',
|
|
739
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态烘焙阴影已禁用。', language),
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
if (state.status === 'missing') {
|
|
743
|
+
const fallback = 'No static shadow bake artifact is available.';
|
|
744
|
+
return {
|
|
745
|
+
summary: language === 'zh' ? '缺少烘焙' : 'Missing bake',
|
|
746
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '当前没有可用的静态阴影烘焙数据。', language),
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
if (state.status === 'preview-unsaved') {
|
|
750
|
+
const fallback = 'Static shadow preview has not been saved yet.';
|
|
751
|
+
return {
|
|
752
|
+
summary: language === 'zh' ? `预览未保存 · ${chunkText}` : `Preview unsaved · ${chunkText}`,
|
|
753
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影预览尚未保存。', language),
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
if (state.status === 'out-of-date') {
|
|
757
|
+
const fallback = 'Static shadow bake is out of date.';
|
|
758
|
+
return {
|
|
759
|
+
summary: language === 'zh' ? `已过期 · ${chunkText}` : `Out of date · ${chunkText}`,
|
|
760
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影烘焙已过期。', language),
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
if (state.status === 'invalid') {
|
|
764
|
+
const fallback = 'Static shadow bake artifact is invalid.';
|
|
765
|
+
return {
|
|
766
|
+
summary: language === 'zh' ? '烘焙无效' : 'Invalid bake',
|
|
767
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影烘焙数据无效。', language),
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
const fallback = 'Static shadow bake artifact is up to date.';
|
|
771
|
+
if (chunkCount === 0) {
|
|
772
|
+
return {
|
|
773
|
+
summary: language === 'zh' ? '无静态投射物' : 'No static casters',
|
|
774
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '没有物体被显式设置为静态烘焙阴影。', language),
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
return {
|
|
778
|
+
summary: language === 'zh' ? `最新 · ${chunkText}` : `Up to date · ${chunkText}`,
|
|
779
|
+
status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影烘焙数据已是最新。', language),
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function resolveLocalizedStaticShadowStatusReason(reason, englishFallback, localizedFallback, language) {
|
|
783
|
+
if (language !== 'zh')
|
|
784
|
+
return reason ?? englishFallback;
|
|
785
|
+
return !reason || reason === englishFallback ? localizedFallback : reason;
|
|
786
|
+
}
|
|
787
|
+
function formatChineseStaticShadowBakingStatus(state) {
|
|
788
|
+
const stats = state.stats ?? null;
|
|
789
|
+
const phase = stats?.phase;
|
|
790
|
+
const attempted = stats?.attemptedChunkCount ?? 0;
|
|
791
|
+
const completed = stats?.chunkCount ?? 0;
|
|
792
|
+
const atlasPages = stats?.pageCount ?? stats?.textureCount ?? 0;
|
|
793
|
+
const encodedPages = stats?.textureCount ?? 0;
|
|
794
|
+
if (phase === 'collect') {
|
|
795
|
+
if ((stats?.sourceRootCount ?? 0) > 0)
|
|
796
|
+
return `已收集 ${stats?.sourceRootCount ?? 0} 个静态投射物,正在准备空间分块。`;
|
|
797
|
+
return '正在收集静态阴影投射物。';
|
|
798
|
+
}
|
|
799
|
+
if (phase === 'sdf') {
|
|
800
|
+
if (attempted > 0)
|
|
801
|
+
return `正在生成静态阴影 SDF ${Math.min(completed + 1, attempted)} / ${attempted}。`;
|
|
802
|
+
return '正在生成静态阴影 SDF。';
|
|
803
|
+
}
|
|
804
|
+
if (phase === 'pack') {
|
|
805
|
+
return `正在将 ${completed} 个静态阴影分块打包到 ${atlasPages} 张 Atlas。`;
|
|
806
|
+
}
|
|
807
|
+
if (phase === 'encode') {
|
|
808
|
+
return `正在编码静态阴影 Atlas ${Math.min(encodedPages + 1, atlasPages || encodedPages + 1)} / ${atlasPages || encodedPages + 1}。`;
|
|
809
|
+
}
|
|
810
|
+
if (phase === 'complete')
|
|
811
|
+
return '正在写入静态阴影烘焙数据。';
|
|
812
|
+
if (attempted > 0)
|
|
813
|
+
return `正在烘焙静态阴影分块 ${Math.min(completed + 1, attempted)} / ${attempted}。`;
|
|
814
|
+
if ((stats?.sourceRootCount ?? 0) > 0)
|
|
815
|
+
return `已收集 ${stats?.sourceRootCount ?? 0} 个静态投射物,正在准备分块。`;
|
|
816
|
+
return '正在收集静态阴影投射物。';
|
|
817
|
+
}
|
|
818
|
+
function formatChineseStaticShadowProgressLabel(state) {
|
|
819
|
+
const stats = state.stats ?? null;
|
|
820
|
+
const phase = stats?.phase;
|
|
821
|
+
const attempted = stats?.attemptedChunkCount ?? 0;
|
|
822
|
+
const completed = stats?.chunkCount ?? 0;
|
|
823
|
+
if (phase === 'collect')
|
|
824
|
+
return '收集静态投射物';
|
|
825
|
+
if (phase === 'pack')
|
|
826
|
+
return '打包静态阴影 Atlas';
|
|
827
|
+
if (phase === 'encode') {
|
|
828
|
+
const atlasPages = stats?.pageCount ?? stats?.textureCount ?? 0;
|
|
829
|
+
const encodedPages = stats?.textureCount ?? 0;
|
|
830
|
+
return `静态阴影 Atlas ${Math.min(encodedPages, atlasPages)} / ${atlasPages}`;
|
|
831
|
+
}
|
|
832
|
+
return attempted > 0
|
|
833
|
+
? `静态阴影烘焙 ${Math.min(completed, attempted)} / ${attempted}`
|
|
834
|
+
: '正在烘焙静态阴影';
|
|
835
|
+
}
|
|
836
|
+
function createStaticShadowBakeDetails(state, language) {
|
|
837
|
+
const stats = state.stats ?? null;
|
|
838
|
+
const details = [];
|
|
839
|
+
const add = (labelEn, labelZh, value, tone) => {
|
|
840
|
+
if (value == null || value === '')
|
|
841
|
+
return;
|
|
842
|
+
details.push({
|
|
843
|
+
label: language === 'zh' ? labelZh : labelEn,
|
|
844
|
+
value: String(value),
|
|
845
|
+
...(tone ? { tone } : {}),
|
|
846
|
+
});
|
|
847
|
+
};
|
|
848
|
+
const chunkCount = stats?.chunkCount ?? state.chunkCount;
|
|
849
|
+
const performance = calculateStaticShadowPerformanceDetails(stats, chunkCount);
|
|
850
|
+
add('Static casters', '静态投射物', formatOptionalCount(stats?.sourceRootCount));
|
|
851
|
+
add('Bake meshes', '参与 Mesh', formatOptionalCount(stats?.sourceMeshCount));
|
|
852
|
+
add('Chunks', '分块', formatOptionalCount(chunkCount), chunkCount === 0 ? 'warning' : undefined);
|
|
853
|
+
add('Atlas pages', 'Atlas 页', formatOptionalCount(stats?.pageCount ?? stats?.textureCount ?? chunkCount));
|
|
854
|
+
add('Texture memory', '贴图显存', performance.textureMemoryText, performance.textureMemoryTone);
|
|
855
|
+
add('Texture pixels', '贴图像素', performance.atlasPixelsText);
|
|
856
|
+
add('Atlas occupancy', 'Atlas 利用率', performance.atlasOccupancyText, performance.atlasOccupancyTone);
|
|
857
|
+
add('Atlas used', 'Atlas 已用', performance.atlasUsedPixelsText);
|
|
858
|
+
add('Atlas allocated', 'Atlas 分配', performance.atlasAllocatedPixelsText);
|
|
859
|
+
add('Runtime draws', '运行时 Draw', performance.drawCallsText);
|
|
860
|
+
add('Shadow mesh', '阴影 Mesh', performance.meshText);
|
|
861
|
+
add('Triangles', '三角形', performance.triangleText);
|
|
862
|
+
add('Vertices', '顶点', performance.vertexText);
|
|
863
|
+
add('Effective texels / m', '实际每米像素', formatOptionalNumber(stats?.effectiveTexelsPerMeter ?? stats?.texelsPerMeter));
|
|
864
|
+
if (stats?.effectiveTexelsPerMeter != null
|
|
865
|
+
&& stats?.texelsPerMeter != null
|
|
866
|
+
&& Math.abs(stats.effectiveTexelsPerMeter - stats.texelsPerMeter) > 0.001) {
|
|
867
|
+
add('Target texels / m', '目标每米像素', formatOptionalNumber(stats.texelsPerMeter), 'warning');
|
|
868
|
+
}
|
|
869
|
+
add('Atlas size', 'Atlas 尺寸', stats?.atlasSize ? `${stats.atlasSize}px` : null);
|
|
870
|
+
add('Page budget', '页预算', formatOptionalCount(stats?.maxAtlasPages));
|
|
871
|
+
add('SDF radius', 'SDF 半径', stats?.sdfRadiusPx != null ? `${stats.sdfRadiusPx}px` : null);
|
|
872
|
+
add('Spatial chunk', '空间分块', stats?.spatialChunkSize ? formatMeters(stats.spatialChunkSize) : null);
|
|
873
|
+
if (stats?.effectiveSpatialChunkSize != null
|
|
874
|
+
&& stats?.spatialChunkSize != null
|
|
875
|
+
&& Math.abs(stats.effectiveSpatialChunkSize - stats.spatialChunkSize) > 0.001) {
|
|
876
|
+
add('Effective chunk', '实际分块', formatMeters(stats.effectiveSpatialChunkSize), 'warning');
|
|
877
|
+
}
|
|
878
|
+
add('Target chunks', '目标分块', formatOptionalCount(stats?.targetChunkCount));
|
|
879
|
+
add('Baked chunks', '重烘分块', formatOptionalCount(stats?.bakedChunkCount));
|
|
880
|
+
add('Reused chunks', '复用分块', formatOptionalCount(stats?.reusedChunkCount), stats?.reusedChunkCount ? 'success' : undefined);
|
|
881
|
+
add('Resolution', '贴图尺寸', stats?.resolution ? `${stats.resolution}px` : null);
|
|
882
|
+
add('Chunk size', '分块尺寸', stats?.chunkSize ? formatMeters(stats.chunkSize) : null);
|
|
883
|
+
add('Duration', '耗时', formatDurationMs(stats?.durationMs, language));
|
|
884
|
+
if (state.status === 'baking') {
|
|
885
|
+
add('Current chunk', '当前分块', stats?.currentChunkId);
|
|
886
|
+
const attempted = stats?.attemptedChunkCount;
|
|
887
|
+
const completed = stats?.chunkCount;
|
|
888
|
+
if (stats?.phase)
|
|
889
|
+
add('Stage', '阶段', formatStaticShadowBakePhase(stats.phase, language));
|
|
890
|
+
if (attempted != null && completed != null) {
|
|
891
|
+
add('Progress', '进度', language === 'zh' ? `${completed} / ${attempted} 个分块` : `${completed} / ${attempted} chunks`);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
else {
|
|
895
|
+
add('Skipped chunks', '跳过分块', formatOptionalCount(stats?.skippedChunkCount), stats?.skippedChunkCount ? 'warning' : undefined);
|
|
896
|
+
}
|
|
897
|
+
return details;
|
|
898
|
+
}
|
|
899
|
+
function calculateStaticShadowPerformanceDetails(stats, fallbackChunkCount) {
|
|
900
|
+
if (!stats) {
|
|
901
|
+
return {
|
|
902
|
+
textureMemoryText: null,
|
|
903
|
+
atlasPixelsText: null,
|
|
904
|
+
atlasUsedPixelsText: null,
|
|
905
|
+
atlasAllocatedPixelsText: null,
|
|
906
|
+
atlasOccupancyText: null,
|
|
907
|
+
drawCallsText: null,
|
|
908
|
+
meshText: null,
|
|
909
|
+
triangleText: null,
|
|
910
|
+
vertexText: null,
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
const chunkCount = Math.max(0, Math.trunc(stats.chunkCount ?? fallbackChunkCount ?? 0));
|
|
914
|
+
const isAtlas = stats.pageCount != null || stats.atlasSize != null || stats.effectiveTexelsPerMeter != null;
|
|
915
|
+
const textureCount = Math.max(0, Math.trunc(isAtlas
|
|
916
|
+
? stats.pageCount ?? stats.textureCount ?? 0
|
|
917
|
+
: stats.textureCount ?? chunkCount));
|
|
918
|
+
const textureSize = isAtlas ? stats.atlasSize : stats.resolution;
|
|
919
|
+
const fallbackTextureBytes = textureCount > 0 && textureSize != null && Number.isFinite(textureSize) && textureSize > 0
|
|
920
|
+
? textureCount * textureSize * textureSize * 4
|
|
921
|
+
: null;
|
|
922
|
+
const allocatedPixels = isAtlas
|
|
923
|
+
? stats.atlasAllocatedPixels ?? (fallbackTextureBytes != null ? fallbackTextureBytes / 4 : null)
|
|
924
|
+
: (fallbackTextureBytes != null ? fallbackTextureBytes / 4 : null);
|
|
925
|
+
const usedPixels = isAtlas ? stats.atlasUsedPixels ?? null : null;
|
|
926
|
+
const textureBytes = allocatedPixels != null ? allocatedPixels * 4 : null;
|
|
927
|
+
const occupancy = isAtlas
|
|
928
|
+
? stats.atlasOccupancy ?? (allocatedPixels != null && allocatedPixels > 0 && usedPixels != null
|
|
929
|
+
? usedPixels / allocatedPixels
|
|
930
|
+
: null)
|
|
931
|
+
: null;
|
|
932
|
+
const drawCalls = textureCount > 0 ? textureCount : null;
|
|
933
|
+
const renderMeshes = isAtlas ? drawCalls : chunkCount || null;
|
|
934
|
+
const triangles = chunkCount > 0 ? chunkCount * 2 : null;
|
|
935
|
+
const vertices = chunkCount > 0 ? chunkCount * 4 : null;
|
|
936
|
+
return {
|
|
937
|
+
textureMemoryText: formatBytes(textureBytes),
|
|
938
|
+
textureMemoryTone: textureBytes != null && textureBytes >= 256 * 1024 * 1024 ? 'warning' : undefined,
|
|
939
|
+
atlasPixelsText: formatPixelCount(allocatedPixels),
|
|
940
|
+
atlasUsedPixelsText: formatPixelCount(usedPixels),
|
|
941
|
+
atlasAllocatedPixelsText: formatPixelCount(allocatedPixels),
|
|
942
|
+
atlasOccupancyText: formatPercentage(occupancy),
|
|
943
|
+
atlasOccupancyTone: occupancy != null && occupancy < 0.35 ? 'warning' : undefined,
|
|
944
|
+
drawCallsText: formatOptionalCount(drawCalls),
|
|
945
|
+
meshText: formatOptionalCount(renderMeshes),
|
|
946
|
+
triangleText: formatOptionalCount(triangles),
|
|
947
|
+
vertexText: formatOptionalCount(vertices),
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function formatStaticShadowBakePhase(phase, language) {
|
|
951
|
+
if (language !== 'zh')
|
|
952
|
+
return phase;
|
|
953
|
+
switch (phase) {
|
|
954
|
+
case 'collect': return '收集';
|
|
955
|
+
case 'reuse': return '复用已有分块';
|
|
956
|
+
case 'chunk': return '烘焙分块';
|
|
957
|
+
case 'sdf': return '生成 SDF';
|
|
958
|
+
case 'pack': return '打包 Atlas';
|
|
959
|
+
case 'encode': return '编码 Atlas';
|
|
960
|
+
case 'complete': return '写入结果';
|
|
961
|
+
default: return phase;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
function formatOptionalCount(value) {
|
|
965
|
+
if (value == null || !Number.isFinite(value))
|
|
966
|
+
return null;
|
|
967
|
+
return String(Math.max(0, Math.trunc(value)));
|
|
968
|
+
}
|
|
969
|
+
function formatOptionalNumber(value) {
|
|
970
|
+
if (value == null || !Number.isFinite(value))
|
|
971
|
+
return null;
|
|
972
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(2).replace(/\.?0+$/, '');
|
|
973
|
+
}
|
|
974
|
+
function formatPixelCount(value) {
|
|
975
|
+
if (value == null || !Number.isFinite(value))
|
|
976
|
+
return null;
|
|
977
|
+
const pixels = Math.max(0, value);
|
|
978
|
+
if (pixels >= 1000000)
|
|
979
|
+
return `${formatOptionalNumber(pixels / 1000000)} MP`;
|
|
980
|
+
if (pixels >= 1000)
|
|
981
|
+
return `${formatOptionalNumber(pixels / 1000)} KP`;
|
|
982
|
+
return formatOptionalCount(pixels);
|
|
983
|
+
}
|
|
984
|
+
function formatPercentage(value) {
|
|
985
|
+
if (value == null || !Number.isFinite(value))
|
|
986
|
+
return null;
|
|
987
|
+
return `${formatOptionalNumber(Math.max(0, Math.min(1, value)) * 100)}%`;
|
|
988
|
+
}
|
|
989
|
+
function formatBytes(value) {
|
|
990
|
+
if (value == null || !Number.isFinite(value))
|
|
991
|
+
return null;
|
|
992
|
+
const bytes = Math.max(0, value);
|
|
993
|
+
if (bytes >= 1024 * 1024 * 1024)
|
|
994
|
+
return `${formatOptionalNumber(bytes / (1024 * 1024 * 1024))} GiB`;
|
|
995
|
+
if (bytes >= 1024 * 1024)
|
|
996
|
+
return `${formatOptionalNumber(bytes / (1024 * 1024))} MiB`;
|
|
997
|
+
if (bytes >= 1024)
|
|
998
|
+
return `${formatOptionalNumber(bytes / 1024)} KiB`;
|
|
999
|
+
return `${formatOptionalCount(bytes)} B`;
|
|
1000
|
+
}
|
|
1001
|
+
function formatMeters(value) {
|
|
1002
|
+
const text = Number.isInteger(value) ? String(value) : value.toFixed(2).replace(/\.?0+$/, '');
|
|
1003
|
+
return `${text} m`;
|
|
1004
|
+
}
|
|
1005
|
+
function formatDurationMs(value, language) {
|
|
1006
|
+
if (value == null || !Number.isFinite(value))
|
|
1007
|
+
return null;
|
|
1008
|
+
const duration = Math.max(0, value);
|
|
1009
|
+
if (duration < 1000)
|
|
1010
|
+
return `${Math.round(duration)} ms`;
|
|
1011
|
+
const seconds = duration / 1000;
|
|
1012
|
+
const text = seconds < 10 ? seconds.toFixed(1) : String(Math.round(seconds));
|
|
1013
|
+
return language === 'zh' ? `${text} 秒` : `${text}s`;
|
|
1014
|
+
}
|
|
1015
|
+
function createRenderingGroupsSection(slots) {
|
|
1016
|
+
return {
|
|
1017
|
+
id: 'rendering-groups',
|
|
1018
|
+
title: 'Rendering Groups / Order Presets',
|
|
1019
|
+
summary: 'Named Babylon rendering groups and alphaIndex presets used by object Inspector dropdowns.',
|
|
1020
|
+
layout: 'list',
|
|
1021
|
+
systems: slots.map((slot) => ({
|
|
1022
|
+
id: `rendering-group-${slot.renderingGroupId}`,
|
|
1023
|
+
label: slot.name,
|
|
1024
|
+
kind: 'rendering-group',
|
|
1025
|
+
active: true,
|
|
1026
|
+
summary: `Babylon group ${slot.renderingGroupId}`,
|
|
1027
|
+
actions: [{
|
|
1028
|
+
id: 'rendering-alpha-preset.add',
|
|
1029
|
+
label: 'Add Order Preset',
|
|
1030
|
+
icon: 'plus',
|
|
1031
|
+
tooltip: 'Add a named alphaIndex preset for this rendering group.',
|
|
1032
|
+
params: { renderingGroupId: slot.renderingGroupId },
|
|
1033
|
+
}],
|
|
1034
|
+
properties: [
|
|
1035
|
+
createReadonlyRenderingProperty(`renderingGroups.slots.${slot.renderingGroupId}.renderingGroupId`, 'Group ID', slot.renderingGroupId),
|
|
1036
|
+
{
|
|
1037
|
+
path: `renderingGroups.slots.${slot.renderingGroupId}.name`,
|
|
1038
|
+
label: 'Group Name',
|
|
1039
|
+
valueType: 'string',
|
|
1040
|
+
control: 'string',
|
|
1041
|
+
value: slot.name,
|
|
1042
|
+
tooltip: 'Display name for this fixed Babylon rendering group id.',
|
|
1043
|
+
commitMode: 'blur',
|
|
1044
|
+
},
|
|
1045
|
+
...slot.alphaIndexPresets.flatMap((preset, index) => [
|
|
1046
|
+
{
|
|
1047
|
+
path: `renderingGroups.slots.${slot.renderingGroupId}.alphaIndexPresets.${index}.name`,
|
|
1048
|
+
label: `Preset ${index + 1} Name`,
|
|
1049
|
+
valueType: 'string',
|
|
1050
|
+
control: 'string',
|
|
1051
|
+
value: preset.name,
|
|
1052
|
+
tooltip: 'User-facing name shown in object Inspector dropdowns.',
|
|
1053
|
+
commitMode: 'blur',
|
|
1054
|
+
actions: [{
|
|
1055
|
+
id: 'rendering-alpha-preset.delete',
|
|
1056
|
+
label: 'Delete',
|
|
1057
|
+
icon: 'trash',
|
|
1058
|
+
tooltip: 'Delete this alphaIndex preset. Existing objects keep their numeric alphaIndex.',
|
|
1059
|
+
params: { renderingGroupId: slot.renderingGroupId, presetIndex: index },
|
|
1060
|
+
}],
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
path: `renderingGroups.slots.${slot.renderingGroupId}.alphaIndexPresets.${index}.alphaIndex`,
|
|
1064
|
+
label: `Preset ${index + 1} Value`,
|
|
1065
|
+
valueType: 'number',
|
|
1066
|
+
control: 'number',
|
|
1067
|
+
value: preset.alphaIndex,
|
|
1068
|
+
step: 1,
|
|
1069
|
+
tooltip: 'Babylon alphaIndex value stored on objects that use this preset.',
|
|
1070
|
+
commitMode: 'blur',
|
|
1071
|
+
},
|
|
1072
|
+
]),
|
|
1073
|
+
],
|
|
1074
|
+
})),
|
|
1075
|
+
};
|
|
613
1076
|
}
|
|
614
1077
|
function createReadonlyRenderingProperty(path, label, value) {
|
|
615
1078
|
return {
|
|
@@ -668,15 +1131,15 @@ function createEnvironmentTexturePickerControlOptions(input) {
|
|
|
668
1131
|
function createShadowDefaultModeOptions(language) {
|
|
669
1132
|
return language === 'zh'
|
|
670
1133
|
? [
|
|
671
|
-
{ label: '静态形状阴影', value: 'static' },
|
|
672
|
-
{ label: 'Blob 阴影', value: 'blob' },
|
|
673
1134
|
{ label: '无阴影', value: 'none' },
|
|
1135
|
+
{ label: 'Blob 阴影', value: 'blob' },
|
|
1136
|
+
{ label: '静态烘焙阴影', value: 'static' },
|
|
674
1137
|
{ label: '主平面阴影', value: 'planar' },
|
|
675
1138
|
]
|
|
676
1139
|
: [
|
|
677
|
-
{ label: 'Static Shape', value: 'static' },
|
|
678
|
-
{ label: 'Blob', value: 'blob' },
|
|
679
1140
|
{ label: 'None', value: 'none' },
|
|
1141
|
+
{ label: 'Blob', value: 'blob' },
|
|
1142
|
+
{ label: 'Static Baked', value: 'static' },
|
|
680
1143
|
{ label: 'Planar', value: 'planar' },
|
|
681
1144
|
];
|
|
682
1145
|
}
|
|
@@ -708,7 +1171,15 @@ const RENDERING_PANEL_TEXT = {
|
|
|
708
1171
|
revert: 'Revert',
|
|
709
1172
|
revertDirty: 'Revert rendering settings to the last saved rendering settings.',
|
|
710
1173
|
revertClean: 'Rendering settings already match the last saved rendering settings.',
|
|
1174
|
+
bakeStatic: 'Bake Static Shadows',
|
|
1175
|
+
bakeStaticReady: 'Bake static shadow chunks for objects authored as Static Baked Shadow.',
|
|
1176
|
+
bakeStaticDisabled: 'Enable Static Baked Shadow before baking.',
|
|
1177
|
+
bakeStaticRunning: 'Static shadow bake is already running.',
|
|
711
1178
|
sections: {
|
|
1179
|
+
'rendering-groups': {
|
|
1180
|
+
title: 'Rendering Groups / Order Presets',
|
|
1181
|
+
summary: 'Named Babylon rendering groups and alphaIndex presets used by object Inspector dropdowns.',
|
|
1182
|
+
},
|
|
712
1183
|
environment: {
|
|
713
1184
|
title: 'Environment / IBL',
|
|
714
1185
|
summary: 'World environment texture and reflection lighting shared by editor preview and runtime.',
|
|
@@ -722,6 +1193,24 @@ const RENDERING_PANEL_TEXT = {
|
|
|
722
1193
|
summary: 'Global shadow systems for editor preview and runtime.',
|
|
723
1194
|
},
|
|
724
1195
|
},
|
|
1196
|
+
groups: {
|
|
1197
|
+
'shadow-group-moving-object': {
|
|
1198
|
+
label: 'Moving Object Shadows',
|
|
1199
|
+
summary: 'Blob: lightweight for moving objects and project-default fallback.',
|
|
1200
|
+
},
|
|
1201
|
+
'shadow-group-static-scene': {
|
|
1202
|
+
label: 'Static Scene Shadows',
|
|
1203
|
+
summary: 'Consumes baked artifacts; update during authoring/build, runtime only displays results.',
|
|
1204
|
+
},
|
|
1205
|
+
'shadow-group-directional-planar': {
|
|
1206
|
+
label: 'Directional Planar Shadows',
|
|
1207
|
+
summary: 'Real-time planar projection following the directional light.',
|
|
1208
|
+
},
|
|
1209
|
+
'shadow-group-compatibility': {
|
|
1210
|
+
label: 'Compatibility Shadows',
|
|
1211
|
+
summary: 'Legacy ShadowGenerator / CSM read-only compatibility paths.',
|
|
1212
|
+
},
|
|
1213
|
+
},
|
|
725
1214
|
systems: {
|
|
726
1215
|
'environment-global': {
|
|
727
1216
|
label: 'Environment Texture',
|
|
@@ -739,7 +1228,7 @@ const RENDERING_PANEL_TEXT = {
|
|
|
739
1228
|
summary: 'Default object shadow',
|
|
740
1229
|
},
|
|
741
1230
|
'static-projected-shadow': {
|
|
742
|
-
label: 'Static
|
|
1231
|
+
label: 'Static Baked Shadow',
|
|
743
1232
|
summary: 'Baked object shape',
|
|
744
1233
|
},
|
|
745
1234
|
'legacy-shadow': {
|
|
@@ -827,8 +1316,8 @@ const RENDERING_PANEL_TEXT = {
|
|
|
827
1316
|
tooltip: 'Vertical offset above the static shadow plane to reduce z-fighting.',
|
|
828
1317
|
},
|
|
829
1318
|
'shadows.staticProjected.bake.resolution': {
|
|
830
|
-
label: 'Resolution',
|
|
831
|
-
tooltip: '
|
|
1319
|
+
label: 'Legacy Resolution',
|
|
1320
|
+
tooltip: 'Legacy v1 mask resolution. v2 SDF atlas bake uses Texels per Meter and Atlas Size.',
|
|
832
1321
|
},
|
|
833
1322
|
'shadows.staticProjected.bake.padding': {
|
|
834
1323
|
label: 'Padding',
|
|
@@ -839,8 +1328,32 @@ const RENDERING_PANEL_TEXT = {
|
|
|
839
1328
|
tooltip: 'Reserved blur radius for static shadow bake softness.',
|
|
840
1329
|
},
|
|
841
1330
|
'shadows.staticProjected.bake.maxSize': {
|
|
842
|
-
label: 'Max Size',
|
|
843
|
-
tooltip: '
|
|
1331
|
+
label: 'Legacy Max Size',
|
|
1332
|
+
tooltip: 'Legacy alias for Spatial Chunk Size.',
|
|
1333
|
+
},
|
|
1334
|
+
'shadows.staticProjected.bake.texelsPerMeter': {
|
|
1335
|
+
label: 'Texels per Meter',
|
|
1336
|
+
tooltip: 'Target SDF atlas texel density for baked static shadows.',
|
|
1337
|
+
},
|
|
1338
|
+
'shadows.staticProjected.bake.atlasSize': {
|
|
1339
|
+
label: 'Atlas Size',
|
|
1340
|
+
tooltip: 'Maximum width and height for each static shadow atlas page.',
|
|
1341
|
+
},
|
|
1342
|
+
'shadows.staticProjected.bake.maxAtlasPages': {
|
|
1343
|
+
label: 'Page Budget',
|
|
1344
|
+
tooltip: 'Maximum atlas pages before bake lowers the effective texel density.',
|
|
1345
|
+
},
|
|
1346
|
+
'shadows.staticProjected.bake.sdfRadiusPx': {
|
|
1347
|
+
label: 'SDF Radius',
|
|
1348
|
+
tooltip: 'Signed-distance radius in pixels used for crisp controllable edges.',
|
|
1349
|
+
},
|
|
1350
|
+
'shadows.staticProjected.bake.spatialChunkSize': {
|
|
1351
|
+
label: 'Spatial Chunk Size',
|
|
1352
|
+
tooltip: 'World size of each spatial bake chunk before atlas packing.',
|
|
1353
|
+
},
|
|
1354
|
+
'shadows.staticProjected.bake.targetChunkCount': {
|
|
1355
|
+
label: 'Target Chunks',
|
|
1356
|
+
tooltip: 'Soft chunk-count budget. Large scenes automatically enlarge spatial chunks to stay near this target.',
|
|
844
1357
|
},
|
|
845
1358
|
},
|
|
846
1359
|
},
|
|
@@ -851,7 +1364,15 @@ const RENDERING_PANEL_TEXT = {
|
|
|
851
1364
|
revert: '还原',
|
|
852
1365
|
revertDirty: '还原到上一次保存的渲染设置。',
|
|
853
1366
|
revertClean: '当前渲染设置已经和上一次保存状态一致。',
|
|
1367
|
+
bakeStatic: '烘焙静态阴影',
|
|
1368
|
+
bakeStaticReady: '为标记为静态烘焙阴影的物体生成分块阴影。',
|
|
1369
|
+
bakeStaticDisabled: '请先启用静态烘焙阴影。',
|
|
1370
|
+
bakeStaticRunning: '静态阴影正在烘焙中。',
|
|
854
1371
|
sections: {
|
|
1372
|
+
'rendering-groups': {
|
|
1373
|
+
title: '渲染分组 / 顺序预设',
|
|
1374
|
+
summary: '项目级 Babylon rendering group 名称和 alphaIndex 预设,用于物体 Inspector 下拉选择。',
|
|
1375
|
+
},
|
|
855
1376
|
environment: {
|
|
856
1377
|
title: '环境 / IBL',
|
|
857
1378
|
summary: '世界环境贴图与 PBR 环境反射,编辑器预览和运行时共用。',
|
|
@@ -865,6 +1386,24 @@ const RENDERING_PANEL_TEXT = {
|
|
|
865
1386
|
summary: '项目级阴影系统,编辑器预览和运行时共用。',
|
|
866
1387
|
},
|
|
867
1388
|
},
|
|
1389
|
+
groups: {
|
|
1390
|
+
'shadow-group-moving-object': {
|
|
1391
|
+
label: '移动物体阴影',
|
|
1392
|
+
summary: 'Blob:低成本,适合移动物体,也可作为项目默认阴影。',
|
|
1393
|
+
},
|
|
1394
|
+
'shadow-group-static-scene': {
|
|
1395
|
+
label: '静态场景阴影',
|
|
1396
|
+
summary: '只显示已烘焙 artifact;编辑器/构建期更新,运行时消费结果。',
|
|
1397
|
+
},
|
|
1398
|
+
'shadow-group-directional-planar': {
|
|
1399
|
+
label: '主平面实时阴影',
|
|
1400
|
+
summary: '跟随直射光动态投影,适合需要方向感的物体。',
|
|
1401
|
+
},
|
|
1402
|
+
'shadow-group-compatibility': {
|
|
1403
|
+
label: '兼容阴影',
|
|
1404
|
+
summary: '旧 ShadowGenerator / CSM 只读兼容路径。',
|
|
1405
|
+
},
|
|
1406
|
+
},
|
|
868
1407
|
systems: {
|
|
869
1408
|
'environment-global': {
|
|
870
1409
|
label: '环境贴图',
|
|
@@ -882,7 +1421,7 @@ const RENDERING_PANEL_TEXT = {
|
|
|
882
1421
|
summary: '默认物体阴影',
|
|
883
1422
|
},
|
|
884
1423
|
'static-projected-shadow': {
|
|
885
|
-
label: '
|
|
1424
|
+
label: '静态烘焙阴影',
|
|
886
1425
|
summary: '烘焙物体轮廓',
|
|
887
1426
|
},
|
|
888
1427
|
'legacy-shadow': {
|
|
@@ -1004,27 +1543,27 @@ const RENDERING_PANEL_TEXT = {
|
|
|
1004
1543
|
},
|
|
1005
1544
|
'shadows.staticProjected.enabled': {
|
|
1006
1545
|
label: '启用',
|
|
1007
|
-
tooltip: '
|
|
1546
|
+
tooltip: '启用共用的静态烘焙阴影系统。',
|
|
1008
1547
|
},
|
|
1009
1548
|
'shadows.staticProjected.appearance.color': {
|
|
1010
1549
|
label: '颜色',
|
|
1011
|
-
tooltip: '
|
|
1550
|
+
tooltip: '静态烘焙阴影颜色。透明度单独编辑。',
|
|
1012
1551
|
},
|
|
1013
1552
|
'shadows.staticProjected.appearance.color.a': {
|
|
1014
1553
|
label: '不透明度',
|
|
1015
|
-
tooltip: '
|
|
1554
|
+
tooltip: '静态烘焙阴影不透明度,范围 0 到 1。',
|
|
1016
1555
|
},
|
|
1017
1556
|
'shadows.staticProjected.plane.height': {
|
|
1018
1557
|
label: '高度',
|
|
1019
|
-
tooltip: '
|
|
1558
|
+
tooltip: '静态烘焙阴影所在的地面高度。',
|
|
1020
1559
|
},
|
|
1021
1560
|
'shadows.staticProjected.plane.yOffset': {
|
|
1022
1561
|
label: 'Y 偏移',
|
|
1023
|
-
tooltip: '
|
|
1562
|
+
tooltip: '静态烘焙阴影相对地面的垂直偏移,用于避免 z-fighting。',
|
|
1024
1563
|
},
|
|
1025
1564
|
'shadows.staticProjected.bake.resolution': {
|
|
1026
|
-
label: '
|
|
1027
|
-
tooltip: '
|
|
1565
|
+
label: '旧版贴图尺寸',
|
|
1566
|
+
tooltip: '旧版 v1 mask 分辨率。v2 SDF atlas 烘焙使用每米像素和 Atlas 尺寸。',
|
|
1028
1567
|
},
|
|
1029
1568
|
'shadows.staticProjected.bake.padding': {
|
|
1030
1569
|
label: '留白',
|
|
@@ -1035,8 +1574,32 @@ const RENDERING_PANEL_TEXT = {
|
|
|
1035
1574
|
tooltip: '静态阴影烘焙柔化预留半径。',
|
|
1036
1575
|
},
|
|
1037
1576
|
'shadows.staticProjected.bake.maxSize': {
|
|
1038
|
-
label: '
|
|
1039
|
-
tooltip: '
|
|
1577
|
+
label: '旧版最大尺寸',
|
|
1578
|
+
tooltip: '旧版字段,作为空间分块尺寸的兼容别名。',
|
|
1579
|
+
},
|
|
1580
|
+
'shadows.staticProjected.bake.texelsPerMeter': {
|
|
1581
|
+
label: '每米像素',
|
|
1582
|
+
tooltip: '静态阴影 SDF atlas 的目标像素密度。',
|
|
1583
|
+
},
|
|
1584
|
+
'shadows.staticProjected.bake.atlasSize': {
|
|
1585
|
+
label: 'Atlas 尺寸',
|
|
1586
|
+
tooltip: '每张静态阴影 atlas 页的最大宽高。',
|
|
1587
|
+
},
|
|
1588
|
+
'shadows.staticProjected.bake.maxAtlasPages': {
|
|
1589
|
+
label: '页预算',
|
|
1590
|
+
tooltip: '超过该 atlas 页数时,烘焙会降低实际每米像素以保护运行时成本。',
|
|
1591
|
+
},
|
|
1592
|
+
'shadows.staticProjected.bake.sdfRadiusPx': {
|
|
1593
|
+
label: 'SDF 半径',
|
|
1594
|
+
tooltip: '用于重建清晰可控边缘的有符号距离半径,单位像素。',
|
|
1595
|
+
},
|
|
1596
|
+
'shadows.staticProjected.bake.spatialChunkSize': {
|
|
1597
|
+
label: '空间分块尺寸',
|
|
1598
|
+
tooltip: '进入 atlas packing 前,每个空间烘焙分块覆盖的世界尺寸。',
|
|
1599
|
+
},
|
|
1600
|
+
'shadows.staticProjected.bake.targetChunkCount': {
|
|
1601
|
+
label: '目标分块数',
|
|
1602
|
+
tooltip: '分块数量软预算。大场景会自动放大空间分块,尽量接近该数量。',
|
|
1040
1603
|
},
|
|
1041
1604
|
'shadows.planar.enabled': {
|
|
1042
1605
|
label: '启用',
|
|
@@ -1124,10 +1687,7 @@ function localizeRenderingPanelState(panel, language, dirty) {
|
|
|
1124
1687
|
if (panel.status === RENDERING_PANEL_TEXT.en.dirtyStatus)
|
|
1125
1688
|
panel.status = text.dirtyStatus;
|
|
1126
1689
|
for (const action of panel.actions ?? []) {
|
|
1127
|
-
|
|
1128
|
-
continue;
|
|
1129
|
-
action.label = text.revert;
|
|
1130
|
-
action.tooltip = dirty ? text.revertDirty : text.revertClean;
|
|
1690
|
+
localizeRenderingAction(action, text, dirty);
|
|
1131
1691
|
}
|
|
1132
1692
|
for (const section of panel.sections) {
|
|
1133
1693
|
const sectionText = text.sections[section.id];
|
|
@@ -1137,10 +1697,18 @@ function localizeRenderingPanelState(panel, language, dirty) {
|
|
|
1137
1697
|
section.summary = sectionText.summary;
|
|
1138
1698
|
for (const system of section.systems) {
|
|
1139
1699
|
const systemText = text.systems[system.id];
|
|
1700
|
+
if (system.group) {
|
|
1701
|
+
const groupText = text.groups[system.group.id];
|
|
1702
|
+
if (groupText?.label)
|
|
1703
|
+
system.group.label = groupText.label;
|
|
1704
|
+
if (groupText?.summary)
|
|
1705
|
+
system.group.summary = groupText.summary;
|
|
1706
|
+
}
|
|
1140
1707
|
if (systemText?.label)
|
|
1141
1708
|
system.label = systemText.label;
|
|
1142
|
-
if (systemText?.summary)
|
|
1709
|
+
if (systemText?.summary && !(system.id === 'static-projected-shadow' && system.status)) {
|
|
1143
1710
|
system.summary = systemText.summary;
|
|
1711
|
+
}
|
|
1144
1712
|
if (language === 'zh' && system.id === 'environment-global' && system.summary === 'No IBL texture') {
|
|
1145
1713
|
system.summary = '未设置 IBL 贴图';
|
|
1146
1714
|
}
|
|
@@ -1148,12 +1716,28 @@ function localizeRenderingPanelState(panel, language, dirty) {
|
|
|
1148
1716
|
system.summary = systemText.disabled;
|
|
1149
1717
|
if (systemText?.compatibility && system.summary === RENDERING_PANEL_TEXT.en.systems[system.id]?.compatibility)
|
|
1150
1718
|
system.summary = systemText.compatibility;
|
|
1719
|
+
for (const action of system.actions ?? [])
|
|
1720
|
+
localizeRenderingAction(action, text, dirty);
|
|
1151
1721
|
for (const property of system.properties)
|
|
1152
1722
|
localizeRenderingProperty(property, text);
|
|
1153
1723
|
}
|
|
1154
1724
|
}
|
|
1155
1725
|
return panel;
|
|
1156
1726
|
}
|
|
1727
|
+
function localizeRenderingAction(action, text, dirty) {
|
|
1728
|
+
if (action.id === 'revert-rendering') {
|
|
1729
|
+
action.label = text.revert;
|
|
1730
|
+
action.tooltip = dirty ? text.revertDirty : text.revertClean;
|
|
1731
|
+
}
|
|
1732
|
+
if (action.id === 'bake-static-shadows') {
|
|
1733
|
+
action.label = text.bakeStatic;
|
|
1734
|
+
action.tooltip = action.disabled
|
|
1735
|
+
? action.tooltip === RENDERING_PANEL_TEXT.en.bakeStaticRunning
|
|
1736
|
+
? text.bakeStaticRunning
|
|
1737
|
+
: text.bakeStaticDisabled
|
|
1738
|
+
: text.bakeStaticReady;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1157
1741
|
function localizeRenderingProperty(property, text) {
|
|
1158
1742
|
const propertyText = text.properties[property.path];
|
|
1159
1743
|
if (!propertyText)
|