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};
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
|
@ -194,7 +132,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
State->Transient = {};
|
||||
State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
|
||||
InitializeInputCommandRegistry(&State->DefaultInputCommandRegistry, 32, &State->Permanent);
|
||||
|
@ -244,12 +182,12 @@ State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
|||
|
||||
u32 CodepointW, CodepointH;
|
||||
Context.PlatformDrawFontCodepoint(
|
||||
Font->BitmapMemory,
|
||||
Font->BitmapWidth,
|
||||
Font->BitmapHeight,
|
||||
CodepointX, CodepointY,
|
||||
Codepoint, FontInfo,
|
||||
&CodepointW, &CodepointH);
|
||||
Font->BitmapMemory,
|
||||
Font->BitmapWidth,
|
||||
Font->BitmapHeight,
|
||||
CodepointX, CodepointY,
|
||||
Codepoint, FontInfo,
|
||||
&CodepointW, &CodepointH);
|
||||
|
||||
AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY);
|
||||
}
|
||||
|
@ -299,35 +237,44 @@ State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
|||
ReloadStaticData(Context, GlobalDebugServices, Alloc, Free);
|
||||
|
||||
// Setup Operation Modes
|
||||
State->Modes.ActiveModesCount = 0;
|
||||
State->Modes.Arena = {};
|
||||
State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly;
|
||||
State->Modes.ActiveModesCount = 0;
|
||||
State->Modes.Arena = {};
|
||||
State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly;
|
||||
|
||||
{ // MODES PLAYGROUND
|
||||
InitializeAnimationSystem(&State->AnimationSystem);
|
||||
|
||||
animation_block BlockZero = {0};
|
||||
BlockZero.StartTime = 0;
|
||||
BlockZero.EndTime = 2;
|
||||
BlockZero.Proc = TestPatternOne;
|
||||
AddAnimationBlock(BlockZero, &State->AnimationSystem);
|
||||
BlockZero.EndTime = 2;
|
||||
BlockZero.Proc = TestPatternOne;
|
||||
AddAnimationBlock(BlockZero, &State->AnimationSystem);
|
||||
|
||||
animation_block BlockOne = {0};
|
||||
BlockOne.StartTime = 3;
|
||||
BlockOne.EndTime = 5;
|
||||
animation_block BlockOne = {0};
|
||||
BlockOne.StartTime = 3;
|
||||
BlockOne.EndTime = 5;
|
||||
BlockOne.Proc = TestPatternTwo;
|
||||
AddAnimationBlock(BlockOne, &State->AnimationSystem);
|
||||
AddAnimationBlock(BlockOne, &State->AnimationSystem);
|
||||
|
||||
animation_block BlockTwo = {0};
|
||||
BlockTwo.StartTime = 5;
|
||||
BlockTwo.EndTime = 8;
|
||||
BlockTwo.Proc = TestPatternThree;
|
||||
animation_block BlockTwo = {0};
|
||||
BlockTwo.StartTime = 5;
|
||||
BlockTwo.EndTime = 8;
|
||||
BlockTwo.Proc = TestPatternThree;
|
||||
AddAnimationBlock(BlockTwo, &State->AnimationSystem);
|
||||
|
||||
State->AnimationSystem.AnimationEnd = 10;
|
||||
} // 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
|
||||
|
@ -433,11 +380,11 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
HandleInput(State, InputQueue, Mouse);
|
||||
|
||||
if (State->AnimationSystem.TimelineShouldAdvance) {
|
||||
State->AnimationSystem.Time += Context.DeltaTime;
|
||||
if (State->AnimationSystem.Time > State->AnimationSystem.AnimationEnd)
|
||||
{
|
||||
State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd;
|
||||
}
|
||||
State->AnimationSystem.Time += Context.DeltaTime;
|
||||
if (State->AnimationSystem.Time > State->AnimationSystem.AnimationEnd)
|
||||
{
|
||||
State->AnimationSystem.Time -= State->AnimationSystem.AnimationEnd;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < State->AnimationSystem.BlocksCount; i++)
|
||||
{
|
||||
|
@ -445,13 +392,13 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
if (!AnimationBlockIsFree(BlockEntry))
|
||||
{
|
||||
animation_block Block = BlockEntry.Block;
|
||||
if (State->AnimationSystem.Time >= Block.StartTime
|
||||
&& State->AnimationSystem.Time <= Block.EndTime)
|
||||
{
|
||||
Block.Proc(State, State->AnimationSystem.Time - Block.StartTime);
|
||||
if (State->AnimationSystem.Time >= Block.StartTime
|
||||
&& State->AnimationSystem.Time <= Block.EndTime)
|
||||
{
|
||||
Block.Proc(State, State->AnimationSystem.Time - Block.StartTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 HeaderSize = State->NetworkProtocolHeaderSize;
|
||||
|
@ -486,20 +433,28 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
Job->DMXBuffers = DMXBuffers;
|
||||
|
||||
Context.GeneralWorkQueue->PushWorkOnQueue(
|
||||
Context.GeneralWorkQueue,
|
||||
SACNSendDMXBufferListJob,
|
||||
Job);
|
||||
Context.GeneralWorkQueue,
|
||||
SACNSendDMXBufferListJob,
|
||||
Job);
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
///////////////////////////////
|
||||
if (Context.WindowIsVisible)
|
||||
{
|
||||
#if 0
|
||||
State->Camera.AspectRatio = (r32)Context.WindowWidth / (r32)Context.WindowHeight;
|
||||
|
||||
m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera);
|
||||
|
@ -507,7 +462,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
|
||||
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);
|
||||
|
||||
// TODO(Peter): Pretty sure this isn't working right now
|
||||
|
@ -540,9 +495,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
JobData->LEDHalfWidth = LEDHalfWidth;
|
||||
|
||||
Context.GeneralWorkQueue->PushWorkOnQueue(
|
||||
Context.GeneralWorkQueue,
|
||||
DrawLEDsInBufferRangeJob,
|
||||
JobData);
|
||||
Context.GeneralWorkQueue,
|
||||
DrawLEDsInBufferRangeJob,
|
||||
JobData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,7 +516,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
///////////////////////////////////////
|
||||
// Menu Bar
|
||||
//////////////////////////////////////
|
||||
|
||||
r32 TopBarHeight = 40;
|
||||
{
|
||||
panel_result TopBarPanel = EvaluatePanel(RenderBuffer,
|
||||
|
@ -606,9 +560,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
v2 TimelineMin = v2{0, 0};
|
||||
v2 TimelineMax = v2{Context.WindowWidth, 125};
|
||||
animation_block_handle NewSelection = DrawAnimationPanel(&State->AnimationSystem,
|
||||
TimelineMin, TimelineMax,
|
||||
State->SelectedAnimationBlockHandle,
|
||||
RenderBuffer, State->Interface, Mouse);
|
||||
TimelineMin, TimelineMax,
|
||||
State->SelectedAnimationBlockHandle,
|
||||
RenderBuffer, State->Interface, Mouse);
|
||||
State->SelectedAnimationBlockHandle = NewSelection;
|
||||
|
||||
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
|
||||
|
@ -623,16 +577,17 @@ State->SelectedAnimationBlockHandle,
|
|||
DrawDebugInterface(RenderBuffer, 25,
|
||||
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
|
||||
Context.DeltaTime, State, State->Camera, Mouse, &State->Transient);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Checking for overflows
|
||||
{
|
||||
DEBUG_TRACK_SCOPE(OverflowChecks);
|
||||
AssertAllocationsNoOverflow(State->Permanent);
|
||||
for (s32 i = 0; i < State->AssemblyList.Used; i++)
|
||||
{
|
||||
assembly* Assembly = GetElementAtIndex(i, State->AssemblyList);
|
||||
AssertAllocationsNoOverflow(Assembly->Arena);
|
||||
AssertAllocationsNoOverflow(State->Permanent);
|
||||
for (s32 i = 0; i < State->AssemblyList.Used; i++)
|
||||
{
|
||||
assembly* Assembly = GetElementAtIndex(i, State->AssemblyList);
|
||||
AssertAllocationsNoOverflow(Assembly->Arena);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
typedef struct app_state app_state;
|
||||
|
||||
#include "foldhaus_panel.h"
|
||||
|
||||
#include "foldhaus_command_dispatch.h"
|
||||
#include "foldhaus_command_dispatch.cpp"
|
||||
#include "foldhaus_operation_mode.h"
|
||||
|
@ -40,7 +42,7 @@ struct app_state
|
|||
memory_arena Permanent;
|
||||
memory_arena Transient;
|
||||
|
||||
s32 NetworkProtocolHeaderSize;
|
||||
s32 NetworkProtocolHeaderSize;
|
||||
network_protocol NetworkProtocol;
|
||||
|
||||
streaming_acn SACN;
|
||||
|
@ -63,6 +65,8 @@ struct app_state
|
|||
|
||||
animation_system AnimationSystem;
|
||||
animation_block_handle SelectedAnimationBlockHandle;
|
||||
|
||||
panel_layout PanelLayout;
|
||||
};
|
||||
|
||||
internal void OpenColorPicker(app_state* State, v4* Address);
|
||||
|
@ -166,3 +170,11 @@ r32 GreenSize = 20.0f;
|
|||
|
||||
#include "foldhaus_interface.cpp"
|
||||
#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
|
||||
RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer,
|
||||
interface_config Interface, mouse_state Mouse,
|
||||
|
@ -188,6 +188,7 @@ DrawDebugFrameList (render_command_buffer* RenderBuffer, interface_config Interf
|
|||
VisibleFrame, Memory);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
@ -311,7 +312,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
|
|||
v2 ProfilerMin = v2{TopOfDebugView.x, TopOfDebugView.y - 500};
|
||||
v2 ProfilerMax = v2{TopOfDebugView.x + 700, TopOfDebugView.y - 64};
|
||||
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
|
||||
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 },
|
||||
};
|
|
@ -191,7 +191,7 @@ enum gs_memory_find_address_rule
|
|||
|
||||
typedef void* gs_memory_alloc(gs_mem_u32 Size);
|
||||
typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize);
|
||||
typedef void gs_memory_free(void* Address, gs_mem_u32 Size);
|
||||
typedef void gs_memory_free(void* Address, gs_mem_u32 Size);
|
||||
|
||||
#ifndef GS_MEMORY_BUFFER_SIZE
|
||||
#define GS_MEMORY_BUFFER_SIZE 1024
|
||||
|
|
|
@ -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