1use 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::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 keyboard;
121pub use keyboard::Keyboard;
122mod mouse;
123pub use mouse::Mouse;
124mod controller;
125pub use controller::Controller;
126mod svg;
127pub use svg::SVG;
128mod dbquery;
129pub use dbquery::DBQuery;
130mod dbparams;
131pub use dbparams::DBParams;
132mod dbrecord;
133pub use dbrecord::DBRecord;
134mod db;
135pub use db::DB;
136mod work_book;
137pub use work_book::WorkBook;
138mod work_sheet;
139pub use work_sheet::WorkSheet;
140mod c_45;
141mod q_learner;
142pub mod ml {
143 pub use super::c_45::C45;
144 pub use super::q_learner::QLearner;
145}
146mod http_client;
147pub use http_client::HttpClient;
148mod buffer;
149pub mod platformer;
150pub use buffer::Buffer;
151mod im_gui;
152pub use im_gui::ImGui;
153mod vgpaint;
154pub use vgpaint::VGPaint;
155mod nvg;
156pub use nvg::Nvg;
157mod vgnode;
158pub use vgnode::VGNode;
159
160type ObjectFunc = fn(i64) -> Option<Box<dyn IObject>>;
161
162thread_local! {
163 static OBJECT_MAP: LazyCell<Vec<Option<ObjectFunc>>> = LazyCell::new(|| {
164 let type_funcs = [
165 Array::type_info(),
166 Dictionary::type_info(),
167 Entity::type_info(),
168 Group::type_info(),
169 Observer::type_info(),
170 Scheduler::type_info(),
171 Camera::type_info(),
172 Camera2D::type_info(),
173 CameraOtho::type_info(),
174 Pass::type_info(),
175 Effect::type_info(),
176 SpriteEffect::type_info(),
177 Grabber::type_info(),
178 Action::type_info(),
179 Node::type_info(),
180 Texture2D::type_info(),
181 Sprite::type_info(),
182 Grid::type_info(),
183 Touch::type_info(),
184 Label::type_info(),
185 RenderTarget::type_info(),
186 ClipNode::type_info(),
187 DrawNode::type_info(),
188 Line::type_info(),
189 Particle::type_info(),
190 Playable::type_info(),
191 Model::type_info(),
192 Spine::type_info(),
193 DragonBone::type_info(),
194 AlignNode::type_info(),
195 EffekNode::type_info(),
196 TileNode::type_info(),
197 PhysicsWorld::type_info(),
198 FixtureDef::type_info(),
199 BodyDef::type_info(),
200 Sensor::type_info(),
201 Body::type_info(),
202 JointDef::type_info(),
203 Joint::type_info(),
204 MotorJoint::type_info(),
205 MoveJoint::type_info(),
206 SVG::type_info(),
207 AudioBus::type_info(),
208 AudioSource::type_info(),
209 ml::QLearner::type_info(),
210 platformer::ActionUpdate::type_info(),
211 platformer::Face::type_info(),
212 platformer::BulletDef::type_info(),
213 platformer::Bullet::type_info(),
214 platformer::Visual::type_info(),
215 platformer::behavior::Tree::type_info(),
216 platformer::decision::Tree::type_info(),
217 platformer::Unit::type_info(),
218 platformer::PlatformCamera::type_info(),
219 platformer::PlatformWorld::type_info(),
220 Buffer::type_info(),
221 VGNode::type_info(),
222 ];
223 let mut map: Vec<Option<ObjectFunc>> = Vec::new();
224 for pair in type_funcs.iter() {
225 let t = pair.0 as usize;
226 if map.len() < t + 1 {
227 map.resize(t + 1, None);
228 }
229 if map[t].is_some() {
230 panic!("cpp object type id {} duplicated!", t);
231 }
232 map[t] = Some(pair.1);
233 }
234 map
235 });
236 static FUNC_MAP: RefCell<Vec<Box<dyn FnMut()>>> = RefCell::new(Vec::new());
237 static FUNC_AVAILABLE: RefCell<Vec<i32>> = RefCell::new(Vec::new());
238}
239
240extern "C" {
241 fn object_get_id(obj: i64) -> i32;
242 fn object_get_type(obj: i64) -> i32;
243 fn object_retain(obj: i64);
244 fn object_release(obj: i64);
245
246 fn object_to_node(obj: i64) -> i64;
247 fn object_to_camera(obj: i64) -> i64;
248 fn object_to_playable(obj: i64) -> i64;
249 fn object_to_physics_world(obj: i64) -> i64;
250 fn object_to_body(obj: i64) -> i64;
251 fn object_to_joint(obj: i64) -> i64;
252
253 fn str_new(len: i32) -> i64;
254 fn str_len(str: i64) -> i32;
255 fn str_read(dest: *mut c_void, src: i64);
256 fn str_write(dest: i64, src: *const c_void);
257 fn str_release(str: i64);
258
259 fn buf_new_i32(len: i32) -> i64;
260 fn buf_new_i64(len: i32) -> i64;
261 fn buf_new_f32(len: i32) -> i64;
262 fn buf_new_f64(len: i32) -> i64;
263 fn buf_len(v: i64) -> i32;
264 fn buf_read(dest: *mut c_void, src: i64);
265 fn buf_write(dest: i64, src: *const c_void);
266 fn buf_release(v: i64);
267
268 fn value_create_i64(value: i64) -> i64;
269 fn value_create_f64(value: f64) -> i64;
270 fn value_create_str(value: i64) -> i64;
271 fn value_create_bool(value: i32) -> i64;
272 fn value_create_object(value: i64) -> i64;
273 fn value_create_vec2(value: i64) -> i64;
274 fn value_create_size(value: i64) -> i64;
275 fn value_release(value: i64);
276 fn value_into_i64(value: i64) -> i64;
277 fn value_into_f64(value: i64) -> f64;
278 fn value_into_str(value: i64) -> i64;
279 fn value_into_bool(value: i64) -> i32;
280 fn value_into_object(value: i64) -> i64;
281 fn value_into_vec2(value: i64) -> i64;
282 fn value_into_size(value: i64) -> i64;
283 fn value_is_i64(value: i64) -> i32;
284 fn value_is_f64(value: i64) -> i32;
285 fn value_is_str(value: i64) -> i32;
286 fn value_is_bool(value: i64) -> i32;
287 fn value_is_object(value: i64) -> i32;
288 fn value_is_vec2(value: i64) -> i32;
289 fn value_is_size(value: i64) -> i32;
290
291 fn call_stack_create() -> i64;
292 fn call_stack_release(info: i64);
293 fn call_stack_push_i64(info: i64, value: i64);
294 fn call_stack_push_f64(info: i64, value: f64);
295 fn call_stack_push_str(info: i64, value: i64);
296 fn call_stack_push_bool(info: i64, value: i32);
297 fn call_stack_push_object(info: i64, value: i64);
298 fn call_stack_push_vec2(info: i64, value: i64);
299 fn call_stack_push_size(info: i64, value: i64);
300 fn call_stack_pop_i64(info: i64) -> i64;
301 fn call_stack_pop_f64(info: i64) -> f64;
302 fn call_stack_pop_str(info: i64) -> i64;
303 fn call_stack_pop_bool(info: i64) -> i32;
304 fn call_stack_pop_object(info: i64) -> i64;
305 fn call_stack_pop_vec2(info: i64) -> i64;
306 fn call_stack_pop_size(info: i64) -> i64;
307 fn call_stack_pop(info: i64) -> i32;
308 fn call_stack_front_i64(info: i64) -> i32;
309 fn call_stack_front_f64(info: i64) -> i32;
310 fn call_stack_front_str(info: i64) -> i32;
311 fn call_stack_front_bool(info: i64) -> i32;
312 fn call_stack_front_object(info: i64) -> i32;
313 fn call_stack_front_vec2(info: i64) -> i32;
314 fn call_stack_front_size(info: i64) -> i32;
315
316 fn dora_print(msg: i64);
317 fn dora_print_warning(msg: i64);
318 fn dora_print_error(msg: i64);
319
320 fn vec2_add(a: i64, b: i64) -> i64;
321 fn vec2_sub(a: i64, b: i64) -> i64;
322 fn vec2_mul(a: i64, b: i64) -> i64;
323 fn vec2_mul_float(a: i64, b: f32) -> i64;
324 fn vec2_div(a: i64, b: f32) -> i64;
325 fn vec2_distance(a: i64, b: i64) -> f32;
326 fn vec2_distance_squared(a: i64, b: i64) -> f32;
327 fn vec2_length(a: i64) -> f32;
328 fn vec2_angle(a: i64) -> f32;
329 fn vec2_normalize(a: i64) -> i64;
330 fn vec2_perp(a: i64) -> i64;
331 fn vec2_dot(a: i64, b: i64) -> f32;
332 fn vec2_clamp(a: i64, from: i64, to: i64) -> i64;
333
334 fn dora_emit(name: i64, stack: i64);
335}
336
337pub fn print(msg: &str) {
338 unsafe {
339 dora_print(from_string(msg));
340 }
341}
342
343pub fn print_warning(msg: &str) {
344 unsafe {
345 dora_print_warning(from_string(msg));
346 }
347}
348
349pub fn print_error(msg: &str) {
350 unsafe {
351 dora_print_error(from_string(msg));
352 }
353}
354
355pub fn emit(name: &str, stack: CallStack) {
377 unsafe {
378 dora_emit(from_string(name), stack.raw());
379 }
380}
381
382#[macro_export]
383macro_rules! p {
384 () => {
385 dora_ssr::print("")
386 };
387 ($($arg:tt)*) => {{
388 dora_ssr::print((format!($($arg)*)).as_str());
389 }};
390}
391
392#[repr(C)]
394#[derive(Clone, Copy, PartialEq)]
395pub struct Vec2 {
396 pub x: f32,
397 pub y: f32,
398}
399
400impl Vec2 {
401 pub(crate) fn from(value: i64) -> Vec2 {
402 unsafe { LightValue { value: value }.vec2 }
403 }
404 pub(crate) fn into_i64(&self) -> i64 {
405 unsafe { LightValue { vec2: *self }.value }
406 }
407 pub fn new(x: f32, y: f32) -> Vec2 {
408 Vec2 { x: x, y: y }
409 }
410 pub fn zero() -> Vec2 {
411 Vec2 { x: 0.0, y: 0.0 }
412 }
413 pub fn is_zero(&self) -> bool {
414 self.x == 0.0 && self.y == 0.0
415 }
416
417 pub fn distance(&self, other: &Vec2) -> f32 {
418 unsafe { vec2_distance(self.into_i64(), other.into_i64()) }
419 }
420 pub fn distance_squared(&self, other: &Vec2) -> f32 {
421 unsafe { vec2_distance_squared(self.into_i64(), other.into_i64()) }
422 }
423 pub fn length(&self) -> f32 {
424 unsafe { vec2_length(self.into_i64()) }
425 }
426 pub fn angle(&self) -> f32 {
427 unsafe { vec2_angle(self.into_i64()) }
428 }
429 pub fn normalize(&self) -> Vec2 {
430 Vec2::from(unsafe { vec2_normalize(self.into_i64()) })
431 }
432 pub fn perp(&self) -> Vec2 {
433 Vec2::from(unsafe { vec2_perp(self.into_i64()) })
434 }
435 pub fn dot(&self, other: &Vec2) -> f32 {
436 unsafe { vec2_dot(self.into_i64(), other.into_i64()) }
437 }
438 pub fn clamp(&self, from: &Vec2, to: &Vec2) -> Vec2 {
439 Vec2::from(unsafe { vec2_clamp(self.into_i64(), from.into_i64(), to.into_i64()) })
440 }
441}
442
443impl std::ops::Add for Vec2 {
444 type Output = Vec2;
445 fn add(self, other: Vec2) -> Vec2 {
446 Vec2::from(unsafe { vec2_add(self.into_i64(), other.into_i64()) })
447 }
448}
449
450impl std::ops::Sub for Vec2 {
451 type Output = Vec2;
452 fn sub(self, other: Vec2) -> Vec2 {
453 Vec2::from(unsafe { vec2_sub(self.into_i64(), other.into_i64()) })
454 }
455}
456
457impl std::ops::Mul for Vec2 {
458 type Output = Vec2;
459 fn mul(self, other: Vec2) -> Vec2 {
460 Vec2::from(unsafe { vec2_mul(self.into_i64(), other.into_i64()) })
461 }
462}
463
464impl std::ops::Mul<f32> for Vec2 {
465 type Output = Vec2;
466 fn mul(self, other: f32) -> Vec2 {
467 Vec2::from(unsafe { vec2_mul_float(self.into_i64(), other) })
468 }
469}
470
471impl std::ops::Div<f32> for Vec2 {
472 type Output = Vec2;
473 fn div(self, other: f32) -> Vec2 {
474 Vec2::from(unsafe { vec2_div(self.into_i64(), other) })
475 }
476}
477
478#[repr(C)]
480#[derive(Clone, Copy, PartialEq)]
481pub struct Size {
482 pub width: f32,
483 pub height: f32,
484}
485
486impl Size {
487 pub fn new(width: f32, height: f32) -> Size {
488 Size { width: width, height: height }
489 }
490 pub fn zero() -> Size {
491 Size { width: 0.0, height: 0.0 }
492 }
493 pub fn is_zero(&self) -> bool {
494 self.width == 0.0 && self.height == 0.0
495 }
496 pub(crate) fn from(value: i64) -> Size {
497 unsafe { LightValue { value: value }.size }
498 }
499 pub(crate) fn into_i64(&self) -> i64 {
500 unsafe { LightValue { size: *self }.value }
501 }
502}
503
504#[repr(C)]
505union LightValue {
506 vec2: Vec2,
507 size: Size,
508 value: i64,
509}
510
511#[repr(C)]
513#[derive(Clone, Copy)]
514pub struct Color {
515 pub b: u8,
516 pub g: u8,
517 pub r: u8,
518 pub a: u8,
519}
520
521#[repr(C)]
522union ColorValue {
523 color: Color,
524 value: i32,
525}
526
527impl Color {
528 pub const WHITE: Color = Color { r: 255, g: 255, b: 255, a: 255 };
529 pub const BLACK: Color = Color { r: 0, g: 0, b: 0, a: 255 };
530 pub const TRANSPARENT: Color = Color { r: 0, g: 0, b: 0, a: 0 };
531 pub fn new(argb: u32) -> Color {
532 let a = argb >> 24;
533 let r = (argb & 0x00ff0000) >> 16;
534 let g = (argb & 0x0000ff00) >> 8;
535 let b = argb & 0x000000ff;
536 Color { r: r as u8, g: g as u8, b: b as u8, a: a as u8 }
537 }
538 pub fn from(argb: i32) -> Color {
539 unsafe { ColorValue { value: argb }.color }
540 }
541 pub fn to_argb(&self) -> u32 {
542 (self.a as u32) << 24 | (self.r as u32) << 16 | (self.g as u32) << 8 | self.b as u32
543 }
544 pub fn to_color3(&self) -> Color3 {
545 Color3 { r: self.r, g: self.g, b: self.b }
546 }
547}
548
549#[repr(C)]
551#[derive(Clone, Copy)]
552pub struct Color3 {
553 pub b: u8,
554 pub g: u8,
555 pub r: u8,
556}
557
558#[repr(C)]
559#[derive(Clone, Copy)]
560struct Color3a {
561 color3: Color3,
562 a: u8,
563}
564
565#[repr(C)]
566union Color3Value {
567 color3a: Color3a,
568 value: i32,
569}
570
571impl Color3 {
572 pub const WHITE: Color3 = Color3 { r: 255, g: 255, b: 255 };
573 pub const BLACK: Color3 = Color3 { r: 0, g: 0, b: 0 };
574 pub fn new(rgb: u32) -> Color3 {
575 let r = (rgb & 0x00ff0000) >> 16;
576 let g = (rgb & 0x0000ff00) >> 8;
577 let b = rgb & 0x000000ff;
578 Color3 { r: r as u8, g: g as u8, b: b as u8 }
579 }
580 pub fn from(rgb: i32) -> Color3 {
581 unsafe { Color3Value { value: rgb }.color3a.color3 }
582 }
583 pub fn to_rgb(&self) -> u32 {
584 (self.r as u32) << 16 | (self.g as u32) << 8 | self.b as u32
585 }
586}
587
588fn to_string(str: i64) -> String {
589 unsafe {
590 let len = str_len(str) as usize;
591 let mut vec = Vec::with_capacity(len as usize);
592 vec.resize(len, 0);
593 let data = vec.as_mut_ptr() as *mut c_void;
594 str_read(data, str);
595 str_release(str);
596 return String::from_utf8(vec).unwrap();
597 }
598}
599
600fn from_string(s: &str) -> i64 {
601 unsafe {
602 let len = s.len() as i32;
603 let ptr = s.as_ptr();
604 let new_str = str_new(len);
605 str_write(new_str, ptr as *const c_void);
606 return new_str;
607 }
608}
609
610pub(crate) trait IBuf {
611 fn to_buf(&self) -> i64;
612}
613
614impl IBuf for Vec<i32> {
615 fn to_buf(&self) -> i64 {
616 unsafe {
617 let len = self.len() as i32;
618 let ptr = self.as_ptr();
619 let new_vec = buf_new_i32(len);
620 buf_write(new_vec, ptr as *const c_void);
621 return new_vec;
622 }
623 }
624}
625
626impl IBuf for Vec<i64> {
627 fn to_buf(&self) -> i64 {
628 unsafe {
629 let len = self.len() as i32;
630 let ptr = self.as_ptr();
631 let new_vec = buf_new_i64(len);
632 buf_write(new_vec, ptr as *const c_void);
633 return new_vec;
634 }
635 }
636}
637
638impl IBuf for Vec<f32> {
639 fn to_buf(&self) -> i64 {
640 unsafe {
641 let len = self.len() as i32;
642 let ptr = self.as_ptr();
643 let new_vec = buf_new_f32(len);
644 buf_write(new_vec, ptr as *const c_void);
645 return new_vec;
646 }
647 }
648}
649
650impl IBuf for Vec<f64> {
651 fn to_buf(&self) -> i64 {
652 unsafe {
653 let len = self.len() as i32;
654 let ptr = self.as_ptr();
655 let new_vec = buf_new_f64(len);
656 buf_write(new_vec, ptr as *const c_void);
657 return new_vec;
658 }
659 }
660}
661
662pub(crate) struct Vector;
663
664impl Vector {
665 pub fn to_num<T>(v: i64) -> Vec<T>
666 where
667 T: Clone + Default,
668 {
669 unsafe {
670 let len = buf_len(v) as usize;
671 let mut vec: Vec<T> = Vec::with_capacity(len as usize);
672 vec.resize(len, Default::default());
673 let data = vec.as_mut_ptr() as *mut c_void;
674 buf_read(data, v);
675 buf_release(v);
676 return vec;
677 }
678 }
679 pub fn to_str(v: i64) -> Vec<String> {
680 unsafe {
681 let len = buf_len(v) as usize;
682 let mut vec: Vec<i64> = Vec::with_capacity(len as usize);
683 vec.resize(len, Default::default());
684 let data = vec.as_mut_ptr() as *mut c_void;
685 buf_read(data, v);
686 let mut strs = Vec::with_capacity(vec.len());
687 for i in 0..vec.len() {
688 strs.push(to_string(vec[i]));
689 }
690 buf_release(v);
691 strs
692 }
693 }
694 pub fn from_num<T: IBuf>(s: &T) -> i64 {
695 return s.to_buf();
696 }
697 pub fn from_str(s: &Vec<&str>) -> i64 {
698 unsafe {
699 let len = s.len() as i32;
700 let mut strs: Vec<i64> = Vec::with_capacity(s.len());
701 for i in 0..s.len() {
702 strs.push(from_string(s[i]));
703 }
704 let ptr = strs.as_ptr();
705 let new_vec = buf_new_i64(len);
706 buf_write(new_vec, ptr as *const c_void);
707 return new_vec;
708 }
709 }
710 pub fn from_vec2(s: &Vec<Vec2>) -> i64 {
711 unsafe {
712 let len = s.len() as i32;
713 let mut vs: Vec<i64> = Vec::with_capacity(s.len());
714 for i in 0..s.len() {
715 vs.push(LightValue { vec2: s[i] }.value);
716 }
717 let ptr = vs.as_ptr();
718 let new_vec = buf_new_i64(len);
719 buf_write(new_vec, ptr as *const c_void);
720 return new_vec;
721 }
722 }
723 pub fn from_vertex_color(s: &Vec<VertexColor>) -> i64 {
724 unsafe {
725 let len = s.len() as i32;
726 let mut vs: Vec<i64> = Vec::with_capacity(s.len());
727 for i in 0..s.len() {
728 vs.push(s[i].raw());
729 }
730 let ptr = vs.as_ptr();
731 let new_vec = buf_new_i64(len);
732 buf_write(new_vec, ptr as *const c_void);
733 return new_vec;
734 }
735 }
736 pub fn from_action_def(s: &Vec<ActionDef>) -> i64 {
737 unsafe {
738 let len = s.len() as i32;
739 let mut vs: Vec<i64> = Vec::with_capacity(s.len());
740 for i in 0..s.len() {
741 vs.push(s[i].raw());
742 }
743 let ptr = vs.as_ptr();
744 let new_vec = buf_new_i64(len);
745 buf_write(new_vec, ptr as *const c_void);
746 return new_vec;
747 }
748 }
749 pub fn from_btree(s: &Vec<platformer::behavior::Tree>) -> i64 {
750 unsafe {
751 let len = s.len() as i32;
752 let mut vs: Vec<i64> = Vec::with_capacity(s.len());
753 for i in 0..s.len() {
754 vs.push(s[i].raw());
755 }
756 let ptr = vs.as_ptr();
757 let new_vec = buf_new_i64(len);
758 buf_write(new_vec, ptr as *const c_void);
759 return new_vec;
760 }
761 }
762 pub fn from_dtree(s: &Vec<platformer::decision::Tree>) -> i64 {
763 unsafe {
764 let len = s.len() as i32;
765 let mut vs: Vec<i64> = Vec::with_capacity(s.len());
766 for i in 0..s.len() {
767 vs.push(s[i].raw());
768 }
769 let ptr = vs.as_ptr();
770 let new_vec = buf_new_i64(len);
771 buf_write(new_vec, ptr as *const c_void);
772 return new_vec;
773 }
774 }
775}
776
777fn into_object(raw: i64) -> Option<Box<dyn IObject>> {
778 let mut converted: Option<Box<dyn IObject>> = None;
779 OBJECT_MAP.with(|map| converted = map[unsafe { object_get_type(raw) } as usize].unwrap()(raw));
780 converted
781}
782
783fn new_object(raw: i64) -> Option<Box<dyn IObject>> {
784 unsafe {
785 object_retain(raw);
786 }
787 let mut converted: Option<Box<dyn IObject>> = None;
788 OBJECT_MAP.with(|map| converted = map[unsafe { object_get_type(raw) } as usize].unwrap()(raw));
789 converted
790}
791
792fn push_function(func: Box<dyn FnMut()>) -> i32 {
793 #[cfg(target_arch = "wasm32")]
794 let flag = 0x01000000;
795 #[cfg(not(target_arch = "wasm32"))]
796 let flag = 0x00000000;
797 let mut ret_func_id = -1;
798 FUNC_MAP.with_borrow_mut(|map| {
799 if map.len() >= 0xffffff {
800 panic!("too many functions!");
801 }
802 FUNC_AVAILABLE.with_borrow_mut(|available| {
803 if let Some(func_id) = available.pop() {
804 map[func_id as usize] = func;
805 ret_func_id = func_id | flag;
806 } else {
807 map.push(func);
808 ret_func_id = (map.len() - 1) as i32 | flag
809 }
810 })
811 });
812 ret_func_id
813}
814
815#[no_mangle]
816pub extern "C" fn dora_wasm_version() -> i32 {
817 const MAJOR: &str = env!("CARGO_PKG_VERSION_MAJOR");
818 const MINOR: &str = env!("CARGO_PKG_VERSION_MINOR");
819 const PATCH: &str = env!("CARGO_PKG_VERSION_PATCH");
820 (MAJOR.parse::<i32>().unwrap() << 16)
821 | (MINOR.parse::<i32>().unwrap() << 8)
822 | PATCH.parse::<i32>().unwrap()
823}
824
825#[no_mangle]
826pub extern "C" fn call_function(func_id: i32) {
827 let real_id = func_id & 0x00ffffff;
828 let mut func: *mut Box<dyn FnMut()> = std::ptr::null_mut();
829 FUNC_MAP.with_borrow_mut(|map| {
830 func = &mut map[real_id as usize];
831 });
832 unsafe {
833 (*func)();
834 }
835}
836
837fn dummy_func() {
838 panic!("the dummy function should not be called.");
839}
840
841#[no_mangle]
842pub extern "C" fn deref_function(func_id: i32) {
843 let real_id = func_id & 0x00ffffff;
844 FUNC_MAP.with_borrow_mut(|map| {
845 map[real_id as usize] = Box::new(dummy_func);
846 FUNC_AVAILABLE.with_borrow_mut(|available| {
847 available.push(real_id);
848 });
849 });
850}
851
852pub trait IObject {
853 fn raw(&self) -> i64;
854 fn obj(&self) -> &dyn IObject;
855 fn get_id(&self) -> i32 {
856 unsafe { object_get_id(self.raw()) }
857 }
858 fn as_any(&self) -> &dyn Any;
859}
860
861pub struct Object {
862 raw: i64,
863}
864impl IObject for Object {
865 fn raw(&self) -> i64 {
866 self.raw
867 }
868 fn obj(&self) -> &dyn IObject {
869 self
870 }
871 fn as_any(&self) -> &dyn std::any::Any {
872 self
873 }
874}
875impl Drop for Object {
876 fn drop(&mut self) {
877 unsafe {
878 crate::dora::object_release(self.raw);
879 }
880 }
881}
882impl Clone for Object {
883 fn clone(&self) -> Object {
884 unsafe {
885 crate::dora::object_retain(self.raw);
886 }
887 Object { raw: self.raw }
888 }
889}
890impl Object {
891 pub(crate) fn from(raw: i64) -> Option<Object> {
892 match raw {
893 0 => None,
894 _ => Some(Object { raw: raw }),
895 }
896 }
897}
898
899pub fn cast<T: Clone + 'static>(obj: &dyn IObject) -> Option<T> {
900 Some(new_object(obj.raw())?.as_any().downcast_ref::<T>()?.clone())
901}
902
903pub struct CallStack {
906 raw: i64,
907}
908
909pub enum DoraValue<'a> {
910 I32(i32),
911 I64(i64),
912 F32(f32),
913 F64(f64),
914 Bool(bool),
915 Str(&'a str),
916 Object(&'a dyn IObject),
917 Vec2(Vec2),
918 Size(Size),
919}
920
921pub trait IntoValue<'a> {
922 fn dora_val(self) -> DoraValue<'a>;
923 fn val(self) -> Value;
924}
925
926impl<'a> DoraValue<'a> {
927 pub fn push(self, info: &mut CallStack) {
928 match self {
929 DoraValue::I32(x) => info.push_i32(x),
930 DoraValue::I64(x) => info.push_i64(x),
931 DoraValue::F32(x) => info.push_f32(x),
932 DoraValue::F64(x) => info.push_f64(x),
933 DoraValue::Bool(x) => info.push_bool(x),
934 DoraValue::Str(x) => info.push_str(x),
935 DoraValue::Object(x) => info.push_object(x),
936 DoraValue::Vec2(x) => info.push_vec2(&x),
937 DoraValue::Size(x) => info.push_size(&x),
938 }
939 }
940}
941
942impl<'a> IntoValue<'a> for i32 {
943 fn dora_val(self) -> DoraValue<'a> {
944 DoraValue::I32(self)
945 }
946 fn val(self) -> Value {
947 unsafe { Value { raw: value_create_i64(self as i64) } }
948 }
949}
950
951impl<'a> IntoValue<'a> for i64 {
952 fn dora_val(self) -> DoraValue<'a> {
953 DoraValue::I64(self)
954 }
955 fn val(self) -> Value {
956 unsafe { Value { raw: value_create_i64(self) } }
957 }
958}
959
960impl<'a> IntoValue<'a> for f32 {
961 fn dora_val(self) -> DoraValue<'a> {
962 DoraValue::F32(self)
963 }
964 fn val(self) -> Value {
965 unsafe { Value { raw: value_create_f64(self as f64) } }
966 }
967}
968
969impl<'a> IntoValue<'a> for f64 {
970 fn dora_val(self) -> DoraValue<'a> {
971 DoraValue::F64(self)
972 }
973 fn val(self) -> Value {
974 unsafe { Value { raw: value_create_f64(self) } }
975 }
976}
977
978impl<'a> IntoValue<'a> for bool {
979 fn dora_val(self) -> DoraValue<'a> {
980 DoraValue::Bool(self)
981 }
982 fn val(self) -> Value {
983 unsafe { Value { raw: value_create_bool(if self { 1 } else { 0 }) } }
984 }
985}
986
987impl<'a> IntoValue<'a> for &'a str {
988 fn dora_val(self) -> DoraValue<'a> {
989 DoraValue::Str(self)
990 }
991 fn val(self) -> Value {
992 unsafe { Value { raw: value_create_str(from_string(self)) } }
993 }
994}
995
996impl<'a> IntoValue<'a> for &'a dyn IObject {
997 fn dora_val(self) -> DoraValue<'a> {
998 DoraValue::Object(self)
999 }
1000 fn val(self) -> Value {
1001 unsafe { Value { raw: value_create_object(self.raw()) } }
1002 }
1003}
1004
1005impl<'a> IntoValue<'a> for Vec2 {
1006 fn dora_val(self) -> DoraValue<'a> {
1007 DoraValue::Vec2(self)
1008 }
1009 fn val(self) -> Value {
1010 unsafe { Value { raw: value_create_vec2(self.into_i64()) } }
1011 }
1012}
1013
1014impl<'a> IntoValue<'a> for Size {
1015 fn dora_val(self) -> DoraValue<'a> {
1016 DoraValue::Size(self)
1017 }
1018 fn val(self) -> Value {
1019 unsafe { Value { raw: value_create_size(self.into_i64()) } }
1020 }
1021}
1022
1023#[macro_export]
1024macro_rules! args {
1025 ( $( $x:expr ),* ) => {
1026 {
1027 let mut stack = dora_ssr::CallStack::new();
1028 $(
1029 dora_ssr::Value::new($x).push(&mut stack);
1030 )*
1031 stack
1032 }
1033 };
1034}
1035
1036#[macro_export]
1037macro_rules! dora_object {
1038 ($name: ident) => {
1039 paste::paste! {
1040 impl IObject for $name {
1041 fn raw(&self) -> i64 { self.raw }
1042 fn obj(&self) -> &dyn IObject { self }
1043 fn as_any(&self) -> &dyn std::any::Any { self }
1044 }
1045 impl Drop for $name {
1046 fn drop(&mut self) { unsafe { crate::dora::object_release(self.raw); } }
1047 }
1048 impl Clone for $name {
1049 fn clone(&self) -> $name {
1050 unsafe { crate::dora::object_retain(self.raw); }
1051 $name { raw: self.raw }
1052 }
1053 }
1054 impl $name {
1055 #[allow(dead_code)]
1056 pub(crate) fn from(raw: i64) -> Option<$name> {
1057 match raw {
1058 0 => None,
1059 _ => Some($name { raw: raw })
1060 }
1061 }
1062 }
1063 }
1064 };
1065}
1066
1067pub struct Value {
1070 raw: i64,
1071}
1072
1073impl Value {
1074 pub fn new<'a, A>(value: A) -> DoraValue<'a>
1075 where
1076 A: IntoValue<'a>,
1077 {
1078 value.dora_val()
1079 }
1080 fn from(raw: i64) -> Option<Value> {
1081 match raw {
1082 0 => None,
1083 _ => Some(Value { raw: raw }),
1084 }
1085 }
1086 pub fn raw(&self) -> i64 {
1087 self.raw
1088 }
1089 pub fn into_i32(&self) -> Option<i32> {
1090 unsafe {
1091 if value_is_i64(self.raw) != 0 {
1092 Some(value_into_i64(self.raw) as i32)
1093 } else {
1094 None
1095 }
1096 }
1097 }
1098 pub fn into_i64(&self) -> Option<i64> {
1099 unsafe {
1100 if value_is_i64(self.raw) != 0 {
1101 Some(value_into_i64(self.raw))
1102 } else {
1103 None
1104 }
1105 }
1106 }
1107 pub fn into_f32(&self) -> Option<f32> {
1108 unsafe {
1109 if value_is_f64(self.raw) != 0 {
1110 Some(value_into_f64(self.raw) as f32)
1111 } else {
1112 None
1113 }
1114 }
1115 }
1116 pub fn into_f64(&self) -> Option<f64> {
1117 unsafe {
1118 if value_is_f64(self.raw) != 0 {
1119 Some(value_into_f64(self.raw))
1120 } else {
1121 None
1122 }
1123 }
1124 }
1125 pub fn into_bool(&self) -> Option<bool> {
1126 unsafe {
1127 if value_is_bool(self.raw) != 0 {
1128 Some(value_into_bool(self.raw) != 0)
1129 } else {
1130 None
1131 }
1132 }
1133 }
1134 pub fn into_str(&self) -> Option<String> {
1135 unsafe {
1136 if value_is_str(self.raw) != 0 {
1137 Some(to_string(value_into_str(self.raw)))
1138 } else {
1139 None
1140 }
1141 }
1142 }
1143 pub fn into_object(&self) -> Option<Box<dyn IObject>> {
1144 unsafe {
1145 if value_is_object(self.raw) != 0 {
1146 into_object(value_into_object(self.raw))
1147 } else {
1148 None
1149 }
1150 }
1151 }
1152 pub fn into_node(&self) -> Option<Node> {
1153 Node::cast(self.into_object()?.as_ref())
1154 }
1155 pub fn into_camera(&self) -> Option<Camera> {
1156 Camera::cast(self.into_object()?.as_ref())
1157 }
1158 pub fn into_playable(&self) -> Option<Playable> {
1159 Playable::cast(self.into_object()?.as_ref())
1160 }
1161 pub fn into_physics_world(&self) -> Option<PhysicsWorld> {
1162 PhysicsWorld::cast(self.into_object()?.as_ref())
1163 }
1164 pub fn into_body(&self) -> Option<Body> {
1165 Body::cast(self.into_object()?.as_ref())
1166 }
1167 pub fn into_joint(&self) -> Option<Joint> {
1168 Joint::cast(self.into_object()?.as_ref())
1169 }
1170 pub fn into_vec2(&self) -> Option<Vec2> {
1171 unsafe {
1172 if value_is_vec2(self.raw) != 0 {
1173 Some(Vec2::from(value_into_vec2(self.raw)))
1174 } else {
1175 None
1176 }
1177 }
1178 }
1179 pub fn into_size(&self) -> Option<Size> {
1180 unsafe {
1181 if value_is_size(self.raw) != 0 {
1182 Some(Size::from(value_into_size(self.raw)))
1183 } else {
1184 None
1185 }
1186 }
1187 }
1188 pub fn cast<T: Clone + 'static>(&self) -> Option<T> {
1189 cast::<T>(self.into_object()?.as_ref())
1190 }
1191}
1192
1193impl Drop for Value {
1194 fn drop(&mut self) {
1195 unsafe {
1196 value_release(self.raw);
1197 }
1198 }
1199}
1200
1201impl CallStack {
1204 fn raw(&self) -> i64 {
1205 self.raw
1206 }
1207 pub fn new() -> CallStack {
1208 CallStack { raw: unsafe { call_stack_create() } }
1209 }
1210 pub fn push_i32(&mut self, value: i32) {
1211 unsafe {
1212 call_stack_push_i64(self.raw, value as i64);
1213 }
1214 }
1215 pub fn push_i64(&mut self, value: i64) {
1216 unsafe {
1217 call_stack_push_i64(self.raw, value);
1218 }
1219 }
1220 pub fn push_f32(&mut self, value: f32) {
1221 unsafe {
1222 call_stack_push_f64(self.raw, value as f64);
1223 }
1224 }
1225 pub fn push_f64(&mut self, value: f64) {
1226 unsafe {
1227 call_stack_push_f64(self.raw, value);
1228 }
1229 }
1230 pub fn push_str(&mut self, value: &str) {
1231 unsafe {
1232 call_stack_push_str(self.raw, from_string(value));
1233 }
1234 }
1235 pub fn push_bool(&mut self, value: bool) {
1236 unsafe {
1237 call_stack_push_bool(self.raw, if value { 1 } else { 0 });
1238 }
1239 }
1240 pub fn push_object(&mut self, value: &dyn IObject) {
1241 unsafe {
1242 call_stack_push_object(self.raw, value.raw());
1243 }
1244 }
1245 pub fn push_vec2(&mut self, value: &Vec2) {
1246 unsafe {
1247 call_stack_push_vec2(self.raw, value.into_i64());
1248 }
1249 }
1250 pub fn push_size(&mut self, value: &Size) {
1251 unsafe {
1252 call_stack_push_size(self.raw, value.into_i64());
1253 }
1254 }
1255 pub fn pop_i32(&mut self) -> Option<i32> {
1257 unsafe {
1258 if call_stack_front_i64(self.raw) != 0 {
1259 Some(call_stack_pop_i64(self.raw) as i32)
1260 } else {
1261 None
1262 }
1263 }
1264 }
1265 pub fn pop_i64(&mut self) -> Option<i64> {
1267 unsafe {
1268 if call_stack_front_i64(self.raw) != 0 {
1269 Some(call_stack_pop_i64(self.raw))
1270 } else {
1271 None
1272 }
1273 }
1274 }
1275 pub fn pop_f32(&mut self) -> Option<f32> {
1277 unsafe {
1278 if call_stack_front_f64(self.raw) != 0 {
1279 Some(call_stack_pop_f64(self.raw) as f32)
1280 } else {
1281 None
1282 }
1283 }
1284 }
1285 pub fn pop_f64(&mut self) -> Option<f64> {
1287 unsafe {
1288 if call_stack_front_f64(self.raw) != 0 {
1289 Some(call_stack_pop_f64(self.raw))
1290 } else {
1291 None
1292 }
1293 }
1294 }
1295 pub fn pop_str(&mut self) -> Option<String> {
1297 unsafe {
1298 if call_stack_front_str(self.raw) != 0 {
1299 Some(to_string(call_stack_pop_str(self.raw)))
1300 } else {
1301 None
1302 }
1303 }
1304 }
1305 pub fn pop_bool(&mut self) -> Option<bool> {
1307 unsafe {
1308 if call_stack_front_bool(self.raw) != 0 {
1309 Some(call_stack_pop_bool(self.raw) != 0)
1310 } else {
1311 None
1312 }
1313 }
1314 }
1315 pub fn pop_vec2(&mut self) -> Option<Vec2> {
1317 unsafe {
1318 if call_stack_front_vec2(self.raw) != 0 {
1319 Some(Vec2::from(call_stack_pop_vec2(self.raw)))
1320 } else {
1321 None
1322 }
1323 }
1324 }
1325 pub fn pop_size(&mut self) -> Option<Size> {
1327 unsafe {
1328 if call_stack_front_size(self.raw) != 0 {
1329 Some(Size::from(call_stack_pop_size(self.raw)))
1330 } else {
1331 None
1332 }
1333 }
1334 }
1335 pub fn pop_object(&mut self) -> Option<Box<dyn IObject>> {
1337 unsafe {
1338 if call_stack_front_object(self.raw) != 0 {
1339 let raw = call_stack_pop_object(self.raw);
1340 into_object(raw)
1341 } else {
1342 None
1343 }
1344 }
1345 }
1346 pub fn pop_into_node(&mut self) -> Option<Node> {
1349 Node::cast(self.pop_object()?.as_ref())
1350 }
1351 pub fn pop_into_camera(&mut self) -> Option<Camera> {
1354 Camera::cast(self.pop_object()?.as_ref())
1355 }
1356 pub fn pop_into_playable(&mut self) -> Option<Playable> {
1359 Playable::cast(self.pop_object()?.as_ref())
1360 }
1361 pub fn pop_into_physics_world(&mut self) -> Option<PhysicsWorld> {
1364 PhysicsWorld::cast(self.pop_object()?.as_ref())
1365 }
1366 pub fn pop_into_body(&mut self) -> Option<Body> {
1369 Body::cast(self.pop_object()?.as_ref())
1370 }
1371 pub fn pop_into_joint(&mut self) -> Option<Joint> {
1374 Joint::cast(self.pop_object()?.as_ref())
1375 }
1376 pub fn pop_cast<T: Clone + 'static>(&mut self) -> Option<T> {
1379 cast::<T>(self.pop_object()?.as_ref())
1380 }
1381 pub fn pop(&mut self) -> bool {
1384 if unsafe { call_stack_pop(self.raw) } == 0 {
1385 return false;
1386 }
1387 true
1388 }
1389}
1390
1391impl Drop for CallStack {
1392 fn drop(&mut self) {
1393 unsafe {
1394 call_stack_release(self.raw);
1395 }
1396 }
1397}
1398
1399pub struct Slot {}
1401impl Slot {
1402 pub const ACTION_END: &'static str = "Action";
1428 pub const TAP_FILTER: &'static str = "TapFilter";
1448 pub const TAP_BEGAN: &'static str = "TapBegan";
1467 pub const TAP_ENDED: &'static str = "TapEnded";
1486 pub const TAPPED: &'static str = "Tapped";
1505 pub const TAP_MOVED: &'static str = "TapMoved";
1524 pub const MOUSE_WHEEL: &'static str = "MouseWheel";
1543 pub const GESTURE: &'static str = "Gesture";
1574 pub const ENTER: &'static str = "Enter";
1577 pub const EXIT: &'static str = "Exit";
1580 pub const CLEANUP: &'static str = "Cleanup";
1583 pub const KEY_DOWN: &'static str = "KeyDown";
1605 pub const KEY_UP: &'static str = "KeyUp";
1627 pub const KEY_PRESSED: &'static str = "KeyPressed";
1649 pub const ATTACH_IME: &'static str = "AttachIME";
1651 pub const DETACH_IME: &'static str = "DetachIME";
1653 pub const TEXT_INPUT: &'static str = "TextInput";
1673 pub const TEXT_EDITING: &'static str = "TextEditing";
1700 pub const BUTTON_DOWN: &'static str = "ButtonDown";
1729 pub const BUTTON_UP: &'static str = "ButtonUp";
1758 pub const BUTTON_PRESSED: &'static str = "ButtonPressed";
1788 pub const AXIS: &'static str = "Axis";
1819 pub const ANIMATION_END: &'static str = "AnimationEnd";
1847 pub const BODY_ENTER: &'static str = "BodyEnter";
1873 pub const BODY_LEAVE: &'static str = "BodyLeave";
1899 pub const CONTACT_START: &'static str = "ContactStart";
1931 pub const CONTACT_END: &'static str = "ContactEnd";
1960 pub const FINISHED: &'static str = "Finished";
1962 pub const ALIGN_LAYOUT: &'static str = "AlignLayout";
1987 pub const EFFEK_END: &'static str = "EffekEnd";
2005 pub fn on_action_end<F>(node: &mut dyn INode, mut callback: F)
2014 where
2015 F: FnMut(Action, Node) + 'static,
2016 {
2017 node.slot(
2018 Slot::ACTION_END,
2019 Box::new(move |stack| {
2020 let (action, node) = match (stack.pop_cast::<Action>(), stack.pop_into_node()) {
2021 (Some(action), Some(node)) => (action, node),
2022 _ => return,
2023 };
2024 callback(action, node);
2025 }),
2026 );
2027 }
2028 pub fn on_tap_filter<F>(node: &mut dyn INode, mut callback: F)
2036 where
2037 F: FnMut(Touch) + 'static,
2038 {
2039 node.set_touch_enabled(true);
2040 node.slot(
2041 Slot::TAP_FILTER,
2042 Box::new(move |stack| {
2043 let touch = match stack.pop_cast::<Touch>() {
2044 Some(touch) => touch,
2045 None => return,
2046 };
2047 callback(touch);
2048 }),
2049 );
2050 }
2051 pub fn on_tap_began<F>(node: &mut dyn INode, mut callback: F)
2059 where
2060 F: FnMut(Touch) + 'static,
2061 {
2062 node.set_touch_enabled(true);
2063 node.slot(
2064 Slot::TAP_BEGAN,
2065 Box::new(move |stack| {
2066 let touch = match stack.pop_cast::<Touch>() {
2067 Some(touch) => touch,
2068 None => return,
2069 };
2070 callback(touch);
2071 }),
2072 );
2073 }
2074 pub fn on_tap_ended<F>(node: &mut dyn INode, mut callback: F)
2082 where
2083 F: FnMut(Touch) + 'static,
2084 {
2085 node.set_touch_enabled(true);
2086 node.slot(
2087 Slot::TAP_ENDED,
2088 Box::new(move |stack| {
2089 let touch = match stack.pop_cast::<Touch>() {
2090 Some(touch) => touch,
2091 None => return,
2092 };
2093 callback(touch);
2094 }),
2095 );
2096 }
2097 pub fn on_tapped<F>(node: &mut dyn INode, mut callback: F)
2105 where
2106 F: FnMut(Touch) + 'static,
2107 {
2108 node.set_touch_enabled(true);
2109 node.slot(
2110 Slot::TAPPED,
2111 Box::new(move |stack| {
2112 let touch = match stack.pop_cast::<Touch>() {
2113 Some(touch) => touch,
2114 None => return,
2115 };
2116 callback(touch);
2117 }),
2118 );
2119 }
2120 pub fn on_tap_moved<F>(node: &mut dyn INode, mut callback: F)
2128 where
2129 F: FnMut(Touch) + 'static,
2130 {
2131 node.set_touch_enabled(true);
2132 node.slot(
2133 Slot::TAP_MOVED,
2134 Box::new(move |stack| {
2135 let touch = match stack.pop_cast::<Touch>() {
2136 Some(touch) => touch,
2137 None => return,
2138 };
2139 callback(touch);
2140 }),
2141 );
2142 }
2143 pub fn on_mouse_wheel<F>(node: &mut dyn INode, mut callback: F)
2151 where
2152 F: FnMut(Vec2) + 'static,
2153 {
2154 node.set_touch_enabled(true);
2155 node.slot(
2156 Slot::MOUSE_WHEEL,
2157 Box::new(move |stack| {
2158 let delta = match stack.pop_vec2() {
2159 Some(delta) => delta,
2160 None => return,
2161 };
2162 callback(delta);
2163 }),
2164 );
2165 }
2166 pub fn on_gesture<F>(node: &mut dyn INode, mut callback: F)
2177 where
2178 F: FnMut(
2179 Vec2,
2180 i32,
2181 f32,
2182 f32,
2183 ) + 'static,
2184 {
2185 node.set_touch_enabled(true);
2186 node.slot(
2187 Slot::GESTURE,
2188 Box::new(move |stack| {
2189 let (center, num_fingers, delta_dist, delta_angle) =
2190 match (stack.pop_vec2(), stack.pop_i32(), stack.pop_f32(), stack.pop_f32()) {
2191 (Some(center), Some(num_fingers), Some(delta_dist), Some(delta_angle)) => {
2192 (center, num_fingers, delta_dist, delta_angle)
2193 }
2194 _ => return,
2195 };
2196 callback(center, num_fingers, delta_dist, delta_angle);
2197 }),
2198 );
2199 }
2200 pub fn on_enter<F>(node: &mut dyn INode, mut callback: F)
2207 where
2208 F: FnMut() + 'static,
2209 {
2210 node.slot(
2211 Slot::ENTER,
2212 Box::new(move |_| {
2213 callback();
2214 }),
2215 );
2216 }
2217 pub fn on_exit<F>(node: &mut dyn INode, mut callback: F)
2224 where
2225 F: FnMut() + 'static,
2226 {
2227 node.slot(
2228 Slot::EXIT,
2229 Box::new(move |_| {
2230 callback();
2231 }),
2232 );
2233 }
2234 pub fn on_cleanup<F>(node: &mut dyn INode, mut callback: F)
2241 where
2242 F: FnMut() + 'static,
2243 {
2244 node.slot(
2245 Slot::CLEANUP,
2246 Box::new(move |_| {
2247 callback();
2248 }),
2249 );
2250 }
2251 pub fn on_key_down<F>(node: &mut dyn INode, key: KeyName, mut callback: F)
2259 where
2260 F: FnMut() + 'static,
2261 {
2262 node.set_keyboard_enabled(true);
2263 node.slot(
2264 Slot::KEY_DOWN,
2265 Box::new(move |stack| {
2266 let key_name = match stack.pop_str() {
2267 Some(key_name) => key_name,
2268 None => return,
2269 };
2270 if key.as_ref() == key_name {
2271 callback();
2272 }
2273 }),
2274 );
2275 }
2276 pub fn on_key_up<F>(node: &mut dyn INode, key: KeyName, mut callback: F)
2283 where
2284 F: FnMut() + 'static,
2285 {
2286 node.set_keyboard_enabled(true);
2287 node.slot(
2288 Slot::KEY_UP,
2289 Box::new(move |stack| {
2290 let key_name = match stack.pop_str() {
2291 Some(key_name) => key_name,
2292 None => return,
2293 };
2294 if key.as_ref() == key_name {
2295 callback();
2296 }
2297 }),
2298 );
2299 }
2300 pub fn on_key_pressed<F>(node: &mut dyn INode, key: KeyName, mut callback: F)
2307 where
2308 F: FnMut() + 'static,
2309 {
2310 node.set_keyboard_enabled(true);
2311 node.slot(
2312 Slot::KEY_PRESSED,
2313 Box::new(move |stack| {
2314 let key_name = match stack.pop_str() {
2315 Some(key_name) => key_name,
2316 None => return,
2317 };
2318 if key.as_ref() == key_name {
2319 callback();
2320 }
2321 }),
2322 );
2323 }
2324 pub fn on_attach_ime<F>(node: &mut dyn INode, mut callback: F)
2331 where
2332 F: FnMut() + 'static,
2333 {
2334 node.slot(
2335 Slot::ATTACH_IME,
2336 Box::new(move |_| {
2337 callback();
2338 }),
2339 );
2340 }
2341 pub fn on_detach_ime<F>(node: &mut dyn INode, mut callback: F)
2348 where
2349 F: FnMut() + 'static,
2350 {
2351 node.slot(
2352 Slot::DETACH_IME,
2353 Box::new(move |_| {
2354 callback();
2355 }),
2356 );
2357 }
2358 pub fn on_text_input<F>(node: &mut dyn INode, mut callback: F)
2366 where
2367 F: FnMut(String) + 'static,
2368 {
2369 node.slot(
2370 Slot::TEXT_INPUT,
2371 Box::new(move |stack| {
2372 let text = match stack.pop_str() {
2373 Some(text) => text,
2374 None => return,
2375 };
2376 callback(text);
2377 }),
2378 );
2379 }
2380 pub fn on_text_editing<F>(node: &mut dyn INode, mut callback: F)
2389 where
2390 F: FnMut(String, i32) + 'static,
2391 {
2392 node.slot(
2393 Slot::TEXT_EDITING,
2394 Box::new(move |stack| {
2395 let (text, start_pos) = match (stack.pop_str(), stack.pop_i32()) {
2396 (Some(text), Some(start_pos)) => (text, start_pos),
2397 _ => return,
2398 };
2399 callback(text, start_pos);
2400 }),
2401 );
2402 }
2403 pub fn on_button_down<F>(node: &mut dyn INode, button: ButtonName, mut callback: F)
2412 where
2413 F: FnMut(i32) + 'static,
2414 {
2415 node.set_controller_enabled(true);
2416 node.slot(
2417 Slot::BUTTON_DOWN,
2418 Box::new(move |stack| {
2419 let (controller_id, button_name) = match (stack.pop_i32(), stack.pop_str()) {
2420 (Some(controller_id), Some(button_name)) => (controller_id, button_name),
2421 _ => return,
2422 };
2423 if button.as_ref() == button_name {
2424 callback(controller_id);
2425 }
2426 }),
2427 );
2428 }
2429 pub fn on_button_up<F>(node: &mut dyn INode, button: ButtonName, mut callback: F)
2438 where
2439 F: FnMut(i32) + 'static,
2440 {
2441 node.set_controller_enabled(true);
2442 node.slot(
2443 Slot::BUTTON_UP,
2444 Box::new(move |stack| {
2445 let (controller_id, button_name) = match (stack.pop_i32(), stack.pop_str()) {
2446 (Some(controller_id), Some(button_name)) => (controller_id, button_name),
2447 _ => return,
2448 };
2449 if button.as_ref() == button_name {
2450 callback(controller_id);
2451 }
2452 }),
2453 );
2454 }
2455 pub fn on_button_pressed<F>(node: &mut dyn INode, button: ButtonName, mut callback: F)
2465 where
2466 F: FnMut(i32) + 'static,
2467 {
2468 node.set_controller_enabled(true);
2469 node.slot(
2470 Slot::BUTTON_PRESSED,
2471 Box::new(move |stack| {
2472 let (controller_id, button_name) = match (stack.pop_i32(), stack.pop_str()) {
2473 (Some(controller_id), Some(button_name)) => (controller_id, button_name),
2474 _ => return,
2475 };
2476 if button.as_ref() == button_name {
2477 callback(controller_id);
2478 }
2479 }),
2480 );
2481 }
2482 pub fn on_axis<F>(node: &mut dyn INode, axis: AxisName, mut callback: F)
2493 where
2494 F: FnMut(i32, f32) + 'static,
2495 {
2496 node.set_controller_enabled(true);
2497 node.slot(
2498 Slot::AXIS,
2499 Box::new(move |stack| {
2500 let (controller_id, axis_name, axis_value) =
2501 match (stack.pop_i32(), stack.pop_str(), stack.pop_f32()) {
2502 (Some(controller_id), Some(axis_name), Some(axis_value)) => {
2503 (controller_id, axis_name, axis_value)
2504 }
2505 _ => return,
2506 };
2507 if axis.as_ref() == axis_name {
2508 callback(controller_id, axis_value);
2509 }
2510 }),
2511 );
2512 }
2513 pub fn on_animation_end<F>(node: &mut dyn IPlayable, mut callback: F)
2522 where
2523 F: FnMut(String, Playable) + 'static,
2524 {
2525 node.slot(
2526 Slot::ANIMATION_END,
2527 Box::new(move |stack| {
2528 let (animation_name, playable) = match (stack.pop_str(), stack.pop_into_playable())
2529 {
2530 (Some(animation_name), Some(playable)) => (animation_name, playable),
2531 _ => return,
2532 };
2533 callback(animation_name, playable);
2534 }),
2535 );
2536 }
2537 pub fn on_body_enter<F>(node: &mut dyn IBody, mut callback: F)
2546 where
2547 F: FnMut(Body, i32) + 'static,
2548 {
2549 node.slot(
2550 Slot::BODY_ENTER,
2551 Box::new(move |stack| {
2552 let (other, sensor_tag) = match (stack.pop_into_body(), stack.pop_i32()) {
2553 (Some(other), Some(sensor_tag)) => (other, sensor_tag),
2554 _ => return,
2555 };
2556 callback(other, sensor_tag);
2557 }),
2558 );
2559 }
2560 pub fn on_body_leave<F>(node: &mut dyn IBody, mut callback: F)
2569 where
2570 F: FnMut(Body, i32) + 'static,
2571 {
2572 node.slot(
2573 Slot::BODY_LEAVE,
2574 Box::new(move |stack| {
2575 let (other, sensor_tag) = match (stack.pop_into_body(), stack.pop_i32()) {
2576 (Some(other), Some(sensor_tag)) => (other, sensor_tag),
2577 _ => return,
2578 };
2579 callback(other, sensor_tag);
2580 }),
2581 );
2582 }
2583 pub fn on_contact_start<F>(node: &mut dyn IBody, mut callback: F)
2594 where
2595 F: FnMut(
2596 Body,
2597 Vec2,
2598 Vec2,
2599 bool,
2600 ) + 'static,
2601 {
2602 node.set_receiving_contact(true);
2603 node.slot(
2604 Slot::CONTACT_START,
2605 Box::new(move |stack| {
2606 let (other, point, normal, enabled) = match (
2607 stack.pop_into_body(),
2608 stack.pop_vec2(),
2609 stack.pop_vec2(),
2610 stack.pop_bool(),
2611 ) {
2612 (Some(other), Some(point), Some(normal), Some(enabled)) => {
2613 (other, point, normal, enabled)
2614 }
2615 _ => return,
2616 };
2617 callback(other, point, normal, enabled);
2618 }),
2619 );
2620 }
2621 pub fn on_contact_end<F>(node: &mut dyn IBody, mut callback: F)
2631 where
2632 F: FnMut(Body, Vec2, Vec2) + 'static,
2633 {
2634 node.set_receiving_contact(true);
2635 node.slot(
2636 Slot::CONTACT_END,
2637 Box::new(move |stack| {
2638 let (other, point, normal) =
2639 match (stack.pop_into_body(), stack.pop_vec2(), stack.pop_vec2()) {
2640 (Some(other), Some(point), Some(normal)) => (other, point, normal),
2641 _ => return,
2642 };
2643 callback(other, point, normal);
2644 }),
2645 );
2646 }
2647 pub fn on_finished<F>(node: &mut Particle, mut callback: F)
2654 where
2655 F: FnMut() + 'static,
2656 {
2657 node.slot(
2658 Slot::FINISHED,
2659 Box::new(move |_| {
2660 callback();
2661 }),
2662 );
2663 }
2664 pub fn on_align_layout<F>(node: &mut AlignNode, mut callback: F)
2673 where
2674 F: FnMut(f32, f32) + 'static,
2675 {
2676 node.slot(
2677 Slot::ALIGN_LAYOUT,
2678 Box::new(move |stack| {
2679 let (width, height) = match (stack.pop_f32(), stack.pop_f32()) {
2680 (Some(width), Some(height)) => (width, height),
2681 _ => return,
2682 };
2683 callback(width, height);
2684 }),
2685 );
2686 }
2687 pub fn on_effek_end<F>(node: &mut EffekNode, mut callback: F)
2695 where
2696 F: FnMut(i32) + 'static,
2697 {
2698 node.slot(
2699 Slot::EFFEK_END,
2700 Box::new(move |stack| {
2701 let handle = match stack.pop_i32() {
2702 Some(handle) => handle,
2703 None => return,
2704 };
2705 callback(handle);
2706 }),
2707 );
2708 }
2709}
2710
2711pub struct GSlot {}
2713impl GSlot {
2714 pub const APP_EVENT: &'static str = "AppEvent";
2732 pub const APP_CHANGE: &'static str = "AppChange";
2750 pub const APP_WS: &'static str = "AppWS";
2772 pub fn on_app_event<F>(node: &mut dyn INode, mut callback: F)
2780 where
2781 F: FnMut(String) + 'static,
2782 {
2783 node.gslot(
2784 GSlot::APP_EVENT,
2785 Box::new(move |stack| {
2786 let event_type = match stack.pop_str() {
2787 Some(event_type) => event_type,
2788 None => return,
2789 };
2790 callback(event_type);
2791 }),
2792 );
2793 }
2794 pub fn on_app_change<F>(node: &mut dyn INode, mut callback: F)
2802 where
2803 F: FnMut(String) + 'static,
2804 {
2805 node.gslot(
2806 GSlot::APP_CHANGE,
2807 Box::new(move |stack| {
2808 let setting_name = match stack.pop_str() {
2809 Some(setting_name) => setting_name,
2810 None => return,
2811 };
2812 callback(setting_name);
2813 }),
2814 );
2815 }
2816 pub fn on_app_ws<F>(node: &mut dyn INode, mut callback: F)
2825 where
2826 F: FnMut(String, String) + 'static,
2827 {
2828 node.gslot(
2829 GSlot::APP_WS,
2830 Box::new(move |stack| {
2831 let (event_type, msg) = match (stack.pop_str(), stack.pop_str()) {
2832 (Some(event_type), Some(msg)) => (event_type, msg),
2833 _ => return,
2834 };
2835 callback(event_type, msg);
2836 }),
2837 );
2838 }
2839}
2840
2841extern "C" {
2844 fn content_load(filename: i64) -> i64;
2845}
2846
2847impl Content {
2848 pub fn load(filename: &str) -> Option<String> {
2858 let result = unsafe { content_load(from_string(filename)) };
2859 if result > 0 {
2860 Some(to_string(result))
2861 } else {
2862 None
2863 }
2864 }
2865}
2866
2867extern "C" {
2870 fn array_set(array: i64, index: i32, item: i64) -> i32;
2871 fn array_get(array: i64, index: i32) -> i64;
2872 fn array_first(array: i64) -> i64;
2873 fn array_last(array: i64) -> i64;
2874 fn array_random_object(array: i64) -> i64;
2875 fn array_add(array: i64, item: i64);
2876 fn array_insert(array: i64, index: i32, item: i64);
2877 fn array_contains(array: i64, item: i64) -> i32;
2878 fn array_index(array: i64, item: i64) -> i32;
2879 fn array_remove_last(array: i64) -> i64;
2880 fn array_fast_remove(array: i64, item: i64) -> i32;
2881}
2882
2883impl Array {
2884 pub fn set<'a, T>(&mut self, index: i32, v: T)
2891 where
2892 T: IntoValue<'a>,
2893 {
2894 if unsafe { array_set(self.raw(), index, v.val().raw()) == 0 } {
2895 panic!("Out of bounds, expecting [0, {}), got {}", self.get_count(), index);
2896 }
2897 }
2898 pub fn get(&self, index: i32) -> Option<Value> {
2908 Value::from(unsafe { array_get(self.raw(), index) })
2909 }
2910 pub fn first(&self) -> Option<Value> {
2912 Value::from(unsafe { array_first(self.raw()) })
2913 }
2914 pub fn last(&self) -> Option<Value> {
2916 Value::from(unsafe { array_last(self.raw()) })
2917 }
2918 pub fn random_object(&self) -> Option<Value> {
2920 Value::from(unsafe { array_random_object(self.raw()) })
2921 }
2922 pub fn add<'a, T>(&mut self, v: T) -> &mut Self
2928 where
2929 T: IntoValue<'a>,
2930 {
2931 unsafe {
2932 array_add(self.raw(), v.val().raw());
2933 }
2934 self
2935 }
2936 pub fn insert<'a, T>(&mut self, index: i32, v: T)
2943 where
2944 T: IntoValue<'a>,
2945 {
2946 unsafe {
2947 array_insert(self.raw(), index, v.val().raw());
2948 }
2949 }
2950 pub fn contains<'a, T>(&self, v: T) -> bool
2960 where
2961 T: IntoValue<'a>,
2962 {
2963 unsafe { array_contains(self.raw(), v.val().raw()) != 0 }
2964 }
2965 pub fn index<'a, T>(&self, v: T) -> i32
2975 where
2976 T: IntoValue<'a>,
2977 {
2978 unsafe { array_index(self.raw(), v.val().raw()) }
2979 }
2980 pub fn remove_last(&mut self) -> Option<Value> {
2986 Value::from(unsafe { array_remove_last(self.raw()) })
2987 }
2988 pub fn fast_remove<'a, T>(&mut self, v: T) -> bool
2998 where
2999 T: IntoValue<'a>,
3000 {
3001 unsafe { array_fast_remove(self.raw(), v.val().raw()) != 0 }
3002 }
3003}
3004
3005extern "C" {
3008 fn dictionary_set(dict: i64, key: i64, value: i64);
3009 fn dictionary_get(dict: i64, key: i64) -> i64;
3010}
3011
3012impl Dictionary {
3013 pub fn set<'a, T>(&mut self, key: &str, v: T)
3020 where
3021 T: IntoValue<'a>,
3022 {
3023 unsafe {
3024 dictionary_set(self.raw(), from_string(key), v.val().raw());
3025 }
3026 }
3027 pub fn get(&self, key: &str) -> Option<Value> {
3037 Value::from(unsafe { dictionary_get(self.raw(), from_string(key)) })
3038 }
3039}
3040
3041extern "C" {
3044 fn entity_set(e: i64, k: i64, v: i64);
3045 fn entity_get(e: i64, k: i64) -> i64;
3046 fn entity_get_old(e: i64, k: i64) -> i64;
3047}
3048
3049impl Entity {
3050 pub fn set<'a, T>(&mut self, key: &str, value: T)
3058 where
3059 T: IntoValue<'a>,
3060 {
3061 unsafe {
3062 entity_set(self.raw(), from_string(key), value.val().raw());
3063 }
3064 }
3065 pub fn get(&self, key: &str) -> Option<Value> {
3075 Value::from(unsafe { entity_get(self.raw(), from_string(key)) })
3076 }
3077 pub fn get_old(&self, key: &str) -> Option<Value> {
3088 Value::from(unsafe { entity_get_old(self.raw(), from_string(key)) })
3089 }
3090}
3091
3092extern "C" {
3095 fn group_watch(group: i64, func: i32, stack: i64);
3096}
3097
3098impl Group {
3099 pub fn watch(&mut self, mut callback: Box<dyn FnMut(&mut CallStack) -> bool>) -> &mut Group {
3109 let mut stack = CallStack::new();
3110 let stack_raw = stack.raw();
3111 let func_id = push_function(Box::new(move || {
3112 let result = callback(&mut stack);
3113 stack.push_bool(result);
3114 }));
3115 unsafe {
3116 group_watch(self.raw(), func_id, stack_raw);
3117 }
3118 self
3119 }
3120 pub fn each(&self, visitor: Box<dyn FnMut(&Entity) -> bool>) -> bool {
3130 match self.find(visitor) {
3131 Some(_) => true,
3132 None => false,
3133 }
3134 }
3135}
3136
3137extern "C" {
3140 fn observer_watch(observer: i64, func: i32, stack: i64);
3141}
3142
3143#[repr(i32)]
3144#[derive(Copy, Clone, Debug, PartialEq)]
3145pub enum EntityEvent {
3146 Add = 1,
3147 Change = 2,
3148 AddOrChange = 3,
3149 Remove = 4,
3150}
3151
3152impl Observer {
3153 pub fn watch(&mut self, mut callback: Box<dyn FnMut(&mut CallStack) -> bool>) -> &mut Observer {
3163 let mut stack = CallStack::new();
3164 let stack_raw = stack.raw();
3165 let func_id = push_function(Box::new(move || {
3166 let result = callback(&mut stack);
3167 stack.push_bool(result);
3168 }));
3169 unsafe {
3170 observer_watch(self.raw(), func_id, stack_raw);
3171 }
3172 self
3173 }
3174}
3175
3176#[cfg(not(target_arch = "wasm32"))]
3179extern "C" {
3180 fn director_get_scheduler() -> i64;
3181 fn director_get_post_scheduler() -> i64;
3182}
3183
3184#[cfg(target_arch = "wasm32")]
3185extern "C" {
3186 fn director_get_wasm_scheduler() -> i64;
3187 fn director_get_post_wasm_scheduler() -> i64;
3188}
3189
3190impl Director {
3191 pub fn get_scheduler() -> Scheduler {
3198 #[cfg(target_arch = "wasm32")]
3199 {
3200 Scheduler::from(unsafe { director_get_wasm_scheduler() }).unwrap()
3201 }
3202 #[cfg(not(target_arch = "wasm32"))]
3203 {
3204 Scheduler::from(unsafe { director_get_scheduler() }).unwrap()
3205 }
3206 }
3207 pub fn get_post_scheduler() -> Scheduler {
3214 #[cfg(target_arch = "wasm32")]
3215 {
3216 Scheduler::from(unsafe { director_get_post_wasm_scheduler() }).unwrap()
3217 }
3218 #[cfg(not(target_arch = "wasm32"))]
3219 {
3220 Scheduler::from(unsafe { director_get_post_scheduler() }).unwrap()
3221 }
3222 }
3223}
3224
3225impl Node {
3228 pub fn cast(obj: &dyn IObject) -> Option<Node> {
3238 let node = Node::from(unsafe { object_to_node(obj.raw()) });
3239 if node.is_some() {
3240 unsafe {
3241 object_retain(obj.raw());
3242 }
3243 }
3244 node
3245 }
3246}
3247
3248impl Camera {
3251 pub fn cast(obj: &dyn IObject) -> Option<Camera> {
3261 let camera = Camera::from(unsafe { object_to_camera(obj.raw()) });
3262 if camera.is_some() {
3263 unsafe {
3264 object_retain(obj.raw());
3265 }
3266 }
3267 camera
3268 }
3269}
3270
3271impl Playable {
3274 pub fn cast(obj: &dyn IObject) -> Option<Playable> {
3284 let playable = Playable::from(unsafe { object_to_playable(obj.raw()) });
3285 if playable.is_some() {
3286 unsafe {
3287 object_retain(obj.raw());
3288 }
3289 }
3290 playable
3291 }
3292}
3293
3294impl Body {
3297 pub fn cast(obj: &dyn IObject) -> Option<Body> {
3307 let body = Body::from(unsafe { object_to_body(obj.raw()) });
3308 if body.is_some() {
3309 unsafe {
3310 object_retain(obj.raw());
3311 }
3312 }
3313 body
3314 }
3315}
3316
3317impl Joint {
3320 pub fn cast(obj: &dyn IObject) -> Option<Joint> {
3330 let joint = Joint::from(unsafe { object_to_joint(obj.raw()) });
3331 if joint.is_some() {
3332 unsafe {
3333 object_retain(obj.raw());
3334 }
3335 }
3336 joint
3337 }
3338}
3339
3340impl PhysicsWorld {
3343 pub fn cast(obj: &dyn IObject) -> Option<PhysicsWorld> {
3353 let physics_world = PhysicsWorld::from(unsafe { object_to_physics_world(obj.raw()) });
3354 if physics_world.is_some() {
3355 unsafe {
3356 object_retain(obj.raw());
3357 }
3358 }
3359 physics_world
3360 }
3361}
3362
3363#[repr(i32)]
3365#[derive(Copy, Clone, Debug, PartialEq)]
3366pub enum TextureWrap {
3367 None = 0,
3368 Mirror = 1,
3369 Clamp = 2,
3370 Border = 3,
3371}
3372
3373#[repr(i32)]
3374#[derive(Copy, Clone, Debug, PartialEq)]
3375pub enum TextureFilter {
3376 None = 0,
3377 Point = 1,
3378 Anisotropic = 2,
3379}
3380
3381#[repr(u64)]
3382#[derive(Copy, Clone, Debug, PartialEq)]
3383pub enum BFunc {
3384 Zero = 0x0000000000001000,
3385 One = 0x0000000000002000,
3386 SrcColor = 0x0000000000003000,
3387 InvSrcColor = 0x0000000000004000,
3388 SrcAlpha = 0x0000000000005000,
3389 InvSrcAlpha = 0x0000000000006000,
3390 DstAlpha = 0x0000000000007000,
3391 InvDstAlpha = 0x0000000000008000,
3392 DstColor = 0x0000000000009000,
3393 InvDstColor = 0x000000000000a000,
3394}
3395
3396pub struct BlendFunc {
3397 value: u64,
3398}
3399
3400impl BlendFunc {
3401 pub fn new_seperate(
3402 src_rgb: BFunc,
3403 dst_rgb: BFunc,
3404 src_alpha: BFunc,
3405 dst_alpha: BFunc,
3406 ) -> Self {
3407 BlendFunc {
3408 value: (src_rgb as u64
3409 | (dst_rgb as u64) << 4
3410 | src_alpha as u64
3411 | (dst_alpha as u64) << 4)
3412 << 8,
3413 }
3414 }
3415 pub fn new(src: BFunc, dst: BFunc) -> Self {
3416 BlendFunc::new_seperate(src, dst, src, dst)
3417 }
3418 pub fn from(value: i64) -> Self {
3419 BlendFunc { value: value as u64 }
3420 }
3421 pub(crate) fn to_value(&self) -> i64 {
3422 self.value as i64
3423 }
3424}
3425
3426#[repr(i32)]
3429#[derive(Copy, Clone, Debug, PartialEq)]
3430pub enum EaseType {
3431 Linear = 0,
3432 InQuad = 1,
3433 OutQuad = 2,
3434 InOutQuad = 3,
3435 InCubic = 4,
3436 OutCubic = 5,
3437 InOutCubic = 6,
3438 InQuart = 7,
3439 OutQuart = 8,
3440 InOutQuart = 9,
3441 InQuint = 10,
3442 OutQuint = 11,
3443 InOutQuint = 12,
3444 InSine = 13,
3445 OutSine = 14,
3446 InOutSine = 15,
3447 InExpo = 16,
3448 OutExpo = 17,
3449 InOutExpo = 18,
3450 InCirc = 19,
3451 OutCirc = 20,
3452 InOutCirc = 21,
3453 InElastic = 22,
3454 OutElastic = 23,
3455 InOutElastic = 24,
3456 InBack = 25,
3457 OutBack = 26,
3458 InOutBack = 27,
3459 InBounce = 28,
3460 OutBounce = 29,
3461 InOutBounce = 30,
3462 OutInQuad = 31,
3463 OutInCubic = 32,
3464 OutInQuart = 33,
3465 OutInQuint = 34,
3466 OutInSine = 35,
3467 OutInExpo = 36,
3468 OutInCirc = 37,
3469 OutInElastic = 38,
3470 OutInBack = 39,
3471 OutInBounce = 40,
3472}
3473
3474#[repr(i32)]
3475#[derive(Copy, Clone, Debug, PartialEq)]
3476pub enum Property {
3477 X = 0,
3478 Y = 1,
3479 Z = 2,
3480 Angle = 3,
3481 AngleX = 4,
3482 AngleY = 5,
3483 ScaleX = 6,
3484 ScaleY = 7,
3485 SkewX = 8,
3486 SkewY = 9,
3487 Width = 10,
3488 Height = 11,
3489 AnchorX = 12,
3490 AnchorY = 13,
3491 Opacity = 14,
3492}
3493
3494#[repr(i32)]
3497#[derive(Copy, Clone, Debug, PartialEq)]
3498pub enum TextAlign {
3499 Left = 0,
3500 Center = 1,
3501 Right = 2,
3502}
3503
3504#[repr(i32)]
3507#[derive(Copy, Clone, Debug, PartialEq)]
3508pub enum BodyType {
3509 Dynamic = 0,
3510 Static = 1,
3511 Kinematic = 2,
3512}
3513
3514#[derive(Copy, Clone, Debug, PartialEq)]
3517pub enum KeyName {
3518 Return,
3519 Escape,
3520 BackSpace,
3521 Tab,
3522 Space,
3523 Exclamation,
3524 DoubleQuote,
3525 Hash,
3526 Percent,
3527 Dollar,
3528 Ampersand,
3529 SingleQuote,
3530 LeftParen,
3531 RightParen,
3532 Asterisk,
3533 Plus,
3534 Comma,
3535 Minus,
3536 Dot,
3537 Slash,
3538 Num1,
3539 Num2,
3540 Num3,
3541 Num4,
3542 Num5,
3543 Num6,
3544 Num7,
3545 Num8,
3546 Num9,
3547 Num0,
3548 Colon,
3549 Semicolon,
3550 LessThan,
3551 Equal,
3552 GreaterThan,
3553 Question,
3554 At,
3555 LeftBracket,
3556 Backslash,
3557 RightBracket,
3558 Caret,
3559 Underscore,
3560 Backtick,
3561 A,
3562 B,
3563 C,
3564 D,
3565 E,
3566 F,
3567 G,
3568 H,
3569 I,
3570 J,
3571 K,
3572 L,
3573 M,
3574 N,
3575 O,
3576 P,
3577 Q,
3578 R,
3579 S,
3580 T,
3581 U,
3582 V,
3583 W,
3584 X,
3585 Y,
3586 Z,
3587 Delete,
3588 CapsLock,
3589 F1,
3590 F2,
3591 F3,
3592 F4,
3593 F5,
3594 F6,
3595 F7,
3596 F8,
3597 F9,
3598 F10,
3599 F11,
3600 F12,
3601 PrintScreen,
3602 ScrollLock,
3603 Pause,
3604 Insert,
3605 Home,
3606 PageUp,
3607 End,
3608 PageDown,
3609 Right,
3610 Left,
3611 Down,
3612 Up,
3613 Application,
3614 LCtrl,
3615 LShift,
3616 LAlt,
3617 LGui,
3618 RCtrl,
3619 RShift,
3620 RAlt,
3621 RGui,
3622}
3623
3624impl AsRef<str> for KeyName {
3625 fn as_ref(&self) -> &str {
3626 match self {
3627 KeyName::Return => "Return",
3628 KeyName::Escape => "Escape",
3629 KeyName::BackSpace => "BackSpace",
3630 KeyName::Tab => "Tab",
3631 KeyName::Space => "Space",
3632 KeyName::Exclamation => "!",
3633 KeyName::DoubleQuote => "\"",
3634 KeyName::Hash => "#",
3635 KeyName::Percent => "%",
3636 KeyName::Dollar => "$",
3637 KeyName::Ampersand => "&",
3638 KeyName::SingleQuote => "'",
3639 KeyName::LeftParen => "(",
3640 KeyName::RightParen => ")",
3641 KeyName::Asterisk => "*",
3642 KeyName::Plus => "+",
3643 KeyName::Comma => ",",
3644 KeyName::Minus => "-",
3645 KeyName::Dot => ".",
3646 KeyName::Slash => "/",
3647 KeyName::Num1 => "1",
3648 KeyName::Num2 => "2",
3649 KeyName::Num3 => "3",
3650 KeyName::Num4 => "4",
3651 KeyName::Num5 => "5",
3652 KeyName::Num6 => "6",
3653 KeyName::Num7 => "7",
3654 KeyName::Num8 => "8",
3655 KeyName::Num9 => "9",
3656 KeyName::Num0 => "0",
3657 KeyName::Colon => ":",
3658 KeyName::Semicolon => ";",
3659 KeyName::LessThan => "<",
3660 KeyName::Equal => "=",
3661 KeyName::GreaterThan => ">",
3662 KeyName::Question => "?",
3663 KeyName::At => "@",
3664 KeyName::LeftBracket => "[",
3665 KeyName::Backslash => "\\",
3666 KeyName::RightBracket => "]",
3667 KeyName::Caret => "^",
3668 KeyName::Underscore => "_",
3669 KeyName::Backtick => "`",
3670 KeyName::A => "A",
3671 KeyName::B => "B",
3672 KeyName::C => "C",
3673 KeyName::D => "D",
3674 KeyName::E => "E",
3675 KeyName::F => "F",
3676 KeyName::G => "G",
3677 KeyName::H => "H",
3678 KeyName::I => "I",
3679 KeyName::J => "J",
3680 KeyName::K => "K",
3681 KeyName::L => "L",
3682 KeyName::M => "M",
3683 KeyName::N => "N",
3684 KeyName::O => "O",
3685 KeyName::P => "P",
3686 KeyName::Q => "Q",
3687 KeyName::R => "R",
3688 KeyName::S => "S",
3689 KeyName::T => "T",
3690 KeyName::U => "U",
3691 KeyName::V => "V",
3692 KeyName::W => "W",
3693 KeyName::X => "X",
3694 KeyName::Y => "Y",
3695 KeyName::Z => "Z",
3696 KeyName::Delete => "Delete",
3697 KeyName::CapsLock => "CapsLock",
3698 KeyName::F1 => "F1",
3699 KeyName::F2 => "F2",
3700 KeyName::F3 => "F3",
3701 KeyName::F4 => "F4",
3702 KeyName::F5 => "F5",
3703 KeyName::F6 => "F6",
3704 KeyName::F7 => "F7",
3705 KeyName::F8 => "F8",
3706 KeyName::F9 => "F9",
3707 KeyName::F10 => "F10",
3708 KeyName::F11 => "F11",
3709 KeyName::F12 => "F12",
3710 KeyName::PrintScreen => "PrintScreen",
3711 KeyName::ScrollLock => "ScrollLock",
3712 KeyName::Pause => "Pause",
3713 KeyName::Insert => "Insert",
3714 KeyName::Home => "Home",
3715 KeyName::PageUp => "PageUp",
3716 KeyName::End => "End",
3717 KeyName::PageDown => "PageDown",
3718 KeyName::Right => "Right",
3719 KeyName::Left => "Left",
3720 KeyName::Down => "Down",
3721 KeyName::Up => "Up",
3722 KeyName::Application => "Application",
3723 KeyName::LCtrl => "LCtrl",
3724 KeyName::LShift => "LShift",
3725 KeyName::LAlt => "LAlt",
3726 KeyName::LGui => "LGui",
3727 KeyName::RCtrl => "RCtrl",
3728 KeyName::RShift => "RShift",
3729 KeyName::RAlt => "RAlt",
3730 KeyName::RGui => "RGui",
3731 }
3732 }
3733}
3734
3735impl Keyboard {
3736 pub fn is_key_down(key: KeyName) -> bool {
3746 Keyboard::_is_key_down(key.as_ref())
3747 }
3748 pub fn is_key_up(key: KeyName) -> bool {
3758 Keyboard::_is_key_up(key.as_ref())
3759 }
3760 pub fn is_key_pressed(key: KeyName) -> bool {
3770 Keyboard::_is_key_pressed(key.as_ref())
3771 }
3772}
3773
3774#[derive(Copy, Clone, Debug, PartialEq)]
3777pub enum AxisName {
3778 LeftX,
3779 LeftY,
3780 RightX,
3781 RightY,
3782 LeftTrigger,
3783 RightTrigger,
3784}
3785
3786impl AsRef<str> for AxisName {
3787 fn as_ref(&self) -> &str {
3788 match self {
3789 AxisName::LeftX => "leftx",
3790 AxisName::LeftY => "lefty",
3791 AxisName::RightX => "rightx",
3792 AxisName::RightY => "righty",
3793 AxisName::LeftTrigger => "lefttrigger",
3794 AxisName::RightTrigger => "righttrigger",
3795 }
3796 }
3797}
3798
3799#[derive(Copy, Clone, Debug, PartialEq)]
3800pub enum ButtonName {
3801 A,
3802 B,
3803 Back,
3804 DPDown,
3805 DPLeft,
3806 DPRight,
3807 DPUp,
3808 LeftShoulder,
3809 LeftStick,
3810 RightShoulder,
3811 RightStick,
3812 Start,
3813 X,
3814 Y,
3815}
3816
3817impl AsRef<str> for ButtonName {
3818 fn as_ref(&self) -> &str {
3819 match self {
3820 ButtonName::A => "a",
3821 ButtonName::B => "b",
3822 ButtonName::Back => "back",
3823 ButtonName::DPDown => "dpdown",
3824 ButtonName::DPLeft => "dpleft",
3825 ButtonName::DPRight => "dpright",
3826 ButtonName::DPUp => "dpup",
3827 ButtonName::LeftShoulder => "leftshoulder",
3828 ButtonName::LeftStick => "leftstick",
3829 ButtonName::RightShoulder => "rightshoulder",
3830 ButtonName::RightStick => "rightstick",
3831 ButtonName::Start => "start",
3832 ButtonName::X => "x",
3833 ButtonName::Y => "y",
3834 }
3835 }
3836}
3837
3838impl Controller {
3839 pub fn is_button_down(controller_id: i32, button: ButtonName) -> bool {
3850 Controller::_is_button_down(controller_id, button.as_ref())
3851 }
3852 pub fn is_button_up(controller_id: i32, button: ButtonName) -> bool {
3863 Controller::_is_button_up(controller_id, button.as_ref())
3864 }
3865 pub fn is_button_pressed(controller_id: i32, button: ButtonName) -> bool {
3876 Controller::_is_button_pressed(controller_id, button.as_ref())
3877 }
3878 pub fn get_axis(controller_id: i32, axis: AxisName) -> f32 {
3889 Controller::_get_axis(controller_id, axis.as_ref())
3890 }
3891}
3892
3893#[repr(i32)]
3896#[derive(Copy, Clone, Debug, PartialEq)]
3897pub enum AttenuationModel {
3898 NoAttenuation = 0,
3899 InverseDistance = 1,
3900 LinearDistance = 2,
3901 ExponentialDistance = 3,
3902}
3903
3904impl platformer::ActionUpdate {
3907 pub fn from_update(mut update: Box<dyn FnMut(f64) -> bool>) -> platformer::ActionUpdate {
3908 platformer::ActionUpdate::new(Box::new(move |_, _, dt| update(dt as f64)))
3909 }
3910}
3911
3912extern "C" {
3915 fn blackboard_set(b: i64, k: i64, v: i64);
3916 fn blackboard_get(b: i64, k: i64) -> i64;
3917}
3918
3919impl platformer::behavior::Blackboard {
3920 pub fn set<'a, T>(&mut self, key: &str, value: T)
3932 where
3933 T: IntoValue<'a>,
3934 {
3935 unsafe {
3936 blackboard_set(self.raw(), from_string(key), value.val().raw());
3937 }
3938 }
3939 pub fn get(&self, key: &str) -> Option<Value> {
3959 Value::from(unsafe { blackboard_get(self.raw(), from_string(key)) })
3960 }
3961}
3962
3963pub use enumflags2::BitFlags;
3964use enumflags2::{bitflags, make_bitflags};
3965
3966#[bitflags]
3967#[repr(u32)]
3968#[derive(Copy, Clone, Debug, PartialEq)]
3969pub enum ImGuiSliderFlag {
3970 Logarithmic = 1 << 5,
3971 NoRoundToFormat = 1 << 6,
3972 NoInput = 1 << 7,
3973 WrapAround = 1 << 8,
3974 ClampOnInput = 1 << 9,
3975 ClampZeroRange = 1 << 10,
3976}
3977
3978impl ImGuiSliderFlag {
3979 pub const ALWAYS_CLAMP: BitFlags<Self> = make_bitflags!(Self::{ClampOnInput | ClampZeroRange});
3980}
3981
3982#[bitflags]
3983#[repr(u32)]
3984#[derive(Copy, Clone, Debug, PartialEq)]
3985pub enum ImGuiWindowFlag {
3986 NoTitleBar = 1 << 0,
3987 NoResize = 1 << 1,
3988 NoMove = 1 << 2,
3989 NoScrollbar = 1 << 3,
3990 NoScrollWithMouse = 1 << 4,
3991 NoCollapse = 1 << 5,
3992 AlwaysAutoResize = 1 << 6,
3993 NoBackground = 1 << 7,
3994 NoSavedSettings = 1 << 8,
3995 NoMouseInputs = 1 << 9,
3996 MenuBar = 1 << 10,
3997 HorizontalScrollbar = 1 << 11,
3998 NoFocusOnAppearing = 1 << 12,
3999 NoBringToFrontOnFocus = 1 << 13,
4000 AlwaysVerticalScrollbar = 1 << 14,
4001 AlwaysHorizontalScrollbar = 1 << 15,
4002 NoNavInputs = 1 << 16,
4003 NoNavFocus = 1 << 17,
4004 UnsavedDocument = 1 << 18,
4005}
4006
4007impl ImGuiWindowFlag {
4008 pub const NO_NAV: BitFlags<Self> = make_bitflags!(Self::{NoNavInputs | NoNavFocus});
4009 pub const NO_DECORATION: BitFlags<Self> =
4010 make_bitflags!(Self::{NoTitleBar | NoResize | NoScrollbar | NoCollapse});
4011 pub const NO_INPUTS: BitFlags<Self> =
4012 make_bitflags!(Self::{NoMouseInputs | NoNavInputs | NoNavFocus});
4013}
4014
4015#[bitflags]
4016#[repr(u8)]
4017#[derive(Copy, Clone, Debug, PartialEq)]
4018pub enum ImGuiChildFlag {
4019 Borders = 1 << 0,
4020 AlwaysUseWindowPadding = 1 << 1,
4021 ResizeX = 1 << 2,
4022 ResizeY = 1 << 3,
4023 AutoResizeX = 1 << 4,
4024 AutoResizeY = 1 << 5,
4025 AlwaysAutoResize = 1 << 6,
4026 FrameStyle = 1 << 7,
4027}
4028
4029#[bitflags]
4030#[repr(u32)]
4031#[derive(Copy, Clone, Debug, PartialEq)]
4032pub enum ImGuiInputTextFlag {
4033 CharsDecimal = 1 << 0,
4034 CharsHexadecimal = 1 << 1,
4035 CharsScientific = 1 << 2,
4036 CharsUppercase = 1 << 3,
4037 CharsNoBlank = 1 << 4,
4038 AllowTabInput = 1 << 5,
4039 EnterReturnsTrue = 1 << 6,
4040 EscapeClearsAll = 1 << 7,
4041 CtrlEnterForNewLine = 1 << 8,
4042 ReadOnly = 1 << 9,
4043 Password = 1 << 10,
4044 AlwaysOverwrite = 1 << 11,
4045 AutoSelectAll = 1 << 12,
4046 ParseEmptyRefVal = 1 << 13,
4047 DisplayEmptyRefVal = 1 << 14,
4048 NoHorizontalScroll = 1 << 15,
4049 NoUndoRedo = 1 << 16,
4050 ElideLeft = 1 << 17,
4051 CallbackCompletion = 1 << 18,
4052 CallbackHistory = 1 << 19,
4053 CallbackAlways = 1 << 20,
4054 CallbackCharFilter = 1 << 21,
4055 CallbackResize = 1 << 22,
4056 CallbackEdit = 1 << 23,
4057}
4058
4059#[bitflags]
4060#[repr(u32)]
4061#[derive(Copy, Clone, Debug, PartialEq)]
4062pub enum ImGuiTreeNodeFlag {
4063 Selected = 1 << 0,
4064 Framed = 1 << 1,
4065 AllowOverlap = 1 << 2,
4066 NoTreePushOnOpen = 1 << 3,
4067 NoAutoOpenOnLog = 1 << 4,
4068 DefaultOpen = 1 << 5,
4069 OpenOnDoubleClick = 1 << 6,
4070 OpenOnArrow = 1 << 7,
4071 Leaf = 1 << 8,
4072 Bullet = 1 << 9,
4073 FramePadding = 1 << 10,
4074 SpanAvailWidth = 1 << 11,
4075 SpanFullWidth = 1 << 12,
4076 SpanLabelWidth = 1 << 13,
4077 SpanAllColumns = 1 << 14,
4078 LabelSpanAllColumns = 1 << 15,
4079 NavLeftJumpsToParent = 1 << 17,
4080}
4081
4082impl ImGuiTreeNodeFlag {
4083 pub const COLLAPSING_HEADER: BitFlags<Self> =
4084 make_bitflags!(Self::{Framed | NoTreePushOnOpen | NoAutoOpenOnLog});
4085}
4086
4087#[bitflags]
4088#[repr(u8)]
4089#[derive(Copy, Clone, Debug, PartialEq)]
4090pub enum ImGuiSelectableFlag {
4091 DontClosePopups = 1 << 0,
4092 SpanAllColumns = 1 << 1,
4093 AllowDoubleClick = 1 << 2,
4094 Disabled = 1 << 3,
4095 AllowOverlap = 1 << 4,
4096}
4097
4098#[derive(Copy, Clone, Debug, PartialEq)]
4099pub enum ImGuiCol {
4100 Text,
4101 TextDisabled,
4102 WindowBg,
4103 ChildBg,
4104 PopupBg,
4105 Border,
4106 BorderShadow,
4107 FrameBg,
4108 FrameBgHovered,
4109 FrameBgActive,
4110 TitleBg,
4111 TitleBgActive,
4112 TitleBgCollapsed,
4113 MenuBarBg,
4114 ScrollbarBg,
4115 ScrollbarGrab,
4116 ScrollbarGrabHovered,
4117 ScrollbarGrabActive,
4118 CheckMark,
4119 SliderGrab,
4120 SliderGrabActive,
4121 Button,
4122 ButtonHovered,
4123 ButtonActive,
4124 Header,
4125 HeaderHovered,
4126 HeaderActive,
4127 Separator,
4128 SeparatorHovered,
4129 SeparatorActive,
4130 ResizeGrip,
4131 ResizeGripHovered,
4132 ResizeGripActive,
4133 TabHovered,
4134 Tab,
4135 TabSelected,
4136 TabSelectedOverline,
4137 TabDimmed,
4138 TabDimmedSelected,
4139 TabDimmedSelectedOverline,
4140 PlotLines,
4141 PlotLinesHovered,
4142 PlotHistogram,
4143 PlotHistogramHovered,
4144 TableHeaderBg,
4145 TableBorderStrong,
4146 TableBorderLight,
4147 TableRowBg,
4148 TableRowBgAlt,
4149 TextLink,
4150 TextSelectedBg,
4151 DragDropTarget,
4152 NavCursor,
4153 NavWindowingHighlight,
4154 NavWindowingDimBg,
4155 ModalWindowDimBg,
4156}
4157
4158#[bitflags]
4159#[repr(u32)]
4160#[derive(Copy, Clone, Debug, PartialEq)]
4161pub enum ImGuiColorEditFlag {
4162 NoAlpha = 1 << 1,
4163 NoPicker = 1 << 2,
4164 NoOptions = 1 << 3,
4165 NoSmallPreview = 1 << 4,
4166 NoInputs = 1 << 5,
4167 NoTooltip = 1 << 6,
4168 NoLabel = 1 << 7,
4169 NoSidePreview = 1 << 8,
4170 NoDragDrop = 1 << 9,
4171 NoBorder = 1 << 10,
4172 AlphaOpaque = 1 << 11,
4173 AlphaNoBg = 1 << 12,
4174 AlphaPreviewHalf = 1 << 13,
4175 AlphaBar = 1 << 16,
4176 HDR = 1 << 19,
4177 DisplayRGB = 1 << 20,
4178 DisplayHSV = 1 << 21,
4179 DisplayHex = 1 << 22,
4180 Uint8 = 1 << 23,
4181 Float = 1 << 24,
4182 PickerHueBar = 1 << 25,
4183 PickerHueWheel = 1 << 26,
4184 InputRGB = 1 << 27,
4185 InputHSV = 1 << 28,
4186}
4187
4188impl ImGuiColorEditFlag {
4189 pub const DEFAULT_OPTIONS: BitFlags<Self> =
4190 make_bitflags!(Self::{Uint8 | DisplayRGB | InputRGB | PickerHueBar});
4191}
4192
4193#[derive(Copy, Clone, Debug, PartialEq)]
4194pub enum ImGuiCond {
4195 Always = 1 << 0,
4196 Once = 1 << 1,
4197 FirstUseEver = 1 << 2,
4198 Appearing = 1 << 3,
4199}
4200
4201#[bitflags]
4202#[repr(u32)]
4203#[derive(Copy, Clone, Debug, PartialEq)]
4204pub enum ImGuiTableFlag {
4205 Resizable = 1 << 0,
4206 Reorderable = 1 << 1,
4207 Hideable = 1 << 2,
4208 Sortable = 1 << 3,
4209 NoSavedSettings = 1 << 4,
4210 ContextMenuInBody = 1 << 5,
4211 RowBg = 1 << 6,
4212 BordersInnerH = 1 << 7,
4213 BordersOuterH = 1 << 8,
4214 BordersInnerV = 1 << 9,
4215 BordersOuterV = 1 << 10,
4216 NoBordersInBody = 1 << 11,
4217 NoBordersInBodyUntilResize = 1 << 12,
4218 SizingFixedFit = 1 << 13,
4219 SizingFixedSame = 1 << 14,
4220 SizingStretchSame = 1 << 15,
4221 NoHostExtendX = 1 << 16,
4222 NoHostExtendY = 1 << 17,
4223 NoKeepColumnsVisible = 1 << 18,
4224 PreciseWidths = 1 << 19,
4225 NoClip = 1 << 20,
4226 PadOuterX = 1 << 21,
4227 NoPadOuterX = 1 << 22,
4228 NoPadInnerX = 1 << 23,
4229 ScrollX = 1 << 24,
4230 ScrollY = 1 << 25,
4231 SortMulti = 1 << 26,
4232 SortTristate = 1 << 27,
4233 HighlightHoveredColumn = 1 << 28,
4234}
4235
4236impl ImGuiTableFlag {
4237 pub const BORDERS_H: BitFlags<Self> = make_bitflags!(Self::{BordersInnerH | BordersOuterH});
4238 pub const BORDERS_V: BitFlags<Self> = make_bitflags!(Self::{BordersInnerV | BordersOuterV});
4239 pub const BORDERS_INNER: BitFlags<Self> = make_bitflags!(Self::{BordersInnerV | BordersInnerH});
4240 pub const BORDERS_OUTER: BitFlags<Self> = make_bitflags!(Self::{BordersOuterV | BordersOuterH});
4241 pub const BORDERS: BitFlags<Self> =
4242 make_bitflags!(Self::{BordersInnerV | BordersInnerH | BordersOuterV | BordersOuterH});
4243 pub const SIZING_STRETCH_PROP: BitFlags<Self> =
4244 make_bitflags!(Self::{SizingFixedFit | SizingFixedSame});
4245}
4246
4247#[bitflags]
4248#[repr(u32)]
4249#[derive(Copy, Clone, Debug, PartialEq)]
4250pub enum ImGuiTableColumnFlag {
4251 Disabled = 1 << 0,
4252 DefaultHide = 1 << 1,
4253 DefaultSort = 1 << 2,
4254 WidthStretch = 1 << 3,
4255 WidthFixed = 1 << 4,
4256 NoResize = 1 << 5,
4257 NoReorder = 1 << 6,
4258 NoHide = 1 << 7,
4259 NoClip = 1 << 8,
4260 NoSort = 1 << 9,
4261 NoSortAscending = 1 << 10,
4262 NoSortDescending = 1 << 11,
4263 NoHeaderLabel = 1 << 12,
4264 NoHeaderWidth = 1 << 13,
4265 PreferSortAscending = 1 << 14,
4266 PreferSortDescending = 1 << 15,
4267 IndentEnable = 1 << 16,
4268 IndentDisable = 1 << 17,
4269 AngledHeader = 1 << 18,
4270 IsEnabled = 1 << 24,
4271 IsVisible = 1 << 25,
4272 IsSorted = 1 << 26,
4273 IsHovered = 1 << 27,
4274}
4275
4276#[derive(Copy, Clone, Debug, PartialEq)]
4277pub enum ImGuiPopupButton {
4278 MouseButtonLeft = 0,
4279 MouseButtonRight = 1,
4280 MouseButtonMiddle = 2,
4281}
4282
4283#[bitflags]
4284#[repr(u32)]
4285#[derive(Copy, Clone, Debug, PartialEq)]
4286pub enum ImGuiPopupFlag {
4287 NoReopen = 1 << 5,
4288 NoOpenOverExistingPopup = 1 << 7,
4289 NoOpenOverItems = 1 << 8,
4290 AnyPopupId = 1 << 10,
4291 AnyPopupLevel = 1 << 11,
4292}
4293
4294impl ImGuiPopupFlag {
4295 pub const ANY_POPUP: BitFlags<Self> = make_bitflags!(Self::{AnyPopupId | AnyPopupLevel});
4296}
4297
4298#[derive(Copy, Clone, Debug, PartialEq)]
4299pub enum ImGuiStyleVar {
4300 Alpha = 0,
4301 DisabledAlpha = 1,
4302 WindowRounding = 3,
4303 WindowBorderSize = 4,
4304 ChildRounding = 7,
4305 ChildBorderSize = 8,
4306 PopupRounding = 9,
4307 PopupBorderSize = 10,
4308 FrameRounding = 12,
4309 FrameBorderSize = 13,
4310 IndentSpacing = 16,
4311 ScrollbarSize = 18,
4312 ScrollbarRounding = 19,
4313 GrabMinSize = 20,
4314 GrabRounding = 21,
4315 TabRounding = 22,
4316 TabBarBorderSize = 23,
4317 SeparatorTextBorderSize = 26,
4318}
4319
4320#[derive(Copy, Clone, Debug, PartialEq)]
4321pub enum ImGuiStyleVec2 {
4322 WindowPadding = 2,
4323 WindowMinSize = 5,
4324 WindowTitleAlign = 6,
4325 FramePadding = 11,
4326 ItemSpacing = 14,
4327 ItemInnerSpacing = 15,
4328 CellPadding = 17,
4329 ButtonTextAlign = 24,
4330 SelectableTextAlign = 25,
4331 SeparatorTextAlign = 27,
4332 SeparatorTextPadding = 28,
4333}
4334
4335#[bitflags]
4336#[repr(u32)]
4337#[derive(Copy, Clone, Debug, PartialEq)]
4338pub enum ImGuiItemFlag {
4339 NoTabStop = 1 << 0,
4340 NoNav = 1 << 1,
4341 NoNavDefaultFocus = 1 << 2,
4342 ButtonRepeat = 1 << 3,
4343 AutoClosePopups = 1 << 4,
4344 AllowDuplicateId = 1 << 5,
4345}
4346
4347#[bitflags]
4348#[repr(u8)]
4349#[derive(Copy, Clone, Debug, PartialEq)]
4350pub enum ImGuiTableRowFlag {
4351 Headers = 1 << 0,
4352}
4353
4354#[bitflags]
4355#[repr(u32)]
4356#[derive(Copy, Clone, Debug, PartialEq)]
4357pub enum ImGuiTabBarFlag {
4358 Reorderable = 1 << 0,
4359 AutoSelectNewTabs = 1 << 1,
4360 TabListPopupButton = 1 << 2,
4361 NoCloseWithMiddleMouseButton = 1 << 3,
4362 NoTabListScrollingButtons = 1 << 4,
4363 NoTooltip = 1 << 5,
4364 DrawSelectedOverline = 1 << 6,
4365 FittingPolicyShrink = 1 << 7,
4366 FittingPolicyScroll = 1 << 8,
4367}
4368
4369#[bitflags]
4370#[repr(u32)]
4371#[derive(Copy, Clone, Debug, PartialEq)]
4372pub enum ImGuiTabItemFlag {
4373 UnsavedDocument = 1 << 0,
4374 SetSelected = 1 << 1,
4375 NoCloseWithMiddleMouseButton = 1 << 2,
4376 NoPushId = 1 << 3,
4377 NoTooltip = 1 << 4,
4378 NoReorder = 1 << 5,
4379 Leading = 1 << 6,
4380 Trailing = 1 << 7,
4381 NoAssumedClosure = 1 << 8,
4382}
4383
4384thread_local! {
4385 static IMGUI_STACK: RefCell<CallStack> = RefCell::new(CallStack::new());
4386}
4387
4388impl ImGui {
4389 pub fn begin<C>(name: &str, inside: C)
4390 where
4391 C: FnOnce(),
4392 {
4393 ImGui::begin_opts(name, BitFlags::default(), inside);
4394 }
4395 pub fn begin_opts<C>(name: &str, windows_flags: BitFlags<ImGuiWindowFlag>, inside: C)
4396 where
4397 C: FnOnce(),
4398 {
4399 if ImGui::_begin_opts(name, windows_flags.bits() as i32) {
4400 inside();
4401 }
4402 ImGui::_end();
4403 }
4404 pub fn begin_ret<C>(name: &str, opened: bool, inside: C) -> bool
4405 where
4406 C: FnOnce(),
4407 {
4408 ImGui::begin_ret_opts(name, opened, BitFlags::default(), inside)
4409 }
4410 pub fn begin_ret_opts<C>(
4411 name: &str,
4412 opened: bool,
4413 windows_flags: BitFlags<ImGuiWindowFlag>,
4414 inside: C,
4415 ) -> bool
4416 where
4417 C: FnOnce(),
4418 {
4419 let mut changed = false;
4420 let mut result = false;
4421 IMGUI_STACK.with_borrow_mut(|stack| {
4422 stack.push_bool(opened);
4423 changed = ImGui::_begin_ret_opts(name, stack, windows_flags.bits() as i32);
4424 result = stack.pop_bool().unwrap();
4425 });
4426 if result {
4427 inside();
4428 }
4429 ImGui::_end();
4430 changed
4431 }
4432 pub fn begin_child<C>(str_id: &str, inside: C)
4433 where
4434 C: FnOnce(),
4435 {
4436 ImGui::begin_child_opts(
4437 str_id,
4438 &Vec2::zero(),
4439 BitFlags::default(),
4440 BitFlags::default(),
4441 inside,
4442 );
4443 }
4444 pub fn begin_child_opts<C>(
4445 str_id: &str,
4446 size: &crate::dora::Vec2,
4447 child_flags: BitFlags<ImGuiChildFlag>,
4448 window_flags: BitFlags<ImGuiWindowFlag>,
4449 inside: C,
4450 ) where
4451 C: FnOnce(),
4452 {
4453 if ImGui::_begin_child_opts(
4454 str_id,
4455 size,
4456 child_flags.bits() as i32,
4457 window_flags.bits() as i32,
4458 ) {
4459 inside();
4460 }
4461 ImGui::_end_child();
4462 }
4463 pub fn begin_child_with_id<C>(id: i32, inside: C)
4464 where
4465 C: FnOnce(),
4466 {
4467 ImGui::begin_child_with_id_opts(
4468 id,
4469 &Vec2::zero(),
4470 BitFlags::default(),
4471 BitFlags::default(),
4472 inside,
4473 );
4474 }
4475 pub fn begin_child_with_id_opts<C>(
4476 id: i32,
4477 size: &crate::dora::Vec2,
4478 child_flags: BitFlags<ImGuiChildFlag>,
4479 window_flags: BitFlags<ImGuiWindowFlag>,
4480 inside: C,
4481 ) where
4482 C: FnOnce(),
4483 {
4484 if ImGui::_begin_child_with_id_opts(
4485 id,
4486 size,
4487 child_flags.bits() as i32,
4488 window_flags.bits() as i32,
4489 ) {
4490 inside();
4491 }
4492 ImGui::_end_child();
4493 }
4494 pub fn collapsing_header_ret(label: &str, opened: bool) -> (bool, bool) {
4495 ImGui::collapsing_header_ret_opts(label, opened, BitFlags::default())
4496 }
4497 pub fn collapsing_header_ret_opts(
4498 label: &str,
4499 opened: bool,
4500 tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
4501 ) -> (bool, bool) {
4502 let mut changed = false;
4503 let mut result = false;
4504 IMGUI_STACK.with_borrow_mut(|stack| {
4505 stack.push_bool(opened);
4506 changed =
4507 ImGui::_collapsing_header_ret_opts(label, stack, tree_node_flags.bits() as i32);
4508 result = stack.pop_bool().unwrap();
4509 });
4510 (changed, result)
4511 }
4512 pub fn selectable_ret(label: &str, selected: bool) -> (bool, bool) {
4513 ImGui::selectable_ret_opts(label, selected, &Vec2::zero(), BitFlags::default())
4514 }
4515 pub fn selectable_ret_opts(
4516 label: &str,
4517 selected: bool,
4518 size: &crate::dora::Vec2,
4519 selectable_flags: BitFlags<ImGuiSelectableFlag>,
4520 ) -> (bool, bool) {
4521 let mut changed = false;
4522 let mut result = false;
4523 IMGUI_STACK.with_borrow_mut(|stack| {
4524 stack.push_bool(selected);
4525 changed =
4526 ImGui::_selectable_ret_opts(label, stack, size, selectable_flags.bits() as i32);
4527 result = stack.pop_bool().unwrap();
4528 });
4529 (changed, result)
4530 }
4531 pub fn combo_ret(label: &str, current_item: i32, items: &Vec<&str>) -> (bool, i32) {
4532 ImGui::combo_ret_opts(label, current_item, items, -1)
4533 }
4534 pub fn combo_ret_opts(
4535 label: &str,
4536 current_item: i32,
4537 items: &Vec<&str>,
4538 height_in_items: i32,
4539 ) -> (bool, i32) {
4540 let mut changed = false;
4541 let mut result = 0_i32;
4542 IMGUI_STACK.with_borrow_mut(|stack| {
4543 stack.push_i32(current_item);
4544 changed = ImGui::_combo_ret_opts(label, stack, items, height_in_items);
4545 result = stack.pop_i32().unwrap();
4546 });
4547 (changed, result)
4548 }
4549 pub fn drag_float_ret(
4550 label: &str,
4551 v: f32,
4552 v_speed: f32,
4553 v_min: f32,
4554 v_max: f32,
4555 ) -> (bool, f32) {
4556 ImGui::drag_float_ret_opts(label, v, v_speed, v_min, v_max, "%.2f", BitFlags::default())
4557 }
4558 pub fn drag_float_ret_opts(
4559 label: &str,
4560 v: f32,
4561 v_speed: f32,
4562 v_min: f32,
4563 v_max: f32,
4564 display_format: &str,
4565 slider_flags: BitFlags<ImGuiSliderFlag>,
4566 ) -> (bool, f32) {
4567 let mut changed = false;
4568 let mut result = 0_f32;
4569 IMGUI_STACK.with_borrow_mut(|stack| {
4570 stack.push_f32(v);
4571 changed = ImGui::_drag_float_ret_opts(
4572 label,
4573 stack,
4574 v_speed,
4575 v_min,
4576 v_max,
4577 display_format,
4578 slider_flags.bits() as i32,
4579 );
4580 result = stack.pop_f32().unwrap();
4581 });
4582 (changed, result)
4583 }
4584 pub fn drag_float2_ret(
4585 label: &str,
4586 v1: f32,
4587 v2: f32,
4588 v_speed: f32,
4589 v_min: f32,
4590 v_max: f32,
4591 ) -> (bool, f32, f32) {
4592 ImGui::drag_float2_ret_opts(
4593 label,
4594 v1,
4595 v2,
4596 v_speed,
4597 v_min,
4598 v_max,
4599 "%.2f",
4600 BitFlags::default(),
4601 )
4602 }
4603 pub fn drag_float2_ret_opts(
4604 label: &str,
4605 v1: f32,
4606 v2: f32,
4607 v_speed: f32,
4608 v_min: f32,
4609 v_max: f32,
4610 display_format: &str,
4611 slider_flags: BitFlags<ImGuiSliderFlag>,
4612 ) -> (bool, f32, f32) {
4613 let mut changed = false;
4614 let mut result1 = 0_f32;
4615 let mut result2 = 0_f32;
4616 IMGUI_STACK.with_borrow_mut(|stack| {
4617 stack.push_f32(v1);
4618 stack.push_f32(v2);
4619 changed = ImGui::_drag_float2_ret_opts(
4620 label,
4621 stack,
4622 v_speed,
4623 v_min,
4624 v_max,
4625 display_format,
4626 slider_flags.bits() as i32,
4627 );
4628 result1 = stack.pop_f32().unwrap();
4629 result2 = stack.pop_f32().unwrap();
4630 });
4631 (changed, result1, result2)
4632 }
4633 pub fn drag_int2_ret(
4634 label: &str,
4635 v1: i32,
4636 v2: i32,
4637 v_speed: f32,
4638 v_min: i32,
4639 v_max: i32,
4640 ) -> (bool, i32, i32) {
4641 ImGui::drag_int2_ret_opts(label, v1, v2, v_speed, v_min, v_max, "%d", BitFlags::default())
4642 }
4643 pub fn drag_int2_ret_opts(
4644 label: &str,
4645 v1: i32,
4646 v2: i32,
4647 v_speed: f32,
4648 v_min: i32,
4649 v_max: i32,
4650 display_format: &str,
4651 slider_flags: BitFlags<ImGuiSliderFlag>,
4652 ) -> (bool, i32, i32) {
4653 let mut changed = false;
4654 let mut result1 = 0_i32;
4655 let mut result2 = 0_i32;
4656 IMGUI_STACK.with_borrow_mut(|stack| {
4657 stack.push_i32(v1);
4658 stack.push_i32(v2);
4659 changed = ImGui::_drag_int2_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_i32().unwrap();
4669 result2 = stack.pop_i32().unwrap();
4670 });
4671 (changed, result1, result2)
4672 }
4673 pub fn input_float_ret(label: &str, v: f32) -> (bool, f32) {
4674 ImGui::input_float_ret_opts(label, v, 0.0, 0.0, "%.2f", BitFlags::default())
4675 }
4676 pub fn input_float_ret_opts(
4677 label: &str,
4678 v: f32,
4679 step: f32,
4680 step_fast: f32,
4681 display_format: &str,
4682 input_text_flags: BitFlags<ImGuiInputTextFlag>,
4683 ) -> (bool, f32) {
4684 let mut changed = false;
4685 let mut result = 0_f32;
4686 IMGUI_STACK.with_borrow_mut(|stack| {
4687 stack.push_f32(v);
4688 changed = ImGui::_input_float_ret_opts(
4689 label,
4690 stack,
4691 step,
4692 step_fast,
4693 display_format,
4694 input_text_flags.bits() as i32,
4695 );
4696 result = stack.pop_f32().unwrap();
4697 });
4698 (changed, result)
4699 }
4700 pub fn input_float2_ret(label: &str, v1: f32, v2: f32) -> (bool, f32, f32) {
4701 ImGui::input_float2_ret_opts(label, v1, v2, "%.2f", BitFlags::default())
4702 }
4703 pub fn input_float2_ret_opts(
4704 label: &str,
4705 v1: f32,
4706 v2: f32,
4707 display_format: &str,
4708 input_text_flags: BitFlags<ImGuiInputTextFlag>,
4709 ) -> (bool, f32, f32) {
4710 let mut changed = false;
4711 let mut result1 = 0_f32;
4712 let mut result2 = 0_f32;
4713 IMGUI_STACK.with_borrow_mut(|stack| {
4714 stack.push_f32(v1);
4715 stack.push_f32(v2);
4716 changed = ImGui::_input_float2_ret_opts(
4717 label,
4718 stack,
4719 display_format,
4720 input_text_flags.bits() as i32,
4721 );
4722 result1 = stack.pop_f32().unwrap();
4723 result2 = stack.pop_f32().unwrap();
4724 });
4725 (changed, result1, result2)
4726 }
4727 pub fn input_int_ret(label: &str, v: i32) -> (bool, i32) {
4728 ImGui::input_int_ret_opts(label, v, 1, 100, BitFlags::default())
4729 }
4730 pub fn input_int_ret_opts(
4731 label: &str,
4732 v: i32,
4733 step: i32,
4734 step_fast: i32,
4735 input_text_flags: BitFlags<ImGuiInputTextFlag>,
4736 ) -> (bool, i32) {
4737 let mut changed = false;
4738 let mut result = 0_i32;
4739 IMGUI_STACK.with_borrow_mut(|stack| {
4740 stack.push_i32(v);
4741 changed = ImGui::_input_int_ret_opts(
4742 label,
4743 stack,
4744 step,
4745 step_fast,
4746 input_text_flags.bits() as i32,
4747 );
4748 result = stack.pop_i32().unwrap();
4749 });
4750 (changed, result)
4751 }
4752 pub fn input_int2_ret(label: &str, v1: i32, v2: i32) -> (bool, i32, i32) {
4753 ImGui::input_int2_ret_opts(label, v1, v2, BitFlags::default())
4754 }
4755 pub fn input_int2_ret_opts(
4756 label: &str,
4757 v1: i32,
4758 v2: i32,
4759 input_text_flags: BitFlags<ImGuiInputTextFlag>,
4760 ) -> (bool, i32, i32) {
4761 let mut changed = false;
4762 let mut result1 = 0_i32;
4763 let mut result2 = 0_i32;
4764 IMGUI_STACK.with_borrow_mut(|stack| {
4765 stack.push_i32(v1);
4766 stack.push_i32(v2);
4767 changed = ImGui::_input_int2_ret_opts(label, stack, input_text_flags.bits() as i32);
4768 result1 = stack.pop_i32().unwrap();
4769 result2 = stack.pop_i32().unwrap();
4770 });
4771 (changed, result1, result2)
4772 }
4773 pub fn slider_float_ret(label: &str, v: f32, v_min: f32, v_max: f32) -> (bool, f32) {
4774 ImGui::slider_float_ret_opts(label, v, v_min, v_max, "%.2f", BitFlags::default())
4775 }
4776 pub fn slider_float_ret_opts(
4777 label: &str,
4778 v: f32,
4779 v_min: f32,
4780 v_max: f32,
4781 display_format: &str,
4782 slider_flags: BitFlags<ImGuiSliderFlag>,
4783 ) -> (bool, f32) {
4784 let mut changed = false;
4785 let mut result = 0_f32;
4786 IMGUI_STACK.with_borrow_mut(|stack| {
4787 stack.push_f32(v);
4788 changed = ImGui::_slider_float_ret_opts(
4789 label,
4790 stack,
4791 v_min,
4792 v_max,
4793 display_format,
4794 slider_flags.bits() as i32,
4795 );
4796 result = stack.pop_f32().unwrap();
4797 });
4798 (changed, result)
4799 }
4800 pub fn slider_float2_ret(
4801 label: &str,
4802 v1: f32,
4803 v2: f32,
4804 v_min: f32,
4805 v_max: f32,
4806 ) -> (bool, f32, f32) {
4807 ImGui::slider_float2_ret_opts(label, v1, v2, v_min, v_max, "%.2f", BitFlags::default())
4808 }
4809 pub fn slider_float2_ret_opts(
4810 label: &str,
4811 v1: f32,
4812 v2: f32,
4813 v_min: f32,
4814 v_max: f32,
4815 display_format: &str,
4816 slider_flags: BitFlags<ImGuiSliderFlag>,
4817 ) -> (bool, f32, f32) {
4818 let mut changed = false;
4819 let mut result1 = 0_f32;
4820 let mut result2 = 0_f32;
4821 IMGUI_STACK.with_borrow_mut(|stack| {
4822 stack.push_f32(v1);
4823 stack.push_f32(v2);
4824 changed = ImGui::_slider_float2_ret_opts(
4825 label,
4826 stack,
4827 v_min,
4828 v_max,
4829 display_format,
4830 slider_flags.bits() as i32,
4831 );
4832 result1 = stack.pop_f32().unwrap();
4833 result2 = stack.pop_f32().unwrap();
4834 });
4835 (changed, result1, result2)
4836 }
4837 pub fn drag_float_range2_ret(
4838 label: &str,
4839 v_current_min: f32,
4840 v_current_max: f32,
4841 v_speed: f32,
4842 v_min: f32,
4843 v_max: f32,
4844 ) -> (bool, f32, f32) {
4845 ImGui::drag_float_range2_ret_opts(
4846 label,
4847 v_current_min,
4848 v_current_max,
4849 v_speed,
4850 v_min,
4851 v_max,
4852 "%.2f",
4853 "%.2f",
4854 BitFlags::default(),
4855 )
4856 }
4857 pub fn drag_float_range2_ret_opts(
4858 label: &str,
4859 v_current_min: f32,
4860 v_current_max: f32,
4861 v_speed: f32,
4862 v_min: f32,
4863 v_max: f32,
4864 format: &str,
4865 format_max: &str,
4866 slider_flags: BitFlags<ImGuiSliderFlag>,
4867 ) -> (bool, f32, f32) {
4868 let mut changed = false;
4869 let mut result1 = 0_f32;
4870 let mut result2 = 0_f32;
4871 IMGUI_STACK.with_borrow_mut(|stack| {
4872 stack.push_f32(v_current_min);
4873 stack.push_f32(v_current_max);
4874 changed = ImGui::_drag_float_range2_ret_opts(
4875 label,
4876 stack,
4877 v_speed,
4878 v_min,
4879 v_max,
4880 format,
4881 format_max,
4882 slider_flags.bits() as i32,
4883 );
4884 result1 = stack.pop_f32().unwrap();
4885 result2 = stack.pop_f32().unwrap();
4886 });
4887 (changed, result1, result2)
4888 }
4889 pub fn drag_int_ret(
4890 label: &str,
4891 value: i32,
4892 v_speed: f32,
4893 v_min: i32,
4894 v_max: i32,
4895 ) -> (bool, i32) {
4896 ImGui::drag_int_ret_opts(label, value, v_speed, v_min, v_max, "%d", BitFlags::default())
4897 }
4898 pub fn drag_int_ret_opts(
4899 label: &str,
4900 value: i32,
4901 v_speed: f32,
4902 v_min: i32,
4903 v_max: i32,
4904 display_format: &str,
4905 slider_flags: BitFlags<ImGuiSliderFlag>,
4906 ) -> (bool, i32) {
4907 let mut changed = false;
4908 let mut result = 0_i32;
4909 IMGUI_STACK.with_borrow_mut(|stack| {
4910 stack.push_i32(value);
4911 changed = ImGui::_drag_int_ret_opts(
4912 label,
4913 stack,
4914 v_speed,
4915 v_min,
4916 v_max,
4917 display_format,
4918 slider_flags.bits() as i32,
4919 );
4920 result = stack.pop_i32().unwrap();
4921 });
4922 (changed, result)
4923 }
4924 pub fn drag_int_range2_ret(
4925 label: &str,
4926 v_current_min: i32,
4927 v_current_max: i32,
4928 v_speed: f32,
4929 v_min: i32,
4930 v_max: i32,
4931 ) -> (bool, i32, i32) {
4932 ImGui::drag_int_range2_ret_opts(
4933 label,
4934 v_current_min,
4935 v_current_max,
4936 v_speed,
4937 v_min,
4938 v_max,
4939 "%d",
4940 "%d",
4941 BitFlags::default(),
4942 )
4943 }
4944 pub fn drag_int_range2_ret_opts(
4945 label: &str,
4946 v_current_min: i32,
4947 v_current_max: i32,
4948 v_speed: f32,
4949 v_min: i32,
4950 v_max: i32,
4951 format: &str,
4952 format_max: &str,
4953 slider_flags: BitFlags<ImGuiSliderFlag>,
4954 ) -> (bool, i32, i32) {
4955 let mut changed = false;
4956 let mut result1 = 0_i32;
4957 let mut result2 = 0_i32;
4958 IMGUI_STACK.with_borrow_mut(|stack| {
4959 stack.push_i32(v_current_min);
4960 stack.push_i32(v_current_max);
4961 changed = ImGui::_drag_int_range2_ret_opts(
4962 label,
4963 stack,
4964 v_speed,
4965 v_min,
4966 v_max,
4967 format,
4968 format_max,
4969 slider_flags.bits() as i32,
4970 );
4971 result1 = stack.pop_i32().unwrap();
4972 result2 = stack.pop_i32().unwrap();
4973 });
4974 (changed, result1, result2)
4975 }
4976 pub fn slider_int_ret(label: &str, value: i32, v_min: i32, v_max: i32) -> (bool, i32) {
4977 ImGui::slider_int_ret_opts(label, value, v_min, v_max, "%d", BitFlags::default())
4978 }
4979 pub fn slider_int_ret_opts(
4980 label: &str,
4981 value: i32,
4982 v_min: i32,
4983 v_max: i32,
4984 format: &str,
4985 slider_flags: BitFlags<ImGuiSliderFlag>,
4986 ) -> (bool, i32) {
4987 let mut changed = false;
4988 let mut result = 0_i32;
4989 IMGUI_STACK.with_borrow_mut(|stack| {
4990 stack.push_i32(value);
4991 changed = ImGui::_slider_int_ret_opts(
4992 label,
4993 stack,
4994 v_min,
4995 v_max,
4996 format,
4997 slider_flags.bits() as i32,
4998 );
4999 result = stack.pop_i32().unwrap();
5000 });
5001 (changed, result)
5002 }
5003 pub fn slider_int2_ret(
5004 label: &str,
5005 v1: i32,
5006 v2: i32,
5007 v_min: i32,
5008 v_max: i32,
5009 ) -> (bool, i32, i32) {
5010 ImGui::slider_int2_ret_opts(label, v1, v2, v_min, v_max, "%d", BitFlags::default())
5011 }
5012 pub fn slider_int2_ret_opts(
5013 label: &str,
5014 v1: i32,
5015 v2: i32,
5016 v_min: i32,
5017 v_max: i32,
5018 display_format: &str,
5019 slider_flags: BitFlags<ImGuiSliderFlag>,
5020 ) -> (bool, i32, i32) {
5021 let mut changed = false;
5022 let mut result1 = 0_i32;
5023 let mut result2 = 0_i32;
5024 IMGUI_STACK.with_borrow_mut(|stack| {
5025 stack.push_i32(v1);
5026 stack.push_i32(v2);
5027 changed = ImGui::_slider_int2_ret_opts(
5028 label,
5029 stack,
5030 v_min,
5031 v_max,
5032 display_format,
5033 slider_flags.bits() as i32,
5034 );
5035 result1 = stack.pop_i32().unwrap();
5036 result2 = stack.pop_i32().unwrap();
5037 });
5038 (changed, result1, result2)
5039 }
5040 pub fn v_slider_float_ret(
5041 label: &str,
5042 size: &crate::dora::Vec2,
5043 v: f32,
5044 v_min: f32,
5045 v_max: f32,
5046 ) -> (bool, f32) {
5047 ImGui::v_slider_float_ret_opts(label, size, v, v_min, v_max, "%.2f", BitFlags::default())
5048 }
5049 pub fn v_slider_float_ret_opts(
5050 label: &str,
5051 size: &crate::dora::Vec2,
5052 v: f32,
5053 v_min: f32,
5054 v_max: f32,
5055 format: &str,
5056 slider_flags: BitFlags<ImGuiSliderFlag>,
5057 ) -> (bool, f32) {
5058 let mut changed = false;
5059 let mut result = 0_f32;
5060 IMGUI_STACK.with_borrow_mut(|stack| {
5061 stack.push_f32(v);
5062 changed = ImGui::_v_slider_float_ret_opts(
5063 label,
5064 size,
5065 stack,
5066 v_min,
5067 v_max,
5068 format,
5069 slider_flags.bits() as i32,
5070 );
5071 result = stack.pop_f32().unwrap();
5072 });
5073 (changed, result)
5074 }
5075 pub fn v_slider_int_ret(
5076 label: &str,
5077 size: &crate::dora::Vec2,
5078 v: i32,
5079 v_min: i32,
5080 v_max: i32,
5081 ) -> (bool, i32) {
5082 ImGui::v_slider_int_ret_opts(label, size, v, v_min, v_max, "%d", BitFlags::default())
5083 }
5084 pub fn v_slider_int_ret_opts(
5085 label: &str,
5086 size: &crate::dora::Vec2,
5087 v: i32,
5088 v_min: i32,
5089 v_max: i32,
5090 format: &str,
5091 slider_flags: BitFlags<ImGuiSliderFlag>,
5092 ) -> (bool, i32) {
5093 let mut changed = false;
5094 let mut result = 0_i32;
5095 IMGUI_STACK.with_borrow_mut(|stack| {
5096 stack.push_i32(v);
5097 changed = ImGui::_v_slider_int_ret_opts(
5098 label,
5099 size,
5100 stack,
5101 v_min,
5102 v_max,
5103 format,
5104 slider_flags.bits() as i32,
5105 );
5106 result = stack.pop_i32().unwrap();
5107 });
5108 (changed, result)
5109 }
5110 pub fn color_edit3_ret(label: &str, color3: &Color3) -> (bool, Color3) {
5111 ImGui::color_edit3_ret_opts(label, color3, BitFlags::default())
5112 }
5113 pub fn color_edit3_ret_opts(
5114 label: &str,
5115 color3: &Color3,
5116 color_edit_flags: BitFlags<ImGuiColorEditFlag>,
5117 ) -> (bool, Color3) {
5118 let mut changed = false;
5119 let mut result = 0_i32;
5120 IMGUI_STACK.with_borrow_mut(|stack| {
5121 stack.push_i32(color3.to_rgb() as i32);
5122 changed = ImGui::_color_edit3_ret_opts(label, stack, color_edit_flags.bits() as i32);
5123 result = stack.pop_i32().unwrap();
5124 });
5125 (changed, Color3::new(result as u32))
5126 }
5127 pub fn color_edit4_ret(label: &str, color: &Color) -> (bool, Color) {
5128 ImGui::color_edit4_ret_opts(label, color, BitFlags::default())
5129 }
5130 pub fn color_edit4_ret_opts(
5131 label: &str,
5132 color: &Color,
5133 color_edit_flags: BitFlags<ImGuiColorEditFlag>,
5134 ) -> (bool, Color) {
5135 let mut changed = false;
5136 let mut result = 0_i32;
5137 IMGUI_STACK.with_borrow_mut(|stack| {
5138 stack.push_i32(color.to_argb() as i32);
5139 changed = ImGui::_color_edit4_ret_opts(label, stack, color_edit_flags.bits() as i32);
5140 result = stack.pop_i32().unwrap();
5141 });
5142 (changed, Color::new(result as u32))
5143 }
5144 pub fn checkbox_ret(label: &str, checked: bool) -> (bool, bool) {
5145 let mut changed = false;
5146 let mut result = false;
5147 IMGUI_STACK.with_borrow_mut(|stack| {
5148 stack.push_bool(checked);
5149 changed = ImGui::_checkbox_ret(label, stack);
5150 result = stack.pop_bool().unwrap();
5151 });
5152 (changed, result)
5153 }
5154 pub fn radio_button_ret(label: &str, value: i32, v_button: i32) -> (bool, i32) {
5155 let mut changed = false;
5156 let mut result = 0_i32;
5157 IMGUI_STACK.with_borrow_mut(|stack| {
5158 stack.push_i32(value);
5159 changed = ImGui::_radio_button_ret(label, stack, v_button);
5160 result = stack.pop_i32().unwrap();
5161 });
5162 (changed, result)
5163 }
5164 pub fn list_box_ret(label: &str, current_item: i32, items: &Vec<&str>) -> (bool, i32) {
5165 ImGui::list_box_ret_opts(label, current_item, items, -1)
5166 }
5167 pub fn list_box_ret_opts(
5168 label: &str,
5169 current_item: i32,
5170 items: &Vec<&str>,
5171 height_in_items: i32,
5172 ) -> (bool, i32) {
5173 let mut changed = false;
5174 let mut result = 0_i32;
5175 IMGUI_STACK.with_borrow_mut(|stack| {
5176 stack.push_i32(current_item);
5177 changed = ImGui::_list_box_ret_opts(label, stack, items, height_in_items);
5178 result = stack.pop_i32().unwrap();
5179 });
5180 (changed, result)
5181 }
5182 pub fn set_next_window_pos_center() {
5183 ImGui::set_next_window_pos_center_opts(ImGuiCond::Always);
5184 }
5185 pub fn set_next_window_pos_center_opts(set_cond: ImGuiCond) {
5186 ImGui::_set_next_window_pos_center_opts(set_cond as i32);
5187 }
5188 pub fn set_next_window_size(size: &crate::dora::Vec2) {
5189 ImGui::set_next_window_size_opts(size, ImGuiCond::Always);
5190 }
5191 pub fn set_next_window_size_opts(size: &crate::dora::Vec2, set_cond: ImGuiCond) {
5192 ImGui::_set_next_window_size_opts(size, set_cond as i32);
5193 }
5194 pub fn set_next_window_collapsed(collapsed: bool) {
5195 ImGui::set_next_window_collapsed_opts(collapsed, ImGuiCond::Always);
5196 }
5197 pub fn set_next_window_collapsed_opts(collapsed: bool, set_cond: ImGuiCond) {
5198 ImGui::_set_next_window_collapsed_opts(collapsed, set_cond as i32);
5199 }
5200 pub fn set_window_pos(name: &str, pos: &crate::dora::Vec2) {
5201 ImGui::set_window_pos_opts(name, pos, ImGuiCond::Always);
5202 }
5203 pub fn set_window_pos_opts(name: &str, pos: &crate::dora::Vec2, set_cond: ImGuiCond) {
5204 ImGui::_set_window_pos_opts(name, pos, set_cond as i32);
5205 }
5206 pub fn set_window_size(name: &str, size: &crate::dora::Vec2) {
5207 ImGui::set_window_size_opts(name, size, ImGuiCond::Always);
5208 }
5209 pub fn set_window_size_opts(name: &str, size: &crate::dora::Vec2, set_cond: ImGuiCond) {
5210 ImGui::_set_window_size_opts(name, size, set_cond as i32);
5211 }
5212 pub fn set_window_collapsed(name: &str, collapsed: bool) {
5213 ImGui::set_window_collapsed_opts(name, collapsed, ImGuiCond::Always);
5214 }
5215 pub fn set_window_collapsed_opts(name: &str, collapsed: bool, set_cond: ImGuiCond) {
5216 ImGui::_set_window_collapsed_opts(name, collapsed, set_cond as i32);
5217 }
5218 pub fn set_color_edit_options(color_edit_flags: BitFlags<ImGuiColorEditFlag>) {
5219 ImGui::_set_color_edit_options(color_edit_flags.bits() as i32);
5220 }
5221 pub fn input_text(label: &str, buffer: &crate::dora::Buffer) -> bool {
5222 ImGui::input_text_opts(label, buffer, BitFlags::default())
5223 }
5224 pub fn input_text_opts(
5225 label: &str,
5226 buffer: &crate::dora::Buffer,
5227 input_text_flags: BitFlags<ImGuiInputTextFlag>,
5228 ) -> bool {
5229 ImGui::_input_text_opts(label, buffer, input_text_flags.bits() as i32)
5230 }
5231 pub fn input_text_multiline(
5232 label: &str,
5233 buffer: &crate::dora::Buffer,
5234 size: &crate::dora::Vec2,
5235 ) -> bool {
5236 ImGui::input_text_multiline_opts(label, buffer, size, BitFlags::default())
5237 }
5238 pub fn input_text_multiline_opts(
5239 label: &str,
5240 buffer: &crate::dora::Buffer,
5241 size: &crate::dora::Vec2,
5242 input_text_flags: BitFlags<ImGuiInputTextFlag>,
5243 ) -> bool {
5244 ImGui::_input_text_multiline_opts(label, buffer, size, input_text_flags.bits() as i32)
5245 }
5246 pub fn tree_push<C>(str_id: &str, inside: C)
5247 where
5248 C: FnOnce(),
5249 {
5250 ImGui::_tree_push(str_id);
5251 inside();
5252 ImGui::_tree_pop();
5253 }
5254 pub fn tree_node<C>(str_id: &str, text: &str, inside: C)
5255 where
5256 C: FnOnce(),
5257 {
5258 if ImGui::_tree_node(str_id, text) {
5259 inside();
5260 ImGui::_tree_pop();
5261 }
5262 }
5263 pub fn tree_node_ex<C>(label: &str, inside: C)
5264 where
5265 C: FnOnce(),
5266 {
5267 ImGui::tree_node_ex_opts(label, BitFlags::default(), inside)
5268 }
5269 pub fn tree_node_ex_opts<C>(
5270 label: &str,
5271 tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
5272 inside: C,
5273 ) where
5274 C: FnOnce(),
5275 {
5276 if ImGui::_tree_node_ex_opts(label, tree_node_flags.bits() as i32) {
5277 inside();
5278 ImGui::_tree_pop();
5279 }
5280 }
5281 pub fn tree_node_ex_with_id<C>(str_id: &str, text: &str, inside: C)
5282 where
5283 C: FnOnce(),
5284 {
5285 ImGui::tree_node_ex_with_id_opts(str_id, text, BitFlags::default(), inside);
5286 }
5287 pub fn tree_node_ex_with_id_opts<C>(
5288 str_id: &str,
5289 text: &str,
5290 tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
5291 inside: C,
5292 ) where
5293 C: FnOnce(),
5294 {
5295 if ImGui::_tree_node_ex_with_id_opts(str_id, text, tree_node_flags.bits() as i32) {
5296 inside();
5297 ImGui::_tree_pop();
5298 }
5299 }
5300 pub fn set_next_item_open(is_open: bool) {
5301 ImGui::set_next_item_open_opts(is_open, ImGuiCond::Always);
5302 }
5303 pub fn set_next_item_open_opts(is_open: bool, set_cond: ImGuiCond) {
5304 ImGui::_set_next_item_open_opts(is_open, set_cond as i32);
5305 }
5306 pub fn collapsing_header(label: &str) -> bool {
5307 ImGui::collapsing_header_opts(label, BitFlags::default())
5308 }
5309 pub fn collapsing_header_opts(
5310 label: &str,
5311 tree_node_flags: BitFlags<ImGuiTreeNodeFlag>,
5312 ) -> bool {
5313 ImGui::_collapsing_header_opts(label, tree_node_flags.bits() as i32)
5314 }
5315 pub fn selectable(label: &str) -> bool {
5316 ImGui::selectable_opts(label, BitFlags::default())
5317 }
5318 pub fn selectable_opts(label: &str, selectable_flags: BitFlags<ImGuiSelectableFlag>) -> bool {
5319 ImGui::_selectable_opts(label, selectable_flags.bits() as i32)
5320 }
5321 pub fn begin_popup<C>(str_id: &str, inside: C)
5322 where
5323 C: FnOnce(),
5324 {
5325 if ImGui::_begin_popup(str_id) {
5326 inside();
5327 ImGui::_end_popup();
5328 }
5329 }
5330 pub fn begin_popup_modal<C>(name: &str, inside: C)
5331 where
5332 C: FnOnce(),
5333 {
5334 ImGui::begin_popup_modal_opts(name, BitFlags::default(), inside);
5335 }
5336 pub fn begin_popup_modal_opts<C>(
5337 name: &str,
5338 windows_flags: BitFlags<ImGuiWindowFlag>,
5339 inside: C,
5340 ) where
5341 C: FnOnce(),
5342 {
5343 if ImGui::_begin_popup_modal_opts(name, windows_flags.bits() as i32) {
5344 inside();
5345 ImGui::_end_popup();
5346 }
5347 }
5348 pub fn begin_popup_modal_ret<C>(
5349 name: &str,
5350 opened: bool,
5351 inside: C,
5352 ) -> (bool, bool)
5353 where
5354 C: FnOnce(),
5355 {
5356 ImGui::begin_popup_modal_ret_opts(name, opened, BitFlags::default(), inside)
5357 }
5358 pub fn begin_popup_modal_ret_opts<C>(
5359 name: &str,
5360 opened: bool,
5361 windows_flags: BitFlags<ImGuiWindowFlag>,
5362 inside: C,
5363 ) -> (bool, bool)
5364 where
5365 C: FnOnce(),
5366 {
5367 let mut changed = false;
5368 let mut result = false;
5369 IMGUI_STACK.with_borrow_mut(|stack| {
5370 stack.push_bool(opened);
5371 changed = ImGui::_begin_popup_modal_ret_opts(name, stack, windows_flags.bits() as i32);
5372 result = stack.pop_bool().unwrap();
5373 });
5374 if changed {
5375 inside();
5376 ImGui::_end_popup();
5377 }
5378 (changed, result)
5379 }
5380 pub fn begin_popup_context_item<C>(name: &str, inside: C)
5381 where
5382 C: FnOnce(),
5383 {
5384 ImGui::begin_popup_context_item_opts(
5385 name,
5386 ImGuiPopupButton::MouseButtonRight,
5387 BitFlags::default(),
5388 inside,
5389 );
5390 }
5391 pub fn begin_popup_context_item_opts<C>(
5392 name: &str,
5393 button: ImGuiPopupButton,
5394 popup_flags: BitFlags<ImGuiPopupFlag>,
5395 inside: C,
5396 ) where
5397 C: FnOnce(),
5398 {
5399 if ImGui::_begin_popup_context_item_opts(name, (button as u32 | popup_flags.bits()) as i32)
5400 {
5401 inside();
5402 ImGui::_end_popup();
5403 }
5404 }
5405 pub fn begin_popup_context_window<C>(name: &str, inside: C)
5406 where
5407 C: FnOnce(),
5408 {
5409 ImGui::begin_popup_context_window_opts(
5410 name,
5411 ImGuiPopupButton::MouseButtonRight,
5412 BitFlags::default(),
5413 inside,
5414 );
5415 }
5416 pub fn begin_popup_context_window_opts<C>(
5417 name: &str,
5418 button: ImGuiPopupButton,
5419 popup_flags: BitFlags<ImGuiPopupFlag>,
5420 inside: C,
5421 ) where
5422 C: FnOnce(),
5423 {
5424 if ImGui::_begin_popup_context_window_opts(
5425 name,
5426 (button as u32 | popup_flags.bits()) as i32,
5427 ) {
5428 inside();
5429 ImGui::_end_popup();
5430 }
5431 }
5432 pub fn begin_popup_context_void<C>(name: &str, inside: C)
5433 where
5434 C: FnOnce(),
5435 {
5436 ImGui::begin_popup_context_void_opts(
5437 name,
5438 ImGuiPopupButton::MouseButtonRight,
5439 BitFlags::default(),
5440 inside,
5441 );
5442 }
5443 pub fn begin_popup_context_void_opts<C>(
5444 name: &str,
5445 button: ImGuiPopupButton,
5446 popup_flags: BitFlags<ImGuiPopupFlag>,
5447 inside: C,
5448 ) where
5449 C: FnOnce(),
5450 {
5451 if ImGui::_begin_popup_context_void_opts(name, (button as u32 | popup_flags.bits()) as i32)
5452 {
5453 inside();
5454 ImGui::_end_popup();
5455 }
5456 }
5457 pub fn begin_table<C>(str_id: &str, column: i32, inside: C)
5458 where
5459 C: FnOnce(),
5460 {
5461 ImGui::begin_table_opts(str_id, column, &Vec2::zero(), -1.0, BitFlags::default(), inside);
5462 }
5463 pub fn begin_table_opts<C>(
5464 str_id: &str,
5465 column: i32,
5466 outer_size: &crate::dora::Vec2,
5467 inner_width: f32,
5468 table_flags: BitFlags<ImGuiTableFlag>,
5469 inside: C,
5470 ) where
5471 C: FnOnce(),
5472 {
5473 if ImGui::_begin_table_opts(
5474 str_id,
5475 column,
5476 outer_size,
5477 inner_width,
5478 table_flags.bits() as i32,
5479 ) {
5480 inside();
5481 ImGui::_end_table();
5482 }
5483 }
5484 pub fn table_setup_column(label: &str, init_width_or_weight: f32) {
5485 ImGui::table_setup_column_opts(label, init_width_or_weight, 0, BitFlags::default())
5486 }
5487 pub fn table_setup_column_opts(
5488 label: &str,
5489 init_width_or_weight: f32,
5490 user_id: i32,
5491 table_column_flags: BitFlags<ImGuiTableColumnFlag>,
5492 ) {
5493 ImGui::_table_setup_column_opts(
5494 label,
5495 init_width_or_weight,
5496 user_id,
5497 table_column_flags.bits() as i32,
5498 );
5499 }
5500 pub fn set_next_window_pos(pos: &crate::dora::Vec2) {
5501 ImGui::set_next_window_pos_opts(pos, ImGuiCond::Always, &Vec2::zero());
5502 }
5503 pub fn set_next_window_pos_opts(
5504 pos: &crate::dora::Vec2,
5505 set_cond: ImGuiCond,
5506 pivot: &crate::dora::Vec2,
5507 ) {
5508 ImGui::_set_next_window_pos_opts(pos, set_cond as i32, pivot);
5509 }
5510 pub fn push_style_color<C>(col: ImGuiCol, color: &crate::dora::Color, inside: C)
5511 where
5512 C: FnOnce(),
5513 {
5514 ImGui::_push_style_color(col as i32, color);
5515 inside();
5516 ImGui::_pop_style_color(1);
5517 }
5518 pub fn push_style_float<C>(style: ImGuiStyleVar, val: f32, inside: C)
5519 where
5520 C: FnOnce(),
5521 {
5522 ImGui::_push_style_float(style as i32, val);
5523 inside();
5524 ImGui::_pop_style_var(1);
5525 }
5526 pub fn push_style_vec2<C>(style: ImGuiStyleVec2, val: &crate::dora::Vec2, inside: C)
5527 where
5528 C: FnOnce(),
5529 {
5530 ImGui::_push_style_vec2(style as i32, val);
5531 inside();
5532 ImGui::_pop_style_var(1);
5533 }
5534 pub fn color_button(desc_id: &str, col: &crate::dora::Color) -> bool {
5535 ImGui::color_button_opts(desc_id, col, BitFlags::default(), &Vec2::zero())
5536 }
5537 pub fn color_button_opts(
5538 desc_id: &str,
5539 col: &crate::dora::Color,
5540 color_edit_flags: BitFlags<ImGuiColorEditFlag>,
5541 size: &crate::dora::Vec2,
5542 ) -> bool {
5543 ImGui::_color_button_opts(desc_id, col, color_edit_flags.bits() as i32, size)
5544 }
5545 pub fn slider_angle_ret(
5546 label: &str,
5547 v: f32,
5548 v_degrees_min: f32,
5549 v_degrees_max: f32,
5550 ) -> (bool, f32) {
5551 let mut changed = false;
5552 let mut result = 0_f32;
5553 IMGUI_STACK.with_borrow_mut(|stack| {
5554 stack.push_f32(v);
5555 changed = ImGui::_slider_angle_ret(label, stack, v_degrees_min, v_degrees_max);
5556 result = stack.pop_f32().unwrap();
5557 });
5558 (changed, result)
5559 }
5560 pub fn image_button(str_id: &str, clip_str: &str, size: &crate::dora::Vec2) -> bool {
5561 ImGui::image_button_opts(str_id, clip_str, size, &Color::TRANSPARENT, &Color::WHITE)
5562 }
5563 pub fn table_next_row() {
5564 ImGui::table_next_row_opts(0.0, BitFlags::default());
5565 }
5566 pub fn table_next_row_opts(min_row_height: f32, table_row_flags: BitFlags<ImGuiTableRowFlag>) {
5567 ImGui::_table_next_row_opts(min_row_height, table_row_flags.bits() as i32);
5568 }
5569 pub fn begin_list_box<C>(label: &str, size: &crate::dora::Vec2, inside: C)
5570 where
5571 C: FnOnce(),
5572 {
5573 if ImGui::_begin_list_box(label, size) {
5574 inside();
5575 ImGui::_end_list_box();
5576 }
5577 }
5578 pub fn begin_group<C>(inside: C)
5579 where
5580 C: FnOnce(),
5581 {
5582 ImGui::_begin_group();
5583 inside();
5584 ImGui::_end_group();
5585 }
5586 pub fn begin_disabled<C>(inside: C)
5587 where
5588 C: FnOnce(),
5589 {
5590 ImGui::_begin_disabled();
5591 inside();
5592 ImGui::_end_disabled();
5593 }
5594 pub fn begin_tooltip<C>(inside: C)
5595 where
5596 C: FnOnce(),
5597 {
5598 if ImGui::_begin_tooltip() {
5599 inside();
5600 ImGui::_end_tooltip();
5601 }
5602 }
5603 pub fn begin_main_menu_bar<C>(inside: C)
5604 where
5605 C: FnOnce(),
5606 {
5607 if ImGui::_begin_main_menu_bar() {
5608 inside();
5609 ImGui::_end_main_menu_bar();
5610 }
5611 }
5612 pub fn begin_menu_bar<C>(inside: C)
5613 where
5614 C: FnOnce(),
5615 {
5616 if ImGui::_begin_menu_bar() {
5617 inside();
5618 ImGui::_end_menu_bar();
5619 }
5620 }
5621 pub fn begin_menu<C>(label: &str, enabled: bool, inside: C)
5622 where
5623 C: FnOnce(),
5624 {
5625 if ImGui::_begin_menu(label, enabled) {
5626 inside();
5627 ImGui::_end_menu();
5628 }
5629 }
5630 pub fn push_item_width<C>(width: f32, inside: C)
5631 where
5632 C: FnOnce(),
5633 {
5634 ImGui::_push_item_width(width);
5635 inside();
5636 ImGui::_pop_item_width();
5637 }
5638 pub fn push_text_wrap_pos<C>(wrap_pos_x: f32, inside: C)
5639 where
5640 C: FnOnce(),
5641 {
5642 ImGui::_push_text_wrap_pos(wrap_pos_x);
5643 inside();
5644 ImGui::_pop_text_wrap_pos();
5645 }
5646 pub fn push_item_flag<C>(flags: BitFlags<ImGuiItemFlag>, v: bool, inside: C)
5647 where
5648 C: FnOnce(),
5649 {
5650 ImGui::_push_item_flag(flags.bits() as i32, v);
5651 inside();
5652 ImGui::_pop_item_flag();
5653 }
5654 pub fn push_id<C>(str_id: &str, inside: C)
5655 where
5656 C: FnOnce(),
5657 {
5658 ImGui::_push_id(str_id);
5659 inside();
5660 ImGui::_pop_id();
5661 }
5662 pub fn push_clip_rect<C>(
5663 clip_rect_min: &crate::dora::Vec2,
5664 clip_rect_max: &crate::dora::Vec2,
5665 intersect_with_current_clip_rect: bool,
5666 inside: C,
5667 ) where
5668 C: FnOnce(),
5669 {
5670 ImGui::_push_clip_rect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
5671 inside();
5672 ImGui::_pop_clip_rect();
5673 }
5674 pub fn begin_tab_bar<C>(str_id: &str, inside: C)
5675 where
5676 C: FnOnce(),
5677 {
5678 if ImGui::_begin_tab_bar(str_id) {
5679 inside();
5680 ImGui::_end_tab_bar();
5681 }
5682 }
5683 pub fn begin_tab_bar_opts<C>(
5684 str_id: &str,
5685 flags: BitFlags<ImGuiTabBarFlag>,
5686 inside: C,
5687 ) where
5688 C: FnOnce(),
5689 {
5690 if ImGui::_begin_tab_bar_opts(str_id, flags.bits() as i32) {
5691 inside();
5692 ImGui::_end_tab_bar();
5693 }
5694 }
5695 pub fn begin_tab_item<C>(label: &str, inside: C)
5696 where
5697 C: FnOnce(),
5698 {
5699 if ImGui::_begin_tab_item(label) {
5700 inside();
5701 ImGui::_end_tab_item();
5702 }
5703 }
5704 pub fn begin_tab_item_opts<C>(
5705 label: &str,
5706 flags: BitFlags<ImGuiTabItemFlag>,
5707 inside: C,
5708 ) where
5709 C: FnOnce(),
5710 {
5711 if ImGui::_begin_tab_item_opts(label, flags.bits() as i32) {
5712 inside();
5713 ImGui::_end_tab_item();
5714 }
5715 }
5716 pub fn begin_tab_item_ret<C>(label: &str, opened: bool, inside: C) -> bool
5717 where
5718 C: FnOnce(),
5719 {
5720 let mut changed = false;
5721 let mut result = false;
5722 IMGUI_STACK.with_borrow_mut(|stack| {
5723 stack.push_bool(opened);
5724 result = ImGui::_begin_tab_item_ret(label, stack);
5725 changed = stack.pop_bool().unwrap();
5726 });
5727 if result {
5728 inside();
5729 ImGui::_end_tab_item();
5730 }
5731 changed
5732 }
5733 pub fn begin_tab_item_ret_opts<C>(
5734 label: &str,
5735 opened: bool,
5736 flags: BitFlags<ImGuiTabItemFlag>,
5737 inside: C,
5738 ) -> bool
5739 where
5740 C: FnOnce(),
5741 {
5742 let mut changed = false;
5743 let mut result = false;
5744 IMGUI_STACK.with_borrow_mut(|stack| {
5745 stack.push_bool(opened);
5746 result = ImGui::_begin_tab_item_ret_opts(label, stack, flags.bits() as i32);
5747 changed = stack.pop_bool().unwrap();
5748 });
5749 if result {
5750 inside();
5751 ImGui::_end_tab_item();
5752 }
5753 changed
5754 }
5755 pub fn tab_item_button_opts(label: &str, flags: BitFlags<ImGuiTabItemFlag>) -> bool {
5756 ImGui::_tab_item_button_opts(label, flags.bits() as i32)
5757 }
5758}
5759
5760#[bitflags]
5761#[repr(u32)]
5762#[derive(Copy, Clone, Debug, PartialEq)]
5763pub enum NvgImageFlag {
5764 GenerateMipmaps = 1 << 0,
5766 RepeatX = 1 << 1,
5768 RepeatY = 1 << 2,
5770 FlipY = 1 << 3,
5772 Premultiplied = 1 << 4,
5774 Nearest = 1 << 5,
5776}
5777
5778#[repr(i32)]
5779#[derive(Copy, Clone, Debug, PartialEq)]
5780pub enum NvgLineCap {
5781 Butt = 0,
5782 Round = 1,
5783 Square = 2,
5784}
5785
5786#[repr(i32)]
5787#[derive(Copy, Clone, Debug, PartialEq)]
5788pub enum NvgLineJoin {
5789 Round = 1,
5790 Bevel = 3,
5791 Miter = 4,
5792}
5793
5794#[repr(i32)]
5795#[derive(Copy, Clone, Debug, PartialEq)]
5796pub enum NvgWinding {
5797 CCW = 1,
5799 CW = 2,
5801}
5802impl NvgWinding {
5803 pub const SOLID: NvgWinding = NvgWinding::CCW;
5804 pub const HOLE: NvgWinding = NvgWinding::CW;
5805}
5806
5807#[repr(i32)]
5808#[derive(Copy, Clone, Debug, PartialEq)]
5809pub enum NvgArcDir {
5810 CCW = 1,
5811 CW = 2,
5812}
5813
5814#[repr(i32)]
5815#[derive(Copy, Clone, Debug, PartialEq)]
5816pub enum NvgHAlign {
5817 Left = 1 << 0,
5819 Center = 1 << 1,
5821 Right = 1 << 2,
5823}
5824
5825#[repr(i32)]
5826#[derive(Copy, Clone, Debug, PartialEq)]
5827pub enum NvgVAlign {
5828 Top = 1 << 3,
5830 Middle = 1 << 4,
5832 Bottom = 1 << 5,
5834 BaseLine = 1 << 6,
5836}
5837
5838impl Nvg {
5839 pub fn create_image(
5840 w: i32,
5841 h: i32,
5842 filename: &str,
5843 image_flags: BitFlags<NvgImageFlag>,
5844 ) -> i32 {
5845 Nvg::_create_image(w, h, filename, image_flags.bits() as i32)
5846 }
5847 pub fn line_cap(cap: NvgLineCap) {
5848 Nvg::_line_cap(cap as i32);
5849 }
5850 pub fn line_join(join: NvgLineJoin) {
5851 Nvg::_line_join(join as i32);
5852 }
5853 pub fn path_winding(winding: NvgWinding) {
5854 Nvg::_path_winding(winding as i32);
5855 }
5856 pub fn arc(x: f32, y: f32, r: f32, a0: f32, a1: f32, dir: NvgArcDir) {
5857 Nvg::_arc(x, y, r, a0, a1, dir as i32);
5858 }
5859 pub fn text_align(h_align: NvgHAlign, v_align: NvgVAlign) {
5860 Nvg::_text_align(h_align as i32, v_align as i32);
5861 }
5862}
5863
5864extern "C" {
5867 fn math_abs(v: f64) -> f64;
5868 fn math_acos(v: f32) -> f32;
5869 fn math_asin(v: f32) -> f32;
5870 fn math_atan(v: f32) -> f32;
5871 fn math_atan2(y: f32, x: f32) -> f32;
5872 fn math_ceil(v: f32) -> f32;
5873 fn math_cos(v: f32) -> f32;
5874 fn math_deg(v: f32) -> f32;
5875 fn math_exp(v: f32) -> f32;
5876 fn math_floor(v: f32) -> f32;
5877 fn math_fmod(x: f32, y: f32) -> f32;
5878 fn math_log(v: f32) -> f32;
5879 fn math_rad(v: f32) -> f32;
5880 fn math_sin(v: f32) -> f32;
5881 fn math_sqrt(v: f32) -> f32;
5882 fn math_tan(v: f32) -> f32;
5883}
5884
5885pub struct Math {}
5886
5887impl Math {
5888 pub const PI: f32 = std::f32::consts::PI;
5889 pub fn abs(v: f64) -> f64 {
5890 unsafe { math_abs(v) }
5891 }
5892 pub fn acos(v: f32) -> f32 {
5893 unsafe { math_acos(v) }
5894 }
5895 pub fn asin(v: f32) -> f32 {
5896 unsafe { math_asin(v) }
5897 }
5898 pub fn atan(v: f32) -> f32 {
5899 unsafe { math_atan(v) }
5900 }
5901 pub fn atan2(y: f32, x: f32) -> f32 {
5902 unsafe { math_atan2(y, x) }
5903 }
5904 pub fn ceil(v: f32) -> f32 {
5905 unsafe { math_ceil(v) }
5906 }
5907 pub fn cos(v: f32) -> f32 {
5908 unsafe { math_cos(v) }
5909 }
5910 pub fn deg(v: f32) -> f32 {
5911 unsafe { math_deg(v) }
5912 }
5913 pub fn exp(v: f32) -> f32 {
5914 unsafe { math_exp(v) }
5915 }
5916 pub fn floor(v: f32) -> f32 {
5917 unsafe { math_floor(v) }
5918 }
5919 pub fn fmod(x: f32, y: f32) -> f32 {
5920 unsafe { math_fmod(x, y) }
5921 }
5922 pub fn log(v: f32) -> f32 {
5923 unsafe { math_log(v) }
5924 }
5925 pub fn rad(v: f32) -> f32 {
5926 unsafe { math_rad(v) }
5927 }
5928 pub fn sin(v: f32) -> f32 {
5929 unsafe { math_sin(v) }
5930 }
5931 pub fn sqrt(v: f32) -> f32 {
5932 unsafe { math_sqrt(v) }
5933 }
5934 pub fn tan(v: f32) -> f32 {
5935 unsafe { math_tan(v) }
5936 }
5937}
5938
5939use std::future::Future;
5940use std::pin::Pin;
5941use std::task::{Context, Poll};
5942
5943enum State {
5944 Halted,
5945 Running,
5946}
5947
5948pub struct Coroutine {
5949 state: State,
5950}
5951
5952impl Coroutine {
5953 pub fn waiter<'a>(&'a mut self) -> Waiter<'a> {
5954 Waiter { co: self }
5955 }
5956}
5957
5958pub struct Waiter<'a> {
5959 co: &'a mut Coroutine,
5960}
5961
5962impl<'a> Future for Waiter<'a> {
5963 type Output = ();
5964
5965 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
5966 match self.co.state {
5967 State::Halted => {
5968 self.co.state = State::Running;
5969 Poll::Ready(())
5970 }
5971 State::Running => {
5972 self.co.state = State::Halted;
5973 Poll::Pending
5974 }
5975 }
5976 }
5977}
5978
5979use std::task::{RawWaker, RawWakerVTable, Waker};
5980
5981fn create_waker() -> Waker {
5982 unsafe { Waker::from_raw(RAW_WAKER) }
5983}
5984
5985const RAW_WAKER: RawWaker = RawWaker::new(std::ptr::null(), &VTABLE);
5986const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
5987
5988unsafe fn clone(_: *const ()) -> RawWaker {
5989 RAW_WAKER
5990}
5991unsafe fn wake(_: *const ()) {}
5992unsafe fn wake_by_ref(_: *const ()) {}
5993unsafe fn drop(_: *const ()) {}
5994
5995struct Executor {
5996 co: Pin<Box<dyn Future<Output = ()>>>,
5997}
5998
5999impl Executor {
6000 fn new<C, F>(closure: C) -> Self
6001 where
6002 F: Future<Output = ()> + 'static,
6003 C: FnOnce(Coroutine) -> F,
6004 {
6005 let co = Coroutine { state: State::Running };
6006 Executor { co: Box::pin(closure(co)) }
6007 }
6008
6009 fn update(&mut self) -> bool {
6010 let waker = create_waker();
6011 let mut context = Context::from_waker(&waker);
6012 match self.co.as_mut().poll(&mut context) {
6013 Poll::Pending => false,
6014 Poll::Ready(()) => true,
6015 }
6016 }
6017}
6018
6019pub fn once<C, F>(closure: C) -> Box<dyn FnMut(f64) -> bool>
6020where
6021 F: Future<Output = ()> + 'static,
6022 C: FnOnce(Coroutine) -> F,
6023{
6024 let mut executor = Executor::new(closure);
6025 Box::new(move |_| executor.update())
6026}
6027
6028pub fn thread<C, F>(closure: C)
6029where
6030 F: Future<Output = ()> + 'static,
6031 C: FnOnce(Coroutine) -> F,
6032{
6033 let mut executor = Executor::new(closure);
6034 Director::schedule_posted(Box::new(move |_| executor.update()));
6035}
6036
6037#[macro_export]
6038macro_rules! sleep {
6039 ($co:expr, $time:expr) => {{
6040 let total = $time;
6041 let mut time: f32 = 0.0;
6042 while time <= total {
6043 time += dora_ssr::App::get_delta_time() as f32;
6044 $co.waiter().await;
6045 }
6046 }};
6047}
6048
6049#[macro_export]
6050macro_rules! cycle {
6051 ($co:expr, $time:expr, $closure:expr) => {{
6052 let total = $time;
6053 let mut time: f32 = 0.0;
6054 loop {
6055 $closure(f32::min(time / $time, 1.0));
6056 if time >= total {
6057 break;
6058 }
6059 $co.waiter().await;
6060 time += dora_ssr::App::get_delta_time() as f32;
6061 }
6062 }};
6063}
6064
6065#[macro_export]
6066macro_rules! wait {
6067 ($co:expr, $condition:expr) => {
6068 while !$condition {
6069 $co.waiter().await;
6070 }
6071 };
6072}