Pārlūkot izejas kodu

Add material selection mode in picker

master
Palash Bansal pirms 11 mēnešiem
vecāks
revīzija
211d62be34
Revīzijas autora e-pasta adrese nav piesaistīta nevienam kontam

+ 2
- 2
plugins/assimpjs/src/AssimpJsPlugin.ts Parādīt failu

return return
} }
const initing = this.init() const initing = this.init()
const selected = this.exportSelected ? this._viewer.getPlugin(PickingPlugin)?.getSelectedObject() : undefined
object = object || selected || this._viewer.scene.modelRoot
const selected = this.exportSelected ? this._viewer.getPlugin(PickingPlugin)?.getSelectedObject<IObject3D>() : undefined
object = object || (selected?.isObject3D ? selected : this._viewer.scene.modelRoot)


// export to glb // export to glb
const blob = await this._viewer.export(object, options) const blob = await this._viewer.export(object, options)

+ 11
- 2
src/plugins/configurator/MaterialConfiguratorBasePlugin.ts Parādīt failu

import {PickingPlugin} from '../interaction/PickingPlugin' import {PickingPlugin} from '../interaction/PickingPlugin'
import {imageBitmapToBase64, makeColorSvgCircle, serialize} from 'ts-browser-helpers' import {imageBitmapToBase64, makeColorSvgCircle, serialize} from 'ts-browser-helpers'
import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'
import {IMaterial, PhysicalMaterial} from '../../core'
import {IMaterial, IObject3D, PhysicalMaterial} from '../../core'
import {MaterialPreviewGenerator} from '../../three' import {MaterialPreviewGenerator} from '../../three'
import {Color} from 'three' import {Color} from 'three'


@serialize() @serialize()
variations: MaterialVariations[] = [] variations: MaterialVariations[] = []


private _selectedMaterial = () => (this._picking?.getSelectedObject()?.material || undefined) as IMaterial | undefined
private _selectedMaterial = () => {
const selected = this._picking?.getSelectedObject()
if (!selected) return undefined
if ((selected as IMaterial).isMaterial) return selected as IMaterial
else {
const mat = ((selected as IObject3D)?.material || undefined) as IMaterial | undefined
if (Array.isArray(mat)) return mat[0]
return mat
}
}
uiConfig: UiObjectConfig = { uiConfig: UiObjectConfig = {
label: 'Material Configurator', label: 'Material Configurator',
type: 'folder', type: 'folder',

+ 3
- 2
src/plugins/configurator/SwitchNodeBasePlugin.ts Parādīt failu

import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'
import {serialize} from 'ts-browser-helpers' import {serialize} from 'ts-browser-helpers'
import {snapObject} from '../../three' import {snapObject} from '../../three'
import {IObject3D} from '../../core'


/** /**
* Switch Node Plugin (Base) * Switch Node Plugin (Base)
@serialize() variations: ObjectSwitchNode[] = [] @serialize() variations: ObjectSwitchNode[] = []


protected _selectedSwitchNode = (): Object3D | undefined => { protected _selectedSwitchNode = (): Object3D | undefined => {
const obj = this._picking?.getSelectedObject() // (?.material || undefined) as IMaterial | undefined
if (!obj) return undefined
const obj = this._picking?.getSelectedObject<IObject3D>() // (?.material || undefined) as IMaterial | undefined
if (!obj?.isObject3D) return undefined
const nodes = this.variations.map(v => v.name) const nodes = this.variations.map(v => v.name)
let found: Object3D | undefined = undefined let found: Object3D | undefined = undefined
obj.traverseAncestors(a => { obj.traverseAncestors(a => {

+ 3
- 2
src/plugins/export/AssetExporterPlugin.ts Parādīt failu

async exportSelected(options?: ExportAssetOptions, download = true) { async exportSelected(options?: ExportAssetOptions, download = true) {
const selected = this._viewer?.getPlugin<PickingPlugin>('PickingPlugin')?.getSelectedObject() as any const selected = this._viewer?.getPlugin<PickingPlugin>('PickingPlugin')?.getSelectedObject() as any
if (!selected) { if (!selected) {
alert('Nothing selected')
this._viewer?.dialog.alert('Export Selected: Nothing selected')
return return
} }
const name = selected.name || 'selected'
const blob = await this._viewer!.assetManager.exporter.exportObject(selected, options ?? this.exportOptions) const blob = await this._viewer!.assetManager.exporter.exportObject(selected, options ?? this.exportOptions)
if (blob && download) await this._viewer?.exportBlob(blob, 'object.' + blob.ext)
if (blob && download) await this._viewer?.exportBlob(blob, name + '.' + blob.ext)
return blob return blob
} }



+ 1
- 1
src/plugins/export/CanvasSnapshotPlugin.ts Parādīt failu

/** /**
* Only for {@link downloadSnapshot} and functions using that * Only for {@link downloadSnapshot} and functions using that
*/ */
@uiConfig()
@uiConfig(undefined, {label: 'Options'})
@serialize() @serialize()
defaultOptions: CanvasSnapshotPluginOptions = { defaultOptions: CanvasSnapshotPluginOptions = {
waitForProgressive: true, waitForProgressive: true,

+ 6
- 5
src/plugins/extras/SimplifyModifierPlugin.ts Parādīt failu



simplifyGeometries(geometry?: ValOrArr<IGeometry>, options?: SimplifyOptions) { simplifyGeometries(geometry?: ValOrArr<IGeometry>, options?: SimplifyOptions) {
if (!geometry) { if (!geometry) {
const selected = this._pickingPlugin?.getSelectedObject()
const selected = this._pickingPlugin?.getSelectedObject<IObject3D>()
if (!selected?.isObject3D) return
const geom: IGeometry[] = [] const geom: IGeometry[] = []
selected?.traverse((o) => { selected?.traverse((o) => {
if (o.geometry && !geom.includes(o.geometry)) geom.push(o.geometry) if (o.geometry && !geom.includes(o.geometry)) geom.push(o.geometry)
disposeOnReplace = false, disposeOnReplace = false,
}: SimplifyOptions = {}): IGeometry|undefined { }: SimplifyOptions = {}): IGeometry|undefined {
if (!geometry) { if (!geometry) {
const selected = this._pickingPlugin?.getSelectedObject()
const selected = this._pickingPlugin?.getSelectedObject<IObject3D>()
geometry = selected?.geometry geometry = selected?.geometry
if (!geometry) return undefined if (!geometry) return undefined
} }
return return
} }
} }
const selected = this._pickingPlugin?.getSelectedObject()
if (!selected) {
await this._viewer.dialog.alert('Simplify: Nothing Selected')
const selected = this._pickingPlugin?.getSelectedObject<IObject3D>()
if (!selected?.isObject3D) {
await this._viewer.dialog.alert('Simplify: No Object Selected')
return return
} }
let doAll = false let doAll = false

+ 83
- 49
src/plugins/interaction/PickingPlugin.ts Parādīt failu

import {EventListener2, Object3D} from 'three' import {EventListener2, Object3D} from 'three'
import {Class, onChange, serialize} from 'ts-browser-helpers' import {Class, onChange, serialize} from 'ts-browser-helpers'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer' import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {BoxSelectionWidget, ObjectPicker, SelectionWidget} from '../../three'
import {bindToValue, BoxSelectionWidget, ObjectPicker, SelectionWidget} from '../../three'
import {IMaterial, IObject3D, IScene, ISceneEventMap} from '../../core' import {IMaterial, IObject3D, IScene, ISceneEventMap} from '../../core'
import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'
import {FrameFadePlugin} from '../pipeline/FrameFadePlugin' import {FrameFadePlugin} from '../pipeline/FrameFadePlugin'
import {ObjectPickerEventMap} from '../../three/utils/ObjectPicker' import {ObjectPickerEventMap} from '../../three/utils/ObjectPicker'
import {CameraViewPlugin} from '../animation/CameraViewPlugin' import {CameraViewPlugin} from '../animation/CameraViewPlugin'


export interface PickingPluginEventMap extends AViewerPluginEventMap{
selectedObjectChanged: {object: IObject3D|null}
hoverObjectChanged: {object: IObject3D|null}
hitObject: {intersects: {selectedObject: IObject3D|null}}
export interface PickingPluginEventMap extends AViewerPluginEventMap, ObjectPickerEventMap{
} }


export class PickingPlugin extends AViewerPluginSync<PickingPluginEventMap> { export class PickingPlugin extends AViewerPluginSync<PickingPluginEventMap> {
this.uiConfig && this.uiConfig.uiRefresh?.() this.uiConfig && this.uiConfig.uiRefresh?.()
} }


@bindToValue({obj: '_picker', key: 'selectionMode'})
selectionMode: 'object' | 'material' = 'object'

@serialize() @serialize()
autoFocus autoFocus


widgetEnabled = true widgetEnabled = true


protected _widgetEnabledChange() { protected _widgetEnabledChange() {
if (this.widgetEnabled && this._picker?.selectedObject)
this._widget?.attach(this._picker.selectedObject)
if (!this._widget) return
if (this.widgetEnabled && (this._picker?.selectedObject as IObject3D)?.isObject3D)
this._widget.attach(this._picker!.selectedObject as IObject3D)
else else
this._widget?.detach()
this._widget.detach()
this.uiConfig?.uiRefresh?.(true) this.uiConfig?.uiRefresh?.(true)
} }


this.dispatchEvent = this.dispatchEvent.bind(this) this.dispatchEvent = this.dispatchEvent.bind(this)
} }


getSelectedObject<T extends IObject3D = IObject3D>(): T|undefined {
getSelectedObject<T extends IObject3D|IMaterial = IObject3D|IMaterial>(): T|undefined {
if (this.isDisabled()) return if (this.isDisabled()) return
return this._picker?.selectedObject as T || undefined return this._picker?.selectedObject as T || undefined
} }


setSelectedObject(object: IObject3D|undefined, focusCamera = false, trackUndo = true) { // todo: listen to object disposed
setSelectedObject(object: IObject3D|IMaterial|undefined, focusCamera = false, trackUndo = true) { // todo: listen to object disposed
const disabled = this.isDisabled() const disabled = this.isDisabled()
if (disabled && !object) return if (disabled && !object) return
if (!this._picker) return if (!this._picker) return
this.autoFocus = false this.autoFocus = false
this._picker.setSelected(object || null, trackUndo) this._picker.setSelected(object || null, trackUndo)
this.autoFocus = t this.autoFocus = t
if (!disabled && object && (t || focusCamera)) this.focusObject(object)
if (!disabled && object && this.selectionMode === 'object' && (t || focusCamera)) this.focusObject(object as IObject3D)
} }


onAdded(viewer: ThreeViewer): void { onAdded(viewer: ThreeViewer): void {
this._picker.addEventListener('selectedObjectChanged', this._selectedObjectChanged) this._picker.addEventListener('selectedObjectChanged', this._selectedObjectChanged)
this._picker.addEventListener('hoverObjectChanged', this._hoverObjectChanged) this._picker.addEventListener('hoverObjectChanged', this._hoverObjectChanged)
this._picker.addEventListener('hitObject', this._onObjectHit) this._picker.addEventListener('hitObject', this._onObjectHit)
this._picker.addEventListener('selectionModeChanged', this._selectionModeChanged)


// on material drop on selected object // on material drop on selected object
// viewer.scene.addEventListener('addSceneObject', async(e) => { // viewer.scene.addEventListener('addSceneObject', async(e) => {
this._picker.removeEventListener('selectedObjectChanged', this._selectedObjectChanged) this._picker.removeEventListener('selectedObjectChanged', this._selectedObjectChanged)
this._picker.removeEventListener('hoverObjectChanged', this._hoverObjectChanged) this._picker.removeEventListener('hoverObjectChanged', this._hoverObjectChanged)
this._picker.removeEventListener('hitObject', this._onObjectHit) this._picker.removeEventListener('hitObject', this._onObjectHit)
this._picker.removeEventListener('selectionModeChanged', this._selectionModeChanged)
this._picker.dispose() this._picker.dispose()
this._picker.undoManager = undefined // because setting above this._picker.undoManager = undefined // because setting above
this._picker = undefined this._picker = undefined
} }


private _checkSelectedInScene() { private _checkSelectedInScene() {
if (this.isDisabled()) return
if (this.isDisabled() || !this._viewer) return
const s = this.getSelectedObject() const s = this.getSelectedObject()
if (!s || !(s as IObject3D).isObject3D) return // ignoring checking for materials in scene
let inScene = false let inScene = false
s?.traverseAncestors((o) => {
if (o === this._viewer?.scene) inScene = true
;(s as IObject3D).traverseAncestors((o) => {
if (inScene || o !== this._viewer!.scene) return
inScene = true
}) })
if (!inScene) this.setSelectedObject(undefined, false, false) if (!inScene) this.setSelectedObject(undefined, false, false)
} }


private _onObjectSelectEvent: EventListener2<'select', ISceneEventMap, IScene> = (e)=>{ private _onObjectSelectEvent: EventListener2<'select', ISceneEventMap, IScene> = (e)=>{
if (e.source === PickingPlugin.PluginType) return if (e.source === PickingPlugin.PluginType) return
if (e.object === undefined && e.value === undefined) console.error('e.object or e.value must be set for picking, can be null to unselect')
if (e.object === undefined && e.value === undefined) console.error('PickingPlugin - Error handling object/material `select` event `e.object` or `e.value` must be set for picking, `value` can be null to unselect')
else this.setSelectedObject(e.object || e.value, this.autoFocus || e.focusCamera, true) else this.setSelectedObject(e.object || e.value, this.autoFocus || e.focusCamera, true)
} }


const ui = this.uiConfig const ui = this.uiConfig
ui.children = [...this._uiConfigChildren] ui.children = [...this._uiConfigChildren]
if (selected) { if (selected) {
ui.children.push(
{
type: 'button',
label: 'Focus',
value: ()=>{
// const selected = this.getSelectedObject()
if (selected.assetType && selected.parentRoot) // todo also check if acceptChildEvents is set on some parent?
selected.dispatchEvent({type: 'select', ui: true, object: selected, bubbleToParent: true, focusCamera: true})
else
this.setSelectedObject(selected, true)
},
},
{
type: 'button',
label: 'Select Parent',
hidden: ()=>!selected.parent,
value: ()=>{
const parent = selected.parent
if (parent) {
if (parent.assetType && parent.parentRoot) // todo also check if acceptChildEvents is set on some parent?
parent.dispatchEvent({type: 'select', ui: true, bubbleToParent: true, object: parent})
if ((selected as IObject3D).isObject3D) {
const obj = (selected as IObject3D)
ui.children.push(
{
type: 'button',
label: 'Focus',
value: () => {
if (!obj.isObject3D) return
// const selected = this.getSelectedObject()
if (selected.assetType && obj.parentRoot) // todo also check if acceptChildEvents is set on some parent?
obj.dispatchEvent({
type: 'select',
ui: true,
object: obj,
bubbleToParent: true,
focusCamera: true,
})
else else
this.setSelectedObject(parent, false)
}
this.setSelectedObject(obj, true)
},
}, },
},
)
{
type: 'button',
label: 'Select Parent',
hidden: () => !obj.parent,
value: () => {
if (!obj.isObject3D) return
const parent = obj.parent
if (parent) {
if (parent.assetType && parent.parentRoot) // todo also check if acceptChildEvents is set on some parent?
parent.dispatchEvent({
type: 'select',
ui: true,
bubbleToParent: true,
object: parent,
})
else
this.setSelectedObject(parent, false)
}
},
},
)
}
let c = selected.uiConfig let c = selected.uiConfig
if (c) ui.children.push(c) if (c) ui.children.push(c)
else { else {
// check materials // check materials
const mats = selected.materials ?? [selected.material as IMaterial]
const mats = (selected as IObject3D).materials ?? [(selected as IObject3D).material as IMaterial]
for (const m of mats) { for (const m of mats) {
c = m?.uiConfig c = m?.uiConfig
if (c) ui.children.push(c) if (c) ui.children.push(c)


const widget = this._widget const widget = this._widget
if (widget && this.widgetEnabled) { if (widget && this.widgetEnabled) {
if (selected) widget.attach(selected)
if ((selected as IObject3D)?.isObject3D) widget.attach((selected as IObject3D))
else widget.detach() else widget.detach()
} }




this._viewer.setDirty() this._viewer.setDirty()


if (this.autoFocus) {
if (this.autoFocus && this.selectionMode === 'object') {
// this._viewer.resetCamera({rootObject: selected, centerOffset: new Vector3(4, 4, 4)}) // this._viewer.resetCamera({rootObject: selected, centerOffset: new Vector3(4, 4, 4)})
this.focusObject(selected)
this.focusObject(selected as IObject3D | undefined)
} }


} }


private _hoverObjectChanged = (e: any) => { private _hoverObjectChanged = (e: any) => {
if (!this._viewer) return
this.dispatchEvent(e) this.dispatchEvent(e)
const selected = this._picker?.hoverObject || undefined const selected = this._picker?.hoverObject || undefined


const widget = this._hoverWidget const widget = this._hoverWidget
if (widget && this.widgetEnabled) { if (widget && this.widgetEnabled) {
if (selected) widget.attach(selected)
if ((selected as IObject3D)?.isObject3D) widget.attach((selected as IObject3D))
else widget.detach() else widget.detach()
} }




this._viewer?.setDirty() this._viewer?.setDirty()


if (this.autoFocusHover) {
if (this.autoFocusHover && this.selectionMode === 'object') {
// this._viewer?.resetCamera({rootObject: selected, centerOffset: new Vector3(4, 4, 4)}) // this._viewer?.resetCamera({rootObject: selected, centerOffset: new Vector3(4, 4, 4)})
this.focusObject(selected)
this.focusObject(selected as IObject3D | undefined)
} }




} }
this.dispatchEvent(e) this.dispatchEvent(e)
} }
private _selectionModeChanged = (e: any)=>{
if (!this._viewer) return
this.dispatchEvent(e)
if (this.isDisabled()) return
this.uiConfig?.uiRefresh?.(true, 'postFrame', 1)
}


public async focusObject(selected?: Object3D) {
this._viewer?.fitToView(selected, 1.25, 1000, 'easeOut')
public async focusObject(selected?: Object3D|null) {
this._viewer?.fitToView(selected ?? undefined, 1.25, 1000, 'easeOut')
} }


private _uiConfigChildren: UiObjectConfig[] = [ private _uiConfigChildren: UiObjectConfig[] = [
property: [this, 'hoverEnabled'], property: [this, 'hoverEnabled'],
onChange: ()=>this.uiConfig.uiRefresh?.(true), // for autoFocusHover onChange: ()=>this.uiConfig.uiRefresh?.(true), // for autoFocusHover
}, },
// {
// label: 'Selection Mode',
// type: 'dropdown',
// children: ['object', 'material'].map(v=>({label: v, value: v})),
// onChange: ()=>this.uiConfig.uiRefresh?.(true),
// },
{ {
label: 'Auto Focus', label: 'Auto Focus',
type: 'checkbox', type: 'checkbox',

+ 2
- 2
src/plugins/interaction/TransformControlsPlugin.ts Parādīt failu

import {PickingPlugin} from './PickingPlugin' import {PickingPlugin} from './PickingPlugin'
import {JSUndoManager, onChange} from 'ts-browser-helpers' import {JSUndoManager, onChange} from 'ts-browser-helpers'
import {TransformControls} from '../../three/controls/TransformControls' import {TransformControls} from '../../three/controls/TransformControls'
import {UnlitLineMaterial, UnlitMaterial} from '../../core'
import {IObject3D, UnlitLineMaterial, UnlitMaterial} from '../../core'
import {Euler, Object3D, Vector3} from 'three' import {Euler, Object3D, Vector3} from 'three'
import type {UndoManagerPlugin} from './UndoManagerPlugin' import type {UndoManagerPlugin} from './UndoManagerPlugin'


this._pickingWidgetDisabled = false this._pickingWidgetDisabled = false
} }
if (this.transformControls) { if (this.transformControls) {
if (enabled && picking.getSelectedObject()) this.transformControls.attach(picking.getSelectedObject()!)
if (enabled && picking.getSelectedObject<IObject3D>()?.isObject3D) this.transformControls.attach(picking.getSelectedObject<IObject3D>()!)
else this.transformControls.detach() else this.transformControls.detach()
} }
this._viewer.setDirty() this._viewer.setDirty()

+ 46
- 18
src/three/utils/ObjectPicker.ts Parādīt failu

import {EventDispatcher, Intersection, Raycaster, Vector2} from 'three' import {EventDispatcher, Intersection, Raycaster, Vector2} from 'three'
import {JSUndoManager, now} from 'ts-browser-helpers'
import {ICamera, IObject3D} from '../../core'
import {JSUndoManager, now, onChangeDispatchEvent} from 'ts-browser-helpers'
import {ICamera, IMaterial, IObject3D} from '../../core'


export interface ObjectPickerEventMap{ export interface ObjectPickerEventMap{
hoverObjectChanged: {object: IObject3D | null}
selectedObjectChanged: {object: IObject3D | null}
hoverObjectChanged: {object: IObject3D | null, material: IMaterial | null, value: IObject3D | IMaterial | null},
selectedObjectChanged: {object: IObject3D | null, material: IMaterial | null, value: IObject3D | IMaterial | null},
hitObject: {time: number, intersects: {selectedObject: IObject3D | null, intersect: Intersection<IObject3D> | null, intersects: Intersection<IObject3D>[]}} hitObject: {time: number, intersects: {selectedObject: IObject3D | null, intersect: Intersection<IObject3D> | null, intersects: Intersection<IObject3D>[]}}
selectionModeChanged: {detail: {key: 'selectionMode', value: 'object' | 'material', oldValue: 'object' | 'material'}}
} }


export class ObjectPicker extends EventDispatcher<ObjectPickerEventMap> { export class ObjectPicker extends EventDispatcher<ObjectPickerEventMap> {
private _firstHit: IObject3D | undefined private _firstHit: IObject3D | undefined


hoverEnabled = false hoverEnabled = false
@onChangeDispatchEvent('selectionModeChanged')
selectionMode: 'object' | 'material' = 'object'

/** /**
* Time threshold for a pointer click event * Time threshold for a pointer click event
*/ */
public selectionCondition: (o: IObject3D) => boolean public selectionCondition: (o: IObject3D) => boolean
public raycaster: Raycaster public raycaster: Raycaster
public mouse: Vector2 public mouse: Vector2
private _selected: IObject3D[]
private _hovering: IObject3D[]
private _selected: IObject3D[] | IMaterial[]
private _hovering: IObject3D[] | IMaterial[]
public cursorStyles: {default: string; down: string} public cursorStyles: {default: string; down: string}
public domElement: HTMLElement public domElement: HTMLElement
constructor(root: IObject3D, domElement: HTMLElement, camera: ICamera, selectionCondition?: (o:IObject3D)=>boolean) { constructor(root: IObject3D, domElement: HTMLElement, camera: ICamera, selectionCondition?: (o:IObject3D)=>boolean) {
} }


dispose() { dispose() {
this.selectedObject = null
this.setSelected(null)
this.hoverObject = null this.hoverObject = null


this.domElement.removeEventListener('pointermove', this._onPointerMove) this.domElement.removeEventListener('pointermove', this._onPointerMove)
this._camera = value this._camera = value
} }


get selectedObject(): IObject3D | null {
get selectedObject(): IObject3D | IMaterial | null {
return this._selected.length > 0 ? this._selected[0] : null return this._selected.length > 0 ? this._selected[0] : null
} }


set selectedObject(object) {
this.setSelected(object)
}
// set selectedObject(object) {
// this.setSelected(object)
// }


setSelected(object: IObject3D|null, record = true) {
setSelected(object: IObject3D | IMaterial | null, record = true) {
if ((object as IObject3D)?.isObject3D && this.selectionMode === 'material' ||
(object as IMaterial)?.isMaterial && this.selectionMode === 'object') {
this.selectionMode = (object as IMaterial)?.isMaterial ? 'material' : 'object'
}
if (!this._selected.length && !object || this._selected.length === 1 && this._selected[0] === object) return if (!this._selected.length && !object || this._selected.length === 1 && this._selected[0] === object) return
const current = [...this._selected] const current = [...this._selected]
this._selected = object ? Array.isArray(object) ? [...object] : [object] : [] this._selected = object ? Array.isArray(object) ? [...object] : [object] : []
this.dispatchEvent({type: 'selectedObjectChanged', object: this.selectedObject})

const obj = this.selectedObject
this.dispatchEvent({
type: 'selectedObjectChanged',
object: (obj as IObject3D)?.isObject3D ? (obj as IObject3D) : null,
material: (obj as IMaterial)?.isMaterial ? (obj as IMaterial) : null,
value: obj,
})

record && this.undoManager?.record({ record && this.undoManager?.record({
undo: () => this.setSelected(current.length ? current[0] : null, false), undo: () => this.setSelected(current.length ? current[0] : null, false),
redo: () => this.setSelected(object, false), redo: () => this.setSelected(object, false),
}) })
} }


get hoverObject(): IObject3D | null {
get hoverObject(): IObject3D | IMaterial | null {
return this._hovering.length > 0 ? this._hovering[0] : null return this._hovering.length > 0 ? this._hovering[0] : null
} }


set hoverObject(object: IObject3D | IObject3D[] | null) {
set hoverObject(object: IObject3D | IObject3D[] | IMaterial | IMaterial[] | null) {
if (!this._hovering.length && !object || this._hovering.length === 1 && this._hovering[0] === object) return if (!this._hovering.length && !object || this._hovering.length === 1 && this._hovering[0] === object) return
this._hovering = object ? Array.isArray(object) ? [...object] : [object] : []
this.dispatchEvent({type: 'hoverObjectChanged', object: this.hoverObject})
this._hovering = (object ? Array.isArray(object) ? [...object] : [object] : []) as (IObject3D[] | IMaterial[])

const obj = this.hoverObject
this.dispatchEvent({
type: 'hoverObjectChanged',
object: (obj as IObject3D)?.isObject3D ? (obj as IObject3D) : null,
material: (obj as IMaterial)?.isMaterial ? (obj as IMaterial) : null,
value: obj,
})
} }


get time() { get time() {
const intersects = this.checkIntersection() const intersects = this.checkIntersection()
if (intersects) this.dispatchEvent({type: 'hitObject', time: this._mouseUpTime, intersects}) if (intersects) this.dispatchEvent({type: 'hitObject', time: this._mouseUpTime, intersects})
else this.dispatchEvent({type: 'hitObject', time: this._mouseUpTime, intersects: {selectedObject: null, intersect: null, intersects: []}}) else this.dispatchEvent({type: 'hitObject', time: this._mouseUpTime, intersects: {selectedObject: null, intersect: null, intersects: []}})
this.selectedObject = intersects?.selectedObject || null

let obj: IObject3D|IMaterial|null = intersects?.selectedObject || null
if (this.selectionMode === 'material' && obj && obj.material) {
obj = Array.isArray(obj.material) ? obj.material[0] : obj.material
}
this.setSelected(obj)
} }


checkIntersection() { checkIntersection() {

Notiek ielāde…
Atcelt
Saglabāt