Skip to main content

arcane_core/scripting/
geometry_ops.rs

1/// Geometry pipeline ops: triangles and line segments submitted from TS,
2/// rendered in a dedicated GPU pass after the sprite batch.
3///
4/// Stream A owns this file. Add ops here; wire into renderer/mod.rs in Phase 2.
5///
6/// ## Command format
7/// Each GeoCommand is a tagged enum collected into GeoState.commands per frame.
8/// The frame callback in dev.rs drains GeoState and passes to GeometryBatch::flush().
9
10use std::cell::RefCell;
11use std::rc::Rc;
12
13use deno_core::OpState;
14
15/// A single geometry draw command queued from TS.
16#[derive(Clone, Debug)]
17pub enum GeoCommand {
18    Triangle {
19        x1: f32, y1: f32,
20        x2: f32, y2: f32,
21        x3: f32, y3: f32,
22        r: f32, g: f32, b: f32, a: f32,
23        layer: i32,
24    },
25    LineSeg {
26        x1: f32, y1: f32,
27        x2: f32, y2: f32,
28        thickness: f32,
29        r: f32, g: f32, b: f32, a: f32,
30        layer: i32,
31    },
32}
33
34/// Geometry command queue: collected by TS ops, drained by the frame callback.
35pub struct GeoState {
36    pub commands: Vec<GeoCommand>,
37}
38
39impl GeoState {
40    pub fn new() -> Self {
41        Self { commands: Vec::new() }
42    }
43}
44
45/// Push a filled triangle to the geometry command queue.
46/// All params are f64 (V8 number boundary), converted to f32 internally.
47#[deno_core::op2(fast)]
48fn op_geo_triangle(
49    state: &mut OpState,
50    x1: f64, y1: f64,
51    x2: f64, y2: f64,
52    x3: f64, y3: f64,
53    r: f64, g: f64, b: f64, a: f64,
54    layer: f64,
55) {
56    let geo = state.borrow::<Rc<RefCell<GeoState>>>();
57    geo.borrow_mut().commands.push(GeoCommand::Triangle {
58        x1: x1 as f32, y1: y1 as f32,
59        x2: x2 as f32, y2: y2 as f32,
60        x3: x3 as f32, y3: y3 as f32,
61        r: r as f32, g: g as f32, b: b as f32, a: a as f32,
62        layer: layer as i32,
63    });
64}
65
66/// Push a thick line segment to the geometry command queue.
67/// The line is rendered as a quad (2 triangles) with the given thickness.
68/// All params are f64 (V8 number boundary), converted to f32 internally.
69#[deno_core::op2(fast)]
70fn op_geo_line(
71    state: &mut OpState,
72    x1: f64, y1: f64,
73    x2: f64, y2: f64,
74    thickness: f64,
75    r: f64, g: f64, b: f64, a: f64,
76    layer: f64,
77) {
78    let geo = state.borrow::<Rc<RefCell<GeoState>>>();
79    geo.borrow_mut().commands.push(GeoCommand::LineSeg {
80        x1: x1 as f32, y1: y1 as f32,
81        x2: x2 as f32, y2: y2 as f32,
82        thickness: thickness as f32,
83        r: r as f32, g: g as f32, b: b as f32, a: a as f32,
84        layer: layer as i32,
85    });
86}
87
88deno_core::extension!(
89    geometry_ext,
90    ops = [
91        op_geo_triangle,
92        op_geo_line,
93    ],
94);