Created a panel system and began moving everything over to it.
This commit is contained in:
parent
f491988c90
commit
9b9fe2f5e1
|
@ -15,147 +15,3 @@ FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlock)
|
||||||
State->SelectedAnimationBlockHandle = {0};
|
State->SelectedAnimationBlockHandle = {0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal animation_block_handle
|
|
||||||
DrawAnimationTimeline (animation_system* AnimationSystem, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse)
|
|
||||||
{
|
|
||||||
animation_block_handle Result = SelectedBlockHandle;
|
|
||||||
|
|
||||||
r32 AnimationPanelHeight = PanelMax.y - PanelMin.y;
|
|
||||||
r32 AnimationPanelWidth = PanelMax.x - PanelMin.x;
|
|
||||||
panel_result AnimationPanel = EvaluatePanel(RenderBuffer, PanelMin, PanelMax,
|
|
||||||
0, Interface);
|
|
||||||
|
|
||||||
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < AnimationSystem->BlocksCount; i++)
|
|
||||||
{
|
|
||||||
animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i];
|
|
||||||
if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; }
|
|
||||||
|
|
||||||
animation_block_handle CurrentBlockHandle = {};
|
|
||||||
CurrentBlockHandle.Index = i;
|
|
||||||
CurrentBlockHandle.Generation = AnimationBlockEntry.Generation;
|
|
||||||
|
|
||||||
animation_block AnimationBlockAt = AnimationBlockEntry.Block;
|
|
||||||
|
|
||||||
r32 StartTimePercent = AnimationBlockAt.StartTime / AnimationSystem->AnimationEnd;
|
|
||||||
r32 StartPosition = AnimationPanelWidth * StartTimePercent;
|
|
||||||
|
|
||||||
r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd;
|
|
||||||
r32 EndPosition = AnimationPanelWidth * EndTimePercent;
|
|
||||||
|
|
||||||
v2 Min = v2{StartPosition, 25};
|
|
||||||
v2 Max = v2{EndPosition, 75};
|
|
||||||
|
|
||||||
v4 BlockColor = BlackV4;
|
|
||||||
if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle))
|
|
||||||
{
|
|
||||||
BlockColor = PinkV4;
|
|
||||||
}
|
|
||||||
|
|
||||||
PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor);
|
|
||||||
PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4);
|
|
||||||
|
|
||||||
if (PointIsInRange(Mouse.Pos, Min, Max)
|
|
||||||
&& MouseButtonTransitionedDown(Mouse.LeftButtonState))
|
|
||||||
{
|
|
||||||
MouseDownAndNotHandled = false;
|
|
||||||
if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle))
|
|
||||||
{
|
|
||||||
// If the block is already selected, deselect it.
|
|
||||||
Result = {0};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result = CurrentBlockHandle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r32 TimePercent = AnimationSystem->Time / AnimationSystem->AnimationEnd;
|
|
||||||
r32 SliderPosition = AnimationPanelWidth * TimePercent;
|
|
||||||
PushRenderQuad2D(RenderBuffer, v2{SliderPosition, AnimationPanelHeight},
|
|
||||||
v2{SliderPosition + 1, 0}, WhiteV4);
|
|
||||||
|
|
||||||
if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, PanelMin, PanelMax))
|
|
||||||
{
|
|
||||||
r32 MouseDownPositionPercent = (Mouse.Pos.x - PanelMin.x) / AnimationPanelWidth;
|
|
||||||
r32 NewBlockTimeStart = MouseDownPositionPercent * AnimationSystem->AnimationEnd;
|
|
||||||
#define NEW_BLOCK_DURATION 1
|
|
||||||
r32 NewBlockTimeEnd = NewBlockTimeStart + NEW_BLOCK_DURATION;
|
|
||||||
|
|
||||||
animation_block Block = {0};
|
|
||||||
Block.StartTime = NewBlockTimeStart;
|
|
||||||
Block.EndTime = NewBlockTimeEnd;
|
|
||||||
Block.Proc = TestPatternThree;
|
|
||||||
|
|
||||||
animation_block_handle NewBlockHandle = AddAnimationBlock(Block, AnimationSystem);
|
|
||||||
Result = NewBlockHandle;
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal animation_block_handle
|
|
||||||
DrawAnimationPanel (animation_system* AnimationSystem,
|
|
||||||
v2 PanelMin, v2 PanelMax,
|
|
||||||
animation_block_handle SelectedBlockHandle,
|
|
||||||
render_command_buffer* RenderBuffer,
|
|
||||||
interface_config Interface, mouse_state Mouse)
|
|
||||||
{
|
|
||||||
animation_block_handle Result = SelectedBlockHandle;
|
|
||||||
|
|
||||||
r32 OptionsRowHeight = 25;
|
|
||||||
v2 TimelineMin = PanelMin;
|
|
||||||
v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight};
|
|
||||||
if (TimelineMax.y - TimelineMin.y > 0)
|
|
||||||
{
|
|
||||||
Result = DrawAnimationTimeline(AnimationSystem,
|
|
||||||
TimelineMin, TimelineMax,
|
|
||||||
SelectedBlockHandle,
|
|
||||||
RenderBuffer, Interface, Mouse);
|
|
||||||
}
|
|
||||||
|
|
||||||
v2 OptionsRowMin = v2{ PanelMin.x, TimelineMax.y };
|
|
||||||
v2 OptionsRowMax = PanelMax;
|
|
||||||
panel_result AnimationPanel = EvaluatePanel(RenderBuffer, OptionsRowMin, OptionsRowMax,
|
|
||||||
0, Interface);
|
|
||||||
|
|
||||||
r32 ButtonWidth = 35;
|
|
||||||
v2 ButtonMin = v2{0, 0};
|
|
||||||
v2 ButtonMax = v2{35, OptionsRowHeight - 2};
|
|
||||||
v2 ButtonAt = v2{OptionsRowMin.x + 1, OptionsRowMin.y + 1};
|
|
||||||
|
|
||||||
button_result PauseResult = EvaluateButton(RenderBuffer,
|
|
||||||
ButtonAt + ButtonMin, ButtonAt + ButtonMax,
|
|
||||||
MakeStringLiteral("Pause"),
|
|
||||||
Interface, Mouse);
|
|
||||||
ButtonAt.x += ButtonWidth + 2;
|
|
||||||
button_result PlayResult = EvaluateButton(RenderBuffer,
|
|
||||||
ButtonAt + ButtonMin, ButtonAt + ButtonMax,
|
|
||||||
MakeStringLiteral("Play"),
|
|
||||||
Interface, Mouse);
|
|
||||||
ButtonAt.x += ButtonWidth + 2;
|
|
||||||
button_result StopResult = EvaluateButton(RenderBuffer,
|
|
||||||
ButtonAt + ButtonMin, ButtonAt + ButtonMax,
|
|
||||||
MakeStringLiteral("Stop"),
|
|
||||||
Interface, Mouse);
|
|
||||||
|
|
||||||
if (PauseResult.Pressed)
|
|
||||||
{
|
|
||||||
AnimationSystem->TimelineShouldAdvance = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PlayResult.Pressed)
|
|
||||||
{
|
|
||||||
AnimationSystem->TimelineShouldAdvance = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StopResult.Pressed)
|
|
||||||
{
|
|
||||||
AnimationSystem->TimelineShouldAdvance = false;
|
|
||||||
AnimationSystem->Time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
|
@ -22,68 +22,6 @@ MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, r32 WindowWidth, r32 Win
|
||||||
return WorldPosition;
|
return WorldPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct draw_leds_job_data
|
|
||||||
{
|
|
||||||
led* LEDs;
|
|
||||||
pixel* Colors;
|
|
||||||
s32 StartIndex;
|
|
||||||
s32 OnePastLastIndex;
|
|
||||||
|
|
||||||
render_quad_batch_constructor* Batch;
|
|
||||||
|
|
||||||
m44 FaceCameraMatrix;
|
|
||||||
m44 ModelViewMatrix;
|
|
||||||
r32 LEDHalfWidth;
|
|
||||||
};
|
|
||||||
|
|
||||||
internal void
|
|
||||||
DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
|
|
||||||
{
|
|
||||||
DEBUG_TRACK_FUNCTION;
|
|
||||||
|
|
||||||
draw_leds_job_data* Data = (draw_leds_job_data*)JobData;
|
|
||||||
|
|
||||||
s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex;
|
|
||||||
|
|
||||||
quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2);
|
|
||||||
s32 TrisUsed = 0;
|
|
||||||
|
|
||||||
r32 HalfWidth = Data->LEDHalfWidth;
|
|
||||||
|
|
||||||
v4 P0_In = v4{-HalfWidth, -HalfWidth, 0, 1};
|
|
||||||
v4 P1_In = v4{HalfWidth, -HalfWidth, 0, 1};
|
|
||||||
v4 P2_In = v4{HalfWidth, HalfWidth, 0, 1};
|
|
||||||
v4 P3_In = v4{-HalfWidth, HalfWidth, 0, 1};
|
|
||||||
|
|
||||||
v2 UV0 = v2{0, 0};
|
|
||||||
v2 UV1 = v2{1, 0};
|
|
||||||
v2 UV2 = v2{1, 1};
|
|
||||||
v2 UV3 = v2{0, 1};
|
|
||||||
|
|
||||||
led* LED = Data->LEDs + Data->StartIndex;
|
|
||||||
for (s32 LEDIdx = 0;
|
|
||||||
LEDIdx < LEDCount;
|
|
||||||
LEDIdx++)
|
|
||||||
{
|
|
||||||
pixel PixelColor = Data->Colors[LED->Index];
|
|
||||||
v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f};
|
|
||||||
|
|
||||||
v4 V4Position = LED->Position;
|
|
||||||
V4Position.w = 0;
|
|
||||||
v4 P0 = P0_In + V4Position;
|
|
||||||
v4 P1 = P1_In + V4Position;
|
|
||||||
v4 P2 = P2_In + V4Position;
|
|
||||||
v4 P3 = P3_In + V4Position;
|
|
||||||
|
|
||||||
SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
|
|
||||||
P0, P1, P2, UV0, UV1, UV2, Color, Color, Color);
|
|
||||||
SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
|
|
||||||
P0, P2, P3, UV0, UV2, UV3, Color, Color, Color);
|
|
||||||
|
|
||||||
LED++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct send_sacn_job_data
|
struct send_sacn_job_data
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -328,6 +266,15 @@ BlockTwo.StartTime = 5;
|
||||||
|
|
||||||
State->AnimationSystem.AnimationEnd = 10;
|
State->AnimationSystem.AnimationEnd = 10;
|
||||||
} // End Animation Playground
|
} // End Animation Playground
|
||||||
|
|
||||||
|
|
||||||
|
{ // Panels Playground
|
||||||
|
InitializePanelLayout(&State->PanelLayout);
|
||||||
|
panel* Panel = TakeNewPanel(&State->PanelLayout);
|
||||||
|
SetPanelDefinition(Panel, GlobalPanelDefs[0]);
|
||||||
|
SplitPanelVertically(Panel, .5f, v2{0, 0}, v2{Context.WindowWidth, Context.WindowHeight}, &State->PanelLayout);
|
||||||
|
SetPanelDefinition(&Panel->Right->Panel, GlobalPanelDefs[1]);
|
||||||
|
} // End Panels Playground
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -495,11 +442,19 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight);
|
||||||
|
PushRenderClearScreen(RenderBuffer);
|
||||||
|
v2 WindowMin = v2{0, 0};
|
||||||
|
v2 WindowMax = v2{Context.WindowWidth, Context.WindowHeight};
|
||||||
|
HandleMousePanelInteraction(&State->PanelLayout, WindowMin, WindowMax, Mouse);
|
||||||
|
DrawAllPanels(State->PanelLayout, WindowMin, WindowMax, RenderBuffer, State->Interface, Mouse, State, Context);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Render Assembly
|
// Render Assembly
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
if (Context.WindowIsVisible)
|
if (Context.WindowIsVisible)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
State->Camera.AspectRatio = (r32)Context.WindowWidth / (r32)Context.WindowHeight;
|
State->Camera.AspectRatio = (r32)Context.WindowWidth / (r32)Context.WindowHeight;
|
||||||
|
|
||||||
m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera);
|
m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera);
|
||||||
|
@ -507,7 +462,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
|
|
||||||
r32 LEDHalfWidth = .5f;
|
r32 LEDHalfWidth = .5f;
|
||||||
|
|
||||||
PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight, State->Camera);
|
PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth / 2, Context.WindowHeight, State->Camera);
|
||||||
PushRenderClearScreen(RenderBuffer);
|
PushRenderClearScreen(RenderBuffer);
|
||||||
|
|
||||||
// TODO(Peter): Pretty sure this isn't working right now
|
// TODO(Peter): Pretty sure this isn't working right now
|
||||||
|
@ -561,7 +516,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Menu Bar
|
// Menu Bar
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
r32 TopBarHeight = 40;
|
r32 TopBarHeight = 40;
|
||||||
{
|
{
|
||||||
panel_result TopBarPanel = EvaluatePanel(RenderBuffer,
|
panel_result TopBarPanel = EvaluatePanel(RenderBuffer,
|
||||||
|
@ -623,6 +577,7 @@ State->SelectedAnimationBlockHandle,
|
||||||
DrawDebugInterface(RenderBuffer, 25,
|
DrawDebugInterface(RenderBuffer, 25,
|
||||||
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
|
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
|
||||||
Context.DeltaTime, State, State->Camera, Mouse, &State->Transient);
|
Context.DeltaTime, State, State->Camera, Mouse, &State->Transient);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checking for overflows
|
// Checking for overflows
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
typedef struct app_state app_state;
|
typedef struct app_state app_state;
|
||||||
|
|
||||||
|
#include "foldhaus_panel.h"
|
||||||
|
|
||||||
#include "foldhaus_command_dispatch.h"
|
#include "foldhaus_command_dispatch.h"
|
||||||
#include "foldhaus_command_dispatch.cpp"
|
#include "foldhaus_command_dispatch.cpp"
|
||||||
#include "foldhaus_operation_mode.h"
|
#include "foldhaus_operation_mode.h"
|
||||||
|
@ -63,6 +65,8 @@ struct app_state
|
||||||
|
|
||||||
animation_system AnimationSystem;
|
animation_system AnimationSystem;
|
||||||
animation_block_handle SelectedAnimationBlockHandle;
|
animation_block_handle SelectedAnimationBlockHandle;
|
||||||
|
|
||||||
|
panel_layout PanelLayout;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal void OpenColorPicker(app_state* State, v4* Address);
|
internal void OpenColorPicker(app_state* State, v4* Address);
|
||||||
|
@ -166,3 +170,11 @@ r32 GreenSize = 20.0f;
|
||||||
|
|
||||||
#include "foldhaus_interface.cpp"
|
#include "foldhaus_interface.cpp"
|
||||||
#include "animation/foldhaus_animation_interface.h"
|
#include "animation/foldhaus_animation_interface.h"
|
||||||
|
|
||||||
|
#include "panels/foldhaus_panel_sculpture_view.h"
|
||||||
|
#include "panels/foldhaus_panel_profiler.h"
|
||||||
|
#include "panels/foldhaus_panel_dmx_view.h"
|
||||||
|
#include "panels/foldhaus_panel_animation_timeline.h"
|
||||||
|
|
||||||
|
#include "generated/foldhaus_panels_generated.h"
|
||||||
|
#include "foldhaus_panel.cpp"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
#if 0
|
||||||
internal void
|
internal void
|
||||||
RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer,
|
RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer,
|
||||||
interface_config Interface, mouse_state Mouse,
|
interface_config Interface, mouse_state Mouse,
|
||||||
|
@ -188,6 +188,7 @@ DrawDebugFrameList (render_command_buffer* RenderBuffer, interface_config Interf
|
||||||
VisibleFrame, Memory);
|
VisibleFrame, Memory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_config Interface, r32 WindowWidth, r32 WindowHeight, r32 DeltaTime, app_state* State, camera Camera, mouse_state Mouse, memory_arena* Transient)
|
DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_config Interface, r32 WindowWidth, r32 WindowHeight, r32 DeltaTime, app_state* State, camera Camera, mouse_state Mouse, memory_arena* Transient)
|
||||||
|
@ -311,7 +312,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
|
||||||
v2 ProfilerMin = v2{TopOfDebugView.x, TopOfDebugView.y - 500};
|
v2 ProfilerMin = v2{TopOfDebugView.x, TopOfDebugView.y - 500};
|
||||||
v2 ProfilerMax = v2{TopOfDebugView.x + 700, TopOfDebugView.y - 64};
|
v2 ProfilerMax = v2{TopOfDebugView.x + 700, TopOfDebugView.y - 64};
|
||||||
PushRenderQuad2D(RenderBuffer, ProfilerMin, ProfilerMax, v4{0, 0, 0, .8f});
|
PushRenderQuad2D(RenderBuffer, ProfilerMin, ProfilerMax, v4{0, 0, 0, .8f});
|
||||||
DrawDebugFrameList(RenderBuffer, Interface, Mouse, ProfilerMin, ProfilerMax, Transient);
|
//DrawDebugFrameList(RenderBuffer, Interface, Mouse, ProfilerMin, ProfilerMax, Transient);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
r32 ColumnsStartX = TopOfScreenLinePos.x;
|
r32 ColumnsStartX = TopOfScreenLinePos.x;
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//
|
||||||
|
// Book-Keeping
|
||||||
|
//
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
internal void
|
||||||
|
InitializePanelLayout(panel_layout* Layout)
|
||||||
|
{
|
||||||
|
Layout->FreeList.Free.Next = &Layout->FreeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal panel_entry*
|
||||||
|
TakeNewPanelEntry(panel_layout* Layout)
|
||||||
|
{
|
||||||
|
panel_entry* FreeEntry = 0;
|
||||||
|
if (Layout->FreeList.Free.Next != &Layout->FreeList)
|
||||||
|
{
|
||||||
|
FreeEntry = Layout->FreeList.Free.Next;
|
||||||
|
Layout->FreeList.Free.Next = FreeEntry->Free.Next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert(Layout->PanelsUsed < PANELS_MAX);
|
||||||
|
FreeEntry = Layout->Panels + Layout->PanelsUsed++;
|
||||||
|
}
|
||||||
|
return FreeEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal panel*
|
||||||
|
TakeNewPanel(panel_layout* Layout)
|
||||||
|
{
|
||||||
|
panel* Result = 0;
|
||||||
|
panel_entry* FreeEntry = TakeNewPanelEntry(Layout);
|
||||||
|
Result = &FreeEntry->Panel;
|
||||||
|
*Result = {0};
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
FreePanelEntry(panel_entry* Entry, panel_layout* Layout)
|
||||||
|
{
|
||||||
|
Assert(Entry >= Layout->Panels && Entry <= Layout->Panels + PANELS_MAX);
|
||||||
|
Entry->Panel = {0};
|
||||||
|
Entry->Free.Next = Layout->FreeList.Free.Next;
|
||||||
|
Layout->FreeList.Free.Next = Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
FreePanelAtIndex(s32 Index, panel_layout* Layout)
|
||||||
|
{
|
||||||
|
Assert(Index > 0 && Index < (s32)Layout->PanelsUsed);
|
||||||
|
panel_entry* EntryToFree = Layout->Panels + Index;
|
||||||
|
EntryToFree->Free.Next = Layout->FreeList.Free.Next;
|
||||||
|
Layout->FreeList.Free.Next = EntryToFree;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
SplitPanelVertically(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout)
|
||||||
|
{
|
||||||
|
r32 SplitX = GSLerp(ParentMin.x, ParentMax.x, Percent);
|
||||||
|
if (SplitX > ParentMin.x && SplitX < ParentMax.x)
|
||||||
|
{
|
||||||
|
Parent->SplitDirection = PanelSplit_Vertical;
|
||||||
|
Parent->SplitPercent = Percent;
|
||||||
|
|
||||||
|
Parent->Left = TakeNewPanelEntry(Layout);
|
||||||
|
Parent->Left->Panel.Render = Parent->Render;
|
||||||
|
|
||||||
|
Parent->Right = TakeNewPanelEntry(Layout);
|
||||||
|
Parent->Right->Panel.Render = Parent->Render;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
SplitPanelHorizontally(panel* Parent, r32 Percent, v2 ParentMin, v2 ParentMax, panel_layout* Layout)
|
||||||
|
{
|
||||||
|
r32 SplitY = GSLerp(ParentMin.y, ParentMax.y, Percent);
|
||||||
|
if (SplitY > ParentMin.y && SplitY < ParentMax.y)
|
||||||
|
{
|
||||||
|
Parent->SplitDirection = PanelSplit_Horizontal;
|
||||||
|
Parent->SplitPercent = Percent;
|
||||||
|
|
||||||
|
Parent->Bottom = TakeNewPanelEntry(Layout);
|
||||||
|
Parent->Bottom->Panel.Render = Parent->Render;
|
||||||
|
|
||||||
|
Parent->Top = TakeNewPanelEntry(Layout);
|
||||||
|
Parent->Top->Panel.Render = Parent->Render;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_layout* Layout)
|
||||||
|
{
|
||||||
|
panel_entry* LeftChild = Parent->Left;
|
||||||
|
panel_entry* RightChild = Parent->Right;
|
||||||
|
|
||||||
|
*Parent = PanelEntryToKeep->Panel;
|
||||||
|
Parent->SplitDirection = PanelSplit_NoSplit;
|
||||||
|
|
||||||
|
FreePanelEntry(LeftChild, Layout);
|
||||||
|
FreePanelEntry(RightChild, Layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
SetPanelDefinition(panel* Panel, panel_definition Def)
|
||||||
|
{
|
||||||
|
if(Panel->Cleanup)
|
||||||
|
{
|
||||||
|
Panel->Cleanup(Panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Panel->Cleanup = Def.Cleanup;
|
||||||
|
Panel->Render = Def.Render;
|
||||||
|
Def.Init(Panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
//
|
||||||
|
// Rendering And Interaction
|
||||||
|
//
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
internal void
|
||||||
|
HandleMousePanelInteractionOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, panel_layout* PanelLayout, mouse_state Mouse)
|
||||||
|
{
|
||||||
|
r32 PanelEdgeClickMaxDistance = 4;
|
||||||
|
|
||||||
|
// TODO(Peter): Need a way to calculate this button's position more systemically
|
||||||
|
if (Panel->SplitDirection == PanelSplit_NoSplit
|
||||||
|
&& PointIsInRange(Mouse.DownPos, PanelMin, PanelMin + v2{25, 25}))
|
||||||
|
{
|
||||||
|
r32 XDistance = GSAbs(Mouse.Pos.x - Mouse.DownPos.x);
|
||||||
|
r32 YDistance = GSAbs(Mouse.Pos.y - Mouse.DownPos.y);
|
||||||
|
|
||||||
|
if (XDistance > YDistance)
|
||||||
|
{
|
||||||
|
r32 XPercent = (Mouse.Pos.x - PanelMin.x) / (PanelMax.x - PanelMin.x);
|
||||||
|
SplitPanelVertically(Panel, XPercent, PanelMin, PanelMax, PanelLayout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r32 YPercent = (Mouse.Pos.y - PanelMin.y) / (PanelMax.y - PanelMin.y);
|
||||||
|
SplitPanelHorizontally(Panel, YPercent, PanelMin, PanelMax, PanelLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Panel->SplitDirection == PanelSplit_Horizontal)
|
||||||
|
{
|
||||||
|
r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent);
|
||||||
|
r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.y - SplitY);
|
||||||
|
if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance)
|
||||||
|
{
|
||||||
|
r32 NewSplitY = Mouse.Pos.y;
|
||||||
|
if (NewSplitY <= PanelMin.y)
|
||||||
|
{
|
||||||
|
ConsolidatePanelsKeepOne(Panel, Panel->Top, PanelLayout);
|
||||||
|
}
|
||||||
|
else if (NewSplitY >= PanelMax.y)
|
||||||
|
{
|
||||||
|
ConsolidatePanelsKeepOne(Panel, Panel->Bottom, PanelLayout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Panel->SplitPercent = (NewSplitY - PanelMin.y) / (PanelMax.y - PanelMin.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleMousePanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, PanelLayout, Mouse);
|
||||||
|
HandleMousePanelInteractionOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, PanelLayout, Mouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Panel->SplitDirection == PanelSplit_Vertical)
|
||||||
|
{
|
||||||
|
r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent);
|
||||||
|
r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.x - SplitX);
|
||||||
|
if (ClickDistanceFromSplit < PanelEdgeClickMaxDistance)
|
||||||
|
{
|
||||||
|
r32 NewSplitX = Mouse.Pos.x;
|
||||||
|
if (NewSplitX <= PanelMin.x)
|
||||||
|
{
|
||||||
|
ConsolidatePanelsKeepOne(Panel, Panel->Right, PanelLayout);
|
||||||
|
}
|
||||||
|
else if (NewSplitX >= PanelMax.x)
|
||||||
|
{
|
||||||
|
ConsolidatePanelsKeepOne(Panel, Panel->Left, PanelLayout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Panel->SplitPercent = (NewSplitX - PanelMin.x) / (PanelMax.x - PanelMin.x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleMousePanelInteractionOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, PanelLayout, Mouse);
|
||||||
|
HandleMousePanelInteractionOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, PanelLayout, Mouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
HandleMousePanelInteraction(panel_layout* PanelLayout, v2 WindowMin, v2 WindowMax, mouse_state Mouse)
|
||||||
|
{
|
||||||
|
r32 PanelEdgeClickMaxDistance = 4;
|
||||||
|
|
||||||
|
if (MouseButtonTransitionedUp(Mouse.LeftButtonState))
|
||||||
|
{
|
||||||
|
Assert(PanelLayout->PanelsUsed > 0);
|
||||||
|
panel* FirstPanel = &PanelLayout->Panels[0].Panel;
|
||||||
|
HandleMousePanelInteractionOrRecurse(FirstPanel, WindowMin, WindowMax, PanelLayout, Mouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, v2 FooterMin, v2 FooterMax, interface_config Interface, mouse_state Mouse)
|
||||||
|
{
|
||||||
|
PushRenderQuad2D(RenderBuffer, FooterMin, v2{FooterMax.x, FooterMin.y + 25}, v4{.5f, .5f, .5f, 1.f});
|
||||||
|
PushRenderQuad2D(RenderBuffer, FooterMin, FooterMin + v2{25, 25}, WhiteV4);
|
||||||
|
|
||||||
|
v2 PanelSelectButtonMin = FooterMin + v2{30, 1};
|
||||||
|
v2 PanelSelectButtonMax = PanelSelectButtonMin + v2{100, 23};
|
||||||
|
|
||||||
|
if (Panel->PanelSelectionMenuOpen)
|
||||||
|
{
|
||||||
|
v2 ButtonDimension = v2{100, 25};
|
||||||
|
v2 ButtonMin = v2{PanelSelectButtonMin.x, FooterMax.y};
|
||||||
|
|
||||||
|
v2 MenuMin = ButtonMin;
|
||||||
|
v2 MenuMax = v2{ButtonMin.x + ButtonDimension.x, ButtonMin.y + (ButtonDimension.y * GlobalPanelDefsCount)};
|
||||||
|
if (MouseButtonTransitionedDown(Mouse.LeftButtonState)
|
||||||
|
&& !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax))
|
||||||
|
{
|
||||||
|
Panel->PanelSelectionMenuOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (s32 i = 0; i < GlobalPanelDefsCount; i++)
|
||||||
|
{
|
||||||
|
panel_definition Def = GlobalPanelDefs[i];
|
||||||
|
string DefName = MakeString(Def.PanelName, Def.PanelNameLength);
|
||||||
|
button_result DefinitionButton = EvaluateButton(RenderBuffer,
|
||||||
|
ButtonMin, ButtonMin + ButtonDimension,
|
||||||
|
DefName, Interface, Mouse);
|
||||||
|
if (DefinitionButton.Pressed)
|
||||||
|
{
|
||||||
|
SetPanelDefinition(Panel, Def);
|
||||||
|
Panel->PanelSelectionMenuOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonMin.y += ButtonDimension.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button_result ButtonResult = EvaluateButton(RenderBuffer,
|
||||||
|
PanelSelectButtonMin,
|
||||||
|
PanelSelectButtonMax,
|
||||||
|
MakeStringLiteral("Select"), Interface, Mouse);
|
||||||
|
if (ButtonResult.Pressed)
|
||||||
|
{
|
||||||
|
Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, render_command_buffer* RenderBuffer)
|
||||||
|
{
|
||||||
|
PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawPanelOrRecurse(panel* Panel, v2 PanelMin, v2 PanelMax, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context)
|
||||||
|
{
|
||||||
|
if (Panel->SplitDirection == PanelSplit_NoSplit)
|
||||||
|
{
|
||||||
|
v2 FooterMin = PanelMin;
|
||||||
|
v2 FooterMax = v2{PanelMax.x, PanelMin.y + 25};
|
||||||
|
v2 PanelViewMin = v2{PanelMin.x, FooterMax.y};
|
||||||
|
v2 PanelViewMax = PanelMax;
|
||||||
|
|
||||||
|
Panel->Render(*Panel, PanelViewMin, PanelViewMax, RenderBuffer, State, Context, Mouse);
|
||||||
|
v4 BorderColor = v4{0, 1, 1, 1};
|
||||||
|
if (PointIsInRange(Mouse.Pos, PanelMin, PanelMax))
|
||||||
|
{
|
||||||
|
BorderColor = v4{1, 0, 1, 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
PushRenderOrthographic(RenderBuffer, WindowMin.x, WindowMin.y, WindowMax.x, WindowMax.y);
|
||||||
|
DrawPanelBorder(*Panel, PanelMin, PanelMax, BorderColor, RenderBuffer);
|
||||||
|
DrawPanelFooter(Panel, RenderBuffer, FooterMin, FooterMax, Interface, Mouse);
|
||||||
|
}
|
||||||
|
else if (Panel->SplitDirection == PanelSplit_Horizontal)
|
||||||
|
{
|
||||||
|
r32 SplitY = GSLerp(PanelMin.y, PanelMax.y, Panel->SplitPercent);
|
||||||
|
DrawPanelOrRecurse(&Panel->Bottom->Panel, PanelMin, v2{PanelMax.x, SplitY}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context);
|
||||||
|
DrawPanelOrRecurse(&Panel->Top->Panel, v2{PanelMin.x, SplitY}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context);
|
||||||
|
}
|
||||||
|
else if (Panel->SplitDirection == PanelSplit_Vertical)
|
||||||
|
{
|
||||||
|
r32 SplitX = GSLerp(PanelMin.x, PanelMax.x, Panel->SplitPercent);
|
||||||
|
DrawPanelOrRecurse(&Panel->Left->Panel, PanelMin, v2{SplitX, PanelMax.y}, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context);
|
||||||
|
DrawPanelOrRecurse(&Panel->Right->Panel, v2{SplitX, PanelMin.y}, PanelMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawAllPanels(panel_layout PanelLayout, v2 WindowMin, v2 WindowMax, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, app_state* State, context Context)
|
||||||
|
{
|
||||||
|
Assert(PanelLayout.PanelsUsed > 0);
|
||||||
|
panel* FirstPanel = &PanelLayout.Panels[0].Panel;
|
||||||
|
DrawPanelOrRecurse(FirstPanel, WindowMin, WindowMax, WindowMin, WindowMax, RenderBuffer, Interface, Mouse, State, Context);
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
|
||||||
|
typedef struct panel panel;
|
||||||
|
|
||||||
|
#define PANEL_INIT_PROC(name) void name(panel* Panel)
|
||||||
|
typedef PANEL_INIT_PROC(panel_init_proc);
|
||||||
|
|
||||||
|
#define PANEL_CLEANUP_PROC(name) void name(panel* Panel)
|
||||||
|
typedef PANEL_CLEANUP_PROC(panel_cleanup_proc);
|
||||||
|
|
||||||
|
#define PANEL_RENDER_PROC(name) void name(panel Panel, v2 PanelMin, v2 PanelMax, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
|
||||||
|
typedef PANEL_RENDER_PROC(panel_render_proc);
|
||||||
|
|
||||||
|
enum panel_split_direction
|
||||||
|
{
|
||||||
|
PanelSplit_NoSplit,
|
||||||
|
PanelSplit_Horizontal,
|
||||||
|
PanelSplit_Vertical,
|
||||||
|
|
||||||
|
PanelSplit_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct panel_entry panel_entry;
|
||||||
|
|
||||||
|
struct panel
|
||||||
|
{
|
||||||
|
panel_render_proc* Render;
|
||||||
|
panel_cleanup_proc* Cleanup;
|
||||||
|
|
||||||
|
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{
|
||||||
|
panel_entry* Left;
|
||||||
|
panel_entry* Top;
|
||||||
|
};
|
||||||
|
union{
|
||||||
|
panel_entry* Right;
|
||||||
|
panel_entry* Bottom;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct free_panel
|
||||||
|
{
|
||||||
|
panel_entry* Next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct panel_entry
|
||||||
|
{
|
||||||
|
panel Panel;
|
||||||
|
free_panel Free;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PANELS_MAX 16
|
||||||
|
struct panel_layout
|
||||||
|
{
|
||||||
|
panel_entry Panels[PANELS_MAX];
|
||||||
|
u32 PanelsUsed;
|
||||||
|
|
||||||
|
panel_entry FreeList;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct panel_definition
|
||||||
|
{
|
||||||
|
char* PanelName;
|
||||||
|
s32 PanelNameLength;
|
||||||
|
panel_init_proc* Init;
|
||||||
|
panel_cleanup_proc* Cleanup;
|
||||||
|
panel_render_proc* Render;
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
global_variable s32 GlobalPanelDefsCount = 4;
|
||||||
|
global_variable panel_definition GlobalPanelDefs[] = {
|
||||||
|
{ "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render },
|
||||||
|
{ "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render },
|
||||||
|
{ "DMX View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render },
|
||||||
|
{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render },
|
||||||
|
};
|
|
@ -0,0 +1,149 @@
|
||||||
|
PANEL_INIT_PROC(AnimationTimeline_Init)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_CLEANUP_PROC(AnimationTimeline_Cleanup)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal animation_block_handle
|
||||||
|
DrawAnimationTimeline (animation_system* AnimationSystem, v2 PanelMin, v2 PanelMax, animation_block_handle SelectedBlockHandle, render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse)
|
||||||
|
{
|
||||||
|
animation_block_handle Result = SelectedBlockHandle;
|
||||||
|
|
||||||
|
r32 AnimationPanelHeight = PanelMax.y - PanelMin.y;
|
||||||
|
r32 AnimationPanelWidth = PanelMax.x - PanelMin.x;
|
||||||
|
panel_result AnimationPanel = EvaluatePanel(RenderBuffer, PanelMin, PanelMax,
|
||||||
|
0, Interface);
|
||||||
|
|
||||||
|
b32 MouseDownAndNotHandled = MouseButtonTransitionedDown(Mouse.LeftButtonState);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < AnimationSystem->BlocksCount; i++)
|
||||||
|
{
|
||||||
|
animation_block_entry AnimationBlockEntry = AnimationSystem->Blocks[i];
|
||||||
|
if (AnimationBlockIsFree(AnimationBlockEntry)) { continue; }
|
||||||
|
|
||||||
|
animation_block_handle CurrentBlockHandle = {};
|
||||||
|
CurrentBlockHandle.Index = i;
|
||||||
|
CurrentBlockHandle.Generation = AnimationBlockEntry.Generation;
|
||||||
|
|
||||||
|
animation_block AnimationBlockAt = AnimationBlockEntry.Block;
|
||||||
|
|
||||||
|
r32 StartTimePercent = AnimationBlockAt.StartTime / AnimationSystem->AnimationEnd;
|
||||||
|
r32 StartPosition = AnimationPanelWidth * StartTimePercent;
|
||||||
|
|
||||||
|
r32 EndTimePercent = AnimationBlockAt.EndTime / AnimationSystem->AnimationEnd;
|
||||||
|
r32 EndPosition = AnimationPanelWidth * EndTimePercent;
|
||||||
|
|
||||||
|
v2 Min = PanelMin + v2{StartPosition, 25};
|
||||||
|
v2 Max = PanelMin + v2{EndPosition, 75};
|
||||||
|
|
||||||
|
v4 BlockColor = BlackV4;
|
||||||
|
if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle))
|
||||||
|
{
|
||||||
|
BlockColor = PinkV4;
|
||||||
|
}
|
||||||
|
|
||||||
|
PushRenderQuad2D(RenderBuffer, Min, Max, BlockColor);
|
||||||
|
PushRenderBoundingBox2D(RenderBuffer, Min, Max, 1, WhiteV4);
|
||||||
|
|
||||||
|
if (PointIsInRange(Mouse.Pos, Min, Max)
|
||||||
|
&& MouseButtonTransitionedDown(Mouse.LeftButtonState))
|
||||||
|
{
|
||||||
|
MouseDownAndNotHandled = false;
|
||||||
|
if (AnimationBlockHandlesAreEqual(SelectedBlockHandle, CurrentBlockHandle))
|
||||||
|
{
|
||||||
|
// If the block is already selected, deselect it.
|
||||||
|
Result = {0};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = CurrentBlockHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r32 TimePercent = AnimationSystem->Time / AnimationSystem->AnimationEnd;
|
||||||
|
r32 SliderX = PanelMin.x + (AnimationPanelWidth * TimePercent);
|
||||||
|
v2 SliderMin = v2{SliderX, PanelMin.y};
|
||||||
|
v2 SliderMax = v2{SliderX + 1, PanelMax.y - 25};
|
||||||
|
PushRenderQuad2D(RenderBuffer, SliderMin, SliderMax, WhiteV4);
|
||||||
|
|
||||||
|
if (MouseDownAndNotHandled && PointIsInRange(Mouse.Pos, PanelMin, PanelMax))
|
||||||
|
{
|
||||||
|
r32 MouseDownPositionPercent = (Mouse.Pos.x - PanelMin.x) / AnimationPanelWidth;
|
||||||
|
r32 NewBlockTimeStart = MouseDownPositionPercent * AnimationSystem->AnimationEnd;
|
||||||
|
#define NEW_BLOCK_DURATION 1
|
||||||
|
r32 NewBlockTimeEnd = NewBlockTimeStart + NEW_BLOCK_DURATION;
|
||||||
|
|
||||||
|
animation_block Block = {0};
|
||||||
|
Block.StartTime = NewBlockTimeStart;
|
||||||
|
Block.EndTime = NewBlockTimeEnd;
|
||||||
|
Block.Proc = TestPatternThree;
|
||||||
|
|
||||||
|
animation_block_handle NewBlockHandle = AddAnimationBlock(Block, AnimationSystem);
|
||||||
|
Result = NewBlockHandle;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_RENDER_PROC(AnimationTimeline_Render)
|
||||||
|
{
|
||||||
|
animation_block_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle;
|
||||||
|
|
||||||
|
r32 OptionsRowHeight = 25;
|
||||||
|
v2 TimelineMin = PanelMin;
|
||||||
|
v2 TimelineMax = v2{PanelMax.x, PanelMax.y - OptionsRowHeight};
|
||||||
|
if (TimelineMax.y - TimelineMin.y > 0)
|
||||||
|
{
|
||||||
|
SelectedBlockHandle = DrawAnimationTimeline(&State->AnimationSystem,
|
||||||
|
TimelineMin, TimelineMax,
|
||||||
|
SelectedBlockHandle,
|
||||||
|
RenderBuffer, State->Interface, Mouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 OptionsRowMin = v2{ PanelMin.x, TimelineMax.y };
|
||||||
|
v2 OptionsRowMax = PanelMax;
|
||||||
|
panel_result AnimationPanel = EvaluatePanel(RenderBuffer, OptionsRowMin, OptionsRowMax,
|
||||||
|
0, State->Interface);
|
||||||
|
|
||||||
|
r32 ButtonWidth = 35;
|
||||||
|
v2 ButtonMin = v2{0, 0};
|
||||||
|
v2 ButtonMax = v2{35, OptionsRowHeight - 2};
|
||||||
|
v2 ButtonAt = v2{OptionsRowMin.x + 1, OptionsRowMin.y + 1};
|
||||||
|
|
||||||
|
button_result PauseResult = EvaluateButton(RenderBuffer,
|
||||||
|
ButtonAt + ButtonMin, ButtonAt + ButtonMax,
|
||||||
|
MakeStringLiteral("Pause"),
|
||||||
|
State->Interface, Mouse);
|
||||||
|
ButtonAt.x += ButtonWidth + 2;
|
||||||
|
button_result PlayResult = EvaluateButton(RenderBuffer,
|
||||||
|
ButtonAt + ButtonMin, ButtonAt + ButtonMax,
|
||||||
|
MakeStringLiteral("Play"),
|
||||||
|
State->Interface, Mouse);
|
||||||
|
ButtonAt.x += ButtonWidth + 2;
|
||||||
|
button_result StopResult = EvaluateButton(RenderBuffer,
|
||||||
|
ButtonAt + ButtonMin, ButtonAt + ButtonMax,
|
||||||
|
MakeStringLiteral("Stop"),
|
||||||
|
State->Interface, Mouse);
|
||||||
|
|
||||||
|
if (PauseResult.Pressed)
|
||||||
|
{
|
||||||
|
State->AnimationSystem.TimelineShouldAdvance = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PlayResult.Pressed)
|
||||||
|
{
|
||||||
|
State->AnimationSystem.TimelineShouldAdvance = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StopResult.Pressed)
|
||||||
|
{
|
||||||
|
State->AnimationSystem.TimelineShouldAdvance = false;
|
||||||
|
State->AnimationSystem.Time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
State->SelectedAnimationBlockHandle = SelectedBlockHandle;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
PANEL_INIT_PROC(DMXView_Init)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_CLEANUP_PROC(DMXView_Cleanup)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_RENDER_PROC(DMXView_Render)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
DEBUG_TRACK_SCOPE(DrawUniverseOutputDisplay);
|
||||||
|
|
||||||
|
universe_view_operation_state* OpState = (universe_view_operation_state*)Operation.OpStateMemory;
|
||||||
|
|
||||||
|
string TitleBarString = InitializeEmptyString(PushArray(State->Transient, char, 64), 64);
|
||||||
|
|
||||||
|
v2 DisplayArea_Dimension = v2{600, 600};
|
||||||
|
|
||||||
|
v2 DisplayContents_Offset = OpState->DisplayOffset;
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO(Peter): I don't like this. Dragging the Universe view should be an operation mode, just
|
||||||
|
// like rotating the 3D view, but modes don't have access to the state of modes above them in the stack
|
||||||
|
// (and attempting to cast those states to the appropriate type seems risky)
|
||||||
|
//
|
||||||
|
// :NeedToPassStateDownModeChain
|
||||||
|
//
|
||||||
|
if (OpState->MouseDown)
|
||||||
|
{
|
||||||
|
DisplayContents_Offset += (Mouse.Pos - Mouse.DownPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 DisplayArea_TopLeft = v2{300, (r32)RenderBuffer->ViewHeight - 50} + DisplayContents_Offset;
|
||||||
|
v2 UniverseDisplayDimension = v2{100, 100} * OpState->Zoom;
|
||||||
|
v2 Padding = v2{25, 50} * OpState->Zoom;
|
||||||
|
|
||||||
|
v2 UniverseDisplayTopLeft = DisplayArea_TopLeft;
|
||||||
|
|
||||||
|
sacn_universe_buffer* UniverseList = State->SACN.UniverseBuffer;
|
||||||
|
while(UniverseList)
|
||||||
|
{
|
||||||
|
for (s32 UniverseIdx = 0;
|
||||||
|
UniverseIdx < UniverseList->Used;
|
||||||
|
UniverseIdx++)
|
||||||
|
{
|
||||||
|
sacn_universe* Universe = UniverseList->Universes + UniverseIdx;
|
||||||
|
DrawSACNUniversePixels(RenderBuffer, Universe, UniverseDisplayTopLeft, UniverseDisplayDimension);
|
||||||
|
|
||||||
|
|
||||||
|
if (OpState->Zoom > .5f)
|
||||||
|
{
|
||||||
|
v2 TitleDisplayStart = UniverseDisplayTopLeft + v2{0, 12};
|
||||||
|
PrintF(&TitleBarString, "Universe %d", Universe->Universe);
|
||||||
|
DrawString(RenderBuffer, TitleBarString, State->Interface.Font,
|
||||||
|
TitleDisplayStart, WhiteV4);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniverseDisplayTopLeft.x += UniverseDisplayDimension.x + Padding.x;
|
||||||
|
if (UniverseDisplayTopLeft.x > DisplayArea_TopLeft.x + DisplayArea_Dimension.x)
|
||||||
|
{
|
||||||
|
UniverseDisplayTopLeft.x = DisplayArea_TopLeft.x;
|
||||||
|
UniverseDisplayTopLeft.y -= UniverseDisplayDimension.y + Padding.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UniverseDisplayTopLeft.y < DisplayArea_TopLeft.y - DisplayArea_Dimension.y)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
UniverseList = UniverseList->Next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
PANEL_INIT_PROC(ProfilerView_Init)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_CLEANUP_PROC(ProfilerView_Cleanup)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer,
|
||||||
|
interface_config Interface, mouse_state Mouse,
|
||||||
|
v2 Min, v2 Max,
|
||||||
|
debug_frame* VisibleFrame, memory_arena* Memory)
|
||||||
|
{
|
||||||
|
v4 ThreadColors[] = {
|
||||||
|
v4{.73f, .33f, .83f, 1},
|
||||||
|
v4{0, .50f, .50f, 1},
|
||||||
|
v4{.83f, 0, 0, 1},
|
||||||
|
v4{.33f, .49f, .83f, 1},
|
||||||
|
v4{.74f, .40f, .25f, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
r32 Width = Max.x - Min.x;
|
||||||
|
r32 DepthHeight = 64;
|
||||||
|
|
||||||
|
s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
|
||||||
|
s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles;
|
||||||
|
|
||||||
|
debug_scope_record_list* ThreadScopeCalls = GetScopeListForThreadInFrame(GlobalDebugServices,
|
||||||
|
VisibleFrame);
|
||||||
|
|
||||||
|
MakeStringBuffer(String, 256);
|
||||||
|
for (s32 i = 0; i < ThreadScopeCalls->Count; i++)
|
||||||
|
{
|
||||||
|
scope_record* Record = ThreadScopeCalls->Calls + i;
|
||||||
|
scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash);
|
||||||
|
r32 PercentStart = (r32)(Record->StartCycles - FrameStartCycles) / (r32)FrameTotalCycles;
|
||||||
|
r32 PercentEnd = (r32)(Record->EndCycles - FrameStartCycles) / (r32)FrameTotalCycles;
|
||||||
|
|
||||||
|
v2 ScopeMin = v2{Min.x + (Width * PercentStart), Max.y - ((Record->CallDepth + 1) * DepthHeight)};
|
||||||
|
v2 ScopeMax = v2{Min.x + (Width * PercentEnd), ScopeMin.y + (DepthHeight - 4)};
|
||||||
|
|
||||||
|
if ((ScopeMax.x - ScopeMin.x) >= 1)
|
||||||
|
{
|
||||||
|
v4 Color = ThreadColors[0];
|
||||||
|
if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax))
|
||||||
|
{
|
||||||
|
Color = GreenV4;
|
||||||
|
}
|
||||||
|
|
||||||
|
PushRenderQuad2D(RenderBuffer, ScopeMin, ScopeMax, Color);
|
||||||
|
PushRenderBoundingBox2D(RenderBuffer, ScopeMin, ScopeMax, 1, BlackV4);
|
||||||
|
|
||||||
|
if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax))
|
||||||
|
{
|
||||||
|
PushRenderQuad2D(RenderBuffer, Mouse.Pos, Mouse.Pos + v2{256, 32}, BlackV4);
|
||||||
|
PrintF(&String, "%.*s : %d - %d", Name->Name.Length, Name->Name.Memory, Record->StartCycles, Record->EndCycles);
|
||||||
|
DrawString(RenderBuffer, String, Interface.Font, Mouse.Pos, WhiteV4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
RenderProfiler_ListVisualization(render_command_buffer* RenderBuffer,
|
||||||
|
interface_config Interface, mouse_state Mouse,
|
||||||
|
v2 Min, v2 Max,
|
||||||
|
debug_frame* VisibleFrame, memory_arena* Memory)
|
||||||
|
{
|
||||||
|
MakeStringBuffer(String, 256);
|
||||||
|
|
||||||
|
r32 YAt = Max.y - Interface.Font->PixelHeight;
|
||||||
|
r32 Column0X = Min.x;
|
||||||
|
r32 Column1X = Column0X + 256;
|
||||||
|
r32 Column2X = Column1X + 128;
|
||||||
|
r32 Column3X = Column2X + 128;
|
||||||
|
r32 Column4X = Column3X + 100;
|
||||||
|
|
||||||
|
for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++)
|
||||||
|
{
|
||||||
|
scope_name NameEntry = VisibleFrame->ScopeNamesHash[n];
|
||||||
|
if (NameEntry.Hash != 0)
|
||||||
|
{
|
||||||
|
collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n;
|
||||||
|
|
||||||
|
PrintF(&String, "%.*s", NameEntry.Name.Length, NameEntry.Name.Memory);
|
||||||
|
DrawString(RenderBuffer, String, Interface.Font, v2{Column0X, YAt}, WhiteV4);
|
||||||
|
|
||||||
|
PrintF(&String, "%f", CollatedRecord->PercentFrameTime);
|
||||||
|
DrawString(RenderBuffer, String, Interface.Font, v2{Column1X, YAt}, WhiteV4);
|
||||||
|
|
||||||
|
PrintF(&String, "%fs", CollatedRecord->TotalSeconds);
|
||||||
|
DrawString(RenderBuffer, String, Interface.Font, v2{Column2X, YAt}, WhiteV4);
|
||||||
|
|
||||||
|
PrintF(&String, "%dcy", CollatedRecord->TotalCycles);
|
||||||
|
DrawString(RenderBuffer, String, Interface.Font, v2{Column3X, YAt}, WhiteV4);
|
||||||
|
|
||||||
|
PrintF(&String, "%d calls", CollatedRecord->CallCount);
|
||||||
|
DrawString(RenderBuffer, String, Interface.Font, v2{Column4X, YAt}, WhiteV4);
|
||||||
|
|
||||||
|
YAt -= Interface.Font->PixelHeight + 4;
|
||||||
|
|
||||||
|
if (YAt < Min.y) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_RENDER_PROC(ProfilerView_Render)
|
||||||
|
{
|
||||||
|
memory_arena* Memory = &State->Transient;
|
||||||
|
string String = InitializeEmptyString(PushArray(Memory, char, 256), 256);
|
||||||
|
|
||||||
|
v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 };
|
||||||
|
|
||||||
|
r32 FrameListHeight = 64;
|
||||||
|
v2 FrameListMin = v2{PanelMin.x + 16, PanelMax.y - (16 + FrameListHeight)};
|
||||||
|
v2 FrameListMax = v2{PanelMax.x - 16, PanelMax.y - 16};
|
||||||
|
|
||||||
|
r32 FrameListPadding = 4;
|
||||||
|
r32 FrameListInnerWidth = (FrameListMax.x - FrameListMin.x) - (FrameListPadding * 2);
|
||||||
|
|
||||||
|
r32 SingleFrameStep = FrameListInnerWidth / DEBUG_FRAME_COUNT;
|
||||||
|
r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2);
|
||||||
|
|
||||||
|
PushRenderBoundingBox2D(RenderBuffer, FrameListMin, FrameListMax, 2, WhiteV4);
|
||||||
|
|
||||||
|
if (PointIsInRange(Mouse.Pos, FrameListMin, FrameListMax) &&
|
||||||
|
MouseButtonHeldDown(Mouse.LeftButtonState))
|
||||||
|
{
|
||||||
|
r32 LocalMouseX = (Mouse.Pos.x - FrameListMin.x) + FrameListPadding;
|
||||||
|
s32 ClosestFrameIndex = (LocalMouseX / SingleFrameStep);
|
||||||
|
|
||||||
|
if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT)
|
||||||
|
{
|
||||||
|
GlobalDebugServices->RecordFrames = false;
|
||||||
|
GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++)
|
||||||
|
{
|
||||||
|
v2 Min = v2{FrameListMin.x + FrameListPadding + (F * SingleFrameStep), FrameListMin.y + 4};
|
||||||
|
v2 Max = v2{Min.x + SingleFrameWidth, FrameListMax.y - 4};
|
||||||
|
|
||||||
|
s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F);
|
||||||
|
if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; }
|
||||||
|
v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)];
|
||||||
|
PushRenderQuad2D(RenderBuffer, Min, Max, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices);
|
||||||
|
s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
|
||||||
|
s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles;
|
||||||
|
|
||||||
|
PrintF(&String, "Frame %d - Total Cycles: %lld",
|
||||||
|
GlobalDebugServices->CurrentDebugFrame - 1,
|
||||||
|
FrameTotalCycles);
|
||||||
|
DrawString(RenderBuffer, String, State->Interface.Font, FrameListMin - v2{0, 32}, WhiteV4);
|
||||||
|
|
||||||
|
v2 ButtonMin = v2{FrameListMax.x - 128, FrameListMin.y - 32};
|
||||||
|
v2 ButtonMax = ButtonMin + v2{128, 28};
|
||||||
|
button_result ShouldResumeRecording = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
|
||||||
|
MakeString("Resume Recording"), State->Interface, Mouse);
|
||||||
|
if (ShouldResumeRecording.Pressed)
|
||||||
|
{
|
||||||
|
GlobalDebugServices->RecordFrames = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonMin = v2{FrameListMin.x, FrameListMin.y - 60};
|
||||||
|
ButtonMax = v2{FrameListMin.x + 128, FrameListMin.y - 42};
|
||||||
|
button_result ActivateScopeView = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
|
||||||
|
MakeString("Scope View"), State->Interface, Mouse);
|
||||||
|
|
||||||
|
ButtonMin.x += 152;
|
||||||
|
ButtonMax.x += 152;
|
||||||
|
button_result ActivateListView = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
|
||||||
|
MakeString("List View"), State->Interface, Mouse);
|
||||||
|
|
||||||
|
if (ActivateScopeView.Pressed) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_PROFILER; }
|
||||||
|
if (ActivateListView.Pressed) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_SCOPE_LIST; }
|
||||||
|
|
||||||
|
v2 ViewModeMin = v2{FrameListMin.x, PanelMin.y};
|
||||||
|
v2 ViewModeMax = v2{FrameListMax.x, FrameListMin.y - 96};
|
||||||
|
|
||||||
|
if (GlobalDebugServices->Interface.FrameView == FRAME_VIEW_PROFILER)
|
||||||
|
{
|
||||||
|
RenderProfiler_ScopeVisualization(RenderBuffer, State->Interface, Mouse,
|
||||||
|
ViewModeMin, ViewModeMax,
|
||||||
|
VisibleFrame, Memory);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RenderProfiler_ListVisualization(RenderBuffer, State->Interface, Mouse,
|
||||||
|
ViewModeMin, ViewModeMax,
|
||||||
|
VisibleFrame, Memory);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
PANEL_INIT_PROC(SculptureView_Init)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_CLEANUP_PROC(SculptureView_Cleanup)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct draw_leds_job_data
|
||||||
|
{
|
||||||
|
led* LEDs;
|
||||||
|
pixel* Colors;
|
||||||
|
s32 StartIndex;
|
||||||
|
s32 OnePastLastIndex;
|
||||||
|
|
||||||
|
render_quad_batch_constructor* Batch;
|
||||||
|
|
||||||
|
m44 FaceCameraMatrix;
|
||||||
|
m44 ModelViewMatrix;
|
||||||
|
r32 LEDHalfWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal void
|
||||||
|
DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
|
||||||
|
{
|
||||||
|
DEBUG_TRACK_FUNCTION;
|
||||||
|
|
||||||
|
draw_leds_job_data* Data = (draw_leds_job_data*)JobData;
|
||||||
|
|
||||||
|
s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex;
|
||||||
|
|
||||||
|
quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2);
|
||||||
|
s32 TrisUsed = 0;
|
||||||
|
|
||||||
|
r32 HalfWidth = Data->LEDHalfWidth;
|
||||||
|
|
||||||
|
v4 P0_In = v4{-HalfWidth, -HalfWidth, 0, 1};
|
||||||
|
v4 P1_In = v4{HalfWidth, -HalfWidth, 0, 1};
|
||||||
|
v4 P2_In = v4{HalfWidth, HalfWidth, 0, 1};
|
||||||
|
v4 P3_In = v4{-HalfWidth, HalfWidth, 0, 1};
|
||||||
|
|
||||||
|
v2 UV0 = v2{0, 0};
|
||||||
|
v2 UV1 = v2{1, 0};
|
||||||
|
v2 UV2 = v2{1, 1};
|
||||||
|
v2 UV3 = v2{0, 1};
|
||||||
|
|
||||||
|
led* LED = Data->LEDs + Data->StartIndex;
|
||||||
|
for (s32 LEDIdx = 0;
|
||||||
|
LEDIdx < LEDCount;
|
||||||
|
LEDIdx++)
|
||||||
|
{
|
||||||
|
pixel PixelColor = Data->Colors[LED->Index];
|
||||||
|
v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f};
|
||||||
|
|
||||||
|
v4 V4Position = LED->Position;
|
||||||
|
V4Position.w = 0;
|
||||||
|
v4 P0 = P0_In + V4Position;
|
||||||
|
v4 P1 = P1_In + V4Position;
|
||||||
|
v4 P2 = P2_In + V4Position;
|
||||||
|
v4 P3 = P3_In + V4Position;
|
||||||
|
|
||||||
|
SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
|
||||||
|
P0, P1, P2, UV0, UV1, UV2, Color, Color, Color);
|
||||||
|
SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
|
||||||
|
P0, P2, P3, UV0, UV2, UV3, Color, Color, Color);
|
||||||
|
|
||||||
|
LED++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_RENDER_PROC(SculptureView_Render)
|
||||||
|
{
|
||||||
|
DEBUG_TRACK_SCOPE(RenderSculpture);
|
||||||
|
|
||||||
|
r32 PanelWidth = PanelMax.x - PanelMin.x;
|
||||||
|
r32 PanelHeight = PanelMax.y - PanelMin.y;
|
||||||
|
State->Camera.AspectRatio = PanelWidth / PanelHeight;
|
||||||
|
|
||||||
|
m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera);
|
||||||
|
m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera);
|
||||||
|
|
||||||
|
r32 LEDHalfWidth = .5f;
|
||||||
|
|
||||||
|
PushRenderPerspective(RenderBuffer, PanelMin.x, PanelMin.y, PanelWidth, PanelHeight, State->Camera);
|
||||||
|
|
||||||
|
// TODO(Peter): Pretty sure this isn't working right now
|
||||||
|
m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1));
|
||||||
|
FaceCameraMatrix = FaceCameraMatrix;
|
||||||
|
|
||||||
|
s32 MaxLEDsPerJob = 2048;
|
||||||
|
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount);
|
||||||
|
|
||||||
|
for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
|
||||||
|
{
|
||||||
|
array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
|
||||||
|
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList);
|
||||||
|
s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob);
|
||||||
|
|
||||||
|
for (s32 Job = 0; Job < JobsNeeded; Job++)
|
||||||
|
{
|
||||||
|
draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data);
|
||||||
|
JobData->LEDs = Assembly.LEDs;
|
||||||
|
JobData->Colors = Assembly.Colors;
|
||||||
|
JobData->StartIndex = Job * MaxLEDsPerJob;
|
||||||
|
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDCount);
|
||||||
|
JobData->Batch = &RenderLEDsBatch;
|
||||||
|
JobData->FaceCameraMatrix;
|
||||||
|
JobData->ModelViewMatrix = ModelViewMatrix;
|
||||||
|
JobData->LEDHalfWidth = LEDHalfWidth;
|
||||||
|
|
||||||
|
Context.GeneralWorkQueue->PushWorkOnQueue(
|
||||||
|
Context.GeneralWorkQueue,
|
||||||
|
DrawLEDsInBufferRangeJob,
|
||||||
|
JobData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0);
|
||||||
|
Context.GeneralWorkQueue->ResetWorkQueue(Context.GeneralWorkQueue);
|
||||||
|
}
|
Loading…
Reference in New Issue