Skip to content

Commit

Permalink
Move scene background handling to CANVAS_OBSERVER
Browse files Browse the repository at this point in the history
Fix path handling when loading BKG/BGM for a scene
  • Loading branch information
Dove6 committed Aug 26, 2024
1 parent b1fbffa commit df2d83d
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 76 deletions.
38 changes: 18 additions & 20 deletions pixlib/src/plugins/graphics_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,11 @@ pub fn assign_pool(mut query: Query<&mut GraphicsMarker>, runner: NonSend<Script
// runner.find_objects(|_| true, &mut all_objects);
// let all_objects: Vec<String> = all_objects.iter().map(|o| o.name.clone()).collect();
// info!("All loaded objects: {:?}", all_objects);
let mut background_assigned = false;
let mut image_counter = 0;
let mut animation_counter = 0;
let mut iter = query.iter_mut();
// info!("Current scene: {:?}", runner.get_current_scene());
if let Some(current_scene) = runner.get_current_scene() {
let CnvContent::Scene(ref current_scene) = &current_scene.content else {
panic!();
};
if current_scene.has_background_image() {
*iter.next().unwrap() = GraphicsMarker::BackgroundImage;
background_assigned = true;
}
}
*iter.next().unwrap() = GraphicsMarker::BackgroundImage;
for (script_index, script) in runner.scripts.borrow().iter().enumerate() {
for (object_index, object) in script.objects.borrow().iter().enumerate() {
if !matches!(&object.content, CnvContent::Image(_)) {
Expand Down Expand Up @@ -180,10 +171,8 @@ pub fn assign_pool(mut query: Query<&mut GraphicsMarker>, runner: NonSend<Script
}
}
info!(
"Assigned {} background, {} images and {} animations",
if background_assigned { "a" } else { "no" },
image_counter,
animation_counter
"Assigned {} images and {} animations",
image_counter, animation_counter
);
}

Expand All @@ -206,20 +195,29 @@ pub fn update_background(
continue;
}
// info!("Current scene: {:?}", runner.get_current_scene());
let Some(scene_object) = runner.get_current_scene() else {
let Some(canvas_observer_object) =
runner.find_object(|o| matches!(&o.content, CnvContent::CanvasObserver(_)))
else {
continue;
};
let CnvContent::Scene(ref scene) = &scene_object.content else {
panic!();
let CnvContent::CanvasObserver(ref canvas_observer) = &canvas_observer_object.content
else {
unreachable!();
};
let Ok((image_definition, image_data)) = scene.get_background_to_show() else {
let result = canvas_observer.get_background_to_show();
let Ok(background_data) = result else {
eprintln!(
"Error getting background image for scene {}",
scene_object.name
"Error getting background image for scene {}: {:?}",
canvas_observer_object.name,
result.unwrap_err()
);
*visibility = Visibility::Hidden;
continue;
};
let Some((image_definition, image_data)) = background_data else {
*visibility = Visibility::Hidden;
continue;
};
sprite.flip_x = false;
sprite.flip_y = false;
sprite.anchor = Anchor::TopLeft;
Expand Down
4 changes: 4 additions & 0 deletions pixlib_parser/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
error::Error,
fmt::Display,
ops::Add,
sync::{RwLockReadGuard, RwLockWriteGuard},
};

#[derive(Clone, Debug, PartialEq, Eq, Copy)]
Expand Down Expand Up @@ -185,6 +186,9 @@ pub trait DroppableRefMut {
impl<T> DroppableRefMut for RefMut<'_, T> {}
impl<T> DroppableRefMut for Ref<'_, T> {}

impl<T> DroppableRefMut for RwLockWriteGuard<'_, T> {}
impl<T> DroppableRefMut for RwLockReadGuard<'_, T> {}

pub trait RemoveSearchable<T> {
fn remove_found<P: FnMut(&T) -> bool>(&mut self, predicate: P) -> Option<T>;
}
Expand Down
151 changes: 125 additions & 26 deletions pixlib_parser/src/runner/classes/canvasobserver.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{any::Any, cell::RefCell};
use lazy_static::lazy_static;
use pixlib_formats::file_formats::img::parse_img;
use std::any::Any;
use std::sync::RwLock;
use xxhash_rust::xxh3::xxh3_64;

use super::super::content::EventHandler;
use super::super::initable::Initable;
Expand Down Expand Up @@ -29,7 +33,7 @@ struct CanvasObserverState {
// deduced from methods
background_data: ImageFileData,
background_position: (isize, isize),
graphics: Vec<Arc<CnvObject>>,
// graphics: Vec<Arc<CnvObject>>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -62,11 +66,18 @@ impl EventHandler for CanvasObserverEventHandlers {
}
}

lazy_static! {
static ref GLOBAL_CANVAS_OBSERVER_STATE: Arc<RwLock<CanvasObserverState>> =
Arc::new(RwLock::new(CanvasObserverState {
..Default::default()
}));
}

#[derive(Debug, Clone)]
pub struct CanvasObserver {
parent: Arc<CnvObject>,

state: RefCell<CanvasObserverState>,
state: Arc<RwLock<CanvasObserverState>>,
event_handlers: CanvasObserverEventHandlers,
}

Expand All @@ -77,9 +88,7 @@ impl CanvasObserver {
) -> Self {
Self {
parent,
state: RefCell::new(CanvasObserverState {
..Default::default()
}),
state: Arc::clone(&GLOBAL_CANVAS_OBSERVER_STATE),
event_handlers: CanvasObserverEventHandlers {
on_done: props.on_done,
on_init: props.on_init,
Expand All @@ -93,6 +102,36 @@ impl CanvasObserver {
},
}
}

pub fn set_background_data(&self, background_data: ImageFileData) -> anyhow::Result<()> {
GLOBAL_CANVAS_OBSERVER_STATE
.write()
.unwrap()
.use_and_drop_mut(|state| state.background_data = background_data);
Ok(())
}

pub fn get_background_to_show(&self) -> anyhow::Result<Option<(ImageDefinition, ImageData)>> {
let runner = &self.parent.parent.runner;
let mut state = GLOBAL_CANVAS_OBSERVER_STATE.write().unwrap();
if let ImageFileData::NotLoaded(filename) = &state.background_data {
let Some(current_scene) = runner.get_current_scene() else {
return Ok(None);
};
let CnvContent::Scene(current_scene) = &current_scene.content else {
unreachable!();
};
let path = ScenePath::new(&current_scene.get_script_path().unwrap(), filename);
state.load_background(runner, &path)?;
} else if let ImageFileData::Empty = &state.background_data {
return Ok(None);
}
let ImageFileData::Loaded(loaded_background) = &state.background_data else {
unreachable!();
};
let image = &loaded_background.image;
Ok(Some((image.0.clone(), image.1.clone())))
}
}

impl CnvType for CanvasObserver {
Expand All @@ -117,54 +156,66 @@ impl CnvType for CanvasObserver {
// println!("Calling method: {:?} of object: {:?}", name, self);
match name {
CallableIdentifier::Method("ADD") => {
self.state.borrow_mut().add().map(|_| CnvValue::Null)
self.state.write().unwrap().add().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("ENABLENOTIFY") => self
.state
.borrow_mut()
.write()
.unwrap()
.enable_notify()
.map(|_| CnvValue::Null),
CallableIdentifier::Method("GETBPP") => self
.state
.borrow()
.read()
.unwrap()
.get_bpp()
.map(|v| CnvValue::Integer(v as i32)),
CallableIdentifier::Method("GETGRAPHICSAT") => self
.state
.borrow()
.read()
.unwrap()
.get_graphics_at()
.map(|v| v.map(CnvValue::String).unwrap_or_default()),
CallableIdentifier::Method("GETGRAPHICSAT2") => self
.state
.borrow()
.read()
.unwrap()
.get_graphics_at2()
.map(|v| v.map(CnvValue::String).unwrap_or_default()),
CallableIdentifier::Method("MOVEBKG") => {
self.state.borrow_mut().move_bkg().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("MOVEBKG") => self
.state
.write()
.unwrap()
.move_bkg()
.map(|_| CnvValue::Null),
CallableIdentifier::Method("PASTE") => {
self.state.borrow_mut().paste().map(|_| CnvValue::Null)
self.state.write().unwrap().paste().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("REDRAW") => {
self.state.borrow_mut().redraw().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("REFRESH") => {
self.state.borrow_mut().refresh().map(|_| CnvValue::Null)
self.state.write().unwrap().redraw().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("REFRESH") => self
.state
.write()
.unwrap()
.refresh()
.map(|_| CnvValue::Null),
CallableIdentifier::Method("REMOVE") => {
self.state.borrow_mut().remove().map(|_| CnvValue::Null)
self.state.write().unwrap().remove().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("SAVE") => {
self.state.borrow_mut().save().map(|_| CnvValue::Null)
self.state.write().unwrap().save().map(|_| CnvValue::Null)
}
CallableIdentifier::Method("SETBACKGROUND") => self
.state
.borrow_mut()
.set_background()
.write()
.unwrap()
.set_background(context, &arguments[0].to_str())
.map(|_| CnvValue::Null),
CallableIdentifier::Method("SETBKGPOS") => self
.state
.borrow_mut()
.write()
.unwrap()
.set_bkg_pos()
.map(|_| CnvValue::Null),
CallableIdentifier::Event(event_name) => {
Expand Down Expand Up @@ -323,13 +374,61 @@ impl CanvasObserverState {
todo!()
}

pub fn set_background(&mut self) -> anyhow::Result<()> {
pub fn set_background(
&mut self,
context: RunnerContext,
object_name: &str,
) -> anyhow::Result<()> {
// SETBACKGROUND
todo!()
let Some(object) = context.runner.get_object(object_name) else {
return Err(RunnerError::ObjectNotFound {
name: object_name.to_owned(),
}
.into());
};
let CnvContent::Image(image) = &object.content else {
return Err(RunnerError::ExpectedGraphicsObject.into());
};
self.background_data = image.get_file_data()?;
Ok(())
}

pub fn set_bkg_pos(&mut self) -> anyhow::Result<()> {
// SETBKGPOS
todo!()
}

// custom

pub fn load_background(
&mut self,
runner: &Arc<CnvRunner>,
path: &ScenePath,
) -> anyhow::Result<()> {
let filesystem = Arc::clone(&runner.filesystem);
let data = filesystem
.borrow_mut()
.read_scene_asset(Arc::clone(&runner.game_paths), path)
.map_err(|_| RunnerError::IoError {
source: std::io::Error::from(std::io::ErrorKind::NotFound),
})?;
let data = parse_img(&data);
let converted_data = data
.image_data
.to_rgba8888(data.header.color_format, data.header.compression_type);
self.background_data = ImageFileData::Loaded(LoadedImage {
filename: Some(path.file_path.to_str()),
image: (
ImageDefinition {
size_px: (data.header.width_px, data.header.height_px),
offset_px: (data.header.x_position_px, data.header.y_position_px),
},
ImageData {
hash: xxh3_64(&converted_data),
data: converted_data,
},
),
});
Ok(())
}
}
4 changes: 4 additions & 0 deletions pixlib_parser/src/runner/classes/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ impl Image {
let image = &loaded_data.image;
Ok(Some((image.0.clone(), image.1.clone())))
}

pub fn get_file_data(&self) -> anyhow::Result<ImageFileData> {
Ok(self.state.borrow().file_data.clone())
}
}

impl GeneralGraphics for Image {
Expand Down
Loading

0 comments on commit df2d83d

Please sign in to comment.