add animation playback
This commit is contained in:
@@ -49,7 +49,21 @@
|
|||||||
<button-custom id="btn-down" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 2 0 0">
|
<button-custom id="btn-down" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 2 0 0">
|
||||||
<icon width="30" icon="bullet_arrow_down"/>
|
<icon width="30" icon="bullet_arrow_down"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<node grow="1"></node>
|
<node grow="1" dir="row" justify="center">
|
||||||
|
<button-custom id="btn-prev" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 2 0 0">
|
||||||
|
<icon width="30" icon="control_start"/>
|
||||||
|
</button-custom>
|
||||||
|
<button-custom id="btn-play" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 2 0 0">
|
||||||
|
<icon width="30" icon="control_play"/>
|
||||||
|
</button-custom>
|
||||||
|
<button-custom id="btn-next" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 2 0 0">
|
||||||
|
<icon width="30" icon="control_end"/>
|
||||||
|
</button-custom>
|
||||||
|
<border pad="5" align="center" margin="0 0 0 10" dir="row" color=".3">
|
||||||
|
<combobox id="fps" text="25" width="35" height="20" combo-list="5,10,15,20,25,30"/>
|
||||||
|
<text text="fps" margin="0 2 0 5"/>
|
||||||
|
</border>
|
||||||
|
</node>
|
||||||
<button-custom id="btn-remove" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 10 0 0">
|
<button-custom id="btn-remove" thickness="1" color="0 0" border-color=".0" shrink="1" margin="0 10 0 0">
|
||||||
<icon width="30" icon="bin_closed"/>
|
<icon width="30" icon="bin_closed"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
|
|||||||
@@ -987,7 +987,7 @@ void App::ui_thread_main()
|
|||||||
// move the task list locally to free the queue for other threads
|
// move the task list locally to free the queue for other threads
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(ui_task_mutex);
|
std::unique_lock<std::mutex> lock(ui_task_mutex);
|
||||||
ui_cv.wait_for(lock, std::chrono::milliseconds(100),
|
ui_cv.wait_for(lock, std::chrono::milliseconds(idle_ms),
|
||||||
[this] { return ui_tasklist.empty() && ui_running ? false : true; });
|
[this] { return ui_tasklist.empty() && ui_running ? false : true; });
|
||||||
working_list = std::move(ui_tasklist);
|
working_list = std::move(ui_tasklist);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ public:
|
|||||||
glm::vec2 gesture_p1;
|
glm::vec2 gesture_p1;
|
||||||
float display_density = 1.f;
|
float display_density = 1.f;
|
||||||
float zoom = 1.f;
|
float zoom = 1.f;
|
||||||
|
int idle_ms = 100;
|
||||||
|
|
||||||
#if defined(__IOS__) && defined(__OBJC__)
|
#if defined(__IOS__) && defined(__OBJC__)
|
||||||
GameViewController* ios_view;
|
GameViewController* ios_view;
|
||||||
|
|||||||
@@ -1351,6 +1351,11 @@ void Canvas::anim_goto_frame(int frame) noexcept
|
|||||||
l->goto_frame(frame);
|
l->goto_frame(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::anim_goto_next() noexcept
|
||||||
|
{
|
||||||
|
anim_goto_frame((m_anim_frame + 1) % anim_duration());
|
||||||
|
}
|
||||||
|
|
||||||
void Canvas::flood_fill(int layer, int plane, std::vector<glm::ivec2> pos, FloodData& plane_data,
|
void Canvas::flood_fill(int layer, int plane, std::vector<glm::ivec2> pos, FloodData& plane_data,
|
||||||
float threshold, glm::vec4 dest_color, std::unique_ptr<glm::vec4>& source_color)
|
float threshold, glm::vec4 dest_color, std::unique_ptr<glm::vec4>& source_color)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ public:
|
|||||||
void layer_merge(int source_idx, int dest_idx);
|
void layer_merge(int source_idx, int dest_idx);
|
||||||
int anim_duration() const noexcept;
|
int anim_duration() const noexcept;
|
||||||
void anim_goto_frame(int frame) noexcept;
|
void anim_goto_frame(int frame) noexcept;
|
||||||
|
void anim_goto_next() noexcept;
|
||||||
void flood_fill(int layer, int plane, std::vector<glm::ivec2> pos, FloodData& plane_data,
|
void flood_fill(int layer, int plane, std::vector<glm::ivec2> pos, FloodData& plane_data,
|
||||||
float threshold, glm::vec4 dest_color, std::unique_ptr<glm::vec4>& source_color);
|
float threshold, glm::vec4 dest_color, std::unique_ptr<glm::vec4>& source_color);
|
||||||
void stroke_start(glm::vec3 point, float pressure);
|
void stroke_start(glm::vec3 point, float pressure);
|
||||||
|
|||||||
@@ -114,3 +114,8 @@ float NodeComboBox::get_float(int index) const noexcept
|
|||||||
{
|
{
|
||||||
return std::stof(m_data[index]);
|
return std::stof(m_data[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float NodeComboBox::get_float() const noexcept
|
||||||
|
{
|
||||||
|
return std::stof(m_data[m_current_index]);
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ public:
|
|||||||
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override;
|
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override;
|
||||||
void set_index(int index);
|
void set_index(int index);
|
||||||
float get_float(int index) const noexcept;
|
float get_float(int index) const noexcept;
|
||||||
|
float get_float() const noexcept;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ void NodePanelAnimation::init_controls()
|
|||||||
btn_up = find<NodeButtonCustom>("btn-up");
|
btn_up = find<NodeButtonCustom>("btn-up");
|
||||||
btn_down = find<NodeButtonCustom>("btn-down");
|
btn_down = find<NodeButtonCustom>("btn-down");
|
||||||
btn_duplicate = find<NodeButtonCustom>("btn-duplicate");
|
btn_duplicate = find<NodeButtonCustom>("btn-duplicate");
|
||||||
|
btn_next = find<NodeButtonCustom>("btn-next");
|
||||||
|
btn_prev = find<NodeButtonCustom>("btn-prev");
|
||||||
|
btn_play = find<NodeButtonCustom>("btn-play");
|
||||||
|
m_fps = find<NodeComboBox>("fps");
|
||||||
|
|
||||||
btn_add->on_click = [this](Node*) {
|
btn_add->on_click = [this](Node*) {
|
||||||
Canvas::I->layer().add_frame();
|
Canvas::I->layer().add_frame();
|
||||||
@@ -57,6 +61,25 @@ void NodePanelAnimation::init_controls()
|
|||||||
Canvas::I->anim_goto_frame(frame);
|
Canvas::I->anim_goto_frame(frame);
|
||||||
load_layers();
|
load_layers();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
btn_play->on_click = [this] (Node* target) {
|
||||||
|
static auto mode = Canvas::I->m_current_mode;
|
||||||
|
auto b = static_cast<NodeButtonCustom*>(target);
|
||||||
|
if (b->is_active())
|
||||||
|
{
|
||||||
|
Canvas::set_mode(mode);
|
||||||
|
b->set_active(false);
|
||||||
|
App::I->idle_ms = 100;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = Canvas::I->m_current_mode;
|
||||||
|
Canvas::set_mode(kCanvasMode::Camera);
|
||||||
|
m_playback_timer = 0;
|
||||||
|
b->set_active(true);
|
||||||
|
App::I->idle_ms = 10;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodePanelAnimation::load_layers()
|
void NodePanelAnimation::load_layers()
|
||||||
@@ -102,6 +125,21 @@ void NodePanelAnimation::load_layers()
|
|||||||
m_timeline->SetWidth(max_width);
|
m_timeline->SetWidth(max_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodePanelAnimation::on_tick(float dt)
|
||||||
|
{
|
||||||
|
parent::on_tick(dt);
|
||||||
|
if (btn_play->is_active())
|
||||||
|
{
|
||||||
|
m_playback_timer += dt;
|
||||||
|
if (m_playback_timer > (1.f / m_fps->get_float()))
|
||||||
|
{
|
||||||
|
m_playback_timer = 0;
|
||||||
|
Canvas::I->anim_goto_next();
|
||||||
|
m_timeline->m_frame = Canvas::I->m_anim_frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodePanelAnimation::added(Node* parent)
|
void NodePanelAnimation::added(Node* parent)
|
||||||
{
|
{
|
||||||
parent::added(parent);
|
parent::added(parent);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "node_text.h"
|
#include "node_text.h"
|
||||||
#include "node_checkbox.h"
|
#include "node_checkbox.h"
|
||||||
#include "node_button_custom.h"
|
#include "node_button_custom.h"
|
||||||
|
#include "node_combobox.h"
|
||||||
|
|
||||||
class NodeAnimationFrame : public NodeButtonCustom
|
class NodeAnimationFrame : public NodeButtonCustom
|
||||||
{
|
{
|
||||||
@@ -43,6 +44,9 @@ public:
|
|||||||
|
|
||||||
class NodePanelAnimation : public Node
|
class NodePanelAnimation : public Node
|
||||||
{
|
{
|
||||||
|
NodeButtonCustom* btn_next = nullptr;
|
||||||
|
NodeButtonCustom* btn_prev = nullptr;
|
||||||
|
NodeButtonCustom* btn_play = nullptr;
|
||||||
NodeButtonCustom* btn_add = nullptr;
|
NodeButtonCustom* btn_add = nullptr;
|
||||||
NodeButtonCustom* btn_remove = nullptr;
|
NodeButtonCustom* btn_remove = nullptr;
|
||||||
NodeButtonCustom* btn_up = nullptr;
|
NodeButtonCustom* btn_up = nullptr;
|
||||||
@@ -52,8 +56,10 @@ class NodePanelAnimation : public Node
|
|||||||
Node* m_frames_container = nullptr;
|
Node* m_frames_container = nullptr;
|
||||||
NodeAnimationFrame* m_selected_frame = nullptr;
|
NodeAnimationFrame* m_selected_frame = nullptr;
|
||||||
NodeAnimationTimeline* m_timeline = nullptr;
|
NodeAnimationTimeline* m_timeline = nullptr;
|
||||||
|
NodeComboBox* m_fps = nullptr;
|
||||||
int m_selected_frame_index = -1;
|
int m_selected_frame_index = -1;
|
||||||
uint32_t m_selected_frame_layer_id = 0;
|
uint32_t m_selected_frame_layer_id = 0;
|
||||||
|
float m_playback_timer = 0;
|
||||||
public:
|
public:
|
||||||
using this_class = NodePanelAnimation;
|
using this_class = NodePanelAnimation;
|
||||||
using parent = Node;
|
using parent = Node;
|
||||||
@@ -62,7 +68,8 @@ public:
|
|||||||
virtual void clone_finalize(Node* dest) const override;
|
virtual void clone_finalize(Node* dest) const override;
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
virtual void added(Node* parent) override;
|
virtual void added(Node* parent) override;
|
||||||
|
virtual void on_tick(float dt) override;
|
||||||
|
|
||||||
void init_controls();
|
void init_controls();
|
||||||
void load_layers();
|
void load_layers();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user