auto-git:
[add] src/geometry/model-instance-collider-generation.ts [add] src/runtime-three/rapier-collision-world.ts [change] AGENTS.md [change] CHAT_CONTEXT.md [change] architecture.md [change] package.json [change] prompts-lite.txt [change] prompts.txt [change] roadmap.md [change] src/assets/model-instances.ts [change] src/document/migrate-scene-document.ts [change] src/document/scene-document-validation.ts [change] src/document/scene-document.ts [change] src/runtime-three/first-person-navigation-controller.ts [change] src/runtime-three/navigation-controller.ts [change] src/runtime-three/runtime-host.ts [change] src/runtime-three/runtime-scene-build.ts [change] src/runtime-three/runtime-scene-validation.ts [change] src/viewport-three/viewport-host.ts [change] testing.md
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import type { LoadedModelAsset } from "../assets/gltf-model-import";
|
||||
import { getModelInstances } from "../assets/model-instances";
|
||||
import type { SceneDocument } from "../document/scene-document";
|
||||
import {
|
||||
assertSceneDocumentIsValid,
|
||||
@@ -6,6 +8,7 @@ import {
|
||||
type SceneDiagnostic
|
||||
} from "../document/scene-document-validation";
|
||||
import { getPrimaryPlayerStartEntity } from "../entities/entity-instances";
|
||||
import { buildGeneratedModelCollider, ModelColliderGenerationError } from "../geometry/model-instance-collider-generation";
|
||||
|
||||
export interface RuntimeSceneBuildValidationResult {
|
||||
diagnostics: SceneDiagnostic[];
|
||||
@@ -13,13 +16,18 @@ export interface RuntimeSceneBuildValidationResult {
|
||||
warnings: SceneDiagnostic[];
|
||||
}
|
||||
|
||||
interface ValidateRuntimeSceneBuildOptions {
|
||||
navigationMode: "firstPerson" | "orbitVisitor";
|
||||
loadedModelAssets?: Record<string, LoadedModelAsset>;
|
||||
}
|
||||
|
||||
export function validateRuntimeSceneBuild(
|
||||
document: SceneDocument,
|
||||
navigationMode: "firstPerson" | "orbitVisitor"
|
||||
options: ValidateRuntimeSceneBuildOptions
|
||||
): RuntimeSceneBuildValidationResult {
|
||||
const diagnostics: SceneDiagnostic[] = [];
|
||||
|
||||
if (navigationMode === "firstPerson" && getPrimaryPlayerStartEntity(document.entities) === null) {
|
||||
if (options.navigationMode === "firstPerson" && getPrimaryPlayerStartEntity(document.entities) === null) {
|
||||
diagnostics.push(
|
||||
createDiagnostic(
|
||||
"error",
|
||||
@@ -31,6 +39,39 @@ export function validateRuntimeSceneBuild(
|
||||
);
|
||||
}
|
||||
|
||||
for (const modelInstance of getModelInstances(document.modelInstances)) {
|
||||
const path = `modelInstances.${modelInstance.id}.collision.mode`;
|
||||
const asset = document.assets[modelInstance.assetId];
|
||||
|
||||
if (modelInstance.collision.mode === "none" || asset === undefined || asset.kind !== "model") {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const generatedCollider = buildGeneratedModelCollider(modelInstance, asset, options.loadedModelAssets?.[modelInstance.assetId]);
|
||||
|
||||
if (generatedCollider?.mode === "dynamic") {
|
||||
diagnostics.push(
|
||||
createDiagnostic(
|
||||
"warning",
|
||||
"dynamic-model-collider-fixed-query-only",
|
||||
"Dynamic model collision currently generates convex compound pieces for Rapier queries, but the runner still uses them as fixed world collision rather than fully simulated rigid bodies.",
|
||||
path,
|
||||
"build"
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Imported model collision generation failed.";
|
||||
const code =
|
||||
error instanceof ModelColliderGenerationError
|
||||
? error.code
|
||||
: "invalid-model-instance-collision-mode";
|
||||
|
||||
diagnostics.push(createDiagnostic("error", code, message, path, "build"));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
diagnostics,
|
||||
errors: diagnostics.filter((diagnostic) => diagnostic.severity === "error"),
|
||||
@@ -38,10 +79,10 @@ export function validateRuntimeSceneBuild(
|
||||
};
|
||||
}
|
||||
|
||||
export function assertRuntimeSceneBuildable(document: SceneDocument, navigationMode: "firstPerson" | "orbitVisitor") {
|
||||
export function assertRuntimeSceneBuildable(document: SceneDocument, options: ValidateRuntimeSceneBuildOptions) {
|
||||
assertSceneDocumentIsValid(document);
|
||||
|
||||
const validation = validateRuntimeSceneBuild(document, navigationMode);
|
||||
const validation = validateRuntimeSceneBuild(document, options);
|
||||
|
||||
if (validation.errors.length > 0) {
|
||||
throw new Error(`Runtime build is blocked: ${formatSceneDiagnosticSummary(validation.errors)}`);
|
||||
|
||||
Reference in New Issue
Block a user