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