chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { ErrorReport } from "./error";
|
||||
import type { EditorContextEdit, GraphInterpolation } from "./editor-workflow";
|
||||
import type { ProgressEvent } from "./progress";
|
||||
import type { NonMeshCurveSplineType, NonMeshFontCharacterIR, NonMeshFontLinksIR, NonMeshFontPropertiesIR, NonMeshFontTextBoxIR, SceneSnapshotIR } from "./scene-ir";
|
||||
import type { SceneDelta } from "./scene-delta";
|
||||
@@ -18,7 +19,7 @@ import type {
|
||||
PhysicsSimulationPlaybackSettings,
|
||||
PhysicsSoftBodySettings,
|
||||
} from "./physics-simulation";
|
||||
import type { ShaderGraphIR } from "./shader-graph";
|
||||
import type { ShaderGraphIR, ShaderNodeEdit } from "./shader-graph";
|
||||
import type { ShaderCompileReport } from "./shader-compiler";
|
||||
import type { NlaMoveStripCommand, NlaTrackIR } from "./nla";
|
||||
import type { RenderCapabilityRequest } from "./render-capabilities";
|
||||
@@ -89,7 +90,7 @@ export interface MeshGeometryDelta {
|
||||
export type MeshElementMode = "VERT" | "EDGE" | "FACE";
|
||||
export type MeshPrimitive = "CUBE" | "PLANE" | "UV_SPHERE" | "ICO_SPHERE" | "CYLINDER" | "CONE" | "TORUS";
|
||||
export type MeshEditOperation = "MERGE" | "DISSOLVE" | "EXTRUDE" | "INSET" | "BEVEL" | "LOOP_CUT" | "SUBDIVIDE" | "FILL" | "TRIANGULATE" | "RECALCULATE_NORMALS" | "BRIDGE_LOOPS" | "DELETE";
|
||||
export type FCurveInterpolation = "CONSTANT" | "LINEAR" | "BEZIER";
|
||||
export type FCurveInterpolation = GraphInterpolation;
|
||||
export type KeyframeHandle = [number, number];
|
||||
export interface FCurvePoint {
|
||||
frame: number;
|
||||
@@ -112,17 +113,22 @@ export type ArmatureEditOperation =
|
||||
| { operation: "RENAME"; boneName: string; name: string }
|
||||
| { operation: "EXTRUDE"; boneName: string; name: string; tail: [number, number, number] }
|
||||
| { operation: "DUPLICATE"; boneName: string; name: string; offset?: [number, number, number] };
|
||||
export type PoseConstraintType = "COPY_LOCATION" | "COPY_ROTATION" | "COPY_SCALE" | "IK" | "TRACK_TO";
|
||||
export type PoseConstraintType = "COPY_LOCATION" | "COPY_ROTATION" | "COPY_SCALE" | "IK" | "TRACK_TO" |
|
||||
"LIMIT_LOCATION" | "LIMIT_ROTATION" | "LIMIT_SCALE" | "DAMPED_TRACK" | "ACTION" | "CHILD_OF" |
|
||||
"COPY_TRANSFORMS" | "LIMIT_DISTANCE" | "FOLLOW_PATH" | "LOCK_TRACK" | "STRETCH_TO" | "MINMAX" | "CLAMP_TO" | "TRANSFORM" | "SHRINKWRAP" |
|
||||
"SAME_VOLUME" | "SPLINE_IK" | "PIVOT" | "FOLLOW_TRACK" | "CAMERA_SOLVER" | "OBJECT_SOLVER" |
|
||||
"TRANSFORM_CACHE" | "ARMATURE" | "GEOMETRY_ATTRIBUTE";
|
||||
|
||||
export type WebEngineEditCommand =
|
||||
| { type: "setFrame"; frame: number }
|
||||
| { type: "setObjectVisibility"; objectId: string; visible: boolean }
|
||||
| { type: "setModifierEnabled"; meshId: string; modifierUuid: string; enabled: boolean }
|
||||
| { type: "setModifierVisibility"; meshId: string; modifierUuid: string; showViewport: boolean; showRender: boolean; showEditMode: boolean; showOnCage: boolean }
|
||||
| { type: "addModifier"; meshId: string; modifierType: string; name?: string }
|
||||
| { type: "removeModifier"; meshId: string; modifierUuid: string }
|
||||
| { type: "moveModifier"; meshId: string; modifierUuid: string; direction?: "UP" | "DOWN"; index?: number }
|
||||
| { type: "setModifierParameters"; meshId: string; modifierUuid: string; parameters: Record<string, unknown> }
|
||||
| { type: "setModifierEnabled"; objectId?: string; baseRevision?: number; meshId: string; modifierUuid: string; enabled: boolean }
|
||||
| { type: "setModifierVisibility"; objectId?: string; baseRevision?: number; meshId: string; modifierUuid: string; showViewport: boolean; showRender: boolean; showEditMode: boolean; showOnCage: boolean }
|
||||
| { type: "addModifier"; objectId?: string; baseRevision?: number; meshId: string; modifierType: string; name?: string }
|
||||
| { type: "removeModifier"; objectId?: string; baseRevision?: number; meshId: string; modifierUuid: string }
|
||||
| { type: "moveModifier"; objectId?: string; baseRevision?: number; meshId: string; modifierUuid: string; direction?: "UP" | "DOWN"; index?: number }
|
||||
| { type: "setModifierParameters"; curveGesture?: { id: string; phase: "begin" | "update" | "commit" | "cancel" }; objectId?: string; baseRevision?: number; meshId: string; modifierUuid: string; parameters: Record<string, unknown> }
|
||||
| { type: "renameModifier"; objectId?: string; baseRevision?: number; meshId: string; modifierUuid: string; name: string }
|
||||
| { type: "decimateMesh"; meshId: string; profile: SimplifyProfile }
|
||||
| { type: "previewDecimateMesh"; meshId: string; profile: SimplifyProfile }
|
||||
| { type: "createPrimitive"; primitive: MeshPrimitive; name?: string; location: [number, number, number] }
|
||||
@@ -135,7 +141,9 @@ export type WebEngineEditCommand =
|
||||
| { type: "setBoneRoll"; objectId: string; boneName: string; roll: number }
|
||||
| { type: "setBoneSymmetry"; objectId: string; enabled: boolean }
|
||||
| { type: "setBoneParenting"; objectId: string; boneName: string; parentName: string | null; connected: boolean }
|
||||
| { type: "setPoseConstraint"; objectId: string; boneName: string; constraintName: string; constraintType: PoseConstraintType | null; targetObjectId?: string | null; targetBoneName?: string; influence?: number; enabled?: boolean }
|
||||
| { type: "setPoseConstraint"; baseRevision?: number; objectId: string; boneName: string; constraintName: string; constraintType: PoseConstraintType | null; targetObjectId?: string | null; targetBoneName?: string; influence?: number; enabled?: boolean }
|
||||
| { type: "editConstraint"; baseRevision?: number; objectId: string; constraintName: string; constraintType: PoseConstraintType | null; targetObjectId?: string | null; targetBoneName?: string; influence?: number; enabled?: boolean }
|
||||
| { type: "renameConstraint"; baseRevision?: number; objectId: string; constraintName: string; newName: string; boneName?: string }
|
||||
| { type: "translateMeshVertices"; meshId: string; vertexIndices: number[]; offset: [number, number, number] }
|
||||
| { type: "meshEdit"; meshId: string; operation: MeshEditOperation; selectionMode: MeshElementMode; elementIndices: number[]; offset?: [number, number, number]; amount?: number; segments?: number }
|
||||
| { type: "meshSubdivide"; meshId: string; selectionMode: MeshElementMode; elementIndices: number[]; segments?: number }
|
||||
@@ -155,7 +163,7 @@ export type WebEngineEditCommand =
|
||||
| { type: "setMaterialImageNode"; materialId: string; imageId: string; usage: "BASE_COLOR" | "NORMAL"; uvMap?: string }
|
||||
| { type: "insertObjectKeyframe"; objectId: string; frame: number; property: "LOCATION" | "ROTATION_EULER" | "SCALE"; interpolation?: FCurveInterpolation }
|
||||
| { type: "deleteObjectKeyframe"; objectId: string; frame: number; property?: "LOCATION" | "ROTATION_EULER" | "SCALE" }
|
||||
| { type: "createAction"; name: string; objectId?: string }
|
||||
| { type: "createAction"; name: string; objectId?: string; useFakeUser?: boolean }
|
||||
| { type: "removeAction"; actionId: string }
|
||||
| { type: "setKeyframe"; animationId: string; path: string; frame: number; value?: number[]; handleLeft?: KeyframeHandle; handleRight?: KeyframeHandle; interpolation?: FCurveInterpolation }
|
||||
| { type: "setFCurveKeyframes"; animationId: string; path: string; points: FCurvePoint[] }
|
||||
@@ -166,10 +174,13 @@ export type WebEngineEditCommand =
|
||||
| { type: "setTimelineMarkers"; dataId: string; markers: Array<{ frame: number; name: string }> }
|
||||
| { type: "setFCurveInterpolation"; animationId: string; path: string; interpolation: FCurveInterpolation }
|
||||
| { type: "setActiveAction"; objectId: string; actionId: string | null }
|
||||
| { type: "setConstraint"; objectId: string; constraintName: string; enabled: boolean; influence: number }
|
||||
| { type: "setConstraint"; baseRevision?: number; objectId: string; constraintName: string; enabled: boolean; influence: number }
|
||||
| { type: "moveConstraint"; baseRevision?: number; objectId: string; constraintName: string; direction: "UP" | "DOWN"; boneName?: string }
|
||||
| { type: "setParent"; objectId: string; parentId: string | null; keepTransform?: boolean }
|
||||
| { type: "setParents"; objectIds: string[]; parentId: string | null; keepTransform?: boolean }
|
||||
| { type: "createCollection"; name: string; parentCollectionId?: string | null }
|
||||
| { type: "moveObjectToCollection"; objectId: string; collectionId: string }
|
||||
| { type: "moveObjectToCollection"; objectId: string; collectionId: string; keepExistingLinks?: boolean }
|
||||
| { type: "moveCollection"; collectionId: string; parentCollectionId?: string | null }
|
||||
| { type: "renameId"; id: string; name: string }
|
||||
| { type: "joinObjects"; activeObjectId: string; objectIds: string[] }
|
||||
| { type: "separateMeshFaces"; objectId: string; faceIndices: number[]; name?: string }
|
||||
@@ -192,6 +203,9 @@ export type WebEngineEditCommand =
|
||||
| { type: "importVFont"; schemaVersion: 1; projectId: string; assetId: string; assetPath: string; sourcePath: string; name: string; format: "TTF" | "OTF" | "PFB"; mimeType: string; byteLength: number; sha256: string; base64: string }
|
||||
| { type: "setFontLinks"; dataId: string; links: NonMeshFontLinksIR }
|
||||
| { type: "setTextSource"; dataId: string; source: string }
|
||||
| { type: "createText"; name:string; source:string }
|
||||
| { type: "editEditorContext"; edit: EditorContextEdit; baseRevision: number }
|
||||
| { type: "editShaderNode"; materialId:string; edit:ShaderNodeEdit; baseRevision:number }
|
||||
| { type: "setSoundProperties"; dataId: string; properties: { volume?: number; attenuation?: number; pitch?: number; minGain?: number; maxGain?: number; distance?: number; offsetTime?: number } }
|
||||
| { type: "setSpeakerProperties"; dataId: string; properties: { volumeMax?: number; volumeMin?: number; distanceMax?: number; distanceReference?: number; attenuation?: number; coneAngleOuter?: number; coneAngleInner?: number; coneVolumeOuter?: number; volume?: number; pitch?: number } }
|
||||
| { type: "setParticleSettings"; dataId: string; properties: { type?: number; from?: number; distribution?: number; physicsType?: number; totalParticles?: number; start?: number; end?: number; lifetime?: number; size?: number; drawSize?: number } }
|
||||
@@ -249,8 +263,8 @@ export type WebEngineEditCommand =
|
||||
| { type: "setMaskPoint"; maskId: string; layerId: string; splineId: string; point: MaskPointIR }
|
||||
| { type: "setSceneLineSettings"; dataId: string; properties: { mode?: 1 | 2; thickness?: number } }
|
||||
| { type: "setSceneViewLayerPassSettings"; dataId: string; layerName: string; properties: { passMask?: number; cryptomatteMask?: number; cryptomatteLevels?: number; alphaThreshold?: number } }
|
||||
| { type: "setSceneViewLayerAOVs"; dataId: string; layerName: string; aovs: Array<{ name: string; type: 0 | 1 }> }
|
||||
| { type: "setSceneViewLayerLightgroups"; dataId: string; layerName: string; lightgroups: string[] }
|
||||
| { type: "setSceneViewLayerAOVs"; baseRevision?: number; dataId: string; layerName: string; aovs: Array<{ name: string; type: 0 | 1 }> }
|
||||
| { type: "setSceneViewLayerLightgroups"; baseRevision?: number; dataId: string; layerName: string; lightgroups: string[] }
|
||||
| { type: "clearObjectTransform"; objectId: string; channels: Array<"LOCATION" | "ROTATION" | "SCALE"> }
|
||||
| { type: "createObjectData"; objectType: "CAMERA" | "LIGHT" | "EMPTY" | "ARMATURE"; name?: string }
|
||||
| { type: "setObjectSelection"; objectId: string; selected: boolean; active?: boolean }
|
||||
@@ -269,6 +283,8 @@ export type WebEngineEditCommand =
|
||||
| { type: "setSimulationPlayback"; settings: PhysicsSimulationPlaybackSettings }
|
||||
| { type: "setShaderGraph"; materialId: string; graph: ShaderGraphIR }
|
||||
| { type: "setNLAStack"; objectId: string; tracks: NlaTrackIR[]; baseRevision?: number }
|
||||
| { type: "setNLAProperty"; objectId: string; trackId: string; target: "TRACK"; property: "solo"; value: boolean; baseRevision?: number }
|
||||
| { type: "setNLAProperty"; objectId: string; trackId: string; target: "STRIP"; stripId: string; property: "frameStart" | "frameEnd" | "actionFrameStart" | "actionFrameEnd" | "actionSlotHandle" | "useSyncLength" | "useAnimatedInfluence" | "useAutoBlend" | "scale" | "repeat" | "blendIn" | "blendOut" | "influence" | "blendMode" | "extrapolation" | "muted" | "reverse"; value: number | boolean | string; baseRevision?: number }
|
||||
| NlaMoveStripCommand
|
||||
| { type: "undo" }
|
||||
| { type: "redo" };
|
||||
@@ -281,8 +297,11 @@ export type WebEngineOperatorInvocation = BlenderOperatorInvocation;
|
||||
|
||||
export type RNAPropertyValue = boolean | number | string | null;
|
||||
export interface RNADataBlockDescriptor {
|
||||
/** Stable opaque identity for selecting one ID when libraries share a name. */
|
||||
dataId?: string;
|
||||
type: string;
|
||||
name: string;
|
||||
library?: string | null;
|
||||
libraryLinked: boolean;
|
||||
editable: boolean;
|
||||
}
|
||||
@@ -315,6 +334,15 @@ export type WebEngineJsonCommand =
|
||||
| "applyCommand"
|
||||
| "undo"
|
||||
| "redo"
|
||||
| "history"
|
||||
| "historyJump"
|
||||
| "ndofDecode"
|
||||
| "ndofNavigate"
|
||||
| "viewportCamera"
|
||||
| "viewportFromCamera"
|
||||
| "pythonExec"
|
||||
| "pythonReset"
|
||||
| "timelineFrame"
|
||||
| "listBlenderOperators"
|
||||
| "invokeBlenderOperator"
|
||||
| "listBlenderMacros"
|
||||
@@ -341,10 +369,16 @@ export type WebEngineRequest =
|
||||
| { requestId: string; command: { type: "init" } }
|
||||
| { requestId: string; command: { type: "loadWasmModule"; id: string } }
|
||||
| { requestId: string; command: { type: "crashForTest" } }
|
||||
| { requestId: string; command: { type: "openBlend"; buffer: ArrayBuffer }; }
|
||||
| { requestId: string; command: { type: "openBlend"; buffer: ArrayBuffer; replacements?: Array<{ sourcePath: string; idCode: number; missingName: string; replacementName: string; replacementSourcePath?: string }>; libraries?: Array<{ path: string; buffer: ArrayBuffer }> }; }
|
||||
| { requestId: string; command: { type: "applyServerBlendResult"; buffer: ArrayBuffer; baseRevision: number }; }
|
||||
| { requestId: string; command: { type: "cancelOpen"; targetRequestId: string } }
|
||||
| { requestId: string; command: { type: "openResourceStatus" } }
|
||||
| { requestId: string; command: { type: "snapshot" } }
|
||||
| { requestId: string; command: { type: "editorArchiveUpload"; path: string; buffer: ArrayBuffer } }
|
||||
| { requestId: string; command: { type: "editorResourceDownload"; path: string } }
|
||||
| { requestId: string; command: { type: "editorResourceList"; path: string } }
|
||||
| { requestId: string; command: { type: "editorResourcePrepare"; path: string } }
|
||||
| { requestId: string; command: WebEngineGPUCommand }
|
||||
| { requestId: string; command: { type: "jsonCommand"; cmd: WebEngineJsonCommand; params?: Record<string, unknown> } }
|
||||
| { requestId: string; command: { type: "applyCommand"; payload: WebEngineEditCommand } }
|
||||
| { requestId: string; command: { type: "appendLibraryObject"; request: LibraryMainAppendRequestIR; source: ArrayBuffer } }
|
||||
@@ -400,6 +434,7 @@ export interface WebEngineLODLevelResult {
|
||||
|
||||
export interface WebEngineLODResult {
|
||||
manifest: LODManifest;
|
||||
sourceBlendSha256?: string;
|
||||
levels: WebEngineLODLevelResult[];
|
||||
errors?: WebEngineLODError[];
|
||||
}
|
||||
@@ -410,8 +445,63 @@ export interface WebEngineLODError {
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** Native WM cursor raster; JS only transports/displays these original pixels. */
|
||||
export interface WebEngineGPUCursor {
|
||||
revision: number;
|
||||
visible: boolean;
|
||||
width: number;
|
||||
height: number;
|
||||
hotspotX: number;
|
||||
hotspotY: number;
|
||||
rgba: Uint8Array;
|
||||
}
|
||||
|
||||
export interface WebEngineGPUInput {
|
||||
type: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;
|
||||
x: number;
|
||||
y: number;
|
||||
value: number;
|
||||
key: number;
|
||||
modifiers: number;
|
||||
codepoint?: number;
|
||||
location?: number;
|
||||
/** Absolute pen samples; tilt uses GHOST's normalized [-1, 1] axes. */
|
||||
tablet?: { mode: 1 | 2; pressure: number; tiltX: number; tiltY: number };
|
||||
/** Types 1-3 from Pointer Lock; native GHOST owns continuous coordinates.
|
||||
* Type 11 reports loss of a browser grab and cancels native modal handlers. */
|
||||
relative?: boolean;
|
||||
/** Type 9: relative paths already staged in this desktop's /browser directory. */
|
||||
paths?: string[];
|
||||
/** Type 10: key 0 = wheel ticks, 1 = trackpad pan, 2 = magnify.
|
||||
* Deltas use GHOST directions; trackpad units are backing pixels.
|
||||
* Relative types 1-3 use backing-pixel motion, zero for button transitions. */
|
||||
deltaX?: number;
|
||||
deltaY?: number;
|
||||
}
|
||||
|
||||
export type WebEngineGPUCommand =
|
||||
| { type: "gpuUI"; op: "files"; session: string; action: "list" }
|
||||
| { type: "gpuUI"; op: "files"; session: string; action: "upload"; path: string; buffer: ArrayBuffer }
|
||||
| { type: "gpuUI"; op: "files"; session: string; action: "download"; path: string }
|
||||
| { type: "gpuUI"; op: "capabilities" }
|
||||
| { type: "gpuUI"; op: "attach"; session: string; canvas: OffscreenCanvas; width: number; height: number; pixelRatio: number }
|
||||
// Shared native operation state: 0 idle, 1 cancellable, 2 cancellation requested.
|
||||
| { type: "gpuUI"; op: "frame"; session: string; ownerGeneration: number; width: number; height: number; pixelRatio: number; events: WebEngineGPUInput[]; interrupt?: SharedArrayBuffer; fullscreen?: boolean }
|
||||
| { type: "gpuUI"; op: "invoke"; session: string; ownerGeneration: number; operator: string; properties: Record<string, BlenderOperatorPropertyValue>; areaType: string; mode: string; interrupt?: SharedArrayBuffer }
|
||||
| { type: "gpuUI"; op: "detach"; session: string };
|
||||
|
||||
export interface WebEngineHistory {
|
||||
schemaVersion: 1;
|
||||
revision: number;
|
||||
cursor: number;
|
||||
limit: number;
|
||||
entries: Array<{ index: number; label: string }>;
|
||||
}
|
||||
|
||||
export interface WebEngineResult {
|
||||
status: WebEngineStatus;
|
||||
desktopFiles?: { root: string; entries: Array<{ path: string; size: number }>; path?: string; buffer?: ArrayBuffer };
|
||||
gpuUI?: { surfaceAvailable: boolean; keyboardTextAvailable?: boolean; tabletInputAvailable?: boolean; cursorGrabAvailable?: boolean; normalGrabAvailable?: boolean; cursorGrab?: number; cursor?: WebEngineGPUCursor; nativeUI: false; attached: boolean; modalActive?: boolean; contextLost?: boolean; session?: string; ownerGeneration?: number; inputDiscarded?: boolean; displayAcknowledged?: boolean; exportPath?: string; exportSaveCopy?: boolean; exportSaveAs?: boolean; exportRevision?: number; error?: ErrorReport };
|
||||
snapshot?: SceneSnapshotIR;
|
||||
geometryBuffers?: MeshGeometryBuffer[];
|
||||
nonMeshGeometryBuffers?: NonMeshGeometryChunk[];
|
||||
@@ -423,6 +513,9 @@ export interface WebEngineResult {
|
||||
capabilityGate?: CapabilityGateResult;
|
||||
json?: unknown;
|
||||
shaderCompile?: ShaderCompileReport;
|
||||
commandFeedback?: string;
|
||||
/** False preserves data history/persistence while transient editor context can refresh. */
|
||||
commandChanged?: boolean;
|
||||
depsgraph?: DepsgraphEvaluationIR;
|
||||
blend?: ArrayBuffer;
|
||||
openResources?: WebEngineOpenResourceStatus;
|
||||
@@ -432,7 +525,8 @@ export interface WebEngineResult {
|
||||
}
|
||||
|
||||
export type WebEngineResponse =
|
||||
| { kind: "audioOutput"; port: MessagePort }
|
||||
| { kind: "progress"; requestId: string; progress: ProgressEvent }
|
||||
| { kind: "result"; requestId: string; ok: true; result: WebEngineResult }
|
||||
| { kind: "result"; requestId: string; ok: false; error: ErrorReport };
|
||||
| { kind: "result"; requestId: string; ok: false; error: ErrorReport; mainChanged?: boolean; recovery?: WebEngineResult; history?: WebEngineHistory };
|
||||
import type { CameraSolveIR, MaskPointIR, MaskSplineIR, TrackingMarkerIR } from "./tracking-mask";
|
||||
|
||||
Reference in New Issue
Block a user