Skip to main content

dora_ssr/
dora.rs

1/* Copyright (c) 2016-2026 Li Jin <dragon-fly@qq.com>
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9use std::cell::{LazyCell, RefCell};
10use std::{any::Any, ffi::c_void};
11
12mod rect;
13pub use rect::Rect;
14mod array;
15pub use array::Array;
16mod dictionary;
17pub use dictionary::Dictionary;
18mod director;
19pub use director::Director;
20mod app;
21pub use app::App;
22mod entity;
23pub use entity::Entity;
24mod group;
25pub use group::Group;
26mod observer;
27pub use observer::Observer;
28mod path;
29pub use path::Path;
30mod content;
31pub use content::Content;
32mod scheduler;
33pub use scheduler::Scheduler;
34mod camera;
35pub use camera::{Camera, ICamera};
36mod camera_2d;
37pub use camera_2d::Camera2D;
38mod camera_otho;
39pub use camera_otho::CameraOtho;
40mod pass;
41pub use pass::Pass;
42mod effect;
43pub use effect::{Effect, IEffect};
44mod sprite_effect;
45pub use sprite_effect::SpriteEffect;
46mod view;
47pub use view::View;
48mod action_def;
49pub use action_def::ActionDef;
50mod action;
51pub use action::Action;
52mod grabber;
53pub use grabber::Grabber;
54mod node;
55pub use node::{INode, Node};
56mod texture_2d;
57pub use texture_2d::Texture2D;
58mod sprite;
59pub use sprite::{ISprite, Sprite};
60mod grid;
61pub use grid::Grid;
62mod touch;
63pub use touch::Touch;
64mod ease;
65pub use ease::Ease;
66mod label;
67pub use label::Label;
68mod render_target;
69pub use render_target::RenderTarget;
70mod clip_node;
71pub use clip_node::ClipNode;
72mod draw_node;
73pub use draw_node::DrawNode;
74mod vertex_color;
75pub use vertex_color::VertexColor;
76mod line;
77pub use line::Line;
78mod particle;
79pub use particle::Particle;
80mod playable;
81pub use playable::{IPlayable, Playable};
82mod model;
83pub use model::Model;
84mod spine;
85pub use spine::Spine;
86mod dragon_bone;
87pub use dragon_bone::DragonBone;
88mod align_node;
89pub use align_node::AlignNode;
90mod effek_node;
91pub use effek_node::EffekNode;
92mod physics_world;
93pub use tile_node::TileNode;
94mod tile_node;
95pub use physics_world::{IPhysicsWorld, PhysicsWorld};
96mod fixture_def;
97pub use fixture_def::FixtureDef;
98mod body_def;
99pub use body_def::BodyDef;
100mod sensor;
101pub use sensor::Sensor;
102mod body;
103pub use body::{Body, IBody};
104mod joint_def;
105pub use joint_def::JointDef;
106mod joint;
107pub use joint::{IJoint, Joint};
108mod motor_joint;
109pub use motor_joint::MotorJoint;
110mod move_joint;
111pub use move_joint::MoveJoint;
112mod cache;
113pub use cache::Cache;
114mod audio;
115pub use audio::Audio;
116mod audio_bus;
117pub use audio_bus::AudioBus;
118mod audio_source;
119pub use audio_source::AudioSource;
120mod video_node;
121pub use video_node::VideoNode;
122mod tic80_node;
123pub use tic80_node::TIC80Node;
124mod keyboard;
125pub use keyboard::Keyboard;
126mod mouse;
127pub use mouse::Mouse;
128mod controller;
129pub use controller::Controller;
130mod svg;
131pub use svg::SVG;
132mod dbquery;
133pub use dbquery::DBQuery;
134mod dbparams;
135pub use dbparams::DBParams;
136mod dbrecord;
137pub use dbrecord::DBRecord;
138mod db;
139pub use db::DB;
140mod work_book;
141pub use work_book::WorkBook;
142mod work_sheet;
143pub use work_sheet::WorkSheet;
144mod c_45;
145mod q_learner;
146pub mod ml {
147	pub use super::c_45::C45;
148	pub use super::q_learner::QLearner;
149}
150mod http_client;
151pub use http_client::HttpClient;
152mod buffer;
153pub mod platformer;
154pub use buffer::Buffer;
155mod im_gui;
156pub use im_gui::ImGui;
157mod vgpaint;
158pub use vgpaint::VGPaint;
159mod nvg;
160pub use nvg::Nvg;
161mod vgnode;
162pub use vgnode::VGNode;
163
164type ObjectFunc = fn(i64) -> Option<Box<dyn IObject>>;
165
166thread_local! {
167	static OBJECT_MAP: LazyCell<Vec<Option<ObjectFunc>>> = LazyCell::new(|| {
168		let type_funcs = [
169			Array::type_info(),
170			Dictionary::type_info(),
171			Entity::type_info(),
172			Group::type_info(),
173			Observer::type_info(),
174			Scheduler::type_info(),
175			Camera::type_info(),
176			Camera2D::type_info(),
177			CameraOtho::type_info(),
178			Pass::type_info(),
179			Effect::type_info(),
180			SpriteEffect::type_info(),
181			Grabber::type_info(),
182			Action::type_info(),
183			Node::type_info(),
184			Texture2D::type_info(),
185			Sprite::type_info(),
186			Grid::type_info(),
187			Touch::type_info(),
188			Label::type_info(),
189			RenderTarget::type_info(),
190			ClipNode::type_info(),
191			DrawNode::type_info(),
192			Line::type_info(),
193			Particle::type_info(),
194			Playable::type_info(),
195			Model::type_info(),
196			Spine::type_info(),
197			DragonBone::type_info(),
198			AlignNode::type_info(),
199			EffekNode::type_info(),
200			TileNode::type_info(),
201			PhysicsWorld::type_info(),
202			FixtureDef::type_info(),
203			BodyDef::type_info(),
204			Sensor::type_info(),
205			Body::type_info(),
206			JointDef::type_info(),
207			Joint::type_info(),
208			MotorJoint::type_info(),
209			MoveJoint::type_info(),
210			SVG::type_info(),
211			AudioBus::type_info(),
212			AudioSource::type_info(),
213			VideoNode::type_info(),
214			TIC80Node::type_info(),
215			ml::QLearner::type_info(),
216			platformer::ActionUpdate::type_info(),
217			platformer::Face::type_info(),
218			platformer::BulletDef::type_info(),
219			platformer::Bullet::type_info(),
220			platformer::Visual::type_info(),
221			platformer::behavior::Tree::type_info(),
222			platformer::decision::Tree::type_info(),
223			platformer::Unit::type_info(),
224			platformer::PlatformCamera::type_info(),
225			platformer::PlatformWorld::type_info(),
226			Buffer::type_info(),
227			VGNode::type_info(),
228		];
229		let mut map: Vec<Option<ObjectFunc>> = Vec::new();
230		for pair in type_funcs.iter() {
231			let t = pair.0 as usize;
232			if map.len() < t + 1 {
233				map.resize(t + 1, None);
234			}
235			if map[t].is_some() {
236				panic!("cpp object type id {} duplicated!", t);
237			}
238			map[t] = Some(pair.1);
239		}
240		map
241	});
242	static FUNC_MAP: RefCell<Vec<Box<dyn FnMut()>>> = RefCell::new(Vec::new());
243	static FUNC_AVAILABLE: RefCell<Vec<i32>> = RefCell::new(Vec::new());
244}
245
246extern "C" {
247	fn object_get_id(obj: i64) -> i32;
248	fn object_get_type(obj: i64) -> i32;
249	fn object_retain(obj: i64);
250	fn object_release(obj: i64);
251
252	fn object_to_node(obj: i64) -> i64;
253	fn object_to_sprite(obj: i64) -> i64;
254	fn object_to_camera(obj: i64) -> i64;
255	fn object_to_playable(obj: i64) -> i64;
256	fn object_to_physics_world(obj: i64) -> i64;
257	fn object_to_body(obj: i64) -> i64;
258	fn object_to_joint(obj: i64) -> i64;
259
260	fn str_new(len: i32) -> i64;
261	fn str_len(str: i64) -> i32;
262	fn str_read(dest: *mut c_void, src: i64);
263	fn str_write(dest: i64, src: *const c_void);
264	fn str_release(str: i64);
265
266	fn buf_new_i32(len: i32) -> i64;
267	fn buf_new_i64(len: i32) -> i64;
268	fn buf_new_f32(len: i32) -> i64;
269	fn buf_new_f64(len: i32) -> i64;
270	fn buf_len(v: i64) -> i32;
271	fn buf_read(dest: *mut c_void, src: i64);
272	fn buf_write(dest: i64, src: *const c_void);
273	fn buf_release(v: i64);
274
275	fn value_create_i64(value: i64) -> i64;
276	fn value_create_f64(value: f64) -> i64;
277	fn value_create_str(value: i64) -> i64;
278	fn value_create_bool(value: i32) -> i64;
279	fn value_create_object(value: i64) -> i64;
280	fn value_create_vec2(value: i64) -> i64;
281	fn value_create_size(value: i64) -> i64;
282	fn value_release(value: i64);
283	fn value_into_i64(value: i64) -> i64;
284	fn value_into_f64(value: i64) -> f64;
285	fn value_into_str(value: i64) -> i64;
286	fn value_into_bool(value: i64) -> i32;
287	fn value_into_object(value: i64) -> i64;
288	fn value_into_vec2(value: i64) -> i64;
289	fn value_into_size(value: i64) -> i64;
290	fn value_is_i64(value: i64) -> i32;
291	fn value_is_f64(value: i64) -> i32;
292	fn value_is_str(value: i64) -> i32;
293	fn value_is_bool(value: i64) -> i32;
294	fn value_is_object(value: i64) -> i32;
295	fn value_is_vec2(value: i64) -> i32;
296	fn value_is_size(value: i64) -> i32;
297
298	fn call_stack_create() -> i64;
299	fn call_stack_release(info: i64);
300	fn call_stack_push_i64(info: i64, value: i64);
301	fn call_stack_push_f64(info: i64, value: f64);
302	fn call_stack_push_str(info: i64, value: i64);
303	fn call_stack_push_bool(info: i64, value: i32);
304	fn call_stack_push_object(info: i64, value: i64);
305	fn call_stack_push_vec2(info: i64, value: i64);
306	fn call_stack_push_size(info: i64, value: i64);
307	fn call_stack_pop_i64(info: i64) -> i64;
308	fn call_stack_pop_f64(info: i64) -> f64;
309	fn call_stack_pop_str(info: i64) -> i64;
310	fn call_stack_pop_bool(info: i64) -> i32;
311	fn call_stack_pop_object(info: i64) -> i64;
312	fn call_stack_pop_vec2(info: i64) -> i64;
313	fn call_stack_pop_size(info: i64) -> i64;
314	fn call_stack_pop(info: i64) -> i32;
315	fn call_stack_front_i64(info: i64) -> i32;
316	fn call_stack_front_f64(info: i64) -> i32;
317	fn call_stack_front_str(info: i64) -> i32;
318	fn call_stack_front_bool(info: i64) -> i32;
319	fn call_stack_front_object(info: i64) -> i32;
320	fn call_stack_front_vec2(info: i64) -> i32;
321	fn call_stack_front_size(info: i64) -> i32;
322
323	fn dora_print(msg: i64);
324	fn dora_print_warning(msg: i64);
325	fn dora_print_error(msg: i64);
326
327	fn vec2_add(a: i64, b: i64) -> i64;
328	fn vec2_sub(a: i64, b: i64) -> i64;
329	fn vec2_mul(a: i64, b: i64) -> i64;
330	fn vec2_mul_float(a: i64, b: f32) -> i64;
331	fn vec2_div(a: i64, b: f32) -> i64;
332	fn vec2_distance(a: i64, b: i64) -> f32;
333	fn vec2_distance_squared(a: i64, b: i64) -> f32;
334	fn vec2_length(a: i64) -> f32;
335	fn vec2_angle(a: i64) -> f32;
336	fn vec2_normalize(a: i64) -> i64;
337	fn vec2_perp(a: i64) -> i64;
338	fn vec2_dot(a: i64, b: i64) -> f32;
339	fn vec2_clamp(a: i64, from: i64, to: i64) -> i64;
340
341	fn dora_emit(name: i64, stack: i64);
342}
343
344pub fn print(msg: &str) {
345	unsafe {
346		dora_print(from_string(msg));
347	}
348}
349
350pub fn print_warning(msg: &str) {
351	unsafe {
352		dora_print_warning(from_string(msg));
353	}
354}
355
356pub fn print_error(msg: &str) {
357	unsafe {
358		dora_print_error(from_string(msg));
359	}
360}
361
362/// Emits a global event with the given name and arguments to all listeners registered by `node.gslot()` function.
363///
364/// # Arguments
365///
366/// * eventName - The name of the event to emit.
367/// * stack - The data to pass to the global event listeners.
368///
369/// # Example
370///
371/// ```
372/// let mut node = Node::new();
373/// node.gslot("MyGlobalEvent", Box::new(|stack| {
374/// 	let (arg1, arg2) = match (stack.pop_str(), stack.pop_i64()) {
375/// 		(Some(arg1), Some(arg2)) => (arg1, arg2),
376/// 		_ => return,
377/// 	};
378/// 	p!("Event triggered: {}, {}", arg1, arg2);
379/// }));
380///
381/// emit("MyGlobalEvent", args!("Hello", 123));
382/// ```
383pub fn emit(name: &str, stack: CallStack) {
384	unsafe {
385		dora_emit(from_string(name), stack.raw());
386	}
387}
388
389#[macro_export]
390macro_rules! p {
391	() => {
392		dora_ssr::print("")
393	};
394	($($arg:tt)*) => {{
395		dora_ssr::print((format!($($arg)*)).as_str());
396	}};
397}
398
399/// A record representing a 2D vector with an x and y component.
400#[repr(C)]
401#[derive(Clone, Copy, PartialEq)]
402pub struct Vec2 {
403	pub x: f32,
404	pub y: f32,
405}
406
407impl Vec2 {
408	pub(crate) fn from(value: i64) -> Vec2 {
409		unsafe { LightValue { value: value }.vec2 }
410	}
411	pub(crate) fn into_i64(&self) -> i64 {
412		unsafe { LightValue { vec2: *self }.value }
413	}
414	pub fn new(x: f32, y: f32) -> Vec2 {
415		Vec2 { x: x, y: y }
416	}
417	pub fn zero() -> Vec2 {
418		Vec2 { x: 0.0, y: 0.0 }
419	}
420	pub fn is_zero(&self) -> bool {
421		self.x == 0.0 && self.y == 0.0
422	}
423
424	pub fn distance(&self, other: &Vec2) -> f32 {
425		unsafe { vec2_distance(self.into_i64(), other.into_i64()) }
426	}
427	pub fn distance_squared(&self, other: &Vec2) -> f32 {
428		unsafe { vec2_distance_squared(self.into_i64(), other.into_i64()) }
429	}
430	pub fn length(&self) -> f32 {
431		unsafe { vec2_length(self.into_i64()) }
432	}
433	pub fn angle(&self) -> f32 {
434		unsafe { vec2_angle(self.into_i64()) }
435	}
436	pub fn normalize(&self) -> Vec2 {
437		Vec2::from(unsafe { vec2_normalize(self.into_i64()) })
438	}
439	pub fn perp(&self) -> Vec2 {
440		Vec2::from(unsafe { vec2_perp(self.into_i64()) })
441	}
442	pub fn dot(&self, other: &Vec2) -> f32 {
443		unsafe { vec2_dot(self.into_i64(), other.into_i64()) }
444	}
445	pub fn clamp(&self, from: &Vec2, to: &Vec2) -> Vec2 {
446		Vec2::from(unsafe { vec2_clamp(self.into_i64(), from.into_i64(), to.into_i64()) })
447	}
448}
449
450impl std::ops::Add for Vec2 {
451	type Output = Vec2;
452	fn add(self, other: Vec2) -> Vec2 {
453		Vec2::from(unsafe { vec2_add(self.into_i64(), other.into_i64()) })
454	}
455}
456
457impl std::ops::Sub for Vec2 {
458	type Output = Vec2;
459	fn sub(self, other: Vec2) -> Vec2 {
460		Vec2::from(unsafe { vec2_sub(self.into_i64(), other.into_i64()) })
461	}
462}
463
464impl std::ops::Mul for Vec2 {
465	type Output = Vec2;
466	fn mul(self, other: Vec2) -> Vec2 {
467		Vec2::from(unsafe { vec2_mul(self.into_i64(), other.into_i64()) })
468	}
469}
470
471impl std::ops::Mul<f32> for Vec2 {
472	type Output = Vec2;
473	fn mul(self, other: f32) -> Vec2 {
474		Vec2::from(unsafe { vec2_mul_float(self.into_i64(), other) })
475	}
476}
477
478impl std::ops::Div<f32> for Vec2 {
479	type Output = Vec2;
480	fn div(self, other: f32) -> Vec2 {
481		Vec2::from(unsafe { vec2_div(self.into_i64(), other) })
482	}
483}
484
485/// A size object with a given width and height.
486#[repr(C)]
487#[derive(Clone, Copy, PartialEq)]
488pub struct Size {
489	pub width: f32,
490	pub height: f32,
491}
492
493impl Size {
494	pub fn new(width: f32, height: f32) -> Size {
495		Size { width: width, height: height }
496	}
497	pub fn zero() -> Size {
498		Size { width: 0.0, height: 0.0 }
499	}
500	pub fn is_zero(&self) -> bool {
501		self.width == 0.0 && self.height == 0.0
502	}
503	pub(crate) fn from(value: i64) -> Size {
504		unsafe { LightValue { value: value }.size }
505	}
506	pub(crate) fn into_i64(&self) -> i64 {
507		unsafe { LightValue { size: *self }.value }
508	}
509}
510
511#[repr(C)]
512union LightValue {
513	vec2: Vec2,
514	size: Size,
515	value: i64,
516}
517
518/// A color with red, green, blue, and alpha channels.
519#[repr(C)]
520#[derive(Clone, Copy)]
521pub struct Color {
522	pub b: u8,
523	pub g: u8,
524	pub r: u8,
525	pub a: u8,
526}
527
528#[repr(C)]
529union ColorValue {
530	color: Color,
531	value: i32,
532}
533
534impl Color {
535	pub const WHITE: Color = Color { r: 255, g: 255, b: 255, a: 255 };
536	pub const BLACK: Color = Color { r: 0, g: 0, b: 0, a: 255 };
537	pub const TRANSPARENT: Color = Color { r: 0, g: 0, b: 0, a: 0 };
538	pub fn new(argb: u32) -> Color {
539		let a = argb >> 24;
540		let r = (argb & 0x00ff0000) >> 16;
541		let g = (argb & 0x0000ff00) >> 8;
542		let b = argb & 0x000000ff;
543		Color { r: r as u8, g: g as u8, b: b as u8, a: a as u8 }
544	}
545	pub fn from(argb: i32) -> Color {
546		unsafe { ColorValue { value: argb }.color }
547	}
548	pub fn to_argb(&self) -> u32 {
549		(self.a as u32) << 24 | (self.r as u32) << 16 | (self.g as u32) << 8 | self.b as u32
550	}
551	pub fn to_color3(&self) -> Color3 {
552		Color3 { r: self.r, g: self.g, b: self.b }
553	}
554}
555
556/// A color with red, green and blue channels.
557#[repr(C)]
558#[derive(Clone, Copy)]
559pub struct Color3 {
560	pub b: u8,
561	pub g: u8,
562	pub r: u8,
563}
564
565#[repr(C)]
566#[derive(Clone, Copy)]
567struct Color3a {
568	color3: Color3,
569	a: u8,
570}
571
572#[repr(C)]
573union Color3Value {
574	color3a: Color3a,
575	value: i32,
576}
577
578impl Color3 {
579	pub const WHITE: Color3 = Color3 { r: 255, g: 255, b: 255 };
580	pub const BLACK: Color3 = Color3 { r: 0, g: 0, b: 0 };
581	pub fn new(rgb: u32) -> Color3 {
582		let r = (rgb & 0x00ff0000) >> 16;
583		let g = (rgb & 0x0000ff00) >> 8;
584		let b = rgb & 0x000000ff;
585		Color3 { r: r as u8, g: g as u8, b: b as u8 }
586	}
587	pub fn from(rgb: i32) -> Color3 {
588		unsafe { Color3Value { value: rgb }.color3a.color3 }
589	}
590	pub fn to_rgb(&self) -> u32 {
591		(self.r as u32) << 16 | (self.g as u32) << 8 | self.b as u32
592	}
593}
594
595fn to_string(str: i64) -> String {
596	unsafe {
597		let len = str_len(str) as usize;
598		let mut vec = Vec::with_capacity(len as usize);
599		vec.resize(len, 0);
600		let data = vec.as_mut_ptr() as *mut c_void;
601		str_read(data, str);
602		str_release(str);
603		return String::from_utf8(vec).unwrap();
604	}
605}
606
607fn from_string(s: &str) -> i64 {
608	unsafe {
609		let len = s.len() as i32;
610		let ptr = s.as_ptr();
611		let new_str = str_new(len);
612		str_write(new_str, ptr as *const c_void);
613		return new_str;
614	}
615}
616
617pub(crate) trait IBuf {
618	fn to_buf(&self) -> i64;
619}
620
621impl IBuf for Vec<i32> {
622	fn to_buf(&self) -> i64 {
623		unsafe {
624			let len = self.len() as i32;
625			let ptr = self.as_ptr();
626			let new_vec = buf_new_i32(len);
627			buf_write(new_vec, ptr as *const c_void);
628			return new_vec;
629		}
630	}
631}
632
633impl IBuf for Vec<i64> {
634	fn to_buf(&self) -> i64 {
635		unsafe {
636			let len = self.len() as i32;
637			let ptr = self.as_ptr();
638			let new_vec = buf_new_i64(len);
639			buf_write(new_vec, ptr as *const c_void);
640			return new_vec;
641		}
642	}
643}
644
645impl IBuf for Vec<f32> {
646	fn to_buf(&self) -> i64 {
647		unsafe {
648			let len = self.len() as i32;
649			let ptr = self.as_ptr();
650			let new_vec = buf_new_f32(len);
651			buf_write(new_vec, ptr as *const c_void);
652			return new_vec;
653		}
654	}
655}
656
657impl IBuf for Vec<f64> {
658	fn to_buf(&self) -> i64 {
659		unsafe {
660			let len = self.len() as i32;
661			let ptr = self.as_ptr();
662			let new_vec = buf_new_f64(len);
663			buf_write(new_vec, ptr as *const c_void);
664			return new_vec;
665		}
666	}
667}
668
669pub(crate) struct Vector;
670
671impl Vector {
672	pub fn to_num<T>(v: i64) -> Vec<T>
673	where
674		T: Clone + Default,
675	{
676		unsafe {
677			let len = buf_len(v) as usize;
678			let mut vec: Vec<T> = Vec::with_capacity(len as usize);
679			vec.resize(len, Default::default());
680			let data = vec.as_mut_ptr() as *mut c_void;
681			buf_read(data, v);
682			buf_release(v);
683			return vec;
684		}
685	}
686	pub fn to_str(v: i64) -> Vec<String> {
687		unsafe {
688			let len = buf_len(v) as usize;
689			let mut vec: Vec<i64> = Vec::with_capacity(len as usize);
690			vec.resize(len, Default::default());
691			let data = vec.as_mut_ptr() as *mut c_void;
692			buf_read(data, v);
693			let mut strs = Vec::with_capacity(vec.len());
694			for i in 0..vec.len() {
695				strs.push(to_string(vec[i]));
696			}
697			buf_release(v);
698			strs
699		}
700	}
701	pub fn from_num<T: IBuf>(s: &T) -> i64 {
702		return s.to_buf();
703	}
704	pub fn from_str(s: &Vec<&str>) -> i64 {
705		unsafe {
706			let len = s.len() as i32;
707			let mut strs: Vec<i64> = Vec::with_capacity(s.len());
708			for i in 0..s.len() {
709				strs.push(from_string(s[i]));
710			}
711			let ptr = strs.as_ptr();
712			let new_vec = buf_new_i64(len);
713			buf_write(new_vec, ptr as *const c_void);
714			return new_vec;
715		}
716	}
717	pub fn from_vec2(s: &Vec<Vec2>) -> i64 {
718		unsafe {
719			let len = s.len() as i32;
720			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
721			for i in 0..s.len() {
722				vs.push(LightValue { vec2: s[i] }.value);
723			}
724			let ptr = vs.as_ptr();
725			let new_vec = buf_new_i64(len);
726			buf_write(new_vec, ptr as *const c_void);
727			return new_vec;
728		}
729	}
730	pub fn from_vertex_color(s: &Vec<VertexColor>) -> i64 {
731		unsafe {
732			let len = s.len() as i32;
733			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
734			for i in 0..s.len() {
735				vs.push(s[i].raw());
736			}
737			let ptr = vs.as_ptr();
738			let new_vec = buf_new_i64(len);
739			buf_write(new_vec, ptr as *const c_void);
740			return new_vec;
741		}
742	}
743	pub fn from_action_def(s: &Vec<ActionDef>) -> i64 {
744		unsafe {
745			let len = s.len() as i32;
746			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
747			for i in 0..s.len() {
748				vs.push(s[i].raw());
749			}
750			let ptr = vs.as_ptr();
751			let new_vec = buf_new_i64(len);
752			buf_write(new_vec, ptr as *const c_void);
753			return new_vec;
754		}
755	}
756	pub fn from_btree(s: &Vec<platformer::behavior::Tree>) -> i64 {
757		unsafe {
758			let len = s.len() as i32;
759			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
760			for i in 0..s.len() {
761				vs.push(s[i].raw());
762			}
763			let ptr = vs.as_ptr();
764			let new_vec = buf_new_i64(len);
765			buf_write(new_vec, ptr as *const c_void);
766			return new_vec;
767		}
768	}
769	pub fn from_dtree(s: &Vec<platformer::decision::Tree>) -> i64 {
770		unsafe {
771			let len = s.len() as i32;
772			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
773			for i in 0..s.len() {
774				vs.push(s[i].raw());
775			}
776			let ptr = vs.as_ptr();
777			let new_vec = buf_new_i64(len);
778			buf_write(new_vec, ptr as *const c_void);
779			return new_vec;
780		}
781	}
782}
783
784fn into_object(raw: i64) -> Option<Box<dyn IObject>> {
785	let mut converted: Option<Box<dyn IObject>> = None;
786	OBJECT_MAP.with(|map| converted = map[unsafe { object_get_type(raw) } as usize].unwrap()(raw));
787	converted
788}
789
790fn new_object(raw: i64) -> Option<Box<dyn IObject>> {
791	unsafe {
792		object_retain(raw);
793	}
794	let mut converted: Option<Box<dyn IObject>> = None;
795	OBJECT_MAP.with(|map| converted = map[unsafe { object_get_type(raw) } as usize].unwrap()(raw));
796	converted
797}
798
799fn push_function(func: Box<dyn FnMut()>) -> i32 {
800	#[cfg(target_arch = "wasm32")]
801	let flag = unsafe { dora_wasm_module_id() << 24 };
802	#[cfg(not(target_arch = "wasm32"))]
803	let flag = 0x00000000;
804	let mut ret_func_id = -1;
805	FUNC_MAP.with_borrow_mut(|map| {
806		if map.len() >= 0xffffff {
807			panic!("too many functions!");
808		}
809		FUNC_AVAILABLE.with_borrow_mut(|available| {
810			if let Some(func_id) = available.pop() {
811				map[func_id as usize] = func;
812				ret_func_id = func_id | flag;
813			} else {
814				map.push(func);
815				ret_func_id = (map.len() - 1) as i32 | flag
816			}
817		})
818	});
819	ret_func_id
820}
821
822#[no_mangle]
823pub extern "C" fn dora_wasm_version() -> i32 {
824	const MAJOR: &str = env!("CARGO_PKG_VERSION_MAJOR");
825	const MINOR: &str = env!("CARGO_PKG_VERSION_MINOR");
826	const PATCH: &str = env!("CARGO_PKG_VERSION_PATCH");
827	(MAJOR.parse::<i32>().unwrap() << 16)
828		| (MINOR.parse::<i32>().unwrap() << 8)
829		| PATCH.parse::<i32>().unwrap()
830}
831
832#[no_mangle]
833pub extern "C" fn call_function(func_id: i32) {
834	let real_id = func_id & 0x00ffffff;
835	let mut func: *mut Box<dyn FnMut()> = std::ptr::null_mut();
836	FUNC_MAP.with_borrow_mut(|map| {
837		func = &mut map[real_id as usize];
838	});
839	unsafe {
840		(*func)();
841	}
842}
843
844fn dummy_func() {
845	panic!("the dummy function should not be called.");
846}
847
848#[no_mangle]
849pub extern "C" fn deref_function(func_id: i32) {
850	let real_id = func_id & 0x00ffffff;
851	FUNC_MAP.with_borrow_mut(|map| {
852		map[real_id as usize] = Box::new(dummy_func);
853		FUNC_AVAILABLE.with_borrow_mut(|available| {
854			available.push(real_id);
855		});
856	});
857}
858
859pub trait IObject {
860	fn raw(&self) -> i64;
861	fn obj(&self) -> &dyn IObject;
862	fn get_id(&self) -> i32 {
863		unsafe { object_get_id(self.raw()) }
864	}
865	fn as_any(&self) -> &dyn Any;
866}
867
868pub struct Object {
869	raw: i64,
870}
871impl IObject for Object {
872	fn raw(&self) -> i64 {
873		self.raw
874	}
875	fn obj(&self) -> &dyn IObject {
876		self
877	}
878	fn as_any(&self) -> &dyn std::any::Any {
879		self
880	}
881}
882impl Drop for Object {
883	fn drop(&mut self) {
884		unsafe {
885			crate::dora::object_release(self.raw);
886		}
887	}
888}
889impl Clone for Object {
890	fn clone(&self) -> Object {
891		unsafe {
892			crate::dora::object_retain(self.raw);
893		}
894		Object { raw: self.raw }
895	}
896}
897impl Object {
898	pub(crate) fn from(raw: i64) -> Option<Object> {
899		match raw {
900			0 => None,
901			_ => Some(Object { raw: raw }),
902		}
903	}
904}
905
906pub fn cast<T: Clone + 'static>(obj: &dyn IObject) -> Option<T> {
907	Some(new_object(obj.raw())?.as_any().downcast_ref::<T>()?.clone())
908}
909
910/// An argument stack for passing values to a function.
911/// The stack is used to pass arguments to a function and to receive return values from a function.
912pub struct CallStack {
913	raw: i64,
914}
915
916pub enum DoraValue<'a> {
917	I32(i32),
918	I64(i64),
919	F32(f32),
920	F64(f64),
921	Bool(bool),
922	Str(&'a str),
923	Object(&'a dyn IObject),
924	Vec2(Vec2),
925	Size(Size),
926}
927
928pub trait IntoValue<'a> {
929	fn dora_val(self) -> DoraValue<'a>;
930	fn val(self) -> Value;
931}
932
933impl<'a> DoraValue<'a> {
934	pub fn push(self, info: &mut CallStack) {
935		match self {
936			DoraValue::I32(x) => info.push_i32(x),
937			DoraValue::I64(x) => info.push_i64(x),
938			DoraValue::F32(x) => info.push_f32(x),
939			DoraValue::F64(x) => info.push_f64(x),
940			DoraValue::Bool(x) => info.push_bool(x),
941			DoraValue::Str(x) => info.push_str(x),
942			DoraValue::Object(x) => info.push_object(x),
943			DoraValue::Vec2(x) => info.push_vec2(&x),
944			DoraValue::Size(x) => info.push_size(&x),
945		}
946	}
947}
948
949impl<'a> IntoValue<'a> for i32 {
950	fn dora_val(self) -> DoraValue<'a> {
951		DoraValue::I32(self)
952	}
953	fn val(self) -> Value {
954		unsafe { Value { raw: value_create_i64(self as i64) } }
955	}
956}
957
958impl<'a> IntoValue<'a> for i64 {
959	fn dora_val(self) -> DoraValue<'a> {
960		DoraValue::I64(self)
961	}
962	fn val(self) -> Value {
963		unsafe { Value { raw: value_create_i64(self) } }
964	}
965}
966
967impl<'a> IntoValue<'a> for f32 {
968	fn dora_val(self) -> DoraValue<'a> {
969		DoraValue::F32(self)
970	}
971	fn val(self) -> Value {
972		unsafe { Value { raw: value_create_f64(self as f64) } }
973	}
974}
975
976impl<'a> IntoValue<'a> for f64 {
977	fn dora_val(self) -> DoraValue<'a> {
978		DoraValue::F64(self)
979	}
980	fn val(self) -> Value {
981		unsafe { Value { raw: value_create_f64(self) } }
982	}
983}
984
985impl<'a> IntoValue<'a> for bool {
986	fn dora_val(self) -> DoraValue<'a> {
987		DoraValue::Bool(self)
988	}
989	fn val(self) -> Value {
990		unsafe { Value { raw: value_create_bool(if self { 1 } else { 0 }) } }
991	}
992}
993
994impl<'a> IntoValue<'a> for &'a str {
995	fn dora_val(self) -> DoraValue<'a> {
996		DoraValue::Str(self)
997	}
998	fn val(self) -> Value {
999		unsafe { Value { raw: value_create_str(from_string(self)) } }
1000	}
1001}
1002
1003impl<'a> IntoValue<'a> for &'a dyn IObject {
1004	fn dora_val(self) -> DoraValue<'a> {
1005		DoraValue::Object(self)
1006	}
1007	fn val(self) -> Value {
1008		unsafe { Value { raw: value_create_object(self.raw()) } }
1009	}
1010}
1011
1012impl<'a> IntoValue<'a> for Vec2 {
1013	fn dora_val(self) -> DoraValue<'a> {
1014		DoraValue::Vec2(self)
1015	}
1016	fn val(self) -> Value {
1017		unsafe { Value { raw: value_create_vec2(self.into_i64()) } }
1018	}
1019}
1020
1021impl<'a> IntoValue<'a> for Size {
1022	fn dora_val(self) -> DoraValue<'a> {
1023		DoraValue::Size(self)
1024	}
1025	fn val(self) -> Value {
1026		unsafe { Value { raw: value_create_size(self.into_i64()) } }
1027	}
1028}
1029
1030#[macro_export]
1031macro_rules! args {
1032	( $( $x:expr ),* ) => {
1033		{
1034			let mut stack = dora_ssr::CallStack::new();
1035			$(
1036				dora_ssr::Value::new($x).push(&mut stack);
1037			)*
1038			stack
1039		}
1040	};
1041}
1042
1043#[macro_export]
1044macro_rules! dora_object {
1045	($name: ident) => {
1046		paste::paste! {
1047			 impl IObject for $name {
1048				fn raw(&self) -> i64 { self.raw }
1049				fn obj(&self) -> &dyn IObject { self }
1050				fn as_any(&self) -> &dyn std::any::Any { self }
1051			}
1052			impl Drop for $name {
1053				fn drop(&mut self) { unsafe { crate::dora::object_release(self.raw); } }
1054			}
1055			impl Clone for $name {
1056				fn clone(&self) -> $name {
1057					unsafe { crate::dora::object_retain(self.raw); }
1058					$name { raw: self.raw }
1059				}
1060			}
1061			impl $name {
1062				#[allow(dead_code)]
1063				pub(crate) fn from(raw: i64) -> Option<$name> {
1064					match raw {
1065						0 => None,
1066						_ => Some($name { raw: raw })
1067					}
1068				}
1069			}
1070		}
1071	};
1072}
1073
1074// Value
1075
1076pub struct Value {
1077	raw: i64,
1078}
1079
1080impl Value {
1081	pub fn new<'a, A>(value: A) -> DoraValue<'a>
1082	where
1083		A: IntoValue<'a>,
1084	{
1085		value.dora_val()
1086	}
1087	fn from(raw: i64) -> Option<Value> {
1088		match raw {
1089			0 => None,
1090			_ => Some(Value { raw: raw }),
1091		}
1092	}
1093	pub fn raw(&self) -> i64 {
1094		self.raw
1095	}
1096	pub fn into_i32(&self) -> Option<i32> {
1097		unsafe {
1098			if value_is_i64(self.raw) != 0 {
1099				Some(value_into_i64(self.raw) as i32)
1100			} else {
1101				None
1102			}
1103		}
1104	}
1105	pub fn into_i64(&self) -> Option<i64> {
1106		unsafe {
1107			if value_is_i64(self.raw) != 0 {
1108				Some(value_into_i64(self.raw))
1109			} else {
1110				None
1111			}
1112		}
1113	}
1114	pub fn into_f32(&self) -> Option<f32> {
1115		unsafe {
1116			if value_is_f64(self.raw) != 0 {
1117				Some(value_into_f64(self.raw) as f32)
1118			} else {
1119				None
1120			}
1121		}
1122	}
1123	pub fn into_f64(&self) -> Option<f64> {
1124		unsafe {
1125			if value_is_f64(self.raw) != 0 {
1126				Some(value_into_f64(self.raw))
1127			} else {
1128				None
1129			}
1130		}
1131	}
1132	pub fn into_bool(&self) -> Option<bool> {
1133		unsafe {
1134			if value_is_bool(self.raw) != 0 {
1135				Some(value_into_bool(self.raw) != 0)
1136			} else {
1137				None
1138			}
1139		}
1140	}
1141	pub fn into_str(&self) -> Option<String> {
1142		unsafe {
1143			if value_is_str(self.raw) != 0 {
1144				Some(to_string(value_into_str(self.raw)))
1145			} else {
1146				None
1147			}
1148		}
1149	}
1150	pub fn into_object(&self) -> Option<Box<dyn IObject>> {
1151		unsafe {
1152			if value_is_object(self.raw) != 0 {
1153				into_object(value_into_object(self.raw))
1154			} else {
1155				None
1156			}
1157		}
1158	}
1159	pub fn into_node(&self) -> Option<Node> {
1160		Node::cast(self.into_object()?.as_ref())
1161	}
1162	pub fn into_camera(&self) -> Option<Camera> {
1163		Camera::cast(self.into_object()?.as_ref())
1164	}
1165	pub fn into_playable(&self) -> Option<Playable> {
1166		Playable::cast(self.into_object()?.as_ref())
1167	}
1168	pub fn into_physics_world(&self) -> Option<PhysicsWorld> {
1169		PhysicsWorld::cast(self.into_object()?.as_ref())
1170	}
1171	pub fn into_body(&self) -> Option<Body> {
1172		Body::cast(self.into_object()?.as_ref())
1173	}
1174	pub fn into_joint(&self) -> Option<Joint> {
1175		Joint::cast(self.into_object()?.as_ref())
1176	}
1177	pub fn into_vec2(&self) -> Option<Vec2> {
1178		unsafe {
1179			if value_is_vec2(self.raw) != 0 {
1180				Some(Vec2::from(value_into_vec2(self.raw)))
1181			} else {
1182				None
1183			}
1184		}
1185	}
1186	pub fn into_size(&self) -> Option<Size> {
1187		unsafe {
1188			if value_is_size(self.raw) != 0 {
1189				Some(Size::from(value_into_size(self.raw)))
1190			} else {
1191				None
1192			}
1193		}
1194	}
1195	pub fn cast<T: Clone + 'static>(&self) -> Option<T> {
1196		cast::<T>(self.into_object()?.as_ref())
1197	}
1198}
1199
1200impl Drop for Value {
1201	fn drop(&mut self) {
1202		unsafe {
1203			value_release(self.raw);
1204		}
1205	}
1206}
1207
1208// CallStack
1209
1210impl CallStack {
1211	fn raw(&self) -> i64 {
1212		self.raw
1213	}
1214	pub fn new() -> CallStack {
1215		CallStack { raw: unsafe { call_stack_create() } }
1216	}
1217	pub fn push_i32(&mut self, value: i32) {
1218		unsafe {
1219			call_stack_push_i64(self.raw, value as i64);
1220		}
1221	}
1222	pub fn push_i64(&mut self, value: i64) {
1223		unsafe {
1224			call_stack_push_i64(self.raw, value);
1225		}
1226	}
1227	pub fn push_f32(&mut self, value: f32) {
1228		unsafe {
1229			call_stack_push_f64(self.raw, value as f64);
1230		}
1231	}
1232	pub fn push_f64(&mut self, value: f64) {
1233		unsafe {
1234			call_stack_push_f64(self.raw, value);
1235		}
1236	}
1237	pub fn push_str(&mut self, value: &str) {
1238		unsafe {
1239			call_stack_push_str(self.raw, from_string(value));
1240		}
1241	}
1242	pub fn push_bool(&mut self, value: bool) {
1243		unsafe {
1244			call_stack_push_bool(self.raw, if value { 1 } else { 0 });
1245		}
1246	}
1247	pub fn push_object(&mut self, value: &dyn IObject) {
1248		unsafe {
1249			call_stack_push_object(self.raw, value.raw());
1250		}
1251	}
1252	pub fn push_vec2(&mut self, value: &Vec2) {
1253		unsafe {
1254			call_stack_push_vec2(self.raw, value.into_i64());
1255		}
1256	}
1257	pub fn push_size(&mut self, value: &Size) {
1258		unsafe {
1259			call_stack_push_size(self.raw, value.into_i64());
1260		}
1261	}
1262	/// Pops the value from the stack if it is a i32.
1263	pub fn pop_i32(&mut self) -> Option<i32> {
1264		unsafe {
1265			if call_stack_front_i64(self.raw) != 0 {
1266				Some(call_stack_pop_i64(self.raw) as i32)
1267			} else {
1268				None
1269			}
1270		}
1271	}
1272	/// Pops the value from the stack if it is a i64.
1273	pub fn pop_i64(&mut self) -> Option<i64> {
1274		unsafe {
1275			if call_stack_front_i64(self.raw) != 0 {
1276				Some(call_stack_pop_i64(self.raw))
1277			} else {
1278				None
1279			}
1280		}
1281	}
1282	/// Pops the value from the stack if it is a f32.
1283	pub fn pop_f32(&mut self) -> Option<f32> {
1284		unsafe {
1285			if call_stack_front_f64(self.raw) != 0 {
1286				Some(call_stack_pop_f64(self.raw) as f32)
1287			} else {
1288				None
1289			}
1290		}
1291	}
1292	/// Pops the value from the stack if it is a f64.
1293	pub fn pop_f64(&mut self) -> Option<f64> {
1294		unsafe {
1295			if call_stack_front_f64(self.raw) != 0 {
1296				Some(call_stack_pop_f64(self.raw))
1297			} else {
1298				None
1299			}
1300		}
1301	}
1302	/// Pops the value from the stack if it is a string.
1303	pub fn pop_str(&mut self) -> Option<String> {
1304		unsafe {
1305			if call_stack_front_str(self.raw) != 0 {
1306				Some(to_string(call_stack_pop_str(self.raw)))
1307			} else {
1308				None
1309			}
1310		}
1311	}
1312	/// Pops the value from the stack if it is a bool.
1313	pub fn pop_bool(&mut self) -> Option<bool> {
1314		unsafe {
1315			if call_stack_front_bool(self.raw) != 0 {
1316				Some(call_stack_pop_bool(self.raw) != 0)
1317			} else {
1318				None
1319			}
1320		}
1321	}
1322	/// Pops the value from the stack if it is a Vec2 object.
1323	pub fn pop_vec2(&mut self) -> Option<Vec2> {
1324		unsafe {
1325			if call_stack_front_vec2(self.raw) != 0 {
1326				Some(Vec2::from(call_stack_pop_vec2(self.raw)))
1327			} else {
1328				None
1329			}
1330		}
1331	}
1332	/// Pops the value from the stack if it is a Size object.
1333	pub fn pop_size(&mut self) -> Option<Size> {
1334		unsafe {
1335			if call_stack_front_size(self.raw) != 0 {
1336				Some(Size::from(call_stack_pop_size(self.raw)))
1337			} else {
1338				None
1339			}
1340		}
1341	}
1342	/// Pops the value from the stack if it is an object.
1343	pub fn pop_object(&mut self) -> Option<Box<dyn IObject>> {
1344		unsafe {
1345			if call_stack_front_object(self.raw) != 0 {
1346				let raw = call_stack_pop_object(self.raw);
1347				into_object(raw)
1348			} else {
1349				None
1350			}
1351		}
1352	}
1353	/// Pops the value from the stack and then converts it to a Node. If the value on the stack is not a object or the object can not be converted to a Node, this function returns None.
1354	/// This function is the same as `Node::cast(stack.pop_object()?.as_ref())`.
1355	pub fn pop_into_node(&mut self) -> Option<Node> {
1356		Node::cast(self.pop_object()?.as_ref())
1357	}
1358	/// Pops the value from the stack and then converts it to a Camera. If the value on the stack is not a object or the object can not be converted to a Camera, this function returns None.
1359	/// This function is the same as `Camera::cast(stack.pop_object()?.as_ref())`.
1360	pub fn pop_into_camera(&mut self) -> Option<Camera> {
1361		Camera::cast(self.pop_object()?.as_ref())
1362	}
1363	/// Pops the value from the stack and then converts it to a Playable. If the value on the stack is not a object or the object can not be converted to a Playable, this function returns None.
1364	/// This function is the same as `Playable::cast(stack.pop_object()?.as_ref())`.
1365	pub fn pop_into_playable(&mut self) -> Option<Playable> {
1366		Playable::cast(self.pop_object()?.as_ref())
1367	}
1368	/// Pops the value from the stack and then converts it to a PhysicsWorld. If the value on the stack is not a object or the object can not be converted to a PhysicsWorld, this function returns None.
1369	/// This function is the same as `PhysicsWorld::cast(stack.pop_object()?.as_ref())`.
1370	pub fn pop_into_physics_world(&mut self) -> Option<PhysicsWorld> {
1371		PhysicsWorld::cast(self.pop_object()?.as_ref())
1372	}
1373	/// Pops the value from the stack and then converts it to a Body. If the value on the stack is not a object or the object can not be converted to a Body, this function returns None.
1374	/// This function is the same as `Body::cast(stack.pop_object()?.as_ref())`.
1375	pub fn pop_into_body(&mut self) -> Option<Body> {
1376		Body::cast(self.pop_object()?.as_ref())
1377	}
1378	/// Pops the value from the stack and then converts it to a Joint. If the value on the stack is not a object or the object can not be converted to a Joint, this function returns None.
1379	/// This function is the same as `Joint::cast(stack.pop_object()?.as_ref())`.
1380	pub fn pop_into_joint(&mut self) -> Option<Joint> {
1381		Joint::cast(self.pop_object()?.as_ref())
1382	}
1383	/// Pops a value from the stack and then casts it to the specified type. If the value on the stack is not a object or can not be casted, it returns None.
1384	/// This function is the same as `cast::<T>(stack.pop_object()?.as_ref())`.
1385	pub fn pop_cast<T: Clone + 'static>(&mut self) -> Option<T> {
1386		cast::<T>(self.pop_object()?.as_ref())
1387	}
1388	/// Pops a value from the stack.
1389	/// Returns true if a value was popped, otherwise false.
1390	pub fn pop(&mut self) -> bool {
1391		if unsafe { call_stack_pop(self.raw) } == 0 {
1392			return false;
1393		}
1394		true
1395	}
1396}
1397
1398impl Drop for CallStack {
1399	fn drop(&mut self) {
1400		unsafe {
1401			call_stack_release(self.raw);
1402		}
1403	}
1404}
1405
1406/// An interface for providing Dora SSR built-in node event names.
1407pub struct Slot {}
1408impl Slot {
1409	/// The ActionEnd slot is triggered when an action is finished.
1410	/// Triggers after calling `node.run_action()`, `node.perform()`, `node.run_action_def()` and `node.perform_def()`.
1411	///
1412	/// # Callback Arguments
1413	///
1414	/// * action: Action - The finished action.
1415	/// * target: Node - The node that finished the action.
1416	///
1417	/// # Callback Example
1418	///
1419	/// ```
1420	/// node.perform_def(ActionDef::prop(1.0, 0.0, 100.0, Property::X, EaseType::Linear));
1421	/// node.slot(Slot::ACTION_END, Box::new(|stack| {
1422	/// 	let (
1423	/// 		action,
1424	/// 		node
1425	/// 	) = match (
1426	/// 		stack.pop_cast::<Action>(),
1427	/// 		stack.pop_into_node()
1428	/// 	) {
1429	/// 		(Some(action), Some(node)) => (action, node),
1430	/// 		_ => return,
1431	/// 	};
1432	/// }));
1433	/// ```
1434	pub const ACTION_END: &'static str = "Action";
1435	/// The TapFilter slot is triggered before the TapBegan slot and can be used to filter out certain taps.
1436	/// Triggers after setting `node.set_touch_enabled(true)`.
1437	///
1438	/// # Callback Arguments
1439	///
1440	/// * touch: Touch - The touch that triggered the tap.
1441	///
1442	/// # Callback Example
1443	///
1444	/// ```
1445	/// node.set_touch_enabled(true);
1446	/// node.slot(Slot::TAP_FILTER, Box::new(|stack| {
1447	/// 	let touch = match stack.pop_cast::<Touch>() {
1448	/// 		Some(touch) => touch,
1449	/// 		None => return,
1450	/// 	};
1451	/// 	touch.set_enabled(false);
1452	/// }));
1453	/// ```
1454	pub const TAP_FILTER: &'static str = "TapFilter";
1455	/// The TapBegan slot is triggered when a tap is detected.
1456	/// Triggers after setting `node.set_touch_enabled(true)`.
1457	///
1458	/// # Callback Arguments
1459	///
1460	/// * touch: Touch - The touch that triggered the tap.
1461	///
1462	/// # Callback Example
1463	///
1464	/// ```
1465	/// node.set_touch_enabled(true);
1466	/// node.slot(Slot::TAP_BEGAN, Box::new(|stack| {
1467	/// 	let touch = match stack.pop_cast::<Touch>() {
1468	/// 		Some(touch) => touch,
1469	/// 		None => return,
1470	/// 	};
1471	/// }));
1472	/// ```
1473	pub const TAP_BEGAN: &'static str = "TapBegan";
1474	/// The TapEnded slot is triggered when a tap ends.
1475	/// Triggers after setting `node.set_touch_enabled(true)`.
1476	///
1477	/// # Callback Arguments
1478	///
1479	/// * touch: Touch - The touch that triggered the tap.
1480	///
1481	/// # Callback Example
1482	///
1483	/// ```
1484	/// node.set_touch_enabled(true);
1485	/// node.slot(Slot::TAP_ENDED, Box::new(|stack| {
1486	/// 	let touch = match stack.pop_cast::<Touch>() {
1487	/// 		Some(touch) => touch,
1488	/// 		None => return,
1489	/// 	};
1490	/// }));
1491	/// ```
1492	pub const TAP_ENDED: &'static str = "TapEnded";
1493	/// The Tapped slot is triggered when a tap is detected and has ended.
1494	/// Triggers after setting `node.set_touch_enabled(true)`.
1495	///
1496	/// # Callback Arguments
1497	///
1498	/// * touch: Touch - The touch that triggered the tap.
1499	///
1500	/// # Callback Example
1501	///
1502	/// ```
1503	/// node.set_touch_enabled(true);
1504	/// node.slot(Slot::TAPPED, Box::new(|stack| {
1505	/// 	let touch = match stack.pop_cast::<Touch>() {
1506	/// 		Some(touch) => touch,
1507	/// 		None => return,
1508	/// 	};
1509	/// }));
1510	/// ```
1511	pub const TAPPED: &'static str = "Tapped";
1512	/// The TapMoved slot is triggered when a tap moves.
1513	/// Triggers after setting `node.set_touch_enabled(true)`.
1514	///
1515	/// # Callback Arguments
1516	///
1517	/// * touch: Touch - The touch that triggered the tap.
1518	///
1519	/// # Callback Example
1520	///
1521	/// ```
1522	/// node.set_touch_enabled(true);
1523	/// node.slot(Slot::TAP_MOVED, Box::new(|stack| {
1524	/// 	let touch = match stack.pop_cast::<Touch>() {
1525	/// 		Some(touch) => touch,
1526	/// 		None => return,
1527	/// 	};
1528	/// }));
1529	/// ```
1530	pub const TAP_MOVED: &'static str = "TapMoved";
1531	/// The MouseWheel slot is triggered when the mouse wheel is scrolled.
1532	/// Triggers after setting `node.set_touch_enabled(true)`.
1533	///
1534	/// # Callback Arguments
1535	///
1536	/// * delta: Vec2 - The amount of scrolling that occurred.
1537	///
1538	/// # Callback Example
1539	///
1540	/// ```
1541	/// node.set_touch_enabled(true);
1542	/// node.slot(Slot::MOUSE_WHEEL, Box::new(|stack| {
1543	/// 	let delta = match stack.pop_vec2() {
1544	/// 		Some(delta) => delta,
1545	/// 		None => return,
1546	/// 	};
1547	/// }));
1548	/// ```
1549	pub const MOUSE_WHEEL: &'static str = "MouseWheel";
1550	/// The Gesture slot is triggered when a gesture is recognized.
1551	///
1552	/// # Callback Arguments
1553	///
1554	/// * center: Vec2 - The center of the gesture.
1555	/// * num_fingers: i32 - The number of fingers involved in the gesture.
1556	/// * delta_dist: f32 - The distance the gesture has moved.
1557	/// * delta_angle: f32 - The angle of the gesture.
1558	///
1559	/// # Callback Example
1560	///
1561	/// ```
1562	/// node.set_touch_enabled(true);
1563	/// node.slot(Slot::GESTURE, Box::new(|stack| {
1564	/// 	let (
1565	/// 		center,
1566	/// 		num_fingers,
1567	/// 		delta_dist,
1568	/// 		delta_angle
1569	/// 	) = match (
1570	/// 		stack.pop_vec2(),
1571	/// 		stack.pop_i32(),
1572	/// 		stack.pop_f32(),
1573	/// 		stack.pop_f32()
1574	/// 	) {
1575	/// 		(Some(center), Some(num_fingers), Some(delta_dist), Some(delta_angle)) => (center, num_fingers, delta_dist, delta_angle),
1576	/// 		_ => return,
1577	/// 	};
1578	/// }));
1579	/// ```
1580	pub const GESTURE: &'static str = "Gesture";
1581	/// The Enter slot is triggered when a node is added to the scene graph.
1582	/// Triggers when doing `node.add_child()`.
1583	pub const ENTER: &'static str = "Enter";
1584	/// The Exit slot is triggered when a node is removed from the scene graph.
1585	/// Triggers when doing `node.remove_child()`.
1586	pub const EXIT: &'static str = "Exit";
1587	/// The Cleanup slot is triggered when a node is cleaned up.
1588	/// Triggers only when doing `parent.remove_child(node, true)`.
1589	pub const CLEANUP: &'static str = "Cleanup";
1590	/// The KeyDown slot is triggered when a key is pressed down.
1591	/// Triggers after setting `node.set_keyboard_enabled(true)`.
1592	///
1593	/// # Callback Arguments
1594	///
1595	/// * key_name: String - The name of the key that was pressed.
1596	///
1597	/// # Callback Example
1598	///
1599	/// ```
1600	/// node.set_keyboard_enabled(true);
1601	/// node.slot(Slot::KEY_DOWN, Box::new(|stack| {
1602	/// 	let key_name = match stack.pop_str() {
1603	/// 		Some(key_name) => key_name,
1604	/// 		None => return,
1605	/// 	};
1606	/// 	if key_name == KeyName::Space.as_ref() {
1607	/// 		p!("Space key down!");
1608	/// 	}
1609	/// }));
1610	/// ```
1611	pub const KEY_DOWN: &'static str = "KeyDown";
1612	/// The KeyUp slot is triggered when a key is released.
1613	/// Triggers after setting `node.set_keyboard_enabled(true)`.
1614	///
1615	/// # Callback Arguments
1616	///
1617	/// * key_name: String - The name of the key that was released.
1618	///
1619	/// # Callback Example
1620	///
1621	/// ```
1622	/// node.set_keyboard_enabled(true);
1623	/// node.slot(Slot::KEY_UP, Box::new(|stack| {
1624	/// 	let key_name = match stack.pop_str() {
1625	/// 		Some(key_name) => key_name,
1626	/// 		None => return,
1627	/// 	};
1628	/// 	if key_name == KeyName::Space.as_ref() {
1629	/// 		p!("Space key up!");
1630	/// 	}
1631	/// }));
1632	/// ```
1633	pub const KEY_UP: &'static str = "KeyUp";
1634	/// The KeyPressed slot is triggered when a key is pressed.
1635	/// Triggers after setting `node.set_keyboard_enabled(true)`.
1636	///
1637	/// # Callback Arguments
1638	///
1639	/// * key_name: String - The name of the key that was pressed.
1640	///
1641	/// # Callback Example
1642	///
1643	/// ```
1644	/// node.set_keyboard_enabled(true);
1645	/// node.slot(Slot::KEY_PRESSED, Box::new(|stack| {
1646	/// 	let key_name = match stack.pop_str() {
1647	/// 		Some(key_name) => key_name,
1648	/// 		None => return,
1649	/// 	};
1650	/// 	if key_name == KeyName::Space.as_ref() {
1651	/// 		p!("Space key pressed!");
1652	/// 	}
1653	/// }));
1654	/// ```
1655	pub const KEY_PRESSED: &'static str = "KeyPressed";
1656	/// The AttachIME slot is triggered when the input method editor (IME) is attached (calling `node.attach_ime()`).
1657	pub const ATTACH_IME: &'static str = "AttachIME";
1658	/// The DetachIME slot is triggered when the input method editor (IME) is detached (calling `node.detach_ime()` or manually closing IME).
1659	pub const DETACH_IME: &'static str = "DetachIME";
1660	/// The TextInput slot is triggered when text input is received.
1661	/// Triggers after calling `node.attach_ime()`.
1662	///
1663	/// # Callback Arguments
1664	///
1665	/// * text: String - The text that was input.
1666	///
1667	/// # Callback Example
1668	///
1669	/// ```
1670	/// node.attach_ime();
1671	/// node.slot(Slot::TEXT_INPUT, Box::new(|stack| {
1672	/// 	let text = match stack.pop_str() {
1673	/// 		Some(text) => text,
1674	/// 		None => return,
1675	/// 	};
1676	/// 	p!(text);
1677	/// }));
1678	/// ```
1679	pub const TEXT_INPUT: &'static str = "TextInput";
1680	/// The TextEditing slot is triggered when text is being edited.
1681	/// Triggers after calling `node.attach_ime()`.
1682	///
1683	/// # Callback Arguments
1684	///
1685	/// * text: String - The text that is being edited.
1686	/// * start_pos: i32 - The starting position of the text being edited.
1687	///
1688	/// # Callback Example
1689	///
1690	/// ```
1691	/// node.attach_ime();
1692	/// node.slot(Slot::TEXT_EDITING, Box::new(|stack| {
1693	/// 	let (
1694	/// 		text,
1695	/// 		start_pos
1696	/// 	) = match (
1697	/// 		stack.pop_str(),
1698	/// 		stack.pop_i32()
1699	/// 	) {
1700	/// 		(Some(text), Some(start_pos)) => (text, start_pos),
1701	/// 		_ => return,
1702	/// 	};
1703	/// 	p!(text, start_pos);
1704	/// }));
1705	/// ```
1706	pub const TEXT_EDITING: &'static str = "TextEditing";
1707	/// The ButtonDown slot is triggered when a game controller button is pressed down.
1708	/// Triggers after setting `node.set_controller_enabled(true)`.
1709	///
1710	/// # Callback Arguments
1711	///
1712	/// * controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
1713	/// * button_name: String - The name of the button that was pressed.
1714	///
1715	/// # Callback Example
1716	///
1717	/// ```
1718	/// node.set_controller_enabled(true);
1719	/// node.slot(Slot::BUTTON_DOWN, Box::new(|stack| {
1720	/// 	let (
1721	/// 		controller_id,
1722	/// 		button_name
1723	/// 	) = match (
1724	/// 		stack.pop_i32(),
1725	/// 		stack.pop_str()
1726	/// 	) {
1727	/// 		(Some(controller_id), Some(button_name)) => (controller_id, button_name),
1728	/// 		_ => return,
1729	/// 	};
1730	/// 	if controller_id == 0 && button_name == ButtonName::DPUp.as_ref() {
1731	/// 		p!("DPad up button down!");
1732	/// 	}
1733	/// }));
1734	/// ```
1735	pub const BUTTON_DOWN: &'static str = "ButtonDown";
1736	/// The ButtonUp slot is triggered when a game controller button is released.
1737	/// Triggers after setting `node.set_controller_enabled(true)`.
1738	///
1739	/// # Callback Arguments
1740	///
1741	/// * controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
1742	/// * button_name: String - The name of the button that was released.
1743	///
1744	/// # Callback Example
1745	///
1746	/// ```
1747	/// node.set_controller_enabled(true);
1748	/// node.slot(Slot::BUTTON_UP, Box::new(|stack| {
1749	/// 	let (
1750	/// 		controller_id,
1751	/// 		button_name
1752	/// 	) = match (
1753	/// 		stack.pop_i32(),
1754	/// 		stack.pop_str()
1755	/// 	) {
1756	/// 		(Some(controller_id), Some(button_name)) => (controller_id, button_name),
1757	/// 		_ => return,
1758	/// 	};
1759	/// 	if controller_id == 0 && button_name == ButtonName::DPUp.as_ref() {
1760	/// 		p!("DPad up button up!");
1761	/// 	}
1762	/// }));
1763	/// ```
1764	pub const BUTTON_UP: &'static str = "ButtonUp";
1765	/// The ButtonPressed slot is triggered when a game controller button is being pressed.
1766	/// Triggers after setting `node.set_controller_enabled(true)`.
1767	/// This slot is triggered every frame while the button is being pressed.
1768	///
1769	/// # Callback Arguments
1770	///
1771	/// * controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
1772	/// * button_name: String - The name of the button that is being pressed.
1773	///
1774	/// # Callback Example
1775	///
1776	/// ```
1777	/// node.set_controller_enabled(true);
1778	/// node.slot(Slot::BUTTON_PRESSED, Box::new(|stack| {
1779	/// 	let (
1780	/// 		controller_id,
1781	/// 		button_name
1782	/// 	) = match (
1783	/// 		stack.pop_i32(),
1784	/// 		stack.pop_str()
1785	/// 	) {
1786	/// 		(Some(controller_id), Some(button_name)) => (controller_id, button_name),
1787	/// 		_ => return,
1788	/// 	};
1789	/// 	if controller_id == 0 && button_name == ButtonName::DPUp.as_ref() {
1790	/// 		p!("DPad up button pressed!");
1791	/// 	}
1792	/// }));
1793	/// ```
1794	pub const BUTTON_PRESSED: &'static str = "ButtonPressed";
1795	/// The Axis slot is triggered when a game controller axis changed.
1796	/// Triggers after setting `node.set_controller_enabled(true)`.
1797	///
1798	/// # Callback Arguments
1799	///
1800	/// * controllerId: i32 - The controller id, incrementing from 0 when multiple controllers connected.
1801	/// * axis_name: String - The name of the axis that changed.
1802	/// * axis_value: f32 - The controller axis value ranging from -1.0 to 1.0.
1803	///
1804	/// # Callback Example
1805	///
1806	/// ```
1807	/// node.set_controller_enabled(true);
1808	/// node.slot(Slot::AXIS, Box::new(|stack| {
1809	/// 	let (
1810	/// 		controller_id,
1811	/// 		axis_name,
1812	/// 		axis_value
1813	/// 	) = match (
1814	/// 		stack.pop_i32(),
1815	/// 		stack.pop_str(),
1816	/// 		stack.pop_f32()
1817	/// 	) {
1818	/// 		(Some(controller_id), Some(axis_name), Some(axis_value)) => (controller_id, axis_name, axis_value),
1819	/// 		_ => return,
1820	/// 	};
1821	/// 	if controller_id == 0 && axis_name == AxisName::LeftX.as_ref() {
1822	/// 		p!("Left stick x value {}", axis_value);
1823	/// 	}
1824	/// }));
1825	pub const AXIS: &'static str = "Axis";
1826	/// Triggers after an animation has ended on a Playable instance.
1827	///
1828	/// # Callback Arguments
1829	///
1830	/// * animation_name: String - The name of the animation that ended.
1831	/// * target: Playable - The Playable instance that the animation was played on.
1832	///
1833	/// # Callback Example
1834	///
1835	/// ```
1836	/// playable.play("Walk", false);
1837	/// playable.slot(Slot::ANIMATION_END, Box::new(|stack| {
1838	/// 	let (
1839	/// 		animation_name,
1840	/// 		playable
1841	/// 	) = match (
1842	/// 		stack.pop_str(),
1843	/// 		stack.pop_into_playable()
1844	/// 	) {
1845	/// 		(Some(animation_name), Some(playable)) => (animation_name, playable),
1846	/// 		_ => return,
1847	/// 	};
1848	/// 	if animation_name == "Walk" {
1849	/// 		playable.play("Idle", true);
1850	/// 	}
1851	/// }));
1852	/// ```
1853	pub const ANIMATION_END: &'static str = "AnimationEnd";
1854	/// Triggers when a Body object collides with a sensor object.
1855	/// Triggers when `Body` was attached with sensors.
1856	///
1857	/// # Callback Arguments
1858	///
1859	/// * other: Body - The other Body object that the current Body is colliding with.
1860	/// * sensorTag: i32 - The tag of the sensor that triggered this collision.
1861	///
1862	/// # Callback Example
1863	///
1864	/// ```
1865	/// body.slot(Slot::BODY_ENTER, Box::new(|stack| {
1866	/// 	let (
1867	/// 		other,
1868	/// 		sensor_tag
1869	/// 	) = match (
1870	/// 		stack.pop_into_body(),
1871	/// 		stack.pop_i32()
1872	/// 	) {
1873	/// 		(Some(other), Some(sensor_tag)) => (other, sensor_tag),
1874	/// 		_ => return,
1875	/// 	};
1876	/// 	p!(sensor_tag);
1877	/// }));
1878	/// ```
1879	pub const BODY_ENTER: &'static str = "BodyEnter";
1880	/// Triggers when a `Body` object is no longer colliding with a sensor object.
1881	/// Triggers when `Body` was attached with sensors.
1882	///
1883	/// # Callback Arguments
1884	///
1885	/// * other: Body - The other `Body` object that the current `Body` is no longer colliding with.
1886	/// * sensor_tag: i32 - The tag of the sensor that triggered this collision.
1887	///
1888	/// # Callback Example
1889	///
1890	/// ```
1891	/// body.slot(Slot::BODY_LEAVE, Box::new(|stack| {
1892	/// 	let (
1893	/// 		other,
1894	/// 		sensor_tag
1895	/// 	) = match (
1896	/// 		stack.pop_into_body(),
1897	/// 		stack.pop_i32()
1898	/// 	) {
1899	/// 		(Some(other), Some(sensor_tag)) => (other, sensor_tag),
1900	/// 		_ => return,
1901	/// 	};
1902	/// 	p!(sensor_tag);
1903	/// }));
1904	/// ```
1905	pub const BODY_LEAVE: &'static str = "BodyLeave";
1906	/// Triggers when a `Body` object starts to collide with another object.
1907	/// Triggers after setting `body.set_receiving_contact(true)`.
1908	///
1909	/// # Callback Arguments
1910	///
1911	/// * other: Body - The other `Body` object that the current `Body` is colliding with.
1912	/// * point: Vec2 - The point of collision in world coordinates.
1913	/// * normal: Vec2 - The normal vector of the contact surface in world coordinates.
1914	/// * enabled: bool - Whether the contact is enabled or not. Collisions that are filtered out will still trigger this event, but the enabled state will be false.
1915	///
1916	/// # Callback Example
1917	///
1918	/// ```
1919	/// body.set_receiving_contact(true);
1920	/// body.slot(Slot::CONTACT_START, Box::new(|stack| {
1921	/// 	let (
1922	/// 		other,
1923	/// 		point,
1924	/// 		normal,
1925	/// 		enabled
1926	/// 	) = match (
1927	/// 		stack.pop_into_body(),
1928	/// 		stack.pop_vec2(),
1929	/// 		stack.pop_vec2(),
1930	/// 		stack.pop_bool()
1931	/// 	) {
1932	/// 		(Some(other), Some(point), Some(normal), Some(enabled)) => (other, point, normal, enabled),
1933	/// 		_ => return,
1934	/// 	};
1935	/// }));
1936	/// ```
1937	pub const CONTACT_START: &'static str = "ContactStart";
1938	/// Triggers when a `Body` object stops colliding with another object.
1939	/// Triggers after setting `body.set_receiving_contact(true)`.
1940	///
1941	/// # Callback Arguments
1942	///
1943	/// * other: Body - The other `Body` object that the current `Body` is no longer colliding with.
1944	/// * point: Vec2 - The point of collision in world coordinates.
1945	/// * normal: Vec2 - The normal vector of the contact surface in world coordinates.
1946	///
1947	/// # Callback Example
1948	///
1949	/// ```
1950	/// body.set_receiving_contact(true);
1951	/// body.slot(Slot::CONTACT_END, Box::new(|stack| {
1952	/// 	let (
1953	/// 		other,
1954	/// 		point,
1955	/// 		normal
1956	/// 	) = match (
1957	/// 		stack.pop_into_body(),
1958	/// 		stack.pop_vec2(),
1959	/// 		stack.pop_vec2()
1960	/// 	) {
1961	/// 		(Some(other), Some(point), Some(normal)) => (other, point, normal),
1962	/// 		_ => return,
1963	/// 	};
1964	/// }));
1965	/// ```
1966	pub const CONTACT_END: &'static str = "ContactEnd";
1967	/// Triggered after a `Particle` node started a stop action and then all the active particles end their lives.
1968	pub const FINISHED: &'static str = "Finished";
1969	/// Triggers when the layout of the `AlignNode` is updated.
1970	///
1971	/// # Callback Arguments
1972	///
1973	/// * width: f32 - The width of the `AlignNode`.
1974	/// * height: f32 - The height of the `AlignNode`.
1975	///
1976	/// # Callback Example
1977	///
1978	/// ```
1979	/// align_node.slot(Slot::ALIGN_LAYOUT, Box::new(|stack| {
1980	/// 	let (
1981	/// 		width,
1982	/// 		height
1983	/// 	) = match (
1984	/// 		stack.pop_f32(),
1985	/// 		stack.pop_f32()
1986	/// 	) {
1987	/// 		(Some(width), Some(height)) => (width, height),
1988	/// 		_ => return,
1989	/// 	};
1990	/// 	p!("width: {}, height: {}", width, height);
1991	/// }));
1992	/// ```
1993	pub const ALIGN_LAYOUT: &'static str = "AlignLayout";
1994	/// Triggers when the `EffekseerNode` finishes playing an effect.
1995	///
1996	/// # Callback Arguments
1997	///
1998	/// * handle: i32 - The handle of the effect that finished playing.
1999	///
2000	/// # Callback Example
2001	///
2002	/// ```
2003	/// effekseer_node.slot(Slot::EFFEK_END, Box::new(|stack| {
2004	/// 	let handle = match stack.pop_i32() {
2005	/// 		Some(handle) => handle,
2006	/// 		None => return,
2007	/// 	};
2008	/// 	p!("Effect handle: {}", handle);
2009	/// }));
2010	/// ```
2011	pub const EFFEK_END: &'static str = "EffekEnd";
2012	/// Registers a callback for event triggered when an action is finished.
2013	///
2014	/// # Arguments
2015	///
2016	/// * node: &mut dyn INode - The node to register the callback on.
2017	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2018	/// 	* action: Action - The finished action.
2019	/// 	* target: Node - The node that finished the action.
2020	pub fn on_action_end<F>(node: &mut dyn INode, mut callback: F)
2021	where
2022		F: FnMut(/*action*/ Action, /*node*/ Node) + 'static,
2023	{
2024		node.slot(
2025			Slot::ACTION_END,
2026			Box::new(move |stack| {
2027				let (action, node) = match (stack.pop_cast::<Action>(), stack.pop_into_node()) {
2028					(Some(action), Some(node)) => (action, node),
2029					_ => return,
2030				};
2031				callback(action, node);
2032			}),
2033		);
2034	}
2035	/// Registers a callback for event triggered when a tap is detected and can be used to filter out certain taps.
2036	///
2037	/// # Arguments
2038	///
2039	/// * node: &mut dyn INode - The node to register the callback on.
2040	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2041	/// 	* touch: Touch - The touch that triggered the tap.
2042	pub fn on_tap_filter<F>(node: &mut dyn INode, mut callback: F)
2043	where
2044		F: FnMut(/*touch*/ Touch) + 'static,
2045	{
2046		node.set_touch_enabled(true);
2047		node.slot(
2048			Slot::TAP_FILTER,
2049			Box::new(move |stack| {
2050				let touch = match stack.pop_cast::<Touch>() {
2051					Some(touch) => touch,
2052					None => return,
2053				};
2054				callback(touch);
2055			}),
2056		);
2057	}
2058	/// Registers a callback for event triggered when a tap is detected.
2059	///
2060	/// # Arguments
2061	///
2062	/// * node: &mut dyn INode - The node to register the callback on.
2063	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2064	/// 	* touch: Touch - The touch that triggered the tap.
2065	pub fn on_tap_began<F>(node: &mut dyn INode, mut callback: F)
2066	where
2067		F: FnMut(/*touch*/ Touch) + 'static,
2068	{
2069		node.set_touch_enabled(true);
2070		node.slot(
2071			Slot::TAP_BEGAN,
2072			Box::new(move |stack| {
2073				let touch = match stack.pop_cast::<Touch>() {
2074					Some(touch) => touch,
2075					None => return,
2076				};
2077				callback(touch);
2078			}),
2079		);
2080	}
2081	/// Registers a callback for event triggered when a tap ends.
2082	///
2083	/// # Arguments
2084	///
2085	/// * node: &mut dyn INode - The node to register the callback on.
2086	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2087	/// 	* touch: Touch - The touch that triggered the tap.
2088	pub fn on_tap_ended<F>(node: &mut dyn INode, mut callback: F)
2089	where
2090		F: FnMut(/*touch*/ Touch) + 'static,
2091	{
2092		node.set_touch_enabled(true);
2093		node.slot(
2094			Slot::TAP_ENDED,
2095			Box::new(move |stack| {
2096				let touch = match stack.pop_cast::<Touch>() {
2097					Some(touch) => touch,
2098					None => return,
2099				};
2100				callback(touch);
2101			}),
2102		);
2103	}
2104	/// Registers a callback for event triggered when a tap is detected and has ended.
2105	///
2106	/// # Arguments
2107	///
2108	/// * node: &mut dyn INode - The node to register the callback on.
2109	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2110	/// 	* touch: Touch - The touch that triggered the tap.
2111	pub fn on_tapped<F>(node: &mut dyn INode, mut callback: F)
2112	where
2113		F: FnMut(/*touch*/ Touch) + 'static,
2114	{
2115		node.set_touch_enabled(true);
2116		node.slot(
2117			Slot::TAPPED,
2118			Box::new(move |stack| {
2119				let touch = match stack.pop_cast::<Touch>() {
2120					Some(touch) => touch,
2121					None => return,
2122				};
2123				callback(touch);
2124			}),
2125		);
2126	}
2127	/// Registers a callback for event triggered when a tap moves.
2128	///
2129	/// # Arguments
2130	///
2131	/// * node: &mut dyn INode - The node to register the callback on.
2132	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2133	/// 	* touch: Touch - The touch that triggered the tap.
2134	pub fn on_tap_moved<F>(node: &mut dyn INode, mut callback: F)
2135	where
2136		F: FnMut(/*touch*/ Touch) + 'static,
2137	{
2138		node.set_touch_enabled(true);
2139		node.slot(
2140			Slot::TAP_MOVED,
2141			Box::new(move |stack| {
2142				let touch = match stack.pop_cast::<Touch>() {
2143					Some(touch) => touch,
2144					None => return,
2145				};
2146				callback(touch);
2147			}),
2148		);
2149	}
2150	/// Registers a callback for event triggered when the mouse wheel is scrolled.
2151	///
2152	/// # Arguments
2153	///
2154	/// * node: &mut dyn INode - The node to register the callback on.
2155	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2156	/// 	* delta: Vec2 - The amount of scrolling that occurred.
2157	pub fn on_mouse_wheel<F>(node: &mut dyn INode, mut callback: F)
2158	where
2159		F: FnMut(/*delta*/ Vec2) + 'static,
2160	{
2161		node.set_touch_enabled(true);
2162		node.slot(
2163			Slot::MOUSE_WHEEL,
2164			Box::new(move |stack| {
2165				let delta = match stack.pop_vec2() {
2166					Some(delta) => delta,
2167					None => return,
2168				};
2169				callback(delta);
2170			}),
2171		);
2172	}
2173	/// Registers a callback for event triggered when a multi-touch gesture is recognized.
2174	///
2175	/// # Arguments
2176	///
2177	/// * node: &mut dyn INode - The node to register the callback on.
2178	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2179	/// 	* center: Vec2 - The center of the gesture.
2180	/// 	* num_fingers: i32 - The number of fingers involved in the gesture.
2181	/// 	* delta_dist: f32 - The distance the gesture has moved.
2182	/// 	* delta_angle: f32 - The angle of the gesture.
2183	pub fn on_gesture<F>(node: &mut dyn INode, mut callback: F)
2184	where
2185		F: FnMut(
2186				/*center*/ Vec2,
2187				/*num_fingers*/ i32,
2188				/*delta_dist*/ f32,
2189				/*delta_angle*/ f32,
2190			) + 'static,
2191	{
2192		node.set_touch_enabled(true);
2193		node.slot(
2194			Slot::GESTURE,
2195			Box::new(move |stack| {
2196				let (center, num_fingers, delta_dist, delta_angle) =
2197					match (stack.pop_vec2(), stack.pop_i32(), stack.pop_f32(), stack.pop_f32()) {
2198						(Some(center), Some(num_fingers), Some(delta_dist), Some(delta_angle)) => {
2199							(center, num_fingers, delta_dist, delta_angle)
2200						}
2201						_ => return,
2202					};
2203				callback(center, num_fingers, delta_dist, delta_angle);
2204			}),
2205		);
2206	}
2207	/// Registers a callback for event triggered when a node is added to the scene graph.
2208	///
2209	/// # Arguments
2210	///
2211	/// * node: &mut dyn INode - The node to register the callback on.
2212	/// * callback: F - The callback to be called when the event is triggered.
2213	pub fn on_enter<F>(node: &mut dyn INode, mut callback: F)
2214	where
2215		F: FnMut() + 'static,
2216	{
2217		node.slot(
2218			Slot::ENTER,
2219			Box::new(move |_| {
2220				callback();
2221			}),
2222		);
2223	}
2224	/// Registers a callback for event triggered when a node is removed from the scene graph.
2225	///
2226	/// # Arguments
2227	///
2228	/// * node: &mut dyn INode - The node to register the callback on.
2229	/// * callback: F - The callback to be called when the event is triggered.
2230	pub fn on_exit<F>(node: &mut dyn INode, mut callback: F)
2231	where
2232		F: FnMut() + 'static,
2233	{
2234		node.slot(
2235			Slot::EXIT,
2236			Box::new(move |_| {
2237				callback();
2238			}),
2239		);
2240	}
2241	/// Registers a callback for event triggered when a node is cleaned up.
2242	///
2243	/// # Arguments
2244	///
2245	/// * node: &mut dyn INode - The node to register the callback on.
2246	/// * callback: F - The callback to be called when the event is triggered.
2247	pub fn on_cleanup<F>(node: &mut dyn INode, mut callback: F)
2248	where
2249		F: FnMut() + 'static,
2250	{
2251		node.slot(
2252			Slot::CLEANUP,
2253			Box::new(move |_| {
2254				callback();
2255			}),
2256		);
2257	}
2258	/// Registers a callback for event triggered when a key is pressed down.
2259	///
2260	/// # Arguments
2261	///
2262	/// * node: &mut dyn INode - The node to register the callback on.
2263	/// * key: KeyName - The key to trigger the callback on.
2264	/// * callback: F - The callback to be called when the event is triggered.
2265	pub fn on_key_down<F>(node: &mut dyn INode, key: KeyName, mut callback: F)
2266	where
2267		F: FnMut() + 'static,
2268	{
2269		node.set_keyboard_enabled(true);
2270		node.slot(
2271			Slot::KEY_DOWN,
2272			Box::new(move |stack| {
2273				let key_name = match stack.pop_str() {
2274					Some(key_name) => key_name,
2275					None => return,
2276				};
2277				if key.as_ref() == key_name {
2278					callback();
2279				}
2280			}),
2281		);
2282	}
2283	/// Registers a callback for event triggered when a key is released.
2284	///
2285	/// # Arguments
2286	///
2287	/// * node: &mut dyn INode - The node to register the callback on.
2288	/// * key: KeyName - The key to trigger the callback on.
2289	pub fn on_key_up<F>(node: &mut dyn INode, key: KeyName, mut callback: F)
2290	where
2291		F: FnMut() + 'static,
2292	{
2293		node.set_keyboard_enabled(true);
2294		node.slot(
2295			Slot::KEY_UP,
2296			Box::new(move |stack| {
2297				let key_name = match stack.pop_str() {
2298					Some(key_name) => key_name,
2299					None => return,
2300				};
2301				if key.as_ref() == key_name {
2302					callback();
2303				}
2304			}),
2305		);
2306	}
2307	/// Registers a callback for event triggered when a key is pressed.
2308	///
2309	/// # Arguments
2310	///
2311	/// * node: &mut dyn INode - The node to register the callback on.
2312	/// * key: KeyName - The key to trigger the callback on.
2313	pub fn on_key_pressed<F>(node: &mut dyn INode, key: KeyName, mut callback: F)
2314	where
2315		F: FnMut() + 'static,
2316	{
2317		node.set_keyboard_enabled(true);
2318		node.slot(
2319			Slot::KEY_PRESSED,
2320			Box::new(move |stack| {
2321				let key_name = match stack.pop_str() {
2322					Some(key_name) => key_name,
2323					None => return,
2324				};
2325				if key.as_ref() == key_name {
2326					callback();
2327				}
2328			}),
2329		);
2330	}
2331	/// Registers a callback for event triggered when the input method editor (IME) is attached.
2332	///
2333	/// # Arguments
2334	///
2335	/// * node: &mut dyn INode - The node to register the callback on.
2336	/// * callback: F - The callback to be called when the event is triggered.
2337	pub fn on_attach_ime<F>(node: &mut dyn INode, mut callback: F)
2338	where
2339		F: FnMut() + 'static,
2340	{
2341		node.slot(
2342			Slot::ATTACH_IME,
2343			Box::new(move |_| {
2344				callback();
2345			}),
2346		);
2347	}
2348	/// Registers a callback for event triggered when the input method editor (IME) is detached.
2349	///
2350	/// # Arguments
2351	///
2352	/// * node: &mut dyn INode - The node to register the callback on.
2353	/// * callback: F - The callback to be called when the event is triggered.
2354	pub fn on_detach_ime<F>(node: &mut dyn INode, mut callback: F)
2355	where
2356		F: FnMut() + 'static,
2357	{
2358		node.slot(
2359			Slot::DETACH_IME,
2360			Box::new(move |_| {
2361				callback();
2362			}),
2363		);
2364	}
2365	/// Registers a callback for event triggered when text input is received.
2366	///
2367	/// # Arguments
2368	///
2369	/// * node: &mut dyn INode - The node to register the callback on.
2370	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2371	/// 	* text: String - The text that was input.
2372	pub fn on_text_input<F>(node: &mut dyn INode, mut callback: F)
2373	where
2374		F: FnMut(/*text*/ String) + 'static,
2375	{
2376		node.slot(
2377			Slot::TEXT_INPUT,
2378			Box::new(move |stack| {
2379				let text = match stack.pop_str() {
2380					Some(text) => text,
2381					None => return,
2382				};
2383				callback(text);
2384			}),
2385		);
2386	}
2387	/// Registers a callback for event triggered when text is being edited.
2388	///
2389	/// # Arguments
2390	///
2391	/// * node: &mut dyn INode - The node to register the callback on.
2392	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2393	/// 	* text: String - The text that is being edited.
2394	/// 	* start_pos: i32 - The starting position of the text being edited.
2395	pub fn on_text_editing<F>(node: &mut dyn INode, mut callback: F)
2396	where
2397		F: FnMut(/*text*/ String, /*start_pos*/ i32) + 'static,
2398	{
2399		node.slot(
2400			Slot::TEXT_EDITING,
2401			Box::new(move |stack| {
2402				let (text, start_pos) = match (stack.pop_str(), stack.pop_i32()) {
2403					(Some(text), Some(start_pos)) => (text, start_pos),
2404					_ => return,
2405				};
2406				callback(text, start_pos);
2407			}),
2408		);
2409	}
2410	/// Registers a callback for event triggered when a game controller button is pressed down.
2411	///
2412	/// # Arguments
2413	///
2414	/// * node: &mut dyn INode - The node to register the callback on.
2415	/// * button: ButtonName - The button to trigger the callback on.
2416	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2417	/// 	* controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
2418	pub fn on_button_down<F>(node: &mut dyn INode, button: ButtonName, mut callback: F)
2419	where
2420		F: FnMut(/*controller_id*/ i32) + 'static,
2421	{
2422		node.set_controller_enabled(true);
2423		node.slot(
2424			Slot::BUTTON_DOWN,
2425			Box::new(move |stack| {
2426				let (controller_id, button_name) = match (stack.pop_i32(), stack.pop_str()) {
2427					(Some(controller_id), Some(button_name)) => (controller_id, button_name),
2428					_ => return,
2429				};
2430				if button.as_ref() == button_name {
2431					callback(controller_id);
2432				}
2433			}),
2434		);
2435	}
2436	/// Registers a callback for event triggered when a game controller button is released.
2437	///
2438	/// # Arguments
2439	///
2440	/// * node: &mut dyn INode - The node to register the callback on.
2441	/// * button: ButtonName - The button to trigger the callback on.
2442	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2443	/// 	* controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
2444	pub fn on_button_up<F>(node: &mut dyn INode, button: ButtonName, mut callback: F)
2445	where
2446		F: FnMut(/*controller_id*/ i32) + 'static,
2447	{
2448		node.set_controller_enabled(true);
2449		node.slot(
2450			Slot::BUTTON_UP,
2451			Box::new(move |stack| {
2452				let (controller_id, button_name) = match (stack.pop_i32(), stack.pop_str()) {
2453					(Some(controller_id), Some(button_name)) => (controller_id, button_name),
2454					_ => return,
2455				};
2456				if button.as_ref() == button_name {
2457					callback(controller_id);
2458				}
2459			}),
2460		);
2461	}
2462	/// Registers a callback for event triggered when a game controller button is being pressed.
2463	/// This slot is triggered every frame while the button is being pressed.
2464	///
2465	/// # Arguments
2466	///
2467	/// * node: &mut dyn INode - The node to register the callback on.
2468	/// * button: ButtonName - The button to trigger the callback on.
2469	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2470	/// 	* controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
2471	pub fn on_button_pressed<F>(node: &mut dyn INode, button: ButtonName, mut callback: F)
2472	where
2473		F: FnMut(/*controller_id*/ i32) + 'static,
2474	{
2475		node.set_controller_enabled(true);
2476		node.slot(
2477			Slot::BUTTON_PRESSED,
2478			Box::new(move |stack| {
2479				let (controller_id, button_name) = match (stack.pop_i32(), stack.pop_str()) {
2480					(Some(controller_id), Some(button_name)) => (controller_id, button_name),
2481					_ => return,
2482				};
2483				if button.as_ref() == button_name {
2484					callback(controller_id);
2485				}
2486			}),
2487		);
2488	}
2489	/// Registers a callback for event triggered when a game controller axis changed.
2490	/// This slot is triggered every frame while the axis value changes.
2491	/// The axis value ranges from -1.0 to 1.0.
2492	///
2493	/// # Arguments
2494	///
2495	/// * node: &mut dyn INode - The node to register the callback on.
2496	/// * axis: AxisName - The axis to trigger the callback on.
2497	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2498	/// 	* controller_id: i32 - The controller id, incrementing from 0 when multiple controllers connected.
2499	pub fn on_axis<F>(node: &mut dyn INode, axis: AxisName, mut callback: F)
2500	where
2501		F: FnMut(/*controller_id*/ i32, /*axis_value*/ f32) + 'static,
2502	{
2503		node.set_controller_enabled(true);
2504		node.slot(
2505			Slot::AXIS,
2506			Box::new(move |stack| {
2507				let (controller_id, axis_name, axis_value) =
2508					match (stack.pop_i32(), stack.pop_str(), stack.pop_f32()) {
2509						(Some(controller_id), Some(axis_name), Some(axis_value)) => {
2510							(controller_id, axis_name, axis_value)
2511						}
2512						_ => return,
2513					};
2514				if axis.as_ref() == axis_name {
2515					callback(controller_id, axis_value);
2516				}
2517			}),
2518		);
2519	}
2520	/// Registers a callback for event triggered when an animation has ended on a Playable instance.
2521	///
2522	/// # Arguments
2523	///
2524	/// * node: &mut dyn IPlayable - The node to register the callback on.
2525	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2526	/// 	* animation_name: String - The name of the animation that ended.
2527	/// 	* target: Playable - The Playable instance that the animation was played on.
2528	pub fn on_animation_end<F>(node: &mut dyn IPlayable, mut callback: F)
2529	where
2530		F: FnMut(/*animation_name*/ String, /*target*/ Playable) + 'static,
2531	{
2532		node.slot(
2533			Slot::ANIMATION_END,
2534			Box::new(move |stack| {
2535				let (animation_name, playable) = match (stack.pop_str(), stack.pop_into_playable())
2536				{
2537					(Some(animation_name), Some(playable)) => (animation_name, playable),
2538					_ => return,
2539				};
2540				callback(animation_name, playable);
2541			}),
2542		);
2543	}
2544	/// Registers a callback for event triggered when a Body object collides with a sensor object.
2545	///
2546	/// # Arguments
2547	///
2548	/// * node: &mut dyn IBody - The node to register the callback on.
2549	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2550	/// 	* other: Body - The other Body object that the current Body is colliding with.
2551	/// 	* sensor_tag: i32 - The tag of the sensor that triggered this collision.
2552	pub fn on_body_enter<F>(node: &mut dyn IBody, mut callback: F)
2553	where
2554		F: FnMut(/*other*/ Body, /*sensor_tag*/ i32) + 'static,
2555	{
2556		node.slot(
2557			Slot::BODY_ENTER,
2558			Box::new(move |stack| {
2559				let (other, sensor_tag) = match (stack.pop_into_body(), stack.pop_i32()) {
2560					(Some(other), Some(sensor_tag)) => (other, sensor_tag),
2561					_ => return,
2562				};
2563				callback(other, sensor_tag);
2564			}),
2565		);
2566	}
2567	/// Registers a callback for event triggered when a Body object is no longer colliding with a sensor object.
2568	///
2569	/// # Arguments
2570	///
2571	/// * node: &mut dyn IBody - The node to register the callback on.
2572	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2573	/// 	* other: Body - The other Body object that the current Body is no longer colliding with.
2574	/// 	* sensor_tag: i32 - The tag of the sensor that triggered this collision.
2575	pub fn on_body_leave<F>(node: &mut dyn IBody, mut callback: F)
2576	where
2577		F: FnMut(/*other*/ Body, /*sensor_tag*/ i32) + 'static,
2578	{
2579		node.slot(
2580			Slot::BODY_LEAVE,
2581			Box::new(move |stack| {
2582				let (other, sensor_tag) = match (stack.pop_into_body(), stack.pop_i32()) {
2583					(Some(other), Some(sensor_tag)) => (other, sensor_tag),
2584					_ => return,
2585				};
2586				callback(other, sensor_tag);
2587			}),
2588		);
2589	}
2590	/// Registers a callback for event triggered when a Body object starts to collide with another object.
2591	///
2592	/// # Arguments
2593	///
2594	/// * node: &mut dyn IBody - The node to register the callback on.
2595	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2596	/// 	* other: Body - The other Body object that the current Body is colliding with.
2597	/// 	* point: Vec2 - The point of collision in world coordinates.
2598	/// 	* normal: Vec2 - The normal vector of the contact surface in world coordinates.
2599	/// 	* enabled: bool - Whether the contact is enabled or not. Collisions that are filtered out will still trigger this event, but the enabled state will be false.
2600	pub fn on_contact_start<F>(node: &mut dyn IBody, mut callback: F)
2601	where
2602		F: FnMut(
2603				/*other*/ Body,
2604				/*point*/ Vec2,
2605				/*normal*/ Vec2,
2606				/*enabled*/ bool,
2607			) + 'static,
2608	{
2609		node.set_receiving_contact(true);
2610		node.slot(
2611			Slot::CONTACT_START,
2612			Box::new(move |stack| {
2613				let (other, point, normal, enabled) = match (
2614					stack.pop_into_body(),
2615					stack.pop_vec2(),
2616					stack.pop_vec2(),
2617					stack.pop_bool(),
2618				) {
2619					(Some(other), Some(point), Some(normal), Some(enabled)) => {
2620						(other, point, normal, enabled)
2621					}
2622					_ => return,
2623				};
2624				callback(other, point, normal, enabled);
2625			}),
2626		);
2627	}
2628	/// Registers a callback for event triggered when a Body object stops colliding with another object.
2629	///
2630	/// # Arguments
2631	///
2632	/// * node: &mut dyn IBody - The node to register the callback on.
2633	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2634	/// 	* other: Body - The other Body object that the current Body is no longer colliding with.
2635	/// 	* point: Vec2 - The point of collision in world coordinates.
2636	/// 	* normal: Vec2 - The normal vector of the contact surface in world coordinates.
2637	pub fn on_contact_end<F>(node: &mut dyn IBody, mut callback: F)
2638	where
2639		F: FnMut(/*other*/ Body, /*point*/ Vec2, /*normal*/ Vec2) + 'static,
2640	{
2641		node.set_receiving_contact(true);
2642		node.slot(
2643			Slot::CONTACT_END,
2644			Box::new(move |stack| {
2645				let (other, point, normal) =
2646					match (stack.pop_into_body(), stack.pop_vec2(), stack.pop_vec2()) {
2647						(Some(other), Some(point), Some(normal)) => (other, point, normal),
2648						_ => return,
2649					};
2650				callback(other, point, normal);
2651			}),
2652		);
2653	}
2654	/// Registers a callback for event triggered when a Particle node starts a stop action and then all the active particles end their lives.
2655	///
2656	/// # Arguments
2657	///
2658	/// * node: &mut Particle - The node to register the callback on.
2659	/// * callback: F - The callback to be called when the event is triggered.
2660	pub fn on_finished<F>(node: &mut Particle, mut callback: F)
2661	where
2662		F: FnMut() + 'static,
2663	{
2664		node.slot(
2665			Slot::FINISHED,
2666			Box::new(move |_| {
2667				callback();
2668			}),
2669		);
2670	}
2671	/// Registers a callback for event triggered when the layout of the AlignNode is updated.
2672	///
2673	/// # Arguments
2674	///
2675	/// * node: &mut AlignNode - The node to register the callback on.
2676	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2677	/// 	* width: f32 - The width of the AlignNode.
2678	/// 	* height: f32 - The height of the AlignNode.
2679	pub fn on_align_layout<F>(node: &mut AlignNode, mut callback: F)
2680	where
2681		F: FnMut(/*width*/ f32, /*height*/ f32) + 'static,
2682	{
2683		node.slot(
2684			Slot::ALIGN_LAYOUT,
2685			Box::new(move |stack| {
2686				let (width, height) = match (stack.pop_f32(), stack.pop_f32()) {
2687					(Some(width), Some(height)) => (width, height),
2688					_ => return,
2689				};
2690				callback(width, height);
2691			}),
2692		);
2693	}
2694	/// Registers a callback for event triggered when the EffekseerNode finishes playing an effect.
2695	///
2696	/// # Arguments
2697	///
2698	/// * node: &mut EffekNode - The node to register the callback on.
2699	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2700	/// 	* handle: i32 - The handle of the effect that finished playing.
2701	pub fn on_effek_end<F>(node: &mut EffekNode, mut callback: F)
2702	where
2703		F: FnMut(/*handle*/ i32) + 'static,
2704	{
2705		node.slot(
2706			Slot::EFFEK_END,
2707			Box::new(move |stack| {
2708				let handle = match stack.pop_i32() {
2709					Some(handle) => handle,
2710					None => return,
2711				};
2712				callback(handle);
2713			}),
2714		);
2715	}
2716}
2717
2718/// An interface for providing Dora SSR built-in global event names.
2719pub struct GSlot {}
2720impl GSlot {
2721	/// Triggers when the application receives an event.
2722	///
2723	/// # Callback Arguments
2724	///
2725	/// * event_type: string - The type of the application event. The event type could be "Quit", "LowMemory", "WillEnterBackground", "DidEnterBackground", "WillEnterForeground", "DidEnterForeground".
2726	///
2727	/// # Callback Example
2728	///
2729	/// ```
2730	/// node.gslot(GSlot::APP_EVENT, Box::new(|stack| {
2731	/// 	let event_type = match stack.pop_str() {
2732	/// 		Some(event_type) => event_type,
2733	/// 		None => return,
2734	/// 	};
2735	/// 	p!(event_type);
2736	/// }));
2737	/// ```
2738	pub const APP_EVENT: &'static str = "AppEvent";
2739	/// Triggers when the application settings change.
2740	///
2741	/// # Callback Arguments
2742	///
2743	/// * setting_name: string - The name of the setting that changed. Could be "Locale", "Theme", "FullScreen", "Position", "Size".
2744	///
2745	/// # Callback Example
2746	///
2747	/// ```
2748	/// node.gslot(GSlot::APP_CHANGE, Box::new(|stack| {
2749	/// 	let setting_name = match stack.pop_str() {
2750	/// 		Some(setting_name) => setting_name,
2751	/// 		None => return,
2752	/// 	};
2753	/// 	p!(setting_name);
2754	/// }));
2755	/// ```
2756	pub const APP_CHANGE: &'static str = "AppChange";
2757	/// Triggers when gets an event from a websocket connection.
2758	///
2759	/// # Callback Arguments
2760	///
2761	/// * event: Dictionary - Event object with fields:
2762	///   * `type`: string - Could be "Open", "Close", "Send", "Receive".
2763	///   * `msg`: string - Message payload.
2764	///
2765	/// # Callback Example
2766	///
2767	/// ```
2768	/// node.gslot(GSlot::APP_WS, Box::new(|stack| {
2769	/// 	let event = match stack.pop_cast::<crate::dora::Dictionary>() {
2770	/// 		Some(event) => event,
2771	/// 		None => return,
2772	/// 	};
2773	/// 	p!(event.get_keys());
2774	/// }));
2775	/// ```
2776	pub const APP_WS: &'static str = "AppWS";
2777	/// Registers a callback for event triggered when the application receives an event.
2778	///
2779	/// # Arguments
2780	///
2781	/// * node: &mut dyn INode - The node to register the callback on.
2782	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2783	/// 	* event_type: String - The type of the application event. The event type could be "Quit", "LowMemory", "WillEnterBackground", "DidEnterBackground", "WillEnterForeground", "DidEnterForeground".
2784	pub fn on_app_event<F>(node: &mut dyn INode, mut callback: F)
2785	where
2786		F: FnMut(/*event_type*/ String) + 'static,
2787	{
2788		node.gslot(
2789			GSlot::APP_EVENT,
2790			Box::new(move |stack| {
2791				let event_type = match stack.pop_str() {
2792					Some(event_type) => event_type,
2793					None => return,
2794				};
2795				callback(event_type);
2796			}),
2797		);
2798	}
2799	/// Registers a callback for event triggered when the application settings change.
2800	///
2801	/// # Arguments
2802	///
2803	/// * node: &mut dyn INode - The node to register the callback on.
2804	/// * callback: F - The callback to be called when the event is triggered with the following arguments:
2805	/// 	* setting_name: String - The name of the setting that changed. Could be "Locale", "Theme", "FullScreen", "Position", "Size".
2806	pub fn on_app_change<F>(node: &mut dyn INode, mut callback: F)
2807	where
2808		F: FnMut(/*setting_name*/ String) + 'static,
2809	{
2810		node.gslot(
2811			GSlot::APP_CHANGE,
2812			Box::new(move |stack| {
2813				let setting_name = match stack.pop_str() {
2814					Some(setting_name) => setting_name,
2815					None => return,
2816				};
2817				callback(setting_name);
2818			}),
2819		);
2820	}
2821	/// Registers a callback for event triggered when gets an event from a websocket connection.
2822	///
2823	/// # Arguments
2824	///
2825	/// * node: &mut dyn INode - The node to register the callback on.
2826	/// * callback: F - The callback to be called when the event is triggered with one argument:
2827	/// 	* event: Dictionary - Event object that contains `type` and `msg`.
2828	///
2829	/// To send AppWS, emit one Dictionary argument (for example: `{ type = "Send", msg = "..." }`).
2830	pub fn on_app_ws<F>(node: &mut dyn INode, mut callback: F)
2831	where
2832		F: FnMut(/*event*/ crate::dora::Dictionary) + 'static,
2833	{
2834		node.gslot(
2835			GSlot::APP_WS,
2836			Box::new(move |stack| {
2837				let event = match stack.pop_cast::<crate::dora::Dictionary>() {
2838					Some(event) => event,
2839					_ => return,
2840				};
2841				callback(event);
2842			}),
2843		);
2844	}
2845}
2846
2847// Content
2848
2849extern "C" {
2850	fn content_load(filename: i64) -> i64;
2851}
2852
2853impl Content {
2854	/// Loads the content of the file with the specified filename.
2855	///
2856	/// # Arguments
2857	///
2858	/// * `filename` - The name of the file to load.
2859	///
2860	/// # Returns
2861	///
2862	/// * `String` - The content of the loaded file.
2863	pub fn load(filename: &str) -> Option<String> {
2864		let result = unsafe { content_load(from_string(filename)) };
2865		if result > 0 {
2866			Some(to_string(result))
2867		} else {
2868			None
2869		}
2870	}
2871}
2872
2873// Array
2874
2875extern "C" {
2876	fn array_set(array: i64, index: i32, item: i64) -> i32;
2877	fn array_get(array: i64, index: i32) -> i64;
2878	fn array_first(array: i64) -> i64;
2879	fn array_last(array: i64) -> i64;
2880	fn array_random_object(array: i64) -> i64;
2881	fn array_add(array: i64, item: i64);
2882	fn array_insert(array: i64, index: i32, item: i64);
2883	fn array_contains(array: i64, item: i64) -> i32;
2884	fn array_index(array: i64, item: i64) -> i32;
2885	fn array_remove_last(array: i64) -> i64;
2886	fn array_fast_remove(array: i64, item: i64) -> i32;
2887}
2888
2889impl Array {
2890	/// Sets the item at the given index.
2891	///
2892	/// # Arguments
2893	///
2894	/// * `index` - The index to set, should be 0 based.
2895	/// * `item` - The new item value.
2896	pub fn set<'a, T>(&mut self, index: i32, v: T)
2897	where
2898		T: IntoValue<'a>,
2899	{
2900		if unsafe { array_set(self.raw(), index, v.val().raw()) == 0 } {
2901			panic!("Out of bounds, expecting [0, {}), got {}", self.get_count(), index);
2902		}
2903	}
2904	/// Gets the item at the given index.
2905	///
2906	/// # Arguments
2907	///
2908	/// * `index` - The index to get, should be 0 based.
2909	///
2910	/// # Returns
2911	///
2912	/// * `Option<Value>` - The item value.
2913	pub fn get(&self, index: i32) -> Option<Value> {
2914		Value::from(unsafe { array_get(self.raw(), index) })
2915	}
2916	/// The first item in the array.
2917	pub fn first(&self) -> Option<Value> {
2918		Value::from(unsafe { array_first(self.raw()) })
2919	}
2920	/// The last item in the array.
2921	pub fn last(&self) -> Option<Value> {
2922		Value::from(unsafe { array_last(self.raw()) })
2923	}
2924	/// A random item from the array.
2925	pub fn random_object(&self) -> Option<Value> {
2926		Value::from(unsafe { array_random_object(self.raw()) })
2927	}
2928	/// Adds an item to the end of the array.
2929	///
2930	/// # Arguments
2931	///
2932	/// * `item` - The item to add.
2933	pub fn add<'a, T>(&mut self, v: T) -> &mut Self
2934	where
2935		T: IntoValue<'a>,
2936	{
2937		unsafe {
2938			array_add(self.raw(), v.val().raw());
2939		}
2940		self
2941	}
2942	/// Inserts an item at the given index, shifting other items to the right.
2943	///
2944	/// # Arguments
2945	///
2946	/// * `index` - The index to insert at.
2947	/// * `item` - The item to insert.
2948	pub fn insert<'a, T>(&mut self, index: i32, v: T)
2949	where
2950		T: IntoValue<'a>,
2951	{
2952		unsafe {
2953			array_insert(self.raw(), index, v.val().raw());
2954		}
2955	}
2956	/// Checks whether the array contains a given item.
2957	///
2958	/// # Arguments
2959	///
2960	/// * `item` - The item to check.
2961	///
2962	/// # Returns
2963	///
2964	/// * `bool` - True if the item is found, false otherwise.
2965	pub fn contains<'a, T>(&self, v: T) -> bool
2966	where
2967		T: IntoValue<'a>,
2968	{
2969		unsafe { array_contains(self.raw(), v.val().raw()) != 0 }
2970	}
2971	/// Gets the index of a given item.
2972	///
2973	/// # Arguments
2974	///
2975	/// * `item` - The item to search for.
2976	///
2977	/// # Returns
2978	///
2979	/// * `i32` - The index of the item, or -1 if it is not found.
2980	pub fn index<'a, T>(&self, v: T) -> i32
2981	where
2982		T: IntoValue<'a>,
2983	{
2984		unsafe { array_index(self.raw(), v.val().raw()) }
2985	}
2986	/// Removes and returns the last item in the array.
2987	///
2988	/// # Returns
2989	///
2990	/// * `Option<Value>` - The last item removed from the array.
2991	pub fn remove_last(&mut self) -> Option<Value> {
2992		Value::from(unsafe { array_remove_last(self.raw()) })
2993	}
2994	/// Removes the first occurrence of a given item from the array without preserving order.
2995	///
2996	/// # Arguments
2997	///
2998	/// * `item` - The item to remove.
2999	///
3000	/// # Returns
3001	///
3002	/// * `bool` - True if the item was found and removed, false otherwise.
3003	pub fn fast_remove<'a, T>(&mut self, v: T) -> bool
3004	where
3005		T: IntoValue<'a>,
3006	{
3007		unsafe { array_fast_remove(self.raw(), v.val().raw()) != 0 }
3008	}
3009}
3010
3011// Dictionary
3012
3013extern "C" {
3014	fn dictionary_set(dict: i64, key: i64, value: i64);
3015	fn dictionary_get(dict: i64, key: i64) -> i64;
3016}
3017
3018impl Dictionary {
3019	/// A method for setting items in the dictionary.
3020	///
3021	/// # Arguments
3022	///
3023	/// * `key` - The key of the item to set.
3024	/// * `item` - The Item to set for the given key, set to None to delete this key-value pair.
3025	pub fn set<'a, T>(&mut self, key: &str, v: T)
3026	where
3027		T: IntoValue<'a>,
3028	{
3029		unsafe {
3030			dictionary_set(self.raw(), from_string(key), v.val().raw());
3031		}
3032	}
3033	/// A method for accessing items in the dictionary.
3034	///
3035	/// # Arguments
3036	///
3037	/// * `key` - The key of the item to retrieve.
3038	///
3039	/// # Returns
3040	///
3041	/// * `Option<Item>` - The Item with the given key, or None if it does not exist.
3042	pub fn get(&self, key: &str) -> Option<Value> {
3043		Value::from(unsafe { dictionary_get(self.raw(), from_string(key)) })
3044	}
3045}
3046
3047// Entity
3048
3049extern "C" {
3050	fn entity_set(e: i64, k: i64, v: i64);
3051	fn entity_get(e: i64, k: i64) -> i64;
3052	fn entity_get_old(e: i64, k: i64) -> i64;
3053}
3054
3055impl Entity {
3056	/// Sets a property of the entity to a given value.
3057	/// This function will trigger events for Observer objects.
3058	///
3059	/// # Arguments
3060	///
3061	/// * `key` - The name of the property to set.
3062	/// * `item` - The value to set the property to.
3063	pub fn set<'a, T>(&mut self, key: &str, value: T)
3064	where
3065		T: IntoValue<'a>,
3066	{
3067		unsafe {
3068			entity_set(self.raw(), from_string(key), value.val().raw());
3069		}
3070	}
3071	/// Retrieves the value of a property of the entity.
3072	///
3073	/// # Arguments
3074	///
3075	/// * `key` - The name of the property to retrieve the value of.
3076	///
3077	/// # Returns
3078	///
3079	/// * `Option<Value>` - The value of the specified property.
3080	pub fn get(&self, key: &str) -> Option<Value> {
3081		Value::from(unsafe { entity_get(self.raw(), from_string(key)) })
3082	}
3083	/// Retrieves the previous value of a property of the entity.
3084	/// The old values are values before the last change of the component values of the Entity.
3085	///
3086	/// # Arguments
3087	///
3088	/// * `key` - The name of the property to retrieve the previous value of.
3089	///
3090	/// # Returns
3091	///
3092	/// * `Option<Value>` - The previous value of the specified property.
3093	pub fn get_old(&self, key: &str) -> Option<Value> {
3094		Value::from(unsafe { entity_get_old(self.raw(), from_string(key)) })
3095	}
3096}
3097
3098// EntityGroup
3099
3100extern "C" {
3101	fn group_watch(group: i64, func: i32, stack: i64);
3102}
3103
3104impl Group {
3105	/// Watches the group for changes to its entities, calling a function whenever an entity is added or changed.
3106	///
3107	/// # Arguments
3108	///
3109	/// * `callback` - The function to call when an entity is added or changed. Returns true to stop watching.
3110	///
3111	/// # Returns
3112	///
3113	/// * `Group` - The same group, for method chaining.
3114	pub fn watch(&mut self, mut callback: Box<dyn FnMut(&mut CallStack) -> bool>) -> &mut Group {
3115		let mut stack = CallStack::new();
3116		let stack_raw = stack.raw();
3117		let func_id = push_function(Box::new(move || {
3118			let result = callback(&mut stack);
3119			stack.push_bool(result);
3120		}));
3121		unsafe {
3122			group_watch(self.raw(), func_id, stack_raw);
3123		}
3124		self
3125	}
3126	/// Calls a function for each entity in the group.
3127	///
3128	/// # Arguments
3129	///
3130	/// * `visitor` - The function to call for each entity. Returning true inside the function will stop iteration.
3131	///
3132	/// # Returns
3133	///
3134	/// * `bool` - Returns false if all entities were processed, true if the iteration was interrupted.
3135	pub fn each(&self, visitor: Box<dyn FnMut(&Entity) -> bool>) -> bool {
3136		match self.find(visitor) {
3137			Some(_) => true,
3138			None => false,
3139		}
3140	}
3141}
3142
3143// Observer
3144
3145extern "C" {
3146	fn observer_watch(observer: i64, func: i32, stack: i64);
3147}
3148
3149#[repr(i32)]
3150#[derive(Copy, Clone, Debug, PartialEq)]
3151pub enum EntityEvent {
3152	Add = 1,
3153	Change = 2,
3154	AddOrChange = 3,
3155	Remove = 4,
3156}
3157
3158impl Observer {
3159	/// Watches the components changes to entities that match the observer's component filter.
3160	///
3161	/// # Arguments
3162	///
3163	/// * `callback` - The function to call when a change occurs. Returns true to stop watching.
3164	///
3165	/// # Returns
3166	///
3167	/// * `Observer` - The same observer, for method chaining.
3168	pub fn watch(&mut self, mut callback: Box<dyn FnMut(&mut CallStack) -> bool>) -> &mut Observer {
3169		let mut stack = CallStack::new();
3170		let stack_raw = stack.raw();
3171		let func_id = push_function(Box::new(move || {
3172			let result = callback(&mut stack);
3173			stack.push_bool(result);
3174		}));
3175		unsafe {
3176			observer_watch(self.raw(), func_id, stack_raw);
3177		}
3178		self
3179	}
3180}
3181
3182// Director
3183
3184#[cfg(not(target_arch = "wasm32"))]
3185extern "C" {
3186	fn director_get_scheduler() -> i64;
3187	fn director_get_post_scheduler() -> i64;
3188}
3189
3190#[cfg(target_arch = "wasm32")]
3191extern "C" {
3192	fn director_get_wasm_scheduler() -> i64;
3193	fn director_get_post_wasm_scheduler() -> i64;
3194	fn dora_wasm_module_id() -> i32;
3195}
3196
3197impl Director {
3198	/// Gets the scheduler for the director.
3199	/// The scheduler is used for scheduling tasks to run for the main game logic.
3200	///
3201	/// # Returns
3202	///
3203	/// * `Scheduler` - The scheduler for the director.
3204	pub fn get_scheduler() -> Scheduler {
3205		#[cfg(target_arch = "wasm32")]
3206		{
3207			Scheduler::from(unsafe { director_get_wasm_scheduler() }).unwrap()
3208		}
3209		#[cfg(not(target_arch = "wasm32"))]
3210		{
3211			Scheduler::from(unsafe { director_get_scheduler() }).unwrap()
3212		}
3213	}
3214	/// Gets the post scheduler for the director.
3215	/// The post scheduler is used for scheduling tasks that should run after the main scheduler has finished.
3216	///
3217	/// # Returns
3218	///
3219	/// * `Scheduler` - The post scheduler for the director.
3220	pub fn get_post_scheduler() -> Scheduler {
3221		#[cfg(target_arch = "wasm32")]
3222		{
3223			Scheduler::from(unsafe { director_get_post_wasm_scheduler() }).unwrap()
3224		}
3225		#[cfg(not(target_arch = "wasm32"))]
3226		{
3227			Scheduler::from(unsafe { director_get_post_scheduler() }).unwrap()
3228		}
3229	}
3230}
3231
3232// Node
3233
3234impl Node {
3235	/// Casts the object to a node.
3236	///
3237	/// # Arguments
3238	///
3239	/// * `obj` - The object to cast.
3240	///
3241	/// # Returns
3242	///
3243	/// * `Option<Node>` - The node if the object is a node, None otherwise.
3244	pub fn cast(obj: &dyn IObject) -> Option<Node> {
3245		let node = Node::from(unsafe { object_to_node(obj.raw()) });
3246		if node.is_some() {
3247			unsafe {
3248				object_retain(obj.raw());
3249			}
3250		}
3251		node
3252	}
3253}
3254
3255// Sprite
3256
3257impl Sprite {
3258	/// Casts the object to a sprite.
3259	///
3260	/// # Arguments
3261	///
3262	/// * `obj` - The object to cast.
3263	///
3264	/// # Returns
3265	///
3266	/// * `Option<Sprite>` - The sprite if the object is a sprite, None otherwise.
3267	pub fn cast(obj: &dyn IObject) -> Option<Sprite> {
3268		let sprite = Sprite::from(unsafe { object_to_sprite(obj.raw()) });
3269		if sprite.is_some() {
3270			unsafe {
3271				object_retain(obj.raw());
3272			}
3273		}
3274		sprite
3275	}
3276}
3277
3278// Camera
3279
3280impl Camera {
3281	/// Casts the object to a camera.
3282	///
3283	/// # Arguments
3284	///
3285	/// * `obj` - The object to cast.
3286	///
3287	/// # Returns
3288	///
3289	/// * `Option<Camera>` - The camera if the object is a camera, None otherwise.
3290	pub fn cast(obj: &dyn IObject) -> Option<Camera> {
3291		let camera = Camera::from(unsafe { object_to_camera(obj.raw()) });
3292		if camera.is_some() {
3293			unsafe {
3294				object_retain(obj.raw());
3295			}
3296		}
3297		camera
3298	}
3299}
3300
3301// Playable
3302
3303impl Playable {
3304	/// Casts the object to a playable.
3305	///
3306	/// # Arguments
3307	///
3308	/// * `obj` - The object to cast.
3309	///
3310	/// # Returns
3311	///
3312	/// * `Option<Playable>` - The playable if the object is a playable, None otherwise.
3313	pub fn cast(obj: &dyn IObject) -> Option<Playable> {
3314		let playable = Playable::from(unsafe { object_to_playable(obj.raw()) });
3315		if playable.is_some() {
3316			unsafe {
3317				object_retain(obj.raw());
3318			}
3319		}
3320		playable
3321	}
3322}
3323
3324// Body
3325
3326impl Body {
3327	/// Casts the object to a body.
3328	///
3329	/// # Arguments
3330	///
3331	/// * `obj` - The object to cast.
3332	///
3333	/// # Returns
3334	///
3335	/// * `Option<Body>` - The body if the object is a body, None otherwise.
3336	pub fn cast(obj: &dyn IObject) -> Option<Body> {
3337		let body = Body::from(unsafe { object_to_body(obj.raw()) });
3338		if body.is_some() {
3339			unsafe {
3340				object_retain(obj.raw());
3341			}
3342		}
3343		body
3344	}
3345}
3346
3347// Joint
3348
3349impl Joint {
3350	/// Casts the object to a joint.
3351	///
3352	/// # Arguments
3353	///
3354	/// * `obj` - The object to cast.
3355	///
3356	/// # Returns
3357	///
3358	/// * `Option<Joint>` - The joint if the object is a joint, None otherwise.
3359	pub fn cast(obj: &dyn IObject) -> Option<Joint> {
3360		let joint = Joint::from(unsafe { object_to_joint(obj.raw()) });
3361		if joint.is_some() {
3362			unsafe {
3363				object_retain(obj.raw());
3364			}
3365		}
3366		joint
3367	}
3368}
3369
3370// PhysicsWorld
3371
3372impl PhysicsWorld {
3373	/// Casts the object to a physics world.
3374	///
3375	/// # Arguments
3376	///
3377	/// * `obj` - The object to cast.
3378	///
3379	/// # Returns
3380	///
3381	/// * `Option<PhysicsWorld>` - The physics world if the object is a physics world, None otherwise.
3382	pub fn cast(obj: &dyn IObject) -> Option<PhysicsWorld> {
3383		let physics_world = PhysicsWorld::from(unsafe { object_to_physics_world(obj.raw()) });
3384		if physics_world.is_some() {
3385			unsafe {
3386				object_retain(obj.raw());
3387			}
3388		}
3389		physics_world
3390	}
3391}
3392
3393// Sprite
3394#[repr(i32)]
3395#[derive(Copy, Clone, Debug, PartialEq)]
3396pub enum TextureWrap {
3397	None = 0,
3398	Mirror = 1,
3399	Clamp = 2,
3400	Border = 3,
3401}
3402
3403#[repr(i32)]
3404#[derive(Copy, Clone, Debug, PartialEq)]
3405pub enum TextureFilter {
3406	None = 0,
3407	Point = 1,
3408	Anisotropic = 2,
3409}
3410
3411#[repr(u64)]
3412#[derive(Copy, Clone, Debug, PartialEq)]
3413pub enum BFunc {
3414	Zero = 0x0000000000001000,
3415	One = 0x0000000000002000,
3416	SrcColor = 0x0000000000003000,
3417	InvSrcColor = 0x0000000000004000,
3418	SrcAlpha = 0x0000000000005000,
3419	InvSrcAlpha = 0x0000000000006000,
3420	DstAlpha = 0x0000000000007000,
3421	InvDstAlpha = 0x0000000000008000,
3422	DstColor = 0x0000000000009000,
3423	InvDstColor = 0x000000000000a000,
3424}
3425
3426pub struct BlendFunc {
3427	value: u64,
3428}
3429
3430impl BlendFunc {
3431	pub fn new_seperate(
3432		src_rgb: BFunc,
3433		dst_rgb: BFunc,
3434		src_alpha: BFunc,
3435		dst_alpha: BFunc,
3436	) -> Self {
3437		BlendFunc {
3438			value: (src_rgb as u64
3439				| (dst_rgb as u64) << 4
3440				| src_alpha as u64
3441				| (dst_alpha as u64) << 4)
3442				<< 8,
3443		}
3444	}
3445	pub fn new(src: BFunc, dst: BFunc) -> Self {
3446		BlendFunc::new_seperate(src, dst, src, dst)
3447	}
3448	pub fn from(value: i64) -> Self {
3449		BlendFunc { value: value as u64 }
3450	}
3451	pub(crate) fn to_value(&self) -> i64 {
3452		self.value as i64
3453	}
3454}
3455
3456// Ease
3457
3458#[repr(i32)]
3459#[derive(Copy, Clone, Debug, PartialEq)]
3460pub enum EaseType {
3461	Linear = 0,
3462	InQuad = 1,
3463	OutQuad = 2,
3464	InOutQuad = 3,
3465	InCubic = 4,
3466	OutCubic = 5,
3467	InOutCubic = 6,
3468	InQuart = 7,
3469	OutQuart = 8,
3470	InOutQuart = 9,
3471	InQuint = 10,
3472	OutQuint = 11,
3473	InOutQuint = 12,
3474	InSine = 13,
3475	OutSine = 14,
3476	InOutSine = 15,
3477	InExpo = 16,
3478	OutExpo = 17,
3479	InOutExpo = 18,
3480	InCirc = 19,
3481	OutCirc = 20,
3482	InOutCirc = 21,
3483	InElastic = 22,
3484	OutElastic = 23,
3485	InOutElastic = 24,
3486	InBack = 25,
3487	OutBack = 26,
3488	InOutBack = 27,
3489	InBounce = 28,
3490	OutBounce = 29,
3491	InOutBounce = 30,
3492	OutInQuad = 31,
3493	OutInCubic = 32,
3494	OutInQuart = 33,
3495	OutInQuint = 34,
3496	OutInSine = 35,
3497	OutInExpo = 36,
3498	OutInCirc = 37,
3499	OutInElastic = 38,
3500	OutInBack = 39,
3501	OutInBounce = 40,
3502}
3503
3504#[repr(i32)]
3505#[derive(Copy, Clone, Debug, PartialEq)]
3506pub enum Property {
3507	X = 0,
3508	Y = 1,
3509	Z = 2,
3510	Angle = 3,
3511	AngleX = 4,
3512	AngleY = 5,
3513	ScaleX = 6,
3514	ScaleY = 7,
3515	SkewX = 8,
3516	SkewY = 9,
3517	Width = 10,
3518	Height = 11,
3519	AnchorX = 12,
3520	AnchorY = 13,
3521	Opacity = 14,
3522}
3523
3524// Label
3525
3526#[repr(i32)]
3527#[derive(Copy, Clone, Debug, PartialEq)]
3528pub enum TextAlign {
3529	Left = 0,
3530	Center = 1,
3531	Right = 2,
3532}
3533
3534// BodyDef
3535
3536#[repr(i32)]
3537#[derive(Copy, Clone, Debug, PartialEq)]
3538pub enum BodyType {
3539	Dynamic = 0,
3540	Static = 1,
3541	Kinematic = 2,
3542}
3543
3544// Shader
3545
3546#[repr(i32)]
3547#[derive(Copy, Clone, Debug, PartialEq)]
3548pub enum ShaderStage {
3549	Vertex = 1,
3550	Fragment = 2,
3551	Compute = 3,
3552}
3553
3554// Keyboard
3555
3556#[derive(Copy, Clone, Debug, PartialEq)]
3557pub enum KeyName {
3558	Return,
3559	Escape,
3560	BackSpace,
3561	Tab,
3562	Space,
3563	Exclamation,
3564	DoubleQuote,
3565	Hash,
3566	Percent,
3567	Dollar,
3568	Ampersand,
3569	SingleQuote,
3570	LeftParen,
3571	RightParen,
3572	Asterisk,
3573	Plus,
3574	Comma,
3575	Minus,
3576	Dot,
3577	Slash,
3578	Num1,
3579	Num2,
3580	Num3,
3581	Num4,
3582	Num5,
3583	Num6,
3584	Num7,
3585	Num8,
3586	Num9,
3587	Num0,
3588	Colon,
3589	Semicolon,
3590	LessThan,
3591	Equal,
3592	GreaterThan,
3593	Question,
3594	At,
3595	LeftBracket,
3596	Backslash,
3597	RightBracket,
3598	Caret,
3599	Underscore,
3600	Backtick,
3601	A,
3602	B,
3603	C,
3604	D,
3605	E,
3606	F,
3607	G,
3608	H,
3609	I,
3610	J,
3611	K,
3612	L,
3613	M,
3614	N,
3615	O,
3616	P,
3617	Q,
3618	R,
3619	S,
3620	T,
3621	U,
3622	V,
3623	W,
3624	X,
3625	Y,
3626	Z,
3627	Delete,
3628	CapsLock,
3629	F1,
3630	F2,
3631	F3,
3632	F4,
3633	F5,
3634	F6,
3635	F7,
3636	F8,
3637	F9,
3638	F10,
3639	F11,
3640	F12,
3641	PrintScreen,
3642	ScrollLock,
3643	Pause,
3644	Insert,
3645	Home,
3646	PageUp,
3647	End,
3648	PageDown,
3649	Right,
3650	Left,
3651	Down,
3652	Up,
3653	Application,
3654	LCtrl,
3655	LShift,
3656	LAlt,
3657	LGui,
3658	RCtrl,
3659	RShift,
3660	RAlt,
3661	RGui,
3662}
3663
3664impl AsRef<str> for KeyName {
3665	fn as_ref(&self) -> &str {
3666		match self {
3667			KeyName::Return => "Return",
3668			KeyName::Escape => "Escape",
3669			KeyName::BackSpace => "BackSpace",
3670			KeyName::Tab => "Tab",
3671			KeyName::Space => "Space",
3672			KeyName::Exclamation => "!",
3673			KeyName::DoubleQuote => "\"",
3674			KeyName::Hash => "#",
3675			KeyName::Percent => "%",
3676			KeyName::Dollar => "$",
3677			KeyName::Ampersand => "&",
3678			KeyName::SingleQuote => "'",
3679			KeyName::LeftParen => "(",
3680			KeyName::RightParen => ")",
3681			KeyName::Asterisk => "*",
3682			KeyName::Plus => "+",
3683			KeyName::Comma => ",",
3684			KeyName::Minus => "-",
3685			KeyName::Dot => ".",
3686			KeyName::Slash => "/",
3687			KeyName::Num1 => "1",
3688			KeyName::Num2 => "2",
3689			KeyName::Num3 => "3",
3690			KeyName::Num4 => "4",
3691			KeyName::Num5 => "5",
3692			KeyName::Num6 => "6",
3693			KeyName::Num7 => "7",
3694			KeyName::Num8 => "8",
3695			KeyName::Num9 => "9",
3696			KeyName::Num0 => "0",
3697			KeyName::Colon => ":",
3698			KeyName::Semicolon => ";",
3699			KeyName::LessThan => "<",
3700			KeyName::Equal => "=",
3701			KeyName::GreaterThan => ">",
3702			KeyName::Question => "?",
3703			KeyName::At => "@",
3704			KeyName::LeftBracket => "[",
3705			KeyName::Backslash => "\\",
3706			KeyName::RightBracket => "]",
3707			KeyName::Caret => "^",
3708			KeyName::Underscore => "_",
3709			KeyName::Backtick => "`",
3710			KeyName::A => "A",
3711			KeyName::B => "B",
3712			KeyName::C => "C",
3713			KeyName::D => "D",
3714			KeyName::E => "E",
3715			KeyName::F => "F",
3716			KeyName::G => "G",
3717			KeyName::H => "H",
3718			KeyName::I => "I",
3719			KeyName::J => "J",
3720			KeyName::K => "K",
3721			KeyName::L => "L",
3722			KeyName::M => "M",
3723			KeyName::N => "N",
3724			KeyName::O => "O",
3725			KeyName::P => "P",
3726			KeyName::Q => "Q",
3727			KeyName::R => "R",
3728			KeyName::S => "S",
3729			KeyName::T => "T",
3730			KeyName::U => "U",
3731			KeyName::V => "V",
3732			KeyName::W => "W",
3733			KeyName::X => "X",
3734			KeyName::Y => "Y",
3735			KeyName::Z => "Z",
3736			KeyName::Delete => "Delete",
3737			KeyName::CapsLock => "CapsLock",
3738			KeyName::F1 => "F1",
3739			KeyName::F2 => "F2",
3740			KeyName::F3 => "F3",
3741			KeyName::F4 => "F4",
3742			KeyName::F5 => "F5",
3743			KeyName::F6 => "F6",
3744			KeyName::F7 => "F7",
3745			KeyName::F8 => "F8",
3746			KeyName::F9 => "F9",
3747			KeyName::F10 => "F10",
3748			KeyName::F11 => "F11",
3749			KeyName::F12 => "F12",
3750			KeyName::PrintScreen => "PrintScreen",
3751			KeyName::ScrollLock => "ScrollLock",
3752			KeyName::Pause => "Pause",
3753			KeyName::Insert => "Insert",
3754			KeyName::Home => "Home",
3755			KeyName::PageUp => "PageUp",
3756			KeyName::End => "End",
3757			KeyName::PageDown => "PageDown",
3758			KeyName::Right => "Right",
3759			KeyName::Left => "Left",
3760			KeyName::Down => "Down",
3761			KeyName::Up => "Up",
3762			KeyName::Application => "Application",
3763			KeyName::LCtrl => "LCtrl",
3764			KeyName::LShift => "LShift",
3765			KeyName::LAlt => "LAlt",
3766			KeyName::LGui => "LGui",
3767			KeyName::RCtrl => "RCtrl",
3768			KeyName::RShift => "RShift",
3769			KeyName::RAlt => "RAlt",
3770			KeyName::RGui => "RGui",
3771		}
3772	}
3773}
3774
3775impl Keyboard {
3776	/// Checks whether a key is pressed down in the current frame.
3777	///
3778	/// # Arguments
3779	///
3780	/// * `name` - The name of the key to check.
3781	///
3782	/// # Returns
3783	///
3784	/// * `bool` - `true` if the key is pressed down, `false` otherwise.
3785	pub fn is_key_down(key: KeyName) -> bool {
3786		Keyboard::_is_key_down(key.as_ref())
3787	}
3788	/// Checks whether a key is released in the current frame.
3789	///
3790	/// # Arguments
3791	///
3792	/// * `name` - The name of the key to check.
3793	///
3794	/// # Returns
3795	///
3796	/// * `bool` - `true` if the key is released, `false` otherwise.
3797	pub fn is_key_up(key: KeyName) -> bool {
3798		Keyboard::_is_key_up(key.as_ref())
3799	}
3800	/// Checks whether a key is in pressed state.
3801	///
3802	/// # Arguments
3803	///
3804	/// * `name` - The name of the key to check.
3805	///
3806	/// # Returns
3807	///
3808	/// * `bool` - `true` if the key is in pressed state, `false` otherwise.
3809	pub fn is_key_pressed(key: KeyName) -> bool {
3810		Keyboard::_is_key_pressed(key.as_ref())
3811	}
3812}
3813
3814// Controller
3815
3816#[derive(Copy, Clone, Debug, PartialEq)]
3817pub enum AxisName {
3818	LeftX,
3819	LeftY,
3820	RightX,
3821	RightY,
3822	LeftTrigger,
3823	RightTrigger,
3824}
3825
3826impl AsRef<str> for AxisName {
3827	fn as_ref(&self) -> &str {
3828		match self {
3829			AxisName::LeftX => "leftx",
3830			AxisName::LeftY => "lefty",
3831			AxisName::RightX => "rightx",
3832			AxisName::RightY => "righty",
3833			AxisName::LeftTrigger => "lefttrigger",
3834			AxisName::RightTrigger => "righttrigger",
3835		}
3836	}
3837}
3838
3839#[derive(Copy, Clone, Debug, PartialEq)]
3840pub enum ButtonName {
3841	A,
3842	B,
3843	Back,
3844	DPDown,
3845	DPLeft,
3846	DPRight,
3847	DPUp,
3848	LeftShoulder,
3849	LeftStick,
3850	RightShoulder,
3851	RightStick,
3852	Start,
3853	X,
3854	Y,
3855}
3856
3857impl AsRef<str> for ButtonName {
3858	fn as_ref(&self) -> &str {
3859		match self {
3860			ButtonName::A => "a",
3861			ButtonName::B => "b",
3862			ButtonName::Back => "back",
3863			ButtonName::DPDown => "dpdown",
3864			ButtonName::DPLeft => "dpleft",
3865			ButtonName::DPRight => "dpright",
3866			ButtonName::DPUp => "dpup",
3867			ButtonName::LeftShoulder => "leftshoulder",
3868			ButtonName::LeftStick => "leftstick",
3869			ButtonName::RightShoulder => "rightshoulder",
3870			ButtonName::RightStick => "rightstick",
3871			ButtonName::Start => "start",
3872			ButtonName::X => "x",
3873			ButtonName::Y => "y",
3874		}
3875	}
3876}
3877
3878impl Controller {
3879	/// Checks whether a button is pressed down in the current frame.
3880	///
3881	/// # Arguments
3882	///
3883	/// * `controller_id` - The controller id, incrementing from 0 when multiple controllers are connected.
3884	/// * `name` - The name of the button to check.
3885	///
3886	/// # Returns
3887	///
3888	/// * `bool` - `true` if the button is pressed down, `false` otherwise.
3889	pub fn is_button_down(controller_id: i32, button: ButtonName) -> bool {
3890		Controller::_is_button_down(controller_id, button.as_ref())
3891	}
3892	/// Checks whether a button is released in the current frame.
3893	///
3894	/// # Arguments
3895	///
3896	/// * `controller_id` - The controller id, incrementing from 0 when multiple controllers are connected.
3897	/// * `name` - The name of the button to check.
3898	///
3899	/// # Returns
3900	///
3901	/// * `bool` - `true` if the button is released, `false` otherwise.
3902	pub fn is_button_up(controller_id: i32, button: ButtonName) -> bool {
3903		Controller::_is_button_up(controller_id, button.as_ref())
3904	}
3905	/// Checks whether a button is in pressed state.
3906	///
3907	/// # Arguments
3908	///
3909	/// * `controller_id` - The controller id, incrementing from 0 when multiple controllers are connected.
3910	/// * `name` - The name of the button to check.
3911	///
3912	/// # Returns
3913	///
3914	/// * `bool` - `true` if the button is in pressed state, `false` otherwise.
3915	pub fn is_button_pressed(controller_id: i32, button: ButtonName) -> bool {
3916		Controller::_is_button_pressed(controller_id, button.as_ref())
3917	}
3918	/// Gets the axis value from a given controller.
3919	///
3920	/// # Arguments
3921	///
3922	/// * `controller_id` - The controller id, incrementing from 0 when multiple controllers are connected.
3923	/// * `name` - The name of the controller axis to check.
3924	///
3925	/// # Returns
3926	///
3927	/// * `f32` - The axis value ranging from -1.0 to 1.0.
3928	pub fn get_axis(controller_id: i32, axis: AxisName) -> f32 {
3929		Controller::_get_axis(controller_id, axis.as_ref())
3930	}
3931}
3932
3933// Audio
3934
3935#[repr(i32)]
3936#[derive(Copy, Clone, Debug, PartialEq)]
3937pub enum AttenuationModel {
3938	NoAttenuation = 0,
3939	InverseDistance = 1,
3940	LinearDistance = 2,
3941	ExponentialDistance = 3,
3942}
3943
3944// platformer::ActionUpdate
3945
3946impl platformer::ActionUpdate {
3947	pub fn from_update(mut update: Box<dyn FnMut(f64) -> bool>) -> platformer::ActionUpdate {
3948		platformer::ActionUpdate::new(Box::new(move |_, _, dt| update(dt as f64)))
3949	}
3950}
3951
3952// Blackboard
3953
3954extern "C" {
3955	fn blackboard_set(b: i64, k: i64, v: i64);
3956	fn blackboard_get(b: i64, k: i64) -> i64;
3957}
3958
3959impl platformer::behavior::Blackboard {
3960	/// Sets a value in the blackboard.
3961	///
3962	/// # Arguments
3963	/// * `key` - The key associated with the value.
3964	/// * `value` - The value to be set.
3965	///
3966	/// # Example
3967	///
3968	/// ```
3969	/// blackboard.set("score", 100);
3970	/// ```
3971	pub fn set<'a, T>(&mut self, key: &str, value: T)
3972	where
3973		T: IntoValue<'a>,
3974	{
3975		unsafe {
3976			blackboard_set(self.raw(), from_string(key), value.val().raw());
3977		}
3978	}
3979	/// Retrieves a value from the blackboard.
3980	///
3981	/// # Arguments
3982	///
3983	/// * `key` - The key associated with the value.
3984	///
3985	/// # Returns
3986	///
3987	/// An `Option` containing the value associated with the key, or `None` if the key does not exist.
3988	///
3989	/// # Example
3990	///
3991	/// ```
3992	/// if let Some(score) = blackboard.get("score") {
3993	///     println!("Score: {}", score.into_i32().unwrap());
3994	/// } else {
3995	///     println!("Score not found.");
3996	/// }
3997	/// ```
3998	pub fn get(&self, key: &str) -> Option<Value> {
3999		Value::from(unsafe { blackboard_get(self.raw(), from_string(key)) })
4000	}
4001}
4002
4003pub use enumflags2::BitFlags;
4004use enumflags2::{bitflags, make_bitflags};
4005
4006#[bitflags]
4007#[repr(u32)]
4008#[derive(Copy, Clone, Debug, PartialEq)]
4009pub enum ImGuiSliderFlag {
4010	Logarithmic = 1 << 5,
4011	NoRoundToFormat = 1 << 6,
4012	NoInput = 1 << 7,
4013	WrapAround = 1 << 8,
4014	ClampOnInput = 1 << 9,
4015	ClampZeroRange = 1 << 10,
4016}
4017
4018impl ImGuiSliderFlag {
4019	pub const ALWAYS_CLAMP: BitFlags<Self> = make_bitflags!(Self::{ClampOnInput | ClampZeroRange});
4020}
4021
4022#[bitflags]
4023#[repr(u32)]
4024#[derive(Copy, Clone, Debug, PartialEq)]
4025pub enum ImGuiWindowFlag {
4026	NoTitleBar = 1 << 0,
4027	NoResize = 1 << 1,
4028	NoMove = 1 << 2,
4029	NoScrollbar = 1 << 3,
4030	NoScrollWithMouse = 1 << 4,
4031	NoCollapse = 1 << 5,
4032	AlwaysAutoResize = 1 << 6,
4033	NoBackground = 1 << 7,
4034	NoSavedSettings = 1 << 8,
4035	NoMouseInputs = 1 << 9,
4036	MenuBar = 1 << 10,
4037	HorizontalScrollbar = 1 << 11,
4038	NoFocusOnAppearing = 1 << 12,
4039	NoBringToFrontOnFocus = 1 << 13,
4040	AlwaysVerticalScrollbar = 1 << 14,
4041	AlwaysHorizontalScrollbar = 1 << 15,
4042	NoNavInputs = 1 << 16,
4043	NoNavFocus = 1 << 17,
4044	UnsavedDocument = 1 << 18,
4045}
4046
4047impl ImGuiWindowFlag {
4048	pub const NO_NAV: BitFlags<Self> = make_bitflags!(Self::{NoNavInputs | NoNavFocus});
4049	pub const NO_DECORATION: BitFlags<Self> =
4050		make_bitflags!(Self::{NoTitleBar | NoResize | NoScrollbar | NoCollapse});
4051	pub const NO_INPUTS: BitFlags<Self> =
4052		make_bitflags!(Self::{NoMouseInputs | NoNavInputs | NoNavFocus});
4053}
4054
4055#[bitflags]
4056#[repr(u8)]
4057#[derive(Copy, Clone, Debug, PartialEq)]
4058pub enum ImGuiChildFlag {
4059	Borders = 1 << 0,
4060	AlwaysUseWindowPadding = 1 << 1,
4061	ResizeX = 1 << 2,
4062	ResizeY = 1 << 3,
4063	AutoResizeX = 1 << 4,
4064	AutoResizeY = 1 << 5,
4065	AlwaysAutoResize = 1 << 6,
4066	FrameStyle = 1 << 7,
4067}
4068
4069#[bitflags]
4070#[repr(u32)]
4071#[derive(Copy, Clone, Debug, PartialEq)]
4072pub enum ImGuiInputTextFlag {
4073	CharsDecimal = 1 << 0,
4074	CharsHexadecimal = 1 << 1,
4075	CharsScientific = 1 << 2,
4076	CharsUppercase = 1 << 3,
4077	CharsNoBlank = 1 << 4,
4078	AllowTabInput = 1 << 5,
4079	EnterReturnsTrue = 1 << 6,
4080	EscapeClearsAll = 1 << 7,
4081	CtrlEnterForNewLine = 1 << 8,
4082	ReadOnly = 1 << 9,
4083	Password = 1 << 10,
4084	AlwaysOverwrite = 1 << 11,
4085	AutoSelectAll = 1 << 12,
4086	ParseEmptyRefVal = 1 << 13,
4087	DisplayEmptyRefVal = 1 << 14,
4088	NoHorizontalScroll = 1 << 15,
4089	NoUndoRedo = 1 << 16,
4090	ElideLeft = 1 << 17,
4091	CallbackCompletion = 1 << 18,
4092	CallbackHistory = 1 << 19,
4093	CallbackAlways = 1 << 20,
4094	CallbackCharFilter = 1 << 21,
4095	CallbackResize = 1 << 22,
4096	CallbackEdit = 1 << 23,
4097}
4098
4099#[bitflags]
4100#[repr(u32)]
4101#[derive(Copy, Clone, Debug, PartialEq)]
4102pub enum ImGuiTreeNodeFlag {
4103	Selected = 1 << 0,
4104	Framed = 1 << 1,
4105	AllowOverlap = 1 << 2,
4106	NoTreePushOnOpen = 1 << 3,
4107	NoAutoOpenOnLog = 1 << 4,
4108	DefaultOpen = 1 << 5,
4109	OpenOnDoubleClick = 1 << 6,
4110	OpenOnArrow = 1 << 7,
4111	Leaf = 1 << 8,
4112	Bullet = 1 << 9,
4113	FramePadding = 1 << 10,
4114	SpanAvailWidth = 1 << 11,
4115	SpanFullWidth = 1 << 12,
4116	SpanLabelWidth = 1 << 13,
4117	SpanAllColumns = 1 << 14,
4118	LabelSpanAllColumns = 1 << 15,
4119	NavLeftJumpsToParent = 1 << 17,
4120}
4121
4122impl ImGuiTreeNodeFlag {
4123	pub const COLLAPSING_HEADER: BitFlags<Self> =
4124		make_bitflags!(Self::{Framed | NoTreePushOnOpen | NoAutoOpenOnLog});
4125}
4126
4127#[bitflags]
4128#[repr(u8)]
4129#[derive(Copy, Clone, Debug, PartialEq)]
4130pub enum ImGuiSelectableFlag {
4131	DontClosePopups = 1 << 0,
4132	SpanAllColumns = 1 << 1,
4133	AllowDoubleClick = 1 << 2,
4134	Disabled = 1 << 3,
4135	AllowOverlap = 1 << 4,
4136}
4137
4138#[derive(Copy, Clone, Debug, PartialEq)]
4139pub enum ImGuiCol {
4140	Text,
4141	TextDisabled,
4142	WindowBg,
4143	ChildBg,
4144	PopupBg,
4145	Border,
4146	BorderShadow,
4147	FrameBg,
4148	FrameBgHovered,
4149	FrameBgActive,
4150	TitleBg,
4151	TitleBgActive,
4152	TitleBgCollapsed,
4153	MenuBarBg,
4154	ScrollbarBg,
4155	ScrollbarGrab,
4156	ScrollbarGrabHovered,
4157	ScrollbarGrabActive,
4158	CheckMark,
4159	SliderGrab,
4160	SliderGrabActive,
4161	Button,
4162	ButtonHovered,
4163	ButtonActive,
4164	Header,
4165	HeaderHovered,
4166	HeaderActive,
4167	Separator,
4168	SeparatorHovered,
4169	SeparatorActive,
4170	ResizeGrip,
4171	ResizeGripHovered,
4172	ResizeGripActive,
4173	TabHovered,
4174	Tab,
4175	TabSelected,
4176	TabSelectedOverline,
4177	TabDimmed,
4178	TabDimmedSelected,
4179	TabDimmedSelectedOverline,
4180	PlotLines,
4181	PlotLinesHovered,
4182	PlotHistogram,
4183	PlotHistogramHovered,
4184	TableHeaderBg,
4185	TableBorderStrong,
4186	TableBorderLight,
4187	TableRowBg,
4188	TableRowBgAlt,
4189	TextLink,
4190	TextSelectedBg,
4191	DragDropTarget,
4192	NavCursor,
4193	NavWindowingHighlight,
4194	NavWindowingDimBg,
4195	ModalWindowDimBg,
4196}
4197
4198#[bitflags]
4199#[repr(u32)]
4200#[derive(Copy, Clone, Debug, PartialEq)]
4201pub enum ImGuiColorEditFlag {
4202	NoAlpha = 1 << 1,
4203	NoPicker = 1 << 2,
4204	NoOptions = 1 << 3,
4205	NoSmallPreview = 1 << 4,
4206	NoInputs = 1 << 5,
4207	NoTooltip = 1 << 6,
4208	NoLabel = 1 << 7,
4209	NoSidePreview = 1 << 8,
4210	NoDragDrop = 1 << 9,
4211	NoBorder = 1 << 10,
4212	AlphaOpaque = 1 << 11,
4213	AlphaNoBg = 1 << 12,
4214	AlphaPreviewHalf = 1 << 13,
4215	AlphaBar = 1 << 16,
4216	HDR = 1 << 19,
4217	DisplayRGB = 1 << 20,
4218	DisplayHSV = 1 << 21,
4219	DisplayHex = 1 << 22,
4220	Uint8 = 1 << 23,
4221	Float = 1 << 24,
4222	PickerHueBar = 1 << 25,
4223	PickerHueWheel = 1 << 26,
4224	InputRGB = 1 << 27,
4225	InputHSV = 1 << 28,
4226}
4227
4228impl ImGuiColorEditFlag {
4229	pub const DEFAULT_OPTIONS: BitFlags<Self> =
4230		make_bitflags!(Self::{Uint8 | DisplayRGB | InputRGB | PickerHueBar});
4231}
4232
4233#[derive(Copy, Clone, Debug, PartialEq)]
4234pub enum ImGuiCond {
4235	Always = 1 << 0,
4236	Once = 1 << 1,
4237	FirstUseEver = 1 << 2,
4238	Appearing = 1 << 3,
4239}
4240
4241#[bitflags]
4242#[repr(u32)]
4243#[derive(Copy, Clone, Debug, PartialEq)]
4244pub enum ImGuiTableFlag {
4245	Resizable = 1 << 0,
4246	Reorderable = 1 << 1,
4247	Hideable = 1 << 2,
4248	Sortable = 1 << 3,
4249	NoSavedSettings = 1 << 4,
4250	ContextMenuInBody = 1 << 5,
4251	RowBg = 1 << 6,
4252	BordersInnerH = 1 << 7,
4253	BordersOuterH = 1 << 8,
4254	BordersInnerV = 1 << 9,
4255	BordersOuterV = 1 << 10,
4256	NoBordersInBody = 1 << 11,
4257	NoBordersInBodyUntilResize = 1 << 12,
4258	SizingFixedFit = 1 << 13,
4259	SizingFixedSame = 1 << 14,
4260	SizingStretchSame = 1 << 15,
4261	NoHostExtendX = 1 << 16,
4262	NoHostExtendY = 1 << 17,
4263	NoKeepColumnsVisible = 1 << 18,
4264	PreciseWidths = 1 << 19,
4265	NoClip = 1 << 20,
4266	PadOuterX = 1 << 21,
4267	NoPadOuterX = 1 << 22,
4268	NoPadInnerX = 1 << 23,
4269	ScrollX = 1 << 24,
4270	ScrollY = 1 << 25,
4271	SortMulti = 1 << 26,
4272	SortTristate = 1 << 27,
4273	HighlightHoveredColumn = 1 << 28,
4274}
4275
4276impl ImGuiTableFlag {
4277	pub const BORDERS_H: BitFlags<Self> = make_bitflags!(Self::{BordersInnerH | BordersOuterH});
4278	pub const BORDERS_V: BitFlags<Self> = make_bitflags!(Self::{BordersInnerV | BordersOuterV});
4279	pub const BORDERS_INNER: BitFlags<Self> = make_bitflags!(Self::{BordersInnerV | BordersInnerH});
4280	pub const BORDERS_OUTER: BitFlags<Self> = make_bitflags!(Self::{BordersOuterV | BordersOuterH});
4281	pub const BORDERS: BitFlags<Self> =
4282		make_bitflags!(Self::{BordersInnerV | BordersInnerH | BordersOuterV | BordersOuterH});
4283	pub const SIZING_STRETCH_PROP: BitFlags<Self> =
4284		make_bitflags!(Self::{SizingFixedFit | SizingFixedSame});
4285}
4286
4287#[bitflags]
4288#[repr(u32)]
4289#[derive(Copy, Clone, Debug, PartialEq)]
4290pub enum ImGuiTableColumnFlag {
4291	Disabled = 1 << 0,
4292	DefaultHide = 1 << 1,
4293	DefaultSort = 1 << 2,
4294	WidthStretch = 1 << 3,
4295	WidthFixed = 1 << 4,
4296	NoResize = 1 << 5,
4297	NoReorder = 1 << 6,
4298	NoHide = 1 << 7,
4299	NoClip = 1 << 8,
4300	NoSort = 1 << 9,
4301	NoSortAscending = 1 << 10,
4302	NoSortDescending = 1 << 11,
4303	NoHeaderLabel = 1 << 12,
4304	NoHeaderWidth = 1 << 13,
4305	PreferSortAscending = 1 << 14,
4306	PreferSortDescending = 1 << 15,
4307	IndentEnable = 1 << 16,
4308	IndentDisable = 1 << 17,
4309	AngledHeader = 1 << 18,
4310	IsEnabled = 1 << 24,
4311	IsVisible = 1 << 25,
4312	IsSorted = 1 << 26,
4313	IsHovered = 1 << 27,
4314}
4315
4316#[derive(Copy, Clone, Debug, PartialEq)]
4317pub enum ImGuiPopupButton {
4318	MouseButtonLeft = 0,
4319	MouseButtonRight = 1,
4320	MouseButtonMiddle = 2,
4321}
4322
4323#[bitflags]
4324#[repr(u32)]
4325#[derive(Copy, Clone, Debug, PartialEq)]
4326pub enum ImGuiPopupFlag {
4327	NoReopen = 1 << 5,
4328	NoOpenOverExistingPopup = 1 << 7,
4329	NoOpenOverItems = 1 << 8,
4330	AnyPopupId = 1 << 10,
4331	AnyPopupLevel = 1 << 11,
4332}
4333
4334impl ImGuiPopupFlag {
4335	pub const ANY_POPUP: BitFlags<Self> = make_bitflags!(Self::{AnyPopupId | AnyPopupLevel});
4336}
4337
4338#[derive(Copy, Clone, Debug, PartialEq)]
4339pub enum ImGuiStyleVar {
4340	Alpha = 0,
4341	DisabledAlpha = 1,
4342	WindowRounding = 3,
4343	WindowBorderSize = 4,
4344	ChildRounding = 7,
4345	ChildBorderSize = 8,
4346	PopupRounding = 9,
4347	PopupBorderSize = 10,
4348	FrameRounding = 12,
4349	FrameBorderSize = 13,
4350	IndentSpacing = 16,
4351	ScrollbarSize = 18,
4352	ScrollbarRounding = 19,
4353	GrabMinSize = 20,
4354	GrabRounding = 21,
4355	TabRounding = 22,
4356	TabBarBorderSize = 23,
4357	SeparatorTextBorderSize = 26,
4358}
4359
4360#[derive(Copy, Clone, Debug, PartialEq)]
4361pub enum ImGuiStyleVec2 {
4362	WindowPadding = 2,
4363	WindowMinSize = 5,
4364	WindowTitleAlign = 6,
4365	FramePadding = 11,
4366	ItemSpacing = 14,
4367	ItemInnerSpacing = 15,
4368	CellPadding = 17,
4369	ButtonTextAlign = 24,
4370	SelectableTextAlign = 25,
4371	SeparatorTextAlign = 27,
4372	SeparatorTextPadding = 28,
4373}
4374
4375#[bitflags]
4376#[repr(u32)]
4377#[derive(Copy, Clone, Debug, PartialEq)]
4378pub enum ImGuiItemFlag {
4379	NoTabStop = 1 << 0,
4380	NoNav = 1 << 1,
4381	NoNavDefaultFocus = 1 << 2,
4382	ButtonRepeat = 1 << 3,
4383	AutoClosePopups = 1 << 4,
4384	AllowDuplicateId = 1 << 5,
4385}
4386
4387#[bitflags]
4388#[repr(u8)]
4389#[derive(Copy, Clone, Debug, PartialEq)]
4390pub enum ImGuiTableRowFlag {
4391	Headers = 1 << 0,
4392}
4393
4394#[bitflags]
4395#[repr(u32)]
4396#[derive(Copy, Clone, Debug, PartialEq)]
4397pub enum ImGuiTabBarFlag {
4398	Reorderable = 1 << 0,
4399	AutoSelectNewTabs = 1 << 1,
4400	TabListPopupButton = 1 << 2,
4401	NoCloseWithMiddleMouseButton = 1 << 3,
4402	NoTabListScrollingButtons = 1 << 4,
4403	NoTooltip = 1 << 5,
4404	DrawSelectedOverline = 1 << 6,
4405	FittingPolicyShrink = 1 << 7,
4406	FittingPolicyScroll = 1 << 8,
4407}
4408
4409#[bitflags]
4410#[repr(u32)]
4411#[derive(Copy, Clone, Debug, PartialEq)]
4412pub enum ImGuiTabItemFlag {
4413	UnsavedDocument = 1 << 0,
4414	SetSelected = 1 << 1,
4415	NoCloseWithMiddleMouseButton = 1 << 2,
4416	NoPushId = 1 << 3,
4417	NoTooltip = 1 << 4,
4418	NoReorder = 1 << 5,
4419	Leading = 1 << 6,
4420	Trailing = 1 << 7,
4421	NoAssumedClosure = 1 << 8,
4422}
4423
4424thread_local! {
4425	static IMGUI_STACK: RefCell<CallStack> = RefCell::new(CallStack::new());
4426}
4427
4428impl ImGui {
4429	pub fn begin<C>(name: &str, inside: C)
4430	where
4431		C: FnOnce(),
4432	{
4433		ImGui::begin_opts(name, BitFlags::default(), inside);
4434	}
4435	pub fn begin_opts<C>(name: &str, windows_flags: BitFlags<ImGuiWindowFlag>, inside: C)
4436	where
4437		C: FnOnce(),
4438	{
4439		if ImGui::_begin_opts(name, windows_flags.bits() as i32) {
4440			inside();
4441		}
4442		ImGui::_end();
4443	}
4444	pub fn begin_ret<C>(name: &str, opened: bool, inside: C) -> bool
4445	where
4446		C: FnOnce(),
4447	{
4448		ImGui::begin_ret_opts(name, opened, BitFlags::default(), inside)
4449	}
4450	pub fn begin_ret_opts<C>(
4451		name: &str,
4452		opened: bool,
4453		windows_flags: BitFlags<ImGuiWindowFlag>,
4454		inside: C,
4455	) -> bool
4456	where
4457		C: FnOnce(),
4458	{
4459		let mut changed = false;
4460		let mut result = false;
4461		IMGUI_STACK.with_borrow_mut(|stack| {
4462			stack.push_bool(opened);
4463			changed = ImGui::_begin_ret_opts(name, stack, windows_flags.bits() as i32);
4464			result = stack.pop_bool().unwrap();
4465		});
4466		if result {
4467			inside();
4468		}
4469		ImGui::_end();
4470		changed
4471	}
4472	pub fn begin_child<C>(str_id: &str, inside: C)
4473	where
4474		C: FnOnce(),
4475	{
4476		ImGui::begin_child_opts(
4477			str_id,
4478			&Vec2::zero(),
4479			BitFlags::default(),
4480			BitFlags::default(),
4481			inside,
4482		);
4483	}
4484	pub fn begin_child_opts<C>(
4485		str_id: &str,
4486		size: &crate::dora::Vec2,
4487		child_flags: BitFlags<ImGuiChildFlag>,
4488		window_flags: BitFlags<ImGuiWindowFlag>,
4489		inside: C,
4490	) where
4491		C: FnOnce(),
4492	{
4493		if ImGui::_begin_child_opts(
4494			str_id,
4495			size,
4496			child_flags.bits() as i32,
4497			window_flags.bits() as i32,
4498		) {
4499			inside();
4500		}
4501		ImGui::_end_child();
4502	}
4503	pub fn begin_child_with_id<C>(id: i32, inside: C)
4504	where
4505		C: FnOnce(),
4506	{
4507		ImGui::begin_child_with_id_opts(
4508			id,
4509			&Vec2::zero(),
4510			BitFlags::default(),
4511			BitFlags::default(),
4512			inside,
4513		);
4514	}
4515	pub fn begin_child_with_id_opts<C>(
4516		id: i32,
4517		size: &crate::dora::Vec2,
4518		child_flags: BitFlags<ImGuiChildFlag>,
4519		window_flags: BitFlags<ImGuiWindowFlag>,
4520		inside: C,
4521	) where
4522		C: FnOnce(),
4523	{
4524		if ImGui::_begin_child_with_id_opts(
4525			id,
4526			size,
4527			child_flags.bits() as i32,
4528			window_flags.bits() as i32,
4529		) {
4530			inside();
4531		}
4532		ImGui::_end_child();
4533	}
4534	pub fn collapsing_header_ret(label: &str, opened: bool) -> (bool, bool) {
4535		ImGui::collapsing_header_ret_opts(label, opened, BitFlags::default())
4536	}
4537	pub fn collapsing_header_ret_opts(
4538		label: &str,
4539		opened: bool,
4540		tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
4541	) -> (bool, bool) {
4542		let mut changed = false;
4543		let mut result = false;
4544		IMGUI_STACK.with_borrow_mut(|stack| {
4545			stack.push_bool(opened);
4546			changed =
4547				ImGui::_collapsing_header_ret_opts(label, stack, tree_node_flags.bits() as i32);
4548			result = stack.pop_bool().unwrap();
4549		});
4550		(changed, result)
4551	}
4552	pub fn selectable_ret(label: &str, selected: bool) -> (bool, bool) {
4553		ImGui::selectable_ret_opts(label, selected, &Vec2::zero(), BitFlags::default())
4554	}
4555	pub fn selectable_ret_opts(
4556		label: &str,
4557		selected: bool,
4558		size: &crate::dora::Vec2,
4559		selectable_flags: BitFlags<ImGuiSelectableFlag>,
4560	) -> (bool, bool) {
4561		let mut changed = false;
4562		let mut result = false;
4563		IMGUI_STACK.with_borrow_mut(|stack| {
4564			stack.push_bool(selected);
4565			changed =
4566				ImGui::_selectable_ret_opts(label, stack, size, selectable_flags.bits() as i32);
4567			result = stack.pop_bool().unwrap();
4568		});
4569		(changed, result)
4570	}
4571	pub fn combo_ret(label: &str, current_item: i32, items: &Vec<&str>) -> (bool, i32) {
4572		ImGui::combo_ret_opts(label, current_item, items, -1)
4573	}
4574	pub fn combo_ret_opts(
4575		label: &str,
4576		current_item: i32,
4577		items: &Vec<&str>,
4578		height_in_items: i32,
4579	) -> (bool, i32) {
4580		let mut changed = false;
4581		let mut result = 0_i32;
4582		IMGUI_STACK.with_borrow_mut(|stack| {
4583			stack.push_i32(current_item);
4584			changed = ImGui::_combo_ret_opts(label, stack, items, height_in_items);
4585			result = stack.pop_i32().unwrap();
4586		});
4587		(changed, result)
4588	}
4589	pub fn drag_float_ret(
4590		label: &str,
4591		v: f32,
4592		v_speed: f32,
4593		v_min: f32,
4594		v_max: f32,
4595	) -> (bool, f32) {
4596		ImGui::drag_float_ret_opts(label, v, v_speed, v_min, v_max, "%.2f", BitFlags::default())
4597	}
4598	pub fn drag_float_ret_opts(
4599		label: &str,
4600		v: f32,
4601		v_speed: f32,
4602		v_min: f32,
4603		v_max: f32,
4604		display_format: &str,
4605		slider_flags: BitFlags<ImGuiSliderFlag>,
4606	) -> (bool, f32) {
4607		let mut changed = false;
4608		let mut result = 0_f32;
4609		IMGUI_STACK.with_borrow_mut(|stack| {
4610			stack.push_f32(v);
4611			changed = ImGui::_drag_float_ret_opts(
4612				label,
4613				stack,
4614				v_speed,
4615				v_min,
4616				v_max,
4617				display_format,
4618				slider_flags.bits() as i32,
4619			);
4620			result = stack.pop_f32().unwrap();
4621		});
4622		(changed, result)
4623	}
4624	pub fn drag_float2_ret(
4625		label: &str,
4626		v1: f32,
4627		v2: f32,
4628		v_speed: f32,
4629		v_min: f32,
4630		v_max: f32,
4631	) -> (bool, f32, f32) {
4632		ImGui::drag_float2_ret_opts(
4633			label,
4634			v1,
4635			v2,
4636			v_speed,
4637			v_min,
4638			v_max,
4639			"%.2f",
4640			BitFlags::default(),
4641		)
4642	}
4643	pub fn drag_float2_ret_opts(
4644		label: &str,
4645		v1: f32,
4646		v2: f32,
4647		v_speed: f32,
4648		v_min: f32,
4649		v_max: f32,
4650		display_format: &str,
4651		slider_flags: BitFlags<ImGuiSliderFlag>,
4652	) -> (bool, f32, f32) {
4653		let mut changed = false;
4654		let mut result1 = 0_f32;
4655		let mut result2 = 0_f32;
4656		IMGUI_STACK.with_borrow_mut(|stack| {
4657			stack.push_f32(v1);
4658			stack.push_f32(v2);
4659			changed = ImGui::_drag_float2_ret_opts(
4660				label,
4661				stack,
4662				v_speed,
4663				v_min,
4664				v_max,
4665				display_format,
4666				slider_flags.bits() as i32,
4667			);
4668			result1 = stack.pop_f32().unwrap();
4669			result2 = stack.pop_f32().unwrap();
4670		});
4671		(changed, result1, result2)
4672	}
4673	pub fn drag_int2_ret(
4674		label: &str,
4675		v1: i32,
4676		v2: i32,
4677		v_speed: f32,
4678		v_min: i32,
4679		v_max: i32,
4680	) -> (bool, i32, i32) {
4681		ImGui::drag_int2_ret_opts(label, v1, v2, v_speed, v_min, v_max, "%d", BitFlags::default())
4682	}
4683	pub fn drag_int2_ret_opts(
4684		label: &str,
4685		v1: i32,
4686		v2: i32,
4687		v_speed: f32,
4688		v_min: i32,
4689		v_max: i32,
4690		display_format: &str,
4691		slider_flags: BitFlags<ImGuiSliderFlag>,
4692	) -> (bool, i32, i32) {
4693		let mut changed = false;
4694		let mut result1 = 0_i32;
4695		let mut result2 = 0_i32;
4696		IMGUI_STACK.with_borrow_mut(|stack| {
4697			stack.push_i32(v1);
4698			stack.push_i32(v2);
4699			changed = ImGui::_drag_int2_ret_opts(
4700				label,
4701				stack,
4702				v_speed,
4703				v_min,
4704				v_max,
4705				display_format,
4706				slider_flags.bits() as i32,
4707			);
4708			result1 = stack.pop_i32().unwrap();
4709			result2 = stack.pop_i32().unwrap();
4710		});
4711		(changed, result1, result2)
4712	}
4713	pub fn input_float_ret(label: &str, v: f32) -> (bool, f32) {
4714		ImGui::input_float_ret_opts(label, v, 0.0, 0.0, "%.2f", BitFlags::default())
4715	}
4716	pub fn input_float_ret_opts(
4717		label: &str,
4718		v: f32,
4719		step: f32,
4720		step_fast: f32,
4721		display_format: &str,
4722		input_text_flags: BitFlags<ImGuiInputTextFlag>,
4723	) -> (bool, f32) {
4724		let mut changed = false;
4725		let mut result = 0_f32;
4726		IMGUI_STACK.with_borrow_mut(|stack| {
4727			stack.push_f32(v);
4728			changed = ImGui::_input_float_ret_opts(
4729				label,
4730				stack,
4731				step,
4732				step_fast,
4733				display_format,
4734				input_text_flags.bits() as i32,
4735			);
4736			result = stack.pop_f32().unwrap();
4737		});
4738		(changed, result)
4739	}
4740	pub fn input_float2_ret(label: &str, v1: f32, v2: f32) -> (bool, f32, f32) {
4741		ImGui::input_float2_ret_opts(label, v1, v2, "%.2f", BitFlags::default())
4742	}
4743	pub fn input_float2_ret_opts(
4744		label: &str,
4745		v1: f32,
4746		v2: f32,
4747		display_format: &str,
4748		input_text_flags: BitFlags<ImGuiInputTextFlag>,
4749	) -> (bool, f32, f32) {
4750		let mut changed = false;
4751		let mut result1 = 0_f32;
4752		let mut result2 = 0_f32;
4753		IMGUI_STACK.with_borrow_mut(|stack| {
4754			stack.push_f32(v1);
4755			stack.push_f32(v2);
4756			changed = ImGui::_input_float2_ret_opts(
4757				label,
4758				stack,
4759				display_format,
4760				input_text_flags.bits() as i32,
4761			);
4762			result1 = stack.pop_f32().unwrap();
4763			result2 = stack.pop_f32().unwrap();
4764		});
4765		(changed, result1, result2)
4766	}
4767	pub fn input_int_ret(label: &str, v: i32) -> (bool, i32) {
4768		ImGui::input_int_ret_opts(label, v, 1, 100, BitFlags::default())
4769	}
4770	pub fn input_int_ret_opts(
4771		label: &str,
4772		v: i32,
4773		step: i32,
4774		step_fast: i32,
4775		input_text_flags: BitFlags<ImGuiInputTextFlag>,
4776	) -> (bool, i32) {
4777		let mut changed = false;
4778		let mut result = 0_i32;
4779		IMGUI_STACK.with_borrow_mut(|stack| {
4780			stack.push_i32(v);
4781			changed = ImGui::_input_int_ret_opts(
4782				label,
4783				stack,
4784				step,
4785				step_fast,
4786				input_text_flags.bits() as i32,
4787			);
4788			result = stack.pop_i32().unwrap();
4789		});
4790		(changed, result)
4791	}
4792	pub fn input_int2_ret(label: &str, v1: i32, v2: i32) -> (bool, i32, i32) {
4793		ImGui::input_int2_ret_opts(label, v1, v2, BitFlags::default())
4794	}
4795	pub fn input_int2_ret_opts(
4796		label: &str,
4797		v1: i32,
4798		v2: i32,
4799		input_text_flags: BitFlags<ImGuiInputTextFlag>,
4800	) -> (bool, i32, i32) {
4801		let mut changed = false;
4802		let mut result1 = 0_i32;
4803		let mut result2 = 0_i32;
4804		IMGUI_STACK.with_borrow_mut(|stack| {
4805			stack.push_i32(v1);
4806			stack.push_i32(v2);
4807			changed = ImGui::_input_int2_ret_opts(label, stack, input_text_flags.bits() as i32);
4808			result1 = stack.pop_i32().unwrap();
4809			result2 = stack.pop_i32().unwrap();
4810		});
4811		(changed, result1, result2)
4812	}
4813	pub fn slider_float_ret(label: &str, v: f32, v_min: f32, v_max: f32) -> (bool, f32) {
4814		ImGui::slider_float_ret_opts(label, v, v_min, v_max, "%.2f", BitFlags::default())
4815	}
4816	pub fn slider_float_ret_opts(
4817		label: &str,
4818		v: f32,
4819		v_min: f32,
4820		v_max: f32,
4821		display_format: &str,
4822		slider_flags: BitFlags<ImGuiSliderFlag>,
4823	) -> (bool, f32) {
4824		let mut changed = false;
4825		let mut result = 0_f32;
4826		IMGUI_STACK.with_borrow_mut(|stack| {
4827			stack.push_f32(v);
4828			changed = ImGui::_slider_float_ret_opts(
4829				label,
4830				stack,
4831				v_min,
4832				v_max,
4833				display_format,
4834				slider_flags.bits() as i32,
4835			);
4836			result = stack.pop_f32().unwrap();
4837		});
4838		(changed, result)
4839	}
4840	pub fn slider_float2_ret(
4841		label: &str,
4842		v1: f32,
4843		v2: f32,
4844		v_min: f32,
4845		v_max: f32,
4846	) -> (bool, f32, f32) {
4847		ImGui::slider_float2_ret_opts(label, v1, v2, v_min, v_max, "%.2f", BitFlags::default())
4848	}
4849	pub fn slider_float2_ret_opts(
4850		label: &str,
4851		v1: f32,
4852		v2: f32,
4853		v_min: f32,
4854		v_max: f32,
4855		display_format: &str,
4856		slider_flags: BitFlags<ImGuiSliderFlag>,
4857	) -> (bool, f32, f32) {
4858		let mut changed = false;
4859		let mut result1 = 0_f32;
4860		let mut result2 = 0_f32;
4861		IMGUI_STACK.with_borrow_mut(|stack| {
4862			stack.push_f32(v1);
4863			stack.push_f32(v2);
4864			changed = ImGui::_slider_float2_ret_opts(
4865				label,
4866				stack,
4867				v_min,
4868				v_max,
4869				display_format,
4870				slider_flags.bits() as i32,
4871			);
4872			result1 = stack.pop_f32().unwrap();
4873			result2 = stack.pop_f32().unwrap();
4874		});
4875		(changed, result1, result2)
4876	}
4877	pub fn drag_float_range2_ret(
4878		label: &str,
4879		v_current_min: f32,
4880		v_current_max: f32,
4881		v_speed: f32,
4882		v_min: f32,
4883		v_max: f32,
4884	) -> (bool, f32, f32) {
4885		ImGui::drag_float_range2_ret_opts(
4886			label,
4887			v_current_min,
4888			v_current_max,
4889			v_speed,
4890			v_min,
4891			v_max,
4892			"%.2f",
4893			"%.2f",
4894			BitFlags::default(),
4895		)
4896	}
4897	pub fn drag_float_range2_ret_opts(
4898		label: &str,
4899		v_current_min: f32,
4900		v_current_max: f32,
4901		v_speed: f32,
4902		v_min: f32,
4903		v_max: f32,
4904		format: &str,
4905		format_max: &str,
4906		slider_flags: BitFlags<ImGuiSliderFlag>,
4907	) -> (bool, f32, f32) {
4908		let mut changed = false;
4909		let mut result1 = 0_f32;
4910		let mut result2 = 0_f32;
4911		IMGUI_STACK.with_borrow_mut(|stack| {
4912			stack.push_f32(v_current_min);
4913			stack.push_f32(v_current_max);
4914			changed = ImGui::_drag_float_range2_ret_opts(
4915				label,
4916				stack,
4917				v_speed,
4918				v_min,
4919				v_max,
4920				format,
4921				format_max,
4922				slider_flags.bits() as i32,
4923			);
4924			result1 = stack.pop_f32().unwrap();
4925			result2 = stack.pop_f32().unwrap();
4926		});
4927		(changed, result1, result2)
4928	}
4929	pub fn drag_int_ret(
4930		label: &str,
4931		value: i32,
4932		v_speed: f32,
4933		v_min: i32,
4934		v_max: i32,
4935	) -> (bool, i32) {
4936		ImGui::drag_int_ret_opts(label, value, v_speed, v_min, v_max, "%d", BitFlags::default())
4937	}
4938	pub fn drag_int_ret_opts(
4939		label: &str,
4940		value: i32,
4941		v_speed: f32,
4942		v_min: i32,
4943		v_max: i32,
4944		display_format: &str,
4945		slider_flags: BitFlags<ImGuiSliderFlag>,
4946	) -> (bool, i32) {
4947		let mut changed = false;
4948		let mut result = 0_i32;
4949		IMGUI_STACK.with_borrow_mut(|stack| {
4950			stack.push_i32(value);
4951			changed = ImGui::_drag_int_ret_opts(
4952				label,
4953				stack,
4954				v_speed,
4955				v_min,
4956				v_max,
4957				display_format,
4958				slider_flags.bits() as i32,
4959			);
4960			result = stack.pop_i32().unwrap();
4961		});
4962		(changed, result)
4963	}
4964	pub fn drag_int_range2_ret(
4965		label: &str,
4966		v_current_min: i32,
4967		v_current_max: i32,
4968		v_speed: f32,
4969		v_min: i32,
4970		v_max: i32,
4971	) -> (bool, i32, i32) {
4972		ImGui::drag_int_range2_ret_opts(
4973			label,
4974			v_current_min,
4975			v_current_max,
4976			v_speed,
4977			v_min,
4978			v_max,
4979			"%d",
4980			"%d",
4981			BitFlags::default(),
4982		)
4983	}
4984	pub fn drag_int_range2_ret_opts(
4985		label: &str,
4986		v_current_min: i32,
4987		v_current_max: i32,
4988		v_speed: f32,
4989		v_min: i32,
4990		v_max: i32,
4991		format: &str,
4992		format_max: &str,
4993		slider_flags: BitFlags<ImGuiSliderFlag>,
4994	) -> (bool, i32, i32) {
4995		let mut changed = false;
4996		let mut result1 = 0_i32;
4997		let mut result2 = 0_i32;
4998		IMGUI_STACK.with_borrow_mut(|stack| {
4999			stack.push_i32(v_current_min);
5000			stack.push_i32(v_current_max);
5001			changed = ImGui::_drag_int_range2_ret_opts(
5002				label,
5003				stack,
5004				v_speed,
5005				v_min,
5006				v_max,
5007				format,
5008				format_max,
5009				slider_flags.bits() as i32,
5010			);
5011			result1 = stack.pop_i32().unwrap();
5012			result2 = stack.pop_i32().unwrap();
5013		});
5014		(changed, result1, result2)
5015	}
5016	pub fn slider_int_ret(label: &str, value: i32, v_min: i32, v_max: i32) -> (bool, i32) {
5017		ImGui::slider_int_ret_opts(label, value, v_min, v_max, "%d", BitFlags::default())
5018	}
5019	pub fn slider_int_ret_opts(
5020		label: &str,
5021		value: i32,
5022		v_min: i32,
5023		v_max: i32,
5024		format: &str,
5025		slider_flags: BitFlags<ImGuiSliderFlag>,
5026	) -> (bool, i32) {
5027		let mut changed = false;
5028		let mut result = 0_i32;
5029		IMGUI_STACK.with_borrow_mut(|stack| {
5030			stack.push_i32(value);
5031			changed = ImGui::_slider_int_ret_opts(
5032				label,
5033				stack,
5034				v_min,
5035				v_max,
5036				format,
5037				slider_flags.bits() as i32,
5038			);
5039			result = stack.pop_i32().unwrap();
5040		});
5041		(changed, result)
5042	}
5043	pub fn slider_int2_ret(
5044		label: &str,
5045		v1: i32,
5046		v2: i32,
5047		v_min: i32,
5048		v_max: i32,
5049	) -> (bool, i32, i32) {
5050		ImGui::slider_int2_ret_opts(label, v1, v2, v_min, v_max, "%d", BitFlags::default())
5051	}
5052	pub fn slider_int2_ret_opts(
5053		label: &str,
5054		v1: i32,
5055		v2: i32,
5056		v_min: i32,
5057		v_max: i32,
5058		display_format: &str,
5059		slider_flags: BitFlags<ImGuiSliderFlag>,
5060	) -> (bool, i32, i32) {
5061		let mut changed = false;
5062		let mut result1 = 0_i32;
5063		let mut result2 = 0_i32;
5064		IMGUI_STACK.with_borrow_mut(|stack| {
5065			stack.push_i32(v1);
5066			stack.push_i32(v2);
5067			changed = ImGui::_slider_int2_ret_opts(
5068				label,
5069				stack,
5070				v_min,
5071				v_max,
5072				display_format,
5073				slider_flags.bits() as i32,
5074			);
5075			result1 = stack.pop_i32().unwrap();
5076			result2 = stack.pop_i32().unwrap();
5077		});
5078		(changed, result1, result2)
5079	}
5080	pub fn v_slider_float_ret(
5081		label: &str,
5082		size: &crate::dora::Vec2,
5083		v: f32,
5084		v_min: f32,
5085		v_max: f32,
5086	) -> (bool, f32) {
5087		ImGui::v_slider_float_ret_opts(label, size, v, v_min, v_max, "%.2f", BitFlags::default())
5088	}
5089	pub fn v_slider_float_ret_opts(
5090		label: &str,
5091		size: &crate::dora::Vec2,
5092		v: f32,
5093		v_min: f32,
5094		v_max: f32,
5095		format: &str,
5096		slider_flags: BitFlags<ImGuiSliderFlag>,
5097	) -> (bool, f32) {
5098		let mut changed = false;
5099		let mut result = 0_f32;
5100		IMGUI_STACK.with_borrow_mut(|stack| {
5101			stack.push_f32(v);
5102			changed = ImGui::_v_slider_float_ret_opts(
5103				label,
5104				size,
5105				stack,
5106				v_min,
5107				v_max,
5108				format,
5109				slider_flags.bits() as i32,
5110			);
5111			result = stack.pop_f32().unwrap();
5112		});
5113		(changed, result)
5114	}
5115	pub fn v_slider_int_ret(
5116		label: &str,
5117		size: &crate::dora::Vec2,
5118		v: i32,
5119		v_min: i32,
5120		v_max: i32,
5121	) -> (bool, i32) {
5122		ImGui::v_slider_int_ret_opts(label, size, v, v_min, v_max, "%d", BitFlags::default())
5123	}
5124	pub fn v_slider_int_ret_opts(
5125		label: &str,
5126		size: &crate::dora::Vec2,
5127		v: i32,
5128		v_min: i32,
5129		v_max: i32,
5130		format: &str,
5131		slider_flags: BitFlags<ImGuiSliderFlag>,
5132	) -> (bool, i32) {
5133		let mut changed = false;
5134		let mut result = 0_i32;
5135		IMGUI_STACK.with_borrow_mut(|stack| {
5136			stack.push_i32(v);
5137			changed = ImGui::_v_slider_int_ret_opts(
5138				label,
5139				size,
5140				stack,
5141				v_min,
5142				v_max,
5143				format,
5144				slider_flags.bits() as i32,
5145			);
5146			result = stack.pop_i32().unwrap();
5147		});
5148		(changed, result)
5149	}
5150	pub fn color_edit3_ret(label: &str, color3: &Color3) -> (bool, Color3) {
5151		ImGui::color_edit3_ret_opts(label, color3, BitFlags::default())
5152	}
5153	pub fn color_edit3_ret_opts(
5154		label: &str,
5155		color3: &Color3,
5156		color_edit_flags: BitFlags<ImGuiColorEditFlag>,
5157	) -> (bool, Color3) {
5158		let mut changed = false;
5159		let mut result = 0_i32;
5160		IMGUI_STACK.with_borrow_mut(|stack| {
5161			stack.push_i32(color3.to_rgb() as i32);
5162			changed = ImGui::_color_edit3_ret_opts(label, stack, color_edit_flags.bits() as i32);
5163			result = stack.pop_i32().unwrap();
5164		});
5165		(changed, Color3::new(result as u32))
5166	}
5167	pub fn color_edit4_ret(label: &str, color: &Color) -> (bool, Color) {
5168		ImGui::color_edit4_ret_opts(label, color, BitFlags::default())
5169	}
5170	pub fn color_edit4_ret_opts(
5171		label: &str,
5172		color: &Color,
5173		color_edit_flags: BitFlags<ImGuiColorEditFlag>,
5174	) -> (bool, Color) {
5175		let mut changed = false;
5176		let mut result = 0_i32;
5177		IMGUI_STACK.with_borrow_mut(|stack| {
5178			stack.push_i32(color.to_argb() as i32);
5179			changed = ImGui::_color_edit4_ret_opts(label, stack, color_edit_flags.bits() as i32);
5180			result = stack.pop_i32().unwrap();
5181		});
5182		(changed, Color::new(result as u32))
5183	}
5184	pub fn checkbox_ret(label: &str, checked: bool) -> (bool, bool) {
5185		let mut changed = false;
5186		let mut result = false;
5187		IMGUI_STACK.with_borrow_mut(|stack| {
5188			stack.push_bool(checked);
5189			changed = ImGui::_checkbox_ret(label, stack);
5190			result = stack.pop_bool().unwrap();
5191		});
5192		(changed, result)
5193	}
5194	pub fn radio_button_ret(label: &str, value: i32, v_button: i32) -> (bool, i32) {
5195		let mut changed = false;
5196		let mut result = 0_i32;
5197		IMGUI_STACK.with_borrow_mut(|stack| {
5198			stack.push_i32(value);
5199			changed = ImGui::_radio_button_ret(label, stack, v_button);
5200			result = stack.pop_i32().unwrap();
5201		});
5202		(changed, result)
5203	}
5204	pub fn list_box_ret(label: &str, current_item: i32, items: &Vec<&str>) -> (bool, i32) {
5205		ImGui::list_box_ret_opts(label, current_item, items, -1)
5206	}
5207	pub fn list_box_ret_opts(
5208		label: &str,
5209		current_item: i32,
5210		items: &Vec<&str>,
5211		height_in_items: i32,
5212	) -> (bool, i32) {
5213		let mut changed = false;
5214		let mut result = 0_i32;
5215		IMGUI_STACK.with_borrow_mut(|stack| {
5216			stack.push_i32(current_item);
5217			changed = ImGui::_list_box_ret_opts(label, stack, items, height_in_items);
5218			result = stack.pop_i32().unwrap();
5219		});
5220		(changed, result)
5221	}
5222	pub fn set_next_window_pos_center() {
5223		ImGui::set_next_window_pos_center_opts(ImGuiCond::Always);
5224	}
5225	pub fn set_next_window_pos_center_opts(set_cond: ImGuiCond) {
5226		ImGui::_set_next_window_pos_center_opts(set_cond as i32);
5227	}
5228	pub fn set_next_window_size(size: &crate::dora::Vec2) {
5229		ImGui::set_next_window_size_opts(size, ImGuiCond::Always);
5230	}
5231	pub fn set_next_window_size_opts(size: &crate::dora::Vec2, set_cond: ImGuiCond) {
5232		ImGui::_set_next_window_size_opts(size, set_cond as i32);
5233	}
5234	pub fn set_next_window_collapsed(collapsed: bool) {
5235		ImGui::set_next_window_collapsed_opts(collapsed, ImGuiCond::Always);
5236	}
5237	pub fn set_next_window_collapsed_opts(collapsed: bool, set_cond: ImGuiCond) {
5238		ImGui::_set_next_window_collapsed_opts(collapsed, set_cond as i32);
5239	}
5240	pub fn set_window_pos(name: &str, pos: &crate::dora::Vec2) {
5241		ImGui::set_window_pos_opts(name, pos, ImGuiCond::Always);
5242	}
5243	pub fn set_window_pos_opts(name: &str, pos: &crate::dora::Vec2, set_cond: ImGuiCond) {
5244		ImGui::_set_window_pos_opts(name, pos, set_cond as i32);
5245	}
5246	pub fn set_window_size(name: &str, size: &crate::dora::Vec2) {
5247		ImGui::set_window_size_opts(name, size, ImGuiCond::Always);
5248	}
5249	pub fn set_window_size_opts(name: &str, size: &crate::dora::Vec2, set_cond: ImGuiCond) {
5250		ImGui::_set_window_size_opts(name, size, set_cond as i32);
5251	}
5252	pub fn set_window_collapsed(name: &str, collapsed: bool) {
5253		ImGui::set_window_collapsed_opts(name, collapsed, ImGuiCond::Always);
5254	}
5255	pub fn set_window_collapsed_opts(name: &str, collapsed: bool, set_cond: ImGuiCond) {
5256		ImGui::_set_window_collapsed_opts(name, collapsed, set_cond as i32);
5257	}
5258	pub fn set_color_edit_options(color_edit_flags: BitFlags<ImGuiColorEditFlag>) {
5259		ImGui::_set_color_edit_options(color_edit_flags.bits() as i32);
5260	}
5261	pub fn input_text(label: &str, buffer: &crate::dora::Buffer) -> bool {
5262		ImGui::input_text_opts(label, buffer, BitFlags::default())
5263	}
5264	pub fn input_text_opts(
5265		label: &str,
5266		buffer: &crate::dora::Buffer,
5267		input_text_flags: BitFlags<ImGuiInputTextFlag>,
5268	) -> bool {
5269		ImGui::_input_text_opts(label, buffer, input_text_flags.bits() as i32)
5270	}
5271	pub fn input_text_multiline(
5272		label: &str,
5273		buffer: &crate::dora::Buffer,
5274		size: &crate::dora::Vec2,
5275	) -> bool {
5276		ImGui::input_text_multiline_opts(label, buffer, size, BitFlags::default())
5277	}
5278	pub fn input_text_multiline_opts(
5279		label: &str,
5280		buffer: &crate::dora::Buffer,
5281		size: &crate::dora::Vec2,
5282		input_text_flags: BitFlags<ImGuiInputTextFlag>,
5283	) -> bool {
5284		ImGui::_input_text_multiline_opts(label, buffer, size, input_text_flags.bits() as i32)
5285	}
5286	pub fn tree_push<C>(str_id: &str, inside: C)
5287	where
5288		C: FnOnce(),
5289	{
5290		ImGui::_tree_push(str_id);
5291		inside();
5292		ImGui::_tree_pop();
5293	}
5294	pub fn tree_node<C>(str_id: &str, text: &str, inside: C)
5295	where
5296		C: FnOnce(),
5297	{
5298		if ImGui::_tree_node(str_id, text) {
5299			inside();
5300			ImGui::_tree_pop();
5301		}
5302	}
5303	pub fn tree_node_ex<C>(label: &str, inside: C)
5304	where
5305		C: FnOnce(),
5306	{
5307		ImGui::tree_node_ex_opts(label, BitFlags::default(), inside)
5308	}
5309	pub fn tree_node_ex_opts<C>(
5310		label: &str,
5311		tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
5312		inside: C,
5313	) where
5314		C: FnOnce(),
5315	{
5316		if ImGui::_tree_node_ex_opts(label, tree_node_flags.bits() as i32) {
5317			inside();
5318			ImGui::_tree_pop();
5319		}
5320	}
5321	pub fn tree_node_ex_with_id<C>(str_id: &str, text: &str, inside: C)
5322	where
5323		C: FnOnce(),
5324	{
5325		ImGui::tree_node_ex_with_id_opts(str_id, text, BitFlags::default(), inside);
5326	}
5327	pub fn tree_node_ex_with_id_opts<C>(
5328		str_id: &str,
5329		text: &str,
5330		tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
5331		inside: C,
5332	) where
5333		C: FnOnce(),
5334	{
5335		if ImGui::_tree_node_ex_with_id_opts(str_id, text, tree_node_flags.bits() as i32) {
5336			inside();
5337			ImGui::_tree_pop();
5338		}
5339	}
5340	pub fn set_next_item_open(is_open: bool) {
5341		ImGui::set_next_item_open_opts(is_open, ImGuiCond::Always);
5342	}
5343	pub fn set_next_item_open_opts(is_open: bool, set_cond: ImGuiCond) {
5344		ImGui::_set_next_item_open_opts(is_open, set_cond as i32);
5345	}
5346	pub fn collapsing_header(label: &str) -> bool {
5347		ImGui::collapsing_header_opts(label, BitFlags::default())
5348	}
5349	pub fn collapsing_header_opts(
5350		label: &str,
5351		tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
5352	) -> bool {
5353		ImGui::_collapsing_header_opts(label, tree_node_flags.bits() as i32)
5354	}
5355	pub fn selectable(label: &str) -> bool {
5356		ImGui::selectable_opts(label, BitFlags::default())
5357	}
5358	pub fn selectable_opts(label: &str, selectable_flags: BitFlags<ImGuiSelectableFlag>) -> bool {
5359		ImGui::_selectable_opts(label, selectable_flags.bits() as i32)
5360	}
5361	pub fn begin_popup<C>(str_id: &str, inside: C)
5362	where
5363		C: FnOnce(),
5364	{
5365		if ImGui::_begin_popup(str_id) {
5366			inside();
5367			ImGui::_end_popup();
5368		}
5369	}
5370	pub fn begin_popup_modal<C>(name: &str, inside: C)
5371	where
5372		C: FnOnce(),
5373	{
5374		ImGui::begin_popup_modal_opts(name, BitFlags::default(), inside);
5375	}
5376	pub fn begin_popup_modal_opts<C>(
5377		name: &str,
5378		windows_flags: BitFlags<ImGuiWindowFlag>,
5379		inside: C,
5380	) where
5381		C: FnOnce(),
5382	{
5383		if ImGui::_begin_popup_modal_opts(name, windows_flags.bits() as i32) {
5384			inside();
5385			ImGui::_end_popup();
5386		}
5387	}
5388	pub fn begin_popup_modal_ret<C>(
5389		name: &str,
5390		opened: bool,
5391		inside: C,
5392	) -> (bool, bool)
5393	where
5394		C: FnOnce(),
5395	{
5396		ImGui::begin_popup_modal_ret_opts(name, opened, BitFlags::default(), inside)
5397	}
5398	pub fn begin_popup_modal_ret_opts<C>(
5399		name: &str,
5400		opened: bool,
5401		windows_flags: BitFlags<ImGuiWindowFlag>,
5402		inside: C,
5403	) -> (bool, bool)
5404	where
5405		C: FnOnce(),
5406	{
5407		let mut changed = false;
5408		let mut result = false;
5409		IMGUI_STACK.with_borrow_mut(|stack| {
5410			stack.push_bool(opened);
5411			changed = ImGui::_begin_popup_modal_ret_opts(name, stack, windows_flags.bits() as i32);
5412			result = stack.pop_bool().unwrap();
5413		});
5414		if changed {
5415			inside();
5416			ImGui::_end_popup();
5417		}
5418		(changed, result)
5419	}
5420	pub fn begin_popup_context_item<C>(name: &str, inside: C)
5421	where
5422		C: FnOnce(),
5423	{
5424		ImGui::begin_popup_context_item_opts(
5425			name,
5426			ImGuiPopupButton::MouseButtonRight,
5427			BitFlags::default(),
5428			inside,
5429		);
5430	}
5431	pub fn begin_popup_context_item_opts<C>(
5432		name: &str,
5433		button: ImGuiPopupButton,
5434		popup_flags: BitFlags<ImGuiPopupFlag>,
5435		inside: C,
5436	) where
5437		C: FnOnce(),
5438	{
5439		if ImGui::_begin_popup_context_item_opts(name, (button as u32 | popup_flags.bits()) as i32)
5440		{
5441			inside();
5442			ImGui::_end_popup();
5443		}
5444	}
5445	pub fn begin_popup_context_window<C>(name: &str, inside: C)
5446	where
5447		C: FnOnce(),
5448	{
5449		ImGui::begin_popup_context_window_opts(
5450			name,
5451			ImGuiPopupButton::MouseButtonRight,
5452			BitFlags::default(),
5453			inside,
5454		);
5455	}
5456	pub fn begin_popup_context_window_opts<C>(
5457		name: &str,
5458		button: ImGuiPopupButton,
5459		popup_flags: BitFlags<ImGuiPopupFlag>,
5460		inside: C,
5461	) where
5462		C: FnOnce(),
5463	{
5464		if ImGui::_begin_popup_context_window_opts(
5465			name,
5466			(button as u32 | popup_flags.bits()) as i32,
5467		) {
5468			inside();
5469			ImGui::_end_popup();
5470		}
5471	}
5472	pub fn begin_popup_context_void<C>(name: &str, inside: C)
5473	where
5474		C: FnOnce(),
5475	{
5476		ImGui::begin_popup_context_void_opts(
5477			name,
5478			ImGuiPopupButton::MouseButtonRight,
5479			BitFlags::default(),
5480			inside,
5481		);
5482	}
5483	pub fn begin_popup_context_void_opts<C>(
5484		name: &str,
5485		button: ImGuiPopupButton,
5486		popup_flags: BitFlags<ImGuiPopupFlag>,
5487		inside: C,
5488	) where
5489		C: FnOnce(),
5490	{
5491		if ImGui::_begin_popup_context_void_opts(name, (button as u32 | popup_flags.bits()) as i32)
5492		{
5493			inside();
5494			ImGui::_end_popup();
5495		}
5496	}
5497	pub fn begin_table<C>(str_id: &str, column: i32, inside: C)
5498	where
5499		C: FnOnce(),
5500	{
5501		ImGui::begin_table_opts(str_id, column, &Vec2::zero(), -1.0, BitFlags::default(), inside);
5502	}
5503	pub fn begin_table_opts<C>(
5504		str_id: &str,
5505		column: i32,
5506		outer_size: &crate::dora::Vec2,
5507		inner_width: f32,
5508		table_flags: BitFlags<ImGuiTableFlag>,
5509		inside: C,
5510	) where
5511		C: FnOnce(),
5512	{
5513		if ImGui::_begin_table_opts(
5514			str_id,
5515			column,
5516			outer_size,
5517			inner_width,
5518			table_flags.bits() as i32,
5519		) {
5520			inside();
5521			ImGui::_end_table();
5522		}
5523	}
5524	pub fn table_setup_column(label: &str, init_width_or_weight: f32) {
5525		ImGui::table_setup_column_opts(label, init_width_or_weight, 0, BitFlags::default())
5526	}
5527	pub fn table_setup_column_opts(
5528		label: &str,
5529		init_width_or_weight: f32,
5530		user_id: i32,
5531		table_column_flags: BitFlags<ImGuiTableColumnFlag>,
5532	) {
5533		ImGui::_table_setup_column_opts(
5534			label,
5535			init_width_or_weight,
5536			user_id,
5537			table_column_flags.bits() as i32,
5538		);
5539	}
5540	pub fn set_next_window_pos(pos: &crate::dora::Vec2) {
5541		ImGui::set_next_window_pos_opts(pos, ImGuiCond::Always, &Vec2::zero());
5542	}
5543	pub fn set_next_window_pos_opts(
5544		pos: &crate::dora::Vec2,
5545		set_cond: ImGuiCond,
5546		pivot: &crate::dora::Vec2,
5547	) {
5548		ImGui::_set_next_window_pos_opts(pos, set_cond as i32, pivot);
5549	}
5550	pub fn push_style_color<C>(col: ImGuiCol, color: &crate::dora::Color, inside: C)
5551	where
5552		C: FnOnce(),
5553	{
5554		ImGui::_push_style_color(col as i32, color);
5555		inside();
5556		ImGui::_pop_style_color(1);
5557	}
5558	pub fn push_style_float<C>(style: ImGuiStyleVar, val: f32, inside: C)
5559	where
5560		C: FnOnce(),
5561	{
5562		ImGui::_push_style_float(style as i32, val);
5563		inside();
5564		ImGui::_pop_style_var(1);
5565	}
5566	pub fn push_style_vec2<C>(style: ImGuiStyleVec2, val: &crate::dora::Vec2, inside: C)
5567	where
5568		C: FnOnce(),
5569	{
5570		ImGui::_push_style_vec2(style as i32, val);
5571		inside();
5572		ImGui::_pop_style_var(1);
5573	}
5574	pub fn color_button(desc_id: &str, col: &crate::dora::Color) -> bool {
5575		ImGui::color_button_opts(desc_id, col, BitFlags::default(), &Vec2::zero())
5576	}
5577	pub fn color_button_opts(
5578		desc_id: &str,
5579		col: &crate::dora::Color,
5580		color_edit_flags: BitFlags<ImGuiColorEditFlag>,
5581		size: &crate::dora::Vec2,
5582	) -> bool {
5583		ImGui::_color_button_opts(desc_id, col, color_edit_flags.bits() as i32, size)
5584	}
5585	pub fn slider_angle_ret(
5586		label: &str,
5587		v: f32,
5588		v_degrees_min: f32,
5589		v_degrees_max: f32,
5590	) -> (bool, f32) {
5591		let mut changed = false;
5592		let mut result = 0_f32;
5593		IMGUI_STACK.with_borrow_mut(|stack| {
5594			stack.push_f32(v);
5595			changed = ImGui::_slider_angle_ret(label, stack, v_degrees_min, v_degrees_max);
5596			result = stack.pop_f32().unwrap();
5597		});
5598		(changed, result)
5599	}
5600	pub fn image_button(str_id: &str, clip_str: &str, size: &crate::dora::Vec2) -> bool {
5601		ImGui::image_button_opts(str_id, clip_str, size, &Color::TRANSPARENT, &Color::WHITE)
5602	}
5603	pub fn table_next_row() {
5604		ImGui::table_next_row_opts(0.0, BitFlags::default());
5605	}
5606	pub fn table_next_row_opts(min_row_height: f32, table_row_flags: BitFlags<ImGuiTableRowFlag>) {
5607		ImGui::_table_next_row_opts(min_row_height, table_row_flags.bits() as i32);
5608	}
5609	pub fn begin_list_box<C>(label: &str, size: &crate::dora::Vec2, inside: C)
5610	where
5611		C: FnOnce(),
5612	{
5613		if ImGui::_begin_list_box(label, size) {
5614			inside();
5615			ImGui::_end_list_box();
5616		}
5617	}
5618	pub fn begin_group<C>(inside: C)
5619	where
5620		C: FnOnce(),
5621	{
5622		ImGui::_begin_group();
5623		inside();
5624		ImGui::_end_group();
5625	}
5626	pub fn begin_disabled<C>(inside: C)
5627	where
5628		C: FnOnce(),
5629	{
5630		ImGui::_begin_disabled();
5631		inside();
5632		ImGui::_end_disabled();
5633	}
5634	pub fn begin_tooltip<C>(inside: C)
5635	where
5636		C: FnOnce(),
5637	{
5638		if ImGui::_begin_tooltip() {
5639			inside();
5640			ImGui::_end_tooltip();
5641		}
5642	}
5643	pub fn begin_main_menu_bar<C>(inside: C)
5644	where
5645		C: FnOnce(),
5646	{
5647		if ImGui::_begin_main_menu_bar() {
5648			inside();
5649			ImGui::_end_main_menu_bar();
5650		}
5651	}
5652	pub fn begin_menu_bar<C>(inside: C)
5653	where
5654		C: FnOnce(),
5655	{
5656		if ImGui::_begin_menu_bar() {
5657			inside();
5658			ImGui::_end_menu_bar();
5659		}
5660	}
5661	pub fn begin_menu<C>(label: &str, enabled: bool, inside: C)
5662	where
5663		C: FnOnce(),
5664	{
5665		if ImGui::_begin_menu(label, enabled) {
5666			inside();
5667			ImGui::_end_menu();
5668		}
5669	}
5670	pub fn push_item_width<C>(width: f32, inside: C)
5671	where
5672		C: FnOnce(),
5673	{
5674		ImGui::_push_item_width(width);
5675		inside();
5676		ImGui::_pop_item_width();
5677	}
5678	pub fn push_text_wrap_pos<C>(wrap_pos_x: f32, inside: C)
5679	where
5680		C: FnOnce(),
5681	{
5682		ImGui::_push_text_wrap_pos(wrap_pos_x);
5683		inside();
5684		ImGui::_pop_text_wrap_pos();
5685	}
5686	pub fn push_item_flag<C>(flags: BitFlags<ImGuiItemFlag>, v: bool, inside: C)
5687	where
5688		C: FnOnce(),
5689	{
5690		ImGui::_push_item_flag(flags.bits() as i32, v);
5691		inside();
5692		ImGui::_pop_item_flag();
5693	}
5694	pub fn push_id<C>(str_id: &str, inside: C)
5695	where
5696		C: FnOnce(),
5697	{
5698		ImGui::_push_id(str_id);
5699		inside();
5700		ImGui::_pop_id();
5701	}
5702	pub fn push_clip_rect<C>(
5703		clip_rect_min: &crate::dora::Vec2,
5704		clip_rect_max: &crate::dora::Vec2,
5705		intersect_with_current_clip_rect: bool,
5706		inside: C,
5707	) where
5708		C: FnOnce(),
5709	{
5710		ImGui::_push_clip_rect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
5711		inside();
5712		ImGui::_pop_clip_rect();
5713	}
5714	pub fn begin_tab_bar<C>(str_id: &str, inside: C)
5715	where
5716		C: FnOnce(),
5717	{
5718		if ImGui::_begin_tab_bar(str_id) {
5719			inside();
5720			ImGui::_end_tab_bar();
5721		}
5722	}
5723	pub fn begin_tab_bar_opts<C>(
5724		str_id: &str,
5725		flags: BitFlags<ImGuiTabBarFlag>,
5726		inside: C,
5727	) where
5728		C: FnOnce(),
5729	{
5730		if ImGui::_begin_tab_bar_opts(str_id, flags.bits() as i32) {
5731			inside();
5732			ImGui::_end_tab_bar();
5733		}
5734	}
5735	pub fn begin_tab_item<C>(label: &str, inside: C)
5736	where
5737		C: FnOnce(),
5738	{
5739		if ImGui::_begin_tab_item(label) {
5740			inside();
5741			ImGui::_end_tab_item();
5742		}
5743	}
5744	pub fn begin_tab_item_opts<C>(
5745		label: &str,
5746		flags: BitFlags<ImGuiTabItemFlag>,
5747		inside: C,
5748	) where
5749		C: FnOnce(),
5750	{
5751		if ImGui::_begin_tab_item_opts(label, flags.bits() as i32) {
5752			inside();
5753			ImGui::_end_tab_item();
5754		}
5755	}
5756	pub fn begin_tab_item_ret<C>(label: &str, opened: bool, inside: C) -> bool
5757	where
5758		C: FnOnce(),
5759	{
5760		let mut changed = false;
5761		let mut result = false;
5762		IMGUI_STACK.with_borrow_mut(|stack| {
5763			stack.push_bool(opened);
5764			result = ImGui::_begin_tab_item_ret(label, stack);
5765			changed = stack.pop_bool().unwrap();
5766		});
5767		if result {
5768			inside();
5769			ImGui::_end_tab_item();
5770		}
5771		changed
5772	}
5773	pub fn begin_tab_item_ret_opts<C>(
5774		label: &str,
5775		opened: bool,
5776		flags: BitFlags<ImGuiTabItemFlag>,
5777		inside: C,
5778	) -> bool
5779	where
5780		C: FnOnce(),
5781	{
5782		let mut changed = false;
5783		let mut result = false;
5784		IMGUI_STACK.with_borrow_mut(|stack| {
5785			stack.push_bool(opened);
5786			result = ImGui::_begin_tab_item_ret_opts(label, stack, flags.bits() as i32);
5787			changed = stack.pop_bool().unwrap();
5788		});
5789		if result {
5790			inside();
5791			ImGui::_end_tab_item();
5792		}
5793		changed
5794	}
5795	pub fn tab_item_button_opts(label: &str, flags: BitFlags<ImGuiTabItemFlag>) -> bool {
5796		ImGui::_tab_item_button_opts(label, flags.bits() as i32)
5797	}
5798}
5799
5800#[bitflags]
5801#[repr(u32)]
5802#[derive(Copy, Clone, Debug, PartialEq)]
5803pub enum NvgImageFlag {
5804	/// Generate mipmaps during creation of the image.
5805	GenerateMipmaps = 1 << 0,
5806	/// Repeat image in X direction.
5807	RepeatX = 1 << 1,
5808	/// Repeat image in Y direction.
5809	RepeatY = 1 << 2,
5810	/// Flips (inverses) image in Y direction when rendered.
5811	FlipY = 1 << 3,
5812	/// Image data has premultiplied alpha.
5813	Premultiplied = 1 << 4,
5814	/// Image interpolation is Nearest instead Linear
5815	Nearest = 1 << 5,
5816}
5817
5818#[repr(i32)]
5819#[derive(Copy, Clone, Debug, PartialEq)]
5820pub enum NvgLineCap {
5821	Butt = 0,
5822	Round = 1,
5823	Square = 2,
5824}
5825
5826#[repr(i32)]
5827#[derive(Copy, Clone, Debug, PartialEq)]
5828pub enum NvgLineJoin {
5829	Round = 1,
5830	Bevel = 3,
5831	Miter = 4,
5832}
5833
5834#[repr(i32)]
5835#[derive(Copy, Clone, Debug, PartialEq)]
5836pub enum NvgWinding {
5837	/// Winding for solid shapes
5838	CCW = 1,
5839	/// Winding for holes
5840	CW = 2,
5841}
5842impl NvgWinding {
5843	pub const SOLID: NvgWinding = NvgWinding::CCW;
5844	pub const HOLE: NvgWinding = NvgWinding::CW;
5845}
5846
5847#[repr(i32)]
5848#[derive(Copy, Clone, Debug, PartialEq)]
5849pub enum NvgArcDir {
5850	CCW = 1,
5851	CW = 2,
5852}
5853
5854#[repr(i32)]
5855#[derive(Copy, Clone, Debug, PartialEq)]
5856pub enum NvgHAlign {
5857	/// Default, align text horizontally to left.
5858	Left = 1 << 0,
5859	/// Align text horizontally to center.
5860	Center = 1 << 1,
5861	/// Align text horizontally to right.
5862	Right = 1 << 2,
5863}
5864
5865#[repr(i32)]
5866#[derive(Copy, Clone, Debug, PartialEq)]
5867pub enum NvgVAlign {
5868	/// Align text vertically to top.
5869	Top = 1 << 3,
5870	/// Align text vertically to middle.
5871	Middle = 1 << 4,
5872	/// Align text vertically to bottom.
5873	Bottom = 1 << 5,
5874	/// Default, align text vertically to baseline.
5875	BaseLine = 1 << 6,
5876}
5877
5878impl Nvg {
5879	pub fn create_image(
5880		w: i32,
5881		h: i32,
5882		filename: &str,
5883		image_flags: BitFlags<NvgImageFlag>,
5884	) -> i32 {
5885		Nvg::_create_image(w, h, filename, image_flags.bits() as i32)
5886	}
5887	pub fn line_cap(cap: NvgLineCap) {
5888		Nvg::_line_cap(cap as i32);
5889	}
5890	pub fn line_join(join: NvgLineJoin) {
5891		Nvg::_line_join(join as i32);
5892	}
5893	pub fn path_winding(winding: NvgWinding) {
5894		Nvg::_path_winding(winding as i32);
5895	}
5896	pub fn arc(x: f32, y: f32, r: f32, a0: f32, a1: f32, dir: NvgArcDir) {
5897		Nvg::_arc(x, y, r, a0, a1, dir as i32);
5898	}
5899	pub fn text_align(h_align: NvgHAlign, v_align: NvgVAlign) {
5900		Nvg::_text_align(h_align as i32, v_align as i32);
5901	}
5902}
5903
5904// math
5905
5906extern "C" {
5907	fn math_abs(v: f64) -> f64;
5908	fn math_acos(v: f32) -> f32;
5909	fn math_asin(v: f32) -> f32;
5910	fn math_atan(v: f32) -> f32;
5911	fn math_atan2(y: f32, x: f32) -> f32;
5912	fn math_ceil(v: f32) -> f32;
5913	fn math_cos(v: f32) -> f32;
5914	fn math_deg(v: f32) -> f32;
5915	fn math_exp(v: f32) -> f32;
5916	fn math_floor(v: f32) -> f32;
5917	fn math_fmod(x: f32, y: f32) -> f32;
5918	fn math_log(v: f32) -> f32;
5919	fn math_rad(v: f32) -> f32;
5920	fn math_sin(v: f32) -> f32;
5921	fn math_sqrt(v: f32) -> f32;
5922	fn math_tan(v: f32) -> f32;
5923}
5924
5925pub struct Math {}
5926
5927impl Math {
5928	pub const PI: f32 = std::f32::consts::PI;
5929	pub fn abs(v: f64) -> f64 {
5930		unsafe { math_abs(v) }
5931	}
5932	pub fn acos(v: f32) -> f32 {
5933		unsafe { math_acos(v) }
5934	}
5935	pub fn asin(v: f32) -> f32 {
5936		unsafe { math_asin(v) }
5937	}
5938	pub fn atan(v: f32) -> f32 {
5939		unsafe { math_atan(v) }
5940	}
5941	pub fn atan2(y: f32, x: f32) -> f32 {
5942		unsafe { math_atan2(y, x) }
5943	}
5944	pub fn ceil(v: f32) -> f32 {
5945		unsafe { math_ceil(v) }
5946	}
5947	pub fn cos(v: f32) -> f32 {
5948		unsafe { math_cos(v) }
5949	}
5950	pub fn deg(v: f32) -> f32 {
5951		unsafe { math_deg(v) }
5952	}
5953	pub fn exp(v: f32) -> f32 {
5954		unsafe { math_exp(v) }
5955	}
5956	pub fn floor(v: f32) -> f32 {
5957		unsafe { math_floor(v) }
5958	}
5959	pub fn fmod(x: f32, y: f32) -> f32 {
5960		unsafe { math_fmod(x, y) }
5961	}
5962	pub fn log(v: f32) -> f32 {
5963		unsafe { math_log(v) }
5964	}
5965	pub fn rad(v: f32) -> f32 {
5966		unsafe { math_rad(v) }
5967	}
5968	pub fn sin(v: f32) -> f32 {
5969		unsafe { math_sin(v) }
5970	}
5971	pub fn sqrt(v: f32) -> f32 {
5972		unsafe { math_sqrt(v) }
5973	}
5974	pub fn tan(v: f32) -> f32 {
5975		unsafe { math_tan(v) }
5976	}
5977}
5978
5979use std::future::Future;
5980use std::pin::Pin;
5981use std::task::{Context, Poll};
5982
5983enum State {
5984	Halted,
5985	Running,
5986}
5987
5988pub struct Coroutine {
5989	state: State,
5990}
5991
5992impl Coroutine {
5993	pub fn waiter<'a>(&'a mut self) -> Waiter<'a> {
5994		Waiter { co: self }
5995	}
5996}
5997
5998pub struct Waiter<'a> {
5999	co: &'a mut Coroutine,
6000}
6001
6002impl<'a> Future for Waiter<'a> {
6003	type Output = ();
6004
6005	fn poll(mut self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
6006		match self.co.state {
6007			State::Halted => {
6008				self.co.state = State::Running;
6009				Poll::Ready(())
6010			}
6011			State::Running => {
6012				self.co.state = State::Halted;
6013				Poll::Pending
6014			}
6015		}
6016	}
6017}
6018
6019use std::task::{RawWaker, RawWakerVTable, Waker};
6020
6021fn create_waker() -> Waker {
6022	unsafe { Waker::from_raw(RAW_WAKER) }
6023}
6024
6025const RAW_WAKER: RawWaker = RawWaker::new(std::ptr::null(), &VTABLE);
6026const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
6027
6028unsafe fn clone(_: *const ()) -> RawWaker {
6029	RAW_WAKER
6030}
6031unsafe fn wake(_: *const ()) {}
6032unsafe fn wake_by_ref(_: *const ()) {}
6033unsafe fn drop(_: *const ()) {}
6034
6035struct Executor {
6036	co: Pin<Box<dyn Future<Output = ()>>>,
6037}
6038
6039impl Executor {
6040	fn new<C, F>(closure: C) -> Self
6041	where
6042		F: Future<Output = ()> + 'static,
6043		C: FnOnce(Coroutine) -> F,
6044	{
6045		let co = Coroutine { state: State::Running };
6046		Executor { co: Box::pin(closure(co)) }
6047	}
6048
6049	fn update(&mut self) -> bool {
6050		let waker = create_waker();
6051		let mut context = Context::from_waker(&waker);
6052		match self.co.as_mut().poll(&mut context) {
6053			Poll::Pending => false,
6054			Poll::Ready(()) => true,
6055		}
6056	}
6057}
6058
6059pub fn once<C, F>(closure: C) -> Box<dyn FnMut(f64) -> bool>
6060where
6061	F: Future<Output = ()> + 'static,
6062	C: FnOnce(Coroutine) -> F,
6063{
6064	let mut executor = Executor::new(closure);
6065	Box::new(move |_| executor.update())
6066}
6067
6068pub fn thread<C, F>(closure: C)
6069where
6070	F: Future<Output = ()> + 'static,
6071	C: FnOnce(Coroutine) -> F,
6072{
6073	let mut executor = Executor::new(closure);
6074	Director::schedule_posted(Box::new(move |_| executor.update()));
6075}
6076
6077#[macro_export]
6078macro_rules! sleep {
6079	($co:expr, $time:expr) => {{
6080		let total = $time;
6081		let mut time: f32 = 0.0;
6082		while time <= total {
6083			time += dora_ssr::App::get_delta_time() as f32;
6084			$co.waiter().await;
6085		}
6086	}};
6087}
6088
6089#[macro_export]
6090macro_rules! cycle {
6091	($co:expr, $time:expr, $closure:expr) => {{
6092		let total = $time;
6093		let mut time: f32 = 0.0;
6094		loop {
6095			$closure(f32::min(time / $time, 1.0));
6096			if time >= total {
6097				break;
6098			}
6099			$co.waiter().await;
6100			time += dora_ssr::App::get_delta_time() as f32;
6101		}
6102	}};
6103}
6104
6105#[macro_export]
6106macro_rules! wait {
6107	($co:expr, $condition:expr) => {
6108		while !$condition {
6109			$co.waiter().await;
6110		}
6111	};
6112}