Newer
Older
kotlin-webgl-test / src / main / kotlin / games / perses / game / View.kt
rnentjes on 21 Mar 2018 5 KB Update kotlin version
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()
  }
}