mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 22:04:51 -05:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ce9c8bed8 | ||
|
|
25c15bffd8 | ||
|
|
8ff91690c1 | ||
|
|
97bbe0fe07 | ||
|
|
2d361c6636 | ||
|
|
9361634d83 | ||
|
|
7cf0363555 | ||
|
|
c2ee3b0ce1 | ||
|
|
ca6fc13171 | ||
|
|
534afbbbf9 | ||
|
|
cb1ea1f828 | ||
|
|
010e3be5dc | ||
|
|
d8dab1a66e | ||
|
|
97b236d04d | ||
|
|
15fe59cc19 | ||
|
|
89bec31540 |
@@ -36,4 +36,168 @@ export class EngineApi extends ApiManager {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async uploadSceneSnapshot({
|
||||
screenshot,
|
||||
sceneMediaToken,
|
||||
}: {
|
||||
screenshot: string; // base64 encoded PNG
|
||||
sceneMediaToken?: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/scene_snapshot`;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("snapshot", screenshot); // Changed from "screenshot" to "snapshot" to match API spec
|
||||
if (sceneMediaToken) {
|
||||
formData.append("scene_media_token", sceneMediaToken);
|
||||
}
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const postResponse = await response.json();
|
||||
|
||||
console.log(postResponse);
|
||||
|
||||
let result: { success: boolean; data?: string; errorMessage?: string };
|
||||
|
||||
if (postResponse.success) {
|
||||
result = {
|
||||
success: true,
|
||||
data: postResponse.snapshot_media_token,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
} else {
|
||||
result = {
|
||||
success: false,
|
||||
errorMessage: postResponse.BadInput,
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async enqueueImageGeneration({
|
||||
prompt,
|
||||
snapshotMediaToken,
|
||||
additionalImages,
|
||||
}: {
|
||||
prompt: string;
|
||||
snapshotMediaToken: string;
|
||||
additionalImages?: string[];
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/prompt`;
|
||||
|
||||
const body = {
|
||||
prompt,
|
||||
snapshot_media_token: snapshotMediaToken, // Changed from scene_media_token to snapshot_media_token
|
||||
additional_images: additionalImages,
|
||||
};
|
||||
|
||||
const postResponse = await this.post<
|
||||
{
|
||||
prompt: string;
|
||||
snapshot_media_token: string;
|
||||
additional_images?: string[];
|
||||
},
|
||||
{ success?: boolean; job_token?: string; BadInput?: string }
|
||||
>({
|
||||
endpoint,
|
||||
body,
|
||||
});
|
||||
|
||||
// Check if the response is successful
|
||||
const isSuccess = postResponse.success ?? false;
|
||||
|
||||
// Prepare the result object
|
||||
const result = {
|
||||
success: isSuccess,
|
||||
data: isSuccess ? postResponse.job_token : undefined,
|
||||
errorMessage: isSuccess ? undefined : postResponse.BadInput,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async pollJobSession(jobToken: string): Promise<
|
||||
ApiResponse<{
|
||||
status: string;
|
||||
result: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/session/${jobToken}`;
|
||||
|
||||
const response = await this.get<{
|
||||
success?: boolean;
|
||||
status?: string;
|
||||
result?: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
BadInput?: string;
|
||||
}>({
|
||||
endpoint,
|
||||
});
|
||||
|
||||
const success = response.success ?? false;
|
||||
const status = response.status ?? "";
|
||||
const result = response.result ?? {
|
||||
generated_images: [],
|
||||
error: undefined,
|
||||
};
|
||||
const errorMessage = response.BadInput;
|
||||
|
||||
return {
|
||||
success,
|
||||
data: { status, result },
|
||||
errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
public async pollStudioSessionJobs(jobToken: string): Promise<
|
||||
ApiResponse<{
|
||||
status: string;
|
||||
result: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/session_jobs/${jobToken}`;
|
||||
|
||||
const response = await this.get<{
|
||||
success?: boolean;
|
||||
status?: string;
|
||||
result?: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
BadInput?: string;
|
||||
}>({
|
||||
endpoint,
|
||||
});
|
||||
|
||||
const success = response.success ?? false;
|
||||
const status = response.status ?? "";
|
||||
const result = response.result ?? {
|
||||
generated_images: [],
|
||||
error: undefined,
|
||||
};
|
||||
const errorMessage = response.BadInput;
|
||||
|
||||
return {
|
||||
success,
|
||||
data: { status, result },
|
||||
errorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ class CdnHostHelper {
|
||||
|
||||
let origin;
|
||||
if (isLocalDev) {
|
||||
origin = 'https://pub-c8a4a5bdbdb048f286b77bdf9f786ff2.r2.dev';
|
||||
//origin = 'https://pub-c8a4a5bdbdb048f286b77bdf9f786ff2.r2.dev';
|
||||
origin = 'https://cdn-2.fakeyou.com';
|
||||
} else {
|
||||
origin = 'https://cdn-2.fakeyou.com';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
import { ReactNode } from "react";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { Button } from "../Button";
|
||||
|
||||
export interface PopoverItem {
|
||||
label: string;
|
||||
selected: boolean;
|
||||
icon?: ReactNode;
|
||||
action?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
interface PopoverMenuProps {
|
||||
items?: PopoverItem[];
|
||||
onSelect?: (item: PopoverItem) => void;
|
||||
onAdd?: () => void;
|
||||
triggerIcon?: ReactNode;
|
||||
showAddButton?: boolean;
|
||||
showIconsInList?: boolean;
|
||||
mode?: "default" | "toggle" | "button";
|
||||
triggerLabel?: string;
|
||||
children?: ReactNode;
|
||||
buttonClassName?: string;
|
||||
panelClassName?: string;
|
||||
onAction?: (action: string) => void;
|
||||
panelTitle?: string;
|
||||
}
|
||||
|
||||
export const PopoverMenu = ({
|
||||
items = [],
|
||||
onSelect,
|
||||
onAdd,
|
||||
triggerIcon,
|
||||
showAddButton = false,
|
||||
showIconsInList = false,
|
||||
mode = "default",
|
||||
triggerLabel,
|
||||
children,
|
||||
buttonClassName,
|
||||
onAction,
|
||||
panelTitle,
|
||||
}: PopoverMenuProps) => {
|
||||
const selectedItem = items.find((item) => item.selected);
|
||||
|
||||
const handleItemClick = (item: PopoverItem, close: () => void) => {
|
||||
if (mode === "button" && item.action && onAction) {
|
||||
onAction(item.action);
|
||||
close();
|
||||
} else {
|
||||
onSelect?.(item);
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
const className = twMerge(
|
||||
"text-sm font-medium rounded-lg px-3 py-2 shadow-sm",
|
||||
"flex gap-2 items-center justify-center outline-none",
|
||||
"transition-all duration-150",
|
||||
"bg-[#5F5F68]/60 px-3 text-white backdrop-blur-lg hover:bg-[#5F5F68]/90",
|
||||
buttonClassName,
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover className="relative">
|
||||
{({ close }) => (
|
||||
<>
|
||||
<Popover.Button className={className}>
|
||||
{triggerIcon}
|
||||
{mode === "toggle" && selectedItem ? selectedItem.label : null}
|
||||
{mode === "default" && triggerLabel ? triggerLabel : null}
|
||||
</Popover.Button>
|
||||
|
||||
<div className="absolute bottom-full left-0 transform-gpu">
|
||||
<Transition
|
||||
enter="transition duration-100 ease-out"
|
||||
enterFrom="translate-y-2 opacity-0"
|
||||
enterTo="translate-y-0 opacity-100"
|
||||
leave="transition duration-100 ease-in"
|
||||
leaveFrom="translate-y-0 opacity-100"
|
||||
leaveTo="translate-y-2 opacity-0"
|
||||
>
|
||||
<Popover.Panel className="origin-bottom">
|
||||
<div
|
||||
className={twMerge(
|
||||
"z-10 mb-2 min-w-48 rounded-lg bg-[#46464B] p-1.5 shadow-lg",
|
||||
)}
|
||||
>
|
||||
{panelTitle && (
|
||||
<div className="mb-2 mt-0.5 px-1.5 text-sm font-normal text-white opacity-70">
|
||||
{panelTitle}
|
||||
</div>
|
||||
)}
|
||||
{mode === "default" && children ? (
|
||||
<div className="text-sm text-white">{children}</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-0 text-sm text-white">
|
||||
{items.map((item, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
className={twMerge(
|
||||
"flex items-center justify-between border-transparent bg-transparent px-1.5",
|
||||
"hover:bg-[#63636B]/60",
|
||||
mode === "toggle" && item.selected
|
||||
? "hover:bg-[#63636B]"
|
||||
: "bg-transparent",
|
||||
item.disabled
|
||||
? "!cursor-not-allowed opacity-50"
|
||||
: "",
|
||||
)}
|
||||
onClick={() =>
|
||||
!item.disabled && handleItemClick(item, close)
|
||||
}
|
||||
variant="secondary"
|
||||
disabled={item.disabled}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{showIconsInList && item.icon}
|
||||
{item.label}
|
||||
</div>
|
||||
{mode === "toggle" && (
|
||||
<input
|
||||
type="radio"
|
||||
checked={item.selected}
|
||||
readOnly
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
))}
|
||||
{showAddButton && onAdd && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
className="mb-0.5 mt-2 border-none bg-[#7B7B84] py-1 hover:bg-[#8c8c96]"
|
||||
onClick={onAdd}
|
||||
>
|
||||
+ Add
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./Popover";
|
||||
@@ -15,6 +15,8 @@ export const uploadImage = async ({
|
||||
}) => {
|
||||
const mediaUploadApi = new MediaUploadApi();
|
||||
|
||||
console.log("Uploading image:", assetFile);
|
||||
|
||||
progressCallback({ status: UploaderStates.uploadingImage });
|
||||
|
||||
const imageResponse = await mediaUploadApi.UploadImage({
|
||||
@@ -24,7 +26,10 @@ export const uploadImage = async ({
|
||||
maybe_title: "char_frame_" + title,
|
||||
});
|
||||
|
||||
console.log("Image response:", imageResponse);
|
||||
|
||||
if (imageResponse == undefined) {
|
||||
console.log("Error: Could not upload image!");
|
||||
progressCallback({
|
||||
status: UploaderStates.imageCreateError,
|
||||
errorMessage: "Could not upload image!",
|
||||
@@ -33,6 +38,7 @@ export const uploadImage = async ({
|
||||
}
|
||||
|
||||
if (!imageResponse.success || !imageResponse.data) {
|
||||
console.log("Error:", imageResponse.errorMessage);
|
||||
progressCallback({
|
||||
status: UploaderStates.imageCreateError,
|
||||
errorMessage: imageResponse.errorMessage,
|
||||
@@ -40,5 +46,9 @@ export const uploadImage = async ({
|
||||
return;
|
||||
}
|
||||
|
||||
progressCallback({ status: UploaderStates.success, data: imageResponse.data });
|
||||
console.log("Upload successful:", imageResponse.data);
|
||||
progressCallback({
|
||||
status: UploaderStates.success,
|
||||
data: imageResponse.data,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ export * from "./LoadingSpinner";
|
||||
export * from "./NumberInput";
|
||||
export * from "./Pagination";
|
||||
export * from "./Pill";
|
||||
export * from "./Popover";
|
||||
export * from "./SearchFilter";
|
||||
export * from "./Select";
|
||||
export * from "./Slider";
|
||||
|
||||
@@ -66,7 +66,7 @@ class Editor {
|
||||
camera: THREE.PerspectiveCamera | null = null;
|
||||
render_camera: THREE.PerspectiveCamera | null = null;
|
||||
render_camera_aspect_ratio: CameraAspectRatio =
|
||||
CameraAspectRatio.HORIZONTAL_16_9;
|
||||
CameraAspectRatio.HORIZONTAL_3_2;
|
||||
renderer: THREE.WebGLRenderer | undefined;
|
||||
rawRenderer: THREE.WebGLRenderer | undefined;
|
||||
clock: THREE.Clock | undefined;
|
||||
@@ -253,7 +253,7 @@ class Editor {
|
||||
this.selectedCanvas = false;
|
||||
// Audio Engine Test.
|
||||
|
||||
this.render_camera_aspect_ratio = CameraAspectRatio.HORIZONTAL_16_9;
|
||||
this.render_camera_aspect_ratio = CameraAspectRatio.HORIZONTAL_3_2;
|
||||
this.render_width = this.getRenderDimensions().width;
|
||||
this.render_height = this.getRenderDimensions().height;
|
||||
|
||||
@@ -334,6 +334,20 @@ class Editor {
|
||||
aspectRatio: 16 / 9,
|
||||
};
|
||||
}
|
||||
case CameraAspectRatio.HORIZONTAL_3_2: {
|
||||
return {
|
||||
width: 1200,
|
||||
height: 800,
|
||||
aspectRatio: 3 / 2,
|
||||
};
|
||||
}
|
||||
case CameraAspectRatio.VERTICAL_2_3: {
|
||||
return {
|
||||
width: 800,
|
||||
height: 1200,
|
||||
aspectRatio: 2 / 3,
|
||||
};
|
||||
}
|
||||
case CameraAspectRatio.VERTICAL_9_16: {
|
||||
return {
|
||||
width: 720,
|
||||
@@ -641,6 +655,25 @@ class Editor {
|
||||
document.body.appendChild(this.stats.dom);
|
||||
}
|
||||
|
||||
public snapShotOfCurrentFrame(shouldDownload: boolean = true) {
|
||||
const snapshot = this.renderer?.domElement.toDataURL("image/png");
|
||||
if (!snapshot) {
|
||||
console.error("Error: Snapshot could not be created.");
|
||||
return null;
|
||||
}
|
||||
|
||||
const base64Snapshot = snapshot.split(",")[1];
|
||||
|
||||
if (shouldDownload) {
|
||||
const link = document.createElement("a");
|
||||
link.download = "scene-snapshot.png";
|
||||
link.href = snapshot;
|
||||
link.click();
|
||||
}
|
||||
|
||||
return base64Snapshot;
|
||||
}
|
||||
|
||||
public async newScene(sceneTitleInput: string) {
|
||||
this.activeScene.clear();
|
||||
this.audio_engine = new AudioEngine();
|
||||
@@ -948,16 +981,28 @@ class Editor {
|
||||
this.render_camera_aspect_ratio === CameraAspectRatio.HORIZONTAL_16_9
|
||||
? 1024
|
||||
: this.render_camera_aspect_ratio ===
|
||||
CameraAspectRatio.VERTICAL_9_16
|
||||
CameraAspectRatio.VERTICAL_9_16
|
||||
? 576
|
||||
: 1000;
|
||||
: this.render_camera_aspect_ratio ===
|
||||
CameraAspectRatio.HORIZONTAL_3_2
|
||||
? 900
|
||||
: this.render_camera_aspect_ratio ===
|
||||
CameraAspectRatio.VERTICAL_2_3
|
||||
? 600
|
||||
: 1000;
|
||||
const height =
|
||||
this.render_camera_aspect_ratio === CameraAspectRatio.HORIZONTAL_16_9
|
||||
? 576
|
||||
: this.render_camera_aspect_ratio ===
|
||||
CameraAspectRatio.VERTICAL_9_16
|
||||
CameraAspectRatio.VERTICAL_9_16
|
||||
? 1024
|
||||
: 1000;
|
||||
: this.render_camera_aspect_ratio ===
|
||||
CameraAspectRatio.HORIZONTAL_3_2
|
||||
? 600
|
||||
: this.render_camera_aspect_ratio ===
|
||||
CameraAspectRatio.VERTICAL_2_3
|
||||
? 900
|
||||
: 1000;
|
||||
|
||||
this.rawRenderer.setSize(width, height);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import { SceneContainer } from "./comps/SceneContainer";
|
||||
import { AspectRatioMenu } from "./comps/AspectRatioMenu";
|
||||
import { Outliner } from "./comps/Outliner";
|
||||
import { CameraAspectRatio } from "./enums";
|
||||
import { PromptBox } from "./comps/PromptBox";
|
||||
|
||||
export const PageEditor = () => {
|
||||
useSignals();
|
||||
@@ -112,7 +113,6 @@ export const PageEditor = () => {
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<ControlsTopButtons />
|
||||
<Controls3D />
|
||||
<AspectRatioMenu />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -134,7 +134,7 @@ export const PageEditor = () => {
|
||||
<Outliner />
|
||||
<PreviewEngineCamera />
|
||||
</div>
|
||||
<ControlsVideo />
|
||||
<PromptBox />
|
||||
<ControlPanelSceneObject />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ export const Wizard = () => {
|
||||
onNext: () => {
|
||||
resetSceneGenerationMetadata();
|
||||
editorEngine?.changeRenderCameraAspectRatio(
|
||||
CameraAspectRatio.HORIZONTAL_16_9,
|
||||
CameraAspectRatio.HORIZONTAL_3_2,
|
||||
);
|
||||
editorEngine?.newScene(textInput.value);
|
||||
showWizard.value = "end";
|
||||
|
||||
@@ -18,13 +18,21 @@ export const AspectRatioMenu = () => {
|
||||
? faRectangle
|
||||
: cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16
|
||||
? faRectangleVertical
|
||||
: faSquare;
|
||||
: cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2
|
||||
? faRectangle
|
||||
: cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3
|
||||
? faRectangleVertical
|
||||
: faSquare;
|
||||
const buttonText =
|
||||
cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_16_9
|
||||
? "16:9 Horizontal"
|
||||
: cameraAspectRatio.value === CameraAspectRatio.VERTICAL_9_16
|
||||
? "9:16 Vertical"
|
||||
: "1:1 Squared";
|
||||
: cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2
|
||||
? "3:2 Horizontal"
|
||||
: cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3
|
||||
? "2:3 Vertical"
|
||||
: "1:1 Squared";
|
||||
|
||||
const handleChangeAspectRatio = (newRatio: CameraAspectRatio) => {
|
||||
Queue.publish({
|
||||
@@ -52,6 +60,26 @@ export const AspectRatioMenu = () => {
|
||||
onClick: () =>
|
||||
handleChangeAspectRatio(CameraAspectRatio.HORIZONTAL_16_9),
|
||||
},
|
||||
{
|
||||
label: "3:2",
|
||||
icon: faRectangle,
|
||||
className: "pl-4",
|
||||
description: "Horizontal",
|
||||
selected:
|
||||
cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2,
|
||||
onClick: () =>
|
||||
handleChangeAspectRatio(CameraAspectRatio.HORIZONTAL_3_2),
|
||||
},
|
||||
{
|
||||
label: "2:3",
|
||||
icon: faRectangleVertical,
|
||||
className: "pl-4",
|
||||
description: "Vertical",
|
||||
selected:
|
||||
cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3,
|
||||
onClick: () =>
|
||||
handleChangeAspectRatio(CameraAspectRatio.VERTICAL_2_3),
|
||||
},
|
||||
{
|
||||
label: "9:16",
|
||||
icon: faRectangleVertical,
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ export const ControlsTopButtons = () => {
|
||||
const handleResetScene = () => {
|
||||
resetSceneGenerationMetadata();
|
||||
editorEngine?.changeRenderCameraAspectRatio(
|
||||
CameraAspectRatio.HORIZONTAL_16_9,
|
||||
CameraAspectRatio.HORIZONTAL_3_2,
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { EngineContext } from "~/pages/PageEnigma/contexts/EngineContext";
|
||||
import { useContext } from "react";
|
||||
import { uploadImage } from "~/components/reusable/UploadModalMedia/uploadImage";
|
||||
import {
|
||||
faPlus,
|
||||
faCamera,
|
||||
faSave,
|
||||
faSparkles,
|
||||
faUpload,
|
||||
faImages,
|
||||
faDownload,
|
||||
faSpinnerThird,
|
||||
faTimes,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import {
|
||||
faRectangleWide,
|
||||
faRectangleVertical,
|
||||
faSquare,
|
||||
faRectangle,
|
||||
} from "@fortawesome/pro-regular-svg-icons";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { PopoverItem, PopoverMenu } from "~/components/reusable/Popover";
|
||||
import { Button } from "~/components";
|
||||
import { CameraAspectRatio } from "~/pages/PageEnigma/enums";
|
||||
import { cameraAspectRatio } from "~/pages/PageEnigma/signals";
|
||||
import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
|
||||
import Queue from "~/pages/PageEnigma/Queue/Queue";
|
||||
import { toEngineActions } from "~/pages/PageEnigma/Queue/toEngineActions";
|
||||
|
||||
interface ReferenceImage {
|
||||
id: string;
|
||||
url: string;
|
||||
file: File;
|
||||
mediaToken: string;
|
||||
}
|
||||
import { EngineApi } from "~/Classes/ApiManager/EngineApi";
|
||||
import { scene } from "~/signals/scene";
|
||||
import { UploaderStates } from "~/enums/UploaderStates";
|
||||
|
||||
export const PromptBox = () => {
|
||||
useSignals();
|
||||
const editorEngine = useContext(EngineContext);
|
||||
const [prompt, setPrompt] = useState("");
|
||||
const [isEnqueueing, setisEnqueueing] = useState(false);
|
||||
const [referenceImages, setReferenceImages] = useState<ReferenceImage[]>([]);
|
||||
const [aspectRatioList, setAspectRatioList] = useState<PopoverItem[]>([
|
||||
{
|
||||
label: "3:2",
|
||||
selected: true,
|
||||
icon: <FontAwesomeIcon icon={faRectangle} className="h-4 w-4" />,
|
||||
},
|
||||
{
|
||||
label: "2:3",
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faRectangleVertical} className="h-4 w-4" />,
|
||||
},
|
||||
{
|
||||
label: "1:1",
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faSquare} className="h-4 w-4" />,
|
||||
},
|
||||
{
|
||||
label: "16:9",
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faRectangleWide} className="h-4 w-4" />,
|
||||
},
|
||||
]);
|
||||
const [cameraList, setCameraList] = useState<PopoverItem[]>([
|
||||
{
|
||||
label: "Main View",
|
||||
selected: true,
|
||||
icon: <FontAwesomeIcon icon={faCamera} className="h-4 w-4" />,
|
||||
},
|
||||
{
|
||||
label: "Camera 2",
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faCamera} className="h-4 w-4" />,
|
||||
},
|
||||
]);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (textareaRef.current) {
|
||||
textareaRef.current.style.height = "auto";
|
||||
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
||||
}
|
||||
}, [prompt]);
|
||||
|
||||
// Update aspect ratio list based on the current cameraAspectRatio signal
|
||||
useEffect(() => {
|
||||
setAspectRatioList((prev) =>
|
||||
prev.map((item) => ({
|
||||
...item,
|
||||
selected:
|
||||
(item.label === "16:9" &&
|
||||
cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_16_9) ||
|
||||
(item.label === "3:2" &&
|
||||
cameraAspectRatio.value === CameraAspectRatio.HORIZONTAL_3_2) ||
|
||||
(item.label === "2:3" &&
|
||||
cameraAspectRatio.value === CameraAspectRatio.VERTICAL_2_3) ||
|
||||
(item.label === "1:1" &&
|
||||
cameraAspectRatio.value === CameraAspectRatio.SQUARE_1_1),
|
||||
})),
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [cameraAspectRatio.value]);
|
||||
|
||||
const handleCameraSelect = (selectedItem: PopoverItem) => {
|
||||
setCameraList((prev) =>
|
||||
prev.map((item) => ({
|
||||
...item,
|
||||
selected: item.label === selectedItem.label,
|
||||
})),
|
||||
);
|
||||
};
|
||||
|
||||
const handleAddCamera = () => {
|
||||
const newIndex = cameraList.length + 1;
|
||||
setCameraList((prev) => [
|
||||
...prev,
|
||||
{
|
||||
label: `Camera ${newIndex}`,
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faCamera} className="h-4 w-4" />,
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
const handleAspectRatioSelect = (selectedItem: PopoverItem) => {
|
||||
setAspectRatioList((prev) =>
|
||||
prev.map((item) => ({
|
||||
...item,
|
||||
selected: item.label === selectedItem.label,
|
||||
})),
|
||||
);
|
||||
|
||||
// Map the selected label to the corresponding CameraAspectRatio enum value
|
||||
let newRatio: CameraAspectRatio;
|
||||
switch (selectedItem.label) {
|
||||
case "16:9":
|
||||
newRatio = CameraAspectRatio.HORIZONTAL_16_9;
|
||||
break;
|
||||
case "3:2":
|
||||
newRatio = CameraAspectRatio.HORIZONTAL_3_2;
|
||||
break;
|
||||
case "2:3":
|
||||
newRatio = CameraAspectRatio.VERTICAL_2_3;
|
||||
break;
|
||||
case "1:1":
|
||||
newRatio = CameraAspectRatio.SQUARE_1_1;
|
||||
break;
|
||||
default:
|
||||
newRatio = CameraAspectRatio.HORIZONTAL_16_9;
|
||||
}
|
||||
|
||||
// Publish the change to the engine
|
||||
Queue.publish({
|
||||
queueName: QueueNames.TO_ENGINE,
|
||||
action: toEngineActions.CHANGE_CAMERA_ASPECT_RATIO,
|
||||
data: newRatio,
|
||||
});
|
||||
};
|
||||
|
||||
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = event.target.files;
|
||||
if (files) {
|
||||
Array.from(files).forEach((file) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
uploadImage({
|
||||
title: `reference-image-${Math.random().toString(36).substring(2, 15)}`,
|
||||
assetFile: file,
|
||||
progressCallback: (newState) => {
|
||||
console.debug("Upload progress:", newState.data);
|
||||
if (newState.status === UploaderStates.success && newState.data) {
|
||||
const referenceImage: ReferenceImage = {
|
||||
id: Math.random().toString(36).substring(7),
|
||||
url: reader.result as string,
|
||||
file,
|
||||
mediaToken: newState.data || "",
|
||||
};
|
||||
setReferenceImages((prev) => [...prev, referenceImage]);
|
||||
console.log("Reference image added:", referenceImage);
|
||||
} else {
|
||||
console.error("No data from uploadImage");
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveReference = (id: string) => {
|
||||
setReferenceImages((prev) => prev.filter((img) => img.id !== id));
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = "";
|
||||
}
|
||||
};
|
||||
|
||||
const handleUploadClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
const handleLibrarySelect = () => {
|
||||
console.log("Opening library selector");
|
||||
};
|
||||
|
||||
const handleAction = (action: string) => {
|
||||
switch (action) {
|
||||
case "upload":
|
||||
handleUploadClick();
|
||||
break;
|
||||
case "library":
|
||||
handleLibrarySelect();
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown action:", action);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
|
||||
e.preventDefault();
|
||||
const pastedText = e.clipboardData.getData("text").trim();
|
||||
setPrompt(pastedText);
|
||||
};
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setPrompt(e.target.value);
|
||||
};
|
||||
|
||||
const handleEnqueue = async () => {
|
||||
if (!prompt.trim()) return;
|
||||
|
||||
if (editorEngine) {
|
||||
editorEngine.positive_prompt = prompt;
|
||||
|
||||
const engineApi = new EngineApi();
|
||||
const snapshot = editorEngine.snapShotOfCurrentFrame(false);
|
||||
|
||||
const snapshotResult = await engineApi.uploadSceneSnapshot({
|
||||
screenshot: snapshot || "",
|
||||
sceneMediaToken: "",
|
||||
});
|
||||
|
||||
await engineApi.enqueueImageGeneration({
|
||||
prompt: prompt,
|
||||
snapshotMediaToken: snapshotResult.data || "",
|
||||
additionalImages: referenceImages.map((image) => image.mediaToken),
|
||||
});
|
||||
|
||||
setisEnqueueing(true);
|
||||
try {
|
||||
// Here we would pass both the prompt and reference images to the generation
|
||||
console.log(
|
||||
"Enqueuing with prompt:",
|
||||
prompt,
|
||||
"and reference images:",
|
||||
referenceImages,
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
} finally {
|
||||
setisEnqueueing(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
handleEnqueue();
|
||||
}
|
||||
};
|
||||
|
||||
// Get the current aspect ratio icon based on the cameraAspectRatio signal
|
||||
const getCurrentAspectRatioIcon = () => {
|
||||
switch (cameraAspectRatio.value) {
|
||||
case CameraAspectRatio.HORIZONTAL_16_9:
|
||||
return faRectangleWide;
|
||||
case CameraAspectRatio.HORIZONTAL_3_2:
|
||||
return faRectangle;
|
||||
case CameraAspectRatio.VERTICAL_2_3:
|
||||
return faRectangleVertical;
|
||||
case CameraAspectRatio.VERTICAL_9_16:
|
||||
return faRectangleVertical;
|
||||
case CameraAspectRatio.SQUARE_1_1:
|
||||
return faSquare;
|
||||
default:
|
||||
return faRectangleWide;
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveFrame = async () => {
|
||||
if (editorEngine) {
|
||||
const snapshot = editorEngine.snapShotOfCurrentFrame(false);
|
||||
const engineApi = new EngineApi();
|
||||
const result = await engineApi.uploadSceneSnapshot({
|
||||
screenshot: snapshot || "",
|
||||
sceneMediaToken: "",
|
||||
});
|
||||
console.log(result);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownloadFrame = () => {
|
||||
if (editorEngine) {
|
||||
editorEngine.snapShotOfCurrentFrame(true);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="absolute bottom-4 left-1/2 flex -translate-x-1/2 flex-col gap-3">
|
||||
{referenceImages.length > 0 && (
|
||||
<div className="flex w-full gap-2">
|
||||
{referenceImages.map((image) => (
|
||||
<div
|
||||
key={image.id}
|
||||
className="glass relative aspect-square w-20 rounded-lg"
|
||||
>
|
||||
<img
|
||||
src={image.url}
|
||||
alt="Reference"
|
||||
className="h-full w-full rounded-lg object-cover"
|
||||
/>
|
||||
<button
|
||||
onClick={() => handleRemoveReference(image.id)}
|
||||
className="absolute right-[2px] top-[2px] flex h-5 w-5 items-center justify-center rounded-full bg-black/40 text-white backdrop-blur-md transition-colors hover:bg-black"
|
||||
>
|
||||
<FontAwesomeIcon icon={faTimes} className="h-2.5 w-2.5" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="glass w-[730px] rounded-xl p-4">
|
||||
<input
|
||||
type="file"
|
||||
ref={fileInputRef}
|
||||
className="hidden"
|
||||
accept="image/*"
|
||||
onChange={handleFileUpload}
|
||||
multiple
|
||||
/>
|
||||
<div className="flex justify-center gap-2">
|
||||
<PopoverMenu
|
||||
mode="button"
|
||||
panelTitle="Add Image"
|
||||
items={[
|
||||
{
|
||||
label: "Upload from device",
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faUpload} className="h-4 w-4" />,
|
||||
action: "upload",
|
||||
},
|
||||
{
|
||||
label: "Choose from library",
|
||||
selected: false,
|
||||
icon: <FontAwesomeIcon icon={faImages} className="h-4 w-4" />,
|
||||
action: "library",
|
||||
disabled: true,
|
||||
},
|
||||
]}
|
||||
onAction={handleAction}
|
||||
showIconsInList
|
||||
buttonClassName="backdrop-blur-none bg-transparent hover:bg-transparent py-1.5 px-0 pr-1 m-0 hover:opacity-50 transition-opacity duration-100 ring-0 border-none focus:ring-0 outline-none"
|
||||
triggerIcon={<FontAwesomeIcon icon={faPlus} className="text-xl" />}
|
||||
/>
|
||||
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
rows={1}
|
||||
placeholder="Describe your image..."
|
||||
className="text-md mb-2 max-h-[5.5em] flex-1 resize-none overflow-y-auto rounded bg-transparent pb-2 pr-2 pt-1 text-white placeholder-white placeholder:text-white/60 focus:outline-none"
|
||||
value={prompt}
|
||||
onChange={handleChange}
|
||||
onPaste={handlePaste}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<PopoverMenu
|
||||
items={aspectRatioList}
|
||||
onSelect={handleAspectRatioSelect}
|
||||
mode="toggle"
|
||||
panelTitle="Aspect Ratio"
|
||||
showIconsInList
|
||||
triggerIcon={
|
||||
<FontAwesomeIcon
|
||||
icon={getCurrentAspectRatioIcon()}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<PopoverMenu
|
||||
items={cameraList}
|
||||
onSelect={handleCameraSelect}
|
||||
onAdd={handleAddCamera}
|
||||
triggerIcon={
|
||||
<FontAwesomeIcon icon={faCamera} className="h-4 w-4" />
|
||||
}
|
||||
showAddButton
|
||||
showIconsInList
|
||||
mode="toggle"
|
||||
panelTitle="Camera"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
className="flex items-center border-none bg-[#5F5F68]/60 px-3 text-sm text-white backdrop-blur-lg hover:bg-[#5F5F68]/90"
|
||||
variant="secondary"
|
||||
icon={faDownload}
|
||||
onClick={handleDownloadFrame}
|
||||
>
|
||||
Download frame
|
||||
</Button>
|
||||
<Button
|
||||
className="flex items-center border-none bg-[#5F5F68]/60 px-3 text-sm text-white backdrop-blur-lg hover:bg-[#5F5F68]/90"
|
||||
variant="secondary"
|
||||
icon={faSave}
|
||||
onClick={handleSaveFrame}
|
||||
>
|
||||
Save frame
|
||||
</Button>
|
||||
<Button
|
||||
className="flex items-center border-none bg-brand-primary px-3 text-sm text-white disabled:cursor-not-allowed disabled:opacity-50"
|
||||
icon={!isEnqueueing ? faSparkles : undefined}
|
||||
onClick={handleEnqueue}
|
||||
disabled={isEnqueueing || !prompt.trim()}
|
||||
>
|
||||
{isEnqueueing ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faSpinnerThird}
|
||||
className="animate-spin text-lg"
|
||||
/>
|
||||
) : (
|
||||
"Generate"
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./PromptBox";
|
||||
@@ -22,10 +22,10 @@ export const Letterbox = ({
|
||||
}) => {
|
||||
useSignals();
|
||||
|
||||
if (editorState.value !== EditorStates.CAMERA_VIEW || !isShowing) {
|
||||
//case of Letterbox should not show
|
||||
return;
|
||||
}
|
||||
// if (editorState.value !== EditorStates.CAMERA_VIEW || !isShowing) {
|
||||
// //case of Letterbox should not show
|
||||
// return;
|
||||
// }
|
||||
|
||||
const matteOri = getMatteOrientation({
|
||||
camAspect: cameraAspectRatio.value,
|
||||
@@ -73,14 +73,14 @@ const Matte = ({
|
||||
if (matteOri === MatteOrientation.TOP_BOTTOM) {
|
||||
return (
|
||||
<div
|
||||
className="h-20 w-full bg-brand-secondary/50 brightness-75"
|
||||
className="h-20 w-full bg-black/30 brightness-75"
|
||||
style={{ height: `${height}px` }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className="h-full w-80 bg-brand-secondary/50 brightness-75"
|
||||
className="h-full w-80 bg-black/30 brightness-75"
|
||||
style={{ width: `${width}px` }}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -25,6 +25,16 @@ export const getMatteOrientation = ({
|
||||
? MatteOrientation.TOP_BOTTOM
|
||||
: MatteOrientation.LEFT_RIGHT;
|
||||
}
|
||||
case CameraAspectRatio.VERTICAL_2_3: {
|
||||
return (height / 3) * 2 - width >= 0
|
||||
? MatteOrientation.TOP_BOTTOM
|
||||
: MatteOrientation.LEFT_RIGHT;
|
||||
}
|
||||
case CameraAspectRatio.HORIZONTAL_3_2: {
|
||||
return (width / 3) * 2 - height >= 0
|
||||
? MatteOrientation.LEFT_RIGHT
|
||||
: MatteOrientation.TOP_BOTTOM;
|
||||
}
|
||||
case CameraAspectRatio.HORIZONTAL_16_9:
|
||||
default: {
|
||||
return (width / 16) * 9 - height >= 0
|
||||
@@ -58,6 +68,12 @@ export const calcMatteWidth = ({
|
||||
case CameraAspectRatio.VERTICAL_9_16: {
|
||||
return (width - (height / 16) * 9) / 2;
|
||||
}
|
||||
case CameraAspectRatio.HORIZONTAL_3_2: {
|
||||
return (width - (height / 2) * 3) / 2;
|
||||
}
|
||||
case CameraAspectRatio.VERTICAL_2_3: {
|
||||
return (width - (height / 3) * 2) / 2;
|
||||
}
|
||||
default: {
|
||||
return undefined;
|
||||
}
|
||||
@@ -88,6 +104,12 @@ export const calcMatteHeight = ({
|
||||
case CameraAspectRatio.VERTICAL_9_16: {
|
||||
return (height - (width / 9) * 16) / 2;
|
||||
}
|
||||
case CameraAspectRatio.HORIZONTAL_3_2: {
|
||||
return (height - (width / 3) * 2) / 2;
|
||||
}
|
||||
case CameraAspectRatio.VERTICAL_2_3: {
|
||||
return (height - (width / 2) * 3) / 2;
|
||||
}
|
||||
default: {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import { ReactNode } from "react";
|
||||
import { FontAwesomeIconProps } from "@fortawesome/react-fontawesome";
|
||||
import { faBrush, faCatSpace } from "@fortawesome/pro-solid-svg-icons";
|
||||
import {
|
||||
faAlienMonster,
|
||||
faCatSpace,
|
||||
faCloud,
|
||||
faCube,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
|
||||
import { TabTitles } from "~/enums";
|
||||
import { StylizeTab } from "~/pages/PageEnigma/comps/SidePanelTabs/tabComps/StylizeTab/StylizeTab";
|
||||
import { CartoonsTab } from "../SidePanelTabs/tabComps/CharactersComboTabs";
|
||||
import { ObjectsTab } from "../SidePanelTabs/tabComps/ObjectsTab";
|
||||
import { SkyboxesTab } from "../SidePanelTabs/tabComps/SkyboxesTab";
|
||||
import { CreaturesTab } from "../SidePanelTabs/tabComps/CreaturesTab";
|
||||
|
||||
export interface TabItem {
|
||||
icon: FontAwesomeIconProps["icon"];
|
||||
@@ -19,9 +26,21 @@ export const tabList: TabItem[] = [
|
||||
component: <CartoonsTab />,
|
||||
},
|
||||
|
||||
// {
|
||||
// icon: faBrush,
|
||||
// title: TabTitles.STYLIZE,
|
||||
// component: <StylizeTab />,
|
||||
// }
|
||||
{
|
||||
icon: faCube,
|
||||
title: TabTitles.OBJECTS,
|
||||
component: <ObjectsTab />,
|
||||
},
|
||||
|
||||
{
|
||||
icon: faCloud,
|
||||
title: TabTitles.SKYBOXES,
|
||||
component: <SkyboxesTab />,
|
||||
},
|
||||
|
||||
{
|
||||
icon: faAlienMonster,
|
||||
title: TabTitles.OBJECTS_CREATURES,
|
||||
component: <CreaturesTab />,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -8,4 +8,6 @@ export enum CameraAspectRatio {
|
||||
HORIZONTAL_16_9 = "horizontal_16_9",
|
||||
VERTICAL_9_16 = "vertical_9_16",
|
||||
SQUARE_1_1 = "SQUARE_1_1",
|
||||
HORIZONTAL_3_2 = "horizontal_3_2",
|
||||
VERTICAL_2_3 = "vertical_2_3",
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CameraAspectRatio, EditorStates } from "~/pages/PageEnigma/enums";
|
||||
export const editorState = signal<EditorStates>(EditorStates.EDIT);
|
||||
|
||||
export const cameraAspectRatio = signal<CameraAspectRatio>(
|
||||
CameraAspectRatio.HORIZONTAL_16_9,
|
||||
CameraAspectRatio.HORIZONTAL_3_2,
|
||||
);
|
||||
|
||||
export const setCameraAspectRatio = (newAspectRatio: CameraAspectRatio) => {
|
||||
|
||||
@@ -14,4 +14,9 @@
|
||||
.filter-tab:disabled {
|
||||
@apply border-transparent bg-ui-controls-button/50 hover:border-transparent disabled:text-white/30;
|
||||
}
|
||||
|
||||
.glass {
|
||||
@apply relative border border-white/10 shadow-lg backdrop-blur-xl transition-colors duration-300;
|
||||
@apply bg-ui-controls/50 !important;
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+12
@@ -9,6 +9,7 @@
|
||||
"@awesome.me/kit-fde2be5eb0": "^1.0.7",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
@@ -1423,6 +1424,17 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/pro-regular-svg-icons": {
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-regular-svg-icons/-/6.7.2/pro-regular-svg-icons-6.7.2.tgz",
|
||||
"integrity": "sha512-cJolK4K/s56mHAqOyno24SmjviHqSqG9ZfckBKCpWjJlgDexi61EfET5wWbmmEot6/BqasFjw9S6tudFQUL/PQ==",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/pro-solid-svg-icons": {
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-solid-svg-icons/-/6.7.2/pro-solid-svg-icons-6.7.2.tgz",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"@awesome.me/kit-fde2be5eb0": "^1.0.7",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
|
||||
@@ -28,21 +28,21 @@ export default {
|
||||
|
||||
"brand-primary": {
|
||||
//sunglo
|
||||
DEFAULT: "#e66462", //=500
|
||||
"50": "#fdf3f3",
|
||||
"100": "#fce4e4",
|
||||
"200": "#facfce",
|
||||
"300": "#f6acab",
|
||||
"400": "#ef7c7a",
|
||||
"500": "#e66462",
|
||||
"600": "#cf3533",
|
||||
"700": "#ae2927",
|
||||
"800": "#902624",
|
||||
"900": "#782524",
|
||||
"950": "#410f0e",
|
||||
DEFAULT: "#2d81ff", //=500
|
||||
"50": "#eef6ff",
|
||||
"100": "#d9ebff",
|
||||
"200": "#bcdcff",
|
||||
"300": "#8ec7ff",
|
||||
"400": "#59a7ff",
|
||||
"500": "#2d81ff",
|
||||
"600": "#1b63f5",
|
||||
"700": "#144ee1",
|
||||
"800": "#173fb6",
|
||||
"900": "#19398f",
|
||||
"950": "#142457",
|
||||
},
|
||||
"brand-secondary": {
|
||||
DEFAULT: "#2E2E2E",
|
||||
DEFAULT: "#3E3E41",
|
||||
"50": "#f6f6f6",
|
||||
"100": "#e7e7e7",
|
||||
"200": "#d1d1d1",
|
||||
@@ -53,7 +53,7 @@ export default {
|
||||
"700": "#4f4f4f",
|
||||
"800": "#454545",
|
||||
"900": "#3d3d3d",
|
||||
"950": "#2e2e2e",
|
||||
"950": "#3E3E41",
|
||||
},
|
||||
"brand-tertiary": {
|
||||
//Aquamarine Blue
|
||||
@@ -103,7 +103,7 @@ export default {
|
||||
},
|
||||
|
||||
action: {
|
||||
DEFAULT: "#2E2E2E",
|
||||
DEFAULT: "#3E3E41",
|
||||
"50": "#f6f6f6",
|
||||
"100": "#e7e7e7",
|
||||
"200": "#d1d1d1",
|
||||
@@ -114,7 +114,7 @@ export default {
|
||||
"700": "#4f4f4f",
|
||||
"800": "#454545",
|
||||
"900": "#3d3d3d",
|
||||
"950": "#2e2e2e",
|
||||
"950": "#3E3E41",
|
||||
},
|
||||
|
||||
character: {
|
||||
@@ -123,7 +123,7 @@ export default {
|
||||
clip: "#7E92DA",
|
||||
groupBg: "#2B3448",
|
||||
titleBg: "#384763",
|
||||
frame: "#6B83D8"
|
||||
frame: "#6B83D8",
|
||||
},
|
||||
camera: {
|
||||
unselected: "#466C7C",
|
||||
@@ -159,7 +159,7 @@ export default {
|
||||
},
|
||||
assets: {
|
||||
background: "#242424",
|
||||
selectedTab: "#2E2E2E",
|
||||
selectedTab: "#3E3E41",
|
||||
},
|
||||
dnd: {
|
||||
canDrop: "#46936E",
|
||||
@@ -174,8 +174,8 @@ export default {
|
||||
background: "#242424",
|
||||
panel: "#1F1F1F",
|
||||
"panel-border": "#3F3F3F",
|
||||
controls: "#2E2E2E",
|
||||
"controls-button": "#2E2E2E",
|
||||
controls: "#3E3E41",
|
||||
"controls-button": "#3E3E41",
|
||||
divider: "#515168",
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user