Skip to content

Commit

Permalink
some refactor for Selection component
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoecheza committed Nov 12, 2024
1 parent 46b6606 commit 0f42758
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const getContext = () => ({
componentPutOperations: {
[Transform.componentId]: jest.fn()
},
componentDeleteOperations: {
[Transform.componentId]: jest.fn()
},
engine: {
RootEntity: 0 as Entity
}
Expand Down Expand Up @@ -71,7 +74,7 @@ describe('EcsEntity', () => {
const Transform = components.Transform(engine)
entity.deleteComponent(Transform)
expect(entity.usedComponents.size).toBe(0)
expect(mockedContext.componentPutOperations[Transform.componentId]).toBeCalledWith(entity, Transform)
expect(mockedContext.componentDeleteOperations[Transform.componentId]).toBeCalledWith(entity, Transform)
})

it('components and native engine', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ export class EcsEntity extends BABYLON.TransformNode {
}

putComponent(component: ComponentDefinition<unknown>) {
const ctx = this.context.deref()!
const operation = ctx.componentPutOperations[component.componentId]
this.usedComponents.set(component.componentId, component)
this.context.deref()!.componentPutOperations[component.componentId]?.call(null, this, component)
operation?.call(null, this, component)
}

deleteComponent(component: ComponentDefinition<unknown>) {
const ctx = this.context.deref()!
const operation = ctx.componentDeleteOperations[component.componentId]
this.usedComponents.delete(component.componentId)
this.context.deref()!.componentPutOperations[component.componentId]?.call(null, this, component)
operation?.call(null, this, component)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import future from 'fp-future'
import { createEditorComponents } from '../../sdk/components'
import { ComponentOperation } from './component-operations'
import { EcsEntity } from './EcsEntity'
import { putEntitySelectedComponent } from './editorComponents/selection'
import { deleteEntitySelectedComponent, putEntitySelectedComponent } from './editorComponents/selection'
import { putBillboardComponent } from './sdkComponents/billboard'
import { putGltfContainerComponent } from './sdkComponents/gltf-container'
import { putMeshRendererComponent } from './sdkComponents/mesh-renderer'
Expand Down Expand Up @@ -77,6 +77,21 @@ export class SceneContext {
[this.editorComponents.Lock.componentId]: putLockComponent
}

readonly componentDeleteOperations: Record<number, ComponentOperation> = {
[this.Transform.componentId]: putTransformComponent,
[this.MeshRenderer.componentId]: putMeshRendererComponent,
[this.Material.componentId]: putMaterialComponent,
[this.Billboard.componentId]: putBillboardComponent,
[this.GltfContainer.componentId]: putGltfContainerComponent,
[this.TextShape.componentId]: putTextShapeComponent,
[this.NftShape.componentId]: putNftShapeComponent,
[this.VideoPlayer.componentId]: putVideoPlayerComponent,
[this.editorComponents.Selection.componentId]: deleteEntitySelectedComponent,
[this.editorComponents.Scene.componentId]: putSceneComponent,
[this.editorComponents.Hide.componentId]: putHideComponent,
[this.editorComponents.Lock.componentId]: putLockComponent
}

// this future is resolved when the scene is disposed
readonly stopped = future<void>()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentType } from '@dcl/ecs'
import type { ComponentOperation } from '../component-operations'
import { updateGizmoManager } from './selection'
import { setGizmoManager, unsetGizmoManager } from './selection'

export const putHideComponent: ComponentOperation = (entity, component) => {
const container = entity.gltfContainer ?? entity.meshRenderer
Expand All @@ -11,10 +11,10 @@ export const putHideComponent: ComponentOperation = (entity, component) => {
const { value: isHidden } = (component.getOrNull(entity.entityId) as { value: boolean } | null) ?? {}
container.setEnabled(!isHidden)
if (isHidden) {
context.gizmos.unsetEntity()
unsetGizmoManager(entity)
} else {
const selectionValue = context.editorComponents.Selection.getOrNull(entity.entityId)
updateGizmoManager(entity, selectionValue)
if (selectionValue) setGizmoManager(entity, selectionValue)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { ComponentType } from '@dcl/ecs'
import type { ComponentOperation } from '../component-operations'
import { toggleSelection, updateGizmoManager } from './selection'
import { setGizmoManager, unsetGizmoManager } from './selection'

export const putLockComponent: ComponentOperation = (entity, component) => {
if (component.componentType === ComponentType.LastWriteWinElementSet) {
const context = entity.context.deref()!
const { value: isLocked } = (component.getOrNull(entity.entityId) as { value: boolean } | null) ?? {}
entity.setLock(!!isLocked)
if (isLocked) {
toggleSelection(entity, false)
context.gizmos.unsetEntity()
unsetGizmoManager(entity)
} else {
const selectionValue = context.editorComponents.Selection.getOrNull(entity.entityId)
toggleSelection(entity, !!selectionValue)
updateGizmoManager(entity, selectionValue)
if (selectionValue) setGizmoManager(entity, selectionValue)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { AbstractMesh, Color3, Gizmo } from '@babylonjs/core'
import { AbstractMesh, Color3 } from '@babylonjs/core'
import { ComponentType } from '@dcl/ecs'
import { CoreComponents } from '../../../sdk/components'
import { CoreComponents, EditorComponentsTypes } from '../../../sdk/components'
import { EcsEntity } from '../EcsEntity'
import type { ComponentOperation } from '../component-operations'

const highlightedMeshes = new Set<AbstractMesh>()

export const putEntitySelectedComponent: ComponentOperation = (entity, component) => {
if (component.componentType === ComponentType.LastWriteWinElementSet) {
const componentValue = entity.isLocked() ? null : (component.getOrNull(entity.entityId) as { gizmo: number } | null)
toggleSelection(entity, !!componentValue)
updateGizmoManager(entity, componentValue)
if (entity.isLocked()) return deleteEntitySelectedComponent(entity, component)

const componentValue = component.get(entity.entityId) as unknown as EditorComponentsTypes['Selection']
setGizmoManager(entity, componentValue)
}
}

export const deleteEntitySelectedComponent: ComponentOperation = (entity, component) => {
if (component.componentType === ComponentType.LastWriteWinElementSet) {
unsetGizmoManager(entity)
}
}

Expand Down Expand Up @@ -38,26 +45,36 @@ export const toggleSelection = (entity: EcsEntity, value: boolean) => {
}
}

export const updateGizmoManager = (entity: EcsEntity, value: { gizmo: number } | null) => {
export const setGizmoManager = (entity: EcsEntity, value: { gizmo: number }) => {
const context = entity.context.deref()!

const Transform = context.engine.getComponent(CoreComponents.TRANSFORM)

if (!Transform.has(entity.entityId)) return

toggleSelection(entity, true)

const selectedEntities = Array.from(context.engine.getEntitiesWith(context.editorComponents.Selection))
const types = context.gizmos.getGizmoTypes()
const type = types[value?.gizmo || 0]
context.gizmos.setGizmoType(type)

for (const [_entity] of selectedEntities) {
if (entity.entityId === _entity && Transform.has(_entity)) {
context.gizmos.setEntity(entity)
const types = context.gizmos.getGizmoTypes()
const type = types[value?.gizmo || 0]
context.gizmos.setGizmoType(type)
return
}
if (selectedEntities.length === 1) {
context.gizmos.setEntity(entity)
} else if (selectedEntities.length > 1) {
context.gizmos.repositionGizmoOnCentroid()
}
}

export const unsetGizmoManager = (entity: EcsEntity) => {
const context = entity.context.deref()!
const selectedEntities = Array.from(context.engine.getEntitiesWith(context.editorComponents.Selection))
const currentEntity = context.gizmos.getEntity()

toggleSelection(entity, false)

if (selectedEntities.length === 0) {
if (currentEntity?.entityId === entity.entityId || selectedEntities.length === 0) {
context.gizmos.unsetEntity()
} else {
// TODO: this will also execute when only one entity is selected, it works but it's not optimal...
context.gizmos.repositionGizmoOnCentroid()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { SceneContext } from './SceneContext'
import { PatchedGizmoManager } from './gizmo-patch'
import { ROOT } from '../../sdk/tree'

const GIZMO_DUMMY_NODE = "GIZMO_DUMMY_NODE"
const GIZMO_DUMMY_NODE = 'GIZMO_DUMMY_NODE'

interface GizmoAxis {
xGizmo: IAxisDragGizmo
Expand All @@ -43,17 +43,14 @@ function areQuaternionsEqual(a: DclQuaternion, b: DclQuaternion) {
}

function calculateCenter(positions: Vector3[]): Vector3 {
if (positions.length === 0) throw new Error("No positions provided to calculate center")

const sum = positions.reduce(
(acc, pos) => {
acc.x += pos.x
acc.y += pos.y
acc.z += pos.z
return acc
},
new Vector3(0, 0, 0)
)
if (positions.length === 0) throw new Error('No positions provided to calculate center')

const sum = positions.reduce((acc, pos) => {
acc.x += pos.x
acc.y += pos.y
acc.z += pos.z
return acc
}, new Vector3(0, 0, 0))

return sum.scale(1 / positions.length)
}
Expand Down Expand Up @@ -200,7 +197,7 @@ export function createGizmoManager(context: SceneContext) {
}

// Map to store the original parent of each entity
const originalParents = new Map<Entity, TransformNode | null>();
const originalParents = new Map<Entity, TransformNode | null>()

// Check if a transform node for the gizmo already exists, or create one
function getDummyNode(): TransformNode {
Expand Down Expand Up @@ -375,7 +372,7 @@ export function createGizmoManager(context: SceneContext) {
return isEnabled
},
setEnabled,
setEntity(entity: EcsEntity | null) {
setEntity(entity: EcsEntity | null): void {
if (
entity === lastEntity ||
!isEnabled ||
Expand All @@ -387,8 +384,7 @@ export function createGizmoManager(context: SceneContext) {
}
restoreOriginalParents()
if (areMultipleEntitiesSelected()) {
repositionGizmoOnCentroid()
return
return repositionGizmoOnCentroid()
} else {
gizmoManager.attachToNode(entity)
lastEntity = entity
Expand Down

0 comments on commit 0f42758

Please sign in to comment.