feat(web): complete portable Blender feature gaps
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-09-06 19:33:50 +08:00
parent ed347098b4
commit 66d3f4e0f4
48 changed files with 58048 additions and 61 deletions

View File

@@ -139,6 +139,14 @@ export interface ArmatureBoneIR {
connected?: boolean;
restMatrix: number[];
poseMatrix?: number[];
poseConstraints?: Array<{
name: string;
type: "COPY_LOCATION" | "COPY_ROTATION" | "COPY_SCALE" | "IK" | "TRACK_TO" | "UNKNOWN";
targetObjectId?: string | null;
targetBoneName?: string;
influence: number;
enabled: boolean;
}>;
}
export interface ArmatureIR {
@@ -661,6 +669,21 @@ export interface SceneIR {
sequencerStatus?: "AVAILABLE" | "BLOCKED";
}
export interface SceneRNADataBlockIR {
type: string;
name: string;
libraryLinked: boolean;
editable: boolean;
}
export interface SceneRNAPropertyIR {
identifier: string;
type: "BOOLEAN" | "INT" | "FLOAT" | "STRING" | "ENUM";
arrayLength: number;
readonly: boolean;
value?: boolean | number | string | null | Array<boolean | number | string | null>;
}
export interface SceneSnapshotIR {
schemaVersion: 1;
revision: number;
@@ -1375,6 +1398,18 @@ export function parseSceneSnapshotIR(value: unknown): SceneSnapshotIR {
if (bone.connected !== undefined) requireBoolean(bone.connected, `armatures[${index}].bones[${boneIndex}].connected`);
requireTuple(bone.restMatrix, 16, `armatures[${index}].bones[${boneIndex}].restMatrix`);
if (bone.poseMatrix !== undefined) requireTuple(bone.poseMatrix, 16, `armatures[${index}].bones[${boneIndex}].poseMatrix`);
if (bone.poseConstraints !== undefined) {
const constraints = requireArray(bone.poseConstraints, `armatures[${index}].bones[${boneIndex}].poseConstraints`);
for (const [constraintIndex, constraint] of constraints.entries()) {
if (!isRecord(constraint)) throw new Error(`armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}] must be an object`);
requireString(constraint.name, `armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}].name`);
requireString(constraint.type, `armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}].type`);
if (constraint.targetObjectId !== undefined && constraint.targetObjectId !== null) requireString(constraint.targetObjectId, `armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}].targetObjectId`);
if (constraint.targetBoneName !== undefined) requireString(constraint.targetBoneName, `armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}].targetBoneName`);
requireNumber(constraint.influence, `armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}].influence`);
requireBoolean(constraint.enabled, `armatures[${index}].bones[${boneIndex}].poseConstraints[${constraintIndex}].enabled`);
}
}
}
}
for (const [index, image] of (value.images as unknown[]).entries()) {