scissoring with respect to world transform matrix
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 7 Jul 2021 20:04:47 +0000 (15:04 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 7 Jul 2021 20:04:47 +0000 (15:04 -0500)
core/container/array.onyx
modules/immediate_mode/immediate_renderer.onyx
modules/ui/components/scrollable_area.onyx [new file with mode: 0644]

index 7ec75b8de2b6b6e7ed50ac3bd4d8cc9c3db2ed92..c1d64feb3ed5c63d47af62807e89bb2c18149596 100644 (file)
@@ -125,7 +125,7 @@ delete :: (arr: ^[..] $T, idx: u32) {
 fast_delete :: (arr: ^[..] $T, idx: u32) {
     if idx >= arr.count do return;
 
-    arr.data[idx] = arr.data[arr.count - 1];
+    if idx != arr.count - 1 do arr.data[idx] = arr.data[arr.count - 1];
     arr.count -= 1;
 }
 
index 8be8a5a6002d7e84f6eef5f0243ae8cf55430c91..250ec88c8c4b9798727f3f561d2633b1c5697ad9 100644 (file)
@@ -23,6 +23,10 @@ Immediate_Vertex :: struct {
     texture    : Vector2;
 }
 
+Scissor_State :: struct {
+    x, y, w, h: f32;
+}
+
 Immediate_Renderer :: struct {
     // Needs to be a multiple of 6!!
     Default_Max_Verticies :: 1020;
@@ -54,6 +58,8 @@ Immediate_Renderer :: struct {
     world_transform_stack : [..] Transform;
     world_transform_dirty := false; // If the world transform matrix should be pushed to the shader uniform.
 
+    scissor_stack : [..] Scissor_State;
+
     make :: (max_verticies := Default_Max_Verticies) -> Immediate_Renderer {
         ir : Immediate_Renderer;
         __initialize(^ir);
@@ -85,6 +91,8 @@ Immediate_Renderer :: struct {
         world_transform_stack = array.make(Transform, capacity=1);
         array.insert_empty(^world_transform_stack, 0);
         transform_identity(array.get_ptr(^world_transform_stack, -1));
+
+        scissor_stack = array.make(Scissor_State);
     
         ir->init_shader_params(^simple_shader);
         ir->init_shader_params(^textured_shader);
@@ -289,13 +297,39 @@ Immediate_Renderer :: struct {
 
     @Cleanup // right now, these are raw screen coordinates, with x and y being the bottom left of the screen.
     // This is backwards from what use_ortho_projections does, so it's not great to work with.
-    scissor :: (use ir: ^Immediate_Renderer, x: f32, y: f32, w: f32, h: f32) {
+    push_scissor :: (use ir: ^Immediate_Renderer, x: f32, y: f32, w: f32, h: f32, intersect_previous := true) {
+        if vertex_count > 0 do ir->flush();
+
         if !gl.isEnabled(gl.SCISSOR_TEST) {
-            ir->flush();
             gl.enable(gl.SCISSOR_TEST);
         }
 
-        gl.scissor(~~x, ~~y, ~~w, ~~h);
+        world_matrix := ir->get_transform()
+                        |> transform_to_matrix();
+
+        new_x0 := world_matrix[0] * x + world_matrix[1] * y + world_matrix[12] * 1;
+        new_y0 := world_matrix[4] * x + world_matrix[5] * y + world_matrix[13] * 1;
+        new_x1 := world_matrix[0] * (x + w) + world_matrix[1] * (y + h) + world_matrix[12] * 1;
+        new_y1 := world_matrix[4] * (x + w) + world_matrix[5] * (y + h) + world_matrix[13] * 1;
+        new_w  := new_x1 - new_x0;
+        new_h  := new_y1 - new_y0;
+
+        array.push(^scissor_stack, .{ new_x0, new_y0, new_w, new_h });
+
+        gl.scissor(~~new_x0, ~~(-new_y0 + new_h * 2), ~~new_w, ~~new_h);
+    }
+
+    pop_scissor :: (use ir: ^Immediate_Renderer) {
+        array.pop(^scissor_stack);
+
+        if scissor_stack.count > 0 {
+            s := scissor_stack[scissor_stack.count - 1];
+
+            gl.scissor(~~s.x, ~~s.y, ~~s.w, ~~s.h);
+
+        } else {
+            ir->scissor_disable();
+        }
     }
 
     scissor_disable :: (use ir: ^Immediate_Renderer) {
@@ -427,10 +461,12 @@ use_alpha_shader :: (texture_id: i32 = -1) {
     global_renderer->use_alpha_shader(texture_id);
 }
 
-scissor :: (x: f32, y: f32, w: f32, h: f32) {
-    global_renderer->scissor(x, y, w, h);
+push_scissor :: (x: f32, y: f32, w: f32, h: f32) {
+    global_renderer->push_scissor(x, y, w, h);
 }
 
+pop_scissor :: () do global_renderer->pop_scissor();
+
 scissor_disable :: () {
     global_renderer->scissor_disable();
 }
diff --git a/modules/ui/components/scrollable_area.onyx b/modules/ui/components/scrollable_area.onyx
new file mode 100644 (file)
index 0000000..5cab4ab
--- /dev/null
@@ -0,0 +1,10 @@
+package ui
+use package core
+
+scrollable_area_start :: (use r: Rectangle) {
+
+}
+
+scrollable_area_end :: () {
+    
+}
\ No newline at end of file