mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
UI WorkspaceWindows follow window resize
Fixed bug in restore window position.
This commit is contained in:
@@ -1878,6 +1878,8 @@ struct ImGuiProperties
|
||||
float progress; // [0 1]
|
||||
float target; // 1 go to outside, 0 go to user pos
|
||||
bool animation; // need animation
|
||||
bool resizing_workspace;
|
||||
ImVec2 resized_pos;
|
||||
|
||||
ImGuiProperties ()
|
||||
{
|
||||
@@ -1885,6 +1887,7 @@ struct ImGuiProperties
|
||||
progress = 0.f;
|
||||
target = 0.f;
|
||||
animation = false;
|
||||
resizing_workspace = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1903,67 +1906,96 @@ void WorkspaceWindow::toggleClearRestoreWorkspace()
|
||||
|
||||
void WorkspaceWindow::restoreWorkspace(bool instantaneous)
|
||||
{
|
||||
clear_workspace_enabled = false;
|
||||
if (clear_workspace_enabled) {
|
||||
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);
|
||||
|
||||
for(auto it = windows_.cbegin(); it != windows_.cend(); ++it) {
|
||||
ImGuiProperties *impl = (*it)->impl_;
|
||||
if (impl && impl->ptr)
|
||||
{
|
||||
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 (instantaneous) {
|
||||
impl->animation = false;
|
||||
ImGui::SetWindowPos(impl->ptr, impl->user_pos);
|
||||
}
|
||||
else {
|
||||
// remember outside position before move
|
||||
impl->outside_pos = impl->ptr->Pos;
|
||||
|
||||
// initialize animation
|
||||
impl->progress = 1.f;
|
||||
impl->target = 0.f;
|
||||
impl->animation = true;
|
||||
// initialize animation
|
||||
impl->progress = 1.f;
|
||||
impl->target = 0.f;
|
||||
impl->animation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clear_workspace_enabled = false;
|
||||
}
|
||||
|
||||
void WorkspaceWindow::clearWorkspace()
|
||||
{
|
||||
clear_workspace_enabled = true;
|
||||
if (!clear_workspace_enabled) {
|
||||
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;
|
||||
|
||||
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
clear_workspace_enabled = true;
|
||||
}
|
||||
|
||||
void WorkspaceWindow::notifyWorkspaceSizeChanged(int prev_width, int prev_height, int curr_width, int curr_height)
|
||||
{
|
||||
for(auto it = windows_.cbegin(); it != windows_.cend(); ++it) {
|
||||
ImGuiProperties *impl = (*it)->impl_;
|
||||
if (impl && impl->ptr)
|
||||
if ((*it)->Visible() && impl && impl->ptr)
|
||||
{
|
||||
// remember user position before move
|
||||
impl->user_pos = impl->ptr->Pos;
|
||||
ImVec2 distance_to_corner = ImVec2(prev_width, prev_height) - impl->ptr->Pos - impl->ptr->SizeFull;
|
||||
|
||||
// init before decision
|
||||
impl->outside_pos = impl->ptr->Pos;
|
||||
impl->resized_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);
|
||||
if ( ABS(distance_to_corner.x) < 100.f ) {
|
||||
impl->resized_pos.x += curr_width - prev_width;
|
||||
impl->resizing_workspace = true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if ( ABS(distance_to_corner.y) < 100.f ) {
|
||||
impl->resized_pos.y += curr_height -prev_height;
|
||||
impl->resizing_workspace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WorkspaceWindow::Update()
|
||||
{
|
||||
// get ImGui pointer to window (available only after first run)
|
||||
@@ -1972,41 +2004,57 @@ void WorkspaceWindow::Update()
|
||||
if (w != NULL) {
|
||||
impl_ = new ImGuiProperties;
|
||||
impl_->ptr = w;
|
||||
impl_->user_pos = w->Pos;
|
||||
}
|
||||
}
|
||||
// if an animation is requested
|
||||
else if (impl_->animation) {
|
||||
// increment animation progress by small steps
|
||||
impl_->progress += SIGN(impl_->target -impl_->progress) * 0.1f;
|
||||
// finished animation : apply full target position
|
||||
if (ABS_DIFF(impl_->target, impl_->progress) < 0.05f) {
|
||||
impl_->animation = false;
|
||||
ImVec2 pos = impl_->user_pos * (1.f -impl_->target) + impl_->outside_pos * impl_->target;
|
||||
else if (Visible()){
|
||||
// perform animation for clear/restore workspace
|
||||
if (impl_->animation) {
|
||||
// increment animation progress by small steps
|
||||
impl_->progress += SIGN(impl_->target -impl_->progress) * 0.1f;
|
||||
// finished animation : apply full target position
|
||||
if (ABS_DIFF(impl_->target, impl_->progress) < 0.05f) {
|
||||
impl_->animation = false;
|
||||
ImVec2 pos = impl_->user_pos * (1.f -impl_->target) + impl_->outside_pos * impl_->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;
|
||||
ImGui::SetWindowPos(impl_->ptr, pos);
|
||||
}
|
||||
}
|
||||
// move windows because workspace was resized
|
||||
if (impl_->resizing_workspace) {
|
||||
// how far from the target ?
|
||||
ImVec2 delta = impl_->resized_pos - impl_->ptr->Pos;
|
||||
// got close enough to stop workspace resize
|
||||
if (ABS(delta.x) < 2.f && ABS(delta.y) < 2.f)
|
||||
impl_->resizing_workspace = false;
|
||||
// dichotomic reach of target position
|
||||
ImVec2 pos = impl_->ptr->Pos + delta * 0.5f;
|
||||
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;
|
||||
ImGui::SetWindowPos(impl_->ptr, pos);
|
||||
}
|
||||
}
|
||||
// if clear mode is fullly enabled
|
||||
else if (clear_workspace_enabled && Visible())
|
||||
{
|
||||
// draw another window on top of the WorkspaceWindow, at exact same position and size
|
||||
ImGuiWindow* window = impl_->ptr;
|
||||
ImGui::SetNextWindowPos(window->Pos, ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(window->Size, ImGuiCond_Always);
|
||||
char nameoverlay[64];
|
||||
sprintf(nameoverlay, "%sOverlay", name_);
|
||||
if (ImGui::Begin(nameoverlay, NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings ))
|
||||
// dimm window if clear mode is fullly enabled
|
||||
if (clear_workspace_enabled)
|
||||
{
|
||||
// exit workspace clear mode if user clics on the window
|
||||
ImGui::InvisibleButton("##dummy", window->Size);
|
||||
if (ImGui::IsItemClicked())
|
||||
WorkspaceWindow::restoreWorkspace();
|
||||
ImGui::End();
|
||||
// draw another window on top of the WorkspaceWindow, at exact same position and size
|
||||
ImGuiWindow* window = impl_->ptr;
|
||||
ImGui::SetNextWindowPos(window->Pos, ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(window->Size, ImGuiCond_Always);
|
||||
char nameoverlay[64];
|
||||
sprintf(nameoverlay, "%sOverlay", name_);
|
||||
if (ImGui::Begin(nameoverlay, NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings ))
|
||||
{
|
||||
// exit workspace clear mode if user clics on the window
|
||||
ImGui::InvisibleButton("##dummy", window->Size);
|
||||
if (ImGui::IsItemClicked())
|
||||
WorkspaceWindow::restoreWorkspace();
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2037,9 +2085,10 @@ void SourceController::resetActiveSelection()
|
||||
|
||||
void SourceController::setVisible(bool on)
|
||||
{
|
||||
// restore workspace to show the window
|
||||
if (WorkspaceWindow::clear_workspace_enabled) {
|
||||
WorkspaceWindow::restoreWorkspace(on);
|
||||
// do not change status: the restore workspace above showed the window
|
||||
// do not change status if ask to hide (consider user asked to toggle because the window was not visible)
|
||||
if (!on) return;
|
||||
}
|
||||
|
||||
@@ -2103,9 +2152,6 @@ void SourceController::Update()
|
||||
|
||||
void SourceController::Render()
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(1180, 400), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
|
||||
|
||||
// estimate window size
|
||||
const ImGuiContext& g = *GImGui;
|
||||
h_space_ = g.Style.ItemInnerSpacing.x;
|
||||
@@ -2118,21 +2164,18 @@ void SourceController::Render()
|
||||
// all together: 1 title bar + spacing + 1 toolbar + spacing + 2 timelines + scrollbar
|
||||
mediaplayer_height_ = buttons_height_ + 2.f * timeline_height_ + 2.f * scrollbar_ + v_space_;
|
||||
|
||||
// constraint position
|
||||
static ImVec2 source_window_pos = ImVec2(1180, 20);
|
||||
static ImVec2 source_window_size = ImVec2(400, 260);
|
||||
// SetNextWindowVisible(source_window_pos, source_window_size);
|
||||
|
||||
// constraint size
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(min_width_, 2.f * mediaplayer_height_), ImVec2(FLT_MAX, FLT_MAX));
|
||||
ImGui::SetNextWindowPos(ImVec2(1180, 400), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
|
||||
|
||||
if ( !ImGui::Begin(name_, &Settings::application.widget.media_player, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse ))
|
||||
// Window named "SourceController" at instanciation
|
||||
if ( !ImGui::Begin(name_, &Settings::application.widget.media_player,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse ))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
source_window_pos = ImGui::GetWindowPos();
|
||||
source_window_size = ImGui::GetWindowSize();
|
||||
|
||||
// menu (no title bar)
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
@@ -3447,9 +3490,10 @@ OutputPreview::OutputPreview() : WorkspaceWindow("OutputPreview"), video_recorde
|
||||
|
||||
void OutputPreview::setVisible(bool on)
|
||||
{
|
||||
// restore workspace to show the window
|
||||
if (WorkspaceWindow::clear_workspace_enabled) {
|
||||
WorkspaceWindow::restoreWorkspace(on);
|
||||
// do not change status: the restore workspace above showed the window
|
||||
// do not change status if ask to hide (consider user asked to toggle because the window was not visible)
|
||||
if (!on) return;
|
||||
}
|
||||
|
||||
@@ -3532,26 +3576,19 @@ void OutputPreview::Render()
|
||||
FrameBuffer *output = Mixer::manager().session()->frame();
|
||||
if (output)
|
||||
{
|
||||
|
||||
// constraint position
|
||||
static ImVec2 preview_window_pos = ImVec2(1180, 20);
|
||||
static ImVec2 preview_window_size = ImVec2(400, 260);
|
||||
// SetNextWindowVisible(preview_window_pos, preview_window_size);
|
||||
|
||||
// constraint aspect ratio resizing
|
||||
float ar = output->aspectRatio();
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300, 200), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, &ar);
|
||||
ImGui::SetNextWindowPos(ImVec2(1180, 20), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(400, 260), ImGuiCond_FirstUseEver);
|
||||
|
||||
// Window named "OutputPreview" at instanciation
|
||||
if ( !ImGui::Begin(name_, &Settings::application.widget.preview,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse ) )
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
preview_window_pos = ImGui::GetWindowPos();
|
||||
preview_window_size = ImGui::GetWindowSize();
|
||||
|
||||
// return from thread for folder openning
|
||||
if (recordFolderDialog->closed() && !recordFolderDialog->path().empty())
|
||||
@@ -3872,9 +3909,10 @@ TimerMetronome::TimerMetronome() : WorkspaceWindow("Timer")
|
||||
|
||||
void TimerMetronome::setVisible(bool on)
|
||||
{
|
||||
// restore workspace to show the window
|
||||
if (WorkspaceWindow::clear_workspace_enabled) {
|
||||
WorkspaceWindow::restoreWorkspace(on);
|
||||
// do not change status: the restore workspace above showed the window
|
||||
// do not change status if ask to hide (consider user asked to toggle because the window was not visible)
|
||||
if (!on) return;
|
||||
}
|
||||
|
||||
@@ -3906,7 +3944,6 @@ void TimerMetronome::Render()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// menu (no title bar)
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
@@ -6312,30 +6349,3 @@ void SetMouseCursor(ImVec2 mousepos, View::Cursor c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void SetNextWindowVisible(ImVec2 pos, ImVec2 size, float margin)
|
||||
//{
|
||||
// bool need_update = false;
|
||||
// ImVec2 pos_target = pos;
|
||||
// const ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// if ( pos_target.y > io.DisplaySize.y - margin ){
|
||||
// pos_target.y = io.DisplaySize.y - margin;
|
||||
// need_update = true;
|
||||
// }
|
||||
// if ( pos_target.y + size.y < margin ){
|
||||
// pos_target.y = margin - size.y;
|
||||
// need_update = true;
|
||||
// }
|
||||
// if ( pos_target.x > io.DisplaySize.x - margin){
|
||||
// pos_target.x = io.DisplaySize.x - margin;
|
||||
// need_update = true;
|
||||
// }
|
||||
// if ( pos_target.x + size.x < margin ){
|
||||
// pos_target.x = margin - size.x;
|
||||
// need_update = true;
|
||||
// }
|
||||
// if (need_update)
|
||||
// ImGui::SetNextWindowPos(pos_target, ImGuiCond_Always);
|
||||
//}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user