mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-21 17:28:24 -04:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f621e75c7 | ||
|
|
e599aecc62 | ||
|
|
7b1bbc4a0e | ||
|
|
1a174345bb |
@@ -206,6 +206,7 @@ class Scene {
|
||||
color: 0xffffff,
|
||||
map: texture,
|
||||
transparent: true,
|
||||
side: THREE.DoubleSide,
|
||||
});
|
||||
obj = new THREE.Mesh(geometry, image_material);
|
||||
obj.userData["media_id"] = name;
|
||||
|
||||
@@ -54,15 +54,18 @@ import {
|
||||
topNavMediaId,
|
||||
topNavMediaUrl,
|
||||
} from "~/components/signaled/TopBar/TopBar";
|
||||
import { setOnImageDrop } from "../../../../../../libs/components/gallery-modal/src/lib/galleryDnd";
|
||||
import { uploadPlaneFromMediaToken } from "~/components/reusable/UploadModalMedia/uploadPlane";
|
||||
import { addObject } from "./signals/objectGroup/addObject";
|
||||
import { AssetType } from "~/enums";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { MediaItem } from "~/pages/PageEnigma/models";
|
||||
import { GalleryItem } from "../../../../../../libs/components/gallery-modal/src/lib/gallery-modal";
|
||||
import { UploaderState } from "~/models";
|
||||
import * as THREE from "three";
|
||||
import {
|
||||
GalleryItem,
|
||||
onImageDrop,
|
||||
removeImageDropListener,
|
||||
} from "@storyteller/ui-gallery-modal";
|
||||
|
||||
export const PageEditor = () => {
|
||||
useSignals();
|
||||
@@ -247,89 +250,63 @@ export const PageEditor = () => {
|
||||
|
||||
// Image drop from gallery/library modal
|
||||
useEffect(() => {
|
||||
setOnImageDrop(
|
||||
async (item: GalleryItem, _position: { x: number; y: number }) => {
|
||||
console.log("Drop debug:", {
|
||||
const handler = onImageDrop(
|
||||
(item: GalleryItem, position: { x: number; y: number }) => {
|
||||
console.log("Drop debug (event):", {
|
||||
editorEngine,
|
||||
camera: editorEngine?.camera,
|
||||
renderer: editorEngine?.renderer,
|
||||
_position,
|
||||
position,
|
||||
});
|
||||
// Diagnostic log for received drop position and canvas rect
|
||||
if (editorEngine?.renderer) {
|
||||
const rect = editorEngine.renderer.domElement.getBoundingClientRect();
|
||||
const canvasX = _position.x - rect.left;
|
||||
const canvasY = _position.y - rect.top;
|
||||
console.log(
|
||||
"[Drop Debug] Received:",
|
||||
_position,
|
||||
"Canvas rect:",
|
||||
rect,
|
||||
"canvasX:",
|
||||
canvasX,
|
||||
"canvasY:",
|
||||
canvasY,
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate world position from cursor immediately on drop
|
||||
let worldPosition = undefined;
|
||||
if (editorEngine?.camera && editorEngine?.renderer && _position) {
|
||||
if (editorEngine?.camera && editorEngine?.renderer && position) {
|
||||
const rect = editorEngine.renderer.domElement.getBoundingClientRect();
|
||||
// Convert client coordinates to canvas coordinates
|
||||
const canvasX = _position.x - rect.left;
|
||||
const canvasY = _position.y - rect.top;
|
||||
const canvasX = position.x - rect.left;
|
||||
const canvasY = position.y - rect.top;
|
||||
const ndcX = (canvasX / rect.width) * 2 - 1;
|
||||
const ndcY = -(canvasY / rect.height) * 2 + 1;
|
||||
const vector = new THREE.Vector3(ndcX, ndcY, 0.5);
|
||||
vector.unproject(editorEngine.camera);
|
||||
worldPosition = vector;
|
||||
// Diagnostic logging
|
||||
console.log({
|
||||
dropPosition: _position,
|
||||
rect: {
|
||||
left: rect.left,
|
||||
top: rect.top,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
},
|
||||
canvasX,
|
||||
canvasY,
|
||||
ndcX,
|
||||
ndcY,
|
||||
worldPosition,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Place the object immediately to avoid upload delay affecting placement
|
||||
const mediaItem: MediaItem = {
|
||||
version: 1,
|
||||
type: AssetType.OBJECT,
|
||||
media_id: item.id || uuidv4(),
|
||||
name: item.label || "Image Plane",
|
||||
...(worldPosition && {
|
||||
position: {
|
||||
x: worldPosition.x,
|
||||
y: worldPosition.y,
|
||||
z: worldPosition.z,
|
||||
(async () => {
|
||||
try {
|
||||
// Place the object immediately to avoid upload delay affecting placement
|
||||
const mediaItem: MediaItem = {
|
||||
version: 1,
|
||||
type: AssetType.OBJECT,
|
||||
media_id: item.id || uuidv4(),
|
||||
name: item.label || "Image Plane",
|
||||
...(worldPosition && {
|
||||
position: {
|
||||
x: worldPosition.x,
|
||||
y: worldPosition.y,
|
||||
z: worldPosition.z,
|
||||
},
|
||||
}),
|
||||
};
|
||||
addObject(mediaItem);
|
||||
|
||||
await uploadPlaneFromMediaToken({
|
||||
title: item.label || "Image Plane",
|
||||
mediaToken: item.id,
|
||||
progressCallback: (state: UploaderState) => {
|
||||
if (state.status) console.log("Upload status:", state.status);
|
||||
},
|
||||
}),
|
||||
};
|
||||
addObject(mediaItem);
|
||||
|
||||
await uploadPlaneFromMediaToken({
|
||||
title: item.label || "Image Plane",
|
||||
mediaToken: item.id,
|
||||
progressCallback: (state: UploaderState) => {
|
||||
if (state.status) console.log("Upload status:", state.status);
|
||||
},
|
||||
});
|
||||
console.log("Upload complete");
|
||||
} catch (err) {
|
||||
console.error("Failed to upload and add image plane:", err);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Failed to add image plane:", err);
|
||||
}
|
||||
})();
|
||||
},
|
||||
);
|
||||
return () => {
|
||||
removeImageDropListener(handler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const display3d = appTabId.value === "3D" ? "block" : "none";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./lib/gallery-modal";
|
||||
export * from "./lib/galleryModalSignals";
|
||||
export * from "./lib/GalleryDragComponent";
|
||||
export * from "./lib/galleryDnd";
|
||||
|
||||
@@ -24,13 +24,6 @@ const dragState: DragState = {
|
||||
|
||||
const dragThreshold = 5;
|
||||
|
||||
export let onImageDrop:
|
||||
| ((item: GalleryItem, position: { x: number; y: number }) => void)
|
||||
| null = null;
|
||||
export function setOnImageDrop(cb: typeof onImageDrop) {
|
||||
onImageDrop = cb;
|
||||
}
|
||||
|
||||
function onPointerDown(event: React.PointerEvent, item: GalleryItem) {
|
||||
if (event.button !== 0) return;
|
||||
dragState.item = item;
|
||||
@@ -59,15 +52,38 @@ function onPointerMove(event: PointerEvent) {
|
||||
dragState.currY = event.pageY;
|
||||
}
|
||||
|
||||
export const IMAGE_DROP_EVENT = "gallery-image-drop";
|
||||
|
||||
export function emitImageDrop(
|
||||
item: GalleryItem,
|
||||
position: { x: number; y: number }
|
||||
) {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(IMAGE_DROP_EVENT, { detail: { item, position } })
|
||||
);
|
||||
}
|
||||
|
||||
export function onImageDrop(
|
||||
callback: (item: GalleryItem, position: { x: number; y: number }) => void
|
||||
) {
|
||||
const handler = (e: any) => {
|
||||
callback(e.detail.item, e.detail.position);
|
||||
};
|
||||
window.addEventListener(IMAGE_DROP_EVENT, handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
export function removeImageDropListener(handler: (e: any) => void) {
|
||||
window.removeEventListener(IMAGE_DROP_EVENT, handler);
|
||||
}
|
||||
|
||||
function onPointerUp(event: PointerEvent) {
|
||||
if (
|
||||
dragState.item &&
|
||||
dragState.isDragging &&
|
||||
dragState.item.mediaClass === "image"
|
||||
) {
|
||||
if (onImageDrop) {
|
||||
onImageDrop(dragState.item, { x: event.pageX, y: event.pageY });
|
||||
}
|
||||
emitImageDrop(dragState.item, { x: event.pageX, y: event.pageY });
|
||||
}
|
||||
dragState.item = null;
|
||||
dragState.isDragging = false;
|
||||
|
||||
Reference in New Issue
Block a user