Work-in-progress: Interpolation of snapshot in Action manager

This commit is contained in:
brunoherbelin
2021-04-21 23:35:34 +02:00
parent e2d2e6ddd8
commit da64172848
14 changed files with 405 additions and 122 deletions

View File

@@ -6,11 +6,13 @@
#include "Mixer.h"
#include "MixingGroup.h"
#include "tinyxml2Toolkit.h"
#include "SessionSource.h"
//#include "SessionSource.h"
#include "ImageProcessingShader.h"
#include "SessionVisitor.h"
#include "SessionCreator.h"
#include "Settings.h"
#include "GlmToolkit.h"
#include "Interpolator.h"
#include "ActionManager.h"
@@ -23,8 +25,10 @@
using namespace tinyxml2;
Action::Action(): history_step_(0), history_max_step_(0)
Action::Action(): history_step_(0), history_max_step_(0), locked_(false),
snapshot_id_(0), snapshot_node_(nullptr), interpolator_(nullptr), interpolator_node_(nullptr)
{
}
void Action::init()
@@ -33,7 +37,11 @@ void Action::init()
history_doc_.Clear();
history_step_ = 0;
history_max_step_ = 0;
// start fresh
// reset snapshot
snapshot_id_ = 0;
snapshot_node_ = nullptr;
store("Session start");
}
@@ -177,41 +185,61 @@ void Action::snapshot(const std::string &label)
#endif
}
void Action::open(uint64_t snapshotid)
{
if ( snapshot_id_ != snapshotid )
{
// get snapshot node of target in current session
Session *se = Mixer::manager().session();
snapshot_node_ = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
if (snapshot_node_)
snapshot_id_ = snapshotid;
else
snapshot_id_ = 0;
interpolator_node_ = nullptr;
}
}
void Action::replace(uint64_t snapshotid)
{
// ignore if locked or if no label is given
if (locked_)
return;
// get snapshot node of target in current session
Session *se = Mixer::manager().session();
XMLElement *sessionNode = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
if (snapshotid > 0)
open(snapshotid);
if (sessionNode) {
std::string l = sessionNode->Attribute("label");
if (snapshot_node_) {
// remember label
std::string label = snapshot_node_->Attribute("label");
se->snapshots()->xmlDoc_->DeleteChild( sessionNode );
// remove previous node
Session *se = Mixer::manager().session();
se->snapshots()->xmlDoc_->DeleteChild( snapshot_node_ );
// create snapshot node
sessionNode = se->snapshots()->xmlDoc_->NewElement( SNAPSHOT_NODE(snapshotid) );
se->snapshots()->xmlDoc_->InsertEndChild(sessionNode);
// label describes the snapshot
sessionNode->SetAttribute("label", l.c_str());
snapshot_node_ = se->snapshots()->xmlDoc_->NewElement( SNAPSHOT_NODE(snapshot_id_) );
se->snapshots()->xmlDoc_->InsertEndChild(snapshot_node_);
// save all sources using source visitor
SessionVisitor sv(se->snapshots()->xmlDoc_, sessionNode);
for (auto iter = se->begin(); iter != se->end(); ++iter, sv.setRoot(sessionNode) )
SessionVisitor sv(se->snapshots()->xmlDoc_, snapshot_node_);
for (auto iter = se->begin(); iter != se->end(); ++iter, sv.setRoot(snapshot_node_) )
(*iter)->accept(sv);
// restore label
snapshot_node_->SetAttribute("label", label.c_str());
// debug
#ifdef ACTION_DEBUG
Log::Info("Snapshot replaced %d '%s'", id, label.c_str());
Log::Info("Snapshot replaced %d '%s'", snapshot_id_, label.c_str());
#endif
}
else
snapshot_id_ = 0;
}
std::list<uint64_t> Action::snapshots() const
{
Session *se = Mixer::manager().session();
@@ -220,39 +248,40 @@ std::list<uint64_t> Action::snapshots() const
std::string Action::label(uint64_t snapshotid) const
{
std::string l = "";
std::string label = "";
// get snapshot node of target in current session
Session *se = Mixer::manager().session();
const XMLElement *sessionNode = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
const XMLElement *snap = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
if (sessionNode) {
l = sessionNode->Attribute("label");
}
return l;
if (snap)
label = snap->Attribute("label");
return label;
}
void Action::setLabel (uint64_t snapshotid, const std::string &label)
{
// get snapshot node of target in current session
Session *se = Mixer::manager().session();
XMLElement *sessionNode = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
open(snapshotid);
if (sessionNode) {
sessionNode->SetAttribute("label", label.c_str());
}
if (snapshot_node_)
snapshot_node_->SetAttribute("label", label.c_str());
}
void Action::remove(uint64_t snapshotid)
{
// get snapshot node of target in current session
Session *se = Mixer::manager().session();
XMLElement *sessionNode = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
if (snapshotid > 0)
open(snapshotid);
if (sessionNode) {
se->snapshots()->xmlDoc_->DeleteChild( sessionNode );
se->snapshots()->keys_.remove(snapshotid);
if (snapshot_node_) {
// remove
Session *se = Mixer::manager().session();
se->snapshots()->xmlDoc_->DeleteChild( snapshot_node_ );
se->snapshots()->keys_.remove( snapshot_id_ );
}
snapshot_node_ = nullptr;
snapshot_id_ = 0;
}
void Action::restore(uint64_t snapshotid)
@@ -260,23 +289,75 @@ void Action::restore(uint64_t snapshotid)
// lock
locked_ = true;
// get snapshot node of target in current session
Session *se = Mixer::manager().session();
XMLElement *sessionNode = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
if (snapshotid > 0)
open(snapshotid);
if (sessionNode) {
if (snapshot_node_)
// actually restore
Mixer::manager().restore(sessionNode);
}
Mixer::manager().restore(snapshot_node_);
// free
locked_ = false;
store("Snapshot " + label(snapshotid));
store("Snapshot " + label(snapshot_id_));
}
void Action::interpolate(uint64_t snapshotid, float val)
float Action::interpolation()
{
float ret = 0.f;
if ( interpolator_node_ == snapshot_node_ && interpolator_)
ret = interpolator_->current();
return ret;
}
void Action::interpolate(float val, uint64_t snapshotid)
{
if (snapshotid > 0)
open(snapshotid);
if (snapshot_node_) {
if ( interpolator_node_ != snapshot_node_ ) {
// change interpolator
if (interpolator_)
delete interpolator_;
// create new interpolator
interpolator_ = new Interpolator;
// current session
Session *se = Mixer::manager().session();
XMLElement* N = snapshot_node_->FirstChildElement("Source");
for( ; N ; N = N->NextSiblingElement()) {
// check if a source with the given id exists in the session
uint64_t id_xml_ = 0;
N->QueryUnsigned64Attribute("id", &id_xml_);
SourceList::iterator sit = se->find(id_xml_);
// a source with this id exists
if ( sit != se->end() ) {
// read target in the snapshot xml
SourceCore target;
SessionLoader::XMLToSourcecore(N, target);
// add an interpolator for this source
interpolator_->add(*sit, target);
}
}
// operate interpolation on opened snapshot
interpolator_node_ = snapshot_node_;
}
if (interpolator_) {
// Log::Info("Action::interpolate %f", val);
interpolator_->apply( val );
}
}
}

View File

@@ -6,7 +6,7 @@
#include <tinyxml2.h>
class Interpolator;
class Action
{
@@ -17,36 +17,41 @@ class Action
public:
static Action& manager()
static Action& manager ()
{
// The only instance
static Action _instance;
return _instance;
}
void init();
void init ();
// UNDO History
void store(const std::string &label);
void undo();
void redo();
void stepTo(uint target);
void store (const std::string &label);
void undo ();
void redo ();
void stepTo (uint target);
inline uint current() const { return history_step_; }
inline uint max() const { return history_max_step_; }
std::string label(uint s) const;
inline uint current () const { return history_step_; }
inline uint max () const { return history_max_step_; }
std::string label (uint s) const;
// Snapshots
void snapshot(const std::string &label);
void snapshot (const std::string &label);
std::list<uint64_t> snapshots() const;
void replace(uint64_t snapshotid);
void restore(uint64_t snapshotid);
void interpolate(uint64_t snapshotid, float val);
void remove (uint64_t snapshotid);
std::list<uint64_t> snapshots () const;
uint64_t currentSnapshot () const { return snapshot_id_; }
std::string label(uint64_t snapshotid) const;
void open (uint64_t snapshotid);
void replace (uint64_t snapshotid = 0);
void restore (uint64_t snapshotid = 0);
void remove (uint64_t snapshotid = 0);
std::string label (uint64_t snapshotid) const;
void setLabel (uint64_t snapshotid, const std::string &label);
float interpolation ();
void interpolate (float val, uint64_t snapshotid = 0);
private:
tinyxml2::XMLDocument history_doc_;
@@ -55,6 +60,11 @@ private:
std::atomic<bool> locked_;
void restore(uint target);
uint64_t snapshot_id_;
tinyxml2::XMLElement *snapshot_node_;
Interpolator *interpolator_;
tinyxml2::XMLElement *interpolator_node_;
};

View File

@@ -4,32 +4,163 @@
#include "defines.h"
#include "Log.h"
#include "Source.h"
#include "ImageProcessingShader.h"
#include "UpdateCallback.h"
#include "Interpolator.h"
Interpolator::Interpolator(Source *subject, const SourceCore &target) :
subject_(subject), from_(static_cast<SourceCore> (*subject)), to_(target), cursor_(0.f)
SourceInterpolator::SourceInterpolator(Source *subject, const SourceCore &target) :
subject_(subject), from_(static_cast<SourceCore>(*subject)), to_(target), current_cursor_(0.f)
{
}
void SourceInterpolator::interpolateGroup(View::Mode m)
{
current_state_.group(m)->translation_ =
(1.f - current_cursor_) * from_.group(m)->translation_
+ current_cursor_ * to_.group(m)->translation_;
current_state_.group(m)->scale_ =
(1.f - current_cursor_) * from_.group(m)->scale_
+ current_cursor_ * to_.group(m)->scale_;
current_state_.group(m)->rotation_ =
(1.f - current_cursor_) * from_.group(m)->rotation_
+ current_cursor_ * to_.group(m)->rotation_;
current_state_.group(m)->crop_ =
(1.f - current_cursor_) * from_.group(m)->crop_
+ current_cursor_ * to_.group(m)->crop_;
CopyCallback *anim = new CopyCallback( current_state_.group(m) );
subject_->group(m)->update_callbacks_.clear();
subject_->group(m)->update_callbacks_.push_back(anim);
}
void SourceInterpolator::interpolateImageProcessing()
{
current_state_.processingShader()->brightness =
(1.f - current_cursor_) * from_.processingShader()->brightness
+ current_cursor_ * to_.processingShader()->brightness;
current_state_.processingShader()->contrast =
(1.f - current_cursor_) * from_.processingShader()->contrast
+ current_cursor_ * to_.processingShader()->contrast;
current_state_.processingShader()->saturation =
(1.f - current_cursor_) * from_.processingShader()->saturation
+ current_cursor_ * to_.processingShader()->saturation;
current_state_.processingShader()->hueshift =
(1.f - current_cursor_) * from_.processingShader()->hueshift
+ current_cursor_ * to_.processingShader()->hueshift;
current_state_.processingShader()->threshold =
(1.f - current_cursor_) * from_.processingShader()->threshold
+ current_cursor_ * to_.processingShader()->threshold;
current_state_.processingShader()->lumakey =
(1.f - current_cursor_) * from_.processingShader()->lumakey
+ current_cursor_ * to_.processingShader()->lumakey;
current_state_.processingShader()->nbColors =
(1.f - current_cursor_) * from_.processingShader()->nbColors
+ current_cursor_ * to_.processingShader()->nbColors;
current_state_.processingShader()->gamma =
(1.f - current_cursor_) * from_.processingShader()->gamma
+ current_cursor_ * to_.processingShader()->gamma;
current_state_.processingShader()->levels =
(1.f - current_cursor_) * from_.processingShader()->levels
+ current_cursor_ * to_.processingShader()->levels;
current_state_.processingShader()->chromakey =
(1.f - current_cursor_) * from_.processingShader()->chromakey
+ current_cursor_ * to_.processingShader()->chromakey;
current_state_.processingShader()->chromadelta =
(1.f - current_cursor_) * from_.processingShader()->chromadelta
+ current_cursor_ * to_.processingShader()->chromadelta;
subject_->processingShader()->copy( *current_state_.processingShader() );
// not interpolated : invert , filterid
}
float SourceInterpolator::current() const
{
return current_cursor_;
}
void SourceInterpolator::apply(float percent)
{
percent = CLAMP( percent, 0.f, 1.f);
if ( subject_ && ABS_DIFF(current_cursor_, percent) > EPSILON)
{
current_cursor_ = percent;
if (current_cursor_ < EPSILON) {
current_cursor_ = 0.f;
current_state_ = from_;
subject_->copy(current_state_);
}
else if (current_cursor_ > 1.f - EPSILON) {
current_cursor_ = 1.f;
current_state_ = to_;
subject_->copy(current_state_);
}
else {
interpolateGroup(View::MIXING);
interpolateGroup(View::GEOMETRY);
interpolateGroup(View::LAYER);
interpolateGroup(View::TEXTURE);
interpolateImageProcessing();
// Log::Info("SourceInterpolator::update %f", cursor);
}
subject_->touch();
}
}
Interpolator::Interpolator()
{
}
Interpolator::~Interpolator()
{
for (auto i = interpolators_.begin(); i != interpolators_.end(); ) {
delete *i;
i = interpolators_.erase(i);
}
}
void Interpolator::add (Source *s, const SourceCore &target)
{
SourceInterpolator *i = new SourceInterpolator(s, target);
interpolators_.push_back(i);
}
float Interpolator::current() const
{
float ret = 0.f;
if (interpolators_.size() > 0)
ret = interpolators_.front()->current();
return ret;
}
void Interpolator::apply(float percent)
{
cursor_ = CLAMP( percent, 0.f, 1.f);
if (cursor_ < EPSILON)
current_ = from_;
else if (cursor_ > 1.f - EPSILON)
current_ = to_;
else {
// current_ =
}
subject_->copy(current_);
for (auto i = interpolators_.begin(); i != interpolators_.end(); ++i)
(*i)->apply( percent );
}

View File

@@ -2,21 +2,41 @@
#define INTERPOLATOR_H
#include "Source.h"
#include "SourceList.h"
class Interpolator
class SourceInterpolator
{
public:
Interpolator(Source *subject, const SourceCore &target);
SourceInterpolator(Source *subject, const SourceCore &target);
void apply (float percent);
float current() const;
protected:
Source *subject_;
SourceCore from_;
SourceCore to_;
SourceCore current_;
SourceCore current_state_;
float current_cursor_;
float cursor_;
void interpolateGroup (View::Mode m);
void interpolateImageProcessing ();
};
void apply(float percent);
class Interpolator
{
public:
Interpolator();
~Interpolator();
void add (Source *s, const SourceCore &target );
void apply (float percent);
float current() const;
protected:
std::list<SourceInterpolator *> interpolators_;
};

View File

@@ -60,7 +60,7 @@ void Node::copyTransform(const Node *other)
{
if (!other)
return;
transform_ = other->transform_;
// transform_ = other->transform_;
scale_ = other->scale_;
rotation_ = other->rotation_;
translation_ = other->translation_;

View File

@@ -530,6 +530,20 @@ void SessionLoader::XMLToNode(tinyxml2::XMLElement *xml, Node &n)
}
}
void SessionLoader::XMLToSourcecore( tinyxml2::XMLElement *xml, SourceCore &s)
{
SessionLoader::XMLToNode(xml->FirstChildElement("Mixing"), *s.group(View::MIXING) );
SessionLoader::XMLToNode(xml->FirstChildElement("Geometry"),*s.group(View::GEOMETRY) );
SessionLoader::XMLToNode(xml->FirstChildElement("Layer"), *s.group(View::LAYER) );
SessionLoader::XMLToNode(xml->FirstChildElement("Texture"), *s.group(View::TEXTURE) );
SessionLoader v(nullptr);
v.xmlCurrent_ = xml->FirstChildElement("ImageProcessing");
if (v.xmlCurrent_)
s.processingShader()->accept(v);
}
void SessionLoader::visit(Node &n)
{
XMLToNode(xmlCurrent_, n);

View File

@@ -58,6 +58,9 @@ public:
void visit (DeviceSource& s) override;
void visit (NetworkSource& s) override;
static void XMLToNode(tinyxml2::XMLElement *xml, Node &n);
static void XMLToSourcecore( tinyxml2::XMLElement *xml, SourceCore &s);
protected:
// result created session
Session *session_;
@@ -70,7 +73,6 @@ protected:
// list of groups (lists of xml source id)
std::list< SourceIdList > groups_sources_id_;
static void XMLToNode(tinyxml2::XMLElement *xml, Node &n);
};
class SessionCreator : public SessionLoader {

View File

@@ -64,6 +64,7 @@ void Settings::Save()
applicationNode->SetAttribute("scale", application.scale);
applicationNode->SetAttribute("accent_color", application.accent_color);
applicationNode->SetAttribute("smooth_transition", application.smooth_transition);
applicationNode->SetAttribute("smooth_snapshot", application.smooth_snapshot);
applicationNode->SetAttribute("smooth_cursor", application.smooth_cursor);
applicationNode->SetAttribute("action_history_follow_view", application.action_history_follow_view);
applicationNode->SetAttribute("accept_connections", application.accept_connections);
@@ -255,6 +256,7 @@ void Settings::Load()
applicationNode->QueryFloatAttribute("scale", &application.scale);
applicationNode->QueryIntAttribute("accent_color", &application.accent_color);
applicationNode->QueryBoolAttribute("smooth_transition", &application.smooth_transition);
applicationNode->QueryBoolAttribute("smooth_snapshot", &application.smooth_snapshot);
applicationNode->QueryBoolAttribute("smooth_cursor", &application.smooth_cursor);
applicationNode->QueryBoolAttribute("action_history_follow_view", &application.action_history_follow_view);
applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);

View File

@@ -178,6 +178,7 @@ struct Application
// Global settings Application interface
float scale;
int accent_color;
bool smooth_snapshot;
bool smooth_transition;
bool smooth_cursor;
bool action_history_follow_view;
@@ -221,7 +222,8 @@ struct Application
Application() : fresh_start(false), instance_id(0), name(APP_NAME), executable(APP_NAME) {
scale = 1.f;
accent_color = 0;
smooth_transition = true;
smooth_transition = false;
smooth_snapshot = false;
smooth_cursor = false;
action_history_follow_view = false;
accept_connections = false;

View File

@@ -69,7 +69,7 @@ SourceCore::~SourceCore()
void SourceCore::copy(SourceCore const& other)
{
// copy groups properties
groups_[View::RENDERING]->copyTransform( other.group(View::RENDERING) );
// groups_[View::RENDERING]->copyTransform( other.group(View::RENDERING) );
groups_[View::MIXING]->copyTransform( other.group(View::MIXING) );
groups_[View::GEOMETRY]->copyTransform( other.group(View::GEOMETRY) );
groups_[View::LAYER]->copyTransform( other.group(View::LAYER) );
@@ -84,14 +84,13 @@ void SourceCore::copy(SourceCore const& other)
void SourceCore::store (View::Mode m)
{
stored_status_->copyTransform(groups_[m]);
stored_status_->copyTransform(groups_[m]);
}
SourceCore& SourceCore::operator= (SourceCore const& other)
{
if (this != &other) { // no self assignment
if (this != &other) // no self assignment
copy(other);
}
return *this;
}

View File

@@ -5,9 +5,11 @@
#include <glm/glm.hpp>
class Source;
class SourceCore;
class Session;
typedef std::list<Source *> SourceList;
typedef std::list<SourceCore *> SourceCoreList;
SourceList depth_sorted (const SourceList &list);
SourceList mixing_sorted (const SourceList &list, glm::vec2 center = glm::vec2(0.f, 0.f));

View File

@@ -11,6 +11,18 @@ UpdateCallback::UpdateCallback() : enabled_(true), finished_(false)
}
CopyCallback::CopyCallback(Node *target) : UpdateCallback(), target_(target)
{
}
void CopyCallback::update(Node *n, float dt)
{
n->copyTransform(target_);
finished_ = true;
}
MoveToCallback::MoveToCallback(glm::vec3 target, float duration) : UpdateCallback(),
duration_(duration), progress_(0.f), initialized_(false), target_(target)
{

View File

@@ -22,6 +22,15 @@ protected:
bool finished_;
};
class CopyCallback : public UpdateCallback
{
Node *target_;
public:
CopyCallback(Node *target);
void update(Node *n, float dt);
};
class MoveToCallback : public UpdateCallback
{
float duration_;

View File

@@ -3129,14 +3129,14 @@ void Navigator::RenderMainPannelVimix()
ImGui::TextDisabled( ICON_FA_REDO );
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()) );
ImGuiToolkit::ButtonToggle(ICON_FA_ELLIPSIS_H, &Settings::application.action_history_follow_view);
ImGuiToolkit::ButtonToggle(ICON_FA_LOCATION_ARROW, &Settings::application.action_history_follow_view);
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Go to view of action");
ImGuiToolkit::ToolTip("Show in view");
}
else {
std::list<uint64_t> snapshots = Action::manager().snapshots();
static uint64_t current_snapshot = 0;
// static uint64_t current_snapshot = Action::manager().currentSnapshot();
pos_top = ImGui::GetCursorPos();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
@@ -3147,20 +3147,20 @@ void Navigator::RenderMainPannelVimix()
{
// size of items
ImVec2 s = size;
if ( current_snapshot == *snapit )
bool selected = ( *snapit == Action::manager().currentSnapshot() );
if ( selected )
s.x -= ImGui::GetTextLineHeightWithSpacing();
// entry
if (ImGui::Selectable( Action::manager().label(*snapit).c_str(), current_snapshot == *snapit, ImGuiSelectableFlags_AllowDoubleClick, s )) {
if (ImGui::Selectable( Action::manager().label(*snapit).c_str(), selected, ImGuiSelectableFlags_AllowDoubleClick, s )) {
// current list item
current_snapshot = *snapit;
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
// trigger snapshot
Action::manager().restore(current_snapshot);
current_snapshot = 0;
}
Action::manager().open(*snapit);
// trigger snapshot
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
Action::manager().restore();
}
// context menu
if ( current_snapshot == *snapit ) {
if ( selected ) {
ImGui::SameLine();
if ( ImGuiToolkit::IconButton( ICON_FA_CHEVRON_DOWN ) )
ImGui::OpenPopup( "MenuSnapshot" );
@@ -3170,25 +3170,19 @@ void Navigator::RenderMainPannelVimix()
// context menu
if (ImGui::BeginPopup( "MenuSnapshot" ))
{
if (ImGui::Selectable( " " ICON_FA_ANGLE_DOUBLE_RIGHT " Apply", false, 0, size )) {
Action::manager().restore(current_snapshot);
current_snapshot = 0;
}
if (ImGui::Selectable( ICON_FA_STAR "_ Remove", false, 0, size )) {
Action::manager().remove(current_snapshot);
current_snapshot = 0;
}
if (ImGui::Selectable( ICON_FA_STAR "= Replace", false, 0, size )) {
Action::manager().replace(current_snapshot);
current_snapshot = 0;
}
if (ImGui::Selectable( " " ICON_FA_ANGLE_DOUBLE_RIGHT " Apply", false, 0, size ))
Action::manager().restore();
if (ImGui::Selectable( ICON_FA_STAR "_ Remove", false, 0, size ))
Action::manager().remove();
if (ImGui::Selectable( ICON_FA_STAR "= Replace", false, 0, size ))
Action::manager().replace();
ImGui::TextDisabled("Rename");
ImGui::SetNextItemWidth(size.x);
if ( current_snapshot > 0 ) {
if ( Action::manager().currentSnapshot() > 0 ) {
static std::string label;
label = Action::manager().label(current_snapshot);
label = Action::manager().label( Action::manager().currentSnapshot() );
if ( ImGuiToolkit::InputText("##Rename", &label ) )
Action::manager().setLabel(current_snapshot, label);
Action::manager().setLabel( Action::manager().currentSnapshot(), label);
}
ImGui::EndPopup();
}
@@ -3199,13 +3193,18 @@ void Navigator::RenderMainPannelVimix()
// right buttons
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y ));
if ( ImGuiToolkit::IconButton( ICON_FA_STAR "+")) {
if ( ImGuiToolkit::IconButton( ICON_FA_STAR "+"))
Action::manager().snapshot( SystemToolkit::date_time_string() );
current_snapshot = 0;
}
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Take Snapshot ", CTRL_MOD "Y");
// toggle button for smooth transition
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()) );
ImGuiToolkit::ButtonToggle(ICON_FA_ROUTE, &Settings::application.smooth_snapshot);
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Interpolation");
// // active list element : delete snapshot button
// ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()));
// if (current_snapshot != snapshots.end()) {
@@ -3218,13 +3217,13 @@ void Navigator::RenderMainPannelVimix()
// else
// ImGui::TextDisabled( ICON_FA_STAR "_" );
if (current_snapshot > 0) {
if (Action::manager().currentSnapshot() > 0) {
ImGui::SetCursorPos( pos_bot );
static float interpolation = 0.f;
int interpolation = static_cast<int> (Action::manager().interpolation() * 100.f);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::SliderFloat("Animate", &interpolation, 0.f, 1.f) ) {
if ( ImGui::SliderInt("Animate", &interpolation, 0, 100, "%d %%") )
Action::manager().interpolate( static_cast<float> ( interpolation ) * 0.01f );
}
}
}