Working on multiple sources selection: created bounding box decoration,

fixed Switch node in Scene, removed Animation node from scene, created
display mode for Source.
This commit is contained in:
brunoherbelin
2020-06-13 18:22:32 +02:00
parent 69b249e7e0
commit aa211fe39b
33 changed files with 457 additions and 256 deletions

65
BoundingBoxVisitor.cpp Normal file
View File

@@ -0,0 +1,65 @@
#include <glm/gtc/matrix_transform.hpp>
#include "BoundingBoxVisitor.h"
#include "Log.h"
#include "Primitives.h"
#include "Decorations.h"
BoundingBoxVisitor::BoundingBoxVisitor(): Visitor()
{
modelview_ = glm::identity<glm::mat4>();
}
void BoundingBoxVisitor::setModelview(glm::mat4 modelview)
{
modelview_ = modelview;
}
GlmToolkit::AxisAlignedBoundingBox BoundingBoxVisitor::bbox()
{
return bbox_;
}
void BoundingBoxVisitor::visit(Node &n)
{
// use the transform modified during update
modelview_ *= n.transform_;
}
void BoundingBoxVisitor::visit(Group &n)
{
if (!n.visible_)
return;
glm::mat4 mv = modelview_;
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
if ( (*node)->visible_ )
(*node)->accept(*this);
modelview_ = mv;
}
}
void BoundingBoxVisitor::visit(Switch &n)
{
if (!n.visible_ || n.numChildren() < 1)
return;
glm::mat4 mv = modelview_;
n.activeChild()->accept(*this);
modelview_ = mv;
}
void BoundingBoxVisitor::visit(Primitive &n)
{
if (!n.visible_)
return;
bbox_.extend(n.bbox().transformed(modelview_));
// Log::Info("visitor box (%f, %f)-(%f, %f)", bbox_.min().x, bbox_.min().y, bbox_.max().x, bbox_.max().y);
}
void BoundingBoxVisitor::visit(Scene &n)
{
n.ws()->accept(*this);
}

28
BoundingBoxVisitor.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef BOUNDINGBOXVISITOR_H
#define BOUNDINGBOXVISITOR_H
#include "GlmToolkit.h"
#include "Visitor.h"
class BoundingBoxVisitor: public Visitor
{
glm::mat4 modelview_;
GlmToolkit::AxisAlignedBoundingBox bbox_;
public:
BoundingBoxVisitor();
void setModelview(glm::mat4 modelview);
GlmToolkit::AxisAlignedBoundingBox bbox();
// Elements of Scene
void visit(Scene& n) override;
void visit(Node& n) override;
void visit(Group& n) override;
void visit(Switch& n) override;
void visit(Primitive& n) override;
};
#endif // BOUNDINGBOXVISITOR_H

View File

@@ -225,6 +225,7 @@ set(VMIX_SRCS
RenderingManager.cpp
UserInterfaceManager.cpp
PickingVisitor.cpp
BoundingBoxVisitor.cpp
DrawVisitor.cpp
SearchVisitor.cpp
ImGuiToolkit.cpp

View File

@@ -5,6 +5,7 @@
#include "Decorations.h"
#include "Visitor.h"
#include "BoundingBoxVisitor.h"
#include "ImageShader.h"
#include "GlmToolkit.h"
#include "Log.h"
@@ -15,11 +16,11 @@ Frame::Frame(Type type) : Node(), type_(type), side_(nullptr), top_(nullptr), sh
color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
switch (type) {
case SHARP_LARGE:
square_ = new LineSquare(color, 3 );
square_ = new LineSquare( 3 );
shadow_ = new Mesh("mesh/glow.ply", "images/glow.dds");
break;
case SHARP_THIN:
square_ = new LineSquare(color, 3 );
square_ = new LineSquare( 3 );
break;
case ROUND_LARGE:
side_ = new Mesh("mesh/border_large_round.ply");
@@ -245,10 +246,10 @@ void Handles::accept(Visitor& v)
}
Icon::Icon(Type style) : Node()
Icon::Icon(Type style, glm::vec3 pos) : Node()
{
color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
translation_ = glm::vec3(0.8f, 0.8f, 0.f);
translation_ = pos;
switch (style) {
case IMAGE:
@@ -272,7 +273,6 @@ Icon::Icon(Type style) : Node()
default:
case GENERIC:
icon_ = new Mesh("mesh/point.ply");
translation_ = glm::vec3(0.f, 0.f, 0.f);
break;
}
@@ -312,3 +312,56 @@ void Icon::accept(Visitor& v)
Node::accept(v);
v.visit(*this);
}
Selection::Selection()
{
// color = glm::vec4( 1.f, 1.f, 1.f, 1.f);
color = glm::vec4( 1.f, 0.f, 0.f, 1.f);
square_ = new LineSquare( 3 );
}
void Selection::draw (glm::mat4 modelview, glm::mat4 projection)
{
if ( !initialized() ) {
square_->init();
init();
}
if (visible_) {
// use a visitor bounding box to calculate extend of all selected nodes
BoundingBoxVisitor vbox;
// visit every child of the selection
for (NodeSet::iterator node = children_.begin();
node != children_.end(); node++) {
// reset the transform before
vbox.setModelview(glm::identity<glm::mat4>());
(*node)->accept(vbox);
}
// get the bounding box
bbox_ = vbox.bbox();
// Log::Info(" -------- visitor box (%f, %f)-(%f, %f)", bbox_.min().x, bbox_.min().y, bbox_.max().x, bbox_.max().y);
// set color
square_->shader()->color = color;
// compute transformation from bounding box
// glm::mat4 ctm = modelview * GlmToolkit::transform(glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f));
glm::mat4 ctm = modelview * GlmToolkit::transform(bbox_.center(), glm::vec3(0.f), bbox_.scale());
// draw bbox
// square_->draw( modelview, projection);
square_->draw( ctm, projection);
// DEBUG
// visible_=false;
}
}

View File

@@ -57,7 +57,7 @@ class Icon : public Node
{
public:
typedef enum { GENERIC = 0, IMAGE, VIDEO, SESSION, CLONE, RENDER, EMPTY } Type;
Icon(Type type);
Icon(Type type = GENERIC, glm::vec3 pos = glm::vec3(0.f));
~Icon();
void draw (glm::mat4 modelview, glm::mat4 projection) override;
@@ -71,6 +71,22 @@ protected:
Type type_;
};
class Selection : public Group
{
public:
Selection();
void draw (glm::mat4 modelview, glm::mat4 projection) override;
glm::vec4 color;
protected:
LineSquare *square_;
GlmToolkit::AxisAlignedBoundingBox bbox_;
};
// TODO Shadow mesh with unique vao

View File

@@ -50,15 +50,10 @@ void DrawVisitor::visit(Scene &n)
void DrawVisitor::visit(Switch &n)
{
glm::mat4 mv = modelview_;
(*n.activeChild())->accept(*this);
n.activeChild()->accept(*this);
modelview_ = mv;
}
void DrawVisitor::visit(Animation &n)
{
}
void DrawVisitor::visit(Primitive &n)
{

View File

@@ -18,7 +18,6 @@ public:
void visit(Node& n) override;
void visit(Group& n) override;
void visit(Switch& n) override;
void visit(Animation& n) override;
void visit(Primitive& n) override;
void visit(Surface& n) override;
void visit(ImageSurface& n) override;

View File

@@ -77,11 +77,6 @@ void GarbageVisitor::visit(Switch &n)
}
void GarbageVisitor::visit(Animation &n)
{
}
void GarbageVisitor::visit(Primitive &n)
{

View File

@@ -22,7 +22,6 @@ public:
void visit(Node& n) override;
void visit(Group& n) override;
void visit(Switch& n) override;
void visit(Animation& n) override;
void visit(Primitive& n) override;
void visit(Surface& n) override;
void visit(ImageSurface& n) override;

View File

@@ -71,6 +71,19 @@ glm::vec3 GlmToolkit::AxisAlignedBoundingBox::center() const
}
}
glm::vec3 GlmToolkit::AxisAlignedBoundingBox::scale() const
{
if (!isNull())
{
glm::vec3 d = mMax - mMin;
return d * 0.5f;
}
else
{
return glm::vec3(0.f);
}
}
bool GlmToolkit::AxisAlignedBoundingBox::intersect(const AxisAlignedBoundingBox& bb, bool ignore_z) const
{
if (isNull() || bb.isNull())
@@ -134,3 +147,16 @@ GlmToolkit::AxisAlignedBoundingBox GlmToolkit::AxisAlignedBoundingBox::scaled(gl
return bb;
}
GlmToolkit::AxisAlignedBoundingBox GlmToolkit::AxisAlignedBoundingBox::transformed(glm::mat4 m)
{
GlmToolkit::AxisAlignedBoundingBox bb;
glm::vec4 vec;
vec = m * glm::vec4(mMin, 1.f);
bb.mMin = glm::vec3(vec);
vec = m * glm::vec4(mMax, 1.f);
bb.mMax = glm::vec3(vec);
return bb;
}

View File

@@ -29,6 +29,7 @@ public:
inline glm::vec3 min() const { return mMin; }
inline glm::vec3 max() const { return mMax; }
glm::vec3 center() const;
glm::vec3 scale() const;
bool intersect(const AxisAlignedBoundingBox& bb, bool ignore_z = true) const;
bool contains(const AxisAlignedBoundingBox& bb, bool ignore_z = true) const;
bool contains(glm::vec3 point, bool ignore_z = true) const;
@@ -40,6 +41,7 @@ public:
AxisAlignedBoundingBox translated(glm::vec3 t);
AxisAlignedBoundingBox scaled(glm::vec3 s);
AxisAlignedBoundingBox transformed(glm::mat4 m);
};
}

View File

@@ -94,14 +94,8 @@ void ImGuiVisitor::visit(Group &n)
void ImGuiVisitor::visit(Switch &n)
{
// TODO : display selection of active child
(*n.activeChild())->accept(*this);
}
void ImGuiVisitor::visit(Animation &n)
{
// TODO : display group and animation parameters
if (n.numChildren()>0)
n.activeChild()->accept(*this);
}
void ImGuiVisitor::visit(Scene &n)

View File

@@ -13,7 +13,6 @@ public:
void visit(Node& n) override;
void visit(Group& n) override;
void visit(Switch& n) override;
void visit(Animation& n) override;
void visit(Primitive& n) override;
void visit(MediaSurface& n) override;
void visit(FrameBufferSurface& n) override;

View File

@@ -173,7 +173,7 @@ void Log::Notify(const char* fmt, ...)
notifications_timeout = 0.f;
// always log
Log::Info("%s\n", buf.c_str());
Log::Info("%s", buf.c_str());
}

View File

@@ -82,16 +82,17 @@ void MediaSource::init()
// icon in mixing view
if (mediaplayer_->duration() == GST_CLOCK_TIME_NONE) {
overlays_[View::MIXING]->attach( new Icon(Icon::IMAGE) );
overlays_[View::LAYER]->attach( new Icon(Icon::IMAGE) );
overlays_[View::MIXING]->attach( new Icon(Icon::IMAGE, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Icon(Icon::IMAGE, glm::vec3(0.8f, 0.8f, 0.01f)) );
}
else {
overlays_[View::MIXING]->attach( new Icon(Icon::VIDEO) );
overlays_[View::LAYER]->attach( new Icon(Icon::VIDEO) );
overlays_[View::MIXING]->attach( new Icon(Icon::VIDEO, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Icon(Icon::VIDEO, glm::vec3(0.8f, 0.8f, 0.01f)) );
}
// done init
initialized_ = true;
Log::Info("Source Media linked to Media %s.", mediaplayer()->uri().c_str());
}
}

View File

@@ -195,6 +195,7 @@ void Mixer::update()
// update session and associated sources
session_->update(dt);
// delete failed sources (one by one)
if (session()->failedSource() != nullptr)
deleteSource(session()->failedSource());
@@ -203,7 +204,7 @@ void Mixer::update()
geometry_.update(dt);
layer_.update(dt);
// optimize the reordering in depth for views
// optimize the reordering in depth for views;
// deep updates shall be performed only 1 frame
View::need_deep_update_ = false;
}
@@ -382,7 +383,7 @@ void Mixer::setCurrentSource(SourceList::iterator it)
if ( it != session_->end() ) {
current_source_ = it;
current_source_index_ = session_->index(it);
(*current_source_)->setOverlayVisible(true);
(*current_source_)->setMode(Source::CURRENT);
}
}
@@ -423,7 +424,7 @@ void Mixer::unsetCurrentSource()
{
// discard overlay for previously current source
if ( current_source_ != session_->end() )
(*current_source_)->setOverlayVisible(false);
(*current_source_)->setMode(Source::NORMAL);
// deselect current source
current_source_ = session_->end();
@@ -606,6 +607,8 @@ void Mixer::clear()
// swap current with empty
sessionSwapRequested_ = true;
Log::Info("New session ready.");
}
void Mixer::set(Session *s)

View File

@@ -29,6 +29,8 @@ void PickingVisitor::visit(Node &n)
void PickingVisitor::visit(Group &n)
{
if (!n.visible_)
return;
glm::mat4 mv = modelview_;
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
if ( (*node)->visible_ )
@@ -39,8 +41,10 @@ void PickingVisitor::visit(Group &n)
void PickingVisitor::visit(Switch &n)
{
if (!n.visible_ || n.numChildren()<1)
return;
glm::mat4 mv = modelview_;
(*n.activeChild())->accept(*this);
n.activeChild()->accept(*this);
modelview_ = mv;
}

View File

@@ -15,7 +15,6 @@ class PickingVisitor: public Visitor
public:
PickingVisitor(glm::vec2 coordinates);
std::vector< std::pair<Node *, glm::vec2> > picked() { return nodes_; }

View File

@@ -233,12 +233,12 @@ void Points::accept(Visitor& v)
v.visit(*this);
}
LineStrip::LineStrip(std::vector<glm::vec3> points, glm::vec4 color, uint linewidth) : Primitive(new Shader), linewidth_(linewidth)
LineStrip::LineStrip(std::vector<glm::vec3> points, std::vector<glm::vec4> colors, uint linewidth) : Primitive(new Shader), linewidth_(linewidth)
{
for(size_t i = 0; i < points.size(); ++i)
{
points_.push_back( points[i] );
colors_.push_back( color );
colors_.push_back( colors[i] );
indices_.push_back ( i );
}
@@ -255,13 +255,13 @@ void LineStrip::draw(glm::mat4 modelview, glm::mat4 projection)
glm::mat4 mv = modelview;
glm::mat4 scale = glm::scale(glm::identity<glm::mat4>(), glm::vec3(1.001f, 1.001f, 1.f));
// TODO FIXME drawing multiple times is not correct to draw lines of different width
// TODO Draw LineStrip using polygons
for (uint i = 0 ; i < linewidth_ ; ++i ) {
Primitive::draw(mv, projection);
mv *= scale;
}
// glLineWidth(1);
}
@@ -279,7 +279,13 @@ static const std::vector<glm::vec3> square_points {
glm::vec3( -1.f, -1.f, 0.f )
};
LineSquare::LineSquare(glm::vec4 color, uint linewidth) : LineStrip(square_points, color, linewidth)
static const std::vector<glm::vec4> square_colors {
glm::vec4( 1.f, 1.f, 1.f, 1.f ), glm::vec4( 1.f, 1.f, 1.f, 1.f ),
glm::vec4( 1.f, 1.f, 1.f, 1.f ), glm::vec4( 1.f, 1.f, 1.f, 1.f ),
glm::vec4( 1.f, 1.f, 1.f, 1.f )
};
LineSquare::LineSquare(uint linewidth) : LineStrip(square_points, square_colors, linewidth)
{
}
@@ -324,22 +330,23 @@ LineSquare::~LineSquare()
}
LineCircle::LineCircle(glm::vec4 color, uint linewidth) : LineStrip(std::vector<glm::vec3>(), color, linewidth)
LineCircle::LineCircle(uint linewidth) : LineStrip(std::vector<glm::vec3>(), std::vector<glm::vec4>(), linewidth)
{
static int N = 72;
static float a = glm::two_pi<float>() / static_cast<float>(N);
static glm::vec4 circle_color_points = glm::vec4(1.f, 1.f, 1.f, 1.f);
// loop to build a circle
glm::vec3 P(1.f, 0.f, 0.f);
for (int i = 0; i < N ; i++ ){
points_.push_back( glm::vec3(P) );
colors_.push_back( color );
colors_.push_back( circle_color_points );
indices_.push_back ( i );
P = glm::rotateZ(P, a);
}
// close loop
points_.push_back( glm::vec3(1.f, 0.f, 0.f) );
colors_.push_back( color );
colors_.push_back( circle_color_points );
indices_.push_back ( N );
}

View File

@@ -133,13 +133,13 @@ class LineStrip : public Primitive {
uint linewidth_;
public:
LineStrip(std::vector<glm::vec3> points, glm::vec4 color, uint linewidth = 1);
LineStrip(std::vector<glm::vec3> points, std::vector<glm::vec4> colors, uint linewidth = 1);
virtual void draw(glm::mat4 modelview, glm::mat4 projection) override;
virtual void accept(Visitor& v) override;
std::vector<glm::vec3> getPoints() { return points_; }
glm::vec4 getColor() { return colors_[0]; }
std::vector<glm::vec4> getColors() { return colors_; }
inline void setLineWidth(uint v) { linewidth_ = v; }
inline uint getLineWidth() const { return linewidth_; }
@@ -152,7 +152,7 @@ public:
class LineSquare : public LineStrip {
public:
LineSquare(glm::vec4 color, uint linewidth = 1);
LineSquare(uint linewidth = 1);
void init() override;
void accept(Visitor& v) override;
@@ -167,7 +167,7 @@ public:
class LineCircle : public LineStrip {
public:
LineCircle(glm::vec4 color, uint linewidth = 1);
LineCircle(uint linewidth = 1);
void init() override;
void accept(Visitor& v) override;

120
Scene.cpp
View File

@@ -49,6 +49,12 @@ void Node::copyTransform(Node *other)
void Node::update( float )
{
std::list<Node::NodeUpdateCallback>::iterator iter;
for (iter=update_callbacks_.begin(); iter != update_callbacks_.end(); iter++)
{
(*iter)(this);
}
// update transform matrix from attributes
transform_ = GlmToolkit::transform(translation_, rotation_, scale_);
}
@@ -296,8 +302,8 @@ void Switch::update( float dt )
Node::update(dt);
// update active child node
if (active_ != children_.end())
(*active_)->update( dt );
if (!children_.empty())
(children_[active_])->update( dt );
}
void Switch::draw(glm::mat4 modelview, glm::mat4 projection)
@@ -307,8 +313,8 @@ void Switch::draw(glm::mat4 modelview, glm::mat4 projection)
if ( visible_ ) {
// draw current child
if (active_ != children_.end())
(*active_)->draw( modelview * transform_, projection);
if (!children_.empty())
(children_[active_])->draw( modelview * transform_, projection);
}
}
@@ -318,95 +324,39 @@ void Switch::accept(Visitor& v)
v.visit(*this);
}
void Switch::attach(Node *child)
void Switch::setActive (uint index)
{
Group::attach(child);
setActiveChild(child);
active_ = CLAMP(index, 0, children_.size() - 1);
}
Node *Switch::child(uint index) const
{
if (!children_.empty()) {
uint i = CLAMP(index, 0, children_.size() - 1);
return children_.at(i);
}
return nullptr;
}
uint Switch::attach(Node *child)
{
children_.push_back(child);
active_ = children_.size() - 1;
return active_;
}
void Switch::detatch(Node *child)
{
Group::detatch(child);
active_ = children_.begin();
}
void Switch::unsetActiveChild ()
{
active_ = children_.end();
}
void Switch::setActiveChild(Node *child)
{
setActiveChild( std::find_if(children_.begin(), children_.end(), hasId(child->id())) );
}
void Switch::setActiveChild(NodeSet::iterator n)
{
if ( n != children_.end())
active_ = n;
else
active_ = children_.begin();
}
NodeSet::iterator Switch::activeChild() const
{
return active_;
}
void Switch::setIndexActiveChild(int index)
{
int i = 0;
for (NodeSet::iterator node = children_.begin();
node != children_.end(); node++, i++) {
if ( i == index ) {
active_ = node;
break;
}
// find the node with this id, and erase it out of the list of children
// NB: do NOT delete with remove : this takes all nodes with same depth (i.e. equal depth in set)
std::vector<Node *>::iterator it = std::find_if(children_.begin(), children_.end(), hasId(child->id()));
if ( it != children_.end()) {
// detatch child from group parent
children_.erase(it);
child->refcount_--;
}
}
int Switch::getIndexActiveChild() const
{
int index = 0;
for (NodeSet::iterator node = children_.begin();
node != children_.end(); node++, index++) {
if (node == active_)
break;
}
return index;
}
void Animation::init()
{
Group::init();
animation_ = glm::identity<glm::mat4>();
// animation_ = glm::translate(glm::identity<glm::mat4>(), glm::vec3(2.f, 0.f, 0.f));
}
void Animation::update( float dt )
{
Group::update(dt);
// incremental rotation
animation_ = glm::rotate(animation_, speed_ * dt, axis_);
// calculate translation of a point at distance radius_ after rotation by animation_
static glm::vec3 any = glm::linearRand( glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.f, 1.f, 1.f));
glm::vec3 pos = glm::normalize( glm::cross(any, axis_) ) * radius_;
glm::vec4 delta = glm::vec4(pos, 0.f) * animation_;
// apply this translation to the Group transform
transform_ *= glm::translate(glm::identity<glm::mat4>(), glm::vec3(delta.x, delta.y, 0.f));
}
void Animation::accept(Visitor& v)
{
Group::accept(v);
v.visit(*this);
}
Scene::Scene()
{

61
Scene.h
View File

@@ -10,6 +10,7 @@
#include <set>
#include <list>
#include <vector>
#include <map>
#include "GlmToolkit.h"
@@ -71,6 +72,10 @@ public:
glm::mat4 transform_;
glm::vec3 scale_, rotation_, translation_;
// animation update callbacks
typedef void (* NodeUpdateCallback)(Node *);
// list of functions to call at each update
std::list<NodeUpdateCallback> update_callbacks_;
};
@@ -164,10 +169,10 @@ public:
virtual void accept (Visitor& v) override;
virtual void draw (glm::mat4 modelview, glm::mat4 projection) override;
virtual void clear();
virtual void attach (Node *child);
virtual void detatch (Node *child);
virtual void sort();
void clear();
void attach (Node *child);
void detatch (Node *child);
void sort();
NodeSet::iterator begin();
NodeSet::iterator end();
@@ -187,53 +192,27 @@ protected:
* draw() will draw only the active child
*
*/
class Switch : public Group {
class Switch : public Node {
public:
Switch() : Group(), active_(end()) {}
Switch() : Node(), active_(0) {}
virtual void update (float dt) override;
virtual void accept (Visitor& v) override;
virtual void draw (glm::mat4 modelview, glm::mat4 projection) override;
void attach (Node *child) override;
void detatch (Node *child) override;
uint attach (Node *child);
void detatch (Node *child);
void setActive (uint index);
void unsetActiveChild ();
void setActiveChild (Node *child);
void setActiveChild (NodeSet::iterator n);
NodeSet::iterator activeChild () const;
void setIndexActiveChild (int index);
int getIndexActiveChild () const;
uint active () const { return active_; }
Node *activeChild () const { return child(active_); }
uint numChildren () const { return children_.size(); }
Node *child (uint index) const;
protected:
NodeSet::iterator active_;
};
/**
* @brief The Animation class is a Group with an update() function
*
* The update() computes a transformation of the Group to apply a movement
* which is applied to all children.
*
*/
class Animation : public Group {
public:
Animation() : Group(), axis_(glm::vec3(0.f, 0.f, 1.f)), speed_(0.f), radius_(1.f) { }
virtual void init () override;
virtual void update (float dt) override;
virtual void accept (Visitor& v) override;
// circular path
glm::vec3 axis_;
float speed_;
float radius_;
protected:
glm::mat4 animation_;
uint active_;
std::vector<Node *> children_;
};

View File

@@ -26,7 +26,8 @@ void SearchVisitor::visit(Group &n)
void SearchVisitor::visit(Switch &n)
{
(*n.activeChild())->accept(*this);
if (n.numChildren()>0)
n.activeChild()->accept(*this);
}

View File

@@ -27,7 +27,6 @@ public:
void visit(Scene& n) override {}
void visit(Group& n) override {}
void visit(Switch& n) override {}
void visit(Animation& n) override {}
void visit(Primitive& n) override {}
void visit(Surface& n) override {}
void visit(ImageSurface& n) override {}

View File

@@ -121,8 +121,8 @@ void SessionSource::init()
attach(renderbuffer);
// icon in mixing view
overlays_[View::MIXING]->attach( new Icon(Icon::SESSION) );
overlays_[View::LAYER]->attach( new Icon(Icon::SESSION) );
overlays_[View::MIXING]->attach( new Icon(Icon::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Icon(Icon::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) );
// done init
initialized_ = true;
@@ -201,8 +201,8 @@ void RenderSource::init()
attach(renderbuffer);
// icon in mixing view
overlays_[View::MIXING]->attach( new Icon(Icon::RENDER) );
overlays_[View::LAYER]->attach( new Icon(Icon::RENDER) );
overlays_[View::MIXING]->attach( new Icon(Icon::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Icon(Icon::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)) );
// done init
initialized_ = true;

View File

@@ -78,32 +78,19 @@ void SessionVisitor::visit(Switch &n)
{
// Node of a different type
xmlCurrent_->SetAttribute("type", "Switch");
xmlCurrent_->SetAttribute("active", n.getIndexActiveChild());
xmlCurrent_->SetAttribute("active", n.active());
if (recursive_) {
// loop over members of the group
XMLElement *group = xmlCurrent_;
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
(*node)->accept(*this);
for(uint i = 0; i < n.numChildren(); i++) {
n.child(i)->accept(*this);
// revert to group as current
xmlCurrent_ = group;
}
}
}
void SessionVisitor::visit(Animation &n)
{
// Group of a different type
xmlCurrent_->SetAttribute("type", "Animation");
XMLElement *anim = xmlDoc_->NewElement("Movement");
anim->SetAttribute("speed", n.speed_);
anim->SetAttribute("radius", n.radius_);
XMLElement *axis = XMLElementFromGLM(xmlDoc_, n.axis_);
anim->InsertEndChild(axis);
xmlCurrent_->InsertEndChild(anim);
}
void SessionVisitor::visit(Primitive &n)
{
// Node of a different type
@@ -229,17 +216,25 @@ void SessionVisitor::visit(LineStrip &n)
// Node of a different type
xmlCurrent_->SetAttribute("type", "LineStrip");
XMLElement *color = xmlDoc_->NewElement("color");
color->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.getColor()) );
xmlCurrent_->InsertEndChild(color);
XMLElement *points_node = xmlDoc_->NewElement("points");
std::vector<glm::vec3> points = n.getPoints();
for(size_t i = 0; i < points.size(); ++i)
{
XMLElement *p = XMLElementFromGLM(xmlDoc_, points[i]);
p->SetAttribute("index", (int) i);
xmlCurrent_->InsertEndChild(p);
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 &)
@@ -254,9 +249,9 @@ void SessionVisitor::visit(LineCircle &n)
// Node of a different type
xmlCurrent_->SetAttribute("type", "LineCircle");
XMLElement *color = xmlDoc_->NewElement("color");
color->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.getColor()) );
xmlCurrent_->InsertEndChild(color);
// XMLElement *color = xmlDoc_->NewElement("color");
// color->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.getColor()) );
// xmlCurrent_->InsertEndChild(color);
}
void SessionVisitor::visit(Mesh &n)

View File

@@ -22,7 +22,6 @@ public:
void visit(Node& n) override;
void visit(Group& n) override;
void visit(Switch& n) override;
void visit(Animation& n) override;
void visit(Primitive& n) override;
void visit(Surface& n) override;
void visit(ImageSurface& n) override;

View File

@@ -20,6 +20,7 @@ Source::Source() : initialized_(false), need_update_(true)
{
sprintf(initials_, "__");
name_ = "Source";
mode_ = Source::HIDDEN;
// create groups and overlays for each view
@@ -30,39 +31,45 @@ Source::Source() : initialized_(false), need_update_(true)
// default mixing nodes
groups_[View::MIXING] = new Group;
groups_[View::MIXING]->visible_ = false;
groups_[View::MIXING]->scale_ = glm::vec3(0.15f, 0.15f, 1.f);
groups_[View::MIXING]->translation_ = glm::vec3(-1.f, 1.f, 0.f);
frames_[View::MIXING] = new Switch;
Frame *frame = new Frame(Frame::ROUND_THIN);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.7f);
groups_[View::MIXING]->attach(frame);
groups_[View::MIXING]->scale_ = glm::vec3(0.15f, 0.15f, 1.f);
groups_[View::MIXING]->translation_ = glm::vec3(-1.f, 1.f, 0.f);
frames_[View::MIXING]->attach(frame);
frame = new Frame(Frame::ROUND_LARGE);
frame->translation_.z = 0.01;
frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
frames_[View::MIXING]->attach(frame);
groups_[View::MIXING]->attach(frames_[View::MIXING]);
overlays_[View::MIXING] = new Group;
overlays_[View::MIXING]->translation_.z = 0.1;
overlays_[View::MIXING]->visible_ = false;
frame = new Frame(Frame::ROUND_LARGE);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
overlays_[View::MIXING]->attach(frame);
Icon *center = new Icon(Icon::GENERIC);
center->translation_.z = 0.1;
Icon *center = new Icon(Icon::GENERIC, glm::vec3(0.f, 0.f, 0.1f));
overlays_[View::MIXING]->attach(center);
groups_[View::MIXING]->attach(overlays_[View::MIXING]);
// default geometry nodes
groups_[View::GEOMETRY] = new Group;
groups_[View::GEOMETRY]->visible_ = false;
frames_[View::GEOMETRY] = new Switch;
frame = new Frame(Frame::SHARP_THIN);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.7f);
groups_[View::GEOMETRY]->attach(frame);
frames_[View::GEOMETRY]->attach(frame);
frame = new Frame(Frame::SHARP_LARGE);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
frames_[View::GEOMETRY]->attach(frame);
groups_[View::GEOMETRY]->attach(frames_[View::GEOMETRY]);
overlays_[View::GEOMETRY] = new Group;
overlays_[View::GEOMETRY]->translation_.z = 0.15;
overlays_[View::GEOMETRY]->visible_ = false;
frame = new Frame(Frame::SHARP_LARGE);
frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
overlays_[View::GEOMETRY]->attach(frame);
resize_handle_ = new Handles(Handles::RESIZE);
resize_handle_->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
resize_handle_->translation_.z = 0.1;
@@ -81,21 +88,24 @@ Source::Source() : initialized_(false), need_update_(true)
overlays_[View::GEOMETRY]->attach(rotate_handle_);
groups_[View::GEOMETRY]->attach(overlays_[View::GEOMETRY]);
// default mixing nodes
// default layer nodes
groups_[View::LAYER] = new Group;
groups_[View::LAYER]->visible_ = false;
frames_[View::LAYER] = new Switch;
frame = new Frame(Frame::ROUND_SHADOW);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.8f);
groups_[View::LAYER]->attach(frame);
frames_[View::LAYER]->attach(frame);
frame = new Frame(Frame::ROUND_LARGE);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
frames_[View::LAYER]->attach(frame);
groups_[View::LAYER]->attach(frames_[View::LAYER]);
overlays_[View::LAYER] = new Group;
overlays_[View::LAYER]->translation_.z = 0.15;
overlays_[View::LAYER]->visible_ = false;
frame = new Frame(Frame::ROUND_LARGE);
frame->translation_.z = 0.1;
frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f);
overlays_[View::LAYER]->attach(frame);
groups_[View::LAYER]->attach(overlays_[View::LAYER]);
// will be associated to nodes later
@@ -103,6 +113,7 @@ Source::Source() : initialized_(false), need_update_(true)
rendershader_ = new ImageProcessingShader;
renderbuffer_ = nullptr;
rendersurface_ = nullptr;
}
Source::~Source()
@@ -138,19 +149,33 @@ void Source::accept(Visitor& v)
v.visit(*this);
}
void Source::setOverlayVisible(bool on)
Source::Mode Source::mode() const
{
for (auto o = overlays_.begin(); o != overlays_.end(); o++)
(*o).second->visible_ = on;
return mode_;
}
void Source::setVisible(bool on)
void Source::setMode(Source::Mode m)
{
// make visible
groups_[View::RENDERING]->visible_ = on;
groups_[View::MIXING]->visible_ = on;
groups_[View::GEOMETRY]->visible_ = on;
groups_[View::LAYER]->visible_ = on;
mode_ = m;
bool visible = mode_ != Source::HIDDEN;
for (auto g = groups_.begin(); g != groups_.end(); g++)
(*g).second->visible_ = visible;
uint index_frame = mode_ == Source::NORMAL ? 0 : 1;
for (auto f = frames_.begin(); f != frames_.end(); f++)
(*f).second->setActive(index_frame);
bool current = mode_ == Source::CURRENT;
for (auto o = overlays_.begin(); o != overlays_.end(); o++)
(*o).second->visible_ = current;
}
void fix_ar(Node *n)
{
n->scale_.y = n->scale_.x;
}
void Source::attach(FrameBuffer *renderbuffer)
@@ -186,7 +211,11 @@ void Source::attach(FrameBuffer *renderbuffer)
(*node)->scale_.x = renderbuffer_->aspectRatio();
}
setVisible(true);
// test update callback
// groups_[View::GEOMETRY]->update_callbacks_.push_front(fix_ar);
setMode(Source::NORMAL);
}
void Source::update(float dt)
@@ -307,8 +336,8 @@ void CloneSource::init()
attach(renderbuffer);
// icon in mixing view
overlays_[View::MIXING]->attach( new Icon(Icon::CLONE) );
overlays_[View::LAYER]->attach( new Icon(Icon::CLONE) );
overlays_[View::MIXING]->attach( new Icon(Icon::CLONE, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Icon(Icon::CLONE, glm::vec3(0.8f, 0.8f, 0.01f)) );
// done init
initialized_ = true;

View File

@@ -41,11 +41,15 @@ public:
// cloning mechanism
virtual CloneSource *clone();
// make visible or hidden
void setVisible(bool on);
// an overlay can be displayed on top of the source
void setOverlayVisible(bool on);
// Display mode
typedef enum {
HIDDEN = 0,
NORMAL = 1,
ACTIVE = 2,
CURRENT = 3
} Mode;
Mode mode() const;
void setMode(Mode m);
// get handle on the nodes used to manipulate the source in a view
inline Group *group(View::Mode m) const { return groups_.at(m); }
@@ -108,8 +112,12 @@ protected:
// blendingshader provides mixing controls
ImageShader *blendingshader_;
// overlay to be displayed on top of source
// mode for display
Mode mode_;
// overlays and frames to be displayed on top of source
std::map<View::Mode, Group*> overlays_;
std::map<View::Mode, Switch*> frames_;
Handles *resize_handle_, *resize_H_handle_, *resize_V_handle_, *rotate_handle_;
// update

View File

@@ -248,6 +248,10 @@ void UserInterface::handleKeyboard()
// Logs
Settings::application.media_player = !Settings::application.media_player;
}
else if (ImGui::IsKeyPressed( GLFW_KEY_A )) {
// select all
Mixer::manager().currentView()->selectall();
}
}
// No CTRL modifier
@@ -386,13 +390,15 @@ void UserInterface::handleMouse()
else {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
// Selection area
// ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
// ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
// ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
// ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
// TODO Multiple sources selection
Mixer::manager().currentView()->select(mouseclic[ImGuiMouseButton_Left], mousepos);
}
}
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) {
@@ -412,6 +418,9 @@ void UserInterface::handleMouse()
navigator.showPannelSource( Mixer::manager().indexCurrentSource() );
}
// TODO deselect if current source is not in selection
Mixer::manager().currentView()->deselect();
}
else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
{
@@ -723,7 +732,7 @@ void UserInterface::RenderMediaPlayer()
ImGui::SetNextWindowPos(ImVec2(1180, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(350, 300), ImVec2(FLT_MAX, FLT_MAX));
if ( !ImGui::Begin(IMGUI_TITLE_MEDIAPLAYER, &Settings::application.media_player, ImGuiWindowFlags_NoScrollbar) || !show)
if ( !ImGui::Begin(IMGUI_TITLE_MEDIAPLAYER, &Settings::application.media_player, ImGuiWindowFlags_NoScrollbar ) || !show)
{
ImGui::End();
return;
@@ -1090,14 +1099,16 @@ void Navigator::Render()
{
Mixer::manager().setCurrentView(View::MIXING);
}
if (ImGui::Selectable( ICON_FA_SIGN , &selected_view[2], 0, iconsize))
if (ImGui::Selectable( ICON_FA_OBJECT_UNGROUP , &selected_view[2], 0, iconsize))
{
Mixer::manager().setCurrentView(View::GEOMETRY);
}
if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[3], 0, iconsize))
if (ImGui::Selectable( ICON_FA_IMAGES, &selected_view[3], 0, iconsize))
// if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[3], 0, iconsize))
{
Mixer::manager().setCurrentView(View::LAYER);
}
}
ImGui::End();

View File

@@ -14,6 +14,7 @@
#include "View.h"
#include "Source.h"
#include "Primitives.h"
#include "Decorations.h"
#include "PickingVisitor.h"
#include "DrawVisitor.h"
#include "Mesh.h"
@@ -29,6 +30,9 @@ bool View::need_deep_update_ = true;
View::View(Mode m) : mode_(m)
{
selection_ = new Selection;
selection_->visible_ = false;
scene.ws()->attach(selection_);
}
void View::restoreSettings()
@@ -95,12 +99,43 @@ std::pair<Node *, glm::vec2> View::pick(glm::vec3 point)
// select top-most Node picked
picked = pv.picked().back();
//DEBUG
select(glm::vec2(-1.f, -1.f), glm::vec2(1.f, 1.f));
}
// cancel selection on clic in background
else {
deselect();
}
return picked;
}
void View::select(glm::vec2 A, glm::vec2 B)
{
}
void View::selectall()
{
for(auto it = scene.ws()->begin(); it != scene.ws()->end(); it++) {
if ( *it != selection_)
selection_->attach(*it);
}
selection_->visible_ = true;
}
void View::deselect()
{
selection_->clear();
selection_->visible_ = false;
}
MixingView::MixingView() : View(MIXING)
{
// read default settings

15
View.h
View File

@@ -43,26 +43,37 @@ public:
Cursor(CursorType t, std::string i = "") { type = t; info = i;}
} Cursor;
// picking of nodes in a view provided a point coordinates in scene reference frame
virtual std::pair<Node *, glm::vec2> pick(glm::vec3 point);
// drag the view provided a start and an end point in screen coordinates
virtual Cursor drag (glm::vec2, glm::vec2);
// grab a source provided a start and an end point in screen coordinates and the picking point
virtual Cursor grab (glm::vec2, glm::vec2, Source*, std::pair<Node *, glm::vec2>) {
return Cursor();
}
// test mouse over provided a point in screen coordinates and the picking point
virtual Cursor over (glm::vec2, Source*, std::pair<Node *, glm::vec2>) {
return Cursor();
}
// select sources provided a start and end selection points in screen coordinates
virtual void select(glm::vec2, glm::vec2);
virtual void selectall();
virtual void deselect();
virtual void restoreSettings();
virtual void saveSettings();
// accessible scene
Scene scene;
// hack to avoid reordering scene of view if not necessary
// avoid reordering scene of view if not necessary
static bool need_deep_update_;
protected:
Mode mode_;
class Selection *selection_;
};

View File

@@ -7,7 +7,6 @@
class Node;
class Group;
class Switch;
class Animation;
class Primitive;
class Scene;
class Surface;
@@ -42,7 +41,6 @@ public:
// not mandatory for all others
virtual void visit (Switch&) {}
virtual void visit (Animation&) {}
virtual void visit (Surface&) {}
virtual void visit (ImageSurface&) {}
virtual void visit (MediaSurface&) {}