Large commit for implementation of load&save of MixingGroups

This commit is contained in:
Bruno
2021-03-07 19:27:00 +01:00
parent 56f0165d75
commit 7656113dcc
22 changed files with 525 additions and 132 deletions
+2 -2
View File
@@ -169,7 +169,7 @@ void Action::restore(uint target, uint64_t id)
return;
// sessionsources contains list of ids of all sources currently in the session
std::list<uint64_t> sessionsources = se->getIdList();
SourceIdList sessionsources = se->getIdList();
// for( auto it = sessionsources.begin(); it != sessionsources.end(); it++)
// Log::Info("sessionsources id %s", std::to_string(*it).c_str());
@@ -180,7 +180,7 @@ void Action::restore(uint target, uint64_t id)
loader.load( sessionNode );
// loadersources contains list of ids of all sources generated by loader
std::list<uint64_t> loadersources = loader.getIdList();
SourceIdList loadersources = loader.getIdList();
// for( auto it = loadersources.begin(); it != loadersources.end(); it++)
// Log::Info("loadersources id %s", std::to_string(*it).c_str());
+1
View File
@@ -280,6 +280,7 @@ set(VMIX_SRCS
TextureView.cpp
TransitionView.cpp
Source.cpp
SourceList.cpp
Session.cpp
Selection.cpp
SessionSource.cpp
+3 -3
View File
@@ -109,7 +109,7 @@ void LayerView::draw()
// manipulation of sources in Mixing view
if (ImGui::Selectable( ICON_FA_ALIGN_CENTER " Distribute" )){
SourceList dsl = depthSorted(Mixer::selection().getCopy());
SourceList dsl = depth_sorted(Mixer::selection().getCopy());
SourceList::iterator it = dsl.begin();
float depth = (*it)->depth();
float depth_inc = (dsl.back()->depth() - depth) / static_cast<float>(Mixer::selection().size()-1);
@@ -120,7 +120,7 @@ void LayerView::draw()
View::need_deep_update_++;
}
if (ImGui::Selectable( ICON_FA_RULER_HORIZONTAL " Space equally" )){
SourceList dsl = depthSorted(Mixer::selection().getCopy());
SourceList dsl = depth_sorted(Mixer::selection().getCopy());
SourceList::iterator it = dsl.begin();
float depth = (*it)->depth();
for (it++; it != dsl.end(); it++) {
@@ -130,7 +130,7 @@ void LayerView::draw()
View::need_deep_update_++;
}
if (ImGui::Selectable( ICON_FA_EXCHANGE_ALT " Reverse order" )){
SourceList dsl = depthSorted(Mixer::selection().getCopy());
SourceList dsl = depth_sorted(Mixer::selection().getCopy());
SourceList::iterator it = dsl.begin();
SourceList::reverse_iterator rit = dsl.rbegin();
for (; it != dsl.end(); it++, rit++) {
+48 -2
View File
@@ -28,6 +28,7 @@ using namespace tinyxml2;
#include "StreamSource.h"
#include "NetworkSource.h"
#include "ActionManager.h"
#include "MixingGroup.h"
#include "Streamer.h"
#include "Mixer.h"
@@ -208,6 +209,22 @@ void Mixer::update()
// update session and associated sources
session_->update(dt_);
// update session's mixing groups
auto group_iter = session_->beginMixingGroup();
while ( group_iter != session_->endMixingGroup() ){
// update all valid groups
if ((*group_iter)->size() > 1) {
(*group_iter)->update(dt_);
group_iter++;
}
// delete invalid groups (singletons)
else {
mixing_.scene.fg()->detach( (*group_iter)->group() );
delete (*group_iter);
group_iter = session_->eraseMixingGroup(group_iter);
}
}
// grab frames to recorders & streamers
FrameGrabbing::manager().grabFrame(session_->frame(), dt_);
@@ -768,7 +785,7 @@ Source * Mixer::findSource (uint64_t id)
SourceList Mixer::findSources (float depth_from, float depth_to)
{
SourceList found;
SourceList dsl = depthSorted( session_->getCopy() );
SourceList dsl = session_->depthSorted();
SourceList::iterator it = dsl.begin();
for (; it != dsl.end(); it++) {
if ( (*it)->depth() > depth_to )
@@ -1037,6 +1054,16 @@ void Mixer::merge(Session *session)
attach(s);
}
// import and attach session's mixing groups
auto group_iter = session->beginMixingGroup();
while ( group_iter != session->endMixingGroup() ){
if (session_->addMixingGroup( *group_iter ) )
mixing_.scene.fg()->attach( (*group_iter)->group() );
else
delete (*group_iter);
group_iter = session->eraseMixingGroup(group_iter);
}
// needs to update !
View::need_deep_update_++;
@@ -1064,7 +1091,7 @@ void Mixer::merge(SessionSource *source)
float target_depth = source->depth();
// get how much space we need from there
SourceList dsl = depthSorted( session->getCopy() );
SourceList dsl = session->depthSorted();
float start_depth = dsl.front()->depth();
float end_depth = dsl.back()->depth();
float need_depth = MAX( end_depth - start_depth, LAYER_STEP);
@@ -1112,6 +1139,16 @@ void Mixer::merge(SessionSource *source)
attach(s);
}
// import and attach session's mixing groups
auto group_iter = session->beginMixingGroup();
while ( group_iter != session->endMixingGroup() ){
if (session_->addMixingGroup( *group_iter ) )
mixing_.scene.fg()->attach( (*group_iter)->group() );
else
delete (*group_iter);
group_iter = session->eraseMixingGroup(group_iter);
}
// needs to update !
View::need_deep_update_++;
@@ -1133,6 +1170,9 @@ void Mixer::swap()
// detatch current session's nodes from views
for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++)
detach(*source_iter);
// detatch current session's mixing groups
for (auto group_iter = session_->beginMixingGroup(); group_iter != session_->endMixingGroup(); group_iter++)
mixing_.scene.fg()->detach( (*group_iter)->group() );
}
// swap back and front
@@ -1150,6 +1190,10 @@ void Mixer::swap()
layer_.scene.root()->copyTransform( session_->config(View::LAYER) );
appearance_.scene.root()->copyTransform( session_->config(View::TEXTURE) );
// attach new session's mixing group to mixingview
for (auto group_iter = session_->beginMixingGroup(); group_iter != session_->endMixingGroup(); group_iter++)
mixing_.scene.fg()->attach( (*group_iter)->group() );
// set resolution
session_->setResolution( session_->config(View::RENDERING)->scale_ );
@@ -1258,4 +1302,6 @@ void Mixer::paste(const std::string& clipboard)
}
}
// TODO : Mixing groups
}
+59 -40
View File
@@ -1,5 +1,4 @@
#include <algorithm>
#include <vector>
#include <glm/gtx/vector_angle.hpp>
#include <glm/gtx/rotate_vector.hpp>
@@ -7,41 +6,33 @@
#include "defines.h"
#include "Source.h"
#include "Decorations.h"
#include "Visitor.h"
#include "Mixer.h"
#include "Log.h"
#include "MixingGroup.h"
// utility to sort Sources in MixingView in a clockwise order
// in reference to a center point
struct clockwise_centered {
clockwise_centered(glm::vec2 c) : center(c) { }
bool operator() (Source * first, Source * second) {
glm::vec2 pos_first = glm::vec2(first->group(View::MIXING)->translation_)-center;
float angle_first = glm::orientedAngle( glm::normalize(pos_first), glm::vec2(1.f, 0.f) );
glm::vec2 pos_second = glm::vec2(second->group(View::MIXING)->translation_)-center;
float angle_second = glm::orientedAngle( glm::normalize(pos_second), glm::vec2(1.f, 0.f) );
return (angle_first < angle_second);
}
glm::vec2 center;
};
MixingGroup::MixingGroup (SourceList sources) : root_(nullptr), lines_(nullptr), center_(nullptr),
center_pos_(glm::vec2(0.f, 0.f)), active_(true)
center_pos_(glm::vec2(0.f, 0.f)), active_(true), update_action_(ACTION_NONE), updated_source_(nullptr)
{
// fill the vector of sources with the given list
for (auto it = sources.begin(); it != sources.end(); it++){
(*it)->mixinggroup_ = this;
sources_.push_back(*it);
// compute barycenter (1)
center_pos_ += glm::vec2((*it)->group(View::MIXING)->translation_);
// add only if not linked already
if ((*it)->mixinggroup_ == nullptr) {
(*it)->mixinggroup_ = this;
sources_.push_back(*it);
// compute barycenter on the way (1)
center_pos_ += glm::vec2((*it)->group(View::MIXING)->translation_);
}
}
// compute barycenter (2)
center_pos_ /= sources_.size();
// sort the vector of sources in clockwise order around the center pos_
std::sort(sources_.begin(), sources_.end(), clockwise_centered(center_pos_));
sources_ = mixing_sorted( sources_, center_pos_);
// scene elements
root_ = new Group;
center_ = new Symbol(Symbol::CIRCLE_POINT);
center_->visible_ = false;
@@ -54,10 +45,17 @@ MixingGroup::MixingGroup (SourceList sources) : root_(nullptr), lines_(nullptr),
MixingGroup::~MixingGroup ()
{
delete center_;
for (auto it = sources_.begin(); it != sources_.end(); it++) {
(*it)->mixinggroup_ = nullptr;
(*it)->overlay_mixinggroup_->visible_ = false;
}
delete root_;
if (lines_)
delete lines_;
}
void MixingGroup::accept(Visitor& v)
{
v.visit(*this);
}
void MixingGroup::update (float dt)
@@ -168,9 +166,11 @@ void MixingGroup::setActive (bool on)
void MixingGroup::detach (Source *s)
{
// find the source
std::vector<Source *>::iterator its = std::find(sources_.begin(), sources_.end(), s);
SourceList::iterator its = std::find(sources_.begin(), sources_.end(), s);
// ok, its in the list !
if (its != sources_.end()) {
// tell the source
(*its)->mixinggroup_ = nullptr;
// erase the source from the list
sources_.erase(its);
// clear index, delete lines_, and recreate path and index with remaining sources
@@ -178,32 +178,52 @@ void MixingGroup::detach (Source *s)
}
}
void MixingGroup::move (Source *s)
uint MixingGroup::size()
{
return sources_.size();
}
SourceList::iterator MixingGroup::begin ()
{
return sources_.begin();
}
SourceList::iterator MixingGroup::end ()
{
return sources_.end();
}
bool MixingGroup::contains (Source *s)
{
// find the source
std::vector<Source *>::iterator its = std::find(sources_.begin(), sources_.end(), s);
// ok, its in the list !
if (its != sources_.end() && lines_) {
SourceList::iterator its = std::find(sources_.begin(), sources_.end(), s);
// in the list ?
return its != sources_.end();
}
void MixingGroup::move (Source *s)
{
if (contains(s) && lines_) {
// modify one point in the path
lines_->editPath(index_points_[s], glm::vec2(s->group(View::MIXING)->translation_));
}
}
void MixingGroup::createLineStrip()
{
if (lines_) {
root_->detach(lines_);
delete lines_;
}
index_points_.clear();
if (sources_.size() > 1) {
if (lines_) {
root_->detach(lines_);
delete lines_;
}
index_points_.clear();
// path linking all sources
std::vector<glm::vec2> path;
auto it = sources_.begin();
// link sources
for (; it != sources_.end(); it++){
for (auto it = sources_.begin(); it != sources_.end(); it++){
index_points_[*it] = path.size();
path.push_back(glm::vec2((*it)->group(View::MIXING)->translation_));
}
@@ -211,7 +231,6 @@ void MixingGroup::createLineStrip()
// create
lines_ = new LineLoop(path, 1.5f);
lines_->shader()->color = glm::vec4(COLOR_MIXING_GROUP, 0.96f);
root_->attach(lines_);
}
}
+14 -7
View File
@@ -4,6 +4,7 @@
#include <map>
#include "View.h"
#include "SourceList.h"
class LineLoop;
class Symbol;
@@ -15,29 +16,34 @@ public:
MixingGroup (SourceList sources);
~MixingGroup ();
// actions for update
typedef enum {
ACTION_NONE = 0,
ACTION_GRAB_ONE = 1,
ACTION_GRAB_ALL = 2,
ACTION_ROTATE_ALL = 3
} Action;
// actions for update
inline void setAction (Action a) { update_action_ = a; }
inline Action action () { return update_action_; }
inline void follow (Source *s) { updated_source_ = s; }
// get node to draw
// node to draw
inline Group *group () { return root_; }
// accept all kind of visitors
virtual void accept (Visitor& v);
// to update in Mixing View
void update (float dt);
inline bool active () const { return active_; }
void setActive (bool on);
// individual change of a source in the group
// Source list manipulation
SourceList::iterator begin ();
SourceList::iterator end ();
uint size ();
bool contains (Source *s);
void detach (Source *s);
void move (Source *s);
private:
@@ -46,10 +52,11 @@ private:
LineLoop *lines_;
Symbol *center_;
void createLineStrip();
void move (Source *s);
// properties linked to sources
glm::vec2 center_pos_;
std::vector<Source *> sources_;
glm::vec2 center_pos_;
SourceList sources_;
std::map< Source *, uint> index_points_;
// status and actions
+7 -7
View File
@@ -129,8 +129,7 @@ void MixingView::draw()
// special action of Mixing view
if (ImGui::Selectable( ICON_FA_DRAW_POLYGON " Link" )){
// TODO create MixingGroup
MixingGroup *mg = new MixingGroup(Mixer::selection().getCopy());
groups_.push_back(mg);
MixingGroup *mg = Mixer::manager().session()->createMixingGroup(Mixer::selection().getCopy());
scene.fg()->attach(mg->group());
Source *cur = Mixer::selection().front();
Mixer::manager().unsetCurrentSource();
@@ -196,9 +195,9 @@ void MixingView::update(float dt)
{
View::update(dt);
// always update the mixinggroups
for (auto g = groups_.begin(); g != groups_.end(); g++)
(*g)->update(dt);
// // always update the mixinggroups
// for (auto g = groups_.begin(); g != groups_.end(); g++)
// (*g)->update(dt);
// a more complete update is requested
// for mixing, this means restore position of the fading slider
@@ -398,8 +397,9 @@ void MixingView::terminate()
{
View::terminate();
// terminate all group actions
for (auto g = groups_.begin(); g != groups_.end(); g++)
// terminate all mixing group actions
for (auto g = Mixer::manager().session()->beginMixingGroup();
g != Mixer::manager().session()->endMixingGroup(); g++)
(*g)->setAction( MixingGroup::ACTION_NONE );
}
+1 -4
View File
@@ -3,7 +3,7 @@
#include "View.h"
class MixingGroup;
//class MixingGroup;
class MixingView : public View
{
@@ -36,9 +36,6 @@ private:
Disk *stashCircle_;
Mesh *mixingCircle_;
Mesh *circle_;
// linked sources
std::list< MixingGroup *> groups_;
};
+2 -3
View File
@@ -173,16 +173,15 @@ std::string Selection::xml() const
SourceList selection_clones_;
SessionVisitor sv(&xmlDoc, selectionNode);
for (auto iter = selection_.begin(); iter != selection_.end(); iter++, sv.setRoot(selectionNode) ){
// keep the clones for later
// start with clones
CloneSource *clone = dynamic_cast<CloneSource *>(*iter);
if (clone)
(*iter)->accept(sv);
else
selection_clones_.push_back(*iter);
}
// add the clones at the end
// add others in front
for (auto iter = selection_clones_.begin(); iter != selection_clones_.end(); iter++, sv.setRoot(selectionNode) ){
(*iter)->accept(sv);
}
+92 -14
View File
@@ -7,6 +7,7 @@
#include "FrameGrabber.h"
#include "SessionCreator.h"
#include "SessionSource.h"
#include "MixingGroup.h"
#include "Log.h"
@@ -37,6 +38,9 @@ Session::Session() : failedSource_(nullptr), active_(true), fading_target_(0.f)
Session::~Session()
{
// TODO delete all mixing groups?
// delete all sources
for(auto it = sources_.begin(); it != sources_.end(); ) {
// erase this source from the list
@@ -87,6 +91,18 @@ void Session::update(float dt)
}
}
// // update the mixinggroups
// for (auto g = mixing_groups_.begin(); g != mixing_groups_.end(); ) {
// // update all valid groups
// if ((*g)->size() > 1) {
// (*g)->update(dt);
// g++;
// }
// // delete invalid groups (singletons)
// else
// g = deleteMixingGroup(g);
// }
// apply fading (smooth dicotomic reaching)
float f = render_.fading();
if ( ABS_DIFF(f, fading_target_) > EPSILON) {
@@ -139,6 +155,9 @@ SourceList::iterator Session::deleteSource(Source *s)
if (its != sources_.end()) {
// remove Node from the rendering scene
render_.scene.ws()->detach( s->group(View::RENDERING) );
// inform group
if (s->mixingGroup() != nullptr)
s->mixingGroup()->detach(s);
// erase the source from the update list & get next element
its = sources_.erase(its);
// delete the source : safe now
@@ -241,11 +260,9 @@ SourceList::iterator Session::find(float depth_from, float depth_to)
return std::find_if(sources_.begin(), sources_.end(), Source::hasDepth(depth_from, depth_to));
}
SourceList Session::getCopy() const
SourceList Session::depthSorted() const
{
SourceList list;
list = sources_;
return list;
return depth_sorted(sources_);
}
uint Session::numSource() const
@@ -253,17 +270,9 @@ uint Session::numSource() const
return sources_.size();
}
std::list<uint64_t> Session::getIdList() const
SourceIdList Session::getIdList() const
{
std::list<uint64_t> idlist;
for( auto sit = sources_.begin(); sit != sources_.end(); sit++)
idlist.push_back( (*sit)->id() );
// make sure no duplicate
idlist.unique();
return idlist;
return ids(sources_);
}
bool Session::empty() const
@@ -315,6 +324,73 @@ void Session::move(int current_index, int target_index)
sources_.insert(to, s);
}
MixingGroup *Session::createMixingGroup(SourceList sources)
{
// will return the pointer to created MixingGroup
MixingGroup *g = nullptr;
// verify that all sources given are valid in the sesion
SourceList valid_sources;
for (auto _it = sources.begin(); _it != sources.end(); _it++) {
SourceList::iterator found = std::find(sources_.begin(), sources_.end(), *_it);
if ( found != sources_.end())
valid_sources.push_back(*found);
}
// create mixing group with valid sources (if it is a group of at least 2 sources)
if (valid_sources.size() > 1) {
g = new MixingGroup(valid_sources);
mixing_groups_.push_back(g);
}
return g;
}
bool Session::addMixingGroup (MixingGroup *mg)
{
// verify that all sources given in MixingGroup are valid in the sesion
bool ok = true;
for (auto _it = mg->begin(); _it != mg->end(); _it++) {
SourceList::iterator found = std::find(sources_.begin(), sources_.end(), *_it);
if ( found == sources_.end()) {
ok = false;
break;
}
}
if (ok)
mixing_groups_.push_back(mg);
return ok;
}
void Session::createMixingGroups (std::list<SourceList> groups)
{
// create mixing groups (if any)
for (auto group_it = groups.begin(); group_it != groups.end(); group_it++){
createMixingGroup( *group_it );
}
}
std::vector<MixingGroup *>::iterator Session::eraseMixingGroup (std::vector<MixingGroup *>::iterator g)
{
return mixing_groups_.erase(g);
}
uint Session::numMixingGroup() const
{
return mixing_groups_.size();
}
std::vector<MixingGroup *>::iterator Session::beginMixingGroup()
{
return mixing_groups_.begin();
}
std::vector<MixingGroup *>::iterator Session::endMixingGroup()
{
return mixing_groups_.end();
}
void Session::lock()
{
access_.lock();
@@ -328,9 +404,11 @@ void Session::unlock()
Session *Session::load(const std::string& filename, uint recursion)
{
// create session
SessionCreator creator(recursion);
creator.load(filename);
// return created session
return creator.session();
}
+13 -2
View File
@@ -7,6 +7,7 @@
#include "Source.h"
class FrameGrabber;
class MixingGroup;
class Session
{
@@ -39,10 +40,10 @@ public:
SourceList::iterator find (std::string name);
SourceList::iterator find (Node *node);
SourceList::iterator find (float depth_from, float depth_to);
SourceList getCopy() const;
SourceList depthSorted() const;
SourceList::iterator find (uint64_t id);
std::list<uint64_t> getIdList() const;
SourceIdList getIdList() const;
SourceList::iterator at (int index);
int index (SourceList::iterator it) const;
@@ -75,6 +76,15 @@ public:
void setFilename(const std::string &filename) { filename_ = filename; }
std::string filename() const { return filename_; }
// mixing group
bool addMixingGroup(MixingGroup *mg);
MixingGroup *createMixingGroup (SourceList sources);
std::vector<MixingGroup *>::iterator eraseMixingGroup (std::vector<MixingGroup *>::iterator g);
void createMixingGroups (std::list<SourceList> groups);
uint numMixingGroup() const;
std::vector<MixingGroup *>::iterator beginMixingGroup();
std::vector<MixingGroup *>::iterator endMixingGroup();
// lock and unlock access (e.g. while saving)
void lock();
void unlock();
@@ -84,6 +94,7 @@ protected:
std::string filename_;
Source *failedSource_;
SourceList sources_;
std::vector<MixingGroup *> mixing_groups_;
std::map<View::Mode, Group*> config_;
bool active_;
std::list<FrameGrabber *> grabbers_;
+93 -11
View File
@@ -91,8 +91,36 @@ void SessionCreator::load(const std::string& filename)
// ready to read sources
SessionLoader::load( xmlDoc_.FirstChildElement("Session") );
// create groups
session_->createMixingGroups( getMixingGroups() );
// all good
session_->setFilename(filename);
// for (std::map< uint64_t, Source* >::iterator qwe = sources_id_.begin(); qwe != sources_id_.end(); qwe++){
// Log::Info("%ld - %ld ", qwe->first, qwe->second->id());
// }
// int count = 0;
// std::list< SourceIdList >::iterator git;
// for (git = groups_sources_id_.begin(); git != groups_sources_id_.end(); git++)
// {
// Log::Info("XML Groups %d", count++);
// std::list<uint64_t>::iterator sit;
// for (sit = (*git).begin(); sit != (*git).end(); sit++ ) {
// Log::Info("- %ld", (*sit) );
// }
// }
// std::list< SourceList > ngrou = getMixingGroupsIdList();
// count = 0;
// for (auto git = ngrou.begin(); git != ngrou.end(); git++)
// {
// Log::Info("NEW Groups %d", count++);
// for (auto sit = (*git).begin(); sit != (*git).end(); sit++ ) {
// Log::Info("- %ld", (*sit)->id() );
// }
// }
}
@@ -108,11 +136,48 @@ void SessionCreator::loadConfig(XMLElement *viewsNode)
}
}
SessionLoader::SessionLoader(Session *session, int recursion): Visitor(), session_(session), recursion_(recursion)
SessionLoader::SessionLoader(Session *session, int recursion): Visitor(),
session_(session), xmlCurrent_(nullptr), recursion_(recursion)
{
}
// get the list of new source id (value in sources_id_ map)
SourceIdList SessionLoader::getIdList() const
{
SourceIdList id_current_value;
for (auto it = sources_id_.begin(); it != sources_id_.end(); it++)
id_current_value.push_back( it->second->id() );
return id_current_value;
}
// groups_sources_id_ is parsed in XML and contains list of groups of ids
// Here we return the list of groups of newly created sources
// based on correspondance map sources_id_
// NB: importantly the list is cleared from duplicates
std::list< SourceList > SessionLoader::getMixingGroups() const
{
std::list< SourceList > groups_new_sources_id;
// perform conversion from xml id to new id
for (auto git = groups_sources_id_.begin(); git != groups_sources_id_.end(); git++)
{
SourceList new_sources;
for (auto sit = (*git).begin(); sit != (*git).end(); sit++ ) {
if (sources_id_.count(*sit) > 0)
new_sources.push_back( sources_id_.at(*sit) );
}
new_sources.sort();
groups_new_sources_id.push_back( new_sources );
}
// remove duplicates
groups_new_sources_id.unique();
return groups_new_sources_id;
}
void SessionLoader::load(XMLElement *sessionNode)
{
sources_id_.clear();
@@ -133,9 +198,9 @@ void SessionLoader::load(XMLElement *sessionNode)
Source *load_source = nullptr;
// check if a source with the given id exists in the session
uint64_t id__ = 0;
xmlCurrent_->QueryUnsigned64Attribute("id", &id__);
SourceList::iterator sit = session_->find(id__);
uint64_t id_xml_ = 0;
xmlCurrent_->QueryUnsigned64Attribute("id", &id_xml_);
SourceList::iterator sit = session_->find(id_xml_);
// no source with this id exists
if ( sit == session_->end() ) {
@@ -179,8 +244,10 @@ void SessionLoader::load(XMLElement *sessionNode)
// apply config to source
load_source->accept(*this);
load_source->touch();
// remember
sources_id_.push_back( load_source->id() );
sources_id_[id_xml_] = load_source;
// sources_id_[id_xml_] = load_source->id();
}
// create clones after all sources, to be able to clone a source created above
@@ -194,9 +261,9 @@ void SessionLoader::load(XMLElement *sessionNode)
if ( pType && std::string(pType) == "CloneSource") {
// check if a source with same id exists
uint64_t id__ = 0;
xmlCurrent_->QueryUnsigned64Attribute("id", &id__);
SourceList::iterator sit = session_->find(id__);
uint64_t id_xml_ = 0;
xmlCurrent_->QueryUnsigned64Attribute("id", &id_xml_);
SourceList::iterator sit = session_->find(id_xml_);
// no source clone with this id exists
if ( sit == session_->end() ) {
@@ -210,20 +277,23 @@ void SessionLoader::load(XMLElement *sessionNode)
if (origin != session_->end()) {
// create a new source of type Clone
Source *clone_source = (*origin)->clone();
// add source to session
session_->addSource(clone_source);
// apply config to source
clone_source->accept(*this);
clone_source->touch();
// remember
sources_id_.push_back( clone_source->id() );
sources_id_[id_xml_] = clone_source;
// sources_id_[id_xml_] = clone_source->id();
}
}
}
}
}
// make sure no duplicate
sources_id_.unique();
}
}
@@ -514,6 +584,18 @@ void SessionLoader::visit (Source& s)
s.setImageProcessingEnabled(on);
}
xmlCurrent_ = sourceNode->FirstChildElement("MixingGroup");
if (xmlCurrent_) {
SourceIdList idlist;
XMLElement* sourceNode = xmlCurrent_->FirstChildElement("source");
for ( ; sourceNode ; sourceNode = sourceNode->NextSiblingElement()) {
uint64_t id__ = 0;
sourceNode->QueryUnsigned64Attribute("id", &id__);
idlist.push_back(id__);
}
groups_sources_id_.push_back(idlist);
}
// restore current
xmlCurrent_ = sourceNode;
}
+13 -5
View File
@@ -1,10 +1,11 @@
#ifndef SESSIONCREATOR_H
#define SESSIONCREATOR_H
#include <list>
#include <map>
#include <tinyxml2.h>
#include "Visitor.h"
#include <tinyxml2.h>
#include "SourceList.h"
class Session;
@@ -17,7 +18,8 @@ public:
inline Session *session() const { return session_; }
void load(tinyxml2::XMLElement *sessionNode);
inline std::list<uint64_t> getIdList() const { return sources_id_; }
SourceIdList getIdList() const;
std::list< SourceList > getMixingGroups() const;
Source *createSource(tinyxml2::XMLElement *sourceNode, bool clone_duplicates = true);
@@ -46,10 +48,16 @@ public:
void visit (NetworkSource& s) override;
protected:
tinyxml2::XMLElement *xmlCurrent_;
// result created session
Session *session_;
std::list<uint64_t> sources_id_;
// parsing current xml
tinyxml2::XMLElement *xmlCurrent_;
// level of loading recursion
int recursion_;
// map of correspondance from xml source id (key) to new source pointer (value)
std::map< uint64_t, Source* > sources_id_;
// list of groups (lists of xml source id)
std::list< SourceIdList > groups_sources_id_;
static void XMLToNode(tinyxml2::XMLElement *xml, Node &n);
};
+21 -13
View File
@@ -13,6 +13,7 @@
#include "ImageShader.h"
#include "ImageProcessingShader.h"
#include "MediaPlayer.h"
#include "MixingGroup.h"
#include <iostream>
@@ -274,16 +275,6 @@ void SessionVisitor::visit(LineStrip &n)
points_node->InsertEndChild(p);
}
xmlCurrent_->InsertEndChild(points_node);
// XMLElement *colors_node = xmlDoc_->NewElement("colors");
// std::vector<glm::vec4> colors = n.getColors();
// for(size_t i = 0; i < colors.size(); ++i)
// {
// XMLElement *p = XMLElementFromGLM(xmlDoc_, colors[i]);
// p->SetAttribute("index", (int) i);
// colors_node->InsertEndChild(p);
// }
// xmlCurrent_->InsertEndChild(colors_node);
}
void SessionVisitor::visit(LineSquare &)
@@ -392,6 +383,12 @@ void SessionVisitor::visit (Source& s)
sourceNode->InsertEndChild(xmlCurrent_);
s.processingShader()->accept(*this);
if (s.mixingGroup()) {
xmlCurrent_ = xmlDoc_->NewElement( "MixingGroup" );
sourceNode->InsertEndChild(xmlCurrent_);
s.mixingGroup()->accept(*this);
}
xmlCurrent_ = sourceNode; // parent for next visits (other subtypes of Source)
}
@@ -423,11 +420,11 @@ void SessionVisitor::visit (SessionGroupSource& s)
Session *se = s.session();
XMLElement *rootgroup = xmlDoc_->NewElement("Session");
xmlCurrent_->InsertEndChild(rootgroup);
XMLElement *sessionNode = xmlDoc_->NewElement("Session");
xmlCurrent_->InsertEndChild(sessionNode);
for (auto iter = se->begin(); iter != se->end(); iter++){
setRoot(rootgroup);
setRoot(sessionNode);
(*iter)->accept(*this);
}
@@ -469,3 +466,14 @@ void SessionVisitor::visit (NetworkSource& s)
xmlCurrent_->SetAttribute("type", "NetworkSource");
xmlCurrent_->SetAttribute("connection", s.connection().c_str() );
}
void SessionVisitor::visit (MixingGroup& g)
{
xmlCurrent_->SetAttribute("size", g.size());
for (auto it = g.begin(); it != g.end(); it++) {
XMLElement *sour = xmlDoc_->NewElement("source");
sour->SetAttribute("id", (*it)->id());
xmlCurrent_->InsertEndChild(sour);
}
}
+1
View File
@@ -50,6 +50,7 @@ public:
void visit (PatternSource& s) override;
void visit (DeviceSource& s) override;
void visit (NetworkSource& s) override;
void visit (MixingGroup& s) override;
static tinyxml2::XMLElement *NodeToXML(Node &n, tinyxml2::XMLDocument *doc);
};
-4
View File
@@ -238,10 +238,6 @@ Source::~Source()
(*it)->detach();
clones_.clear();
// inform group
if (mixinggroup_)
mixinggroup_->detach(this);
// delete objects
delete stored_status_;
if (renderbuffer_)
+6
View File
@@ -131,12 +131,17 @@ public:
void setMask (FrameBufferImage *img);
void storeMask (FrameBufferImage *img = nullptr);
// operations on depth
float depth () const;
void setDepth (float d);
// operations on alpha
float alpha () const;
void setAlpha (float a);
// groups for mixing
MixingGroup *mixingGroup() const { return mixinggroup_; }
struct hasNode: public std::unary_function<Source*, bool>
{
bool operator()(const Source* elem) const;
@@ -179,6 +184,7 @@ public:
float _to;
};
// class-dependent icon
virtual glm::ivec2 icon () const { return glm::ivec2(12, 11); }
// get the xml description text of a source
+118
View File
@@ -0,0 +1,118 @@
#include <algorithm>
#include <glm/gtx/vector_angle.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include "Source.h"
#include "SourceList.h"
// utility to sort Sources by depth
bool compare_depth (Source * first, Source * second)
{
return ( first->depth() < second->depth() );
}
SourceList depth_sorted(SourceList list)
{
SourceList sl = list;
sl.sort(compare_depth);
return sl;
}
// utility to sort Sources in MixingView in a clockwise order
// in reference to a center point
struct clockwise_centered {
clockwise_centered(glm::vec2 c) : center(c) { }
bool operator() (Source * first, Source * second) {
glm::vec2 pos_first = glm::vec2(first->group(View::MIXING)->translation_)-center;
float angle_first = glm::orientedAngle( glm::normalize(pos_first), glm::vec2(1.f, 0.f) );
glm::vec2 pos_second = glm::vec2(second->group(View::MIXING)->translation_)-center;
float angle_second = glm::orientedAngle( glm::normalize(pos_second), glm::vec2(1.f, 0.f) );
return (angle_first < angle_second);
}
glm::vec2 center;
};
SourceList mixing_sorted(SourceList list, glm::vec2 center)
{
SourceList sl = list;
sl.sort(clockwise_centered(center));
return sl;
}
SourceIdList ids (SourceList list)
{
SourceIdList idlist;
for( auto sit = list.begin(); sit != list.end(); sit++)
idlist.push_back( (*sit)->id() );
// make sure no duplicate
idlist.unique();
return idlist;
}
SourceListCompare compare (SourceList first, SourceList second)
{
SourceListCompare ret = SOURCELIST_DISTINCT;
if (first.empty() || first.empty())
return ret;
// a new test list: start with the second list and remove all commons with first list
SourceList test = second;
for (auto it = first.begin(); it != first.end(); it++){
test.remove(*it);
}
// all sources of the second list were in the first list
if (test.empty()) {
// same size, therefore they are the same!
if (first.size() == second.size())
ret = SOURCELIST_EQUAL;
// otherwise, first list contains all sources of the second list.
else
ret = SOURCELIST_SECOND_IN_FIRST;
}
// some sources of the second list were in the first
else if ( second.size() != test.size() ){
// if the number of sources removed from second is the number of sources in the first
if (second.size() - test.size() == first.size())
ret = SOURCELIST_FIRST_IN_SECOND;
// else, there is a patrial intersection
else
ret = SOURCELIST_INTERSECT;
}
// else no intersection, lists are distinct (return detault)
return ret;
}
SourceList intersect (SourceList first, SourceList second)
{
// take second list and remove all elements also in first list
// -> builds the list of what remains in second list
SourceList l1 = second;
for (auto it = first.begin(); it != first.end(); it++)
l1.remove(*it);
// take second list and remove all elements in the remainer list
// -> builds the list of what is in second list and was part of the first list
SourceList l2 = second;
for (auto it = l1.begin(); it != l1.end(); it++)
l2.remove(*it);
return l2;
}
SourceList join (SourceList first, SourceList second)
{
SourceList l = second;
for (auto it = first.begin(); it != first.end(); it++)
l.push_back(*it);
return l;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef SOURCELIST_H
#define SOURCELIST_H
#include <list>
#include <glm/glm.hpp>
class Source;
typedef std::list<Source *> SourceList;
SourceList depth_sorted (SourceList list);
SourceList mixing_sorted (SourceList list, glm::vec2 center = glm::vec2(0.f, 0.f));
SourceList intersect (SourceList first, SourceList second);
SourceList join (SourceList first, SourceList second);
typedef enum {
SOURCELIST_DISTINCT = 0,
SOURCELIST_INTERSECT = 1,
SOURCELIST_EQUAL = 2,
SOURCELIST_FIRST_IN_SECOND = 3,
SOURCELIST_SECOND_IN_FIRST = 4
} SourceListCompare;
SourceListCompare compare (SourceList first, SourceList second);
typedef std::list<uint64_t> SourceIdList;
SourceIdList ids (SourceList list);
#endif // SOURCELIST_H
-13
View File
@@ -275,16 +275,3 @@ void View::updateSelectionOverlay()
overlay_selection_->scale_ = glm::vec3(0.f, 0.f, 1.f);
}
bool compare_depth (Source * first, Source * second)
{
return ( first->depth() < second->depth() );
}
SourceList depthSorted(SourceList list)
{
SourceList dsl = list;
dsl.sort(compare_depth);
return dsl;
}
+1 -2
View File
@@ -5,6 +5,7 @@
#include "Scene.h"
#include "FrameBuffer.h"
#include "SourceList.h"
class Session;
class SessionFileSource;
@@ -16,8 +17,6 @@ class Disk;
class Handles;
class Source;
typedef std::list<Source *> SourceList;
SourceList depthSorted(SourceList);
class View
{
+2
View File
@@ -37,6 +37,7 @@ class SessionGroupSource;
class RenderSource;
class CloneSource;
class NetworkSource;
class MixingGroup;
// Declares the interface for the visitors
class Visitor {
@@ -69,6 +70,7 @@ public:
virtual void visit (ImageProcessingShader&) {}
// utility
virtual void visit (MixingGroup&) {}
virtual void visit (Source&) {}
virtual void visit (MediaSource&) {}
virtual void visit (NetworkSource&) {}