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: |
diff --git a/.gitmodules b/.gitmodules
index 44da10b0bf..8f7b277463 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "mirabuf"]
path = mirabuf
url = https://github.com/HiceS/mirabuf.git
+[submodule "jolt"]
+ path = jolt
+ 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/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py
index 20f3fb35d6..deba3c9551 100644
--- a/exporter/SynthesisFusionAddin/Synthesis.py
+++ b/exporter/SynthesisFusionAddin/Synthesis.py
@@ -3,35 +3,45 @@
import adsk.core
-# Currently required for `resolveDependencies()`, will be required for absolute imports.
+# 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 # isort:skip
+from src.Dependencies import resolveDependencies
+from src.Logging import logFailure, setupLogger
-# Transition: AARD-1741
-# Import order should be removed in AARD-1737 and `setupLogger()` moved to `__init__.py`
-from .src.Logging import getLogger, logFailure, setupLogger # isort:skip
-
-setupLogger()
+logger = setupLogger()
try:
- from .src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm
- from .src.UI import (
- HUI,
- Camera,
- ConfigCommand,
- MarkingMenu,
- ShowAPSAuthCommand,
- ShowWebsiteCommand,
+ # Attempt to import required pip dependencies to verify their installation.
+ import requests
+ from proto.proto_out import (
+ assembly_pb2,
+ joint_pb2,
+ material_pb2,
+ motor_pb2,
+ signal_pb2,
+ types_pb2,
)
- from .src.UI.Toolbar import Toolbar
-except (ImportError, ModuleNotFoundError) as error:
- getLogger().warn(f"Running resolve dependencies with error of:\n{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:
adsk.core.Application.get().userInterface.messageBox("Installed required dependencies.\nPlease restart Fusion.")
+from src import APP_NAME, DESCRIPTION, INTERNAL_ID, gm
+from src.UI import (
+ HUI,
+ Camera,
+ ConfigCommand,
+ MarkingMenu,
+ ShowAPSAuthCommand,
+ ShowWebsiteCommand,
+)
+from src.UI.Toolbar import Toolbar
+
+
@logFailure
def run(_):
"""## Entry point to application from Fusion.
@@ -68,28 +78,8 @@ def stop(_):
# nm.deleteMe()
- logger = getLogger(INTERNAL_ID)
logger.cleanupHandlers()
-
- for file in gm.files:
- try:
- os.remove(file)
- except OSError:
- pass
-
- # removes path so that proto files don't get confused
-
- import sys
-
- path = os.path.abspath(os.path.dirname(__file__))
-
- path_proto_files = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "proto", "proto_out"))
-
- if path in sys.path:
- sys.path.remove(path)
-
- if path_proto_files in sys.path:
- sys.path.remove(path_proto_files)
+ gm.clear()
@logFailure
diff --git a/exporter/SynthesisFusionAddin/src/APS/APS.py b/exporter/SynthesisFusionAddin/src/APS/APS.py
index a65728ec23..a6f4f34a5b 100644
--- a/exporter/SynthesisFusionAddin/src/APS/APS.py
+++ b/exporter/SynthesisFusionAddin/src/APS/APS.py
@@ -10,13 +10,13 @@
import requests
-from ..general_imports import INTERNAL_ID, gm, my_addin_path
-from ..Logging import getLogger
+from src import ADDIN_PATH, gm
+from src.Logging import getLogger
logger = getLogger()
CLIENT_ID = "GCxaewcLjsYlK8ud7Ka9AKf9dPwMR3e4GlybyfhAK2zvl3tU"
-auth_path = os.path.abspath(os.path.join(my_addin_path, "..", ".aps_auth"))
+auth_path = os.path.abspath(os.path.join(ADDIN_PATH, "..", ".aps_auth"))
APS_AUTH = None
APS_USER_INFO = None
diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py
index b9ad31f7be..c6c1b26b4c 100644
--- a/exporter/SynthesisFusionAddin/src/Dependencies.py
+++ b/exporter/SynthesisFusionAddin/src/Dependencies.py
@@ -1,7 +1,6 @@
import importlib.machinery
import importlib.util
import os
-import platform
import subprocess
import sys
from pathlib import Path
@@ -9,10 +8,10 @@
import adsk.core
import adsk.fusion
-from .Logging import getLogger, logFailure
+from src import SYSTEM
+from src.Logging import getLogger, logFailure
logger = getLogger()
-system = platform.system()
# Since the Fusion python runtime is separate from the system python runtime we need to do some funky things
# in order to download and install python packages separate from the standard library.
@@ -29,13 +28,11 @@ def getInternalFusionPythonInstillationFolder() -> str:
pythonStandardLibraryModulePath = importlib.machinery.PathFinder.find_spec("os", sys.path).origin
# Depending on platform, adjust to folder to where the python executable binaries are stored.
- if system == "Windows":
+ if SYSTEM == "Windows":
folder = f"{Path(pythonStandardLibraryModulePath).parents[1]}"
- elif system == "Darwin":
- folder = f"{Path(pythonStandardLibraryModulePath).parents[2]}/bin"
else:
- # TODO: System string should be moved to __init__ after GH-1013
- raise RuntimeError("Unsupported platform.")
+ assert SYSTEM == "Darwin"
+ folder = f"{Path(pythonStandardLibraryModulePath).parents[2]}/bin"
return folder
@@ -100,7 +97,7 @@ def resolveDependencies() -> bool | None:
adsk.doEvents()
pythonFolder = getInternalFusionPythonInstillationFolder()
- pythonExecutableFile = "python.exe" if system == "Windows" else "python" # Confirming 110% everything is fine.
+ pythonExecutableFile = "python.exe" if SYSTEM == "Windows" else "python" # Confirming 110% everything is fine.
pythonExecutablePath = os.path.join(pythonFolder, pythonExecutableFile)
progressBar = ui.createProgressDialog()
@@ -109,7 +106,7 @@ def resolveDependencies() -> bool | None:
progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP) * 2 + 2, 0)
# Install pip manually on macos as it is not included by default? Really?
- if system == "Darwin" and not os.path.exists(os.path.join(pythonFolder, "pip")):
+ if SYSTEM == "Darwin" and not os.path.exists(os.path.join(pythonFolder, "pip")):
pipInstallScriptPath = os.path.join(pythonFolder, "get-pip.py")
if not os.path.exists(pipInstallScriptPath):
executeCommand("curl", "https://bootstrap.pypa.io/get-pip.py", "-o", pipInstallScriptPath)
diff --git a/exporter/SynthesisFusionAddin/src/GlobalManager.py b/exporter/SynthesisFusionAddin/src/GlobalManager.py
index a31688d119..6841a58750 100644
--- a/exporter/SynthesisFusionAddin/src/GlobalManager.py
+++ b/exporter/SynthesisFusionAddin/src/GlobalManager.py
@@ -1,13 +1,8 @@
""" Initializes the global variables that are set in the run method to reduce hanging commands. """
-import logging
-
import adsk.core
import adsk.fusion
-from .general_imports import *
-from .strings import *
-
class GlobalManager(object):
"""Global Manager instance"""
@@ -47,6 +42,11 @@ def __init__(self):
def __str__(self):
return "GlobalManager"
+ def clear(self):
+ for attr, value in self.__dict__.items():
+ if isinstance(value, list):
+ setattr(self, attr, [])
+
instance = None
def __new__(cls):
diff --git a/exporter/SynthesisFusionAddin/src/Logging.py b/exporter/SynthesisFusionAddin/src/Logging.py
index 2bf9ce191b..e5f352f480 100644
--- a/exporter/SynthesisFusionAddin/src/Logging.py
+++ b/exporter/SynthesisFusionAddin/src/Logging.py
@@ -11,8 +11,8 @@
import adsk.core
-from .strings import INTERNAL_ID
-from .UI.OsHelper import getOSPath
+from src import INTERNAL_ID
+from src.UI.OsHelper import getOSPath
MAX_LOG_FILES_TO_KEEP = 10
TIMING_LEVEL = 25
@@ -27,7 +27,7 @@ def cleanupHandlers(self) -> None:
handler.close()
-def setupLogger() -> None:
+def setupLogger() -> SynthesisLogger:
now = datetime.now().strftime("%H-%M-%S")
today = date.today()
logFileFolder = getOSPath(f"{pathlib.Path(__file__).parent.parent}", "logs")
@@ -46,6 +46,7 @@ def setupLogger() -> None:
logger = getLogger(INTERNAL_ID)
logger.setLevel(10) # Debug
logger.addHandler(logHandler)
+ return cast(SynthesisLogger, logger)
def getLogger(name: str | None = None) -> SynthesisLogger:
diff --git a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py
index 9151a7115d..69e9bbef5d 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py
@@ -11,9 +11,9 @@
import adsk.core
from adsk.fusion import CalculationAccuracy, TriangleMeshQualityOptions
-from ..Logging import logFailure, timed
-from ..strings import INTERNAL_ID
-from ..Types import (
+from src import INTERNAL_ID
+from src.Logging import logFailure, timed
+from src.Types import (
KG,
ExportLocation,
ExportMode,
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py
index aa77cac500..aea709f04a 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py
@@ -1,20 +1,18 @@
# Contains all of the logic for mapping the Components / Occurrences
-import logging
-import traceback
-import uuid
-from typing import *
-
import adsk.core
import adsk.fusion
-
from proto.proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2
-from ...Logging import logFailure, timed
-from ...Types import ExportMode
-from ..ExporterOptions import ExporterOptions
-from . import PhysicalProperties
-from .PDMessage import PDMessage
-from .Utilities import *
+from src.Logging import logFailure
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Parser.SynthesisParser import PhysicalProperties
+from src.Parser.SynthesisParser.PDMessage import PDMessage
+from src.Parser.SynthesisParser.Utilities import (
+ fill_info,
+ guid_component,
+ guid_occurrence,
+)
+from src.Types import ExportMode
# TODO: Impelement Material overrides
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py
index 53dd3d10fa..cf8c5e04b0 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py
@@ -1,18 +1,15 @@
import enum
-import logging
-import traceback
-from typing import *
+from typing import Union
import adsk.core
import adsk.fusion
-
from proto.proto_out import joint_pb2, types_pb2
-from ...general_imports import *
-from ...Logging import getLogger, logFailure
-from ..ExporterOptions import ExporterOptions
-from .PDMessage import PDMessage
-from .Utilities import guid_component, guid_occurrence
+from src import gm
+from src.Logging import getLogger, logFailure
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Parser.SynthesisParser.PDMessage import PDMessage
+from src.Parser.SynthesisParser.Utilities import guid_component, guid_occurrence
logger = getLogger()
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py
index c79a0240d0..6b1650b3f9 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py
@@ -28,15 +28,17 @@
import adsk.core
import adsk.fusion
-
-from proto.proto_out import assembly_pb2, joint_pb2, motor_pb2, signal_pb2, types_pb2
-
-from ...general_imports import *
-from ...Logging import getLogger
-from ...Types import JointParentType, SignalType
-from ..ExporterOptions import ExporterOptions
-from .PDMessage import PDMessage
-from .Utilities import construct_info, fill_info, guid_occurrence
+from proto.proto_out import assembly_pb2, joint_pb2, signal_pb2, types_pb2
+
+from src.Logging import getLogger
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Parser.SynthesisParser.PDMessage import PDMessage
+from src.Parser.SynthesisParser.Utilities import (
+ construct_info,
+ fill_info,
+ guid_occurrence,
+)
+from src.Types import JointParentType, SignalType
logger = getLogger()
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py
index 97d8d47f57..a077c764b7 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py
@@ -1,18 +1,10 @@
-# Should contain Physical and Apperance materials ?
-import json
-import logging
-import math
-import traceback
-
import adsk
-
from proto.proto_out import material_pb2
-from ...general_imports import *
-from ...Logging import logFailure, timed
-from ..ExporterOptions import ExporterOptions
-from .PDMessage import PDMessage
-from .Utilities import *
+from src.Logging import logFailure
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Parser.SynthesisParser.PDMessage import PDMessage
+from src.Parser.SynthesisParser.Utilities import construct_info, fill_info
OPACITY_RAMPING_CONSTANT = 14.0
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py
index fe034d20b4..338f5a300a 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py
@@ -4,17 +4,22 @@
import adsk.core
import adsk.fusion
from google.protobuf.json_format import MessageToJson
-
from proto.proto_out import assembly_pb2, types_pb2
-from ...APS.APS import getAuth, upload_mirabuf
-from ...general_imports import *
-from ...Logging import getLogger, logFailure, timed
-from ...Types import ExportLocation, ExportMode
-from ...UI.Camera import captureThumbnail, clearIconCache
-from ..ExporterOptions import ExporterOptions
-from . import Components, JointHierarchy, Joints, Materials, PDMessage
-from .Utilities import *
+from src import gm
+from src.APS.APS import getAuth, upload_mirabuf
+from src.Logging import getLogger, logFailure, timed
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Parser.SynthesisParser import (
+ Components,
+ JointHierarchy,
+ Joints,
+ Materials,
+ PDMessage,
+)
+from src.Parser.SynthesisParser.Utilities import fill_info
+from src.Types import ExportLocation, ExportMode
+from src.UI.Camera import captureThumbnail, clearIconCache
logger = getLogger()
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py
index db488c115a..b178bcb3bb 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py
@@ -16,16 +16,12 @@
"""
-import logging
-import traceback
from typing import Union
import adsk
-
from proto.proto_out import types_pb2
-from ...general_imports import INTERNAL_ID
-from ...Logging import logFailure
+from src.Logging import logFailure
@logFailure
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py
index 362a2a6e72..8516cefae6 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py
@@ -12,14 +12,13 @@
- Success
"""
-from typing import *
+from typing import Union
import adsk.core
import adsk.fusion
-
from proto.proto_out import assembly_pb2
-from ...Logging import logFailure
+from src.Logging import logFailure
@logFailure
diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py
index f508f32117..0a5d277766 100644
--- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py
+++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py
@@ -1,11 +1,9 @@
import math
import uuid
-from adsk.core import Base, Vector3D
+from adsk.core import Vector3D
from adsk.fusion import Component, Occurrence
-# from proto.proto_out import types_pb2
-
def guid_component(comp: Component) -> str:
return f"{comp.entityToken}_{comp.id}"
diff --git a/exporter/SynthesisFusionAddin/src/UI/Camera.py b/exporter/SynthesisFusionAddin/src/UI/Camera.py
index 538968034d..02de04083a 100644
--- a/exporter/SynthesisFusionAddin/src/UI/Camera.py
+++ b/exporter/SynthesisFusionAddin/src/UI/Camera.py
@@ -1,11 +1,9 @@
import os
-from adsk.core import SaveImageFileOptions
+import adsk.core
-from ..general_imports import *
-from ..Logging import logFailure, timed
-from ..Types import OString
-from . import Helper
+from src.Logging import logFailure
+from src.Types import OString
@logFailure
@@ -25,7 +23,7 @@ def captureThumbnail(size=250):
path = OString.ThumbnailPath(name)
- saveOptions = SaveImageFileOptions.create(str(path.getPath()))
+ saveOptions = adsk.core.SaveImageFileOptions.create(str(path.getPath()))
saveOptions.height = size
saveOptions.width = size
saveOptions.isAntiAliased = True
diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py
index d7fd6ec6bb..c50c7feed2 100644
--- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py
+++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py
@@ -9,22 +9,17 @@
import adsk.core
import adsk.fusion
-from ..APS.APS import getAuth, getUserInfo, refreshAuthToken
-from ..general_imports import *
-from ..Logging import getLogger, logFailure
-from ..Parser.ExporterOptions import ExporterOptions
-from ..Parser.SynthesisParser.Parser import Parser
-from ..Parser.SynthesisParser.Utilities import guid_occurrence
-from ..Types import ExportLocation, ExportMode
-from . import CustomGraphics, FileDialogConfig, Helper, IconPaths
-from .Configuration.SerialCommand import SerialCommand
-from .GamepieceConfigTab import GamepieceConfigTab
-from .GeneralConfigTab import GeneralConfigTab
-
-# Transition: AARD-1685
-# In the future all components should be handled in this way.
-# This import broke everything when attempting to use absolute imports??? Investigate?
-from .JointConfigTab import JointConfigTab
+from src import gm
+from src.APS.APS import getAuth, getUserInfo
+from src.Logging import getLogger, logFailure
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Parser.SynthesisParser.Parser import Parser
+from src.Types import ExportLocation, ExportMode
+from src.UI import FileDialogConfig
+from src.UI.Configuration.SerialCommand import SerialCommand
+from src.UI.GamepieceConfigTab import GamepieceConfigTab
+from src.UI.GeneralConfigTab import GeneralConfigTab
+from src.UI.JointConfigTab import JointConfigTab
# ====================================== CONFIG COMMAND ======================================
diff --git a/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py b/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py
index 16084148c5..663afe9337 100644
--- a/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py
+++ b/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py
@@ -7,7 +7,7 @@
import json
-from ...Types import OString
+from src.Types import OString
def generateFilePath() -> str:
diff --git a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py
index 536b93b57d..1f78b469bd 100644
--- a/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py
+++ b/exporter/SynthesisFusionAddin/src/UI/CreateCommandInputsHelper.py
@@ -1,6 +1,6 @@
import adsk.core
-from ..Logging import logFailure
+from src.Logging import logFailure
@logFailure
diff --git a/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py b/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py
index 52a49fa5d4..3b6bd8e2c2 100644
--- a/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py
+++ b/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py
@@ -1,11 +1,8 @@
-import logging
-import traceback
-
import adsk.core
import adsk.fusion
-from ..general_imports import *
-from ..Logging import logFailure
+from src import gm
+from src.Logging import logFailure
@logFailure
diff --git a/exporter/SynthesisFusionAddin/src/UI/Events.py b/exporter/SynthesisFusionAddin/src/UI/Events.py
index 281ebf3f0e..64d0f1ea29 100644
--- a/exporter/SynthesisFusionAddin/src/UI/Events.py
+++ b/exporter/SynthesisFusionAddin/src/UI/Events.py
@@ -1,7 +1,10 @@
-from typing import Sequence, Tuple
+import json
+from typing import Sequence
-from ..general_imports import *
-from ..Logging import getLogger
+import adsk.core
+
+from src import gm
+from src.Logging import getLogger
""" # This file is Special
It links all function names to command requests that palletes can make automatically
diff --git a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py
index 6f6f764cd9..d2465ae29b 100644
--- a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py
+++ b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py
@@ -1,12 +1,8 @@
-from typing import Union
-
import adsk.core
import adsk.fusion
-from ..general_imports import *
-
-# from ..proto_out import Configuration_pb2
-from ..Types import OString
+from src import gm
+from src.Types import OString
def saveFileDialog(defaultPath: str | None = None, defaultName: str | None = None) -> str | bool:
diff --git a/exporter/SynthesisFusionAddin/src/UI/GamepieceConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/GamepieceConfigTab.py
index f0d2f7d4bd..8eb4f80044 100644
--- a/exporter/SynthesisFusionAddin/src/UI/GamepieceConfigTab.py
+++ b/exporter/SynthesisFusionAddin/src/UI/GamepieceConfigTab.py
@@ -1,11 +1,11 @@
import adsk.core
import adsk.fusion
-from ..Logging import logFailure
-from ..Parser.ExporterOptions import ExporterOptions
-from ..Types import Gamepiece, PreferredUnits, toKg, toLbs
-from . import IconPaths
-from .CreateCommandInputsHelper import (
+from src.Logging import logFailure
+from src.Parser.ExporterOptions import ExporterOptions
+from src.Types import Gamepiece, PreferredUnits, toKg, toLbs
+from src.UI import IconPaths
+from src.UI.CreateCommandInputsHelper import (
createBooleanInput,
createTableInput,
createTextBoxInput,
diff --git a/exporter/SynthesisFusionAddin/src/UI/GeneralConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/GeneralConfigTab.py
index 116b8ca7d7..40a602a406 100644
--- a/exporter/SynthesisFusionAddin/src/UI/GeneralConfigTab.py
+++ b/exporter/SynthesisFusionAddin/src/UI/GeneralConfigTab.py
@@ -1,18 +1,18 @@
import adsk.core
import adsk.fusion
-from ..Logging import logFailure
-from ..Parser.ExporterOptions import (
+from src.Logging import logFailure
+from src.Parser.ExporterOptions import (
ExporterOptions,
ExportLocation,
ExportMode,
PreferredUnits,
)
-from ..Types import KG, toKg, toLbs
-from . import IconPaths
-from .CreateCommandInputsHelper import createBooleanInput, createTableInput
-from .GamepieceConfigTab import GamepieceConfigTab
-from .JointConfigTab import JointConfigTab
+from src.Types import KG, toKg, toLbs
+from src.UI import IconPaths
+from src.UI.CreateCommandInputsHelper import createBooleanInput, createTableInput
+from src.UI.GamepieceConfigTab import GamepieceConfigTab
+from src.UI.JointConfigTab import JointConfigTab
class GeneralConfigTab:
diff --git a/exporter/SynthesisFusionAddin/src/UI/HUI.py b/exporter/SynthesisFusionAddin/src/UI/HUI.py
index 3b52de9999..d1a968d642 100644
--- a/exporter/SynthesisFusionAddin/src/UI/HUI.py
+++ b/exporter/SynthesisFusionAddin/src/UI/HUI.py
@@ -1,6 +1,8 @@
-from ..general_imports import *
-from ..Logging import logFailure
-from . import Handlers, OsHelper
+import adsk.core
+
+from src import INTERNAL_ID, gm
+from src.Logging import logFailure
+from src.UI import Handlers, OsHelper
# no longer used
diff --git a/exporter/SynthesisFusionAddin/src/UI/Handlers.py b/exporter/SynthesisFusionAddin/src/UI/Handlers.py
index 710f61e8c8..4529b861db 100644
--- a/exporter/SynthesisFusionAddin/src/UI/Handlers.py
+++ b/exporter/SynthesisFusionAddin/src/UI/Handlers.py
@@ -1,4 +1,4 @@
-from ..general_imports import *
+import adsk.core
class HButtonCommandCreatedEvent(adsk.core.CommandCreatedEventHandler):
diff --git a/exporter/SynthesisFusionAddin/src/UI/Helper.py b/exporter/SynthesisFusionAddin/src/UI/Helper.py
index 7c8e3a5930..ba8bf9b0e9 100644
--- a/exporter/SynthesisFusionAddin/src/UI/Helper.py
+++ b/exporter/SynthesisFusionAddin/src/UI/Helper.py
@@ -1,8 +1,9 @@
from inspect import getmembers, isfunction
-from typing import Union
-from ..general_imports import *
-from . import HUI, Events
+import adsk.core
+
+from src import APP_NAME, APP_TITLE, INTERNAL_ID, gm
+from src.UI import HUI, Events
def getDocName() -> str or None:
diff --git a/exporter/SynthesisFusionAddin/src/UI/IconPaths.py b/exporter/SynthesisFusionAddin/src/UI/IconPaths.py
index 261720494c..2804af221a 100644
--- a/exporter/SynthesisFusionAddin/src/UI/IconPaths.py
+++ b/exporter/SynthesisFusionAddin/src/UI/IconPaths.py
@@ -1,6 +1,6 @@
import os
-from . import OsHelper
+from src.UI import OsHelper
"""
Dictionaries that store all the icon paths in ConfigCommand. All path strings are OS-independent
diff --git a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py
index 7e34757783..b06ae6f2af 100644
--- a/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py
+++ b/exporter/SynthesisFusionAddin/src/UI/JointConfigTab.py
@@ -1,14 +1,10 @@
-import logging
-import traceback
-
import adsk.core
import adsk.fusion
-from ..general_imports import INTERNAL_ID
-from ..Logging import logFailure
-from ..Types import Joint, JointParentType, SignalType, Wheel, WheelType
-from . import IconPaths
-from .CreateCommandInputsHelper import (
+from src.Logging import logFailure
+from src.Types import Joint, JointParentType, SignalType, Wheel, WheelType
+from src.UI import IconPaths
+from src.UI.CreateCommandInputsHelper import (
createBooleanInput,
createTableInput,
createTextBoxInput,
diff --git a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py
index 30c9f078e6..5b90c1b671 100644
--- a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py
+++ b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py
@@ -1,10 +1,7 @@
-import logging.handlers
-import traceback
-
import adsk.core
import adsk.fusion
-from ..Logging import logFailure
+from src.Logging import getLogger, logFailure
# Ripped all the boiler plate from the example code: https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c90ce6a2-c282-11e6-a365-3417ebc87622
@@ -15,6 +12,8 @@
entities = []
occurrencesOfComponents = {}
+logger = getLogger()
+
@logFailure(messageBox=True)
def setupMarkingMenu(ui: adsk.core.UserInterface):
@@ -207,6 +206,7 @@ def stopMarkingMenu(ui: adsk.core.UserInterface):
if obj.isValid:
obj.deleteMe()
else:
- ui.messageBox(str(obj) + " is not a valid object")
+ logger.warn(f"{str(obj)} is not a valid object")
+ cmdDefs.clear()
handlers.clear()
diff --git a/exporter/SynthesisFusionAddin/src/UI/ShowAPSAuthCommand.py b/exporter/SynthesisFusionAddin/src/UI/ShowAPSAuthCommand.py
index bd45cfc062..999abd1176 100644
--- a/exporter/SynthesisFusionAddin/src/UI/ShowAPSAuthCommand.py
+++ b/exporter/SynthesisFusionAddin/src/UI/ShowAPSAuthCommand.py
@@ -1,15 +1,13 @@
import json
-import os
import time
import traceback
import urllib.parse
import urllib.request
-import webbrowser
import adsk.core
+from src import gm
from src.APS.APS import CLIENT_ID, auth_path, convertAuthToken, getCodeChallenge
-from src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm, my_addin_path
from src.Logging import getLogger
logger = getLogger()
diff --git a/exporter/SynthesisFusionAddin/src/UI/ShowWebsiteCommand.py b/exporter/SynthesisFusionAddin/src/UI/ShowWebsiteCommand.py
index d7e1539e5e..cc99cffb07 100644
--- a/exporter/SynthesisFusionAddin/src/UI/ShowWebsiteCommand.py
+++ b/exporter/SynthesisFusionAddin/src/UI/ShowWebsiteCommand.py
@@ -1,8 +1,9 @@
+import traceback
import webbrowser
import adsk.core
-from ..general_imports import *
+from src import gm
class ShowWebsiteCommandExecuteHandler(adsk.core.CommandEventHandler):
diff --git a/exporter/SynthesisFusionAddin/src/UI/Toolbar.py b/exporter/SynthesisFusionAddin/src/UI/Toolbar.py
index bfcc34189a..f9d150cc3c 100644
--- a/exporter/SynthesisFusionAddin/src/UI/Toolbar.py
+++ b/exporter/SynthesisFusionAddin/src/UI/Toolbar.py
@@ -1,6 +1,5 @@
-from ..general_imports import *
-from ..Logging import logFailure
-from ..strings import INTERNAL_ID
+from src import INTERNAL_ID, gm
+from src.Logging import logFailure
class Toolbar:
diff --git a/exporter/SynthesisFusionAddin/src/__init__.py b/exporter/SynthesisFusionAddin/src/__init__.py
new file mode 100644
index 0000000000..1e426279bb
--- /dev/null
+++ b/exporter/SynthesisFusionAddin/src/__init__.py
@@ -0,0 +1,17 @@
+import os
+import platform
+
+from src.GlobalManager import GlobalManager
+
+APP_NAME = "Synthesis"
+APP_TITLE = "Synthesis Robot Exporter"
+DESCRIPTION = "Exports files from Fusion into the Synthesis Format"
+INTERNAL_ID = "Synthesis"
+ADDIN_PATH = os.path.dirname(os.path.realpath(__file__))
+
+SYSTEM = platform.system()
+assert SYSTEM != "Linux"
+
+gm = GlobalManager()
+
+__all__ = ["APP_NAME", "APP_TITLE", "DESCRIPTION", "INTERNAL_ID", "ADDIN_PATH", "SYSTEM", "gm"]
diff --git a/exporter/SynthesisFusionAddin/src/general_imports.py b/exporter/SynthesisFusionAddin/src/general_imports.py
deleted file mode 100644
index aabdae5cac..0000000000
--- a/exporter/SynthesisFusionAddin/src/general_imports.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import json
-import os
-import pathlib
-import sys
-import traceback
-import uuid
-from datetime import datetime
-from time import time
-from types import FunctionType
-
-import adsk.core
-import adsk.fusion
-
-from .GlobalManager import *
-from .Logging import getLogger
-from .strings import *
-
-logger = getLogger()
-
-# hard coded to bypass errors for now
-PROTOBUF = True
-DEBUG = True
-
-try:
- path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
-
- path_proto_files = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "proto", "proto_out"))
-
- if not path in sys.path:
- sys.path.insert(1, path)
-
- if not path_proto_files in sys.path:
- sys.path.insert(2, path_proto_files)
-except:
- logger.error("Failed:\n{}".format(traceback.format_exc()))
-
-try:
- # Setup the global state
- gm: GlobalManager = GlobalManager()
- my_addin_path = os.path.dirname(os.path.realpath(__file__))
-except:
- logger.error("Failed:\n{}".format(traceback.format_exc()))
diff --git a/exporter/SynthesisFusionAddin/src/strings.py b/exporter/SynthesisFusionAddin/src/strings.py
deleted file mode 100644
index b5d79c055c..0000000000
--- a/exporter/SynthesisFusionAddin/src/strings.py
+++ /dev/null
@@ -1,4 +0,0 @@
-APP_NAME = "Synthesis"
-APP_TITLE = "Synthesis Robot Exporter"
-DESCRIPTION = "Exports files from Fusion into the Synthesis Format"
-INTERNAL_ID = "Synthesis"
diff --git a/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py b/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py
index 0f9d899d5a..61772e05cb 100644
--- a/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py
+++ b/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py
@@ -18,9 +18,16 @@ def main() -> None:
exitCode = 0
for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)):
for j, (previousLine, newLine) in enumerate(zip(oldFileState, newFileState)):
- if previousLine != newLine:
- print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}")
- exitCode = 1
+ if previousLine == newLine:
+ continue
+
+ print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}")
+ oldFileStateRange = range(max(0, j - 10), min(len(oldFileState), j + 11))
+ print("\nOld file state:\n" + "\n".join(oldFileState[k].strip() for k in oldFileStateRange))
+ newFileStateRange = range(max(0, j - 10), min(len(newFileState), j + 11))
+ print("\nNew file state:\n" + "\n".join(newFileState[k].strip() for k in newFileStateRange))
+ exitCode = 1
+ break
if not exitCode:
print("All files are formatted correctly with isort!")
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/Synthesis.tsx b/fission/src/Synthesis.tsx
index 5d34da6495..0e2fe2a29b 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"
@@ -37,13 +36,9 @@ 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 ConfigureGamepiecePickupPanel from "@/panels/configuring/ConfigureGamepiecePickupPanel"
-import ConfigureShotTrajectoryPanel from "@/panels/configuring/ConfigureShotTrajectoryPanel"
-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"
-import ManageAssembliesModal from "@/modals/spawning/ManageAssembliesModal.tsx"
import World from "@/systems/World.ts"
import { AddRobotsModal, AddFieldsModal, SpawningModal } from "@/modals/spawning/SpawningModals.tsx"
import ImportLocalMirabufModal from "@/modals/mirabuf/ImportLocalMirabufModal.tsx"
@@ -51,14 +46,13 @@ import ImportMirabufPanel from "@/ui/panels/mirabuf/ImportMirabufPanel.tsx"
import Skybox from "./ui/components/Skybox.tsx"
import ChooseInputSchemePanel from "./ui/panels/configuring/ChooseInputSchemePanel.tsx"
import ProgressNotifications from "./ui/components/ProgressNotification.tsx"
-import ConfigureRobotModal from "./ui/modals/configuring/ConfigureRobotModal.tsx"
-import ResetAllInputsModal from "./ui/modals/configuring/inputs/ResetAllInputsModal.tsx"
-import ZoneConfigPanel from "./ui/panels/configuring/scoring/ZoneConfigPanel.tsx"
+import ConfigureRobotBrainPanel from "./ui/panels/configuring/ConfigureRobotBrainPanel.tsx"
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 RCConfigPWMGroupModal from "@/modals/configuring/rio-config/RCConfigPWMGroupModal.tsx"
import RCConfigCANGroupModal from "@/modals/configuring/rio-config/RCConfigCANGroupModal.tsx"
import DebugPanel from "./ui/panels/DebugPanel.tsx"
@@ -66,7 +60,9 @@ import NewInputSchemeModal from "./ui/modals/configuring/theme-editor/NewInputSc
import AssignNewSchemeModal from "./ui/modals/configuring/theme-editor/AssignNewSchemeModal.tsx"
import AnalyticsConsent from "./ui/components/AnalyticsConsent.tsx"
import PreferencesSystem from "./systems/preferences/PreferencesSystem.ts"
+import ResetAllInputsModal from "./ui/modals/configuring/inputs/ResetAllInputsModal.tsx"
import APSManagementModal from "./ui/modals/APSManagementModal.tsx"
+import ConfigurePanel from "./ui/panels/configuring/assembly-config/ConfigurePanel.tsx"
const worker = new Lazy(() => new WPILibWSWorker())
@@ -209,7 +205,6 @@ const initialModals = [
,
,
,
- ,
,
,
,
@@ -224,9 +219,7 @@ const initialModals = [
,
,
,
- ,
,
- ,
,
,
]
@@ -236,25 +229,18 @@ const initialPanels: ReactElement[] = [
,
,
,
- ,
- ,
+ ,
+ ,
- ,
- ,
- ,
- ,
,
,
,
+ ,
]
export default Synthesis
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";
diff --git a/fission/src/mirabuf/MirabufLoader.ts b/fission/src/mirabuf/MirabufLoader.ts
index 00c0068733..1355d9e38c 100644
--- a/fission/src/mirabuf/MirabufLoader.ts
+++ b/fission/src/mirabuf/MirabufLoader.ts
@@ -21,7 +21,7 @@ export interface MirabufRemoteInfo {
src: string
}
-type MiraCache = { [id: string]: MirabufCacheInfo }
+type MapCache = { [id: MirabufCacheID]: MirabufCacheInfo }
const robotsDirName = "Robots"
const fieldsDirName = "Fields"
@@ -29,6 +29,33 @@ const root = await navigator.storage.getDirectory()
const robotFolderHandle = await root.getDirectoryHandle(robotsDirName, { create: true })
const fieldFolderHandle = await root.getDirectoryHandle(fieldsDirName, { create: true })
+export const backUpRobots: Map = new Map()
+export const backUpFields: Map = new Map()
+
+const canOPFS = await (async () => {
+ try {
+ 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)
+
+ return true
+ } else {
+ console.log(`No access to OPFS`)
+ return false
+ }
+ } catch (e) {
+ console.log(`No access to 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,11 +69,11 @@ 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): MiraCache {
+ public static GetCacheMap(miraType: MiraType): MapCache {
if (
(window.localStorage.getItem(MIRABUF_LOCALSTORAGE_GENERATION_KEY) ?? "") == MIRABUF_LOCALSTORAGE_GENERATION
) {
@@ -159,18 +186,18 @@ 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
+ map[key] = info
window.localStorage.setItem(miraType == MiraType.ROBOT ? robotsDirName : fieldsDirName, JSON.stringify(map))
return true
} catch (e) {
@@ -213,16 +240,21 @@ class MirabufCachingService {
*/
public static async Get(id: MirabufCacheID, miraType: MiraType): Promise {
try {
- const fileHandle = await (miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle).getFileHandle(
- id,
- {
- create: false,
- }
- )
-
- // Get assembly from file
- if (fileHandle) {
- const buff = await fileHandle.getFile().then(x => x.arrayBuffer())
+ // Get buffer from hashMap. If not in hashMap, check OPFS. Otherwise, buff is undefined
+ const cache = miraType == MiraType.ROBOT ? backUpRobots : backUpFields
+ const buff =
+ cache.get(id) ??
+ (await (async () => {
+ const fileHandle = canOPFS
+ ? await (miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle).getFileHandle(id, {
+ create: false,
+ })
+ : undefined
+ return fileHandle ? await fileHandle.getFile().then(x => x.arrayBuffer()) : undefined
+ })())
+
+ // If we have buffer, get assembly
+ if (buff) {
const assembly = this.AssemblyFromBuffer(buff)
World.AnalyticsSystem?.Event("Cache Get", {
key: id,
@@ -232,11 +264,10 @@ class MirabufCachingService {
})
return assembly
} else {
- console.error(`Failed to get file handle for ID: ${id}`)
- return undefined
+ console.error(`Failed to find arrayBuffer 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
}
}
@@ -261,8 +292,15 @@ class MirabufCachingService {
)
}
- const dir = miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle
- await dir.removeEntry(id)
+ if (canOPFS) {
+ const dir = miraType == MiraType.ROBOT ? robotFolderHandle : fieldFolderHandle
+ await dir.removeEntry(id)
+ }
+
+ const backUpCache = miraType == MiraType.ROBOT ? backUpRobots : backUpFields
+ if (backUpCache) {
+ backUpCache.delete(id)
+ }
World.AnalyticsSystem?.Event("Cache Remove", {
key: key,
@@ -289,6 +327,9 @@ class MirabufCachingService {
window.localStorage.removeItem(robotsDirName)
window.localStorage.removeItem(fieldsDirName)
+
+ backUpRobots.clear()
+ backUpFields.clear()
}
// Optional name for when assembly is being decoded anyway like in CacheAndGetLocal()
@@ -298,7 +339,6 @@ class MirabufCachingService {
miraType?: MiraType,
name?: string
): Promise {
- // Store in OPFS
const backupID = Date.now().toString()
try {
if (!miraType) {
@@ -306,16 +346,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,
@@ -331,6 +363,22 @@ class MirabufCachingService {
type: miraType == MiraType.ROBOT ? "robot" : "field",
fileSize: miraBuff.byteLength,
})
+
+ // Store buffer
+ 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()
+ }
+
+ // Store in hash
+ const cache = miraType == MiraType.ROBOT ? backUpRobots : backUpFields
+ cache.set(backupID, miraBuff)
+
return info
} catch (e) {
console.error("Failed to cache mira " + e)
@@ -353,7 +401,7 @@ class MirabufCachingService {
export enum MiraType {
ROBOT = 1,
- FIELD = 2,
+ FIELD,
}
export default MirabufCachingService
diff --git a/fission/src/mirabuf/MirabufParser.ts b/fission/src/mirabuf/MirabufParser.ts
index dd7df1e7cf..7dab72156b 100644
--- a/fission/src/mirabuf/MirabufParser.ts
+++ b/fission/src/mirabuf/MirabufParser.ts
@@ -240,7 +240,6 @@ class MirabufParser {
console.log("Failed to get part definitions")
return
}
- console.log(partDefinitions)
}
private NewRigidNode(suffix?: string): RigidNode {
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/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/systems/preferences/PreferenceTypes.ts b/fission/src/systems/preferences/PreferenceTypes.ts
index 37b04a83ce..9331cc425e 100644
--- a/fission/src/systems/preferences/PreferenceTypes.ts
+++ b/fission/src/systems/preferences/PreferenceTypes.ts
@@ -43,10 +43,29 @@ export type EjectorPreferences = {
parentNode: string | undefined
}
+export type BehaviorType = "Elevator" | "Arm"
+
+export type SequentialBehaviorPreferences = {
+ jointIndex: number
+ parentJointIndex: number | undefined
+ type: BehaviorType
+ inverted: boolean
+}
+
+export function DefaultSequentialConfig(index: number, type: BehaviorType): SequentialBehaviorPreferences {
+ return {
+ jointIndex: index,
+ parentJointIndex: undefined,
+ type: type,
+ inverted: false,
+ }
+}
+
export type RobotPreferences = {
inputsSchemes: InputScheme[]
intake: IntakePreferences
ejector: EjectorPreferences
+ sequentialConfig?: SequentialBehaviorPreferences[]
}
export type Alliance = "red" | "blue"
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/systems/simulation/behavior/synthesis/ArcadeDriveBehavior.ts b/fission/src/systems/simulation/behavior/synthesis/ArcadeDriveBehavior.ts
index 6851ad4305..a76d2f98d3 100644
--- a/fission/src/systems/simulation/behavior/synthesis/ArcadeDriveBehavior.ts
+++ b/fission/src/systems/simulation/behavior/synthesis/ArcadeDriveBehavior.ts
@@ -11,6 +11,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/synthesis/GenericArmBehavior.ts b/fission/src/systems/simulation/behavior/synthesis/GenericArmBehavior.ts
index a9d19c5c03..e177549d54 100644
--- a/fission/src/systems/simulation/behavior/synthesis/GenericArmBehavior.ts
+++ b/fission/src/systems/simulation/behavior/synthesis/GenericArmBehavior.ts
@@ -1,30 +1,31 @@
-import HingeDriver from "@/systems/simulation/driver/HingeDriver"
-import HingeStimulus from "@/systems/simulation/stimulus/HingeStimulus"
-import Behavior from "@/systems/simulation/behavior/Behavior"
-import InputSystem from "@/systems/input/InputSystem"
+import { SequentialBehaviorPreferences } from "@/systems/preferences/PreferenceTypes"
+import HingeDriver from "../../driver/HingeDriver"
+import HingeStimulus from "../../stimulus/HingeStimulus"
+import SequenceableBehavior from "./SequenceableBehavior"
-class GenericArmBehavior extends Behavior {
+class GenericArmBehavior extends SequenceableBehavior {
private _hingeDriver: HingeDriver
- private _inputName: string
- private _brainIndex: number
- private _rotationalSpeed = 6
+ public get hingeDriver(): HingeDriver {
+ return this._hingeDriver
+ }
- constructor(hingeDriver: HingeDriver, hingeStimulus: HingeStimulus, jointIndex: number, brainIndex: number) {
- super([hingeDriver], [hingeStimulus])
+ maxVelocity: number = 6
- this._hingeDriver = hingeDriver
- this._inputName = "joint " + jointIndex
- this._brainIndex = brainIndex
- }
+ constructor(
+ hingeDriver: HingeDriver,
+ hingeStimulus: HingeStimulus,
+ jointIndex: number,
+ brainIndex: number,
+ sequentialConfig: SequentialBehaviorPreferences | undefined
+ ) {
+ super(jointIndex, brainIndex, [hingeDriver], [hingeStimulus], sequentialConfig)
- // Sets the arms target rotational velocity
- rotateArm(rotationalVelocity: number) {
- this._hingeDriver.targetVelocity = rotationalVelocity
+ this._hingeDriver = hingeDriver
}
- public Update(_: number): void {
- this.rotateArm(InputSystem.getInput(this._inputName, this._brainIndex) * this._rotationalSpeed)
+ applyInput = (velocity: number) => {
+ this._hingeDriver.targetVelocity = velocity
}
}
diff --git a/fission/src/systems/simulation/behavior/synthesis/GenericElevatorBehavior.ts b/fission/src/systems/simulation/behavior/synthesis/GenericElevatorBehavior.ts
index fb8b237d16..ceb93f813f 100644
--- a/fission/src/systems/simulation/behavior/synthesis/GenericElevatorBehavior.ts
+++ b/fission/src/systems/simulation/behavior/synthesis/GenericElevatorBehavior.ts
@@ -1,30 +1,31 @@
-import SliderDriver from "@/systems/simulation/driver/SliderDriver"
-import SliderStimulus from "@/systems/simulation/stimulus/SliderStimulus"
-import Behavior from "@/systems/simulation/behavior/Behavior"
-import InputSystem from "@/systems/input/InputSystem"
+import { SequentialBehaviorPreferences } from "@/systems/preferences/PreferenceTypes"
+import SliderDriver from "../../driver/SliderDriver"
+import SliderStimulus from "../../stimulus/SliderStimulus"
+import SequenceableBehavior from "./SequenceableBehavior"
-class GenericElevatorBehavior extends Behavior {
+class GenericElevatorBehavior extends SequenceableBehavior {
private _sliderDriver: SliderDriver
- private _inputName: string
- private _brainIndex: number
- private _linearSpeed = 2.5
+ maxVelocity = 6
- constructor(sliderDriver: SliderDriver, sliderStimulus: SliderStimulus, jointIndex: number, brainIndex: number) {
- super([sliderDriver], [sliderStimulus])
-
- this._sliderDriver = sliderDriver
- this._inputName = "joint " + jointIndex
- this._brainIndex = brainIndex
+ public get sliderDriver(): SliderDriver {
+ return this._sliderDriver
}
- // Changes the elevators target position
- moveElevator(linearVelocity: number) {
- this._sliderDriver.targetVelocity = linearVelocity
+ constructor(
+ sliderDriver: SliderDriver,
+ sliderStimulus: SliderStimulus,
+ jointIndex: number,
+ brainIndex: number,
+ sequentialConfig: SequentialBehaviorPreferences | undefined
+ ) {
+ super(jointIndex, brainIndex, [sliderDriver], [sliderStimulus], sequentialConfig)
+
+ this._sliderDriver = sliderDriver
}
- public Update(_: number): void {
- this.moveElevator(InputSystem.getInput(this._inputName, this._brainIndex) * this._linearSpeed)
+ applyInput = (velocity: number) => {
+ this._sliderDriver.targetVelocity = velocity
}
}
diff --git a/fission/src/systems/simulation/behavior/synthesis/SequenceableBehavior.ts b/fission/src/systems/simulation/behavior/synthesis/SequenceableBehavior.ts
new file mode 100644
index 0000000000..034765097c
--- /dev/null
+++ b/fission/src/systems/simulation/behavior/synthesis/SequenceableBehavior.ts
@@ -0,0 +1,42 @@
+import { SequentialBehaviorPreferences } from "@/systems/preferences/PreferenceTypes"
+import Driver from "../../driver/Driver"
+import Stimulus from "../../stimulus/Stimulus"
+import Behavior from "../Behavior"
+import InputSystem from "@/systems/input/InputSystem"
+
+abstract class SequenceableBehavior extends Behavior {
+ private _jointIndex: number
+ private _brainIndex: number
+ private _sequentialConfig: SequentialBehaviorPreferences | undefined
+
+ abstract maxVelocity: number
+
+ public get jointIndex(): number {
+ return this._jointIndex
+ }
+
+ constructor(
+ jointIndex: number,
+ brainIndex: number,
+ drivers: Driver[],
+ stimuli: Stimulus[],
+ sequentialConfig: SequentialBehaviorPreferences | undefined
+ ) {
+ super(drivers, stimuli)
+
+ this._jointIndex = jointIndex
+ this._brainIndex = brainIndex
+ this._sequentialConfig = sequentialConfig
+ }
+
+ abstract applyInput: (velocity: number) => void
+
+ public Update(_: number): void {
+ const inputName = "joint " + (this._sequentialConfig?.parentJointIndex ?? this._jointIndex)
+ const inverted = this._sequentialConfig?.inverted ?? false
+
+ this.applyInput(InputSystem.getInput(inputName, this._brainIndex) * this.maxVelocity * (inverted ? -1 : 1))
+ }
+}
+
+export default SequenceableBehavior
diff --git a/fission/src/systems/simulation/driver/HingeDriver.ts b/fission/src/systems/simulation/driver/HingeDriver.ts
index 29ab7fc6af..1558f0f4c0 100644
--- a/fission/src/systems/simulation/driver/HingeDriver.ts
+++ b/fission/src/systems/simulation/driver/HingeDriver.ts
@@ -11,6 +11,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 dd442b38aa..9af74046e1 100644
--- a/fission/src/systems/simulation/driver/SliderDriver.ts
+++ b/fission/src/systems/simulation/driver/SliderDriver.ts
@@ -11,6 +11,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 bdbd902102..03db0cdf2c 100644
--- a/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts
+++ b/fission/src/systems/simulation/synthesis_brain/SynthesisBrain.ts
@@ -15,6 +15,7 @@ import SliderDriver from "../driver/SliderDriver"
import SliderStimulus from "../stimulus/SliderStimulus"
import GenericElevatorBehavior from "../behavior/synthesis/GenericElevatorBehavior"
import PreferencesSystem from "@/systems/preferences/PreferencesSystem"
+import { DefaultSequentialConfig } from "@/systems/preferences/PreferenceTypes"
import InputSystem from "@/systems/input/InputSystem"
class SynthesisBrain extends Brain {
@@ -28,6 +29,17 @@ class SynthesisBrain extends Brain {
// Tracks how many joins have been made with unique controls
private _currentJointIndex = 1
+ public get assemblyName(): string {
+ return this._assemblyName
+ }
+
+ public get behaviors(): Behavior[] {
+ return this._behaviors
+ }
+
+ // Tracks the number of each specific mira file spawned
+ public static numberRobotsSpawned: { [key: string]: number } = {}
+
public get inputSchemeName(): string {
const scheme = InputSystem.brainIndexSchemeMap.get(this._brainIndex)
if (scheme == undefined) return "Not Configured"
@@ -132,8 +144,28 @@ class SynthesisBrain extends Brain {
) as HingeStimulus[]
for (let i = 0; i < hingeDrivers.length; i++) {
+ let sequentialConfig = PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig?.find(
+ sc => sc.jointIndex == this._currentJointIndex
+ )
+
+ if (sequentialConfig == undefined) {
+ sequentialConfig = DefaultSequentialConfig(this._currentJointIndex, "Arm")
+
+ if (PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig == undefined)
+ PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig = []
+
+ PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig?.push(sequentialConfig)
+ PreferencesSystem.savePreferences()
+ }
+
this._behaviors.push(
- new GenericArmBehavior(hingeDrivers[i], hingeStimuli[i], this._currentJointIndex, this._brainIndex)
+ new GenericArmBehavior(
+ hingeDrivers[i],
+ hingeStimuli[i],
+ this._currentJointIndex,
+ this._brainIndex,
+ sequentialConfig
+ )
)
this._currentJointIndex++
}
@@ -149,12 +181,27 @@ class SynthesisBrain extends Brain {
) as SliderStimulus[]
for (let i = 0; i < sliderDrivers.length; i++) {
+ let sequentialConfig = PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig?.find(
+ sc => sc.jointIndex == this._currentJointIndex
+ )
+
+ if (sequentialConfig == undefined) {
+ sequentialConfig = DefaultSequentialConfig(this._currentJointIndex, "Elevator")
+
+ if (PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig == undefined)
+ PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig = []
+
+ PreferencesSystem.getRobotPreferences(this._assemblyName).sequentialConfig?.push(sequentialConfig)
+ PreferencesSystem.savePreferences()
+ }
+
this._behaviors.push(
new GenericElevatorBehavior(
sliderDrivers[i],
sliderStimuli[i],
this._currentJointIndex,
- this._brainIndex
+ this._brainIndex,
+ sequentialConfig
)
)
this._currentJointIndex++
diff --git a/fission/src/ui/components/Checkbox.tsx b/fission/src/ui/components/Checkbox.tsx
index 451891073a..6ebdd578f8 100644
--- a/fission/src/ui/components/Checkbox.tsx
+++ b/fission/src/ui/components/Checkbox.tsx
@@ -8,16 +8,19 @@ type CheckboxProps = {
className?: string
defaultState: boolean
stateOverride?: boolean
+ hideLabel?: boolean
onClick?: (checked: boolean) => void
}
-const Checkbox: React.FC = ({ label, className, defaultState, stateOverride, onClick }) => {
+const Checkbox: React.FC = ({ label, className, defaultState, stateOverride, hideLabel, onClick }) => {
const [state] = useState(defaultState)
return (
-
+ {hideLabel ? null : (
+
+ )}
) => onClick && onClick(e.target.checked)}
slotProps={{
diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx
index 47af184cbb..5c1e13a907 100644
--- a/fission/src/ui/components/MainHUD.tsx
+++ b/fission/src/ui/components/MainHUD.tsx
@@ -85,11 +85,6 @@ const MainHUD: React.FC = () => {
onClick={() => openPanel("import-mirabuf")}
/>
- openModal("manage-assemblies")}
- />
{
icon={SynthesisIcons.MagnifyingGlass}
onClick={() => openModal("view")}
/> */}
- openModal("change-inputs")}
- />
-
-
-
{
- openPanel("scoring-zones")
- }}
- />
openModal("config-robot")}
+ onClick={() => openPanel("configure")}
/>
= ({ colorClass, size, value, pl
return (
-
+