Skip to content

Commit

Permalink
Add configuration to flip node (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbrea-c committed Feb 14, 2024
1 parent cf901d6 commit 320328c
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 69 deletions.
27 changes: 0 additions & 27 deletions .github/workflows/ci.yaml
Expand Up @@ -62,33 +62,6 @@ jobs:
- name: Run clippy
run: cargo clippy -- -D warnings

# Run cargo publish pipeline as a dry run
dry_run:
name: Dry Run Publish
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.toml') }}
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install Dependencies
run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev
- name: Run cargo publish dry run for library
run: cargo publish --dry-run -p bevy_animation_graph
- name: Run cargo publish dry run for editor
run: cargo publish --dry-run -p bevy_animation_graph_editor

# Run cargo fmt --all -- --check
format:
name: Format
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/dry_run.yaml
@@ -0,0 +1,34 @@
name: DryRun

on: {}

env:
CARGO_TERM_COLOR: always

jobs:
# Run cargo publish pipeline as a dry run
dry_run:
name: Dry Run Publish
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.toml') }}
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install Dependencies
run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev
- name: Run cargo publish dry run for library
run: cargo publish --dry-run -p bevy_animation_graph
- name: Run cargo publish dry run for editor
run: cargo publish --dry-run -p bevy_animation_graph_editor
1 change: 1 addition & 0 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions assets/animation_graphs/human.animgraph.ron
Expand Up @@ -2,7 +2,7 @@
nodes: [
(
name: "Walk Flip LR",
node: FlipLR,
node: FlipLR(),
),
(
name: "Walk Clip",
Expand All @@ -18,7 +18,7 @@
),
(
name: "Run Flip LR",
node: FlipLR,
node: FlipLR(),
),
(
name: "Run Chain",
Expand Down Expand Up @@ -114,4 +114,4 @@
input_position: (-242.0, 134.0),
output_position: (860.0, -42.0),
),
)
)
6 changes: 3 additions & 3 deletions assets/animation_graphs/human_ik.animgraph.ron
Expand Up @@ -6,7 +6,7 @@
),
(
name: "Walk Flip LR",
node: FlipLR,
node: FlipLR(),
),
(
name: "Walk Clip 2",
Expand All @@ -22,7 +22,7 @@
),
(
name: "Run Flip LR",
node: FlipLR,
node: FlipLR(),
),
(
name: "Extend to skeleton",
Expand Down Expand Up @@ -140,4 +140,4 @@
input_position: (69.0, 330.0),
output_position: (1229.0, 56.0),
),
)
)
1 change: 1 addition & 0 deletions crates/bevy_animation_graph/Cargo.toml
Expand Up @@ -14,3 +14,4 @@ thiserror = "1.0.50"
ron = "0.8.1"
serde = { version = "1.0.193", features = ["derive"] }
indexmap = { version = "2.2.1", features = ["serde"] }
regex = "1.10.3"
Expand Up @@ -129,7 +129,9 @@ impl AssetLoader for AnimationGraphLoader {
}
AnimationNodeTypeSerial::Blend => BlendNode::new().wrapped(&serial_node.name),
AnimationNodeTypeSerial::Chain => ChainNode::new().wrapped(&serial_node.name),
AnimationNodeTypeSerial::FlipLR => FlipLRNode::new().wrapped(&serial_node.name),
AnimationNodeTypeSerial::FlipLR { config } => {
FlipLRNode::new(config.clone()).wrapped(&serial_node.name)
}
AnimationNodeTypeSerial::Loop => LoopNode::new().wrapped(&serial_node.name),
AnimationNodeTypeSerial::Speed => SpeedNode::new().wrapped(&serial_node.name),
AnimationNodeTypeSerial::Rotation => {
Expand Down
11 changes: 8 additions & 3 deletions crates/bevy_animation_graph/src/core/animation_graph/serial.rs
@@ -1,7 +1,7 @@
use super::{pin, AnimationGraph, Extra};
use crate::{
core::frame::PoseSpec,
prelude::{AnimationNode, AnimationNodeType, ParamSpec, ParamValue},
prelude::{config::FlipConfig, AnimationNode, AnimationNodeType, ParamSpec, ParamValue},
utils::ordered_map::OrderedMap,
};
use bevy::utils::HashMap;
Expand Down Expand Up @@ -55,7 +55,10 @@ pub enum AnimationNodeTypeSerial {
Clip(String, Option<f32>),
Blend,
Chain,
FlipLR,
FlipLR {
#[serde(default)]
config: FlipConfig,
},
Loop,
Speed,
Rotation,
Expand Down Expand Up @@ -124,7 +127,9 @@ impl From<&AnimationNodeType> for AnimationNodeTypeSerial {
),
AnimationNodeType::Blend(_) => AnimationNodeTypeSerial::Blend,
AnimationNodeType::Chain(_) => AnimationNodeTypeSerial::Chain,
AnimationNodeType::FlipLR(_) => AnimationNodeTypeSerial::FlipLR,
AnimationNodeType::FlipLR(n) => AnimationNodeTypeSerial::FlipLR {
config: n.config.clone(),
},
AnimationNodeType::Loop(_) => AnimationNodeTypeSerial::Loop,
AnimationNodeType::Speed(_) => AnimationNodeTypeSerial::Speed,
AnimationNodeType::Rotation(_) => AnimationNodeTypeSerial::Rotation,
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_animation_graph/src/core/plugin.rs
Expand Up @@ -8,6 +8,7 @@ use super::{
systems::{animation_player, animation_player_deferred_gizmos},
};
use crate::prelude::{
config::{FlipConfig, FlipNameMapper, PatternMapper, PatternMapperSerial},
AbsF32, AddF32, AnimationGraph, AnimationGraphPlayer, AnimationNodeType, BlendNode, ChainNode,
ClampF32, ClipNode, DivF32, DummyNode, ExtendSkeleton, FlipLRNode, GraphClip, GraphNode,
IntoBoneSpaceNode, IntoCharacterSpaceNode, IntoGlobalSpaceNode, LoopNode, MulF32,
Expand Down Expand Up @@ -57,7 +58,10 @@ impl AnimationGraphPlugin {
.register_type::<PoseSpec>()
.register_type::<AnimationNode>()
.register_type::<AnimationNodeType>()

.register_type::<FlipConfig>()
.register_type::<FlipNameMapper>()
.register_type::<PatternMapper>()
.register_type::<PatternMapperSerial>()
// --- Node registrations
// ------------------------------------------
.register_type::<BlendNode>()
Expand Down
140 changes: 140 additions & 0 deletions crates/bevy_animation_graph/src/flipping/config.rs
@@ -0,0 +1,140 @@
use bevy::reflect::{std_traits::ReflectDefault, Reflect};
use regex::{escape, Regex};
use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Reflect, Clone, Serialize, Deserialize)]
#[reflect(Default)]
pub struct FlipConfig {
pub name_mapper: FlipNameMapper,
}

#[derive(Debug, Reflect, Clone)]
#[reflect(Default)]
pub struct PatternMapper {
key_1: String,
key_2: String,
pattern_before: String,
pattern_after: String,
#[reflect(ignore, default = "default_regex")]
regex: Regex,
}

pub fn default_regex() -> Regex {
Regex::new("").unwrap()
}

impl TryFrom<PatternMapperSerial> for PatternMapper {
type Error = regex::Error;

fn try_from(value: PatternMapperSerial) -> Result<Self, Self::Error> {
let regex = Regex::new(&format!(
"({})({}|{})({})",
&value.pattern_before,
escape(&value.key_1),
escape(&value.key_2),
&value.pattern_after,
))?;

Ok(Self {
key_1: value.key_1,
key_2: value.key_2,
pattern_before: value.pattern_before,
pattern_after: value.pattern_after,
regex,
})
}
}

impl From<PatternMapper> for PatternMapperSerial {
fn from(value: PatternMapper) -> Self {
Self {
key_1: value.key_1,
key_2: value.key_2,
pattern_before: value.pattern_before,
pattern_after: value.pattern_after,
}
}
}

impl Default for PatternMapper {
fn default() -> Self {
Self::try_from(PatternMapperSerial::default()).unwrap()
}
}

impl Serialize for PatternMapper {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
PatternMapperSerial::from(self.clone()).serialize(serializer)
}
}

impl<'de> Deserialize<'de> for PatternMapper {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
PatternMapperSerial::deserialize(deserializer).map(|r| r.try_into().unwrap())
}
}

impl PatternMapper {
pub fn flip(&self, input: &str) -> Option<String> {
if let Some(captures) = self.regex.captures(input) {
let key_capture = captures.get(2).unwrap().as_str();
let replacement_key = if key_capture == self.key_1 {
&self.key_2
} else {
&self.key_1
};
Some(
self.regex
.replace(input, format!("${{1}}{replacement_key}${{3}}"))
.into(),
)
} else {
None
}
}
}

#[derive(Debug, Reflect, Serialize, Deserialize, Clone)]
pub struct PatternMapperSerial {
pub key_1: String,
pub key_2: String,
pub pattern_before: String,
pub pattern_after: String,
}

impl Default for PatternMapperSerial {
fn default() -> Self {
Self {
key_1: "L".into(),
key_2: "R".into(),
pattern_before: r"^.*".into(),
pattern_after: r"$".into(),
}
}
}

#[derive(Debug, Reflect, Clone, Serialize, Deserialize)]
#[reflect(Default)]
pub enum FlipNameMapper {
Pattern(PatternMapper),
}

impl Default for FlipNameMapper {
fn default() -> Self {
Self::Pattern(PatternMapper::default())
}
}

impl FlipNameMapper {
pub fn flip(&self, input: &str) -> Option<String> {
match self {
Self::Pattern(pattern) => pattern.flip(input),
}
}
}

0 comments on commit 320328c

Please sign in to comment.