diff --git a/src/app/editor/foldhaus_editor.cpp b/src/app/editor/foldhaus_editor.cpp new file mode 100644 index 0000000..d2e1f6f --- /dev/null +++ b/src/app/editor/foldhaus_editor.cpp @@ -0,0 +1,107 @@ +// +// File: foldhaus_editor.cpp +// Author: Peter Slattery +// Creation Date: 2020-10-24 +// +#ifndef FOLDHAUS_EDITOR_CPP + +internal void +Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse, context Context) +{ + DEBUG_TRACK_FUNCTION; + + b32 PanelSystemHandledInput = HandleMousePanelInteraction(&State->PanelSystem, State->WindowBounds, Mouse, State); + + if (!PanelSystemHandledInput) + { + input_command_registry ActiveCommands = {}; + if (State->Modes.ActiveModesCount > 0) + { + ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands; + } + else + { + panel* PanelWithMouseOverIt = GetPanelContainingPoint(Mouse.Pos, State->PanelSystem.Panels + 0); + if (!PanelWithMouseOverIt) { return; } + State->HotPanel = PanelWithMouseOverIt; + + s32 PanelTypeIndex = PanelWithMouseOverIt->TypeIndex; + panel_definition PanelDefinition = GlobalPanelDefs[PanelTypeIndex]; + if (!PanelDefinition.InputCommands) { return; } + + ActiveCommands.Commands = PanelDefinition.InputCommands; + ActiveCommands.Size = sizeof(*PanelDefinition.InputCommands) / sizeof(PanelDefinition.InputCommands[0]); + ActiveCommands.Used = ActiveCommands.Size; + } + + for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++) + { + input_entry Event = InputQueue.Entries[EventIdx]; + + // NOTE(Peter): These are in the order Down, Up, Held because we want to privalege + // Down and Up over Held. In other words, we don't want to call a Held command on the + // frame when the button was released, even if the command is registered to both events + if (KeyTransitionedDown(Event)) + { + FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue); + } + else if (KeyTransitionedUp(Event)) + { + FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue); + } + else if (KeyHeldDown(Event)) + { + FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue); + } + } + } + + // Execute all commands in CommandQueue + for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--) + { + command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx]; + Entry->Command.Proc(State, Entry->Event, Mouse, Context); + } + + ClearCommandQueue(&State->CommandQueue); +} + +internal void +Editor_Update(app_state* State, context* Context, input_queue InputQueue) +{ + Context->Mouse.CursorType = CursorType_Arrow; + State->WindowBounds = Context->WindowBounds; + State->Interface.Mouse = Context->Mouse; + State->Camera.AspectRatio = RectAspectRatio(Context->WindowBounds); + + PanelSystem_UpdateLayout(&State->PanelSystem, State->WindowBounds); + Editor_HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context); +} + +internal void +Editor_Render(app_state* State, context* Context, render_command_buffer* RenderBuffer) +{ + PushRenderOrthographic(RenderBuffer, State->WindowBounds); + PushRenderClearScreen(RenderBuffer); + + State->Interface.RenderBuffer = RenderBuffer; + + DrawAllPanels(State->PanelSystem, RenderBuffer, &Context->Mouse, State, *Context); + + for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) + { + operation_mode OperationMode = State->Modes.ActiveModes[m]; + if (OperationMode.Render != 0) + { + OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context); + } + } + + Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext); + Context->GeneralWorkQueue->ResetWorkQueue(Context->GeneralWorkQueue); + +} + + +#define FOLDHAUS_EDITOR_CPP +#endif // FOLDHAUS_EDITOR_CPP \ No newline at end of file diff --git a/src/app/editor/foldhaus_interface.cpp b/src/app/editor/foldhaus_interface.cpp index 28a24c2..8b7878c 100644 --- a/src/app/editor/foldhaus_interface.cpp +++ b/src/app/editor/foldhaus_interface.cpp @@ -13,6 +13,8 @@ enum panel_edit_mode { + PanelEdit_Invalid, + PanelEdit_Modify, PanelEdit_Destroy, @@ -111,6 +113,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) else { Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / Rect2Height(PanelBounds); + Panel_UpdateLayout(Panel, PanelBounds); } } else if (Panel->SplitDirection == PanelSplit_Vertical) @@ -127,6 +130,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) else { Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / Rect2Width(PanelBounds); + Panel_UpdateLayout(Panel, PanelBounds); } } } @@ -239,9 +243,9 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) s32 PanelTypeIndex = Panel->TypeIndex; gs_data PanelStateMemory = Panel->StateMemory; - Panel_SetCurrentType(&Panel->Left->Panel, &State->PanelSystem, PanelTypeIndex, PanelStateMemory, State, Context); + Panel_SetCurrentType(Panel->Left, &State->PanelSystem, PanelTypeIndex, PanelStateMemory, State, Context); - SetAndInitPanelType(&Panel->Right->Panel, &State->PanelSystem, PanelTypeIndex, State, Context); + SetAndInitPanelType(Panel->Right, &State->PanelSystem, PanelTypeIndex, State, Context); DeactivateCurrentOperationMode(&State->Modes); } @@ -251,12 +255,12 @@ input_command SplitPanelCommands[] = { }; internal void -BeginSplitPanelOperation(panel* Panel, rect2 PanelBounds, mouse_state Mouse, app_state* State) +BeginSplitPanelOperation(panel* Panel, mouse_state Mouse, app_state* State) { operation_mode* SplitPanel = ActivateOperationModeWithCommands(&State->Modes, SplitPanelCommands, UpdateAndRenderSplitPanel); split_panel_operation_state* OpState = CreateOperationState(SplitPanel, &State->Modes, split_panel_operation_state); OpState->Panel = Panel; - OpState->InitialPanelBounds = PanelBounds; + OpState->InitialPanelBounds = Panel->Bounds; } @@ -265,61 +269,44 @@ BeginSplitPanelOperation(panel* Panel, rect2 PanelBounds, mouse_state Mouse, app #define PANEL_EDGE_CLICK_MAX_DISTANCE 6 internal b32 -HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, rect2 PanelBounds, mouse_state Mouse, app_state* State) +HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, mouse_state Mouse, app_state* State) { b32 HandledMouseInput = false; - rect2 PanelSplitButtonBounds = rect2{ PanelBounds.Min, PanelBounds.Min + v2{25, 25} }; + // TODO(pjs): this can probably live in panel_with_layout + rect2 PanelSplitButtonBounds = rect2{ Panel->Bounds.Min, Panel->Bounds.Min + v2{25, 25} }; if (Panel->SplitDirection == PanelSplit_NoSplit && PointIsInRect(PanelSplitButtonBounds, Mouse.DownPos)) { - BeginSplitPanelOperation(Panel, PanelBounds, Mouse, State); + BeginSplitPanelOperation(Panel, Mouse, State); HandledMouseInput = true; } - else if (Panel->SplitDirection == PanelSplit_Horizontal) + else if (Panel->SplitDirection != PanelSplit_NoSplit) { - r32 SplitY = LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); - r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.y - SplitY); + u32 ElementIndex = 0; + switch(Panel->SplitDirection) + { + case PanelSplit_Vertical: { ElementIndex = 0; } break; + case PanelSplit_Horizontal: { ElementIndex = 1; } break; + InvalidDefaultCase; + } + + r32 SplitPosition = LerpR32(Panel->SplitPercent, Panel->Bounds.Min.E[ElementIndex], Panel->Bounds.Max.E[ElementIndex]); + r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.E[ElementIndex] - SplitPosition); if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE) { - BeginDragPanelBorder(Panel, PanelEditMode, PanelBounds, PanelSplit_Horizontal, Mouse, State); - HandledMouseInput = true; + BeginDragPanelBorder(Panel, PanelEditMode, Panel->Bounds, Panel->SplitDirection, Mouse, State); } else { - rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - if (PointIsInRect(BottomPanelBounds, Mouse.DownPos)) + if (PointIsInRect(Panel->Bottom->Bounds, Mouse.DownPos)) { - HandleMouseDownPanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelEditMode, BottomPanelBounds, Mouse, State); + HandleMouseDownPanelInteractionOrRecurse(Panel->Bottom, PanelEditMode, Mouse, State); } - if (PointIsInRect(TopPanelBounds, Mouse.DownPos)) + else if (PointIsInRect(Panel->Top->Bounds, Mouse.DownPos)) { - HandleMouseDownPanelInteractionOrRecurse(&Panel->Top->Panel, PanelEditMode, TopPanelBounds, Mouse, State); - } - } - } - else if (Panel->SplitDirection == PanelSplit_Vertical) - { - r32 SplitX = LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); - r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.x - SplitX); - if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE) - { - BeginDragPanelBorder(Panel, PanelEditMode, PanelBounds, PanelSplit_Vertical, Mouse, State); - HandledMouseInput = true; - } - else - { - rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - if (PointIsInRect(LeftPanelBounds, Mouse.DownPos)) - { - HandleMouseDownPanelInteractionOrRecurse(&Panel->Left->Panel, PanelEditMode, LeftPanelBounds, Mouse, State); - } - if (PointIsInRect(RightPanelBounds, Mouse.DownPos)) - { - HandleMouseDownPanelInteractionOrRecurse(&Panel->Right->Panel, PanelEditMode, RightPanelBounds, Mouse, State); + HandleMouseDownPanelInteractionOrRecurse(Panel->Top, PanelEditMode, Mouse, State); } } } @@ -332,14 +319,21 @@ HandleMousePanelInteraction(panel_system* PanelSystem, rect2 WindowBounds, mouse { b32 HandledMouseInput = false; - panel* FirstPanel = &PanelSystem->Panels[0].Panel; + panel* FirstPanel = PanelSystem->Panels + 0; + panel_edit_mode EditMode = PanelEdit_Invalid; + if (MouseButtonTransitionedDown(Mouse.LeftButtonState)) { - HandledMouseInput = HandleMouseDownPanelInteractionOrRecurse(FirstPanel, PanelEdit_Modify, WindowBounds, Mouse, State); + EditMode = PanelEdit_Modify; } else if (MouseButtonTransitionedDown(Mouse.RightButtonState)) { - HandledMouseInput = HandleMouseDownPanelInteractionOrRecurse(FirstPanel, PanelEdit_Destroy, WindowBounds, Mouse, State); + EditMode = PanelEdit_Destroy; + } + + if (EditMode != PanelEdit_Invalid) + { + HandledMouseInput = HandleMouseDownPanelInteractionOrRecurse(FirstPanel, EditMode, Mouse, State); } return HandledMouseInput; @@ -456,21 +450,36 @@ RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_ } internal void -DrawAllPanels(panel_layout PanelLayout, render_command_buffer* RenderBuffer, mouse_state* Mouse, app_state* State, context Context) +DrawPanelRecursive(panel* Panel, render_command_buffer* RenderBuffer, mouse_state* Mouse, app_state* State, context Context) { - for (u32 i = 0; i < PanelLayout.PanelsCount; i++) + switch (Panel->SplitDirection) { - panel_with_layout PanelWithLayout = PanelLayout.Panels[i]; - panel* Panel = PanelWithLayout.Panel; - rect2 PanelBounds = PanelWithLayout.Bounds; + case PanelSplit_Horizontal: + case PanelSplit_Vertical: + { + DrawPanelRecursive(Panel->Left, RenderBuffer, Mouse, State, Context); + DrawPanelRecursive(Panel->Right, RenderBuffer, Mouse, State, Context); + }break; - RenderPanel(Panel, PanelBounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse); - v4 BorderColor = v4{0, 0, 0, 1}; + case PanelSplit_NoSplit: + { + RenderPanel(Panel, Panel->Bounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse); + v4 BorderColor = v4{0, 0, 0, 1}; + + PushRenderOrthographic(RenderBuffer, State->WindowBounds); + DrawPanelBorder(*Panel, Panel->Bounds.Min, Panel->Bounds.Max, BorderColor, Mouse, RenderBuffer); + }break; - PushRenderOrthographic(RenderBuffer, State->WindowBounds); - DrawPanelBorder(*Panel, PanelBounds.Min, PanelBounds.Max, BorderColor, Mouse, RenderBuffer); + InvalidDefaultCase; } } +internal void +DrawAllPanels(panel_system System, render_command_buffer* RenderBuffer, mouse_state* Mouse, app_state* State, context Context) +{ + panel* PanelAt = System.Panels + 0; + DrawPanelRecursive(PanelAt, RenderBuffer, Mouse, State, Context); +} + #define FOLDHAUS_INTERFACE_CPP #endif // FOLDHAUS_INTERFACE_CPP \ No newline at end of file diff --git a/src/app/editor/foldhaus_panel.h b/src/app/editor/foldhaus_panel.h index 658a8a3..81961b9 100644 --- a/src/app/editor/foldhaus_panel.h +++ b/src/app/editor/foldhaus_panel.h @@ -18,7 +18,6 @@ enum panel_split_direction PanelSplit_Count, }; -typedef struct panel_entry panel_entry; typedef struct panel panel; #define PANEL_MODAL_OVERRIDE_CALLBACK(name) void name(panel* ReturningFrom, app_state* State, context Context) @@ -29,10 +28,11 @@ struct panel s32 TypeIndex; gs_data StateMemory; - panel_entry* ModalOverride; - panel* IsModalOverrideFor; // TODO(pjs): I don't like that this is panel* but ModalOverride is panel_entry* + panel* ModalOverride; + panel* IsModalOverrideFor; panel_modal_override_callback* ModalOverrideCB; + rect2 Bounds; panel_split_direction SplitDirection; r32 SplitPercent; @@ -40,25 +40,21 @@ struct panel // Probably belongs in a more generalized PanelInterfaceState or something b32 PanelSelectionMenuOpen; + panel* Parent; + union{ - panel_entry* Left; - panel_entry* Top; + panel* Left; + panel* Top; }; union{ - panel_entry* Right; - panel_entry* Bottom; + panel* Right; + panel* Bottom; }; }; struct free_panel { - panel_entry* Next; -}; - -struct panel_entry -{ - panel Panel; - free_panel Free; + free_panel* Next; }; #define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State, context Context) @@ -88,26 +84,10 @@ struct panel_system panel_definition* PanelDefs; u32 PanelDefsCount; - panel_entry Panels[PANELS_MAX]; + panel Panels[PANELS_MAX]; u32 PanelsUsed; - panel_entry FreeList; -}; - -// NOTE(Peter): This representation is used to let external code render and interact -// with panels. It shouldn't be stored across frame boundaries as the pointers to -// Panel's are liable to change. -struct panel_with_layout -{ - panel* Panel; - rect2 Bounds; -}; - -struct panel_layout -{ - panel_with_layout* Panels; - u32 PanelsCount; - u32 PanelsMax; + free_panel* FreeList; }; ///////////////////////////////// @@ -119,19 +99,20 @@ struct panel_layout internal void InitializePanelSystem(panel_system* PanelSystem, panel_definition* PanelDefs, u32 PanelDefsCount) { - PanelSystem->FreeList.Free.Next = &PanelSystem->FreeList; + PanelSystem->FreeList = 0; PanelSystem->PanelDefs = PanelDefs; PanelSystem->PanelDefsCount = PanelDefsCount; } -internal panel_entry* +internal panel* TakeNewPanelEntry(panel_system* PanelSystem) { - panel_entry* FreeEntry = 0; - if (PanelSystem->FreeList.Free.Next != &PanelSystem->FreeList) + panel* FreeEntry = 0; + if (PanelSystem->FreeList != 0) { - FreeEntry = PanelSystem->FreeList.Free.Next; - PanelSystem->FreeList.Free.Next = FreeEntry->Free.Next; + free_panel* FreePanel = PanelSystem->FreeList; + PanelSystem->FreeList = FreePanel->Next; + FreeEntry = (panel*)PanelSystem->FreeList; } else { @@ -142,43 +123,24 @@ TakeNewPanelEntry(panel_system* PanelSystem) } internal void -FreePanelEntry(panel_entry* Entry, panel_system* PanelSystem) +FreePanelEntry(panel* Panel, panel_system* PanelSystem) { - Assert(Entry >= PanelSystem->Panels && Entry <= PanelSystem->Panels + PANELS_MAX); - Entry->Panel = {0}; - Entry->Free.Next = PanelSystem->FreeList.Free.Next; - PanelSystem->FreeList.Free.Next = Entry; + Assert(Panel >= PanelSystem->Panels && Panel <= PanelSystem->Panels + PANELS_MAX); + + free_panel* FreeEntry = (free_panel*)Panel; + FreeEntry->Next = PanelSystem->FreeList; + PanelSystem->FreeList = FreeEntry; } internal void -FreePanelEntryRecursive(panel_entry* Entry, panel_system* PanelSystem) +FreePanelEntryRecursive(panel* Panel, panel_system* PanelSystem) { - if (Entry->Panel.SplitDirection != PanelSplit_NoSplit) + if (Panel->SplitDirection != PanelSplit_NoSplit) { - FreePanelEntryRecursive(Entry->Panel.Left, PanelSystem); - FreePanelEntryRecursive(Entry->Panel.Right, PanelSystem); + FreePanelEntryRecursive(Panel->Left, PanelSystem); + FreePanelEntryRecursive(Panel->Right, PanelSystem); } - FreePanelEntry(Entry, PanelSystem); -} - -internal void -FreePanelAtIndex(s32 Index, panel_system* PanelSystem) -{ - Assert(Index > 0 && Index < (s32)PanelSystem->PanelsUsed); - panel_entry* EntryToFree = PanelSystem->Panels + Index; - EntryToFree->Free.Next = PanelSystem->FreeList.Free.Next; - PanelSystem->FreeList.Free.Next = EntryToFree; -} - -internal panel_entry* -Panel_GetModalOverride(panel_entry* PanelEntry) -{ - panel_entry* Result = PanelEntry; - if (PanelEntry->Panel.ModalOverride != 0) - { - Result = Panel_GetModalOverride(PanelEntry->Panel.ModalOverride); - } - return Result; + FreePanelEntry(Panel, PanelSystem); } internal panel* @@ -187,17 +149,17 @@ Panel_GetModalOverride(panel* Panel) panel* Result = Panel; if (Panel->ModalOverride != 0) { - Result = &Panel_GetModalOverride(Panel->ModalOverride)->Panel; + Result = Panel_GetModalOverride(Panel->ModalOverride); } return Result; } internal void -Panel_PushModalOverride(panel* Root, panel_entry* Override, panel_modal_override_callback* Callback) +Panel_PushModalOverride(panel* Root, panel* Override, panel_modal_override_callback* Callback) { Root->ModalOverride = Override; Root->ModalOverrideCB = Callback; - Override->Panel.IsModalOverrideFor = Root; + Override->IsModalOverrideFor = Root; } internal void @@ -239,12 +201,12 @@ Panel_GetStateMemory(panel* Panel, u64 Size) return Result; } -internal panel_entry* +internal panel* PanelSystem_PushPanel(panel_system* PanelSystem, s32 PanelTypeIndex, app_state* State, context Context) { - panel_entry* PanelEntry = TakeNewPanelEntry(PanelSystem); - SetAndInitPanelType(&PanelEntry->Panel, PanelSystem, PanelTypeIndex, State, Context); - return PanelEntry; + panel* Panel = TakeNewPanelEntry(PanelSystem); + SetAndInitPanelType(Panel, PanelSystem, PanelTypeIndex, State, Context); + return Panel; } internal void @@ -257,11 +219,14 @@ SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, pan s32 ParentTypeIndex = Parent->TypeIndex; gs_data ParentStateMemory = Parent->StateMemory; + Parent->Left = TakeNewPanelEntry(PanelSystem); - Panel_SetCurrentType(&Parent->Left->Panel, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context); + Panel_SetCurrentType(Parent->Left, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context); + Parent->Left->Parent = Parent; Parent->Right = TakeNewPanelEntry(PanelSystem); - Panel_SetCurrentType(&Parent->Right->Panel, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context); + Panel_SetCurrentType(Parent->Right, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context); + Parent->Right->Parent = Parent; } } @@ -278,17 +243,17 @@ SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem, ap } internal void -ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_system* PanelSystem) +ConsolidatePanelsKeepOne(panel* Parent, panel* PanelToKeep, panel_system* PanelSystem) { - panel_entry* LeftChild = Parent->Left; - panel_entry* RightChild = Parent->Right; + panel* LeftChild = Parent->Left; + panel* RightChild = Parent->Right; - panel_entry* PanelEntryToDestroy = PanelEntryToKeep == LeftChild ? RightChild : LeftChild; + panel* PanelToDestroy = PanelToKeep == LeftChild ? RightChild : LeftChild; - *Parent = PanelEntryToKeep->Panel; + *Parent = *PanelToKeep; - FreePanelEntry(PanelEntryToKeep, PanelSystem); - FreePanelEntryRecursive(PanelEntryToDestroy, PanelSystem); + FreePanelEntry(PanelToKeep, PanelSystem); + FreePanelEntryRecursive(PanelToDestroy, PanelSystem); } ///////////////////////////////// @@ -297,6 +262,54 @@ ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_sys // ///////////////////////////////// +internal rect2 +GetTopPanelBounds(panel* Panel) +{ + rect2 Result = {}; + Result.Min = v2{ + Panel->Bounds.Min.x, + LerpR32(Panel->SplitPercent, Panel->Bounds.Min.y, Panel->Bounds.Max.y) + }; + Result.Max = Panel->Bounds.Max; + return Result; +} + +internal rect2 +GetBottomPanelBounds(panel* Panel) +{ + rect2 Result = {}; + Result.Min = Panel->Bounds.Min; + Result.Max = v2{ + Panel->Bounds.Max.x, + LerpR32(Panel->SplitPercent, Panel->Bounds.Min.y, Panel->Bounds.Max.y) + }; + return Result; +} + +internal rect2 +GetRightPanelBounds(panel* Panel) +{ + rect2 Result = {}; + Result.Min = v2{ + LerpR32(Panel->SplitPercent, Panel->Bounds.Min.x, Panel->Bounds.Max.x), + Panel->Bounds.Min.y + }; + Result.Max = Panel->Bounds.Max; + return Result; +} + +internal rect2 +GetLeftPanelBounds(panel* Panel) +{ + rect2 Result = {}; + Result.Min = Panel->Bounds.Min; + Result.Max = v2{ + LerpR32(Panel->SplitPercent, Panel->Bounds.Min.x, Panel->Bounds.Max.x), + Panel->Bounds.Max.y + }; + return Result; +} + internal rect2 GetTopPanelBounds(panel* Panel, rect2 PanelBounds) { @@ -346,103 +359,77 @@ GetLeftPanelBounds(panel* Panel, rect2 PanelBounds) } internal void -LayoutPanel(panel* Panel, rect2 PanelBounds, panel_layout* Layout) +Panel_UpdateLayout(panel* Panel, rect2 Bounds) { - if (Panel->SplitDirection == PanelSplit_NoSplit) + Panel->Bounds = Bounds; + + if (Panel->SplitDirection != PanelSplit_NoSplit) { - panel_with_layout* WithLayout = Layout->Panels + Layout->PanelsCount++; - WithLayout->Panel = Panel_GetModalOverride(Panel); - WithLayout->Bounds = PanelBounds; - } - else if (Panel->SplitDirection == PanelSplit_Horizontal) - { - rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + rect2 LeftOrTopBounds = {}; + rect2 RightOrBottomBounds = {}; + switch (Panel->SplitDirection) + { + case PanelSplit_Horizontal: + { + LeftOrTopBounds = GetTopPanelBounds(Panel); + RightOrBottomBounds = GetBottomPanelBounds(Panel); + } break; + + case PanelSplit_Vertical: + { + LeftOrTopBounds = GetLeftPanelBounds(Panel); + RightOrBottomBounds = GetRightPanelBounds(Panel); + } break; + + InvalidDefaultCase; + } - panel* TopPanel = Panel_GetModalOverride(&Panel->Top->Panel); - panel* BottomPanel = Panel_GetModalOverride(&Panel->Bottom->Panel); - - LayoutPanel(&Panel->Top->Panel, TopPanelBounds, Layout); - LayoutPanel(&Panel->Bottom->Panel, BottomPanelBounds, Layout); - } - else if (Panel->SplitDirection == PanelSplit_Vertical) - { - rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - - panel* LeftPanel = Panel_GetModalOverride(&Panel->Top->Panel); - panel* RightPanel = Panel_GetModalOverride(&Panel->Bottom->Panel); - - LayoutPanel(&Panel->Left->Panel, LeftPanelBounds, Layout); - LayoutPanel(&Panel->Right->Panel, RightPanelBounds, Layout); + Panel_UpdateLayout(Panel->Left, LeftOrTopBounds); + Panel_UpdateLayout(Panel->Right, RightOrBottomBounds); } } -internal panel_layout -GetPanelLayout(panel_system* System, rect2 WindowBounds, gs_memory_arena* Storage) +internal void +PanelSystem_UpdateLayout(panel_system* System, rect2 WindowBounds) { - panel_layout Result = {}; - Result.PanelsMax = System->PanelsUsed; - Result.Panels = PushArray(Storage, panel_with_layout, Result.PanelsMax); - - LayoutPanel(&System->Panels[0].Panel, WindowBounds, &Result); - - return Result; + panel* Root = System->Panels; + Panel_UpdateLayout(Root, WindowBounds); } -internal panel_with_layout -GetPanelContainingPoint(v2 Point, panel* Panel, rect2 PanelBounds) +internal panel* +GetPanelContainingPoint(v2 Point, panel* Panel) { - panel_with_layout Result = {0}; + panel* Result = 0; - if (Panel->SplitDirection == PanelSplit_NoSplit) + if (PointIsInRect(Panel->Bounds, Point)) { - Result.Panel = Panel; - Result.Bounds = PanelBounds; - } - else if (Panel->SplitDirection == PanelSplit_Horizontal) - { - rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - - if (PointIsInRect(TopPanelBounds, Point)) + switch (Panel->SplitDirection) { - Result = GetPanelContainingPoint(Point, &Panel->Top->Panel, TopPanelBounds); - } - else if (PointIsInRect(BottomPanelBounds, Point)) - { - Result = GetPanelContainingPoint(Point, &Panel->Bottom->Panel, BottomPanelBounds); - } - } - else if (Panel->SplitDirection == PanelSplit_Vertical) - { - rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - - if (PointIsInRect(LeftPanelBounds, Point)) - { - Result = GetPanelContainingPoint(Point, &Panel->Left->Panel, LeftPanelBounds); - } - else if (PointIsInRect(RightPanelBounds, Point)) - { - Result = GetPanelContainingPoint(Point, &Panel->Right->Panel, RightPanelBounds); + case PanelSplit_NoSplit: + { + Result = Panel; + }break; + + case PanelSplit_Vertical: + case PanelSplit_Horizontal: + { + if (PointIsInRect(Panel->Left->Bounds, Point)) + { + Result = GetPanelContainingPoint(Point, Panel->Left); + } + else if (PointIsInRect(Panel->Right->Bounds, Point)) + { + Result = GetPanelContainingPoint(Point, Panel->Right); + } + }break; + + InvalidDefaultCase; } } return Result; } -internal panel_with_layout -GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect2 WindowBounds) -{ - panel_with_layout Result = {0}; - if (PanelSystem->PanelsUsed > 0) - { - Result = GetPanelContainingPoint(Point, &PanelSystem->Panels[0].Panel, WindowBounds); - } - return Result; -} - #define FOLDHAUS_PANEL_H #endif // FOLDHAUS_PANEL_H \ No newline at end of file diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index a37dc78..ee26944 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -264,9 +264,9 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand) { animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); - panel_with_layout ActivePanel = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, State->WindowBounds); + panel* ActivePanel = GetPanelContainingPoint(Mouse.Pos, State->PanelSystem.Panels + 0); frame_range Range = ActiveAnim->PlayableRange; - u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel.Bounds, Range); + u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, ActivePanel->Bounds, Range); handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, State->SelectedAnimationLayer); SelectAnimationBlock(NewBlockHandle, State); @@ -641,7 +641,7 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Load"))) { - panel_entry* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); + panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); Panel_PushModalOverride(Panel, FileBrowser, LoadAnimationFileCallback); } } diff --git a/src/app/editor/panels/foldhaus_panel_hierarchy.h b/src/app/editor/panels/foldhaus_panel_hierarchy.h index fdecc36..2c076b3 100644 --- a/src/app/editor/panels/foldhaus_panel_hierarchy.h +++ b/src/app/editor/panels/foldhaus_panel_hierarchy.h @@ -75,7 +75,7 @@ HierarchyView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren PrintF(&TempString, "+ Add Assembly"); if (ui_ListButton(&State->Interface, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) { - panel_entry* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); + panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context); Panel_PushModalOverride(Panel, FileBrowser, LoadAssemblyCallback); } } diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index af0c7ae..f4afde3 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -162,66 +162,6 @@ INITIALIZE_APPLICATION(InitializeApplication) PanelSystem_PushPanel(&State->PanelSystem, PanelType_SculptureView, State, Context); } -internal void -HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse, context Context) -{ - DEBUG_TRACK_FUNCTION; - - b32 PanelSystemHandledInput = HandleMousePanelInteraction(&State->PanelSystem, State->WindowBounds, Mouse, State); - if (!PanelSystemHandledInput) - { - input_command_registry ActiveCommands = {}; - if (State->Modes.ActiveModesCount > 0) - { - ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands; - } - else - { - panel_with_layout PanelWithMouseOverIt = GetPanelContainingPoint(Mouse.Pos, &State->PanelSystem, WindowBounds); - if (!PanelWithMouseOverIt.Panel) { return; } - State->HotPanel = PanelWithMouseOverIt.Panel; - - s32 PanelTypeIndex = PanelWithMouseOverIt.Panel->TypeIndex; - panel_definition PanelDefinition = GlobalPanelDefs[PanelTypeIndex]; - if (!PanelDefinition.InputCommands) { return; } - - ActiveCommands.Commands = PanelDefinition.InputCommands; - ActiveCommands.Size = sizeof(*PanelDefinition.InputCommands) / sizeof(PanelDefinition.InputCommands[0]); - ActiveCommands.Used = ActiveCommands.Size; - } - - for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++) - { - input_entry Event = InputQueue.Entries[EventIdx]; - - // NOTE(Peter): These are in the order Down, Up, Held because we want to privalege - // Down and Up over Held. In other words, we don't want to call a Held command on the - // frame when the button was released, even if the command is registered to both events - if (KeyTransitionedDown(Event)) - { - FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue); - } - else if (KeyTransitionedUp(Event)) - { - FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue); - } - else if (KeyHeldDown(Event)) - { - FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue); - } - } - } - - // Execute all commands in CommandQueue - for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--) - { - command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx]; - Entry->Command.Proc(State, Entry->Event, Mouse, Context); - } - - ClearCommandQueue(&State->CommandQueue); -} - UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_FUNCTION; @@ -232,12 +172,8 @@ UPDATE_AND_RENDER(UpdateAndRender) // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically // incorrect to clear the arena, and then access the memory later. ClearArena(State->Transient); - Context->Mouse.CursorType = CursorType_Arrow; - PushRenderClearScreen(RenderBuffer); - State->Camera.AspectRatio = RectAspectRatio(Context->WindowBounds); - - HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context); + Editor_Update(State, Context, InputQueue); { animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem); @@ -348,27 +284,7 @@ UPDATE_AND_RENDER(UpdateAndRender) UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem); } - PushRenderOrthographic(RenderBuffer, State->WindowBounds); - PushRenderClearScreen(RenderBuffer); - - State->WindowBounds = Context->WindowBounds; - State->Interface.RenderBuffer = RenderBuffer; - State->Interface.Mouse = Context->Mouse; - - panel_layout PanelsToRender = GetPanelLayout(&State->PanelSystem, State->WindowBounds, State->Transient); - DrawAllPanels(PanelsToRender, RenderBuffer, &Context->Mouse, State, *Context); - - for (s32 m = 0; m < State->Modes.ActiveModesCount; m++) - { - operation_mode OperationMode = State->Modes.ActiveModes[m]; - if (OperationMode.Render != 0) - { - OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context); - } - } - - Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext); - Context->GeneralWorkQueue->ResetWorkQueue(Context->GeneralWorkQueue); + Editor_Render(State, Context, RenderBuffer); // Checking for overflows #if 0 diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 05bd69f..60937fc 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -233,5 +233,7 @@ animation_clip GlobalAnimationClips[] = { #include "../meta/gs_meta_include.cpp" +#include "editor/foldhaus_editor.cpp" + #define FOLDHAUS_APP_H #endif // FOLDHAUS_APP_H \ No newline at end of file diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h index e36f2ed..e647f5c 100644 --- a/src/gs_libs/gs_types.h +++ b/src/gs_libs/gs_types.h @@ -231,7 +231,7 @@ struct u64_array # define InvalidDefaultCase default: { AssertBreak("invalid default case"); } break; # define StaticAssert(c) \ enum { \ -Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \ + Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \ } #else # define Assert(c)