-
+
+
-
{clampedProgress}%
+
{years}
Years
-
you're on track to hit it by July 2029
);
};
diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx
index e9946ae..5ce5da8 100644
--- a/app/src/components/ui/analysis/ThroughputSummary.tsx
+++ b/app/src/components/ui/analysis/ThroughputSummary.tsx
@@ -1,102 +1,23 @@
-import React from "react";
-import { Line } from "react-chartjs-2";
import {
- Chart as ChartJS,
- LineElement,
- CategoryScale,
- LinearScale,
- PointElement,
-} from "chart.js";
-import { PowerIcon, ThroughputSummaryIcon } from "../../icons/analysis";
-import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
+ ProductionCapacityIcon,
+ ThroughputSummaryIcon,
+} from "../../icons/analysis";
-ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement);
-
-// Helper function to generate random colors
-const getRandomColor = () => {
- const letters = "0123456789ABCDEF";
- let color = "#";
- for (let i = 0; i < 6; i++) {
- color += letters[Math.floor(Math.random() * 16)];
- }
- return color;
-};
-
-const ThroughputSummary = () => {
- // Define all data internally within the component
- const timeRange = {
- startTime: "08:00 AM",
- endTime: "09:00 AM",
- };
-
- const throughputData = {
- labels: ["08:00", "08:10", "08:20", "08:30", "08:40", "08:50", "09:00"],
- data: [100, 120, 110, 130, 125, 128, 132],
- totalThroughput: 1240,
- assetUsage: 85,
- };
-
- const energyConsumption = {
- energyConsumed: 456,
- unit: "KWH",
- };
-
- // Dynamic shift data
- const shiftUtilization = [
- { shift: 1, percentage: 30 },
- { shift: 2, percentage: 40 },
- { shift: 3, percentage: 30 },
- ];
-
- // Chart data configuration
- const chartData = {
- labels: throughputData.labels,
- datasets: [
- {
- label: "Units/hour",
- data: throughputData.data,
- borderColor: "#B392F0",
- tension: 0.4,
- pointRadius: 0, // Hide points
- },
- ],
- };
-
- const chartOptions = {
- responsive: true,
- scales: {
- x: {
- grid: {
- display: false,
- },
- ticks: {
- display: false,
- color: "#fff",
- },
- },
- y: {
- grid: {
- display: false,
- },
- ticks: {
- display: false,
- color: "#fff",
- },
- },
- },
- plugins: {
- legend: {
- display: false,
- },
- tooltip: {
- enabled: true,
- },
- },
- };
+const ProductionCapacity = ({
+ progressPercent = 50,
+ avgProcessTime = "28.4 Secs/unit",
+ machineUtilization = "78%",
+ throughputValue = 128,
+ timeRange = { startTime: "08:00 AM", endTime: "09:00 AM" },
+}) => {
+ const totalBars = 6;
+ const barsToFill = Math.floor((progressPercent / 100) * totalBars);
+ const partialFillPercent =
+ ((progressPercent / 100) * totalBars - barsToFill) * 100;
return (
-
-
+
+
Throughput Summary
@@ -111,63 +32,34 @@ const ThroughputSummary = () => {
- {throughputData.totalThroughput}{" "}
- Units/hour
+ {throughputValue} Units/hour
-
-
-
Asset usage
-
{throughputData.assetUsage}%
-
-
+
+ {/* Dynamic Progress Bar */}
+
+ {[...Array(totalBars)].map((_, i) => (
+
+ {i < barsToFill ? (
+
+ ) : i === barsToFill ? (
+
+ ) : null}
+
+ ))}
-
-
-
Energy Consumption
-
-
-
-
{energyConsumption.energyConsumed}
-
{energyConsumption.unit}
-
-
+
+
+ Avg. Process Time
+ {avgProcessTime}
-
-
Shift Utilization
-
-
{throughputData.assetUsage}%
-
-
- {/* Dynamically create progress bars based on shiftUtilization array */}
- {shiftUtilization.map((shift, index) => (
-
- ))}
-
-
-
- {/* Dynamically create shift indicators with random colors */}
- {shiftUtilization.map((shift, index) => (
-
-
-
-
- ))}
-
-
+
+ Machine Utilization
+ {machineUtilization}
@@ -175,4 +67,4 @@ const ThroughputSummary = () => {
);
};
-export default ThroughputSummary;
+export default ProductionCapacity;
diff --git a/app/src/components/ui/features/RenameTooltip.tsx b/app/src/components/ui/features/RenameTooltip.tsx
new file mode 100644
index 0000000..180ba85
--- /dev/null
+++ b/app/src/components/ui/features/RenameTooltip.tsx
@@ -0,0 +1,50 @@
+import React, { useState } from "react";
+import { RenameIcon } from "../../icons/ContextMenuIcons";
+import {
+ useLeftData,
+ useTopData,
+} from "../../../store/visualization/useZone3DWidgetStore";
+
+type RenameTooltipProps = {
+ name: string;
+ onSubmit: (newName: string) => void;
+};
+
+const RenameTooltip: React.FC
= ({ name, onSubmit }) => {
+ const [value, setValue] = useState(name);
+
+ const { top } = useTopData();
+ const { left } = useLeftData();
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ onSubmit(value.trim());
+ };
+
+ return (
+
+ );
+};
+
+export default RenameTooltip;
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
index eebcaa7..b5403e1 100644
--- a/app/src/components/ui/list/List.tsx
+++ b/app/src/components/ui/list/List.tsx
@@ -27,6 +27,7 @@ interface ZoneItem {
id: string;
name: string;
assets?: Asset[];
+ active?: boolean;
}
interface ListProps {
@@ -157,7 +158,7 @@ const List: React.FC = ({ items = [], remove }) => {
{items?.map((item) => (
-
+
-
{/* Tabs */}
-
- {["all", "info", "warning", "error"].map((type) => (
-
setSelectedTab(type as any)}
- >
- {`${type.charAt(0).toUpperCase() + type.slice(1)} Logs`}
-
- ))}
+
+
+ {["all", "info", "warning", "error"].map((type) => (
+ setSelectedTab(type as any)}
+ >
+ {`${type.charAt(0).toUpperCase() + type.slice(1)} Logs`}
+
+ ))}
+
+
+ clear
+
{/* Log Entries */}
- {filteredLogs.map((log) => (
-
-
{getLogIcon(log.type)}
-
-
{log.message}
-
- {formatTimestamp(log.timestamp)}
+ {filteredLogs.length > 0 ? (
+ filteredLogs.map((log) => (
+
+
{GetLogIcon(log.type)}
+
+
{log.message}
+
+ {formatTimestamp(log.timestamp)}
+
-
- ))}
+ ))
+ ) : (
+
There are no logs to display at the moment.
+ )}
diff --git a/app/src/components/ui/log/LoggerContext.tsx b/app/src/components/ui/log/LoggerContext.tsx
index f323b93..6e63a55 100644
--- a/app/src/components/ui/log/LoggerContext.tsx
+++ b/app/src/components/ui/log/LoggerContext.tsx
@@ -1,6 +1,7 @@
-import React, { createContext, useContext, useState, useCallback } from "react";
+import React, { createContext, useContext, useState, useCallback, useMemo } from "react";
+import { MathUtils } from "three";
-export type LogType = "log" | "info" | "warning" | "error";
+export type LogType = "log" | "info" | "warning" | "error" | "success";
export interface LogEntry {
id: string;
@@ -18,6 +19,7 @@ interface LoggerContextValue {
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
+ success: (message: string) => void;
clear: () => void;
}
@@ -29,37 +31,34 @@ export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({
const [logs, setLogs] = useState
([]);
const [isLogListVisible, setIsLogListVisible] = useState(false);
- const generateId = useCallback(
- () => Math.random().toString(36).substring(2, 9),
- []
- );
-
const addLog = useCallback(
(type: LogType, message: string) => {
const newLog: LogEntry = {
- id: generateId(),
+ id: MathUtils.generateUUID(),
type,
message,
timestamp: new Date(),
};
setLogs((prevLogs) => [...prevLogs, newLog]);
},
- [generateId]
+ []
);
- const loggerMethods: LoggerContextValue = {
- logs,
- setLogs,
- isLogListVisible,
- setIsLogListVisible,
- log: (message: string) => addLog("log", message),
- info: (message: string) => addLog("info", message),
- warn: (message: string) => addLog("warning", message),
- error: (message: string) => addLog("error", message),
- clear: () => {
- setLogs([]);
- },
- };
+ const loggerMethods: LoggerContextValue = useMemo(
+ () => ({
+ logs,
+ setLogs,
+ isLogListVisible,
+ setIsLogListVisible,
+ log: (message: string) => addLog("log", message),
+ info: (message: string) => addLog("info", message),
+ warn: (message: string) => addLog("warning", message),
+ error: (message: string) => addLog("error", message),
+ success: (message: string) => addLog("success", message),
+ clear: () => setLogs([]),
+ }),
+ [logs, setLogs, isLogListVisible, setIsLogListVisible, addLog]
+ );
return (
diff --git a/app/src/components/ui/log/logger.ts b/app/src/components/ui/log/logger.ts
deleted file mode 100644
index 1781e26..0000000
--- a/app/src/components/ui/log/logger.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-type LogType = 'log' | 'info' | 'warning' | 'error';
-
-interface LogEntry {
- type: LogType;
- message: string;
- timestamp: Date;
- context?: string;
-}
-
-class Logger {
- private static instance: Logger;
- private logs: LogEntry[] = [];
- private subscribers: Array<(log: LogEntry) => void> = [];
-
- private constructor() {}
-
- public static getInstance(): Logger {
- if (!Logger.instance) {
- Logger.instance = new Logger();
- }
- return Logger.instance;
- }
-
- private notifySubscribers(log: LogEntry) {
- this.subscribers.forEach(callback => callback(log));
- }
-
- private addLog(type: LogType, message: string, context?: string) {
- const log: LogEntry = { type, message, timestamp: new Date(), context };
- this.logs.push(log);
- this.notifySubscribers(log);
-
- if (process.env.NODE_ENV === 'development') {
- const logMessage = context ? `[${context}] ${message}` : message;
- console[type === 'warning' ? 'warn' : type](logMessage);
- }
- }
-
- public log(message: string, context?: string) {
- this.addLog('log', message, context);
- }
-
- public info(message: string, context?: string) {
- this.addLog('info', message, context);
- }
-
- public warning(message: string, context?: string) {
- this.addLog('warning', message, context);
- }
-
- public error(message: string, context?: string) {
- this.addLog('error', message, context);
- }
-
- public getLogs(): LogEntry[] {
- return [...this.logs];
- }
-
- public clear() {
- this.logs = [];
- }
-
- public subscribe(callback: (log: LogEntry) => void) {
- this.subscribers.push(callback);
- return () => {
- this.subscribers = this.subscribers.filter(sub => sub !== callback);
- };
- }
-}
-
-export const logger = Logger.getInstance();
diff --git a/app/src/components/ui/menu/EditWidgetOption.tsx b/app/src/components/ui/menu/EditWidgetOption.tsx
index eb937c8..558957b 100644
--- a/app/src/components/ui/menu/EditWidgetOption.tsx
+++ b/app/src/components/ui/menu/EditWidgetOption.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect } from "react";
+import React from "react";
import {
useLeftData,
useTopData,
@@ -16,29 +16,25 @@ const EditWidgetOption: React.FC = ({
const { top } = useTopData();
const { left } = useLeftData();
- useEffect(() => {
-
- }, [top, left]);
-
return (
-
+
{options.map((option, index) => (
-
onClick(option)}
>
{option}
-
+
))}
diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx
index e569250..2d9d4e3 100644
--- a/app/src/components/ui/simulation/simulationPlayer.tsx
+++ b/app/src/components/ui/simulation/simulationPlayer.tsx
@@ -19,8 +19,8 @@ import {
} from "../../icons/ExportCommonIcons";
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
import { useSubModuleStore } from "../../../store/useModuleStore";
-import ProductionCapacity from "../analysis/ProductionCapacity";
-import ThroughputSummary from "../analysis/ThroughputSummary";
+import ProductionCapacity from "../analysis/ThroughputSummary";
+import ThroughputSummary from "../analysis/ProductionCapacity";
import ROISummary from "../analysis/ROISummary";
const SimulationPlayer: React.FC = () => {
@@ -64,8 +64,6 @@ const SimulationPlayer: React.FC = () => {
const handleMouseDown = () => {
isDragging.current = true;
- document.addEventListener("mousemove", handleMouseMove);
- document.addEventListener("mouseup", handleMouseUp);
};
const handleMouseMove = (e: MouseEvent) => {
@@ -80,15 +78,16 @@ const SimulationPlayer: React.FC = () => {
const handleMouseUp = () => {
isDragging.current = false;
- document.removeEventListener("mousemove", handleMouseMove);
- document.removeEventListener("mouseup", handleMouseUp);
};
useEffect(() => {
+ document.addEventListener("mousemove", handleMouseMove);
+ document.addEventListener("mouseup", handleMouseUp);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Slider function ends
@@ -109,24 +108,6 @@ const SimulationPlayer: React.FC = () => {
{ name: "process 9", completed: 90 }, // 90% completed
{ name: "process 10", completed: 30 }, // 30% completed
];
- // Move getRandomColor out of render
- const getRandomColor = () => {
- const letters = "0123456789ABCDEF";
- let color = "#";
- for (let i = 0; i < 6; i++) {
- color += letters[Math.floor(Math.random() * 16)];
- }
- return color;
- };
-
- // Store colors for each process item
- const [_, setProcessColors] = useState
([]);
-
- // Generate colors on mount or when process changes
- useEffect(() => {
- const generatedColors = process.map(() => getRandomColor());
- setProcessColors(generatedColors);
- }, []);
const intervals = [10, 20, 30, 40, 50, 60]; // in minutes
const totalSegments = intervals.length;
@@ -218,7 +199,7 @@ const SimulationPlayer: React.FC = () => {
)}
- {subModule === "simulations" && (
+ {subModule !== "analysis" && (
{playSimulation
@@ -281,7 +262,7 @@ const SimulationPlayer: React.FC = () => {
const segmentProgress = (index / totalSegments) * 100;
const isFilled = progress >= segmentProgress;
return (
-
+
{label} mins
{
-
-
- {speed.toFixed(1)}x
-
-
+
+
+
+ {speed.toFixed(1)}x
+
+
+
+
4x
-
4x
@@ -360,6 +345,7 @@ const SimulationPlayer: React.FC = () => {
className="process-wrapper"
style={{ padding: expand ? "0px" : "5px 35px" }}
>
+ {/* eslint-disable-next-line */}
{
>
{process.map((item, index) => (
{
)}
-
-
-
-
+ {/* {subModule === "analysis" && ( */}
+ {subModule === "analysis" && (
+
-
-
+ )}
+ {/* )} */}
>
);
};
diff --git a/app/src/index.css b/app/src/index.css
deleted file mode 100644
index bd5bd6d..0000000
--- a/app/src/index.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
-}
diff --git a/app/src/index.tsx b/app/src/index.tsx
index f241ca6..ba329e8 100644
--- a/app/src/index.tsx
+++ b/app/src/index.tsx
@@ -1,6 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
-import './index.css';
import App from './app';
import reportWebVitals from './reportWebVitals';
diff --git a/app/src/modules/builder/builder.tsx b/app/src/modules/builder/builder.tsx
index d367493..c0a3267 100644
--- a/app/src/modules/builder/builder.tsx
+++ b/app/src/modules/builder/builder.tsx
@@ -22,7 +22,6 @@ import {
useDeletePointOrLine,
useMovePoint,
useActiveLayer,
- useSocketStore,
useWallVisibility,
useRoofVisibility,
useShadows,
@@ -48,15 +47,11 @@ import FloorGroupAilse from "./groups/floorGroupAisle";
import Draw from "./functions/draw";
import WallsAndWallItems from "./groups/wallsAndWallItems";
import Ground from "../scene/environment/ground";
-// import ZoneGroup from "../groups/zoneGroup1";
import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment";
import Layer2DVisibility from "./geomentries/layers/layer2DVisibility";
-import DrieHtmlTemp from "../visualization/mqttTemp/drieHtmlTemp";
import ZoneGroup from "./groups/zoneGroup";
-import useModuleStore from "../../store/useModuleStore";
import MeasurementTool from "../scene/tools/measurementTool";
import NavMesh from "../simulation/vehicle/navMesh/navMesh";
-import ProductionCapacity from "../../components/ui/analysis/ProductionCapacity";
export default function Builder() {
const state = useThree
(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
@@ -113,21 +108,19 @@ export default function Builder() {
const [selectedItemsIndex, setSelectedItemsIndex] =
useState(null); // State for tracking the index of the selected item.
- const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
- const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D.
+ const { activeLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
+ const { toggleView } = useToggleView(); // State for toggling between 2D and 3D.
const { toolMode, setToolMode } = useToolMode();
- const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not.
- const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
- const { socket } = useSocketStore();
- const { roofVisibility, setRoofVisibility } = useRoofVisibility();
- const { wallVisibility, setWallVisibility } = useWallVisibility();
- const { shadows, setShadows } = useShadows();
- const { renderDistance, setRenderDistance } = useRenderDistance();
- const { limitDistance, setLimitDistance } = useLimitDistance();
- const { updateScene, setUpdateScene } = useUpdateScene();
- const { walls, setWalls } = useWalls();
+ const { setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not.
+ const { setDeletePointOrLine } = useDeletePointOrLine();
+ const { setRoofVisibility } = useRoofVisibility();
+ const { setWallVisibility } = useWallVisibility();
+ const { setShadows } = useShadows();
+ const { setRenderDistance } = useRenderDistance();
+ const { setLimitDistance } = useLimitDistance();
+ const { setUpdateScene } = useUpdateScene();
+ const { setWalls } = useWalls();
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
- const { activeModule } = useModuleStore();
// const loader = new GLTFLoader();
// const dracoLoader = new DRACOLoader();
diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx
index f3f5050..d5ca04f 100644
--- a/app/src/modules/builder/groups/floorItemsGroup.tsx
+++ b/app/src/modules/builder/groups/floorItemsGroup.tsx
@@ -1,11 +1,25 @@
import { useFrame, useThree } from "@react-three/fiber";
-import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store";
+import {
+ useActiveTool,
+ useAsset3dWidget,
+ useCamMode,
+ useDeletableFloorItem,
+ useDeleteTool,
+ useFloorItems,
+ useLoadingProgress,
+ useRenderDistance,
+ useSelectedFloorItem,
+ useSelectedItem,
+ useSocketStore,
+ useToggleView,
+ useTransformMode,
+} from "../../../store/store";
import assetVisibility from "../geomentries/assets/assetVisibility";
import { useEffect } from "react";
import * as THREE from "three";
import * as Types from "../../../types/world/worldTypes";
import assetManager, {
- cancelOngoingTasks,
+ cancelOngoingTasks,
} from "../geomentries/assets/assetManager";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
@@ -18,313 +32,422 @@ import useModuleStore from "../../../store/useModuleStore";
// import { retrieveGLTF } from "../../../utils/indexDB/idbUtils";
import { useEventsStore } from "../../../store/simulation/useEventsStore";
-const assetManagerWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/assetManagerWorker.js", import.meta.url));
-const gltfLoaderWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", import.meta.url));
+const assetManagerWorker = new Worker(
+ new URL(
+ "../../../services/factoryBuilder/webWorkers/assetManagerWorker.js",
+ import.meta.url
+ )
+);
+const gltfLoaderWorker = new Worker(
+ new URL(
+ "../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js",
+ import.meta.url
+ )
+);
-const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane, }: any) => {
- const state: Types.ThreeState = useThree();
- const { raycaster, controls }: any = state;
- const { renderDistance } = useRenderDistance();
- const { toggleView } = useToggleView();
- const { floorItems, setFloorItems } = useFloorItems();
- const { camMode } = useCamMode();
- const { deleteTool } = useDeleteTool();
- const { setDeletableFloorItem } = useDeletableFloorItem();
- const { transformMode } = useTransformMode();
- const { setSelectedFloorItem } = useSelectedFloorItem();
- const { activeTool } = useActiveTool();
- const { selectedItem, setSelectedItem } = useSelectedItem();
- const { setLoadingProgress } = useLoadingProgress();
- const { activeModule } = useModuleStore();
- const { socket } = useSocketStore();
- const loader = new GLTFLoader();
- const dracoLoader = new DRACOLoader();
- const { addEvent } = useEventsStore();
+const FloorItemsGroup = ({
+ itemsGroup,
+ hoveredDeletableFloorItem,
+ AttachedObject,
+ floorGroup,
+ tempLoader,
+ isTempLoader,
+ plane,
+}: any) => {
+ const state: Types.ThreeState = useThree();
+ const { raycaster, controls }: any = state;
+ const { renderDistance } = useRenderDistance();
+ const { toggleView } = useToggleView();
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { camMode } = useCamMode();
+ const { deleteTool } = useDeleteTool();
+ const { setDeletableFloorItem } = useDeletableFloorItem();
+ const { transformMode } = useTransformMode();
+ const { setSelectedFloorItem } = useSelectedFloorItem();
+ const { activeTool } = useActiveTool();
+ const { selectedItem, setSelectedItem } = useSelectedItem();
+ const { setLoadingProgress } = useLoadingProgress();
+ const { activeModule } = useModuleStore();
+ const { socket } = useSocketStore();
+ const loader = new GLTFLoader();
+ const dracoLoader = new DRACOLoader();
+ const { addEvent } = useEventsStore();
- dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/");
- loader.setDRACOLoader(dracoLoader);
+ dracoLoader.setDecoderPath(
+ "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/"
+ );
+ loader.setDRACOLoader(dracoLoader);
- useEffect(() => {
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
+ useEffect(() => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
- let totalAssets = 0;
- let loadedAssets = 0;
+ let totalAssets = 0;
+ let loadedAssets = 0;
- const updateLoadingProgress = (progress: number) => {
- if (progress < 100) {
- setLoadingProgress(progress);
- } else if (progress === 100) {
- setTimeout(() => {
- setLoadingProgress(100);
- setTimeout(() => {
- setLoadingProgress(0);
- }, 1500);
- }, 1000);
- }
- };
+ const updateLoadingProgress = (progress: number) => {
+ if (progress < 100) {
+ setLoadingProgress(progress);
+ } else if (progress === 100) {
+ setTimeout(() => {
+ setLoadingProgress(100);
+ setTimeout(() => {
+ setLoadingProgress(0);
+ }, 1500);
+ }, 1000);
+ }
+ };
- getFloorAssets(organization).then((data) => {
- if (data.length > 0) {
- const uniqueItems = (data as Types.FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.modelfileID === item.modelfileID));
- totalAssets = uniqueItems.length;
- if (totalAssets === 0) {
- updateLoadingProgress(100);
- return;
- }
- gltfLoaderWorker.postMessage({ floorItems: data });
- } else {
- gltfLoaderWorker.postMessage({ floorItems: [] });
- loadInitialFloorItems(itemsGroup, setFloorItems, addEvent, renderDistance);
- updateLoadingProgress(100);
- }
+ getFloorAssets(organization).then((data) => {
+ if (data.length > 0) {
+ const uniqueItems = (data as Types.FloorItems).filter(
+ (item, index, self) =>
+ index === self.findIndex((t) => t.modelfileID === item.modelfileID)
+ );
+ totalAssets = uniqueItems.length;
+ if (totalAssets === 0) {
+ updateLoadingProgress(100);
+ return;
+ }
+ gltfLoaderWorker.postMessage({ floorItems: data });
+ } else {
+ gltfLoaderWorker.postMessage({ floorItems: [] });
+ loadInitialFloorItems(
+ itemsGroup,
+ setFloorItems,
+ addEvent,
+ renderDistance
+ );
+ updateLoadingProgress(100);
+ }
+ });
+
+ gltfLoaderWorker.onmessage = async (event) => {
+ if (event.data.message === "gltfLoaded" && event.data.modelBlob) {
+ const blobUrl = URL.createObjectURL(event.data.modelBlob);
+
+ loader.load(blobUrl, (gltf) => {
+ URL.revokeObjectURL(blobUrl);
+ THREE.Cache.remove(blobUrl);
+ THREE.Cache.add(event.data.modelID, gltf);
+
+ loadedAssets++;
+ const progress = Math.round((loadedAssets / totalAssets) * 100);
+ updateLoadingProgress(progress);
+
+ if (loadedAssets === totalAssets) {
+ loadInitialFloorItems(
+ itemsGroup,
+ setFloorItems,
+ addEvent,
+ renderDistance
+ );
+ updateLoadingProgress(100);
+ }
});
+ }
+ };
+ }, []);
- gltfLoaderWorker.onmessage = async (event) => {
- if (event.data.message === "gltfLoaded" && event.data.modelBlob) {
- const blobUrl = URL.createObjectURL(event.data.modelBlob);
+ useEffect(() => {
+ assetManagerWorker.onmessage = async (event) => {
+ cancelOngoingTasks(); // Cancel the ongoing process
+ await assetManager(event.data, itemsGroup, loader);
+ };
+ }, [assetManagerWorker]);
- loader.load(blobUrl, (gltf) => {
- URL.revokeObjectURL(blobUrl);
- THREE.Cache.remove(blobUrl);
- THREE.Cache.add(event.data.modelID, gltf);
+ useEffect(() => {
+ if (toggleView) return;
- loadedAssets++;
- const progress = Math.round((loadedAssets / totalAssets) * 100);
- updateLoadingProgress(progress);
+ const uuids: string[] = [];
+ itemsGroup.current?.children.forEach((child: any) => {
+ uuids.push(child.uuid);
+ });
+ const cameraPosition = state.camera.position;
- if (loadedAssets === totalAssets) {
- loadInitialFloorItems(itemsGroup, setFloorItems, addEvent, renderDistance);
- updateLoadingProgress(100);
- }
- });
- }
- };
- }, []);
+ assetManagerWorker.postMessage({
+ floorItems,
+ cameraPosition,
+ uuids,
+ renderDistance,
+ });
+ }, [camMode, renderDistance]);
- useEffect(() => {
- assetManagerWorker.onmessage = async (event) => {
- cancelOngoingTasks(); // Cancel the ongoing process
- await assetManager(event.data, itemsGroup, loader);
- };
- }, [assetManagerWorker]);
+ useEffect(() => {
+ const controls: any = state.controls;
+ const camera: any = state.camera;
- useEffect(() => {
+ if (controls) {
+ let intervalId: NodeJS.Timeout | null = null;
+
+ const handleChange = () => {
if (toggleView) return;
const uuids: string[] = [];
- itemsGroup.current?.children.forEach((child: any) => { uuids.push(child.uuid); });
- const cameraPosition = state.camera.position;
+ itemsGroup.current?.children.forEach((child: any) => {
+ uuids.push(child.uuid);
+ });
+ const cameraPosition = camera.position;
- assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance, });
- }, [camMode, renderDistance]);
+ assetManagerWorker.postMessage({
+ floorItems,
+ cameraPosition,
+ uuids,
+ renderDistance,
+ });
+ };
- useEffect(() => {
- const controls: any = state.controls;
- const camera: any = state.camera;
-
- if (controls) {
- let intervalId: NodeJS.Timeout | null = null;
-
- const handleChange = () => {
- if (toggleView) return;
-
- const uuids: string[] = [];
- itemsGroup.current?.children.forEach((child: any) => { uuids.push(child.uuid); });
- const cameraPosition = camera.position;
-
- assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance, });
- };
-
- const startInterval = () => {
- if (!intervalId) {
- intervalId = setInterval(handleChange, 50);
- }
- };
-
- const stopInterval = () => {
- handleChange();
- if (intervalId) {
- clearInterval(intervalId);
- intervalId = null;
- }
- };
-
- controls.addEventListener("rest", handleChange);
- controls.addEventListener("rest", stopInterval);
- controls.addEventListener("control", startInterval);
- controls.addEventListener("controlend", stopInterval);
-
- return () => {
- controls.removeEventListener("rest", handleChange);
- controls.removeEventListener("rest", stopInterval);
- controls.removeEventListener("control", startInterval);
- controls.removeEventListener("controlend", stopInterval);
- if (intervalId) {
- clearInterval(intervalId);
- }
- };
+ const startInterval = () => {
+ if (!intervalId) {
+ intervalId = setInterval(handleChange, 50);
}
- }, [state.controls, floorItems, toggleView, renderDistance]);
+ };
- useEffect(() => {
- const canvasElement = state.gl.domElement;
- let drag = false;
- let isLeftMouseDown = false;
-
- const onMouseDown = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
- }
- };
-
- const onMouseMove = () => {
- if (isLeftMouseDown) {
- drag = true;
- }
- };
-
- const onMouseUp = async (evt: any) => {
- if (controls) {
- (controls as any).enabled = true;
- }
- if (evt.button === 0) {
- isLeftMouseDown = false;
- if (drag) return;
-
- if (deleteTool) {
- DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, socket);
- }
- const Mode = transformMode;
-
- if (Mode !== null || activeTool === "cursor") {
- if (!itemsGroup.current) return;
- let intersects = raycaster.intersectObjects(
- itemsGroup.current.children,
- true
- );
- if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
- // let currentObject = intersects[0].object;
- // while (currentObject) {
- // if (currentObject.name === "Scene") {
- // break;
- // }
- // currentObject = currentObject.parent as THREE.Object3D;
- // }
- // if (currentObject) {
- // AttachedObject.current = currentObject as any;
- // setSelectedFloorItem(AttachedObject.current!);
- // }
- } else {
- const target = controls.getTarget(new THREE.Vector3());
- await controls.setTarget(target.x, 0, target.z, true);
- setSelectedFloorItem(null);
- }
- }
- }
- };
-
- const onDblClick = async (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = false;
- if (drag) return;
-
- const Mode = transformMode;
-
- if (Mode !== null || activeTool === "cursor") {
- if (!itemsGroup.current) return;
- let intersects = raycaster.intersectObjects(itemsGroup.current.children, true);
- if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
- let currentObject = intersects[0].object;
-
- while (currentObject) {
- if (currentObject.name === "Scene") {
- break;
- }
- currentObject = currentObject.parent as THREE.Object3D;
- }
- if (currentObject) {
- AttachedObject.current = currentObject as any;
- // controls.fitToSphere(AttachedObject.current!, true);
-
- const bbox = new THREE.Box3().setFromObject(AttachedObject.current);
- const size = bbox.getSize(new THREE.Vector3());
- const center = bbox.getCenter(new THREE.Vector3());
-
- const front = new THREE.Vector3(0, 0, 1);
- AttachedObject.current.localToWorld(front);
- front.sub(AttachedObject.current.position).normalize();
-
- const distance = Math.max(size.x, size.y, size.z) * 2;
- const newPosition = center.clone().addScaledVector(front, distance);
-
- controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true);
- controls.setTarget(center.x, center.y, center.z, true);
- controls.fitToBox(AttachedObject.current!, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
-
- setSelectedFloorItem(AttachedObject.current!);
- }
- } else {
- const target = controls.getTarget(new THREE.Vector3());
- await controls.setTarget(target.x, 0, target.z, true);
- setSelectedFloorItem(null);
- }
- }
- }
- };
-
- const onDrop = (event: any) => {
- if (!event.dataTransfer?.files[0]) return;
-
- if (selectedItem.id !== "" && event.dataTransfer?.files[0]) {
- addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, addEvent, plane);
- }
- };
-
- const onDragOver = (event: any) => {
- event.preventDefault();
- };
-
- if (activeModule === "builder") {
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- canvasElement.addEventListener("dblclick", onDblClick);
- canvasElement.addEventListener("drop", onDrop);
- canvasElement.addEventListener("dragover", onDragOver);
- } else {
- if (controls) {
- const target = controls.getTarget(new THREE.Vector3());
- controls.setTarget(target.x, 0, target.z, true);
- setSelectedFloorItem(null);
- }
+ const stopInterval = () => {
+ handleChange();
+ if (intervalId) {
+ clearInterval(intervalId);
+ intervalId = null;
}
+ };
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("dblclick", onDblClick);
- canvasElement.removeEventListener("drop", onDrop);
- canvasElement.removeEventListener("dragover", onDragOver);
- };
- }, [deleteTool, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule,]);
+ controls.addEventListener("rest", handleChange);
+ controls.addEventListener("rest", stopInterval);
+ controls.addEventListener("control", startInterval);
+ controls.addEventListener("controlend", stopInterval);
- useFrame(() => {
- if (controls)
- // assetVisibility(itemsGroup, state.camera.position, renderDistance);
- if (deleteTool && activeModule === "builder") {
- DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
- } else if (!deleteTool) {
- if (hoveredDeletableFloorItem.current) {
- hoveredDeletableFloorItem.current = undefined;
- setDeletableFloorItem(null);
- }
+ return () => {
+ controls.removeEventListener("rest", handleChange);
+ controls.removeEventListener("rest", stopInterval);
+ controls.removeEventListener("control", startInterval);
+ controls.removeEventListener("controlend", stopInterval);
+ if (intervalId) {
+ clearInterval(intervalId);
+ }
+ };
+ }
+ }, [state.controls, floorItems, toggleView, renderDistance]);
+
+ useEffect(() => {
+ const canvasElement = state.gl.domElement;
+ let drag = false;
+ let isLeftMouseDown = false;
+
+ const onMouseDown = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown = true;
+ drag = false;
+ }
+ };
+
+ const onMouseMove = () => {
+ console.log('isLeftMouseDown: ', isLeftMouseDown);
+ if (isLeftMouseDown) {
+ drag = true;
+ }
+ };
+
+ const onMouseUp = async (evt: any) => {
+ if (controls) {
+ (controls as any).enabled = true;
+ }
+ if (evt.button === 0) {
+ isLeftMouseDown = false;
+ if (drag) return;
+
+ if (deleteTool) {
+ DeleteFloorItems(
+ itemsGroup,
+ hoveredDeletableFloorItem,
+ setFloorItems,
+ socket
+ );
+ }
+ const Mode = transformMode;
+
+ if (Mode !== null || activeTool === "cursor") {
+ if (!itemsGroup.current) return;
+ let intersects = raycaster.intersectObjects(
+ itemsGroup.current.children,
+ true
+ );
+ if (
+ intersects.length > 0 &&
+ intersects[0]?.object?.parent?.parent?.position &&
+ intersects[0]?.object?.parent?.parent?.scale &&
+ intersects[0]?.object?.parent?.parent?.rotation
+ ) {
+ // let currentObject = intersects[0].object;
+ // while (currentObject) {
+ // if (currentObject.name === "Scene") {
+ // break;
+ // }
+ // currentObject = currentObject.parent as THREE.Object3D;
+ // }
+ // if (currentObject) {
+ // AttachedObject.current = currentObject as any;
+ // setSelectedFloorItem(AttachedObject.current!);
+ // }
+ } else {
+ const target = controls.getTarget(new THREE.Vector3());
+ await controls.setTarget(target.x, 0, target.z, true);
+ setSelectedFloorItem(null);
+ }
+ }
+ }
+ };
+
+ const onDblClick = async (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown = false;
+ if (drag) return;
+
+ const Mode = transformMode;
+
+ if (Mode !== null || activeTool === "cursor") {
+ if (!itemsGroup.current) return;
+ let intersects = raycaster.intersectObjects(
+ itemsGroup.current.children,
+ true
+ );
+ if (
+ intersects.length > 0 &&
+ intersects[0]?.object?.parent?.parent?.position &&
+ intersects[0]?.object?.parent?.parent?.scale &&
+ intersects[0]?.object?.parent?.parent?.rotation
+ ) {
+ let currentObject = intersects[0].object;
+
+ while (currentObject) {
+ if (currentObject.name === "Scene") {
+ break;
+ }
+ currentObject = currentObject.parent as THREE.Object3D;
}
- });
+ if (currentObject) {
+ AttachedObject.current = currentObject as any;
+ // controls.fitToSphere(AttachedObject.current!, true);
- return ;
+ const bbox = new THREE.Box3().setFromObject(
+ AttachedObject.current
+ );
+ const size = bbox.getSize(new THREE.Vector3());
+ const center = bbox.getCenter(new THREE.Vector3());
+
+ const front = new THREE.Vector3(0, 0, 1);
+ AttachedObject.current.localToWorld(front);
+ front.sub(AttachedObject.current.position).normalize();
+
+ const distance = Math.max(size.x, size.y, size.z) * 2;
+ const newPosition = center
+ .clone()
+ .addScaledVector(front, distance);
+
+ controls.setPosition(
+ newPosition.x,
+ newPosition.y,
+ newPosition.z,
+ true
+ );
+ controls.setTarget(center.x, center.y, center.z, true);
+ controls.fitToBox(AttachedObject.current!, true, {
+ cover: true,
+ paddingTop: 5,
+ paddingLeft: 5,
+ paddingBottom: 5,
+ paddingRight: 5,
+ });
+
+ setSelectedFloorItem(AttachedObject.current!);
+ }
+ } else {
+ const target = controls.getTarget(new THREE.Vector3());
+ await controls.setTarget(target.x, 0, target.z, true);
+ setSelectedFloorItem(null);
+ }
+ }
+ }
+ };
+
+ const onDrop = (event: any) => {
+ if (!event.dataTransfer?.files[0]) return;
+
+ if (selectedItem.id !== "" && event.dataTransfer?.files[0]) {
+ addAssetModel(
+ raycaster,
+ state.camera,
+ state.pointer,
+ floorGroup,
+ setFloorItems,
+ itemsGroup,
+ isTempLoader,
+ tempLoader,
+ socket,
+ selectedItem,
+ setSelectedItem,
+ addEvent,
+ plane
+ );
+ }
+ };
+
+ const onDragOver = (event: any) => {
+ event.preventDefault();
+ };
+
+ if (activeModule === "builder") {
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ canvasElement.addEventListener("dblclick", onDblClick);
+ canvasElement.addEventListener("drop", onDrop);
+ canvasElement.addEventListener("dragover", onDragOver);
+ } else {
+ if (controls) {
+ const target = controls.getTarget(new THREE.Vector3());
+ controls.setTarget(target.x, 0, target.z, true);
+ setSelectedFloorItem(null);
+ }
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener("dblclick", onDblClick);
+ canvasElement.removeEventListener("drop", onDrop);
+ canvasElement.removeEventListener("dragover", onDragOver);
+ };
+ }, [
+ deleteTool,
+ transformMode,
+ controls,
+ selectedItem,
+ state.camera,
+ state.pointer,
+ activeTool,
+ activeModule,
+ ]);
+
+ useFrame(() => {
+ if (controls)
+ if (deleteTool && activeModule === "builder") {
+ // assetVisibility(itemsGroup, state.camera.position, renderDistance);
+ DeletableHoveredFloorItems(
+ state,
+ itemsGroup,
+ hoveredDeletableFloorItem,
+ setDeletableFloorItem
+ );
+ } else if (!deleteTool) {
+ if (hoveredDeletableFloorItem.current) {
+ hoveredDeletableFloorItem.current = undefined;
+ setDeletableFloorItem(null);
+ }
+ }
+ });
+
+ return ;
};
export default FloorItemsGroup;
diff --git a/app/src/modules/scene/environment/ground.tsx b/app/src/modules/scene/environment/ground.tsx
index 8d2fa22..ef3e690 100644
--- a/app/src/modules/scene/environment/ground.tsx
+++ b/app/src/modules/scene/environment/ground.tsx
@@ -3,7 +3,6 @@ import * as CONSTANTS from "../../../types/world/worldConstants";
const Ground = ({ grid, plane }: any) => {
const { toggleView } = useToggleView();
- const savedTheme: string | null = localStorage.getItem("theme");
const { planeValue, gridValue } = useTileDistance();
return (
diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
index af6767a..29a6db7 100644
--- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
+++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
@@ -1,255 +1,276 @@
import React, { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
-import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore";
+import useModuleStore, {
+ useSubModuleStore,
+} from "../../../../../store/useModuleStore";
import { TransformControls } from "@react-three/drei";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import {
- useSelectedEventSphere,
- useSelectedEventData,
+ useSelectedEventSphere,
+ useSelectedEventData,
} from "../../../../../store/simulation/useSimulationStore";
import { useThree } from "@react-three/fiber";
function PointsCreator() {
- const { gl, raycaster, scene, pointer, camera } = useThree();
- const { subModule } = useSubModuleStore();
- const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
- const { activeModule } = useModuleStore();
- const transformRef = useRef(null);
- const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
- const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
- const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere();
- const { setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
+ const { gl, raycaster, scene, pointer, camera } = useThree();
+ const { subModule } = useSubModuleStore();
+ const { events, updatePoint, getPointByUuid, getEventByModelUuid } =
+ useEventsStore();
+ const { activeModule } = useModuleStore();
+ const transformRef = useRef(null);
+ const [transformMode, setTransformMode] = useState<
+ "translate" | "rotate" | null
+ >(null);
+ const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
+ const {
+ selectedEventSphere,
+ setSelectedEventSphere,
+ clearSelectedEventSphere,
+ } = useSelectedEventSphere();
+ const { setSelectedEventData, clearSelectedEventData } =
+ useSelectedEventData();
- useEffect(() => {
- if (selectedEventSphere) {
- const eventData = getEventByModelUuid(
- selectedEventSphere.userData.modelUuid
- );
+ useEffect(() => {
+ if (selectedEventSphere) {
+ const eventData = getEventByModelUuid(
+ selectedEventSphere.userData.modelUuid
+ );
- if (eventData) {
- setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid);
- } else {
- clearSelectedEventData();
- }
- } else {
- clearSelectedEventData();
- }
- }, [selectedEventSphere]);
+ if (eventData) {
+ setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid);
+ } else {
+ clearSelectedEventData();
+ }
+ } else {
+ clearSelectedEventData();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [selectedEventSphere]);
- useEffect(() => {
- const handleKeyDown = (e: KeyboardEvent) => {
- const keyCombination = detectModifierKeys(e);
- if (!selectedEventSphere) return;
- if (keyCombination === "G") {
- setTransformMode((prev) => (prev === "translate" ? null : "translate"));
- }
- if (keyCombination === "R") {
- setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
- }
- };
-
- window.addEventListener("keydown", handleKeyDown);
- return () => window.removeEventListener("keydown", handleKeyDown);
- }, [selectedEventSphere]);
-
- const updatePointToState = (selectedEventSphere: THREE.Mesh) => {
- let point = JSON.parse(
- JSON.stringify(getPointByUuid(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid))
- );
- if (point) {
- point.position = [selectedEventSphere.position.x, selectedEventSphere.position.y, selectedEventSphere.position.z,];
- updatePoint(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid, point);
- }
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(e);
+ if (!selectedEventSphere) return;
+ if (keyCombination === "G") {
+ setTransformMode((prev) => (prev === "translate" ? null : "translate"));
+ }
+ if (keyCombination === "R") {
+ setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
+ }
};
- useEffect(() => {
- const canvasElement = gl.domElement;
+ window.addEventListener("keydown", handleKeyDown);
+ return () => window.removeEventListener("keydown", handleKeyDown);
+ }, [selectedEventSphere]);
- let drag = false;
- let isMouseDown = false;
-
- const onMouseDown = () => {
- isMouseDown = true;
- drag = false;
- };
-
- const onMouseUp = () => {
- if (selectedEventSphere && !drag) {
- raycaster.setFromCamera(pointer, camera);
- const intersects = raycaster
- .intersectObjects(scene.children, true)
- .filter(
- (intersect) =>
- intersect.object.name === ('Event-Sphere')
- );
- if (intersects.length === 0) {
- clearSelectedEventSphere();
- setTransformMode(null);
- }
- }
- }
-
- const onMouseMove = () => {
- if (isMouseDown) {
- drag = true;
- }
- };
-
- if (subModule === 'mechanics') {
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- }
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- };
-
- }, [gl, subModule, selectedEventSphere]);
-
- return (
- <>
- {activeModule === "simulation" && (
- <>
-
- {events.map((event, i) => {
- if (event.type === "transfer") {
- return (
-
- {event.points.map((point, j) => (
- (sphereRefs.current[point.uuid] = el!)}
- onClick={(e) => {
- e.stopPropagation();
- setSelectedEventSphere(
- sphereRefs.current[point.uuid]
- );
- }}
- key={`${i}-${j}`}
- position={new THREE.Vector3(...point.position)}
- userData={{
- modelUuid: event.modelUuid,
- pointUuid: point.uuid,
- }}
- >
-
-
-
- ))}
-
- );
- } else if (event.type === "vehicle") {
- return (
-
- (sphereRefs.current[event.point.uuid] = el!)}
- onClick={(e) => {
- e.stopPropagation();
- setSelectedEventSphere(
- sphereRefs.current[event.point.uuid]
- );
- }}
- position={new THREE.Vector3(...event.point.position)}
- userData={{
- modelUuid: event.modelUuid,
- pointUuid: event.point.uuid,
- }}
- >
-
-
-
-
- );
- } else if (event.type === "roboticArm") {
- return (
-
- (sphereRefs.current[event.point.uuid] = el!)}
- onClick={(e) => {
- e.stopPropagation();
- setSelectedEventSphere(
- sphereRefs.current[event.point.uuid]
- );
- }}
- position={new THREE.Vector3(...event.point.position)}
- userData={{
- modelUuid: event.modelUuid,
- pointUuid: event.point.uuid,
- }}
- >
-
-
-
-
- );
- } else if (event.type === "machine") {
- return (
-
- (sphereRefs.current[event.point.uuid] = el!)}
- onClick={(e) => {
- e.stopPropagation();
- setSelectedEventSphere(
- sphereRefs.current[event.point.uuid]
- );
- }}
- position={new THREE.Vector3(...event.point.position)}
- userData={{
- modelUuid: event.modelUuid,
- pointUuid: event.point.uuid,
- }}
- >
-
-
-
-
- );
- } else {
- return null;
- }
- })}
-
- {selectedEventSphere && transformMode && (
- {
- updatePointToState(selectedEventSphere);
- }}
- />
- )}
- >
- )}
- >
+ const updatePointToState = (selectedEventSphere: THREE.Mesh) => {
+ let point = JSON.parse(
+ JSON.stringify(
+ getPointByUuid(
+ selectedEventSphere.userData.modelUuid,
+ selectedEventSphere.userData.pointUuid
+ )
+ )
);
+ if (point) {
+ point.position = [
+ selectedEventSphere.position.x,
+ selectedEventSphere.position.y,
+ selectedEventSphere.position.z,
+ ];
+ updatePoint(
+ selectedEventSphere.userData.modelUuid,
+ selectedEventSphere.userData.pointUuid,
+ point
+ );
+ }
+ };
+
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ let drag = false;
+ let isMouseDown = false;
+
+ const onMouseDown = () => {
+ isMouseDown = true;
+ drag = false;
+ };
+
+ const onMouseUp = () => {
+ if (selectedEventSphere && !drag) {
+ raycaster.setFromCamera(pointer, camera);
+ const intersects = raycaster
+ .intersectObjects(scene.children, true)
+ .filter((intersect) => intersect.object.name === "Event-Sphere");
+ if (intersects.length === 0) {
+ clearSelectedEventSphere();
+ setTransformMode(null);
+ }
+ }
+ };
+
+ const onMouseMove = () => {
+ if (isMouseDown) {
+ drag = true;
+ }
+ };
+
+ if (subModule === "mechanics") {
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [gl, subModule, selectedEventSphere]);
+
+ return (
+ <>
+ {activeModule === "simulation" && (
+ <>
+
+ {events.map((event, index) => {
+ if (event.type === "transfer") {
+ return (
+
+ {event.points.map((point, j) => (
+ (sphereRefs.current[point.uuid] = el!)}
+ onClick={(e) => {
+ e.stopPropagation();
+ setSelectedEventSphere(
+ sphereRefs.current[point.uuid]
+ );
+ }}
+ key={`${index}-${point.uuid}`}
+ position={new THREE.Vector3(...point.position)}
+ userData={{
+ modelUuid: event.modelUuid,
+ pointUuid: point.uuid,
+ }}
+ >
+
+
+
+ ))}
+
+ );
+ } else if (event.type === "vehicle") {
+ return (
+
+ (sphereRefs.current[event.point.uuid] = el!)}
+ onClick={(e) => {
+ e.stopPropagation();
+ setSelectedEventSphere(
+ sphereRefs.current[event.point.uuid]
+ );
+ }}
+ position={new THREE.Vector3(...event.point.position)}
+ userData={{
+ modelUuid: event.modelUuid,
+ pointUuid: event.point.uuid,
+ }}
+ >
+
+
+
+
+ );
+ } else if (event.type === "roboticArm") {
+ return (
+
+ (sphereRefs.current[event.point.uuid] = el!)}
+ onClick={(e) => {
+ e.stopPropagation();
+ setSelectedEventSphere(
+ sphereRefs.current[event.point.uuid]
+ );
+ }}
+ position={new THREE.Vector3(...event.point.position)}
+ userData={{
+ modelUuid: event.modelUuid,
+ pointUuid: event.point.uuid,
+ }}
+ >
+
+
+
+
+ );
+ } else if (event.type === "machine") {
+ return (
+
+ (sphereRefs.current[event.point.uuid] = el!)}
+ onClick={(e) => {
+ e.stopPropagation();
+ setSelectedEventSphere(
+ sphereRefs.current[event.point.uuid]
+ );
+ }}
+ position={new THREE.Vector3(...event.point.position)}
+ userData={{
+ modelUuid: event.modelUuid,
+ pointUuid: event.point.uuid,
+ }}
+ >
+
+
+
+
+ );
+ } else {
+ return null;
+ }
+ })}
+
+ {selectedEventSphere && transformMode && (
+ {
+ updatePointToState(selectedEventSphere);
+ }}
+ />
+ )}
+ >
+ )}
+ >
+ );
}
-export default PointsCreator;
\ No newline at end of file
+export default PointsCreator;
diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
index 74cdd92..06d50a1 100644
--- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
@@ -1,220 +1,261 @@
-import React, { useEffect, useMemo, useRef, useState } from 'react';
-import { useFrame } from '@react-three/fiber';
-import * as THREE from 'three';
-import { Line } from '@react-three/drei';
+import React, { useEffect, useRef, useState } from "react";
+import { useFrame } from "@react-three/fiber";
+import * as THREE from "three";
+import { Line } from "@react-three/drei";
import {
- useAnimationPlaySpeed,
- usePauseButtonStore,
- usePlayButtonStore,
- useResetButtonStore
-} from '../../../../../store/usePlayButtonStore';
+ useAnimationPlaySpeed,
+ usePauseButtonStore,
+ usePlayButtonStore,
+ useResetButtonStore,
+} from "../../../../../store/usePlayButtonStore";
function RoboticArmAnimator({
- HandleCallback,
- restPosition,
- ikSolver,
- targetBone,
- armBot,
- logStatus,
- path
+ HandleCallback,
+ restPosition,
+ ikSolver,
+ targetBone,
+ armBot,
+ logStatus,
+ path,
}: any) {
- const progressRef = useRef(0);
- const curveRef = useRef(null);
- const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
- const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]);
- const [customCurvePoints, setCustomCurvePoints] = useState(null);
+ const progressRef = useRef(0);
+ const curveRef = useRef(null);
+ const [currentPath, setCurrentPath] = useState<[number, number, number][]>(
+ []
+ );
+ const [circlePoints, setCirclePoints] = useState<[number, number, number][]>(
+ []
+ );
+ const [customCurvePoints, setCustomCurvePoints] = useState<
+ THREE.Vector3[] | null
+ >(null);
- // Zustand stores
- const { isPlaying } = usePlayButtonStore();
- const { isPaused } = usePauseButtonStore();
- const { isReset } = useResetButtonStore();
- const { speed } = useAnimationPlaySpeed();
+ // Zustand stores
+ const { isPlaying } = usePlayButtonStore();
+ const { isPaused } = usePauseButtonStore();
+ const { isReset } = useResetButtonStore();
+ const { speed } = useAnimationPlaySpeed();
- // Update path state whenever `path` prop changes
- useEffect(() => {
- setCurrentPath(path);
- }, [path]);
+ // Update path state whenever `path` prop changes
+ useEffect(() => {
+ setCurrentPath(path);
+ }, [path]);
- // Reset logic when `isPlaying` changes
- useEffect(() => {
- if (!isPlaying) {
- setCurrentPath([]);
- curveRef.current = null;
- }
- }, [isPlaying]);
-
- // Handle circle points based on armBot position
- useEffect(() => {
- const points = generateRingPoints(1.6, 64)
- setCirclePoints(points);
- }, [armBot.position]);
-
-
- function generateRingPoints(radius: any, segments: any) {
- const points: [number, number, number][] = [];
- for (let i = 0; i < segments; i++) {
- // Calculate angle for current segment
- const angle = (i / segments) * Math.PI * 2;
- // Calculate x and z coordinates (y remains the same for a flat ring)
- const x = Math.cos(angle) * radius;
- const z = Math.sin(angle) * radius;
- points.push([x, 1.5, z]);
- }
- return points;
+ // Reset logic when `isPlaying` changes
+ useEffect(() => {
+ if (!isPlaying) {
+ setCurrentPath([]);
+ curveRef.current = null;
}
+ }, [isPlaying]);
- const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => {
- for (let i = 0; i < points.length; i++) {
- const [x, y, z] = points[i];
- if (
- Math.abs(x - nearestPoint[0]) < epsilon &&
- Math.abs(y - nearestPoint[1]) < epsilon &&
- Math.abs(z - nearestPoint[2]) < epsilon
- ) {
- return i; // Found the matching index
- }
+ // Handle circle points based on armBot position
+ useEffect(() => {
+ const points = generateRingPoints(1.6, 64);
+ setCirclePoints(points);
+ }, [armBot.position]);
+
+ function generateRingPoints(radius: any, segments: any) {
+ const points: [number, number, number][] = [];
+ for (let i = 0; i < segments; i++) {
+ // Calculate angle for current segment
+ const angle = (i / segments) * Math.PI * 2;
+ // Calculate x and z coordinates (y remains the same for a flat ring)
+ const x = Math.cos(angle) * radius;
+ const z = Math.sin(angle) * radius;
+ points.push([x, 1.5, z]);
+ }
+ return points;
+ }
+
+ const findNearestIndex = (
+ nearestPoint: [number, number, number],
+ points: [number, number, number][],
+ epsilon = 1e-6
+ ) => {
+ for (let i = 0; i < points.length; i++) {
+ const [x, y, z] = points[i];
+ if (
+ Math.abs(x - nearestPoint[0]) < epsilon &&
+ Math.abs(y - nearestPoint[1]) < epsilon &&
+ Math.abs(z - nearestPoint[2]) < epsilon
+ ) {
+ return i; // Found the matching index
+ }
+ }
+ return -1; // Not found
+ };
+
+ // Handle nearest points and final path (including arc points)
+ useEffect(() => {
+ if (circlePoints.length > 0 && currentPath.length > 0) {
+ const start = currentPath[0];
+ const end = currentPath[currentPath.length - 1];
+
+ const raisedStart = [start[0], start[1] + 0.5, start[2]] as [
+ number,
+ number,
+ number
+ ];
+ const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [
+ number,
+ number,
+ number
+ ];
+
+ const findNearest = (target: [number, number, number]) => {
+ return circlePoints.reduce((nearest, point) => {
+ const distance = Math.hypot(
+ target[0] - point[0],
+ target[1] - point[1],
+ target[2] - point[2]
+ );
+ const nearestDistance = Math.hypot(
+ target[0] - nearest[0],
+ target[1] - nearest[1],
+ target[2] - nearest[2]
+ );
+ return distance < nearestDistance ? point : nearest;
+ }, circlePoints[0]);
+ };
+
+ const nearestToStart = findNearest(raisedStart);
+
+ const nearestToEnd = findNearest(raisedEnd);
+
+ const indexOfNearestStart = findNearestIndex(
+ nearestToStart,
+ circlePoints
+ );
+
+ const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
+
+ // Find clockwise and counter-clockwise distances
+ const clockwiseDistance =
+ (indexOfNearestEnd - indexOfNearestStart + 64) % 64;
+
+ const counterClockwiseDistance =
+ (indexOfNearestStart - indexOfNearestEnd + 64) % 64;
+
+ const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
+
+ // Collect arc points between start and end
+ let arcPoints: [number, number, number][] = [];
+
+ if (clockwiseIsShorter) {
+ if (indexOfNearestStart <= indexOfNearestEnd) {
+ arcPoints = circlePoints.slice(
+ indexOfNearestStart,
+ indexOfNearestEnd + 1
+ );
+ } else {
+ // Wrap around
+ arcPoints = [
+ ...circlePoints.slice(indexOfNearestStart, 64),
+ ...circlePoints.slice(0, indexOfNearestEnd + 1),
+ ];
}
- return -1; // Not found
- };
-
-
- // Handle nearest points and final path (including arc points)
- useEffect(() => {
- if (circlePoints.length > 0 && currentPath.length > 0) {
- const start = currentPath[0];
- const end = currentPath[currentPath.length - 1];
-
- const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
- const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
-
- const findNearest = (target: [number, number, number]) => {
- return circlePoints.reduce((nearest, point) => {
- const distance = Math.hypot(
- target[0] - point[0],
- target[1] - point[1],
- target[2] - point[2]
- );
- const nearestDistance = Math.hypot(
- target[0] - nearest[0],
- target[1] - nearest[1],
- target[2] - nearest[2]
- );
- return distance < nearestDistance ? point : nearest;
- }, circlePoints[0]);
- };
-
- const nearestToStart = findNearest(raisedStart);
-
- const nearestToEnd = findNearest(raisedEnd);
-
- const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints);
-
- const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
-
- // Find clockwise and counter-clockwise distances
- const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64;
-
- const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64;
-
- const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
-
- // Collect arc points between start and end
- let arcPoints: [number, number, number][] = [];
-
- if (clockwiseIsShorter) {
- if (indexOfNearestStart <= indexOfNearestEnd) {
- arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1);
- } else {
- // Wrap around
- arcPoints = [
- ...circlePoints.slice(indexOfNearestStart, 64),
- ...circlePoints.slice(0, indexOfNearestEnd + 1)
- ];
- }
- } else {
- if (indexOfNearestStart >= indexOfNearestEnd) {
- for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
- arcPoints.push(circlePoints[i]);
- }
- } else {
- for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
- arcPoints.push(circlePoints[i]);
- }
- }
- }
-
- // Continue your custom path logic
- const pathVectors = [
- new THREE.Vector3(start[0], start[1], start[2]), // start
- new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up
- new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start
- ...arcPoints.map(point => new THREE.Vector3(point[0], raisedStart[1], point[2])),
- new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end
- new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end
- new THREE.Vector3(end[0], end[1], end[2]) // end
- ];
-
- const customCurve = new THREE.CatmullRomCurve3(pathVectors, false, 'centripetal', 1);
- const generatedPoints = customCurve.getPoints(100);
- setCustomCurvePoints(generatedPoints);
+ } else if (indexOfNearestStart >= indexOfNearestEnd) {
+ for (
+ let i = indexOfNearestStart;
+ i !== (indexOfNearestEnd - 1 + 64) % 64;
+ i = (i - 1 + 64) % 64
+ ) {
+ arcPoints.push(circlePoints[i]);
}
- }, [circlePoints, currentPath]);
+ }
- // Frame update for animation
- useFrame((_, delta) => {
- if (!ikSolver) return;
+ // Continue your custom path logic
+ const pathVectors = [
+ new THREE.Vector3(start[0], start[1], start[2]), // start
+ new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up
+ new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start
+ ...arcPoints.map(
+ (point) => new THREE.Vector3(point[0], raisedStart[1], point[2])
+ ),
+ new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end
+ new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end
+ new THREE.Vector3(end[0], end[1], end[2]), // end
+ ];
- const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
- if (!bone) return;
+ const customCurve = new THREE.CatmullRomCurve3(
+ pathVectors,
+ false,
+ "centripetal",
+ 1
+ );
+ const generatedPoints = customCurve.getPoints(100);
+ setCustomCurvePoints(generatedPoints);
+ }
+ }, [circlePoints, currentPath]);
- if (isPlaying) {
- if (!isPaused && customCurvePoints && currentPath.length > 0) {
- const curvePoints = customCurvePoints;
- const speedAdjustedProgress = progressRef.current + (speed * armBot.speed);
- const index = Math.floor(speedAdjustedProgress);
+ // Frame update for animation
+ useFrame((_, delta) => {
+ if (!ikSolver) return;
- if (index >= curvePoints.length) {
- // Reached the end of the curve
- HandleCallback();
- setCurrentPath([]);
- curveRef.current = null;
- progressRef.current = 0;
- } else {
- const point = curvePoints[index];
- bone.position.copy(point);
- progressRef.current = speedAdjustedProgress;
- }
- } else if (isPaused) {
- logStatus(armBot.modelUuid, 'Simulation Paused');
- }
-
- ikSolver.update();
- } else if (!isPlaying && currentPath.length === 0) {
- // Not playing anymore, reset to rest
- bone.position.copy(restPosition);
- ikSolver.update();
- }
- });
-
-
- return (
- <>
- {/* {customCurvePoints && currentPath && isPlaying && (
-
- [p.x, p.y, p.z] as [number, number, number])}
- color="green"
- lineWidth={5}
- dashed={false}
- />
-
- )} */}
- {/*
-
-
- */}
- >
+ const bone = ikSolver.mesh.skeleton.bones.find(
+ (b: any) => b.name === targetBone
);
+ if (!bone) return;
+
+ if (isPlaying) {
+ if (!isPaused && customCurvePoints && currentPath.length > 0) {
+ const curvePoints = customCurvePoints;
+ const speedAdjustedProgress =
+ progressRef.current + speed * armBot.speed;
+ const index = Math.floor(speedAdjustedProgress);
+
+ if (index >= curvePoints.length) {
+ // Reached the end of the curve
+ HandleCallback();
+ setCurrentPath([]);
+ curveRef.current = null;
+ progressRef.current = 0;
+ } else {
+ const point = curvePoints[index];
+ bone.position.copy(point);
+ progressRef.current = speedAdjustedProgress;
+ }
+ } else if (isPaused) {
+ logStatus(armBot.modelUuid, "Simulation Paused");
+ }
+
+ ikSolver.update();
+ } else if (!isPlaying && currentPath.length === 0) {
+ // Not playing anymore, reset to rest
+ bone.position.copy(restPosition);
+ ikSolver.update();
+ }
+ });
+
+ return (
+ <>
+ {customCurvePoints && currentPath && isPlaying && (
+
+ [p.x, p.y, p.z] as [number, number, number]
+ )}
+ color="green"
+ lineWidth={5}
+ dashed={false}
+ />
+
+ )}
+
+
+
+
+ >
+ );
}
export default RoboticArmAnimator;
diff --git a/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx b/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx
index 3070c3a..4a8947b 100644
--- a/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx
@@ -67,13 +67,12 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef }: IKIns
setIkSolver(solver);
const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05)
- // groupRef.current.add(helper);
setSelectedArm(OOI.Target_Bone);
// scene.add(helper);
- }, [gltf]);
+ }, [cloned, gltf, setIkSolver]);
return (
<>
diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx
index 17a6315..4fe26b3 100644
--- a/app/src/pages/Project.tsx
+++ b/app/src/pages/Project.tsx
@@ -58,7 +58,7 @@ const Project: React.FC = () => {
setOrganization(Organization);
setUserName(name);
}
- echo.info("Log in success full");
+ echo.warn("Log in success full");
} else {
navigate("/");
}
diff --git a/app/src/styles/abstracts/variables.scss b/app/src/styles/abstracts/variables.scss
index 29976dc..3545151 100644
--- a/app/src/styles/abstracts/variables.scss
+++ b/app/src/styles/abstracts/variables.scss
@@ -115,17 +115,23 @@ $color5: #c7a8ff;
// log indication colors
// ------------ text -------------
$log-default-text-color: #6f42c1;
-$log-info-text-color: #488ef6;
+$log-info-text-color: #1773fd;
$log-warn-text-color: #f3a50c;
-$log-error-text-color: #f65648;
-$log-success-text-color: #43c06d;
+$log-error-text-color: #fc230f;
+$log-success-text-color: #23a84f;
+// ----------- dark ---------------
+$log-default-text-color-dark: #b18ef1;
+$log-info-text-color-dark: #7eb0fa;
+$log-warn-text-color-dark: #ffaa00;
+$log-error-text-color-dark: #ff887d;
+$log-success-text-color-dark: #43ff81;
// ------------ background -------------
$log-default-backgroung-color: #6e42c133;
-$log-info-background-color: #488ef633;
+$log-info-background-color: #1773fd5d;
$log-warn-background-color: #f3a50c33;
-$log-error-background-color: #f6564833;
-$log-success-background-color: #43c06d33;
+$log-error-background-color: #fc230f33;
+$log-success-background-color: #0ef75b33;
// old variables
$accent-color: #6f42c1;
diff --git a/app/src/styles/base/base.scss b/app/src/styles/base/base.scss
index 4555ed9..8843bfe 100644
--- a/app/src/styles/base/base.scss
+++ b/app/src/styles/base/base.scss
@@ -35,6 +35,18 @@
--icon-default-color: #{$icon-default-color};
--icon-default-color-active: #{$icon-default-color-active};
+ // log colors
+ --default-text-color: #{$log-default-text-color};
+ --log-info-text-color: #{$log-info-text-color};
+ --log-warn-text-color: #{$log-warn-text-color};
+ --log-error-text-color: #{$log-error-text-color};
+ --log-success-text-color: #{$log-success-text-color};
+ --log-default-background-color: #{$log-default-backgroung-color};
+ --log-info-background-color: #{$log-info-background-color};
+ --log-warn-background-color: #{$log-warn-background-color};
+ --log-error-background-color: #{$log-error-background-color};
+ --log-success-background-color: #{$log-success-background-color};
+
// old colors
--accent-color: #{$accent-color};
--accent-gradient-color: #{$acent-gradient};
@@ -85,6 +97,18 @@
--icon-default-color: #{$icon-default-color-dark};
--icon-default-color-active: #{$icon-default-color-active-dark};
+ // log colors
+ --default-text-color: #{$log-default-text-color-dark};
+ --log-info-text-color: #{$log-info-text-color-dark};
+ --log-warn-text-color: #{$log-warn-text-color-dark};
+ --log-error-text-color: #{$log-error-text-color-dark};
+ --log-success-text-color: #{$log-success-text-color-dark};
+ --log-default-background-color: #{$log-default-backgroung-color};
+ --log-info-background-color: #{$log-info-background-color};
+ --log-warn-background-color: #{$log-warn-background-color};
+ --log-error-background-color: #{$log-error-background-color};
+ --log-success-background-color: #{$log-success-background-color};
+
// old colors
--accent-color: #{$accent-color-dark};
--accent-gradient-color: #{$acent-gradient-dark};
@@ -115,7 +139,6 @@
}
body {
- background: var(--background-color);
--font-size-tiny: #{$tiny};
--font-size-small: #{$small};
--font-size-regular: #{$regular};
diff --git a/app/src/styles/components/footer/footer.scss b/app/src/styles/components/footer/footer.scss
index b2d85d0..a457557 100644
--- a/app/src/styles/components/footer/footer.scss
+++ b/app/src/styles/components/footer/footer.scss
@@ -23,6 +23,7 @@
padding: 3px 6px;
border-radius: 12px;
color: var(--text-color);
+ backdrop-filter: blur(14px);
.selector {
color: var(--text-color);
@@ -33,24 +34,55 @@
.logs-wrapper {
display: flex;
gap: 6px;
+ position: relative;
+ // dummy
+ .bg-dummy{
+ background: var(--background-color-solid);
+ position: absolute;
+ z-index: -1;
+ }
+ .bg-dummy.left-top{
+ top: 1px;
+ left: 4px;
+ width: 60%;
+ height: 16px;
+ border-radius: 20px;
+ }
+ .bg-dummy.right-bottom{
+ right: 68px;
+ bottom: 0;
+ width: 20%;
+ height: 100%;
+ border-radius: 50%;
+ }
+
+ .log-container {
+ background: var(--background-color);
+ backdrop-filter: blur(20px);
+ border-radius: 12px;
+ @include flex-center;
+ overflow: hidden;
+ }
.logs-detail,
.version {
+ @include flex-center;
border-radius: 12px;
- background: var(--background-color);
padding: 3px 6px;
+ height: 100%;
color: var(--text-color);
- display: flex;
- align-items: center;
gap: 6px;
}
.logs-detail {
padding: 2px 12px;
cursor: pointer;
+ outline: 0 solid var(--border-color);
+ outline-offset: -1px;
.log-icon {
@include flex-center;
}
+
.log-message {
max-width: 40vw;
white-space: nowrap;
@@ -60,12 +92,51 @@
}
.version {
+ background: var(--background-color);
font-size: var(--font-size-tiny);
- display: flex;
- gap: 6px;
- .icon{
+
+ .icon {
@include flex-center;
}
}
+
+ .log {
+ background: var(--log-default-background-color);
+ outline-color: var(--default-text-color);
+ .log-message {
+ color: var(--default-text-color);
+ }
+ }
+
+ .info {
+ background: var(--log-info-background-color);
+ outline-color: var(--log-info-text-color);
+ .log-message {
+ color: var(--log-info-text-color);
+ }
+ }
+
+ .error {
+ background: var(--log-error-background-color);
+ outline-color: var(--log-error-text-color);
+ .log-message {
+ color: var(--log-error-text-color);
+ }
+ }
+
+ .warning {
+ background: var(--log-warn-background-color);
+ outline-color: var(--log-warn-text-color);
+ .log-message {
+ color: var(--log-warn-text-color);
+ }
+ }
+
+ .success {
+ background: var(--log-success-background-color);
+ .log-message {
+ color: var(--log-success-text-color);
+ }
+ }
}
}
diff --git a/app/src/styles/components/form.scss b/app/src/styles/components/form.scss
index e69de29..67accd2 100644
--- a/app/src/styles/components/form.scss
+++ b/app/src/styles/components/form.scss
@@ -0,0 +1,26 @@
+@use "../abstracts/variables" as *;
+@use "../abstracts/mixins" as *;
+
+.rename-tool-tip {
+ position: absolute;
+ background: var(--background-color);
+ padding: 10px 16px;
+ width: 260px;
+ border-radius: #{$border-radius-large};
+ outline: 1px solid var(--border-color);
+ z-index: 100;
+ .header {
+ @include flex-center;
+ gap: 8px;
+ .icon {
+ @include flex-center;
+ }
+ .name {
+ color: var(--text-color);
+ }
+ input {
+ width: 100%;
+ margin-top: 6px;
+ }
+ }
+}
diff --git a/app/src/styles/components/lists.scss b/app/src/styles/components/lists.scss
index 894eac1..27ccda8 100644
--- a/app/src/styles/components/lists.scss
+++ b/app/src/styles/components/lists.scss
@@ -2,8 +2,6 @@
@use "../abstracts/mixins" as *;
.dropdown-list-container {
- border-bottom: 1px solid var(--border-color);
-
.lists-container {
margin-bottom: 6px;
}
@@ -44,7 +42,7 @@
text-align: center;
padding: 4px 8px;
border-radius: #{$border-radius-large};
- .zone-header{
+ .zone-header {
@include flex-center;
.value {
width: 100%;
@@ -62,16 +60,10 @@
cursor: pointer;
}
}
- &:first-child{
- background: var(--highlight-accent-color);
- .input-value{
- color: var(--highlight-text-color);
- }
- }
}
.active {
background: var(--highlight-accent-color);
- .input-value{
+ .input-value {
color: var(--highlight-text-color);
}
}
diff --git a/app/src/styles/components/logs/logs.scss b/app/src/styles/components/logs/logs.scss
index f07708b..b7c1363 100644
--- a/app/src/styles/components/logs/logs.scss
+++ b/app/src/styles/components/logs/logs.scss
@@ -5,14 +5,11 @@
width: 100vw;
height: 100vh;
background: var(--background-color-secondary);
+ @include flex-center;
.log-list-wrapper {
- height: 50%;
- min-width: 50%;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
+ height: 60%;
+ min-width: 55%;
z-index: 5;
background: var(--background-color);
padding: 14px 12px;
@@ -31,6 +28,10 @@
display: flex;
align-items: center;
gap: 6px;
+ .icon {
+ @include flex-center;
+ scale: 0.8;
+ }
}
.close {
@@ -38,47 +39,66 @@
height: 28px;
width: 28px;
cursor: pointer;
+ border-radius: #{$border-radius-medium};
svg {
scale: 1.6;
}
+ &:hover {
+ background: var(--background-color);
+ }
+ }
+ }
+ .log-nav-container {
+ @include flex-space-between;
+ align-items: flex-end;
+ .log-nav-wrapper {
+ display: flex;
+ gap: 6px;
+
+ .log-nav {
+ padding: 8px 16px;
+ border-radius: 19px;
+ }
+
+ .log-nav.active {
+ background-color: var(--background-color-accent);
+ color: var(--text-button-color);
+ }
+ }
+ .clear-button{
+ margin: 0 6px;
+ padding: 4px 12px;
+ color: var(--text-disabled);
+ border-radius: #{$border-radius-large};
+ &:hover{
+ font-weight: 300;
+ color: var(--text-color);
+ background: var(--background-color-solid-gradient);
+ }
}
}
- .log-nav-wrapper {
- display: flex;
- gap: 6px;
-
- .log-nav {
- padding: 8px 16px;
- border-radius: 19px;
- }
-
- .log-nav.active {
- background-color: var(--background-color-accent);
- color: var(--text-button-color);
- }
- }
-
.log-entry-wrapper {
- height: 100%;
+ height: calc(100% - 80px);
display: flex;
flex-direction: column;
gap: 4px;
background: var(--background-color);
- padding: 18px 10px;
+ padding: 10px;
border-radius: 16px;
outline: 1px solid var(--border-color);
outline-offset: -1px;
+ overflow: auto;
.log-entry {
padding: 4px;
border-radius: 4px;
font-size: var(--font-size-small);
display: flex;
- align-items: center;
- gap: 6px;
.log-icon {
+ height: 24px;
+ width: 24px;
@include flex-center;
}
.log-entry-message-container {
@@ -90,8 +110,9 @@
font-weight: 300;
opacity: 0.8;
text-wrap: nowrap;
+ height: 100%;
}
- .log-entry-message{
+ .log-entry-message {
width: 100%;
}
}
@@ -101,5 +122,10 @@
}
}
}
+ .no-log{
+ padding: 20px;
+ text-align: center;
+ color: var(--text-color);
+ }
}
}
diff --git a/app/src/styles/components/simulation/analysis.scss b/app/src/styles/components/simulation/analysis.scss
index 9aed5c8..b838b0b 100644
--- a/app/src/styles/components/simulation/analysis.scss
+++ b/app/src/styles/components/simulation/analysis.scss
@@ -11,18 +11,12 @@
width: 100%;
height: 100vh;
pointer-events: none;
- padding: 10px;
z-index: 2;
- .analysis-wrapper {
- display: flex;
- flex-direction: column;
- gap: 12px;
- }
.analysis-card {
min-width: 333px;
border-radius: 20px;
- padding: 8px;
+ margin: 8px;
pointer-events: all;
.analysis-card-wrapper {
@@ -47,6 +41,13 @@
line-height: 20px;
font-size: var(--font-size-regular);
}
+
+ .sub-header {
+ font-weight: 300;
+ font-size: var(--font-size-tiny);
+ color: var(--text-color);
+ opacity: 0.8;
+ }
}
.process-container {
@@ -97,7 +98,7 @@
.metrics-section {
padding-top: 16px;
- border-top: 1px solid var(--background-color-gray);
+ border-top: 1px solid var(--border-color);
.metric {
display: flex;
@@ -116,7 +117,8 @@
}
}
}
- .throughoutSummary-wrapper {
+
+ .production-wrapper {
.process-container {
display: flex;
flex-direction: row;
@@ -127,7 +129,7 @@
.throughput-value {
font-size: var(--font-size-small);
- flex: 1;
+ flex: 0.8;
display: flex;
flex-direction: column;
@@ -139,15 +141,24 @@
}
.lineChart {
+ flex: 1.2;
max-width: 200px;
height: 100px;
position: relative;
+ background-image: radial-gradient(#8d8d8da4 1px, transparent 1px);
+ background-size: 10px 10px;
+ border-radius: 8px;
.assetUsage {
text-align: right;
position: absolute;
right: 0;
top: 0;
+
+ .key,
+ .value {
+ font-size: var(--font-size-regular);
+ }
}
canvas {
@@ -163,12 +174,13 @@
.footer-card {
width: 100%;
- background: var(--background-color-gray);
- border-radius: 6px;
- padding: 8px;
+ background: var(--background-color);
+ border-radius: #{$border-radius-large};
+ padding: 12px;
display: flex;
flex-direction: column;
- gap: 6px;
+ gap: 12px;
+ outline: 1px solid var(--border-color);
&:first-child {
width: 85%;
@@ -225,7 +237,7 @@
justify-content: space-between;
width: 100%;
gap: 6px;
-
+ padding-top: 3px;
.shift-wrapper {
display: flex;
align-items: center;
@@ -251,7 +263,8 @@
}
label {
- font-size: var(--font-size-small);
+ font-weight: 200;
+ font-size: var(--font-size-tiny);
position: relative;
}
@@ -268,19 +281,29 @@
}
}
}
+
.roiSummary-wrapper {
max-width: 470px;
background-color: var(--background-color);
.product-info {
display: flex;
+ align-items: center;
+ gap: 6px;
}
.playBack {
display: flex;
- background-color: var(--background-color);
- border-radius: 12px;
- padding: 6px;
+ align-items: center;
+ gap: 2px;
+ border-radius: 66px;
+ background: var(--background-color);
+ padding: 6px 12px;
+ border: 1px solid var(--border-color);
+
+ svg {
+ scale: 0.8;
+ }
.info {
span {
@@ -313,10 +336,12 @@
flex-direction: column;
gap: 3px;
align-items: center;
+ font-weight: 300;
.key {
- font-size: var(--font-size-xlarge);
- color: var(--accent-color);
+ font-weight: 500;
+ font-size: var(--font-size-large);
+ color: #28b9f3;
}
}
}
@@ -363,8 +388,9 @@
gap: 6px;
.metric-item {
+ padding: 8px;
border-radius: #{$border-radius-large};
- background-color: var(--background-color);
+ background: var(--background-color);
border: 1px solid var(--border-color);
}
}
@@ -372,10 +398,12 @@
}
.cost-breakdown {
- background-color: var(--background-color);
+ background: var(--background-color);
border: 1px solid var(--border-color);
border-radius: #{$border-radius-extra-large};
+ max-height: 20vh;
padding: 16px;
+ overflow: auto;
.breakdown-header {
display: flex;
@@ -385,7 +413,7 @@
.section-wrapper {
display: flex;
- gap: 4px;
+ gap: 6px;
align-items: center;
}
@@ -427,6 +455,7 @@
text-align: left;
border: 1px solid var(--border-color);
}
+
th {
background-color: var(--background-color);
}
@@ -434,8 +463,8 @@
}
.tips-section {
- background-color: var(--background-color);
- border-radius: #{$border-radius-large};
+ background: var(--background-color);
+ border-radius: #{$border-radius-extra-large};
outline: 1px solid var(--border-color);
display: flex;
flex-direction: column;
@@ -445,7 +474,10 @@
.tip-header {
display: flex;
align-items: center;
-
+ gap: 4px;
+ .lightbulb-icon{
+ @include flex-center;
+ }
.tip-title {
color: var(--text-color);
font-weight: 600;
@@ -490,43 +522,22 @@
}
}
- .semi-circle-wrapper {
- width: 100%;
- height: 125px;
- overflow-y: hidden;
+ .svg-half-donut {
position: relative;
- .semi-circle {
+
+ .label-wrapper {
width: 100%;
- height: 250px;
- border-radius: 50%;
- position: relative;
- }
- .progress-cover {
position: absolute;
- width: 75%;
- height: 75%;
- top: 12.5%;
- left: 12.5%;
- border-radius: 50%;
- }
- }
+ bottom: 2px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
- .label-wrapper {
- .label {
- font-size: var(--font-size-xxxlarge);
+ .label {
+ font-size: var(--font-size-xxlarge);
+ }
}
-
- position: absolute;
- bottom: 0%;
- left: 50%;
- transform: translate(-50%, 0%);
- font-weight: bold;
- font-size: 1.2rem;
- color: #333;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
}
}
@@ -554,4 +565,3 @@
}
// Breakdown Table Open/Close Logic
-
diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss
index 88f85dc..37a87a8 100644
--- a/app/src/styles/components/simulation/simulation.scss
+++ b/app/src/styles/components/simulation/simulation.scss
@@ -3,7 +3,7 @@
.simulation-player-wrapper {
position: fixed;
- bottom: 12px;
+ bottom: 32px;
left: 50%;
z-index: 2;
transform: translate(-50%, 0);
@@ -35,11 +35,11 @@
@include flex-space-between;
gap: 12px;
justify-content: space-between;
- .header{
+ .header {
@include flex-center;
gap: 6px;
padding: 0 8px;
- svg{
+ svg {
scale: 1.3;
}
}
@@ -144,14 +144,21 @@
&::after {
content: "";
- background-color: #e5e5ea;
+ background: var(--background-color-solid);
+ opacity: 0.4;
position: absolute;
top: 50%;
transform: translate(0, -50%);
width: 100%;
height: 3px;
}
-
+ .custom-slider-wrapper {
+ height: 100%;
+ width: 100%;
+ padding: 0 26px;
+ background: transparent;
+ border-radius: #{$border-radius-large};
+ }
.custom-slider {
height: 100%;
width: 100%;
@@ -185,11 +192,13 @@
.marker {
position: absolute;
- background-color: var(--text-disabled);
+ background: var(--background-color-solid);
+ opacity: 0.6;
width: 2px;
height: 12px;
border-radius: 1px;
top: 8px;
+ z-index: 1;
}
.marker.marker-10 {
@@ -299,6 +308,37 @@
}
}
}
+
+ .open {
+ .start-displayer,
+ .end-displayer {
+ display: none;
+ }
+
+ .timmer {
+ display: none;
+ }
+ .progresser-wrapper {
+ padding-top: 4px;
+ }
+
+ .time-displayer {
+ height: 0;
+ opacity: 0;
+ pointer-events: none;
+ display: none;
+ }
+
+ .processDisplayer {
+ padding: 0 8px;
+ background: transparent;
+
+ .process-player {
+ width: 0;
+ display: none !important;
+ }
+ }
+ }
}
.processDisplayer {
@@ -314,22 +354,6 @@
font-size: var(--font-size-tiny);
}
- .timmer {
- width: auto;
- position: absolute;
- bottom: 0;
- font-size: var(--font-size-tiny);
- }
-
- .start-displayer {
- left: 8px;
- }
-
- .end-displayer {
- width: auto;
- right: 8px;
- }
-
.start-displayer {
bottom: 4px;
left: 16px;
@@ -351,12 +375,12 @@
border-width: 1px;
background: var(--background-color-accent, #6f42c1);
}
- .process-wrapper{
+ .process-wrapper {
.process-container {
position: relative;
display: flex;
width: 100%;
-
+
.process {
height: 5px;
border-radius: 4px;
@@ -368,35 +392,3 @@
}
}
}
-
-.simulation-player-container.open {
-
- .start-displayer,
- .end-displayer {
- display: none;
- }
-
- .timmer {
- display: none;
- }
- .progresser-wrapper {
- padding-top: 4px;
- }
-
- .time-displayer {
- height: 0;
- opacity: 0;
- pointer-events: none;
- display: none;
- }
-
- .processDisplayer {
- padding: 0 8px;
- background: transparent;
-
- .process-player {
- width: 0;
- display: none !important;
- }
- }
-}
diff --git a/app/src/styles/components/tools.scss b/app/src/styles/components/tools.scss
index 29d37b4..03813a4 100644
--- a/app/src/styles/components/tools.scss
+++ b/app/src/styles/components/tools.scss
@@ -14,7 +14,7 @@
width: fit-content;
transition: width 0.2s;
background: var(--background-color);
- backdrop-filter: blur(8px);
+ backdrop-filter: blur(20px);
z-index: 2;
outline: 1px solid var(--border-color);
outline-offset: -1px;
@@ -31,10 +31,12 @@
.activeDropicon {
@include flex-center;
gap: 2px;
+ // stylelint-disable-next-line
interpolate-size: allow-keywords;
width: 0;
opacity: 0;
animation: expandWidth 0.2s ease-in-out forwards;
+ will-change: width;
.tool-button {
@include flex-center;
@@ -44,9 +46,11 @@
border-radius: #{$border-radius-medium};
&:hover {
- background: color-mix(in srgb,
- var(--highlight-accent-color) 60%,
- transparent);
+ background: color-mix(
+ in srgb,
+ var(--highlight-accent-color) 60%,
+ transparent
+ );
}
}
@@ -70,9 +74,11 @@
position: relative;
&:hover {
- background: color-mix(in srgb,
- var(--highlight-accent-color) 60%,
- transparent);
+ background: color-mix(
+ in srgb,
+ var(--highlight-accent-color) 60%,
+ transparent
+ );
}
.drop-down-container {
@@ -179,11 +185,11 @@
font-weight: 500;
background: var(--accent-color);
color: var(--highlight-accent-color);
- &::after{
+ &::after {
animation: pulse 1s ease-out infinite;
}
}
- &::after{
+ &::after {
content: "";
position: absolute;
height: 100%;
@@ -195,14 +201,14 @@
}
@keyframes pulse {
- 0%{
+ 0% {
opacity: 0;
- scale: .5;
+ scale: 0.5;
}
- 50%{
+ 50% {
opacity: 1;
}
- 100%{
+ 100% {
opacity: 0;
scale: 2;
}
@@ -218,4 +224,4 @@
width: fit-content;
opacity: 1;
}
-}
\ No newline at end of file
+}
diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss
index f8c022f..cffee1e 100644
--- a/app/src/styles/layout/sidebar.scss
+++ b/app/src/styles/layout/sidebar.scss
@@ -7,7 +7,7 @@
top: 32px;
left: 8px;
background: var(--background-color);
- backdrop-filter: blur(15px);
+ backdrop-filter: blur(20px);
border-radius: #{$border-radius-extra-large};
outline: 1px solid var(--border-color);
box-shadow: #{$box-shadow-medium};
@@ -250,7 +250,7 @@
top: 32px;
right: 8px;
background: var(--background-color);
- backdrop-filter: blur(15px);
+ backdrop-filter: blur(20px);
border-radius: #{$border-radius-extra-large};
outline: 1px solid var(--border-color);
box-shadow: #{$box-shadow-medium};
@@ -363,7 +363,7 @@
height: 34px;
width: 34px;
border-radius: #{$border-radius-circle};
- background: var(--background-color-secondary);
+ background: var(--background-color-solid-gradient);
backdrop-filter: blur(12px);
outline: 1px solid var(--border-color);
outline-offset: -1px;
diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss
index abc626a..09b73a9 100644
--- a/app/src/styles/pages/realTimeViz.scss
+++ b/app/src/styles/pages/realTimeViz.scss
@@ -67,8 +67,8 @@
min-width: 150px;
z-index: 3;
transform: translate(-50%, -10%);
- transition: transform 0.5s linear;
pointer-events: all;
+ transition: all 0.3s linear;
&::-webkit-scrollbar {
display: none;
@@ -243,6 +243,7 @@
&:hover {
background: var(--highlight-accent-color);
width: 100%;
+
.label {
color: var(--accent-color);
}
@@ -619,6 +620,7 @@
.label {
color: var(--accent-color);
}
+
background: var(--highlight-accent-color);
width: 100%;
@@ -738,10 +740,10 @@
outline-color: #ffe3e0;
}
-.editWidgetOptions {
+.context-menu-options {
position: absolute;
background: var(--background-color);
- backdrop-filter: blur(10px);
+ backdrop-filter: blur(20px);
z-index: 3;
display: flex;
flex-direction: column;
@@ -749,6 +751,7 @@
overflow: hidden;
padding: 4px;
min-width: 150px;
+ outline: 1px solid var(--border-color);
.option {
padding: 4px 10px;
@@ -933,4 +936,4 @@
opacity: 0;
transform: scaleY(0);
}
-}
+}
\ No newline at end of file
diff --git a/app/src/styles/pages/userAuth.scss b/app/src/styles/pages/userAuth.scss
index 9d07dcf..cb45c13 100644
--- a/app/src/styles/pages/userAuth.scss
+++ b/app/src/styles/pages/userAuth.scss
@@ -48,16 +48,16 @@
max-width: 350px;
padding: 10px;
margin-bottom: 20px;
- border: 1px solid var(--accent-color);
+ border: 1px solid var(--highlight-text-color);
border-radius: #{$border-radius-extra-large};
background: transparent;
- color: var(--accent-color);
+ color: var(--highlight-text-color);
font-size: 14px;
outline: none;
cursor: pointer;
.google-icon {
- color: var(--accent-color);
+ color: var(--highlight-text-color);
font-weight: bold;
font-size: 16px;
margin-right: 10px;
@@ -89,7 +89,7 @@
border-radius: #{$border-radius-extra-large};
background: var(--background-color);
font-size: 14px;
- color: var(--input-text-color);
+ color: var(--text-button-color);
&:focus {
border-color: var(--accent-color);
@@ -120,8 +120,8 @@
.continue-button {
width: 100%;
padding: 10px;
- background: var(--accent-gradient-color);
- color: var(--background-color);
+ background: var(--background-color-button);
+ color: var(--text-button-color);
font-size: 14px;
border: none;
outline: none;
@@ -158,7 +158,7 @@
text-align: center;
.link {
- color: var(--accent-color);
+ color: var(--highlight-text-color);
text-decoration: none;
&:hover {
text-decoration: underline;