Improved vimix first launch (or after upgrade)

Changed Mixer Load behavior at init, detect change of version and do not load settings if different, show About Vimix after change of version, fixed initial position of windows at first run.
This commit is contained in:
Bruno Herbelin
2024-01-28 12:26:05 +01:00
parent fcce9b62d5
commit 2f8411a658
7 changed files with 292 additions and 267 deletions

View File

@@ -671,7 +671,7 @@ void InputMappingWindow::Render()
const float fixed_height = keyLetterItemSize.y * 5.f + g.Style.WindowBorderSize + g.FontSize + g.Style.FramePadding.y * 2.0f + keyItemSpacing.y; const float fixed_height = keyLetterItemSize.y * 5.f + g.Style.WindowBorderSize + g.FontSize + g.Style.FramePadding.y * 2.0f + keyItemSpacing.y;
const float inputarea_width = keyLetterItemSize.x * 5.f; const float inputarea_width = keyLetterItemSize.x * 5.f;
ImGui::SetNextWindowPos(ImVec2(600, 400), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(530, 600), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(1000, fixed_height), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(1000, fixed_height), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(900, fixed_height), ImVec2(FLT_MAX, fixed_height)); ImGui::SetNextWindowSizeConstraints(ImVec2(900, fixed_height), ImVec2(FLT_MAX, fixed_height));

View File

@@ -69,7 +69,7 @@ struct AppLog
void Draw(const char* title, bool* p_open = NULL) void Draw(const char* title, bool* p_open = NULL)
{ {
ImGui::SetNextWindowPos(ImVec2(430, 660), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(440, 700), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(1150, 220), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(1150, 220), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(600, 180), ImVec2(FLT_MAX, FLT_MAX)); ImGui::SetNextWindowSizeConstraints(ImVec2(600, 180), ImVec2(FLT_MAX, FLT_MAX));
@@ -196,7 +196,6 @@ void Log::Info(const char* fmt, ...)
void Log::ShowLogWindow(bool* p_open) void Log::ShowLogWindow(bool* p_open)
{ {
ImGui::SetNextWindowSize(ImVec2(700, 600), ImGuiCond_FirstUseEver);
logs.Draw( IMGUI_TITLE_LOGS, p_open); logs.Draw( IMGUI_TITLE_LOGS, p_open);
} }

View File

@@ -73,24 +73,12 @@ Mixer::Mixer() : session_(nullptr), back_session_(nullptr), sessionSwapRequested
current_view_(nullptr), busy_(false), dt_(16.f), dt__(16.f) current_view_(nullptr), busy_(false), dt_(16.f), dt__(16.f)
{ {
// unsused initial empty session // unsused initial empty session
session_ = new Session;
current_source_ = session_->end(); current_source_ = session_->end();
current_source_index_ = -1; current_source_index_ = -1;
// auto load if Settings ask to // initialize with a new empty session
if ( Settings::application.recentSessions.load_at_start && clear();
Settings::application.recentSessions.front_is_valid && setView( View::MIXING );
Settings::application.recentSessions.filenames.size() > 0 &&
Settings::application.fresh_start) {
load( Settings::application.recentSessions.filenames.front() );
// initialize with the current view
setView( (View::Mode) Settings::application.current_view );
}
else {
// initialize with a new empty session
clear();
setView( View::MIXING );
}
} }
void Mixer::update() void Mixer::update()
@@ -1236,12 +1224,14 @@ void Mixer::setView(View::Mode m)
Settings::application.current_view = (int) m; Settings::application.current_view = (int) m;
// selection might have to change // selection might have to change
for (auto sit = session_->begin(); sit != session_->end(); ++sit) { if (session_) {
Source *s = *sit; for (auto sit = session_->begin(); sit != session_->end(); ++sit) {
if ( s != nullptr && !current_view_->canSelect( s ) ) { Source *s = *sit;
if ( s == *current_source_ ) if ( s != nullptr && !current_view_->canSelect( s ) ) {
unsetCurrentSource(); if ( s == *current_source_ )
Mixer::selection().remove( s ); unsetCurrentSource();
Mixer::selection().remove( s );
}
} }
} }
@@ -1299,8 +1289,22 @@ void Mixer::saveas(const std::string& filename, bool with_version)
void Mixer::load(const std::string& filename) void Mixer::load(const std::string& filename)
{ {
if (filename.empty()) std::string sessionfile = filename;
// given an empty filename, try to revert to recent file according to user settings
if (filename.empty() && Settings::application.recentSessions.load_at_start
&& Settings::application.recentSessions.front_is_valid
&& Settings::application.recentSessions.filenames.size() > 0) {
sessionfile = Settings::application.recentSessions.filenames.front();
setView((View::Mode) Settings::application.current_view);
}
// ignore invalid file name
if (!SystemToolkit::file_exists(sessionfile)) {
if (!sessionfile.empty())
Log::Notify("Invalid filename '%s'", sessionfile.c_str());
return; return;
}
#ifdef THREADED_LOADING #ifdef THREADED_LOADING
// load only one at a time // load only one at a time
@@ -1308,7 +1312,7 @@ void Mixer::load(const std::string& filename)
busy_ = true; busy_ = true;
// Start async thread for loading the session // Start async thread for loading the session
// Will be obtained in the future in update() // Will be obtained in the future in update()
sessionLoaders_.emplace_back( std::async(std::launch::async, Session::load, filename, 0) ); sessionLoaders_.emplace_back( std::async(std::launch::async, Session::load, sessionfile, 0) );
} }
#else #else
set( Session::load(filename) ); set( Session::load(filename) );
@@ -1548,9 +1552,14 @@ void Mixer::swap()
Action::manager().init(); Action::manager().init();
// notification // notification
uint N = session_->size(); if (session_->filename().empty())
std::string numsource = ( N>0 ? std::to_string(N) : "no" ) + " source" + (N>1 ? "s" : ""); Log::Info("New session ready.");
Log::Notify("Session '%s' loaded with %s.", session_->filename().c_str(), numsource.c_str()); else {
uint N = session_->size();
std::string numsource = ( N>0 ? std::to_string(N) : "no" ) + " source" + (N>1 ? "s" : "");
Log::Notify("Session '%s' loaded with %s.", session_->filename().c_str(), numsource.c_str());
}
} }
void Mixer::close(bool smooth) void Mixer::close(bool smooth)
@@ -1568,6 +1577,9 @@ void Mixer::close(bool smooth)
} }
else else
clear(); clear();
// closing session : filename at font in history should not be reloaded
Settings::application.recentSessions.front_is_valid = false;
} }
void Mixer::clear() void Mixer::clear()
@@ -1584,9 +1596,6 @@ void Mixer::clear()
// need to deeply update view to apply eventual changes // need to deeply update view to apply eventual changes
++View::need_deep_update_; ++View::need_deep_update_;
Settings::application.recentSessions.front_is_valid = false;
Log::Info("New session ready.");
} }
void Mixer::set(Session *s) void Mixer::set(Session *s)

View File

@@ -83,10 +83,11 @@ void Settings::Save(uint64_t runtime)
#ifdef VIMIX_VERSION_MAJOR #ifdef VIMIX_VERSION_MAJOR
pRoot->SetAttribute("major", VIMIX_VERSION_MAJOR); pRoot->SetAttribute("major", VIMIX_VERSION_MAJOR);
pRoot->SetAttribute("minor", VIMIX_VERSION_MINOR); pRoot->SetAttribute("minor", VIMIX_VERSION_MINOR);
pRoot->SetAttribute("patch", VIMIX_VERSION_PATCH);
#endif #endif
// runtime // runtime
if (runtime>0) pRoot->SetAttribute("runtime", runtime + application.total_runtime);
pRoot->SetAttribute("runtime", runtime + application.total_runtime);
string comment = "Settings for " + application.name; string comment = "Settings for " + application.name;
XMLComment *pComment = xmlDoc.NewComment(comment.c_str()); XMLComment *pComment = xmlDoc.NewComment(comment.c_str());
@@ -414,243 +415,279 @@ void Settings::Load()
else if (XMLResultError(eResult)) else if (XMLResultError(eResult))
return; return;
// first element should be called by the application name // first element should be called by the application name
XMLElement *pRoot = xmlDoc.FirstChildElement(application.name.c_str()); XMLElement *pRoot = xmlDoc.FirstChildElement(application.name.c_str());
if (pRoot == nullptr) if (pRoot == nullptr)
return; return;
// runtime
pRoot->QueryUnsigned64Attribute("runtime", &application.total_runtime);
// General application preferences // version
XMLElement * applicationNode = pRoot->FirstChildElement("Application"); int major, minor, patch;
if (applicationNode != nullptr) { pRoot->QueryIntAttribute("major", &major);
applicationNode->QueryFloatAttribute("scale", &application.scale); pRoot->QueryIntAttribute("minor", &minor);
applicationNode->QueryIntAttribute("accent_color", &application.accent_color); pRoot->QueryIntAttribute("patch", &patch);
applicationNode->QueryBoolAttribute("smooth_transition", &application.smooth_transition); bool version_same = (major == VIMIX_VERSION_MAJOR)
applicationNode->QueryBoolAttribute("save_snapshot", &application.save_version_snapshot); && (minor == VIMIX_VERSION_MINOR)
applicationNode->QueryBoolAttribute("action_history_follow_view", &application.action_history_follow_view); && (patch == VIMIX_VERSION_PATCH);
applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips);
applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);
applicationNode->QueryBoolAttribute("pannel_always_visible", &application.pannel_always_visible);
applicationNode->QueryIntAttribute("pannel_main_mode", &application.pannel_main_mode);
applicationNode->QueryIntAttribute("pannel_playlist_mode", &application.pannel_playlist_mode);
applicationNode->QueryIntAttribute("pannel_history_mode", &application.pannel_current_session_mode);
applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol);
applicationNode->QueryIntAttribute("broadcast_port", &application.broadcast_port);
applicationNode->QueryIntAttribute("loopback_camera", &application.loopback_camera);
applicationNode->QueryBoolAttribute("accept_audio", &application.accept_audio);
// text attributes //
const char *tmpstr = applicationNode->Attribute("shm_socket_path"); // Restore settings only if version is same
if (tmpstr) //
application.shm_socket_path = std::string(tmpstr); if (version_same) {
}
// Widgets // runtime
XMLElement * widgetsNode = pRoot->FirstChildElement("Widgets"); pRoot->QueryUnsigned64Attribute("runtime", &application.total_runtime);
if (widgetsNode != nullptr) {
widgetsNode->QueryBoolAttribute("preview", &application.widget.preview);
widgetsNode->QueryIntAttribute("preview_view", &application.widget.preview_view);
widgetsNode->QueryBoolAttribute("timer", &application.widget.timer);
widgetsNode->QueryIntAttribute("timer_view", &application.widget.timer_view);
widgetsNode->QueryBoolAttribute("inputs", &application.widget.inputs);
widgetsNode->QueryIntAttribute("inputs_view", &application.widget.inputs_view);
widgetsNode->QueryBoolAttribute("media_player", &application.widget.media_player);
widgetsNode->QueryIntAttribute("media_player_view", &application.widget.media_player_view);
widgetsNode->QueryBoolAttribute("timeline_editmode", &application.widget.media_player_timeline_editmode);
widgetsNode->QueryFloatAttribute("media_player_slider", &application.widget.media_player_slider);
widgetsNode->QueryBoolAttribute("shader_editor", &application.widget.shader_editor);
widgetsNode->QueryIntAttribute("shader_editor_view", &application.widget.shader_editor_view);
widgetsNode->QueryBoolAttribute("stats", &application.widget.stats);
widgetsNode->QueryIntAttribute("stats_mode", &application.widget.stats_mode);
widgetsNode->QueryIntAttribute("stats_corner", &application.widget.stats_corner);
widgetsNode->QueryBoolAttribute("logs", &application.widget.logs);
widgetsNode->QueryBoolAttribute("toolbox", &application.widget.toolbox);
widgetsNode->QueryBoolAttribute("source_toolbar", &application.widget.source_toolbar);
widgetsNode->QueryIntAttribute("source_toolbar_mode", &application.widget.source_toolbar_mode);
widgetsNode->QueryIntAttribute("source_toolbar_border", &application.widget.source_toolbar_border);
}
// Render // General application preferences
XMLElement * rendernode = pRoot->FirstChildElement("Render"); XMLElement * applicationNode = pRoot->FirstChildElement("Application");
if (rendernode != nullptr) { if (applicationNode != nullptr) {
rendernode->QueryIntAttribute("vsync", &application.render.vsync); applicationNode->QueryFloatAttribute("scale", &application.scale);
rendernode->QueryIntAttribute("multisampling", &application.render.multisampling); applicationNode->QueryIntAttribute("accent_color", &application.accent_color);
rendernode->QueryBoolAttribute("gpu_decoding", &application.render.gpu_decoding); applicationNode->QueryBoolAttribute("smooth_transition", &application.smooth_transition);
rendernode->QueryIntAttribute("ratio", &application.render.ratio); applicationNode->QueryBoolAttribute("save_snapshot", &application.save_version_snapshot);
rendernode->QueryIntAttribute("res", &application.render.res); applicationNode->QueryBoolAttribute("action_history_follow_view", &application.action_history_follow_view);
rendernode->QueryIntAttribute("custom_width", &application.render.custom_width); applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips);
rendernode->QueryIntAttribute("custom_height", &application.render.custom_height); applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);
} applicationNode->QueryBoolAttribute("pannel_always_visible", &application.pannel_always_visible);
applicationNode->QueryIntAttribute("pannel_main_mode", &application.pannel_main_mode);
applicationNode->QueryIntAttribute("pannel_playlist_mode", &application.pannel_playlist_mode);
applicationNode->QueryIntAttribute("pannel_history_mode", &application.pannel_current_session_mode);
applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol);
applicationNode->QueryIntAttribute("broadcast_port", &application.broadcast_port);
applicationNode->QueryIntAttribute("loopback_camera", &application.loopback_camera);
applicationNode->QueryBoolAttribute("accept_audio", &application.accept_audio);
// Record // text attributes
XMLElement * recordnode = pRoot->FirstChildElement("Record"); const char *tmpstr = applicationNode->Attribute("shm_socket_path");
if (recordnode != nullptr) { if (tmpstr)
recordnode->QueryIntAttribute("profile", &application.record.profile); application.shm_socket_path = std::string(tmpstr);
recordnode->QueryUnsignedAttribute("timeout", &application.record.timeout); }
recordnode->QueryIntAttribute("delay", &application.record.delay);
recordnode->QueryIntAttribute("resolution_mode", &application.record.resolution_mode);
recordnode->QueryIntAttribute("framerate_mode", &application.record.framerate_mode);
recordnode->QueryIntAttribute("buffering_mode", &application.record.buffering_mode);
recordnode->QueryIntAttribute("priority_mode", &application.record.priority_mode);
recordnode->QueryIntAttribute("naming_mode", &application.record.naming_mode);
const char *path_ = recordnode->Attribute("path"); // Widgets
if (path_) XMLElement * widgetsNode = pRoot->FirstChildElement("Widgets");
application.record.path = std::string(path_); if (widgetsNode != nullptr) {
else widgetsNode->QueryBoolAttribute("preview", &application.widget.preview);
application.record.path = SystemToolkit::home_path(); widgetsNode->QueryIntAttribute("preview_view", &application.widget.preview_view);
widgetsNode->QueryBoolAttribute("timer", &application.widget.timer);
widgetsNode->QueryIntAttribute("timer_view", &application.widget.timer_view);
widgetsNode->QueryBoolAttribute("inputs", &application.widget.inputs);
widgetsNode->QueryIntAttribute("inputs_view", &application.widget.inputs_view);
widgetsNode->QueryBoolAttribute("media_player", &application.widget.media_player);
widgetsNode->QueryIntAttribute("media_player_view", &application.widget.media_player_view);
widgetsNode->QueryBoolAttribute("timeline_editmode", &application.widget.media_player_timeline_editmode);
widgetsNode->QueryFloatAttribute("media_player_slider", &application.widget.media_player_slider);
widgetsNode->QueryBoolAttribute("shader_editor", &application.widget.shader_editor);
widgetsNode->QueryIntAttribute("shader_editor_view", &application.widget.shader_editor_view);
widgetsNode->QueryBoolAttribute("stats", &application.widget.stats);
widgetsNode->QueryIntAttribute("stats_mode", &application.widget.stats_mode);
widgetsNode->QueryIntAttribute("stats_corner", &application.widget.stats_corner);
widgetsNode->QueryBoolAttribute("logs", &application.widget.logs);
widgetsNode->QueryBoolAttribute("toolbox", &application.widget.toolbox);
widgetsNode->QueryBoolAttribute("source_toolbar", &application.widget.source_toolbar);
widgetsNode->QueryIntAttribute("source_toolbar_mode", &application.widget.source_toolbar_mode);
widgetsNode->QueryIntAttribute("source_toolbar_border", &application.widget.source_toolbar_border);
}
const char *dev_ = recordnode->Attribute("audio_device"); // Render
if (dev_) XMLElement * rendernode = pRoot->FirstChildElement("Render");
application.record.audio_device = std::string(dev_); if (rendernode != nullptr) {
else rendernode->QueryIntAttribute("vsync", &application.render.vsync);
application.record.audio_device = ""; rendernode->QueryIntAttribute("multisampling", &application.render.multisampling);
} rendernode->QueryBoolAttribute("gpu_decoding", &application.render.gpu_decoding);
rendernode->QueryIntAttribute("ratio", &application.render.ratio);
rendernode->QueryIntAttribute("res", &application.render.res);
rendernode->QueryIntAttribute("custom_width", &application.render.custom_width);
rendernode->QueryIntAttribute("custom_height", &application.render.custom_height);
}
// Source // Record
XMLElement * sourceconfnode = pRoot->FirstChildElement("Source"); XMLElement * recordnode = pRoot->FirstChildElement("Record");
if (sourceconfnode != nullptr) { if (recordnode != nullptr) {
sourceconfnode->QueryIntAttribute("new_type", &application.source.new_type); recordnode->QueryIntAttribute("profile", &application.record.profile);
sourceconfnode->QueryIntAttribute("ratio", &application.source.ratio); recordnode->QueryUnsignedAttribute("timeout", &application.record.timeout);
sourceconfnode->QueryIntAttribute("res", &application.source.res); recordnode->QueryIntAttribute("delay", &application.record.delay);
recordnode->QueryIntAttribute("resolution_mode", &application.record.resolution_mode);
recordnode->QueryIntAttribute("framerate_mode", &application.record.framerate_mode);
recordnode->QueryIntAttribute("buffering_mode", &application.record.buffering_mode);
recordnode->QueryIntAttribute("priority_mode", &application.record.priority_mode);
recordnode->QueryIntAttribute("naming_mode", &application.record.naming_mode);
sourceconfnode->QueryIntAttribute("capture_naming", &application.source.capture_naming); const char *path_ = recordnode->Attribute("path");
const char *path_ = sourceconfnode->Attribute("capture_path"); if (path_)
if (path_) application.record.path = std::string(path_);
application.source.capture_path = std::string(path_); else
else application.record.path = SystemToolkit::home_path();
application.source.capture_path = SystemToolkit::home_path();
sourceconfnode->QueryFloatAttribute("inspector_zoom", &application.source.inspector_zoom);
}
// Transition const char *dev_ = recordnode->Attribute("audio_device");
XMLElement * transitionnode = pRoot->FirstChildElement("Transition"); if (dev_)
if (transitionnode != nullptr) { application.record.audio_device = std::string(dev_);
transitionnode->QueryBoolAttribute("cross_fade", &application.transition.cross_fade); else
transitionnode->QueryFloatAttribute("duration", &application.transition.duration); application.record.audio_device = "";
transitionnode->QueryIntAttribute("profile", &application.transition.profile); }
}
// Windows // Source
{ XMLElement * sourceconfnode = pRoot->FirstChildElement("Source");
XMLElement * pElement = pRoot->FirstChildElement("OutputWindows"); if (sourceconfnode != nullptr) {
if (pElement) sourceconfnode->QueryIntAttribute("new_type", &application.source.new_type);
sourceconfnode->QueryIntAttribute("ratio", &application.source.ratio);
sourceconfnode->QueryIntAttribute("res", &application.source.res);
sourceconfnode->QueryIntAttribute("capture_naming", &application.source.capture_naming);
const char *path_ = sourceconfnode->Attribute("capture_path");
if (path_)
application.source.capture_path = std::string(path_);
else
application.source.capture_path = SystemToolkit::home_path();
sourceconfnode->QueryFloatAttribute("inspector_zoom", &application.source.inspector_zoom);
}
// Transition
XMLElement * transitionnode = pRoot->FirstChildElement("Transition");
if (transitionnode != nullptr) {
transitionnode->QueryBoolAttribute("cross_fade", &application.transition.cross_fade);
transitionnode->QueryFloatAttribute("duration", &application.transition.duration);
transitionnode->QueryIntAttribute("profile", &application.transition.profile);
}
// Windows
{ {
pElement->QueryIntAttribute("num_output_windows", &application.num_output_windows); XMLElement * pElement = pRoot->FirstChildElement("OutputWindows");
if (pElement)
XMLElement* windowNode = pElement->FirstChildElement("Window");
for( ; windowNode ; windowNode=windowNode->NextSiblingElement())
{ {
Settings::WindowConfig w; pElement->QueryIntAttribute("num_output_windows", &application.num_output_windows);
windowNode->QueryIntAttribute("x", &w.x); // If this fails, original value is left as-is
windowNode->QueryIntAttribute("y", &w.y);
windowNode->QueryIntAttribute("w", &w.w);
windowNode->QueryIntAttribute("h", &w.h);
windowNode->QueryBoolAttribute("f", &w.fullscreen);
windowNode->QueryBoolAttribute("s", &w.custom);
windowNode->QueryBoolAttribute("d", &w.decorated);
const char *text = windowNode->Attribute("m");
if (text)
w.monitor = std::string(text);
int i = 0; XMLElement* windowNode = pElement->FirstChildElement("Window");
windowNode->QueryIntAttribute("id", &i); for( ; windowNode ; windowNode=windowNode->NextSiblingElement())
if (i > 0) {
w.name = "Output " + std::to_string(i) + " - " APP_NAME; Settings::WindowConfig w;
else windowNode->QueryIntAttribute("x", &w.x); // If this fails, original value is left as-is
w.name = APP_TITLE; windowNode->QueryIntAttribute("y", &w.y);
// vec4 values for white balance correction windowNode->QueryIntAttribute("w", &w.w);
XMLElement *tmp = windowNode->FirstChildElement("whitebalance"); windowNode->QueryIntAttribute("h", &w.h);
if (tmp) windowNode->QueryBoolAttribute("f", &w.fullscreen);
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("vec4"), w.whitebalance); windowNode->QueryBoolAttribute("s", &w.custom);
// mat4 values for custom fit distortion windowNode->QueryBoolAttribute("d", &w.decorated);
w.nodes = glm::zero<glm::mat4>(); const char *text = windowNode->Attribute("m");
tmp = windowNode->FirstChildElement("nodes"); if (text)
if (tmp) w.monitor = std::string(text);
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("mat4"), w.nodes);
else { int i = 0;
// backward compatibility windowNode->QueryIntAttribute("id", &i);
glm::vec3 scale, translation; if (i > 0)
tmp = windowNode->FirstChildElement("scale"); w.name = "Output " + std::to_string(i) + " - " APP_NAME;
if (tmp) { else
tinyxml2::XMLElementToGLM(tmp->FirstChildElement("vec3"), scale); w.name = APP_TITLE;
tmp = windowNode->FirstChildElement("translation"); // vec4 values for white balance correction
XMLElement *tmp = windowNode->FirstChildElement("whitebalance");
if (tmp)
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("vec4"), w.whitebalance);
// mat4 values for custom fit distortion
w.nodes = glm::zero<glm::mat4>();
tmp = windowNode->FirstChildElement("nodes");
if (tmp)
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("mat4"), w.nodes);
else {
// backward compatibility
glm::vec3 scale, translation;
tmp = windowNode->FirstChildElement("scale");
if (tmp) { if (tmp) {
tinyxml2::XMLElementToGLM(tmp->FirstChildElement("vec3"), translation); tinyxml2::XMLElementToGLM(tmp->FirstChildElement("vec3"), scale);
// calculate nodes with scale and translation tmp = windowNode->FirstChildElement("translation");
w.nodes[0].x = 1.f - ( 1.f * scale.x - translation.x ); if (tmp) {
w.nodes[0].y = 1.f - ( 1.f * scale.y - translation.y ); tinyxml2::XMLElementToGLM(tmp->FirstChildElement("vec3"), translation);
w.nodes[1].x = 1.f - ( 1.f * scale.x - translation.x ); // calculate nodes with scale and translation
w.nodes[1].y = -1.f - (-1.f * scale.y - translation.y ); w.nodes[0].x = 1.f - ( 1.f * scale.x - translation.x );
w.nodes[2].x = -1.f - (-1.f * scale.x - translation.x ); w.nodes[0].y = 1.f - ( 1.f * scale.y - translation.y );
w.nodes[2].y = 1.f - ( 1.f * scale.y - translation.y ); w.nodes[1].x = 1.f - ( 1.f * scale.x - translation.x );
w.nodes[3].x = -1.f - (-1.f * scale.x - translation.x ); w.nodes[1].y = -1.f - (-1.f * scale.y - translation.y );
w.nodes[3].y = -1.f - (-1.f * scale.y - translation.y ); w.nodes[2].x = -1.f - (-1.f * scale.x - translation.x );
w.nodes[2].y = 1.f - ( 1.f * scale.y - translation.y );
w.nodes[3].x = -1.f - (-1.f * scale.x - translation.x );
w.nodes[3].y = -1.f - (-1.f * scale.y - translation.y );
}
} }
} }
application.windows[i] = w;
} }
application.windows[i] = w;
} }
} }
}
// Brush // Brush
XMLElement * brushnode = pRoot->FirstChildElement("Brush"); XMLElement * brushnode = pRoot->FirstChildElement("Brush");
if (brushnode != nullptr) { if (brushnode != nullptr) {
tinyxml2::XMLElementToGLM( brushnode->FirstChildElement("vec3"), application.brush); tinyxml2::XMLElementToGLM( brushnode->FirstChildElement("vec3"), application.brush);
}
// Pointer
XMLElement * pointernode = pRoot->FirstChildElement("MousePointer");
if (pointernode != nullptr) {
pointernode->QueryIntAttribute("mode", &application.mouse_pointer);
pointernode->QueryBoolAttribute("lock", &application.mouse_pointer_lock);
pointernode->QueryBoolAttribute("proportional_grid", &application.proportional_grid);
XMLElement* strengthNode = pointernode->FirstChildElement("vec2");
for( ; strengthNode ; strengthNode = strengthNode->NextSiblingElement())
{
glm::vec2 val;
tinyxml2::XMLElementToGLM( strengthNode, val);
application.mouse_pointer_strength[ (size_t) ceil(val.x) ] = val.y;
} }
}
// bloc views // Pointer
{ XMLElement * pointernode = pRoot->FirstChildElement("MousePointer");
XMLElement * pElement = pRoot->FirstChildElement("Views"); if (pointernode != nullptr) {
if (pElement) pointernode->QueryIntAttribute("mode", &application.mouse_pointer);
{ pointernode->QueryBoolAttribute("lock", &application.mouse_pointer_lock);
application.views.clear(); // trash existing list pointernode->QueryBoolAttribute("proportional_grid", &application.proportional_grid);
pElement->QueryIntAttribute("current", &application.current_view);
pElement->QueryIntAttribute("workspace", &application.current_workspace);
XMLElement* viewNode = pElement->FirstChildElement("View"); XMLElement* strengthNode = pointernode->FirstChildElement("vec2");
for( ; viewNode ; viewNode=viewNode->NextSiblingElement()) for( ; strengthNode ; strengthNode = strengthNode->NextSiblingElement())
{ {
int id = 0; glm::vec2 val;
viewNode->QueryIntAttribute("id", &id); tinyxml2::XMLElementToGLM( strengthNode, val);
application.views[id].name = viewNode->Attribute("name"); application.mouse_pointer_strength[ (size_t) ceil(val.x) ] = val.y;
viewNode->QueryBoolAttribute("ignore_mix", &application.views[id].ignore_mix);
XMLElement* scaleNode = viewNode->FirstChildElement("default_scale");
if (scaleNode)
tinyxml2::XMLElementToGLM( scaleNode->FirstChildElement("vec3"),
application.views[id].default_scale);
XMLElement* translationNode = viewNode->FirstChildElement("default_translation");
if (translationNode)
tinyxml2::XMLElementToGLM( translationNode->FirstChildElement("vec3"),
application.views[id].default_translation);
} }
} }
// bloc views
{
XMLElement * pElement = pRoot->FirstChildElement("Views");
if (pElement)
{
application.views.clear(); // trash existing list
pElement->QueryIntAttribute("current", &application.current_view);
pElement->QueryIntAttribute("workspace", &application.current_workspace);
XMLElement* viewNode = pElement->FirstChildElement("View");
for( ; viewNode ; viewNode=viewNode->NextSiblingElement())
{
int id = 0;
viewNode->QueryIntAttribute("id", &id);
application.views[id].name = viewNode->Attribute("name");
viewNode->QueryBoolAttribute("ignore_mix", &application.views[id].ignore_mix);
XMLElement* scaleNode = viewNode->FirstChildElement("default_scale");
if (scaleNode)
tinyxml2::XMLElementToGLM( scaleNode->FirstChildElement("vec3"),
application.views[id].default_scale);
XMLElement* translationNode = viewNode->FirstChildElement("default_translation");
if (translationNode)
tinyxml2::XMLElementToGLM( translationNode->FirstChildElement("vec3"),
application.views[id].default_translation);
}
}
}
// Mapping
XMLElement * mappingconfnode = pRoot->FirstChildElement("Mapping");
if (mappingconfnode != nullptr) {
mappingconfnode->QueryUnsigned64Attribute("mode", &application.mapping.mode);
mappingconfnode->QueryUnsignedAttribute("current", &application.mapping.current);
mappingconfnode->QueryBoolAttribute("disabled", &application.mapping.disabled);
}
// Timer Metronome
XMLElement * timerconfnode = pRoot->FirstChildElement("Timer");
if (timerconfnode != nullptr) {
timerconfnode->QueryUnsigned64Attribute("mode", &application.timer.mode);
timerconfnode->QueryBoolAttribute("link_enabled", &application.timer.link_enabled);
timerconfnode->QueryDoubleAttribute("link_tempo", &application.timer.link_tempo);
timerconfnode->QueryDoubleAttribute("link_quantum", &application.timer.link_quantum);
timerconfnode->QueryBoolAttribute("link_start_stop_sync", &application.timer.link_start_stop_sync);
timerconfnode->QueryUnsigned64Attribute("stopwatch_duration", &application.timer.stopwatch_duration);
}
} }
//
// Restore history and user entries
//
// bloc history of recent // bloc history of recent
{ {
XMLElement * pElement = pRoot->FirstChildElement("Recent"); XMLElement * pElement = pRoot->FirstChildElement("Recent");
@@ -702,27 +739,8 @@ void Settings::Load()
} }
} }
// Timer Metronome
XMLElement * timerconfnode = pRoot->FirstChildElement("Timer");
if (timerconfnode != nullptr) {
timerconfnode->QueryUnsigned64Attribute("mode", &application.timer.mode);
timerconfnode->QueryBoolAttribute("link_enabled", &application.timer.link_enabled);
timerconfnode->QueryDoubleAttribute("link_tempo", &application.timer.link_tempo);
timerconfnode->QueryDoubleAttribute("link_quantum", &application.timer.link_quantum);
timerconfnode->QueryBoolAttribute("link_start_stop_sync", &application.timer.link_start_stop_sync);
timerconfnode->QueryUnsigned64Attribute("stopwatch_duration", &application.timer.stopwatch_duration);
}
// Mapping
XMLElement * mappingconfnode = pRoot->FirstChildElement("Mapping");
if (mappingconfnode != nullptr) {
mappingconfnode->QueryUnsigned64Attribute("mode", &application.mapping.mode);
mappingconfnode->QueryUnsignedAttribute("current", &application.mapping.current);
mappingconfnode->QueryBoolAttribute("disabled", &application.mapping.disabled);
}
// bloc Controller // bloc Controller
XMLElement *controlconfnode = pRoot->FirstChildElement("Control"); XMLElement * controlconfnode = pRoot->FirstChildElement("Control");
if (controlconfnode != nullptr) { if (controlconfnode != nullptr) {
controlconfnode->QueryIntAttribute("osc_port_receive", &application.control.osc_port_receive); controlconfnode->QueryIntAttribute("osc_port_receive", &application.control.osc_port_receive);
controlconfnode->QueryIntAttribute("osc_port_send", &application.control.osc_port_send); controlconfnode->QueryIntAttribute("osc_port_send", &application.control.osc_port_send);

View File

@@ -349,6 +349,7 @@ struct Application
InputMappingConfig mapping; InputMappingConfig mapping;
Application() : fresh_start(false), instance_id(0), name(APP_NAME), executable(APP_NAME) { Application() : fresh_start(false), instance_id(0), name(APP_NAME), executable(APP_NAME) {
total_runtime = 0;
scale = 1.f; scale = 1.f;
accent_color = 0; accent_color = 0;
smooth_transition = true; smooth_transition = true;

View File

@@ -223,6 +223,9 @@ bool UserInterface::Init()
// init tooltips // init tooltips
ImGuiToolkit::setToolTipsEnabled(Settings::application.show_tooptips); ImGuiToolkit::setToolTipsEnabled(Settings::application.show_tooptips);
// show about dialog on first run
show_vimix_about = (Settings::application.total_runtime < 1);
return true; return true;
} }
@@ -2084,7 +2087,7 @@ void UserInterface::RenderSourceToolbar(bool *p_open, int* p_border, int *p_mode
void UserInterface::RenderAbout(bool* p_open) void UserInterface::RenderAbout(bool* p_open)
{ {
ImGui::SetNextWindowPos(ImVec2(1100, 20), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(600, 40), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("About " APP_TITLE, p_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize)) if (!ImGui::Begin("About " APP_TITLE, p_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize))
{ {
ImGui::End(); ImGui::End();
@@ -2092,15 +2095,13 @@ void UserInterface::RenderAbout(bool* p_open)
} }
ImVec2 top = ImGui::GetCursorScreenPos(); ImVec2 top = ImGui::GetCursorScreenPos();
#ifdef VIMIX_VERSION_MAJOR
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
#ifdef VIMIX_VERSION_MAJOR
ImGui::Text("%s %d.%d.%d", APP_NAME, VIMIX_VERSION_MAJOR, VIMIX_VERSION_MINOR, VIMIX_VERSION_PATCH); ImGui::Text("%s %d.%d.%d", APP_NAME, VIMIX_VERSION_MAJOR, VIMIX_VERSION_MINOR, VIMIX_VERSION_PATCH);
ImGui::PopFont();
#else #else
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_BOLD);
ImGui::Text("%s", APP_NAME); ImGui::Text("%s", APP_NAME);
ImGui::PopFont();
#endif #endif
ImGui::PopFont();
#ifdef VIMIX_GIT #ifdef VIMIX_GIT
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC); ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC);

View File

@@ -102,6 +102,8 @@ int main(int argc, char *argv[])
else { else {
// try to open the file // try to open the file
_openfile = argument; _openfile = argument;
if (!_openfile.empty())
fprintf(stderr, "Loading '%s' ...\n", _openfile.c_str());
} }
} }
@@ -114,11 +116,6 @@ int main(int argc, char *argv[])
/// lock to inform an instance is running /// lock to inform an instance is running
Settings::Lock(); Settings::Lock();
if (!_openfile.empty()) {
Settings::application.fresh_start = false;
fprintf(stderr, "Loading %s\n", _openfile.c_str());
}
/// ///
/// CONNECTION INIT /// CONNECTION INIT
/// ///