From cdcdf60e02b7616b4718738b8a99df36f6dfa52f Mon Sep 17 00:00:00 2001 From: arorad1 Date: Wed, 17 Jul 2024 19:53:24 -0700 Subject: [PATCH 01/56] Basic UI for ConfiguringRobotBrainPanel --- fission/src/Synthesis.tsx | 2 + fission/src/systems/simulation/Brain.ts | 4 +- fission/src/ui/components/MainHUD.tsx | 1 + .../configuring/ConfigureRobotBrainPanel.tsx | 86 +++++++++++++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index 57025c7b95..5a2dcd44c8 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -59,6 +59,7 @@ import Skybox from "./ui/components/Skybox.tsx" import ConfigureRobotModal from "./ui/modals/configuring/ConfigureRobotModal.tsx" import ResetAllInputsModal from "./ui/modals/configuring/ResetAllInputsModal.tsx" import ZoneConfigPanel from "./ui/panels/configuring/scoring/ZoneConfigPanel.tsx" +import ConfigureRobotBrainPanel from "./ui/panels/configuring/ConfigureRobotBrainPanel.tsx" const DEFAULT_MIRA_PATH = "/api/mira/Robots/Team 2471 (2018)_v7.mira" @@ -243,6 +244,7 @@ const initialPanels: ReactElement[] = [ , , , + , ] export default Synthesis diff --git a/fission/src/systems/simulation/Brain.ts b/fission/src/systems/simulation/Brain.ts index a047d65671..d784195e8e 100644 --- a/fission/src/systems/simulation/Brain.ts +++ b/fission/src/systems/simulation/Brain.ts @@ -3,8 +3,8 @@ import Mechanism from "../physics/Mechanism" abstract class Brain { protected _mechanism: Mechanism - constructor(mechansim: Mechanism) { - this._mechanism = mechansim + constructor(mechanism: Mechanism) { + this._mechanism = mechanism } public abstract Update(deltaT: number): void diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 717df814de..457ee80282 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -189,6 +189,7 @@ const MainHUD: React.FC = () => { }} /> } onClick={() => openModal("config-robot")} /> + } onClick={() => openPanel("config-robot-brain")} /> {userInfo ? ( = ({ panelId, openLocation, sidePadding }) => { + const [selectedRobot, setSelectedRobot] = useState(undefined) + const [viewType, setViewType] = useState(ConfigureRobotBrainTypes.SYNTHESIS) + const robots = useMemo(() => { + const assemblies = [...World.SceneRenderer.sceneObjects.values()].filter(x => { + if (x instanceof MirabufSceneObject) { + return x.miraType === MiraType.ROBOT + } + return false + }) as MirabufSceneObject[] + return assemblies + }, []) + + return ( + } + panelId={panelId} + openLocation={openLocation} + sidePadding={sidePadding} + onAccept={() => { }} + onCancel={() => { }} + > + {selectedRobot?.ejectorPreferences == undefined ? ( + <> + + {/** Scroll view for selecting a robot to configure */} +
+ {robots.map(mirabufSceneObject => { + return ( + + ) + })} +
+ {/* TODO: remove the accept button on this version */} + + ) : ( + <> + +
+ v != null && setViewType(v)} + sx={{ + alignSelf: "center", + }} + > + SynthesisBrain + WIPLIBBrain + + {viewType === ConfigureRobotBrainTypes.SYNTHESIS ? ( + + ) : ( + + )} +
+ + )} +
+ ); +} + +export default ConfigureRobotBrainPanel; \ No newline at end of file From 4cb61f24e317fbdbc8685af582e96d9f3c378ade Mon Sep 17 00:00:00 2001 From: arorad1 Date: Thu, 18 Jul 2024 14:38:17 -0700 Subject: [PATCH 02/56] Formatting --- fission/src/Synthesis.tsx | 7 +++- fission/src/ui/components/MainHUD.tsx | 6 +++- .../configuring/ConfigureRobotBrainPanel.tsx | 33 ++++++++----------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index 5a2dcd44c8..1dff4b2c9d 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -244,7 +244,12 @@ const initialPanels: ReactElement[] = [ , , , - , + , ] export default Synthesis diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 457ee80282..9a138905dc 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -189,7 +189,11 @@ const MainHUD: React.FC = () => { }} /> } onClick={() => openModal("config-robot")} /> - } onClick={() => openPanel("config-robot-brain")} /> + } + onClick={() => openPanel("config-robot-brain")} + /> {userInfo ? ( = ({ panelId, openLocat panelId={panelId} openLocation={openLocation} sidePadding={sidePadding} - onAccept={() => { }} - onCancel={() => { }} + onAccept={() => {}} + onCancel={() => {}} > {selectedRobot?.ejectorPreferences == undefined ? ( <> @@ -58,7 +58,6 @@ const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocat ) : ( <> -
= ({ panelId, openLocat SynthesisBrain WIPLIBBrain - {viewType === ConfigureRobotBrainTypes.SYNTHESIS ? ( - - ) : ( - - )} + {viewType === ConfigureRobotBrainTypes.SYNTHESIS ? : }
)} - ); + ) } -export default ConfigureRobotBrainPanel; \ No newline at end of file +export default ConfigureRobotBrainPanel From c2e80f72fb191b4c5ac3862b027ef54d650e74ec Mon Sep 17 00:00:00 2001 From: arorad1 Date: Fri, 19 Jul 2024 13:12:13 -0700 Subject: [PATCH 03/56] Added UI --- .../configuring/ConfigureRobotBrainPanel.tsx | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx index 199fef056c..e13f244727 100644 --- a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx +++ b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx @@ -1,12 +1,13 @@ import { MiraType } from "@/mirabuf/MirabufLoader" import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" import World from "@/systems/World" -import Label from "@/ui/components/Label" +import Label, { LabelSize } from "@/ui/components/Label" import Button from "@/ui/components/Button" import Panel, { PanelPropsImpl } from "@/ui/components/Panel" import { useMemo, useState } from "react" import { FaGear } from "react-icons/fa6" import { ToggleButton, ToggleButtonGroup } from "@/ui/components/ToggleButtonGroup" +import { Divider, styled } from "@mui/material" // eslint-disable-next-line react-refresh/only-export-components export enum ConfigureRobotBrainTypes { @@ -14,6 +15,15 @@ export enum ConfigureRobotBrainTypes { WIPLIB = 1, } +const LabelStyled = styled(Label)({ + fontWeight: 700, + margin: "0pt", +}) + +const DividerStyled = styled(Divider)({ + borderColor: "white", +}) + const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocation, sidePadding }) => { const [selectedRobot, setSelectedRobot] = useState(undefined) const [viewType, setViewType] = useState(ConfigureRobotBrainTypes.SYNTHESIS) @@ -70,7 +80,31 @@ const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocat SynthesisBrain WIPLIBBrain - {viewType === ConfigureRobotBrainTypes.SYNTHESIS ? : } + {viewType === ConfigureRobotBrainTypes.SYNTHESIS ? ( + <> + + Behaviors + + + + + thing2 + + + + + thing3 + + + + + thing4 + + + + ) : ( + + )} )} From 628a1aec4a55d4941c9d764bb54d391248707a15 Mon Sep 17 00:00:00 2001 From: arorad1 Date: Fri, 19 Jul 2024 13:14:58 -0700 Subject: [PATCH 04/56] Updated wiplibbrain --- .../configuring/ConfigureRobotBrainPanel.tsx | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx index e13f244727..ad04d5bb68 100644 --- a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx +++ b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx @@ -103,7 +103,27 @@ const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocat ) : ( - + <> + + Example WIPLIB Brain + + + + + Example 2 + + + + + Example 3 + + + + + Example 4 + + + )} From 4f182f02735744565b81b7dcad0aa8d1eae0171f Mon Sep 17 00:00:00 2001 From: arorad1 Date: Fri, 19 Jul 2024 20:04:42 -0700 Subject: [PATCH 05/56] Adding basic Cascading Shadows implementation --- fission/src/systems/scene/CascadingShadows.ts | 94 +++++++++++++++++++ fission/src/systems/scene/SceneRenderer.ts | 36 ++++--- 2 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 fission/src/systems/scene/CascadingShadows.ts diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts new file mode 100644 index 0000000000..f80a61f237 --- /dev/null +++ b/fission/src/systems/scene/CascadingShadows.ts @@ -0,0 +1,94 @@ +import * as THREE from 'three'; + +class CascadingShadows { + private _camera: THREE.PerspectiveCamera; + private _shadowCameras: THREE.OrthographicCamera[] = []; + private _scene: THREE.Scene; + + private _renderer: THREE.WebGLRenderer; + private _light: THREE.DirectionalLight; + private _shadowMaps: THREE.WebGLRenderTarget[] = []; // One shadow map per cascade + + private _numCascades: number; + private _cascadeSplits: number[]; + + constructor(camera: THREE.PerspectiveCamera, scene: THREE.Scene, renderer: THREE.WebGLRenderer, numCascades: number = 5) { + this._camera = camera; + this._scene = scene; + this._renderer = renderer; + this._numCascades = numCascades; + + // Creating the directional light + this._light = new THREE.DirectionalLight(0xffffff, 3); + this._light.position.set(-1, 3, 2); + this._light.castShadow = true; + scene.add(this._light); + + // Split the camera frustum into numCascades cascades + this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades); + + // Create the shadow camera and shadow maps + for (let i = 0; i < numCascades; i++) { + const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500); + shadowCamera.position.copy(this._light.position); + shadowCamera.lookAt(0, 0, 0); + this._shadowCameras.push(shadowCamera); + + const shadowMap = new THREE.WebGLRenderTarget(1024, 1024, { + minFilter: THREE.NearestFilter, + magFilter: THREE.NearestFilter, + format: THREE.RGBAFormat, + }); + this._shadowMaps.push(shadowMap); + } + } + + /** Updates the shadow maps */ + public Update() { + const frustum = new THREE.Frustum(); + const projScreenMatrix = new THREE.Matrix4(); + projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse); + frustum.setFromProjectionMatrix(projScreenMatrix); + + for (let i = 0; i < this._numCascades; i++) { + const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near); + const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near); + + const cascadeFrustum = new THREE.Frustum(); + cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)); + + const shadowCamera = this._shadowCameras[i]; + shadowCamera.position.copy(this._light.position); + shadowCamera.lookAt(0, 0, 0); + shadowCamera.updateMatrixWorld(); + shadowCamera.updateProjectionMatrix(); + + this._renderer.setRenderTarget(this._shadowMaps[i]); + this._renderer.render(this._scene, shadowCamera); + } + + this._renderer.setRenderTarget(null); + } + + /** Returns the projection matrix for the cascade */ + private GetCascadeMatrix(near: number, far: number): THREE.Matrix4 { + const matrix = new THREE.Matrix4(); + const projMatrix = new THREE.Matrix4().makePerspective( + this._camera.fov, + this._camera.aspect, + near, + far, + this._camera.near, + this._camera.far + ); + const invMatrix = this._camera.matrixWorld.invert(); + matrix.multiplyMatrices(projMatrix, invMatrix); + return matrix; + } + + public getShadowMap(index: number): THREE.WebGLRenderTarget { + return this._shadowMaps[index]; + } +} + +export default CascadingShadows; diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 1590a15c9a..6458b6508a 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -14,6 +14,7 @@ import InputSystem from "../input/InputSystem" import { PixelSpaceCoord, SceneOverlayEvent, SceneOverlayEventKey } from "@/ui/components/SceneOverlayEvents" import {} from "@/ui/components/SceneOverlayEvents" import PreferencesSystem from "../preferences/PreferencesSystem" +import CascadingShadows from "./CascadingShadows" const CLEAR_COLOR = 0x121212 const GROUND_COLOR = 0x4066c7 @@ -34,6 +35,8 @@ class SceneRenderer extends WorldSystem { private _orbitControls: OrbitControls private _transformControls: Map // maps all rendered transform controls to their size + private _light: CascadingShadows + public get sceneObjects() { return this._sceneObjects } @@ -74,23 +77,25 @@ class SceneRenderer extends WorldSystem { this._renderer.shadowMap.type = THREE.PCFSoftShadowMap this._renderer.setSize(window.innerWidth, window.innerHeight) - const directionalLight = new THREE.DirectionalLight(0xffffff, 3.0) - directionalLight.position.set(-1.0, 3.0, 2.0) - directionalLight.castShadow = true - this._scene.add(directionalLight) + // const directionalLight = new THREE.DirectionalLight(0xffffff, 3.0) + // directionalLight.position.set(-1.0, 3.0, 2.0) + // directionalLight.castShadow = true + // this._scene.add(directionalLight) + + // const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) + // const shadowCamSize = 15 + // console.debug(`Shadow Map Size: ${shadowMapSize}`) - const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) - const shadowCamSize = 15 - console.debug(`Shadow Map Size: ${shadowMapSize}`) + // directionalLight.shadow.camera.top = shadowCamSize + // directionalLight.shadow.camera.bottom = -shadowCamSize + // directionalLight.shadow.camera.left = -shadowCamSize + // directionalLight.shadow.camera.right = shadowCamSize + // directionalLight.shadow.mapSize = new THREE.Vector2(shadowMapSize, shadowMapSize) + // directionalLight.shadow.blurSamples = 16 + // directionalLight.shadow.normalBias = 0.01 + // directionalLight.shadow.bias = 0.0 - directionalLight.shadow.camera.top = shadowCamSize - directionalLight.shadow.camera.bottom = -shadowCamSize - directionalLight.shadow.camera.left = -shadowCamSize - directionalLight.shadow.camera.right = shadowCamSize - directionalLight.shadow.mapSize = new THREE.Vector2(shadowMapSize, shadowMapSize) - directionalLight.shadow.blurSamples = 16 - directionalLight.shadow.normalBias = 0.01 - directionalLight.shadow.bias = 0.0 + this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) this._scene.add(ambientLight) @@ -143,6 +148,7 @@ class SceneRenderer extends WorldSystem { this._sceneObjects.forEach(obj => { obj.Update() }) + this._light.Update() this._skybox.position.copy(this._mainCamera.position) From 323386e0b7e0900e8ed0eed854597ec81983ac20 Mon Sep 17 00:00:00 2001 From: arorad1 Date: Fri, 19 Jul 2024 20:08:16 -0700 Subject: [PATCH 06/56] Formatting --- fission/src/systems/scene/CascadingShadows.ts | 109 +++++++++--------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts index f80a61f237..65d7a11667 100644 --- a/fission/src/systems/scene/CascadingShadows.ts +++ b/fission/src/systems/scene/CascadingShadows.ts @@ -1,78 +1,83 @@ -import * as THREE from 'three'; +import * as THREE from "three" class CascadingShadows { - private _camera: THREE.PerspectiveCamera; - private _shadowCameras: THREE.OrthographicCamera[] = []; - private _scene: THREE.Scene; - - private _renderer: THREE.WebGLRenderer; - private _light: THREE.DirectionalLight; - private _shadowMaps: THREE.WebGLRenderTarget[] = []; // One shadow map per cascade - - private _numCascades: number; - private _cascadeSplits: number[]; - - constructor(camera: THREE.PerspectiveCamera, scene: THREE.Scene, renderer: THREE.WebGLRenderer, numCascades: number = 5) { - this._camera = camera; - this._scene = scene; - this._renderer = renderer; - this._numCascades = numCascades; + private _camera: THREE.PerspectiveCamera + private _shadowCameras: THREE.OrthographicCamera[] = [] + private _scene: THREE.Scene + + private _renderer: THREE.WebGLRenderer + private _light: THREE.DirectionalLight + private _shadowMaps: THREE.WebGLRenderTarget[] = [] // One shadow map per cascade + + private _numCascades: number + private _cascadeSplits: number[] + + constructor( + camera: THREE.PerspectiveCamera, + scene: THREE.Scene, + renderer: THREE.WebGLRenderer, + numCascades: number = 5 + ) { + this._camera = camera + this._scene = scene + this._renderer = renderer + this._numCascades = numCascades // Creating the directional light - this._light = new THREE.DirectionalLight(0xffffff, 3); - this._light.position.set(-1, 3, 2); - this._light.castShadow = true; - scene.add(this._light); - + this._light = new THREE.DirectionalLight(0xffffff, 3) + this._light.position.set(-1, 3, 2) + this._light.castShadow = true + scene.add(this._light) + // Split the camera frustum into numCascades cascades - this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades); + this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades) // Create the shadow camera and shadow maps for (let i = 0; i < numCascades; i++) { - const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500); - shadowCamera.position.copy(this._light.position); - shadowCamera.lookAt(0, 0, 0); - this._shadowCameras.push(shadowCamera); + const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500) + shadowCamera.position.copy(this._light.position) + shadowCamera.lookAt(0, 0, 0) + this._shadowCameras.push(shadowCamera) const shadowMap = new THREE.WebGLRenderTarget(1024, 1024, { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat, - }); - this._shadowMaps.push(shadowMap); + }) + this._shadowMaps.push(shadowMap) } } /** Updates the shadow maps */ public Update() { - const frustum = new THREE.Frustum(); - const projScreenMatrix = new THREE.Matrix4(); - projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse); - frustum.setFromProjectionMatrix(projScreenMatrix); + const frustum = new THREE.Frustum() + const projScreenMatrix = new THREE.Matrix4() + projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse) + frustum.setFromProjectionMatrix(projScreenMatrix) for (let i = 0; i < this._numCascades; i++) { - const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near); - const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near); + const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near) + const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near) - const cascadeFrustum = new THREE.Frustum(); - cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)); + const cascadeFrustum = new THREE.Frustum() + cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)) - const shadowCamera = this._shadowCameras[i]; - shadowCamera.position.copy(this._light.position); - shadowCamera.lookAt(0, 0, 0); - shadowCamera.updateMatrixWorld(); - shadowCamera.updateProjectionMatrix(); + const shadowCamera = this._shadowCameras[i] + shadowCamera.position.copy(this._light.position) + shadowCamera.lookAt(0, 0, 0) + shadowCamera.updateMatrixWorld() + shadowCamera.updateProjectionMatrix() - this._renderer.setRenderTarget(this._shadowMaps[i]); - this._renderer.render(this._scene, shadowCamera); + this._renderer.setRenderTarget(this._shadowMaps[i]) + this._renderer.render(this._scene, shadowCamera) } - this._renderer.setRenderTarget(null); + this._renderer.setRenderTarget(null) } /** Returns the projection matrix for the cascade */ private GetCascadeMatrix(near: number, far: number): THREE.Matrix4 { - const matrix = new THREE.Matrix4(); + const matrix = new THREE.Matrix4() const projMatrix = new THREE.Matrix4().makePerspective( this._camera.fov, this._camera.aspect, @@ -80,15 +85,15 @@ class CascadingShadows { far, this._camera.near, this._camera.far - ); - const invMatrix = this._camera.matrixWorld.invert(); - matrix.multiplyMatrices(projMatrix, invMatrix); - return matrix; + ) + const invMatrix = this._camera.matrixWorld.invert() + matrix.multiplyMatrices(projMatrix, invMatrix) + return matrix } public getShadowMap(index: number): THREE.WebGLRenderTarget { - return this._shadowMaps[index]; + return this._shadowMaps[index] } } -export default CascadingShadows; +export default CascadingShadows From e716d0ba0c329f0ae3644981a36d0360f5536928 Mon Sep 17 00:00:00 2001 From: arorad1 Date: Mon, 22 Jul 2024 11:57:24 -0700 Subject: [PATCH 07/56] Changing light color and intensity and removing old lighting implementation --- fission/src/systems/scene/CascadingShadows.ts | 2 +- fission/src/systems/scene/SceneRenderer.ts | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts index 65d7a11667..b1b9d5b4a2 100644 --- a/fission/src/systems/scene/CascadingShadows.ts +++ b/fission/src/systems/scene/CascadingShadows.ts @@ -24,7 +24,7 @@ class CascadingShadows { this._numCascades = numCascades // Creating the directional light - this._light = new THREE.DirectionalLight(0xffffff, 3) + this._light = new THREE.DirectionalLight(0xb6c6e3, 5.0) this._light.position.set(-1, 3, 2) this._light.castShadow = true scene.add(this._light) diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 6458b6508a..a4af554078 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -77,24 +77,6 @@ class SceneRenderer extends WorldSystem { this._renderer.shadowMap.type = THREE.PCFSoftShadowMap this._renderer.setSize(window.innerWidth, window.innerHeight) - // const directionalLight = new THREE.DirectionalLight(0xffffff, 3.0) - // directionalLight.position.set(-1.0, 3.0, 2.0) - // directionalLight.castShadow = true - // this._scene.add(directionalLight) - - // const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) - // const shadowCamSize = 15 - // console.debug(`Shadow Map Size: ${shadowMapSize}`) - - // directionalLight.shadow.camera.top = shadowCamSize - // directionalLight.shadow.camera.bottom = -shadowCamSize - // directionalLight.shadow.camera.left = -shadowCamSize - // directionalLight.shadow.camera.right = shadowCamSize - // directionalLight.shadow.mapSize = new THREE.Vector2(shadowMapSize, shadowMapSize) - // directionalLight.shadow.blurSamples = 16 - // directionalLight.shadow.normalBias = 0.01 - // directionalLight.shadow.bias = 0.0 - this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) From adeccb677c6182190abd756b1ae4a78e4ebad740 Mon Sep 17 00:00:00 2001 From: arorad1 Date: Mon, 22 Jul 2024 15:05:05 -0700 Subject: [PATCH 08/56] Adding basic UI for displaying joints --- fission/src/mirabuf/MirabufSceneObject.ts | 4 + .../behavior/ArcadeDriveBehavior.ts | 4 + .../simulation/behavior/GenericArmBehavior.ts | 4 + .../behavior/GenericElevatorBehavior.ts | 4 + .../systems/simulation/driver/HingeDriver.ts | 4 + .../systems/simulation/driver/SliderDriver.ts | 4 + .../synthesis_brain/SynthesisBrain.ts | 4 + .../configuring/ConfigureRobotBrainPanel.tsx | 150 +++++++++++++++--- 8 files changed, 159 insertions(+), 19 deletions(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 4c4cdd1414..8dfc12fa8a 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -56,6 +56,10 @@ class MirabufSceneObject extends SceneObject { return this._mechanism } + get brain() { + return this._brain + } + get assemblyName() { return this._assemblyName } diff --git a/fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts b/fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts index 374f5684d9..8d4392e349 100644 --- a/fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts +++ b/fission/src/systems/simulation/behavior/ArcadeDriveBehavior.ts @@ -12,6 +12,10 @@ class ArcadeDriveBehavior extends Behavior { private _driveSpeed = 30 private _turnSpeed = 30 + public get wheels(): WheelDriver[] { + return this.leftWheels.concat(this.rightWheels) + } + constructor( leftWheels: WheelDriver[], rightWheels: WheelDriver[], diff --git a/fission/src/systems/simulation/behavior/GenericArmBehavior.ts b/fission/src/systems/simulation/behavior/GenericArmBehavior.ts index fc9e9bbd5d..6572bdb94a 100644 --- a/fission/src/systems/simulation/behavior/GenericArmBehavior.ts +++ b/fission/src/systems/simulation/behavior/GenericArmBehavior.ts @@ -11,6 +11,10 @@ class GenericArmBehavior extends Behavior { private _rotationalSpeed = 6 + public get hingeDriver(): HingeDriver { + return this._hingeDriver + } + constructor( hingeDriver: HingeDriver, hingeStimulus: HingeStimulus, diff --git a/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts b/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts index f1c01bde56..811b9211ec 100644 --- a/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts +++ b/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts @@ -11,6 +11,10 @@ class GenericElevatorBehavior extends Behavior { private _linearSpeed = 2.5 + public get sliderDriver(): SliderDriver { + return this._sliderDriver + } + constructor( sliderDriver: SliderDriver, sliderStimulus: SliderStimulus, diff --git a/fission/src/systems/simulation/driver/HingeDriver.ts b/fission/src/systems/simulation/driver/HingeDriver.ts index 6940afbc8c..f747c99f48 100644 --- a/fission/src/systems/simulation/driver/HingeDriver.ts +++ b/fission/src/systems/simulation/driver/HingeDriver.ts @@ -10,6 +10,10 @@ class HingeDriver extends Driver { private _targetVelocity: number = 0.0 private _targetAngle: number + public get constraint(): Jolt.HingeConstraint { + return this._constraint + } + public get targetVelocity(): number { return this._targetVelocity } diff --git a/fission/src/systems/simulation/driver/SliderDriver.ts b/fission/src/systems/simulation/driver/SliderDriver.ts index 6bf361d445..68fff04d85 100644 --- a/fission/src/systems/simulation/driver/SliderDriver.ts +++ b/fission/src/systems/simulation/driver/SliderDriver.ts @@ -10,6 +10,10 @@ class SliderDriver extends Driver { private _targetVelocity: number = 0.0 private _targetPosition: number = 0.0 + public get constraint(): Jolt.SliderConstraint { + return this._constraint + } + public get targetVelocity(): number { return this._targetVelocity } diff --git a/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts b/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts index a44411acaf..77030adae0 100644 --- a/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts +++ b/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts @@ -28,6 +28,10 @@ class SynthesisBrain extends Brain { private _assemblyName: string private _assemblyIndex: number = 0 + public get behaviors(): Behavior[] { + return this._behaviors + } + // Tracks the number of each specific mira file spawned public static numberRobotsSpawned: { [key: string]: number } = {} diff --git a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx index ad04d5bb68..5ed2db3995 100644 --- a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx +++ b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx @@ -1,5 +1,5 @@ import { MiraType } from "@/mirabuf/MirabufLoader" -import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" +import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject" import World from "@/systems/World" import Label, { LabelSize } from "@/ui/components/Label" import Button from "@/ui/components/Button" @@ -8,6 +8,11 @@ import { useMemo, useState } from "react" import { FaGear } from "react-icons/fa6" import { ToggleButton, ToggleButtonGroup } from "@/ui/components/ToggleButtonGroup" import { Divider, styled } from "@mui/material" +import ArcadeDriveBehavior from "@/systems/simulation/behavior/ArcadeDriveBehavior" +import GenericArmBehavior from "@/systems/simulation/behavior/GenericArmBehavior" +import GenericElevatorBehavior from "@/systems/simulation/behavior/GenericElevatorBehavior" +import Stack, { StackDirection } from "@/ui/components/Stack" +import { JSX } from "react/jsx-runtime" // eslint-disable-next-line react-refresh/only-export-components export enum ConfigureRobotBrainTypes { @@ -24,6 +29,127 @@ const DividerStyled = styled(Divider)({ borderColor: "white", }) +/** + * Retrieves the joints of a robot and generates JSX elements for each joint. + * @param robot The MirabufSceneObject representing the robot. + * @returns An array of JSX elements representing the joints of the robot. + */ +function GetJoints(robot: MirabufSceneObject): JSX.Element[] { + const output: JSX.Element[] = [] + let elementKey = 0 + + /* Iterate through each behavior of the robot */ + robot.brain?.behaviors.forEach(behavior => { + /* Adds the joints that the wheels are associated with */ + if (behavior instanceof ArcadeDriveBehavior) { + behavior.wheels.forEach(wheel => { + const assoc = World.PhysicsSystem.GetBodyAssociation( + wheel.constraint.GetVehicleBody().GetID() + ) as RigidNodeAssociate + + if (!assoc || assoc.sceneObject !== robot) { + return + } + + output.push( + + + Wheel Node {elementKey} + + + {assoc.rigidNodeId} + + + ) + elementKey++ + }) + output.push() + } else if (behavior instanceof GenericArmBehavior) { + + /* Adds the joints that the arm is associated with */ + // Get the rigid node associates for the two bodies + const assoc1 = World.PhysicsSystem.GetBodyAssociation( + behavior.hingeDriver.constraint.GetBody1().GetID() + ) as RigidNodeAssociate + const assoc2 = World.PhysicsSystem.GetBodyAssociation( + behavior.hingeDriver.constraint.GetBody2().GetID() + ) as RigidNodeAssociate + + if (!assoc1 || assoc1.sceneObject !== robot || !assoc2 || assoc2.sceneObject !== robot) { + return + } + + output.push( + + + Arm Nodes + + + {assoc1.rigidNodeId + " " + assoc2.rigidNodeId} + + + ) + elementKey++ + } else if (behavior instanceof GenericElevatorBehavior) { + + /* Adds the joints that the elevator is associated with */ + // Get the rigid node associates for the two bodies + const assoc1 = World.PhysicsSystem.GetBodyAssociation( + behavior.sliderDriver.constraint.GetBody1().GetID() + ) as RigidNodeAssociate + const assoc2 = World.PhysicsSystem.GetBodyAssociation( + behavior.sliderDriver.constraint.GetBody2().GetID() + ) as RigidNodeAssociate + + if (!assoc1 || assoc1.sceneObject !== robot || !assoc2 || assoc2.sceneObject !== robot) { + return + } + + output.push( + + + Elevator Nodes + + + {assoc1.rigidNodeId + " " + assoc2.rigidNodeId} + + + ) + elementKey++ + } + }) + + return output +} + const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocation, sidePadding }) => { const [selectedRobot, setSelectedRobot] = useState(undefined) const [viewType, setViewType] = useState(ConfigureRobotBrainTypes.SYNTHESIS) @@ -83,29 +209,15 @@ const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocat {viewType === ConfigureRobotBrainTypes.SYNTHESIS ? ( <> - Behaviors - - - - - thing2 - - - - - thing3 + Behaviors - - - thing4 - - + {GetJoints(selectedRobot)} ) : ( <> - Example WIPLIB Brain + Example WIPLIB Brain @@ -122,7 +234,7 @@ const ConfigureRobotBrainPanel: React.FC = ({ panelId, openLocat Example 4 - + )} From 1f936431a1166fc934c123144445398982181efd Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Tue, 23 Jul 2024 16:56:41 -0700 Subject: [PATCH 09/56] Basic parenting UI for sequential joints --- fission/src/Synthesis.tsx | 2 + .../simulation/behavior/GenericArmBehavior.ts | 6 + .../behavior/GenericElevatorBehavior.ts | 6 + fission/src/ui/components/MainHUD.tsx | 9 +- .../src/ui/panels/SequentialJointsPanel.tsx | 299 ++++++++++++++++++ .../configuring/ConfigureRobotBrainPanel.tsx | 6 +- 6 files changed, 322 insertions(+), 6 deletions(-) create mode 100644 fission/src/ui/panels/SequentialJointsPanel.tsx diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index dd3cf5985c..e39d2cddd1 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -67,6 +67,7 @@ import SceneOverlay from "./ui/components/SceneOverlay.tsx" import WPILibWSWorker from "@/systems/simulation/wpilib_brain/WPILibWSWorker.ts?worker" import WSViewPanel from "./ui/panels/WSViewPanel.tsx" import Lazy from "./util/Lazy.ts" +import SequentialJointsPanel from "./ui/panels/SequentialJointsPanel.tsx" const DEFAULT_MIRA_PATH = "/api/mira/Robots/Team 2471 (2018)_v7.mira" @@ -274,6 +275,7 @@ const initialPanels: ReactElement[] = [ sidePadding={8} />, , + , ] export default Synthesis diff --git a/fission/src/systems/simulation/behavior/GenericArmBehavior.ts b/fission/src/systems/simulation/behavior/GenericArmBehavior.ts index 6572bdb94a..86243d0d45 100644 --- a/fission/src/systems/simulation/behavior/GenericArmBehavior.ts +++ b/fission/src/systems/simulation/behavior/GenericArmBehavior.ts @@ -6,6 +6,7 @@ import InputSystem from "@/systems/input/InputSystem" class GenericArmBehavior extends Behavior { private _hingeDriver: HingeDriver private _inputName: string + private _jointIndex: number private _assemblyName: string private _assemblyIndex: number @@ -15,6 +16,10 @@ class GenericArmBehavior extends Behavior { return this._hingeDriver } + public get jointIndex(): number { + return this._jointIndex + } + constructor( hingeDriver: HingeDriver, hingeStimulus: HingeStimulus, @@ -26,6 +31,7 @@ class GenericArmBehavior extends Behavior { this._hingeDriver = hingeDriver this._inputName = "joint " + jointIndex + this._jointIndex = jointIndex this._assemblyName = assemblyName this._assemblyIndex = assemblyIndex } diff --git a/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts b/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts index 811b9211ec..90a8737e1a 100644 --- a/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts +++ b/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts @@ -6,6 +6,7 @@ import InputSystem from "@/systems/input/InputSystem" class GenericElevatorBehavior extends Behavior { private _sliderDriver: SliderDriver private _inputName: string + private _jointIndex: number private _assemblyName: string private _assemblyIndex: number @@ -15,6 +16,10 @@ class GenericElevatorBehavior extends Behavior { return this._sliderDriver } + public get jointIndex(): number { + return this._jointIndex + } + constructor( sliderDriver: SliderDriver, sliderStimulus: SliderStimulus, @@ -26,6 +31,7 @@ class GenericElevatorBehavior extends Behavior { this._sliderDriver = sliderDriver this._inputName = "joint " + jointIndex + this._jointIndex = jointIndex this._assemblyName = assemblyName this._assemblyIndex = assemblyIndex } diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 083a89f1fd..1715198771 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -181,7 +181,7 @@ const MainHUD: React.FC = () => { openPanel("scoring-zones") }} /> - } onClick={() => openModal("drivetrain")} /> + {/* } onClick={() => openModal("drivetrain")} /> } @@ -205,8 +205,13 @@ const MainHUD: React.FC = () => { const type: ToastType = ["info", "warning", "error"][Math.floor(Random() * 3)] as ToastType addToast(type, type, "This is a test toast to test the toast system") }} - /> + /> */} } onClick={() => openModal("config-robot")} /> + } + onClick={() => openPanel("sequential-joints")} + /> } diff --git a/fission/src/ui/panels/SequentialJointsPanel.tsx b/fission/src/ui/panels/SequentialJointsPanel.tsx new file mode 100644 index 0000000000..16b75585b2 --- /dev/null +++ b/fission/src/ui/panels/SequentialJointsPanel.tsx @@ -0,0 +1,299 @@ +import React, { useMemo, useReducer, useState } from "react" +import Panel, { PanelPropsImpl } from "../components/Panel" +import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" +import Label, { LabelSize } from "../components/Label" +import World from "@/systems/World" +import { MiraType } from "@/mirabuf/MirabufLoader" +import { FaArrowLeft, FaArrowRight, FaChevronDown, FaChevronUp, FaGear } from "react-icons/fa6" +import { Box, Button as MUIButton, Divider, styled } from "@mui/material" +import Button from "../components/Button" +import GenericArmBehavior from "@/systems/simulation/behavior/GenericArmBehavior" +import GenericElevatorBehavior from "@/systems/simulation/behavior/GenericElevatorBehavior" +import Behavior from "@/systems/simulation/behavior/Behavior" + +const ShiftRight = +const ShiftLeft = +const UpArrow = +const DownArrow = + +const LabelStyled = styled(Label)({ + fontWeight: 700, + margin: "0pt", +}) + +const ChildLabelStyled = styled(Label)({ + fontWeight: 700, + margin: "0pt", + color: "grey", +}) + +const DividerStyled = styled(Divider)({ + borderColor: "white", +}) + +function shiftArrayElementUp(arr: T[], elem: T): void { + const index = arr.indexOf(elem) + if (index > 0 && index < arr.length) { + let temp = arr[index] + arr[index] = arr[index - 1] + arr[index - 1] = temp + } +} + +function shiftArrayElementDown(arr: T[], elem: T): void { + const index = arr.indexOf(elem) + if (index >= 0 && index < arr.length - 1) { + let temp = arr[index] + arr[index] = arr[index + 1] + arr[index + 1] = temp + } +} + +type BehaviorConfiguration = { + behavior: Behavior + child: boolean +} + +interface BehaviorCardProps { + elementKey: number + name: string + behavior: BehaviorConfiguration + update: () => void + shiftUp: () => void + shiftDown: () => void + canShiftUp: boolean + canShiftDown: boolean + canBecomeChild: boolean +} + +const BehaviorCard: React.FC = ({ + elementKey, + name, + behavior, + update, + shiftUp, + shiftDown, + canShiftUp, + canShiftDown, + canBecomeChild, +}) => { + return ( + + + {behavior.child ? ( + <> + + + {name} + + + ) : ( + <> + + {name} + + + )} + + + + <> + + ) + })} + + + ) : ( + <> + + Behaviors + + + {GetBehaviorCards(behaviors, update)} + + )} + + ) +} + +export default SequentialJointsPanel diff --git a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx index 5ed2db3995..ba3c7b85b3 100644 --- a/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx +++ b/fission/src/ui/panels/configuring/ConfigureRobotBrainPanel.tsx @@ -77,8 +77,7 @@ function GetJoints(robot: MirabufSceneObject): JSX.Element[] { }) output.push() } else if (behavior instanceof GenericArmBehavior) { - - /* Adds the joints that the arm is associated with */ + /* Adds the joints that the arm is associated with */ // Get the rigid node associates for the two bodies const assoc1 = World.PhysicsSystem.GetBodyAssociation( behavior.hingeDriver.constraint.GetBody1().GetID() @@ -111,8 +110,7 @@ function GetJoints(robot: MirabufSceneObject): JSX.Element[] { ) elementKey++ } else if (behavior instanceof GenericElevatorBehavior) { - - /* Adds the joints that the elevator is associated with */ + /* Adds the joints that the elevator is associated with */ // Get the rigid node associates for the two bodies const assoc1 = World.PhysicsSystem.GetBodyAssociation( behavior.sliderDriver.constraint.GetBody1().GetID() From 96ca9586339bcc4c3819213be50249acf0bb0472 Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Wed, 24 Jul 2024 11:21:48 -0700 Subject: [PATCH 10/56] Working behavior parenting with a 'set' button, highlighting, and sorting --- fission/src/Synthesis.tsx | 4 +- .../ui/panels/SequentialBehaviorsPanel.tsx | 274 ++++++++++++++++ .../src/ui/panels/SequentialJointsPanel.tsx | 299 ------------------ 3 files changed, 276 insertions(+), 301 deletions(-) create mode 100644 fission/src/ui/panels/SequentialBehaviorsPanel.tsx delete mode 100644 fission/src/ui/panels/SequentialJointsPanel.tsx diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index e39d2cddd1..e8613d339a 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -67,7 +67,7 @@ import SceneOverlay from "./ui/components/SceneOverlay.tsx" import WPILibWSWorker from "@/systems/simulation/wpilib_brain/WPILibWSWorker.ts?worker" import WSViewPanel from "./ui/panels/WSViewPanel.tsx" import Lazy from "./util/Lazy.ts" -import SequentialJointsPanel from "./ui/panels/SequentialJointsPanel.tsx" +import SequentialBehaviorsPanel from "./ui/panels/SequentialBehaviorsPanel.tsx" const DEFAULT_MIRA_PATH = "/api/mira/Robots/Team 2471 (2018)_v7.mira" @@ -275,7 +275,7 @@ const initialPanels: ReactElement[] = [ sidePadding={8} />, , - , + , ] export default Synthesis diff --git a/fission/src/ui/panels/SequentialBehaviorsPanel.tsx b/fission/src/ui/panels/SequentialBehaviorsPanel.tsx new file mode 100644 index 0000000000..f0a10484de --- /dev/null +++ b/fission/src/ui/panels/SequentialBehaviorsPanel.tsx @@ -0,0 +1,274 @@ +import React, { useMemo, useReducer, useState } from "react" +import Panel, { PanelPropsImpl } from "../components/Panel" +import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" +import Label, { LabelSize } from "../components/Label" +import World from "@/systems/World" +import { MiraType } from "@/mirabuf/MirabufLoader" +import { FaGear, FaXmark } from "react-icons/fa6" +import { Box, Button as MUIButton, Divider, styled, alpha } from "@mui/material" +import Button, { ButtonSize } from "../components/Button" +import GenericArmBehavior from "@/systems/simulation/behavior/GenericArmBehavior" +import GenericElevatorBehavior from "@/systems/simulation/behavior/GenericElevatorBehavior" +import Behavior from "@/systems/simulation/behavior/Behavior" + +const UnselectParent = + +const LabelStyled = styled(Label)({ + fontWeight: 700, + margin: "0pt", +}) + +const ChildLabelStyled = styled(Label)({ + fontWeight: 700, + margin: "0pt", + color: "grey", +}) + +const DividerStyled = styled(Divider)({ + borderColor: "white", +}) + +const CustomButton = styled(MUIButton)({ + "borderStyle": "solid", + "borderWidth": "1px", + "transition": "border-color 0.3s ease", + "&:hover": { + borderColor: "white", + }, + "position": "relative", + "overflow": "hidden", + "& .MuiTouchRipple-root span": { + backgroundColor: alpha("#ffffff", 0.3), // Set your desired ripple color here + animationDuration: "300ms", + }, +}) + +type BehaviorConfiguration = { + behavior: Behavior + parent: BehaviorConfiguration | undefined +} + +interface BehaviorCardProps { + elementKey: number + name: string + behavior: BehaviorConfiguration + update: () => void + onParentPressed: () => void + parentPressed: BehaviorConfiguration | undefined + onBehaviorSelected: () => void + hasChild: boolean +} + +const BehaviorCard: React.FC = ({ + elementKey, + name, + behavior, + update, + onParentPressed, + parentPressed, + onBehaviorSelected, + hasChild, +}) => { + return ( + + + + {behavior.parent != undefined ? ( + <> + + {name} + + + ) : ( + <> + + {name} + + + )} + + { + onBehaviorSelected() + update() + }} + disabled={parentPressed == undefined || parentPressed == behavior || behavior.parent != undefined} + sx={{ + borderColor: + parentPressed == undefined || parentPressed == behavior || behavior.parent != undefined + ? "transparent" + : "#888888", + }} + /> + + + + + ) + })} + + + ) : ( + <> + + Set Parent Behaviors + + + {behaviors.map(behavior => { + if ( + behavior.behavior instanceof GenericArmBehavior || + behavior.behavior instanceof GenericElevatorBehavior + ) { + const jointIndex = behavior.behavior.jointIndex + return ( + { + if (behavior.parent != undefined) { + behavior.parent = undefined + update() + } else { + setLookingForParent(lookingForParent == behavior ? undefined : behavior) + } + update() + }} + parentPressed={lookingForParent} + onBehaviorSelected={() => { + if (lookingForParent) lookingForParent.parent = behavior + setLookingForParent(undefined) + update() + }} + hasChild={behaviors.some(b => b.parent == behavior)} + /> + ) + } else { + throw new Error("Behavior not of correct type") + } + })} + + )} + + ) +} + +export default SequentialBehaviorsPanel diff --git a/fission/src/ui/panels/SequentialJointsPanel.tsx b/fission/src/ui/panels/SequentialJointsPanel.tsx deleted file mode 100644 index 16b75585b2..0000000000 --- a/fission/src/ui/panels/SequentialJointsPanel.tsx +++ /dev/null @@ -1,299 +0,0 @@ -import React, { useMemo, useReducer, useState } from "react" -import Panel, { PanelPropsImpl } from "../components/Panel" -import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" -import Label, { LabelSize } from "../components/Label" -import World from "@/systems/World" -import { MiraType } from "@/mirabuf/MirabufLoader" -import { FaArrowLeft, FaArrowRight, FaChevronDown, FaChevronUp, FaGear } from "react-icons/fa6" -import { Box, Button as MUIButton, Divider, styled } from "@mui/material" -import Button from "../components/Button" -import GenericArmBehavior from "@/systems/simulation/behavior/GenericArmBehavior" -import GenericElevatorBehavior from "@/systems/simulation/behavior/GenericElevatorBehavior" -import Behavior from "@/systems/simulation/behavior/Behavior" - -const ShiftRight = -const ShiftLeft = -const UpArrow = -const DownArrow = - -const LabelStyled = styled(Label)({ - fontWeight: 700, - margin: "0pt", -}) - -const ChildLabelStyled = styled(Label)({ - fontWeight: 700, - margin: "0pt", - color: "grey", -}) - -const DividerStyled = styled(Divider)({ - borderColor: "white", -}) - -function shiftArrayElementUp(arr: T[], elem: T): void { - const index = arr.indexOf(elem) - if (index > 0 && index < arr.length) { - let temp = arr[index] - arr[index] = arr[index - 1] - arr[index - 1] = temp - } -} - -function shiftArrayElementDown(arr: T[], elem: T): void { - const index = arr.indexOf(elem) - if (index >= 0 && index < arr.length - 1) { - let temp = arr[index] - arr[index] = arr[index + 1] - arr[index + 1] = temp - } -} - -type BehaviorConfiguration = { - behavior: Behavior - child: boolean -} - -interface BehaviorCardProps { - elementKey: number - name: string - behavior: BehaviorConfiguration - update: () => void - shiftUp: () => void - shiftDown: () => void - canShiftUp: boolean - canShiftDown: boolean - canBecomeChild: boolean -} - -const BehaviorCard: React.FC = ({ - elementKey, - name, - behavior, - update, - shiftUp, - shiftDown, - canShiftUp, - canShiftDown, - canBecomeChild, -}) => { - return ( - - - {behavior.child ? ( - <> - - - {name} - - - ) : ( - <> - - {name} - - - )} - - - - <> - - ) - })} - - - ) : ( - <> - - Behaviors - - - {GetBehaviorCards(behaviors, update)} - - )} - - ) -} - -export default SequentialJointsPanel From 965bed1d1b4808ea6a7ceee60e748dba203e7ad2 Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Wed, 24 Jul 2024 12:06:33 -0700 Subject: [PATCH 11/56] Comments, cleanup, and format --- .../systems/simulation/behavior/Behavior.ts | 4 + .../simulation/behavior/GenericArmBehavior.ts | 4 +- .../behavior/GenericElevatorBehavior.ts | 4 +- fission/src/ui/components/MainHUD.tsx | 14 +- .../ui/panels/SequentialBehaviorsPanel.tsx | 191 ++++++++++-------- 5 files changed, 117 insertions(+), 100 deletions(-) diff --git a/fission/src/systems/simulation/behavior/Behavior.ts b/fission/src/systems/simulation/behavior/Behavior.ts index 2dd0fcb190..f9125f0514 100644 --- a/fission/src/systems/simulation/behavior/Behavior.ts +++ b/fission/src/systems/simulation/behavior/Behavior.ts @@ -20,4 +20,8 @@ abstract class Behavior { public abstract Update(deltaT: number): void } +export interface SequenceableBehavior { + get jointIndex(): number +} + export default Behavior diff --git a/fission/src/systems/simulation/behavior/GenericArmBehavior.ts b/fission/src/systems/simulation/behavior/GenericArmBehavior.ts index 86243d0d45..6c184f2f92 100644 --- a/fission/src/systems/simulation/behavior/GenericArmBehavior.ts +++ b/fission/src/systems/simulation/behavior/GenericArmBehavior.ts @@ -1,9 +1,9 @@ import HingeDriver from "../driver/HingeDriver" import HingeStimulus from "../stimulus/HingeStimulus" -import Behavior from "./Behavior" +import Behavior, { SequenceableBehavior } from "./Behavior" import InputSystem from "@/systems/input/InputSystem" -class GenericArmBehavior extends Behavior { +class GenericArmBehavior extends Behavior implements SequenceableBehavior { private _hingeDriver: HingeDriver private _inputName: string private _jointIndex: number diff --git a/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts b/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts index 90a8737e1a..f79989c60f 100644 --- a/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts +++ b/fission/src/systems/simulation/behavior/GenericElevatorBehavior.ts @@ -1,9 +1,9 @@ import SliderDriver from "../driver/SliderDriver" import SliderStimulus from "../stimulus/SliderStimulus" -import Behavior from "./Behavior" +import Behavior, { SequenceableBehavior } from "./Behavior" import InputSystem from "@/systems/input/InputSystem" -class GenericElevatorBehavior extends Behavior { +class GenericElevatorBehavior extends Behavior implements SequenceableBehavior { private _sliderDriver: SliderDriver private _inputName: string private _jointIndex: number diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 1715198771..43aca20504 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -160,6 +160,11 @@ const MainHUD: React.FC = () => { icon={} onClick={() => openPanel("driver-station")} /> + } + onClick={() => openPanel("sequential-joints")} + /> {/* MiraMap and OPFS Temp Buttons */} { openPanel("scoring-zones") }} /> - {/* } onClick={() => openModal("drivetrain")} /> + } onClick={() => openModal("drivetrain")} /> } @@ -205,13 +210,8 @@ const MainHUD: React.FC = () => { const type: ToastType = ["info", "warning", "error"][Math.floor(Random() * 3)] as ToastType addToast(type, type, "This is a test toast to test the toast system") }} - /> */} - } onClick={() => openModal("config-robot")} /> - } - onClick={() => openPanel("sequential-joints")} /> + } onClick={() => openModal("config-robot")} /> } diff --git a/fission/src/ui/panels/SequentialBehaviorsPanel.tsx b/fission/src/ui/panels/SequentialBehaviorsPanel.tsx index f0a10484de..c5107e1c62 100644 --- a/fission/src/ui/panels/SequentialBehaviorsPanel.tsx +++ b/fission/src/ui/panels/SequentialBehaviorsPanel.tsx @@ -8,16 +8,17 @@ import { FaGear, FaXmark } from "react-icons/fa6" import { Box, Button as MUIButton, Divider, styled, alpha } from "@mui/material" import Button, { ButtonSize } from "../components/Button" import GenericArmBehavior from "@/systems/simulation/behavior/GenericArmBehavior" -import GenericElevatorBehavior from "@/systems/simulation/behavior/GenericElevatorBehavior" -import Behavior from "@/systems/simulation/behavior/Behavior" +import { SequenceableBehavior } from "@/systems/simulation/behavior/Behavior" const UnselectParent = +/** White label for a behavior name */ const LabelStyled = styled(Label)({ fontWeight: 700, margin: "0pt", }) +/** Grey label for a child behavior name */ const ChildLabelStyled = styled(Label)({ fontWeight: 700, margin: "0pt", @@ -28,6 +29,7 @@ const DividerStyled = styled(Divider)({ borderColor: "white", }) +/** A button used to select a parent behavior. Appears at a grey outline when the 'set' button is pressed on a different behavior */ const CustomButton = styled(MUIButton)({ "borderStyle": "solid", "borderWidth": "1px", @@ -44,17 +46,19 @@ const CustomButton = styled(MUIButton)({ }) type BehaviorConfiguration = { - behavior: Behavior + behavior: SequenceableBehavior parent: BehaviorConfiguration | undefined } interface BehaviorCardProps { elementKey: number name: string + // The behavior displayed in this card behavior: BehaviorConfiguration + // The behavior whose 'set' button was just pressed + lookingForParent: BehaviorConfiguration | undefined update: () => void - onParentPressed: () => void - parentPressed: BehaviorConfiguration | undefined + onSetPressed: () => void onBehaviorSelected: () => void hasChild: boolean } @@ -64,91 +68,108 @@ const BehaviorCard: React.FC = ({ name, behavior, update, - onParentPressed, - parentPressed, + onSetPressed, + lookingForParent, onBehaviorSelected, hasChild, }) => { return ( + /* Box containing the entire card */ + {/* Box containing the label */} - + {/* Indentation before the name */} + + {/* Label for joint index and type (grey if child) */} {behavior.parent != undefined ? ( - <> - - {name} - - + + {name} + ) : ( - <> - - {name} - - + + {name} + )} + + {/* Button used for selecting a parent (shows up as an outline) */} { onBehaviorSelected() update() }} - disabled={parentPressed == undefined || parentPressed == behavior || behavior.parent != undefined} + disabled={lookingForParent == undefined || lookingForParent == behavior || behavior.parent != undefined} sx={{ borderColor: - parentPressed == undefined || parentPressed == behavior || behavior.parent != undefined + lookingForParent == undefined || lookingForParent == behavior || behavior.parent != undefined ? "transparent" : "#888888", }} /> - - - - ) - })} - - {/* TODO: remove the accept button on this version */} - - ) : ( - <> - {/* Button for user to select the parent node */} - trySetSelectedNode(body.GetID())} - /> - - {/* Slider for user to set velocity of ejector configuration */} - { - setZoneSize(vel as number) - }} - step={0.01} - /> - { - if (transformGizmo) { - const robotTransformation = JoltMat44_ThreeMatrix4( - World.PhysicsSystem.GetBody(selectedRobot.GetRootNodeId()!).GetWorldTransform() - ) - transformGizmo.mesh.position.setFromMatrixPosition(robotTransformation) - transformGizmo.mesh.rotation.setFromRotationMatrix(robotTransformation) - } - setZoneSize((MIN_ZONE_SIZE + MAX_ZONE_SIZE) / 2.0) - setSelectedNode(selectedRobot?.rootNodeId) - }} - /> - - )} - + <> + {/* Button for user to select the parent node */} + trySetSelectedNode(body.GetID())} + /> + + {/* Slider for user to set velocity of ejector configuration */} + { + setZoneSize(vel as number) + }} + step={0.01} + /> + { + if (transformGizmo) { + const robotTransformation = JoltMat44_ThreeMatrix4( + World.PhysicsSystem.GetBody(selectedRobot.GetRootNodeId()!).GetWorldTransform() + ) + transformGizmo.mesh.position.setFromMatrixPosition(robotTransformation) + transformGizmo.mesh.rotation.setFromRotationMatrix(robotTransformation) + } + setZoneSize((MIN_ZONE_SIZE + MAX_ZONE_SIZE) / 2.0) + setSelectedNode(selectedRobot?.rootNodeId) + }} + /> + ) } -export default ConfigureGamepiecePickupPanel +export default ConfigureGamepiecePickupInterface diff --git a/fission/src/ui/panels/configuring/ConfigureShotTrajectoryPanel.tsx b/fission/src/ui/panels/configuring/assembly-config/ConfigureShotTrajectoryInterface.tsx similarity index 57% rename from fission/src/ui/panels/configuring/ConfigureShotTrajectoryPanel.tsx rename to fission/src/ui/panels/configuring/assembly-config/ConfigureShotTrajectoryInterface.tsx index 6f8d2cd046..29ff7ad713 100644 --- a/fission/src/ui/panels/configuring/ConfigureShotTrajectoryPanel.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/ConfigureShotTrajectoryInterface.tsx @@ -1,17 +1,12 @@ import * as THREE from "three" import { useCallback, useEffect, useMemo, useState } from "react" -import { FaGear } from "react-icons/fa6" -import Panel, { PanelPropsImpl } from "@/components/Panel" import SelectButton from "@/components/SelectButton" import TransformGizmos from "@/ui/components/TransformGizmos" import Slider from "@/ui/components/Slider" import Jolt from "@barclah/jolt-physics" -import Label from "@/ui/components/Label" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" -import Button from "@/ui/components/Button" import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject" import World from "@/systems/World" -import { MiraType } from "@/mirabuf/MirabufLoader" import { Array_ThreeMatrix4, JoltMat44_ThreeMatrix4, @@ -21,6 +16,7 @@ import { import { useTheme } from "@/ui/ThemeContext" import LabeledButton, { LabelPlacement } from "@/ui/components/LabeledButton" import { RigidNodeId } from "@/mirabuf/MirabufParser" +import { ConfigurationSavedEvent } from "./ConfigureAssembliesPanel" // slider constants const MIN_VELOCITY = 0.0 @@ -77,25 +73,36 @@ function save( PreferencesSystem.savePreferences() } -const ConfigureShotTrajectoryPanel: React.FC = ({ panelId, openLocation, sidePadding }) => { +interface ConfigEjectorProps { + selectedRobot: MirabufSceneObject +} + +const ConfigureShotTrajectoryInterface: React.FC = ({ selectedRobot }) => { const { currentTheme, themes } = useTheme() const theme = useMemo(() => { return themes[currentTheme] }, [currentTheme, themes]) - const [selectedRobot, setSelectedRobot] = useState(undefined) const [selectedNode, setSelectedNode] = useState(undefined) const [ejectorVelocity, setEjectorVelocity] = useState((MIN_VELOCITY + MAX_VELOCITY) / 2.0) const [transformGizmo, setTransformGizmo] = useState(undefined) - const robots = useMemo(() => { - const assemblies = [...World.SceneRenderer.sceneObjects.values()].filter(x => { - if (x instanceof MirabufSceneObject) { - return x.miraType === MiraType.ROBOT - } - return false - }) as MirabufSceneObject[] - return assemblies - }, []) + + const saveEvent = useCallback(() => { + if (transformGizmo && selectedRobot) { + save(ejectorVelocity, transformGizmo, selectedRobot, selectedNode) + const currentGp = selectedRobot.activeEjectable + selectedRobot.SetEjectable(undefined, true) + selectedRobot.SetEjectable(currentGp) + } + }, [transformGizmo, selectedRobot, selectedNode, ejectorVelocity]) + + useEffect(() => { + ConfigurationSavedEvent.Listen(saveEvent) + + return () => { + ConfigurationSavedEvent.RemoveListener(saveEvent) + } + }, [saveEvent]) // Not sure I like this, but made it a state and effect rather than a memo to add the cleanup to the end useEffect(() => { @@ -176,84 +183,45 @@ const ConfigureShotTrajectoryPanel: React.FC = ({ panelId, openL ) return ( - } - panelId={panelId} - openLocation={openLocation} - sidePadding={sidePadding} - onAccept={() => { - if (transformGizmo && selectedRobot) { - save(ejectorVelocity, transformGizmo, selectedRobot, selectedNode) - const currentGp = selectedRobot.activeEjectable - selectedRobot.SetEjectable(undefined, true) - selectedRobot.SetEjectable(currentGp) - } - }} - onCancel={() => {}} - acceptEnabled={selectedRobot?.ejectorPreferences != undefined} - > - {selectedRobot?.ejectorPreferences == undefined ? ( - <> - - {/** Scroll view for selecting a robot to configure */} -
- {robots.map(mirabufSceneObject => { - return ( - - ) - })} -
- {/* TODO: remove the accept button on this version */} - - ) : ( - <> - {/* Button for user to select the parent node */} - trySetSelectedNode(body.GetID())} - /> - - {/* Slider for user to set velocity of ejector configuration */} - { - setEjectorVelocity(vel as number) - }} - step={0.01} - /> - { - if (transformGizmo) { - const robotTransformation = JoltMat44_ThreeMatrix4( - World.PhysicsSystem.GetBody(selectedRobot.GetRootNodeId()!).GetWorldTransform() - ) - transformGizmo.mesh.position.setFromMatrixPosition(robotTransformation) - transformGizmo.mesh.rotation.setFromRotationMatrix(robotTransformation) - } - setEjectorVelocity((MIN_VELOCITY + MAX_VELOCITY) / 2.0) - setSelectedNode(selectedRobot?.rootNodeId) - }} - /> - - )} -
+ <> + {/* Button for user to select the parent node */} + trySetSelectedNode(body.GetID())} + /> + + {/* Slider for user to set velocity of ejector configuration */} + { + setEjectorVelocity(vel as number) + }} + step={0.01} + /> + { + if (transformGizmo) { + const robotTransformation = JoltMat44_ThreeMatrix4( + World.PhysicsSystem.GetBody(selectedRobot.GetRootNodeId()!).GetWorldTransform() + ) + transformGizmo.mesh.position.setFromMatrixPosition(robotTransformation) + transformGizmo.mesh.rotation.setFromRotationMatrix(robotTransformation) + } + setEjectorVelocity((MIN_VELOCITY + MAX_VELOCITY) / 2.0) + setSelectedNode(selectedRobot?.rootNodeId) + }} + /> + ) } -export default ConfigureShotTrajectoryPanel +export default ConfigureShotTrajectoryInterface From 1b141da50e878bdeb6f3d9fe743ace5980b11183 Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Wed, 31 Jul 2024 11:47:10 -0700 Subject: [PATCH 22/56] Scoring zone config in configure assemblies panel --- fission/src/Synthesis.tsx | 4 - fission/src/ui/components/MainHUD.tsx | 8 - .../ConfigureAssembliesPanel.tsx | 23 +- .../ConfigureGamepiecePickupInterface.tsx | 2 +- .../ConfigureShotTrajectoryInterface.tsx | 2 +- .../ConfigureScoringZonesInterface.tsx | 47 ++++ .../scoring/ManageZonesInterface.tsx | 156 +++++++++++++ .../scoring/ZoneConfigInterface.tsx} | 202 ++++++++--------- .../configuring/scoring/ScoringZonesPanel.tsx | 206 ------------------ 9 files changed, 319 insertions(+), 331 deletions(-) rename fission/src/ui/panels/configuring/assembly-config/{ => interfaces}/ConfigureGamepiecePickupInterface.tsx (99%) rename fission/src/ui/panels/configuring/assembly-config/{ => interfaces}/ConfigureShotTrajectoryInterface.tsx (99%) create mode 100644 fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ConfigureScoringZonesInterface.tsx create mode 100644 fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ManageZonesInterface.tsx rename fission/src/ui/panels/configuring/{scoring/ZoneConfigPanel.tsx => assembly-config/interfaces/scoring/ZoneConfigInterface.tsx} (58%) delete mode 100644 fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index 5ce7e04b9d..88a719202d 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -37,7 +37,6 @@ import ThemeEditorModal from "@/modals/configuring/theme-editor/ThemeEditorModal import MatchModeModal from "@/modals/spawning/MatchModeModal" import RobotSwitchPanel from "@/panels/RobotSwitchPanel" import SpawnLocationsPanel from "@/panels/SpawnLocationPanel" -import ScoringZonesPanel from "@/panels/configuring/scoring/ScoringZonesPanel" import ScoreboardPanel from "@/panels/information/ScoreboardPanel" import DriverStationPanel from "@/panels/simulation/DriverStationPanel" import PokerPanel from "@/panels/PokerPanel.tsx" @@ -50,7 +49,6 @@ import Skybox from "./ui/components/Skybox.tsx" import ChooseInputSchemePanel from "./ui/panels/configuring/ChooseInputSchemePanel.tsx" import ProgressNotifications from "./ui/components/ProgressNotification.tsx" import ResetAllInputsModal from "./ui/modals/configuring/ResetAllInputsModal.tsx" -import ZoneConfigPanel from "./ui/panels/configuring/scoring/ZoneConfigPanel.tsx" import SceneOverlay from "./ui/components/SceneOverlay.tsx" import WPILibWSWorker from "@/systems/simulation/wpilib_brain/WPILibWSWorker.ts?worker" @@ -231,8 +229,6 @@ const initialPanels: ReactElement[] = [ , , , - , - , , , , diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 3450c0deab..2b0bb212c8 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -4,7 +4,6 @@ import { // FaMagnifyingGlass, FaPlus, FaGamepad, - FaBasketball, FaFileImport, FaWrench, FaScrewdriverWrench, @@ -112,13 +111,6 @@ const MainHUD: React.FC = () => { />
- } - onClick={() => { - openPanel("scoring-zones") - }} - /> } onClick={() => openModal("config-robot")} /> @@ -122,7 +123,12 @@ const ConfigInterface: React.FC = ({ configMode, assembly case ConfigMode.CONTROLS: return case ConfigMode.SCORING_ZONES: - return + const zones = assembly.fieldPreferences?.scoringZones + if (zones == undefined) { + console.error("Field does not contain scoring zone preferences!") + return + } + return default: throw new Error(`Config mode ${configMode} has no associated interface`) } @@ -159,6 +165,7 @@ const ConfigureAssembliesPanel: React.FC = ({ panelId }) => { onAccept={() => { new ConfigurationSavedEvent() }} + acceptName="Close" >
= ({ panelId }) => { onChange={(_, v) => { v != null && setAssemblyType(v) setSelectedAssembly(undefined) - setSelectedConfigMode(undefined) + if (selectedConfigMode != undefined) { + new ConfigurationSavedEvent() + setSelectedConfigMode(undefined) + } }} sx={{ alignSelf: "center", @@ -179,7 +189,10 @@ const ConfigureAssembliesPanel: React.FC = ({ panelId }) => { { - if (selectedConfigMode != undefined) new ConfigurationSavedEvent() + if (selectedConfigMode != undefined) { + new ConfigurationSavedEvent() + setSelectedConfigMode(undefined) + } setSelectedAssembly(a) }} /> diff --git a/fission/src/ui/panels/configuring/assembly-config/ConfigureGamepiecePickupInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx similarity index 99% rename from fission/src/ui/panels/configuring/assembly-config/ConfigureGamepiecePickupInterface.tsx rename to fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx index 63a7fcbba5..6e30d2d81c 100644 --- a/fission/src/ui/panels/configuring/assembly-config/ConfigureGamepiecePickupInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx @@ -17,7 +17,7 @@ import { import LabeledButton, { LabelPlacement } from "@/ui/components/LabeledButton" import { useTheme } from "@/ui/ThemeContext" import React from "react" -import { ConfigurationSavedEvent } from "./ConfigureAssembliesPanel" +import { ConfigurationSavedEvent } from "../ConfigureAssembliesPanel" // slider constants const MIN_ZONE_SIZE = 0.1 diff --git a/fission/src/ui/panels/configuring/assembly-config/ConfigureShotTrajectoryInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx similarity index 99% rename from fission/src/ui/panels/configuring/assembly-config/ConfigureShotTrajectoryInterface.tsx rename to fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx index 29ff7ad713..99ebb95ac8 100644 --- a/fission/src/ui/panels/configuring/assembly-config/ConfigureShotTrajectoryInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx @@ -16,7 +16,7 @@ import { import { useTheme } from "@/ui/ThemeContext" import LabeledButton, { LabelPlacement } from "@/ui/components/LabeledButton" import { RigidNodeId } from "@/mirabuf/MirabufParser" -import { ConfigurationSavedEvent } from "./ConfigureAssembliesPanel" +import { ConfigurationSavedEvent } from "../ConfigureAssembliesPanel" // slider constants const MIN_VELOCITY = 0.0 diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ConfigureScoringZonesInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ConfigureScoringZonesInterface.tsx new file mode 100644 index 0000000000..ff48d4f917 --- /dev/null +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ConfigureScoringZonesInterface.tsx @@ -0,0 +1,47 @@ +import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" +import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" +import React, { useState } from "react" +import ManageZonesInterface from "./ManageZonesInterface" +import ZoneConfigInterface from "./ZoneConfigInterface" +import PreferencesSystem from "@/systems/preferences/PreferencesSystem" + +const saveZones = (zones: ScoringZonePreferences[] | undefined, field: MirabufSceneObject | undefined) => { + if (!zones || !field) return + + const fieldPrefs = field.fieldPreferences + if (fieldPrefs) fieldPrefs.scoringZones = zones + + PreferencesSystem.savePreferences() + field.UpdateScoringZones() +} + +interface ConfigureZonesProps { + selectedField: MirabufSceneObject + initialZones: ScoringZonePreferences[] +} + +const ConfigureScoringZonesInterface: React.FC = ({ selectedField, initialZones }) => { + const [selectedZone, setSelectedZone] = useState(undefined) + + return ( + <> + {selectedZone == undefined ? ( + + ) : ( + { + saveZones(selectedField.fieldPreferences?.scoringZones, selectedField) + }} + /> + )} + + ) +} + +export default ConfigureScoringZonesInterface diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ManageZonesInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ManageZonesInterface.tsx new file mode 100644 index 0000000000..61fa0743dc --- /dev/null +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/scoring/ManageZonesInterface.tsx @@ -0,0 +1,156 @@ +import { useCallback, useEffect, useState } from "react" +import Button from "@/components/Button" +import Label, { LabelSize } from "@/components/Label" +import ScrollView from "@/components/ScrollView" +import Stack, { StackDirection } from "@/components/Stack" +import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" +import PreferencesSystem from "@/systems/preferences/PreferencesSystem" +import { AiOutlinePlus } from "react-icons/ai" +import { IoPencil, IoTrashBin } from "react-icons/io5" +import World from "@/systems/World" +import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" +import { Box } from "@mui/material" +import { ConfigurationSavedEvent } from "../../ConfigureAssembliesPanel" + +const AddIcon = +const DeleteIcon = +const EditIcon = + +const saveZones = (zones: ScoringZonePreferences[] | undefined, field: MirabufSceneObject | undefined) => { + if (!zones || !field) return + + const fieldPrefs = field.fieldPreferences + if (fieldPrefs) fieldPrefs.scoringZones = zones + + PreferencesSystem.savePreferences() + field.UpdateScoringZones() +} + +type ScoringZoneRowProps = { + zone: ScoringZonePreferences + save: () => void + deleteZone: () => void + selectZone: (zone: ScoringZonePreferences) => void +} + +const ScoringZoneRow: React.FC = ({ zone, save, deleteZone, selectZone }) => { + return ( + + +
+ + + + + + +
- + {/** When checked, points will stay even when a gamepiece leaves the zone */} + + + {/** Switch between transform control modes */} + + { + if (v == undefined) return + + setTransformMode(v) + transformGizmo?.SwitchGizmo(v, 1.5) + }} + sx={{ + alignSelf: "center", + }} + > + Move + Scale + Rotate + +
) } -export default ZoneConfigPanel +export default ZoneConfigInterface diff --git a/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx b/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx deleted file mode 100644 index d8e3a281e4..0000000000 --- a/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx +++ /dev/null @@ -1,206 +0,0 @@ -import { useEffect, useMemo, useState } from "react" -import { usePanelControlContext } from "@/ui/PanelContext" -import Button from "@/components/Button" -import Label, { LabelSize } from "@/components/Label" -import Panel, { PanelPropsImpl } from "@/components/Panel" -import ScrollView from "@/components/ScrollView" -import Stack, { StackDirection } from "@/components/Stack" -import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" -import PreferencesSystem from "@/systems/preferences/PreferencesSystem" -import { AiOutlinePlus } from "react-icons/ai" -import { IoPencil, IoTrashBin } from "react-icons/io5" -import World from "@/systems/World" -import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" -import { MiraType } from "@/mirabuf/MirabufLoader" -import { Box } from "@mui/material" -import { FaBasketball } from "react-icons/fa6" - -const AddIcon = -const DeleteIcon = -const EditIcon = - -type ScoringZoneRowProps = { - zone: ScoringZonePreferences - field: MirabufSceneObject - save: () => void - openPanel: (id: string) => void - deleteZone: () => void -} - -export class SelectedZone { - public static field: MirabufSceneObject | undefined - public static zone: ScoringZonePreferences -} - -const saveZones = (zones: ScoringZonePreferences[] | undefined, field: MirabufSceneObject | undefined) => { - if (!zones || !field) return - - const fieldPrefs = field.fieldPreferences - if (fieldPrefs) fieldPrefs.scoringZones = zones - - PreferencesSystem.savePreferences() - field.UpdateScoringZones() -} - -const ScoringZoneRow: React.FC = ({ zone, save, field, openPanel, deleteZone }) => { - return ( - - -
- - - - - - - - ) - })} -
- - ) : ( - <> - {zones?.length > 0 ? ( - - {zones.map((zonePrefs: ScoringZonePreferences, i: number) => ( - { - return zonePrefs - })()} - field={selectedField} - openPanel={openPanel} - save={() => saveZones(zones, selectedField)} - deleteZone={() => { - setZones(zones.filter((_, idx) => idx !== i)) - saveZones( - zones.filter((_, idx) => idx !== i), - selectedField - ) - }} - /> - ))} - - ) : ( - - )} -
= ({ modalId }) => { return ( = ({ modalId }) => { >
-
openPanel("configure-assemblies")} + onClick={() => openPanel("configure")} /> void } -const OptionCard: React.FC = ({ value, onSelected }) => { +const OptionCard: React.FC = ({ value, index, onSelected }) => { return ( /* Box containing the entire card */ @@ -56,7 +57,7 @@ const OptionCard: React.FC = ({ value, onSelected }) => { {/* Label for joint index and type (grey if child) */} @@ -79,29 +80,27 @@ const OptionCard: React.FC = ({ value, onSelected }) => { interface SelectMenuProps { options: SelectMenuOption[] onOptionSelected: (val: SelectMenuOption | undefined) => void - headerText: string + defaultHeaderText: string indentation?: number } -const SelectMenu: React.FC = ({ options, onOptionSelected, headerText, indentation }) => { +const SelectMenu: React.FC = ({ + options, + onOptionSelected, + defaultHeaderText: headerText, + indentation, +}) => { const [selectedOption, setSelectedOption] = useState(undefined) useEffect(() => { if (selectedOption == undefined) return if (!options.some(o => o.name == selectedOption.name)) setSelectedOption(undefined) - }, [options]) + }, [options, selectedOption]) return ( <> - + {selectedOption != undefined ? ( - ) - })} -
- - ) : ( -
- - Set Parent Behaviors - - - {behaviors.map(behavior => { - const jointIndex = behavior.jointIndex - return ( - { - if (behavior.parentJointIndex != undefined) { - behavior.parentJointIndex = undefined - update() - } else { - setLookingForParent(lookingForParent == behavior ? undefined : behavior) - } - update() - }} - lookingForParent={lookingForParent} - onBehaviorSelected={() => { - if (lookingForParent) lookingForParent.parentJointIndex = behavior.jointIndex - setLookingForParent(undefined) - update() - }} - hasChild={behaviors.some(b => b.parentJointIndex == behavior.jointIndex)} - /> - ) - })} -
- )} - + return () => { + ConfigurationSavedEvent.RemoveListener(saveEvent) + } + }, [saveEvent]) + + + return ( +
+ + Set Parent Behaviors + + + {behaviors.map(behavior => { + const jointIndex = behavior.jointIndex + return ( + { + if (behavior.parentJointIndex != undefined) { + behavior.parentJointIndex = undefined + update() + } else { + setLookingForParent(lookingForParent == behavior ? undefined : behavior) + } + update() + }} + lookingForParent={lookingForParent} + onBehaviorSelected={() => { + if (lookingForParent) lookingForParent.parentJointIndex = behavior.jointIndex + setLookingForParent(undefined) + update() + }} + hasChild={behaviors.some(b => b.parentJointIndex == behavior.jointIndex)} + /> + ) + })} +
) } -export default SequentialBehaviorsPanel +export default SequentialBehaviorsInterface From dcca428e55c4b1a6477acfb8a87b8be5ef31151b Mon Sep 17 00:00:00 2001 From: Dhruv Arora Date: Mon, 5 Aug 2024 20:45:41 -0700 Subject: [PATCH 28/56] Formatting --- fission/src/systems/scene/SceneRenderer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 25effaebdf..c610259076 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -192,7 +192,8 @@ class SceneRenderer extends WorldSystem { this._light.shadow.bias = 0.0 this._light.shadow.normalBias = 0.01 this._scene.add(this._light) - } else if (quality === "High") { // setting light to cascading shadows + } else if (quality === "High") { + // setting light to cascading shadows this._light = new CSM({ parent: this._scene, camera: this._mainCamera, From ff45ebcf5e1c4c7e64d8abe6b535147a9e83a7c7 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 6 Aug 2024 10:05:03 -0700 Subject: [PATCH 29/56] Hopeful fix (Works when OPFS on PC, but need Mac to test on) --- fission/src/mirabuf/MirabufLoader.ts | 146 ++++++++++++++++++++------- 1 file changed, 110 insertions(+), 36 deletions(-) diff --git a/fission/src/mirabuf/MirabufLoader.ts b/fission/src/mirabuf/MirabufLoader.ts index 00c0068733..505d684e1f 100644 --- a/fission/src/mirabuf/MirabufLoader.ts +++ b/fission/src/mirabuf/MirabufLoader.ts @@ -21,14 +21,39 @@ export interface MirabufRemoteInfo { src: string } -type MiraCache = { [id: string]: MirabufCacheInfo } +type MapCache = { [id: string]: MirabufCacheInfo } +type BackUpBufferCache = { [id: string]: ArrayBuffer } +// Local Storage +const robotMapDirName = "RobotMap" +const fieldMapDirName = "FieldMap" +const backUpRobotsDirName = "BackUpRobots" +const backUpFieldsDirName = "BackUpFields" + +// OPFS const robotsDirName = "Robots" const fieldsDirName = "Fields" const root = await navigator.storage.getDirectory() const robotFolderHandle = await root.getDirectoryHandle(robotsDirName, { create: true }) const fieldFolderHandle = await root.getDirectoryHandle(fieldsDirName, { create: true }) +const canOPFS = await (async() => { + try { + console.log(`trying OPFS`) + const fileHandle = await robotFolderHandle.getFileHandle( + "0", + { create: true } + ) + const writable = await fileHandle.createWritable() + await writable.close() + console.log(`yes OPFS`) + return true + } catch (e) { + console.log(`no OPFS`) + return false + } +})() + export function UnzipMira(buff: Uint8Array): Uint8Array { // Check if file is gzipped via magic gzip numbers 31 139 if (buff[0] == 31 && buff[1] == 139) { @@ -42,21 +67,47 @@ class MirabufCachingService { /** * Get the map of mirabuf keys and paired MirabufCacheInfo from local storage * - * @param {MiraType} miraType Type of Mirabuf Assembly. + * @param {MiraType} miraType Type of Mirabuf Assembly * - * @returns {MiraCache} Map of cached keys and paired MirabufCacheInfo + * @returns {MapCache} Map of cached keys and paired MirabufCacheInfo + */ + public static GetCacheMap(miraType: MiraType): MapCache { + if ( + (window.localStorage.getItem(MIRABUF_LOCALSTORAGE_GENERATION_KEY) ?? "") == MIRABUF_LOCALSTORAGE_GENERATION + ) { + window.localStorage.setItem(MIRABUF_LOCALSTORAGE_GENERATION_KEY, MIRABUF_LOCALSTORAGE_GENERATION) + window.localStorage.setItem(robotMapDirName, "{}") + window.localStorage.setItem(fieldMapDirName, "{}") + return {} + } + + const key = miraType == MiraType.ROBOT ? robotMapDirName : fieldMapDirName + const map = window.localStorage.getItem(key) + + if (map) { + return JSON.parse(map) + } else { + window.localStorage.setItem(key, "{}") + return {} + } + } + + /** + * Get back up cache from local storage. Used if no access to OPFS (Safari and iOS) + * @param miraType Type of Mirabuf Assembly + * @returns IDs and buffers */ - public static GetCacheMap(miraType: MiraType): MiraCache { + public static GetBackUpCache(miraType: MiraType): BackUpBufferCache { if ( (window.localStorage.getItem(MIRABUF_LOCALSTORAGE_GENERATION_KEY) ?? "") == MIRABUF_LOCALSTORAGE_GENERATION ) { window.localStorage.setItem(MIRABUF_LOCALSTORAGE_GENERATION_KEY, MIRABUF_LOCALSTORAGE_GENERATION) - window.localStorage.setItem(robotsDirName, "{}") - window.localStorage.setItem(fieldsDirName, "{}") + window.localStorage.setItem(robotMapDirName, "{}") + window.localStorage.setItem(fieldMapDirName, "{}") return {} } - const key = miraType == MiraType.ROBOT ? robotsDirName : fieldsDirName + const key = miraType == MiraType.ROBOT ? backUpRobotsDirName : backUpFieldsDirName const map = window.localStorage.getItem(key) if (map) { @@ -67,6 +118,7 @@ class MirabufCachingService { } } + /** * Cache remote Mirabuf file * @@ -159,19 +211,19 @@ class MirabufCachingService { thumbnailStorageID?: string ): Promise { try { - const map: MiraCache = this.GetCacheMap(miraType) + const map: MapCache = this.GetCacheMap(miraType) const id = map[key].id const _name = map[key].name const _thumbnailStorageID = map[key].thumbnailStorageID - const hi: MirabufCacheInfo = { + const info: MirabufCacheInfo = { id: id, cacheKey: key, miraType: miraType, name: name ?? _name, thumbnailStorageID: thumbnailStorageID ?? _thumbnailStorageID, } - map[key] = hi - window.localStorage.setItem(miraType == MiraType.ROBOT ? robotsDirName : fieldsDirName, JSON.stringify(map)) + map[key] = info + window.localStorage.setItem(miraType == MiraType.ROBOT ? robotMapDirName : fieldMapDirName, JSON.stringify(map)) return true } catch (e) { console.error(`Failed to cache info\n${e}`) @@ -213,16 +265,18 @@ class MirabufCachingService { */ public static async Get(id: MirabufCacheID, miraType: MiraType): Promise { try { - const fileHandle = await (miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle).getFileHandle( + // If we have access to OPFS, get file handle from OPFS + const fileHandle = canOPFS ? await (miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle).getFileHandle( id, { create: false, } - ) + ) : undefined + + // If we have OPFS file, get buffer from OPFS, otherwise get from local storage + const buff = fileHandle ? await fileHandle.getFile().then(x => x.arrayBuffer()) : this.GetBackUpCache(miraType)[id] - // Get assembly from file - if (fileHandle) { - const buff = await fileHandle.getFile().then(x => x.arrayBuffer()) + if (buff) { const assembly = this.AssemblyFromBuffer(buff) World.AnalyticsSystem?.Event("Cache Get", { key: id, @@ -232,11 +286,10 @@ class MirabufCachingService { }) return assembly } else { - console.error(`Failed to get file handle for ID: ${id}`) - return undefined + console.error(`Failed to find file for id: ${id}`) } } catch (e) { - console.error(`Failed to find file from OPFS\n${e}`) + console.error(`Failed to find file\n${e}`) return undefined } } @@ -256,13 +309,24 @@ class MirabufCachingService { if (map) { delete map[key] window.localStorage.setItem( - miraType == MiraType.ROBOT ? robotsDirName : fieldsDirName, + miraType == MiraType.ROBOT ? robotMapDirName : fieldMapDirName, JSON.stringify(map) ) } - const dir = miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle - await dir.removeEntry(id) + if (canOPFS) { + const dir = miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle + await dir.removeEntry(id) + } else { + const backUpCache = this.GetBackUpCache(miraType) + if (backUpCache) { + delete backUpCache[key] + window.localStorage.setItem( + miraType == MiraType.ROBOT ? backUpRobotsDirName : backUpFieldsDirName, + JSON.stringify(backUpCache) + ) + } + } World.AnalyticsSystem?.Event("Cache Remove", { key: key, @@ -287,8 +351,10 @@ class MirabufCachingService { fieldFolderHandle.removeEntry(key) } - window.localStorage.removeItem(robotsDirName) - window.localStorage.removeItem(fieldsDirName) + window.localStorage.removeItem(robotMapDirName) + window.localStorage.removeItem(fieldMapDirName) + window.localStorage.removeItem(backUpRobotsDirName) + window.localStorage.removeItem(backUpFieldsDirName) } // Optional name for when assembly is being decoded anyway like in CacheAndGetLocal() @@ -298,7 +364,6 @@ class MirabufCachingService { miraType?: MiraType, name?: string ): Promise { - // Store in OPFS const backupID = Date.now().toString() try { if (!miraType) { @@ -306,16 +371,8 @@ class MirabufCachingService { miraType = this.AssemblyFromBuffer(miraBuff).dynamic ? MiraType.ROBOT : MiraType.FIELD } - const fileHandle = await (miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle).getFileHandle( - backupID, - { create: true } - ) - const writable = await fileHandle.createWritable() - await writable.write(miraBuff) - await writable.close() - // Local cache map - const map: MiraCache = this.GetCacheMap(miraType) + const map: MapCache = this.GetCacheMap(miraType) const info: MirabufCacheInfo = { id: backupID, cacheKey: key, @@ -323,7 +380,7 @@ class MirabufCachingService { name: name, } map[key] = info - window.localStorage.setItem(miraType == MiraType.ROBOT ? robotsDirName : fieldsDirName, JSON.stringify(map)) + window.localStorage.setItem(miraType == MiraType.ROBOT ? robotMapDirName : fieldMapDirName, JSON.stringify(map)) World.AnalyticsSystem?.Event("Cache Store", { name: name ?? "-", @@ -331,6 +388,23 @@ class MirabufCachingService { type: miraType == MiraType.ROBOT ? "robot" : "field", fileSize: miraBuff.byteLength, }) + + if (canOPFS) { + // Store in OPFS + const fileHandle = await (miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle).getFileHandle( + backupID, + { create: true } + ) + const writable = await fileHandle.createWritable() + await writable.write(miraBuff) + await writable.close() + } else { + // Store in localStorage + const cache: BackUpBufferCache = this.GetBackUpCache(miraType) + cache[key] = miraBuff + window.localStorage.setItem(miraType == MiraType.ROBOT ? backUpRobotsDirName : backUpFieldsDirName, JSON.stringify(cache)) + } + return info } catch (e) { console.error("Failed to cache mira " + e) @@ -353,7 +427,7 @@ class MirabufCachingService { export enum MiraType { ROBOT = 1, - FIELD = 2, + FIELD, } export default MirabufCachingService From fa668d31a5057495218769a8e7535d6423e7a89d Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 6 Aug 2024 10:16:01 -0700 Subject: [PATCH 30/56] More checks --- fission/src/mirabuf/MirabufLoader.ts | 29 ++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/fission/src/mirabuf/MirabufLoader.ts b/fission/src/mirabuf/MirabufLoader.ts index 505d684e1f..4ce17696b4 100644 --- a/fission/src/mirabuf/MirabufLoader.ts +++ b/fission/src/mirabuf/MirabufLoader.ts @@ -40,14 +40,27 @@ const fieldFolderHandle = await root.getDirectoryHandle(fieldsDirName, { create: const canOPFS = await (async() => { try { console.log(`trying OPFS`) - const fileHandle = await robotFolderHandle.getFileHandle( - "0", - { create: true } - ) - const writable = await fileHandle.createWritable() - await writable.close() - console.log(`yes OPFS`) - return true + + if (robotFolderHandle.name == robotsDirName) { + robotFolderHandle.entries + robotFolderHandle.keys + + const fileHandle = await robotFolderHandle.getFileHandle( + "0", + { create: true } + ) + const writable = await fileHandle.createWritable() + await writable.close() + await fileHandle.getFile() + + robotFolderHandle.removeEntry(fileHandle.name) + + console.log(`yes OPFS`) + return true + } else { + console.log(`no OPFS`) + return false + } } catch (e) { console.log(`no OPFS`) return false From dd3597b22c39e6d6807b29ece9a6543b4f426a4d Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Tue, 6 Aug 2024 11:06:08 -0700 Subject: [PATCH 31/56] Completely functional panel --- fission/src/Synthesis.tsx | 2 - fission/src/ui/components/MainHUD.tsx | 5 - fission/src/ui/components/SelectButton.tsx | 2 +- fission/src/ui/components/SelectMenu.tsx | 61 +- .../src/ui/components/StyledComponents.tsx | 4 +- .../configuring/inputs/ChangeInputsModal.tsx | 932 +++++++++--------- .../configuring/ChooseInputSchemePanel.tsx | 2 +- .../assembly-config/ConfigurePanel.tsx | 50 +- .../ConfigureGamepiecePickupInterface.tsx | 10 +- .../SequentialBehaviorsInterface.tsx | 24 +- .../inputs/ConfigureInputsInterface.tsx | 58 +- .../inputs/ConfigureSchemeInterface.tsx | 72 ++ 12 files changed, 655 insertions(+), 567 deletions(-) create mode 100644 fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index e9b1a92efd..42945e5e6a 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -20,7 +20,6 @@ import UpdateAvailableModal from "@/modals/UpdateAvailableModal" import ViewModal from "@/modals/ViewModal" import ConnectToMultiplayerModal from "@/modals/aether/ConnectToMultiplayerModal" import ServerHostingModal from "@/modals/aether/ServerHostingModal" -import ChangeInputsModal from "@/ui/modals/configuring/inputs/ChangeInputsModal.tsx" import ChooseMultiplayerModeModal from "@/modals/configuring/ChooseMultiplayerModeModal" import ChooseSingleplayerModeModal from "@/modals/configuring/ChooseSingleplayerModeModal" import ConfigMotorModal from "@/modals/configuring/ConfigMotorModal" @@ -206,7 +205,6 @@ const initialModals = [ , , , - , , , , diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 2bf38ffa64..17c036db3f 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -100,11 +100,6 @@ const MainHUD: React.FC = () => { icon={SynthesisIcons.MagnifyingGlass} onClick={() => openModal("view")} /> */} - openModal("change-inputs")} - /> = ({ colorClass, size, value, pl return ( - + - ) -} - -const AssemblyCard: React.FC = ({ mira, update }) => { - const { openPanel } = usePanelControlContext() - const { closeModal } = useModalControlContext() - - const brain = useMemo(() => (mira.brain as SynthesisBrain)?.brainIndex, [mira]) - - return ( -
- -
-
-
- ) -} - -const ManageAssembliesModal: React.FC = ({ modalId }) => { - const [_, update] = useReducer(x => !x, false) - - const assemblies = [...World.SceneRenderer.sceneObjects.entries()] - .filter(x => { - const y = x[1] instanceof MirabufSceneObject - return y - }) - .map(x => x[1] as MirabufSceneObject) - - return ( - -
- - {assemblies.map(x => ( - - ))} -
-
- ) -} - -export default ManageAssembliesModal diff --git a/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx b/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx index 0d6e0f8214..e9b1dbc47c 100644 --- a/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx @@ -6,7 +6,6 @@ import Panel, { PanelPropsImpl } from "@/ui/components/Panel" import SelectMenu, { SelectMenuOption } from "@/ui/components/SelectMenu" import { ToggleButton, ToggleButtonGroup } from "@/ui/components/ToggleButtonGroup" import { useMemo, useReducer, useState } from "react" -import { AiOutlinePlus } from "react-icons/ai" import ConfigureGamepiecePickupInterface from "./interfaces/ConfigureGamepiecePickupInterface" import ConfigureShotTrajectoryInterface from "./interfaces/ConfigureShotTrajectoryInterface" import ConfigureScoringZonesInterface from "./interfaces/scoring/ConfigureScoringZonesInterface" @@ -18,9 +17,9 @@ import { usePanelControlContext } from "@/ui/PanelContext" import Button from "@/ui/components/Button" import { setSelectedBrainIndexGlobal } from "../ChooseInputSchemePanel" import ConfigureSchemeInterface from "./interfaces/inputs/ConfigureSchemeInterface" +import { SynthesisIcons } from "@/ui/components/StyledComponents" -const AddIcon = - +/** Option for selecting a robot of field */ class AssemblySelectionOption extends SelectMenuOption { assemblyObject: MirabufSceneObject @@ -36,7 +35,8 @@ interface ConfigurationSelectionProps { } const AssemblySelection: React.FC = ({ configurationType, onAssemblySelected }) => { - const [x, update] = useReducer(x => !x, false) + // Update is used when a robot or field is deleted to update the select menu + const [u, update] = useReducer(x => !x, false) const { openPanel } = usePanelControlContext() const robots = useMemo(() => { @@ -48,7 +48,8 @@ const AssemblySelection: React.FC = ({ configuratio }) as MirabufSceneObject[] return assemblies - }, [x]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [u]) const fields = useMemo(() => { const assemblies = [...World.SceneRenderer.sceneObjects.values()].filter(x => { @@ -59,11 +60,12 @@ const AssemblySelection: React.FC = ({ configuratio }) as MirabufSceneObject[] return assemblies - }, [x]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [u]) + /** Robot or field select menu */ return ( { return new AssemblySelectionOption( `${configurationType == ConfigurationType.ROBOT ? `[${InputSystem.brainIndexSchemeMap.get((assembly.brain as SynthesisBrain).brainIndex)?.schemeName ?? "-"}]` : ""} ${assembly.assemblyName}`, @@ -83,6 +85,7 @@ const AssemblySelection: React.FC = ({ configuratio console.log("Open spawn panel") openPanel("import-mirabuf") }} + noOptionsText={`No ${configurationType == ConfigurationType.ROBOT ? "robots" : "fields"} spawned!`} /> ) } @@ -107,7 +110,7 @@ class ConfigModeSelectionOption extends SelectMenuOption { const robotModes = [ new ConfigModeSelectionOption("Intake", ConfigMode.INTAKE), new ConfigModeSelectionOption("Ejector", ConfigMode.EJECTOR), - new ConfigModeSelectionOption("Motors", ConfigMode.MOTORS), + new ConfigModeSelectionOption("Joints", ConfigMode.MOTORS), new ConfigModeSelectionOption("Controls", ConfigMode.CONTROLS), ] const fieldModes = [new ConfigModeSelectionOption("Scoring Zones", ConfigMode.SCORING_ZONES)] @@ -136,6 +139,7 @@ interface ConfigInterfaceProps { openPanel: (panelId: string) => void } +/** The interface for the actual configuration */ const ConfigInterface: React.FC = ({ configMode, assembly, openPanel }) => { switch (configMode) { case ConfigMode.INTAKE: @@ -144,7 +148,7 @@ const ConfigInterface: React.FC = ({ configMode, assembly, return case ConfigMode.MOTORS: return - case ConfigMode.CONTROLS: + case ConfigMode.CONTROLS: { const brainIndex = (assembly.brain as SynthesisBrain).brainIndex const scheme = InputSystem.brainIndexSchemeMap.get(brainIndex) @@ -160,6 +164,7 @@ const ConfigInterface: React.FC = ({ configMode, assembly, {scheme && } ) + } case ConfigMode.SCORING_ZONES: { const zones = assembly.fieldPreferences?.scoringZones if (zones == undefined) { @@ -173,6 +178,7 @@ const ConfigInterface: React.FC = ({ configMode, assembly, } } +/** An event to save whatever configuration interface is open when it is closed */ export class ConfigurationSavedEvent extends Event { public constructor() { super("ConfigurationSaved") @@ -204,7 +210,7 @@ const ConfigurePanel: React.FC = ({ panelId }) => { return ( = ({ panelId }) => { }} acceptName="Close" > -
+
+ {/** Toggle button group for the robot, field, and input buttons */} = ({ panelId }) => { ) : ( <> + {/** Select menu to pick a robot or field */} { @@ -245,6 +253,7 @@ const ConfigurePanel: React.FC = ({ panelId }) => { setSelectedAssembly(a) }} /> + {/** Nested select menu to pick a configuration mode */} {selectedAssembly != undefined && ( = ({ panelId }) => { }} /> )} + {/** The interface for the selected configuration mode */} {selectedConfigMode != undefined && selectedAssembly != undefined && ( = ({ select {Spacer(10)}
) } @@ -298,6 +365,7 @@ const EditInputInterface: React.FC = ({ input, useGamepad, onInp checkGamepadState() }) + /** Input detection for setting inputs */ useEffect(() => { // // Assign keyboard inputs when a key is pressed if (!useGamepad && selectedInput && chosenKey) { @@ -357,7 +425,7 @@ const EditInputInterface: React.FC = ({ input, useGamepad, onInp }, [chosenKey, chosenButton, chosenGamepadAxis, input, modifierState, onInputChanged, selectedInput, useGamepad]) return ( -
{ if (selectedInput != "") setChosenKey(selectedInput ? e.code : "") setModifierState({ @@ -369,7 +437,7 @@ const EditInputInterface: React.FC = ({ input, useGamepad, onInp }} > {inputConfig()} -
+ ) } diff --git a/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx b/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx index d2be05336f..0c5906fa78 100644 --- a/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx +++ b/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx @@ -335,7 +335,7 @@ const ImportMirabufPanel: React.FC = ({ panelId }) => { return ( Date: Tue, 6 Aug 2024 16:45:50 -0700 Subject: [PATCH 40/56] Fixed scrollbar --- fission/src/index.css | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fission/src/index.css b/fission/src/index.css index afa1fa6dc6..f3c04e2d14 100644 --- a/fission/src/index.css +++ b/fission/src/index.css @@ -2,6 +2,24 @@ @tailwind components; @tailwind utilities; +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: "transparent"; +} + +::-webkit-scrollbar-thumb { + background: #444444; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #555; +} + :root { /* font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; */ font-family: "Artifakt"; From 83ed35c0e4cae031f86ece8be0615fd375921709 Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Wed, 7 Aug 2024 11:24:00 -0700 Subject: [PATCH 41/56] Delete, create, and modify input schemes in a way that is easy and integrated with the config panel --- fission/index.html | 32 +++++---- fission/src/systems/input/InputSystem.ts | 3 - fission/src/ui/components/SelectMenu.tsx | 16 ++++- .../theme-editor/AssignNewSchemeModal.tsx | 12 ++-- .../theme-editor/NewInputSchemeModal.tsx | 12 ++-- .../configuring/ChooseInputSchemePanel.tsx | 15 ++-- .../assembly-config/ConfigurePanel.tsx | 70 ++++++++++++------- .../inputs/ConfigureInputsInterface.tsx | 52 +++++++++++++- .../inputs/ConfigureSchemeInterface.tsx | 2 +- 9 files changed, 152 insertions(+), 62 deletions(-) diff --git a/fission/index.html b/fission/index.html index bf462bd999..5916fa6750 100644 --- a/fission/index.html +++ b/fission/index.html @@ -1,16 +1,22 @@ - - - - - - - - Fission | Synthesis - - -
- - + + + + + + + + Fission | Synthesis + + +
+ + diff --git a/fission/src/systems/input/InputSystem.ts b/fission/src/systems/input/InputSystem.ts index 3a396f8968..d56aadd692 100644 --- a/fission/src/systems/input/InputSystem.ts +++ b/fission/src/systems/input/InputSystem.ts @@ -141,9 +141,6 @@ class InputSystem extends WorldSystem { private static _gpIndex: number | null public static gamepad: Gamepad | null - // The scheme most recently selected in the controls modal - public static selectedScheme: InputScheme | undefined - // Maps a brain index to a certain input scheme public static brainIndexSchemeMap: Map = new Map() diff --git a/fission/src/ui/components/SelectMenu.tsx b/fission/src/ui/components/SelectMenu.tsx index 852bb9852f..c4c93b5fb4 100644 --- a/fission/src/ui/components/SelectMenu.tsx +++ b/fission/src/ui/components/SelectMenu.tsx @@ -54,9 +54,10 @@ interface OptionCardProps { index: number onSelected: (val: SelectMenuOption) => void onDelete?: () => void + includeDelete: boolean } -const OptionCard: React.FC = ({ value, index, onSelected, onDelete }) => { +const OptionCard: React.FC = ({ value, index, onSelected, onDelete, includeDelete }) => { return ( = ({ value, index, onSelected, onDel sx={{ borderColor: "#888888" }} /> {/** Delete button only if onDelete is defined */} - {onDelete && ( + {onDelete && includeDelete && ( <> {Spacer(0, 10)} {DeleteButton(onDelete != undefined ? onDelete : () => {})} @@ -102,23 +103,31 @@ const OptionCard: React.FC = ({ value, index, onSelected, onDel interface SelectMenuProps { options: SelectMenuOption[] onOptionSelected: (val: SelectMenuOption | undefined) => void + + // Function to return a default value + defaultSelectedOption?: (options: SelectMenuOption[]) => SelectMenuOption | undefined defaultHeaderText: string noOptionsText?: string indentation?: number onDelete?: (val: SelectMenuOption) => void | undefined + + // If false, this menu option will not have a delete button + deleteCondition?: (val: SelectMenuOption) => boolean onAddClicked?: () => void } const SelectMenu: React.FC = ({ options, onOptionSelected, + defaultSelectedOption, defaultHeaderText, noOptionsText, indentation, onDelete, + deleteCondition, onAddClicked, }) => { - const [selectedOption, setSelectedOption] = useState(undefined) + const [selectedOption, setSelectedOption] = useState(defaultSelectedOption?.(options)) // If the selected option no longer exists as an option, deselect it useEffect(() => { @@ -170,6 +179,7 @@ const SelectMenu: React.FC = ({ }} key={option.name + i} onDelete={onDelete ? () => onDelete(option) : undefined} + includeDelete={deleteCondition == undefined || deleteCondition(option)} /> ) }) diff --git a/fission/src/ui/modals/configuring/theme-editor/AssignNewSchemeModal.tsx b/fission/src/ui/modals/configuring/theme-editor/AssignNewSchemeModal.tsx index e55c885ff8..1f5c98bd2f 100644 --- a/fission/src/ui/modals/configuring/theme-editor/AssignNewSchemeModal.tsx +++ b/fission/src/ui/modals/configuring/theme-editor/AssignNewSchemeModal.tsx @@ -1,14 +1,16 @@ import React, { useState } from "react" import Input from "@/components/Input" import Modal, { ModalPropsImpl } from "@/components/Modal" -import { useModalControlContext } from "@/ui/ModalContext" import InputSchemeManager from "@/systems/input/InputSchemeManager" import InputSystem from "@/systems/input/InputSystem" import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain" import { SynthesisIcons } from "@/ui/components/StyledComponents" +import { usePanelControlContext } from "@/ui/PanelContext" +import { ConfigurationType, setSelectedConfigurationType } from "@/ui/panels/configuring/assembly-config/ConfigurePanel" +import { setSelectedScheme } from "@/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureInputsInterface" const AssignNewSchemeModal: React.FC = ({ modalId }) => { - const { openModal } = useModalControlContext() + const { openPanel } = usePanelControlContext() const [name, setName] = useState(InputSchemeManager.randomAvailableName) @@ -24,12 +26,12 @@ const AssignNewSchemeModal: React.FC = ({ modalId }) => { scheme.schemeName = name - InputSystem.selectedScheme = scheme InputSchemeManager.addCustomScheme(scheme) - InputSchemeManager.saveSchemes() - openModal("change-inputs") + setSelectedConfigurationType(ConfigurationType.INPUTS) + setSelectedScheme(scheme) + openPanel("configure") }} cancelEnabled={false} > diff --git a/fission/src/ui/modals/configuring/theme-editor/NewInputSchemeModal.tsx b/fission/src/ui/modals/configuring/theme-editor/NewInputSchemeModal.tsx index 403ad9588c..81c59769aa 100644 --- a/fission/src/ui/modals/configuring/theme-editor/NewInputSchemeModal.tsx +++ b/fission/src/ui/modals/configuring/theme-editor/NewInputSchemeModal.tsx @@ -1,14 +1,15 @@ import React, { useState } from "react" import Input from "@/components/Input" import Modal, { ModalPropsImpl } from "@/components/Modal" -import { useModalControlContext } from "@/ui/ModalContext" import InputSchemeManager from "@/systems/input/InputSchemeManager" -import InputSystem from "@/systems/input/InputSystem" import DefaultInputs from "@/systems/input/DefaultInputs" import { SynthesisIcons } from "@/ui/components/StyledComponents" +import { usePanelControlContext } from "@/ui/PanelContext" +import { ConfigurationType, setSelectedConfigurationType } from "@/ui/panels/configuring/assembly-config/ConfigurePanel" +import { setSelectedScheme } from "@/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureInputsInterface" const NewInputSchemeModal: React.FC = ({ modalId }) => { - const { openModal } = useModalControlContext() + const { openPanel } = usePanelControlContext() const [name, setName] = useState(InputSchemeManager.randomAvailableName) @@ -24,8 +25,9 @@ const NewInputSchemeModal: React.FC = ({ modalId }) => { InputSchemeManager.addCustomScheme(scheme) InputSchemeManager.saveSchemes() - InputSystem.selectedScheme = scheme - openModal("change-inputs") + setSelectedConfigurationType(ConfigurationType.INPUTS) + setSelectedScheme(scheme) + openPanel("configure") }} cancelEnabled={false} > diff --git a/fission/src/ui/panels/configuring/ChooseInputSchemePanel.tsx b/fission/src/ui/panels/configuring/ChooseInputSchemePanel.tsx index e1755c2500..2b61340430 100644 --- a/fission/src/ui/panels/configuring/ChooseInputSchemePanel.tsx +++ b/fission/src/ui/panels/configuring/ChooseInputSchemePanel.tsx @@ -18,6 +18,8 @@ import { useModalControlContext } from "@/ui/ModalContext" import { usePanelControlContext } from "@/ui/PanelContext" import { Box } from "@mui/material" import { useEffect, useReducer } from "react" +import { ConfigurationType, setSelectedConfigurationType } from "./assembly-config/ConfigurePanel" +import { setSelectedScheme } from "./assembly-config/interfaces/inputs/ConfigureInputsInterface" let selectedBrainIndexGlobal: number | undefined = undefined // eslint-disable-next-line react-refresh/only-export-components @@ -30,7 +32,7 @@ function getBrainIndex() { } const ChooseInputSchemePanel: React.FC = ({ panelId }) => { - const { closePanel } = usePanelControlContext() + const { closePanel, openPanel } = usePanelControlContext() const { openModal } = useModalControlContext() const [_, update] = useReducer(x => !x, false) @@ -47,9 +49,10 @@ const ChooseInputSchemePanel: React.FC = ({ panelId }) => { const scheme = InputSchemeManager.availableInputSchemes[0] InputSystem.brainIndexSchemeMap.set(brainIndex, scheme) - InputSystem.selectedScheme = scheme - openModal("change-inputs") + setSelectedConfigurationType(ConfigurationType.INPUTS) + setSelectedScheme(scheme) + openPanel("configure") } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -109,8 +112,10 @@ const ChooseInputSchemePanel: React.FC = ({ panelId }) => { {/** Edit button - same as select but opens the inputs modal */} {EditButton(() => { InputSystem.brainIndexSchemeMap.set(getBrainIndex(), scheme) - InputSystem.selectedScheme = scheme - openModal("change-inputs") + + setSelectedConfigurationType(ConfigurationType.INPUTS) + setSelectedScheme(scheme) + openPanel("configure") })} {/** Delete button (only if the scheme is customized) */} diff --git a/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx b/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx index e9b1dbc47c..a2cb525533 100644 --- a/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/ConfigurePanel.tsx @@ -5,7 +5,7 @@ import Label from "@/ui/components/Label" import Panel, { PanelPropsImpl } from "@/ui/components/Panel" import SelectMenu, { SelectMenuOption } from "@/ui/components/SelectMenu" import { ToggleButton, ToggleButtonGroup } from "@/ui/components/ToggleButtonGroup" -import { useMemo, useReducer, useState } from "react" +import { useEffect, useMemo, useReducer, useState } from "react" import ConfigureGamepiecePickupInterface from "./interfaces/ConfigureGamepiecePickupInterface" import ConfigureShotTrajectoryInterface from "./interfaces/ConfigureShotTrajectoryInterface" import ConfigureScoringZonesInterface from "./interfaces/scoring/ConfigureScoringZonesInterface" @@ -19,6 +19,31 @@ import { setSelectedBrainIndexGlobal } from "../ChooseInputSchemePanel" import ConfigureSchemeInterface from "./interfaces/inputs/ConfigureSchemeInterface" import { SynthesisIcons } from "@/ui/components/StyledComponents" +enum ConfigMode { + INTAKE, + EJECTOR, + MOTORS, + CONTROLS, + SCORING_ZONES, +} + +// eslint-disable-next-line react-refresh/only-export-components +export enum ConfigurationType { + ROBOT, + FIELD, + INPUTS, +} + +let selectedConfigurationType: ConfigurationType = ConfigurationType.ROBOT +// eslint-disable-next-line react-refresh/only-export-components +export function setSelectedConfigurationType(type: ConfigurationType) { + selectedConfigurationType = type +} + +function getConfigurationType() { + return selectedConfigurationType +} + /** Option for selecting a robot of field */ class AssemblySelectionOption extends SelectMenuOption { assemblyObject: MirabufSceneObject @@ -90,14 +115,6 @@ const AssemblySelection: React.FC = ({ configuratio ) } -enum ConfigMode { - INTAKE, - EJECTOR, - MOTORS, - CONTROLS, - SCORING_ZONES, -} - class ConfigModeSelectionOption extends SelectMenuOption { configMode: ConfigMode @@ -195,17 +212,16 @@ export class ConfigurationSavedEvent extends Event { } } -enum ConfigurationType { - ROBOT, - FIELD, - INPUTS, -} - const ConfigurePanel: React.FC = ({ panelId }) => { - const { openPanel } = usePanelControlContext() - const [configurationType, setConfigurationType] = useState(ConfigurationType.ROBOT) + const { openPanel, closePanel } = usePanelControlContext() + const [configurationType, setConfigurationType] = useState(getConfigurationType()) const [selectedAssembly, setSelectedAssembly] = useState(undefined) - const [selectedConfigMode, setSelectedConfigMode] = useState(undefined) + const [configMode, setConfigMode] = useState(undefined) + + useEffect(() => { + closePanel("choose-scheme") + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) return ( = ({ panelId }) => { cancelEnabled={false} openLocation="right" onAccept={() => { + // Save the current panel state + setSelectedConfigurationType(configurationType) + new ConfigurationSavedEvent() }} acceptName="Close" @@ -226,9 +245,10 @@ const ConfigurePanel: React.FC = ({ panelId }) => { exclusive onChange={(_, v) => { v != null && setConfigurationType(v) + //console.log(v) setSelectedAssembly(undefined) new ConfigurationSavedEvent() - setSelectedConfigMode(undefined) + setConfigMode(undefined) }} sx={{ alignSelf: "center", @@ -246,10 +266,10 @@ const ConfigurePanel: React.FC = ({ panelId }) => { { - if (selectedConfigMode != undefined) { + if (configMode != undefined) { new ConfigurationSavedEvent() } - setSelectedConfigMode(undefined) + setConfigMode(undefined) setSelectedAssembly(a) }} /> @@ -258,15 +278,15 @@ const ConfigurePanel: React.FC = ({ panelId }) => { { - if (selectedConfigMode != undefined) new ConfigurationSavedEvent() - setSelectedConfigMode(mode) + if (configMode != undefined) new ConfigurationSavedEvent() + setConfigMode(mode) }} /> )} {/** The interface for the selected configuration mode */} - {selectedConfigMode != undefined && selectedAssembly != undefined && ( + {configMode != undefined && selectedAssembly != undefined && ( diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureInputsInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureInputsInterface.tsx index 6d466bc8ef..dd2fdfbeef 100644 --- a/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureInputsInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureInputsInterface.tsx @@ -5,6 +5,18 @@ import InputSystem from "@/systems/input/InputSystem" import InputSchemeManager, { InputScheme } from "@/systems/input/InputSchemeManager" import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain" import ConfigureSchemeInterface from "./ConfigureSchemeInterface" +import PreferencesSystem from "@/systems/preferences/PreferencesSystem" +import { useModalControlContext } from "@/ui/ModalContext" + +let selectedScheme: InputScheme | undefined = undefined +// eslint-disable-next-line react-refresh/only-export-components +export function setSelectedScheme(scheme: InputScheme | undefined) { + selectedScheme = scheme +} + +function getSelectedScheme() { + return selectedScheme +} /** If a scheme is assigned to a robot, find the name of that robot */ const findSchemeRobotName = (scheme: InputScheme): string | undefined => { @@ -29,7 +41,10 @@ class SchemeSelectionOption extends SelectMenuOption { } const ConfigureInputsInterface = () => { - const [selectedScheme, setSelectedScheme] = useState(undefined) + const { openModal } = useModalControlContext() + + const [selectedScheme, setSelectedScheme] = useState(getSelectedScheme()) + const [schemes, setSchemes] = useState(InputSchemeManager.allInputSchemes) const saveEvent = useCallback(() => { InputSchemeManager.saveSchemes() @@ -39,6 +54,7 @@ const ConfigureInputsInterface = () => { ConfigurationSavedEvent.Listen(saveEvent) return () => { + setSelectedScheme(undefined) ConfigurationSavedEvent.RemoveListener(saveEvent) } }, [saveEvent]) @@ -47,7 +63,7 @@ const ConfigureInputsInterface = () => { <> {/** Select menu with input schemes */} new SchemeSelectionOption(s))} + options={schemes.map(s => new SchemeSelectionOption(s))} onOptionSelected={val => { setSelectedScheme((val as SchemeSelectionOption)?.scheme) if (val == undefined) { @@ -55,6 +71,38 @@ const ConfigureInputsInterface = () => { } }} defaultHeaderText={"Select an Input Scheme"} + onDelete={val => { + if (!(val instanceof SchemeSelectionOption)) return + + // Fetch current custom schemes + InputSchemeManager.saveSchemes() + InputSchemeManager.resetDefaultSchemes() + const schemes = PreferencesSystem.getGlobalPreference("InputSchemes") + + // Find and remove this input scheme + const index = schemes.indexOf(val.scheme) + schemes.splice(index, 1) + + // Save to preferences + PreferencesSystem.setGlobalPreference("InputSchemes", schemes) + PreferencesSystem.savePreferences() + + // Update UI with new schemes + setSchemes(InputSchemeManager.allInputSchemes) + }} + deleteCondition={val => { + if (!(val instanceof SchemeSelectionOption)) return false + + return val.scheme.customized + }} + onAddClicked={() => { + openModal("new-scheme") + }} + defaultSelectedOption={options => { + if (options.length < 0 || !(options[0] instanceof SchemeSelectionOption)) return undefined + + return options.find(o => (o as SchemeSelectionOption).scheme == getSelectedScheme()) + }} /> {selectedScheme && } diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx index 06887a84aa..996ef2f574 100644 --- a/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx @@ -11,7 +11,6 @@ interface ConfigSchemeProps { /** Interface to configure a specific input scheme */ const ConfigureSchemeInterface: React.FC = ({ selectedScheme }) => { - //const [selectedInput, setSelectedInput] = useState(undefined) const [useGamepad, setUseGamepad] = useState(selectedScheme.usesGamepad) const saveEvent = useCallback(() => { @@ -44,6 +43,7 @@ const ConfigureSchemeInterface: React.FC = ({ selectedScheme {selectedScheme.inputs.map(i => { return ( { From 44f2860b8466299a3383c13ededef1bd7757b6b4 Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Wed, 7 Aug 2024 15:39:51 -0700 Subject: [PATCH 42/56] Close config panel when you choose to spawn a new robot or field --- fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx b/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx index 0c5906fa78..1b0d050045 100644 --- a/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx +++ b/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx @@ -136,6 +136,11 @@ const ImportMirabufPanel: React.FC = ({ panelId }) => { } }, []) + useEffect(() => { + closePanel("configure") + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + // Get Default Mirabuf Data, Load into manifest. useEffect(() => { // To remove the prettier warning From 2c1047441fcbab3b08fed8d36adf4a7138521f34 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Thu, 8 Aug 2024 13:35:58 -0700 Subject: [PATCH 43/56] Added Hunters jolt submodule --- .gitmodules | 3 +++ README.md | 4 ++++ jolt-physics-barclay | 1 + 3 files changed, 8 insertions(+) create mode 160000 jolt-physics-barclay diff --git a/.gitmodules b/.gitmodules index 44da10b0bf..43708ce766 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "mirabuf"] path = mirabuf url = https://github.com/HiceS/mirabuf.git +[submodule "JoltPhysics.js"] + path = jolt-physics-barclay + url = https://github.com/HunterBarclay/JoltPhysics.js.git diff --git a/README.md b/README.md index 3a6135d588..cd19a6d963 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,10 @@ All code is under a configured formatting utility. See each component for more d Mirabuf is a file format we use to store physical data from Fusion to load into the Synthesis simulator (Fission). This is a separate project that is a submodule of Synthesis. [See Mirabuf](https://github.com/HiceS/mirabuf/) +### Jolt Physics + +Jolt is the core physics engine for our web biased simulator. [See JoltPhysics.js](https://github.com/HunterBarclay/JoltPhysics.js) for more information. + ### Tutorials Our source code for the tutorials featured on our [Tutorials Page](https://synthesis.autodesk.com/tutorials.html). diff --git a/jolt-physics-barclay b/jolt-physics-barclay new file mode 160000 index 0000000000..37d20efc60 --- /dev/null +++ b/jolt-physics-barclay @@ -0,0 +1 @@ +Subproject commit 37d20efc6075d0bfc360a67345ca44a2d5caeb8b From 59f2bda202fb53506577434926a1850266e26c2f Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Thu, 8 Aug 2024 13:41:55 -0700 Subject: [PATCH 44/56] Rename jolt submodule --- .gitmodules | 4 ++-- jolt-physics-barclay => jolt | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename jolt-physics-barclay => jolt (100%) diff --git a/.gitmodules b/.gitmodules index 43708ce766..8f7b277463 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "mirabuf"] path = mirabuf url = https://github.com/HiceS/mirabuf.git -[submodule "JoltPhysics.js"] - path = jolt-physics-barclay +[submodule "jolt"] + path = jolt url = https://github.com/HunterBarclay/JoltPhysics.js.git diff --git a/jolt-physics-barclay b/jolt similarity index 100% rename from jolt-physics-barclay rename to jolt From 1fdb7677547b5ac84978ace5c3ee5e858fb05bbb Mon Sep 17 00:00:00 2001 From: Dhruv Arora Date: Thu, 8 Aug 2024 14:10:04 -0700 Subject: [PATCH 45/56] Increased number of cascades --- fission/src/systems/scene/SceneRenderer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index c610259076..205aa4434d 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -197,7 +197,7 @@ class SceneRenderer extends WorldSystem { this._light = new CSM({ parent: this._scene, camera: this._mainCamera, - cascades: 3, + cascades: 4, lightDirection: new THREE.Vector3(1.0, -3.0, -2.0).normalize(), lightIntensity: 5, shadowMapSize: shadowMapSize, @@ -314,7 +314,7 @@ class SceneRenderer extends WorldSystem { return [(window.innerWidth * (screenSpace.x + 1.0)) / 2.0, (window.innerHeight * (1.0 - screenSpace.y)) / 2.0] } - /** + /** * Updates the skybox colors based on the current theme * @param currentTheme: current theme from ThemeContext.useTheme() From 7e9d8ff5ed48e1ce0863e1998d5b35566ddfc01b Mon Sep 17 00:00:00 2001 From: Dhruv Arora Date: Thu, 8 Aug 2024 14:36:27 -0700 Subject: [PATCH 46/56] Removed commented code --- fission/src/ui/components/MainHUD.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 394101b6f8..a637faf9f0 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -105,11 +105,6 @@ const MainHUD: React.FC = () => { icon={SynthesisIcons.Gamepad} onClick={() => openModal("change-inputs")} /> - {/* openModal("import-local-mirabuf")} - /> */}
Date: Thu, 8 Aug 2024 15:53:46 -0700 Subject: [PATCH 47/56] Version detection for protobuf fix --- exporter/SynthesisFusionAddin/Synthesis.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 06ead88431..5398577fde 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -14,8 +14,15 @@ try: # Attempt to import required pip dependencies to verify their installation. - import google.protobuf import requests + from proto.proto_out import ( + assembly_pb2, + joint_pb2, + material_pb2, + motor_pb2, + signal_pb2, + types_pb2, + ) except (ImportError, ModuleNotFoundError) as error: logger.warn(f"Running resolve dependencies with error of:\n{error}") result = resolveDependencies() From db138f94aca32ee5149b9fcac6b437868de59a40 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:10:07 -0700 Subject: [PATCH 48/56] Added `BaseException` catch for google `VersionError` --- exporter/SynthesisFusionAddin/Synthesis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 5398577fde..deba3c9551 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -23,7 +23,7 @@ signal_pb2, types_pb2, ) -except (ImportError, ModuleNotFoundError) as error: +except (ImportError, ModuleNotFoundError, BaseException) as error: # BaseException required to catch proto.VersionError logger.warn(f"Running resolve dependencies with error of:\n{error}") result = resolveDependencies() if result: From 9c3de89876fd1ead974fe1766c089d5b018267ab Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:48:06 -0700 Subject: [PATCH 49/56] Ensure browser cache key --- .github/workflows/FissionUnitTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/FissionUnitTest.yml b/.github/workflows/FissionUnitTest.yml index 1a0389244b..b3dc4e6be2 100644 --- a/.github/workflows/FissionUnitTest.yml +++ b/.github/workflows/FissionUnitTest.yml @@ -44,7 +44,7 @@ jobs: with: path: | ~/.cache/ms-playwright/ - key: ${{ runner.os }}-assets-playwright-${{ env.PLAYWRIGHT_VERSION }} + key: ${{ runner.os }}-assets-playwright-${{ env.PLAYWRIGHT_VERSION }}-v2 - name: Install Dependencies run: | From 4514f7ec87300e961abdffd896e14185028f5ae7 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:06:46 -0700 Subject: [PATCH 50/56] Import formatting fixes --- .../src/Parser/SynthesisParser/Components.py | 1 + .../src/Parser/SynthesisParser/JointHierarchy.py | 1 + .../SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py | 1 + .../SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py | 1 + .../src/Parser/SynthesisParser/PhysicalProperties.py | 1 + .../src/Parser/SynthesisParser/RigidGroup.py | 1 + 6 files changed, 6 insertions(+) diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py index 6f53db6eb1..aea709f04a 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py @@ -2,6 +2,7 @@ import adsk.core import adsk.fusion from proto.proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 + from src.Logging import logFailure from src.Parser.ExporterOptions import ExporterOptions from src.Parser.SynthesisParser import PhysicalProperties diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py index 811a39cc00..cf8c5e04b0 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py @@ -4,6 +4,7 @@ import adsk.core import adsk.fusion from proto.proto_out import joint_pb2, types_pb2 + from src import gm from src.Logging import getLogger, logFailure from src.Parser.ExporterOptions import ExporterOptions diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py index dbc996c08a..a077c764b7 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py @@ -1,5 +1,6 @@ import adsk from proto.proto_out import material_pb2 + from src.Logging import logFailure from src.Parser.ExporterOptions import ExporterOptions from src.Parser.SynthesisParser.PDMessage import PDMessage diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py index f43add6642..338f5a300a 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py @@ -5,6 +5,7 @@ import adsk.fusion from google.protobuf.json_format import MessageToJson from proto.proto_out import assembly_pb2, types_pb2 + from src import gm from src.APS.APS import getAuth, upload_mirabuf from src.Logging import getLogger, logFailure, timed diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py index f9c5ef7249..b178bcb3bb 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py @@ -20,6 +20,7 @@ import adsk from proto.proto_out import types_pb2 + from src.Logging import logFailure diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py index bdc012dbd1..8516cefae6 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py @@ -17,6 +17,7 @@ import adsk.core import adsk.fusion from proto.proto_out import assembly_pb2 + from src.Logging import logFailure From ff07568b4676c32e52b48eb5f62f18f8e72a3c84 Mon Sep 17 00:00:00 2001 From: LucaHaverty Date: Fri, 9 Aug 2024 10:17:50 -0700 Subject: [PATCH 51/56] merge fixes --- fission/src/systems/input/DefaultInputs.ts | 4 +-- fission/src/ui/components/MainHUD.tsx | 2 -- fission/src/ui/components/SelectMenu.tsx | 4 +-- .../assembly-config/ConfigurePanel.tsx | 6 ++--- .../ConfigureGamepiecePickupInterface.tsx | 2 +- .../ConfigureShotTrajectoryInterface.tsx | 2 +- .../inputs/ConfigureSchemeInterface.tsx | 25 +++++++++++++++++-- 7 files changed, 31 insertions(+), 14 deletions(-) diff --git a/fission/src/systems/input/DefaultInputs.ts b/fission/src/systems/input/DefaultInputs.ts index 2b9ac8d65a..e15fe82d44 100644 --- a/fission/src/systems/input/DefaultInputs.ts +++ b/fission/src/systems/input/DefaultInputs.ts @@ -91,8 +91,8 @@ class DefaultInputs { shift: false, meta: false, }), - new AxisInput("joint 5", "KeyN", "true", -1, false, false, -1, -1, EmptyModifierState, { - ctrl: false, + new AxisInput("joint 5", "KeyN", "KeyN", -1, false, false, -1, -1, EmptyModifierState, { + ctrl: true, alt: false, shift: false, meta: false, diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 34c53855d1..c2c9fea4df 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -100,8 +100,6 @@ const MainHUD: React.FC = () => { icon={SynthesisIcons.Import} onClick={() => openModal("import-local-mirabuf")} /> -
-
= ({ configuratio update() }} onAddClicked={() => { - console.log("Open spawn panel") openPanel("import-mirabuf") }} noOptionsText={`No ${configurationType == ConfigurationType.ROBOT ? "robots" : "fields"} spawned!`} @@ -127,7 +126,7 @@ class ConfigModeSelectionOption extends SelectMenuOption { const robotModes = [ new ConfigModeSelectionOption("Intake", ConfigMode.INTAKE), new ConfigModeSelectionOption("Ejector", ConfigMode.EJECTOR), - new ConfigModeSelectionOption("Joints", ConfigMode.MOTORS), + new ConfigModeSelectionOption("Sequential Joints", ConfigMode.MOTORS), new ConfigModeSelectionOption("Controls", ConfigMode.CONTROLS), ] const fieldModes = [new ConfigModeSelectionOption("Scoring Zones", ConfigMode.SCORING_ZONES)] @@ -225,7 +224,7 @@ const ConfigurePanel: React.FC = ({ panelId }) => { return ( = ({ panelId }) => { exclusive onChange={(_, v) => { v != null && setConfigurationType(v) - //console.log(v) setSelectedAssembly(undefined) new ConfigurationSavedEvent() setConfigMode(undefined) diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx index 62f4ae818d..4981082dfe 100644 --- a/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureGamepiecePickupInterface.tsx @@ -220,7 +220,7 @@ const ConfigureGamepiecePickupInterface: React.FC = ({ select transformGizmo.mesh.position.setFromMatrixPosition(robotTransformation) transformGizmo.mesh.rotation.setFromRotationMatrix(robotTransformation) } - setZoneSize((MIN_ZONE_SIZE + MAX_ZONE_SIZE) / 2.0) + setZoneSize(0.5) setSelectedNode(selectedRobot?.rootNodeId) }} /> diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx index 49e716b93e..f5293e93cf 100644 --- a/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/ConfigureShotTrajectoryInterface.tsx @@ -215,7 +215,7 @@ const ConfigureShotTrajectoryInterface: React.FC = ({ select transformGizmo.mesh.position.setFromMatrixPosition(robotTransformation) transformGizmo.mesh.rotation.setFromRotationMatrix(robotTransformation) } - setEjectorVelocity((MIN_VELOCITY + MAX_VELOCITY) / 2.0) + setEjectorVelocity(1) setSelectedNode(selectedRobot?.rootNodeId) }} /> diff --git a/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx b/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx index 996ef2f574..f2a3721704 100644 --- a/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx +++ b/fission/src/ui/panels/configuring/assembly-config/interfaces/inputs/ConfigureSchemeInterface.tsx @@ -1,7 +1,7 @@ import InputSchemeManager, { InputScheme } from "@/systems/input/InputSchemeManager" import Checkbox from "@/ui/components/Checkbox" import EditInputInterface from "./EditInputInterface" -import { useCallback, useEffect, useState } from "react" +import { useCallback, useEffect, useRef, useState } from "react" import { ConfigurationSavedEvent } from "../../ConfigurePanel" import { SectionDivider } from "@/ui/components/StyledComponents" @@ -12,6 +12,7 @@ interface ConfigSchemeProps { /** Interface to configure a specific input scheme */ const ConfigureSchemeInterface: React.FC = ({ selectedScheme }) => { const [useGamepad, setUseGamepad] = useState(selectedScheme.usesGamepad) + const scrollRef = useRef(null) const saveEvent = useCallback(() => { InputSchemeManager.saveSchemes() @@ -25,6 +26,26 @@ const ConfigureSchemeInterface: React.FC = ({ selectedScheme } }, [saveEvent]) + /** Disable scrolling with arrow keys to stop accidentally scrolling when binding keys */ + useEffect(() => { + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "ArrowUp" || event.key === "ArrowDown") { + event.preventDefault() + } + } + + const scrollElement = scrollRef.current + if (scrollElement) { + scrollElement.addEventListener("keydown", handleKeyDown as unknown as EventListener) + } + + return () => { + if (scrollElement) { + scrollElement.removeEventListener("keydown", handleKeyDown as unknown as EventListener) + } + } + }, []) + return ( <> {/** Toggle the input scheme between controller and keyboard mode */} @@ -39,7 +60,7 @@ const ConfigureSchemeInterface: React.FC = ({ selectedScheme {/* Scroll view for inputs */} -
+
{selectedScheme.inputs.map(i => { return ( Date: Fri, 9 Aug 2024 11:41:55 -0700 Subject: [PATCH 52/56] Forgot to add the button change :( --- fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx b/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx index fdc5a0efcb..aa3f37b2f8 100644 --- a/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx +++ b/fission/src/ui/panels/mirabuf/ImportMirabufPanel.tsx @@ -372,10 +372,6 @@ const ImportMirabufPanel: React.FC = ({ panelId }) => { {cachedRobotElements} - {Spacer(5)} - -
) From fe1a8a71528b28a3973d370ddd45e4904186a476 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:54:32 -0700 Subject: [PATCH 53/56] Remove unused import --- exporter/SynthesisFusionAddin/src/Dependencies.py | 1 - 1 file changed, 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index 367677c9e6..3bb7261501 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -1,5 +1,4 @@ import importlib.machinery -import importlib.util import os import subprocess import sys From 63864f52328c0abee5db19a92acbba114117120f Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:55:29 -0700 Subject: [PATCH 54/56] Remove import path for `proto.proto_out` --- exporter/SynthesisFusionAddin/Synthesis.py | 1 - 1 file changed, 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index bd61e28e39..c5befeddde 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -5,7 +5,6 @@ # Required for absolute imports. sys.path.append(os.path.dirname(os.path.abspath(__file__))) -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "proto", "proto_out"))) from src.Dependencies import resolveDependencies from src.Logging import logFailure, setupLogger From dbaca757dbe6b29f3489f7b3a3328c4a2238a794 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:50:13 -0700 Subject: [PATCH 55/56] Added a "It works on my machine fix" --- exporter/SynthesisFusionAddin/src/Proto/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 exporter/SynthesisFusionAddin/src/Proto/__init__.py diff --git a/exporter/SynthesisFusionAddin/src/Proto/__init__.py b/exporter/SynthesisFusionAddin/src/Proto/__init__.py new file mode 100644 index 0000000000..96a36c3a66 --- /dev/null +++ b/exporter/SynthesisFusionAddin/src/Proto/__init__.py @@ -0,0 +1,4 @@ +import sys +import os + +sys.path.append(os.path.dirname(os.path.abspath(__file__))) From faae7872dd028ffd4bedde42d762c2792737b0d5 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:53:42 -0700 Subject: [PATCH 56/56] Update `README.md` + formatting fix --- exporter/SynthesisFusionAddin/README.md | 17 ++++++++--------- .../SynthesisFusionAddin/src/Proto/__init__.py | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/exporter/SynthesisFusionAddin/README.md b/exporter/SynthesisFusionAddin/README.md index 4fc4933373..1e61d0735c 100644 --- a/exporter/SynthesisFusionAddin/README.md +++ b/exporter/SynthesisFusionAddin/README.md @@ -33,15 +33,14 @@ We use `VSCode` Primarily, download it to interact with our code or use your own ### How to Build + Run -1. See root [`README`](/README.md) on how to run `init` script -2. Open `Autodesk Fusion` -3. Select `UTILITIES` from the top bar -4. Click `ADD-INS` Button -5. Click `Add-Ins` tab at the top of Scripts and Add-Ins dialog -6. Press + Button under **My Add-Ins** -7. Navigate to the containing folder for this Addin and click open at bottom - _clone-directory_/synthesis/exporters/SynthesisFusionAddin -8. Synthesis should be an option - select it and click run at the bottom of the dialog -9. There should now be a button that says Synthesis in your utilities menu +1. Open `Autodesk Fusion` +2. Select `UTILITIES` from the top bar +3. Click `ADD-INS` Button +4. Click `Add-Ins` tab at the top of Scripts and Add-Ins dialog +5. Press + Button under **My Add-Ins** +6. Navigate to the containing folder for this Addin and click open at bottom - _clone-directory_/synthesis/exporters/SynthesisFusionAddin +7. Synthesis should be an option - select it and click run at the bottom of the dialog +8. There should now be a button that says Synthesis in your utilities menu - If there is no button there may be a problem - see below for [checking log file](#debug-non-start) --- diff --git a/exporter/SynthesisFusionAddin/src/Proto/__init__.py b/exporter/SynthesisFusionAddin/src/Proto/__init__.py index 96a36c3a66..087dab646e 100644 --- a/exporter/SynthesisFusionAddin/src/Proto/__init__.py +++ b/exporter/SynthesisFusionAddin/src/Proto/__init__.py @@ -1,4 +1,4 @@ -import sys import os +import sys sys.path.append(os.path.dirname(os.path.abspath(__file__)))