From 41c9f69e4be0be184ae67131a9d16ae67cfc97e2 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Thu, 11 Jul 2024 10:36:49 -0700 Subject: [PATCH 01/39] Collision with a sensor Co-authored-by: Hunter Barclay --- fission/bun.lockb | Bin 306880 -> 307786 bytes fission/src/mirabuf/MirabufSceneObject.ts | 2 +- fission/src/systems/World.ts | 8 ++ fission/src/systems/physics/PhysicsSystem.ts | 19 ++++- fission/src/systems/scoring/ScoringSystem.ts | 82 +++++++++++++++++++ 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 fission/src/systems/scoring/ScoringSystem.ts diff --git a/fission/bun.lockb b/fission/bun.lockb index 7e72545e8a6a8de73c28c1d66777e037aece4f4d..553e671e03d5ccdaaca4bb0a0b13c11bbbcb6f52 100755 GIT binary patch delta 49758 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 delta 49346 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 diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 8fa995a5b9..a287509fb8 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -122,7 +122,7 @@ class MirabufSceneObject extends SceneObject { return this._mechanism.nodeToBody.get(this._mechanism.rootBody) } - private CreateMeshForShape(shape: Jolt.Shape): THREE.Mesh { + public CreateMeshForShape(shape: Jolt.Shape): THREE.Mesh { const scale = new JOLT.Vec3(1, 1, 1) const triangleContext = new JOLT.ShapeGetTriangles( shape, diff --git a/fission/src/systems/World.ts b/fission/src/systems/World.ts index 7470618dc8..427358cf79 100644 --- a/fission/src/systems/World.ts +++ b/fission/src/systems/World.ts @@ -4,6 +4,7 @@ import PhysicsSystem from "./physics/PhysicsSystem" import SceneRenderer from "./scene/SceneRenderer" import SimulationSystem from "./simulation/SimulationSystem" import InputSystem from "./input/InputSystem" +import ScoringSystem from "./scoring/ScoringSystem" class World { private static _isAlive: boolean = false @@ -13,6 +14,7 @@ class World { private static _physicsSystem: PhysicsSystem private static _simulationSystem: SimulationSystem private static _inputSystem: InputSystem + private static _scoringSystem: ScoringSystem public static get isAlive() { return World._isAlive @@ -30,6 +32,9 @@ class World { public static get InputSystem() { return World._inputSystem } + public static get ScoringSystem() { + return World._scoringSystem + } public static InitWorld() { if (World._isAlive) return @@ -41,6 +46,7 @@ class World { World._physicsSystem = new PhysicsSystem() World._simulationSystem = new SimulationSystem() World._inputSystem = new InputSystem() + World._scoringSystem = new ScoringSystem() } public static DestroyWorld() { @@ -52,6 +58,7 @@ class World { World._sceneRenderer.Destroy() World._simulationSystem.Destroy() World._inputSystem.Destroy() + World._scoringSystem.Destroy() } public static UpdateWorld() { @@ -60,6 +67,7 @@ class World { World._physicsSystem.Update(deltaT) World._inputSystem.Update(deltaT) World._sceneRenderer.Update(deltaT) + World._scoringSystem.Update(deltaT) } } diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 3ef4a4fcf0..7ad92a49a2 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -13,6 +13,7 @@ import { mirabuf } from "../../proto/mirabuf" import MirabufParser, { GAMEPIECE_SUFFIX, GROUNDED_JOINT_ID, RigidNodeReadOnly } from "../../mirabuf/MirabufParser" import WorldSystem from "../WorldSystem" import Mechanism from "./Mechanism" +import { M } from "node_modules/vite/dist/node/types.d-jgA8ss1A" /** * Layers used for determining enabled/disabled collisions. @@ -50,7 +51,7 @@ const SUSPENSION_MIN_FACTOR = 0.1 const SUSPENSION_MAX_FACTOR = 0.3 /** - * The PhysicsSystem handles all Jolt Phyiscs interactions within Synthesis. + * The PhysicsSystem handles all Jolt Physics interactions within Synthesis. * This system can create physical representations of objects such as Robots, * Fields, and Game pieces, and simulate them. */ @@ -61,6 +62,14 @@ class PhysicsSystem extends WorldSystem { private _bodies: Array private _constraints: Array + public get JoltPhysicsSystem() { + return this._joltPhysSystem + } + + public get JoltBodyInterface() { + return this._joltBodyInterface + } + /** * Creates a PhysicsSystem object. */ @@ -84,7 +93,7 @@ class PhysicsSystem extends WorldSystem { const ground = this.CreateBox( new THREE.Vector3(5.0, 0.5, 5.0), undefined, - new THREE.Vector3(0.0, -2.0, 0.0), + new THREE.Vector3(0.0, -2.05, 0.0), undefined ) ground.SetFriction(FLOOR_FRICTION) @@ -105,7 +114,8 @@ class PhysicsSystem extends WorldSystem { halfExtents: THREE.Vector3, mass: number | undefined, position: THREE.Vector3 | undefined, - rotation: THREE.Euler | THREE.Quaternion | undefined + rotation: THREE.Euler | THREE.Quaternion | undefined, + isSensor: boolean = false ) { const size = ThreeVector3_JoltVec3(halfExtents) const shape = new JOLT.BoxShape(size, 0.1) @@ -123,6 +133,9 @@ class PhysicsSystem extends WorldSystem { if (mass) { creationSettings.mMassPropertiesOverride.mMass = mass } + if (isSensor) { + creationSettings.mIsSensor = isSensor + } const body = this._joltBodyInterface.CreateBody(creationSettings) JOLT.destroy(pos) JOLT.destroy(rot) diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts new file mode 100644 index 0000000000..0c4df81e41 --- /dev/null +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -0,0 +1,82 @@ +import * as THREE from "three"; +import World from "../World"; +import WorldSystem from "../WorldSystem"; +import JOLT from "@/util/loading/JoltSyncLoader"; +import Jolt from "@barclah/jolt-physics"; + +class ScoringSystem extends WorldSystem { + private zone: Jolt.Body; + + private _contactListener: Jolt.ContactListenerJS; + + private points = 0 + + constructor() { + super() + + const geometry = new THREE.BoxGeometry( 1, 1, 1 ); + const material = new THREE.MeshBasicMaterial( { color: 0x0000ff } ); + const cube = new THREE.Mesh( geometry, material ); + World.SceneRenderer.scene.add( cube ); + + const zone = World.PhysicsSystem.CreateBox( + new THREE.Vector3(0.5, 0.5, 0.5), + undefined, + undefined, + undefined, + true + ) + + + this.zone = zone + + World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) + + this._contactListener = new JOLT.ContactListenerJS() + + this._contactListener.OnContactAdded = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { + const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; + const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; + const manifold = JOLT.wrapPointer(manifoldPtr, Jolt.ContactManifold); + const settings = JOLT.wrapPointer(settingsPtr, Jolt.ContactSettings); + console.log(`${body1.GetID().GetIndex()} collided with ${body2.GetID().GetIndex()}`) + + if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { + this.points++ + console.log(this.points) + } + }; + + this._contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { + + } + + this._contactListener.OnContactRemoved = (subShapePairPtr) => { + const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair + const body1ID = shapePair.GetBody1ID() + const body2ID = shapePair.GetBody2ID() + + console.log(`${body1ID.GetIndex()} collided with ${body2ID.GetIndex()}`) + + } + + this._contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { + const body1 = JOLT.wrapPointer(bodyPtr1, Jolt.Body); + const body2 = JOLT.wrapPointer(bodyPtr2, Jolt.Body); + const collideShapeResult = JOLT.wrapPointer(inCollisionResultPtr, Jolt.CollideShapeResult); + return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair + } + + World.PhysicsSystem.JoltPhysicsSystem.SetContactListener(this._contactListener) + } + + public Update(_: number): void { + + } + + public Destroy(): void { + + } +} + +export default ScoringSystem \ No newline at end of file From 847bd0c7dbe4a50a23646d0e0a747b134e9eedf9 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 15 Jul 2024 10:39:36 -0700 Subject: [PATCH 02/39] Testing collision --- fission/src/Synthesis.tsx | 12 ++++++------ fission/src/mirabuf/MirabufParser.ts | 3 +++ fission/src/systems/scoring/ScoringSystem.ts | 6 ++++-- fission/src/ui/components/MainHUD.tsx | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index e35d70a915..b8c5cd6786 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -58,7 +58,7 @@ import APS from "./aps/APS.ts" import Skybox from "./ui/components/Skybox.tsx" import PokerPanel from "@/panels/PokerPanel.tsx" -const DEFAULT_MIRA_PATH = "/api/mira/Robots/Team 2471 (2018)_v7.mira" +const DEFAULT_MIRA_PATH = "/api/mira/Fields/FRC Field 2018_v13.mira" function Synthesis() { const urlParams = new URLSearchParams(document.location.search) @@ -97,12 +97,12 @@ function Synthesis() { } const setup = async () => { - const info = await MirabufCachingService.CacheRemote(mira_path, MiraType.ROBOT) - .catch(_ => MirabufCachingService.CacheRemote(DEFAULT_MIRA_PATH, MiraType.ROBOT)) + const info = await MirabufCachingService.CacheRemote(mira_path, MiraType.FIELD) + .catch(_ => MirabufCachingService.CacheRemote(DEFAULT_MIRA_PATH, MiraType.FIELD)) .catch(console.error) - - const miraAssembly = await MirabufCachingService.Get(info!.id, MiraType.ROBOT) - + const miraAssembly = await MirabufCachingService.Get(info!.id, MiraType.FIELD) + + await (async () => { if (!miraAssembly || !(miraAssembly instanceof mirabuf.Assembly)) { return diff --git a/fission/src/mirabuf/MirabufParser.ts b/fission/src/mirabuf/MirabufParser.ts index a9a814e85a..cc41ad4fe4 100644 --- a/fission/src/mirabuf/MirabufParser.ts +++ b/fission/src/mirabuf/MirabufParser.ts @@ -78,6 +78,8 @@ class MirabufParser { this.GenerateTreeValues() this.LoadGlobalTransforms() + console.log(assembly) + // eslint-disable-next-line @typescript-eslint/no-this-alias const that = this @@ -166,6 +168,7 @@ class MirabufParser { rn = this.MergeRigidNodes(currentRn, rn) } }) + console.log(`rg: ${rg.name}`) }) // this.DebugPrintHierarchy(1, ...this._designHierarchyRoot.children!); diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 0c4df81e41..e0f36716b6 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -39,10 +39,11 @@ class ScoringSystem extends WorldSystem { const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; const manifold = JOLT.wrapPointer(manifoldPtr, Jolt.ContactManifold); const settings = JOLT.wrapPointer(settingsPtr, Jolt.ContactSettings); - console.log(`${body1.GetID().GetIndex()} collided with ${body2.GetID().GetIndex()}`) if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { this.points++ + // GetSceneObject and check if gamepiece + console.log(`${body1.GetID().GetIndex()} collided with ${body2.GetID().GetIndex()}`) console.log(this.points) } }; @@ -56,7 +57,8 @@ class ScoringSystem extends WorldSystem { const body1ID = shapePair.GetBody1ID() const body2ID = shapePair.GetBody2ID() - console.log(`${body1ID.GetIndex()} collided with ${body2ID.GetIndex()}`) + if (body1ID.GetIndex() == zone.GetID().GetIndex()) + console.log(`${body1ID.GetIndex()} removed from ${body2ID.GetIndex()}`) } diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index cd8c07de8e..2827c61129 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -101,7 +101,7 @@ const MainHUD: React.FC = () => { } - onClick={() => openModal("manage-assembles")} + onClick={() => openModal("manage-assemblies")} /> } onClick={() => openModal("settings")} /> } onClick={() => openModal("view")} /> From 3ba9fd4a61ffb5535720d308e0563d50dfe9783f Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 15 Jul 2024 19:36:02 -0700 Subject: [PATCH 03/39] Delete duplicate func --- fission/src/mirabuf/MirabufSceneObject.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index a7d05a7bb8..9a400048f3 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -229,10 +229,6 @@ class MirabufSceneObject extends SceneObject { World.PhysicsSystem.DisablePhysicsForBody(this._mechanism.GetBodyByNodeId(rn.id)!) }) } - - public GetRootNodeId(): Jolt.BodyID | undefined { - return this._mechanism.GetBodyByNodeId(this._mechanism.rootBody) - } } export async function CreateMirabuf(assembly: mirabuf.Assembly): Promise { From 8837fa8e2ed1250dd3609532fadee6ae77c491b7 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 15 Jul 2024 19:39:19 -0700 Subject: [PATCH 04/39] Of course the other one was removed --- fission/src/mirabuf/MirabufSceneObject.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 5bf065d99a..3366381742 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -340,6 +340,10 @@ class MirabufSceneObject extends SceneObject { World.PhysicsSystem.DisablePhysicsForBody(this._mechanism.GetBodyByNodeId(rn.id)!) }) } + + public GetRootNodeId(): Jolt.BodyID | undefined { + return this._mechanism.GetBodyByNodeId(this._mechanism.rootBody) + } } export async function CreateMirabuf(assembly: mirabuf.Assembly): Promise { From 61e624af641d47eeca9e96fd3a4c063e1663d5da Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 15 Jul 2024 20:25:59 -0700 Subject: [PATCH 05/39] Start to ejectable-specific collision --- fission/src/systems/scoring/ScoringSystem.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index e0f36716b6..2d04746e78 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -3,6 +3,7 @@ import World from "../World"; import WorldSystem from "../WorldSystem"; import JOLT from "@/util/loading/JoltSyncLoader"; import Jolt from "@barclah/jolt-physics"; +import EjectableSceneObject from "@/mirabuf/EjectableSceneObject"; class ScoringSystem extends WorldSystem { private zone: Jolt.Body; @@ -40,6 +41,22 @@ class ScoringSystem extends WorldSystem { const manifold = JOLT.wrapPointer(manifoldPtr, Jolt.ContactManifold); const settings = JOLT.wrapPointer(settingsPtr, Jolt.ContactSettings); + const ejectables = [...World.SceneRenderer.sceneObjects.entries()] + .filter(x => { + const y = x[1] instanceof EjectableSceneObject + return y + }) + .map(x => x[1]) + + ejectables.forEach( x => { + console.log(x as EjectableSceneObject) + }) + + // for (const ejectable in ejectables) { + // if (body2.GetID().GetIndex() == (ejectable as EjectableSceneObject).id) + // console.log("Game object detected") + // } + if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { this.points++ // GetSceneObject and check if gamepiece From 7aab74b636416644e7b239004b767d371672dd29 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 16 Jul 2024 11:55:08 -0700 Subject: [PATCH 06/39] Gamepiece-specific collision --- fission/src/mirabuf/MirabufParser.ts | 1 - fission/src/systems/scoring/ScoringSystem.ts | 50 ++++++++++++-------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/fission/src/mirabuf/MirabufParser.ts b/fission/src/mirabuf/MirabufParser.ts index 78bdf343d0..5303d03120 100644 --- a/fission/src/mirabuf/MirabufParser.ts +++ b/fission/src/mirabuf/MirabufParser.ts @@ -171,7 +171,6 @@ class MirabufParser { rn = this.MergeRigidNodes(currentRn, rn) } }) - console.log(`rg: ${rg.name}`) }) // this.DebugPrintHierarchy(1, ...this._designHierarchyRoot.children!); diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 2d04746e78..77a2c170fa 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -3,7 +3,8 @@ import World from "../World"; import WorldSystem from "../WorldSystem"; import JOLT from "@/util/loading/JoltSyncLoader"; import Jolt from "@barclah/jolt-physics"; -import EjectableSceneObject from "@/mirabuf/EjectableSceneObject"; +import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; +import { MiraType } from "@/mirabuf/MirabufLoader"; class ScoringSystem extends WorldSystem { private zone: Jolt.Body; @@ -41,27 +42,36 @@ class ScoringSystem extends WorldSystem { const manifold = JOLT.wrapPointer(manifoldPtr, Jolt.ContactManifold); const settings = JOLT.wrapPointer(settingsPtr, Jolt.ContactSettings); - const ejectables = [...World.SceneRenderer.sceneObjects.entries()] - .filter(x => { - const y = x[1] instanceof EjectableSceneObject - return y - }) - .map(x => x[1]) - - ejectables.forEach( x => { - console.log(x as EjectableSceneObject) - }) - - // for (const ejectable in ejectables) { - // if (body2.GetID().GetIndex() == (ejectable as EjectableSceneObject).id) - // console.log("Game object detected") - // } - if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { - this.points++ - // GetSceneObject and check if gamepiece console.log(`${body1.GetID().GetIndex()} collided with ${body2.GetID().GetIndex()}`) - console.log(this.points) + + const fields = [...World.SceneRenderer.sceneObjects.entries()] + .filter(x => { + if (!(x[1] instanceof MirabufSceneObject)) { + return false + } else { + return x[1].miraType == MiraType.FIELD + } + }) + .map(x => x[1]) as MirabufSceneObject[] + + fields.forEach(x => { + x.mechanism.nodeToBody.forEach( (bodyID, rigidNodeID) => { + const associate = World.PhysicsSystem.GetBodyAssociation(bodyID) + if (associate instanceof RigidNodeAssociate) { + if (associate.isGamePiece) { + const body2ID = body2.GetID().GetIndex() + const gamepieceID = +associate.rigidNodeId.replace("_gp", "") // Gets number without gamepiece tag + + console.log(`${(gamepieceID)} and ${body2ID}`) + if (body2ID == gamepieceID) { + this.points++ + console.log(this.points) + } + } + } + }) + }) } }; From 1c65afc92253f538f27cef9c7aa33bdd67c05b18 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 16 Jul 2024 16:31:46 -0700 Subject: [PATCH 07/39] Events! --- fission/src/systems/physics/ContactEvents.ts | 111 +++++++++++++++++++ fission/src/systems/physics/PhysicsSystem.ts | 71 ++++++++++++ fission/src/systems/scoring/ScoringSystem.ts | 40 ++----- 3 files changed, 189 insertions(+), 33 deletions(-) create mode 100644 fission/src/systems/physics/ContactEvents.ts diff --git a/fission/src/systems/physics/ContactEvents.ts b/fission/src/systems/physics/ContactEvents.ts new file mode 100644 index 0000000000..bc279dcc61 --- /dev/null +++ b/fission/src/systems/physics/ContactEvents.ts @@ -0,0 +1,111 @@ +import Jolt from "@barclah/jolt-physics"; + +export interface CurrentContactData { + body1: Jolt.Body + body2: Jolt.Body + manifold: Jolt.ContactManifold + settings: Jolt.ContactSettings +} + +export interface OnContactValidateData { + body1: Jolt.Body + body2: Jolt.Body + baseOffset: Jolt.RVec3 + collisionResult: Jolt.CollideShapeResult +} + +export class OnContactAddedEvent extends Event { + public static readonly EVENT_KEY = 'OnContactAddedEvent' + + public message: CurrentContactData + + public constructor(data: CurrentContactData) { + super(OnContactAddedEvent.EVENT_KEY) + + this.message = data + } + + public static Dispatch(data: CurrentContactData) { + window.dispatchEvent(new OnContactAddedEvent(data)) + } + + public static AddListener(func: (e: Event) => void) { + window.addEventListener(OnContactAddedEvent.EVENT_KEY, func) + } + + public static RemoveListener(func: (e: Event) => void) { + window.removeEventListener(OnContactAddedEvent.EVENT_KEY, func) + } +} + +export class OnContactPersistedEvent extends Event { + public static readonly EVENT_KEY = 'OnContactPersistedEvent' + + public message: CurrentContactData + + public constructor(data: CurrentContactData) { + super(OnContactPersistedEvent.EVENT_KEY) + + this.message = data + } + + public static Dispatch(data: CurrentContactData) { + window.dispatchEvent(new OnContactPersistedEvent(data)) + } + + public static AddListener(func: (e: Event) => void) { + window.addEventListener(OnContactPersistedEvent.EVENT_KEY, func) + } + + public static RemoveListener(func: (e: Event) => void) { + window.removeEventListener(OnContactPersistedEvent.EVENT_KEY, func) + } +} + +export class OnContactRemovedEvent extends Event { + public static readonly EVENT_KEY = 'OnContactRemovedEvent' + + public message: Jolt.SubShapeIDPair + + public constructor(data: Jolt.SubShapeIDPair) { + super(OnContactRemovedEvent.EVENT_KEY) + + this.message = data + } + + public static Dispatch(data: Jolt.SubShapeIDPair) { + window.dispatchEvent(new OnContactRemovedEvent(data)) + } + + public static AddListener(func: (e: Event) => void) { + window.addEventListener(OnContactRemovedEvent.EVENT_KEY, func) + } + + public static RemoveListener(func: (e: Event) => void) { + window.removeEventListener(OnContactRemovedEvent.EVENT_KEY, func) + } +} + +export class OnContactValidateEvent extends Event { + public static readonly EVENT_KEY = 'OnContactValidateEvent' + + public message: OnContactValidateData + + public constructor(data: OnContactValidateData) { + super(OnContactValidateEvent.EVENT_KEY) + + this.message = data + } + + public static Dispatch(data: OnContactValidateData) { + window.dispatchEvent(new OnContactValidateEvent(data)) + } + + public static AddListener(func: (e: Event) => void) { + window.addEventListener(OnContactValidateEvent.EVENT_KEY, func) + } + + public static RemoveListener(func: (e: Event) => void) { + window.removeEventListener(OnContactValidateEvent.EVENT_KEY, func) + } +} \ No newline at end of file diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 1d46de5ff7..2230cb4bb6 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -15,6 +15,7 @@ import MirabufParser, { GAMEPIECE_SUFFIX, GROUNDED_JOINT_ID, RigidNodeReadOnly } import WorldSystem from "../WorldSystem" import Mechanism from "./Mechanism" import { M } from "node_modules/vite/dist/node/types.d-jgA8ss1A" +import { OnContactAddedEvent, CurrentContactData, OnContactPersistedEvent, OnContactRemovedEvent, OnContactValidateEvent, OnContactValidateData } from "./ContactEvents" export type JoltBodyIndexAndSequence = number @@ -81,6 +82,7 @@ class PhysicsSystem extends WorldSystem { return this._joltBodyInterface } + /** * Creates a PhysicsSystem object. */ @@ -98,6 +100,7 @@ class PhysicsSystem extends WorldSystem { this._joltPhysSystem = this._joltInterface.GetPhysicsSystem() this._joltBodyInterface = this._joltPhysSystem.GetBodyInterface() + SetUpContactListener(this._joltPhysSystem) this._joltPhysSystem.SetGravity(new JOLT.Vec3(0, -9.8, 0)) @@ -1125,6 +1128,74 @@ function tryGetPerpendicular(vec: Jolt.Vec3, toCheck: Jolt.Vec3): Jolt.Vec3 | un ).Normalized() } +/** + * Creates and assigns Jolt contact listener that dispatches events. + * + * @param physSystem + */ +function SetUpContactListener(physSystem: Jolt.PhysicsSystem) { + const contactListener = new JOLT.ContactListenerJS() + + contactListener.OnContactAdded = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { + const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; + const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; + const manifold = JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold; + const settings = JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings; + + const message: CurrentContactData = { + body1: body1, + body2: body2, + manifold: manifold, + settings: settings + } + + OnContactAddedEvent.Dispatch(message) + }; + + contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { + const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; + const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; + const manifold = JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold; + const settings = JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings; + + const message: CurrentContactData = { + body1: body1, + body2: body2, + manifold: manifold, + settings: settings + } + + OnContactPersistedEvent.Dispatch(message) + } + + contactListener.OnContactRemoved = (subShapePairPtr) => { + const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair + + OnContactRemovedEvent.Dispatch(shapePair) + } + + contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { + const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; + const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; + const baseOffset = JOLT.wrapPointer(inBaseOffsetPtr, JOLT.RVec3) as Jolt.RVec3; + const collideShapeResult = JOLT.wrapPointer(inCollisionResultPtr, JOLT.CollideShapeResult) as Jolt.CollideShapeResult; + + const message: OnContactValidateData = { + body1: body1, + body2: body2, + baseOffset: baseOffset, + collisionResult: collideShapeResult + } + + + OnContactValidateEvent.Dispatch(message) + + return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair + } + + physSystem.SetContactListener(contactListener) +} + export type RayCastHit = { data: Jolt.RayCastResult point: Jolt.Vec3 diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 77a2c170fa..25c53a9e49 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -5,12 +5,11 @@ import JOLT from "@/util/loading/JoltSyncLoader"; import Jolt from "@barclah/jolt-physics"; import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; import { MiraType } from "@/mirabuf/MirabufLoader"; +import { OnContactAddedEvent } from "../physics/ContactEvents"; class ScoringSystem extends WorldSystem { private zone: Jolt.Body; - private _contactListener: Jolt.ContactListenerJS; - private points = 0 constructor() { @@ -29,18 +28,14 @@ class ScoringSystem extends WorldSystem { true ) - this.zone = zone - - World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) - this._contactListener = new JOLT.ContactListenerJS() + World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) - this._contactListener.OnContactAdded = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; - const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; - const manifold = JOLT.wrapPointer(manifoldPtr, Jolt.ContactManifold); - const settings = JOLT.wrapPointer(settingsPtr, Jolt.ContactSettings); + const onContactAdded = (e: Event) => { + const event = e as OnContactAddedEvent + const body1 = event.message.body1 + const body2 = event.message.body2 if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { console.log(`${body1.GetID().GetIndex()} collided with ${body2.GetID().GetIndex()}`) @@ -63,7 +58,6 @@ class ScoringSystem extends WorldSystem { const body2ID = body2.GetID().GetIndex() const gamepieceID = +associate.rigidNodeId.replace("_gp", "") // Gets number without gamepiece tag - console.log(`${(gamepieceID)} and ${body2ID}`) if (body2ID == gamepieceID) { this.points++ console.log(this.points) @@ -73,30 +67,10 @@ class ScoringSystem extends WorldSystem { }) }) } - }; - - this._contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - - } - - this._contactListener.OnContactRemoved = (subShapePairPtr) => { - const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair - const body1ID = shapePair.GetBody1ID() - const body2ID = shapePair.GetBody2ID() - - if (body1ID.GetIndex() == zone.GetID().GetIndex()) - console.log(`${body1ID.GetIndex()} removed from ${body2ID.GetIndex()}`) - - } - this._contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { - const body1 = JOLT.wrapPointer(bodyPtr1, Jolt.Body); - const body2 = JOLT.wrapPointer(bodyPtr2, Jolt.Body); - const collideShapeResult = JOLT.wrapPointer(inCollisionResultPtr, Jolt.CollideShapeResult); - return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair } - World.PhysicsSystem.JoltPhysicsSystem.SetContactListener(this._contactListener) + OnContactAddedEvent.AddListener(onContactAdded) } public Update(_: number): void { From 6fb8214007a53e9b11097c2c34e378912a3798e0 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 16 Jul 2024 17:09:21 -0700 Subject: [PATCH 08/39] Event refactor --- fission/src/systems/physics/ContactEvents.ts | 18 ++----- fission/src/systems/physics/PhysicsSystem.ts | 49 +++++++------------- fission/src/systems/scoring/ScoringSystem.ts | 2 + 3 files changed, 24 insertions(+), 45 deletions(-) diff --git a/fission/src/systems/physics/ContactEvents.ts b/fission/src/systems/physics/ContactEvents.ts index bc279dcc61..3ddcc0fad1 100644 --- a/fission/src/systems/physics/ContactEvents.ts +++ b/fission/src/systems/physics/ContactEvents.ts @@ -23,10 +23,8 @@ export class OnContactAddedEvent extends Event { super(OnContactAddedEvent.EVENT_KEY) this.message = data - } - - public static Dispatch(data: CurrentContactData) { - window.dispatchEvent(new OnContactAddedEvent(data)) + + window.dispatchEvent(this) } public static AddListener(func: (e: Event) => void) { @@ -47,10 +45,8 @@ export class OnContactPersistedEvent extends Event { super(OnContactPersistedEvent.EVENT_KEY) this.message = data - } - public static Dispatch(data: CurrentContactData) { - window.dispatchEvent(new OnContactPersistedEvent(data)) + window.dispatchEvent(this) } public static AddListener(func: (e: Event) => void) { @@ -71,10 +67,8 @@ export class OnContactRemovedEvent extends Event { super(OnContactRemovedEvent.EVENT_KEY) this.message = data - } - public static Dispatch(data: Jolt.SubShapeIDPair) { - window.dispatchEvent(new OnContactRemovedEvent(data)) + window.dispatchEvent(this) } public static AddListener(func: (e: Event) => void) { @@ -95,10 +89,8 @@ export class OnContactValidateEvent extends Event { super(OnContactValidateEvent.EVENT_KEY) this.message = data - } - public static Dispatch(data: OnContactValidateData) { - window.dispatchEvent(new OnContactValidateEvent(data)) + window.dispatchEvent(this) } public static AddListener(func: (e: Event) => void) { diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 2230cb4bb6..12ebac0362 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -943,6 +943,7 @@ class PhysicsSystem extends WorldSystem { JOLT.destroy(this._joltBodyInterface) JOLT.destroy(this._joltInterface) + JOLT.destroy(this._joltPhysSystem.GetContactListener()) } /** @@ -1137,58 +1138,42 @@ function SetUpContactListener(physSystem: Jolt.PhysicsSystem) { const contactListener = new JOLT.ContactListenerJS() contactListener.OnContactAdded = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; - const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; - const manifold = JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold; - const settings = JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings; - const message: CurrentContactData = { - body1: body1, - body2: body2, - manifold: manifold, - settings: settings + body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, + body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, + manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, + settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings } - OnContactAddedEvent.Dispatch(message) + new OnContactAddedEvent(message) }; contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; - const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; - const manifold = JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold; - const settings = JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings; - const message: CurrentContactData = { - body1: body1, - body2: body2, - manifold: manifold, - settings: settings + body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, + body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, + manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, + settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings } - OnContactPersistedEvent.Dispatch(message) + new OnContactPersistedEvent(message) } contactListener.OnContactRemoved = (subShapePairPtr) => { const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair - OnContactRemovedEvent.Dispatch(shapePair) + new OnContactRemovedEvent(shapePair) } contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { - const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body; - const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body; - const baseOffset = JOLT.wrapPointer(inBaseOffsetPtr, JOLT.RVec3) as Jolt.RVec3; - const collideShapeResult = JOLT.wrapPointer(inCollisionResultPtr, JOLT.CollideShapeResult) as Jolt.CollideShapeResult; - const message: OnContactValidateData = { - body1: body1, - body2: body2, - baseOffset: baseOffset, - collisionResult: collideShapeResult + body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, + body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, + baseOffset: JOLT.wrapPointer(inBaseOffsetPtr, JOLT.RVec3) as Jolt.RVec3, + collisionResult: JOLT.wrapPointer(inCollisionResultPtr, JOLT.CollideShapeResult) as Jolt.CollideShapeResult } - - OnContactValidateEvent.Dispatch(message) + new OnContactValidateEvent(message) return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair } diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 25c53a9e49..68fb04cce1 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -15,6 +15,7 @@ class ScoringSystem extends WorldSystem { constructor() { super() + // Create and render a zone sensor const geometry = new THREE.BoxGeometry( 1, 1, 1 ); const material = new THREE.MeshBasicMaterial( { color: 0x0000ff } ); const cube = new THREE.Mesh( geometry, material ); @@ -32,6 +33,7 @@ class ScoringSystem extends WorldSystem { World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) + // When zone collides with gamepiece, adds point const onContactAdded = (e: Event) => { const event = e as OnContactAddedEvent const body1 = event.message.body1 From bddff1643fd2ff5670712d81905cd349b2056791 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 16 Jul 2024 17:56:04 -0700 Subject: [PATCH 09/39] Refactored scoring collision and start to intake collision --- .../src/mirabuf/IntakeSensorSceneObject.ts | 39 +++++++++++++++---- fission/src/mirabuf/MirabufSceneObject.ts | 2 + fission/src/systems/physics/PhysicsSystem.ts | 11 ++++++ fission/src/systems/scoring/ScoringSystem.ts | 39 ++++++------------- 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index 260523f201..a7e98edc3f 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -10,6 +10,7 @@ import { ThreeQuaternion_JoltQuat, ThreeVector3_JoltVec3, } from "@/util/TypeConversions" +import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" class IntakeSensorSceneObject extends SceneObject { private _parentAssembly: MirabufSceneObject @@ -73,15 +74,30 @@ class IntakeSensorSceneObject extends SceneObject { if (!World.PhysicsSystem.isPaused) { // TEMPORARY GAME PIECE DETECTION - const hitRes = World.PhysicsSystem.RayCast(ThreeVector3_JoltVec3(position), new JOLT.Vec3(0, 0, 3)) - if (hitRes) { - const gpAssoc = World.PhysicsSystem.GetBodyAssociation(hitRes.data.mBodyID) - // This works, however the check for game piece is doing two checks. - if (gpAssoc?.isGamePiece) { - console.debug("Found game piece!") - this._parentAssembly.SetEjectable(hitRes.data.mBodyID, false) + // const hitRes = World.PhysicsSystem.RayCast(ThreeVector3_JoltVec3(position), new JOLT.Vec3(0, 0, 3)) + // if (hitRes) { + // const gpAssoc = World.PhysicsSystem.GetBodyAssociation(hitRes.data.mBodyID) + // // This works, however the check for game piece is doing two checks. + // if (gpAssoc?.isGamePiece) { + // console.debug("Found game piece!") + // this._parentAssembly.SetEjectable(hitRes.data.mBodyID, false) + // } + // } + + const collision = (e: Event) => { + const event = e as OnContactAddedEvent + const body1 = event.message.body1 + const body2 = event.message.body2 + + if (body1.GetID().GetIndex() == this._joltBodyId?.GetIndex()) { + this.IntakeCollision(body2.GetID()) + } else if (body2.GetID().GetIndex() == this._joltBodyId?.GetIndex()) { + this.IntakeCollision(body1.GetID()) } } + + OnContactAddedEvent.AddListener(collision) + } } } @@ -99,6 +115,15 @@ class IntakeSensorSceneObject extends SceneObject { } } } + + private IntakeCollision(gpID: Jolt.BodyID) { + console.log(`Intake collided with ${gpID.GetIndex()}`) + + const associate = World.PhysicsSystem.GetBodyAssociation(gpID) + if (associate?.isGamePiece) { + this._parentAssembly.SetEjectable(gpID, false) + } + } } export default IntakeSensorSceneObject diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 3366381742..fa142410a3 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -307,7 +307,9 @@ class MirabufSceneObject extends SceneObject { } this._ejectable = new EjectableSceneObject(this, bodyId) + console.log("3/4 there") World.SceneRenderer.RegisterSceneObject(this._ejectable) + console.log("About to return") return true } diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 12ebac0362..8d5d9fc815 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -172,12 +172,20 @@ class PhysicsSystem extends WorldSystem { * @param bodyId */ public DisablePhysicsForBody(bodyId: Jolt.BodyID) { + console.log(`1`) if (!this.IsBodyAdded(bodyId)) { + console.log(`2`) + return } + console.log(`3`) this._joltBodyInterface.DeactivateBody(bodyId) + console.log(`4`) + this.GetBody(bodyId).SetIsSensor(true) + console.log(`5`) + } /** @@ -195,6 +203,9 @@ class PhysicsSystem extends WorldSystem { } public IsBodyAdded(bodyId: Jolt.BodyID) { + console.log(`6 ${this}`) + console.log(`6.1 ${this._joltBodyInterface}`) + console.log(`7 ${this._joltBodyInterface.IsAdded(bodyId)}`) return this._joltBodyInterface.IsAdded(bodyId) } diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 68fb04cce1..dd0fbb2899 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -39,35 +39,11 @@ class ScoringSystem extends WorldSystem { const body1 = event.message.body1 const body2 = event.message.body2 + if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { - console.log(`${body1.GetID().GetIndex()} collided with ${body2.GetID().GetIndex()}`) - - const fields = [...World.SceneRenderer.sceneObjects.entries()] - .filter(x => { - if (!(x[1] instanceof MirabufSceneObject)) { - return false - } else { - return x[1].miraType == MiraType.FIELD - } - }) - .map(x => x[1]) as MirabufSceneObject[] - - fields.forEach(x => { - x.mechanism.nodeToBody.forEach( (bodyID, rigidNodeID) => { - const associate = World.PhysicsSystem.GetBodyAssociation(bodyID) - if (associate instanceof RigidNodeAssociate) { - if (associate.isGamePiece) { - const body2ID = body2.GetID().GetIndex() - const gamepieceID = +associate.rigidNodeId.replace("_gp", "") // Gets number without gamepiece tag - - if (body2ID == gamepieceID) { - this.points++ - console.log(this.points) - } - } - } - }) - }) + this.ZoneCollision(body2.GetID()) + } else if (body2.GetID().GetIndex() == zone.GetID().GetIndex()) { + this.ZoneCollision(body1.GetID()) } } @@ -82,6 +58,13 @@ class ScoringSystem extends WorldSystem { public Destroy(): void { } + + private ZoneCollision(gpID: Jolt.BodyID) { + console.log(`Scoring zone collided with ${gpID.GetIndex()}`) + + const associate = World.PhysicsSystem.GetBodyAssociation(gpID) + if (associate.isGamePiece) this.points++ + } } export default ScoringSystem \ No newline at end of file From 06321616d5fc25073ded94cac4bd29c809c6dd2a Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 16 Jul 2024 19:12:34 -0700 Subject: [PATCH 10/39] Debugging SetEjectable > isAdded(bodyID) --- .../src/mirabuf/IntakeSensorSceneObject.ts | 44 ++++++++++++------- fission/src/systems/physics/ContactEvents.ts | 32 +++++++------- fission/src/systems/physics/PhysicsSystem.ts | 6 +-- fission/src/systems/scoring/ScoringSystem.ts | 7 ++- 4 files changed, 51 insertions(+), 38 deletions(-) diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index a7e98edc3f..bec9646422 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -50,6 +50,33 @@ class IntakeSensorSceneObject extends SceneObject { ) World.SceneRenderer.scene.add(this._mesh) + const collision = (event: OnContactAddedEvent) => { + if (this._joltBodyId && this._parentBodyId && this._deltaTransformation && !World.PhysicsSystem.isPaused) { + const body1 = event.message.body1 + const body2 = event.message.body2 + + if (body1.GetID().GetIndex() == this._joltBodyId.GetIndex()) { + console.log("1") + console.log(`Intake collided with ${body2.GetID().GetIndex()}`) + + const associate = World.PhysicsSystem.GetBodyAssociation(body2.GetID()) + if (associate?.isGamePiece) { + this._parentAssembly.SetEjectable(body2.GetID(), false) + } + } else if (body2.GetID().GetIndex() == this._joltBodyId.GetIndex()) { + console.log("2") + console.log(`Intake collided with ${body1.GetID().GetIndex()}`) + + const associate = World.PhysicsSystem.GetBodyAssociation(body1.GetID()) + if (associate?.isGamePiece) { + this._parentAssembly.SetEjectable(body1.GetID(), false) + } + } + } + } + + OnContactAddedEvent.AddListener(collision) + console.debug("Intake sensor created successfully!") } } @@ -84,26 +111,13 @@ class IntakeSensorSceneObject extends SceneObject { // } // } - const collision = (e: Event) => { - const event = e as OnContactAddedEvent - const body1 = event.message.body1 - const body2 = event.message.body2 - - if (body1.GetID().GetIndex() == this._joltBodyId?.GetIndex()) { - this.IntakeCollision(body2.GetID()) - } else if (body2.GetID().GetIndex() == this._joltBodyId?.GetIndex()) { - this.IntakeCollision(body1.GetID()) - } - } - - OnContactAddedEvent.AddListener(collision) - + } } } public Dispose(): void { - console.debug("Destroying intake sensor") + console.log("Destroying intake sensor") if (this._joltBodyId) { World.PhysicsSystem.DestroyBodyIds(this._joltBodyId) diff --git a/fission/src/systems/physics/ContactEvents.ts b/fission/src/systems/physics/ContactEvents.ts index 3ddcc0fad1..2b0c0f92a7 100644 --- a/fission/src/systems/physics/ContactEvents.ts +++ b/fission/src/systems/physics/ContactEvents.ts @@ -27,12 +27,12 @@ export class OnContactAddedEvent extends Event { window.dispatchEvent(this) } - public static AddListener(func: (e: Event) => void) { - window.addEventListener(OnContactAddedEvent.EVENT_KEY, func) + public static AddListener(func: (e: OnContactAddedEvent) => void) { + window.addEventListener(OnContactAddedEvent.EVENT_KEY, func as (e: Event) => void) } - public static RemoveListener(func: (e: Event) => void) { - window.removeEventListener(OnContactAddedEvent.EVENT_KEY, func) + public static RemoveListener(func: (e: OnContactAddedEvent) => void) { + window.removeEventListener(OnContactAddedEvent.EVENT_KEY, func as (e: Event) => void) } } @@ -49,12 +49,12 @@ export class OnContactPersistedEvent extends Event { window.dispatchEvent(this) } - public static AddListener(func: (e: Event) => void) { - window.addEventListener(OnContactPersistedEvent.EVENT_KEY, func) + public static AddListener(func: (e: OnContactPersistedEvent) => void) { + window.addEventListener(OnContactPersistedEvent.EVENT_KEY, func as (e: Event) => void) } - public static RemoveListener(func: (e: Event) => void) { - window.removeEventListener(OnContactPersistedEvent.EVENT_KEY, func) + public static RemoveListener(func: (e: OnContactPersistedEvent) => void) { + window.removeEventListener(OnContactPersistedEvent.EVENT_KEY, func as (e: Event) => void) } } @@ -71,12 +71,12 @@ export class OnContactRemovedEvent extends Event { window.dispatchEvent(this) } - public static AddListener(func: (e: Event) => void) { - window.addEventListener(OnContactRemovedEvent.EVENT_KEY, func) + public static AddListener(func: (e: OnContactRemovedEvent) => void) { + window.addEventListener(OnContactRemovedEvent.EVENT_KEY, func as (e: Event) => void) } - public static RemoveListener(func: (e: Event) => void) { - window.removeEventListener(OnContactRemovedEvent.EVENT_KEY, func) + public static RemoveListener(func: (e: OnContactRemovedEvent) => void) { + window.removeEventListener(OnContactRemovedEvent.EVENT_KEY, func as (e: Event) => void) } } @@ -93,11 +93,11 @@ export class OnContactValidateEvent extends Event { window.dispatchEvent(this) } - public static AddListener(func: (e: Event) => void) { - window.addEventListener(OnContactValidateEvent.EVENT_KEY, func) + public static AddListener(func: (e: OnContactValidateEvent) => void) { + window.addEventListener(OnContactValidateEvent.EVENT_KEY, func as (e: Event) => void) } - public static RemoveListener(func: (e: Event) => void) { - window.removeEventListener(OnContactValidateEvent.EVENT_KEY, func) + public static RemoveListener(func: (e: OnContactValidateEvent) => void) { + window.removeEventListener(OnContactValidateEvent.EVENT_KEY, func as (e: Event) => void) } } \ No newline at end of file diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 8d5d9fc815..2076b763ba 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -7,7 +7,8 @@ import { ThreeVector3_JoltVec3, _JoltQuat, } from "../../util/TypeConversions" -import JOLT from "../../util/loading/JoltSyncLoader" +import JOLT from "@/util/loading/JoltSyncLoader" + import Jolt from "@barclah/jolt-physics" import * as THREE from "three" import { mirabuf } from "../../proto/mirabuf" @@ -203,8 +204,7 @@ class PhysicsSystem extends WorldSystem { } public IsBodyAdded(bodyId: Jolt.BodyID) { - console.log(`6 ${this}`) - console.log(`6.1 ${this._joltBodyInterface}`) + console.log(`6 ${bodyId.GetIndex()}`) console.log(`7 ${this._joltBodyInterface.IsAdded(bodyId)}`) return this._joltBodyInterface.IsAdded(bodyId) } diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index dd0fbb2899..d52a49d56d 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -34,13 +34,12 @@ class ScoringSystem extends WorldSystem { World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) // When zone collides with gamepiece, adds point - const onContactAdded = (e: Event) => { - const event = e as OnContactAddedEvent + const onContactAdded = (event: OnContactAddedEvent) => { const body1 = event.message.body1 const body2 = event.message.body2 - - if (body1.GetID().GetIndex() == zone.GetID().GetIndex()) { + console.log(`index1: ${body1.GetID().GetIndex()} and seq1: ${body1.GetID().GetIndexAndSequenceNumber()} `) + if (body1.GetID().GetIndex() == zone.GetID().GetIndexAndSequenceNumber()) { this.ZoneCollision(body2.GetID()) } else if (body2.GetID().GetIndex() == zone.GetID().GetIndex()) { this.ZoneCollision(body1.GetID()) From 9a460d346a66f23dcd9d3c78083b66c1e0e860dd Mon Sep 17 00:00:00 2001 From: KyroVibe Date: Tue, 16 Jul 2024 21:27:36 -0600 Subject: [PATCH 11/39] Physics system be crazy --- .../src/mirabuf/IntakeSensorSceneObject.ts | 18 ++- fission/src/systems/physics/ContactEvents.ts | 20 ++- fission/src/systems/physics/PhysicsSystem.ts | 153 ++++++++++-------- fission/src/systems/scoring/ScoringSystem.ts | 10 +- 4 files changed, 113 insertions(+), 88 deletions(-) diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index bec9646422..d54818120b 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -55,21 +55,23 @@ class IntakeSensorSceneObject extends SceneObject { const body1 = event.message.body1 const body2 = event.message.body2 - if (body1.GetID().GetIndex() == this._joltBodyId.GetIndex()) { + if (body1.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { console.log("1") - console.log(`Intake collided with ${body2.GetID().GetIndex()}`) + console.log(`Intake collided with ${body2.GetIndex()}`) - const associate = World.PhysicsSystem.GetBodyAssociation(body2.GetID()) + const associate = World.PhysicsSystem.GetBodyAssociation(body2) if (associate?.isGamePiece) { - this._parentAssembly.SetEjectable(body2.GetID(), false) + this._parentAssembly.SetEjectable(body2, false) + World.PhysicsSystem.GetBody(body2).AddImpulse(new JOLT.Vec3(0, 100, 0)) } - } else if (body2.GetID().GetIndex() == this._joltBodyId.GetIndex()) { + } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { console.log("2") - console.log(`Intake collided with ${body1.GetID().GetIndex()}`) + console.log(`Intake collided with ${body1.GetIndex()}`) - const associate = World.PhysicsSystem.GetBodyAssociation(body1.GetID()) + const associate = World.PhysicsSystem.GetBodyAssociation(body1) if (associate?.isGamePiece) { - this._parentAssembly.SetEjectable(body1.GetID(), false) + this._parentAssembly.SetEjectable(body1, false) + // World.PhysicsSystem.GetBody(body1).AddImpulse(new JOLT.Vec3(0, 100, 0)) } } } diff --git a/fission/src/systems/physics/ContactEvents.ts b/fission/src/systems/physics/ContactEvents.ts index 2b0c0f92a7..b072920859 100644 --- a/fission/src/systems/physics/ContactEvents.ts +++ b/fission/src/systems/physics/ContactEvents.ts @@ -1,8 +1,8 @@ import Jolt from "@barclah/jolt-physics"; export interface CurrentContactData { - body1: Jolt.Body - body2: Jolt.Body + body1: Jolt.BodyID + body2: Jolt.BodyID manifold: Jolt.ContactManifold settings: Jolt.ContactSettings } @@ -14,7 +14,11 @@ export interface OnContactValidateData { collisionResult: Jolt.CollideShapeResult } -export class OnContactAddedEvent extends Event { +export abstract class PhysicsEvent extends Event { + abstract Dispatch(): void +} + +export class OnContactAddedEvent extends PhysicsEvent { public static readonly EVENT_KEY = 'OnContactAddedEvent' public message: CurrentContactData @@ -23,7 +27,9 @@ export class OnContactAddedEvent extends Event { super(OnContactAddedEvent.EVENT_KEY) this.message = data - + } + + public Dispatch(): void { window.dispatchEvent(this) } @@ -36,7 +42,7 @@ export class OnContactAddedEvent extends Event { } } -export class OnContactPersistedEvent extends Event { +export class OnContactPersistedEvent extends PhysicsEvent { public static readonly EVENT_KEY = 'OnContactPersistedEvent' public message: CurrentContactData @@ -49,6 +55,10 @@ export class OnContactPersistedEvent extends Event { window.dispatchEvent(this) } + public Dispatch(): void { + window.dispatchEvent(this) + } + public static AddListener(func: (e: OnContactPersistedEvent) => void) { window.addEventListener(OnContactPersistedEvent.EVENT_KEY, func as (e: Event) => void) } diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 2076b763ba..87f0dc5299 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -15,8 +15,9 @@ import { mirabuf } from "../../proto/mirabuf" import MirabufParser, { GAMEPIECE_SUFFIX, GROUNDED_JOINT_ID, RigidNodeReadOnly } from "../../mirabuf/MirabufParser" import WorldSystem from "../WorldSystem" import Mechanism from "./Mechanism" -import { M } from "node_modules/vite/dist/node/types.d-jgA8ss1A" -import { OnContactAddedEvent, CurrentContactData, OnContactPersistedEvent, OnContactRemovedEvent, OnContactValidateEvent, OnContactValidateData } from "./ContactEvents" +import { OnContactAddedEvent, CurrentContactData, OnContactPersistedEvent, OnContactRemovedEvent, OnContactValidateEvent, OnContactValidateData, PhysicsEvent } from "./ContactEvents" +import World from "../World" +import Queue from "@/util/Queue" export type JoltBodyIndexAndSequence = number @@ -67,6 +68,8 @@ class PhysicsSystem extends WorldSystem { private _bodies: Array private _constraints: Array + private _physicsEventQueue: PhysicsEvent[] = [] + private _pauseCounter = 0 private _bodyAssociations: Map @@ -101,7 +104,7 @@ class PhysicsSystem extends WorldSystem { this._joltPhysSystem = this._joltInterface.GetPhysicsSystem() this._joltBodyInterface = this._joltPhysSystem.GetBodyInterface() - SetUpContactListener(this._joltPhysSystem) + this.SetUpContactListener(this._joltPhysSystem) this._joltPhysSystem.SetGravity(new JOLT.Vec3(0, -9.8, 0)) @@ -174,11 +177,11 @@ class PhysicsSystem extends WorldSystem { */ public DisablePhysicsForBody(bodyId: Jolt.BodyID) { console.log(`1`) - if (!this.IsBodyAdded(bodyId)) { - console.log(`2`) + // if (!this.IsBodyAdded(bodyId)) { + // console.log(`2`) - return - } + // return + // } console.log(`3`) this._joltBodyInterface.DeactivateBody(bodyId) @@ -195,10 +198,6 @@ class PhysicsSystem extends WorldSystem { * @param bodyId */ public EnablePhysicsForBody(bodyId: Jolt.BodyID) { - if (!this.IsBodyAdded(bodyId)) { - return - } - this._joltBodyInterface.ActivateBody(bodyId) this.GetBody(bodyId).SetIsSensor(false) } @@ -939,6 +938,9 @@ class PhysicsSystem extends WorldSystem { substeps = Math.min(MAX_SUBSTEPS, Math.max(MIN_SUBSTEPS, substeps)) this._joltInterface.Step(lastDeltaT, substeps) + + this._physicsEventQueue.forEach(x => x.Dispatch()) + this._physicsEventQueue = [] } public Destroy(): void { @@ -1011,9 +1013,9 @@ class PhysicsSystem extends WorldSystem { * @param position The new position of the body */ public SetBodyPosition(id: Jolt.BodyID, position: Jolt.Vec3, activate: boolean = true): void { - if (!this.IsBodyAdded(id)) { - return - } + // if (!this.IsBodyAdded(id)) { + // return + // } this._joltBodyInterface.SetPosition( id, @@ -1023,9 +1025,9 @@ class PhysicsSystem extends WorldSystem { } public SetBodyRotation(id: Jolt.BodyID, rotation: Jolt.Quat, activate: boolean = true): void { - if (!this.IsBodyAdded(id)) { - return - } + // if (!this.IsBodyAdded(id)) { + // return + // } this._joltBodyInterface.SetRotation( id, @@ -1033,6 +1035,71 @@ class PhysicsSystem extends WorldSystem { activate ? JOLT.EActivation_Activate : JOLT.EActivation_DontActivate ) } + + /** + * Creates and assigns Jolt contact listener that dispatches events. + * + * @param physSystem + */ + private SetUpContactListener(physSystem: Jolt.PhysicsSystem) { + const contactListener = new JOLT.ContactListenerJS() + + contactListener.OnContactAdded = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { + + const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body + const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body + + const body1Id = new JOLT.BodyID(body1.GetID().GetIndexAndSequenceNumber()) + const body2Id = new JOLT.BodyID(body2.GetID().GetIndexAndSequenceNumber()) + + const message: CurrentContactData = { + body1: body1Id, + body2: body2Id, + manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, + settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings + }; + + this._physicsEventQueue.push(new OnContactAddedEvent(message)) + }; + + contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { + // const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body + // const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body + + // const body1Id = body1.GetID() + // const body2Id = body2.GetID() + + // const message: CurrentContactData = { + // body1: body1Id, + // body2: body2Id, + // manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, + // settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings + // }; + + // (async () => new OnContactPersistedEvent(message))() + } + + contactListener.OnContactRemoved = (subShapePairPtr) => { + const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair + + new OnContactRemovedEvent(shapePair) + } + + contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { + const message: OnContactValidateData = { + body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, + body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, + baseOffset: JOLT.wrapPointer(inBaseOffsetPtr, JOLT.RVec3) as Jolt.RVec3, + collisionResult: JOLT.wrapPointer(inCollisionResultPtr, JOLT.CollideShapeResult) as Jolt.CollideShapeResult + } + + new OnContactValidateEvent(message) + + return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair + } + + physSystem.SetContactListener(contactListener) + } } export class LayerReserve { @@ -1140,58 +1207,6 @@ function tryGetPerpendicular(vec: Jolt.Vec3, toCheck: Jolt.Vec3): Jolt.Vec3 | un ).Normalized() } -/** - * Creates and assigns Jolt contact listener that dispatches events. - * - * @param physSystem - */ -function SetUpContactListener(physSystem: Jolt.PhysicsSystem) { - const contactListener = new JOLT.ContactListenerJS() - - contactListener.OnContactAdded = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - const message: CurrentContactData = { - body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, - body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, - manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, - settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings - } - - new OnContactAddedEvent(message) - }; - - contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - const message: CurrentContactData = { - body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, - body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, - manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, - settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings - } - - new OnContactPersistedEvent(message) - } - - contactListener.OnContactRemoved = (subShapePairPtr) => { - const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair - - new OnContactRemovedEvent(shapePair) - } - - contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { - const message: OnContactValidateData = { - body1: JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body, - body2: JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body, - baseOffset: JOLT.wrapPointer(inBaseOffsetPtr, JOLT.RVec3) as Jolt.RVec3, - collisionResult: JOLT.wrapPointer(inCollisionResultPtr, JOLT.CollideShapeResult) as Jolt.CollideShapeResult - } - - new OnContactValidateEvent(message) - - return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair - } - - physSystem.SetContactListener(contactListener) -} - export type RayCastHit = { data: Jolt.RayCastResult point: Jolt.Vec3 diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index d52a49d56d..37a8efa97b 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -38,13 +38,11 @@ class ScoringSystem extends WorldSystem { const body1 = event.message.body1 const body2 = event.message.body2 - console.log(`index1: ${body1.GetID().GetIndex()} and seq1: ${body1.GetID().GetIndexAndSequenceNumber()} `) - if (body1.GetID().GetIndex() == zone.GetID().GetIndexAndSequenceNumber()) { - this.ZoneCollision(body2.GetID()) - } else if (body2.GetID().GetIndex() == zone.GetID().GetIndex()) { - this.ZoneCollision(body1.GetID()) + if (body1.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { + this.ZoneCollision(body2) + } else if (body2.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { + this.ZoneCollision(body1) } - } OnContactAddedEvent.AddListener(onContactAdded) From a0f0ccccbbe522d09b3f2973cb438d8885c7597d Mon Sep 17 00:00:00 2001 From: a-crowell Date: Wed, 17 Jul 2024 09:42:12 -0700 Subject: [PATCH 12/39] Debug clean up --- .../src/mirabuf/IntakeSensorSceneObject.ts | 36 +++---------------- fission/src/mirabuf/MirabufSceneObject.ts | 3 +- fission/src/systems/physics/PhysicsSystem.ts | 27 +++++--------- fission/src/systems/scoring/ScoringSystem.ts | 5 ++- 4 files changed, 18 insertions(+), 53 deletions(-) diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index d54818120b..7e4ca459bb 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -51,28 +51,15 @@ class IntakeSensorSceneObject extends SceneObject { World.SceneRenderer.scene.add(this._mesh) const collision = (event: OnContactAddedEvent) => { - if (this._joltBodyId && this._parentBodyId && this._deltaTransformation && !World.PhysicsSystem.isPaused) { + //TODO: Add intake key pressed check + if (this._joltBodyId && !World.PhysicsSystem.isPaused) { const body1 = event.message.body1 const body2 = event.message.body2 if (body1.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { - console.log("1") - console.log(`Intake collided with ${body2.GetIndex()}`) - - const associate = World.PhysicsSystem.GetBodyAssociation(body2) - if (associate?.isGamePiece) { - this._parentAssembly.SetEjectable(body2, false) - World.PhysicsSystem.GetBody(body2).AddImpulse(new JOLT.Vec3(0, 100, 0)) - } + this.IntakeCollision(body2) } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { - console.log("2") - console.log(`Intake collided with ${body1.GetIndex()}`) - - const associate = World.PhysicsSystem.GetBodyAssociation(body1) - if (associate?.isGamePiece) { - this._parentAssembly.SetEjectable(body1, false) - // World.PhysicsSystem.GetBody(body1).AddImpulse(new JOLT.Vec3(0, 100, 0)) - } + this.IntakeCollision(body1) } } } @@ -100,21 +87,6 @@ class IntakeSensorSceneObject extends SceneObject { this._mesh.position.setFromMatrixPosition(bodyTransform) this._mesh.rotation.setFromRotationMatrix(bodyTransform) } - - if (!World.PhysicsSystem.isPaused) { - // TEMPORARY GAME PIECE DETECTION - // const hitRes = World.PhysicsSystem.RayCast(ThreeVector3_JoltVec3(position), new JOLT.Vec3(0, 0, 3)) - // if (hitRes) { - // const gpAssoc = World.PhysicsSystem.GetBodyAssociation(hitRes.data.mBodyID) - // // This works, however the check for game piece is doing two checks. - // if (gpAssoc?.isGamePiece) { - // console.debug("Found game piece!") - // this._parentAssembly.SetEjectable(hitRes.data.mBodyID, false) - // } - // } - - - } } } diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index fa142410a3..15d7d717f9 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -295,6 +295,7 @@ class MirabufSceneObject extends SceneObject { public SetEjectable(bodyId?: Jolt.BodyID, removeExisting: boolean = false): boolean { if (this._ejectable) { if (!removeExisting) { + console.log("sup") return false } @@ -307,9 +308,7 @@ class MirabufSceneObject extends SceneObject { } this._ejectable = new EjectableSceneObject(this, bodyId) - console.log("3/4 there") World.SceneRenderer.RegisterSceneObject(this._ejectable) - console.log("About to return") return true } diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 87f0dc5299..88438551c5 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -176,20 +176,13 @@ class PhysicsSystem extends WorldSystem { * @param bodyId */ public DisablePhysicsForBody(bodyId: Jolt.BodyID) { - console.log(`1`) - // if (!this.IsBodyAdded(bodyId)) { - // console.log(`2`) - - // return - // } - console.log(`3`) + if (!this.IsBodyAdded(bodyId)) { + return + } this._joltBodyInterface.DeactivateBody(bodyId) - console.log(`4`) this.GetBody(bodyId).SetIsSensor(true) - console.log(`5`) - } /** @@ -203,8 +196,6 @@ class PhysicsSystem extends WorldSystem { } public IsBodyAdded(bodyId: Jolt.BodyID) { - console.log(`6 ${bodyId.GetIndex()}`) - console.log(`7 ${this._joltBodyInterface.IsAdded(bodyId)}`) return this._joltBodyInterface.IsAdded(bodyId) } @@ -1013,9 +1004,9 @@ class PhysicsSystem extends WorldSystem { * @param position The new position of the body */ public SetBodyPosition(id: Jolt.BodyID, position: Jolt.Vec3, activate: boolean = true): void { - // if (!this.IsBodyAdded(id)) { - // return - // } + if (!this.IsBodyAdded(id)) { + return + } this._joltBodyInterface.SetPosition( id, @@ -1025,9 +1016,9 @@ class PhysicsSystem extends WorldSystem { } public SetBodyRotation(id: Jolt.BodyID, rotation: Jolt.Quat, activate: boolean = true): void { - // if (!this.IsBodyAdded(id)) { - // return - // } + if (!this.IsBodyAdded(id)) { + return + } this._joltBodyInterface.SetRotation( id, diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 37a8efa97b..9f3197f99e 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -60,7 +60,10 @@ class ScoringSystem extends WorldSystem { console.log(`Scoring zone collided with ${gpID.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) - if (associate.isGamePiece) this.points++ + if (associate?.isGamePiece) { + this.points++ + console.log(`points ${this.points}`) + } } } From f1f48e627c7e1cb214b6464248dfbe7d7b4adb02 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Wed, 17 Jul 2024 11:17:34 -0700 Subject: [PATCH 13/39] More testing and cleaning --- fission/src/systems/physics/ContactEvents.ts | 10 +++++--- fission/src/systems/physics/PhysicsSystem.ts | 26 ++++++++++---------- fission/src/systems/scoring/ScoringSystem.ts | 13 +++++----- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/fission/src/systems/physics/ContactEvents.ts b/fission/src/systems/physics/ContactEvents.ts index b072920859..1f0cd6ad33 100644 --- a/fission/src/systems/physics/ContactEvents.ts +++ b/fission/src/systems/physics/ContactEvents.ts @@ -51,8 +51,6 @@ export class OnContactPersistedEvent extends PhysicsEvent { super(OnContactPersistedEvent.EVENT_KEY) this.message = data - - window.dispatchEvent(this) } public Dispatch(): void { @@ -68,7 +66,7 @@ export class OnContactPersistedEvent extends PhysicsEvent { } } -export class OnContactRemovedEvent extends Event { +export class OnContactRemovedEvent extends PhysicsEvent { public static readonly EVENT_KEY = 'OnContactRemovedEvent' public message: Jolt.SubShapeIDPair @@ -77,7 +75,9 @@ export class OnContactRemovedEvent extends Event { super(OnContactRemovedEvent.EVENT_KEY) this.message = data + } + public Dispatch(): void { window.dispatchEvent(this) } @@ -90,7 +90,7 @@ export class OnContactRemovedEvent extends Event { } } -export class OnContactValidateEvent extends Event { +export class OnContactValidateEvent extends PhysicsEvent { public static readonly EVENT_KEY = 'OnContactValidateEvent' public message: OnContactValidateData @@ -99,7 +99,9 @@ export class OnContactValidateEvent extends Event { super(OnContactValidateEvent.EVENT_KEY) this.message = data + } + public Dispatch(): void { window.dispatchEvent(this) } diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index 88438551c5..c8b796c190 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -1054,26 +1054,26 @@ class PhysicsSystem extends WorldSystem { }; contactListener.OnContactPersisted = (bodyPtr1, bodyPtr2, manifoldPtr, settingsPtr) => { - // const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body - // const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body + const body1 = JOLT.wrapPointer(bodyPtr1, JOLT.Body) as Jolt.Body + const body2 = JOLT.wrapPointer(bodyPtr2, JOLT.Body) as Jolt.Body - // const body1Id = body1.GetID() - // const body2Id = body2.GetID() + const body1Id = body1.GetID() + const body2Id = body2.GetID() - // const message: CurrentContactData = { - // body1: body1Id, - // body2: body2Id, - // manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, - // settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings - // }; + const message: CurrentContactData = { + body1: body1Id, + body2: body2Id, + manifold: JOLT.wrapPointer(manifoldPtr, JOLT.ContactManifold) as Jolt.ContactManifold, + settings: JOLT.wrapPointer(settingsPtr, JOLT.ContactSettings) as Jolt.ContactSettings + }; - // (async () => new OnContactPersistedEvent(message))() + this._physicsEventQueue.push(new OnContactPersistedEvent(message)) } contactListener.OnContactRemoved = (subShapePairPtr) => { const shapePair = JOLT.wrapPointer(subShapePairPtr, JOLT.SubShapeIDPair) as Jolt.SubShapeIDPair - new OnContactRemovedEvent(shapePair) + this._physicsEventQueue.push(new OnContactRemovedEvent(shapePair)) } contactListener.OnContactValidate = (bodyPtr1, bodyPtr2, inBaseOffsetPtr, inCollisionResultPtr) => { @@ -1084,7 +1084,7 @@ class PhysicsSystem extends WorldSystem { collisionResult: JOLT.wrapPointer(inCollisionResultPtr, JOLT.CollideShapeResult) as Jolt.CollideShapeResult } - new OnContactValidateEvent(message) + this._physicsEventQueue.push(new OnContactValidateEvent(message)) return JOLT.ValidateResult_AcceptAllContactsForThisBodyPair } diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 9f3197f99e..8132f9ddbd 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -3,13 +3,10 @@ import World from "../World"; import WorldSystem from "../WorldSystem"; import JOLT from "@/util/loading/JoltSyncLoader"; import Jolt from "@barclah/jolt-physics"; -import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; -import { MiraType } from "@/mirabuf/MirabufLoader"; +import { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; import { OnContactAddedEvent } from "../physics/ContactEvents"; class ScoringSystem extends WorldSystem { - private zone: Jolt.Body; - private points = 0 constructor() { @@ -29,8 +26,6 @@ class ScoringSystem extends WorldSystem { true ) - this.zone = zone - World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) // When zone collides with gamepiece, adds point @@ -46,6 +41,12 @@ class ScoringSystem extends WorldSystem { } OnContactAddedEvent.AddListener(onContactAdded) + + + // ContactListenerTests + // OnContactPersistedEvent.AddListener((event: OnContactPersistedEvent) => console.log(`persisted: ${event.message.body1.GetIndexAndSequenceNumber()}`)) + // OnContactRemovedEvent.AddListener((event: OnContactRemovedEvent) => console.log(`removed: ${event.message.GetSubShapeID1()}`)) + // OnContactValidateEvent.AddListener((event: OnContactValidateEvent) => console.log(`validate: ${event.message.body1.GetID().GetIndexAndSequenceNumber()}`)) } public Update(_: number): void { From 9d05c4736f99f8a5f785f0e5e12e43631ed9ebec Mon Sep 17 00:00:00 2001 From: a-crowell Date: Wed, 17 Jul 2024 11:47:49 -0700 Subject: [PATCH 14/39] Bug handling --- fission/src/mirabuf/MirabufSceneObject.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 7ae3a0bd7d..c4e06e8c50 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -292,7 +292,6 @@ class MirabufSceneObject extends SceneObject { public SetEjectable(bodyId?: Jolt.BodyID, removeExisting: boolean = false): boolean { if (this._ejectable) { if (!removeExisting) { - console.log("sup") return false } @@ -301,6 +300,7 @@ class MirabufSceneObject extends SceneObject { } if (!this._ejectorPreferences || !this._ejectorPreferences.parentNode || !bodyId) { + console.log(`Configure an ejectable first.`) return false } From 93cee52a1d42ad88295c2e7b7e9f6592470ce9f9 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Wed, 17 Jul 2024 18:33:11 -0700 Subject: [PATCH 15/39] ScoringSceneObject made and partially gets changed by config panel --- fission/src/mirabuf/MirabufSceneObject.ts | 22 +++ fission/src/mirabuf/ScoringZoneSceneObject.ts | 114 +++++++++++++++ fission/src/systems/World.ts | 16 +-- fission/src/systems/scene/SceneRenderer.ts | 11 ++ fission/src/systems/scoring/ScoringSystem.ts | 133 +++++++++--------- .../configuring/scoring/ScoringZonesPanel.tsx | 1 + .../configuring/scoring/ZoneConfigPanel.tsx | 4 +- 7 files changed, 226 insertions(+), 75 deletions(-) create mode 100644 fission/src/mirabuf/ScoringZoneSceneObject.ts diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index d17f956b06..d0a8ae28a7 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -17,6 +17,7 @@ import PreferencesSystem from "@/systems/preferences/PreferencesSystem" import { MiraType } from "./MirabufLoader" import IntakeSensorSceneObject from "./IntakeSensorSceneObject" import EjectableSceneObject from "./EjectableSceneObject" +import ScoringZoneSceneObject from "./ScoringZoneSceneObject" const DEBUG_BODIES = false @@ -43,6 +44,7 @@ class MirabufSceneObject extends SceneObject { private _intakeSensor?: IntakeSensorSceneObject private _ejectable?: EjectableSceneObject + private _scoringZone?: ScoringZoneSceneObject get mirabufInstance() { return this._mirabufInstance @@ -137,6 +139,8 @@ class MirabufSceneObject extends SceneObject { // Intake this.UpdateIntakeSensor() + + this.UpdateScoringZones() } public Update(): void { @@ -218,6 +222,11 @@ class MirabufSceneObject extends SceneObject { this._ejectable = undefined } + //TODO: pluralize + if (this._scoringZone) { + World.SceneRenderer.RemoveSceneObject(this._scoringZone.id) + } + this._mechanism.nodeToBody.forEach(bodyId => { World.PhysicsSystem.RemoveBodyAssocation(bodyId) }) @@ -315,6 +324,19 @@ class MirabufSceneObject extends SceneObject { return true } + public UpdateScoringZones() { + //TODO: pluralize + if (this._scoringZone) { + World.SceneRenderer.RemoveSceneObject(this._scoringZone.id) + this._scoringZone = undefined + } + + if (this._fieldPreferences && this._fieldPreferences.scoringZones[0].parentNode) { + this._scoringZone = new ScoringZoneSceneObject(this) + World.SceneRenderer.RegisterSceneObject(this._scoringZone) + } + } + /** * Changes the mode of the mirabuf object from being interacted with to being placed. */ diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts new file mode 100644 index 0000000000..1dd46fb778 --- /dev/null +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -0,0 +1,114 @@ +import { Array_ThreeMatrix4, JoltMat44_ThreeMatrix4, ThreeQuaternion_JoltQuat, ThreeVector3_JoltVec3 } from "@/util/TypeConversions" +import MirabufSceneObject, { RigidNodeAssociate } from "./MirabufSceneObject" +import JOLT from "@/util/loading/JoltSyncLoader" +import World from "@/systems/World" +import Jolt from "@barclah/jolt-physics" +import * as THREE from "three" +import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" +import SceneObject from "@/systems/scene/SceneObject" + + +class ScoringZoneSceneObject extends SceneObject { + private _parentAssembly: MirabufSceneObject + private _parentBodyId?: Jolt.BodyID + private _deltaTransformation?: THREE.Matrix4 + + private _joltBodyId?: Jolt.BodyID + private _mesh?: THREE.Mesh + private points = 0 + + public constructor(parentAssembly: MirabufSceneObject) { + super() + + console.debug("Trying to create scoring zone...") + + this._parentAssembly = parentAssembly + } + + public Setup(): void { + const zones = this._parentAssembly.fieldPreferences?.scoringZones + if (zones) { + //TODO pluralize + this._parentBodyId = this._parentAssembly.mechanism.nodeToBody.get(zones[0].parentNode ?? this._parentAssembly.rootNodeId) + + this._deltaTransformation = Array_ThreeMatrix4(zones[0].deltaTransformation) + this._joltBodyId = World.PhysicsSystem.CreateSensor( + new JOLT.BoxShapeSettings( + ThreeVector3_JoltVec3(new THREE.Vector3(0.5, 0.5, 0.5)) + ) + ) + + if (!this._joltBodyId) { + console.log("Failed to create scoring zone. No Jolt Body") + return + } + + this._mesh = World.SceneRenderer.CreateBox( + ThreeVector3_JoltVec3(new THREE.Vector3(0.5, 0.5, 0.5)), + World.SceneRenderer.CreateToonMaterial(0x5eeb67) + ) + World.SceneRenderer.scene.add(this._mesh) + + const collision = (event: OnContactAddedEvent) => { + const body1 = event.message.body1 + const body2 = event.message.body2 + + if (body1.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollision(body2) + } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollision(body1) + } + } + + OnContactAddedEvent.AddListener(collision) + + console.log("Scoring zone created successfully") + } + } + + public Update(): void { + if (this._joltBodyId && this._parentBodyId && this._deltaTransformation) { + const parentBody = World.PhysicsSystem.GetBody(this._parentBodyId) + const bodyTransform = this._deltaTransformation + .clone() + .premultiply(JoltMat44_ThreeMatrix4(parentBody.GetWorldTransform())) + const position = new THREE.Vector3(0, 0, 0) + const rotation = new THREE.Quaternion(0, 0, 0, 1) + bodyTransform.decompose(position, rotation, new THREE.Vector3(1, 1, 1)) + + World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(position)) + World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) + + if (this._mesh) { + this._mesh.position.setFromMatrixPosition(bodyTransform) + this._mesh.rotation.setFromRotationMatrix(bodyTransform) + } + } + } + + public Dispose(): void { + console.log("Destroying scoring zone") + + if (this._joltBodyId) { + World.PhysicsSystem.DestroyBodyIds(this._joltBodyId) + + if (this._mesh) { + this._mesh.geometry.dispose() + ;(this._mesh.material as THREE.Material).dispose() + World.SceneRenderer.scene.remove(this._mesh) + } + } + } + + private ZoneCollision(gpID: Jolt.BodyID) { + console.log(`Scoring zone collided with ${gpID.GetIndex()}`) + + const associate = World.PhysicsSystem.GetBodyAssociation(gpID) + if (associate?.isGamePiece) { + this.points++ + console.log(`points ${this.points}`) + } + } +} + +export default ScoringZoneSceneObject \ No newline at end of file diff --git a/fission/src/systems/World.ts b/fission/src/systems/World.ts index 427358cf79..9bebeb8c38 100644 --- a/fission/src/systems/World.ts +++ b/fission/src/systems/World.ts @@ -4,7 +4,7 @@ import PhysicsSystem from "./physics/PhysicsSystem" import SceneRenderer from "./scene/SceneRenderer" import SimulationSystem from "./simulation/SimulationSystem" import InputSystem from "./input/InputSystem" -import ScoringSystem from "./scoring/ScoringSystem" +// import ScoringSystem from "./scoring/ScoringSystem" class World { private static _isAlive: boolean = false @@ -14,7 +14,7 @@ class World { private static _physicsSystem: PhysicsSystem private static _simulationSystem: SimulationSystem private static _inputSystem: InputSystem - private static _scoringSystem: ScoringSystem + // private static _scoringSystem: ScoringSystem public static get isAlive() { return World._isAlive @@ -32,9 +32,9 @@ class World { public static get InputSystem() { return World._inputSystem } - public static get ScoringSystem() { - return World._scoringSystem - } + // public static get ScoringSystem() { + // return World._scoringSystem + // } public static InitWorld() { if (World._isAlive) return @@ -46,7 +46,7 @@ class World { World._physicsSystem = new PhysicsSystem() World._simulationSystem = new SimulationSystem() World._inputSystem = new InputSystem() - World._scoringSystem = new ScoringSystem() + // World._scoringSystem = new ScoringSystem() } public static DestroyWorld() { @@ -58,7 +58,7 @@ class World { World._sceneRenderer.Destroy() World._simulationSystem.Destroy() World._inputSystem.Destroy() - World._scoringSystem.Destroy() + // World._scoringSystem.Destroy() } public static UpdateWorld() { @@ -67,7 +67,7 @@ class World { World._physicsSystem.Update(deltaT) World._inputSystem.Update(deltaT) World._sceneRenderer.Update(deltaT) - World._scoringSystem.Update(deltaT) + // World._scoringSystem.Update(deltaT) } } diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 2617401501..a4b341f185 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -10,6 +10,7 @@ import vertexShader from "@/shaders/vertex.glsl" import fragmentShader from "@/shaders/fragment.glsl" import { Theme } from "@/ui/ThemeContext" import InputSystem from "../input/InputSystem" +import Jolt from "@barclah/jolt-physics" const CLEAR_COLOR = 0x121212 const GROUND_COLOR = 0x4066c7 @@ -187,6 +188,16 @@ class SceneRenderer extends WorldSystem { } } + public CreateBox(halfExtent: Jolt.Vec3, material?: THREE.Material | undefined): THREE.Mesh { + const geo = new THREE.BoxGeometry(halfExtent.GetX(), halfExtent.GetY(), halfExtent.GetZ()) + if (material) { + return new THREE.Mesh(geo, material) + } else { + return new THREE.Mesh(geo, this.CreateToonMaterial()) + } + } + + public CreateToonMaterial(color: THREE.ColorRepresentation = 0xff00aa, steps: number = 5): THREE.MeshToonMaterial { const format = this._renderer.capabilities.isWebGL2 ? THREE.RedFormat : THREE.LuminanceFormat const colors = new Uint8Array(steps) diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts index 8132f9ddbd..9f637a78aa 100644 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ b/fission/src/systems/scoring/ScoringSystem.ts @@ -1,71 +1,74 @@ -import * as THREE from "three"; -import World from "../World"; -import WorldSystem from "../WorldSystem"; -import JOLT from "@/util/loading/JoltSyncLoader"; -import Jolt from "@barclah/jolt-physics"; -import { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; -import { OnContactAddedEvent } from "../physics/ContactEvents"; - -class ScoringSystem extends WorldSystem { - private points = 0 - - constructor() { - super() - - // Create and render a zone sensor - const geometry = new THREE.BoxGeometry( 1, 1, 1 ); - const material = new THREE.MeshBasicMaterial( { color: 0x0000ff } ); - const cube = new THREE.Mesh( geometry, material ); - World.SceneRenderer.scene.add( cube ); - - const zone = World.PhysicsSystem.CreateBox( - new THREE.Vector3(0.5, 0.5, 0.5), - undefined, - undefined, - undefined, - true - ) - - World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) - - // When zone collides with gamepiece, adds point - const onContactAdded = (event: OnContactAddedEvent) => { - const body1 = event.message.body1 - const body2 = event.message.body2 - - if (body1.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { - this.ZoneCollision(body2) - } else if (body2.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { - this.ZoneCollision(body1) - } - } - - OnContactAddedEvent.AddListener(onContactAdded) - - - // ContactListenerTests - // OnContactPersistedEvent.AddListener((event: OnContactPersistedEvent) => console.log(`persisted: ${event.message.body1.GetIndexAndSequenceNumber()}`)) - // OnContactRemovedEvent.AddListener((event: OnContactRemovedEvent) => console.log(`removed: ${event.message.GetSubShapeID1()}`)) - // OnContactValidateEvent.AddListener((event: OnContactValidateEvent) => console.log(`validate: ${event.message.body1.GetID().GetIndexAndSequenceNumber()}`)) - } - - public Update(_: number): void { +// import * as THREE from "three"; +// import World from "../World"; +// import WorldSystem from "../WorldSystem"; +// import JOLT from "@/util/loading/JoltSyncLoader"; +// import Jolt from "@barclah/jolt-physics"; +// import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; +// import { OnContactAddedEvent } from "../physics/ContactEvents"; +// import { FieldPreferencesKey } from "../preferences/PreferenceTypes"; + +// class ScoringSystem extends WorldSystem { +// private points = 0 + +// constructor() { +// super() + +// // // Create and render a zone sensor +// // const geometry = new THREE.BoxGeometry( 1, 1, 1 ); +// // const material = new THREE.MeshBasicMaterial( { color: 0x0000ff } ); +// // const cube = new THREE.Mesh( geometry, material ); +// // World.SceneRenderer.scene.add( cube ); + +// // const zone = World.PhysicsSystem.CreateBox( +// // new THREE.Vector3(0.5, 0.5, 0.5), +// // undefined, +// // undefined, +// // undefined, +// // true +// // ) + +// // World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) + +// // const field = ([...World.SceneRenderer.sceneObjects.entries()][0][1] as MirabufSceneObject).fieldPreferences?.scoringZones[0] + +// // // When zone collides with gamepiece, adds point +// // const onContactAdded = (event: OnContactAddedEvent) => { +// // const body1 = event.message.body1 +// // const body2 = event.message.body2 + +// // if (body1.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { +// // this.ZoneCollision(body2) +// // } else if (body2.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { +// // this.ZoneCollision(body1) +// // } +// // } + +// // OnContactAddedEvent.AddListener(onContactAdded) + + +// // ContactListenerTests +// // OnContactPersistedEvent.AddListener((event: OnContactPersistedEvent) => console.log(`persisted: ${event.message.body1.GetIndexAndSequenceNumber()}`)) +// // OnContactRemovedEvent.AddListener((event: OnContactRemovedEvent) => console.log(`removed: ${event.message.GetSubShapeID1()}`)) +// // OnContactValidateEvent.AddListener((event: OnContactValidateEvent) => console.log(`validate: ${event.message.body1.GetID().GetIndexAndSequenceNumber()}`)) +// } + +// public Update(_: number): void { - } +// } - public Destroy(): void { +// public Destroy(): void { - } +// } - private ZoneCollision(gpID: Jolt.BodyID) { - console.log(`Scoring zone collided with ${gpID.GetIndex()}`) +// private ZoneCollision(gpID: Jolt.BodyID) { +// console.log(`Scoring zone collided with ${gpID.GetIndex()}`) - const associate = World.PhysicsSystem.GetBodyAssociation(gpID) - if (associate?.isGamePiece) { - this.points++ - console.log(`points ${this.points}`) - } - } -} +// const associate = World.PhysicsSystem.GetBodyAssociation(gpID) +// if (associate?.isGamePiece) { +// this.points++ +// console.log(`points ${this.points}`) +// } +// } +// } -export default ScoringSystem \ No newline at end of file +// export default ScoringSystem \ No newline at end of file diff --git a/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx b/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx index d020c61595..ae6a2b184d 100644 --- a/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx @@ -38,6 +38,7 @@ const saveZones = (zones: ScoringZonePreferences[] | undefined, field: MirabufSc if (fieldPrefs) fieldPrefs.scoringZones = zones PreferencesSystem.savePreferences() + field.UpdateScoringZones() } const ScoringZoneRow: React.FC = ({ zone, save, field, openPanel, deleteZone }) => { diff --git a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx index 57660af0b4..b212e2ae7e 100644 --- a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx @@ -140,9 +140,9 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side }) /* World.SceneRenderer.CreateToonMaterial(ReactRgbaColor_ThreeColor(theme.HighlightHover.color)) */ ) - ) + ); - ;(gizmo.mesh.material as THREE.Material).depthTest = false + (gizmo.mesh.material as THREE.Material).depthTest = false gizmo.AddMeshToScene() gizmo.CreateGizmo("translate", 1.5) From fc3eb0fac881f43fed185f5da93f775649d26d50 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Thu, 18 Jul 2024 12:06:58 -0700 Subject: [PATCH 16/39] Scoring zone rotation not messed up by scale and scoring zone detects points. --- fission/src/mirabuf/MirabufSceneObject.ts | 2 +- fission/src/mirabuf/ScoringZoneSceneObject.ts | 99 ++++++++++--------- fission/src/systems/physics/PhysicsSystem.ts | 22 +++++ .../configuring/scoring/ScoringZonesPanel.tsx | 2 +- 4 files changed, 78 insertions(+), 47 deletions(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index d0a8ae28a7..4dcaca9791 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -331,7 +331,7 @@ class MirabufSceneObject extends SceneObject { this._scoringZone = undefined } - if (this._fieldPreferences && this._fieldPreferences.scoringZones[0].parentNode) { + if (this._fieldPreferences && this._fieldPreferences.scoringZones[0] && this._fieldPreferences.scoringZones[0].parentNode) { this._scoringZone = new ScoringZoneSceneObject(this) World.SceneRenderer.RegisterSceneObject(this._scoringZone) } diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 1dd46fb778..123b806e66 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -6,6 +6,7 @@ import Jolt from "@barclah/jolt-physics" import * as THREE from "three" import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" import SceneObject from "@/systems/scene/SceneObject" +import TransformGizmos from "@/ui/components/TransformGizmos" class ScoringZoneSceneObject extends SceneObject { @@ -13,6 +14,7 @@ class ScoringZoneSceneObject extends SceneObject { private _parentBodyId?: Jolt.BodyID private _deltaTransformation?: THREE.Matrix4 + private _gizmo?: TransformGizmos private _joltBodyId?: Jolt.BodyID private _mesh?: THREE.Mesh private points = 0 @@ -31,63 +33,70 @@ class ScoringZoneSceneObject extends SceneObject { //TODO pluralize this._parentBodyId = this._parentAssembly.mechanism.nodeToBody.get(zones[0].parentNode ?? this._parentAssembly.rootNodeId) - this._deltaTransformation = Array_ThreeMatrix4(zones[0].deltaTransformation) - this._joltBodyId = World.PhysicsSystem.CreateSensor( - new JOLT.BoxShapeSettings( - ThreeVector3_JoltVec3(new THREE.Vector3(0.5, 0.5, 0.5)) + if (this._parentBodyId) { + + this._deltaTransformation = Array_ThreeMatrix4(zones[0].deltaTransformation) + + this._joltBodyId = World.PhysicsSystem.CreateSensor( + new JOLT.BoxShapeSettings( + new JOLT.Vec3(1,1,1) + ) ) - ) - if (!this._joltBodyId) { - console.log("Failed to create scoring zone. No Jolt Body") - return - } + if (!this._joltBodyId) { + console.log("Failed to create scoring zone. No Jolt Body") + return + } - this._mesh = World.SceneRenderer.CreateBox( - ThreeVector3_JoltVec3(new THREE.Vector3(0.5, 0.5, 0.5)), - World.SceneRenderer.CreateToonMaterial(0x5eeb67) - ) - World.SceneRenderer.scene.add(this._mesh) + this._mesh = World.SceneRenderer.CreateBox( + new JOLT.Vec3(1,1,1), + World.SceneRenderer.CreateToonMaterial(0x0000ff) + ) - const collision = (event: OnContactAddedEvent) => { - const body1 = event.message.body1 - const body2 = event.message.body2 - - if (body1.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { - this.ZoneCollision(body2) - } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { - this.ZoneCollision(body1) + World.SceneRenderer.scene.add(this._mesh) + + const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) + const gizmoTransformation = this._deltaTransformation.premultiply(fieldTransformation) + + const translation = new THREE.Vector3(0, 0, 0) + const rotation = new THREE.Quaternion(0, 0, 0, 1) + const scale = new THREE.Vector3(1, 1, 1) + gizmoTransformation.decompose(translation, rotation, scale) + + this._mesh.position.set(translation.x, translation.y, translation.z) + this._mesh.rotation.setFromQuaternion(rotation) + this._mesh.scale.set(scale.x, scale.y, scale.z) + + World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) + World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) + + const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) + const shape = shapeSettings.Create() + World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) + + const collision = (event: OnContactAddedEvent) => { + const body1 = event.message.body1 + const body2 = event.message.body2 + + if (body1.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollision(body2) + } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollision(body1) + } } - } - - OnContactAddedEvent.AddListener(collision) + + OnContactAddedEvent.AddListener(collision) - console.log("Scoring zone created successfully") + console.debug("Scoring zone created successfully") + } } } public Update(): void { - if (this._joltBodyId && this._parentBodyId && this._deltaTransformation) { - const parentBody = World.PhysicsSystem.GetBody(this._parentBodyId) - const bodyTransform = this._deltaTransformation - .clone() - .premultiply(JoltMat44_ThreeMatrix4(parentBody.GetWorldTransform())) - const position = new THREE.Vector3(0, 0, 0) - const rotation = new THREE.Quaternion(0, 0, 0, 1) - bodyTransform.decompose(position, rotation, new THREE.Vector3(1, 1, 1)) - - World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(position)) - World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) - - if (this._mesh) { - this._mesh.position.setFromMatrixPosition(bodyTransform) - this._mesh.rotation.setFromRotationMatrix(bodyTransform) - } - } } public Dispose(): void { - console.log("Destroying scoring zone") + console.debug("Destroying scoring zone") if (this._joltBodyId) { World.PhysicsSystem.DestroyBodyIds(this._joltBodyId) @@ -109,6 +118,6 @@ class ScoringZoneSceneObject extends SceneObject { console.log(`points ${this.points}`) } } + } - export default ScoringZoneSceneObject \ No newline at end of file diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index c8b796c190..f67b86a602 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -1027,6 +1027,28 @@ class PhysicsSystem extends WorldSystem { ) } + /** + * Exposes SetShape method on the _joltBodyInterface + * Sets the shape of the body + * + * @param id + * @param shape + * @param massProperties + * @param activationMode + */ + public SetShape(id: Jolt.BodyID, shape: Jolt.Shape, massProperties: boolean, activationMode: Jolt.EActivation): void { + if (!this.IsBodyAdded(id)) { + return + } + + this._joltBodyInterface.SetShape( + id, + shape, + massProperties, + activationMode + ) + } + /** * Creates and assigns Jolt contact listener that dispatches events. * diff --git a/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx b/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx index ae6a2b184d..6a1d3f4722 100644 --- a/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ScoringZonesPanel.tsx @@ -179,7 +179,7 @@ const ScoringZonesPanel: React.FC = ({ panelId, openLocation, si points: 0, destroyGamepiece: false, persistentPoints: false, - deltaTransformation: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + deltaTransformation: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] } saveZones(zones, selectedField) From 6e3dbadbbe4d296837434b899ca9f590e6307451 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Thu, 18 Jul 2024 13:14:11 -0700 Subject: [PATCH 17/39] Update works --- fission/src/mirabuf/MirabufSceneObject.ts | 1 + fission/src/mirabuf/ScoringZoneSceneObject.ts | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 4dcaca9791..bd2e29acd1 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -225,6 +225,7 @@ class MirabufSceneObject extends SceneObject { //TODO: pluralize if (this._scoringZone) { World.SceneRenderer.RemoveSceneObject(this._scoringZone.id) + this._scoringZone = undefined } this._mechanism.nodeToBody.forEach(bodyId => { diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 123b806e66..5d2aeb1bc6 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -93,6 +93,28 @@ class ScoringZoneSceneObject extends SceneObject { } public Update(): void { + if (this._parentBodyId && this._deltaTransformation && this._joltBodyId && this._mesh) { + const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) + const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) + + const translation = new THREE.Vector3(0, 0, 0) + const rotation = new THREE.Quaternion(0, 0, 0, 1) + const scale = new THREE.Vector3(1, 1, 1) + gizmoTransformation.decompose(translation, rotation, scale) + + this._mesh.position.set(translation.x, translation.y, translation.z) + this._mesh.rotation.setFromQuaternion(rotation) + this._mesh.scale.set(scale.x, scale.y, scale.z) + + World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) + World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) + + const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) + const shape = shapeSettings.Create() + World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) + } else { + console.debug("Failed to update scoring zone") + } } public Dispose(): void { From 0b3704cafc9e461cf169928c50b4bfe3c10e2ba3 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Thu, 18 Jul 2024 13:28:25 -0700 Subject: [PATCH 18/39] Positioning bug fix --- fission/src/mirabuf/ScoringZoneSceneObject.ts | 4 +++- fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 5d2aeb1bc6..5a5621169d 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -56,7 +56,7 @@ class ScoringZoneSceneObject extends SceneObject { World.SceneRenderer.scene.add(this._mesh) const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) - const gizmoTransformation = this._deltaTransformation.premultiply(fieldTransformation) + const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) const translation = new THREE.Vector3(0, 0, 0) const rotation = new THREE.Quaternion(0, 0, 0, 1) @@ -101,6 +101,8 @@ class ScoringZoneSceneObject extends SceneObject { const rotation = new THREE.Quaternion(0, 0, 0, 1) const scale = new THREE.Vector3(1, 1, 1) gizmoTransformation.decompose(translation, rotation, scale) + // console.log(`update trans: ${translation.toArray()} ${rotation.toArray()} ${scale.toArray()}`) + this._mesh.position.set(translation.x, translation.y, translation.z) this._mesh.rotation.setFromQuaternion(rotation) diff --git a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx index b212e2ae7e..63b83b80d6 100644 --- a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx @@ -163,6 +163,8 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side const rotation = new THREE.Quaternion(0, 0, 0, 1) const scale = new THREE.Vector3(1, 1, 1) gizmoTransformation.decompose(translation, rotation, scale) + // console.log(`config trans: ${translation.toArray()} ${rotation.toArray()} ${scale.toArray()}`) + gizmo.mesh.position.set(translation.x, translation.y, translation.z) gizmo.mesh.rotation.setFromQuaternion(rotation) From 0c4b510cf05ea71d05da90680f614d676294d818 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Thu, 18 Jul 2024 17:18:38 -0700 Subject: [PATCH 19/39] Multiple scoring zones --- fission/src/mirabuf/MirabufSceneObject.ts | 29 +++++------ fission/src/mirabuf/ScoringZoneSceneObject.ts | 48 ++++++++++++------- .../systems/simulation/SimulationSystem.ts | 8 ++++ 3 files changed, 52 insertions(+), 33 deletions(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index bd2e29acd1..900dd7ffa5 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -12,7 +12,7 @@ import Mechanism from "@/systems/physics/Mechanism" import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain" import InputSystem from "@/systems/input/InputSystem" import TransformGizmos from "@/ui/components/TransformGizmos" -import { EjectorPreferences, FieldPreferences, IntakePreferences } from "@/systems/preferences/PreferenceTypes" +import { EjectorPreferences, FieldPreferences, IntakePreferences, ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" import { MiraType } from "./MirabufLoader" import IntakeSensorSceneObject from "./IntakeSensorSceneObject" @@ -44,7 +44,7 @@ class MirabufSceneObject extends SceneObject { private _intakeSensor?: IntakeSensorSceneObject private _ejectable?: EjectableSceneObject - private _scoringZone?: ScoringZoneSceneObject + private _scoringZones: ScoringZoneSceneObject[] = [] get mirabufInstance() { return this._mirabufInstance @@ -222,11 +222,8 @@ class MirabufSceneObject extends SceneObject { this._ejectable = undefined } - //TODO: pluralize - if (this._scoringZone) { - World.SceneRenderer.RemoveSceneObject(this._scoringZone.id) - this._scoringZone = undefined - } + this._scoringZones.forEach(zone => World.SceneRenderer.RemoveSceneObject(zone.id)) + this._scoringZones = [] this._mechanism.nodeToBody.forEach(bodyId => { World.PhysicsSystem.RemoveBodyAssocation(bodyId) @@ -326,15 +323,15 @@ class MirabufSceneObject extends SceneObject { } public UpdateScoringZones() { - //TODO: pluralize - if (this._scoringZone) { - World.SceneRenderer.RemoveSceneObject(this._scoringZone.id) - this._scoringZone = undefined - } - - if (this._fieldPreferences && this._fieldPreferences.scoringZones[0] && this._fieldPreferences.scoringZones[0].parentNode) { - this._scoringZone = new ScoringZoneSceneObject(this) - World.SceneRenderer.RegisterSceneObject(this._scoringZone) + this._scoringZones.forEach(zone => World.SceneRenderer.RemoveSceneObject(zone.id)) + this._scoringZones = [] + + if (this._fieldPreferences && this._fieldPreferences.scoringZones) { + for (let i = 0; i < this._fieldPreferences.scoringZones.length; i++) { + const newZone = new ScoringZoneSceneObject(this, i) + this._scoringZones.push(newZone) + World.SceneRenderer.RegisterSceneObject(newZone) + } } } diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 5a5621169d..67a51f4553 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -6,36 +6,40 @@ import Jolt from "@barclah/jolt-physics" import * as THREE from "three" import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" import SceneObject from "@/systems/scene/SceneObject" -import TransformGizmos from "@/ui/components/TransformGizmos" +import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" +import SimulationSystem from "@/systems/simulation/SimulationSystem" class ScoringZoneSceneObject extends SceneObject { + //Official FIRST hex + static redMaterial = new THREE.MeshBasicMaterial( { color: 0xED1C24 } ) //0xff0000 + static blueMaterial = new THREE.MeshBasicMaterial( { color: 0x0066B3 } ) //0x0000ff + private _parentAssembly: MirabufSceneObject private _parentBodyId?: Jolt.BodyID private _deltaTransformation?: THREE.Matrix4 - private _gizmo?: TransformGizmos + private _prefs?: ScoringZonePreferences private _joltBodyId?: Jolt.BodyID private _mesh?: THREE.Mesh - private points = 0 + private _collision?: (event: OnContactAddedEvent) => void - public constructor(parentAssembly: MirabufSceneObject) { + public constructor(parentAssembly: MirabufSceneObject, index: number) { super() console.debug("Trying to create scoring zone...") this._parentAssembly = parentAssembly + this._prefs = this._parentAssembly.fieldPreferences?.scoringZones[index] } public Setup(): void { - const zones = this._parentAssembly.fieldPreferences?.scoringZones - if (zones) { - //TODO pluralize - this._parentBodyId = this._parentAssembly.mechanism.nodeToBody.get(zones[0].parentNode ?? this._parentAssembly.rootNodeId) + if (this._prefs) { + this._parentBodyId = this._parentAssembly.mechanism.nodeToBody.get(this._prefs.parentNode ?? this._parentAssembly.rootNodeId) if (this._parentBodyId) { - this._deltaTransformation = Array_ThreeMatrix4(zones[0].deltaTransformation) + this._deltaTransformation = Array_ThreeMatrix4(this._prefs.deltaTransformation) this._joltBodyId = World.PhysicsSystem.CreateSensor( new JOLT.BoxShapeSettings( @@ -74,7 +78,7 @@ class ScoringZoneSceneObject extends SceneObject { const shape = shapeSettings.Create() World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) - const collision = (event: OnContactAddedEvent) => { + this._collision = (event: OnContactAddedEvent) => { const body1 = event.message.body1 const body2 = event.message.body2 @@ -85,7 +89,7 @@ class ScoringZoneSceneObject extends SceneObject { } } - OnContactAddedEvent.AddListener(collision) + OnContactAddedEvent.AddListener(this._collision) console.debug("Scoring zone created successfully") } @@ -93,7 +97,7 @@ class ScoringZoneSceneObject extends SceneObject { } public Update(): void { - if (this._parentBodyId && this._deltaTransformation && this._joltBodyId && this._mesh) { + if (this._parentBodyId && this._deltaTransformation && this._joltBodyId && this._mesh && this._prefs) { const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) @@ -113,7 +117,10 @@ class ScoringZoneSceneObject extends SceneObject { const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) const shape = shapeSettings.Create() - World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) + World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate); + + this._mesh.material = this._prefs.alliance == "red" ? ScoringZoneSceneObject.redMaterial : ScoringZoneSceneObject.blueMaterial + } else { console.debug("Failed to update scoring zone") } @@ -131,17 +138,24 @@ class ScoringZoneSceneObject extends SceneObject { World.SceneRenderer.scene.remove(this._mesh) } } + + if (this._collision) OnContactAddedEvent.RemoveListener(this._collision) } private ZoneCollision(gpID: Jolt.BodyID) { - console.log(`Scoring zone collided with ${gpID.GetIndex()}`) + console.log(`Scoring zone ${this._joltBodyId?.GetIndexAndSequenceNumber()} collided with ${gpID.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) - if (associate?.isGamePiece) { - this.points++ - console.log(`points ${this.points}`) + if (associate?.isGamePiece && this._prefs) { + if (this._prefs.alliance == "red") { + SimulationSystem.redScore += this._prefs.points + } else { + SimulationSystem.blueScore += this._prefs.points + } + console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) } } } + export default ScoringZoneSceneObject \ No newline at end of file diff --git a/fission/src/systems/simulation/SimulationSystem.ts b/fission/src/systems/simulation/SimulationSystem.ts index 331739f8a7..d444fc41f5 100644 --- a/fission/src/systems/simulation/SimulationSystem.ts +++ b/fission/src/systems/simulation/SimulationSystem.ts @@ -15,6 +15,9 @@ import ChassisStimulus from "./stimulus/ChassisStimulus" class SimulationSystem extends WorldSystem { private _simMechanisms: Map + public static redScore = 0 + public static blueScore = 0 + constructor() { super() @@ -49,6 +52,11 @@ class SimulationSystem extends WorldSystem { return false } } + + public ResetScores(): void { + SimulationSystem.redScore = 0 + SimulationSystem.blueScore = 0 + } } class SimulationLayer { From 4d240caefc5c1eb4b15076b22228e8ca5eb16863 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Thu, 18 Jul 2024 23:37:00 -0700 Subject: [PATCH 20/39] Prefs render scoring zones --- fission/src/mirabuf/MirabufSceneObject.ts | 15 ++++- fission/src/mirabuf/ScoringZoneSceneObject.ts | 61 +++++++++++++------ .../systems/preferences/PreferencesSystem.ts | 2 +- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 900dd7ffa5..60d0fc89f3 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -13,7 +13,7 @@ import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain" import InputSystem from "@/systems/input/InputSystem" import TransformGizmos from "@/ui/components/TransformGizmos" import { EjectorPreferences, FieldPreferences, IntakePreferences, ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" -import PreferencesSystem from "@/systems/preferences/PreferencesSystem" +import PreferencesSystem, { PreferenceEvent } from "@/systems/preferences/PreferencesSystem" import { MiraType } from "./MirabufLoader" import IntakeSensorSceneObject from "./IntakeSensorSceneObject" import EjectableSceneObject from "./EjectableSceneObject" @@ -141,6 +141,15 @@ class MirabufSceneObject extends SceneObject { this.UpdateIntakeSensor() this.UpdateScoringZones() + + // Purely because mesh will not properly switch to more opaque material if the array changes or is formed while RenderScoringZones = false + PreferencesSystem.addEventListener((event: PreferenceEvent) => { + if (event.prefName == "RenderScoringZones") { + if (event.prefValue) { + this.UpdateScoringZones(event.prefValue as boolean) + } + } + }) } public Update(): void { @@ -322,13 +331,13 @@ class MirabufSceneObject extends SceneObject { return true } - public UpdateScoringZones() { + public UpdateScoringZones(render?: boolean) { this._scoringZones.forEach(zone => World.SceneRenderer.RemoveSceneObject(zone.id)) this._scoringZones = [] if (this._fieldPreferences && this._fieldPreferences.scoringZones) { for (let i = 0; i < this._fieldPreferences.scoringZones.length; i++) { - const newZone = new ScoringZoneSceneObject(this, i) + const newZone = new ScoringZoneSceneObject(this, i, render ?? PreferencesSystem.getGlobalPreference("RenderScoringZones")) this._scoringZones.push(newZone) World.SceneRenderer.RegisterSceneObject(newZone) } diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 67a51f4553..1391b5b215 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -8,29 +8,48 @@ import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" import SceneObject from "@/systems/scene/SceneObject" import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" import SimulationSystem from "@/systems/simulation/SimulationSystem" +import PreferencesSystem from "@/systems/preferences/PreferencesSystem" class ScoringZoneSceneObject extends SceneObject { //Official FIRST hex - static redMaterial = new THREE.MeshBasicMaterial( { color: 0xED1C24 } ) //0xff0000 - static blueMaterial = new THREE.MeshBasicMaterial( { color: 0x0066B3 } ) //0x0000ff + static redMaterial = new THREE.MeshPhongMaterial({ + color: 0xED1C24, + shininess: 0.0, + opacity: 0.7, + transparent: true, + }) + static blueMaterial = new THREE.MeshPhongMaterial({ + color: 0x0066B3, + shininess: 0.0, + opacity: 0.7, + transparent: true, + }) //0x0000ff + static transparentMaterial = new THREE.MeshPhongMaterial({ + color: 0x0000, + shininess: 0.0, + opacity: 0.0, + transparent: true + }) private _parentAssembly: MirabufSceneObject private _parentBodyId?: Jolt.BodyID private _deltaTransformation?: THREE.Matrix4 + private _toRender: boolean private _prefs?: ScoringZonePreferences private _joltBodyId?: Jolt.BodyID private _mesh?: THREE.Mesh private _collision?: (event: OnContactAddedEvent) => void - public constructor(parentAssembly: MirabufSceneObject, index: number) { + public constructor(parentAssembly: MirabufSceneObject, index: number, render?: boolean) { super() console.debug("Trying to create scoring zone...") this._parentAssembly = parentAssembly this._prefs = this._parentAssembly.fieldPreferences?.scoringZones[index] + this._toRender = render ?? PreferencesSystem.getGlobalPreference("RenderScoringZones") } public Setup(): void { @@ -51,13 +70,6 @@ class ScoringZoneSceneObject extends SceneObject { console.log("Failed to create scoring zone. No Jolt Body") return } - - this._mesh = World.SceneRenderer.CreateBox( - new JOLT.Vec3(1,1,1), - World.SceneRenderer.CreateToonMaterial(0x0000ff) - ) - - World.SceneRenderer.scene.add(this._mesh) const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) @@ -67,9 +79,18 @@ class ScoringZoneSceneObject extends SceneObject { const scale = new THREE.Vector3(1, 1, 1) gizmoTransformation.decompose(translation, rotation, scale) - this._mesh.position.set(translation.x, translation.y, translation.z) - this._mesh.rotation.setFromQuaternion(rotation) - this._mesh.scale.set(scale.x, scale.y, scale.z) + this._mesh = World.SceneRenderer.CreateBox( + new JOLT.Vec3(1,1,1), + ScoringZoneSceneObject.blueMaterial + ) + + if (this._toRender) { + this._mesh.position.set(translation.x, translation.y, translation.z) + this._mesh.rotation.setFromQuaternion(rotation) + this._mesh.scale.set(scale.x, scale.y, scale.z) + + World.SceneRenderer.scene.add(this._mesh) + } World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) @@ -98,6 +119,7 @@ class ScoringZoneSceneObject extends SceneObject { public Update(): void { if (this._parentBodyId && this._deltaTransformation && this._joltBodyId && this._mesh && this._prefs) { + this._toRender = PreferencesSystem.getGlobalPreference("RenderScoringZones") const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) @@ -107,10 +129,14 @@ class ScoringZoneSceneObject extends SceneObject { gizmoTransformation.decompose(translation, rotation, scale) // console.log(`update trans: ${translation.toArray()} ${rotation.toArray()} ${scale.toArray()}`) - - this._mesh.position.set(translation.x, translation.y, translation.z) - this._mesh.rotation.setFromQuaternion(rotation) - this._mesh.scale.set(scale.x, scale.y, scale.z) + if (this._toRender) { + this._mesh.position.set(translation.x, translation.y, translation.z) + this._mesh.rotation.setFromQuaternion(rotation) + this._mesh.scale.set(scale.x, scale.y, scale.z) + this._mesh.material = this._prefs.alliance == "red" ? ScoringZoneSceneObject.redMaterial : ScoringZoneSceneObject.blueMaterial + } else { + this._mesh.material = ScoringZoneSceneObject.transparentMaterial + } World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) @@ -119,7 +145,6 @@ class ScoringZoneSceneObject extends SceneObject { const shape = shapeSettings.Create() World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate); - this._mesh.material = this._prefs.alliance == "red" ? ScoringZoneSceneObject.redMaterial : ScoringZoneSceneObject.blueMaterial } else { console.debug("Failed to update scoring zone") diff --git a/fission/src/systems/preferences/PreferencesSystem.ts b/fission/src/systems/preferences/PreferencesSystem.ts index 97f02363c1..bbe2d4c678 100644 --- a/fission/src/systems/preferences/PreferencesSystem.ts +++ b/fission/src/systems/preferences/PreferencesSystem.ts @@ -9,7 +9,7 @@ import { RobotPreferencesKey, } from "./PreferenceTypes" -class PreferenceEvent extends Event { +export class PreferenceEvent extends Event { public prefName: GlobalPreference public prefValue: unknown From eb2421e682e9d40963c126d19a741458b6dce285 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Fri, 19 Jul 2024 00:21:59 -0700 Subject: [PATCH 21/39] A start to persistent --- fission/src/mirabuf/EjectableSceneObject.ts | 4 ++ fission/src/mirabuf/ScoringZoneSceneObject.ts | 56 ++++++++++++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/fission/src/mirabuf/EjectableSceneObject.ts b/fission/src/mirabuf/EjectableSceneObject.ts index 53fbdd7a10..5b054d783b 100644 --- a/fission/src/mirabuf/EjectableSceneObject.ts +++ b/fission/src/mirabuf/EjectableSceneObject.ts @@ -23,6 +23,10 @@ class EjectableSceneObject extends SceneObject { return this._gamePieceBodyId } + public get parentBodyId() { + return this._parentBodyId + } + public constructor(parentAssembly: MirabufSceneObject, gamePieceBody: Jolt.BodyID) { super() diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 1391b5b215..f9b89572ea 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -4,11 +4,12 @@ import JOLT from "@/util/loading/JoltSyncLoader" import World from "@/systems/World" import Jolt from "@barclah/jolt-physics" import * as THREE from "three" -import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" +import { OnContactAddedEvent, OnContactRemovedEvent } from "@/systems/physics/ContactEvents" import SceneObject from "@/systems/scene/SceneObject" import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" import SimulationSystem from "@/systems/simulation/SimulationSystem" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" +import EjectableSceneObject from "./EjectableSceneObject" class ScoringZoneSceneObject extends SceneObject { @@ -41,6 +42,7 @@ class ScoringZoneSceneObject extends SceneObject { private _joltBodyId?: Jolt.BodyID private _mesh?: THREE.Mesh private _collision?: (event: OnContactAddedEvent) => void + private _collisionRemoved?: (event: OnContactRemovedEvent) => void public constructor(parentAssembly: MirabufSceneObject, index: number, render?: boolean) { super() @@ -109,8 +111,22 @@ class ScoringZoneSceneObject extends SceneObject { this.ZoneCollision(body1) } } + + this._collisionRemoved = (event: OnContactRemovedEvent) => { + if (this._prefs?.persistentPoints) { + const body1 = event.message.GetBody1ID() + const body2 = event.message.GetBody2ID() + + if (body1.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollisionRemoved(body2) + } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollisionRemoved(body1) + } + } + } OnContactAddedEvent.AddListener(this._collision) + OnContactRemovedEvent.AddListener(this._collisionRemoved) console.debug("Scoring zone created successfully") } @@ -165,11 +181,10 @@ class ScoringZoneSceneObject extends SceneObject { } if (this._collision) OnContactAddedEvent.RemoveListener(this._collision) + if (this._collisionRemoved) OnContactRemovedEvent.RemoveListener(this._collisionRemoved) } private ZoneCollision(gpID: Jolt.BodyID) { - console.log(`Scoring zone ${this._joltBodyId?.GetIndexAndSequenceNumber()} collided with ${gpID.GetIndex()}`) - const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece && this._prefs) { if (this._prefs.alliance == "red") { @@ -181,6 +196,41 @@ class ScoringZoneSceneObject extends SceneObject { } } + // TODO: Add handling for when the ejectable carries the gamepiece out + private ZoneCollisionRemoved(gpID: Jolt.BodyID) { + console.log(`Scoring zone ${gpID.GetIndex()} removed from ${this._joltBodyId?.GetIndex()}`) + + const associate = World.PhysicsSystem.GetBodyAssociation(gpID) + if (associate?.isGamePiece) { + this.RemoveScore() + } else { + const ejectables = [...World.SceneRenderer.sceneObjects.entries()] + .filter(x => { + const y = x[1] instanceof EjectableSceneObject + return y + }) + .map(x => x[1]) as EjectableSceneObject[] + console.log(`eject ${ejectables.length}`) + + ejectables.forEach(x => { + if (x.parentBodyId == gpID) { + this.RemoveScore() + } + }) + } + } + + private RemoveScore() { + if (this._prefs) + if (this._prefs.alliance == "red") { + SimulationSystem.redScore -= this._prefs.points + if (SimulationSystem.redScore < 1) SimulationSystem.redScore = 0 + } else { + SimulationSystem.blueScore -= this._prefs.points + if (SimulationSystem.blueScore < 1) SimulationSystem.blueScore = 0 + } + console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) + } } export default ScoringZoneSceneObject \ No newline at end of file From 96068c3ed3cea03a6923dab26add7ae70e042ba4 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Fri, 19 Jul 2024 00:24:42 -0700 Subject: [PATCH 22/39] Print clean up --- fission/src/mirabuf/IntakeSensorSceneObject.ts | 2 +- fission/src/mirabuf/ScoringZoneSceneObject.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index 7e4ca459bb..311e705d7a 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -105,7 +105,7 @@ class IntakeSensorSceneObject extends SceneObject { } private IntakeCollision(gpID: Jolt.BodyID) { - console.log(`Intake collided with ${gpID.GetIndex()}`) + // console.log(`Intake collided with ${gpID.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index f9b89572ea..b13d5bc389 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -198,7 +198,7 @@ class ScoringZoneSceneObject extends SceneObject { // TODO: Add handling for when the ejectable carries the gamepiece out private ZoneCollisionRemoved(gpID: Jolt.BodyID) { - console.log(`Scoring zone ${gpID.GetIndex()} removed from ${this._joltBodyId?.GetIndex()}`) + // console.log(`Scoring zone ${gpID.GetIndex()} removed from ${this._joltBodyId?.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { @@ -210,7 +210,7 @@ class ScoringZoneSceneObject extends SceneObject { return y }) .map(x => x[1]) as EjectableSceneObject[] - console.log(`eject ${ejectables.length}`) + // console.log(`eject ${ejectables.length}`) ejectables.forEach(x => { if (x.parentBodyId == gpID) { From e8050ce567f93ffdc356dc74b1457fa76a406eac Mon Sep 17 00:00:00 2001 From: a-crowell Date: Fri, 19 Jul 2024 00:49:57 -0700 Subject: [PATCH 23/39] Intake key check --- .../src/mirabuf/IntakeSensorSceneObject.ts | 30 +++++++++++-------- fission/src/systems/World.ts | 7 ----- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index 311e705d7a..7e0eff8345 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -10,7 +10,8 @@ import { ThreeQuaternion_JoltQuat, ThreeVector3_JoltVec3, } from "@/util/TypeConversions" -import { OnContactAddedEvent } from "@/systems/physics/ContactEvents" +import { OnContactPersistedEvent } from "@/systems/physics/ContactEvents" +import InputSystem from "@/systems/input/InputSystem" class IntakeSensorSceneObject extends SceneObject { private _parentAssembly: MirabufSceneObject @@ -19,6 +20,7 @@ class IntakeSensorSceneObject extends SceneObject { private _joltBodyId?: Jolt.BodyID private _mesh?: THREE.Mesh + private _collision?: (e: OnContactPersistedEvent) => void public constructor(parentAssembly: MirabufSceneObject) { super() @@ -50,21 +52,22 @@ class IntakeSensorSceneObject extends SceneObject { ) World.SceneRenderer.scene.add(this._mesh) - const collision = (event: OnContactAddedEvent) => { - //TODO: Add intake key pressed check - if (this._joltBodyId && !World.PhysicsSystem.isPaused) { - const body1 = event.message.body1 - const body2 = event.message.body2 - - if (body1.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { - this.IntakeCollision(body2) - } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { - this.IntakeCollision(body1) + this._collision = (event: OnContactPersistedEvent) => { + if (InputSystem.isKeyPressed("KeyQ")) { + if (this._joltBodyId && !World.PhysicsSystem.isPaused) { + const body1 = event.message.body1 + const body2 = event.message.body2 + + if (body1.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { + this.IntakeCollision(body2) + } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId.GetIndexAndSequenceNumber()) { + this.IntakeCollision(body1) + } } } } - OnContactAddedEvent.AddListener(collision) + OnContactPersistedEvent.AddListener(this._collision) console.debug("Intake sensor created successfully!") } @@ -102,11 +105,12 @@ class IntakeSensorSceneObject extends SceneObject { World.SceneRenderer.scene.remove(this._mesh) } } + + if (this._collision) OnContactPersistedEvent.RemoveListener(this._collision) } private IntakeCollision(gpID: Jolt.BodyID) { // console.log(`Intake collided with ${gpID.GetIndex()}`) - const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { this._parentAssembly.SetEjectable(gpID, false) diff --git a/fission/src/systems/World.ts b/fission/src/systems/World.ts index 9bebeb8c38..24e8c8fa85 100644 --- a/fission/src/systems/World.ts +++ b/fission/src/systems/World.ts @@ -14,7 +14,6 @@ class World { private static _physicsSystem: PhysicsSystem private static _simulationSystem: SimulationSystem private static _inputSystem: InputSystem - // private static _scoringSystem: ScoringSystem public static get isAlive() { return World._isAlive @@ -32,9 +31,6 @@ class World { public static get InputSystem() { return World._inputSystem } - // public static get ScoringSystem() { - // return World._scoringSystem - // } public static InitWorld() { if (World._isAlive) return @@ -46,7 +42,6 @@ class World { World._physicsSystem = new PhysicsSystem() World._simulationSystem = new SimulationSystem() World._inputSystem = new InputSystem() - // World._scoringSystem = new ScoringSystem() } public static DestroyWorld() { @@ -58,7 +53,6 @@ class World { World._sceneRenderer.Destroy() World._simulationSystem.Destroy() World._inputSystem.Destroy() - // World._scoringSystem.Destroy() } public static UpdateWorld() { @@ -67,7 +61,6 @@ class World { World._physicsSystem.Update(deltaT) World._inputSystem.Update(deltaT) World._sceneRenderer.Update(deltaT) - // World._scoringSystem.Update(deltaT) } } From aff8e03a836453f36a8ad3faf82da601689f529e Mon Sep 17 00:00:00 2001 From: a-crowell Date: Fri, 19 Jul 2024 01:01:18 -0700 Subject: [PATCH 24/39] Clean up --- fission/src/mirabuf/MirabufParser.ts | 4 +- fission/src/systems/World.ts | 1 - fission/src/systems/physics/PhysicsSystem.ts | 12 ++- fission/src/systems/scoring/ScoringSystem.ts | 74 ------------------- .../configuring/scoring/ZoneConfigPanel.tsx | 1 - 5 files changed, 6 insertions(+), 86 deletions(-) delete mode 100644 fission/src/systems/scoring/ScoringSystem.ts diff --git a/fission/src/mirabuf/MirabufParser.ts b/fission/src/mirabuf/MirabufParser.ts index 5303d03120..7dab62c4bf 100644 --- a/fission/src/mirabuf/MirabufParser.ts +++ b/fission/src/mirabuf/MirabufParser.ts @@ -79,9 +79,7 @@ class MirabufParser { this.GenerateTreeValues() this.LoadGlobalTransforms() - - console.log(assembly) - + // eslint-disable-next-line @typescript-eslint/no-this-alias const that = this diff --git a/fission/src/systems/World.ts b/fission/src/systems/World.ts index 24e8c8fa85..7470618dc8 100644 --- a/fission/src/systems/World.ts +++ b/fission/src/systems/World.ts @@ -4,7 +4,6 @@ import PhysicsSystem from "./physics/PhysicsSystem" import SceneRenderer from "./scene/SceneRenderer" import SimulationSystem from "./simulation/SimulationSystem" import InputSystem from "./input/InputSystem" -// import ScoringSystem from "./scoring/ScoringSystem" class World { private static _isAlive: boolean = false diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index f67b86a602..ca42b63625 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -16,8 +16,6 @@ import MirabufParser, { GAMEPIECE_SUFFIX, GROUNDED_JOINT_ID, RigidNodeReadOnly } import WorldSystem from "../WorldSystem" import Mechanism from "./Mechanism" import { OnContactAddedEvent, CurrentContactData, OnContactPersistedEvent, OnContactRemovedEvent, OnContactValidateEvent, OnContactValidateData, PhysicsEvent } from "./ContactEvents" -import World from "../World" -import Queue from "@/util/Queue" export type JoltBodyIndexAndSequence = number @@ -191,6 +189,10 @@ class PhysicsSystem extends WorldSystem { * @param bodyId */ public EnablePhysicsForBody(bodyId: Jolt.BodyID) { + if (!this.IsBodyAdded(bodyId)) { + return + } + this._joltBodyInterface.ActivateBody(bodyId) this.GetBody(bodyId).SetIsSensor(false) } @@ -213,8 +215,7 @@ class PhysicsSystem extends WorldSystem { halfExtents: THREE.Vector3, mass: number | undefined, position: THREE.Vector3 | undefined, - rotation: THREE.Euler | THREE.Quaternion | undefined, - isSensor: boolean = false + rotation: THREE.Euler | THREE.Quaternion | undefined ) { const size = ThreeVector3_JoltVec3(halfExtents) const shape = new JOLT.BoxShape(size, 0.1) @@ -232,9 +233,6 @@ class PhysicsSystem extends WorldSystem { if (mass) { creationSettings.mMassPropertiesOverride.mMass = mass } - if (isSensor) { - creationSettings.mIsSensor = isSensor - } const body = this._joltBodyInterface.CreateBody(creationSettings) JOLT.destroy(pos) JOLT.destroy(rot) diff --git a/fission/src/systems/scoring/ScoringSystem.ts b/fission/src/systems/scoring/ScoringSystem.ts deleted file mode 100644 index 9f637a78aa..0000000000 --- a/fission/src/systems/scoring/ScoringSystem.ts +++ /dev/null @@ -1,74 +0,0 @@ -// import * as THREE from "three"; -// import World from "../World"; -// import WorldSystem from "../WorldSystem"; -// import JOLT from "@/util/loading/JoltSyncLoader"; -// import Jolt from "@barclah/jolt-physics"; -// import MirabufSceneObject, { RigidNodeAssociate } from "@/mirabuf/MirabufSceneObject"; -// import { OnContactAddedEvent } from "../physics/ContactEvents"; -// import { FieldPreferencesKey } from "../preferences/PreferenceTypes"; - -// class ScoringSystem extends WorldSystem { -// private points = 0 - -// constructor() { -// super() - -// // // Create and render a zone sensor -// // const geometry = new THREE.BoxGeometry( 1, 1, 1 ); -// // const material = new THREE.MeshBasicMaterial( { color: 0x0000ff } ); -// // const cube = new THREE.Mesh( geometry, material ); -// // World.SceneRenderer.scene.add( cube ); - -// // const zone = World.PhysicsSystem.CreateBox( -// // new THREE.Vector3(0.5, 0.5, 0.5), -// // undefined, -// // undefined, -// // undefined, -// // true -// // ) - -// // World.PhysicsSystem.JoltBodyInterface.AddBody(zone.GetID(), JOLT.EActivation_Activate) - -// // const field = ([...World.SceneRenderer.sceneObjects.entries()][0][1] as MirabufSceneObject).fieldPreferences?.scoringZones[0] - -// // // When zone collides with gamepiece, adds point -// // const onContactAdded = (event: OnContactAddedEvent) => { -// // const body1 = event.message.body1 -// // const body2 = event.message.body2 - -// // if (body1.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { -// // this.ZoneCollision(body2) -// // } else if (body2.GetIndexAndSequenceNumber() == zone.GetID().GetIndexAndSequenceNumber()) { -// // this.ZoneCollision(body1) -// // } -// // } - -// // OnContactAddedEvent.AddListener(onContactAdded) - - -// // ContactListenerTests -// // OnContactPersistedEvent.AddListener((event: OnContactPersistedEvent) => console.log(`persisted: ${event.message.body1.GetIndexAndSequenceNumber()}`)) -// // OnContactRemovedEvent.AddListener((event: OnContactRemovedEvent) => console.log(`removed: ${event.message.GetSubShapeID1()}`)) -// // OnContactValidateEvent.AddListener((event: OnContactValidateEvent) => console.log(`validate: ${event.message.body1.GetID().GetIndexAndSequenceNumber()}`)) -// } - -// public Update(_: number): void { - -// } - -// public Destroy(): void { - -// } - -// private ZoneCollision(gpID: Jolt.BodyID) { -// console.log(`Scoring zone collided with ${gpID.GetIndex()}`) - -// const associate = World.PhysicsSystem.GetBodyAssociation(gpID) -// if (associate?.isGamePiece) { -// this.points++ -// console.log(`points ${this.points}`) -// } -// } -// } - -// export default ScoringSystem \ No newline at end of file diff --git a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx index 63b83b80d6..b0a3226278 100644 --- a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx @@ -163,7 +163,6 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side const rotation = new THREE.Quaternion(0, 0, 0, 1) const scale = new THREE.Vector3(1, 1, 1) gizmoTransformation.decompose(translation, rotation, scale) - // console.log(`config trans: ${translation.toArray()} ${rotation.toArray()} ${scale.toArray()}`) gizmo.mesh.position.set(translation.x, translation.y, translation.z) From b4c074a91ee3ac835047a9eb8d90da7fddae0dee Mon Sep 17 00:00:00 2001 From: a-crowell Date: Fri, 19 Jul 2024 12:52:48 -0700 Subject: [PATCH 25/39] Persistent scoring --- fission/src/mirabuf/EjectableSceneObject.ts | 13 +++++ fission/src/mirabuf/ScoringZoneSceneObject.ts | 47 ++++++++++++------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/fission/src/mirabuf/EjectableSceneObject.ts b/fission/src/mirabuf/EjectableSceneObject.ts index 5b054d783b..0e07511fec 100644 --- a/fission/src/mirabuf/EjectableSceneObject.ts +++ b/fission/src/mirabuf/EjectableSceneObject.ts @@ -10,6 +10,7 @@ import { ThreeVector3_JoltVec3, } from "@/util/TypeConversions" import * as THREE from "three" +import ScoringZoneSceneObject from "./ScoringZoneSceneObject" class EjectableSceneObject extends SceneObject { private _parentAssembly: MirabufSceneObject @@ -47,6 +48,18 @@ class EjectableSceneObject extends SceneObject { World.PhysicsSystem.DisablePhysicsForBody(this._gamePieceBodyId) + const zones = [...World.SceneRenderer.sceneObjects.entries()] + .filter(x => { + const y = x[1] instanceof ScoringZoneSceneObject + return y + }) + .map(x => x[1]) as ScoringZoneSceneObject[] + + zones.forEach(x => { + if (this._gamePieceBodyId) + ScoringZoneSceneObject.RemoveGamepiece(x, this._gamePieceBodyId) + }) + console.debug("Ejectable created successfully!") } } diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index b13d5bc389..731d265fee 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -9,8 +9,6 @@ import SceneObject from "@/systems/scene/SceneObject" import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" import SimulationSystem from "@/systems/simulation/SimulationSystem" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" -import EjectableSceneObject from "./EjectableSceneObject" - class ScoringZoneSceneObject extends SceneObject { //Official FIRST hex @@ -44,6 +42,13 @@ class ScoringZoneSceneObject extends SceneObject { private _collision?: (event: OnContactAddedEvent) => void private _collisionRemoved?: (event: OnContactRemovedEvent) => void + private _gpContacted: Jolt.BodyID[] = [] + // private _gpContacting: Jolt.BodyID[] = [] + + public get gpContacted() { + return this._gpContacted + } + public constructor(parentAssembly: MirabufSceneObject, index: number, render?: boolean) { super() @@ -161,7 +166,9 @@ class ScoringZoneSceneObject extends SceneObject { const shape = shapeSettings.Create() World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate); - + // console.log(`length ${this._gpContacted.length}`) + // this._gpContacted.forEach(x => + // console.log(`gp ${x.GetIndex()}`)) } else { console.debug("Failed to update scoring zone") } @@ -187,6 +194,8 @@ class ScoringZoneSceneObject extends SceneObject { private ZoneCollision(gpID: Jolt.BodyID) { const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece && this._prefs) { + console.log(`Adding ${gpID.GetIndex()}`) + this._gpContacted.push(gpID) if (this._prefs.alliance == "red") { SimulationSystem.redScore += this._prefs.points } else { @@ -202,21 +211,14 @@ class ScoringZoneSceneObject extends SceneObject { const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { - this.RemoveScore() - } else { - const ejectables = [...World.SceneRenderer.sceneObjects.entries()] - .filter(x => { - const y = x[1] instanceof EjectableSceneObject - return y - }) - .map(x => x[1]) as EjectableSceneObject[] - // console.log(`eject ${ejectables.length}`) - - ejectables.forEach(x => { - if (x.parentBodyId == gpID) { - this.RemoveScore() - } + console.log(`Removing ${gpID.GetIndex()}`) + const temp = this._gpContacted.filter(x => { + return x.GetIndexAndSequenceNumber() != gpID.GetIndexAndSequenceNumber() }) + if (this._gpContacted != temp) { + this._gpContacted = temp + this.RemoveScore() + } } } @@ -231,6 +233,17 @@ class ScoringZoneSceneObject extends SceneObject { } console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) } + + public static RemoveGamepiece(zone: ScoringZoneSceneObject, gpID: Jolt.BodyID) { + console.log(`Removing ${gpID.GetIndex()} from ${zone.id}`) + const temp = zone._gpContacted.filter(x => { + return x.GetIndexAndSequenceNumber() != gpID.GetIndexAndSequenceNumber() + }) + if (zone._gpContacted != temp) { + zone._gpContacted = temp + zone.RemoveScore() + } + } } export default ScoringZoneSceneObject \ No newline at end of file From 350f8e0b58738a009400cb2b0cf65f033f0b659f Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 22 Jul 2024 12:19:50 -0700 Subject: [PATCH 26/39] Scoreboard --- fission/src/Synthesis.tsx | 1 + fission/src/mirabuf/ScoringZoneSceneObject.ts | 36 +++++++++++++++++-- fission/src/ui/components/MainHUD.tsx | 11 ++---- .../ui/panels/information/ScoreboardPanel.tsx | 24 +++++++++---- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index 1e34ac2805..4cfcb40fb4 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -243,6 +243,7 @@ const initialPanels: ReactElement[] = [ , , , + , ] export default Synthesis diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index 731d265fee..a9277a1ca5 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -43,7 +43,6 @@ class ScoringZoneSceneObject extends SceneObject { private _collisionRemoved?: (event: OnContactRemovedEvent) => void private _gpContacted: Jolt.BodyID[] = [] - // private _gpContacting: Jolt.BodyID[] = [] public get gpContacted() { return this._gpContacted @@ -201,6 +200,8 @@ class ScoringZoneSceneObject extends SceneObject { } else { SimulationSystem.blueScore += this._prefs.points } + const event = new OnScoreChangedEvent(SimulationSystem.redScore, SimulationSystem.blueScore) + event.Dispatch() console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) } } @@ -223,7 +224,7 @@ class ScoringZoneSceneObject extends SceneObject { } private RemoveScore() { - if (this._prefs) + if (this._prefs) { if (this._prefs.alliance == "red") { SimulationSystem.redScore -= this._prefs.points if (SimulationSystem.redScore < 1) SimulationSystem.redScore = 0 @@ -231,7 +232,10 @@ class ScoringZoneSceneObject extends SceneObject { SimulationSystem.blueScore -= this._prefs.points if (SimulationSystem.blueScore < 1) SimulationSystem.blueScore = 0 } - console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) + const event = new OnScoreChangedEvent(SimulationSystem.redScore, SimulationSystem.blueScore) + event.Dispatch() + console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) + } } public static RemoveGamepiece(zone: ScoringZoneSceneObject, gpID: Jolt.BodyID) { @@ -246,4 +250,30 @@ class ScoringZoneSceneObject extends SceneObject { } } +export class OnScoreChangedEvent extends Event { + public static readonly EVENT_KEY = 'OnScoreChangedEvent' + + public red: number + public blue: number + + public constructor(redScore: number, blueScore: number) { + super(OnScoreChangedEvent.EVENT_KEY) + + this.red = redScore + this.blue = blueScore + } + + public Dispatch(): void { + window.dispatchEvent(this) + } + + public static AddListener(func: (e: OnScoreChangedEvent) => void) { + window.addEventListener(OnScoreChangedEvent.EVENT_KEY, func as (e: Event) => void) + } + + public static RemoveListener(func: (e: OnScoreChangedEvent) => void) { + window.removeEventListener(OnScoreChangedEvent.EVENT_KEY, func as (e: Event) => void) + } +} + export default ScoringZoneSceneObject \ No newline at end of file diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 717df814de..30f9ae8faf 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -18,7 +18,7 @@ import World from "@/systems/World" import JOLT from "@/util/loading/JoltSyncLoader" import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" import { Button } from "@mui/base/Button" -import MirabufCachingService, { MiraType } from "@/mirabuf/MirabufLoader" +import MirabufCachingService from "@/mirabuf/MirabufLoader" import Jolt from "@barclah/jolt-physics" import { AiOutlineDoubleRight } from "react-icons/ai" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" @@ -106,6 +106,7 @@ const MainHUD: React.FC = () => { /> } onClick={() => openModal("settings")} /> } onClick={() => openModal("view")} /> + } onClick={() => openPanel("scoreboard")} /> } @@ -159,14 +160,6 @@ const MainHUD: React.FC = () => { onClick={() => openPanel("driver-station")} /> {/* MiraMap and OPFS Temp Buttons */} - } - onClick={() => { - console.log(MirabufCachingService.GetCacheMap(MiraType.ROBOT)) - console.log(MirabufCachingService.GetCacheMap(MiraType.FIELD)) - }} - /> } diff --git a/fission/src/ui/panels/information/ScoreboardPanel.tsx b/fission/src/ui/panels/information/ScoreboardPanel.tsx index cefd4785c5..7d2c481bf4 100644 --- a/fission/src/ui/panels/information/ScoreboardPanel.tsx +++ b/fission/src/ui/panels/information/ScoreboardPanel.tsx @@ -2,10 +2,11 @@ import { useCallback, useEffect, useState } from "react" import Label, { LabelSize } from "@/components/Label" import Panel, { PanelPropsImpl } from "@/components/Panel" import Stack, { StackDirection } from "@/components/Stack" +import { OnScoreChangedEvent } from "@/mirabuf/ScoringZoneSceneObject" const ScoreboardPanel: React.FC = ({ panelId, openLocation, sidePadding }) => { - const [redScore] = useState(0) - const [blueScore] = useState(0) + const [redScore, setRedScore] = useState(0) + const [blueScore, setBlueScore] = useState(0) const [initialTime, setInitialTime] = useState(-1) const [startTime, setStartTime] = useState(Date.now()) const [time, setTime] = useState(-1) @@ -20,6 +21,13 @@ const ScoreboardPanel: React.FC = ({ panelId, openLocation, side [setInitialTime, setTime, setStartTime] ) + const onScoreChange = useCallback( + (e: OnScoreChangedEvent) => { + setRedScore(e.red) + setBlueScore(e.blue) + }, [setRedScore, setBlueScore]) + + useEffect(() => { const interval: NodeJS.Timeout = setInterval(() => { const elapsed = Math.round((Date.now() - startTime) / 1_000) @@ -33,8 +41,12 @@ const ScoreboardPanel: React.FC = ({ panelId, openLocation, side }, [initialTime, time, startTime]) useEffect(() => { - if (initialTime == -1) startTimer(15) - }, [initialTime, startTimer]) + OnScoreChangedEvent.AddListener(onScoreChange) + }) + + // useEffect(() => { + // if (initialTime == -1) startTimer(15) + // }, [initialTime, startTimer]) return ( = ({ panelId, openLocation, side acceptEnabled={false} contentClassName="mx-0 w-min" > - {time >= 0 && ( + {/* {time >= 0 && (
- )} + )} */}
From d18763400d2dc38b34407c45ac7f0407c7cd0958 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 22 Jul 2024 12:32:21 -0700 Subject: [PATCH 27/39] Persistent points bug fix --- fission/src/mirabuf/ScoringZoneSceneObject.ts | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index a9277a1ca5..d5a9674696 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -115,22 +115,24 @@ class ScoringZoneSceneObject extends SceneObject { this.ZoneCollision(body1) } } + OnContactAddedEvent.AddListener(this._collision) + - this._collisionRemoved = (event: OnContactRemovedEvent) => { - if (this._prefs?.persistentPoints) { - const body1 = event.message.GetBody1ID() - const body2 = event.message.GetBody2ID() + if (this._prefs.persistentPoints) { + this._collisionRemoved = (event: OnContactRemovedEvent) => { + if (this._prefs?.persistentPoints) { + const body1 = event.message.GetBody1ID() + const body2 = event.message.GetBody2ID() - if (body1.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { - this.ZoneCollisionRemoved(body2) - } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { - this.ZoneCollisionRemoved(body1) + if (body1.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollisionRemoved(body2) + } else if (body2.GetIndexAndSequenceNumber() == this._joltBodyId?.GetIndexAndSequenceNumber()) { + this.ZoneCollisionRemoved(body1) + } } } + OnContactRemovedEvent.AddListener(this._collisionRemoved) } - - OnContactAddedEvent.AddListener(this._collision) - OnContactRemovedEvent.AddListener(this._collisionRemoved) console.debug("Scoring zone created successfully") } @@ -194,7 +196,7 @@ class ScoringZoneSceneObject extends SceneObject { const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece && this._prefs) { console.log(`Adding ${gpID.GetIndex()}`) - this._gpContacted.push(gpID) + if (this._prefs.persistentPoints) this._gpContacted.push(gpID) if (this._prefs.alliance == "red") { SimulationSystem.redScore += this._prefs.points } else { @@ -208,7 +210,7 @@ class ScoringZoneSceneObject extends SceneObject { // TODO: Add handling for when the ejectable carries the gamepiece out private ZoneCollisionRemoved(gpID: Jolt.BodyID) { - // console.log(`Scoring zone ${gpID.GetIndex()} removed from ${this._joltBodyId?.GetIndex()}`) + console.debug(`Scoring zone ${gpID.GetIndex()} removed from ${this._joltBodyId?.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { @@ -239,13 +241,15 @@ class ScoringZoneSceneObject extends SceneObject { } public static RemoveGamepiece(zone: ScoringZoneSceneObject, gpID: Jolt.BodyID) { - console.log(`Removing ${gpID.GetIndex()} from ${zone.id}`) - const temp = zone._gpContacted.filter(x => { - return x.GetIndexAndSequenceNumber() != gpID.GetIndexAndSequenceNumber() - }) - if (zone._gpContacted != temp) { - zone._gpContacted = temp - zone.RemoveScore() + if (zone._prefs && zone._prefs.persistentPoints) { + console.debug(`Removing ${gpID.GetIndex()} from ${zone.id}`) + const temp = zone._gpContacted.filter(x => { + return x.GetIndexAndSequenceNumber() != gpID.GetIndexAndSequenceNumber() + }) + if (zone._gpContacted != temp) { + zone._gpContacted = temp + zone.RemoveScore() + } } } } From b86386a0b9967054f9ffcee90b7504b4eb7a0c0a Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 22 Jul 2024 12:35:43 -0700 Subject: [PATCH 28/39] Scoreboard on start up --- fission/src/Synthesis.tsx | 2 +- fission/src/ui/components/MainHUD.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index 4cfcb40fb4..cf1d926948 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -172,6 +172,7 @@ function Synthesis() { + {panelElements.length > 0 && panelElements} {modalElement && (
@@ -243,7 +244,6 @@ const initialPanels: ReactElement[] = [ , , , - , ] export default Synthesis diff --git a/fission/src/ui/components/MainHUD.tsx b/fission/src/ui/components/MainHUD.tsx index 30f9ae8faf..75f9a35999 100644 --- a/fission/src/ui/components/MainHUD.tsx +++ b/fission/src/ui/components/MainHUD.tsx @@ -106,7 +106,6 @@ const MainHUD: React.FC = () => { /> } onClick={() => openModal("settings")} /> } onClick={() => openModal("view")} /> - } onClick={() => openPanel("scoreboard")} /> } From 450560ffa1f1fa2228562ec230751c8811b7683d Mon Sep 17 00:00:00 2001 From: a-crowell Date: Mon, 22 Jul 2024 15:28:13 -0700 Subject: [PATCH 29/39] Refactoring and documentation --- fission/src/Synthesis.tsx | 1 - fission/src/mirabuf/EjectableSceneObject.ts | 2 + .../src/mirabuf/IntakeSensorSceneObject.ts | 3 +- fission/src/mirabuf/MirabufParser.ts | 2 +- fission/src/mirabuf/MirabufSceneObject.ts | 11 +-- fission/src/mirabuf/ScoringZoneSceneObject.ts | 75 +++++++++---------- fission/src/systems/physics/PhysicsSystem.ts | 20 ++--- .../systems/preferences/PreferencesSystem.ts | 2 +- .../configuring/scoring/ZoneConfigPanel.tsx | 1 - 9 files changed, 45 insertions(+), 72 deletions(-) diff --git a/fission/src/Synthesis.tsx b/fission/src/Synthesis.tsx index cf1d926948..5bb017b528 100644 --- a/fission/src/Synthesis.tsx +++ b/fission/src/Synthesis.tsx @@ -104,7 +104,6 @@ function Synthesis() { .catch(console.error) const miraAssembly = await MirabufCachingService.Get(info!.id, MiraType.FIELD) - await (async () => { if (!miraAssembly || !(miraAssembly instanceof mirabuf.Assembly)) { return diff --git a/fission/src/mirabuf/EjectableSceneObject.ts b/fission/src/mirabuf/EjectableSceneObject.ts index 0e07511fec..ceb715ca70 100644 --- a/fission/src/mirabuf/EjectableSceneObject.ts +++ b/fission/src/mirabuf/EjectableSceneObject.ts @@ -48,6 +48,8 @@ class EjectableSceneObject extends SceneObject { World.PhysicsSystem.DisablePhysicsForBody(this._gamePieceBodyId) + // Checks if the gamepiece comes from a zone for persistent point score updates + // because gamepieces removed by intake are not detected in the collision listener const zones = [...World.SceneRenderer.sceneObjects.entries()] .filter(x => { const y = x[1] instanceof ScoringZoneSceneObject diff --git a/fission/src/mirabuf/IntakeSensorSceneObject.ts b/fission/src/mirabuf/IntakeSensorSceneObject.ts index 7e0eff8345..fb9d2cbb43 100644 --- a/fission/src/mirabuf/IntakeSensorSceneObject.ts +++ b/fission/src/mirabuf/IntakeSensorSceneObject.ts @@ -94,7 +94,7 @@ class IntakeSensorSceneObject extends SceneObject { } public Dispose(): void { - console.log("Destroying intake sensor") + console.debug("Destroying intake sensor") if (this._joltBodyId) { World.PhysicsSystem.DestroyBodyIds(this._joltBodyId) @@ -110,7 +110,6 @@ class IntakeSensorSceneObject extends SceneObject { } private IntakeCollision(gpID: Jolt.BodyID) { - // console.log(`Intake collided with ${gpID.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { this._parentAssembly.SetEjectable(gpID, false) diff --git a/fission/src/mirabuf/MirabufParser.ts b/fission/src/mirabuf/MirabufParser.ts index 7dab62c4bf..8565a00335 100644 --- a/fission/src/mirabuf/MirabufParser.ts +++ b/fission/src/mirabuf/MirabufParser.ts @@ -79,7 +79,7 @@ class MirabufParser { this.GenerateTreeValues() this.LoadGlobalTransforms() - + // eslint-disable-next-line @typescript-eslint/no-this-alias const that = this diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index 60d0fc89f3..de8912837c 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -13,7 +13,7 @@ import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain" import InputSystem from "@/systems/input/InputSystem" import TransformGizmos from "@/ui/components/TransformGizmos" import { EjectorPreferences, FieldPreferences, IntakePreferences, ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" -import PreferencesSystem, { PreferenceEvent } from "@/systems/preferences/PreferencesSystem" +import PreferencesSystem from "@/systems/preferences/PreferencesSystem" import { MiraType } from "./MirabufLoader" import IntakeSensorSceneObject from "./IntakeSensorSceneObject" import EjectableSceneObject from "./EjectableSceneObject" @@ -141,15 +141,6 @@ class MirabufSceneObject extends SceneObject { this.UpdateIntakeSensor() this.UpdateScoringZones() - - // Purely because mesh will not properly switch to more opaque material if the array changes or is formed while RenderScoringZones = false - PreferencesSystem.addEventListener((event: PreferenceEvent) => { - if (event.prefName == "RenderScoringZones") { - if (event.prefValue) { - this.UpdateScoringZones(event.prefValue as boolean) - } - } - }) } public Update(): void { diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index d5a9674696..c250e0e87c 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -63,48 +63,47 @@ class ScoringZoneSceneObject extends SceneObject { this._parentBodyId = this._parentAssembly.mechanism.nodeToBody.get(this._prefs.parentNode ?? this._parentAssembly.rootNodeId) if (this._parentBodyId) { - - this._deltaTransformation = Array_ThreeMatrix4(this._prefs.deltaTransformation) - + // Create a default sensor this._joltBodyId = World.PhysicsSystem.CreateSensor( new JOLT.BoxShapeSettings( new JOLT.Vec3(1,1,1) ) ) - if (!this._joltBodyId) { console.log("Failed to create scoring zone. No Jolt Body") return } + // Position/rotate/scale sensor to settings + this._deltaTransformation = Array_ThreeMatrix4(this._prefs.deltaTransformation) const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) - const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) + const zoneTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) const translation = new THREE.Vector3(0, 0, 0) const rotation = new THREE.Quaternion(0, 0, 0, 1) const scale = new THREE.Vector3(1, 1, 1) - gizmoTransformation.decompose(translation, rotation, scale) - + zoneTransformation.decompose(translation, rotation, scale) + + World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) + World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) + const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) + const shape = shapeSettings.Create() + World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) + + // Mesh for the user to visualize sensor this._mesh = World.SceneRenderer.CreateBox( new JOLT.Vec3(1,1,1), - ScoringZoneSceneObject.blueMaterial + ScoringZoneSceneObject.transparentMaterial ) + World.SceneRenderer.scene.add(this._mesh) if (this._toRender) { this._mesh.position.set(translation.x, translation.y, translation.z) this._mesh.rotation.setFromQuaternion(rotation) this._mesh.scale.set(scale.x, scale.y, scale.z) - - World.SceneRenderer.scene.add(this._mesh) } - World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) - World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) - - const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) - const shape = shapeSettings.Create() - World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) - + // Detect new gamepiece listener this._collision = (event: OnContactAddedEvent) => { const body1 = event.message.body1 const body2 = event.message.body2 @@ -117,7 +116,7 @@ class ScoringZoneSceneObject extends SceneObject { } OnContactAddedEvent.AddListener(this._collision) - + // If persistent, detect gamepiece removed listener if (this._prefs.persistentPoints) { this._collisionRemoved = (event: OnContactRemovedEvent) => { if (this._prefs?.persistentPoints) { @@ -140,8 +139,8 @@ class ScoringZoneSceneObject extends SceneObject { } public Update(): void { - if (this._parentBodyId && this._deltaTransformation && this._joltBodyId && this._mesh && this._prefs) { - this._toRender = PreferencesSystem.getGlobalPreference("RenderScoringZones") + if (this._parentBodyId && this._deltaTransformation && this._joltBodyId&& this._prefs) { + // Update translation, rotation, and scale const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) @@ -149,27 +148,24 @@ class ScoringZoneSceneObject extends SceneObject { const rotation = new THREE.Quaternion(0, 0, 0, 1) const scale = new THREE.Vector3(1, 1, 1) gizmoTransformation.decompose(translation, rotation, scale) - // console.log(`update trans: ${translation.toArray()} ${rotation.toArray()} ${scale.toArray()}`) - if (this._toRender) { - this._mesh.position.set(translation.x, translation.y, translation.z) - this._mesh.rotation.setFromQuaternion(rotation) - this._mesh.scale.set(scale.x, scale.y, scale.z) - this._mesh.material = this._prefs.alliance == "red" ? ScoringZoneSceneObject.redMaterial : ScoringZoneSceneObject.blueMaterial - } else { - this._mesh.material = ScoringZoneSceneObject.transparentMaterial - } - World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) - const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) const shape = shapeSettings.Create() World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate); - // console.log(`length ${this._gpContacted.length}`) - // this._gpContacted.forEach(x => - // console.log(`gp ${x.GetIndex()}`)) + // Mesh for visualization + this._toRender = PreferencesSystem.getGlobalPreference("RenderScoringZones") + if (this._mesh) + if (this._toRender) { + this._mesh.position.set(translation.x, translation.y, translation.z) + this._mesh.rotation.setFromQuaternion(rotation) + this._mesh.scale.set(scale.x, scale.y, scale.z) + this._mesh.material = this._prefs.alliance == "red" ? ScoringZoneSceneObject.redMaterial : ScoringZoneSceneObject.blueMaterial + } else { + this._mesh.material = ScoringZoneSceneObject.transparentMaterial + } } else { console.debug("Failed to update scoring zone") } @@ -180,10 +176,9 @@ class ScoringZoneSceneObject extends SceneObject { if (this._joltBodyId) { World.PhysicsSystem.DestroyBodyIds(this._joltBodyId) - if (this._mesh) { - this._mesh.geometry.dispose() - ;(this._mesh.material as THREE.Material).dispose() + this._mesh.geometry.dispose(); + (this._mesh.material as THREE.Material).dispose() World.SceneRenderer.scene.remove(this._mesh) } } @@ -195,26 +190,24 @@ class ScoringZoneSceneObject extends SceneObject { private ZoneCollision(gpID: Jolt.BodyID) { const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece && this._prefs) { - console.log(`Adding ${gpID.GetIndex()}`) if (this._prefs.persistentPoints) this._gpContacted.push(gpID) + if (this._prefs.alliance == "red") { SimulationSystem.redScore += this._prefs.points } else { SimulationSystem.blueScore += this._prefs.points } + const event = new OnScoreChangedEvent(SimulationSystem.redScore, SimulationSystem.blueScore) event.Dispatch() - console.log(`Red: ${SimulationSystem.redScore} Blue: ${SimulationSystem.blueScore}`) } } - // TODO: Add handling for when the ejectable carries the gamepiece out private ZoneCollisionRemoved(gpID: Jolt.BodyID) { console.debug(`Scoring zone ${gpID.GetIndex()} removed from ${this._joltBodyId?.GetIndex()}`) const associate = World.PhysicsSystem.GetBodyAssociation(gpID) if (associate?.isGamePiece) { - console.log(`Removing ${gpID.GetIndex()}`) const temp = this._gpContacted.filter(x => { return x.GetIndexAndSequenceNumber() != gpID.GetIndexAndSequenceNumber() }) diff --git a/fission/src/systems/physics/PhysicsSystem.ts b/fission/src/systems/physics/PhysicsSystem.ts index ca42b63625..42a097e696 100644 --- a/fission/src/systems/physics/PhysicsSystem.ts +++ b/fission/src/systems/physics/PhysicsSystem.ts @@ -8,7 +8,6 @@ import { _JoltQuat, } from "../../util/TypeConversions" import JOLT from "@/util/loading/JoltSyncLoader" - import Jolt from "@barclah/jolt-physics" import * as THREE from "three" import { mirabuf } from "../../proto/mirabuf" @@ -76,15 +75,6 @@ class PhysicsSystem extends WorldSystem { return this._pauseCounter > 0 } - public get JoltPhysicsSystem() { - return this._joltPhysSystem - } - - public get JoltBodyInterface() { - return this._joltBodyInterface - } - - /** * Creates a PhysicsSystem object. */ @@ -1029,10 +1019,10 @@ class PhysicsSystem extends WorldSystem { * Exposes SetShape method on the _joltBodyInterface * Sets the shape of the body * - * @param id - * @param shape - * @param massProperties - * @param activationMode + * @param id The id of the body + * @param shape The new shape of the body + * @param massProperties The mass properties of the new body + * @param activationMode The activation mode of the new body */ public SetShape(id: Jolt.BodyID, shape: Jolt.Shape, massProperties: boolean, activationMode: Jolt.EActivation): void { if (!this.IsBodyAdded(id)) { @@ -1050,7 +1040,7 @@ class PhysicsSystem extends WorldSystem { /** * Creates and assigns Jolt contact listener that dispatches events. * - * @param physSystem + * @param physSystem The physics system the contact listener will attach to */ private SetUpContactListener(physSystem: Jolt.PhysicsSystem) { const contactListener = new JOLT.ContactListenerJS() diff --git a/fission/src/systems/preferences/PreferencesSystem.ts b/fission/src/systems/preferences/PreferencesSystem.ts index bbe2d4c678..97f02363c1 100644 --- a/fission/src/systems/preferences/PreferencesSystem.ts +++ b/fission/src/systems/preferences/PreferencesSystem.ts @@ -9,7 +9,7 @@ import { RobotPreferencesKey, } from "./PreferenceTypes" -export class PreferenceEvent extends Event { +class PreferenceEvent extends Event { public prefName: GlobalPreference public prefValue: unknown diff --git a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx index b0a3226278..b212e2ae7e 100644 --- a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx @@ -164,7 +164,6 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side const scale = new THREE.Vector3(1, 1, 1) gizmoTransformation.decompose(translation, rotation, scale) - gizmo.mesh.position.set(translation.x, translation.y, translation.z) gizmo.mesh.rotation.setFromQuaternion(rotation) gizmo.mesh.scale.set(scale.x, scale.y, scale.z) From b2a5f58f776df0ae8c4b3a584178d7f95c597019 Mon Sep 17 00:00:00 2001 From: a-crowell Date: Tue, 23 Jul 2024 13:11:48 -0700 Subject: [PATCH 30/39] Simple requested changes --- fission/src/mirabuf/MirabufSceneObject.ts | 2 +- fission/src/mirabuf/ScoringZoneSceneObject.ts | 39 +++++++--------- .../systems/simulation/SimulationSystem.ts | 2 +- .../configuring/scoring/ZoneConfigPanel.tsx | 44 +++++++++++-------- .../ui/panels/information/ScoreboardPanel.tsx | 20 ++++----- fission/src/util/threejs/MeshCreation.ts | 20 +++++++++ 6 files changed, 73 insertions(+), 54 deletions(-) diff --git a/fission/src/mirabuf/MirabufSceneObject.ts b/fission/src/mirabuf/MirabufSceneObject.ts index d52a608352..13b95f4426 100644 --- a/fission/src/mirabuf/MirabufSceneObject.ts +++ b/fission/src/mirabuf/MirabufSceneObject.ts @@ -12,7 +12,7 @@ import Mechanism from "@/systems/physics/Mechanism" import SynthesisBrain from "@/systems/simulation/synthesis_brain/SynthesisBrain" import InputSystem from "@/systems/input/InputSystem" import TransformGizmos from "@/ui/components/TransformGizmos" -import { EjectorPreferences, FieldPreferences, IntakePreferences, ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" +import { EjectorPreferences, FieldPreferences, IntakePreferences } from "@/systems/preferences/PreferenceTypes" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" import { MiraType } from "./MirabufLoader" import IntakeSensorSceneObject from "./IntakeSensorSceneObject" diff --git a/fission/src/mirabuf/ScoringZoneSceneObject.ts b/fission/src/mirabuf/ScoringZoneSceneObject.ts index c250e0e87c..cf8160ab81 100644 --- a/fission/src/mirabuf/ScoringZoneSceneObject.ts +++ b/fission/src/mirabuf/ScoringZoneSceneObject.ts @@ -9,6 +9,7 @@ import SceneObject from "@/systems/scene/SceneObject" import { ScoringZonePreferences } from "@/systems/preferences/PreferenceTypes" import SimulationSystem from "@/systems/simulation/SimulationSystem" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" +import { DeltaFieldTransforms_PhysicalProp } from "@/util/threejs/MeshCreation" class ScoringZoneSceneObject extends SceneObject { //Official FIRST hex @@ -77,16 +78,11 @@ class ScoringZoneSceneObject extends SceneObject { // Position/rotate/scale sensor to settings this._deltaTransformation = Array_ThreeMatrix4(this._prefs.deltaTransformation) const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) - const zoneTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) + const props = DeltaFieldTransforms_PhysicalProp(this._deltaTransformation, fieldTransformation) - const translation = new THREE.Vector3(0, 0, 0) - const rotation = new THREE.Quaternion(0, 0, 0, 1) - const scale = new THREE.Vector3(1, 1, 1) - zoneTransformation.decompose(translation, rotation, scale) - - World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) - World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) - const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) + World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(props.translation)) + World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(props.rotation)) + const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(props.scale.x / 2, props.scale.y / 2, props.scale.z / 2)) const shape = shapeSettings.Create() World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate) @@ -98,9 +94,9 @@ class ScoringZoneSceneObject extends SceneObject { World.SceneRenderer.scene.add(this._mesh) if (this._toRender) { - this._mesh.position.set(translation.x, translation.y, translation.z) - this._mesh.rotation.setFromQuaternion(rotation) - this._mesh.scale.set(scale.x, scale.y, scale.z) + this._mesh.position.set(props.translation.x, props.translation.y, props.translation.z) + this._mesh.rotation.setFromQuaternion(props.rotation) + this._mesh.scale.set(props.scale.x, props.scale.y, props.scale.z) } // Detect new gamepiece listener @@ -142,16 +138,11 @@ class ScoringZoneSceneObject extends SceneObject { if (this._parentBodyId && this._deltaTransformation && this._joltBodyId&& this._prefs) { // Update translation, rotation, and scale const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(this._parentBodyId).GetWorldTransform()) - const gizmoTransformation = this._deltaTransformation.clone().premultiply(fieldTransformation) - - const translation = new THREE.Vector3(0, 0, 0) - const rotation = new THREE.Quaternion(0, 0, 0, 1) - const scale = new THREE.Vector3(1, 1, 1) - gizmoTransformation.decompose(translation, rotation, scale) + const props = DeltaFieldTransforms_PhysicalProp(this._deltaTransformation, fieldTransformation) - World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(translation)) - World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(rotation)) - const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(scale.x / 2, scale.y / 2, scale.z / 2)) + World.PhysicsSystem.SetBodyPosition(this._joltBodyId, ThreeVector3_JoltVec3(props.translation)) + World.PhysicsSystem.SetBodyRotation(this._joltBodyId, ThreeQuaternion_JoltQuat(props.rotation)) + const shapeSettings = new JOLT.BoxShapeSettings(new JOLT.Vec3(props.scale.x / 2, props.scale.y / 2, props.scale.z / 2)) const shape = shapeSettings.Create() World.PhysicsSystem.SetShape(this._joltBodyId, shape.Get(), false, Jolt.EActivation_Activate); @@ -159,9 +150,9 @@ class ScoringZoneSceneObject extends SceneObject { this._toRender = PreferencesSystem.getGlobalPreference("RenderScoringZones") if (this._mesh) if (this._toRender) { - this._mesh.position.set(translation.x, translation.y, translation.z) - this._mesh.rotation.setFromQuaternion(rotation) - this._mesh.scale.set(scale.x, scale.y, scale.z) + this._mesh.position.set(props.translation.x, props.translation.y, props.translation.z) + this._mesh.rotation.setFromQuaternion(props.rotation) + this._mesh.scale.set(props.scale.x, props.scale.y, props.scale.z) this._mesh.material = this._prefs.alliance == "red" ? ScoringZoneSceneObject.redMaterial : ScoringZoneSceneObject.blueMaterial } else { this._mesh.material = ScoringZoneSceneObject.transparentMaterial diff --git a/fission/src/systems/simulation/SimulationSystem.ts b/fission/src/systems/simulation/SimulationSystem.ts index d444fc41f5..59efefc1f5 100644 --- a/fission/src/systems/simulation/SimulationSystem.ts +++ b/fission/src/systems/simulation/SimulationSystem.ts @@ -53,7 +53,7 @@ class SimulationSystem extends WorldSystem { } } - public ResetScores(): void { + public static ResetScores(): void { SimulationSystem.redScore = 0 SimulationSystem.blueScore = 0 } diff --git a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx index b212e2ae7e..2f10815363 100644 --- a/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx +++ b/fission/src/ui/panels/configuring/scoring/ZoneConfigPanel.tsx @@ -19,6 +19,7 @@ import { ToggleButton, ToggleButtonGroup } from "@/ui/components/ToggleButtonGro import { Alliance } from "@/systems/preferences/PreferenceTypes" import { RgbaColor } from "react-colorful" import { RigidNodeId } from "@/mirabuf/MirabufParser" +import { DeltaFieldTransforms_PhysicalProp as DeltaFieldTransforms_VisualProperties } from "@/util/threejs/MeshCreation" /** * Saves ejector configuration to selected field. @@ -93,6 +94,19 @@ function save( } const ZoneConfigPanel: React.FC = ({ panelId, openLocation, sidePadding }) => { + //Official FIRST hex + const redMaterial = new THREE.MeshPhongMaterial({ + color: 0xED1C24, + shininess: 0.0, + opacity: 0.7, + transparent: true, + }) + const blueMaterial = new THREE.MeshPhongMaterial({ + color: 0x0066B3, + shininess: 0.0, + opacity: 0.7, + transparent: true, + }) //0x0000ff const { openPanel, closePanel } = usePanelControlContext() const [name, setName] = useState(SelectedZone.zone.name) @@ -132,13 +146,7 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side const gizmo = new TransformGizmos( new THREE.Mesh( new THREE.BoxGeometry(1, 1, 1), - new THREE.MeshPhongMaterial({ - color: colorToNumber(theme.HighlightHover.color), - shininess: 0.0, - opacity: 0.7, - transparent: true, - }) - /* World.SceneRenderer.CreateToonMaterial(ReactRgbaColor_ThreeColor(theme.HighlightHover.color)) */ + zone.alliance == "blue" ? blueMaterial : redMaterial ) ); @@ -156,17 +164,12 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side /** W = L x R. See save() for math details */ const fieldTransformation = JoltMat44_ThreeMatrix4(World.PhysicsSystem.GetBody(nodeBodyId).GetWorldTransform()) - const gizmoTransformation = deltaTransformation.premultiply(fieldTransformation) + const props = DeltaFieldTransforms_VisualProperties(deltaTransformation, fieldTransformation) - // This step seems useless, but keeps the scale from messing up the rotation - const translation = new THREE.Vector3(0, 0, 0) - const rotation = new THREE.Quaternion(0, 0, 0, 1) - const scale = new THREE.Vector3(1, 1, 1) - gizmoTransformation.decompose(translation, rotation, scale) - gizmo.mesh.position.set(translation.x, translation.y, translation.z) - gizmo.mesh.rotation.setFromQuaternion(rotation) - gizmo.mesh.scale.set(scale.x, scale.y, scale.z) + gizmo.mesh.position.set(props.translation.x, props.translation.y, props.translation.z) + gizmo.mesh.rotation.setFromQuaternion(props.rotation) + gizmo.mesh.scale.set(props.scale.x, props.scale.y, props.scale.z) setTransformGizmo(gizmo) @@ -219,13 +222,18 @@ const ZoneConfigPanel: React.FC = ({ panelId, openLocation, side {/** Set the alliance color */}