From c40fb7c82be088db4166e92f131865f72b975f56 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Fri, 27 Jan 2023 22:49:03 -0500 Subject: selection improvements --- src/createcalls.cpp | 9 ++-- src/imgui_ui.cpp | 9 ++++ src/imgui_ui_timeline.cpp | 16 +++--- src/imgui_ui_viewport.cpp | 124 ++++++++++++++++++++++++++++++++++------------ src/include/all.h | 4 ++ src/include/functions.h | 2 + src/include/main.h | 1 + 7 files changed, 123 insertions(+), 42 deletions(-) diff --git a/src/createcalls.cpp b/src/createcalls.cpp index adb6ff5..fd60b4e 100644 --- a/src/createcalls.cpp +++ b/src/createcalls.cpp @@ -264,7 +264,7 @@ Effect_Add(project_data *File, project_state *State, memory *Memory, uint32 Effe block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); if (Layer->IsSelected) { Layer->Block_Effect_Index[Layer->Block_Effect_Count] = Effect_Init(State, Memory, EffectEntryIndex, Layer->Block_Effect_Count); - History_Action_Swap(Memory, F_File, sizeof(Layer->Block_Effect_Count), &Layer->Block_Effect_Count); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->Block_Effect_Count), &Layer->Block_Effect_Count); Layer->Block_Effect_Count++; Selected++; } @@ -675,6 +675,9 @@ Project_Layer_Duplicate(project_data *File, project_state *State, memory *Memory block_layer *NewLayer = (block_layer *)Memory_Block_AllocateAddress(Memory, F_Layers); History_Action_Block_Swap(Memory, F_Layers, NewLayer); *NewLayer = *Layer; + + Assert(Layer->Block_Effect_Count == 0); + NewLayer->IsSelected = true; NewLayer->Vertical_Offset--; @@ -832,7 +835,7 @@ void Source_UICreateButton(project_data *File, project_state *State, memory *Mem CommitAction = 1; } if (Source->Type == source_type_principal_temp) { - History_Action_Swap(Memory, F_File, sizeof(Source->Type), &Source->Type); + History_Action_Swap(Memory, F_Sources, sizeof(Source->Type), &Source->Type); Source->Type = source_type_principal; } block_layer *Layer = Layer_Init(File, Memory); @@ -932,7 +935,7 @@ void Precomp_UICreateButton(project_data *File, project_state *State, memory *Me uint32 Index_Physical = SortEntry.Block_Layer_Index; block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); if (Layer->IsSelected) { - History_Action_Swap(Memory, F_File, sizeof(Layer->Block_Composition_Index), &Layer->Block_Composition_Index); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->Block_Composition_Index), &Layer->Block_Composition_Index); Layer->Block_Composition_Index = File->Comp_Count - 1; } } diff --git a/src/imgui_ui.cpp b/src/imgui_ui.cpp index 7c8adf9..871c69d 100644 --- a/src/imgui_ui.cpp +++ b/src/imgui_ui.cpp @@ -192,6 +192,14 @@ ImGui_Key_GetUIInfo(key_entry KeyEntry, real32 KeySize, ImVec2 *Offset_ScreenPos *KeyScreenSize = (KeyEntry.WidthRatio > 0.0f) ? ImVec2(KeySize * KeyEntry.WidthRatio, KeySize) : ImVec2(KeySize, KeySize * -KeyEntry.WidthRatio); } +inline void +ImGui_DrawCenteredRect(ImDrawList *draw_list, ImVec2 Point, real32 Width, uint32 col) +{ + ImVec2 MinPos = Point - ImVec2(Width/2, Width/2); + ImVec2 MaxPos = Point + ImVec2(Width/2, Width/2); + draw_list->AddRectFilled(MinPos, MaxPos, col); +} + static void ImGui_KeybindUI(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io) { @@ -433,6 +441,7 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me History_Entry_Commit(Memory, "Duplicate layers"); v2 Offset = V2(State->Interact_Dup_Previous[0], State->Interact_Dup_Previous[1]); Project_Layer_Duplicate(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Offset, 0); + State->Interact_Transform = {}; History_Entry_End(Memory); } else { State->Tool = tool_pen; diff --git a/src/imgui_ui_timeline.cpp b/src/imgui_ui_timeline.cpp index a85d58e..29b2835 100644 --- a/src/imgui_ui_timeline.cpp +++ b/src/imgui_ui_timeline.cpp @@ -466,8 +466,10 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem #else sprintf(buf, "%s", String->Char); #endif - if (UI->TimelinePercentZoomed.y <= 1.0f) - draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, buf); + if (UI->TimelinePercentZoomed.y <= 1.0f) { + real32 TextX = (Layer_ScreenPos_Min.x > TimelineAbsolutePos.x) ? Layer_ScreenPos_Min.x : TimelineAbsolutePos.x; + draw_list->AddText(ImVec2(TextX, Layer_ScreenPos_Min.y), 0xFFFFFFFF, buf); + } if (Layer->IsSelected == 1) { draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2); @@ -541,8 +543,8 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); if (Layer->IsSelected) { // NOTE(fox): Some data on the tree could be saved here. - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Start), &Layer->Frame_Start); - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_End), &Layer->Frame_End); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->Frame_Start), &Layer->Frame_Start); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->Frame_End), &Layer->Frame_End); Interact_Evaluate_Layer(Memory, State, Index_Physical, SortedCompStart, SortedLayerStart, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Frame_Offset); } } @@ -580,7 +582,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem History_Entry_Commit(Memory, "Toggle visibility"); Commit = true; } - History_Action_Swap(Memory, F_File, sizeof(Layer->IsVisible), &Layer->IsVisible); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->IsVisible), &Layer->IsVisible); Layer->IsVisible ^= 1; } } @@ -681,10 +683,10 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem uint32 Index_Physical = SortEntry.Block_Layer_Index; block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); // NOTE(fox): Some data on the tree could be saved here. - History_Action_Swap(Memory, F_File, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset); Layer->Vertical_Offset = SortEntry.SortedOffset; if (Layer->IsSelected) { - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Offset), &Layer->Frame_Offset); + History_Action_Swap(Memory, F_Layers, sizeof(Layer->Frame_Offset), &Layer->Frame_Offset); Interact_Evaluate_Layer(Memory, State, Index_Physical, SortedCompStart, SortedLayerStart, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Frame_Offset); } } diff --git a/src/imgui_ui_viewport.cpp b/src/imgui_ui_viewport.cpp index c846c7e..749999d 100644 --- a/src/imgui_ui_viewport.cpp +++ b/src/imgui_ui_viewport.cpp @@ -3,7 +3,6 @@ #include "main.h" #endif - static void ImGui_Viewport_Toolbar(project_state *State, ImDrawList *draw_list) { @@ -133,6 +132,8 @@ ImGui_Viewport_ShapeUI(project_state *State, memory *Memory, ui *UI, ImGuiIO &io if (IsItemDeactivated) { if (Layer == NULL && a == 0 && i == 0 && Shape->IsClosed == false) { History_Entry_Commit(Memory, "Close shape"); + Assert(0); + // which one?? History_Action_Swap(Memory, F_File, sizeof(Shape->IsClosed), &Shape->IsClosed); Shape->IsClosed = true; History_Entry_End(Memory); @@ -261,7 +262,7 @@ T_FindBestFit(int PointCount, v2 *PointData, v2 *Center, v2 *NewCenter, v2 *Best *BestMin = Min; *BestMax = Max; *BestRadians = 0; - // real32 Angles[4] = { 15, 30, 45, 60 }; + // TODO(fox): Make more efficient and more precise. for (real32 i = 0; i < 90; i+= 1) { v2 NewMin = {}, NewMax = {}; real32 NewArea = T_AreaAtAngle(PointCount, PointData, *Center, i, &NewMin, &NewMax); @@ -294,7 +295,8 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me real32 Scale = 1; if (Interact->Min.x == 0.0f) { - T_FindBestFit(*PointCount, PointData, &Interact->OGCenter, &Interact->NewCenter, &Interact->Min, &Interact->Max, &Interact->RadianOffset); + if (*PointCount > 0) + T_FindBestFit(*PointCount, PointData, &Interact->OGCenter, &Interact->NewCenter, &Interact->Min, &Interact->Max, &Interact->RadianOffset); // Interact->RadianOffset += Interact->Scale = 1.0f; } @@ -394,8 +396,8 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me real32 U = LayerPoint.x / BoxLength.x; real32 V = LayerPoint.y / BoxLength.y; - DebugWatchVar("U", &U, d_float); - DebugWatchVar("V", &V, d_float); + // DebugWatchVar("U", &U, d_float); + // DebugWatchVar("V", &V, d_float); ImVec2 ScaleHandleSize(50, 50); @@ -407,9 +409,18 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me ImGui::PushID(i); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertFloat4ToU32(ImVec4(0.6f, 0.0f, 0.3f, 1.0f))); - ImGui::Button("##ScaleMids", ScaleHandleSize); + ImGui::InvisibleButton("##ScaleMids", ScaleHandleSize); ImGui::PopStyleColor(); + ImGui_DrawCenteredRect(draw_list, Mid_P[i], 12, IM_COL32(20, 20, 20, 255)); + ImGui_DrawCenteredRect(draw_list, Mid_P[i], 10, IM_COL32(20, 20, 220, 255)); + ImGui_DrawCenteredRect(draw_list, Mid_P[i], 6, IM_COL32(255, 255, 225, 50)); + + + if (ImGui::GetMouseCursor() != ImGuiMouseCursor_None && ImGui::IsItemHovered() && !OtherActions) { + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS); + } + if (ImGui::IsItemActivated() && !OtherActions) { State->Interact_Active = interact_type_viewport_transform_gizmo; State->InteractTransformMode = 1; @@ -420,36 +431,56 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me uint32 side = i; v2 Dir = {}; if (i == 0) { - Dir = V2(-1, 1); + Dir = V2(1, -1); } else if (i == 1) { - Dir = V2(1, 1); + Dir = V2(-1, -1); } else if (i == 2) { - Dir = V2(1, -1); + Dir = V2(-1, 0); } else if (i == 3) { - Dir = V2(-1, -1); + Dir = V2(1, 0); } else { Assert(0); } + // InteractMin + V2(BoxLength.x * 0.5, 0), InteractMin + V2(0, BoxLength.y * 0.5), + // InteractMax - V2(BoxLength.x * 0.5, 0), InteractMax - V2(0, BoxLength.y * 0.5) }; + + ImVec2 LengthVec = (io.MousePos - io.MouseClickedPos[0]) / CompScale; real32 NegRad = -Rad; v2 UnrotatedLengthVec = {}; { v2 XAxis = (LengthVec.x * 1.0f)*V2(cos(NegRad), sin(NegRad)); v2 YAxis = (LengthVec.y * -1.0f)*V2(sin(NegRad), -cos(NegRad)); - v2 UnrotatedLengthVec = XAxis + YAxis; + UnrotatedLengthVec = XAxis + YAxis; } real32 Length = UnrotatedLengthVec.x * Dir.x; - DebugWatchVar("Len", &Length, d_float); real32 BoxAxis = BoxLength.x; Interact->Scale = 1.0f + Length / BoxAxis; v2 MovePos = V2((Length / 2), -(Length / 2) * (BoxLength.y / BoxLength.x)); v2 XAxis = (MovePos.x * Dir.x)*V2(cos(Rad), sin(Rad)); v2 YAxis = (MovePos.y * Dir.y)*V2(sin(Rad), -cos(Rad)); v2 Pos = XAxis + YAxis; - Interact->Position.x = Pos.x; - Interact->Position.y = Pos.y; + + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; +#if 0 + if (i == 0) { + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; + } else if (i == 1) { + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; + } else if (i == 2) { + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; + } else if (i == 3) { + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; + } +#endif + } ImGui::PopID(); @@ -459,7 +490,7 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me // Scale if cursor is on button within the UV, rotate if outside UV, and position if a non-button is dragged. if (U >= 0.0f && U <= 1.0f && V >= 0.0f && V <= 1.0f) { - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertFloat4ToU32(ImVec4(0.6f, 0.0f, 0.3f, 1.0f))); + // ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertFloat4ToU32(ImVec4(0.6f, 0.0f, 0.3f, 1.0f))); InBounds = true; } @@ -467,7 +498,19 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me for (int i = 0; i < 4; i++) { ImGui::SetCursorScreenPos(P[i] - ScaleHandleSize/2); ImGui::PushID(i); - ImGui::Button("##ScaleRotateCorners", ScaleHandleSize); + ImGui::InvisibleButton("##ScaleRotateCorners", ScaleHandleSize); + + ImGui_DrawCenteredRect(draw_list, P[i], 12, IM_COL32(80, 80, 80, 255)); + ImGui_DrawCenteredRect(draw_list, P[i], 10, IM_COL32(20, 20, 220, 255)); + ImGui_DrawCenteredRect(draw_list, P[i], 6, IM_COL32(255, 255, 225, 50)); + + if (ImGui::GetMouseCursor() != ImGuiMouseCursor_None && ImGui::IsItemHovered() && !OtherActions) { + if (InBounds) { + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNESW); + } else { + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); + } + } if (ImGui::IsItemActivated() && !OtherActions) { if (InBounds) @@ -545,6 +588,10 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me MouseRadians = 0.0f; Interact->Radians = Direction * MouseRadians; + if (io.KeyShift) { + real32 Angle = (Interact->Radians / (PI / 180)); + Interact->Radians = (int)(Angle / 15.0f) * 15.0f * (PI / 180); + } } ImGui::PopID(); } @@ -553,8 +600,11 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me v2 MouseLocalUV = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos); bool32 LayerHovered = Layer_TestForPoint(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex, MouseLocalUV); if (LayerHovered) { + if (ImGui::GetMouseCursor() == ImGuiMouseCursor_None) { + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + } ImGui::SetCursorScreenPos(io.MousePos - ScaleHandleSize/2); - ImGui::Button("##mover", ScaleHandleSize); + ImGui::InvisibleButton("##mover", ScaleHandleSize); if (!State->InteractTransformMode && ImGui::IsItemActivated() && !OtherActions) { State->Interact_Active = interact_type_viewport_transform_gizmo; State->InteractTransformMode = 3; @@ -598,7 +648,7 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me } if (InBounds == true) { - ImGui::PopStyleColor(); + // ImGui::PopStyleColor(); } } @@ -1159,7 +1209,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, BoxMin.y = (MousePos.y < ClickedPos.y) ? MousePos.y : ClickedPos.y; BoxMax.x = (MousePos.x > ClickedPos.x) ? MousePos.x : ClickedPos.x; BoxMax.y = (MousePos.y > ClickedPos.y) ? MousePos.y : ClickedPos.y; - if (BoxMax.x - BoxMin.x > 2.0f && BoxMax.y - BoxMin.y > 2.0f) { + if (BoxMax.x - BoxMin.x > 0.1f && BoxMax.y - BoxMin.y > 0.1f) { Assert(BoxMax.x > BoxMin.x && BoxMax.y > BoxMin.y) BoxMax.y = (MousePos.y > ClickedPos.y) ? MousePos.y : ClickedPos.y; @@ -1167,15 +1217,16 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, if (State->Tool == tool_default && State->Interact_Active == interact_type_none) { int32 Selection = Layer_TestSelection(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex); if (!State->InteractTransformMode && Selection != -1) { + Layer_DeselectAll(File, State, Memory); Layer_Select(Memory, State, Selection); State->Interact_Active = interact_type_viewport_transform_gizmo; + State->Interact_OutOfDrag = true; State->InteractTransformMode = 3; } else { State->Interact_Active = interact_type_viewport_selection; } } if (State->Interact_Active == interact_type_viewport_selection) { - Layer_DeselectAll(File, State, Memory); v2 MinPos_Comp = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, BoxMin) * V2(MainComp->Width, MainComp->Height); v2 MaxPos_Comp = ImGui_ScreenPointToCompUV(ViewportMax, UI->CompPos, UI->CompZoom, BoxMax) * V2(MainComp->Width, MainComp->Height); @@ -1191,18 +1242,27 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, } } - if (((io.KeyAlt && IsActivated && State->MostRecentlySelectedLayer == -1) || - (IsHovered && IsDeactivated && !io.KeyCtrl && !io.KeyAlt)) && - !ImGui::IsMouseDown(ImGuiMouseButton_Right) && !ImGui::IsKeyDown(ImGuiKey_Z)) - { - // Layer selection - if (State->Tool == tool_default && State->Interact_Active == interact_type_none) { - int32 Selection = Layer_TestSelection(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex); - if (!io.KeyShift && State->Interact_Active == interact_type_none) - Layer_DeselectAll(File, State, Memory); - if (Selection != -1) - Layer_Select(Memory, State, Selection); - } + bool32 Delta = (io.MouseDelta.x || io.MouseDelta.y); + if (IsActivated || IsDeactivated) { + if (((io.KeyAlt && IsActivated && State->MostRecentlySelectedLayer == -1) || + (IsHovered && IsDeactivated && !Delta && !io.KeyCtrl && !io.KeyAlt)) && + !ImGui::IsMouseDown(ImGuiMouseButton_Right) && !ImGui::IsKeyDown(ImGuiKey_Z)) + { + if (State->Interact_OutOfDrag) { + State->Interact_OutOfDrag = 0; + } else { + // Layer selection + int32 Selection = Layer_TestSelection(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex); + if (State->Tool == tool_default && State->Interact_Active == interact_type_none) { + if (!io.KeyShift && State->Interact_Active == interact_type_none) { + Layer_DeselectAll(File, State, Memory); + State->Interact_Transform = {}; + } + if (Selection != -1) + Layer_Select(Memory, State, Selection); + } + } + } } if (IsDeactivated && State->Interact_Active == interact_type_viewport_selection) { diff --git a/src/include/all.h b/src/include/all.h index e2a2a2f..08a96e6 100644 --- a/src/include/all.h +++ b/src/include/all.h @@ -507,6 +507,10 @@ Transform_Recurse(project_state *State, memory *Memory, block_composition *MainC sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, real32 *MinX, real32 *MinY, real32 *MaxX, real32 *MaxY); + +inline void +ImGui_DrawCenteredRect(ImDrawList *draw_list, ImVec2 Point, real32 Width, uint32 col); + static bool32 Layer_TestForPoint(memory *Memory, project_state *State, ui *UI, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 PrincipalIndex, v2 CompUV); diff --git a/src/include/functions.h b/src/include/functions.h index 4ded552..4c4ea2d 100644 --- a/src/include/functions.h +++ b/src/include/functions.h @@ -44,6 +44,8 @@ static layer_transforms Transform_Inverse(layer_transforms T); static v2 T_CompPosToLayerPos(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, real32 X, real32 Y); +inline void +ImGui_DrawCenteredRect(ImDrawList *draw_list, ImVec2 Point, real32 Width, uint32 col) static void ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_file Sorted); static void ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, sorted_property_array *SortedPropertyStart, uint16 *SortedKeyframeArray); diff --git a/src/include/main.h b/src/include/main.h index 38e9105..e1d1787 100644 --- a/src/include/main.h +++ b/src/include/main.h @@ -490,6 +490,7 @@ struct project_state interact_transform Interact_Transform; interact_type Interact_Active; int32 Interact_Modifier; + bool32 Interact_OutOfDrag; // TODO(fox): replace this real32 Interact_Offset[12]; real32 Interact_Dup_Previous[2]; void *Interact_Address; -- cgit v1.2.3