Now loading the new animations out of assets/animate2.json
This commit is contained in:
parent
df730047ac
commit
dea0607901
7 changed files with 108 additions and 137 deletions
74
animate2.cpp
74
animate2.cpp
|
|
@ -3,20 +3,23 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include "dbc.hpp"
|
#include "dbc.hpp"
|
||||||
#include "rand.hpp"
|
#include "rand.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
constexpr float SUB_FRAME_SENSITIVITY = 0.999f;
|
constexpr float SUB_FRAME_SENSITIVITY = 0.999f;
|
||||||
|
|
||||||
namespace animate2 {
|
namespace animate2 {
|
||||||
std::vector<sf::IntRect> Animate2::calc_frames() {
|
std::vector<sf::IntRect> Animate2::calc_frames() {
|
||||||
dbc::check($sequence.frames.size() == $sequence.durations.size(), "$sequence.frames.size() != $sequence.durations.size()");
|
dbc::check(sequence.frames.size() == sequence.durations.size(), "sequence.frames.size() != sequence.durations.size()");
|
||||||
|
|
||||||
std::vector<sf::IntRect> frames;
|
std::vector<sf::IntRect> frames;
|
||||||
|
|
||||||
for(int frame_i : $sequence.frames) {
|
for(int frame_i : sequence.frames) {
|
||||||
|
dbc::check(frame_i < sheet.frames, "frame index greater than sheet frames");
|
||||||
frames.emplace_back(
|
frames.emplace_back(
|
||||||
sf::Vector2i{$sheet.frame_width * frame_i, 0}, // NOTE: one row only for now
|
sf::Vector2i{sheet.frame_width * frame_i, 0}, // NOTE: one row only for now
|
||||||
sf::Vector2i{$sheet.frame_width,
|
sf::Vector2i{sheet.frame_width,
|
||||||
$sheet.frame_height});
|
sheet.frame_height});
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames;
|
return frames;
|
||||||
|
|
@ -24,56 +27,58 @@ namespace animate2 {
|
||||||
|
|
||||||
void Animate2::play() {
|
void Animate2::play() {
|
||||||
dbc::check(!playing, "can't call play while playing?");
|
dbc::check(!playing, "can't call play while playing?");
|
||||||
$sequence.current = 0;
|
sequence.current = 0;
|
||||||
$sequence.subframe = 0.0f;
|
sequence.subframe = 0.0f;
|
||||||
$sequence.loop_count = 0;
|
sequence.loop_count = 0;
|
||||||
playing = true;
|
playing = true;
|
||||||
$sequence.timer.start();
|
sequence.timer.start();
|
||||||
|
sequence.frame_count = sequence.frames.size();
|
||||||
|
$frame_rects = calc_frames();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animate2::stop() {
|
void Animate2::stop() {
|
||||||
playing = false;
|
playing = false;
|
||||||
$sequence.timer.reset();
|
sequence.timer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// need one for each kind of thing to animate
|
// need one for each kind of thing to animate
|
||||||
// NOTE: possibly find a way to only run apply on frame change?
|
// NOTE: possibly find a way to only run apply on frame change?
|
||||||
void Animate2::apply(sf::Sprite& sprite) {
|
void Animate2::apply(sf::Sprite& sprite) {
|
||||||
dbc::check(!$transform.simple, "can't call ::apply() on a simple animation, only ::motion()");
|
dbc::check(!transform.simple, "can't call ::apply() on a simple animation, only ::motion()");
|
||||||
|
|
||||||
dbc::check($sequence.current < $frame_rects.size(), "current frame past $frame_rects");
|
dbc::check(sequence.current < $frame_rects.size(), "current frame past $frame_rects");
|
||||||
// NOTE: pos is not updated yet
|
// NOTE: pos is not updated yet
|
||||||
auto& rect = $frame_rects.at($sequence.current);
|
auto& rect = $frame_rects.at(sequence.current);
|
||||||
sprite.setTextureRect(rect);
|
sprite.setTextureRect(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaces step
|
// replaces step
|
||||||
void Animate2::update_frame() {
|
void Animate2::update_frame() {
|
||||||
dbc::check(playing, "attempt to update animation that's not playing");
|
dbc::check(playing, "attempt to update animation that's not playing");
|
||||||
dbc::check($sequence.frame_count == $sequence.frames.size(), "frame_count doesn't match frame.size()");
|
dbc::check(sequence.frame_count == sequence.frames.size(), "frame_count doesn't match frame.size()");
|
||||||
|
|
||||||
auto duration = $sequence.durations.at($sequence.current);
|
auto duration = sequence.durations.at(sequence.current);
|
||||||
bool frame_change = false;
|
bool frame_change = false;
|
||||||
|
|
||||||
if($sequence.timer.getElapsedTime() >= duration) {
|
if(sequence.timer.getElapsedTime() >= duration) {
|
||||||
$sequence.timer.restart();
|
sequence.timer.restart();
|
||||||
$sequence.current++;
|
sequence.current++;
|
||||||
if($sequence.subframe > SUB_FRAME_SENSITIVITY) $sequence.subframe = 0.0f;
|
if(sequence.subframe > SUB_FRAME_SENSITIVITY) sequence.subframe = 0.0f;
|
||||||
frame_change = true;
|
frame_change = true;
|
||||||
} else {
|
} else {
|
||||||
$sequence.subframe = std::lerp($sequence.subframe, 1.0, $sequence.timer.DELTA * $transform.ease_rate);
|
sequence.subframe = std::lerp(sequence.subframe, 1.0, sequence.timer.DELTA * transform.ease_rate);
|
||||||
|
|
||||||
fmt::println("subframe: {}, alpha: {}", $sequence.subframe, $sequence.timer.alpha);
|
std::cout << "subframe: " << sequence.subframe << " duration: " << duration << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($sequence.current >= $sequence.frame_count) {
|
if(sequence.current >= sequence.frame_count) {
|
||||||
$sequence.loop_count++;
|
sequence.loop_count++;
|
||||||
playing = onLoop($sequence, $transform);
|
playing = onLoop(sequence, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(frame_change && onFrame != nullptr) onFrame();
|
if(frame_change && onFrame != nullptr) onFrame();
|
||||||
|
|
||||||
dbc::check($sequence.current < $sequence.frame_count, "onLoop fail: current frame out of frames.size()");
|
dbc::check(sequence.current < sequence.frame_count, "onLoop fail: current frame out of frames.size()");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animate2::update() {
|
void Animate2::update() {
|
||||||
|
|
@ -81,21 +86,21 @@ namespace animate2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animate2::motion(sf::Sprite& sprite, sf::Vector2f pos, sf::Vector2f scale) {
|
void Animate2::motion(sf::Sprite& sprite, sf::Vector2f pos, sf::Vector2f scale) {
|
||||||
$transform.lerp($sequence, pos, scale);
|
transform.lerp(sequence, pos, scale);
|
||||||
|
|
||||||
if($transform.flipped) {
|
if(transform.flipped) {
|
||||||
scale.x *= -1;
|
scale.x *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite.setPosition(pos);
|
sprite.setPosition(pos);
|
||||||
|
|
||||||
if($transform.scaled) {
|
if(transform.scaled) {
|
||||||
sprite.setScale(scale);
|
sprite.setScale(scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, double> Animate2::commit() {
|
std::pair<int, double> Animate2::commit() {
|
||||||
return $sequence.timer.commit();
|
return sequence.timer.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::start() {
|
void Timer::start() {
|
||||||
|
|
@ -151,4 +156,15 @@ namespace animate2 {
|
||||||
seq.subframe, tick, min_y, max_y, pos_out.x, pos_out.y,
|
seq.subframe, tick, min_y, max_y, pos_out.x, pos_out.y,
|
||||||
scale_out.x, scale_out.y);
|
scale_out.x, scale_out.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Animate2 load(const std::string &file, const std::string &anim_name) {
|
||||||
|
using nlohmann::json;
|
||||||
|
std::ifstream infile(file);
|
||||||
|
auto data = json::parse(infile);
|
||||||
|
|
||||||
|
Animate2 anim;
|
||||||
|
animate2::from_json(data[anim_name], anim);
|
||||||
|
|
||||||
|
return anim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
animate2.hpp
21
animate2.hpp
|
|
@ -8,11 +8,14 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "ease2.hpp"
|
#include "ease2.hpp"
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
#include "json_mods.hpp"
|
||||||
|
|
||||||
namespace animate2 {
|
namespace animate2 {
|
||||||
|
|
||||||
|
template <typename T> struct NameOf;
|
||||||
|
|
||||||
struct Sheet {
|
struct Sheet {
|
||||||
int width{0};
|
int frames{0};
|
||||||
int height{0};
|
|
||||||
int frame_width{0};
|
int frame_width{0};
|
||||||
int frame_height{0};
|
int frame_height{0};
|
||||||
};
|
};
|
||||||
|
|
@ -38,7 +41,7 @@ namespace animate2 {
|
||||||
std::vector<std::chrono::milliseconds> durations{};
|
std::vector<std::chrono::milliseconds> durations{};
|
||||||
size_t current{0};
|
size_t current{0};
|
||||||
int loop_count{0};
|
int loop_count{0};
|
||||||
size_t frame_count{frames.size()};
|
size_t frame_count{0};
|
||||||
Timer timer{};
|
Timer timer{};
|
||||||
float subframe{0.0f};
|
float subframe{0.0f};
|
||||||
};
|
};
|
||||||
|
|
@ -82,9 +85,9 @@ namespace animate2 {
|
||||||
|
|
||||||
class Animate2 {
|
class Animate2 {
|
||||||
public:
|
public:
|
||||||
Sheet $sheet;
|
Sheet sheet;
|
||||||
Sequence $sequence;
|
Sequence sequence;
|
||||||
Transform $transform;
|
Transform transform;
|
||||||
OnFrameHandler onFrame = nullptr;
|
OnFrameHandler onFrame = nullptr;
|
||||||
|
|
||||||
std::vector<sf::IntRect> $frame_rects{calc_frames()};
|
std::vector<sf::IntRect> $frame_rects{calc_frames()};
|
||||||
|
|
@ -101,4 +104,10 @@ namespace animate2 {
|
||||||
std::pair<int, double> commit();
|
std::pair<int, double> commit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Animate2 load(const std::string &file, const std::string &anim_name);
|
||||||
|
|
||||||
|
ENROLL_COMPONENT(Sheet, frames, frame_width, frame_height);
|
||||||
|
ENROLL_COMPONENT(Sequence, frames, durations);
|
||||||
|
ENROLL_COMPONENT(Transform, min_x, min_y, max_x, max_y, simple, flipped, ease_rate, scaled, toggled, looped);
|
||||||
|
ENROLL_COMPONENT(Animate2, sheet, sequence, transform);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
assets/animate2.json
Normal file
25
assets/animate2.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"rat_king_boss": {
|
||||||
|
"sheet": {
|
||||||
|
"frames": 2,
|
||||||
|
"frame_width": 720,
|
||||||
|
"frame_height": 720
|
||||||
|
},
|
||||||
|
"sequence": {
|
||||||
|
"frames": [0, 1],
|
||||||
|
"durations": [33, 33]
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"min_x": 0.6,
|
||||||
|
"min_y": 0.6,
|
||||||
|
"max_x": 0.8,
|
||||||
|
"max_y": 0.8,
|
||||||
|
"simple": false,
|
||||||
|
"flipped": false,
|
||||||
|
"ease_rate": 5.0,
|
||||||
|
"scaled": true,
|
||||||
|
"toggled": false,
|
||||||
|
"looped": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -231,7 +231,6 @@ namespace components {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void configure_entity(DinkyECS::World& world, DinkyECS::Entity ent, json& data);
|
void configure_entity(DinkyECS::World& world, DinkyECS::Entity ent, json& data);
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,15 @@ namespace nlohmann {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct adl_serializer<std::chrono::milliseconds> {
|
||||||
|
static void to_json(json& j, const std::chrono::milliseconds& opt) {
|
||||||
|
j = opt.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json& j, std::chrono::milliseconds& opt) {
|
||||||
|
opt = std::chrono::milliseconds{int(j)};
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,40 +15,6 @@ using namespace textures;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
using namespace animate2;
|
using namespace animate2;
|
||||||
|
|
||||||
Animate2 crafter() {
|
|
||||||
Sheet sheet{
|
|
||||||
.width{720*2},
|
|
||||||
.height{720},
|
|
||||||
.frame_width{720},
|
|
||||||
.frame_height{720},
|
|
||||||
};
|
|
||||||
|
|
||||||
Sequence sequence{
|
|
||||||
.frames{0,1},
|
|
||||||
.durations{Random::milliseconds(1, 33), Random::milliseconds(1, 33)}
|
|
||||||
};
|
|
||||||
|
|
||||||
REQUIRE(sequence.frame_count == sequence.frames.size());
|
|
||||||
REQUIRE(sequence.frame_count == sequence.durations.size());
|
|
||||||
|
|
||||||
Transform transform{
|
|
||||||
.min_x{0.6f},
|
|
||||||
.min_y{0.6f},
|
|
||||||
.max_x{0.8f},
|
|
||||||
.max_y{0.8f},
|
|
||||||
.simple{false},
|
|
||||||
.flipped{false},
|
|
||||||
.ease_rate{5.0f},
|
|
||||||
.scaled{true},
|
|
||||||
.toggled{false},
|
|
||||||
.looped{false},
|
|
||||||
.easing = ease2::in_out_back,
|
|
||||||
.motion = ease2::move_rush,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {sheet, sequence, transform};
|
|
||||||
}
|
|
||||||
|
|
||||||
void FAKE_RENDER() {
|
void FAKE_RENDER() {
|
||||||
std::this_thread::sleep_for(Random::milliseconds(5, 32));
|
std::this_thread::sleep_for(Random::milliseconds(5, 32));
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +44,7 @@ void PLAY_TEST(Animate2 &anim) {
|
||||||
TEST_CASE("new animation system", "[animation-new]") {
|
TEST_CASE("new animation system", "[animation-new]") {
|
||||||
textures::init();
|
textures::init();
|
||||||
|
|
||||||
auto anim = crafter();
|
auto anim = animate2::load("assets/animate2.json", "rat_king_boss");
|
||||||
PLAY_TEST(anim);
|
PLAY_TEST(anim);
|
||||||
|
|
||||||
bool onLoop_ran = false;
|
bool onLoop_ran = false;
|
||||||
|
|
@ -103,7 +69,7 @@ TEST_CASE("new animation system", "[animation-new]") {
|
||||||
};
|
};
|
||||||
|
|
||||||
PLAY_TEST(anim);
|
PLAY_TEST(anim);
|
||||||
REQUIRE(anim.$sequence.loop_count == 2);
|
REQUIRE(anim.sequence.loop_count == 2);
|
||||||
|
|
||||||
// stops at end
|
// stops at end
|
||||||
anim.onLoop = [](auto& seq, auto& tr) -> bool {
|
anim.onLoop = [](auto& seq, auto& tr) -> bool {
|
||||||
|
|
@ -121,10 +87,10 @@ TEST_CASE("confirm frame sequencing works", "[animation-new]") {
|
||||||
textures::init();
|
textures::init();
|
||||||
animation::init();
|
animation::init();
|
||||||
|
|
||||||
auto anim = crafter();
|
auto anim = animate2::load("assets/animate2.json", "rat_king_boss");
|
||||||
|
|
||||||
auto blanket = textures::get_sprite("ritual_crafting_area");
|
auto boss = textures::get_sprite("rat_king_boss");
|
||||||
sf::IntRect init_rect{{0,0}, {anim.$sheet.frame_width, anim.$sheet.frame_height}};
|
sf::IntRect init_rect{{0,0}, {anim.sheet.frame_width, anim.sheet.frame_height}};
|
||||||
|
|
||||||
anim.play();
|
anim.play();
|
||||||
bool loop_ran = false;
|
bool loop_ran = false;
|
||||||
|
|
@ -134,12 +100,12 @@ TEST_CASE("confirm frame sequencing works", "[animation-new]") {
|
||||||
seq.current = 0;
|
seq.current = 0;
|
||||||
loop_ran = true;
|
loop_ran = true;
|
||||||
|
|
||||||
REQUIRE(blanket.sprite->getTextureRect() != init_rect);
|
REQUIRE(boss.sprite->getTextureRect() != init_rect);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
anim.onFrame = [&](){
|
anim.onFrame = [&](){
|
||||||
anim.apply(*blanket.sprite);
|
anim.apply(*boss.sprite);
|
||||||
};
|
};
|
||||||
|
|
||||||
while(anim.playing) {
|
while(anim.playing) {
|
||||||
|
|
@ -151,7 +117,7 @@ TEST_CASE("confirm frame sequencing works", "[animation-new]") {
|
||||||
REQUIRE(anim.playing == false);
|
REQUIRE(anim.playing == false);
|
||||||
|
|
||||||
// this confirms it went back to the first frame
|
// this confirms it went back to the first frame
|
||||||
REQUIRE(blanket.sprite->getTextureRect() == init_rect);
|
REQUIRE(boss.sprite->getTextureRect() == init_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("confirm transition changes work", "[animation-new]") {
|
TEST_CASE("confirm transition changes work", "[animation-new]") {
|
||||||
|
|
@ -162,7 +128,7 @@ TEST_CASE("confirm transition changes work", "[animation-new]") {
|
||||||
sf::Vector2f pos{100,100};
|
sf::Vector2f pos{100,100};
|
||||||
sprite.setPosition(pos);
|
sprite.setPosition(pos);
|
||||||
auto scale = sprite.getScale();
|
auto scale = sprite.getScale();
|
||||||
auto anim = crafter();
|
auto anim = animate2::load("assets/animate2.json", "rat_king_boss");
|
||||||
|
|
||||||
// also testing that onFrame being null means it's not run
|
// also testing that onFrame being null means it's not run
|
||||||
REQUIRE(anim.onFrame == nullptr);
|
REQUIRE(anim.onFrame == nullptr);
|
||||||
|
|
@ -170,23 +136,11 @@ TEST_CASE("confirm transition changes work", "[animation-new]") {
|
||||||
anim.play();
|
anim.play();
|
||||||
REQUIRE(anim.playing == true);
|
REQUIRE(anim.playing == true);
|
||||||
|
|
||||||
sf::Clock clock;
|
|
||||||
clock.start();
|
|
||||||
sf::Time start;
|
|
||||||
sf::Time delta;
|
|
||||||
|
|
||||||
while(anim.playing) {
|
while(anim.playing) {
|
||||||
start = clock.getElapsedTime();
|
|
||||||
|
|
||||||
anim.update();
|
anim.update();
|
||||||
anim.motion(sprite, pos, scale);
|
anim.motion(sprite, pos, scale);
|
||||||
|
|
||||||
std::this_thread::sleep_for(10ms);
|
std::this_thread::sleep_for(10ms);
|
||||||
fmt::println("POSITION: {},{}; SCALE: {},{}; current: {}; subframe: {}",
|
|
||||||
pos.x, pos.y, scale.x, scale.y, anim.$sequence.current, anim.$sequence.subframe);
|
|
||||||
|
|
||||||
delta = clock.getElapsedTime() - start;
|
|
||||||
fmt::println("FRAME RATE {}", 1.0f / delta.asSeconds());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(anim.playing == false);
|
REQUIRE(anim.playing == false);
|
||||||
|
|
|
||||||
|
|
@ -12,50 +12,7 @@
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
bool YES_SYNC=true;
|
bool YES_SYNC=true;
|
||||||
|
animate2::Animate2 anim = animate2::load("assets/animate2.json", "rat_king_boss");
|
||||||
animate2::Sheet sheet{
|
|
||||||
.width{720*2},
|
|
||||||
.height{720},
|
|
||||||
.frame_width{720},
|
|
||||||
.frame_height{720},
|
|
||||||
};
|
|
||||||
|
|
||||||
animate2::Sequence sequence{
|
|
||||||
.frames{0,1},
|
|
||||||
.durations{800ms, 200ms}
|
|
||||||
};
|
|
||||||
|
|
||||||
animate2::Transform scale_tr{
|
|
||||||
.min_x{0.6f},
|
|
||||||
.min_y{0.6f},
|
|
||||||
.max_x{0.8f},
|
|
||||||
.max_y{0.8f},
|
|
||||||
.simple{false},
|
|
||||||
.flipped{false},
|
|
||||||
.ease_rate{4.0f},
|
|
||||||
.scaled{true},
|
|
||||||
.toggled{false},
|
|
||||||
.looped{true},
|
|
||||||
.easing = ease2::in_out_back,
|
|
||||||
.motion = ease2::move_rush,
|
|
||||||
};
|
|
||||||
|
|
||||||
animate2::Transform move_tr{
|
|
||||||
.min_x{-20.0f},
|
|
||||||
.min_y{-20.0f},
|
|
||||||
.max_x{20.0f},
|
|
||||||
.max_y{20.0f},
|
|
||||||
.simple{false},
|
|
||||||
.flipped{false},
|
|
||||||
.ease_rate{2.5f},
|
|
||||||
.scaled{true},
|
|
||||||
.toggled{false},
|
|
||||||
.looped{true},
|
|
||||||
.easing = ease2::normal_dist,
|
|
||||||
.motion = ease2::move_shake,
|
|
||||||
};
|
|
||||||
|
|
||||||
animate2::Animate2 anim{sheet, sequence, scale_tr};
|
|
||||||
|
|
||||||
namespace animator {
|
namespace animator {
|
||||||
|
|
||||||
|
|
@ -100,10 +57,10 @@ namespace animator {
|
||||||
if(anim.playing) anim.stop();
|
if(anim.playing) anim.stop();
|
||||||
break;
|
break;
|
||||||
case Event::LOOP:
|
case Event::LOOP:
|
||||||
anim.$transform.looped = !anim.$transform.looped;
|
anim.transform.looped = !anim.transform.looped;
|
||||||
break;
|
break;
|
||||||
case Event::TOGGLE:
|
case Event::TOGGLE:
|
||||||
anim.$transform.toggled = !anim.$transform.toggled;
|
anim.transform.toggled = !anim.transform.toggled;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state(State::START);
|
state(State::START);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue