diff --git a/frontend/editor3d/app/pages/PageEnigma/DragAndDrop/DndAsset.ts b/frontend/editor3d/app/pages/PageEnigma/DragAndDrop/DndAsset.ts
index 9add5bb681..88f3aaaf02 100644
--- a/frontend/editor3d/app/pages/PageEnigma/DragAndDrop/DndAsset.ts
+++ b/frontend/editor3d/app/pages/PageEnigma/DragAndDrop/DndAsset.ts
@@ -13,6 +13,8 @@ import {
overTimeline,
sidePanelWidth,
timelineHeight,
+ assetModalVisibleDuringDrag,
+ reopenAfterDragSignal,
} from "~/pages/PageEnigma/signals";
import { pageHeight, pageWidth } from "~/signals";
import { addShape } from "~/pages/PageEnigma/signals/shape";
@@ -42,6 +44,7 @@ class DndAsset {
this.initY = event.pageY;
canDrop.value = false;
this.notDropText = "";
+ assetModalVisibleDuringDrag.value = false;
window.addEventListener("pointerup", this.onPointerUp);
window.addEventListener("pointermove", this.onPointerMove);
}
@@ -54,6 +57,14 @@ class DndAsset {
this.overElement = null;
overTimeline.value = false;
this.notDropText = "";
+ if (reopenAfterDragSignal.value) {
+ assetModalVisibleDuringDrag.value = true;
+ } else {
+ assetModalVisibleDuringDrag.value = true;
+ setTimeout(() => {
+ assetModalVisibleDuringDrag.value = false;
+ }, 0);
+ }
}
}
diff --git a/frontend/editor3d/app/pages/PageEnigma/PageEditor.tsx b/frontend/editor3d/app/pages/PageEnigma/PageEditor.tsx
index afa8c6b48b..b7d1538aaa 100644
--- a/frontend/editor3d/app/pages/PageEnigma/PageEditor.tsx
+++ b/frontend/editor3d/app/pages/PageEnigma/PageEditor.tsx
@@ -23,7 +23,6 @@ import {
} from "~/pages/PageEnigma/signals";
import { EditorCanvas } from "./comps/EngineCanvases";
import { SceneContainer } from "./comps/SceneContainer";
-import { AspectRatioMenu } from "./comps/AspectRatioMenu";
import { Outliner } from "./comps/Outliner";
import { CameraAspectRatio } from "./enums";
import { PromptBox } from "./comps/PromptBox";
@@ -95,7 +94,6 @@ export const PageEditor = () => {
className="flex"
style={{
height,
- width,
}}
>
@@ -136,10 +134,12 @@ export const PageEditor = () => {
-
+
+
+
{
{/* Side panel */}
- */}
{/* Timeline */}
diff --git a/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetMenu.tsx b/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetMenu.tsx
index ba8ea8b22d..1114003d17 100644
--- a/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetMenu.tsx
+++ b/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetMenu.tsx
@@ -2,6 +2,7 @@ import { faCube, faMagicWandSparkles } from "@fortawesome/pro-solid-svg-icons";
import { Button, Tooltip } from "~/components";
import { useState } from "react";
import { AssetModal } from "./AssetModal";
+import { assetModalVisibleDuringDrag } from "../../signals";
export const AssetMenu = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -11,6 +12,11 @@ export const AssetMenu = () => {
console.log("Adding asset...");
};
+ const handleOpenModal = () => {
+ assetModalVisibleDuringDrag.value = true;
+ setIsModalOpen(true);
+ };
+
return (
<>
@@ -18,7 +24,7 @@ export const AssetMenu = () => {
diff --git a/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetModal.tsx b/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetModal.tsx
index 6b04a87a31..f84b4454f1 100644
--- a/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetModal.tsx
+++ b/frontend/editor3d/app/pages/PageEnigma/comps/AssetMenu/AssetModal.tsx
@@ -3,16 +3,30 @@ import {
faPlus,
faSearch,
faChevronRight,
+ faChevronLeft,
+ faLayerGroup,
+ faUser,
+ faSun,
+ faTree,
+ faCube,
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button, CloseButton, Input, Tooltip } from "~/components";
import { TabSelector } from "~/components/reusable/TabSelector";
-import { useState, useEffect, useMemo } from "react";
+import { useState, useEffect, useMemo, useRef } from "react";
import { ItemElements } from "../SidePanelTabs/sharedComps/ItemElements";
-import { demoSkyboxItems, demoShapeItems } from "../../signals";
+import {
+ demoSkyboxItems,
+ demoShapeItems,
+ demoCharacterItems,
+ assetModalVisibleDuringDrag,
+ reopenAfterDragSignal,
+} from "../../signals";
import { MediaItem } from "../../models";
import { useUserObjects, useFeaturedObjects } from "../SidePanelTabs/hooks";
import { FilterEngineCategories } from "~/enums";
+import { twMerge } from "tailwind-merge";
+import { useSignals } from "@preact/signals-react/runtime";
interface AssetModalProps {
isOpen: boolean;
@@ -23,6 +37,7 @@ interface AssetModalProps {
type AssetTab = {
id: string;
label: string;
+ icon: typeof faLayerGroup;
engineCategory?: FilterEngineCategories;
items: MediaItem[];
};
@@ -36,9 +51,9 @@ const AllTabSection = ({
items: MediaItem[];
onViewAll: () => void;
}) => (
-
+
-
{label}
+ {label}
-
+
{
+ useSignals();
const [activeLibraryTab, setActiveLibraryTab] = useState("library");
const [activeAssetTab, setActiveAssetTab] = useState("all");
const [searchTerm, setSearchTerm] = useState("");
+ const [reopenAfterAdd, setReopenAfterAdd] = useState(true);
+ const searchInputRef = useRef(null);
+
+ // Update the signal when the preference changes
+ useEffect(() => {
+ reopenAfterDragSignal.value = reopenAfterAdd;
+ }, [reopenAfterAdd]);
+
+ useEffect(() => {
+ if (isOpen) {
+ // Small delay to ensure the modal is fully mounted
+ const timer = setTimeout(() => {
+ searchInputRef.current?.focus();
+ }, 100);
+ return () => clearTimeout(timer);
+ }
+ }, [isOpen]);
// Fetch objects for different categories
const { userObjects: userCharacters } = useUserObjects({
@@ -103,25 +136,29 @@ export const AssetModal = ({
{ id: "mine", label: "Mine" },
];
+ // eslint-disable-next-line react-hooks/exhaustive-deps
const assetTabs: AssetTab[] = [
- { id: "all", label: "All", items: [] },
+ { id: "all", label: "All", icon: faLayerGroup, items: [] },
{
id: "character",
label: "Character",
+ icon: faUser,
engineCategory: FilterEngineCategories.CHARACTER,
items:
activeLibraryTab === "library"
- ? (featuredCharacters ?? [])
+ ? [...demoCharacterItems.value, ...(featuredCharacters ?? [])]
: (userCharacters ?? []),
},
{
id: "skybox",
label: "Skybox",
+ icon: faSun,
items: demoSkyboxItems.value,
},
{
id: "nature",
label: "Nature",
+ icon: faTree,
engineCategory: FilterEngineCategories.SET_DRESSING,
items:
activeLibraryTab === "library"
@@ -131,6 +168,7 @@ export const AssetModal = ({
{
id: "objects",
label: "Objects",
+ icon: faCube,
engineCategory: FilterEngineCategories.OBJECT,
items:
activeLibraryTab === "library"
@@ -171,12 +209,13 @@ export const AssetModal = ({
if (searchTerm && activeAssetTab !== "all") {
setActiveAssetTab("all");
}
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchTerm]);
const renderContent = () => {
if (activeAssetTab === "all" && !searchTerm) {
return (
-
+
{assetTabs.slice(1).map((tab) => (
{
+ onAddAsset();
+ if (reopenAfterAdd) {
+ // Small delay to allow the modal to close and reopen
+ setTimeout(() => {
+ onClose();
+ }, 100);
+ } else {
+ onClose();
+ }
+ };
+
return (
-
+
3D Assets
-
+
{assetTabs.map((tab) => (
))}
+
+ setReopenAfterAdd(e.target.checked)}
+ className="h-4 w-4 rounded-lg border-gray-300 bg-gray-700 text-brand-primary focus:ring-brand-primary"
+ />
+
+
-
+
-
+
-
+
+ {activeAssetTab !== "all" && !searchTerm && (
+
+
+ {currentTab.label}
+
+ )}
{renderContent()}
-
-
-
diff --git a/frontend/editor3d/app/pages/PageEnigma/comps/SceneContainer/SceneContainer.tsx b/frontend/editor3d/app/pages/PageEnigma/comps/SceneContainer/SceneContainer.tsx
index c71d6f259e..fb52a50062 100644
--- a/frontend/editor3d/app/pages/PageEnigma/comps/SceneContainer/SceneContainer.tsx
+++ b/frontend/editor3d/app/pages/PageEnigma/comps/SceneContainer/SceneContainer.tsx
@@ -1,12 +1,7 @@
import { useCallback, useContext } from "react";
import { useSignals } from "@preact/signals-react/runtime";
import { pageHeight, pageWidth } from "~/signals";
-import {
- editorLetterBox,
- timelineHeight,
- sidePanelWidth,
- sidePanelVisible,
-} from "~/pages/PageEnigma/signals";
+import { editorLetterBox, timelineHeight } from "~/pages/PageEnigma/signals";
import { EngineContext } from "~/pages/PageEnigma/contexts/EngineContext";
import { Letterbox } from "./Letterbox";
@@ -14,8 +9,7 @@ export const SceneContainer = ({ children }: { children: React.ReactNode }) => {
useSignals();
const editorEngine = useContext(EngineContext);
- const containerWidth =
- pageWidth.value - (sidePanelVisible.value ? sidePanelWidth.value : 0) - 84;
+ const containerWidth = pageWidth.value;
const containerHeight = pageHeight.value - timelineHeight.value - 64;
diff --git a/frontend/editor3d/app/pages/PageEnigma/comps/SidePanelTabs/sharedComps/ItemElement.tsx b/frontend/editor3d/app/pages/PageEnigma/comps/SidePanelTabs/sharedComps/ItemElement.tsx
index 819f3167d4..2c1cf89464 100644
--- a/frontend/editor3d/app/pages/PageEnigma/comps/SidePanelTabs/sharedComps/ItemElement.tsx
+++ b/frontend/editor3d/app/pages/PageEnigma/comps/SidePanelTabs/sharedComps/ItemElement.tsx
@@ -66,7 +66,7 @@ export const ItemElement = ({ item }: Props) => {
/>
)}
-
+
{item.name || item.media_id}
diff --git a/frontend/editor3d/app/pages/PageEnigma/signals/assetModal.ts b/frontend/editor3d/app/pages/PageEnigma/signals/assetModal.ts
new file mode 100644
index 0000000000..b66116b5d2
--- /dev/null
+++ b/frontend/editor3d/app/pages/PageEnigma/signals/assetModal.ts
@@ -0,0 +1,4 @@
+import { signal } from "@preact/signals-react";
+
+export const assetModalVisibleDuringDrag = signal(true);
+export const reopenAfterDragSignal = signal(true);
diff --git a/frontend/editor3d/app/pages/PageEnigma/signals/index.ts b/frontend/editor3d/app/pages/PageEnigma/signals/index.ts
index e3c2a1d293..f348ce199e 100644
--- a/frontend/editor3d/app/pages/PageEnigma/signals/index.ts
+++ b/frontend/editor3d/app/pages/PageEnigma/signals/index.ts
@@ -18,3 +18,4 @@ export * from "./stylizeTab";
export * from "./timing";
export * from "./timeline";
export * from "./error";
+export * from "./assetModal";