Files
webeditor3d/src/document/world-settings.js

236 lines
9.3 KiB
JavaScript
Raw Normal View History

auto-git: [add] playwright.config.js [add] src/app/App.js [add] src/app/editor-store.js [add] src/app/use-editor-store.js [add] src/assets/audio-assets.js [add] src/assets/gltf-model-import.js [add] src/assets/image-assets.js [add] src/assets/model-instance-labels.js [add] src/assets/model-instance-rendering.js [add] src/assets/model-instances.js [add] src/assets/project-asset-storage.js [add] src/assets/project-assets.js [add] src/commands/brush-command-helpers.js [add] src/commands/command-history.js [add] src/commands/command.js [add] src/commands/commit-transform-session-command.js [add] src/commands/create-box-brush-command.js [add] src/commands/delete-box-brush-command.js [add] src/commands/delete-entity-command.js [add] src/commands/delete-interaction-link-command.js [add] src/commands/delete-model-instance-command.js [add] src/commands/import-audio-asset-command.js [add] src/commands/import-background-image-asset-command.js [add] src/commands/import-model-asset-command.js [add] src/commands/move-box-brush-command.js [add] src/commands/resize-box-brush-command.js [add] src/commands/rotate-box-brush-command.js [add] src/commands/set-box-brush-face-material-command.js [add] src/commands/set-box-brush-face-uv-state-command.js [add] src/commands/set-box-brush-name-command.js [add] src/commands/set-box-brush-transform-command.js [add] src/commands/set-entity-name-command.js [add] src/commands/set-model-instance-name-command.js [add] src/commands/set-player-start-command.js [add] src/commands/set-scene-name-command.js [add] src/commands/set-world-settings-command.js [add] src/commands/upsert-entity-command.js [add] src/commands/upsert-interaction-link-command.js [add] src/commands/upsert-model-instance-command.js [add] src/core/ids.js [add] src/core/selection.js [add] src/core/tool-mode.js [add] src/core/transform-session.js [add] src/core/vector.js [add] src/core/whitebox-selection-feedback.js [add] src/core/whitebox-selection-mode.js [add] src/document/brushes.js [add] src/document/migrate-scene-document.js [add] src/document/scene-document-validation.js [add] src/document/scene-document.js [add] src/document/world-settings.js [add] src/entities/entity-instances.js [add] src/entities/entity-labels.js [add] src/geometry/box-brush-components.js [add] src/geometry/box-brush-mesh.js [add] src/geometry/box-brush.js [add] src/geometry/box-face-uvs.js [add] src/geometry/grid-snapping.js [add] src/geometry/model-instance-collider-debug-mesh.js [add] src/geometry/model-instance-collider-generation.js [add] src/interactions/interaction-links.js [add] src/main.js [add] src/materials/starter-material-library.js [add] src/materials/starter-material-textures.js [add] src/rendering/advanced-rendering.js [add] src/runner-web/RunnerCanvas.js [add] src/runtime-three/first-person-navigation-controller.js [add] src/runtime-three/navigation-controller.js [add] src/runtime-three/orbit-visitor-navigation-controller.js [add] src/runtime-three/player-collision.js [add] src/runtime-three/rapier-collision-world.js [add] src/runtime-three/runtime-audio-system.js [add] src/runtime-three/runtime-host.js [add] src/runtime-three/runtime-interaction-system.js [add] src/runtime-three/runtime-scene-build.js [add] src/runtime-three/runtime-scene-validation.js [add] src/serialization/local-draft-storage.js [add] src/serialization/scene-document-json.js [add] src/shared-ui/HierarchicalMenu.js [add] src/shared-ui/Panel.js [add] src/shared-ui/world-background-style.js [add] src/viewport-three/ViewportCanvas.js [add] src/viewport-three/ViewportPanel.js [add] src/viewport-three/viewport-entity-markers.js [add] src/viewport-three/viewport-focus.js [add] src/viewport-three/viewport-host.js [add] src/viewport-three/viewport-layout.js [add] src/viewport-three/viewport-transient-state.js [add] src/viewport-three/viewport-view-modes.js [add] tests/domain/box-brush-face-editing.command.test.js [add] tests/domain/build-runtime-scene.test.js [add] tests/domain/create-box-brush.command.test.js [add] tests/domain/create-empty-scene-document.test.js [add] tests/domain/editor-store.test.js [add] tests/domain/entity.command.test.js [add] tests/domain/interaction-links.validation.test.js [add] tests/domain/model-import.test.js [add] tests/domain/model-instance.command.test.js [add] tests/domain/player-start.command.test.js [add] tests/domain/rapier-collision-world.test.js [add] tests/domain/runtime-audio-system.test.js [add] tests/domain/runtime-interaction-system.test.js [add] tests/domain/runtime-scene-validation.test.js [add] tests/domain/scene-document-validation.test.js [add] tests/domain/transform-session.command.test.js [add] tests/domain/world-settings.command.test.js [add] tests/domain/world-settings.test.js [add] tests/e2e/app-smoke.e2e.js [add] tests/e2e/box-brush-authoring.e2e.js [add] tests/e2e/entities-foundation.e2e.js [add] tests/e2e/face-material-authoring.e2e.js [add] tests/e2e/first-room-workflow.e2e.js [add] tests/e2e/import-draco-model-asset.e2e.js [add] tests/e2e/import-external-model-asset.e2e.js [add] tests/e2e/import-model-asset.e2e.js [add] tests/e2e/local-lights-and-background.e2e.js [add] tests/e2e/orthographic-views.e2e.js [add] tests/e2e/runner-v1.e2e.js [add] tests/e2e/runtime-click-interaction.e2e.js [add] tests/e2e/runtime-trigger-teleport.e2e.js [add] tests/e2e/viewport-quad-layout.e2e.js [add] tests/e2e/viewport-test-helpers.js [add] tests/e2e/whitebox-component-selection.e2e.js [add] tests/e2e/world-environment.e2e.js [add] tests/geometry/box-brush-geometry.test.js [add] tests/geometry/box-face-uvs.test.js [add] tests/geometry/model-instance-collider-generation.test.js [add] tests/helpers/model-collider-fixtures.js [add] tests/serialization/local-draft-storage.test.js [add] tests/serialization/project-asset-storage.test.js [add] tests/serialization/scene-document-json.test.js [add] tests/setup/vitest.setup.js [add] tests/unit/audio-assets.test.js [add] tests/unit/entity-instances.test.js [add] tests/unit/package-scripts.test.js [add] tests/unit/transform-foundation.integration.test.js [add] tests/unit/viewport-canvas.test.js [add] tests/unit/viewport-entity-markers.test.js [add] tests/unit/viewport-focus.test.js [add] tests/unit/viewport-layout.test.js [add] tests/unit/viewport-view-modes.test.js [add] vite.config.js [add] vitest.config.js
2026-04-05 02:25:08 +02:00
import { DEFAULT_SUN_DIRECTION } from "../core/vector";
export const ADVANCED_RENDERING_SHADOW_MAP_SIZES = [512, 1024, 2048, 4096];
export const ADVANCED_RENDERING_SHADOW_TYPES = ["basic", "pcf", "pcfSoft"];
export const ADVANCED_RENDERING_TONE_MAPPING_MODES = ["none", "linear", "reinhard", "cineon", "acesFilmic"];
const DEFAULT_SOLID_BACKGROUND_COLOR = "#2f3947";
const DEFAULT_GRADIENT_TOP_COLOR = DEFAULT_SOLID_BACKGROUND_COLOR;
const DEFAULT_GRADIENT_BOTTOM_COLOR = "#141a22";
const DEFAULT_ADVANCED_RENDERING_SHADOW_MAP_SIZE = 2048;
const DEFAULT_ADVANCED_RENDERING_SHADOW_TYPE = "pcfSoft";
const DEFAULT_ADVANCED_RENDERING_SHADOW_BIAS = -0.0005;
const DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_INTENSITY = 1;
const DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_RADIUS = 0.5;
const DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_SAMPLES = 8;
const DEFAULT_ADVANCED_RENDERING_BLOOM_INTENSITY = 0.75;
const DEFAULT_ADVANCED_RENDERING_BLOOM_THRESHOLD = 0.85;
const DEFAULT_ADVANCED_RENDERING_BLOOM_RADIUS = 0.35;
const DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_MODE = "acesFilmic";
const DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_EXPOSURE = 1;
const DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCUS_DISTANCE = 10;
const DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCAL_LENGTH = 0.03;
const DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_BOKEH_SCALE = 1.5;
export function isAdvancedRenderingShadowMapSize(value) {
return ADVANCED_RENDERING_SHADOW_MAP_SIZES.includes(value);
}
export function isAdvancedRenderingShadowType(value) {
return ADVANCED_RENDERING_SHADOW_TYPES.includes(value);
}
export function isAdvancedRenderingToneMappingMode(value) {
return ADVANCED_RENDERING_TONE_MAPPING_MODES.includes(value);
}
export function createDefaultAdvancedRenderingSettings() {
return {
enabled: false,
shadows: {
enabled: false,
mapSize: DEFAULT_ADVANCED_RENDERING_SHADOW_MAP_SIZE,
type: DEFAULT_ADVANCED_RENDERING_SHADOW_TYPE,
bias: DEFAULT_ADVANCED_RENDERING_SHADOW_BIAS
},
ambientOcclusion: {
enabled: false,
intensity: DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_INTENSITY,
radius: DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_RADIUS,
samples: DEFAULT_ADVANCED_RENDERING_AMBIENT_OCCLUSION_SAMPLES
},
bloom: {
enabled: false,
intensity: DEFAULT_ADVANCED_RENDERING_BLOOM_INTENSITY,
threshold: DEFAULT_ADVANCED_RENDERING_BLOOM_THRESHOLD,
radius: DEFAULT_ADVANCED_RENDERING_BLOOM_RADIUS
},
toneMapping: {
mode: DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_MODE,
exposure: DEFAULT_ADVANCED_RENDERING_TONE_MAPPING_EXPOSURE
},
depthOfField: {
enabled: false,
focusDistance: DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCUS_DISTANCE,
focalLength: DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_FOCAL_LENGTH,
bokehScale: DEFAULT_ADVANCED_RENDERING_DEPTH_OF_FIELD_BOKEH_SCALE
}
};
}
export function createDefaultWorldSettings() {
return {
background: {
mode: "solid",
colorHex: DEFAULT_SOLID_BACKGROUND_COLOR
},
ambientLight: {
colorHex: "#f7f1e8",
intensity: 1
},
sunLight: {
colorHex: "#fff1d5",
intensity: 1.75,
direction: {
...DEFAULT_SUN_DIRECTION
}
},
advancedRendering: createDefaultAdvancedRenderingSettings()
};
}
export function isHexColorString(value) {
return /^#[0-9a-f]{6}$/i.test(value);
}
export function isWorldBackgroundMode(value) {
return value === "solid" || value === "verticalGradient" || value === "image";
}
export function cloneWorldBackgroundSettings(background) {
if (background.mode === "solid") {
return {
mode: "solid",
colorHex: background.colorHex
};
}
if (background.mode === "verticalGradient") {
return {
mode: "verticalGradient",
topColorHex: background.topColorHex,
bottomColorHex: background.bottomColorHex
};
}
return {
mode: "image",
assetId: background.assetId,
environmentIntensity: background.environmentIntensity
};
}
export function cloneWorldSettings(world) {
return {
background: cloneWorldBackgroundSettings(world.background),
ambientLight: {
...world.ambientLight
},
sunLight: {
...world.sunLight,
direction: {
...world.sunLight.direction
}
},
advancedRendering: cloneAdvancedRenderingSettings(world.advancedRendering)
};
}
export function cloneAdvancedRenderingSettings(settings) {
return {
enabled: settings.enabled,
shadows: {
...settings.shadows
},
ambientOcclusion: {
...settings.ambientOcclusion
},
bloom: {
...settings.bloom
},
toneMapping: {
...settings.toneMapping
},
depthOfField: {
...settings.depthOfField
}
};
}
export function areWorldBackgroundSettingsEqual(left, right) {
if (left.mode !== right.mode) {
return false;
}
if (left.mode === "solid" && right.mode === "solid") {
return left.colorHex === right.colorHex;
}
if (left.mode === "verticalGradient" && right.mode === "verticalGradient") {
return left.topColorHex === right.topColorHex && left.bottomColorHex === right.bottomColorHex;
}
return left.mode === "image" && right.mode === "image" && left.assetId === right.assetId && left.environmentIntensity === right.environmentIntensity;
}
export function areWorldSettingsEqual(left, right) {
return (areWorldBackgroundSettingsEqual(left.background, right.background) &&
left.ambientLight.colorHex === right.ambientLight.colorHex &&
left.ambientLight.intensity === right.ambientLight.intensity &&
left.sunLight.colorHex === right.sunLight.colorHex &&
left.sunLight.intensity === right.sunLight.intensity &&
left.sunLight.direction.x === right.sunLight.direction.x &&
left.sunLight.direction.y === right.sunLight.direction.y &&
left.sunLight.direction.z === right.sunLight.direction.z &&
areAdvancedRenderingSettingsEqual(left.advancedRendering, right.advancedRendering));
}
export function areAdvancedRenderingSettingsEqual(left, right) {
return (left.enabled === right.enabled &&
left.shadows.enabled === right.shadows.enabled &&
left.shadows.mapSize === right.shadows.mapSize &&
left.shadows.type === right.shadows.type &&
left.shadows.bias === right.shadows.bias &&
left.ambientOcclusion.enabled === right.ambientOcclusion.enabled &&
left.ambientOcclusion.intensity === right.ambientOcclusion.intensity &&
left.ambientOcclusion.radius === right.ambientOcclusion.radius &&
left.ambientOcclusion.samples === right.ambientOcclusion.samples &&
left.bloom.enabled === right.bloom.enabled &&
left.bloom.intensity === right.bloom.intensity &&
left.bloom.threshold === right.bloom.threshold &&
left.bloom.radius === right.bloom.radius &&
left.toneMapping.mode === right.toneMapping.mode &&
left.toneMapping.exposure === right.toneMapping.exposure &&
left.depthOfField.enabled === right.depthOfField.enabled &&
left.depthOfField.focusDistance === right.depthOfField.focusDistance &&
left.depthOfField.focalLength === right.depthOfField.focalLength &&
left.depthOfField.bokehScale === right.depthOfField.bokehScale);
}
export function changeWorldBackgroundMode(background, mode, imageAssetId) {
if (mode === "image") {
if (imageAssetId === undefined || imageAssetId.trim().length === 0) {
if (background.mode === "image") {
return cloneWorldBackgroundSettings(background);
}
throw new Error("An image asset must be selected to use an image background.");
}
return {
mode: "image",
assetId: imageAssetId,
environmentIntensity: background.mode === "image" ? background.environmentIntensity : 0.5
};
}
if (background.mode === mode) {
return cloneWorldBackgroundSettings(background);
}
if (mode === "solid") {
return {
mode: "solid",
colorHex: background.mode === "solid"
? background.colorHex
: background.mode === "verticalGradient"
? background.topColorHex
: DEFAULT_SOLID_BACKGROUND_COLOR
};
}
if (background.mode === "solid") {
return {
mode: "verticalGradient",
topColorHex: background.colorHex,
bottomColorHex: DEFAULT_GRADIENT_BOTTOM_COLOR
};
}
if (background.mode === "verticalGradient") {
return {
mode: "verticalGradient",
topColorHex: background.topColorHex,
bottomColorHex: background.bottomColorHex
};
}
return {
mode: "verticalGradient",
topColorHex: DEFAULT_GRADIENT_TOP_COLOR,
bottomColorHex: DEFAULT_GRADIENT_BOTTOM_COLOR
};
}