mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
Merge remote-tracking branch 'origin/beta' into beta
This commit is contained in:
@@ -43,24 +43,25 @@
|
||||
using namespace tinyxml2;
|
||||
|
||||
|
||||
Action::Action(): history_step_(0), history_max_step_(0),
|
||||
Action::Action(): history_step_(0), history_max_step_(0), history_min_step_(0),
|
||||
snapshot_id_(0), snapshot_node_(nullptr), interpolator_(nullptr), interpolator_node_(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Action::init()
|
||||
void Action::init(const std::string &label)
|
||||
{
|
||||
// clean the history
|
||||
history_doc_.Clear();
|
||||
history_step_ = 0;
|
||||
history_max_step_ = 0;
|
||||
history_min_step_ = 1;
|
||||
history_max_step_ = 1;
|
||||
|
||||
// reset snapshot
|
||||
snapshot_id_ = 0;
|
||||
snapshot_node_ = nullptr;
|
||||
|
||||
store("Session start");
|
||||
store(label);
|
||||
}
|
||||
|
||||
// must be called in a thread running in parrallel of the rendering
|
||||
@@ -131,8 +132,12 @@ void captureMixerSession(Session *se, std::string node, std::string label, tinyx
|
||||
|
||||
void Action::storeSession(Session *se, std::string label)
|
||||
{
|
||||
//
|
||||
if (!Action::manager().history_access_.try_lock())
|
||||
// force lock for creation of first step
|
||||
if (Action::manager().history_step_ < 1)
|
||||
Action::manager().history_access_.lock();
|
||||
// try lock for storing history in normal case
|
||||
// (i.e. priority to realtime performance over storing history)
|
||||
else if (!Action::manager().history_access_.try_lock())
|
||||
return;
|
||||
|
||||
// incremental naming of history nodes
|
||||
@@ -146,6 +151,14 @@ void Action::storeSession(Session *se, std::string label)
|
||||
}
|
||||
Action::manager().history_max_step_ = Action::manager().history_step_;
|
||||
|
||||
// Ensure a maximum amount of stored steps (even very big, just to ensure memory limit)
|
||||
if (Action::manager().history_max_step_ - Action::manager().history_min_step_ > MAX_COUNT_HISTORY) {
|
||||
XMLElement *node = Action::manager().history_doc_.FirstChildElement( HISTORY_NODE(Action::manager().history_min_step_+1).c_str() );
|
||||
if ( node )
|
||||
Action::manager().history_doc_.DeleteChild(node);
|
||||
Action::manager().history_min_step_++;
|
||||
}
|
||||
|
||||
// capture current session
|
||||
captureMixerSession(se,
|
||||
HISTORY_NODE(Action::manager().history_step_),
|
||||
@@ -158,9 +171,7 @@ void Action::storeSession(Session *se, std::string label)
|
||||
|
||||
void Action::store(const std::string &label)
|
||||
{
|
||||
// TODO: set a maximum amount of stored steps? (even very big, just to ensure memory limit)
|
||||
|
||||
// ignore if locked or if no label is given
|
||||
// ignore if no label is given
|
||||
if (label.empty())
|
||||
return;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#define MAX_COUNT_HISTORY 1000
|
||||
|
||||
class Session;
|
||||
class Interpolator;
|
||||
class FrameBufferImage;
|
||||
@@ -26,7 +28,7 @@ public:
|
||||
static Action _instance;
|
||||
return _instance;
|
||||
}
|
||||
void init ();
|
||||
void init (const std::string &label);
|
||||
|
||||
// Undo History
|
||||
void store (const std::string &label);
|
||||
@@ -36,6 +38,7 @@ public:
|
||||
|
||||
inline uint current () const { return history_step_; }
|
||||
inline uint max () const { return history_max_step_; }
|
||||
inline uint min () const { return history_min_step_; }
|
||||
std::string label (uint s) const;
|
||||
std::string shortlabel (uint s) const;
|
||||
FrameBufferImage *thumbnail (uint s) const;
|
||||
@@ -66,6 +69,7 @@ private:
|
||||
tinyxml2::XMLDocument history_doc_;
|
||||
uint history_step_;
|
||||
uint history_max_step_;
|
||||
uint history_min_step_;
|
||||
std::mutex history_access_;
|
||||
static void storeSession(Session *se, std::string label);
|
||||
void restore(uint target);
|
||||
|
||||
@@ -749,7 +749,11 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
|
||||
arguments >> t >> osc::EndMessage;
|
||||
target->call( new SetGeometry( &transform, t), true );
|
||||
}
|
||||
/// e.g. '/vimix/current/corner ffffffff 0 0 0 0 0 0 0 0'
|
||||
/// e.g. '/vimix/current/corner ffffffff -1 -1 -1 +1 +1 -1 +1 +1'
|
||||
/// 1. Lower left (-1 -1)
|
||||
/// 2. Upper left (-1 +1)
|
||||
/// 3. Lower right (+1 -1)
|
||||
/// 4. Upper right (+1 +1)
|
||||
else if (attribute.compare(OSC_SOURCE_CORNER) == 0) {
|
||||
// read 8 float values
|
||||
float corners[8] = {0.f};
|
||||
@@ -764,14 +768,14 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
|
||||
// convert to data_ matrix format
|
||||
Group transform;
|
||||
transform.copyTransform(target->group(View::GEOMETRY));
|
||||
transform.data_[0].x = corners[0];
|
||||
transform.data_[0].y = corners[1];
|
||||
transform.data_[1].x = corners[2];
|
||||
transform.data_[1].y = corners[3];
|
||||
transform.data_[2].x = corners[4];
|
||||
transform.data_[2].y = corners[5];
|
||||
transform.data_[3].x = corners[6];
|
||||
transform.data_[3].y = corners[7];
|
||||
transform.data_[0].x = corners[0] + 1.f;
|
||||
transform.data_[0].y = corners[1] + 1.f;
|
||||
transform.data_[1].x = corners[2] + 1.f;
|
||||
transform.data_[1].y = corners[3] - 1.f;
|
||||
transform.data_[2].x = corners[4] - 1.f;
|
||||
transform.data_[2].y = corners[5] + 1.f;
|
||||
transform.data_[3].x = corners[6] - 1.f;
|
||||
transform.data_[3].y = corners[7] - 1.f;
|
||||
// duration argument
|
||||
float t = 0.f;
|
||||
if (arguments.Eos())
|
||||
|
||||
@@ -1555,7 +1555,7 @@ void Mixer::swap()
|
||||
}
|
||||
|
||||
// reset History manager
|
||||
Action::manager().init();
|
||||
Action::manager().init("Session start");
|
||||
|
||||
// notification
|
||||
if (session_->filename().empty())
|
||||
|
||||
@@ -1064,7 +1064,7 @@ void UserInterface::showMenuEdit()
|
||||
bool has_clipboard = (clipboard != nullptr && strlen(clipboard) > 0 && SessionLoader::isClipboard(clipboard));
|
||||
|
||||
// UNDO
|
||||
if ( ImGui::MenuItem( MENU_UNDO, SHORTCUT_UNDO, false, Action::manager().current() > 1) )
|
||||
if ( ImGui::MenuItem( MENU_UNDO, SHORTCUT_UNDO, false, Action::manager().current() > Action::manager().min()) )
|
||||
Action::manager().undo();
|
||||
if ( ImGui::MenuItem( MENU_REDO, SHORTCUT_REDO, false, Action::manager().current() < Action::manager().max()) )
|
||||
Action::manager().redo();
|
||||
@@ -4898,7 +4898,7 @@ void Navigator::RenderMainPannelSession()
|
||||
static bool _tooltip = 0;
|
||||
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y -ImGui::GetFrameHeight() ));
|
||||
if ( Action::manager().current() > 1 ) {
|
||||
if ( Action::manager().current() > Action::manager().min() ) {
|
||||
if ( ImGuiToolkit::IconButton( ICON_FA_UNDO, "Undo" ) )
|
||||
Action::manager().undo();
|
||||
} else
|
||||
@@ -4920,7 +4920,8 @@ void Navigator::RenderMainPannelSession()
|
||||
int count_over = 0;
|
||||
ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() );
|
||||
|
||||
for (uint i = Action::manager().max(); i > 0; --i) {
|
||||
for (uint i = Action::manager().max();
|
||||
i >= Action::manager().min(); --i) {
|
||||
|
||||
if (ImGui::Selectable( Action::manager().shortlabel(i).c_str(), i == Action::manager().current(), ImGuiSelectableFlags_AllowDoubleClick, size )) {
|
||||
// go to on double clic
|
||||
@@ -4978,7 +4979,7 @@ void Navigator::RenderMainPannelSession()
|
||||
if ( Action::manager().max() > 1 ) {
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y ));
|
||||
if (ImGuiToolkit::IconButton( 12, 14, "Clear history"))
|
||||
Action::manager().init();
|
||||
Action::manager().init("Reset");
|
||||
}
|
||||
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
|
||||
|
||||
Reference in New Issue
Block a user