mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-05 15:28:29 +08:00
You can now force panning/rotating mode by holding ctrl while clicking and dragging the mouse.
This commit is contained in:
parent
585ce44667
commit
d6751b0151
@ -1,8 +1,11 @@
|
|||||||
package world.phantasmal.web.core.rendering
|
package world.phantasmal.web.core.rendering
|
||||||
|
|
||||||
import org.w3c.dom.HTMLCanvasElement
|
import org.w3c.dom.HTMLCanvasElement
|
||||||
|
import org.w3c.dom.pointerevents.PointerEvent
|
||||||
|
import world.phantasmal.core.disposable.Disposable
|
||||||
import world.phantasmal.core.disposable.TrackedDisposable
|
import world.phantasmal.core.disposable.TrackedDisposable
|
||||||
import world.phantasmal.web.externals.three.*
|
import world.phantasmal.web.externals.three.*
|
||||||
|
import world.phantasmal.webui.dom.disposableListener
|
||||||
import world.phantasmal.webui.obj
|
import world.phantasmal.webui.obj
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
@ -15,7 +18,10 @@ class OrbitalCameraInputManager(
|
|||||||
screenSpacePanning: Boolean,
|
screenSpacePanning: Boolean,
|
||||||
enableRotate: Boolean = true,
|
enableRotate: Boolean = true,
|
||||||
) : TrackedDisposable(), InputManager {
|
) : TrackedDisposable(), InputManager {
|
||||||
private val controls = OrbitControls(camera, canvas)
|
private lateinit var controls: OrbitControls
|
||||||
|
|
||||||
|
@Suppress("JoinDeclarationAndAssignment")
|
||||||
|
private val pointerDownListener: Disposable
|
||||||
|
|
||||||
var enabled: Boolean
|
var enabled: Boolean
|
||||||
get() = controls.enabled
|
get() = controls.enabled
|
||||||
@ -24,11 +30,37 @@ class OrbitalCameraInputManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
// Switch mouse button actions when certain modifier keys are pressed to counteract
|
||||||
|
// OrbitControls switching left and right click behavior in that case.
|
||||||
|
pointerDownListener = canvas.disposableListener<PointerEvent>("pointerdown", {
|
||||||
|
if (it.ctrlKey || it.metaKey || it.shiftKey) {
|
||||||
|
controls.mouseButtons = obj {
|
||||||
|
LEFT = MOUSE.ROTATE
|
||||||
|
MIDDLE = MOUSE.DOLLY
|
||||||
|
RIGHT = MOUSE.PAN
|
||||||
|
}
|
||||||
|
} else {
|
||||||
controls.mouseButtons = obj {
|
controls.mouseButtons = obj {
|
||||||
LEFT = MOUSE.PAN
|
LEFT = MOUSE.PAN
|
||||||
MIDDLE = MOUSE.DOLLY
|
MIDDLE = MOUSE.DOLLY
|
||||||
RIGHT = MOUSE.ROTATE
|
RIGHT = MOUSE.ROTATE
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ensure OrbitControls is instantiated after the pointerdown event listener is attached.
|
||||||
|
controls = OrbitControls(camera, canvas)
|
||||||
|
|
||||||
|
controls.mouseButtons = obj {
|
||||||
|
LEFT = MOUSE.PAN
|
||||||
|
MIDDLE = MOUSE.DOLLY
|
||||||
|
RIGHT = MOUSE.ROTATE
|
||||||
|
}
|
||||||
|
|
||||||
|
controls.touches = obj {
|
||||||
|
ONE = TOUCH.PAN
|
||||||
|
TWO = TOUCH.DOLLY_ROTATE
|
||||||
|
}
|
||||||
|
|
||||||
camera.position.copy(position)
|
camera.position.copy(position)
|
||||||
controls.screenSpacePanning = screenSpacePanning
|
controls.screenSpacePanning = screenSpacePanning
|
||||||
@ -40,6 +72,7 @@ class OrbitalCameraInputManager(
|
|||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
controls.dispose()
|
controls.dispose()
|
||||||
|
pointerDownListener.dispose()
|
||||||
super.dispose()
|
super.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@ external interface OrbitControlsMouseButtons {
|
|||||||
var RIGHT: MOUSE
|
var RIGHT: MOUSE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
external interface OrbitControlsMouseTouches {
|
||||||
|
var ONE: TOUCH
|
||||||
|
var TWO: TOUCH
|
||||||
|
}
|
||||||
|
|
||||||
external class OrbitControls(`object`: Camera, domElement: HTMLElement = definedExternally) {
|
external class OrbitControls(`object`: Camera, domElement: HTMLElement = definedExternally) {
|
||||||
var enabled: Boolean
|
var enabled: Boolean
|
||||||
var enablePan: Boolean
|
var enablePan: Boolean
|
||||||
@ -23,6 +28,8 @@ external class OrbitControls(`object`: Camera, domElement: HTMLElement = defined
|
|||||||
|
|
||||||
var mouseButtons: OrbitControlsMouseButtons
|
var mouseButtons: OrbitControlsMouseButtons
|
||||||
|
|
||||||
|
var touches: OrbitControlsMouseTouches
|
||||||
|
|
||||||
fun update(): Boolean
|
fun update(): Boolean
|
||||||
|
|
||||||
fun saveState()
|
fun saveState()
|
||||||
|
@ -744,6 +744,13 @@ external enum class MOUSE {
|
|||||||
PAN,
|
PAN,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
external enum class TOUCH {
|
||||||
|
ROTATE,
|
||||||
|
PAN,
|
||||||
|
DOLLY_PAN,
|
||||||
|
DOLLY_ROTATE,
|
||||||
|
}
|
||||||
|
|
||||||
external class Raycaster(
|
external class Raycaster(
|
||||||
origin: Vector3 = definedExternally,
|
origin: Vector3 = definedExternally,
|
||||||
direction: Vector3 = definedExternally,
|
direction: Vector3 = definedExternally,
|
||||||
|
@ -73,7 +73,7 @@ class QuestInputManager(
|
|||||||
renderContext.canvas.observeEntityDrop(::onEntityDrop),
|
renderContext.canvas.observeEntityDrop(::onEntityDrop),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ensure OrbitalCameraControls attaches its listeners after ours.
|
// Ensure OrbitalCameraControls attaches its listeners after we've attached ours.
|
||||||
cameraInputManager = OrbitalCameraInputManager(
|
cameraInputManager = OrbitalCameraInputManager(
|
||||||
renderContext.canvas,
|
renderContext.canvas,
|
||||||
renderContext.camera,
|
renderContext.camera,
|
||||||
|
@ -19,9 +19,18 @@ class IdleState(
|
|||||||
private var shouldCheckHighlight = false
|
private var shouldCheckHighlight = false
|
||||||
|
|
||||||
override fun processEvent(event: Evt): State {
|
override fun processEvent(event: Evt): State {
|
||||||
|
// Don't highlight or manipulate entities in forced panning/rotating mode.
|
||||||
|
val forcedPanningRotatingMode = when (event) {
|
||||||
|
is KeyboardEvt -> event.key == "Control"
|
||||||
|
is PointerEvt -> event.ctrlKey
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
when (event) {
|
when (event) {
|
||||||
is KeyboardEvt -> {
|
is KeyboardEvt -> {
|
||||||
if (entityManipulationEnabled) {
|
if (forcedPanningRotatingMode) {
|
||||||
|
ctx.setHighlightedEntity(null)
|
||||||
|
} else if (entityManipulationEnabled) {
|
||||||
val quest = ctx.quest.value
|
val quest = ctx.quest.value
|
||||||
val entity = ctx.selectedEntity.value
|
val entity = ctx.selectedEntity.value
|
||||||
|
|
||||||
@ -32,7 +41,9 @@ class IdleState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is PointerDownEvt -> {
|
is PointerDownEvt -> {
|
||||||
val pick = pickEntity(event.pointerDevicePosition)
|
val pick =
|
||||||
|
if (forcedPanningRotatingMode) null
|
||||||
|
else pickEntity(event.pointerDevicePosition)
|
||||||
|
|
||||||
when (event.buttons) {
|
when (event.buttons) {
|
||||||
1 -> {
|
1 -> {
|
||||||
@ -93,10 +104,14 @@ class IdleState(
|
|||||||
is PointerMoveEvt -> {
|
is PointerMoveEvt -> {
|
||||||
if (!panning && !rotating && !zooming) {
|
if (!panning && !rotating && !zooming) {
|
||||||
// User is hovering.
|
// User is hovering.
|
||||||
|
if (forcedPanningRotatingMode) {
|
||||||
|
ctx.setHighlightedEntity(null)
|
||||||
|
} else {
|
||||||
pointerDevicePosition.copy(event.pointerDevicePosition)
|
pointerDevicePosition.copy(event.pointerDevicePosition)
|
||||||
shouldCheckHighlight = true
|
shouldCheckHighlight = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is PointerOutEvt -> {
|
is PointerOutEvt -> {
|
||||||
ctx.setHighlightedEntity(null)
|
ctx.setHighlightedEntity(null)
|
||||||
|
Loading…
Reference in New Issue
Block a user