auto-git:

[change] src/core/transform-session.ts
This commit is contained in:
2026-05-11 13:54:54 +02:00
parent a101249d26
commit c90c51b31f

View File

@@ -175,6 +175,7 @@ export interface EntityTransformTarget {
entityKind: EntityKind; entityKind: EntityKind;
initialPosition: Vec3; initialPosition: Vec3;
initialRotation: EntityTransformRotationState; initialRotation: EntityTransformRotationState;
initialScale: EntityTransformScaleState;
} }
export interface BrushesTransformTarget { export interface BrushesTransformTarget {
@@ -252,6 +253,7 @@ export interface EntityTransformPreview {
kind: "entity"; kind: "entity";
position: Vec3; position: Vec3;
rotation: EntityTransformRotationState; rotation: EntityTransformRotationState;
scale: EntityTransformScaleState;
} }
export interface BrushTransformPreviewItem { export interface BrushTransformPreviewItem {
@@ -285,6 +287,7 @@ export interface EntityTransformPreviewItem {
entityId: string; entityId: string;
position: Vec3; position: Vec3;
rotation: EntityTransformRotationState; rotation: EntityTransformRotationState;
scale: EntityTransformScaleState;
} }
export interface EntitiesTransformPreview { export interface EntitiesTransformPreview {
@@ -381,6 +384,32 @@ function cloneEntityTransformRotationState(
kind: "direction", kind: "direction",
direction: cloneVec3(rotation.direction) direction: cloneVec3(rotation.direction)
}; };
case "euler":
return {
kind: "euler",
rotationDegrees: cloneVec3(rotation.rotationDegrees)
};
}
}
function cloneEntityTransformScaleState(
scale: EntityTransformScaleState
): EntityTransformScaleState {
switch (scale.kind) {
case "none":
return {
kind: "none"
};
case "scale":
return {
kind: "scale",
scale: cloneVec3(scale.scale)
};
case "size":
return {
kind: "size",
size: cloneVec3(scale.size)
};
} }
} }
@@ -413,7 +442,8 @@ function cloneEntityTransformPreviewItem(
return { return {
entityId: preview.entityId, entityId: preview.entityId,
position: cloneVec3(preview.position), position: cloneVec3(preview.position),
rotation: cloneEntityTransformRotationState(preview.rotation) rotation: cloneEntityTransformRotationState(preview.rotation),
scale: cloneEntityTransformScaleState(preview.scale)
}; };
} }
@@ -449,7 +479,8 @@ function areEntityTransformPreviewItemsEqual(
return ( return (
left.entityId === right.entityId && left.entityId === right.entityId &&
areVec3Equal(left.position, right.position) && areVec3Equal(left.position, right.position) &&
areEntityTransformRotationsEqual(left.rotation, right.rotation) areEntityTransformRotationsEqual(left.rotation, right.rotation) &&
areEntityTransformScalesEqual(left.scale, right.scale)
); );
} }
@@ -526,6 +557,29 @@ function areEntityTransformRotationsEqual(
right.kind === "direction" && right.kind === "direction" &&
areVec3Equal(left.direction, right.direction) areVec3Equal(left.direction, right.direction)
); );
case "euler":
return (
right.kind === "euler" &&
areVec3Equal(left.rotationDegrees, right.rotationDegrees)
);
}
}
function areEntityTransformScalesEqual(
left: EntityTransformScaleState,
right: EntityTransformScaleState
): boolean {
if (left.kind !== right.kind) {
return false;
}
switch (left.kind) {
case "none":
return true;
case "scale":
return right.kind === "scale" && areVec3Equal(left.scale, right.scale);
case "size":
return right.kind === "size" && areVec3Equal(left.size, right.size);
} }
} }
@@ -634,7 +688,8 @@ export function cloneTransformTarget(target: TransformTarget): TransformTarget {
initialPosition: cloneVec3(target.initialPosition), initialPosition: cloneVec3(target.initialPosition),
initialRotation: cloneEntityTransformRotationState( initialRotation: cloneEntityTransformRotationState(
target.initialRotation target.initialRotation
) ),
initialScale: cloneEntityTransformScaleState(target.initialScale)
}; };
case "entities": case "entities":
return { return {
@@ -688,7 +743,8 @@ export function cloneTransformPreview(
return { return {
kind: "entity", kind: "entity",
position: cloneVec3(preview.position), position: cloneVec3(preview.position),
rotation: cloneEntityTransformRotationState(preview.rotation) rotation: cloneEntityTransformRotationState(preview.rotation),
scale: cloneEntityTransformScaleState(preview.scale)
}; };
case "entities": case "entities":
return { return {
@@ -869,7 +925,8 @@ function areTransformTargetsEqual(
areEntityTransformRotationsEqual( areEntityTransformRotationsEqual(
left.initialRotation, left.initialRotation,
right.initialRotation right.initialRotation
) ) &&
areEntityTransformScalesEqual(left.initialScale, right.initialScale)
); );
case "entities": case "entities":
return ( return (
@@ -935,7 +992,8 @@ function areTransformPreviewsEqual(
return ( return (
right.kind === "entity" && right.kind === "entity" &&
areVec3Equal(left.position, right.position) && areVec3Equal(left.position, right.position) &&
areEntityTransformRotationsEqual(left.rotation, right.rotation) areEntityTransformRotationsEqual(left.rotation, right.rotation) &&
areEntityTransformScalesEqual(left.scale, right.scale)
); );
case "entities": case "entities":
return ( return (
@@ -1026,7 +1084,8 @@ export function createTransformPreviewFromTarget(
return { return {
kind: "entity", kind: "entity",
position: cloneVec3(target.initialPosition), position: cloneVec3(target.initialPosition),
rotation: cloneEntityTransformRotationState(target.initialRotation) rotation: cloneEntityTransformRotationState(target.initialRotation),
scale: cloneEntityTransformScaleState(target.initialScale)
}; };
case "entities": case "entities":
return { return {
@@ -1035,7 +1094,8 @@ export function createTransformPreviewFromTarget(
items: target.items.map((item) => ({ items: target.items.map((item) => ({
entityId: item.entityId, entityId: item.entityId,
position: cloneVec3(item.initialPosition), position: cloneVec3(item.initialPosition),
rotation: cloneEntityTransformRotationState(item.initialRotation) rotation: cloneEntityTransformRotationState(item.initialRotation),
scale: cloneEntityTransformScaleState(item.initialScale)
})) }))
}; };
} }
@@ -1137,6 +1197,10 @@ export function doesTransformSessionChangeTarget(
!areEntityTransformRotationsEqual( !areEntityTransformRotationsEqual(
session.preview.rotation, session.preview.rotation,
session.target.initialRotation session.target.initialRotation
) ||
!areEntityTransformScalesEqual(
session.preview.scale,
session.target.initialScale
)) ))
); );
case "entities": case "entities":
@@ -1154,6 +1218,10 @@ export function doesTransformSessionChangeTarget(
!areEntityTransformRotationsEqual( !areEntityTransformRotationsEqual(
item.rotation, item.rotation,
targetItem.initialRotation targetItem.initialRotation
) ||
!areEntityTransformScalesEqual(
item.scale,
targetItem.initialScale
) )
); );
})) }))
@@ -1229,16 +1297,40 @@ export function getSupportedTransformOperations(
case "modelInstance": case "modelInstance":
case "modelInstances": case "modelInstances":
return ["translate", "rotate", "scale"]; return ["translate", "rotate", "scale"];
case "entity": case "entity": {
return target.initialRotation.kind === "none" const operations: TransformOperation[] = ["translate"];
? ["translate"]
: ["translate", "rotate"]; if (target.initialRotation.kind !== "none") {
case "entities": operations.push("rotate");
return target.items.every( }
(item) => getSupportedTransformOperations(item).includes("rotate")
) if (target.initialScale.kind !== "none") {
? ["translate", "rotate"] operations.push("scale");
: ["translate"]; }
return operations;
}
case "entities": {
const operations: TransformOperation[] = ["translate"];
if (
target.items.every((item) =>
getSupportedTransformOperations(item).includes("rotate")
)
) {
operations.push("rotate");
}
if (
target.items.every((item) =>
getSupportedTransformOperations(item).includes("scale")
)
) {
operations.push("scale");
}
return operations;
}
} }
} }
@@ -1299,6 +1391,16 @@ export function supportsTransformAxisConstraint(
return true; return true;
} }
if (session.target.kind === "entity") {
return session.target.initialScale.kind !== "none";
}
if (session.target.kind === "entities") {
return session.target.items.every(
(item) => item.initialScale.kind !== "none"
);
}
if ( if (
session.target.kind === "brushVertex" || session.target.kind === "brushVertex" ||
session.target.kind === "pathPoint" session.target.kind === "pathPoint"
@@ -1423,11 +1525,41 @@ function resolveEntityRotation(
}; };
case "pointLight": case "pointLight":
case "soundEmitter": case "soundEmitter":
case "triggerVolume":
case "interactable": case "interactable":
return { return {
kind: "none" kind: "none"
}; };
case "triggerVolume":
return {
kind: "euler",
rotationDegrees: cloneVec3(entity.rotationDegrees)
};
}
}
function resolveEntityScale(entity: EntityInstance): EntityTransformScaleState {
switch (entity.kind) {
case "npc":
return {
kind: "scale",
scale: cloneVec3(entity.scale)
};
case "triggerVolume":
return {
kind: "size",
size: cloneVec3(entity.size)
};
case "cameraRig":
case "interactable":
case "playerStart":
case "pointLight":
case "sceneEntry":
case "soundEmitter":
case "spotLight":
case "teleportTarget":
return {
kind: "none"
};
} }
} }
@@ -1660,7 +1792,8 @@ function createEntityTransformTarget(
entityId: clonedEntity.id, entityId: clonedEntity.id,
entityKind: clonedEntity.kind, entityKind: clonedEntity.kind,
initialPosition: cloneVec3(entity.position), initialPosition: cloneVec3(entity.position),
initialRotation: resolveEntityRotation(clonedEntity) initialRotation: resolveEntityRotation(clonedEntity),
initialScale: resolveEntityScale(clonedEntity)
}, },
message: null message: null
}; };