fix: 优化Gizmo
This commit is contained in:
@@ -30,6 +30,8 @@ import { DEFAULT_CHARACTER_BODY_TYPE, normalizeBodyType } from "../runtime/manne
|
||||
import {
|
||||
DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT,
|
||||
getCameraRigPositionFromViewSnapshot,
|
||||
getCameraLookRotationFromTarget,
|
||||
migrateLegacyCameraShot,
|
||||
} from "../schema/cameraGeometry";
|
||||
import type { ViewportAspectRatio } from "../schema/viewportAspectRatio";
|
||||
import {
|
||||
@@ -215,7 +217,7 @@ export interface DirectorActions {
|
||||
cameraId: string,
|
||||
patch: Partial<DirectorCameraShot> & {
|
||||
transform?: DirectorTransform;
|
||||
target?: [number, number, number];
|
||||
lookRotation?: [number, number, number];
|
||||
}
|
||||
) => void;
|
||||
// 物体关键帧
|
||||
@@ -517,8 +519,57 @@ function withSceneDefaults(project: DirectorProject): DirectorProject {
|
||||
return { ...project, scene: nextScene };
|
||||
}
|
||||
|
||||
/**
|
||||
* 旧工程里机位的注视是一个世界坐标 target:统一换算成注视朝向角
|
||||
* (水平角 / 俯仰角 / 横滚角),运镜关键帧同理。
|
||||
*/
|
||||
function withCameraLookRotations(project: DirectorProject): DirectorProject {
|
||||
const cameras = project.cameras ?? [];
|
||||
const cameraTracks = project.timeline?.cameraTracks ?? [];
|
||||
const legacyCamera = cameras.some((camera) => Boolean(camera) && !Array.isArray(camera.lookRotation));
|
||||
const legacyKeyframe = cameraTracks.some((track) =>
|
||||
(track.keyframes ?? []).some((keyframe) => Boolean(keyframe) && !Array.isArray(keyframe.value?.lookRotation))
|
||||
);
|
||||
|
||||
if (!legacyCamera && !legacyKeyframe) return project;
|
||||
|
||||
return {
|
||||
...project,
|
||||
cameras: cameras.map((camera) => (camera ? migrateLegacyCameraShot(camera) : camera)),
|
||||
timeline: legacyKeyframe
|
||||
? {
|
||||
...project.timeline,
|
||||
cameraTracks: cameraTracks.map((track) => ({
|
||||
...track,
|
||||
keyframes: (track.keyframes ?? []).map((keyframe) => ({
|
||||
...keyframe,
|
||||
value: migrateLegacyCameraKeyframeValue(keyframe.value),
|
||||
})),
|
||||
})),
|
||||
}
|
||||
: project.timeline,
|
||||
};
|
||||
}
|
||||
|
||||
function migrateLegacyCameraKeyframeValue(value: {
|
||||
position: [number, number, number];
|
||||
fov: number;
|
||||
lookRotation?: [number, number, number];
|
||||
target?: [number, number, number];
|
||||
}): CameraKeyframeValue {
|
||||
return {
|
||||
position: value.position,
|
||||
fov: value.fov,
|
||||
lookRotation: Array.isArray(value.lookRotation)
|
||||
? value.lookRotation
|
||||
: Array.isArray(value.target)
|
||||
? getCameraLookRotationFromTarget(value.position, value.target)
|
||||
: [...DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT.lookRotation],
|
||||
};
|
||||
}
|
||||
|
||||
function migrateDirectorProject(project: DirectorProject): DirectorProject {
|
||||
const withTimelineProject = withSceneDefaults(withTimeline(project));
|
||||
const withTimelineProject = withSceneDefaults(withCameraLookRotations(withTimeline(project)));
|
||||
return {
|
||||
...withTimelineProject,
|
||||
objects: withTimelineProject.objects.map((object) => {
|
||||
@@ -676,7 +727,7 @@ export function createDefaultDirectorProject({
|
||||
fov: DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT.fov,
|
||||
transform: createTransform(getCameraRigPositionFromViewSnapshot(DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT)),
|
||||
targetMode: "manual",
|
||||
target: DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT.target,
|
||||
lookRotation: [...DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT.lookRotation],
|
||||
lastCaptureUrl: null,
|
||||
captures: [],
|
||||
};
|
||||
@@ -928,7 +979,11 @@ function refreshCamerasFocusedOnObject(cameras: DirectorCameraShot[], object: Di
|
||||
camera.targetMode === "object" && camera.targetObjectId === object.id
|
||||
? {
|
||||
...camera,
|
||||
target: getDirectorObjectFocusTarget(object),
|
||||
// 锁定物体:把「机位 → 物体」这条视线换算成注视朝向角存下来
|
||||
lookRotation: getCameraLookRotationFromTarget(
|
||||
camera.transform.position,
|
||||
getDirectorObjectFocusTarget(object)
|
||||
),
|
||||
}
|
||||
: camera
|
||||
);
|
||||
@@ -960,7 +1015,10 @@ function refreshCamerasFocusedOnObjects(
|
||||
|
||||
return {
|
||||
...camera,
|
||||
target: getDirectorObjectFocusTarget(targetObject),
|
||||
lookRotation: getCameraLookRotationFromTarget(
|
||||
camera.transform.position,
|
||||
getDirectorObjectFocusTarget(targetObject)
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -1298,8 +1356,8 @@ function pasteClipboardEntries(state: DirectorRuntimeState): DirectorRuntimeStat
|
||||
id: nextCameraId,
|
||||
name: formatSceneItemName("机位", cameraIndex),
|
||||
transform: applyOffsetToTransform(entry.camera.transform, offset),
|
||||
target:
|
||||
entry.camera.targetMode === "manual" ? applyPositionOffset(entry.camera.target, offset) : entry.camera.target,
|
||||
// 注视是朝向角,平移机位不会改变它(锁物体的机位稍后按新位置重算)
|
||||
lookRotation: [...entry.camera.lookRotation],
|
||||
targetObjectId: targetObjectId ?? entry.camera.targetObjectId ?? null,
|
||||
captures: [],
|
||||
lastCaptureUrl: null,
|
||||
@@ -1354,7 +1412,10 @@ function pasteClipboardEntries(state: DirectorRuntimeState): DirectorRuntimeStat
|
||||
return {
|
||||
...camera,
|
||||
targetObjectId: mappedTargetObjectId,
|
||||
target: getDirectorObjectFocusTarget(targetObject),
|
||||
lookRotation: getCameraLookRotationFromTarget(
|
||||
camera.transform.position,
|
||||
getDirectorObjectFocusTarget(targetObject)
|
||||
),
|
||||
};
|
||||
});
|
||||
const lastPastedObject = pastedObjectIds.length
|
||||
@@ -2348,7 +2409,9 @@ export const useDirectorStore = create<DirectorStore>((set, get) => {
|
||||
fov: snapshot?.fov ?? 50,
|
||||
transform,
|
||||
targetMode: "manual",
|
||||
target: snapshot?.target ?? [0, 1.2, 0],
|
||||
lookRotation: snapshot
|
||||
? getCameraLookRotationFromTarget(snapshot.position, snapshot.target)
|
||||
: [...DEFAULT_DIRECTOR_CAMERA_VIEW_SNAPSHOT.lookRotation],
|
||||
lastCaptureUrl: null,
|
||||
captures: [],
|
||||
};
|
||||
@@ -2643,7 +2706,7 @@ export const useDirectorStore = create<DirectorStore>((set, get) => {
|
||||
...item,
|
||||
...patch,
|
||||
transform: patch.transform ?? item.transform,
|
||||
target: patch.target ?? item.target,
|
||||
lookRotation: patch.lookRotation ?? item.lookRotation,
|
||||
}
|
||||
: item
|
||||
),
|
||||
@@ -2744,12 +2807,12 @@ export const useDirectorStore = create<DirectorStore>((set, get) => {
|
||||
},
|
||||
})),
|
||||
applyCameraKeyframeToShot: (cameraId, value) => {
|
||||
// 只改 position/target/fov,rotation/scale 保留 shot 原值(相机朝向由 target 决定)
|
||||
// 只改 position/注视朝向/fov,scale 保留 shot 原值
|
||||
const camera = get().project.cameras.find((item) => item.id === cameraId);
|
||||
if (!camera) return;
|
||||
get().updateCamera(cameraId, {
|
||||
fov: value.fov,
|
||||
target: value.target,
|
||||
lookRotation: value.lookRotation,
|
||||
transform: { ...camera.transform, position: value.position },
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user