mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
116 lines (106 loc) • 3.96 kB
text/typescript
import { createNestedEffect, createRef } from "@lincode/reactivity"
import { isPositionedItem } from "../../../../api/core/PositionedItem"
import { mouseEvents } from "../../../../api/mouse"
import { onSceneGraphChange } from "../../../../events/onSceneGraphChange"
import { onSelectionRecompute } from "../../../../events/onSelectionRecompute"
import {
emitSelectionTarget,
onSelectionTarget
} from "../../../../events/onSelectionTarget"
import { getEditing } from "../../../../states/useEditing"
import { getEditorMode } from "../../../../states/useEditorMode"
import { getMultipleSelection } from "../../../../states/useMultipleSelection"
import {
pushMultipleSelectionTargets,
getMultipleSelectionTargets,
pullMultipleSelectionTargets,
resetMultipleSelectionTargets
} from "../../../../states/useMultipleSelectionTargets"
import {
getSelectionTarget,
setSelectionTarget
} from "../../../../states/useSelectionTarget"
import { getTransformControlsDragging } from "../../../../states/useTransformControlsDragging"
import pickable from "./pickable"
import selectionCandidates, {
getSelectionCandidates
} from "./selectionCandidates"
export default () => {
const multipleSelection = getMultipleSelection()
const firstMultipleSelection = createRef(true)
createNestedEffect(() => {
!multipleSelection && (firstMultipleSelection.current = true)
}, [multipleSelection])
createNestedEffect(() => {
const mode = getEditorMode()
if (
!getEditing() ||
getTransformControlsDragging() ||
(mode !== "rotate" &&
mode !== "scale" &&
mode !== "select" &&
mode !== "translate")
)
return
getSelectionCandidates()
const handle0 = onSceneGraphChange(() => getSelectionCandidates())
const handle1 = onSelectionRecompute(() => {
getSelectionCandidates()
emitSelectionTarget()
})
const handle2 = mouseEvents.on("click", () => emitSelectionTarget())
let rightClick = false
const handle3 = mouseEvents.on("rightClick", () => {
rightClick = true
queueMicrotask(() => {
if (!rightClick) return
rightClick = false
emitSelectionTarget(undefined, true)
})
})
const handle4 = pickable(
["click", "rightClick"],
selectionCandidates,
(target) => {
emitSelectionTarget(target, rightClick)
rightClick = false
}
)
const handle5 = onSelectionTarget(({ target, rightClick }) => {
if (multipleSelection) {
if (!isPositionedItem(target) || rightClick) return
if (firstMultipleSelection.current) {
const currentTarget = getSelectionTarget()
isPositionedItem(currentTarget) &&
pushMultipleSelectionTargets(currentTarget)
}
firstMultipleSelection.current = false
if (getMultipleSelectionTargets().includes(target))
pullMultipleSelectionTargets(target)
else pushMultipleSelectionTargets(target)
return
}
resetMultipleSelectionTargets()
setSelectionTarget(
rightClick
? target
: target === getSelectionTarget()
? undefined
: target
)
})
return () => {
handle0.cancel()
handle1.cancel()
handle2.cancel()
handle3.cancel()
handle4.cancel()
handle5.cancel()
}
}, [
getEditing,
getTransformControlsDragging,
getEditorMode,
multipleSelection
])
}