mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Save thumbnail of session when storing history or snapshot
This commit is contained in:
@@ -20,11 +20,41 @@
|
|||||||
#define ACTION_DEBUG
|
#define ACTION_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HISTORY_NODE(i) std::to_string(i).insert(0, "H").c_str()
|
#define HISTORY_NODE(i) std::to_string(i).insert(0, "H")
|
||||||
#define SNAPSHOT_NODE(i) std::to_string(i).insert(0, "S").c_str()
|
#define SNAPSHOT_NODE(i) std::to_string(i).insert(0, "S")
|
||||||
|
|
||||||
using namespace tinyxml2;
|
using namespace tinyxml2;
|
||||||
|
|
||||||
|
void captureMixerSession(tinyxml2::XMLDocument *doc, std::string node, std::string label)
|
||||||
|
{
|
||||||
|
// get session to operate on
|
||||||
|
Session *se = Mixer::manager().session();
|
||||||
|
se->lock();
|
||||||
|
|
||||||
|
// create node
|
||||||
|
XMLElement *sessionNode = doc->NewElement( node.c_str() );
|
||||||
|
doc->InsertEndChild(sessionNode);
|
||||||
|
// label describes the action
|
||||||
|
sessionNode->SetAttribute("label", label.c_str() );
|
||||||
|
// view indicates the view when this action occured
|
||||||
|
sessionNode->SetAttribute("view", (int) Mixer::manager().view()->mode());
|
||||||
|
|
||||||
|
// get the thumbnail (requires one opengl update to render)
|
||||||
|
FrameBufferImage *thumbnail = se->thumbnail();
|
||||||
|
XMLElement *imageelement = SessionVisitor::ImageToXML(thumbnail, doc);
|
||||||
|
if (imageelement)
|
||||||
|
sessionNode->InsertEndChild(imageelement);
|
||||||
|
delete thumbnail;
|
||||||
|
|
||||||
|
// save all sources using source visitor
|
||||||
|
SessionVisitor sv(doc, sessionNode);
|
||||||
|
for (auto iter = se->begin(); iter != se->end(); ++iter, sv.setRoot(sessionNode) )
|
||||||
|
(*iter)->accept(sv);
|
||||||
|
|
||||||
|
se->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Action::Action(): history_step_(0), history_max_step_(0), locked_(false),
|
Action::Action(): history_step_(0), history_max_step_(0), locked_(false),
|
||||||
snapshot_id_(0), snapshot_node_(nullptr), interpolator_(nullptr), interpolator_node_(nullptr)
|
snapshot_id_(0), snapshot_node_(nullptr), interpolator_(nullptr), interpolator_node_(nullptr)
|
||||||
{
|
{
|
||||||
@@ -56,32 +86,18 @@ void Action::store(const std::string &label)
|
|||||||
|
|
||||||
// erase future
|
// erase future
|
||||||
for (uint e = history_step_; e <= history_max_step_; e++) {
|
for (uint e = history_step_; e <= history_max_step_; e++) {
|
||||||
XMLElement *node = history_doc_.FirstChildElement( HISTORY_NODE(e) );
|
XMLElement *node = history_doc_.FirstChildElement( HISTORY_NODE(e).c_str() );
|
||||||
if ( node )
|
if ( node )
|
||||||
history_doc_.DeleteChild(node);
|
history_doc_.DeleteChild(node);
|
||||||
}
|
}
|
||||||
history_max_step_ = history_step_;
|
history_max_step_ = history_step_;
|
||||||
|
|
||||||
// create history node
|
// threaded capturing state of current session
|
||||||
XMLElement *sessionNode = history_doc_.NewElement( HISTORY_NODE(history_step_) );
|
std::thread(captureMixerSession, &history_doc_, HISTORY_NODE(history_step_), label).detach();
|
||||||
history_doc_.InsertEndChild(sessionNode);
|
|
||||||
// label describes the action
|
|
||||||
sessionNode->SetAttribute("label", label.c_str());
|
|
||||||
// view indicates the view when this action occured
|
|
||||||
sessionNode->SetAttribute("view", (int) Mixer::manager().view()->mode());
|
|
||||||
|
|
||||||
// get session to operate on
|
|
||||||
Session *se = Mixer::manager().session();
|
|
||||||
|
|
||||||
// save all sources using source visitor
|
|
||||||
SessionVisitor sv(&history_doc_, sessionNode);
|
|
||||||
for (auto iter = se->begin(); iter != se->end(); ++iter, sv.setRoot(sessionNode) )
|
|
||||||
(*iter)->accept(sv);
|
|
||||||
|
|
||||||
// debug
|
|
||||||
#ifdef ACTION_DEBUG
|
#ifdef ACTION_DEBUG
|
||||||
Log::Info("Action stored %d '%s'", history_step_, label.c_str());
|
Log::Info("Action stored %d '%s'", history_step_, label.c_str());
|
||||||
// XMLSaveDoc(&xmlDoc_, "/home/bhbn/history.xml");
|
XMLSaveDoc(&history_doc_, "/home/bhbn/history.xml");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,12 +137,26 @@ std::string Action::label(uint s) const
|
|||||||
std::string l = "";
|
std::string l = "";
|
||||||
|
|
||||||
if (s > 0 && s <= history_max_step_) {
|
if (s > 0 && s <= history_max_step_) {
|
||||||
const XMLElement *sessionNode = history_doc_.FirstChildElement( HISTORY_NODE(s));
|
const XMLElement *sessionNode = history_doc_.FirstChildElement( HISTORY_NODE(s).c_str());
|
||||||
l = sessionNode->Attribute("label");
|
if (sessionNode)
|
||||||
|
l = sessionNode->Attribute("label");
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameBufferImage *Action::thumbnail(uint s) const
|
||||||
|
{
|
||||||
|
FrameBufferImage *img = nullptr;
|
||||||
|
|
||||||
|
if (s > 0 && s <= history_max_step_) {
|
||||||
|
const XMLElement *sessionNode = history_doc_.FirstChildElement( HISTORY_NODE(s).c_str());
|
||||||
|
if (sessionNode)
|
||||||
|
img = SessionLoader::XMLToImage(sessionNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
void Action::restore(uint target)
|
void Action::restore(uint target)
|
||||||
{
|
{
|
||||||
// lock
|
// lock
|
||||||
@@ -134,7 +164,7 @@ void Action::restore(uint target)
|
|||||||
|
|
||||||
// get history node of target step
|
// get history node of target step
|
||||||
history_step_ = CLAMP(target, 1, history_max_step_);
|
history_step_ = CLAMP(target, 1, history_max_step_);
|
||||||
XMLElement *sessionNode = history_doc_.FirstChildElement( HISTORY_NODE(history_step_) );
|
XMLElement *sessionNode = history_doc_.FirstChildElement( HISTORY_NODE(history_step_).c_str() );
|
||||||
|
|
||||||
if (sessionNode) {
|
if (sessionNode) {
|
||||||
|
|
||||||
@@ -152,34 +182,24 @@ void Action::restore(uint target)
|
|||||||
locked_ = false;
|
locked_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Action::snapshot(const std::string &label)
|
void Action::snapshot(const std::string &label)
|
||||||
{
|
{
|
||||||
// ignore if locked or if no label is given
|
// ignore if locked or if no label is given
|
||||||
if (locked_ || label.empty())
|
if (locked_ || label.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// get session to operate on
|
|
||||||
Session *se = Mixer::manager().session();
|
|
||||||
|
|
||||||
// create snapshot id
|
// create snapshot id
|
||||||
u_int64_t id = GlmToolkit::uniqueId();
|
u_int64_t id = GlmToolkit::uniqueId();
|
||||||
|
|
||||||
|
// get session to operate on
|
||||||
|
Session *se = Mixer::manager().session();
|
||||||
se->snapshots()->keys_.push_back(id);
|
se->snapshots()->keys_.push_back(id);
|
||||||
|
|
||||||
// create snapshot node
|
// threaded capture state of current session
|
||||||
XMLElement *sessionNode = se->snapshots()->xmlDoc_->NewElement( SNAPSHOT_NODE(id) );
|
std::thread(captureMixerSession, se->snapshots()->xmlDoc_, SNAPSHOT_NODE(id), label).detach();
|
||||||
se->snapshots()->xmlDoc_->InsertEndChild(sessionNode);
|
|
||||||
|
|
||||||
// label describes the snapshot
|
|
||||||
sessionNode->SetAttribute("label", label.c_str());
|
|
||||||
|
|
||||||
// save all sources using source visitor
|
|
||||||
SessionVisitor sv(se->snapshots()->xmlDoc_, sessionNode);
|
|
||||||
for (auto iter = se->begin(); iter != se->end(); ++iter, sv.setRoot(sessionNode) )
|
|
||||||
(*iter)->accept(sv);
|
|
||||||
|
|
||||||
// TODO: copy current action history instead?
|
|
||||||
|
|
||||||
// debug
|
|
||||||
#ifdef ACTION_DEBUG
|
#ifdef ACTION_DEBUG
|
||||||
Log::Info("Snapshot stored %d '%s'", id, label.c_str());
|
Log::Info("Snapshot stored %d '%s'", id, label.c_str());
|
||||||
#endif
|
#endif
|
||||||
@@ -191,7 +211,7 @@ void Action::open(uint64_t snapshotid)
|
|||||||
{
|
{
|
||||||
// get snapshot node of target in current session
|
// get snapshot node of target in current session
|
||||||
Session *se = Mixer::manager().session();
|
Session *se = Mixer::manager().session();
|
||||||
snapshot_node_ = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
|
snapshot_node_ = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid).c_str() );
|
||||||
|
|
||||||
if (snapshot_node_)
|
if (snapshot_node_)
|
||||||
snapshot_id_ = snapshotid;
|
snapshot_id_ = snapshotid;
|
||||||
@@ -220,7 +240,7 @@ void Action::replace(uint64_t snapshotid)
|
|||||||
se->snapshots()->xmlDoc_->DeleteChild( snapshot_node_ );
|
se->snapshots()->xmlDoc_->DeleteChild( snapshot_node_ );
|
||||||
|
|
||||||
// create snapshot node
|
// create snapshot node
|
||||||
snapshot_node_ = se->snapshots()->xmlDoc_->NewElement( SNAPSHOT_NODE(snapshot_id_) );
|
snapshot_node_ = se->snapshots()->xmlDoc_->NewElement( SNAPSHOT_NODE(snapshot_id_).c_str() );
|
||||||
se->snapshots()->xmlDoc_->InsertEndChild(snapshot_node_);
|
se->snapshots()->xmlDoc_->InsertEndChild(snapshot_node_);
|
||||||
|
|
||||||
// save all sources using source visitor
|
// save all sources using source visitor
|
||||||
@@ -242,8 +262,7 @@ void Action::replace(uint64_t snapshotid)
|
|||||||
|
|
||||||
std::list<uint64_t> Action::snapshots() const
|
std::list<uint64_t> Action::snapshots() const
|
||||||
{
|
{
|
||||||
Session *se = Mixer::manager().session();
|
return Mixer::manager().session()->snapshots()->keys_;
|
||||||
return se->snapshots()->keys_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Action::label(uint64_t snapshotid) const
|
std::string Action::label(uint64_t snapshotid) const
|
||||||
@@ -252,7 +271,7 @@ std::string Action::label(uint64_t snapshotid) const
|
|||||||
|
|
||||||
// get snapshot node of target in current session
|
// get snapshot node of target in current session
|
||||||
Session *se = Mixer::manager().session();
|
Session *se = Mixer::manager().session();
|
||||||
const XMLElement *snap = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid) );
|
const XMLElement *snap = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid).c_str() );
|
||||||
|
|
||||||
if (snap)
|
if (snap)
|
||||||
label = snap->Attribute("label");
|
label = snap->Attribute("label");
|
||||||
@@ -268,6 +287,21 @@ void Action::setLabel (uint64_t snapshotid, const std::string &label)
|
|||||||
snapshot_node_->SetAttribute("label", label.c_str());
|
snapshot_node_->SetAttribute("label", label.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameBufferImage *Action::thumbnail(uint64_t snapshotid) const
|
||||||
|
{
|
||||||
|
FrameBufferImage *img = nullptr;
|
||||||
|
|
||||||
|
// get snapshot node of target in current session
|
||||||
|
Session *se = Mixer::manager().session();
|
||||||
|
const XMLElement *snap = se->snapshots()->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(snapshotid).c_str() );
|
||||||
|
|
||||||
|
if (snap){
|
||||||
|
img = SessionLoader::XMLToImage(snap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
void Action::remove(uint64_t snapshotid)
|
void Action::remove(uint64_t snapshotid)
|
||||||
{
|
{
|
||||||
if (snapshotid > 0)
|
if (snapshotid > 0)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
class Interpolator;
|
class Interpolator;
|
||||||
|
class FrameBufferImage;
|
||||||
|
|
||||||
class Action
|
class Action
|
||||||
{
|
{
|
||||||
@@ -25,7 +26,7 @@ public:
|
|||||||
}
|
}
|
||||||
void init ();
|
void init ();
|
||||||
|
|
||||||
// UNDO History
|
// Undo History
|
||||||
void store (const std::string &label);
|
void store (const std::string &label);
|
||||||
void undo ();
|
void undo ();
|
||||||
void redo ();
|
void redo ();
|
||||||
@@ -34,6 +35,7 @@ public:
|
|||||||
inline uint current () const { return history_step_; }
|
inline uint current () const { return history_step_; }
|
||||||
inline uint max () const { return history_max_step_; }
|
inline uint max () const { return history_max_step_; }
|
||||||
std::string label (uint s) const;
|
std::string label (uint s) const;
|
||||||
|
FrameBufferImage *thumbnail (uint s) const;
|
||||||
|
|
||||||
// Snapshots
|
// Snapshots
|
||||||
void snapshot (const std::string &label);
|
void snapshot (const std::string &label);
|
||||||
@@ -48,6 +50,7 @@ public:
|
|||||||
|
|
||||||
std::string label (uint64_t snapshotid) const;
|
std::string label (uint64_t snapshotid) const;
|
||||||
void setLabel (uint64_t snapshotid, const std::string &label);
|
void setLabel (uint64_t snapshotid, const std::string &label);
|
||||||
|
FrameBufferImage *thumbnail (uint64_t snapshotid) const;
|
||||||
|
|
||||||
float interpolation ();
|
float interpolation ();
|
||||||
void interpolate (float val, uint64_t snapshotid = 0);
|
void interpolate (float val, uint64_t snapshotid = 0);
|
||||||
@@ -65,6 +68,7 @@ private:
|
|||||||
|
|
||||||
Interpolator *interpolator_;
|
Interpolator *interpolator_;
|
||||||
tinyxml2::XMLElement *interpolator_node_;
|
tinyxml2::XMLElement *interpolator_node_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user