Files
speckle-server/packages/frontend-2/lib/viewer/composables/setup/selection.ts
T
Kristaps Fabians Geikins f80a7189a0 chore(fe2): upgrade to nuxt 3.8.2 (#1887)
* chore(fe2): upgrade to nuxt 3.8.2

* fix tailwind-theme build

* readme update

* removing storybook from fe2 :(

* fix(fe2): codegen schema url resolution
2023-11-29 10:22:17 +02:00

114 lines
3.9 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import type { SpeckleObject } from '~~/lib/common/helpers/sceneExplorer'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useInjectedViewerState } from '~~/lib/viewer/composables/setup'
import { useCameraUtilities, useSelectionUtilities } from '~~/lib/viewer/composables/ui'
import { useSelectionEvents } from '~~/lib/viewer/composables/viewer'
function useCollectSelection() {
const {
ui: { selection }
} = useInjectedViewerState()
const selectionCallback: Parameters<
typeof useSelectionEvents
>[0]['singleClickCallback'] = (_event, { firstVisibleSelectionHit }) => {
if (!firstVisibleSelectionHit) return (selection.value = null) // reset selection location
selection.value = firstVisibleSelectionHit.point
}
useSelectionEvents({
singleClickCallback: selectionCallback,
doubleClickCallback: selectionCallback
})
}
function useSelectOrZoomOnSelection() {
const state = useInjectedViewerState()
const { clearSelection, addToSelection } = useSelectionUtilities()
const { zoom } = useCameraUtilities()
const mp = useMixpanel()
const logger = useLogger()
const trackAndClearSelection = () => {
clearSelection()
mp.track('Viewer Action', {
type: 'action',
name: 'selection',
action: 'clear',
source: 'viewer'
})
}
useSelectionEvents(
{
singleClickCallback: (args, { firstVisibleSelectionHit }) => {
if (!args) return trackAndClearSelection()
if (args.hits.length === 0) return trackAndClearSelection()
if (!args.multiple) clearSelection() // note we're not tracking selectino clearing here
if (!firstVisibleSelectionHit) return clearSelection()
addToSelection(firstVisibleSelectionHit.object)
// Expands default viewer selection behaviour with a special case in diff mode.
// In diff mode, if we select via a mouse click an object, and that object is
// "modified", we want to select its pair as well.
if (
state.ui.diff.enabled.value &&
state.ui.diff.result.value &&
firstVisibleSelectionHit.object.applicationId
) {
const modifiedObjectPairs = state.ui.diff.result.value.modified
const obj = firstVisibleSelectionHit.object
const pairedItems = modifiedObjectPairs.find(
(item) =>
(item[0].model.raw as SpeckleObject).id === obj.id ||
(item[1].model.raw as SpeckleObject).id === obj.id
)
if (!pairedItems) return
const pair =
(pairedItems[0].model.raw as SpeckleObject).id === obj.id
? (pairedItems[1].model.raw as SpeckleObject)
: (pairedItems[0].model.raw as SpeckleObject)
if (!pair) return
addToSelection(pair)
}
mp.track('Viewer Action', {
type: 'action',
name: 'selection',
action: 'select',
multiple: args.multiple
})
},
doubleClickCallback: (args, { firstVisibleSelectionHit }) => {
if (!args) return zoom()
if (!args.hits) return zoom()
if (args.hits.length === 0) return zoom()
const firstVisHit = firstVisibleSelectionHit
if (!firstVisHit) return clearSelection()
if (state.ui.filters.selectedObjects.value.length !== 0) {
const ids = state.ui.filters.selectedObjects.value.map((o) => o.id as string)
zoom(ids)
} // else somethingn is weird.
else {
logger.warn(
"Got a double click event but there's no selected object in the state - this should be impossible :)"
)
}
mp.track('Viewer Action', {
type: 'action',
name: 'zoom',
source: 'object-double-click'
})
}
},
{ state }
)
}
export function useViewerSelectionEventHandler() {
useCollectSelection()
useSelectOrZoomOnSelection()
}