diff --git a/DeviceSource.cpp b/DeviceSource.cpp index 8a8b16f..4bab613 100644 --- a/DeviceSource.cpp +++ b/DeviceSource.cpp @@ -330,10 +330,8 @@ DeviceSource::DeviceSource() : StreamSource() // create stream stream_ = new Stream; - // set icons - overlays_[View::MIXING]->attach( new Symbol(Symbol::CAMERA, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::CAMERA, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::CAMERA, glm::vec3(1.1f, 0.9f, 0.01f)) ); + // set symbol + symbol_ = new Symbol(Symbol::CAMERA, glm::vec3(0.8f, 0.8f, 0.01f)); } DeviceSource::~DeviceSource() diff --git a/GarbageVisitor.cpp b/GarbageVisitor.cpp index b279389..a57f3da 100644 --- a/GarbageVisitor.cpp +++ b/GarbageVisitor.cpp @@ -34,7 +34,7 @@ void GarbageVisitor::visit(Node &n) // take the node out of the Tree if (current_) - current_->detatch(&n); + current_->detach(&n); } diff --git a/MediaSource.cpp b/MediaSource.cpp index 1fdd049..20c3654 100644 --- a/MediaSource.cpp +++ b/MediaSource.cpp @@ -77,21 +77,15 @@ void MediaSource::init() float height = float(mediaplayer_->width()) / mediaplayer_->aspectRatio(); FrameBuffer *renderbuffer = new FrameBuffer(mediaplayer_->width(), (uint)height, true); + // icon in mixing view + if (mediaplayer_->isImage()) + symbol_ = new Symbol(Symbol::IMAGE, glm::vec3(0.8f, 0.8f, 0.01f)); + else + symbol_ = new Symbol(Symbol::VIDEO, glm::vec3(0.8f, 0.8f, 0.01f)); + // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); - // icon in mixing view - if (mediaplayer_->isImage()) { - overlays_[View::MIXING]->attach( new Symbol(Symbol::IMAGE, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::IMAGE, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::IMAGE, glm::vec3(1.1f, 0.9f, 0.01f)) ); - } - else { - overlays_[View::MIXING]->attach( new Symbol(Symbol::VIDEO, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::VIDEO, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::VIDEO, glm::vec3(1.1f, 0.9f, 0.01f)) ); - } - // done init initialized_ = true; Log::Info("Source '%s' linked to Media %s.", name().c_str(), std::to_string(mediaplayer_->id()).c_str()); diff --git a/Mixer.cpp b/Mixer.cpp index ee6b4d5..52b14e4 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -450,11 +450,11 @@ void Mixer::detach(Source *s) // in case it was selected.. selection().remove(s); // detach from views - mixing_.scene.ws()->detatch( s->group(View::MIXING) ); - geometry_.scene.ws()->detatch( s->group(View::GEOMETRY) ); - layer_.scene.ws()->detatch( s->group(View::LAYER) ); - appearance_.scene.ws()->detatch( s->group(View::APPEARANCE) ); - transition_.scene.ws()->detatch( s->group(View::TRANSITION) ); + mixing_.scene.ws()->detach( s->group(View::MIXING) ); + geometry_.scene.ws()->detach( s->group(View::GEOMETRY) ); + layer_.scene.ws()->detach( s->group(View::LAYER) ); + appearance_.scene.ws()->detach( s->group(View::APPEARANCE) ); + transition_.scene.ws()->detach( s->group(View::TRANSITION) ); } } @@ -493,7 +493,7 @@ void Mixer::uncover(Source *s) if ( it != stash_.end() ) { stash_.erase(it); - mixing_.scene.bg()->detatch( s->group(View::MIXING) ); + mixing_.scene.bg()->detach( s->group(View::MIXING) ); attach(s); session_->addSource(s); } diff --git a/NetworkSource.cpp b/NetworkSource.cpp index 11340c2..212dd49 100644 --- a/NetworkSource.cpp +++ b/NetworkSource.cpp @@ -273,10 +273,9 @@ NetworkSource::NetworkSource() : StreamSource() // create stream stream_ = (Stream *) new NetworkStream; - // set icons - overlays_[View::MIXING]->attach( new Symbol(Symbol::SHARE, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::SHARE, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::SHARE, glm::vec3(1.1f, 0.9f, 0.01f)) ); + // set symbol + symbol_ = new Symbol(Symbol::SHARE, glm::vec3(0.8f, 0.8f, 0.01f)); + } diff --git a/PatternSource.cpp b/PatternSource.cpp index da09cc1..f1dab60 100644 --- a/PatternSource.cpp +++ b/PatternSource.cpp @@ -133,10 +133,8 @@ PatternSource::PatternSource() : StreamSource() // create stream stream_ = (Stream *) new Pattern; - // set icons - overlays_[View::MIXING]->attach( new Symbol(Symbol::PATTERN, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::PATTERN, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::PATTERN, glm::vec3(1.1f, 0.9f, 0.01f)) ); + // set symbol + symbol_ = new Symbol(Symbol::PATTERN, glm::vec3(0.8f, 0.8f, 0.01f)); } void PatternSource::setPattern(uint type, glm::ivec2 resolution) diff --git a/Resource.cpp b/Resource.cpp index d7a6e20..98645e3 100644 --- a/Resource.cpp +++ b/Resource.cpp @@ -59,6 +59,23 @@ uint Resource::getTextureWhite() return tex_index_white; } +uint Resource::getTextureTransparent() +{ + static uint tex_index_transparent = 0; + + // generate texture (once) + if (tex_index_transparent == 0) { + glGenTextures(1, &tex_index_transparent); + glBindTexture( GL_TEXTURE_2D, tex_index_transparent); + unsigned char clearColor[4] = {0, 0, 0, 0}; + // texture with one black pixel + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, clearColor); + } + + return tex_index_transparent; +} + const char *Resource::getData(const std::string& path, size_t* out_file_size){ auto fs = cmrc::vmix::get_filesystem(); diff --git a/Resource.h b/Resource.h index 9a6929d..1d8463d 100644 --- a/Resource.h +++ b/Resource.h @@ -22,12 +22,15 @@ namespace Resource // Returns the OpenGL generated Texture index uint getTextureImage(const std::string& path, float *aspect_ratio = nullptr); - // Returns the OpenGL generated Texture index for an empty 1x1 black transparent pixel texture + // Returns the OpenGL generated Texture index for an empty 1x1 black opaque pixel texture uint getTextureBlack(); // Returns the OpenGL generated Texture index for an empty 1x1 white opaque pixel texture uint getTextureWhite(); + // Returns the OpenGL generated Texture index for an empty 1x1 back transparent pixel texture + uint getTextureTransparent(); + // Generic access to pointer to data const char *getData(const std::string& path, size_t* out_file_size); diff --git a/Scene.cpp b/Scene.cpp index 8cbf0d4..c04d150 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -228,8 +228,10 @@ void Group::clear() void Group::attach(Node *child) { - children_.insert(child); - child->refcount_++; + if (child != nullptr) { + children_.insert(child); + child->refcount_++; + } } @@ -242,17 +244,18 @@ void Group::sort() children_.swap(ordered_children); } -void Group::detatch(Node *child) +void Group::detach(Node *child) { - // 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) - NodeSet::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_--; + if (child != nullptr) { + // 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) + NodeSet::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_--; + } } - } void Group::update( float dt ) diff --git a/Scene.h b/Scene.h index 43cd33c..c2000fc 100644 --- a/Scene.h +++ b/Scene.h @@ -173,7 +173,7 @@ public: // container void clear(); void attach (Node *child); - void detatch (Node *child); + void detach (Node *child); inline uint numChildren () const { return children_.size(); } // Group specific access to its Nodes diff --git a/Session.cpp b/Session.cpp index 4257261..65005f8 100644 --- a/Session.cpp +++ b/Session.cpp @@ -132,7 +132,7 @@ SourceList::iterator Session::deleteSource(Source *s) if (its != sources_.end()) { // remove Node from the rendering scene - render_.scene.ws()->detatch( s->group(View::RENDERING) ); + render_.scene.ws()->detach( s->group(View::RENDERING) ); // erase the source from the update list & get next element its = sources_.erase(its); @@ -160,7 +160,7 @@ void Session::removeSource(Source *s) if (its != sources_.end()) { // remove Node from the rendering scene - render_.scene.ws()->detatch( s->group(View::RENDERING) ); + render_.scene.ws()->detach( s->group(View::RENDERING) ); // erase the source from the update list & get next element sources_.erase(its); @@ -181,7 +181,7 @@ Source *Session::popSource() s = *its; // remove Node from the rendering scene - render_.scene.ws()->detatch( s->group(View::RENDERING) ); + render_.scene.ws()->detach( s->group(View::RENDERING) ); // erase the source from the update list & get next element sources_.erase(its); diff --git a/SessionCreator.cpp b/SessionCreator.cpp index 7ad21b1..e210007 100644 --- a/SessionCreator.cpp +++ b/SessionCreator.cpp @@ -248,6 +248,7 @@ void SessionLoader::load(XMLElement *sessionNode) session_->addSource(clone_source); // apply config to source clone_source->accept(*this); + clone_source->touch(); // remember sources_id_.push_back( clone_source->id() ); } @@ -294,6 +295,9 @@ Source *SessionLoader::cloneOrCreateSource(tinyxml2::XMLElement *sourceNode) else if ( std::string(pType) == "DeviceSource") { load_source = new DeviceSource; } + else if ( std::string(pType) == "NetworkSource") { + load_source = new NetworkSource; + } else if ( std::string(pType) == "CloneSource") { // clone from given origin XMLElement* originNode = xmlCurrent_->FirstChildElement("origin"); @@ -478,6 +482,9 @@ void SessionLoader::visit (Source& s) xmlCurrent_ = sourceNode->FirstChildElement("Layer"); s.groupNode(View::LAYER)->accept(*this); + xmlCurrent_ = sourceNode->FirstChildElement("Appearance"); + s.groupNode(View::APPEARANCE)->accept(*this); + xmlCurrent_ = sourceNode->FirstChildElement("Blending"); s.blendingShader()->accept(*this); diff --git a/SessionSource.cpp b/SessionSource.cpp index 87b3eab..61f2aaa 100644 --- a/SessionSource.cpp +++ b/SessionSource.cpp @@ -47,6 +47,9 @@ SessionSource::SessionSource() : Source(), path_("") overlays_[View::TRANSITION]->attach(center); groups_[View::TRANSITION]->attach(overlays_[View::TRANSITION]); + // set symbol + symbol_ = new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)); + failed_ = false; wait_for_sources_ = false; session_ = nullptr; @@ -155,11 +158,6 @@ void SessionSource::init() // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); - // icon in mixing view - overlays_[View::MIXING]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::SESSION, glm::vec3(1.1f, 0.9f, 0.01f)) ); - // wait for all sources to init if (session_->numSource() > 0) wait_for_sources_ = true; @@ -173,7 +171,7 @@ void SessionSource::init() if (initialized_){ // remove the loading icon Node *loader = overlays_[View::TRANSITION]->back(); - overlays_[View::TRANSITION]->detatch(loader); + overlays_[View::TRANSITION]->detach(loader); delete loader; } } @@ -208,18 +206,6 @@ void SessionSource::update(float dt) Source::update(dt); } -void SessionSource::render() -{ - if (!initialized_) - init(); - else { - // render the sesion into frame buffer - static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); - renderbuffer_->begin(); - texturesurface_->draw(glm::identity(), projection); - renderbuffer_->end(); - } -} void SessionSource::accept(Visitor& v) { @@ -231,6 +217,8 @@ void SessionSource::accept(Visitor& v) RenderSource::RenderSource(Session *session) : Source(), session_(session) { + // set symbol + symbol_ = new Symbol(Symbol::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)); } @@ -262,11 +250,6 @@ void RenderSource::init() // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); - // icon in mixing view - overlays_[View::MIXING]->attach( new Symbol(Symbol::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::RENDER, glm::vec3(1.1f, 0.9f, 0.01f)) ); - // done init initialized_ = true; @@ -274,19 +257,6 @@ void RenderSource::init() } } -void RenderSource::render() -{ - if (!initialized_) - init(); - else { - // render the view into frame buffer - static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); - renderbuffer_->begin(); - texturesurface_->draw(glm::identity(), projection); - renderbuffer_->end(); - } -} - void RenderSource::accept(Visitor& v) { diff --git a/SessionSource.h b/SessionSource.h index 4df0e3b..42e20fe 100644 --- a/SessionSource.h +++ b/SessionSource.h @@ -14,7 +14,6 @@ public: // implementation of source API void update (float dt) override; void setActive (bool on) override; - void render() override; bool failed() const override; uint texture() const override; void accept (Visitor& v) override; @@ -48,7 +47,6 @@ public: RenderSource(Session *session); // implementation of source API - void render() override; bool failed() const override; uint texture() const override; void accept (Visitor& v) override; diff --git a/SessionVisitor.cpp b/SessionVisitor.cpp index 2dcb6b9..e4fe65d 100644 --- a/SessionVisitor.cpp +++ b/SessionVisitor.cpp @@ -343,6 +343,10 @@ void SessionVisitor::visit (Source& s) sourceNode->InsertEndChild(xmlCurrent_); s.groupNode(View::LAYER)->accept(*this); + xmlCurrent_ = xmlDoc_->NewElement( "Appearance" ); + sourceNode->InsertEndChild(xmlCurrent_); + s.groupNode(View::APPEARANCE)->accept(*this); + xmlCurrent_ = xmlDoc_->NewElement( "Blending" ); sourceNode->InsertEndChild(xmlCurrent_); s.blendingShader()->accept(*this); diff --git a/Source.cpp b/Source.cpp index 8157f52..dfded20 100644 --- a/Source.cpp +++ b/Source.cpp @@ -15,7 +15,7 @@ #include "Log.h" #include "Mixer.h" -Source::Source() : initialized_(false), active_(true), need_update_(true) +Source::Source() : initialized_(false), active_(true), need_update_(true), symbol_(nullptr) { // create unique id id_ = GlmToolkit::uniqueId(); @@ -72,26 +72,26 @@ Source::Source() : initialized_(false), active_(true), need_update_(true) overlays_[View::GEOMETRY] = new Group; overlays_[View::GEOMETRY]->translation_.z = 0.15; overlays_[View::GEOMETRY]->visible_ = false; - handle_[Handles::RESIZE] = new Handles(Handles::RESIZE); - handle_[Handles::RESIZE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); - handle_[Handles::RESIZE]->translation_.z = 0.1; - overlays_[View::GEOMETRY]->attach(handle_[Handles::RESIZE]); - handle_[Handles::RESIZE_H] = new Handles(Handles::RESIZE_H); - handle_[Handles::RESIZE_H]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); - handle_[Handles::RESIZE_H]->translation_.z = 0.1; - overlays_[View::GEOMETRY]->attach(handle_[Handles::RESIZE_H]); - handle_[Handles::RESIZE_V] = new Handles(Handles::RESIZE_V); - handle_[Handles::RESIZE_V]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); - handle_[Handles::RESIZE_V]->translation_.z = 0.1; - overlays_[View::GEOMETRY]->attach(handle_[Handles::RESIZE_V]); - handle_[Handles::ROTATE] = new Handles(Handles::ROTATE); - handle_[Handles::ROTATE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); - handle_[Handles::ROTATE]->translation_.z = 0.1; - overlays_[View::GEOMETRY]->attach(handle_[Handles::ROTATE]); - handle_[Handles::SCALE] = new Handles(Handles::SCALE); - handle_[Handles::SCALE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); - handle_[Handles::SCALE]->translation_.z = 0.1; - overlays_[View::GEOMETRY]->attach(handle_[Handles::SCALE]); + handles_[View::GEOMETRY][Handles::RESIZE] = new Handles(Handles::RESIZE); + handles_[View::GEOMETRY][Handles::RESIZE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); + handles_[View::GEOMETRY][Handles::RESIZE]->translation_.z = 0.1; + overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::RESIZE]); + handles_[View::GEOMETRY][Handles::RESIZE_H] = new Handles(Handles::RESIZE_H); + handles_[View::GEOMETRY][Handles::RESIZE_H]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); + handles_[View::GEOMETRY][Handles::RESIZE_H]->translation_.z = 0.1; + overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::RESIZE_H]); + handles_[View::GEOMETRY][Handles::RESIZE_V] = new Handles(Handles::RESIZE_V); + handles_[View::GEOMETRY][Handles::RESIZE_V]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); + handles_[View::GEOMETRY][Handles::RESIZE_V]->translation_.z = 0.1; + overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::RESIZE_V]); + handles_[View::GEOMETRY][Handles::ROTATE] = new Handles(Handles::ROTATE); + handles_[View::GEOMETRY][Handles::ROTATE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); + handles_[View::GEOMETRY][Handles::ROTATE]->translation_.z = 0.1; + overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::ROTATE]); + handles_[View::GEOMETRY][Handles::SCALE] = new Handles(Handles::SCALE); + handles_[View::GEOMETRY][Handles::SCALE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); + handles_[View::GEOMETRY][Handles::SCALE]->translation_.z = 0.1; + overlays_[View::GEOMETRY]->attach(handles_[View::GEOMETRY][Handles::SCALE]); frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); frame->translation_.z = 0.1; @@ -124,9 +124,36 @@ Source::Source() : initialized_(false), active_(true), need_update_(true) groups_[View::APPEARANCE] = new Group; groups_[View::APPEARANCE]->visible_ = false; + frames_[View::APPEARANCE] = new Switch; + frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); + frame->translation_.z = 0.1; + frame->color = glm::vec4( COLOR_APPEARANCE_SOURCE, 0.7f); + frames_[View::APPEARANCE]->attach(frame); + frame = new Frame(Frame::SHARP, Frame::LARGE, Frame::NONE); + frame->translation_.z = 0.1; + frame->color = glm::vec4( COLOR_APPEARANCE_SOURCE, 1.f); + frames_[View::APPEARANCE]->attach(frame); + groups_[View::APPEARANCE]->attach(frames_[View::APPEARANCE]); + overlays_[View::APPEARANCE] = new Group; overlays_[View::APPEARANCE]->translation_.z = 0.1; overlays_[View::APPEARANCE]->visible_ = false; + handles_[View::APPEARANCE][Handles::RESIZE] = new Handles(Handles::RESIZE); + handles_[View::APPEARANCE][Handles::RESIZE]->color = glm::vec4( COLOR_APPEARANCE_SOURCE, 1.f); + handles_[View::APPEARANCE][Handles::RESIZE]->translation_.z = 0.1; + overlays_[View::APPEARANCE]->attach(handles_[View::APPEARANCE][Handles::RESIZE]); + handles_[View::APPEARANCE][Handles::RESIZE_H] = new Handles(Handles::RESIZE_H); + handles_[View::APPEARANCE][Handles::RESIZE_H]->color = glm::vec4( COLOR_APPEARANCE_SOURCE, 1.f); + handles_[View::APPEARANCE][Handles::RESIZE_H]->translation_.z = 0.1; + overlays_[View::APPEARANCE]->attach(handles_[View::APPEARANCE][Handles::RESIZE_H]); + handles_[View::APPEARANCE][Handles::RESIZE_V] = new Handles(Handles::RESIZE_V); + handles_[View::APPEARANCE][Handles::RESIZE_V]->color = glm::vec4( COLOR_APPEARANCE_SOURCE, 1.f); + handles_[View::APPEARANCE][Handles::RESIZE_V]->translation_.z = 0.1; + overlays_[View::APPEARANCE]->attach(handles_[View::APPEARANCE][Handles::RESIZE_V]); + handles_[View::APPEARANCE][Handles::SCALE] = new Handles(Handles::SCALE); + handles_[View::APPEARANCE][Handles::SCALE]->color = glm::vec4( COLOR_APPEARANCE_SOURCE, 1.f); + handles_[View::APPEARANCE][Handles::SCALE]->translation_.z = 0.1; + overlays_[View::APPEARANCE]->attach(handles_[View::APPEARANCE][Handles::SCALE]); groups_[View::APPEARANCE]->attach(overlays_[View::APPEARANCE]); // empty transition node @@ -266,10 +293,29 @@ bool Source::imageProcessingEnabled() return ( renderingshader_ == processingshader_ ); } +void Source::render() +{ + if (!initialized_) + init(); + else { + // render the view into frame buffer + static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); + renderbuffer_->begin(); + texturesurface_->draw(glm::identity(), projection); + renderbuffer_->end(); + } +} + void Source::attach(FrameBuffer *renderbuffer) { renderbuffer_ = renderbuffer; + // if a symbol is available, add it to icons + if (symbol_) { + overlays_[View::MIXING]->attach( symbol_ ); + overlays_[View::LAYER]->attach( symbol_ ); + } + // create the surfaces to draw the frame buffer in the views rendersurface_ = new FrameBufferSurface(renderbuffer_, blendingshader_); groups_[View::RENDERING]->attach(rendersurface_); @@ -285,9 +331,11 @@ void Source::attach(FrameBuffer *renderbuffer) groups_[View::MIXING]->attach(surfacemix); groups_[View::LAYER]->attach(surfacemix); - // for appearance view, a dedicated surface without blending - Surface *surfacepreview = new FrameBufferSurface(renderbuffer_); - groups_[View::APPEARANCE]->attach(surfacepreview); +// // for appearance view, a dedicated surface without blending + // Surface *surfacepreview = new FrameBufferSurface(renderbuffer_); + Surface *surfacetmp = new Surface(); + surfacetmp->setTextureIndex(Resource::getTextureTransparent()); + groups_[View::APPEARANCE]->attach(surfacetmp); // scale all icon nodes to match aspect ratio of the media NodeSet::iterator node; @@ -385,6 +433,19 @@ void Source::update(float dt) groups_[View::GEOMETRY]->translation_.z = groups_[View::LAYER]->translation_.z; groups_[View::RENDERING]->translation_.z = groups_[View::LAYER]->translation_.z; + // MODIFY texture projection based on APPEARANCE node + texturesurface_->translation_.x = groups_[View::APPEARANCE]->translation_.x; + if (renderbuffer_) + texturesurface_->translation_.x /= renderbuffer_->aspectRatio(); + texturesurface_->translation_.y = groups_[View::APPEARANCE]->translation_.y; + texturesurface_->rotation_.z = groups_[View::APPEARANCE]->rotation_.z; + // avoid any null scale + s = groups_[View::APPEARANCE]->scale_; + s.x = CLAMP_SCALE(s.x); + s.y = CLAMP_SCALE(s.y); + s.z = 1.f; + texturesurface_->scale_ = s; + texturesurface_->update(dt); need_update_ = false; } @@ -451,6 +512,8 @@ CloneSource *Source::clone() CloneSource::CloneSource(Source *origin) : Source(), origin_(origin) { + // set symbol + symbol_ = new Symbol(Symbol::CLONE, glm::vec3(0.8f, 0.8f, 0.01f)); } CloneSource::~CloneSource() @@ -481,11 +544,6 @@ void CloneSource::init() // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); - // icon in mixing view - overlays_[View::MIXING]->attach( new Symbol(Symbol::CLONE, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::CLONE, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::CLONE, glm::vec3(1.1f, 0.9f, 0.01f)) ); - // done init initialized_ = true; @@ -514,19 +572,6 @@ uint CloneSource::texture() const return Resource::getTextureBlack(); } -void CloneSource::render() -{ - if (!initialized_) - init(); - else if (origin_) { - // render the view into frame buffer - static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); - renderbuffer_->begin(); - texturesurface_->draw(glm::identity(), projection); - renderbuffer_->end(); - } -} - void CloneSource::accept(Visitor& v) { Source::accept(v); diff --git a/Source.h b/Source.h index b44c6c8..1f458bd 100644 --- a/Source.h +++ b/Source.h @@ -17,6 +17,7 @@ class FrameBufferSurface; class Session; class Frame; class Handles; +class Symbol; class CloneSource; typedef std::list CloneList; @@ -28,6 +29,7 @@ class Source friend class MixingView; friend class GeometryView; friend class LayerView; + friend class AppearanceView; friend class TransitionView; public: @@ -101,7 +103,7 @@ public: virtual uint texture() const = 0; // a Source shall define how to render into the frame buffer - virtual void render() = 0; + virtual void render(); // accept all kind of visitors virtual void accept (Visitor& v); @@ -176,7 +178,8 @@ protected: // overlays and frames to be displayed on top of source std::map overlays_; std::map frames_; - Handles *handle_[5]; + std::map handles_; + Symbol *symbol_; // update bool active_; @@ -199,7 +202,6 @@ public: // implementation of source API void setActive (bool on) override; - void render() override; uint texture() const override; bool failed() const override { return origin_ == nullptr; } void accept (Visitor& v) override; diff --git a/StreamSource.cpp b/StreamSource.cpp index 26ddf07..c399f8c 100644 --- a/StreamSource.cpp +++ b/StreamSource.cpp @@ -17,10 +17,8 @@ GenericStreamSource::GenericStreamSource() : StreamSource() // create stream stream_ = new Stream; - // icon in mixing view - overlays_[View::MIXING]->attach( new Symbol(Symbol::EMPTY, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::LAYER]->attach( new Symbol(Symbol::EMPTY, glm::vec3(0.8f, 0.8f, 0.01f)) ); - overlays_[View::APPEARANCE]->attach( new Symbol(Symbol::EMPTY, glm::vec3(1.1f, 0.9f, 0.01f)) ); + // set symbol + symbol_ = new Symbol(Symbol::EMPTY, glm::vec3(0.8f, 0.8f, 0.01f)); } void GenericStreamSource::setDescription(const std::string &desc) @@ -115,16 +113,3 @@ void StreamSource::update(float dt) if (stream_) stream_->update(); } - -void StreamSource::render() -{ - if (!initialized_) - init(); - else { - // render the media player into frame buffer - static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); - renderbuffer_->begin(); - texturesurface_->draw(glm::identity(), projection); - renderbuffer_->end(); - } -} diff --git a/StreamSource.h b/StreamSource.h index 52f8dae..77417ea 100644 --- a/StreamSource.h +++ b/StreamSource.h @@ -30,7 +30,6 @@ public: // implementation of source API void update (float dt) override; void setActive (bool on) override; - void render() override; bool failed() const override; uint texture() const override; diff --git a/View.cpp b/View.cpp index d7980c6..01795a6 100644 --- a/View.cpp +++ b/View.cpp @@ -890,7 +890,7 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p // work on the given source if (!s) return ret; - Group *sourceNode = s->group(mode_); + Group *sourceNode = s->group(mode_); // groups_[View::GEOMETRY] // grab coordinates in scene-View reference frame glm::vec3 scene_from = Rendering::manager().unProject(from, scene.root()->transform_); @@ -928,10 +928,10 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p glm::vec4 center = scene_to_corner_transform * glm::vec4( s->stored_status_->translation_, 1.f); // picking on the resizing handles in the corners - if ( pick.first == s->handle_[Handles::RESIZE] ) { + if ( pick.first == s->handles_[mode_][Handles::RESIZE] ) { // inform on which corner should be overlayed (opposite) - s->handle_[Handles::RESIZE]->overlayActiveCorner(-corner); + s->handles_[mode_][Handles::RESIZE]->overlayActiveCorner(-corner); // overlay_scaling_grid_->visible_ = false; // glm::vec4 icon = corner_to_scene_transform * glm::vec4(0.f, 0.f, 0.f, 1.f); @@ -983,10 +983,10 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p } // picking on the BORDER RESIZING handles left or right - else if ( pick.first == s->handle_[Handles::RESIZE_H] ) { + else if ( pick.first == s->handles_[mode_][Handles::RESIZE_H] ) { // inform on which corner should be overlayed (opposite) - s->handle_[Handles::RESIZE_H]->overlayActiveCorner(-corner); + s->handles_[mode_][Handles::RESIZE_H]->overlayActiveCorner(-corner); // SHIFT: HORIZONTAL SCALE to restore source aspect ratio if (UserInterface::manager().shiftModifier()) { @@ -1018,10 +1018,10 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p info << " x " << sourceNode->scale_.y; } // picking on the BORDER RESIZING handles top or bottom - else if ( pick.first == s->handle_[Handles::RESIZE_V] ) { + else if ( pick.first == s->handles_[mode_][Handles::RESIZE_V] ) { // inform on which corner should be overlayed (opposite) - s->handle_[Handles::RESIZE_V]->overlayActiveCorner(-corner); + s->handles_[mode_][Handles::RESIZE_V]->overlayActiveCorner(-corner); // SHIFT: VERTICAL SCALE to restore source aspect ratio if (UserInterface::manager().shiftModifier()) { @@ -1053,7 +1053,7 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p info << " x " << sourceNode->scale_.y; } // picking on the CENTRER SCALING handle - else if ( pick.first == s->handle_[Handles::SCALE] ) { + else if ( pick.first == s->handles_[mode_][Handles::SCALE] ) { overlay_scaling_cross_->visible_ = false; overlay_scaling_grid_->visible_ = false; @@ -1086,7 +1086,7 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p info << " x " << sourceNode->scale_.y; } // picking on the rotating handle - else if ( pick.first == s->handle_[Handles::ROTATE] ) { + else if ( pick.first == s->handles_[mode_][Handles::ROTATE] ) { // ROTATION on CENTER overlay_rotation_->visible_ = true; @@ -1208,9 +1208,9 @@ void GeometryView::terminate() for (auto sit = Mixer::manager().session()->begin(); sit != Mixer::manager().session()->end(); sit++){ - (*sit)->handle_[Handles::RESIZE]->overlayActiveCorner(c); - (*sit)->handle_[Handles::RESIZE_H]->overlayActiveCorner(c); - (*sit)->handle_[Handles::RESIZE_V]->overlayActiveCorner(c); + (*sit)->handles_[mode_][Handles::RESIZE]->overlayActiveCorner(c); + (*sit)->handles_[mode_][Handles::RESIZE_H]->overlayActiveCorner(c); + (*sit)->handles_[mode_][Handles::RESIZE_V]->overlayActiveCorner(c); } } @@ -1590,7 +1590,7 @@ Session *TransitionView::detach() // get and detatch the group node from the view workspace Group *tg = transition_source_->group(View::TRANSITION); - scene.ws()->detatch( tg ); + scene.ws()->detach( tg ); // test if the icon of the transition source is "Ready" if ( tg->translation_.x > 0.f ) @@ -1708,31 +1708,72 @@ AppearanceView::AppearanceView() : View(APPEARANCE), index_source_(-1) restoreSettings(); // Scene background - Surface *rect = new Surface; + Surface *rect = new Surface; // black : TODO transparency grid scene.bg()->attach(rect); + surfacepreview = new Surface; // to attach source preview + surfacepreview->translation_.z = 0.01f; + scene.bg()->attach(surfacepreview); // Geometry Scene foreground - Frame *border = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); + Frame *border = new Frame(Frame::SHARP, Frame::LARGE, Frame::GLOW); border->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f ); scene.fg()->attach(border); -} - -void AppearanceView::update(float dt) -{ - View::update(dt); - - -// // a more complete update is requested (e.g. after switching to view) -// // AND no source selected -// if (View::need_deep_update_ && Mixer::manager().indexCurrentSource() < 0) { - -// index_source_ = -1; -// } - + // User interface foreground + // + // point to show POSITION + overlay_position_ = new Symbol(Symbol::SQUARE_POINT); + overlay_position_->scale_ = glm::vec3(0.5f, 0.5f, 1.f); + scene.fg()->attach(overlay_position_); + overlay_position_->visible_ = false; + // cross to show the axis for POSITION + overlay_position_cross_ = new Symbol(Symbol::CROSS); + overlay_position_cross_->rotation_ = glm::vec3(0.f, 0.f, M_PI_4); + overlay_position_cross_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); + scene.fg()->attach(overlay_position_cross_); + overlay_position_cross_->visible_ = false; + // 'grid' : tic marks every 0.1 step for SCALING + // with dark background + Group *g = new Group; + Symbol *s = new Symbol(Symbol::GRID); + g->attach(s); + s = new Symbol(Symbol::SQUARE_POINT); + s->color = glm::vec4(0.f, 0.f, 0.f, 0.25f); + s->scale_ = glm::vec3(18.f, 18.f, 1.f); + s->translation_.z = -0.1; + g->attach(s); + overlay_scaling_grid_ = g; + overlay_scaling_grid_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); + scene.fg()->attach(overlay_scaling_grid_); + overlay_scaling_grid_->visible_ = false; + // cross in the square for proportional SCALING + overlay_scaling_cross_ = new Symbol(Symbol::CROSS); + overlay_scaling_cross_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); + scene.fg()->attach(overlay_scaling_cross_); + overlay_scaling_cross_->visible_ = false; + // square to show the center of SCALING + overlay_scaling_ = new Symbol(Symbol::SQUARE); + overlay_scaling_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); + scene.fg()->attach(overlay_scaling_); + overlay_scaling_->visible_ = false; } +//void AppearanceView::update(float dt) +//{ +// View::update(dt); + + +//// // a more complete update is requested (e.g. after switching to view) +//// // AND no source selected +//// if (View::need_deep_update_ && Mixer::manager().indexCurrentSource() < 0) { + +//// index_source_ = -1; +//// } + + +//} + void AppearanceView::zoom (float factor) { float z = scene.root()->scale_.x; @@ -1771,6 +1812,11 @@ void AppearanceView::draw() if (s != nullptr) { // update rendering frame to match current source AR scale = s->frame()->aspectRatio(); + + surfacepreview->setTextureIndex( s->frame()->texture() ); + } + else { + surfacepreview->setTextureIndex(0); } // update aspect ratio @@ -1790,29 +1836,308 @@ void AppearanceView::draw() View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) { +// View::Cursor ret = Cursor(); +// std::ostringstream info; + +// // work on the given source // if (!s) - return Cursor(); +// return ret; + +// Group *sourceNode = s->group(mode_); // groups_[View::APPEARANCE] + +// // grab coordinates in scene-View reference frame +// glm::vec3 scene_from = Rendering::manager().unProject(from, scene.root()->transform_); +// glm::vec3 scene_to = Rendering::manager().unProject(to, scene.root()->transform_); +// glm::vec3 scene_translation = scene_to - scene_from; + +// // make sure matrix transform of stored status is updated +// s->stored_status_->update(0); + +// ret.type = Cursor_ResizeAll; +// info << "UV " ; + +// sourceNode->translation_ = s->stored_status_->translation_ + scene_translation; + +//// ImageShader *shader = s->blendingShader (); +//// shader->uv.x += scene_translation.x; +//// shader->uv.y += scene_translation.y; +//// shader->uv.z += scene_translation.x; +//// shader->uv.w += scene_translation.y; + + +// // request update +// s->touch(); + +// // update cursor +// ret.info = info.str(); +// return ret; + View::Cursor ret = Cursor(); + + // work on the given source + if (!s) + return ret; + Group *sourceNode = s->group(mode_); // groups_[View::GEOMETRY] // grab coordinates in scene-View reference frame glm::vec3 scene_from = Rendering::manager().unProject(from, scene.root()->transform_); glm::vec3 scene_to = Rendering::manager().unProject(to, scene.root()->transform_); glm::vec3 scene_translation = scene_to - scene_from; + // make sure matrix transform of stored status is updated + s->stored_status_->update(0); + // grab coordinates in source-root reference frame + glm::vec4 source_from = glm::inverse(s->stored_status_->transform_) * glm::vec4( scene_from, 1.f ); + glm::vec4 source_to = glm::inverse(s->stored_status_->transform_) * glm::vec4( scene_to, 1.f ); + glm::vec3 source_scaling = glm::vec3(source_to) / glm::vec3(source_from); + + // which manipulation to perform? std::ostringstream info; - info << "UV " ; + if (pick.first) { + // which corner was picked ? + glm::vec2 corner = glm::round(pick.second); - ImageShader *shader = s->blendingShader (); - shader->uv.x += scene_translation.x; - shader->uv.y += scene_translation.y; - shader->uv.z += scene_translation.x; - shader->uv.w += scene_translation.y; + // transform from source center to corner + glm::mat4 T = GlmToolkit::transform(glm::vec3(corner.x, corner.y, 0.f), glm::vec3(0.f, 0.f, 0.f), + glm::vec3(1.f / s->frame()->aspectRatio(), 1.f, 1.f)); + // transformation from scene to corner: + glm::mat4 scene_to_corner_transform = T * glm::inverse(s->stored_status_->transform_); + glm::mat4 corner_to_scene_transform = glm::inverse(scene_to_corner_transform); - return Cursor(Cursor_ResizeAll, info.str() ); + // compute cursor movement in corner reference frame + glm::vec4 corner_from = scene_to_corner_transform * glm::vec4( scene_from, 1.f ); + glm::vec4 corner_to = scene_to_corner_transform * glm::vec4( scene_to, 1.f ); + // operation of scaling in corner reference frame + glm::vec3 corner_scaling = glm::vec3(corner_to) / glm::vec3(corner_from); + + // convert source position in corner reference frame + glm::vec4 center = scene_to_corner_transform * glm::vec4( s->stored_status_->translation_, 1.f); + + // picking on the resizing handles in the corners + if ( pick.first == s->handles_[mode_][Handles::RESIZE] ) { + + // inform on which corner should be overlayed (opposite) + s->handles_[mode_][Handles::RESIZE]->overlayActiveCorner(-corner); + + // RESIZE CORNER + // proportional SCALING with SHIFT + if (UserInterface::manager().shiftModifier()) { + // calculate proportional scaling factor + float factor = glm::length( glm::vec2( corner_to ) ) / glm::length( glm::vec2( corner_from ) ); + // scale node + sourceNode->scale_ = s->stored_status_->scale_ * glm::vec3(factor, factor, 1.f); + // discretized scaling with ALT + if (UserInterface::manager().altModifier()) { + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + factor = sourceNode->scale_.x / s->stored_status_->scale_.x; + sourceNode->scale_.y = s->stored_status_->scale_.y * factor; + } + // update corner scaling to apply to center coordinates + corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; + } + // non-proportional CORNER RESIZE (normal case) + else { + // scale node + sourceNode->scale_ = s->stored_status_->scale_ * corner_scaling; + // discretized scaling with ALT + if (UserInterface::manager().altModifier()) { + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); + corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; + } + } + // transform source center (in corner reference frame) + center = glm::scale(glm::identity(), corner_scaling) * center; + // convert center back into scene reference frame + center = corner_to_scene_transform * center; + // apply to node + sourceNode->translation_ = glm::vec3(center); + // show cursor depending on diagonal (corner picked) + T = glm::rotate(glm::identity(), s->stored_status_->rotation_.z, glm::vec3(0.f, 0.f, 1.f)); + T = glm::scale(T, s->stored_status_->scale_); + corner = T * glm::vec4( corner, 0.f, 0.f ); + ret.type = corner.x * corner.y > 0.f ? Cursor_ResizeNESW : Cursor_ResizeNWSE; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; + + } + // picking on the BORDER RESIZING handles left or right + else if ( pick.first == s->handles_[mode_][Handles::RESIZE_H] ) { + + // inform on which corner should be overlayed (opposite) + s->handles_[mode_][Handles::RESIZE_H]->overlayActiveCorner(-corner); + + // SHIFT: HORIZONTAL SCALE to restore source aspect ratio + if (UserInterface::manager().shiftModifier()) { + sourceNode->scale_.x = ABS(sourceNode->scale_.y) * SIGN(sourceNode->scale_.x); + corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; + } + // HORIZONTAL RESIZE (normal case) + else { + // x scale only + corner_scaling = glm::vec3(corner_scaling.x, 1.f, 1.f); + // scale node + sourceNode->scale_ = s->stored_status_->scale_ * corner_scaling; + // POST-CORRECTION ; discretized scaling with ALT + if (UserInterface::manager().altModifier()) { + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; + } + } + // transform source center (in corner reference frame) + center = glm::scale(glm::identity(), corner_scaling) * center; + // convert center back into scene reference frame + center = corner_to_scene_transform * center; + // apply to node + sourceNode->translation_ = glm::vec3(center); + // show cursor depending on angle + float c = tan(sourceNode->rotation_.z); + ret.type = ABS(c) > 1.f ? Cursor_ResizeNS : Cursor_ResizeEW; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; + } + // picking on the BORDER RESIZING handles top or bottom + else if ( pick.first == s->handles_[mode_][Handles::RESIZE_V] ) { + + // inform on which corner should be overlayed (opposite) + s->handles_[mode_][Handles::RESIZE_V]->overlayActiveCorner(-corner); + + // SHIFT: VERTICAL SCALE to restore source aspect ratio + if (UserInterface::manager().shiftModifier()) { + sourceNode->scale_.y = ABS(sourceNode->scale_.x) * SIGN(sourceNode->scale_.y); + corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; + } + // VERTICAL RESIZE (normal case) + else { + // y scale only + corner_scaling = glm::vec3(1.f, corner_scaling.y, 1.f); + // scale node + sourceNode->scale_ = s->stored_status_->scale_ * corner_scaling; + // POST-CORRECTION ; discretized scaling with ALT + if (UserInterface::manager().altModifier()) { + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); + corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; + } + } + // transform source center (in corner reference frame) + center = glm::scale(glm::identity(), corner_scaling) * center; + // convert center back into scene reference frame + center = corner_to_scene_transform * center; + // apply to node + sourceNode->translation_ = glm::vec3(center); + // show cursor depending on angle + float c = tan(sourceNode->rotation_.z); + ret.type = ABS(c) > 1.f ? Cursor_ResizeEW : Cursor_ResizeNS; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; + } + // picking on the CENTRER SCALING handle + else if ( pick.first == s->handles_[mode_][Handles::SCALE] ) { + + overlay_scaling_cross_->visible_ = false; + overlay_scaling_grid_->visible_ = false; + overlay_scaling_->visible_ = true; + overlay_scaling_->translation_.x = s->stored_status_->translation_.x; + overlay_scaling_->translation_.y = s->stored_status_->translation_.y; + overlay_scaling_->rotation_.z = s->stored_status_->rotation_.z; + overlay_scaling_->update(0); + + // PROPORTIONAL ONLY + if (UserInterface::manager().shiftModifier()) { + float factor = glm::length( glm::vec2( source_to ) ) / glm::length( glm::vec2( source_from ) ); + source_scaling = glm::vec3(factor, factor, 1.f); + overlay_scaling_cross_->visible_ = true; + overlay_scaling_cross_->copyTransform(overlay_scaling_); + } + // apply center scaling + sourceNode->scale_ = s->stored_status_->scale_ * source_scaling; + // POST-CORRECTION ; discretized scaling with ALT + if (UserInterface::manager().altModifier()) { + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); + overlay_scaling_grid_->visible_ = true; + overlay_scaling_grid_->copyTransform(overlay_scaling_); + } + // show cursor depending on diagonal + corner = glm::sign(sourceNode->scale_); + ret.type = (corner.x * corner.y) > 0.f ? Cursor_ResizeNWSE : Cursor_ResizeNESW; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; + } + // picking anywhere but on a handle: user wants to move the source + else { + ret.type = Cursor_ResizeAll; + sourceNode->translation_ = s->stored_status_->translation_ + scene_translation; + // discretized translation with ALT + if (UserInterface::manager().altModifier()) { + sourceNode->translation_.x = ROUND(sourceNode->translation_.x, 10.f); + sourceNode->translation_.y = ROUND(sourceNode->translation_.y, 10.f); + } + // ALT: single axis movement + overlay_position_cross_->visible_ = false; + if (UserInterface::manager().shiftModifier()) { + overlay_position_cross_->visible_ = true; + overlay_position_cross_->translation_.x = s->stored_status_->translation_.x; + overlay_position_cross_->translation_.y = s->stored_status_->translation_.y; + overlay_position_cross_->update(0); + + glm::vec3 dif = s->stored_status_->translation_ - sourceNode->translation_; + if (ABS(dif.x) > ABS(dif.y) ) { + sourceNode->translation_.y = s->stored_status_->translation_.y; + ret.type = Cursor_ResizeEW; + } else { + sourceNode->translation_.x = s->stored_status_->translation_.x; + ret.type = Cursor_ResizeNS; + } + } + // Show center overlay for POSITION + overlay_position_->visible_ = true; + overlay_position_->translation_.x = sourceNode->translation_.x; + overlay_position_->translation_.y = sourceNode->translation_.y; + overlay_position_->update(0); + // Show move cursor + info << "Position " << std::fixed << std::setprecision(3) << sourceNode->translation_.x; + info << ", " << sourceNode->translation_.y ; + } + } + + // request update + s->touch(); + + // store action in history + current_action_ = s->name() + ": " + info.str(); + current_id_ = s->id(); + + // update cursor + ret.info = info.str(); + return ret; } +void AppearanceView::terminate() +{ + View::terminate(); + + // hide all overlays + overlay_position_->visible_ = false; + overlay_position_cross_->visible_ = false; + overlay_scaling_grid_->visible_ = false; + overlay_scaling_cross_->visible_ = false; + overlay_scaling_->visible_ = false; + + // cancel of all handles overlays + glm::vec2 c(0.f, 0.f); + for (auto sit = Mixer::manager().session()->begin(); + sit != Mixer::manager().session()->end(); sit++){ + + (*sit)->handles_[mode_][Handles::RESIZE]->overlayActiveCorner(c); + (*sit)->handles_[mode_][Handles::RESIZE_H]->overlayActiveCorner(c); + (*sit)->handles_[mode_][Handles::RESIZE_V]->overlayActiveCorner(c); + } + +} + View::Cursor AppearanceView::drag (glm::vec2 from, glm::vec2 to) { Cursor ret = View::drag(from, to); diff --git a/View.h b/View.h index 57279d3..8e095ab 100644 --- a/View.h +++ b/View.h @@ -223,17 +223,25 @@ public: void draw () override; - void update (float dt) override; +// void update (float dt) override; void zoom (float factor) override; void resize (int) override; int size () override; Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) override; Cursor drag (glm::vec2, glm::vec2) override; + void terminate() override; private: int index_source_; + Surface *surfacepreview; + + Node *overlay_position_; + Node *overlay_position_cross_; + Node *overlay_scaling_; + Node *overlay_scaling_cross_; + Node *overlay_scaling_grid_; }; diff --git a/defines.h b/defines.h index 483232e..0d0779e 100644 --- a/defines.h +++ b/defines.h @@ -71,6 +71,7 @@ #define COLOR_HIGHLIGHT_SOURCE 1.f, 1.f, 1.f #define COLOR_TRANSITION_SOURCE 1.f, 0.5f, 1.f #define COLOR_TRANSITION_LINES 0.9f, 0.9f, 0.9f +#define COLOR_APPEARANCE_SOURCE 0.0f, 0.9f, 0.9f #define COLOR_FRAME 0.8f, 0.f, 0.8f #define COLOR_LIMBO_CIRCLE 0.16f, 0.16f, 0.16f #define COLOR_SLIDER_CIRCLE 0.11f, 0.11f, 0.11f