mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Stabilized implementation of fading control, with change of view and
trigger of smooth transition. Bugfix with image processing shader change.
This commit is contained in:
@@ -103,7 +103,8 @@ void ImageProcessingShader::operator = (const ImageProcessingShader &S )
|
||||
}
|
||||
|
||||
|
||||
void ImageProcessingShader::accept(Visitor& v) {
|
||||
void ImageProcessingShader::accept(Visitor& v)
|
||||
{
|
||||
// Shader::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,6 @@ void ImageShader::operator = (const ImageShader &S )
|
||||
|
||||
|
||||
void ImageShader::accept(Visitor& v) {
|
||||
// Shader::accept(v);
|
||||
Shader::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
@@ -221,7 +221,6 @@ void Mixer::update()
|
||||
layer_.update(dt_);
|
||||
transition_.update(dt_);
|
||||
|
||||
// optimize the reordering in depth for views;
|
||||
// deep updates shall be performed only 1 frame
|
||||
View::need_deep_update_ = false;
|
||||
}
|
||||
@@ -552,11 +551,12 @@ void Mixer::setView(View::Mode m)
|
||||
case View::MIXING:
|
||||
default:
|
||||
current_view_ = &mixing_;
|
||||
// need to deeply update mixer view to apply fading change
|
||||
View::need_deep_update_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// need to deeply update view to apply eventual changes
|
||||
View::need_deep_update_ = true;
|
||||
|
||||
Settings::application.current_view = (int) m;
|
||||
}
|
||||
|
||||
|
||||
@@ -159,11 +159,14 @@ void SessionCreator::XMLToNode(tinyxml2::XMLElement *xml, Node &n)
|
||||
return;
|
||||
|
||||
XMLElement *scaleNode = node->FirstChildElement("scale");
|
||||
tinyxml2::XMLElementToGLM( scaleNode->FirstChildElement("vec3"), n.scale_);
|
||||
if (scaleNode)
|
||||
tinyxml2::XMLElementToGLM( scaleNode->FirstChildElement("vec3"), n.scale_);
|
||||
XMLElement *translationNode = node->FirstChildElement("translation");
|
||||
tinyxml2::XMLElementToGLM( translationNode->FirstChildElement("vec3"), n.translation_);
|
||||
if (translationNode)
|
||||
tinyxml2::XMLElementToGLM( translationNode->FirstChildElement("vec3"), n.translation_);
|
||||
XMLElement *rotationNode = node->FirstChildElement("rotation");
|
||||
tinyxml2::XMLElementToGLM( rotationNode->FirstChildElement("vec3"), n.rotation_);
|
||||
if (rotationNode)
|
||||
tinyxml2::XMLElementToGLM( rotationNode->FirstChildElement("vec3"), n.rotation_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,13 +194,14 @@ void SessionCreator::visit(MediaPlayer &n)
|
||||
void SessionCreator::visit(Shader &n)
|
||||
{
|
||||
XMLElement* color = xmlCurrent_->FirstChildElement("color");
|
||||
tinyxml2::XMLElementToGLM( color->FirstChildElement("vec4"), n.color);
|
||||
|
||||
XMLElement* blending = xmlCurrent_->FirstChildElement("blending");
|
||||
if (blending) {
|
||||
int blend = 0;
|
||||
blending->QueryIntAttribute("mode", &blend);
|
||||
n.blending = (Shader::BlendMode) blend;
|
||||
if ( color ) {
|
||||
tinyxml2::XMLElementToGLM( color->FirstChildElement("vec4"), n.color);
|
||||
XMLElement* blending = xmlCurrent_->FirstChildElement("blending");
|
||||
if (blending) {
|
||||
int blend = 0;
|
||||
blending->QueryIntAttribute("mode", &blend);
|
||||
n.blending = (Shader::BlendMode) blend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,11 +239,14 @@ void SessionCreator::visit(ImageProcessingShader &n)
|
||||
}
|
||||
|
||||
XMLElement* gamma = xmlCurrent_->FirstChildElement("gamma");
|
||||
tinyxml2::XMLElementToGLM( gamma->FirstChildElement("vec4"), n.gamma);
|
||||
if (gamma)
|
||||
tinyxml2::XMLElementToGLM( gamma->FirstChildElement("vec4"), n.gamma);
|
||||
XMLElement* levels = xmlCurrent_->FirstChildElement("levels");
|
||||
tinyxml2::XMLElementToGLM( levels->FirstChildElement("vec4"), n.levels);
|
||||
if (levels)
|
||||
tinyxml2::XMLElementToGLM( levels->FirstChildElement("vec4"), n.levels);
|
||||
XMLElement* chromakey = xmlCurrent_->FirstChildElement("chromakey");
|
||||
tinyxml2::XMLElementToGLM( chromakey->FirstChildElement("vec4"), n.chromakey);
|
||||
if (chromakey)
|
||||
tinyxml2::XMLElementToGLM( chromakey->FirstChildElement("vec4"), n.chromakey);
|
||||
}
|
||||
|
||||
void SessionCreator::visit (Source& s)
|
||||
|
||||
@@ -39,6 +39,37 @@ void MoveToCallback::update(Node *n, float dt)
|
||||
}
|
||||
}
|
||||
|
||||
RotateToCallback::RotateToCallback(float target, float duration) : UpdateCallback(),
|
||||
target_(target), duration_(duration), progress_(0.f), initialized_(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RotateToCallback::update(Node *n, float dt)
|
||||
{
|
||||
// set start position on first run or upon call of reset()
|
||||
if (!initialized_){
|
||||
startingangle_ = n->rotation_.z;
|
||||
initialized_ = true;
|
||||
// TODO select direction for shorter animation (CW or CCW)
|
||||
|
||||
Log::Info("starting angle %.2f", startingangle_);
|
||||
Log::Info("target_ %.2f", target_);
|
||||
}
|
||||
|
||||
// calculate amplitude of movement
|
||||
progress_ += dt / duration_;
|
||||
|
||||
// perform movement
|
||||
n->rotation_.z = startingangle_ + progress_ * (target_ - startingangle_);
|
||||
|
||||
// end of movement
|
||||
if ( progress_ > 1.f ) {
|
||||
n->rotation_.z = target_;
|
||||
finished_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
BounceScaleCallback::BounceScaleCallback(float duration) : UpdateCallback(),
|
||||
duration_(duration), progress_(0.f), initialized_(false)
|
||||
{
|
||||
@@ -65,6 +96,7 @@ void BounceScaleCallback::update(Node *n, float dt)
|
||||
finished_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
InfiniteGlowCallback::InfiniteGlowCallback(float amplitude) : UpdateCallback(),
|
||||
amplitude_(amplitude), time_(0.f), initialized_(false)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ class MoveToCallback : public UpdateCallback
|
||||
{
|
||||
float duration_;
|
||||
float progress_;
|
||||
bool initialized_;
|
||||
bool initialized_;
|
||||
glm::vec3 startingpoint_;
|
||||
glm::vec3 target_;
|
||||
|
||||
@@ -37,11 +37,26 @@ public:
|
||||
inline void reset() { initialized_ = false; }
|
||||
};
|
||||
|
||||
class RotateToCallback : public UpdateCallback
|
||||
{
|
||||
float duration_;
|
||||
float progress_;
|
||||
bool initialized_;
|
||||
float startingangle_;
|
||||
float target_;
|
||||
|
||||
public:
|
||||
RotateToCallback(float target, float speed = 1000.f);
|
||||
void update(Node *n, float dt);
|
||||
|
||||
inline void reset() { initialized_ = false; }
|
||||
};
|
||||
|
||||
class BounceScaleCallback : public UpdateCallback
|
||||
{
|
||||
float duration_;
|
||||
float progress_;
|
||||
bool initialized_;
|
||||
bool initialized_;
|
||||
glm::vec3 initial_scale_;
|
||||
|
||||
public:
|
||||
@@ -53,7 +68,7 @@ class InfiniteGlowCallback : public UpdateCallback
|
||||
{
|
||||
float amplitude_;
|
||||
float time_;
|
||||
bool initialized_;
|
||||
bool initialized_;
|
||||
glm::vec3 initial_scale_;
|
||||
|
||||
public:
|
||||
|
||||
158
View.cpp
158
View.cpp
@@ -99,12 +99,10 @@ std::pair<Node *, glm::vec2> View::pick(glm::vec2 P)
|
||||
|
||||
// picking visitor found nodes?
|
||||
if ( !pv.picked().empty()) {
|
||||
|
||||
// select top-most Node picked
|
||||
pick = pv.picked().back();
|
||||
|
||||
Log::Info("picked %d", pick.first->id());
|
||||
}
|
||||
|
||||
return pick;
|
||||
}
|
||||
|
||||
@@ -236,16 +234,35 @@ MixingView::MixingView() : View(MIXING), limbo_scale_(1.3f)
|
||||
mixingCircle_->shader()->color = glm::vec4( 1.f, 1.f, 1.f, 1.f );
|
||||
scene.bg()->attach(mixingCircle_);
|
||||
|
||||
Symbol *dot = new Symbol(Symbol::POINT, glm::vec3(0.f, 1.f, 0.1f));
|
||||
dot->scale_ = glm::vec3( 0.33f, 0.33f, 1.f);
|
||||
dot->color = glm::vec4( COLOR_FRAME, 1.f );
|
||||
scene.bg()->attach(dot);
|
||||
|
||||
tmp = new Mesh("mesh/circle.ply");
|
||||
tmp->shader()->color = glm::vec4( COLOR_FRAME, 0.9f );
|
||||
scene.bg()->attach(tmp);
|
||||
|
||||
// Mixing scene foreground
|
||||
tmp = new Mesh("mesh/disk.ply");
|
||||
tmp->scale_ = glm::vec3(0.033f, 0.033f, 1.f);
|
||||
tmp->translation_ = glm::vec3(0.f, 1.f, 0.f);
|
||||
tmp->shader()->color = glm::vec4( COLOR_FRAME, 0.9f );
|
||||
scene.fg()->attach(tmp);
|
||||
|
||||
button_white_ = new Disk();
|
||||
button_white_->scale_ = glm::vec3(0.026f, 0.026f, 1.f);
|
||||
button_white_->translation_ = glm::vec3(0.f, 1.f, 0.f);
|
||||
button_white_->color = glm::vec4( 0.85f, 0.85f, 0.85f, 1.0f );
|
||||
scene.fg()->attach(button_white_);
|
||||
|
||||
tmp = new Mesh("mesh/disk.ply");
|
||||
tmp->scale_ = glm::vec3(0.033f, 0.033f, 1.f);
|
||||
tmp->translation_ = glm::vec3(0.f, -1.f, 0.f);
|
||||
tmp->shader()->color = glm::vec4( COLOR_FRAME, 0.9f );
|
||||
scene.fg()->attach(tmp);
|
||||
|
||||
button_black_ = new Disk();
|
||||
button_black_->scale_ = glm::vec3(0.026f, 0.026f, 1.f);
|
||||
button_black_->translation_ = glm::vec3(0.f, -1.f, 0.f);
|
||||
button_black_->color = glm::vec4( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
scene.fg()->attach(button_black_);
|
||||
|
||||
slider_root_ = new Group;
|
||||
scene.fg()->attach(slider_root_);
|
||||
|
||||
@@ -308,20 +325,72 @@ void MixingView::update(float dt)
|
||||
View::update(dt);
|
||||
|
||||
// a more complete update is requested
|
||||
// for mixing, this means restore position of the fading slider
|
||||
if (View::need_deep_update_) {
|
||||
|
||||
// reverse calculate angle from fading
|
||||
//
|
||||
// Set slider to match the actual fading of the session
|
||||
//
|
||||
float f = Mixer::manager().session()->fading();
|
||||
float angle = SIGN(slider_root_->rotation_.z) * asin(f) * 2.f;
|
||||
// move slider
|
||||
slider_root_->rotation_.z = angle;
|
||||
|
||||
// reverse calculate angle from fading & move slider
|
||||
slider_root_->rotation_.z = SIGN(slider_root_->rotation_.z) * asin(f) * 2.f;
|
||||
|
||||
// visual feedback on mixing circle
|
||||
f = 1.f - f;
|
||||
mixingCircle_->shader()->color = glm::vec4(f, f, f, 1.f);
|
||||
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Set session fading to match the slider angle
|
||||
//
|
||||
|
||||
// calculate fading from angle
|
||||
float f = sin( ABS(slider_root_->rotation_.z) * 0.5f);
|
||||
|
||||
// apply fading
|
||||
if ( ABS_DIFF( f, Mixer::manager().session()->fading()) > EPSILON )
|
||||
{
|
||||
// apply fading to session
|
||||
Mixer::manager().session()->setFading(f);
|
||||
|
||||
// visual feedback on mixing circle
|
||||
f = 1.f - f;
|
||||
mixingCircle_->shader()->color = glm::vec4(f, f, f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::pair<Node *, glm::vec2> MixingView::pick(glm::vec2 P)
|
||||
{
|
||||
// get picking from generic View
|
||||
std::pair<Node *, glm::vec2> pick = View::pick(P);
|
||||
|
||||
// deal with internal interactive objects and do not forward
|
||||
if ( pick.first == button_white_ || pick.first == button_black_ ) {
|
||||
|
||||
RotateToCallback *anim = nullptr;
|
||||
if (pick.first == button_white_)
|
||||
anim = new RotateToCallback(0.f, 500.f);
|
||||
else
|
||||
anim = new RotateToCallback(SIGN(slider_root_->rotation_.z) * M_PI, 500.f);
|
||||
|
||||
// reset & start animation
|
||||
slider_root_->update_callbacks_.clear();
|
||||
slider_root_->update_callbacks_.push_back(anim);
|
||||
|
||||
// capture this pick
|
||||
pick = { nullptr, glm::vec2(0.f) };
|
||||
}
|
||||
|
||||
return pick;
|
||||
}
|
||||
|
||||
|
||||
|
||||
View::Cursor MixingView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick)
|
||||
{
|
||||
// unproject
|
||||
@@ -344,21 +413,11 @@ View::Cursor MixingView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pai
|
||||
angle = M_PI;
|
||||
|
||||
// animate slider (rotation angle on its parent)
|
||||
slider_root_->rotation_.z = angle;
|
||||
|
||||
// calculate fading from angle
|
||||
float fading = sin( ABS(angle) * 0.5f);
|
||||
|
||||
// apply fading to session
|
||||
Mixer::manager().session()->setFading(fading);
|
||||
|
||||
// visual feedback on mixing circle
|
||||
fading = 1.f - fading;
|
||||
mixingCircle_->shader()->color = glm::vec4(fading, fading, fading, 1.f);
|
||||
slider_root_->rotation_.z = angle;
|
||||
|
||||
// cursor feedback
|
||||
std::ostringstream info;
|
||||
info << "Global opacity " << int(fading * 100.0) << " %";
|
||||
info << "Global opacity " << 100 - int(Mixer::manager().session()->fading() * 100.0) << " %";
|
||||
return Cursor(Cursor_Hand, info.str() );
|
||||
}
|
||||
|
||||
@@ -980,6 +1039,23 @@ TransitionView::TransitionView() : View(TRANSITION), transition_source_(nullptr)
|
||||
|
||||
void TransitionView::update(float dt)
|
||||
{
|
||||
// update scene
|
||||
View::update(dt);
|
||||
|
||||
// a more complete update is requested
|
||||
if (View::need_deep_update_) {
|
||||
|
||||
// update rendering of render frame
|
||||
FrameBuffer *output = Mixer::manager().session()->frame();
|
||||
if (output){
|
||||
float aspect_ratio = output->aspectRatio();
|
||||
for (NodeSet::iterator node = scene.bg()->begin(); node != scene.bg()->end(); node++) {
|
||||
(*node)->scale_.x = aspect_ratio;
|
||||
}
|
||||
output_surface_->setTextureIndex( output->texture() );
|
||||
}
|
||||
}
|
||||
|
||||
// Update transition source
|
||||
if ( transition_source_ != nullptr) {
|
||||
|
||||
@@ -1001,8 +1077,6 @@ void TransitionView::update(float dt)
|
||||
transition_source_->group(View::MIXING)->translation_.x = CLAMP(f, -1.f, 0.f);
|
||||
transition_source_->group(View::MIXING)->translation_.y = 0.f;
|
||||
|
||||
// reset / no fading
|
||||
Mixer::manager().session()->setFading( 0.f );
|
||||
}
|
||||
// fade to black
|
||||
else
|
||||
@@ -1016,7 +1090,7 @@ void TransitionView::update(float dt)
|
||||
if (Settings::application.transition.profile == 0)
|
||||
f = ABS(2.f * d + 1.f); // linear
|
||||
else {
|
||||
f = ( 2 * d + 1.f); // quadratic
|
||||
f = ( 2.f * d + 1.f); // quadratic
|
||||
f *= f;
|
||||
}
|
||||
Mixer::manager().session()->setFading( 1.f - f );
|
||||
@@ -1030,22 +1104,6 @@ void TransitionView::update(float dt)
|
||||
|
||||
}
|
||||
|
||||
// update scene
|
||||
View::update(dt);
|
||||
|
||||
// a more complete update is requested
|
||||
if (View::need_deep_update_) {
|
||||
|
||||
// update rendering of render frame
|
||||
FrameBuffer *output = Mixer::manager().session()->frame();
|
||||
if (output){
|
||||
float aspect_ratio = output->aspectRatio();
|
||||
for (NodeSet::iterator node = scene.bg()->begin(); node != scene.bg()->end(); node++) {
|
||||
(*node)->scale_.x = aspect_ratio;
|
||||
}
|
||||
output_surface_->setTextureIndex( output->texture() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1108,6 +1166,20 @@ void TransitionView::attach(SessionSource *ts)
|
||||
Group *tg = transition_source_->group(View::TRANSITION);
|
||||
tg->visible_ = true;
|
||||
scene.ws()->attach(tg);
|
||||
|
||||
// in fade to black transition, start transition from current fading value
|
||||
if ( !Settings::application.transition.cross_fade) {
|
||||
|
||||
// reverse calculate x position to match actual vading of session
|
||||
float d = 0.f;
|
||||
if (Settings::application.transition.profile == 0)
|
||||
d = -1.f + 0.5f * Mixer::manager().session()->fading(); // linear
|
||||
else {
|
||||
d = -1.f - 0.5f * ( sqrt(1.f - Mixer::manager().session()->fading()) - 1.f); // quadratic
|
||||
}
|
||||
|
||||
transition_source_->group(View::TRANSITION)->translation_.x = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
View.h
4
View.h
@@ -93,19 +93,21 @@ public:
|
||||
void centerSource(Source *) override;
|
||||
void selectAll() override;
|
||||
|
||||
std::pair<Node *, glm::vec2> pick(glm::vec2) override;
|
||||
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2>) override;
|
||||
Cursor drag (glm::vec2, glm::vec2) override;
|
||||
|
||||
void setAlpha (Source *s);
|
||||
inline float limboScale() { return limbo_scale_; }
|
||||
|
||||
|
||||
private:
|
||||
uint textureMixingQuadratic();
|
||||
float limbo_scale_;
|
||||
|
||||
Group *slider_root_;
|
||||
class Disk *slider_;
|
||||
class Disk *button_white_;
|
||||
class Disk *button_black_;
|
||||
class Mesh *mixingCircle_;
|
||||
};
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
#define IMGUI_TITLE_MAINWINDOW ICON_FA_CIRCLE_NOTCH " vimix"
|
||||
#define IMGUI_TITLE_MEDIAPLAYER ICON_FA_FILM " Player"
|
||||
#define IMGUI_TITLE_TOOLBOX ICON_FA_WRENCH " Tools"
|
||||
#define IMGUI_TITLE_TOOLBOX ICON_FA_WRENCH " Development Tools"
|
||||
#define IMGUI_TITLE_SHADEREDITOR ICON_FA_CODE " Shader Editor"
|
||||
#define IMGUI_TITLE_PREVIEW ICON_FA_DESKTOP " Ouput"
|
||||
#define IMGUI_TITLE_DELETE ICON_FA_BROOM " Delete?"
|
||||
|
||||
Reference in New Issue
Block a user