Newer
Older
kotlin-webgl-test / src / main / kotlin / games / perses / game / View.kt
rnentjes on 28 Mar 2017 6 KB Remove logging
package games.perses.game

import games.perses.math.Matrix4
import kotlin.browser.document

enum class ViewType {
    PROJECTION,
    WIDTH,
    HEIGHT,
    ABSOLUTE
}

class View(
  var lastWindowWidth: Int = 2000,
  var lastWindowHeight: Int = 1000,
  var windowWidth: Int = 2000,
  var windowHeight: Int = 1000,
  var width: Float = 1024f,
  var height: Float = 1024f,
  var angle: Float = 60f,
  var near: Float = -0.1f,
  var far: Float = -100f,
  var minAspectRatio: Float = 1f,
  var maxAspectRatio: Float = 1f,
  var leftOffset: Int = 0,
  var bottomOffset: Int = 0,
  var viewType: ViewType = ViewType.WIDTH,
  var drawMode: DrawMode = DrawMode.LINEAR) {
    var vMatrix = Matrix4()
    var aspectRatio = 1f

    init {
        updateView()
    }

    fun requestFullscreen() {
        val element = document.body
        //language=javascript
        js("""
             if(element.requestFullscreen) {
                element.requestFullscreen();
              } else if(element.mozRequestFullScreen) {
                element.mozRequestFullScreen();
              } else if(element.webkitRequestFullscreen) {
                element.webkitRequestFullscreen();
              } else if(element.msRequestFullscreen) {
                element.msRequestFullscreen();
              }
        """)
    }

    fun exitFullscreen() {
        js("""
              if(document.exitFullscreen) {
                document.exitFullscreen();
              } else if(document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
              } else if(document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
              }
        """)
    }

    fun switchFullscreen() {
        if (isFullscreen()) {
            exitFullscreen()
        } else {
            requestFullscreen()
        }
    }

    fun isFullscreen(): Boolean {
        val fse = js("document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement");

        return fse != undefined
    }

    fun updateView() {
        aspectRatio = windowWidth / windowHeight.toFloat()

        if (aspectRatio < minAspectRatio) {
            aspectRatio = minAspectRatio

            windowHeight = (windowWidth / aspectRatio).toInt()
        }

        if (aspectRatio > maxAspectRatio) {
            aspectRatio = maxAspectRatio

            windowWidth = (windowHeight * aspectRatio).toInt()
        }

        when (viewType) {
            ViewType.ABSOLUTE -> {
                vMatrix.setOrthographicProjection(0f, width, 0f, height, near, far)
            }
            ViewType.WIDTH -> {
                height = width / aspectRatio

                vMatrix.setOrthographicProjection(0f, width, 0f, height, near, far)
            }
            ViewType.HEIGHT -> {
                width = height * aspectRatio

                vMatrix.setOrthographicProjection(0f, width, 0f, height, near, far)
            }
            ViewType.PROJECTION -> {
                vMatrix.setPerspectiveProjection(angle, aspectRatio, near, far)
            }
            else -> {
                throw IllegalStateException("ViewType $viewType not implemented!")
            }
        }

        //println("width: $width, height: $height")
    }

    fun screenToGameCoordX(screenX: Float): Float {
        var result = screenX

        when (viewType) {
            ViewType.ABSOLUTE -> {
                // nop
            }
            ViewType.WIDTH, ViewType.HEIGHT -> {
                result = ( (screenX - Game.borderLeft) * width / windowWidth )
            }
            ViewType.PROJECTION -> {
                // uhm
            }
            else -> {
                throw IllegalStateException("ViewType $viewType not implemented!")
            }
        }

        return result
    }

    fun screenToGameCoordY(screenY: Float): Float {
        var result = screenY

        when (viewType) {
            ViewType.ABSOLUTE -> {
                // nop
            }
            ViewType.WIDTH, ViewType.HEIGHT -> {
                result = height - ( (screenY - Game.borderTop) * height / windowHeight )
            }
            ViewType.PROJECTION -> {
                // uhm
            }
            else -> {
                throw IllegalStateException("ViewType $viewType not implemented!")
            }
        }

        return result
    }

    fun gameToScreenCoordX(gameX: Float): Float {
        var result = gameX
        val normalizedX = gameX + (width / 2)

        when (viewType) {
            ViewType.ABSOLUTE -> {
                // nop
            }
            ViewType.WIDTH, ViewType.HEIGHT -> {
                result = ( gameX / width * windowWidth ) + Game.borderLeft
            }
            ViewType.PROJECTION -> {
                // uhm
            }
            else -> {
                throw IllegalStateException("ViewType $viewType not implemented!")
            }
        }

        return result
    }

    fun gameToScreenCoordY(gameY: Float): Float {
        var result = gameY
        val normalizedY = gameY + (height / 2)

        when (viewType) {
            ViewType.ABSOLUTE -> {
                // nop
            }
            ViewType.WIDTH, ViewType.HEIGHT -> {
                result = height - ( gameY / height * windowHeight ) + Game.borderTop
            }
            ViewType.PROJECTION -> {
                // uhm
            }
            else -> {
                throw IllegalStateException("ViewType $viewType not implemented!")
            }
        }

        return result
    }

    fun setToWidth(width: Float) {
        this.width = width
        this.viewType = ViewType.WIDTH

        updateView()
    }

    fun setToHeight(height: Float) {
        this.height = height
        this.viewType = ViewType.HEIGHT

        updateView()
    }

    fun setProjection(angle: Float) {
        this.angle = angle
        this.viewType = ViewType.PROJECTION

        updateView()
    }

    fun setNear(near: Float) {
        this.near = near

        updateView()
    }

    fun setFar(far: Float) {
        this.far = far

        updateView()
    }
}