Skip to content

Commit

Permalink
refactor scene input logic and update new scene params
Browse files Browse the repository at this point in the history
  • Loading branch information
mi-sts committed Nov 28, 2023
1 parent f580219 commit 64afcdc
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 155 deletions.
111 changes: 30 additions & 81 deletions src/main/kotlin/solve/rendering/canvas/SceneCanvas.kt
Original file line number Diff line number Diff line change
@@ -1,72 +1,62 @@
package solve.rendering.canvas

import javafx.beans.InvalidationListener
import javafx.event.EventHandler
import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent
import javafx.scene.input.ScrollEvent
import org.joml.Vector2f
import org.joml.Vector2i
import solve.rendering.engine.rendering.renderers.FramesRenderer
import solve.rendering.engine.scene.Scene
import solve.rendering.engine.utils.minus
import solve.rendering.engine.utils.toFloatVector
import solve.scene.SceneFacade
import solve.scene.controller.SceneController
import solve.scene.model.VisualizationFrame
import solve.utils.ServiceLocator
import kotlin.math.pow
import kotlin.math.sign

class SceneCanvas : OpenGLCanvas() {
private var sceneController: SceneController? = null
private var framesRenderer: FramesRenderer? = null
private var canvasScene: Scene? = null

private var mousePosition = Vector2i()

private var isDraggingScene = false
private var dragStartCameraPosition = Vector2f()
private var dragStartCameraPoint = Vector2f()
private var dragStartPoint = Vector2i()

private val projectChangedEventHandler = InvalidationListener {
val controller = sceneController ?: return@InvalidationListener
framesRenderer?.setNewSceneFrames(controller.scene.frames)

init {
initializeCanvasEvents()
}
private val framesChangedEventHandler = InvalidationListener {
val controller = sceneController ?: return@InvalidationListener
framesRenderer?.setFramesSelection(controller.scene.frames)

fun setNewSceneFrames(frames: List<VisualizationFrame>) {
framesRenderer?.setNewSceneFrames(frames)
}

private val wheelScrolledEventHandler = EventHandler<ScrollEvent> { event ->
val scrollValueSign = event.deltaY.sign.toInt()
onWheelScrolled(scrollValueSign)
fun setFramesSelection(framesSelection: List<VisualizationFrame>) {
framesRenderer?.setFramesSelection(framesSelection)
}
private val mouseMovedEventHandler = EventHandler<MouseEvent> { event ->
mousePosition = extrudeEventMousePosition(event)

fun setColumnsNumber(columnsNumber: Int) {
framesRenderer?.setGridWidth(columnsNumber)
}
private val mouseDraggedEventHandler = EventHandler<MouseEvent> { event ->
val mousePosition = extrudeEventMousePosition(event)
if (event.button == MouseButton.MIDDLE) {
onMouseDragged(mousePosition)

fun dragTo(toScreenPoint: Vector2i) {
val mousePoint = fromScreenToCameraPoint(toScreenPoint)
if (isDraggingScene) {
val dragVector = mousePoint - dragStartPoint
window.camera.position = dragStartCameraPoint - dragVector.toFloatVector() / window.camera.scaledZoom
}
}
private val wheelPressedEventHandler = EventHandler<MouseEvent> { event ->
if (event.button != MouseButton.MIDDLE) {
return@EventHandler
}
dragStartCameraPosition = window.camera.position
dragStartPoint = fromScreenToCameraPoint(mousePosition)

fun startDragging(fromScreenPoint: Vector2i) {
dragStartCameraPoint = window.camera.position
dragStartPoint = fromScreenToCameraPoint(fromScreenPoint)
isDraggingScene = true
}
private val wheelReleasedEventHandler = EventHandler<MouseEvent> { event ->
if (event.button != MouseButton.MIDDLE) {
return@EventHandler
}

fun stopDragging() {
isDraggingScene = false
}

init {
initializeCanvasEvents()
fun zoomToPoint(screenPoint: Vector2i, newZoom: Float) {
val cameraPoint = fromScreenToCameraPoint(screenPoint)
window.camera.zoomToPoint(cameraPoint, newZoom)
}

override fun onInit() {
Expand All @@ -78,64 +68,23 @@ class SceneCanvas : OpenGLCanvas() {
val renderer = FramesRenderer(window)
framesRenderer = renderer
canvasScene = Scene(listOf(renderer))

addBindings()
}

override fun onDraw(deltaTime: Float) {
canvasScene?.renderers?.forEach { it.render() }
}

override fun onDispose() {
removeBindings()
}

private fun onMouseDragged(mousePosition: Vector2i) {
val mousePoint = fromScreenToCameraPoint(mousePosition)
if (isDraggingScene) {
val dragVector = mousePoint - dragStartPoint
window.camera.position = dragStartCameraPosition - dragVector.toFloatVector() / window.camera.scaledZoom
}
}

private fun onWheelScrolled(scrollValueSign: Int) {
val pointPosition = fromScreenToCameraPoint(mousePosition)
val zoomMultiplier = OnWheelScrolledZoomMultiplier.pow(scrollValueSign)
window.camera.zoomToPoint(pointPosition, zoomMultiplier)
}

private fun extrudeEventMousePosition(event: MouseEvent) = Vector2i(event.x.toInt(), event.y.toInt())

private fun fromScreenToCameraPoint(screenPoint: Vector2i) = screenPoint - (window.size / 2)

private fun moveCameraToLeftUpperCorner() {
window.camera.position =
Vector2f(window.width.toFloat(), window.height.toFloat()) / (2f * window.camera.scaledZoom)
}

private fun addBindings() {
SceneFacade.lastVisualizationKeepSettingsProperty.addListener(projectChangedEventHandler)
sceneController?.sceneProperty?.addListener(framesChangedEventHandler)

canvas.onMouseMoved = mouseMovedEventHandler
canvas.onMouseDragged = mouseDraggedEventHandler
canvas.onMousePressed = wheelPressedEventHandler
canvas.onMouseReleased = wheelReleasedEventHandler
canvas.onScroll = wheelScrolledEventHandler
}

private fun removeBindings() {
SceneFacade.lastVisualizationKeepSettingsProperty.removeListener(projectChangedEventHandler)
sceneController?.sceneProperty?.removeListener(framesChangedEventHandler)

canvas.removeEventHandler(MouseEvent.MOUSE_MOVED, mouseMovedEventHandler)
canvas.removeEventHandler(MouseEvent.MOUSE_DRAGGED, mouseDraggedEventHandler)
canvas.removeEventHandler(MouseEvent.MOUSE_PRESSED, wheelPressedEventHandler)
canvas.removeEventHandler(MouseEvent.MOUSE_RELEASED, wheelReleasedEventHandler)
canvas.removeEventHandler(ScrollEvent.SCROLL, wheelScrolledEventHandler)
}

companion object {
private const val OnWheelScrolledZoomMultiplier = 1.1f
private const val DefaultMinZoom = 0.1f
private const val DefaultMaxZoom = 10f
}
}
7 changes: 4 additions & 3 deletions src/main/kotlin/solve/rendering/engine/camera/Camera.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ class Camera(var position: Vector2f = Vector2f(), zoom: Float = 1f) {
zoom *= currentZoomMultiplier
}

fun zoomToPoint(point: Vector2i, currentZoomMultiplier: Float) {
zoom *= currentZoomMultiplier
position += point.toFloatVector() * (currentZoomMultiplier - 1f) / scaledZoom
fun zoomToPoint(point: Vector2i, newZoom: Float) {
val zoomMultiplier = newZoom / zoom
zoom = newZoom
position += point.toFloatVector() * (zoomMultiplier - 1f) / scaledZoom
}

fun calculateProjectionMatrix(projectionSize: Vector2f): Matrix4f {
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/solve/rendering/engine/components/Component.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package solve.rendering.engine.components

import solve.rendering.engine.scene.GameObject
import solve.rendering.engine.scene.SceneObject

abstract class Component {
var gameObject: GameObject? = null
var sceneObject: SceneObject? = null
private set

fun addToGameObject(gameObject: GameObject) {
this.gameObject?.removeComponent(this)
fun addToGameObject(sceneObject: SceneObject) {
this.sceneObject?.removeComponent(this)

this.gameObject = gameObject
gameObject.addComponent(this)
this.sceneObject = sceneObject
sceneObject.addComponent(this)
}

open fun start() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import solve.rendering.engine.Window
import solve.rendering.engine.components.SpriteRenderer
import solve.rendering.engine.rendering.batch.PrimitiveType
import solve.rendering.engine.rendering.batch.RenderBatch
import solve.rendering.engine.scene.GameObject
import solve.rendering.engine.scene.SceneObject
import solve.rendering.engine.shader.ShaderAttributeType
import solve.rendering.engine.shader.ShaderProgram
import solve.rendering.engine.shader.ShaderType
Expand Down Expand Up @@ -59,7 +59,7 @@ class DefaultRenderer(
override fun updateBatchesData() {
spriteRenderers.forEach { spriteRenderer ->
val sprite = spriteRenderer.sprite ?: return@forEach
val gameObject = spriteRenderer.gameObject ?: return@forEach
val gameObject = spriteRenderer.sceneObject ?: return@forEach

val texture = sprite.texture
val batch = getAvailableBatch(texture, gameObject.transform.zIndex)
Expand All @@ -80,8 +80,8 @@ class DefaultRenderer(
}
}

override fun addGameObject(gameObject: GameObject) {
val spriteRenderer = gameObject.getComponentOfType<SpriteRenderer>()
override fun addGameObject(sceneObject: SceneObject) {
val spriteRenderer = sceneObject.getComponentOfType<SpriteRenderer>()
if (spriteRenderer == null) {
println("The adding gameobject does not has a sprite renderer component!")
return
Expand All @@ -90,8 +90,8 @@ class DefaultRenderer(
spriteRenderers.add(spriteRenderer)
}

override fun removeGameObject(gameObject: GameObject): Boolean {
val spriteRenderer = gameObject.getComponentOfType<SpriteRenderer>() ?: return false
override fun removeGameObject(sceneObject: SceneObject): Boolean {
val spriteRenderer = sceneObject.getComponentOfType<SpriteRenderer>() ?: return false

return spriteRenderers.remove(spriteRenderer)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ class FramesRenderer(
modelsCommonMatrix = newMatrix
}

fun setGridWidth(gridWidth: Int) {
if (gridWidth < 1) {
println("The width of the frames grid should be a positive value!")
return
}

this.gridWidth = gridWidth
}

fun setNewSceneFrames(frames: List<VisualizationFrame>) {
if (frames.isEmpty()) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import org.lwjgl.opengl.GL11.glDrawElements
import solve.rendering.engine.Window
import solve.rendering.engine.rendering.batch.RenderBatch
import solve.rendering.engine.rendering.texture.Texture2D
import solve.rendering.engine.scene.GameObject
import solve.rendering.engine.scene.SceneObject
import solve.rendering.engine.shader.ShaderProgram

abstract class Renderer(protected val window: Window) {
Expand Down Expand Up @@ -45,9 +45,9 @@ abstract class Renderer(protected val window: Window) {
batches.forEach { it.deleteBuffers() }
}

open fun addGameObject(gameObject: GameObject) { }
open fun addGameObject(sceneObject: SceneObject) { }

open fun removeGameObject(gameObject: GameObject): Boolean = false
open fun removeGameObject(sceneObject: SceneObject): Boolean = false

protected fun getAvailableBatch(texture: Texture2D?, requiredZIndex: Int): RenderBatch {
batches.forEach { batch ->
Expand Down
24 changes: 12 additions & 12 deletions src/main/kotlin/solve/rendering/engine/scene/Scene.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ package solve.rendering.engine.scene
import solve.rendering.engine.rendering.renderers.Renderer

class Scene(renderers: List<Renderer> = emptyList()) {
private val _gameObjects = mutableListOf<GameObject>()
val gameObjects: List<GameObject>
get() = _gameObjects
private val _sceneObjects = mutableListOf<SceneObject>()
val sceneObjects: List<SceneObject>
get() = _sceneObjects

private val _renderers = renderers
val renderers: List<Renderer>
get() = _renderers

fun update(deltaTime: Float) {
_gameObjects.forEach { gameObject ->
_sceneObjects.forEach { gameObject ->
if (gameObject.isDestroyed) {
removeGameObject(gameObject)
return@forEach
Expand All @@ -23,17 +23,17 @@ class Scene(renderers: List<Renderer> = emptyList()) {
}
}

fun addGameObject(gameObject: GameObject) {
if (_gameObjects.contains(gameObject)) {
println("The scene already contains adding game object ($gameObject)!")
fun addGameObject(sceneObject: SceneObject) {
if (_sceneObjects.contains(sceneObject)) {
println("The scene already contains adding game object ($sceneObject)!")
return
}
_gameObjects.add(gameObject)
_renderers.forEach { it.addGameObject(gameObject) }
_sceneObjects.add(sceneObject)
_renderers.forEach { it.addGameObject(sceneObject) }
}

fun removeGameObject(gameObject: GameObject) {
_gameObjects.remove(gameObject)
_renderers.forEach { it.removeGameObject(gameObject) }
fun removeGameObject(sceneObject: SceneObject) {
_sceneObjects.remove(sceneObject)
_renderers.forEach { it.removeGameObject(sceneObject) }
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/solve/rendering/engine/scene/SceneData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package solve.rendering.engine.scene
import solve.rendering.engine.camera.Camera

data class SceneData(
val gameObjects: List<GameObject>,
val sceneObjects: List<SceneObject>,
val camera: Camera
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package solve.rendering.engine.scene

import solve.rendering.engine.components.Component

class GameObject(
class SceneObject(
name: String,
val transform: Transform = Transform(),
components: List<Component> = emptyList()
Expand All @@ -18,7 +18,7 @@ class GameObject(
private set

init {
_gameObjects.add(this)
_sceneObjects.add(this)
_components.forEach { it.addToGameObject(this) }
}

Expand Down Expand Up @@ -66,8 +66,8 @@ class GameObject(
}

companion object {
private val _gameObjects = mutableListOf<GameObject>()
val gameObjects: List<GameObject>
get() = _gameObjects
private val _sceneObjects = mutableListOf<SceneObject>()
val sceneObjects: List<SceneObject>
get() = _sceneObjects
}
}
Loading

0 comments on commit 64afcdc

Please sign in to comment.