1use anyhow::{bail, Context, Result};
7
8use crate::image_manager::{ImageId, ImageManager};
9use crate::layer::{
10 ClipRect, LayerId, LayerManager, Sprite, SpriteBlend, SpriteFit, SpriteId, SpriteSizeMode,
11};
12
13fn sg_cgm_coord_trace_enabled() -> bool {
14 std::env::var_os("SG_DEBUG").is_some()
15}
16
17fn sg_cgm_coord_trace(msg: impl AsRef<str>) {
18 if sg_cgm_coord_trace_enabled() {
19 eprintln!("[SG_DEBUG][CGM_COORD_TRACE][GFX] {}", msg.as_ref());
20 }
21}
22
23fn cgm_file_interesting(file: Option<&str>) -> bool {
24 file.map(|name| name.to_ascii_lowercase().contains("cgm_"))
25 .unwrap_or(false)
26}
27
28#[derive(Debug, Clone)]
29struct ObjectState {
30 is_bg: bool,
31
32 layer_id: Option<LayerId>,
34 sprite_id: Option<SpriteId>,
35
36 is_mesh: bool,
38 file: Option<String>,
39 patno: i64,
40 disp: bool,
41 x: i64,
42 y: i64,
43 layer_no: i64,
44 order: i64,
45 alpha: i64,
46 z: i64,
48 center_x: i64,
49 center_y: i64,
50 scale_x: i64,
51 scale_y: i64,
52 rotate_z: i64,
53 clip_use: i64,
54 clip_left: i64,
55 clip_top: i64,
56 clip_right: i64,
57 clip_bottom: i64,
58 src_clip_use: i64,
59 src_clip_left: i64,
60 src_clip_top: i64,
61 src_clip_right: i64,
62 src_clip_bottom: i64,
63 tr: i64,
64 mono: i64,
65 reverse: i64,
66 bright: i64,
67 dark: i64,
68 color_rate: i64,
69 color_add_r: i64,
70 color_add_g: i64,
71 color_add_b: i64,
72 color_r: i64,
73 color_g: i64,
74 color_b: i64,
75 blend: i64,
76 light_no: i64,
77 fog_use: i64,
78}
79
80impl Default for ObjectState {
81 fn default() -> Self {
82 Self {
83 is_bg: false,
84 layer_id: None,
85 sprite_id: None,
86 is_mesh: false,
87 file: None,
88 patno: 0,
89 disp: false,
90 x: 0,
91 y: 0,
92 layer_no: 0,
93 order: 0,
94 alpha: 255,
95 z: 0,
96 center_x: 0,
97 center_y: 0,
98 scale_x: 1000,
99 scale_y: 1000,
100 rotate_z: 0,
101 clip_use: 0,
102 clip_left: 0,
103 clip_top: 0,
104 clip_right: 0,
105 clip_bottom: 0,
106 src_clip_use: 0,
107 src_clip_left: 0,
108 src_clip_top: 0,
109 src_clip_right: 0,
110 src_clip_bottom: 0,
111 tr: 255,
112 mono: 0,
113 reverse: 0,
114 bright: 0,
115 dark: 0,
116 color_rate: 0,
117 color_add_r: 0,
118 color_add_g: 0,
119 color_add_b: 0,
120 color_r: 0,
121 color_g: 0,
122 color_b: 0,
123 blend: 0,
124 light_no: -1,
125 fog_use: 0,
126 }
127 }
128}
129
130#[derive(Debug, Clone)]
131pub struct DebugObjectSpriteBinding {
132 pub stage: usize,
133 pub obj_idx: usize,
134 pub is_bg: bool,
135 pub layer_id: Option<LayerId>,
136 pub sprite_id: Option<SpriteId>,
137 pub file: Option<String>,
138 pub patno: i64,
139 pub disp: bool,
140 pub x: i64,
141 pub y: i64,
142 pub layer_no: i64,
143 pub order: i64,
144 pub alpha: i64,
145 pub z: i64,
146 pub tr: i64,
147 pub clip_use: i64,
148 pub clip_left: i64,
149 pub clip_top: i64,
150 pub clip_right: i64,
151 pub clip_bottom: i64,
152 pub scale_x: i64,
153 pub scale_y: i64,
154 pub rotate_z: i64,
155}
156
157#[derive(Debug, Clone)]
158struct StageState {
159 layer_id: Option<LayerId>,
160 objects: Vec<ObjectState>,
161}
162
163impl Default for StageState {
164 fn default() -> Self {
165 Self {
166 layer_id: None,
167 objects: Vec::new(),
168 }
169 }
170}
171
172#[derive(Debug)]
173pub struct GfxRuntime {
174 pub current_layer: i32,
177 stages: [StageState; 3],
178}
179
180impl Default for GfxRuntime {
181 fn default() -> Self {
182 Self {
183 current_layer: 0,
184 stages: [
185 StageState::default(),
186 StageState::default(),
187 StageState::default(),
188 ],
189 }
190 }
191}
192
193impl GfxRuntime {
194 pub fn new() -> Self {
195 Self::default()
196 }
197
198 fn ensure_stage(&mut self, stage: usize) -> &mut StageState {
199 &mut self.stages[stage]
200 }
201
202 fn ensure_stage_layer(&mut self, layers: &mut LayerManager, stage: usize) -> LayerId {
203 let st = self.ensure_stage(stage);
204 if let Some(id) = st.layer_id {
205 return id;
206 }
207 let id = layers.create_layer();
208 st.layer_id = Some(id);
209 id
210 }
211
212 pub fn ensure_stage_layer_id(
214 &mut self,
215 layers: &mut LayerManager,
216 stage: i64,
217 ) -> Option<LayerId> {
218 if stage < 0 || stage > 2 {
219 return None;
220 }
221 Some(self.ensure_stage_layer(layers, stage as usize))
222 }
223
224 fn ensure_object_mut(&mut self, stage: usize, obj_idx: usize) -> &mut ObjectState {
225 let st = self.ensure_stage(stage);
226 if st.objects.len() <= obj_idx {
227 st.objects.resize_with(obj_idx + 1, Default::default);
228 }
229 &mut st.objects[obj_idx]
230 }
231
232 fn object(&self, stage: usize, obj_idx: usize) -> Option<&ObjectState> {
233 self.stages.get(stage)?.objects.get(obj_idx)
234 }
235
236 fn reset_object_for_create(
237 &mut self,
238 layers: &mut LayerManager,
239 stage: usize,
240 obj_idx: usize,
241 ) {
242 let (layer_id, sprite_id) = {
243 let obj = self.ensure_object_mut(stage, obj_idx);
244 (obj.layer_id, obj.sprite_id)
245 };
246
247 {
248 let obj = self.ensure_object_mut(stage, obj_idx);
249 *obj = ObjectState::default();
250 obj.layer_id = layer_id;
251 obj.sprite_id = sprite_id;
252 obj.is_bg = stage == 0 && obj_idx == 0;
253 }
254
255 if stage == 0 && obj_idx == 0 {
256 *layers.bg_mut() = Sprite::default();
257 return;
258 }
259
260 if let (Some(lid), Some(sid)) = (layer_id, sprite_id) {
261 if let Some(sprite) = layers.layer_mut(lid).and_then(|layer| layer.sprite_mut(sid)) {
262 *sprite = Sprite::default();
263 }
264 }
265 }
266
267
268 pub fn debug_object_snapshot(
269 &self,
270 stage: usize,
271 obj_idx: usize,
272 ) -> Option<DebugObjectSpriteBinding> {
273 let obj = self.object(stage, obj_idx)?;
274 Some(DebugObjectSpriteBinding {
275 stage,
276 obj_idx,
277 is_bg: obj.is_bg,
278 layer_id: obj.layer_id,
279 sprite_id: obj.sprite_id,
280 file: obj.file.clone(),
281 patno: obj.patno,
282 disp: obj.disp,
283 x: obj.x,
284 y: obj.y,
285 layer_no: obj.layer_no,
286 order: obj.order,
287 alpha: obj.alpha,
288 z: obj.z,
289 tr: obj.tr,
290 clip_use: obj.clip_use,
291 clip_left: obj.clip_left,
292 clip_top: obj.clip_top,
293 clip_right: obj.clip_right,
294 clip_bottom: obj.clip_bottom,
295 scale_x: obj.scale_x,
296 scale_y: obj.scale_y,
297 rotate_z: obj.rotate_z,
298 })
299 }
300
301 pub fn object_sprite_binding(&self, stage: i64, obj_idx: i64) -> Option<(LayerId, SpriteId)> {
302 let stage_i = stage as isize;
303 if !(0..3).contains(&stage_i) || obj_idx < 0 {
304 return None;
305 }
306 let obj = self.object(stage_i as usize, obj_idx as usize)?;
307 if obj.is_bg {
308 return None;
309 }
310 match (obj.layer_id, obj.sprite_id) {
311 (Some(lid), Some(sid)) => Some((lid, sid)),
312 _ => None,
313 }
314 }
315
316 fn load_any_image(images: &mut ImageManager, file: &str, patno: i64) -> Result<ImageId> {
317 let pat_u32 = if patno < 0 { 0 } else { patno as u32 };
319 match images.load_g00(file, pat_u32) {
320 Ok(id) => Ok(id),
321 Err(_) => images
322 .load_bg(file)
323 .with_context(|| format!("failed to load image as g00/bg: {file}")),
324 }
325 }
326
327 fn ensure_bound_sprite(
328 &mut self,
329 layers: &mut LayerManager,
330 stage: usize,
331 obj_idx: usize,
332 ) -> Result<(LayerId, SpriteId)> {
333 let st_layer = self.ensure_stage_layer(layers, stage);
334 let obj = self.ensure_object_mut(stage, obj_idx);
335
336 if obj.is_bg {
337 bail!("BG object does not have a bound sprite");
338 }
339
340 if let (Some(lid), Some(sid)) = (obj.layer_id, obj.sprite_id) {
341 return Ok((lid, sid));
342 }
343
344 let sid = {
345 let layer = layers
346 .layer_mut(st_layer)
347 .context("stage layer not found")?;
348 layer.create_sprite()
349 };
350
351 if let Some(layer) = layers.layer_mut(st_layer) {
353 if let Some(sprite) = layer.sprite_mut(sid) {
354 sprite.visible = true;
355 sprite.alpha = 255;
356 sprite.fit = SpriteFit::PixelRect;
357 sprite.size_mode = SpriteSizeMode::Intrinsic;
358 sprite.x = 0;
359 sprite.y = 0;
360 sprite.order = 0;
361 }
362 }
363
364 obj.layer_id = Some(st_layer);
365 obj.sprite_id = Some(sid);
366 Ok((st_layer, sid))
367 }
368
369 fn sync_object_sprite(
370 &mut self,
371 images: &mut ImageManager,
372 layers: &mut LayerManager,
373 stage: usize,
374 obj_idx: usize,
375 ) -> Result<()> {
376 let obj = self.ensure_object_mut(stage, obj_idx).clone();
377
378 if obj.is_bg {
379 let bg = layers.bg_mut();
380 bg.visible = obj.disp;
381 bg.x = obj.x as i32;
382 bg.y = obj.y as i32;
383 bg.alpha = obj.alpha.clamp(0, 255) as u8;
384 bg.fit = SpriteFit::FullScreen;
385 bg.size_mode = SpriteSizeMode::Intrinsic;
386 bg.scale_x = obj.scale_x as f32 / 1000.0;
387 bg.scale_y = obj.scale_y as f32 / 1000.0;
388 bg.rotate = obj.rotate_z as f32 * std::f32::consts::PI / 1800.0;
389 bg.pivot_x = obj.center_x as f32;
390 bg.pivot_y = obj.center_y as f32;
391 bg.dst_clip = clip_rect(
392 obj.clip_use,
393 obj.clip_left,
394 obj.clip_top,
395 obj.clip_right,
396 obj.clip_bottom,
397 );
398 bg.src_clip = clip_rect(
399 obj.src_clip_use,
400 obj.src_clip_left,
401 obj.src_clip_top,
402 obj.src_clip_right,
403 obj.src_clip_bottom,
404 );
405 bg.tr = obj.tr.clamp(0, 255) as u8;
406 bg.mono = obj.mono.clamp(0, 255) as u8;
407 bg.reverse = obj.reverse.clamp(0, 255) as u8;
408 bg.bright = obj.bright.clamp(0, 255) as u8;
409 bg.dark = obj.dark.clamp(0, 255) as u8;
410 bg.color_rate = obj.color_rate.clamp(0, 255) as u8;
411 bg.color_add_r = obj.color_add_r.clamp(0, 255) as u8;
412 bg.color_add_g = obj.color_add_g.clamp(0, 255) as u8;
413 bg.color_add_b = obj.color_add_b.clamp(0, 255) as u8;
414 bg.color_r = obj.color_r.clamp(0, 255) as u8;
415 bg.color_g = obj.color_g.clamp(0, 255) as u8;
416 bg.color_b = obj.color_b.clamp(0, 255) as u8;
417 bg.blend = SpriteBlend::from_i64(obj.blend);
418 bg.light_no = obj.light_no as i32;
419 bg.fog_use = obj.fog_use != 0;
420
421 if obj.is_mesh {
422 bg.image_id = None;
423 bg.mesh_file_name = obj.file.clone();
424 bg.mesh_kind = 1;
425 bg.camera_enabled = true;
426 } else if let Some(file) = &obj.file {
427 match Self::load_any_image(images, file, obj.patno) {
428 Ok(img_id) => {
429 bg.image_id = Some(img_id);
430 bg.object_anchor = false;
431 bg.texture_center_x = 0.0;
432 bg.texture_center_y = 0.0;
433 }
434 Err(err) if is_probable_mesh_path(file) => {
435 let _ = err;
436 bg.image_id = None;
437 }
438 Err(err) => return Err(err),
439 }
440 }
441 return Ok(());
442 }
443
444 let (lid, sid) = self.ensure_bound_sprite(layers, stage, obj_idx)?;
445 let sprite = layers
446 .layer_mut(lid)
447 .and_then(|l| l.sprite_mut(sid))
448 .context("sprite not found")?;
449
450 sprite.visible = obj.disp;
451 sprite.x = obj.x as i32;
452 sprite.y = obj.y as i32;
453 sprite.alpha = obj.alpha.clamp(0, 255) as u8;
454 sprite.scale_x = obj.scale_x as f32 / 1000.0;
455 sprite.scale_y = obj.scale_y as f32 / 1000.0;
456 sprite.rotate = obj.rotate_z as f32 * std::f32::consts::PI / 1800.0;
457 sprite.pivot_x = obj.center_x as f32;
458 sprite.pivot_y = obj.center_y as f32;
459 sprite.dst_clip = clip_rect(
460 obj.clip_use,
461 obj.clip_left,
462 obj.clip_top,
463 obj.clip_right,
464 obj.clip_bottom,
465 );
466 sprite.src_clip = clip_rect(
467 obj.src_clip_use,
468 obj.src_clip_left,
469 obj.src_clip_top,
470 obj.src_clip_right,
471 obj.src_clip_bottom,
472 );
473 sprite.tr = obj.tr.clamp(0, 255) as u8;
474 sprite.mono = obj.mono.clamp(0, 255) as u8;
475 sprite.reverse = obj.reverse.clamp(0, 255) as u8;
476 sprite.bright = obj.bright.clamp(0, 255) as u8;
477 sprite.dark = obj.dark.clamp(0, 255) as u8;
478 sprite.color_rate = obj.color_rate.clamp(0, 255) as u8;
479 sprite.color_add_r = obj.color_add_r.clamp(0, 255) as u8;
480 sprite.color_add_g = obj.color_add_g.clamp(0, 255) as u8;
481 sprite.color_add_b = obj.color_add_b.clamp(0, 255) as u8;
482 sprite.color_r = obj.color_r.clamp(0, 255) as u8;
483 sprite.color_g = obj.color_g.clamp(0, 255) as u8;
484 sprite.color_b = obj.color_b.clamp(0, 255) as u8;
485 sprite.blend = SpriteBlend::from_i64(obj.blend);
486 sprite.light_no = obj.light_no as i32;
487 sprite.fog_use = obj.fog_use != 0;
488
489 let coarse = obj.layer_no.clamp(-10000, 10000) as i32;
491 let fine = obj.order.clamp(-100000, 100000) as i32;
492 sprite.order = coarse.saturating_mul(1000).saturating_add(fine);
493
494 if obj.is_mesh {
495 sprite.image_id = None;
496 sprite.mesh_file_name = obj.file.clone();
497 sprite.mesh_kind = 1;
498 sprite.camera_enabled = true;
499 sprite.shadow_cast = true;
500 sprite.shadow_receive = true;
501 sprite.object_anchor = false;
502 sprite.texture_center_x = 0.0;
503 sprite.texture_center_y = 0.0;
504 } else if let Some(file) = &obj.file {
505 match Self::load_any_image(images, file, obj.patno) {
506 Ok(img_id) => {
507 set_object_sprite_image(sprite, images, img_id);
508 }
509 Err(err) if is_probable_mesh_path(file) => {
510 let _ = err;
511 sprite.image_id = None;
512 sprite.object_anchor = false;
513 sprite.texture_center_x = 0.0;
514 sprite.texture_center_y = 0.0;
515 }
516 Err(err) => return Err(err),
517 }
518 }
519
520 Ok(())
521 }
522
523 pub fn object_set_center(
524 &mut self,
525 images: &mut ImageManager,
526 layers: &mut LayerManager,
527 stage: i64,
528 obj_idx: i64,
529 x: i64,
530 y: i64,
531 ) -> Result<()> {
532 let stage_i = stage as isize;
533 if !(0..3).contains(&stage_i) || obj_idx < 0 {
534 return Ok(());
535 }
536 let stage_u = stage_i as usize;
537 let obj_u = obj_idx as usize;
538 {
539 let obj = self.ensure_object_mut(stage_u, obj_u);
540 obj.center_x = x;
541 obj.center_y = y;
542 }
543 self.sync_object_sprite(images, layers, stage_u, obj_u)
544 }
545
546 pub fn object_set_scale(
547 &mut self,
548 images: &mut ImageManager,
549 layers: &mut LayerManager,
550 stage: i64,
551 obj_idx: i64,
552 x: i64,
553 y: i64,
554 ) -> Result<()> {
555 let stage_i = stage as isize;
556 if !(0..3).contains(&stage_i) || obj_idx < 0 {
557 return Ok(());
558 }
559 let stage_u = stage_i as usize;
560 let obj_u = obj_idx as usize;
561 {
562 let obj = self.ensure_object_mut(stage_u, obj_u);
563 obj.scale_x = x;
564 obj.scale_y = y;
565 }
566 self.sync_object_sprite(images, layers, stage_u, obj_u)
567 }
568
569 pub fn object_set_rotate(
570 &mut self,
571 images: &mut ImageManager,
572 layers: &mut LayerManager,
573 stage: i64,
574 obj_idx: i64,
575 z: i64,
576 ) -> Result<()> {
577 let stage_i = stage as isize;
578 if !(0..3).contains(&stage_i) || obj_idx < 0 {
579 return Ok(());
580 }
581 let stage_u = stage_i as usize;
582 let obj_u = obj_idx as usize;
583 {
584 let obj = self.ensure_object_mut(stage_u, obj_u);
585 obj.rotate_z = z;
586 }
587 self.sync_object_sprite(images, layers, stage_u, obj_u)
588 }
589
590 pub fn object_set_clip(
591 &mut self,
592 images: &mut ImageManager,
593 layers: &mut LayerManager,
594 stage: i64,
595 obj_idx: i64,
596 use_flag: i64,
597 left: i64,
598 top: i64,
599 right: i64,
600 bottom: i64,
601 ) -> Result<()> {
602 let stage_i = stage as isize;
603 if !(0..3).contains(&stage_i) || obj_idx < 0 {
604 return Ok(());
605 }
606 let stage_u = stage_i as usize;
607 let obj_u = obj_idx as usize;
608 {
609 let obj = self.ensure_object_mut(stage_u, obj_u);
610 obj.clip_use = use_flag;
611 obj.clip_left = left;
612 obj.clip_top = top;
613 obj.clip_right = right;
614 obj.clip_bottom = bottom;
615 }
616 self.sync_object_sprite(images, layers, stage_u, obj_u)
617 }
618
619 pub fn object_set_src_clip(
620 &mut self,
621 images: &mut ImageManager,
622 layers: &mut LayerManager,
623 stage: i64,
624 obj_idx: i64,
625 use_flag: i64,
626 left: i64,
627 top: i64,
628 right: i64,
629 bottom: i64,
630 ) -> Result<()> {
631 let stage_i = stage as isize;
632 if !(0..3).contains(&stage_i) || obj_idx < 0 {
633 return Ok(());
634 }
635 let stage_u = stage_i as usize;
636 let obj_u = obj_idx as usize;
637 {
638 let obj = self.ensure_object_mut(stage_u, obj_u);
639 obj.src_clip_use = use_flag;
640 obj.src_clip_left = left;
641 obj.src_clip_top = top;
642 obj.src_clip_right = right;
643 obj.src_clip_bottom = bottom;
644 }
645 self.sync_object_sprite(images, layers, stage_u, obj_u)
646 }
647
648 pub fn stage_clear(
649 &mut self,
650 images: &mut ImageManager,
651 layers: &mut LayerManager,
652 stage: i64,
653 ) -> Result<()> {
654 let stage_i = stage as isize;
655 if !(0..3).contains(&stage_i) {
656 return Ok(());
657 }
658 let stage_u = stage_i as usize;
659 let len = self.stages[stage_u].objects.len();
660 for idx in 0..len {
661 {
662 let obj = self.ensure_object_mut(stage_u, idx);
663 obj.disp = false;
664 }
665 let _ = self.sync_object_sprite(images, layers, stage_u, idx);
666 }
667 Ok(())
668 }
669
670 fn object_create_impl(
671 &mut self,
672 images: &mut ImageManager,
673 layers: &mut LayerManager,
674 stage: i64,
675 obj_idx: i64,
676 file: &str,
677 disp: i64,
678 x: i64,
679 y: i64,
680 patno: i64,
681 reinit: bool,
682 ) -> Result<()> {
683 let stage_i = stage as isize;
684 if !(0..3).contains(&stage_i) {
685 bail!("invalid stage: {stage}");
686 }
687 if obj_idx < 0 {
688 bail!("invalid obj idx: {obj_idx}");
689 }
690
691 let stage_u = stage_i as usize;
692 let obj_u = obj_idx as usize;
693 let current_layer = self.current_layer;
694
695 if reinit {
696 self.reset_object_for_create(layers, stage_u, obj_u);
697 }
698
699 {
700 let obj = self.ensure_object_mut(stage_u, obj_u);
701 obj.is_bg = stage_u == 0 && obj_u == 0;
702 obj.is_mesh = false;
703 obj.file = Some(file.to_string());
704 obj.patno = patno;
705 obj.disp = disp != 0;
706 obj.x = x;
707 obj.y = y;
708
709 if obj.layer_no == 0 {
711 obj.layer_no = current_layer as i64;
712 }
713 }
714
715 if !(stage_u == 0 && obj_u == 0) {
717 let _ = self.ensure_bound_sprite(layers, stage_u, obj_u)?;
718 }
719
720 if cgm_file_interesting(Some(file)) || (30..=59).contains(&obj_u) {
721 let obj = self.object(stage_u, obj_u);
722 sg_cgm_coord_trace(format!(
723 "object_create stage={} obj={} file={} disp={} x={} y={} patno={} reinit={} layer_no={:?} binding={:?}/{:?}",
724 stage,
725 obj_idx,
726 file,
727 disp,
728 x,
729 y,
730 patno,
731 reinit,
732 obj.map(|o| o.layer_no),
733 obj.and_then(|o| o.layer_id),
734 obj.and_then(|o| o.sprite_id)
735 ));
736 }
737
738 self.sync_object_sprite(images, layers, stage_u, obj_u)
739 }
740
741 pub fn object_create(
742 &mut self,
743 images: &mut ImageManager,
744 layers: &mut LayerManager,
745 stage: i64,
746 obj_idx: i64,
747 file: &str,
748 disp: i64,
749 x: i64,
750 y: i64,
751 patno: i64,
752 ) -> Result<()> {
753 self.object_create_impl(images, layers, stage, obj_idx, file, disp, x, y, patno, true)
754 }
755
756 pub fn restore_gfx_object_from_globals(
768 &mut self,
769 images: &mut ImageManager,
770 layers: &mut LayerManager,
771 stage: i64,
772 obj_idx: i64,
773 src: &crate::runtime::globals::ObjectState,
774 ) -> Result<()> {
775 let stage_i = stage as isize;
776 if !(0..3).contains(&stage_i) || obj_idx < 0 {
777 return Ok(());
778 }
779 let file = match src.file_name.as_deref() {
780 Some(f) if !f.is_empty() => f.to_string(),
781 _ => return Ok(()),
782 };
783 let stage_u = stage_i as usize;
784 let obj_u = obj_idx as usize;
785
786 let current_layer = self.current_layer;
787 self.reset_object_for_create(layers, stage_u, obj_u);
788 {
789 let pe = &src.runtime.prop_events;
790 let dst = self.ensure_object_mut(stage_u, obj_u);
791 dst.is_bg = stage_u == 0 && obj_u == 0;
792 dst.is_mesh = false;
793 dst.file = Some(file);
794 dst.patno = src.base.patno;
795 dst.disp = src.base.disp != 0;
796 dst.x = pe.x.get_total_value() as i64;
797 dst.y = pe.y.get_total_value() as i64;
798 dst.z = pe.z.get_total_value() as i64;
799 dst.layer_no = src.base.layer;
800 dst.order = src.base.order;
801 dst.center_x = pe.center_x.get_total_value() as i64;
802 dst.center_y = pe.center_y.get_total_value() as i64;
803 dst.scale_x = pe.scale_x.get_total_value() as i64;
804 dst.scale_y = pe.scale_y.get_total_value() as i64;
805 dst.rotate_z = pe.rotate_z.get_total_value() as i64;
806 dst.clip_use = src.base.clip_use;
807 dst.clip_left = pe.clip_left.get_total_value() as i64;
808 dst.clip_top = pe.clip_top.get_total_value() as i64;
809 dst.clip_right = pe.clip_right.get_total_value() as i64;
810 dst.clip_bottom = pe.clip_bottom.get_total_value() as i64;
811 dst.src_clip_use = src.base.src_clip_use;
812 dst.src_clip_left = pe.src_clip_left.get_total_value() as i64;
813 dst.src_clip_top = pe.src_clip_top.get_total_value() as i64;
814 dst.src_clip_right = pe.src_clip_right.get_total_value() as i64;
815 dst.src_clip_bottom = pe.src_clip_bottom.get_total_value() as i64;
816 let tr = pe.tr.get_total_value() as i64;
817 dst.alpha = tr;
818 dst.tr = tr;
819 dst.mono = pe.mono.get_total_value() as i64;
820 dst.reverse = pe.reverse.get_total_value() as i64;
821 dst.bright = pe.bright.get_total_value() as i64;
822 dst.dark = pe.dark.get_total_value() as i64;
823 dst.color_rate = pe.color_rate.get_total_value() as i64;
824 dst.color_add_r = pe.color_add_r.get_total_value() as i64;
825 dst.color_add_g = pe.color_add_g.get_total_value() as i64;
826 dst.color_add_b = pe.color_add_b.get_total_value() as i64;
827 dst.color_r = pe.color_r.get_total_value() as i64;
828 dst.color_g = pe.color_g.get_total_value() as i64;
829 dst.color_b = pe.color_b.get_total_value() as i64;
830 dst.blend = src.base.blend;
831 dst.light_no = src.base.light_no;
832 dst.fog_use = src.base.fog_use;
833 if dst.layer_no == 0 {
834 dst.layer_no = current_layer as i64;
835 }
836 }
837
838 if !(stage_u == 0 && obj_u == 0) {
839 let _ = self.ensure_bound_sprite(layers, stage_u, obj_u)?;
840 }
841 self.sync_object_sprite(images, layers, stage_u, obj_u)
842 }
843
844 pub fn object_change_file(
845 &mut self,
846 images: &mut ImageManager,
847 layers: &mut LayerManager,
848 stage: i64,
849 obj_idx: i64,
850 file: &str,
851 disp: i64,
852 x: i64,
853 y: i64,
854 patno: i64,
855 ) -> Result<()> {
856 self.object_create_impl(images, layers, stage, obj_idx, file, disp, x, y, patno, false)
857 }
858
859 pub fn object_create_mesh(
860 &mut self,
861 layers: &mut LayerManager,
862 stage: i64,
863 obj_idx: i64,
864 file: &str,
865 disp: i64,
866 x: i64,
867 y: i64,
868 patno: i64,
869 ) -> Result<()> {
870 let stage_i = stage as isize;
871 if !(0..3).contains(&stage_i) {
872 bail!("invalid stage: {stage}");
873 }
874 if obj_idx < 0 {
875 bail!("invalid obj idx: {obj_idx}");
876 }
877
878 let stage_u = stage_i as usize;
879 let obj_u = obj_idx as usize;
880 let current_layer = self.current_layer;
881
882 self.reset_object_for_create(layers, stage_u, obj_u);
883
884 {
885 let obj = self.ensure_object_mut(stage_u, obj_u);
886 obj.is_bg = stage_u == 0 && obj_u == 0;
887 obj.is_mesh = true;
888 obj.file = Some(file.to_string());
889 obj.patno = patno;
890 obj.disp = disp != 0;
891 obj.x = x;
892 obj.y = y;
893 if obj.layer_no == 0 {
894 obj.layer_no = current_layer as i64;
895 }
896 }
897
898 if cgm_file_interesting(Some(file)) || (30..=59).contains(&obj_u) {
899 sg_cgm_coord_trace(format!(
900 "object_create_mesh stage={} obj={} file={} disp={} x={} y={} patno={}",
901 stage, obj_idx, file, disp, x, y, patno
902 ));
903 }
904
905 if stage_u == 0 && obj_u == 0 {
906 let bg = layers.bg_mut();
907 bg.visible = disp != 0;
908 bg.image_id = None;
909 bg.x = x as i32;
910 bg.y = y as i32;
911 } else {
912 let (lid, sid) = self.ensure_bound_sprite(layers, stage_u, obj_u)?;
913 let sprite = layers
914 .layer_mut(lid)
915 .and_then(|l| l.sprite_mut(sid))
916 .context("mesh sprite not found")?;
917 sprite.visible = disp != 0;
918 sprite.image_id = None;
919 sprite.x = x as i32;
920 sprite.y = y as i32;
921 sprite.alpha = 255;
922 sprite.tr = 255;
923 sprite.fit = SpriteFit::PixelRect;
924 sprite.size_mode = SpriteSizeMode::Intrinsic;
925 sprite.mesh_file_name = Some(file.to_string());
926 sprite.mesh_kind = 1;
927 sprite.camera_enabled = true;
928 sprite.shadow_cast = true;
929 sprite.shadow_receive = true;
930 }
931
932 Ok(())
933 }
934
935 pub fn object_set_disp(
936 &mut self,
937 images: &mut ImageManager,
938 layers: &mut LayerManager,
939 stage: i64,
940 obj_idx: i64,
941 disp: i64,
942 ) -> Result<()> {
943 let stage_i = stage as isize;
944 if !(0..3).contains(&stage_i) || obj_idx < 0 {
945 return Ok(());
946 }
947 let stage_u = stage_i as usize;
948 let obj_u = obj_idx as usize;
949 {
950 let obj = self.ensure_object_mut(stage_u, obj_u);
951 obj.disp = disp != 0;
952 }
953 self.sync_object_sprite(images, layers, stage_u, obj_u)
954 }
955
956 pub fn object_set_pos(
957 &mut self,
958 images: &mut ImageManager,
959 layers: &mut LayerManager,
960 stage: i64,
961 obj_idx: i64,
962 x: i64,
963 y: i64,
964 ) -> Result<()> {
965 let stage_i = stage as isize;
966 if !(0..3).contains(&stage_i) || obj_idx < 0 {
967 return Ok(());
968 }
969 let stage_u = stage_i as usize;
970 let obj_u = obj_idx as usize;
971 let current_layer = self.current_layer;
972 {
973 let obj = self.ensure_object_mut(stage_u, obj_u);
974 obj.x = x;
975 obj.y = y;
976 if obj.layer_no == 0 {
977 obj.layer_no = current_layer as i64;
978 }
979 }
980 if let Some(obj) = self.object(stage_u, obj_u) {
981 if cgm_file_interesting(obj.file.as_deref()) || (30..=59).contains(&obj_u) {
982 sg_cgm_coord_trace(format!(
983 "object_set_pos stage={} obj={} file={:?} x={} y={} layer_no={} binding={:?}/{:?}",
984 stage,
985 obj_idx,
986 obj.file.as_deref(),
987 x,
988 y,
989 obj.layer_no,
990 obj.layer_id,
991 obj.sprite_id
992 ));
993 }
994 }
995 self.sync_object_sprite(images, layers, stage_u, obj_u)
996 }
997
998 pub fn object_set_x(
999 &mut self,
1000 images: &mut ImageManager,
1001 layers: &mut LayerManager,
1002 stage: i64,
1003 obj_idx: i64,
1004 x: i64,
1005 ) -> Result<()> {
1006 let stage_i = stage as isize;
1007 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1008 return Ok(());
1009 }
1010 let stage_u = stage_i as usize;
1011 let obj_u = obj_idx as usize;
1012 {
1013 let obj = self.ensure_object_mut(stage_u, obj_u);
1014 obj.x = x;
1015 }
1016 self.sync_object_sprite(images, layers, stage_u, obj_u)
1017 }
1018
1019 pub fn object_set_y(
1020 &mut self,
1021 images: &mut ImageManager,
1022 layers: &mut LayerManager,
1023 stage: i64,
1024 obj_idx: i64,
1025 y: i64,
1026 ) -> Result<()> {
1027 let stage_i = stage as isize;
1028 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1029 return Ok(());
1030 }
1031 let stage_u = stage_i as usize;
1032 let obj_u = obj_idx as usize;
1033 {
1034 let obj = self.ensure_object_mut(stage_u, obj_u);
1035 obj.y = y;
1036 }
1037 self.sync_object_sprite(images, layers, stage_u, obj_u)
1038 }
1039
1040 pub fn object_set_patno(
1041 &mut self,
1042 images: &mut ImageManager,
1043 layers: &mut LayerManager,
1044 stage: i64,
1045 obj_idx: i64,
1046 patno: i64,
1047 ) -> Result<()> {
1048 let stage_i = stage as isize;
1049 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1050 return Ok(());
1051 }
1052 let stage_u = stage_i as usize;
1053 let obj_u = obj_idx as usize;
1054 {
1055 let obj = self.ensure_object_mut(stage_u, obj_u);
1056 obj.patno = patno;
1057 }
1058 self.sync_object_sprite(images, layers, stage_u, obj_u)
1059 }
1060
1061 pub fn object_set_layer(
1062 &mut self,
1063 images: &mut ImageManager,
1064 layers: &mut LayerManager,
1065 stage: i64,
1066 obj_idx: i64,
1067 layer_no: i64,
1068 ) -> Result<()> {
1069 let stage_i = stage as isize;
1070 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1071 return Ok(());
1072 }
1073 let stage_u = stage_i as usize;
1074 let obj_u = obj_idx as usize;
1075 {
1076 let obj = self.ensure_object_mut(stage_u, obj_u);
1077 obj.layer_no = layer_no;
1078 }
1079 self.sync_object_sprite(images, layers, stage_u, obj_u)
1080 }
1081
1082 pub fn object_set_order(
1083 &mut self,
1084 images: &mut ImageManager,
1085 layers: &mut LayerManager,
1086 stage: i64,
1087 obj_idx: i64,
1088 order: i64,
1089 ) -> Result<()> {
1090 let stage_i = stage as isize;
1091 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1092 return Ok(());
1093 }
1094 let stage_u = stage_i as usize;
1095 let obj_u = obj_idx as usize;
1096 {
1097 let obj = self.ensure_object_mut(stage_u, obj_u);
1098 obj.order = order;
1099 }
1100 self.sync_object_sprite(images, layers, stage_u, obj_u)
1101 }
1102
1103 pub fn object_set_alpha(
1104 &mut self,
1105 images: &mut ImageManager,
1106 layers: &mut LayerManager,
1107 stage: i64,
1108 obj_idx: i64,
1109 alpha: i64,
1110 ) -> Result<()> {
1111 let stage_i = stage as isize;
1112 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1113 return Ok(());
1114 }
1115 let stage_u = stage_i as usize;
1116 let obj_u = obj_idx as usize;
1117 {
1118 let obj = self.ensure_object_mut(stage_u, obj_u);
1119 obj.alpha = alpha;
1120 }
1121 self.sync_object_sprite(images, layers, stage_u, obj_u)
1122 }
1123
1124 pub fn object_set_tr(
1125 &mut self,
1126 images: &mut ImageManager,
1127 layers: &mut LayerManager,
1128 stage: i64,
1129 obj_idx: i64,
1130 tr: i64,
1131 ) -> Result<()> {
1132 let stage_i = stage as isize;
1133 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1134 return Ok(());
1135 }
1136 let stage_u = stage_i as usize;
1137 let obj_u = obj_idx as usize;
1138 {
1139 let obj = self.ensure_object_mut(stage_u, obj_u);
1140 obj.tr = tr;
1141 }
1142 self.sync_object_sprite(images, layers, stage_u, obj_u)
1143 }
1144
1145 pub fn object_set_mono(
1146 &mut self,
1147 images: &mut ImageManager,
1148 layers: &mut LayerManager,
1149 stage: i64,
1150 obj_idx: i64,
1151 mono: i64,
1152 ) -> Result<()> {
1153 let stage_i = stage as isize;
1154 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1155 return Ok(());
1156 }
1157 let stage_u = stage_i as usize;
1158 let obj_u = obj_idx as usize;
1159 {
1160 let obj = self.ensure_object_mut(stage_u, obj_u);
1161 obj.mono = mono;
1162 }
1163 self.sync_object_sprite(images, layers, stage_u, obj_u)
1164 }
1165
1166 pub fn object_set_reverse(
1167 &mut self,
1168 images: &mut ImageManager,
1169 layers: &mut LayerManager,
1170 stage: i64,
1171 obj_idx: i64,
1172 reverse: i64,
1173 ) -> Result<()> {
1174 let stage_i = stage as isize;
1175 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1176 return Ok(());
1177 }
1178 let stage_u = stage_i as usize;
1179 let obj_u = obj_idx as usize;
1180 {
1181 let obj = self.ensure_object_mut(stage_u, obj_u);
1182 obj.reverse = reverse;
1183 }
1184 self.sync_object_sprite(images, layers, stage_u, obj_u)
1185 }
1186
1187 pub fn object_set_bright(
1188 &mut self,
1189 images: &mut ImageManager,
1190 layers: &mut LayerManager,
1191 stage: i64,
1192 obj_idx: i64,
1193 bright: i64,
1194 ) -> Result<()> {
1195 let stage_i = stage as isize;
1196 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1197 return Ok(());
1198 }
1199 let stage_u = stage_i as usize;
1200 let obj_u = obj_idx as usize;
1201 {
1202 let obj = self.ensure_object_mut(stage_u, obj_u);
1203 obj.bright = bright;
1204 }
1205 self.sync_object_sprite(images, layers, stage_u, obj_u)
1206 }
1207
1208 pub fn object_set_dark(
1209 &mut self,
1210 images: &mut ImageManager,
1211 layers: &mut LayerManager,
1212 stage: i64,
1213 obj_idx: i64,
1214 dark: i64,
1215 ) -> Result<()> {
1216 let stage_i = stage as isize;
1217 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1218 return Ok(());
1219 }
1220 let stage_u = stage_i as usize;
1221 let obj_u = obj_idx as usize;
1222 {
1223 let obj = self.ensure_object_mut(stage_u, obj_u);
1224 obj.dark = dark;
1225 }
1226 self.sync_object_sprite(images, layers, stage_u, obj_u)
1227 }
1228
1229 pub fn object_set_color_rate(
1230 &mut self,
1231 images: &mut ImageManager,
1232 layers: &mut LayerManager,
1233 stage: i64,
1234 obj_idx: i64,
1235 rate: i64,
1236 ) -> Result<()> {
1237 let stage_i = stage as isize;
1238 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1239 return Ok(());
1240 }
1241 let stage_u = stage_i as usize;
1242 let obj_u = obj_idx as usize;
1243 {
1244 let obj = self.ensure_object_mut(stage_u, obj_u);
1245 obj.color_rate = rate;
1246 }
1247 self.sync_object_sprite(images, layers, stage_u, obj_u)
1248 }
1249
1250 pub fn object_set_color_add(
1251 &mut self,
1252 images: &mut ImageManager,
1253 layers: &mut LayerManager,
1254 stage: i64,
1255 obj_idx: i64,
1256 r: i64,
1257 g: i64,
1258 b: i64,
1259 ) -> Result<()> {
1260 let stage_i = stage as isize;
1261 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1262 return Ok(());
1263 }
1264 let stage_u = stage_i as usize;
1265 let obj_u = obj_idx as usize;
1266 {
1267 let obj = self.ensure_object_mut(stage_u, obj_u);
1268 obj.color_add_r = r;
1269 obj.color_add_g = g;
1270 obj.color_add_b = b;
1271 }
1272 self.sync_object_sprite(images, layers, stage_u, obj_u)
1273 }
1274
1275 pub fn object_set_color(
1276 &mut self,
1277 images: &mut ImageManager,
1278 layers: &mut LayerManager,
1279 stage: i64,
1280 obj_idx: i64,
1281 r: i64,
1282 g: i64,
1283 b: i64,
1284 ) -> Result<()> {
1285 let stage_i = stage as isize;
1286 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1287 return Ok(());
1288 }
1289 let stage_u = stage_i as usize;
1290 let obj_u = obj_idx as usize;
1291 {
1292 let obj = self.ensure_object_mut(stage_u, obj_u);
1293 obj.color_r = r;
1294 obj.color_g = g;
1295 obj.color_b = b;
1296 }
1297 self.sync_object_sprite(images, layers, stage_u, obj_u)
1298 }
1299
1300 pub fn object_set_blend(
1301 &mut self,
1302 images: &mut ImageManager,
1303 layers: &mut LayerManager,
1304 stage: i64,
1305 obj_idx: i64,
1306 blend: i64,
1307 ) -> Result<()> {
1308 let stage_i = stage as isize;
1309 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1310 return Ok(());
1311 }
1312 let stage_u = stage_i as usize;
1313 let obj_u = obj_idx as usize;
1314 {
1315 let obj = self.ensure_object_mut(stage_u, obj_u);
1316 obj.blend = blend;
1317 }
1318 self.sync_object_sprite(images, layers, stage_u, obj_u)
1319 }
1320
1321 pub fn object_set_light_no(
1322 &mut self,
1323 images: &mut ImageManager,
1324 layers: &mut LayerManager,
1325 stage: i64,
1326 obj_idx: i64,
1327 light_no: i64,
1328 ) -> Result<()> {
1329 let stage_i = stage as isize;
1330 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1331 return Ok(());
1332 }
1333 let stage_u = stage_i as usize;
1334 let obj_u = obj_idx as usize;
1335 {
1336 let obj = self.ensure_object_mut(stage_u, obj_u);
1337 obj.light_no = light_no;
1338 }
1339 self.sync_object_sprite(images, layers, stage_u, obj_u)
1340 }
1341
1342 pub fn object_set_fog_use(
1343 &mut self,
1344 images: &mut ImageManager,
1345 layers: &mut LayerManager,
1346 stage: i64,
1347 obj_idx: i64,
1348 fog_use: i64,
1349 ) -> Result<()> {
1350 let stage_i = stage as isize;
1351 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1352 return Ok(());
1353 }
1354 let stage_u = stage_i as usize;
1355 let obj_u = obj_idx as usize;
1356 {
1357 let obj = self.ensure_object_mut(stage_u, obj_u);
1358 obj.fog_use = fog_use;
1359 }
1360 self.sync_object_sprite(images, layers, stage_u, obj_u)
1361 }
1362
1363 pub fn object_set_z(&mut self, stage: i64, obj_idx: i64, z: i64) -> Result<()> {
1364 let stage_i = stage as isize;
1365 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1366 return Ok(());
1367 }
1368 let stage_u = stage_i as usize;
1369 let obj_u = obj_idx as usize;
1370 let obj = self.ensure_object_mut(stage_u, obj_u);
1371 obj.z = z;
1372 Ok(())
1373 }
1374
1375 pub fn object_clear(
1376 &mut self,
1377 images: &mut ImageManager,
1378 layers: &mut LayerManager,
1379 stage: i64,
1380 obj_idx: i64,
1381 ) -> Result<()> {
1382 let stage_i = stage as isize;
1383 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1384 return Ok(());
1385 }
1386 let stage_u = stage_i as usize;
1387 let obj_u = obj_idx as usize;
1388 {
1389 let obj = self.ensure_object_mut(stage_u, obj_u);
1390 obj.file = None;
1391 obj.patno = 0;
1392 obj.disp = false;
1393 obj.alpha = 255;
1394 }
1395 let _ = self.sync_object_sprite(images, layers, stage_u, obj_u);
1396 Ok(())
1397 }
1398
1399 pub fn clear_objects_in_layer_no(
1400 &mut self,
1401 images: &mut ImageManager,
1402 layers: &mut LayerManager,
1403 layer_no: i64,
1404 ) -> Result<()> {
1405 for stage in 0..3usize {
1406 let len = self.stages[stage].objects.len();
1407 for obj_idx in 0..len {
1408 let matches = self
1409 .object(stage, obj_idx)
1410 .map(|o| o.layer_no == layer_no)
1411 .unwrap_or(false);
1412 if !matches {
1413 continue;
1414 }
1415 {
1416 let obj = self.ensure_object_mut(stage, obj_idx);
1417 obj.disp = false;
1418 }
1419 let _ = self.sync_object_sprite(images, layers, stage, obj_idx);
1420 }
1421 }
1422 Ok(())
1423 }
1424
1425 pub fn object_get_pos(&self, stage: i64, obj_idx: i64) -> Option<(i64, i64)> {
1426 self.object_peek_pos(stage, obj_idx)
1427 }
1428
1429 pub fn object_get_disp(&self, stage: i64, obj_idx: i64) -> Option<bool> {
1430 self.object_peek_disp(stage, obj_idx).map(|v| v != 0)
1431 }
1432
1433 pub fn object_get_patno(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1434 self.object_peek_patno(stage, obj_idx)
1435 }
1436
1437 pub fn object_get_layer(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1438 self.object_peek_layer(stage, obj_idx)
1439 }
1440
1441 pub fn object_get_order(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1442 self.object_peek_order(stage, obj_idx)
1443 }
1444
1445 pub fn object_get_alpha(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1446 self.object_peek_alpha(stage, obj_idx)
1447 }
1448
1449 pub fn object_set_pat_no(
1450 &mut self,
1451 images: &mut ImageManager,
1452 layers: &mut LayerManager,
1453 stage: i64,
1454 obj_idx: i64,
1455 patno: i64,
1456 ) -> Result<()> {
1457 self.object_set_patno(images, layers, stage, obj_idx, patno)
1458 }
1459
1460 pub fn object_peek_pos(&self, stage: i64, obj_idx: i64) -> Option<(i64, i64)> {
1461 let stage_i = stage as isize;
1462 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1463 return None;
1464 }
1465 let stage_u = stage_i as usize;
1466 let obj_u = obj_idx as usize;
1467 let obj = self.object(stage_u, obj_u)?;
1468 Some((obj.x, obj.y))
1469 }
1470
1471 pub fn object_peek_disp(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1472 let stage_i = stage as isize;
1473 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1474 return None;
1475 }
1476 let stage_u = stage_i as usize;
1477 let obj_u = obj_idx as usize;
1478 let obj = self.object(stage_u, obj_u)?;
1479 Some(if obj.disp { 1 } else { 0 })
1480 }
1481
1482 pub fn object_peek_patno(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1483 let stage_i = stage as isize;
1484 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1485 return None;
1486 }
1487 let stage_u = stage_i as usize;
1488 let obj_u = obj_idx as usize;
1489 let obj = self.object(stage_u, obj_u)?;
1490 Some(obj.patno)
1491 }
1492
1493 pub fn object_peek_layer(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1494 let stage_i = stage as isize;
1495 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1496 return None;
1497 }
1498 let stage_u = stage_i as usize;
1499 let obj_u = obj_idx as usize;
1500 let obj = self.object(stage_u, obj_u)?;
1501 Some(obj.layer_no)
1502 }
1503
1504 pub fn object_peek_order(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1505 let stage_i = stage as isize;
1506 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1507 return None;
1508 }
1509 let stage_u = stage_i as usize;
1510 let obj_u = obj_idx as usize;
1511 let obj = self.object(stage_u, obj_u)?;
1512 Some(obj.order)
1513 }
1514
1515 pub fn object_peek_alpha(&self, stage: i64, obj_idx: i64) -> Option<i64> {
1516 let stage_i = stage as isize;
1517 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1518 return None;
1519 }
1520 let stage_u = stage_i as usize;
1521 let obj_u = obj_idx as usize;
1522 let obj = self.object(stage_u, obj_u)?;
1523 Some(obj.alpha)
1524 }
1525
1526 pub fn object_peek_file(&self, stage: i64, obj_idx: i64) -> Option<String> {
1527 let stage_i = stage as isize;
1528 if !(0..3).contains(&stage_i) || obj_idx < 0 {
1529 return None;
1530 }
1531 let stage_u = stage_i as usize;
1532 let obj_u = obj_idx as usize;
1533 let obj = self.object(stage_u, obj_u)?;
1534 obj.file.clone()
1535 }
1536}
1537
1538fn is_probable_mesh_path(file: &str) -> bool {
1539 let lower = file.to_ascii_lowercase();
1540 lower.ends_with(".x")
1541 || lower.ends_with(".obj")
1542 || lower.ends_with(".fbx")
1543 || lower.ends_with(".gltf")
1544 || lower.ends_with(".glb")
1545}
1546
1547
1548fn set_object_sprite_image(sprite: &mut Sprite, images: &ImageManager, image_id: ImageId) {
1549 sprite.image_id = Some(image_id);
1550 if let Some(img) = images.get(image_id) {
1551 sprite.object_anchor = true;
1552 sprite.texture_center_x = img.center_x as f32;
1553 sprite.texture_center_y = img.center_y as f32;
1554 } else {
1555 sprite.object_anchor = false;
1556 sprite.texture_center_x = 0.0;
1557 sprite.texture_center_y = 0.0;
1558 }
1559}
1560
1561fn clip_rect(use_flag: i64, left: i64, top: i64, right: i64, bottom: i64) -> Option<ClipRect> {
1562 if use_flag == 0 {
1563 return None;
1564 }
1565 Some(ClipRect {
1566 left: left as i32,
1567 top: top as i32,
1568 right: right as i32,
1569 bottom: bottom as i32,
1570 })
1571}