Skip to content

Commit

Permalink
Implement Animation::set_frame (partially), Array::add and Text::set_…
Browse files Browse the repository at this point in the history
…priority

Come up with better (less conflicting) naming for animatino objects created when parsing SEQ files
  • Loading branch information
Dove6 committed Aug 26, 2024
1 parent 7a6edec commit 119125b
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 52 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pixlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ zip = { version = "2.1", default-features = false, features = [
"deflate",
"time",
] }
log = "0.4"
chrono = "0.4"
31 changes: 31 additions & 0 deletions pixlib/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use bevy::{
DefaultPlugins,
};
use bevy_kira_audio::AudioPlugin;
use chrono::Utc;
use filesystems::{InsertedDisk, InsertedDiskResource};
use pixlib_parser::{common::IssueManager, runner::ObjectBuilderError};
use plugins::{
Expand All @@ -38,6 +39,36 @@ pub enum AppState {
SceneViewer,
}

use log::{Level, Metadata, Record};
use log::{LevelFilter, SetLoggerError};

struct SimpleLogger;

impl log::Log for SimpleLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Info
}

fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!(
"{} {} - {}",
Utc::now().format("%+"),
record.level(),
record.args()
);
}
}

fn flush(&self) {}
}

static LOGGER: SimpleLogger = SimpleLogger;

pub fn init() -> Result<(), SetLoggerError> {
log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Info))
}

#[allow(clippy::arc_with_non_send_sync)]
fn main() {
let mut issue_manager: IssueManager<ObjectBuilderError> = Default::default();
Expand Down
12 changes: 5 additions & 7 deletions pixlib/src/plugins/graphics_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use bevy::{
use pixlib_parser::runner::{classes::GeneralGraphics, CnvContent, ScenePath, ScriptEvent};

use crate::{
util::{add_tuples, animation_data_to_handle, image_data_to_handle},
util::{animation_data_to_handle, image_data_to_handle},
AppState,
};

Expand Down Expand Up @@ -346,7 +346,7 @@ pub fn update_animations(
else {
continue;
};
let Some((frame_definition, sprite_definition, sprite_data)) = frame_to_show else {
let Some((rect, sprite_data)) = frame_to_show else {
*visibility = Visibility::Hidden;
continue;
};
Expand All @@ -355,21 +355,19 @@ pub fn update_animations(
} else {
Visibility::Hidden
};
let total_offset = add_tuples(sprite_definition.offset_px, frame_definition.offset_px);
sprite.flip_x = false;
sprite.flip_y = false;
sprite.anchor = Anchor::TopLeft;
let base_position = animation.get_base_position().unwrap();
*transform = Transform::from_xyz(
base_position.0 as f32 + total_offset.0 as f32,
base_position.1 as f32 + total_offset.1 as f32,
rect.top_left_x as f32,
rect.top_left_y as f32,
animation.get_priority().unwrap() as f32
+ (*script_index as f32) / 100f32
+ (*object_index as f32) / 100000f32,
)
.with_scale(Vec3::new(1f32, -1f32, 1f32));
if !ident.0.is_some_and(|h| h == sprite_data.hash) {
*handle = animation_data_to_handle(&mut textures, &sprite_definition, &sprite_data);
*handle = animation_data_to_handle(&mut textures, rect, &sprite_data);
ident.0 = Some(sprite_data.hash);
// info!(
// "Updated animation {} with priority {} to position ({}, {})+({}, {})+({}, {})",
Expand Down
22 changes: 14 additions & 8 deletions pixlib/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use std::ops::Add;

use pixlib_parser::{
common::{Issue, IssueHandler, IssueKind},
runner::common::{ImageData, ImageDefinition, SpriteData, SpriteDefinition},
runner::{
common::{ImageData, ImageDefinition, SpriteData},
Rect,
},
};

pub fn image_data_to_handle(
Expand All @@ -36,13 +39,13 @@ pub fn image_data_to_handle(

pub fn animation_data_to_handle(
textures: &mut Assets<Image>,
sprite_definition: &SpriteDefinition,
rect: Rect,
sprite_data: &SpriteData,
) -> Handle<Image> {
textures.add(Image::new(
Extent3d {
width: sprite_definition.size_px.0,
height: sprite_definition.size_px.1,
width: rect.get_width() as u32,
height: rect.get_height() as u32,
depth_or_array_layers: 1,
},
bevy::render::render_resource::TextureDimension::D2,
Expand All @@ -64,10 +67,13 @@ impl<I: Issue> IssueHandler<I> for IssuePrinter {
}
}

pub fn add_tuples<T: Add>(
a: (T, T),
b: (T, T),
) -> (<T as std::ops::Add>::Output, <T as std::ops::Add>::Output) {
pub fn add_tuples<TR, TL: Add<TR>>(
a: (TL, TL),
b: (TR, TR),
) -> (
<TL as std::ops::Add<TR>>::Output,
<TL as std::ops::Add<TR>>::Output,
) {
(a.0 + b.0, a.1 + b.1)
}

Expand Down
1 change: 1 addition & 0 deletions pixlib_parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ xxhash-rust = { version = "0.8", default-features = false, features = ["xxh3"] }
keyboard-types = "0.7"
rand = "0.8"
libm = "0.2"
log = "0.4"

[build-dependencies]
lalrpop = "0.20"
Expand Down
22 changes: 22 additions & 0 deletions pixlib_parser/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,25 @@ impl<T> RemoveSearchable<T> for Vec<T> {
self.iter().position(predicate).map(|idx| self.remove(idx))
}
}

pub fn add_tuples<TR, TL: Add<TR>>(
a: (TL, TL),
b: (TR, TR),
) -> (
<TL as std::ops::Add<TR>>::Output,
<TL as std::ops::Add<TR>>::Output,
) {
(a.0 + b.0, a.1 + b.1)
}

pub fn pair_u32_to_usize(pair: (u32, u32)) -> (usize, usize) {
(pair.0 as usize, pair.1 as usize)
}

pub fn pair_u32_to_isize(pair: (u32, u32)) -> (isize, isize) {
(pair.0 as isize, pair.1 as isize)
}

pub fn pair_i32_to_isize(pair: (i32, i32)) -> (isize, isize) {
(pair.0 as isize, pair.1 as isize)
}
98 changes: 73 additions & 25 deletions pixlib_parser/src/runner/classes/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{any::Any, cell::RefCell, sync::Arc};
use xxhash_rust::xxh3::xxh3_64;

use crate::{
common::DroppableRefMut,
common::{add_tuples, pair_i32_to_isize, pair_u32_to_usize, DroppableRefMut},
parser::ast::ParsedScript,
runner::{InternalEvent, RunnerError},
};
Expand Down Expand Up @@ -72,6 +72,7 @@ struct AnimationState {
pub is_paused: bool,
pub is_reversed: bool,
pub current_frame: FrameIdentifier,
pub sprite_idx_override: Option<usize>,
// more temporary
pub current_frame_duration: f64,

Expand Down Expand Up @@ -253,9 +254,7 @@ impl Animation {
self.state.borrow_mut().step(context, seconds)
}

pub fn get_frame_to_show(
&self,
) -> anyhow::Result<Option<(FrameDefinition, SpriteDefinition, SpriteData)>> {
pub fn get_frame_to_show(&self) -> anyhow::Result<Option<(Rect, SpriteData)>> {
// eprintln!("[ANIMO: {}] is_visible: {}", self.parent.name, self.is_visible);
let context = RunnerContext::new_minimal(&self.parent.parent.runner, &self.parent);
self.state
Expand All @@ -268,6 +267,21 @@ impl Animation {
let AnimationFileData::Loaded(ref loaded_data) = *state.file_data else {
return Ok(None);
};
if loaded_data.sprites.is_empty() {
return Ok(None);
}
if let Some(sprite_idx_override) = state.sprite_idx_override {
let Some(sprite) = loaded_data.sprites.get(sprite_idx_override) else {
return Err(RunnerError::SpriteIndexNotFound {
object_name: context.current_object.name.clone(),
index: sprite_idx_override,
}
.into());
};
let position = add_tuples(state.position, pair_i32_to_isize(sprite.0.offset_px));
let size = pair_u32_to_usize(sprite.0.size_px);
return Ok(Some((Rect::from(position, size), sprite.1.clone())));
};
if loaded_data.sequences.is_empty() {
return Ok(None);
}
Expand All @@ -290,8 +304,11 @@ impl Animation {
}
.into());
};
let position = add_tuples(state.position, pair_i32_to_isize(sprite.0.offset_px));
let position = add_tuples(position, pair_i32_to_isize(frame.offset_px));
let size = pair_u32_to_usize(sprite.0.size_px);
// eprintln!("[ANIMO: {}] [current frame] position: {:?} + {:?}, hash: {:?}", self.parent.name, sprite.0.offset_px, frame.offset_px, sprite.1.hash);
Ok(Some((frame.clone(), sprite.0.clone(), sprite.1.clone())))
Ok(Some((Rect::from(position, size), sprite.1.clone())))
}

pub fn play(&self, sequence_name: &str) -> anyhow::Result<()> {
Expand Down Expand Up @@ -773,7 +790,7 @@ impl CnvType for Animation {
// }
self.state
.borrow_mut()
.set_frame(sequence_name.as_deref(), frame_no.max(0) as usize)
.set_frame(context, sequence_name.as_deref(), frame_no.max(0) as usize)
.map(|_| CnvValue::Null)
}
CallableIdentifier::Method("SETFRAMENAME") => self
Expand Down Expand Up @@ -1321,7 +1338,11 @@ impl AnimationState {
})?;
let data = parse_ann(&data);
self.current_frame = FrameIdentifier {
sequence_idx: data.sequences.len().saturating_sub(1),
sequence_idx: data
.sequences
.iter()
.position(|s| !s.frames.is_empty())
.unwrap_or_default(),
frame_idx: 0,
};
self.file_data = Arc::new(AnimationFileData::Loaded(LoadedAnimation {
Expand Down Expand Up @@ -1582,14 +1603,19 @@ impl AnimationState {

pub fn set_frame(
&mut self,
context: RunnerContext,
sequence_name: Option<&str>,
frame_no: usize,
) -> anyhow::Result<()> {
// SETFRAME ([STRING], INTEGER)
self.load_if_needed(context)?;
let AnimationFileData::Loaded(ref loaded_data) = *self.file_data else {
return Ok(());
};
if let Some(_sequence_name) = sequence_name {
todo!()
} else {
self.current_frame.frame_idx = frame_no;
} else if loaded_data.sprites.len() > frame_no {
self.sprite_idx_override = Some(frame_no);
}
Ok(())
}
Expand Down Expand Up @@ -1697,38 +1723,27 @@ impl AnimationState {
}

pub fn get_frame_position(&self, context: RunnerContext) -> anyhow::Result<(isize, isize)> {
let (_, frame, sprite) = self.get_sprite_data(context)?;
let (_, frame, sprite) = self.get_frame_sprite_data(context)?;
Ok((
self.position.0 + frame.offset_px.0 as isize + sprite.0.offset_px.0 as isize,
self.position.1 + frame.offset_px.1 as isize + sprite.0.offset_px.1 as isize,
))
}

pub fn get_frame_size(&self, context: RunnerContext) -> anyhow::Result<(usize, usize)> {
let (_, _, sprite) = self.get_sprite_data(context)?;
let (_, _, sprite) = self.get_frame_sprite_data(context)?;
Ok((sprite.0.size_px.0 as usize, sprite.0.size_px.1 as usize))
}

pub fn get_frame_rect(&self, context: RunnerContext) -> anyhow::Result<Rect> {
let (_, frame, sprite) = self.get_sprite_data(context)?;
let position = (
self.position.0 + frame.offset_px.0 as isize + sprite.0.offset_px.0 as isize,
self.position.1 + frame.offset_px.1 as isize + sprite.0.offset_px.1 as isize,
);
let size = (sprite.0.size_px.0 as isize, sprite.0.size_px.1 as isize);
Ok(Rect {
top_left_x: position.0,
top_left_y: position.1,
bottom_right_x: position.0 + size.0,
bottom_right_y: position.1 + size.1,
})
self.get_sprite_data(context).map(|d| d.0)
}

pub fn get_center_frame_position(
&self,
context: RunnerContext,
) -> anyhow::Result<(isize, isize)> {
let (_, frame, sprite) = self.get_sprite_data(context)?;
let (_, frame, sprite) = self.get_frame_sprite_data(context)?;
Ok((
self.position.0
+ frame.offset_px.0 as isize
Expand Down Expand Up @@ -1773,7 +1788,7 @@ impl AnimationState {
Ok((sequence, frame))
}

fn get_sprite_data(
fn get_frame_sprite_data(
&self,
context: RunnerContext,
) -> anyhow::Result<(
Expand All @@ -1797,6 +1812,38 @@ impl AnimationState {
Ok((sequence, frame, sprite))
}

fn get_sprite_data(&self, context: RunnerContext) -> anyhow::Result<(Rect, SpriteData)> {
let AnimationFileData::Loaded(ref loaded_file) = *self.file_data else {
return Err(
RunnerError::NoAnimationDataLoaded(context.current_object.name.clone()).into(),
);
};
if let Some(sprite_idx_override) = self.sprite_idx_override {
let Some(sprite) = loaded_file.sprites.get(sprite_idx_override) else {
return Err(RunnerError::SpriteIndexNotFound {
object_name: context.current_object.name.clone(),
index: sprite_idx_override,
}
.into());
};
let position = add_tuples(self.position, pair_i32_to_isize(sprite.0.offset_px));
let size = pair_u32_to_usize(sprite.0.size_px);
return Ok((Rect::from(position, size), sprite.1.clone()));
};
let (_, frame) = self.get_frame_data(context.clone())?;
let Some(sprite) = loaded_file.sprites.get(frame.sprite_idx) else {
return Err(RunnerError::SpriteIndexNotFound {
object_name: context.current_object.name.clone(),
index: frame.sprite_idx,
}
.into());
};
let position = add_tuples(self.position, pair_i32_to_isize(sprite.0.offset_px));
let position = add_tuples(position, pair_i32_to_isize(frame.offset_px));
let size = pair_u32_to_usize(sprite.0.size_px);
Ok((Rect::from(position, size), sprite.1.clone()))
}

pub fn step(&mut self, context: RunnerContext, seconds: f64) -> anyhow::Result<()> {
let file_data = self.file_data.clone();
let AnimationFileData::Loaded(ref loaded_data) = *file_data else {
Expand All @@ -1806,6 +1853,7 @@ impl AnimationState {
return Ok(());
}
// eprintln!("Ticking animation {} with time {}, current frame: {:?}", animation.parent.name, duration, self.current_frame);
self.sprite_idx_override = None;
let sequence = &loaded_data.sequences[self.current_frame.sequence_idx];
let sequence_looping = sequence.looping;
let sequence_length = sequence.frames.len();
Expand Down
Loading

0 comments on commit 119125b

Please sign in to comment.