-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transform Gizmo Refactor #1085
Transform Gizmo Refactor #1085
Changes from 12 commits
e310017
4fa1ccd
faea318
a2b9e63
b2cfa39
8be2b6f
10010b4
bf9c086
0937d76
1b64d2b
6d0bc2f
6f5f2ab
1e9dbcd
9cd80ac
3181c05
ffdf3ff
03a9d3f
980bf10
2f8c826
8f6c6d8
50f1ce3
47b9301
6dbdc35
18b9383
8f4ded3
38495f7
b2b648a
ceaf33f
269d333
b10ccc7
2fc64cc
1177d0d
ec877bf
bcd59b9
306d807
633d20d
710bc8a
fd519b3
e09be3c
7cb3837
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,163 @@ | ||||||
import SceneObject from "./SceneObject" | ||||||
import { TransformControls } from "three/examples/jsm/controls/TransformControls.js" | ||||||
import InputSystem from "../input/InputSystem" | ||||||
import World from "../World" | ||||||
import MirabufSceneObject from "@/mirabuf/MirabufSceneObject" | ||||||
import { PerspectiveCamera } from "three" | ||||||
import { ThreeMatrix4_JoltMat44, ThreeQuaternion_JoltQuat } from "@/util/TypeConversions" | ||||||
|
||||||
export type GizmoMode = "translate" | "rotate" | "scale" | ||||||
|
||||||
class GizmoSceneObject extends SceneObject { | ||||||
private _gizmo: TransformControls | ||||||
private _mesh: THREE.Mesh | ||||||
private _parentObject: MirabufSceneObject | undefined | ||||||
HunterBarclay marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
private _mainCamera: PerspectiveCamera | ||||||
|
||||||
private _size: number | ||||||
|
||||||
public get gizmo() { | ||||||
return this._gizmo | ||||||
} | ||||||
|
||||||
public get mesh() { | ||||||
return this._mesh | ||||||
} | ||||||
|
||||||
public constructor(mesh: THREE.Mesh, mode: GizmoMode, size: number, parentObject?: MirabufSceneObject) { | ||||||
super() | ||||||
|
||||||
this._mesh = mesh | ||||||
this._parentObject = parentObject | ||||||
this._mainCamera = World.SceneRenderer.mainCamera | ||||||
|
||||||
this._size = size | ||||||
|
||||||
this._gizmo = new TransformControls(World.SceneRenderer.mainCamera, World.SceneRenderer.renderer.domElement) | ||||||
this._gizmo.setMode(mode) | ||||||
|
||||||
World.SceneRenderer.RegisterSceneObject(this) | ||||||
} | ||||||
|
||||||
public Setup(): void { | ||||||
// adding the mesh and gizmo to the scene | ||||||
World.SceneRenderer.AddObject(this._mesh) | ||||||
World.SceneRenderer.AddObject(this._gizmo) | ||||||
|
||||||
// forcing the gizmo to rotate and transform with the object | ||||||
this._gizmo.setSpace("local") | ||||||
this._gizmo.attach(this._mesh) | ||||||
|
||||||
this._gizmo.addEventListener("dragging-changed", (event: { target: TransformControls; value: unknown }) => { | ||||||
// disable orbit controls when dragging the transform gizmo | ||||||
const gizmoDragging = World.SceneRenderer.IsAnyGizmoDragging() | ||||||
if (!event.value && !gizmoDragging) { | ||||||
World.SceneRenderer.orbitControls.enabled = true // enable orbit controls when not dragging another transform gizmo | ||||||
} else if (!event.value && gizmoDragging) { | ||||||
World.SceneRenderer.orbitControls.enabled = false // disable orbit controls when dragging another transform gizmo | ||||||
} else { | ||||||
World.SceneRenderer.orbitControls.enabled = !event.value // disable orbit controls when dragging transform gizmo | ||||||
} | ||||||
HunterBarclay marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
if (event.target.mode === "translate") { | ||||||
// disable other gizmos when translating | ||||||
Array.from(World.SceneRenderer.sceneObjects.values()) | ||||||
.filter(obj => obj instanceof GizmoSceneObject) | ||||||
.forEach(obj => { | ||||||
if (obj.gizmo.object === event.target.object && obj.gizmo.mode !== "translate") { | ||||||
obj.gizmo.dragging = false | ||||||
obj.gizmo.enabled = !event.value | ||||||
return | ||||||
} | ||||||
}) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you have the As long as the mirabuf instance id that would be the key in |
||||||
} else if ( | ||||||
event.target.mode === "scale" && | ||||||
(InputSystem.isKeyPressed("ShiftRight") || InputSystem.isKeyPressed("ShiftLeft")) | ||||||
) { | ||||||
// scale uniformly if shift is pressed | ||||||
event.target.axis = "XYZE" | ||||||
} else if (event.target.mode === "rotate") { | ||||||
// scale on all axes | ||||||
Array.from(World.SceneRenderer.sceneObjects.values()) | ||||||
.filter(obj => obj instanceof GizmoSceneObject) | ||||||
.forEach(obj => { | ||||||
if ( | ||||||
obj.gizmo.mode === "scale" && | ||||||
event.target !== obj.gizmo && | ||||||
obj.gizmo.object === event.target.object | ||||||
) { | ||||||
obj.gizmo.dragging = false | ||||||
obj.gizmo.enabled = !event.value | ||||||
return | ||||||
} | ||||||
}) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing here - use the |
||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would a switch be better here? I'm not sure if the if will be optimized, especially since you're checking inputs in one of the conditions. |
||||||
}) | ||||||
|
||||||
if (this._parentObject !== undefined) this._parentObject.DisablePhysics() | ||||||
} | ||||||
public Update(): void { | ||||||
// updating the size of the gizmo based on the distance from the camera | ||||||
const mainCameraFovRadians = (Math.PI * (this._mainCamera.fov * 0.5)) / 180 | ||||||
this._gizmo.setSize( | ||||||
(this._size / this._mainCamera.position.distanceTo(this.gizmo.object!.position)) * | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure object is always going to be non-null? |
||||||
Math.tan(mainCameraFovRadians) * | ||||||
1.9 | ||||||
) | ||||||
|
||||||
// mapping the mesh transformations to the mirabuf object | ||||||
if (this._parentObject !== undefined) { | ||||||
this._parentObject.DisablePhysics() | ||||||
|
||||||
if (this._gizmo.dragging) { | ||||||
this._parentObject.mirabufInstance.parser.rigidNodes.forEach(rn => { | ||||||
World.PhysicsSystem.SetBodyPosition( | ||||||
this._parentObject!.mechanism.GetBodyByNodeId(rn.id)!, | ||||||
ThreeMatrix4_JoltMat44(this._mesh.matrix).GetTranslation() | ||||||
) | ||||||
World.PhysicsSystem.SetBodyRotation( | ||||||
this._parentObject!.mechanism.GetBodyByNodeId(rn.id)!, | ||||||
ThreeQuaternion_JoltQuat(this._mesh.quaternion) | ||||||
) | ||||||
|
||||||
rn.parts.forEach(part => { | ||||||
const partTransform = this._parentObject!.mirabufInstance.parser.globalTransforms.get(part)! | ||||||
.clone() | ||||||
.premultiply(this._mesh.matrix) | ||||||
|
||||||
const meshes = this._parentObject!.mirabufInstance.meshes.get(part) ?? [] | ||||||
meshes.forEach(([batch, id]) => batch.setMatrixAt(id, partTransform)) | ||||||
}) | ||||||
}) | ||||||
} | ||||||
} | ||||||
|
||||||
// creating enter key and escape key event listeners | ||||||
if (InputSystem.isKeyPressed("Enter") && this._parentObject) { | ||||||
// confirming placement of object | ||||||
if (this._parentObject !== undefined) this._parentObject.EnablePhysics() | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I know |
||||||
World.SceneRenderer.RemoveSceneObject(this.id) | ||||||
return | ||||||
} else if (InputSystem.isKeyPressed("Escape") && this._parentObject) { | ||||||
// cancelling the creation of the mirabuf scene object | ||||||
World.SceneRenderer.RemoveSceneObject(this._parentObject.id) | ||||||
World.SceneRenderer.RemoveSceneObject(this.id) | ||||||
return | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should |
||||||
} | ||||||
|
||||||
public Dispose(): void { | ||||||
this._gizmo.detach() | ||||||
if (this._parentObject) this._parentObject.RemoveGizmo() | ||||||
World.SceneRenderer.RemoveObject(this._mesh) | ||||||
World.SceneRenderer.RemoveObject(this._gizmo) | ||||||
} | ||||||
|
||||||
/** changes the mode of the gizmo */ | ||||||
public SetMode(mode: GizmoMode) { | ||||||
this._gizmo.setMode(mode) | ||||||
} | ||||||
} | ||||||
|
||||||
export default GizmoSceneObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we've decided that only once gizmo will exist, this should be some kind of static either in the SceneRenderer or GizmoSceneObject itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can think of a case where we would want more than one gizmo in a scene at a time. For instance, what about placing more than one robot during the initialization of match mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I think for initial robot placement, we should move away from using the gizmo tool altogether and move towards Luca's placement for bots for match mode in v6 where you can click and place. In which case, gizmo controls should be reserved for fine movement/orientation/scale control.