mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
Auto collapse of Shader Editor window
Reduces height of shader editor when there is no shader to edit. Cleanup of Workspace window implementation.
This commit is contained in:
@@ -124,6 +124,7 @@ ShaderEditWindow::ShaderEditWindow() : WorkspaceWindow("Shader"), _cs_id(0), cur
|
||||
|
||||
// status
|
||||
status_ = "-";
|
||||
|
||||
}
|
||||
|
||||
void ShaderEditWindow::setVisible(bool on)
|
||||
@@ -139,6 +140,7 @@ void ShaderEditWindow::setVisible(bool on)
|
||||
Settings::application.widget.shader_editor_view = -1;
|
||||
|
||||
Settings::application.widget.shader_editor = on;
|
||||
|
||||
}
|
||||
|
||||
bool ShaderEditWindow::Visible() const
|
||||
@@ -188,7 +190,6 @@ void ShaderEditWindow::BuildAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ShaderEditWindow::Render()
|
||||
{
|
||||
static DialogToolkit::OpenFileDialog selectcodedialog("Open GLSL shader code",
|
||||
@@ -198,18 +199,54 @@ void ShaderEditWindow::Render()
|
||||
"Text files",
|
||||
{"*.glsl", "*.fs", "*.txt"} );
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
|
||||
std::string file_to_build_ = "";
|
||||
Source *cs = Mixer::manager().currentSource();
|
||||
|
||||
// garbage collection
|
||||
if ( !filters_.empty() && Mixer::manager().session()->numSources() < 1 )
|
||||
{
|
||||
// empty list of edited filter when session empty
|
||||
filters_.clear();
|
||||
current_ = nullptr;
|
||||
|
||||
// clear editor text and recent file
|
||||
_editor.SetText("");
|
||||
Settings::application.recentShaderCode.assign("");
|
||||
}
|
||||
|
||||
// File dialog Export code gives a filename to save to
|
||||
if (exportcodedialog.closed() && !exportcodedialog.path().empty()) {
|
||||
|
||||
// set shader program to be a file
|
||||
file_to_build_ = exportcodedialog.path();
|
||||
|
||||
// save the current content of editor into given file
|
||||
saveEditorText(file_to_build_);
|
||||
}
|
||||
|
||||
// File dialog select code gives a filename to open
|
||||
if (selectcodedialog.closed() && !selectcodedialog.path().empty()) {
|
||||
|
||||
// set shader program to be a file
|
||||
file_to_build_ = selectcodedialog.path();
|
||||
|
||||
// read file and display content in editor
|
||||
_editor.SetText(SystemToolkit::get_text_content(file_to_build_));
|
||||
}
|
||||
|
||||
// AUTO COLLAPSE
|
||||
setCollapsed(current_ == nullptr);
|
||||
|
||||
// Render window
|
||||
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
|
||||
if ( !ImGui::Begin(name_, &Settings::application.widget.shader_editor,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse ))
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string file_to_build_ = "";
|
||||
Source *cs = Mixer::manager().currentSource();
|
||||
|
||||
// menu (no title bar)
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
@@ -387,37 +424,25 @@ void ShaderEditWindow::Render()
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
// garbage collection
|
||||
if ( !filters_.empty() && Mixer::manager().session()->numSources() < 1 )
|
||||
{
|
||||
// empty list of edited filter when session empty
|
||||
filters_.clear();
|
||||
current_ = nullptr;
|
||||
// clear editor text and recent file
|
||||
_editor.SetText("");
|
||||
Settings::application.recentShaderCode.assign("");
|
||||
}
|
||||
|
||||
// File dialog Export code gives a filename to save to
|
||||
if (exportcodedialog.closed() && !exportcodedialog.path().empty()) {
|
||||
|
||||
// set shader program to be a file
|
||||
file_to_build_ = exportcodedialog.path();
|
||||
|
||||
// save the current content of editor into given file
|
||||
saveEditorText(file_to_build_);
|
||||
}
|
||||
|
||||
// File dialog select code gives a filename to open
|
||||
if (selectcodedialog.closed() && !selectcodedialog.path().empty()) {
|
||||
|
||||
// set shader program to be a file
|
||||
file_to_build_ = selectcodedialog.path();
|
||||
|
||||
// read file and display content in editor
|
||||
_editor.SetText(SystemToolkit::get_text_content(file_to_build_));
|
||||
// the TextEditor captures keyboard focus from the main imgui context
|
||||
// so UserInterface::handleKeyboard cannot capture this event:
|
||||
// reading key press before render bypasses this problem
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl) {
|
||||
// special case for 'CTRL + B' keyboard shortcut
|
||||
if (ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_A] + 1))
|
||||
BuildShader();
|
||||
// special case for 'CTRL + S' keyboard shortcut
|
||||
if (ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_V] - 3)) {
|
||||
// if present, save the program file with current content of editor
|
||||
if (!filters_[current_].filename().empty())
|
||||
saveEditorText(filters_[current_].filename());
|
||||
// save session
|
||||
Mixer::manager().save();
|
||||
}
|
||||
}
|
||||
|
||||
// compile
|
||||
if (current_ != nullptr && !file_to_build_.empty()) {
|
||||
|
||||
// ok editor
|
||||
@@ -446,7 +471,6 @@ void ShaderEditWindow::Render()
|
||||
}
|
||||
// not compiling
|
||||
else {
|
||||
|
||||
// if there is a current source
|
||||
if (cs != nullptr) {
|
||||
// if current source is different from previous one
|
||||
@@ -519,7 +543,6 @@ void ShaderEditWindow::Render()
|
||||
_cs_id = 0;
|
||||
status_ = "-";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// render status message
|
||||
@@ -527,10 +550,11 @@ void ShaderEditWindow::Render()
|
||||
ImGui::Text("Status: %s", status_.c_str());
|
||||
|
||||
// Right-align on same line than status
|
||||
const float w = ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeight();
|
||||
|
||||
// Display name of program for embedded code
|
||||
if (current_ != nullptr) {
|
||||
|
||||
const float w = ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeight();
|
||||
ImVec2 txtsize = ImGui::CalcTextSize(Settings::application.recentShaderCode.path.c_str(), NULL);
|
||||
ImGui::SameLine(w - txtsize.x - IMGUI_SAME_LINE, 0);
|
||||
|
||||
@@ -569,6 +593,14 @@ void ShaderEditWindow::Render()
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ImVec2 txtsize = ImGui::CalcTextSize("No shader", NULL);
|
||||
ImGui::SameLine(w - txtsize.x - IMGUI_SAME_LINE, 0);
|
||||
// right-aligned in italics and greyed out
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.8, 0.8, 0.9f));
|
||||
ImGui::Text("No Shader");
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
|
||||
ImGui::PopFont();
|
||||
|
||||
@@ -576,7 +608,7 @@ void ShaderEditWindow::Render()
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO);
|
||||
|
||||
// render shader input
|
||||
if (show_shader_inputs_) {
|
||||
if (current_ != nullptr && show_shader_inputs_) {
|
||||
ImGuiTextBuffer info;
|
||||
info.append(FilteringProgram::getFilterCodeInputs().c_str());
|
||||
|
||||
@@ -610,26 +642,9 @@ void ShaderEditWindow::Render()
|
||||
else
|
||||
ImGui::Spacing();
|
||||
|
||||
// the TextEditor captures keyboard focus from the main imgui context
|
||||
// so UserInterface::handleKeyboard cannot capture this event:
|
||||
// reading key press before render bypasses this problem
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl) {
|
||||
// special case for 'CTRL + B' keyboard shortcut
|
||||
if (ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_A] + 1))
|
||||
BuildShader();
|
||||
// special case for 'CTRL + S' keyboard shortcut
|
||||
if (ImGui::IsKeyPressed(io.KeyMap[ImGuiKey_V] - 3)) {
|
||||
// if present, save the program file with current content of editor
|
||||
if (!filters_[current_].filename().empty())
|
||||
saveEditorText(filters_[current_].filename());
|
||||
// save session
|
||||
Mixer::manager().save();
|
||||
}
|
||||
}
|
||||
|
||||
// render main editor
|
||||
_editor.Render("Shader Editor");
|
||||
if (_editor.GetTotalLines()>1)
|
||||
_editor.Render("Shader Editor");
|
||||
|
||||
ImGui::PopFont();
|
||||
|
||||
|
||||
@@ -31,21 +31,24 @@ std::list<WorkspaceWindow *> WorkspaceWindow::windows_;
|
||||
struct ImGuiProperties
|
||||
{
|
||||
ImGuiWindow *ptr;
|
||||
ImVec2 user_pos;
|
||||
ImVec2 outside_pos;
|
||||
float progress; // [0 1]
|
||||
float target; // 1 go to outside, 0 go to user pos
|
||||
bool animation; // need animation
|
||||
bool animation; // need animation
|
||||
bool resizing_workspace;
|
||||
bool hidden;
|
||||
bool collapsed;
|
||||
ImVec2 user_pos;
|
||||
ImVec2 user_size;
|
||||
ImVec2 hidden_pos;
|
||||
ImVec2 resized_pos;
|
||||
|
||||
ImGuiProperties ()
|
||||
{
|
||||
ptr = nullptr;
|
||||
progress = 0.f;
|
||||
target = 0.f;
|
||||
animation = false;
|
||||
resizing_workspace = false;
|
||||
hidden = false;
|
||||
collapsed = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,32 +72,98 @@ void WorkspaceWindow::toggleClearRestoreWorkspace()
|
||||
clearWorkspace();
|
||||
}
|
||||
|
||||
void WorkspaceWindow::restoreWorkspace(bool instantaneous)
|
||||
void WorkspaceWindow::setHidden(bool h, bool force)
|
||||
{
|
||||
if (clear_workspace_enabled) {
|
||||
// hide if valid pointer and if status 'hidden' is changing (or forcing entry)
|
||||
if (impl_ && impl_->ptr && ( impl_->hidden != h || force )) {
|
||||
|
||||
// set status
|
||||
impl_->hidden = h;
|
||||
|
||||
// utility variables
|
||||
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
for(auto it = windows_.cbegin(); it != windows_.cend(); ++it) {
|
||||
ImGuiProperties *impl = (*it)->impl_;
|
||||
if (impl && impl->ptr)
|
||||
{
|
||||
float margin = (impl->ptr->MenuBarHeight() + impl->ptr->TitleBarHeight()) * 3.f;
|
||||
impl->user_pos.x = CLAMP(impl->user_pos.x, -impl->ptr->SizeFull.x +margin, display_size.x -margin);
|
||||
impl->user_pos.y = CLAMP(impl->user_pos.y, -impl->ptr->SizeFull.y +margin, display_size.y -margin);
|
||||
|
||||
if (instantaneous) {
|
||||
impl->animation = false;
|
||||
ImGui::SetWindowPos(impl->ptr, impl->user_pos);
|
||||
}
|
||||
else {
|
||||
// remember outside position before move
|
||||
impl->outside_pos = impl->ptr->Pos;
|
||||
if (h) {
|
||||
// remember user position before animation
|
||||
impl_->user_pos = impl_->ptr->Pos;
|
||||
|
||||
// initialize animation
|
||||
impl->progress = 1.f;
|
||||
impl->target = 0.f;
|
||||
impl->animation = true;
|
||||
}
|
||||
// distance to right side, top & bottom
|
||||
float right = display_size.x - (impl_->ptr->Pos.x + impl_->ptr->SizeFull.x * 0.7);
|
||||
float top = impl_->ptr->Pos.y;
|
||||
float bottom = display_size.y - (impl_->ptr->Pos.y + impl_->ptr->SizeFull.y);
|
||||
|
||||
// hidden_pos starts from user position,
|
||||
// + moved to closest border, with a margin to keep visible
|
||||
impl_->hidden_pos = impl_->ptr->Pos;
|
||||
float margin = (impl_->ptr->MenuBarHeight() + impl_->ptr->TitleBarHeight()) * 1.5f;
|
||||
if (top < bottom && top < right)
|
||||
impl_->hidden_pos.y = margin - impl_->ptr->SizeFull.y;
|
||||
else if (right < top && right < bottom)
|
||||
impl_->hidden_pos.x = display_size.x - margin;
|
||||
else
|
||||
impl_->hidden_pos.y = display_size.y - margin;
|
||||
|
||||
if (force) {
|
||||
impl_->animation = false;
|
||||
ImGui::SetWindowPos(impl_->ptr, impl_->hidden_pos);
|
||||
}
|
||||
else {
|
||||
// initialize animation
|
||||
impl_->progress = 0.f;
|
||||
impl_->animation = true;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// remember outside position before animation
|
||||
impl_->hidden_pos = impl_->ptr->Pos;
|
||||
|
||||
float margin = (impl_->ptr->MenuBarHeight() + impl_->ptr->TitleBarHeight()) * 3.f;
|
||||
impl_->user_pos.x = CLAMP(impl_->user_pos.x,
|
||||
-impl_->ptr->SizeFull.x + margin,
|
||||
display_size.x - margin);
|
||||
impl_->user_pos.y = CLAMP(impl_->user_pos.y,
|
||||
-impl_->ptr->SizeFull.y + margin,
|
||||
display_size.y - margin);
|
||||
|
||||
if (force) {
|
||||
impl_->animation = false;
|
||||
// ImGui::SetWindowPos(impl_->ptr, impl_->user_pos);
|
||||
}
|
||||
else {
|
||||
// initialize animation
|
||||
impl_->progress = 1.f;
|
||||
impl_->animation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorkspaceWindow::setCollapsed(bool c)
|
||||
{
|
||||
// hide if valid pointer and if status 'collapsed' is changing
|
||||
if (impl_ && impl_->ptr && impl_->collapsed != c && !impl_->hidden) {
|
||||
impl_->collapsed = c;
|
||||
|
||||
ImVec2 s = impl_->ptr->SizeFull;
|
||||
if (c) {
|
||||
impl_->user_size = s;
|
||||
s.y = impl_->ptr->MenuBarHeight() * 2.3f;
|
||||
} else
|
||||
s.y = impl_->user_size.y;
|
||||
|
||||
ImGui::SetWindowSize(impl_->ptr, s);
|
||||
}
|
||||
}
|
||||
|
||||
void WorkspaceWindow::restoreWorkspace(bool force)
|
||||
{
|
||||
if (clear_workspace_enabled || force) {
|
||||
// const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
for(auto it = windows_.cbegin(); it != windows_.cend(); ++it) {
|
||||
if (force)
|
||||
(*it)->setCollapsed(false);
|
||||
(*it)->setHidden(false, force);
|
||||
}
|
||||
}
|
||||
clear_workspace_enabled = false;
|
||||
@@ -103,36 +172,9 @@ void WorkspaceWindow::restoreWorkspace(bool instantaneous)
|
||||
void WorkspaceWindow::clearWorkspace()
|
||||
{
|
||||
if (!clear_workspace_enabled) {
|
||||
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
// const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
for(auto it = windows_.cbegin(); it != windows_.cend(); ++it) {
|
||||
ImGuiProperties *impl = (*it)->impl_;
|
||||
if (impl && impl->ptr)
|
||||
{
|
||||
// remember user position before move
|
||||
impl->user_pos = impl->ptr->Pos;
|
||||
|
||||
// init before decision
|
||||
impl->outside_pos = impl->ptr->Pos;
|
||||
|
||||
// distance to right side, top & bottom
|
||||
float right = display_size.x - (impl->ptr->Pos.x + impl->ptr->SizeFull.x * 0.7);
|
||||
float top = impl->ptr->Pos.y;
|
||||
float bottom = display_size.y - (impl->ptr->Pos.y + impl->ptr->SizeFull.y);
|
||||
|
||||
// move to closest border, with a margin to keep visible
|
||||
float margin = (impl->ptr->MenuBarHeight() + impl->ptr->TitleBarHeight()) * 1.5f;
|
||||
if (top < bottom && top < right)
|
||||
impl->outside_pos.y = margin - impl->ptr->SizeFull.y;
|
||||
else if (right < top && right < bottom)
|
||||
impl->outside_pos.x = display_size.x - margin;
|
||||
else
|
||||
impl->outside_pos.y = display_size.y - margin;
|
||||
|
||||
// initialize animation
|
||||
impl->progress = 0.f;
|
||||
impl->target = 1.f;
|
||||
impl->animation = true;
|
||||
}
|
||||
(*it)->setHidden(true);
|
||||
}
|
||||
}
|
||||
clear_workspace_enabled = true;
|
||||
@@ -180,17 +222,18 @@ void WorkspaceWindow::Update()
|
||||
if ( Visible() ) {
|
||||
// perform animation for clear/restore workspace
|
||||
if (impl_->animation) {
|
||||
const float target = impl_->hidden ? 1.f : 0.f;
|
||||
// increment animation progress by small steps
|
||||
impl_->progress += SIGN(impl_->target -impl_->progress) * 0.1f;
|
||||
impl_->progress += SIGN(target -impl_->progress) * 0.1f;
|
||||
// finished animation : apply full target position
|
||||
if (ABS_DIFF(impl_->target, impl_->progress) < 0.05f) {
|
||||
if (ABS_DIFF(target, impl_->progress) < 0.05f) {
|
||||
impl_->animation = false;
|
||||
ImVec2 pos = impl_->user_pos * (1.f -impl_->target) + impl_->outside_pos * impl_->target;
|
||||
ImVec2 pos = impl_->user_pos * (1.f -target) + impl_->hidden_pos * target;
|
||||
ImGui::SetWindowPos(impl_->ptr, pos);
|
||||
}
|
||||
// move window by interpolation between user position and outside target position
|
||||
else {
|
||||
ImVec2 pos = impl_->user_pos * (1.f -impl_->progress) + impl_->outside_pos * impl_->progress;
|
||||
ImVec2 pos = impl_->user_pos * (1.f -impl_->progress) + impl_->hidden_pos * impl_->progress;
|
||||
ImGui::SetWindowPos(impl_->ptr, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,14 @@ public:
|
||||
static bool clear() { return clear_workspace_enabled; }
|
||||
static void toggleClearRestoreWorkspace();
|
||||
static void clearWorkspace();
|
||||
static void restoreWorkspace(bool instantaneous = false);
|
||||
static void restoreWorkspace(bool force = false);
|
||||
static void notifyWorkspaceSizeChanged(int prev_width, int prev_height, int curr_width, int curr_height);
|
||||
|
||||
// for inherited classes
|
||||
virtual void Update();
|
||||
virtual bool Visible() const { return true; }
|
||||
virtual void setHidden(bool h, bool force = false);
|
||||
virtual void setCollapsed(bool c);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user