Skip to content
This repository has been archived by the owner on Jul 8, 2022. It is now read-only.

Commit

Permalink
Support use existant JS canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
soywiz committed May 26, 2021
1 parent ecb4708 commit 7642e49
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 50 deletions.
15 changes: 13 additions & 2 deletions korgw/src/jsMain/kotlin/com/soywiz/korag/GlExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,26 @@ fun jsObject(vararg pairs: Pair<String, Any?>): dynamic {
return out
}

class AGWebgl(val config: AGConfig, val glDecorator: (KmlGl) -> KmlGl = { it }) : AGOpengl(), AGContainer {
val korgwCanvasQuery: String? by lazy { window.asDynamic().korgwCanvasQuery.unsafeCast<String?>() }
val isCanvasCreatedAndHandled get() = korgwCanvasQuery == null

open class AGWebgl(val config: AGConfig, val glDecorator: (KmlGl) -> KmlGl = { it }) : AGOpengl(), AGContainer {
companion object {
//var UNPACK_PREMULTIPLY_ALPHA_WEBGL = document.createElement('canvas').getContext('webgl').UNPACK_PREMULTIPLY_ALPHA_WEBGL
const val UNPACK_PREMULTIPLY_ALPHA_WEBGL = 37441
}

override val ag: AG = this

val canvas = document.createElement("canvas") as HTMLCanvasElement
open fun getCanvas(): HTMLCanvasElement {
return (korgwCanvasQuery?.let { document.querySelector(it) as HTMLCanvasElement })
?: (document.createElement("canvas") as HTMLCanvasElement)
}



val canvas by lazy { getCanvas() }

val glOpts = jsObject(
"premultipliedAlpha" to true,
"alpha" to false,
Expand Down
107 changes: 59 additions & 48 deletions korgw/src/jsMain/kotlin/com/soywiz/korgw/DefaultGameWindowJs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import org.w3c.files.*

private external val navigator: dynamic

class BrowserGameWindow : GameWindow() {
open class BrowserGameWindow : GameWindow() {
override val ag: AGWebgl = AGWebgl(AGConfig())
val canvas get() = ag.canvas

Expand Down Expand Up @@ -88,44 +88,26 @@ class BrowserGameWindow : GameWindow() {

private fun onResized() {
isTouchDeviceCache = null
val scale = quality.computeTargetScale(window.innerWidth, window.innerHeight, ag.devicePixelRatio)
canvasRatio = scale
canvas.width = (window.innerWidth * scale).toInt()
canvas.height = (window.innerHeight * scale).toInt()
canvas.style.position = "absolute"
canvas.style.left = "0"
canvas.style.right = "0"
canvas.style.width = "${window.innerWidth}px"
canvas.style.height = "${window.innerHeight}px"

canvas.ondragenter = {
dispatchDropfileEvent(DropFileEvent.Type.START, null)
}
canvas.ondragexit = {
dispatchDropfileEvent(DropFileEvent.Type.END, null)
}
canvas.ondragleave = {
dispatchDropfileEvent(DropFileEvent.Type.END, null)
}
canvas.ondragover = {
it.preventDefault()
}
canvas.ondragstart = {
dispatchDropfileEvent(DropFileEvent.Type.START, null)
}
canvas.ondragend = {
dispatchDropfileEvent(DropFileEvent.Type.END, null)
}
canvas.ondrop = {
it.preventDefault()
dispatchDropfileEvent(DropFileEvent.Type.END, null)
val items = it.dataTransfer!!.items
val files = (0 until items.length).map { items[it]?.getAsFile()?.toVfs() }.filterNotNull()
dispatchDropfileEvent(DropFileEvent.Type.DROP, files)
if (isCanvasCreatedAndHandled) {
val scale = quality.computeTargetScale(window.innerWidth, window.innerHeight, ag.devicePixelRatio)
val canvasWidth = (window.innerWidth * scale).toInt()
val canvasHeight = (window.innerHeight * scale).toInt()
canvas.width = canvasWidth
canvas.height = canvasHeight
canvas.style.position = "absolute"
canvas.style.left = "0"
canvas.style.right = "0"
canvas.style.width = "${window.innerWidth}px"
canvas.style.height = "${window.innerHeight}px"
canvasRatio = scale

//ag.resized(canvas.width, canvas.height)
//dispatchReshapeEvent(0, 0, window.innerWidth, window.innerHeight)
} else {
canvasRatio = (canvas.width.toDouble() / canvas.clientWidth.toDouble())
}
//canvasRatio = (canvas.width.toDouble() / canvas.clientWidth.toDouble())

//ag.resized(canvas.width, canvas.height)
//dispatchReshapeEvent(0, 0, window.innerWidth, window.innerHeight)
dispatchReshapeEvent(0, 0, canvas.width, canvas.height)
}

Expand Down Expand Up @@ -197,14 +179,15 @@ class BrowserGameWindow : GameWindow() {

// JS TouchEvent contains only active touches (ie. touchend just return the list of non ended-touches)
private fun touchEvent(e: TouchEvent, type: com.soywiz.korev.TouchEvent.Type) {
val canvasBounds = canvas.getBoundingClientRect()
dispatch(touchBuilder.frame(TouchBuilder.Mode.JS, type) {
for (n in 0 until e.touches.length) {
val touch = e.touches.item(n) ?: continue
val touchId = touch.identifier
touch(
id = touchId,
x = transformEventX(touch.clientX.toDouble()),
y = transformEventY(touch.clientY.toDouble()),
x = transformEventX(touch.clientX.toDouble() - canvasBounds.left),
y = transformEventY(touch.clientY.toDouble() - canvasBounds.top),
force = touch.asDynamic().force.unsafeCast<Double?>() ?: 1.0,
kind = Touch.Kind.FINGER
)
Expand All @@ -218,8 +201,10 @@ class BrowserGameWindow : GameWindow() {
// If we are in a touch device, touch events will be dispatched, and then we don't want to emit mouse events, that would be duplicated
if (is_touch_device()) return

val tx = transformEventX(e.clientX.toDouble()).toInt()
val ty = transformEventY(e.clientY.toDouble()).toInt()
val canvasBounds = canvas.getBoundingClientRect()

val tx = transformEventX(e.clientX.toDouble() - canvasBounds.left).toInt()
val ty = transformEventY(e.clientY.toDouble() - canvasBounds.top).toInt()
//console.log("mouseEvent", type.toString(), e.clientX, e.clientY, tx, ty)
dispatch(mouseEvent {
this.type = if (e.buttons.toInt() != 0) pressingType else type
Expand Down Expand Up @@ -347,11 +332,13 @@ class BrowserGameWindow : GameWindow() {
window.asDynamic().canvas = canvas
window.asDynamic().ag = ag
window.asDynamic().gl = ag.gl
document.body?.appendChild(canvas)
document.body?.style?.margin = "0px"
document.body?.style?.padding = "0px"
document.body?.style?.overflowX = "hidden"
document.body?.style?.overflowY = "hidden"
if (isCanvasCreatedAndHandled) {
document.body?.appendChild(canvas)
document.body?.style?.margin = "0px"
document.body?.style?.padding = "0px"
document.body?.style?.overflowX = "hidden"
document.body?.style?.overflowY = "hidden"
}
canvas.addEventListener("mouseenter", { mouseEvent(it.unsafeCast<MouseEvent>(), com.soywiz.korev.MouseEvent.Type.ENTER) })
canvas.addEventListener("mouseleave", { mouseEvent(it.unsafeCast<MouseEvent>(), com.soywiz.korev.MouseEvent.Type.EXIT) })
canvas.addEventListener("mouseover", { mouseEvent(it.unsafeCast<MouseEvent>(), com.soywiz.korev.MouseEvent.Type.MOVE, com.soywiz.korev.MouseEvent.Type.DRAG) })
Expand Down Expand Up @@ -386,10 +373,34 @@ class BrowserGameWindow : GameWindow() {
this.gamepad = e.gamepad.index
})
})


window.addEventListener("resize", { onResized() })
canvas.ondragenter = {
dispatchDropfileEvent(DropFileEvent.Type.START, null)
}
canvas.ondragexit = {
dispatchDropfileEvent(DropFileEvent.Type.END, null)
}
canvas.ondragleave = {
dispatchDropfileEvent(DropFileEvent.Type.END, null)
}
canvas.ondragover = {
it.preventDefault()
}
canvas.ondragstart = {
dispatchDropfileEvent(DropFileEvent.Type.START, null)
}
canvas.ondragend = {
dispatchDropfileEvent(DropFileEvent.Type.END, null)
}
canvas.ondrop = {
it.preventDefault()
dispatchDropfileEvent(DropFileEvent.Type.END, null)
val items = it.dataTransfer!!.items
val files = (0 until items.length).mapNotNull { items[it]?.getAsFile()?.toVfs() }
dispatchDropfileEvent(DropFileEvent.Type.DROP, files)
}
onResized()

jsFrame = { step: Double ->
val startTime = PerformanceCounter.reference
window.requestAnimationFrame(jsFrame) // Execute first to prevent exceptions breaking the loop
Expand Down

0 comments on commit 7642e49

Please sign in to comment.