Compare commits

...
Author SHA1 Message Date
bflatastic 19205248bf can now drag and drop gallery 3d objects to 3d scene 2025-06-10 12:47:13 +07:00
6 changed files with 65 additions and 29 deletions
@@ -2,6 +2,7 @@ export enum FilterMediaClasses {
AUDIO = "audio",
IMAGE = "image",
VIDEO = "video",
DIMENSIONAL = "dimensional",
}
export enum FilterMediaType {
@@ -295,31 +295,50 @@ export const PageEditor = () => {
(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);
if (item.mediaClass === "dimensional") {
// Handle 3D models
const mediaItem: MediaItem = {
version: 1,
type: AssetType.OBJECT,
media_id: item.id || uuidv4(),
name: item.label || "3D Object",
...(worldPosition && {
position: {
x: worldPosition.x,
y: worldPosition.y,
z: worldPosition.z,
},
}),
};
addObject(mediaItem);
} else {
// Handle images (create image planes)
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);
},
});
await uploadPlaneFromMediaToken({
title: item.label || "Image Plane",
mediaToken: item.id,
progressCallback: (state: UploaderState) => {
if (state.status)
console.log("Upload status:", state.status);
},
});
}
} catch (err) {
console.error("Failed to add image plane:", err);
console.error("Failed to add object to scene:", err);
}
})();
},
@@ -2,6 +2,7 @@ export enum FilterMediaClasses {
AUDIO = "audio",
IMAGE = "image",
VIDEO = "video",
DIMENSIONAL = "dimensional",
}
export enum FilterMediaType {
@@ -80,7 +80,7 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
{/* Media class badge on hover */}
{!disableTooltipAndBadge && item.mediaClass && (
<div className="pointer-events-none absolute right-2 top-2 z-20 rounded-full bg-black/50 backdrop-blur-lg px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-white opacity-0 group-hover:opacity-100 transition-opacity duration-150">
{item.mediaClass}
{item.mediaClass === "dimensional" ? "3D" : item.mediaClass}
</div>
)}
{/* Tooltip on hover */}
@@ -138,7 +138,11 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
{item.mediaClass !== "video" && (
<span>
<span className="font-bold">Drag</span>
<span className="opacity-50"> to add</span>
<span className="opacity-50">
{item.mediaClass === "dimensional"
? " to add to scene"
: " to add"}
</span>
</span>
)}
<span>
@@ -173,8 +173,14 @@ export const GalleryModal = React.memo(
return [FilterMediaClasses.IMAGE];
case "video":
return [FilterMediaClasses.VIDEO];
case "3d":
return [FilterMediaClasses.DIMENSIONAL];
case "uploaded":
return [FilterMediaClasses.IMAGE, FilterMediaClasses.VIDEO];
return [
FilterMediaClasses.IMAGE,
FilterMediaClasses.VIDEO,
FilterMediaClasses.DIMENSIONAL,
];
default:
return undefined;
}
@@ -190,7 +196,9 @@ export const GalleryModal = React.memo(
filter_media_classes: filterMediaClasses,
username: username,
include_user_uploads:
activeFilter === "uploaded" || activeFilter === "all",
activeFilter === "uploaded" ||
activeFilter === "all" ||
activeFilter === "3d",
user_uploads_only: activeFilter === "uploaded",
page_index: reset ? 0 : pageIndex,
page_size: pageSize,
@@ -205,6 +213,8 @@ export const GalleryModal = React.memo(
thumbnail:
item.media_class === "video"
? item.media_links.maybe_video_previews.still
: item.media_class === "dimensional"
? item.cover_image?.maybe_cover_image_public_bucket_url
: item.media_links.maybe_thumbnail_template?.replace(
"{WIDTH}",
thumbnail_size.toString()
@@ -480,7 +490,7 @@ export const GalleryModal = React.memo(
([date, dateItems]) => {
const filteredItems = dateItems.filter((item) => {
if (activeFilter === "3d")
return item.mediaClass === "3d";
return item.mediaClass === "dimensional";
if (activeFilter === "all")
return item.mediaClass !== "audio";
return true;
@@ -81,7 +81,8 @@ function onPointerUp(event: PointerEvent) {
if (
dragState.item &&
dragState.isDragging &&
dragState.item.mediaClass === "image"
(dragState.item.mediaClass === "image" ||
dragState.item.mediaClass === "dimensional")
) {
emitImageDrop(dragState.item, { x: event.pageX, y: event.pageY });
}