Skip to content
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

feat: Add planar movement #882

Merged
merged 5 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions packages/@dcl/inspector/src/components/Toolbar/Gizmos/Gizmos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,18 @@ export const Gizmos = withSdk(({ sdk }) => {

const [selection, setSelection] = useComponentValue(entity || ROOT, sdk.components.Selection)

const handlePositionGizmo = useCallback(() => setSelection({ gizmo: GizmoType.POSITION }), [setSelection])
const handleRotationGizmo = useCallback(() => setSelection({ gizmo: GizmoType.ROTATION }), [setSelection])
const handleScaleGizmo = useCallback(() => setSelection({ gizmo: GizmoType.SCALE }), [setSelection])
const handlePositionGizmo = useCallback(
() => setSelection({ gizmo: selection.gizmo !== GizmoType.POSITION ? GizmoType.POSITION : GizmoType.FREE }),
[selection, setSelection]
)
const handleRotationGizmo = useCallback(
() => setSelection({ gizmo: selection.gizmo !== GizmoType.ROTATION ? GizmoType.ROTATION : GizmoType.FREE }),
[selection, setSelection]
)
const handleScaleGizmo = useCallback(
() => setSelection({ gizmo: selection.gizmo !== GizmoType.SCALE ? GizmoType.SCALE : GizmoType.FREE }),
[selection, setSelection]
)

const {
isPositionGizmoWorldAligned,
Expand Down
1 change: 1 addition & 0 deletions packages/@dcl/inspector/src/hooks/editor/useSnap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { GizmoType } from '../../lib/utils/gizmo'
function getSnapValue(gizmo: GizmoType) {
switch (gizmo) {
case GizmoType.POSITION:
case GizmoType.FREE:
return snapManager.getPositionSnap()
case GizmoType.ROTATION:
return Math.round(snapManager.getRotationSnap() * (180 / Math.PI))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,12 @@ describe('GizmoManager', () => {
})
describe('When getting the gizmo types', () => {
it('should return the gizmo types', () => {
expect(gizmos.getGizmoTypes()).toEqual([GizmoType.POSITION, GizmoType.ROTATION, GizmoType.SCALE])
expect(gizmos.getGizmoTypes()).toEqual([
GizmoType.POSITION,
GizmoType.ROTATION,
GizmoType.SCALE,
GizmoType.FREE
])
})
})
describe('When setting the gizmo type', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import mitt from 'mitt'
import { IAxisDragGizmo, PickingInfo, Quaternion, Node } from '@babylonjs/core'
import {
IAxisDragGizmo,
PickingInfo,
Quaternion,
Node,
Vector3,
PointerDragBehavior,
AbstractMesh
} from '@babylonjs/core'
import { Entity, TransformType } from '@dcl/ecs'
import { Vector3 as DclVector3, Quaternion as DclQuaternion } from '@dcl/ecs-math'
import { GizmoType } from '../../utils/gizmo'
Expand Down Expand Up @@ -54,8 +62,12 @@
let isEnabled = true
const parentMapper: Map<Entity, Node> = new Map()

function getSelectedEntities() {
return context.operations.getSelectedEntities()
}

function areMultipleEntitiesSelected() {
return context.operations.getSelectedEntities().length > 1
return getSelectedEntities().length > 1
}

function fixRotationGizmoAlignment(value: TransformType) {
Expand Down Expand Up @@ -142,7 +154,7 @@

// Update entity transform for all the selected entities
if (areMultipleEntitiesSelected()) {
for (const entityId of context.operations.getSelectedEntities()) {
for (const entityId of getSelectedEntities()) {

Check warning on line 157 in packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts#L157

Added line #L157 was not covered by tests
if (entityId === lastEntity.entityId) continue
const entity = context.getEntityOrNull(entityId)!
const transform = getTransform(entity)
Expand All @@ -154,7 +166,7 @@
function initTransform() {
if (lastEntity === null) return
if (areMultipleEntitiesSelected()) {
for (const entityId of context.operations.getSelectedEntities()) {
for (const entityId of getSelectedEntities()) {

Check warning on line 169 in packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts#L169

Added line #L169 was not covered by tests
if (entityId === lastEntity.entityId) continue
const entity = context.getEntityOrNull(entityId)!
parentMapper.set(entityId, entity.parent!)
Expand Down Expand Up @@ -250,6 +262,25 @@
}
})

const meshPointerDragBehavior = new PointerDragBehavior({
dragPlaneNormal: new Vector3(0, 1, 0)
})

context.scene.onPointerDown = function (_e, pickResult) {
if (lastEntity === null || pickResult.pickedMesh === null || !gizmoManager.freeGizmoEnabled) return
const selectedEntities = getSelectedEntities().map((entityId) => context.getEntityOrNull(entityId)!)
if (selectedEntities.some((entity) => pickResult.pickedMesh!.isDescendantOf(entity))) {
initTransform()
meshPointerDragBehavior.attach(lastEntity as unknown as AbstractMesh)
}
}

Check warning on line 276 in packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts#L270-L276

Added lines #L270 - L276 were not covered by tests

context.scene.onPointerUp = function () {
if (lastEntity === null || !gizmoManager.freeGizmoEnabled) return
updateTransform()
meshPointerDragBehavior.detach()
}

Check warning on line 282 in packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/decentraland/gizmo-manager.ts#L279-L282

Added lines #L279 - L282 were not covered by tests

if (canvas) {
canvas.addEventListener('pointerenter', () => {
if (movingNode) {
Expand Down Expand Up @@ -291,12 +322,13 @@
unsetEntity()
},
getGizmoTypes() {
return [GizmoType.POSITION, GizmoType.ROTATION, GizmoType.SCALE] as const
return [GizmoType.POSITION, GizmoType.ROTATION, GizmoType.SCALE, GizmoType.FREE] as const
},
setGizmoType(type: GizmoType) {
gizmoManager.positionGizmoEnabled = type === GizmoType.POSITION
gizmoManager.rotationGizmoEnabled = type === GizmoType.ROTATION
gizmoManager.scaleGizmoEnabled = type === GizmoType.SCALE
gizmoManager.freeGizmoEnabled = type === GizmoType.FREE
events.emit('change')
},
isPositionGizmoWorldAligned,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,20 @@ export class PatchedRotationGizmo extends RotationGizmo {
}

export class PatchedGizmoManager extends GizmoManager {
protected _gizmosEnabled: {
positionGizmo: boolean
rotationGizmo: boolean
scaleGizmo: boolean
boundingBoxGizmo: boolean
freeGizmo: boolean
} = {
positionGizmo: false,
rotationGizmo: false,
scaleGizmo: false,
boundingBoxGizmo: false,
freeGizmo: false
}

set rotationGizmoEnabled(value: boolean) {
if (value) {
if (!this.gizmos.rotationGizmo) {
Expand All @@ -388,4 +402,12 @@ export class PatchedGizmoManager extends GizmoManager {
get rotationGizmoEnabled() {
return this._gizmosEnabled.rotationGizmo
}

set freeGizmoEnabled(value: boolean) {
this._gizmosEnabled.freeGizmo = value
}

get freeGizmoEnabled(): boolean {
return this._gizmosEnabled.freeGizmo
}
}
23 changes: 23 additions & 0 deletions packages/@dcl/inspector/src/lib/babylon/setup/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import { getAncestors, isAncestor, mapNodes } from '../../sdk/nodes'

let isSnapEnabled = snapManager.isEnabled()
let clickStartTimer: ReturnType<typeof setTimeout>
let isDragging = false

export function initKeyboard(canvas: HTMLCanvasElement, scene: BABYLON.Scene) {
canvas.addEventListener('keydown', (e) => {
Expand All @@ -25,6 +27,17 @@
keyState[e.keyCode] = false
})

// When the canvas lost the focus, clear the special keys state
canvas.addEventListener('blur', () => {
keyState[Keys.KEY_SHIFT] = false
keyState[Keys.KEY_CTRL] = false
})

// Event to store the ctrlKey when the canvas has lost the focus
canvas.addEventListener('contextmenu', (e) => {
keyState[Keys.KEY_CTRL] = e.ctrlKey
})

Check warning on line 40 in packages/@dcl/inspector/src/lib/babylon/setup/input.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/setup/input.ts#L30-L40

Added lines #L30 - L40 were not covered by tests
scene.onPointerObservable.add((e) => {
if (e.type === BABYLON.PointerEventTypes.POINTERDOWN) {
const evt = e.event as PointerEvent
Expand Down Expand Up @@ -69,6 +82,10 @@
const entity = mesh && findParentEntity(mesh)

if (entity && pointerEvent === 'pointerDown') {
clickStartTimer = setTimeout(() => {
isDragging = true
}, 150) // 150ms to detect if the user is dragging
} else if (entity && pointerEvent === 'pointerUp' && !isDragging) {

Check warning on line 88 in packages/@dcl/inspector/src/lib/babylon/setup/input.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/setup/input.ts#L85-L88

Added lines #L85 - L88 were not covered by tests
const context = entity.context.deref()!
const { operations, engine, editorComponents } = context
const ancestors = getAncestors(engine, entity.entityId)
Expand All @@ -77,4 +94,10 @@
operations.updateSelectedEntity(entity.entityId, !!keyState[Keys.KEY_CTRL])
void operations.dispatch()
}

// Clear isDragging flag each pointerUp
if (pointerEvent === 'pointerUp') {
clearTimeout(clickStartTimer)
isDragging = false
}

Check warning on line 102 in packages/@dcl/inspector/src/lib/babylon/setup/input.ts

View check run for this annotation

Codecov / codecov/patch

packages/@dcl/inspector/src/lib/babylon/setup/input.ts#L97-L102

Added lines #L97 - L102 were not covered by tests
}
3 changes: 2 additions & 1 deletion packages/@dcl/inspector/src/lib/utils/gizmo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum GizmoType {
POSITION = 0,
ROTATION = 1,
SCALE = 2
SCALE = 2,
FREE = 3
}
Loading