2020-01-02 02:41:43 +00:00
|
|
|
//
|
|
|
|
// File: foldhaus_panel.h
|
|
|
|
// Author: Peter Slattery
|
|
|
|
// Creation Date: 2019-12-26
|
|
|
|
//
|
|
|
|
// Usage:
|
2020-06-10 03:33:51 +00:00
|
|
|
// Include this file in ONE file in your project.
|
2020-01-02 02:41:43 +00:00
|
|
|
// Define SetPanelDefinitionExternal
|
|
|
|
//
|
|
|
|
#ifndef FOLDHAUS_PANEL_H
|
2019-12-26 20:42:55 +00:00
|
|
|
|
|
|
|
enum panel_split_direction
|
|
|
|
{
|
|
|
|
PanelSplit_NoSplit,
|
2019-12-28 18:51:47 +00:00
|
|
|
PanelSplit_Horizontal,
|
2019-12-26 20:42:55 +00:00
|
|
|
PanelSplit_Vertical,
|
|
|
|
|
|
|
|
PanelSplit_Count,
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct panel_entry panel_entry;
|
2020-10-18 22:31:53 +00:00
|
|
|
typedef struct panel panel;
|
|
|
|
|
|
|
|
#define PANEL_MODAL_OVERRIDE_CALLBACK(name) void name(panel* ReturningFrom, app_state* State, context Context)
|
|
|
|
typedef PANEL_MODAL_OVERRIDE_CALLBACK(panel_modal_override_callback);
|
2019-12-26 20:42:55 +00:00
|
|
|
|
|
|
|
struct panel
|
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
s32 TypeIndex;
|
|
|
|
gs_data StateMemory;
|
2020-10-17 19:43:05 +00:00
|
|
|
|
2020-10-18 22:31:53 +00:00
|
|
|
panel_entry* ModalOverride;
|
|
|
|
panel* IsModalOverrideFor; // TODO(pjs): I don't like that this is panel* but ModalOverride is panel_entry*
|
|
|
|
panel_modal_override_callback* ModalOverrideCB;
|
2019-12-26 21:14:00 +00:00
|
|
|
|
2019-12-26 20:42:55 +00:00
|
|
|
panel_split_direction SplitDirection;
|
|
|
|
r32 SplitPercent;
|
|
|
|
|
|
|
|
// TODO(Peter): This REALLY doesn't want to live here
|
|
|
|
// Probably belongs in a more generalized PanelInterfaceState or something
|
|
|
|
b32 PanelSelectionMenuOpen;
|
|
|
|
|
|
|
|
union{
|
2019-12-28 18:51:47 +00:00
|
|
|
panel_entry* Left;
|
2019-12-26 20:42:55 +00:00
|
|
|
panel_entry* Top;
|
|
|
|
};
|
|
|
|
union{
|
|
|
|
panel_entry* Right;
|
|
|
|
panel_entry* Bottom;
|
2019-12-28 18:51:47 +00:00
|
|
|
};
|
2019-12-26 20:42:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct free_panel
|
|
|
|
{
|
|
|
|
panel_entry* Next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct panel_entry
|
|
|
|
{
|
|
|
|
panel Panel;
|
2019-12-28 18:51:47 +00:00
|
|
|
free_panel Free;
|
2019-12-26 20:42:55 +00:00
|
|
|
};
|
|
|
|
|
2020-10-18 22:31:53 +00:00
|
|
|
#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State, context Context)
|
|
|
|
typedef PANEL_INIT_PROC(panel_init_proc);
|
|
|
|
|
|
|
|
#define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State)
|
|
|
|
typedef PANEL_CLEANUP_PROC(panel_cleanup_proc);
|
|
|
|
|
|
|
|
#define PANEL_RENDER_PROC(name) void name(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
|
|
|
typedef PANEL_RENDER_PROC(panel_render_proc);
|
|
|
|
|
|
|
|
// NOTE(Peter): This is used by the meta system to generate panel type info
|
|
|
|
struct panel_definition
|
|
|
|
{
|
|
|
|
char* PanelName;
|
|
|
|
s32 PanelNameLength;
|
|
|
|
panel_init_proc* Init;
|
|
|
|
panel_cleanup_proc* Cleanup;
|
|
|
|
panel_render_proc* Render;
|
|
|
|
input_command* InputCommands;
|
|
|
|
s32 InputCommandsCount;
|
|
|
|
};
|
|
|
|
|
2019-12-26 20:42:55 +00:00
|
|
|
#define PANELS_MAX 16
|
2019-12-28 21:02:19 +00:00
|
|
|
struct panel_system
|
2019-12-26 20:42:55 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
panel_definition* PanelDefs;
|
|
|
|
u32 PanelDefsCount;
|
|
|
|
|
2019-12-28 18:51:47 +00:00
|
|
|
panel_entry Panels[PANELS_MAX];
|
2019-12-26 20:42:55 +00:00
|
|
|
u32 PanelsUsed;
|
|
|
|
|
2019-12-28 18:51:47 +00:00
|
|
|
panel_entry FreeList;
|
2019-12-26 20:42:55 +00:00
|
|
|
};
|
|
|
|
|
2019-12-28 21:02:19 +00:00
|
|
|
// NOTE(Peter): This representation is used to let external code render and interact
|
2020-06-10 03:33:51 +00:00
|
|
|
// with panels. It shouldn't be stored across frame boundaries as the pointers to
|
|
|
|
// Panel's are liable to change.
|
2019-12-28 21:02:19 +00:00
|
|
|
struct panel_with_layout
|
|
|
|
{
|
|
|
|
panel* Panel;
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 Bounds;
|
2019-12-28 21:02:19 +00:00
|
|
|
};
|
2019-12-26 21:14:00 +00:00
|
|
|
|
2019-12-28 21:02:19 +00:00
|
|
|
struct panel_layout
|
|
|
|
{
|
|
|
|
panel_with_layout* Panels;
|
|
|
|
u32 PanelsCount;
|
|
|
|
u32 PanelsMax;
|
|
|
|
};
|
|
|
|
|
2019-12-26 21:14:00 +00:00
|
|
|
/////////////////////////////////
|
|
|
|
//
|
|
|
|
// Book-Keeping
|
|
|
|
//
|
|
|
|
/////////////////////////////////
|
|
|
|
|
|
|
|
internal void
|
2020-10-18 22:31:53 +00:00
|
|
|
InitializePanelSystem(panel_system* PanelSystem, panel_definition* PanelDefs, u32 PanelDefsCount)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2019-12-28 21:02:19 +00:00
|
|
|
PanelSystem->FreeList.Free.Next = &PanelSystem->FreeList;
|
2020-10-18 22:31:53 +00:00
|
|
|
PanelSystem->PanelDefs = PanelDefs;
|
|
|
|
PanelSystem->PanelDefsCount = PanelDefsCount;
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal panel_entry*
|
2019-12-28 21:02:19 +00:00
|
|
|
TakeNewPanelEntry(panel_system* PanelSystem)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
|
|
|
panel_entry* FreeEntry = 0;
|
2019-12-28 21:02:19 +00:00
|
|
|
if (PanelSystem->FreeList.Free.Next != &PanelSystem->FreeList)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2019-12-28 21:02:19 +00:00
|
|
|
FreeEntry = PanelSystem->FreeList.Free.Next;
|
|
|
|
PanelSystem->FreeList.Free.Next = FreeEntry->Free.Next;
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-28 21:02:19 +00:00
|
|
|
Assert(PanelSystem->PanelsUsed < PANELS_MAX);
|
|
|
|
FreeEntry = PanelSystem->Panels + PanelSystem->PanelsUsed++;
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
return FreeEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2019-12-28 21:02:19 +00:00
|
|
|
FreePanelEntry(panel_entry* Entry, panel_system* PanelSystem)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2019-12-28 21:02:19 +00:00
|
|
|
Assert(Entry >= PanelSystem->Panels && Entry <= PanelSystem->Panels + PANELS_MAX);
|
2019-12-26 21:14:00 +00:00
|
|
|
Entry->Panel = {0};
|
2019-12-28 21:02:19 +00:00
|
|
|
Entry->Free.Next = PanelSystem->FreeList.Free.Next;
|
|
|
|
PanelSystem->FreeList.Free.Next = Entry;
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
|
2019-12-28 23:01:02 +00:00
|
|
|
internal void
|
|
|
|
FreePanelEntryRecursive(panel_entry* Entry, panel_system* PanelSystem)
|
|
|
|
{
|
|
|
|
if (Entry->Panel.SplitDirection != PanelSplit_NoSplit)
|
|
|
|
{
|
|
|
|
FreePanelEntryRecursive(Entry->Panel.Left, PanelSystem);
|
|
|
|
FreePanelEntryRecursive(Entry->Panel.Right, PanelSystem);
|
|
|
|
}
|
|
|
|
FreePanelEntry(Entry, PanelSystem);
|
|
|
|
}
|
|
|
|
|
2019-12-26 21:14:00 +00:00
|
|
|
internal void
|
2019-12-28 21:02:19 +00:00
|
|
|
FreePanelAtIndex(s32 Index, panel_system* PanelSystem)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2019-12-28 21:02:19 +00:00
|
|
|
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;
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 22:31:53 +00:00
|
|
|
internal panel_entry*
|
|
|
|
Panel_GetModalOverride(panel_entry* PanelEntry)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
panel_entry* Result = PanelEntry;
|
|
|
|
if (PanelEntry->Panel.ModalOverride != 0)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
Result = Panel_GetModalOverride(PanelEntry->Panel.ModalOverride);
|
2020-10-17 19:43:05 +00:00
|
|
|
}
|
2020-10-18 22:31:53 +00:00
|
|
|
return Result;
|
2020-10-17 19:43:05 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 22:31:53 +00:00
|
|
|
internal panel*
|
|
|
|
Panel_GetModalOverride(panel* Panel)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
panel* Result = Panel;
|
|
|
|
if (Panel->ModalOverride != 0)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
Result = &Panel_GetModalOverride(Panel->ModalOverride)->Panel;
|
2020-10-17 19:43:05 +00:00
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2020-10-18 22:31:53 +00:00
|
|
|
internal void
|
|
|
|
Panel_PushModalOverride(panel* Root, panel_entry* Override, panel_modal_override_callback* Callback)
|
2020-10-17 20:12:40 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
Root->ModalOverride = Override;
|
|
|
|
Root->ModalOverrideCB = Callback;
|
|
|
|
Override->Panel.IsModalOverrideFor = Root;
|
2020-10-17 20:12:40 +00:00
|
|
|
}
|
|
|
|
|
2020-10-17 19:43:05 +00:00
|
|
|
internal void
|
2020-10-18 22:31:53 +00:00
|
|
|
Panel_PopModalOverride(panel* Parent, panel_system* System)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
// TODO(pjs): Free the overrided panel
|
|
|
|
FreePanelEntry(Parent->ModalOverride, System);
|
|
|
|
Parent->ModalOverride = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
Panel_SetCurrentType(panel* Panel, panel_system* System, s32 NewPanelType, gs_data TypeStateMemory, app_state* State, context Context)
|
|
|
|
{
|
|
|
|
s32 OldTypeIndex = Panel->TypeIndex;
|
|
|
|
|
|
|
|
Panel->TypeIndex = NewPanelType;
|
|
|
|
Panel->StateMemory = TypeStateMemory;
|
|
|
|
|
|
|
|
if(OldTypeIndex >= 0)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
System->PanelDefs[OldTypeIndex].Cleanup(Panel, State);
|
2020-10-17 19:43:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2020-10-18 22:31:53 +00:00
|
|
|
SetAndInitPanelType(panel* Panel, panel_system* System, s32 NewPanelTypeIndex, app_state* State, context Context)
|
|
|
|
{
|
|
|
|
gs_data EmptyStateData = {0};
|
|
|
|
Panel_SetCurrentType(Panel, System, NewPanelTypeIndex, EmptyStateData, State, Context);
|
|
|
|
System->PanelDefs[NewPanelTypeIndex].Init(Panel, State, Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define Panel_GetStateStruct(p, type) (type*)Panel_GetStateMemory((p), sizeof(type)).Memory
|
|
|
|
internal gs_data
|
|
|
|
Panel_GetStateMemory(panel* Panel, u64 Size)
|
|
|
|
{
|
|
|
|
Assert(Panel->StateMemory.Size == Size);
|
|
|
|
gs_data Result = Panel->StateMemory;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal panel_entry*
|
|
|
|
PanelSystem_PushPanel(panel_system* PanelSystem, s32 PanelTypeIndex, app_state* State, context Context)
|
2020-10-17 19:43:05 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
panel_entry* PanelEntry = TakeNewPanelEntry(PanelSystem);
|
|
|
|
SetAndInitPanelType(&PanelEntry->Panel, PanelSystem, PanelTypeIndex, State, Context);
|
|
|
|
return PanelEntry;
|
2020-10-17 19:43:05 +00:00
|
|
|
}
|
|
|
|
|
2019-12-26 21:14:00 +00:00
|
|
|
internal void
|
2020-10-18 22:31:53 +00:00
|
|
|
SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, panel_system* PanelSystem, app_state* State, context Context)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2020-06-10 03:33:51 +00:00
|
|
|
if (Percent >= 0.0f && Percent <= 1.0f)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2020-10-10 23:52:00 +00:00
|
|
|
Parent->SplitDirection = SplitDirection;
|
2019-12-28 18:51:47 +00:00
|
|
|
Parent->SplitPercent = Percent;
|
|
|
|
|
2020-10-18 22:31:53 +00:00
|
|
|
s32 ParentTypeIndex = Parent->TypeIndex;
|
|
|
|
gs_data ParentStateMemory = Parent->StateMemory;
|
2019-12-28 21:02:19 +00:00
|
|
|
Parent->Left = TakeNewPanelEntry(PanelSystem);
|
2020-10-18 22:31:53 +00:00
|
|
|
Panel_SetCurrentType(&Parent->Left->Panel, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context);
|
2019-12-28 18:51:47 +00:00
|
|
|
|
2019-12-28 21:02:19 +00:00
|
|
|
Parent->Right = TakeNewPanelEntry(PanelSystem);
|
2020-10-18 22:31:53 +00:00
|
|
|
Panel_SetCurrentType(&Parent->Right->Panel, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context);
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-10 23:52:00 +00:00
|
|
|
internal void
|
2020-10-18 22:31:53 +00:00
|
|
|
SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem, app_state* State, context Context)
|
2020-10-10 23:52:00 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
SplitPanel(Parent, Percent, PanelSplit_Vertical, PanelSystem, State, Context);
|
2020-10-10 23:52:00 +00:00
|
|
|
}
|
|
|
|
|
2019-12-26 21:14:00 +00:00
|
|
|
internal void
|
2020-10-18 22:31:53 +00:00
|
|
|
SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem, app_state* State, context Context)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
2020-10-18 22:31:53 +00:00
|
|
|
SplitPanel(Parent, Percent, PanelSplit_Horizontal, PanelSystem, State, Context);
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2019-12-28 21:02:19 +00:00
|
|
|
ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_system* PanelSystem)
|
2019-12-26 21:14:00 +00:00
|
|
|
{
|
|
|
|
panel_entry* LeftChild = Parent->Left;
|
|
|
|
panel_entry* RightChild = Parent->Right;
|
|
|
|
|
2019-12-28 23:01:02 +00:00
|
|
|
panel_entry* PanelEntryToDestroy = PanelEntryToKeep == LeftChild ? RightChild : LeftChild;
|
|
|
|
|
2019-12-26 21:14:00 +00:00
|
|
|
*Parent = PanelEntryToKeep->Panel;
|
|
|
|
|
2019-12-28 23:01:02 +00:00
|
|
|
FreePanelEntry(PanelEntryToKeep, PanelSystem);
|
|
|
|
FreePanelEntryRecursive(PanelEntryToDestroy, PanelSystem);
|
2019-12-26 21:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////
|
|
|
|
//
|
|
|
|
// Rendering And Interaction
|
|
|
|
//
|
|
|
|
/////////////////////////////////
|
|
|
|
|
2020-07-18 19:00:14 +00:00
|
|
|
internal rect2
|
|
|
|
GetTopPanelBounds(panel* Panel, rect2 PanelBounds)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 Result = {};
|
2019-12-28 18:51:47 +00:00
|
|
|
Result.Min = v2{
|
|
|
|
PanelBounds.Min.x,
|
2020-07-18 19:00:14 +00:00
|
|
|
LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y)
|
2019-12-28 18:51:47 +00:00
|
|
|
};
|
|
|
|
Result.Max = PanelBounds.Max;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2020-07-18 19:00:14 +00:00
|
|
|
internal rect2
|
|
|
|
GetBottomPanelBounds(panel* Panel, rect2 PanelBounds)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 Result = {};
|
2019-12-28 18:51:47 +00:00
|
|
|
Result.Min = PanelBounds.Min;
|
|
|
|
Result.Max = v2{
|
|
|
|
PanelBounds.Max.x,
|
2020-07-18 19:00:14 +00:00
|
|
|
LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y)
|
2019-12-28 18:51:47 +00:00
|
|
|
};
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2020-07-18 19:00:14 +00:00
|
|
|
internal rect2
|
|
|
|
GetRightPanelBounds(panel* Panel, rect2 PanelBounds)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 Result = {};
|
2019-12-28 18:51:47 +00:00
|
|
|
Result.Min = v2{
|
2020-07-18 19:00:14 +00:00
|
|
|
LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x),
|
2019-12-28 18:51:47 +00:00
|
|
|
PanelBounds.Min.y
|
|
|
|
};
|
|
|
|
Result.Max = PanelBounds.Max;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2020-07-18 19:00:14 +00:00
|
|
|
internal rect2
|
|
|
|
GetLeftPanelBounds(panel* Panel, rect2 PanelBounds)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 Result = {};
|
2019-12-28 18:51:47 +00:00
|
|
|
Result.Min = PanelBounds.Min;
|
|
|
|
Result.Max = v2{
|
2020-07-18 19:00:14 +00:00
|
|
|
LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x),
|
2019-12-28 18:51:47 +00:00
|
|
|
PanelBounds.Max.y
|
|
|
|
};
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2019-12-28 21:02:19 +00:00
|
|
|
internal void
|
2020-07-18 19:00:14 +00:00
|
|
|
LayoutPanel(panel* Panel, rect2 PanelBounds, panel_layout* Layout)
|
2019-12-28 21:02:19 +00:00
|
|
|
{
|
|
|
|
if (Panel->SplitDirection == PanelSplit_NoSplit)
|
|
|
|
{
|
|
|
|
panel_with_layout* WithLayout = Layout->Panels + Layout->PanelsCount++;
|
2020-10-18 22:31:53 +00:00
|
|
|
WithLayout->Panel = Panel_GetModalOverride(Panel);
|
2019-12-28 21:02:19 +00:00
|
|
|
WithLayout->Bounds = PanelBounds;
|
|
|
|
}
|
|
|
|
else if (Panel->SplitDirection == PanelSplit_Horizontal)
|
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds);
|
|
|
|
rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds);
|
2020-10-18 22:31:53 +00:00
|
|
|
|
|
|
|
panel* TopPanel = Panel_GetModalOverride(&Panel->Top->Panel);
|
|
|
|
panel* BottomPanel = Panel_GetModalOverride(&Panel->Bottom->Panel);
|
|
|
|
|
2019-12-28 21:02:19 +00:00
|
|
|
LayoutPanel(&Panel->Top->Panel, TopPanelBounds, Layout);
|
|
|
|
LayoutPanel(&Panel->Bottom->Panel, BottomPanelBounds, Layout);
|
|
|
|
}
|
|
|
|
else if (Panel->SplitDirection == PanelSplit_Vertical)
|
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds);
|
|
|
|
rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds);
|
2020-10-18 22:31:53 +00:00
|
|
|
|
|
|
|
panel* LeftPanel = Panel_GetModalOverride(&Panel->Top->Panel);
|
|
|
|
panel* RightPanel = Panel_GetModalOverride(&Panel->Bottom->Panel);
|
|
|
|
|
2019-12-28 21:02:19 +00:00
|
|
|
LayoutPanel(&Panel->Left->Panel, LeftPanelBounds, Layout);
|
|
|
|
LayoutPanel(&Panel->Right->Panel, RightPanelBounds, Layout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal panel_layout
|
2020-07-18 19:00:14 +00:00
|
|
|
GetPanelLayout(panel_system* System, rect2 WindowBounds, gs_memory_arena* Storage)
|
2019-12-28 21:02:19 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-10-10 23:52:00 +00:00
|
|
|
internal panel_with_layout
|
2020-07-18 19:00:14 +00:00
|
|
|
GetPanelContainingPoint(v2 Point, panel* Panel, rect2 PanelBounds)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2020-10-10 23:52:00 +00:00
|
|
|
panel_with_layout Result = {0};
|
2019-12-28 18:51:47 +00:00
|
|
|
|
|
|
|
if (Panel->SplitDirection == PanelSplit_NoSplit)
|
|
|
|
{
|
|
|
|
Result.Panel = Panel;
|
|
|
|
Result.Bounds = PanelBounds;
|
|
|
|
}
|
|
|
|
else if (Panel->SplitDirection == PanelSplit_Horizontal)
|
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds);
|
|
|
|
rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds);
|
2019-12-28 18:51:47 +00:00
|
|
|
|
2020-07-18 19:00:14 +00:00
|
|
|
if (PointIsInRect(TopPanelBounds, Point))
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
|
|
|
Result = GetPanelContainingPoint(Point, &Panel->Top->Panel, TopPanelBounds);
|
|
|
|
}
|
2020-07-18 19:00:14 +00:00
|
|
|
else if (PointIsInRect(BottomPanelBounds, Point))
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
|
|
|
Result = GetPanelContainingPoint(Point, &Panel->Bottom->Panel, BottomPanelBounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (Panel->SplitDirection == PanelSplit_Vertical)
|
|
|
|
{
|
2020-07-18 19:00:14 +00:00
|
|
|
rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds);
|
|
|
|
rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds);
|
2019-12-28 18:51:47 +00:00
|
|
|
|
2020-07-18 19:00:14 +00:00
|
|
|
if (PointIsInRect(LeftPanelBounds, Point))
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
|
|
|
Result = GetPanelContainingPoint(Point, &Panel->Left->Panel, LeftPanelBounds);
|
|
|
|
}
|
2020-07-18 19:00:14 +00:00
|
|
|
else if (PointIsInRect(RightPanelBounds, Point))
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
|
|
|
Result = GetPanelContainingPoint(Point, &Panel->Right->Panel, RightPanelBounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2020-10-10 23:52:00 +00:00
|
|
|
internal panel_with_layout
|
2020-07-18 19:00:14 +00:00
|
|
|
GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect2 WindowBounds)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2020-10-10 23:52:00 +00:00
|
|
|
panel_with_layout Result = {0};
|
2019-12-28 21:02:19 +00:00
|
|
|
if (PanelSystem->PanelsUsed > 0)
|
2019-12-28 18:51:47 +00:00
|
|
|
{
|
2019-12-28 21:02:19 +00:00
|
|
|
Result = GetPanelContainingPoint(Point, &PanelSystem->Panels[0].Panel, WindowBounds);
|
2019-12-28 18:51:47 +00:00
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
2020-01-02 02:41:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define FOLDHAUS_PANEL_H
|
|
|
|
#endif // FOLDHAUS_PANEL_H
|