dorothy_ssr/
dora.rs

1use std::{ffi::c_void, any::Any};
2use once_cell::sync::Lazy;
3
4mod rect;
5pub use rect::Rect;
6mod array;
7pub use array::Array;
8mod dictionary;
9pub use dictionary::Dictionary;
10mod director;
11pub use director::Director;
12mod app;
13pub use app::App;
14mod entity;
15pub use entity::Entity;
16mod group;
17pub use group::Group;
18mod observer;
19pub use observer::Observer;
20mod path;
21pub use path::Path;
22mod content;
23pub use content::Content;
24mod scheduler;
25pub use scheduler::Scheduler;
26mod camera;
27pub use camera::{ICamera, Camera};
28mod camera_2d;
29pub use camera_2d::Camera2D;
30mod camera_otho;
31pub use camera_otho::CameraOtho;
32mod pass;
33pub use pass::Pass;
34mod effect;
35pub use effect::{IEffect, Effect};
36mod sprite_effect;
37pub use sprite_effect::SpriteEffect;
38mod view;
39pub use view::View;
40mod action_def;
41pub use action_def::ActionDef;
42mod action;
43pub use action::Action;
44mod grabber;
45pub use grabber::Grabber;
46mod node;
47pub use node::{INode, Node};
48mod texture_2d;
49pub use texture_2d::Texture2D;
50mod sprite;
51pub use sprite::Sprite;
52mod grid;
53pub use grid::Grid;
54mod touch;
55pub use touch::Touch;
56mod ease;
57pub use ease::Ease;
58mod label;
59pub use label::Label;
60mod render_target;
61pub use render_target::RenderTarget;
62mod clip_node;
63pub use clip_node::ClipNode;
64mod draw_node;
65pub use draw_node::DrawNode;
66mod vertex_color;
67pub use vertex_color::VertexColor;
68mod line;
69pub use line::Line;
70mod particle;
71pub use particle::Particle;
72mod playable;
73pub use playable::{IPlayable, Playable};
74mod model;
75pub use model::Model;
76mod spine;
77pub use spine::Spine;
78mod dragon_bone;
79pub use dragon_bone::DragonBone;
80mod physics_world;
81pub use physics_world::{IPhysicsWorld, PhysicsWorld};
82mod fixture_def;
83pub use fixture_def::FixtureDef;
84mod body_def;
85pub use body_def::BodyDef;
86mod sensor;
87pub use sensor::Sensor;
88mod body;
89pub use body::{IBody, Body};
90mod joint_def;
91pub use joint_def::JointDef;
92mod joint;
93pub use joint::{IJoint, Joint};
94mod motor_joint;
95pub use motor_joint::MotorJoint;
96mod move_joint;
97pub use move_joint::MoveJoint;
98mod cache;
99pub use cache::Cache;
100mod audio;
101pub use audio::Audio;
102mod keyboard;
103pub use keyboard::Keyboard;
104mod svg;
105pub use svg::SVG;
106mod dbquery;
107pub use dbquery::DBQuery;
108mod dbparams;
109pub use dbparams::DBParams;
110mod dbrecord;
111pub use dbrecord::DBRecord;
112mod db;
113pub use db::DB;
114mod c_45;
115mod q_learner;
116pub mod ml {
117	pub use super::c_45::C45;
118	pub use super::q_learner::QLearner;
119}
120pub mod platformer;
121mod buffer;
122pub use buffer::Buffer;
123mod im_gui;
124pub use im_gui::ImGui;
125
126fn none_type(_: i64) -> Option<Box<dyn IObject>> {
127	panic!("'none_type' should not be called!");
128}
129
130static OBJECT_MAP: Lazy<Vec<fn(i64) -> Option<Box<dyn IObject>>>> = Lazy::new(|| {
131	let mut map: Vec<fn(i64) -> Option<Box<dyn IObject>>> = Vec::new();
132	let type_funcs = [
133		Array::type_info(),
134		Dictionary::type_info(),
135		Entity::type_info(),
136		Group::type_info(),
137		Observer::type_info(),
138		Scheduler::type_info(),
139		Camera::type_info(),
140		Camera2D::type_info(),
141		CameraOtho::type_info(),
142		Pass::type_info(),
143		Effect::type_info(),
144		SpriteEffect::type_info(),
145		Grabber::type_info(),
146		Node::type_info(),
147		Texture2D::type_info(),
148		Sprite::type_info(),
149		Grid::type_info(),
150		Touch::type_info(),
151		Label::type_info(),
152		RenderTarget::type_info(),
153		ClipNode::type_info(),
154		DrawNode::type_info(),
155		Line::type_info(),
156		Particle::type_info(),
157		Playable::type_info(),
158		Model::type_info(),
159		Spine::type_info(),
160		DragonBone::type_info(),
161		PhysicsWorld::type_info(),
162		FixtureDef::type_info(),
163		BodyDef::type_info(),
164		Sensor::type_info(),
165		Body::type_info(),
166		JointDef::type_info(),
167		Joint::type_info(),
168		MotorJoint::type_info(),
169		MoveJoint::type_info(),
170		SVG::type_info(),
171		ml::QLearner::type_info(),
172		platformer::Face::type_info(),
173		platformer::BulletDef::type_info(),
174		platformer::Bullet::type_info(),
175		platformer::Visual::type_info(),
176		platformer::behavior::Tree::type_info(),
177		platformer::decision::Tree::type_info(),
178		platformer::Unit::type_info(),
179		platformer::PlatformCamera::type_info(),
180		platformer::PlatformWorld::type_info(),
181		Buffer::type_info(),
182	];
183	for pair in type_funcs.iter() {
184		let t = pair.0 as usize;
185		if map.len() < t + 1 {
186			map.resize(t + 1, none_type);
187		}
188		if map[t] != none_type {
189			panic!("cpp object type id {} duplicated!", t);
190		}
191		map[t] = pair.1;
192	}
193	map
194});
195static mut FUNC_MAP: Vec<Box<dyn FnMut()>> = Vec::new();
196static mut FUNC_AVAILABLE: Vec<i32> = Vec::new();
197
198extern "C" {
199	fn object_get_id(obj: i64) -> i32;
200	fn object_get_type(obj: i64) -> i32;
201	fn object_retain(obj: i64);
202	fn object_release(obj: i64);
203
204	fn str_new(len: i32) -> i64;
205	fn str_len(str: i64) -> i32;
206	fn str_read(dest: *mut c_void, src: i64);
207	fn str_write(dest: i64, src: *const c_void);
208	fn str_release(str: i64);
209
210	fn buf_new_i32(len: i32) -> i64;
211	fn buf_new_i64(len: i32) -> i64;
212	fn buf_new_f32(len: i32) -> i64;
213	fn buf_new_f64(len: i32) -> i64;
214	fn buf_len(v: i64) -> i32;
215	fn buf_read(dest: *mut c_void, src: i64);
216	fn buf_write(dest: i64, src: *const c_void);
217	fn buf_release(v: i64);
218
219	fn value_create_i64(value: i64) -> i64;
220	fn value_create_f64(value: f64) -> i64;
221	fn value_create_str(value: i64) -> i64;
222	fn value_create_bool(value: i32) -> i64;
223	fn value_create_object(value: i64) -> i64;
224	fn value_create_vec2(value: i64) -> i64;
225	fn value_create_size(value: i64) -> i64;
226	fn value_release(value: i64);
227	fn value_into_i64(value: i64) -> i64;
228	fn value_into_f64(value: i64) -> f64;
229	fn value_into_str(value: i64) -> i64;
230	fn value_into_bool(value: i64) -> i32;
231	fn value_into_object(value: i64) -> i64;
232	fn value_into_vec2(value: i64) -> i64;
233	fn value_into_size(value: i64) -> i64;
234	fn value_is_i64(value: i64) -> i32;
235	fn value_is_f64(value: i64) -> i32;
236	fn value_is_str(value: i64) -> i32;
237	fn value_is_bool(value: i64) -> i32;
238	fn value_is_object(value: i64) -> i32;
239	fn value_is_vec2(value: i64) -> i32;
240	fn value_is_size(value: i64) -> i32;
241
242	fn call_stack_create() -> i64;
243	fn call_stack_release(info: i64);
244	fn call_stack_push_i64(info: i64, value: i64);
245	fn call_stack_push_f64(info: i64, value: f64);
246	fn call_stack_push_str(info: i64, value: i64);
247	fn call_stack_push_bool(info: i64, value: i32);
248	fn call_stack_push_object(info: i64, value: i64);
249	fn call_stack_push_vec2(info: i64, value: i64);
250	fn call_stack_push_size(info: i64, value: i64);
251	fn call_stack_pop_i64(info: i64) -> i64;
252	fn call_stack_pop_f64(info: i64) -> f64;
253	fn call_stack_pop_str(info: i64) -> i64;
254	fn call_stack_pop_bool(info: i64) -> i32;
255	fn call_stack_pop_object(info: i64) -> i64;
256	fn call_stack_pop_vec2(info: i64) -> i64;
257	fn call_stack_pop_size(info: i64) -> i64;
258	fn call_stack_pop(info: i64) -> i32;
259	fn call_stack_front_i64(info: i64) -> i32;
260	fn call_stack_front_f64(info: i64) -> i32;
261	fn call_stack_front_str(info: i64) -> i32;
262	fn call_stack_front_bool(info: i64) -> i32;
263	fn call_stack_front_object(info: i64) -> i32;
264	fn call_stack_front_vec2(info: i64) -> i32;
265	fn call_stack_front_size(info: i64) -> i32;
266
267	fn dora_print(msg: i64);
268}
269
270pub fn print(msg: &str) {
271	unsafe { dora_print(from_string(msg)); }
272}
273
274#[macro_export]
275macro_rules! p {
276	() => {
277		dorothy_ssr::print("\n")
278	};
279	($($arg:tt)*) => {{
280		dorothy_ssr::print((format!($($arg)*) + "\n").as_str());
281	}};
282}
283
284#[repr(C)]
285#[derive(Clone, Copy)]
286#[derive(PartialEq)]
287pub struct Vec2 {
288	pub x: f32,
289	pub y: f32
290}
291
292impl Vec2 {
293	pub fn from(value: i64) -> Vec2 {
294		unsafe { LightValue { value: value }.vec2 }
295	}
296	pub fn zero() -> Vec2 {
297		Vec2 { x: 0.0, y: 0.0 }
298	}
299	pub fn into_i64(&self) -> i64 {
300		unsafe { LightValue { vec2: *self }.value }
301	}
302	pub fn is_zero(&self) -> bool {
303		self.x == 0.0 && self.y == 0.0
304	}
305}
306
307#[repr(C)]
308#[derive(Clone, Copy)]
309#[derive(PartialEq)]
310pub struct Size {
311	pub width: f32,
312	pub height: f32
313}
314
315impl Size {
316	pub fn from(value: i64) -> Size {
317		unsafe { LightValue { value: value }.size }
318	}
319	pub fn zero() -> Size {
320		Size { width: 0.0, height: 0.0 }
321	}
322	pub fn into_i64(&self) -> i64 {
323		unsafe { LightValue { size: *self }.value }
324	}
325	pub fn is_zero(&self) -> bool {
326		self.width == 0.0 && self.height == 0.0
327	}
328}
329
330#[repr(C)]
331union LightValue {
332	vec2: Vec2,
333	size: Size,
334	value: i64,
335}
336
337#[repr(C)]
338#[derive(Clone, Copy)]
339pub struct Color {
340	pub r: u8,
341	pub g: u8,
342	pub b: u8,
343	pub a: u8
344}
345
346#[repr(C)]
347union ColorValue {
348	color: Color,
349	value: i32,
350}
351
352impl Color {
353	pub fn new(argb: u32) -> Color {
354		let a = argb >> 24;
355		let r = (argb & 0x00ff0000) >> 16;
356		let g = (argb & 0x0000ff00) >> 8;
357		let b = argb & 0x000000ff;
358		Color { r: r as u8, g: g as u8, b: b as u8, a: a as u8 }
359	}
360	pub fn from(agbr: i32) -> Color {
361		unsafe { ColorValue{ value: agbr }.color }
362	}
363	pub fn to_argb(&self) -> u32 {
364		(self.a as u32) << 24 | (self.r as u32) << 16 | (self.g as u32) << 8 | self.b as u32
365	}
366	pub fn to_color3(&self) -> Color3 {
367		Color3 { r: self.r, g: self.g, b: self.b }
368	}
369}
370
371#[repr(C)]
372#[derive(Clone, Copy)]
373pub struct Color3 {
374	pub r: u8,
375	pub g: u8,
376	pub b: u8
377}
378
379#[repr(C)]
380#[derive(Clone, Copy)]
381struct Color3a {
382	color3: Color3,
383	a: u8
384}
385
386#[repr(C)]
387union Color3Value {
388	color3a: Color3a,
389	value: i32,
390}
391
392impl Color3 {
393	pub fn new(rgb: u32) -> Color3 {
394		let r = (rgb & 0x00ff0000) >> 16;
395		let g = (rgb & 0x0000ff00) >> 8;
396		let b = rgb & 0x000000ff;
397		Color3 { r: r as u8, g: g as u8, b: b as u8 }
398	}
399	pub fn from(gbr: i32) -> Color3 {
400		unsafe { Color3Value { value: gbr }.color3a.color3 }
401	}
402	pub fn to_rgb(&self) -> u32 {
403		(self.r as u32) << 16 | (self.g as u32) << 8 | self.b as u32
404	}
405}
406
407fn to_string(str: i64) -> String {
408	unsafe {
409		let len = str_len(str) as usize;
410		let mut vec = Vec::with_capacity(len as usize);
411		vec.resize(len, 0);
412		let data = vec.as_mut_ptr() as *mut c_void;
413		str_read(data, str);
414		str_release(str);
415		return String::from_utf8(vec).unwrap();
416	}
417}
418
419fn from_string(s: &str) -> i64 {
420	unsafe {
421		let len = s.len() as i32;
422		let ptr = s.as_ptr();
423		let new_str = str_new(len);
424		str_write(new_str, ptr as *const c_void);
425		return new_str;
426	}
427}
428
429pub struct Vector;
430
431impl Vector {
432	pub fn to_i32(v: i64) -> Vec<i32> {
433		unsafe {
434			let len = buf_len(v) as usize;
435			let mut vec: Vec<i32> = Vec::with_capacity(len as usize);
436			vec.resize(len, Default::default());
437			let data = vec.as_mut_ptr() as *mut c_void;
438			buf_read(data, v);
439			buf_release(v);
440			return vec;
441		}
442	}
443	pub fn to_i64(v: i64) -> Vec<i64> {
444		unsafe {
445			let len = buf_len(v) as usize;
446			let mut vec: Vec<i64> = Vec::with_capacity(len as usize);
447			vec.resize(len, Default::default());
448			let data = vec.as_mut_ptr() as *mut c_void;
449			buf_read(data, v);
450			buf_release(v);
451			return vec;
452		}
453	}
454	pub fn to_f32(v: i64) -> Vec<f32> {
455		unsafe {
456			let len = buf_len(v) as usize;
457			let mut vec: Vec<f32> = Vec::with_capacity(len as usize);
458			vec.resize(len, Default::default());
459			let data = vec.as_mut_ptr() as *mut c_void;
460			buf_read(data, v);
461			buf_release(v);
462			return vec;
463		}
464	}
465	pub fn to_f64(v: i64) -> Vec<f64> {
466		unsafe {
467			let len = buf_len(v) as usize;
468			let mut vec: Vec<f64> = Vec::with_capacity(len as usize);
469			vec.resize(len, Default::default());
470			let data = vec.as_mut_ptr() as *mut c_void;
471			buf_read(data, v);
472			buf_release(v);
473			return vec;
474		}
475	}
476	pub fn to_str(v: i64) -> Vec<String> {
477		unsafe {
478			let len = buf_len(v) as usize;
479			let mut vec: Vec<i64> = Vec::with_capacity(len as usize);
480			vec.resize(len, Default::default());
481			let data = vec.as_mut_ptr() as *mut c_void;
482			buf_read(data, v);
483			let mut strs = Vec::with_capacity(vec.len());
484			for i in 0..vec.len() {
485				strs.push(to_string(vec[i]));
486			}
487			buf_release(v);
488			strs
489		}
490	}
491	pub fn from_i32(s: &Vec<i32>) -> i64 {
492		unsafe {
493			let len = s.len() as i32;
494			let ptr = s.as_ptr();
495			let new_vec = buf_new_i32(len);
496			buf_write(new_vec, ptr as *const c_void);
497			return new_vec;
498		}
499	}
500	pub fn from_i64(s: &Vec<i64>) -> i64 {
501		unsafe {
502			let len = s.len() as i32;
503			let ptr = s.as_ptr();
504			let new_vec = buf_new_i64(len);
505			buf_write(new_vec, ptr as *const c_void);
506			return new_vec;
507		}
508	}
509	pub fn from_f32(s: &Vec<f32>) -> i64 {
510		unsafe {
511			let len = s.len() as i32;
512			let ptr = s.as_ptr();
513			let new_vec = buf_new_f32(len);
514			buf_write(new_vec, ptr as *const c_void);
515			return new_vec;
516		}
517	}
518	pub fn from_f64(s: &Vec<f64>) -> i64 {
519		unsafe {
520			let len = s.len() as i32;
521			let ptr = s.as_ptr();
522			let new_vec = buf_new_f64(len);
523			buf_write(new_vec, ptr as *const c_void);
524			return new_vec;
525		}
526	}
527	pub fn from_str(s: &Vec<&str>) -> i64 {
528		unsafe {
529			let len = s.len() as i32;
530			let mut strs: Vec<i64> = Vec::with_capacity(s.len());
531			for i in 0..s.len() {
532				strs.push(from_string(s[i]));
533			}
534			let ptr = strs.as_ptr();
535			let new_vec = buf_new_i64(len);
536			buf_write(new_vec, ptr as *const c_void);
537			return new_vec;
538		}
539	}
540	pub fn from_vec2(s: &Vec<Vec2>) -> i64 {
541		unsafe {
542			let len = s.len() as i32;
543			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
544			for i in 0..s.len() {
545				vs.push(LightValue { vec2: s[i] }.value);
546			}
547			let ptr = vs.as_ptr();
548			let new_vec = buf_new_i64(len);
549			buf_write(new_vec, ptr as *const c_void);
550			return new_vec;
551		}
552	}
553	pub fn from_vertex_color(s: &Vec<VertexColor>) -> i64 {
554		unsafe {
555			let len = s.len() as i32;
556			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
557			for i in 0..s.len() {
558				vs.push(s[i].raw());
559			}
560			let ptr = vs.as_ptr();
561			let new_vec = buf_new_i64(len);
562			buf_write(new_vec, ptr as *const c_void);
563			return new_vec;
564		}
565	}
566	pub fn from_action_def(s: &Vec<ActionDef>) -> i64 {
567		unsafe {
568			let len = s.len() as i32;
569			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
570			for i in 0..s.len() {
571				vs.push(s[i].raw());
572			}
573			let ptr = vs.as_ptr();
574			let new_vec = buf_new_i64(len);
575			buf_write(new_vec, ptr as *const c_void);
576			return new_vec;
577		}
578	}
579	pub fn from_btree(s: &Vec<platformer::behavior::Tree>) -> i64 {
580		unsafe {
581			let len = s.len() as i32;
582			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
583			for i in 0..s.len() {
584				vs.push(s[i].raw());
585			}
586			let ptr = vs.as_ptr();
587			let new_vec = buf_new_i64(len);
588			buf_write(new_vec, ptr as *const c_void);
589			return new_vec;
590		}
591	}
592	pub fn from_dtree(s: &Vec<platformer::decision::Tree>) -> i64 {
593		unsafe {
594			let len = s.len() as i32;
595			let mut vs: Vec<i64> = Vec::with_capacity(s.len());
596			for i in 0..s.len() {
597				vs.push(s[i].raw());
598			}
599			let ptr = vs.as_ptr();
600			let new_vec = buf_new_i64(len);
601			buf_write(new_vec, ptr as *const c_void);
602			return new_vec;
603		}
604	}
605}
606
607fn get_object(raw: i64) -> Option<Box<dyn IObject>> {
608	unsafe { OBJECT_MAP[object_get_type(raw) as usize](raw) }
609}
610
611fn push_function(func: Box<dyn FnMut()>) -> i32 {
612	unsafe {
613		if let Some(func_id) = FUNC_AVAILABLE.pop() {
614			FUNC_MAP[func_id as usize] = func;
615			func_id
616		} else {
617			FUNC_MAP.push(func);
618			(FUNC_MAP.len() - 1) as i32
619		}
620	}
621}
622
623#[no_mangle]
624pub extern fn call_function(func_id: i32) {
625	unsafe { FUNC_MAP[func_id as usize](); }
626}
627
628fn dummy_func() {
629	panic!("the dummy function should not be called.");
630}
631
632#[no_mangle]
633pub extern fn deref_function(func_id: i32) {
634	unsafe {
635		FUNC_MAP[func_id as usize] = Box::new(dummy_func);
636		FUNC_AVAILABLE.push(func_id);
637	}
638}
639
640pub trait IObject {
641	fn raw(&self) -> i64;
642	fn obj(&self) -> &dyn IObject;
643	fn get_id(&self) -> i32 { unsafe { object_get_id(self.raw()) } }
644	fn as_any(&self) -> &dyn Any;
645}
646
647pub struct Object { raw: i64 }
648impl IObject for Object {
649	fn raw(&self) -> i64 { self.raw }
650	fn obj(&self) -> &dyn IObject { self }
651	fn as_any(&self) -> &dyn std::any::Any { self }
652}
653impl Drop for Object {
654	fn drop(&mut self) { unsafe { crate::dora::object_release(self.raw); } }
655}
656impl Clone for Object {
657	fn clone(&self) -> Object {
658		unsafe { crate::dora::object_retain(self.raw); }
659		Object { raw: self.raw }
660	}
661}
662impl Object {
663	pub fn from(raw: i64) -> Option<Object> {
664		match raw {
665			0 => None,
666			_ => Some(Object { raw: raw })
667		}
668	}
669}
670
671pub fn cast<T: Clone + 'static>(obj: &dyn IObject) -> Option<T> {
672	Some(obj.as_any().downcast_ref::<T>()?.clone())
673}
674
675pub struct CallStack { raw: i64 }
676
677pub enum DoraValue<'a> {
678	I32(i32),
679	I64(i64),
680	F32(f32),
681	F64(f64),
682	Bool(bool),
683	Str(&'a str),
684	Object(&'a dyn IObject),
685	Vec2(Vec2),
686	Size(Size),
687}
688
689pub trait IntoValue<'a> {
690	fn dora_val(self) -> DoraValue<'a>;
691	fn val(self) -> Value;
692}
693
694impl<'a> DoraValue<'a> {
695	pub fn push(self, info: &mut CallStack) {
696		match self {
697			DoraValue::I32(x) => { info.push_i32(x); },
698			DoraValue::I64(x) => { info.push_i64(x); },
699			DoraValue::F32(x) => { info.push_f32(x); },
700			DoraValue::F64(x) => { info.push_f64(x); },
701			DoraValue::Bool(x) => { info.push_bool(x); },
702			DoraValue::Str(x) => { info.push_str(x); },
703			DoraValue::Object(x) => { info.push_object(x); },
704			DoraValue::Vec2(x) => { info.push_vec2(&x); },
705			DoraValue::Size(x) => { info.push_size(&x); },
706		}
707	}
708}
709
710impl<'a> IntoValue<'a> for i32 {
711	fn dora_val(self) -> DoraValue<'a> { DoraValue::I32(self) }
712	fn val(self) -> Value {
713		unsafe { Value{ raw: value_create_i64(self as i64) } }
714	}
715}
716
717impl<'a> IntoValue<'a> for i64 {
718	fn dora_val(self) -> DoraValue<'a> { DoraValue::I64(self) }
719	fn val(self) -> Value {
720		unsafe { Value{ raw: value_create_i64(self) } }
721	}
722}
723
724impl<'a> IntoValue<'a> for f32 {
725	fn dora_val(self) -> DoraValue<'a> { DoraValue::F32(self) }
726	fn val(self) -> Value {
727		unsafe { Value{ raw: value_create_f64(self as f64) } }
728	}
729}
730
731impl<'a> IntoValue<'a> for f64 {
732	fn dora_val(self) -> DoraValue<'a> { DoraValue::F64(self) }
733	fn val(self) -> Value {
734		unsafe { Value{ raw: value_create_f64(self) } }
735	}
736}
737
738impl<'a> IntoValue<'a> for bool {
739	fn dora_val(self) -> DoraValue<'a> { DoraValue::Bool(self) }
740	fn val(self) -> Value {
741		unsafe { Value{ raw: value_create_bool(if self { 1 } else { 0 }) } }
742	}
743}
744
745impl<'a> IntoValue<'a> for &'a str {
746	fn dora_val(self) -> DoraValue<'a> { DoraValue::Str(self) }
747	fn val(self) -> Value {
748		unsafe { Value{ raw: value_create_str(from_string(self)) } }
749	}
750}
751
752impl<'a> IntoValue<'a> for &'a dyn IObject {
753	fn dora_val(self) -> DoraValue<'a> { DoraValue::Object(self) }
754	fn val(self) -> Value {
755		unsafe { Value{ raw: value_create_object(self.raw()) } }
756	}
757}
758
759impl<'a> IntoValue<'a> for Vec2 {
760	fn dora_val(self) -> DoraValue<'a> { DoraValue::Vec2(self) }
761	fn val(self) -> Value {
762		unsafe { Value{ raw: value_create_vec2(self.into_i64()) } }
763	}
764}
765
766impl<'a> IntoValue<'a> for Size {
767	fn dora_val(self) -> DoraValue<'a> { DoraValue::Size(self) }
768	fn val(self) -> Value {
769		unsafe { Value{ raw: value_create_size(self.into_i64()) } }
770	}
771}
772
773#[macro_export]
774macro_rules! args {
775	( $( $x:expr ),* ) => {
776		{
777			let mut stack = dorothy_ssr::CallStack::new();
778			$(
779				dorothy_ssr::Value::new($x).push(&mut stack);
780			)*
781			stack
782		}
783	};
784}
785
786#[macro_export]
787macro_rules! dora_object {
788	($name: ident) => {
789		paste::paste! {
790			 impl IObject for $name {
791				fn raw(&self) -> i64 { self.raw }
792				fn obj(&self) -> &dyn IObject { self }
793				fn as_any(&self) -> &dyn std::any::Any { self }
794			}
795			impl Drop for $name {
796				fn drop(&mut self) { unsafe { crate::dora::object_release(self.raw); } }
797			}
798			impl Clone for $name {
799				fn clone(&self) -> $name {
800					unsafe { crate::dora::object_retain(self.raw); }
801					$name { raw: self.raw }
802				}
803			}
804			impl $name {
805				pub fn from(raw: i64) -> Option<$name> {
806					match raw {
807						0 => None,
808						_ => Some($name { raw: raw })
809					}
810				}
811			}
812		}
813	};
814}
815
816// Value
817
818pub struct Value { raw: i64 }
819
820impl Value {
821	pub fn new<'a, A>(value: A) -> DoraValue<'a>
822		where A: IntoValue<'a> {
823		value.dora_val()
824	}
825	fn from(raw: i64) -> Option<Value> {
826		match raw {
827			0 => { None },
828			_ => { Some(Value { raw: raw }) }
829		}
830	}
831	pub fn raw(&self) -> i64 { self.raw }
832	pub fn into_i32(&self) -> Option<i32> {
833		unsafe {
834			if value_is_i64(self.raw) != 0 {
835				Some(value_into_i64(self.raw) as i32)
836			} else { None }
837		}
838	}
839	pub fn into_i64(&self) -> Option<i64> {
840		unsafe {
841			if value_is_i64(self.raw) != 0 {
842				Some(value_into_i64(self.raw))
843			} else { None }
844		}
845	}
846	pub fn into_f32(&self) -> Option<f32> {
847		unsafe {
848			if value_is_f64(self.raw) != 0 {
849				Some(value_into_f64(self.raw) as f32)
850			} else { None }
851		}
852	}
853	pub fn into_f64(&self) -> Option<f64> {
854		unsafe {
855			if value_is_f64(self.raw) != 0 {
856				Some(value_into_f64(self.raw))
857			} else { None }
858		}
859	}
860	pub fn into_bool(&self) -> Option<bool> {
861		unsafe {
862			if value_is_bool(self.raw) != 0 {
863				Some(value_into_bool(self.raw) != 0)
864			} else { None }
865		}
866	}
867	pub fn into_str(&self) -> Option<String> {
868		unsafe {
869			if value_is_str(self.raw) != 0 {
870				Some(to_string(value_into_str(self.raw)))
871			} else { None }
872		}
873	}
874	pub fn into_object(&self) -> Option<Box<dyn IObject>> {
875		unsafe {
876			if value_is_object(self.raw) != 0 {
877				get_object(value_into_object(self.raw))
878			} else { None }
879		}
880	}
881	pub fn into_vec2(&self) -> Option<Vec2> {
882		unsafe {
883			if value_is_vec2(self.raw) != 0 {
884				Some(Vec2::from(value_into_vec2(self.raw)))
885			} else { None }
886		}
887	}
888	pub fn into_size(&self) -> Option<Size> {
889		unsafe {
890			if value_is_size(self.raw) != 0 {
891				Some(Size::from(value_into_size(self.raw)))
892			} else { None }
893		}
894	}
895	pub fn cast<T: Clone + 'static>(&self) -> Option<T> {
896		cast::<T>(self.into_object()?.as_ref())
897	}
898}
899
900impl Drop for Value {
901	fn drop(&mut self) { unsafe { value_release(self.raw); } }
902}
903
904// CallStack
905
906impl CallStack {
907	fn raw(&self) -> i64 {
908		self.raw
909	}
910	pub fn new() -> CallStack {
911		CallStack { raw: unsafe { call_stack_create() } }
912	}
913	pub fn push_i32(&mut self, value: i32) {
914		unsafe { call_stack_push_i64(self.raw, value as i64); }
915	}
916	pub fn push_i64(&mut self, value: i64) {
917		unsafe { call_stack_push_i64(self.raw, value); }
918	}
919	pub fn push_f32(&mut self, value: f32) {
920		unsafe { call_stack_push_f64(self.raw, value as f64); }
921	}
922	pub fn push_f64(&mut self, value: f64) {
923		unsafe { call_stack_push_f64(self.raw, value); }
924	}
925	pub fn push_str(&mut self, value: &str) {
926		unsafe { call_stack_push_str(self.raw, from_string(value)); }
927	}
928	pub fn push_bool(&mut self, value: bool) {
929		unsafe { call_stack_push_bool(self.raw, if value { 1 } else { 0 }); }
930	}
931	pub fn push_object(&mut self, value: &dyn IObject) {
932		unsafe { call_stack_push_object(self.raw, value.raw()); }
933	}
934	pub fn push_vec2(&mut self, value: &Vec2) {
935		unsafe { call_stack_push_vec2(self.raw, value.into_i64()); }
936	}
937	pub fn push_size(&mut self, value: &Size) {
938		unsafe { call_stack_push_size(self.raw, value.into_i64()); }
939	}
940	pub fn pop_i32(&mut self) -> Option<i32> {
941		unsafe {
942			if call_stack_front_i64(self.raw) != 0 {
943				Some(call_stack_pop_i64(self.raw) as i32)
944			} else { None }
945		}
946	}
947	pub fn pop_i64(&mut self) -> Option<i64> {
948		unsafe {
949			if call_stack_front_i64(self.raw) != 0 {
950				Some(call_stack_pop_i64(self.raw))
951			} else { None }
952		}
953	}
954	pub fn pop_f32(&mut self) -> Option<f32> {
955		unsafe {
956			if call_stack_front_f64(self.raw) != 0 {
957				Some(call_stack_pop_f64(self.raw) as f32)
958			} else { None }
959		}
960	}
961	pub fn pop_f64(&mut self) -> Option<f64> {
962		unsafe {
963			if call_stack_front_f64(self.raw) != 0 {
964				Some(call_stack_pop_f64(self.raw))
965			} else { None }
966		}
967	}
968	pub fn pop_str(&mut self) -> Option<String> {
969		unsafe {
970			if call_stack_front_str(self.raw) != 0 {
971				Some(to_string(call_stack_pop_str(self.raw)))
972			} else { None }
973		}
974	}
975	pub fn pop_bool(&mut self) -> Option<bool> {
976		unsafe {
977			if call_stack_front_bool(self.raw) != 0 {
978				Some(call_stack_pop_bool(self.raw) != 0)
979			} else { None }
980		}
981	}
982	pub fn pop_object(&mut self) -> Option<Box<dyn IObject>> {
983		unsafe {
984			if call_stack_front_object(self.raw) != 0 {
985				let raw = call_stack_pop_object(self.raw);
986				get_object(raw)
987			} else { None }
988		}
989	}
990	pub fn pop_cast<T: Clone + 'static>(&mut self) -> Option<T> {
991		unsafe {
992			if call_stack_front_object(self.raw) != 0 {
993				let raw = call_stack_pop_object(self.raw);
994				cast::<T>(get_object(raw)?.as_ref())
995			} else { None }
996		}
997	}
998	pub fn pop_vec2(&mut self) -> Option<Vec2> {
999		unsafe {
1000			if call_stack_front_vec2(self.raw) != 0 {
1001				Some(Vec2::from(call_stack_pop_vec2(self.raw)))
1002			} else { None }
1003		}
1004	}
1005	pub fn pop_size(&mut self) -> Option<Size> {
1006		unsafe {
1007			if call_stack_front_size(self.raw) != 0 {
1008				Some(Size::from(call_stack_pop_size(self.raw)))
1009			} else { None }
1010		}
1011	}
1012	pub fn pop(&mut self) {
1013		if unsafe { call_stack_pop(self.raw) } == 0 {
1014			panic!("pop from empty call stack!");
1015		}
1016	}
1017}
1018
1019impl Drop for CallStack {
1020	fn drop(&mut self) { unsafe { call_stack_release(self.raw); } }
1021}
1022
1023// Array
1024
1025extern "C" {
1026	fn array_set(array: i64, index: i32, item: i64) -> i32;
1027	fn array_get(array: i64, index: i32) -> i64;
1028	fn array_first(array: i64) -> i64;
1029	fn array_last(array: i64) -> i64;
1030	fn array_random_object(array: i64) -> i64;
1031	fn array_add(array: i64, item: i64);
1032	fn array_insert(array: i64, index: i32, item: i64);
1033	fn array_contains(array: i64, item: i64) -> i32;
1034	fn array_index(array: i64, item: i64) -> i32;
1035	fn array_remove_last(array: i64) -> i64;
1036	fn array_fast_remove(array: i64, item: i64) -> i32;
1037}
1038
1039impl Array {
1040	pub fn set<'a, T>(&mut self, index: i32, v: T) where T: IntoValue<'a> {
1041		if unsafe { array_set(self.raw(), index, v.val().raw()) == 0 } {
1042			panic!("Out of bounds, expecting [0, {}), got {}", self.get_count(), index);
1043		}
1044	}
1045	pub fn get(&self, index: i32) -> Option<Value> {
1046		Value::from(unsafe { array_get(self.raw(), index) })
1047	}
1048	pub fn first(&self) -> Option<Value> {
1049		Value::from(unsafe { array_first(self.raw()) })
1050	}
1051	pub fn last(&self) -> Option<Value> {
1052		Value::from(unsafe { array_last(self.raw()) })
1053	}
1054	pub fn random_object(&self) -> Option<Value> {
1055		Value::from(unsafe { array_random_object(self.raw()) })
1056	}
1057	pub fn add<'a, T>(&mut self, v: T) where T: IntoValue<'a> {
1058		unsafe { array_add(self.raw(), v.val().raw()); }
1059	}
1060	pub fn insert<'a, T>(&mut self, index: i32, v: T) where T: IntoValue<'a> {
1061		unsafe { array_insert(self.raw(), index, v.val().raw()); }
1062	}
1063	pub fn contains<'a, T>(&self, v: T) -> bool where T: IntoValue<'a> {
1064		unsafe { array_contains(self.raw(), v.val().raw()) != 0 }
1065	}
1066	pub fn index<'a, T>(&self, v: T) -> i32 where T: IntoValue<'a> {
1067		unsafe { array_index(self.raw(), v.val().raw()) }
1068	}
1069	pub fn remove_last(&mut self) -> Option<Value> {
1070		Value::from(unsafe { array_remove_last(self.raw()) })
1071	}
1072	pub fn fast_remove<'a, T>(&mut self, v: T) -> bool where T: IntoValue<'a> {
1073		unsafe { array_fast_remove(self.raw(), v.val().raw()) != 0 }
1074	}
1075}
1076
1077// Dictionary
1078
1079extern "C" {
1080	fn dictionary_set(dict: i64, key: i64, value: i64);
1081	fn dictionary_get(dict: i64, key: i64) -> i64;
1082}
1083
1084impl Dictionary {
1085	pub fn set<'a, T>(&mut self, key: &str, v: T) where T: IntoValue<'a> {
1086		unsafe { dictionary_set(self.raw(), from_string(key), v.val().raw()); }
1087	}
1088	pub fn get(&self, key: &str) -> Option<Value> {
1089		Value::from(unsafe { dictionary_get(self.raw(), from_string(key)) })
1090	}
1091}
1092
1093// Entity
1094
1095extern "C" {
1096	fn entity_set(e: i64, k: i64, v: i64);
1097	fn entity_get(e: i64, k: i64) -> i64;
1098	fn entity_get_old(e: i64, k: i64) -> i64;
1099}
1100
1101impl Entity {
1102	pub fn set<'a, T>(&mut self, key: &str, value: T) where T: IntoValue<'a> {
1103		unsafe { entity_set(self.raw(), from_string(key), value.val().raw()); }
1104	}
1105	pub fn get(&self, key: &str) -> Option<Value> {
1106		Value::from(unsafe { entity_get(self.raw(), from_string(key)) })
1107	}
1108	pub fn get_old(&self, key: &str) -> Option<Value> {
1109		Value::from(unsafe { entity_get_old(self.raw(), from_string(key)) })
1110	}
1111}
1112
1113// EntityGroup
1114
1115extern "C" {
1116	fn group_watch(group: i64, func: i32, stack: i64);
1117}
1118
1119impl Group {
1120	pub fn watch(&mut self, mut func: Box<dyn FnMut(&mut CallStack)>) {
1121		let mut stack = CallStack::new();
1122		let stack_raw = stack.raw();
1123		let func_id = push_function(Box::new(move || { func(&mut stack); }));
1124		unsafe { group_watch(self.raw(), func_id, stack_raw); }
1125	}
1126	pub fn each(&self, func: Box<dyn FnMut(&Entity) -> bool>) -> bool {
1127		match self.find(func) {
1128			Some(_) => true,
1129			None => false
1130		}
1131	}
1132}
1133
1134// Observer
1135
1136extern "C" {
1137	fn observer_watch(observer: i64, func: i32, stack: i64);
1138}
1139
1140#[repr(i32)]
1141pub enum EntityEvent {
1142	Add = 1,
1143	Change = 2,
1144	AddOrChange = 3,
1145	Remove = 4
1146}
1147
1148impl Observer {
1149	pub fn watch(&mut self, mut func: Box<dyn FnMut(&mut CallStack)>) {
1150		let mut stack = CallStack::new();
1151		let stack_raw = stack.raw();
1152		let func_id = push_function(Box::new(move || { func(&mut stack); }));
1153		unsafe { observer_watch(self.raw(), func_id, stack_raw); }
1154	}
1155}
1156
1157// Node
1158
1159extern "C" {
1160	fn node_emit(node: i64, name: i64, stack: i64);
1161}
1162
1163impl Node {
1164	pub fn emit(&mut self, name: &str, stack: CallStack) {
1165		unsafe { node_emit(self.raw(), from_string(name), stack.raw()); }
1166	}
1167}
1168
1169// Sprite
1170#[repr(i32)]
1171pub enum TextureWrap {
1172	None = 0,
1173	Mirror = 1,
1174	Clamp = 2,
1175	Border = 3,
1176}
1177
1178#[repr(i32)]
1179pub enum TextureFilter {
1180	None = 0,
1181	Point = 1,
1182	Anisotropic = 2,
1183}
1184
1185// Ease
1186
1187#[repr(i32)]
1188pub enum EaseType {
1189	Linear = 0,
1190	InQuad = 1,
1191	OutQuad = 2,
1192	InOutQuad = 3,
1193	InCubic = 4,
1194	OutCubic = 5,
1195	InOutCubic = 6,
1196	InQuart = 7,
1197	OutQuart = 8,
1198	InOutQuart = 9,
1199	InQuint = 10,
1200	OutQuint = 11,
1201	InOutQuint = 12,
1202	InSine = 13,
1203	OutSine = 14,
1204	InOutSine = 15,
1205	InExpo = 16,
1206	OutExpo = 17,
1207	InOutExpo = 18,
1208	InCirc = 19,
1209	OutCirc = 20,
1210	InOutCirc = 21,
1211	InElastic = 22,
1212	OutElastic = 23,
1213	InOutElastic = 24,
1214	InBack = 25,
1215	OutBack = 26,
1216	InOutBack = 27,
1217	InBounce = 28,
1218	OutBounce = 29,
1219	InOutBounce = 30,
1220	OutInQuad = 31,
1221	OutInCubic = 32,
1222	OutInQuart = 33,
1223	OutInQuint = 34,
1224	OutInSine = 35,
1225	OutInExpo = 36,
1226	OutInCirc = 37,
1227	OutInElastic = 38,
1228	OutInBack = 39,
1229	OutInBounce = 40,
1230}
1231
1232#[repr(i32)]
1233pub enum Property {
1234	X = 0,
1235	Y = 1,
1236	Z = 2,
1237	Angle = 3,
1238	AngleX = 4,
1239	AngleY = 5,
1240	ScaleX = 6,
1241	ScaleY = 7,
1242	SkewX = 8,
1243	SkewY = 9,
1244	Width = 10,
1245	Height = 11,
1246	AnchorX = 12,
1247	AnchorY = 13,
1248	Opacity = 14,
1249}
1250
1251// Label
1252
1253#[repr(i32)]
1254pub enum TextAlign {
1255	Left = 0,
1256	Center = 1,
1257	Right = 2,
1258}
1259
1260// Blackboard
1261
1262extern "C" {
1263	fn blackboard_set(b: i64, k: i64, v: i64);
1264	fn blackboard_get(b: i64, k: i64) -> i64;
1265}
1266
1267impl platformer::behavior::Blackboard {
1268	pub fn set<'a, T>(&mut self, key: &str, value: T) where T: IntoValue<'a> {
1269		unsafe { blackboard_set(self.raw(), from_string(key), value.val().raw()); }
1270	}
1271	pub fn get(&self, key: &str) -> Option<Value> {
1272		Value::from(unsafe { blackboard_get(self.raw(), from_string(key)) })
1273	}
1274}
1275
1276static mut IMGUI_STACK: Lazy<CallStack> = Lazy::new(|| { CallStack::new() });
1277
1278impl ImGui {
1279	fn push_bool(v: bool) -> &'static mut CallStack {
1280		let stack = unsafe { &mut IMGUI_STACK };
1281		stack.push_bool(v);
1282		stack
1283	}
1284	fn push_i32(v: i32) -> &'static mut CallStack {
1285		let stack = unsafe { &mut IMGUI_STACK };
1286		stack.push_i32(v);
1287		stack
1288	}
1289	fn push_i32x2(v1: i32, v2: i32) -> &'static mut CallStack {
1290		let stack = unsafe { &mut IMGUI_STACK };
1291		stack.push_i32(v1);
1292		stack.push_i32(v2);
1293		stack
1294	}
1295	fn push_f32(v: f32) -> &'static mut CallStack {
1296		let stack = unsafe { &mut IMGUI_STACK };
1297		stack.push_f32(v);
1298		stack
1299	}
1300	fn push_f32x2(v1: f32, v2: f32) -> &'static mut CallStack {
1301		let stack = unsafe { &mut IMGUI_STACK };
1302		stack.push_f32(v1);
1303		stack.push_f32(v2);
1304		stack
1305	}
1306	pub fn begin_ret(name: &str, opened: bool) -> (bool, bool) {
1307		let stack = ImGui::push_bool(opened);
1308		let changed = ImGui::_begin(name, stack);
1309		(changed, stack.pop_bool().unwrap())
1310	}
1311	pub fn begin_ret_opts(name: &str, opened: bool, windows_flags: &Vec<&str>) -> (bool, bool) {
1312		let stack = ImGui::push_bool(opened);
1313		let changed = ImGui::_begin_opts(name, stack, windows_flags);
1314		(changed, stack.pop_bool().unwrap())
1315	}
1316	pub fn collapsing_header_ret(label: &str, opened: bool) -> (bool, bool) {
1317		let stack = ImGui::push_bool(opened);
1318		let changed = ImGui::_collapsing_header(label, stack);
1319		(changed, stack.pop_bool().unwrap())
1320	}
1321	pub fn collapsing_header_ret_opts(label: &str, opened: bool, tree_node_flags: &Vec<&str>) -> (bool, bool) {
1322		let stack = ImGui::push_bool(opened);
1323		let changed = ImGui::_collapsing_header_opts(label, stack, tree_node_flags);
1324		(changed, stack.pop_bool().unwrap())
1325	}
1326	pub fn selectable_ret(label: &str, selected: bool) -> (bool, bool) {
1327		let stack = ImGui::push_bool(selected);
1328		let changed = ImGui::_selectable(label, stack);
1329		(changed, stack.pop_bool().unwrap())
1330	}
1331	pub fn selectable_ret_opts(label: &str, selected: bool, size: &crate::dora::Vec2, selectable_flags: &Vec<&str>) -> (bool, bool) {
1332		let stack = ImGui::push_bool(selected);
1333		let changed = ImGui::_selectable_opts(label, stack, size, selectable_flags);
1334		(changed, stack.pop_bool().unwrap())
1335	}
1336	pub fn begin_popup_modal_ret(name: &str, opened: bool) -> (bool, bool) {
1337		let stack = ImGui::push_bool(opened);
1338		let changed = ImGui::_begin_popup_modal(name, stack);
1339		(changed, stack.pop_bool().unwrap())
1340	}
1341	pub fn begin_popup_modal_ret_opts(name: &str, opened: bool, windows_flags: &Vec<&str>) -> (bool, bool) {
1342		let stack = ImGui::push_bool(opened);
1343		let changed = ImGui::_begin_popup_modal_opts(name, stack, windows_flags);
1344		(changed, stack.pop_bool().unwrap())
1345	}
1346	pub fn combo_ret(label: &str, current_item: i32, items: &Vec<&str>) -> (bool, i32) {
1347		let stack = ImGui::push_i32(current_item);
1348		let changed = ImGui::_combo(label, stack, items);
1349		(changed, stack.pop_i32().unwrap())
1350	}
1351	pub fn combo_ret_opts(label: &str, current_item: i32, items: &Vec<&str>, height_in_items: i32) -> (bool, i32) {
1352		let stack = ImGui::push_i32(current_item);
1353		let changed = ImGui::_combo_opts(label, stack, items, height_in_items);
1354		(changed, stack.pop_i32().unwrap())
1355	}
1356	pub fn drag_float_ret(label: &str, v: f32, v_speed: f32, v_min: f32, v_max: f32) -> (bool, f32) {
1357		let stack = ImGui::push_f32(v);
1358		let changed = ImGui::_drag_float(label, stack, v_speed, v_min, v_max);
1359		(changed, stack.pop_f32().unwrap())
1360	}
1361	pub fn drag_float_ret_opts(label: &str, v: f32, v_speed: f32, v_min: f32, v_max: f32, display_format: &str, slider_flags: &Vec<&str>) -> (bool, f32) {
1362		let stack = ImGui::push_f32(v);
1363		let changed = ImGui::_drag_float_opts(label, stack, v_speed, v_min, v_max, display_format, slider_flags);
1364		(changed, stack.pop_f32().unwrap())
1365	}
1366	pub fn drag_float2_ret(label: &str, v1: f32, v2: f32, v_speed: f32, v_min: f32, v_max: f32) -> (bool, f32, f32) {
1367		let stack = ImGui::push_f32x2(v1, v2);
1368		let changed = ImGui::_drag_float2(label, stack, v_speed, v_min, v_max);
1369		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1370	}
1371	pub fn drag_float2_ret_opts(label: &str, v1: f32, v2: f32, v_speed: f32, v_min: f32, v_max: f32, display_format: &str, slider_flags: &Vec<&str>) -> (bool, f32, f32) {
1372		let stack = ImGui::push_f32x2(v1, v2);
1373		let changed = ImGui::_drag_float2_opts(label, stack, v_speed, v_min, v_max, display_format, slider_flags);
1374		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1375	}
1376	pub fn drag_int2_ret(label: &str, v1: i32, v2: i32, v_speed: f32, v_min: i32, v_max: i32) -> (bool, i32, i32) {
1377		let stack = ImGui::push_i32x2(v1, v2);
1378		let changed = ImGui::_drag_int2(label, stack, v_speed, v_min, v_max);
1379		(changed, stack.pop_i32().unwrap(), stack.pop_i32().unwrap())
1380	}
1381	pub fn drag_int2_opts(label: &str, v1: i32, v2: i32, v_speed: f32, v_min: i32, v_max: i32, display_format: &str, slider_flags: &Vec<&str>) -> (bool, i32, i32) {
1382		let stack = ImGui::push_i32x2(v1, v2);
1383		let changed = ImGui::_drag_int2_opts(label, stack, v_speed, v_min, v_max, display_format, slider_flags);
1384		(changed, stack.pop_i32().unwrap(), stack.pop_i32().unwrap())
1385	}
1386	pub fn input_float_ret(label: &str, v: f32) -> (bool, f32) {
1387		let stack = ImGui::push_f32(v);
1388		let changed = ImGui::_input_float(label, stack);
1389		(changed, stack.pop_f32().unwrap())
1390	}
1391	pub fn input_float_ret_opts(label: &str, v: f32, step: f32, step_fast: f32, display_format: &str, input_text_flags: &Vec<&str>) -> (bool, f32) {
1392		let stack = ImGui::push_f32(v);
1393		let changed = ImGui::_input_float_opts(label, stack, step, step_fast, display_format, input_text_flags);
1394		(changed, stack.pop_f32().unwrap())
1395	}
1396	pub fn input_float2_ret(label: &str, v1: f32, v2: f32) -> (bool, f32, f32) {
1397		let stack = ImGui::push_f32x2(v1, v2);
1398		let changed = ImGui::_input_float2(label, stack);
1399		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1400	}
1401	pub fn input_float2_ret_opts(label: &str, v1: f32, v2: f32, display_format: &str, input_text_flags: &Vec<&str>) -> (bool, f32, f32) {
1402		let stack = ImGui::push_f32x2(v1, v2);
1403		let changed = ImGui::_input_float2_opts(label, stack, display_format, input_text_flags);
1404		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1405	}
1406	pub fn input_int_ret(label: &str, v: i32) -> (bool, i32) {
1407		let stack = ImGui::push_i32(v);
1408		let changed = ImGui::_input_int(label, stack);
1409		(changed, stack.pop_i32().unwrap())
1410	}
1411	pub fn input_int_ret_opts(label: &str, v: i32, step: i32, step_fast: i32, input_text_flags: &Vec<&str>) -> (bool, i32) {
1412		let stack = ImGui::push_i32(v);
1413		let changed = ImGui::_input_int_opts(label, stack, step, step_fast, input_text_flags);
1414		(changed, stack.pop_i32().unwrap())
1415	}
1416	pub fn input_int2_ret(label: &str, v1: i32, v2: i32) -> (bool, i32, i32) {
1417		let stack = ImGui::push_i32x2(v1, v2);
1418		let changed = ImGui::_input_int2(label, stack);
1419		(changed, stack.pop_i32().unwrap(), stack.pop_i32().unwrap())
1420	}
1421	pub fn input_int2_ret_opts(label: &str, v1: i32, v2: i32, input_text_flags: &Vec<&str>) -> (bool, i32, i32) {
1422		let stack = ImGui::push_i32x2(v1, v2);
1423		let changed = ImGui::_input_int2_opts(label, stack, input_text_flags);
1424		(changed, stack.pop_i32().unwrap(), stack.pop_i32().unwrap())
1425	}
1426	pub fn slider_float_ret(label: &str, v: f32, v_min: f32, v_max: f32) -> (bool, f32) {
1427		let stack = ImGui::push_f32(v);
1428		let changed = ImGui::_slider_float(label, stack, v_min, v_max);
1429		(changed, stack.pop_f32().unwrap())
1430	}
1431	pub fn slider_float_ret_opts(label: &str, v: f32, v_min: f32, v_max: f32, display_format: &str, slider_flags: &Vec<&str>) -> (bool, f32) {
1432		let stack = ImGui::push_f32(v);
1433		let changed = ImGui::_slider_float_opts(label, stack, v_min, v_max, display_format, slider_flags);
1434		(changed, stack.pop_f32().unwrap())
1435	}
1436	pub fn slider_float2_ret(label: &str, v1: f32, v2: f32, v_min: f32, v_max: f32) -> (bool, f32, f32) {
1437		let stack = ImGui::push_f32x2(v1, v2);
1438		let changed = ImGui::_slider_float2(label, stack, v_min, v_max);
1439		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1440	}
1441	pub fn slider_float2_ret_opts(label: &str, v1: f32, v2: f32, v_min: f32, v_max: f32, display_format: &str, slider_flags: &Vec<&str>) -> (bool, f32, f32) {
1442		let stack = ImGui::push_f32x2(v1, v2);
1443		let changed = ImGui::_slider_float2_opts(label, stack, v_min, v_max, display_format, slider_flags);
1444		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1445	}
1446	pub fn drag_float_range2_ret(label: &str, v_current_min: f32, v_current_max: f32, v_speed: f32, v_min: f32, v_max: f32) -> (bool, f32, f32) {
1447		let stack = ImGui::push_f32x2(v_current_min, v_current_max);
1448		let changed = ImGui::_drag_float_range2(label, stack, v_speed, v_min, v_max);
1449		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1450	}
1451	pub fn drag_float_range2_ret_opts(label: &str, v_current_min: f32, v_current_max: f32, v_speed: f32, v_min: f32, v_max: f32, format: &str, format_max: &str, slider_flags: &Vec<&str>) -> (bool, f32, f32) {
1452		let stack = ImGui::push_f32x2(v_current_min, v_current_max);
1453		let changed = ImGui::_drag_float_range2_opts(label, stack, v_speed, v_min, v_max, format, format_max, slider_flags);
1454		(changed, stack.pop_f32().unwrap(), stack.pop_f32().unwrap())
1455	}
1456	pub fn drag_int_range2_ret(label: &str, v_current_min: i32, v_current_max: i32, v_speed: f32, v_min: i32, v_max: i32) -> (bool, i32, i32) {
1457		let stack = ImGui::push_i32x2(v_current_min, v_current_max);
1458		let changed = ImGui::_drag_int_range2(label, stack, v_speed, v_min, v_max);
1459		(changed, stack.pop_i32().unwrap(), stack.pop_i32().unwrap())
1460	}
1461	pub fn drag_int_range2_ret_opts(label: &str, v_current_min: i32, v_current_max: i32, v_speed: f32, v_min: i32, v_max: i32, format: &str, format_max: &str, slider_flags: &Vec<&str>) -> (bool, i32, i32) {
1462		let stack = ImGui::push_i32x2(v_current_min, v_current_max);
1463		let changed = ImGui::_drag_int_range2_opts(label, stack, v_speed, v_min, v_max, format, format_max, slider_flags);
1464		(changed, stack.pop_i32().unwrap(), stack.pop_i32().unwrap())
1465	}
1466	pub fn v_slider_float_ret(label: &str, size: &crate::dora::Vec2, v: f32, v_min: f32, v_max: f32) -> (bool, f32) {
1467		let stack = ImGui::push_f32(v);
1468		let changed = ImGui::_v_slider_float(label, size, stack, v_min, v_max);
1469		(changed, stack.pop_f32().unwrap())
1470	}
1471	pub fn v_slider_float_ret_opts(label: &str, size: &crate::dora::Vec2, v: f32, v_min: f32, v_max: f32, format: &str, slider_flags: &Vec<&str>) -> (bool, f32) {
1472		let stack = ImGui::push_f32(v);
1473		let changed = ImGui::_v_slider_float_opts(label, size, stack, v_min, v_max, format, slider_flags);
1474		(changed, stack.pop_f32().unwrap())
1475	}
1476	pub fn v_slider_int_ret(label: &str, size: &crate::dora::Vec2, v: i32, v_min: i32, v_max: i32) -> (bool, i32) {
1477		let stack = ImGui::push_i32(v);
1478		let changed = ImGui::_v_slider_int(label, size, stack, v_min, v_max);
1479		(changed, stack.pop_i32().unwrap())
1480	}
1481	pub fn v_slider_int_ret_opts(label: &str, size: &crate::dora::Vec2, v: i32, v_min: i32, v_max: i32, format: &str, slider_flags: &Vec<&str>) -> (bool, i32) {
1482		let stack = ImGui::push_i32(v);
1483		let changed = ImGui::_v_slider_int_opts(label, size, stack, v_min, v_max, format, slider_flags);
1484		(changed, stack.pop_i32().unwrap())
1485	}
1486	pub fn color_edit3(label: &str, color3: &Color3) -> (bool, Color3) {
1487		let stack = ImGui::push_i32(color3.to_rgb() as i32);
1488		let changed = ImGui::_color_edit3(label, stack);
1489		(changed, Color3::new(stack.pop_i32().unwrap() as u32))
1490	}
1491	pub fn color_edit4(label: &str, color: &Color, show_alpha: bool) -> (bool, Color) {
1492		let stack = ImGui::push_i32(color.to_argb() as i32);
1493		let changed = ImGui::_color_edit4(label, stack, show_alpha);
1494		(changed, Color::new(stack.pop_i32().unwrap() as u32))
1495	}
1496}