Skip to content

Commit

Permalink
Center mouse position, improve dom api from getting window pos/size
Browse files Browse the repository at this point in the history
  • Loading branch information
thetarnav committed Jan 17, 2024
1 parent f04d1be commit abd0158
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 53 deletions.
49 changes: 26 additions & 23 deletions example/main.odin
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import "core:fmt"
import "core:intrinsics"
import glm "core:math/linalg/glsl"
import "core:mem"
import "core:runtime"
Expand All @@ -15,8 +16,8 @@ shader_vertex := #load("shader_vertex.glsl", string)
dpr: f32
res: [2]i32
canvas_pos: [2]f32
canvas_rect: [2]f32
window_rect: [2]f32
canvas_size: [2]f32
window_size: [2]f32
mouse_pos: [2]f32

scale: f32 = 1
Expand Down Expand Up @@ -89,24 +90,24 @@ main :: proc() {
colors_buffer = webgl.CreateBuffer()

dpr = f32(dom.device_pixel_ratio())
canvas_rect = {640, 480}
window_rect = canvas_rect + 200
mouse_pos = window_rect / 2
window_size = cast_vec2(f32, dom.get_window_inner_size())
canvas_size = window_size - 200
mouse_pos = window_size / 2
}

on_mouse_move :: proc(e: dom.Event) {
mouse_pos = {f32(e.data.mouse.client.x), f32(e.data.mouse.client.y)}
mouse_pos = cast_vec2(f32, e.data.mouse.client)
}
on_wheel :: proc(e: dom.Event) {
scale += f32(e.data.wheel.delta.y) * 0.001
scale = clamp(scale, scale_min, scale_max)
}
@(export)
on_window_resize :: proc "c" (vw, vh, cw, ch, cx, cy: f32) {
window_rect = {vw, vh}
canvas_rect = {cw, ch}
on_window_resize :: proc "contextless" (vw, vh, cw, ch, cx, cy: f32) {
window_size = {vw, vh}
canvas_size = {cw, ch}
canvas_pos = {cx, cy}
res = {i32(f32(canvas_rect.x) * dpr), i32(f32(canvas_rect.y) * dpr)}
res = cast_vec2(i32, canvas_size * dpr)
}

@(export)
Expand Down Expand Up @@ -135,56 +136,58 @@ frame :: proc "c" (delta: i32, ctx: ^runtime.Context) {

webgl.BindBuffer(webgl.ARRAY_BUFFER, positions_buffer)
webgl.BufferDataSlice(webgl.ARRAY_BUFFER, positions[:], webgl.STATIC_DRAW)

// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
webgl.VertexAttribPointer(a_position, 2, webgl.FLOAT, false, 0, 0)

// bind, and fill color buffer
webgl.BindBuffer(webgl.ARRAY_BUFFER, colors_buffer)
webgl.BufferDataSlice(webgl.ARRAY_BUFFER, colors[:], webgl.STATIC_DRAW)
webgl.VertexAttribPointer(a_color, 4, webgl.UNSIGNED_BYTE, true, 0, 0)

// set the resolution
webgl.Uniform2f(u_resolution, canvas_rect.x, canvas_rect.y)
webgl.Uniform2f(u_resolution, canvas_size.x, canvas_size.y)

// Tell WebGL how to convert from clip space to pixels
webgl.Viewport(0, 0, res.x, res.y)

// Clear the canvas
webgl.ClearColor(0, 0.01, 0.02, 0)
webgl.Clear(webgl.COLOR_BUFFER_BIT)

rotation += 0.01 * f32(delta) * (window_rect.x / 2 - mouse_pos.x) / window_rect.x

rotation += 0.01 * f32(delta) * (window_size.x / 2 - mouse_pos.x) / window_size.x
mat :=
mat3_translate(mouse_pos - canvas_pos) *
mat3_scale({scale, scale}) *
mat3_rotate(rotation) *
mat3_translate(-box_size / 2)

webgl.UniformMatrix3fv(u_matrix, mat)

// draw
webgl.DrawArrays(webgl.TRIANGLES, 0, 6) // 2 triangles, 6 vertices
}

cast_vec2 :: proc "contextless" (
$To: typeid,
v: [2]$From,
) -> [2]To where intrinsics.type_is_numeric(From) &&
intrinsics.type_is_numeric(To) {
return {To(v.x), To(v.y)}
}

// odinfmt: disable
@(require_results)
mat3_translate :: proc(v: [2]f32) -> glm.mat3 {
mat3_translate :: proc "contextless" (v: [2]f32) -> glm.mat3 {
return {
1, 0, v.x,
0, 1, v.y,
0, 0, 1,
}
}
@(require_results)
mat3_scale :: proc(v: [2]f32) -> glm.mat3 {
mat3_scale :: proc "contextless" (v: [2]f32) -> glm.mat3 {
return {
v.x, 0, 0,
0, v.y, 0,
0, 0, 1,
}
}
@(require_results)
mat3_rotate :: proc(angle: f32) -> glm.mat3 {
mat3_rotate :: proc "contextless" (angle: f32) -> glm.mat3 {
c := glm.cos(angle)
s := glm.sin(angle)
return {
Expand Down
47 changes: 32 additions & 15 deletions wasm/dom/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,39 +449,56 @@ export function makeOdinDOM(_wasm) {
values[3] = rect.bottom - rect.top
},
/**
* Get window rect
*
* @param {number} rect_ptr pointer to Rect
* @param {number} size_ptr pointer to [2]f64
* @returns {void}
*/
window_get_rect(rect_ptr) {
const values = mem.load_f64_array(wasm.memory.buffer, rect_ptr, 4)

get_window_inner_size(size_ptr) {
const values = mem.load_f64_array(wasm.memory.buffer, size_ptr, 2)
values[0] = window.innerWidth
values[1] = window.innerHeight
},
/**
* @param {number} size_ptr pointer to [2]f64
* @returns {void}
*/
get_window_outer_size(size_ptr) {
const values = mem.load_f64_array(wasm.memory.buffer, size_ptr, 2)
values[0] = window.outerWidth
values[1] = window.outerHeight
},
/**
* @param {number} size_ptr pointer to [2]f64
* @returns {void}
*/
get_screen_size(size_ptr) {
const values = mem.load_f64_array(wasm.memory.buffer, size_ptr, 2)
values[0] = window.screen.width
values[1] = window.screen.height
},
/**
* @param {number} pos_ptr pointer to [2]f64
* @returns {void}
*/
get_window_position(pos_ptr) {
const values = mem.load_f64_array(wasm.memory.buffer, pos_ptr, 2)
values[0] = window.screenX
values[1] = window.screenY
values[2] = window.screen.width
values[3] = window.screen.height
},
/**
* Get window scroll
*
* @param {number} pos_ptr pointer to [2]f64
* @returns {void}
*/
window_get_scroll(pos_ptr) {
get_window_scroll(pos_ptr) {
const values = mem.load_f64_array(wasm.memory.buffer, pos_ptr, 2)

values[0] = window.scrollX
values[1] = window.scrollY
},
/**
* Set window scroll
*
* @param {number} x scroll x
* @param {number} y scroll y
* @returns {void}
*/
window_set_scroll(x, y) {
set_window_scroll(x, y) {
window.scroll(x, y)
},
/**
Expand Down
19 changes: 17 additions & 2 deletions wasm/dom/dom_all_targets.odin
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,27 @@ get_bounding_client_rect :: proc "contextless" (id: string) -> (rect: Rect) {
panic("vendor:wasm/js not supported on non JS targets")
}

window_get_rect :: proc "contextless" () -> (rect: Rect) {
get_window_inner_size :: proc "contextless" () -> (size: [2]f64) {
context = runtime.default_context()
panic("vendor:wasm/js not supported on non JS targets")
}

window_get_scroll :: proc "contextless" () -> (x, y: f64) {
get_window_outer_size :: proc "contextless" () -> (size: [2]f64) {
context = runtime.default_context()
panic("vendor:wasm/js not supported on non JS targets")
}

get_screen_size :: proc "contextless" () -> (size: [2]f64) {
context = runtime.default_context()
panic("vendor:wasm/js not supported on non JS targets")
}

get_window_position :: proc "contextless" () -> (pos: [2]f64) {
context = runtime.default_context()
panic("vendor:wasm/js not supported on non JS targets")
}

get_window_scroll :: proc "contextless" () -> (x, y: f64) {
context = runtime.default_context()
panic("vendor:wasm/js not supported on non JS targets")
}
54 changes: 41 additions & 13 deletions wasm/dom/dom_js.odin
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ foreign dom_lib {

device_pixel_ratio :: proc() -> f64 ---

window_set_scroll :: proc(x, y: f64) ---
set_window_scroll :: proc(x, y: f64) ---
}

get_element_value_string :: proc "contextless" (id: string, buf: []byte) -> string {
Expand Down Expand Up @@ -53,32 +53,60 @@ Rect :: struct {
}

get_bounding_client_rect :: proc "contextless" (id: string) -> (rect: Rect) {
@(default_calling_convention = "contextless")
foreign dom_lib {
@(link_name = "get_bounding_client_rect")
_get_bounding_client_rect :: proc(rect: ^Rect, id: string) ---
_get_bounding_client_rect :: proc "contextless" (rect: ^Rect, id: string) ---
}
_get_bounding_client_rect(&rect, id)
return
}

window_get_rect :: proc "contextless" () -> (rect: Rect) {
@(default_calling_convention = "contextless")
// Get `window.innerWidth` and `window.innerHeight`
get_window_inner_size :: proc "contextless" () -> (size: [2]f64) {
foreign dom_lib {
@(link_name = "window_get_rect")
_window_get_rect :: proc(rect: ^Rect) ---
@(link_name = "get_window_inner_size")
_get_window_inner_size :: proc "contextless" (size: ^[2]f64) ---
}
_window_get_rect(&rect)
_get_window_inner_size(&size)
return
}

window_get_scroll :: proc "contextless" () -> (x, y: f64) {
@(default_calling_convention = "contextless")
// Get `window.outerWidth` and `window.outerHeight`
get_window_outer_size :: proc "contextless" () -> (size: [2]f64) {
foreign dom_lib {
@(link_name = "get_window_outer_size")
_get_window_outer_size :: proc "contextless" (size: ^[2]f64) ---
}
_get_window_outer_size(&size)
return
}

// Get `window.screen.width` and `window.screen.height`
get_screen_size :: proc "contextless" () -> (size: [2]f64) {
foreign dom_lib {
@(link_name = "get_screen_size")
_get_screen_size :: proc "contextless" (size: ^[2]f64) ---
}
_get_screen_size(&size)
return
}

// Get `window.screenX` and `window.screenY`
get_window_position :: proc "contextless" () -> (pos: [2]f64) {
foreign dom_lib {
@(link_name = "get_window_position")
_get_window_position :: proc "contextless" (pos: ^[2]f64) ---
}
_get_window_position(&pos)
return
}

get_window_scroll :: proc "contextless" () -> (x, y: f64) {
foreign dom_lib {
@(link_name = "window_get_scroll")
_window_get_scroll :: proc(scroll: ^[2]f64) ---
@(link_name = "get_window_scroll")
_get_window_scroll :: proc "contextless" (scroll: ^[2]f64) ---
}
scroll := [2]f64{x, y}
_window_get_scroll(&scroll)
_get_window_scroll(&scroll)
return
}

0 comments on commit abd0158

Please sign in to comment.