Interface fixes. Fixed the problem with strip LUT tables where substrips were stamping over previous substrips. Some pattern building too.
This commit is contained in:
parent
8d923a5e3c
commit
71547b05dc
|
@ -29,6 +29,8 @@ cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /lin
|
|||
|
||||
cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
||||
|
||||
cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
||||
|
||||
popd
|
||||
|
||||
call %MyPath%\_postbuild_win32.bat
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
call remedybg.bat ./app_run_tree/win32_msvc/debug/session.rdbg
|
|
@ -12,6 +12,8 @@ Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue
|
|||
|
||||
b32 MouseInputHandled = HandleMousePanelInteraction(&State->PanelSystem, State->WindowBounds, Mouse, State);
|
||||
|
||||
gs_string TextInputString = PushString(State->Transient, 32);
|
||||
|
||||
panel* ActivePanel = PanelSystem_GetPanelContainingPoint(&State->PanelSystem, Mouse.Pos);
|
||||
if (ActivePanel)
|
||||
{
|
||||
|
@ -47,7 +49,14 @@ Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue
|
|||
// frame when the button was released, even if the command is registered to both events
|
||||
if (KeyTransitionedDown(Event))
|
||||
{
|
||||
FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue);
|
||||
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue))
|
||||
{
|
||||
char KeyASCII = KeyCodeToChar(Event.Key);
|
||||
if (KeyASCII)
|
||||
{
|
||||
OutChar(&TextInputString, KeyASCII);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (KeyTransitionedUp(Event))
|
||||
{
|
||||
|
@ -55,7 +64,14 @@ Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue
|
|||
}
|
||||
else if (KeyHeldDown(Event))
|
||||
{
|
||||
FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue);
|
||||
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue))
|
||||
{
|
||||
char KeyASCII = KeyCodeToChar(Event.Key);
|
||||
if (KeyASCII)
|
||||
{
|
||||
OutChar(&TextInputString, KeyASCII);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +90,8 @@ Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue
|
|||
}
|
||||
}
|
||||
|
||||
State->Interface.TempInputString = TextInputString.ConstString;
|
||||
|
||||
ClearCommandQueue(&State->CommandQueue);
|
||||
}
|
||||
|
||||
|
@ -84,6 +102,12 @@ Editor_Update(app_state* State, context* Context, input_queue InputQueue)
|
|||
State->WindowBounds = Context->WindowBounds;
|
||||
State->Interface.Mouse = Context->Mouse;
|
||||
|
||||
State->Interface.HotWidgetFramesSinceUpdate += 1;
|
||||
if (State->Interface.HotWidgetFramesSinceUpdate > 1)
|
||||
{
|
||||
State->Interface.HotWidget = {};
|
||||
}
|
||||
|
||||
PanelSystem_UpdateLayout(&State->PanelSystem, State->WindowBounds);
|
||||
Editor_HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context);
|
||||
}
|
||||
|
@ -91,6 +115,8 @@ Editor_Update(app_state* State, context* Context, input_queue InputQueue)
|
|||
internal void
|
||||
Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ClippingBox, v4 Color)
|
||||
{
|
||||
gs_string Temp = PushString(State->Transient, 256);
|
||||
PrintF(&Temp, "%d", Widget.Id.Id);
|
||||
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer,
|
||||
Widget.String.Length,
|
||||
State->Interface.Style.Font->BitmapMemory,
|
||||
|
@ -199,14 +225,14 @@ Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* Ren
|
|||
FillBounds.Max.y = FillToPoint;
|
||||
}
|
||||
}
|
||||
PushRenderQuad2DClipped(RenderBuffer, FillBounds, WidgetParentUnion, Color);
|
||||
rect2 ClippedFillBounds = Rect2Union(FillBounds, WidgetParentUnion);
|
||||
PushRenderQuad2D(RenderBuffer, ClippedFillBounds, Color);
|
||||
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
|
||||
{
|
||||
// TODO(pjs): Mask this text by the horizontal fill
|
||||
// TODO(pjs): add this color to the style
|
||||
v4 TextColor = BlackV4;
|
||||
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, WidgetParentUnion, TextColor);
|
||||
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, ClippedFillBounds, TextColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,120 +257,67 @@ Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* Ren
|
|||
}
|
||||
}
|
||||
|
||||
global r32 TestSlider_Value = 5;
|
||||
global r32 TestSlider_Min = 0;
|
||||
global r32 TestSlider_Max = 10;
|
||||
global bool TestToggle = true;
|
||||
#include "../interface_test.cpp"
|
||||
|
||||
internal void
|
||||
TestRender(app_state* State, context* Context, render_command_buffer* RenderBuffer)
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(ActiveWidget_TypeCharacter)
|
||||
{
|
||||
ui_InterfaceReset(&State->Interface);
|
||||
State->Interface.RenderBuffer = RenderBuffer;
|
||||
State->Interface.WindowBounds = Context->WindowBounds;
|
||||
|
||||
gs_string A = MakeString("TestRender Layout");
|
||||
|
||||
ui_PushLayout(&State->Interface, A);
|
||||
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
|
||||
ui_widget_retained_state* WidgetState = ui_GetRetainedState(&State->Interface, ActiveWidget->Id);
|
||||
if (WidgetState)
|
||||
{
|
||||
#if 0
|
||||
ui_Label(&State->Interface, MakeString("Spacer"));
|
||||
ui_Label(&State->Interface, MakeString("Spacer"));
|
||||
ui_Label(&State->Interface, MakeString("Spacer"));
|
||||
ui_Label(&State->Interface, MakeString("Spacer"));
|
||||
ui_Label(&State->Interface, MakeString("Spacer"));
|
||||
|
||||
ui_BeginList(&State->Interface, MakeString("TestList"), 5, 16);
|
||||
char AsciiValue = CharacterFromKeyCode(Event.Key);
|
||||
if (AsciiValue)
|
||||
{
|
||||
ui_BeginRow(&State->Interface, 3);
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
|
||||
ui_Button(&State->Interface, MakeString("B"));
|
||||
ui_Button(&State->Interface, MakeString("C"));
|
||||
ui_Button(&State->Interface, MakeString("D"));
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
OutChar(&WidgetState->EditString, AsciiValue);
|
||||
}
|
||||
ui_EndList(&State->Interface);
|
||||
//ui_Button(&State->Interface, MakeString("B"));
|
||||
//ui_Button(&State->Interface, MakeString("C"));
|
||||
//TestSlider_Value = ui_RangeSlider(&State->Interface, MakeString("TestSlider"), TestSlider_Value, TestSlider_Min, TestSlider_Max);
|
||||
#elif 1
|
||||
ui_PushLayout(&State->Interface, MakeString("Outer"));
|
||||
{
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("A"));
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
||||
ui_BeginRow(&State->Interface, 2);
|
||||
{
|
||||
ui_PushLayout(&State->Interface, MakeString("TestLayout"));
|
||||
{
|
||||
for (u32 i = 0; i < 5; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
||||
ui_PushLayout(&State->Interface, MakeString("TestLayout"));
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
TestToggle = ui_Toggle(&State->Interface, MakeString("Toggle"), TestToggle);
|
||||
TestSlider_Value = ui_RangeSlider(&State->Interface, MakeString("TestSlider"), TestSlider_Value, TestSlider_Min, TestSlider_Max);
|
||||
if (ui_BeginDropdown(&State->Interface, MakeString("TestDropdown")))
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
}
|
||||
ui_EndDropdown(&State->Interface);
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
|
||||
ui_PushLayout(&State->Interface, MakeString("Outer"));
|
||||
{
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("B"));
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
||||
|
||||
ui_PushOverlayLayout(&State->Interface, rect2{25, 25, 200, 200}, LayoutDirection_TopDown, MakeString("t"));
|
||||
{
|
||||
ui_Label(&State->Interface, PushStringF(State->Interface.PerFrameMemory, 256, "Mouse Pos - %f %f", State->Interface.Mouse.Pos.x, State->Interface.Mouse.Pos.y));
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
#else
|
||||
ui_BeginList(&State->Interface, MakeString("Test List"), 10);
|
||||
{
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("Option"));
|
||||
}
|
||||
}
|
||||
ui_EndList(&State->Interface);
|
||||
#endif
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(ActiveWidget_DeleteBackwards)
|
||||
{
|
||||
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
|
||||
ui_widget_retained_state* WidgetState = ui_GetRetainedState(&State->Interface, ActiveWidget->Id);
|
||||
if (WidgetState)
|
||||
{
|
||||
WidgetState->EditString.Length -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(ActiveWidget_EndTypingMode)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
OPERATION_RENDER_PROC(ActiveWidget_EndTypingMode)
|
||||
{
|
||||
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
|
||||
ui_widget* LastActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.LastActiveWidget);
|
||||
if (ActiveWidget == 0 && LastActiveWidget != 0)
|
||||
{
|
||||
// if there was an active widget last frame that was typable, we want to deactivate the typing mode
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
}
|
||||
|
||||
input_command InterfaceTypingCommands [] = {
|
||||
{ KeyCode_A, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
|
||||
{ KeyCode_B, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
|
||||
{ KeyCode_C, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
|
||||
{ KeyCode_D, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
|
||||
{ KeyCode_E, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
|
||||
{ KeyCode_Enter, KeyCode_Invalid, Command_Began, ActiveWidget_EndTypingMode },
|
||||
{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_DeleteBackwards },
|
||||
};
|
||||
|
||||
internal void
|
||||
Editor_Render(app_state* State, context* Context, render_command_buffer* RenderBuffer)
|
||||
{
|
||||
State->Interface.WindowBounds = Context->WindowBounds;
|
||||
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
|
||||
PushRenderClearScreen(RenderBuffer);
|
||||
|
||||
#if 0
|
||||
TestRender(State, Context, RenderBuffer);
|
||||
InterfaceTest_Render(State, Context, RenderBuffer);
|
||||
#else
|
||||
ui_InterfaceReset(&State->Interface);
|
||||
State->Interface.RenderBuffer = RenderBuffer;
|
||||
|
@ -369,6 +342,19 @@ Editor_Render(app_state* State, context* Context, render_command_buffer* RenderB
|
|||
{
|
||||
ui_widget Widget = *State->Interface.DrawOrderRoot;
|
||||
Editor_DrawWidget(State, Context, RenderBuffer, Widget, Context->WindowBounds);
|
||||
|
||||
#if 0
|
||||
// TODO(pjs): got distracted halfway through getting typing input into the interface
|
||||
if (ui_WidgetIdsEqual(State->Interface.ActiveWidget, State->Interface.LastActiveWidget))
|
||||
{
|
||||
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
|
||||
if (ActiveWidget != 0 &&
|
||||
ui_WidgetIsFlagSet(*ActiveWidget, UIWidgetFlag_Typable))
|
||||
{
|
||||
operation_mode* TypingMode = ActivateOperationModeWithCommands(&State->Modes, InterfaceTypingCommands, ActiveWidget_EndTypingMode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext);
|
||||
|
|
|
@ -40,7 +40,7 @@ OperationModeSystemInit(gs_memory_arena* Storage, gs_thread_context ThreadContex
|
|||
// TODO(Peter): Do we really need an arena? Can this just operate in constant memory footprint?
|
||||
Result.Arena.Allocator = ThreadContext.Allocator;
|
||||
|
||||
Result.ModeMemoryPagesFreeList.CountMax = 16; // TODO(Peter): Static number of modes that can be active simultaneously
|
||||
Result.ModeMemoryPagesFreeList.CountMax = 32; // TODO(Peter): Static number of modes that can be active simultaneously
|
||||
Result.ModeMemoryPagesFreeList.Data = PushArray(Storage, gs_data, Result.ModeMemoryPagesFreeList.CountMax);
|
||||
for (u32 Page = 0; Page < Result.ModeMemoryPagesFreeList.CountMax; Page++)
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ GetXPositionFromFrameInAnimationPanel (u32 Frame, rect2 PanelBounds, frame_range
|
|||
}
|
||||
|
||||
internal handle
|
||||
AddAnimationBlockAtCurrentTime (u32 AnimationProcHandle, u32 LayerHandle, animation_system* System)
|
||||
AddAnimationBlockAtCurrentTime (animation_pattern_handle AnimationProcHandle, u32 LayerHandle, animation_system* System)
|
||||
{
|
||||
u32 NewBlockStart = System->CurrentFrame;
|
||||
u32 NewBlockEnd = NewBlockStart + SecondsToFrames(3, *System);
|
||||
|
@ -260,7 +260,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddAnimationBlockCommand)
|
|||
frame_range Range = ActiveAnim->PlayableRange;
|
||||
u32 MouseDownFrame = GetFrameFromPointInAnimationPanel(Mouse.Pos, Panel->Bounds, Range);
|
||||
|
||||
handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), 4, TimelineState->SelectedAnimationLayer);
|
||||
animation_pattern_handle PatternHandle = Patterns_IndexToHandle(4);
|
||||
handle NewBlockHandle = Animation_AddBlock(ActiveAnim, MouseDownFrame, MouseDownFrame + SecondsToFrames(3, State->AnimationSystem), PatternHandle, TimelineState->SelectedAnimationLayer);
|
||||
TimelineState->SelectedBlockHandle = NewBlockHandle;
|
||||
}
|
||||
|
||||
|
@ -575,8 +576,10 @@ PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback)
|
|||
if (FileInfo.Path.Length > 0)
|
||||
{
|
||||
gs_file AnimFile = ReadEntireFile(Context.ThreadContext.FileHandler, FileInfo.Path);
|
||||
|
||||
gs_string AnimFileString = MakeString((char*)AnimFile.Data.Memory, AnimFile.Data.Size);
|
||||
animation NewAnim = AnimParser_Parse(AnimFileString, State->AnimationSystem.Storage, GlobalAnimationPatternsCount, GlobalAnimationPatterns);
|
||||
animation NewAnim = AnimParser_Parse(AnimFileString, State->AnimationSystem.Storage, State->Patterns);
|
||||
NewAnim.FileInfo = AnimFile.FileInfo;
|
||||
|
||||
u32 NewAnimIndex = AnimationArray_Push(&State->AnimationSystem.Animations, NewAnim);
|
||||
State->AnimationSystem.ActiveAnimationIndex = NewAnimIndex;
|
||||
|
@ -584,16 +587,17 @@ PANEL_MODAL_OVERRIDE_CALLBACK(LoadAnimationFileCallback)
|
|||
}
|
||||
|
||||
internal void
|
||||
DrawAnimationPatternList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayerHandle, animation_system* AnimationSystem)
|
||||
DrawAnimationPatternList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayerHandle, animation_system* AnimationSystem, animation_pattern_array Patterns)
|
||||
{
|
||||
ui_PushLayout(Interface, PanelBounds, LayoutDirection_TopDown, MakeString("AnimClips Layout"));
|
||||
for (s32 i = 0; i < GlobalAnimationPatternsCount; i++)
|
||||
for (u32 i = 0; i < Patterns.Count; i++)
|
||||
{
|
||||
animation_pattern Pattern = GlobalAnimationPatterns[i];
|
||||
animation_pattern Pattern = Patterns.Values[i];
|
||||
gs_string PatternName = MakeString(Pattern.Name, Pattern.NameLength);
|
||||
if (ui_Button(Interface, PatternName))
|
||||
{
|
||||
AddAnimationBlockAtCurrentTime(i + 1, SelectedAnimationLayerHandle, AnimationSystem);
|
||||
animation_pattern_handle PatternHandle = Patterns_IndexToHandle(i);
|
||||
AddAnimationBlockAtCurrentTime(PatternHandle, SelectedAnimationLayerHandle, AnimationSystem);
|
||||
}
|
||||
}
|
||||
ui_PopLayout(Interface);
|
||||
|
@ -624,12 +628,6 @@ PlayBar_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Pan
|
|||
AnimSystem->TimelineShouldAdvance = false;
|
||||
AnimSystem->CurrentFrame = 0;
|
||||
}
|
||||
|
||||
if (ui_Button(Interface, MakeString("Load")))
|
||||
{
|
||||
panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context);
|
||||
Panel_PushModalOverride(Panel, FileBrowser, LoadAnimationFileCallback);
|
||||
}
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
@ -640,7 +638,11 @@ FrameCount_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_
|
|||
{
|
||||
ui_interface* Interface = &State->Interface;
|
||||
gs_string TempString = PushString(State->Transient, 256);
|
||||
frame_range VisibleFrames = TimelineState->VisibleRange;
|
||||
// :FrameRange
|
||||
// frame_range VisibleFrames = TimelineState->VisibleRange;
|
||||
animation ActiveAnim = *AnimationSystem_GetActiveAnimation(&State->AnimationSystem);
|
||||
frame_range VisibleFrames = ActiveAnim.PlayableRange;
|
||||
|
||||
s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min;
|
||||
|
||||
ui_FillRect(Interface, Bounds, Interface->Style.PanelBGColors[0]);
|
||||
|
@ -685,7 +687,7 @@ FrameCount_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_
|
|||
}
|
||||
|
||||
internal void
|
||||
LayerList_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
LayerList_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
ui_interface* Interface = &State->Interface;
|
||||
animation ActiveAnim = *AnimationSystem_GetActiveAnimation(&State->AnimationSystem);
|
||||
|
@ -720,9 +722,15 @@ internal void
|
|||
TimeRange_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
ui_interface* Interface = &State->Interface;
|
||||
frame_range ViewRange = TimelineState->VisibleRange;
|
||||
|
||||
animation ActiveAnim = *AnimationSystem_GetActiveAnimation(&State->AnimationSystem);
|
||||
|
||||
// TODO(pjs): setting the timeline to show the entire range
|
||||
// of the current animation until I reimplement the range
|
||||
// slider bars
|
||||
// :FrameRange
|
||||
// frame_range ViewRange = TimelineState->VisibleRange;
|
||||
frame_range ViewRange = ActiveAnim.PlayableRange;
|
||||
|
||||
handle SelectedBlockHandle = TimelineState->SelectedBlockHandle;
|
||||
s32 CurrentFrame = State->AnimationSystem.CurrentFrame;
|
||||
|
||||
|
@ -785,7 +793,7 @@ TimeRange_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_c
|
|||
}
|
||||
|
||||
internal void
|
||||
AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
animation_system* AnimSystem = &State->AnimationSystem;
|
||||
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(AnimSystem);
|
||||
|
@ -795,23 +803,84 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, rende
|
|||
|
||||
ui_FillRect(&State->Interface, Bounds, Interface->Style.PanelBGColors[0]);
|
||||
|
||||
ui_BeginRow(&State->Interface, 2);
|
||||
if (ui_BeginLabeledDropdown(Interface, MakeString("Active Animation"), ActiveAnim->Name))
|
||||
{
|
||||
ui_Label(Interface, MakeString("Active Animation"));
|
||||
if (ui_BeginDropdown(Interface, ActiveAnim->Name))
|
||||
for (u32 i = 0; i < AnimSystem->Animations.Count; i++)
|
||||
{
|
||||
for (u32 i = 0; i < AnimSystem->Animations.Count; i++)
|
||||
animation Animation = AnimSystem->Animations.Values[i];
|
||||
if (ui_Button(Interface, Animation.Name))
|
||||
{
|
||||
animation Animation = AnimSystem->Animations.Values[i];
|
||||
if (ui_Button(Interface, Animation.Name))
|
||||
AnimSystem->ActiveAnimationIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_EndLabeledDropdown(&State->Interface);
|
||||
|
||||
ui_BeginRow(Interface, 3);
|
||||
{
|
||||
if (ui_Button(Interface, MakeString("New")))
|
||||
{
|
||||
animation NewAnim = {};
|
||||
NewAnim.Name = PushString(State->AnimationSystem.Storage, 256);
|
||||
|
||||
u32 NewAnimIndex = AnimationArray_Push(&State->AnimationSystem.Animations, NewAnim);
|
||||
State->AnimationSystem.ActiveAnimationIndex = NewAnimIndex;
|
||||
}
|
||||
if (ui_Button(Interface, MakeString("Save")))
|
||||
{
|
||||
// Save Animation File
|
||||
// TODO(pjs): If you created the animation via the "new" button, there won't be a file attached.
|
||||
// need to use the file browser to create a file
|
||||
u32 ActiveAnimIndex = State->AnimationSystem.ActiveAnimationIndex;
|
||||
animation ActiveAnimation = State->AnimationSystem.Animations.Values[ActiveAnimIndex];
|
||||
gs_string FileText = AnimSerializer_Serialize(ActiveAnimation, State->Patterns, State->Transient);
|
||||
if (WriteEntireFile(Context.ThreadContext.FileHandler, ActiveAnimation.FileInfo.Path, StringToData(FileText)))
|
||||
{
|
||||
InvalidCodePath;
|
||||
}
|
||||
}
|
||||
if (ui_Button(Interface, MakeString("Load")))
|
||||
{
|
||||
panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context);
|
||||
Panel_PushModalOverride(Panel, FileBrowser, LoadAnimationFileCallback);
|
||||
}
|
||||
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
|
||||
ui_TextEntry(Interface, MakeString("Anim Name"), &ActiveAnim->Name);
|
||||
|
||||
ui_Label(Interface, MakeString("Frame Range"));
|
||||
ui_BeginRow(Interface, 3);
|
||||
{
|
||||
ActiveAnim->PlayableRange.Min = ui_TextEntryU64(Interface, MakeString("StartFrame"), ActiveAnim->PlayableRange.Min);
|
||||
ActiveAnim->PlayableRange.Max = ui_TextEntryU64(Interface, MakeString("EndFrame"), ActiveAnim->PlayableRange.Max);
|
||||
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
|
||||
animation_block* SelectedBlock = Animation_GetBlockFromHandle(ActiveAnim, TimelineState->SelectedBlockHandle);
|
||||
if (SelectedBlock)
|
||||
{
|
||||
animation_pattern BlockPattern = Patterns_GetPattern(State->Patterns, SelectedBlock->AnimationProcHandle);
|
||||
|
||||
ui_BeginRow(Interface, 3);
|
||||
ui_Label(Interface, MakeString("Selected Pattern"));
|
||||
//if (ui_BeginLabeledDropdown(Interface, MakeString("Selected Pattern"), MakeString(BlockPattern.Name, BlockPattern.NameLength)))
|
||||
if (ui_BeginDropdown(Interface, MakeString(BlockPattern.Name, BlockPattern.NameLength)))
|
||||
{
|
||||
for (u32 i = 0; i < State->Patterns.Count; i++)
|
||||
{
|
||||
animation_pattern Pattern = State->Patterns.Values[i];
|
||||
if (ui_Button(Interface, MakeString(Pattern.Name, Pattern.NameLength)))
|
||||
{
|
||||
AnimSystem->ActiveAnimationIndex = i;
|
||||
SelectedBlock->AnimationProcHandle = Patterns_IndexToHandle(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_EndDropdown(Interface);
|
||||
ui_EndLabeledDropdown(Interface);
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
|
||||
ui_PopLayout(Interface);
|
||||
}
|
||||
|
||||
|
@ -831,8 +900,10 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer*
|
|||
rect2 TimelineBounds, InfoBounds;
|
||||
RectVSplit(PanelBounds, 300, &InfoBounds, &TimelineBounds);
|
||||
|
||||
#if 0
|
||||
rect2 AnimInfoBounds, SelectionInfoBounds;
|
||||
RectHSplitAtPercent(InfoBounds, .65f, &AnimInfoBounds, &SelectionInfoBounds);
|
||||
#endif
|
||||
|
||||
{ // Timeline
|
||||
rect2 LayersPanelBounds, TimeRangePanelBounds;
|
||||
|
@ -847,12 +918,11 @@ AnimationTimeline_Render(panel* Panel, rect2 PanelBounds, render_command_buffer*
|
|||
|
||||
PlayBar_Render(TimelineState, PlayBarBounds, Panel, RenderBuffer, State, Context);
|
||||
FrameCount_Render(TimelineState, FrameCountBounds, RenderBuffer, State, Context);
|
||||
LayerList_Render(TimelineState, LayersBounds, RenderBuffer, State, Context);
|
||||
LayerList_Render(TimelineState, LayersBounds, Panel, RenderBuffer, State, Context);
|
||||
TimeRange_Render(TimelineState, TimeRangeBounds, RenderBuffer, State, Context);
|
||||
}
|
||||
|
||||
AnimInfoView_Render(TimelineState, AnimInfoBounds, RenderBuffer, State, Context);
|
||||
SelectionInfoView_Render(TimelineState, SelectionInfoBounds, RenderBuffer, State, Context);
|
||||
AnimInfoView_Render(TimelineState, InfoBounds, Panel, RenderBuffer, State, Context);
|
||||
}
|
||||
|
||||
#define FOLDHAUS_PANEL_ANIMATION_TIMELINE_H
|
||||
|
|
|
@ -69,7 +69,12 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_widget* Layout, de
|
|||
|
||||
ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover"));
|
||||
{
|
||||
PrintF(&String, "%S : %d - %d", Name->Name, Record->StartCycles, Record->EndCycles);
|
||||
s64 Cycles = (Record->EndCycles - Record->StartCycles);
|
||||
r64 PercentFrame = (r64)(Cycles) / (r64)(FrameTotalCycles);
|
||||
PrintF(&String, "%S : %.2f%% frame | %dcy",
|
||||
Name->Name,
|
||||
PercentFrame,
|
||||
Cycles);
|
||||
ui_Label(Interface, String);
|
||||
}
|
||||
ui_EndMousePopup(Interface);
|
||||
|
|
|
@ -226,14 +226,10 @@ SculptureView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren
|
|||
v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, PanelState->Camera, PanelBounds);
|
||||
|
||||
gs_string Tempgs_string = PushString(State->Transient, 256);
|
||||
PrintF(&Tempgs_string, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y);
|
||||
PrintF(&Tempgs_string, "Hot Id: %u, ZIndex: %u | Active Id: %u", State->Interface.HotWidget.Id,
|
||||
State->Interface.HotWidget.ZIndex,State->Interface.ActiveWidget.Id);
|
||||
DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4);
|
||||
|
||||
|
||||
v2 BoxHalfDim = v2{ 25, 25 };
|
||||
v2 BoxMin = LedOnScreenPosition - BoxHalfDim;
|
||||
v2 BoxMax = LedOnScreenPosition + BoxHalfDim;
|
||||
PushRenderBoundingBox2D(RenderBuffer, BoxMin, BoxMax, 2.0f, TealV4);
|
||||
}
|
||||
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,11 @@ struct frame_range
|
|||
s32 Max;
|
||||
};
|
||||
|
||||
struct animation_pattern_handle
|
||||
{
|
||||
s32 IndexPlusOne;
|
||||
};
|
||||
|
||||
// NOTE(pjs): An animation block is a time range paired with an
|
||||
// animation_pattern (see below). While a timeline's current time
|
||||
// is within the range of a block, that particular block's animation
|
||||
|
@ -21,7 +26,7 @@ struct frame_range
|
|||
struct animation_block
|
||||
{
|
||||
frame_range Range;
|
||||
u32 AnimationProcHandle;
|
||||
animation_pattern_handle AnimationProcHandle;
|
||||
u32 Layer;
|
||||
};
|
||||
|
||||
|
@ -76,6 +81,9 @@ struct animation
|
|||
animation_block_array Blocks_;
|
||||
|
||||
frame_range PlayableRange;
|
||||
|
||||
// The information / path to the file where this animation is to be saved / where it is loaded from
|
||||
gs_file_info FileInfo;
|
||||
};
|
||||
|
||||
struct animation_array
|
||||
|
@ -132,6 +140,13 @@ struct animation_pattern
|
|||
animation_proc* Proc;
|
||||
};
|
||||
|
||||
struct animation_pattern_array
|
||||
{
|
||||
animation_pattern* Values;
|
||||
u32 Count;
|
||||
u32 CountMax;
|
||||
};
|
||||
|
||||
// Serialization
|
||||
|
||||
enum animation_field
|
||||
|
@ -185,6 +200,55 @@ global gs_const_string AnimationFieldStrings[] = {
|
|||
ConstString("animation_name"),// AnimField_BlockAnimName
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Patterns List
|
||||
|
||||
internal animation_pattern_array
|
||||
Patterns_Create(gs_memory_arena* Arena, s32 CountMax)
|
||||
{
|
||||
animation_pattern_array Result = {0};
|
||||
Result.CountMax = CountMax;
|
||||
Result.Values = PushArray(Arena, animation_pattern, Result.CountMax);
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define Patterns_PushPattern(array, proc) Patterns_PushPattern_((array), (proc), Stringify(proc), sizeof(Stringify(proc)))
|
||||
internal void
|
||||
Patterns_PushPattern_(animation_pattern_array* Array, animation_proc* Proc, char* Name, u32 NameLength)
|
||||
{
|
||||
Assert(Array->Count < Array->CountMax);
|
||||
|
||||
animation_pattern Pattern = {0};
|
||||
Pattern.Name = Name;
|
||||
Pattern.NameLength = NameLength;
|
||||
Pattern.Proc = Proc;
|
||||
|
||||
Array->Values[Array->Count++] = Pattern;
|
||||
}
|
||||
|
||||
internal animation_pattern_handle
|
||||
Patterns_IndexToHandle(s32 Index)
|
||||
{
|
||||
animation_pattern_handle Result = {};
|
||||
Result.IndexPlusOne = Index + 1;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal animation_pattern
|
||||
Patterns_GetPattern(animation_pattern_array Patterns, animation_pattern_handle Handle)
|
||||
{
|
||||
animation_pattern Result = {0};
|
||||
if (Handle.IndexPlusOne > 0)
|
||||
{
|
||||
u32 Index = Handle.IndexPlusOne - 1;
|
||||
Assert(Index < Patterns.Count);
|
||||
Result = Patterns.Values[Index];
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Anim Block Array
|
||||
|
@ -291,7 +355,7 @@ AnimationArray_Push(animation_array* Array, animation Value)
|
|||
// Animation
|
||||
|
||||
internal handle
|
||||
Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, u32 AnimationProcHandle, u32 LayerIndex)
|
||||
Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, animation_pattern_handle AnimationProcHandle, u32 LayerIndex)
|
||||
{
|
||||
Assert(LayerIndex < Animation->Layers.Count);
|
||||
|
||||
|
|
|
@ -81,21 +81,19 @@ LedBlend_GetProc(blend_mode BlendMode)
|
|||
}
|
||||
|
||||
internal void
|
||||
AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, assembly Assembly, animation_pattern* Patterns, gs_memory_arena* Transient)
|
||||
AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, assembly Assembly, animation_pattern_array Patterns, gs_memory_arena* Transient)
|
||||
{
|
||||
u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min;
|
||||
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
|
||||
|
||||
// :AnimProcHandle
|
||||
u32 AnimationProcIndex = Block.AnimationProcHandle - 1;
|
||||
animation_proc* AnimationProc = Patterns[AnimationProcIndex].Proc;
|
||||
AnimationProc(Buffer, Assembly, SecondsIntoBlock, Transient);
|
||||
animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle);
|
||||
Pattern.Proc(Buffer, Assembly, SecondsIntoBlock, Transient);
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies,
|
||||
led_system* LedSystem,
|
||||
animation_pattern* Patterns,
|
||||
animation_pattern_array Patterns,
|
||||
gs_memory_arena* Transient)
|
||||
{
|
||||
s32 CurrentFrame = System->CurrentFrame;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
||||
|
||||
internal gs_string
|
||||
AnimSerializer_Serialize(animation Anim, animation_pattern* GlobalClips, gs_memory_arena* Arena)
|
||||
AnimSerializer_Serialize(animation Anim, animation_pattern_array Patterns, gs_memory_arena* Arena)
|
||||
{
|
||||
serializer Serializer = {0};
|
||||
Serializer.String = PushString(Arena, 4096);
|
||||
|
@ -45,10 +45,7 @@ AnimSerializer_Serialize(animation Anim, animation_pattern* GlobalClips, gs_memo
|
|||
// TODO(pjs): Handle free'd animation blocks
|
||||
animation_block AnimationBlockAt = Anim.Blocks_.Values[i];
|
||||
|
||||
// TODO(pjs): Systematize the AnimationProcHandle
|
||||
// :AnimProcHandle
|
||||
u32 AnimationProcIndex = AnimationBlockAt.AnimationProcHandle - 1;
|
||||
animation_pattern Animation = GlobalClips[AnimationProcIndex];
|
||||
animation_pattern Animation = Patterns_GetPattern(Patterns, AnimationBlockAt.AnimationProcHandle);
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_Block);
|
||||
{
|
||||
|
@ -70,7 +67,7 @@ AnimSerializer_Serialize(animation Anim, animation_pattern* GlobalClips, gs_memo
|
|||
}
|
||||
|
||||
internal animation
|
||||
AnimParser_Parse(gs_string File, gs_memory_arena* Arena, u32 AnimClipsCount, animation_pattern* AnimClips)
|
||||
AnimParser_Parse(gs_string File, gs_memory_arena* Arena, animation_pattern_array AnimPatterns)
|
||||
{
|
||||
animation Result = {0};
|
||||
|
||||
|
@ -162,12 +159,13 @@ AnimParser_Parse(gs_string File, gs_memory_arena* Arena, u32 AnimClipsCount, ani
|
|||
|
||||
// TODO(pjs): AnimName -> Animation Proc Handle
|
||||
gs_string AnimName = Parser_ReadStringValue(&Parser, AnimField_BlockAnimName);
|
||||
Block.AnimationProcHandle = 0;
|
||||
for (u32 i = 0; i < AnimClipsCount; i++)
|
||||
Block.AnimationProcHandle = {0};
|
||||
for (u32 i = 0; i < AnimPatterns.Count; i++)
|
||||
{
|
||||
if (StringEqualsCharArray(AnimName.ConstString, AnimClips[i].Name, CStringLength(AnimClips[i].Name)))
|
||||
animation_pattern Pattern = AnimPatterns.Values[i];
|
||||
if (StringEqualsCharArray(AnimName.ConstString, Pattern.Name, Pattern.NameLength))
|
||||
{
|
||||
Block.AnimationProcHandle = i + 1;
|
||||
Block.AnimationProcHandle = Patterns_IndexToHandle(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position)
|
|||
}
|
||||
|
||||
internal u32
|
||||
Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* StripAt, strip_gen_data GenData, v4 RootPosition, u32 LedStartIndex)
|
||||
Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* StripAt, strip_gen_data GenData, v4 RootPosition, u32 LedStartIndex, u32 LedLUTStartIndex)
|
||||
{
|
||||
u32 LedsAdded = 0;
|
||||
|
||||
|
@ -154,7 +154,7 @@ Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* Str
|
|||
s32 LedIndex = LedStartIndex + LedsAdded++;
|
||||
v4 LedPosition = WS_StripStart + (SingleStep * Step);
|
||||
LedBufferSetLed(LedBuffer, LedIndex, LedPosition);
|
||||
StripAt->LedLUT[Step] = LedIndex;
|
||||
StripAt->LedLUT[Step + LedLUTStartIndex] = LedIndex;
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -164,7 +164,7 @@ Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* Str
|
|||
for (u32 i = 0; i < Sequence.ElementsCount; i++)
|
||||
{
|
||||
strip_gen_data SegmentGenData = Sequence.Elements[i];
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded);
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded, LedsAdded);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -190,7 +190,7 @@ ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
|||
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
|
||||
|
||||
strip_gen_data GenData = StripAt->GenerationData;
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded);
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,23 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal void
|
||||
ClearAndPushPatterns(animation_pattern_array* Patterns)
|
||||
{
|
||||
if (Patterns->CountMax == 0) { return; }
|
||||
|
||||
Patterns->Count = 0;
|
||||
Patterns_PushPattern(Patterns, TestPatternOne);
|
||||
Patterns_PushPattern(Patterns, TestPatternTwo);
|
||||
Patterns_PushPattern(Patterns, TestPatternThree);
|
||||
Patterns_PushPattern(Patterns, Pattern_AllGreen);
|
||||
Patterns_PushPattern(Patterns, Pattern_HueShift);
|
||||
Patterns_PushPattern(Patterns, Pattern_HueFade);
|
||||
Patterns_PushPattern(Patterns, Pattern_Spots);
|
||||
Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow);
|
||||
Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow);
|
||||
}
|
||||
|
||||
RELOAD_STATIC_DATA(ReloadStaticData)
|
||||
{
|
||||
app_state* State = (app_state*)Context.MemoryBase;
|
||||
|
@ -17,6 +34,8 @@ RELOAD_STATIC_DATA(ReloadStaticData)
|
|||
GlobalDebugServices = DebugServices;
|
||||
State->PanelSystem.PanelDefs = GlobalPanelDefs;
|
||||
State->PanelSystem.PanelDefsCount = GlobalPanelDefsCount;
|
||||
|
||||
ClearAndPushPatterns(&State->Patterns);
|
||||
}
|
||||
|
||||
INITIALIZE_APPLICATION(InitializeApplication)
|
||||
|
@ -34,6 +53,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
|
||||
State->CommandQueue = CommandQueue_Create(&State->Permanent, 32);
|
||||
|
||||
State->Patterns = Patterns_Create(&State->Permanent, 10);
|
||||
ClearAndPushPatterns(&State->Patterns);
|
||||
|
||||
// TODO(Peter): put in InitializeInterface?
|
||||
r32 FontSize = 14;
|
||||
{
|
||||
|
@ -112,13 +134,14 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->Interface.Widgets = PushArray(&State->Permanent, ui_widget, State->Interface.WidgetsCountMax);
|
||||
State->Interface.PerFrameMemory = PushStruct(&State->Permanent, gs_memory_arena);
|
||||
*State->Interface.PerFrameMemory = CreateMemoryArena(Context.ThreadContext.Allocator);
|
||||
State->Interface.Permanent = &State->Permanent;
|
||||
|
||||
State->SACN = SACN_Initialize(Context);
|
||||
|
||||
State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128);
|
||||
|
||||
#if 1
|
||||
gs_const_string SculpturePath = ConstString("data/blumen_lumen_silver_spring.fold");
|
||||
gs_const_string SculpturePath = ConstString("data/test_blumen.fold");
|
||||
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);
|
||||
#endif
|
||||
|
||||
|
@ -147,7 +170,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
Animation_AddLayer(&Anim, MakeString("Color Layer"), BlendMode_Multiply, &State->AnimationSystem);
|
||||
Animation_AddLayer(&Anim, MakeString("Sparkles"), BlendMode_Add, &State->AnimationSystem);
|
||||
|
||||
Animation_AddBlock(&Anim, 0, Anim.PlayableRange.Max, 4, 0);
|
||||
Animation_AddBlock(&Anim, 0, Anim.PlayableRange.Max, Patterns_IndexToHandle(5), 0);
|
||||
|
||||
AnimationArray_Push(&State->AnimationSystem.Animations, Anim);
|
||||
|
||||
|
@ -178,7 +201,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
AnimationSystem_RenderToLedBuffers(&State->AnimationSystem,
|
||||
State->Assemblies,
|
||||
&State->LedSystem,
|
||||
GlobalAnimationPatterns,
|
||||
State->Patterns,
|
||||
State->Transient);
|
||||
}
|
||||
|
||||
|
@ -192,19 +215,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
}
|
||||
|
||||
Editor_Render(State, Context, RenderBuffer);
|
||||
|
||||
// Checking for overflows
|
||||
#if 0
|
||||
{
|
||||
DEBUG_TRACK_SCOPE(OverflowChecks);
|
||||
AssertAllocationsNoOverflow(State->Permanent);
|
||||
for (u32 i = 0; i < State->Assemblies.Count; i++)
|
||||
{
|
||||
assembly* Assembly = &State->Assemblies.Values[i];
|
||||
AssertAllocationsNoOverflow(Assembly->Arena);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP_APPLICATION(CleanupApplication)
|
||||
|
|
|
@ -53,6 +53,7 @@ struct app_state
|
|||
assembly_array Assemblies;
|
||||
animation_system AnimationSystem;
|
||||
event_log* GlobalLog;
|
||||
animation_pattern_array Patterns;
|
||||
|
||||
// Interface
|
||||
//
|
||||
|
@ -205,8 +206,15 @@ TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
|
|||
v4 HSVToRGB (v4 In)
|
||||
{
|
||||
float Hue = In.x;
|
||||
while (Hue > 360.0f) { Hue -= 360.0f; }
|
||||
/*
|
||||
while (Hue > 360.0f) { Hue -= 360.0f; }
|
||||
while (Hue < 0.0f) { Hue += 360.0f; }
|
||||
*/
|
||||
Hue = ModR32(Hue, 360.0f);
|
||||
if (Hue < 0) { Hue += 360.0f; }
|
||||
if (Hue == MinR32) { Hue = 0; }
|
||||
if (Hue == MaxR32) { Hue = 360; }
|
||||
Assert(Hue >= 0 && Hue < 360);
|
||||
|
||||
float Sat = In.y;
|
||||
float Value = In.z;
|
||||
|
@ -279,9 +287,8 @@ v4 HSVToRGB (v4 In)
|
|||
}
|
||||
|
||||
internal void
|
||||
Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
{
|
||||
#if 1
|
||||
r32 Height = SinR32(Time) * 25;
|
||||
|
||||
r32 CycleLength = 5.0f;
|
||||
|
@ -304,7 +311,41 @@ Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
|
|||
Leds->Colors[LedIndex].G = G;
|
||||
Leds->Colors[LedIndex].B = B;
|
||||
}
|
||||
#else
|
||||
}
|
||||
|
||||
internal pixel
|
||||
V4ToRGBPixel(v4 C)
|
||||
{
|
||||
pixel Result = {};
|
||||
Result.R = (u8)(C.x * 255);
|
||||
Result.G = (u8)(C.y * 255);
|
||||
Result.B = (u8)(C.z * 255);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
{
|
||||
r32 HueBase = ModR32(Time * 50, 360);
|
||||
|
||||
r32 CycleLength = 5.0f;
|
||||
r32 CycleProgress = FractR32(Time / CycleLength);
|
||||
r32 CycleBlend = (SinR32(Time) * .5f) + .5f;
|
||||
|
||||
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
|
||||
{
|
||||
v4 Pos = Leds->Positions[LedIndex];
|
||||
r32 Hue = HueBase + Pos.y + Pos.x;
|
||||
v4 HSV = { Hue, 1, 1, 1 };
|
||||
v4 RGB = HSVToRGB(HSV);
|
||||
|
||||
Leds->Colors[LedIndex] = V4ToRGBPixel(RGB);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
{
|
||||
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
|
||||
{
|
||||
u32 I = LedIndex + 1;
|
||||
|
@ -322,6 +363,110 @@ Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
|
|||
Leds->Colors[LedIndex].B = 255;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal r32
|
||||
PatternHash(r32 Seed)
|
||||
{
|
||||
return FractR32(Seed * 17.0 * FractR32(Seed * 0.3183099));
|
||||
}
|
||||
|
||||
internal void
|
||||
Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
{
|
||||
pixel ColorA = { 0, 255, 255 };
|
||||
pixel ColorB = { 255, 0, 255 };
|
||||
|
||||
r32 Speed = .5f;
|
||||
Time *= Speed;
|
||||
r32 ScaleA = 2 * SinR32(Time / 5);
|
||||
r32 ScaleB = 2.4f * CosR32(Time / 2.5f);
|
||||
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
|
||||
{
|
||||
v4 P = Leds->Positions[LedIndex];
|
||||
r32 V = P.y;
|
||||
r32 Noise = .3f * PatternHash(V);
|
||||
r32 ThetaY = (Leds->Positions[LedIndex].y / 10) + Time + Noise;
|
||||
r32 ThetaX = (Leds->Positions[LedIndex].x / 13) + Time + Noise;
|
||||
r32 Fade = (ScaleA * SinR32(ThetaY)) + (ScaleB * CosR32(3 * ThetaX));
|
||||
Fade = RemapClampedR32(Fade, -1, 1, 0, 1);
|
||||
|
||||
Leds->Colors[LedIndex].R = (u8)LerpR32(Fade, ColorA.R, ColorB.R);
|
||||
Leds->Colors[LedIndex].G = (u8)LerpR32(Fade, ColorA.G, ColorB.G);
|
||||
Leds->Colors[LedIndex].B = (u8)LerpR32(Fade, ColorA.B, ColorB.B);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
Pattern_LighthouseRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
{
|
||||
v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) });
|
||||
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
|
||||
{
|
||||
v2 Vector = v2{
|
||||
Leds->Positions[LedIndex].x,
|
||||
Leds->Positions[LedIndex].z
|
||||
};
|
||||
Vector = V2Normalize(Vector);
|
||||
|
||||
r32 Angle = V2Dot(RefVector, Vector);
|
||||
|
||||
#if 0
|
||||
r32 Fade = RemapR32(Angle, -1, 1, 0, 1);
|
||||
Leds->Colors[LedIndex].R = (u8)(Fade * 255);
|
||||
Leds->Colors[LedIndex].G = (u8)(Fade * 255);
|
||||
Leds->Colors[LedIndex].B = (u8)(Fade * 255);
|
||||
#endif
|
||||
|
||||
v4 HSV = { (Angle * 30) + (Time * 10) + Leds->Positions[LedIndex].y, 1, 1, 1 };
|
||||
v4 RGB = HSVToRGB(HSV);
|
||||
|
||||
Leds->Colors[LedIndex] = V4ToRGBPixel(RGB);
|
||||
}
|
||||
}
|
||||
|
||||
internal r32
|
||||
Smoothstep(r32 T)
|
||||
{
|
||||
r32 Result = (T * T * (3 - (2 * T)));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
Pattern_SmoothGrowRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient)
|
||||
{
|
||||
r32 FillCycleTime = ModR32(Time, 7.0f) / 7.0f;
|
||||
r32 ColorCycleTime = ModR32(Time, 21.0f) / 21.0f;
|
||||
|
||||
//v4 HSV = { ColorCycleTime * 360, 1, 1, 1 };
|
||||
//v4 RGB0 = HSVToRGB(HSV);
|
||||
//HSV.x += ;
|
||||
//v4 RGB1 = HSVToRGB(HSV);
|
||||
|
||||
v4 HSV = { 0, 1, 1, 1 };
|
||||
for (u32 s = 0; s < Assembly.StripCount; s++)
|
||||
{
|
||||
v2_strip Strip = Assembly.Strips[s];
|
||||
|
||||
v4 RGB0 = HSVToRGB(HSV);
|
||||
for (u32 l = 0; l < Strip.LedCount; l++)
|
||||
{
|
||||
u32 LedIndex = Strip.LedLUT[l];
|
||||
Leds->Colors[LedIndex] = V4ToRGBPixel(RGB0);
|
||||
}
|
||||
|
||||
HSV.x += 15;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
|
||||
{
|
||||
v4 P = Leds->Positions[LedIndex];
|
||||
|
||||
Leds->Colors[LedIndex] = V4ToRGBPixel(RGB0);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -334,14 +479,6 @@ EndCurrentOperationMode(app_state* State)
|
|||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
s32 GlobalAnimationPatternsCount = 4;
|
||||
animation_pattern GlobalAnimationPatterns[] = {
|
||||
{ "Test Pattern One", 16, TestPatternOne },
|
||||
{ "Test Pattern Two", 16, TestPatternTwo },
|
||||
{ "Test Pattern Three", 18, TestPatternThree },
|
||||
{ "Pattern_AllGreen", 16, Pattern_AllGreen },
|
||||
};
|
||||
|
||||
#include "editor/panels/foldhaus_panel_types.h"
|
||||
|
||||
#include "editor/panels/foldhaus_panel_file_view.h"
|
||||
|
|
|
@ -231,20 +231,24 @@ DrawStringWithCursor (render_command_buffer* RenderBuffer, gs_string String, s32
|
|||
enum ui_widget_flag
|
||||
{
|
||||
UIWidgetFlag_ExpandsToFitChildren,
|
||||
|
||||
UIWidgetFlag_DrawBackground,
|
||||
UIWidgetFlag_DrawString,
|
||||
UIWidgetFlag_DrawOutline,
|
||||
UIWidgetFlag_Clickable,
|
||||
UIWidgetFlag_DrawHorizontalFill,
|
||||
UIWidgetFlag_DrawVerticalFill,
|
||||
UIWidgetFlag_DrawFillReversed,
|
||||
UIWidgetFlag_DrawFillAsHandle,
|
||||
|
||||
UIWidgetFlag_Clickable,
|
||||
UIWidgetFlag_Selectable,
|
||||
UIWidgetFlag_Typable,
|
||||
};
|
||||
|
||||
struct ui_widget_id
|
||||
{
|
||||
u64 Id;
|
||||
u64 ParentId;
|
||||
u64 ZIndex;
|
||||
};
|
||||
|
||||
enum ui_layout_direction
|
||||
|
@ -293,6 +297,8 @@ struct ui_widget
|
|||
// we can check the retained state of that dropdown
|
||||
ui_widget_id WidgetReference;
|
||||
|
||||
u64 ChildZIndexOffset;
|
||||
|
||||
ui_widget* ChildrenRoot;
|
||||
ui_widget* ChildrenHead;
|
||||
u32 ChildCount;
|
||||
|
@ -334,6 +340,8 @@ struct ui_widget_retained_state
|
|||
|
||||
// For use in layouts that allow you to scroll / pan
|
||||
v2 ChildrenDrawOffset;
|
||||
|
||||
gs_string EditString;
|
||||
};
|
||||
|
||||
struct ui_interface
|
||||
|
@ -343,6 +351,9 @@ struct ui_interface
|
|||
mouse_state Mouse;
|
||||
rect2 WindowBounds;
|
||||
|
||||
// A per-frame string of the characters which have been typed
|
||||
gs_const_string TempInputString;
|
||||
|
||||
render_command_buffer* RenderBuffer;
|
||||
|
||||
ui_widget* Widgets;
|
||||
|
@ -353,7 +364,11 @@ struct ui_interface
|
|||
ui_widget* DrawOrderRoot;
|
||||
|
||||
ui_widget_id HotWidget;
|
||||
// This should really never get higher than 1 or 2
|
||||
u8 HotWidgetFramesSinceUpdate;
|
||||
|
||||
ui_widget_id ActiveWidget;
|
||||
ui_widget_id LastActiveWidget;
|
||||
|
||||
ui_widget* ActiveLayout;
|
||||
|
||||
|
@ -362,6 +377,12 @@ struct ui_interface
|
|||
u64 RetainedStateCount;
|
||||
|
||||
gs_memory_arena* PerFrameMemory;
|
||||
|
||||
// TODO(pjs): DONT USE THIS
|
||||
// Right now you only need this to create EditStrings for ui_widget_retained_state's
|
||||
// and even for those, you eventually want a better solution than "create a string and it lives forever"
|
||||
// TODO(pjs): Get rid of the need for this vvv
|
||||
gs_memory_arena* Permanent;
|
||||
};
|
||||
|
||||
internal void
|
||||
|
@ -380,12 +401,14 @@ ui_InterfaceReset(ui_interface* Interface)
|
|||
Interface->RetainedState[i] = {0};
|
||||
}
|
||||
}
|
||||
|
||||
Interface->LastActiveWidget = Interface->ActiveWidget;
|
||||
}
|
||||
|
||||
internal bool
|
||||
ui_WidgetIdsEqual(ui_widget_id A, ui_widget_id B)
|
||||
{
|
||||
bool Result = (A.Id == B.Id) && (A.ParentId == B.ParentId);
|
||||
bool Result = (A.Id == B.Id);// && (A.ParentId == B.ParentId);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -411,6 +434,53 @@ ui_WidgetIsFlagSet(ui_widget Widget, u64 Flag)
|
|||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ui_WidgetSetChildrenPopover(ui_widget* Widget)
|
||||
{
|
||||
Widget->ChildZIndexOffset = 1000;
|
||||
}
|
||||
|
||||
internal ui_widget*
|
||||
ui_WidgetGetWidgetWithId(ui_widget* Parent, ui_widget_id Id)
|
||||
{
|
||||
ui_widget* Result = 0;
|
||||
|
||||
if (ui_WidgetIdsEqual(Parent->Id, Id))
|
||||
{
|
||||
Result = Parent;
|
||||
}
|
||||
else if (Parent->ChildrenRoot != 0)
|
||||
{
|
||||
for (ui_widget* At = Parent->ChildrenRoot; At != 0; At = At->Next)
|
||||
{
|
||||
Result = ui_WidgetGetWidgetWithId(At, Id);
|
||||
if (Result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal ui_widget*
|
||||
ui_InterfaceGetWidgetWithId(ui_interface* Interface, ui_widget_id Id)
|
||||
{
|
||||
ui_widget* Result = 0;
|
||||
|
||||
for (ui_widget* At = Interface->DrawOrderRoot; At != 0; At = At->Next)
|
||||
{
|
||||
Result = ui_WidgetGetWidgetWithId(At, Id);
|
||||
if (Result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal ui_widget_retained_state*
|
||||
ui_GetRetainedState(ui_interface* Interface, ui_widget_id Id)
|
||||
{
|
||||
|
@ -433,6 +503,7 @@ ui_CreateRetainedState(ui_interface* Interface, ui_widget* Widget)
|
|||
u64 Index = Interface->RetainedStateCount++;
|
||||
ui_widget_retained_state* Result = Interface->RetainedState + Index;
|
||||
Result->Id = Widget->Id;
|
||||
Result->EditString = PushString(Interface->Permanent, 256);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -451,7 +522,8 @@ internal ui_widget*
|
|||
ui_CreateWidget(ui_interface* Interface, gs_string String)
|
||||
{
|
||||
Assert(Interface->WidgetsCount < Interface->WidgetsCountMax);
|
||||
ui_widget* Result = Interface->Widgets + Interface->WidgetsCount++;
|
||||
u64 Index = Interface->WidgetsCount++;
|
||||
ui_widget* Result = Interface->Widgets + Index;
|
||||
ZeroStruct(Result);
|
||||
|
||||
Result->Parent = Interface->ActiveLayout;
|
||||
|
@ -461,10 +533,18 @@ ui_CreateWidget(ui_interface* Interface, gs_string String)
|
|||
{
|
||||
Id = HashAppendDJB2ToU32(Id, Result->Parent->Id.Id);
|
||||
Id = HashAppendDJB2ToU32(Id, Result->Parent->ChildCount);
|
||||
Result->Id.ParentId = Result->Parent->Id.Id;
|
||||
//Result->Id.ParentId = Result->Parent->Id.Id;
|
||||
}
|
||||
Result->Id.Id = Id;
|
||||
|
||||
u64 ZIndex = Index + 1;
|
||||
if (Result->Parent)
|
||||
{
|
||||
Result->ChildZIndexOffset += Result->Parent->ChildZIndexOffset;
|
||||
ZIndex += Result->Parent->ChildZIndexOffset;
|
||||
}
|
||||
Result->Id.ZIndex = ZIndex;
|
||||
|
||||
Result->String = PushStringCopy(Interface->PerFrameMemory, String.ConstString);
|
||||
Result->Alignment = Align_Left;
|
||||
Result->Next = 0;
|
||||
|
@ -859,20 +939,81 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds)
|
|||
Interface->ActiveLayout->ChildCount += 1;
|
||||
ui_CommitBounds(Widget->Parent, Widget->Bounds);
|
||||
|
||||
if (PointIsInRect(Widget->Parent->Bounds, Interface->Mouse.Pos) &&
|
||||
PointIsInRect(Widget->Bounds, Interface->Mouse.Pos))
|
||||
{
|
||||
if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState))
|
||||
{
|
||||
if (ui_WidgetIdsEqual(Interface->HotWidget, Widget->Id))
|
||||
{
|
||||
Result.Clicked = true;
|
||||
Interface->ActiveWidget = Widget->Id;
|
||||
}
|
||||
}
|
||||
|
||||
if (Interface->HotWidget.ZIndex == 0 ||
|
||||
Interface->HotWidget.ZIndex <= Widget->Id.ZIndex)
|
||||
{
|
||||
Interface->HotWidget = Widget->Id;
|
||||
Interface->HotWidgetFramesSinceUpdate = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id) &&
|
||||
MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState))
|
||||
{
|
||||
Interface->ActiveWidget = {};
|
||||
}
|
||||
}
|
||||
|
||||
if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id))
|
||||
{
|
||||
// click & drag
|
||||
if (MouseButtonHeldDown(Interface->Mouse.LeftButtonState))
|
||||
{
|
||||
Result.Held = true;
|
||||
Result.DragDelta = Interface->Mouse.Pos - Interface->Mouse.DownPos;
|
||||
}
|
||||
|
||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable) &&
|
||||
Interface->TempInputString.Length > 0)
|
||||
{
|
||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
||||
|
||||
// TODO(pjs): Backspace?
|
||||
for (u32 i = 0; i < Interface->TempInputString.Length; i++)
|
||||
{
|
||||
if (Interface->TempInputString.Str[i] == '\b')
|
||||
{
|
||||
State->EditString.Length -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutChar(&State->EditString, Interface->TempInputString.Str[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// if you can click it
|
||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Clickable))
|
||||
{
|
||||
// updating hot widget, and handling mouse clicks
|
||||
if (PointIsInRect(Widget->Parent->Bounds, Interface->Mouse.Pos) &&
|
||||
PointIsInRect(Widget->Bounds, Interface->Mouse.Pos))
|
||||
{
|
||||
if (ui_WidgetIdsEqual(Interface->HotWidget, Widget->Id) && MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState))
|
||||
{
|
||||
Assert(!ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id));
|
||||
Result.Clicked = true;
|
||||
Interface->ActiveWidget = Widget->Id;
|
||||
}
|
||||
|
||||
Interface->HotWidget = Widget->Id;
|
||||
}
|
||||
|
||||
// click and drag
|
||||
if (MouseButtonHeldDown(Interface->Mouse.LeftButtonState) &&
|
||||
PointIsInRect(Widget->Bounds, Interface->Mouse.DownPos))
|
||||
{
|
||||
|
@ -880,13 +1021,45 @@ ui_EvaluateWidget(ui_interface* Interface, ui_widget* Widget, rect2 Bounds)
|
|||
Result.DragDelta = Interface->Mouse.Pos - Interface->Mouse.DownPos;
|
||||
}
|
||||
|
||||
if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id) &&
|
||||
MouseButtonTransitionedUp(Interface->Mouse.LeftButtonState))
|
||||
// if this is the active widget (its been clicked)
|
||||
if (ui_WidgetIdsEqual(Interface->ActiveWidget, Widget->Id))
|
||||
{
|
||||
Interface->ActiveWidget = {};
|
||||
}
|
||||
// if you can select it
|
||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Selectable))
|
||||
{
|
||||
//
|
||||
if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState) &&
|
||||
!PointIsInRect(Widget->Bounds, Interface->Mouse.Pos))
|
||||
{
|
||||
Interface->ActiveWidget = {};
|
||||
}
|
||||
|
||||
if (ui_WidgetIsFlagSet(*Widget, UIWidgetFlag_Typable) &&
|
||||
Interface->TempInputString.Length > 0)
|
||||
{
|
||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
||||
|
||||
// TODO(pjs): Backspace?
|
||||
for (u32 i = 0; i < Interface->TempInputString.Length; i++)
|
||||
{
|
||||
if (Interface->TempInputString.Str[i] == '\b')
|
||||
{
|
||||
State->EditString.Length -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutChar(&State->EditString, Interface->TempInputString.Str[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MouseButtonTransitionedUp(Interface->Mouse.LeftButtonState))
|
||||
{
|
||||
Interface->ActiveWidget = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Assert(Widget->Parent != 0);
|
||||
return Result;
|
||||
|
@ -941,6 +1114,77 @@ ui_Label(ui_interface* Interface, gs_string String, gs_string_alignment Alignmen
|
|||
ui_EvaluateWidget(Interface, Widget);
|
||||
}
|
||||
|
||||
internal void
|
||||
ui_TextEntrySetFlags(ui_widget* Widget, gs_string EditString)
|
||||
{
|
||||
Widget->String = EditString;
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString);
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground);
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_Clickable);
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_Selectable);
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_Typable);
|
||||
}
|
||||
|
||||
internal void
|
||||
ui_TextEntry(ui_interface* Interface, gs_string Identifier, gs_string* Value)
|
||||
{
|
||||
ui_widget* Widget = ui_CreateWidget(Interface, Identifier);
|
||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
||||
if (!State)
|
||||
{
|
||||
State = ui_CreateRetainedState(Interface, Widget);
|
||||
}
|
||||
PrintF(&State->EditString, "%S", *Value);
|
||||
|
||||
ui_TextEntrySetFlags(Widget, State->EditString);
|
||||
|
||||
ui_eval_result Result = ui_EvaluateWidget(Interface, Widget);
|
||||
PrintF(Value, "%S", State->EditString);
|
||||
}
|
||||
|
||||
internal u64
|
||||
ui_TextEntryU64(ui_interface* Interface, gs_string String, u64 CurrentValue)
|
||||
{
|
||||
ui_widget* Widget = ui_CreateWidget(Interface, String);
|
||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
||||
if (!State)
|
||||
{
|
||||
State = ui_CreateRetainedState(Interface, Widget);
|
||||
PrintF(&State->EditString, "%u", CurrentValue);
|
||||
}
|
||||
ui_TextEntrySetFlags(Widget, State->EditString);
|
||||
|
||||
ui_eval_result Result = ui_EvaluateWidget(Interface, Widget);
|
||||
parse_uint_result ParseResult = ValidateAndParseUInt(State->EditString.ConstString);
|
||||
u64 ValueResult = CurrentValue;
|
||||
if (ParseResult.Success)
|
||||
{
|
||||
ValueResult = ParseResult.Value;
|
||||
}
|
||||
return ValueResult;
|
||||
}
|
||||
|
||||
internal r64
|
||||
ui_TextEntryR64(ui_interface* Interface, gs_string String, r64 CurrentValue)
|
||||
{
|
||||
ui_widget* Widget = ui_CreateWidget(Interface, String);
|
||||
ui_widget_retained_state* State = ui_GetRetainedState(Interface, Widget->Id);
|
||||
if (!State)
|
||||
{
|
||||
State = ui_CreateRetainedState(Interface, Widget);
|
||||
PrintF(&State->EditString, "%f", CurrentValue);
|
||||
}
|
||||
ui_TextEntrySetFlags(Widget, State->EditString);
|
||||
ui_eval_result Result = ui_EvaluateWidget(Interface, Widget);
|
||||
parse_float_result ParseResult = ValidateAndParseFloat(State->EditString.ConstString);
|
||||
r64 ValueResult = CurrentValue;
|
||||
if (ParseResult.Success)
|
||||
{
|
||||
ValueResult = ParseResult.Value;
|
||||
}
|
||||
return ValueResult;
|
||||
}
|
||||
|
||||
internal ui_widget*
|
||||
ui_CreateButtonWidget(ui_interface* Interface, gs_string Text)
|
||||
{
|
||||
|
@ -1057,6 +1301,7 @@ ui_EvaluateDropdown(ui_interface* Interface, ui_widget* Widget, ui_eval_result E
|
|||
Layout->Margin.y = 0;
|
||||
Layout->WidgetReference = Widget->Id;
|
||||
ui_WidgetClearFlag(Layout, UIWidgetFlag_DrawOutline);
|
||||
ui_WidgetSetChildrenPopover(Layout);
|
||||
}
|
||||
|
||||
return State->Value;
|
||||
|
@ -1070,6 +1315,7 @@ ui_BeginDropdown(ui_interface* Interface, gs_string Text, rect2 Bounds)
|
|||
ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawBackground);
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawString);
|
||||
ui_WidgetSetFlag(Widget, UIWidgetFlag_DrawOutline);
|
||||
|
||||
ui_eval_result Result = ui_EvaluateWidget(Interface, Widget, Bounds);
|
||||
return ui_EvaluateDropdown(Interface, Widget, Result);
|
||||
}
|
||||
|
@ -1266,5 +1512,21 @@ ui_EndMousePopup(ui_interface* Interface)
|
|||
ui_PopLayout(Interface);
|
||||
}
|
||||
|
||||
//
|
||||
internal bool
|
||||
ui_BeginLabeledDropdown(ui_interface* Interface, gs_string Label, gs_string DropdownValue)
|
||||
{
|
||||
ui_BeginRow(Interface, 2);
|
||||
ui_Label(Interface, Label);
|
||||
return ui_BeginDropdown(Interface, DropdownValue);
|
||||
}
|
||||
|
||||
internal void
|
||||
ui_EndLabeledDropdown(ui_interface* Interface)
|
||||
{
|
||||
ui_EndDropdown(Interface);
|
||||
ui_EndRow(Interface);
|
||||
}
|
||||
|
||||
#define INTERFACE_H
|
||||
#endif // INTERFACE_H
|
|
@ -0,0 +1,102 @@
|
|||
//
|
||||
// File: interface_test.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-11-15
|
||||
//
|
||||
#ifndef INTERFACE_TEST_CPP
|
||||
|
||||
global r32 TestSlider_Value = 5;
|
||||
global r32 TestSlider_Min = 0;
|
||||
global r32 TestSlider_Max = 10;
|
||||
global bool TestToggle = true;
|
||||
global r64 TestTextEntry = 3.1415f;
|
||||
|
||||
internal void
|
||||
InterfaceTest_Render(app_state* State, context* Context, render_command_buffer* RenderBuffer)
|
||||
{
|
||||
ui_InterfaceReset(&State->Interface);
|
||||
State->Interface.RenderBuffer = RenderBuffer;
|
||||
State->Interface.WindowBounds = Context->WindowBounds;
|
||||
|
||||
gs_string A = MakeString("TestRender Layout");
|
||||
|
||||
ui_PushLayout(&State->Interface, A);
|
||||
{
|
||||
#if 1
|
||||
TestTextEntry = ui_TextEntryR64(&State->Interface, MakeString("Spacer"), TestTextEntry);
|
||||
ui_Button(&State->Interface, MakeString("A"));
|
||||
TestSlider_Value = ui_RangeSlider(&State->Interface, MakeString("TestSlider"), TestSlider_Value, TestSlider_Min, TestSlider_Max);
|
||||
#elif 0
|
||||
ui_PushLayout(&State->Interface, MakeString("Outer"));
|
||||
{
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("A"));
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
||||
ui_BeginRow(&State->Interface, 2);
|
||||
{
|
||||
ui_PushLayout(&State->Interface, MakeString("TestLayout"));
|
||||
{
|
||||
for (u32 i = 0; i < 5; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
||||
ui_PushLayout(&State->Interface, MakeString("TestLayout"));
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
TestToggle = ui_Toggle(&State->Interface, MakeString("Toggle"), TestToggle);
|
||||
TestSlider_Value = ui_RangeSlider(&State->Interface, MakeString("TestSlider"), TestSlider_Value, TestSlider_Min, TestSlider_Max);
|
||||
if (ui_BeginDropdown(&State->Interface, MakeString("TestDropdown")))
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
ui_Button(&State->Interface, MakeString("TestButon"));
|
||||
}
|
||||
ui_EndDropdown(&State->Interface);
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
|
||||
ui_PushLayout(&State->Interface, MakeString("Outer"));
|
||||
{
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("B"));
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
|
||||
#else
|
||||
ui_BeginList(&State->Interface, MakeString("Test List"), 10);
|
||||
{
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
ui_Button(&State->Interface, MakeString("Option"));
|
||||
}
|
||||
}
|
||||
ui_EndList(&State->Interface);
|
||||
#endif
|
||||
|
||||
ui_PushOverlayLayout(&State->Interface, rect2{25, 25, 400, 200}, LayoutDirection_TopDown, MakeString("t"));
|
||||
{
|
||||
ui_Label(&State->Interface, PushStringF(State->Interface.PerFrameMemory, 256, "Mouse Pos - %f %f", State->Interface.Mouse.Pos.x, State->Interface.Mouse.Pos.y));
|
||||
ui_Label(&State->Interface, PushStringF(State->Interface.PerFrameMemory, 256, "Hot - %lld | Active - %lld",
|
||||
State->Interface.HotWidget.Id, State->Interface.ActiveWidget.Id));
|
||||
ui_Label(&State->Interface, PushStringF(State->Interface.PerFrameMemory, 256, "Last Active - %lld",
|
||||
State->Interface.LastActiveWidget.Id));
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
}
|
||||
ui_PopLayout(&State->Interface);
|
||||
}
|
||||
|
||||
|
||||
#define INTERFACE_TEST_CPP
|
||||
#endif // INTERFACE_TEST_CPP
|
|
@ -276,6 +276,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
|
|||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
#if 0
|
||||
int VirtualKey = (int)Message.wParam;
|
||||
key_code Key = Win32GetKeyCode(VirtualKey, true, false);
|
||||
s32 KeyIndex = (int)Key;
|
||||
|
@ -287,6 +288,27 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
|
|||
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
||||
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
||||
|
||||
// New Input Queue
|
||||
AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown,
|
||||
ShiftDown, AltDown, CtrlDown, false);
|
||||
#endif
|
||||
TranslateMessage(&Message);
|
||||
DispatchMessage(&Message);
|
||||
}break;
|
||||
|
||||
case WM_CHAR:
|
||||
{
|
||||
char VirtualKey = (char)Message.wParam;
|
||||
key_code Key = CharToKeyCode(VirtualKey);
|
||||
s32 KeyIndex = (int)Key;
|
||||
|
||||
b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0;
|
||||
b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0;
|
||||
|
||||
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
||||
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
||||
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
||||
|
||||
// New Input Queue
|
||||
AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown,
|
||||
ShiftDown, AltDown, CtrlDown, false);
|
||||
|
@ -370,6 +392,7 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_
|
|||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
u32 BuffersSent = 0;
|
||||
u32 DataSizeSent = 0;
|
||||
|
||||
for (addressed_data_buffer* BufferAt = OutputData.Root;
|
||||
BufferAt != 0;
|
||||
|
@ -397,6 +420,7 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_
|
|||
if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
|
||||
{
|
||||
BuffersSent += 1;
|
||||
DataSizeSent += BufferAt->Data.Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,9 +435,9 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_
|
|||
}
|
||||
|
||||
gs_string OutputStr = AllocatorAllocString(Context.Allocator, 256);
|
||||
PrintF(&OutputStr, "Buffers Sent: %d\n", BuffersSent);
|
||||
PrintF(&OutputStr, "Buffers Sent: %d | Size Sent: %d\n", BuffersSent, DataSizeSent);
|
||||
NullTerminate(&OutputStr);
|
||||
//OutputDebugStringA(OutputStr.Str);
|
||||
OutputDebugStringA(OutputStr.Str);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
|
|
@ -407,5 +407,253 @@ GetMouseButtonStateAdvanced (b32 ButtonState)
|
|||
return Result;
|
||||
}
|
||||
|
||||
internal char
|
||||
KeyCodeToChar(key_code Code)
|
||||
{
|
||||
char Result = 0;
|
||||
|
||||
switch (Code)
|
||||
{
|
||||
case KeyCode_Space: { Result = ' '; } break;
|
||||
case KeyCode_Tab: { Result = '\t'; } break;
|
||||
case KeyCode_Enter: { Result = '\n'; } break;
|
||||
case KeyCode_Backspace: { Result = '\b'; } break;
|
||||
|
||||
case KeyCode_a: { Result = 'a'; } break;
|
||||
case KeyCode_b: { Result = 'b'; } break;
|
||||
case KeyCode_c: { Result = 'c'; } break;
|
||||
case KeyCode_d: { Result = 'd'; } break;
|
||||
case KeyCode_e: { Result = 'e'; } break;
|
||||
case KeyCode_f: { Result = 'f'; } break;
|
||||
case KeyCode_g: { Result = 'g'; } break;
|
||||
case KeyCode_h: { Result = 'h'; } break;
|
||||
case KeyCode_i: { Result = 'i'; } break;
|
||||
case KeyCode_j: { Result = 'j'; } break;
|
||||
case KeyCode_k: { Result = 'k'; } break;
|
||||
case KeyCode_l: { Result = 'l'; } break;
|
||||
case KeyCode_m: { Result = 'm'; } break;
|
||||
case KeyCode_n: { Result = 'n'; } break;
|
||||
case KeyCode_o: { Result = 'o'; } break;
|
||||
case KeyCode_p: { Result = 'p'; } break;
|
||||
case KeyCode_q: { Result = 'q'; } break;
|
||||
case KeyCode_r: { Result = 'r'; } break;
|
||||
case KeyCode_s: { Result = 's'; } break;
|
||||
case KeyCode_t: { Result = 't'; } break;
|
||||
case KeyCode_u: { Result = 'u'; } break;
|
||||
case KeyCode_v: { Result = 'v'; } break;
|
||||
case KeyCode_w: { Result = 'w'; } break;
|
||||
case KeyCode_x: { Result = 'x'; } break;
|
||||
case KeyCode_y: { Result = 'y'; } break;
|
||||
case KeyCode_z: { Result = 'z'; } break;
|
||||
case KeyCode_A: { Result = 'A'; } break;
|
||||
case KeyCode_B: { Result = 'B'; } break;
|
||||
case KeyCode_C: { Result = 'C'; } break;
|
||||
case KeyCode_D: { Result = 'D'; } break;
|
||||
case KeyCode_E: { Result = 'E'; } break;
|
||||
case KeyCode_F: { Result = 'F'; } break;
|
||||
case KeyCode_G: { Result = 'G'; } break;
|
||||
case KeyCode_H: { Result = 'H'; } break;
|
||||
case KeyCode_I: { Result = 'I'; } break;
|
||||
case KeyCode_J: { Result = 'J'; } break;
|
||||
case KeyCode_K: { Result = 'K'; } break;
|
||||
case KeyCode_L: { Result = 'L'; } break;
|
||||
case KeyCode_M: { Result = 'M'; } break;
|
||||
case KeyCode_N: { Result = 'N'; } break;
|
||||
case KeyCode_O: { Result = 'O'; } break;
|
||||
case KeyCode_P: { Result = 'P'; } break;
|
||||
case KeyCode_Q: { Result = 'Q'; } break;
|
||||
case KeyCode_R: { Result = 'R'; } break;
|
||||
case KeyCode_S: { Result = 'S'; } break;
|
||||
case KeyCode_T: { Result = 'T'; } break;
|
||||
case KeyCode_U: { Result = 'U'; } break;
|
||||
case KeyCode_V: { Result = 'V'; } break;
|
||||
case KeyCode_W: { Result = 'W'; } break;
|
||||
case KeyCode_X: { Result = 'X'; } break;
|
||||
case KeyCode_Y: { Result = 'Y'; } break;
|
||||
case KeyCode_Z: { Result = 'Z'; } break;
|
||||
|
||||
case KeyCode_Num0:
|
||||
case KeyCode_0: { Result = '0'; } break;
|
||||
case KeyCode_Num1:
|
||||
case KeyCode_1: { Result = '1'; } break;
|
||||
case KeyCode_Num2:
|
||||
case KeyCode_2: { Result = '2'; } break;
|
||||
case KeyCode_Num3:
|
||||
case KeyCode_3: { Result = '3'; } break;
|
||||
case KeyCode_Num4:
|
||||
case KeyCode_4: { Result = '4'; } break;
|
||||
case KeyCode_Num5:
|
||||
case KeyCode_5: { Result = '5'; } break;
|
||||
case KeyCode_Num6:
|
||||
case KeyCode_6: { Result = '6'; } break;
|
||||
case KeyCode_Num7:
|
||||
case KeyCode_7: { Result = '7'; } break;
|
||||
case KeyCode_Num8:
|
||||
case KeyCode_8: { Result = '8'; } break;
|
||||
case KeyCode_Num9:
|
||||
case KeyCode_9: { Result = '9'; } break;
|
||||
|
||||
case KeyCode_Bang: { Result = '!'; } break;
|
||||
case KeyCode_At: { Result = '@'; } break;
|
||||
case KeyCode_Pound: { Result = '#'; } break;
|
||||
case KeyCode_Dollar: { Result = '$'; } break;
|
||||
case KeyCode_Percent: { Result = '%'; } break;
|
||||
case KeyCode_Carrot: { Result = '^'; } break;
|
||||
case KeyCode_Ampersand: { Result = '&'; } break;
|
||||
case KeyCode_Star: { Result = '*'; } break;
|
||||
case KeyCode_LeftParen: { Result = '('; } break;
|
||||
case KeyCode_RightParen: { Result = ')'; } break;
|
||||
case KeyCode_Minus: { Result = '-'; } break;
|
||||
case KeyCode_Plus: { Result = '+'; } break;
|
||||
case KeyCode_Equals: { Result = '='; } break;
|
||||
case KeyCode_Underscore: { Result = '_'; } break;
|
||||
case KeyCode_LeftBrace: { Result = '{'; } break;
|
||||
case KeyCode_RightBrace: { Result = '}'; } break;
|
||||
case KeyCode_LeftBracket: { Result = '['; } break;
|
||||
case KeyCode_RightBracket: { Result = ']'; } break;
|
||||
case KeyCode_Colon: { Result = ':'; } break;
|
||||
case KeyCode_SemiColon: { Result = ';'; } break;
|
||||
case KeyCode_SingleQuote: { Result = '\''; } break;
|
||||
case KeyCode_DoubleQuote: { Result = '"'; } break;
|
||||
case KeyCode_ForwardSlash: { Result = '/'; } break;
|
||||
case KeyCode_Backslash: { Result = '\\'; } break;
|
||||
case KeyCode_Pipe: { Result = '|'; } break;
|
||||
case KeyCode_Comma: { Result = ','; } break;
|
||||
case KeyCode_Period: { Result = '.'; } break;
|
||||
case KeyCode_QuestionMark: { Result = '?'; } break;
|
||||
case KeyCode_LessThan: { Result = '<'; } break;
|
||||
case KeyCode_GreaterThan: { Result = '>'; } break;
|
||||
case KeyCode_Tilde: { Result = '~'; } break;
|
||||
case KeyCode_BackQuote: { Result = '`'; } break;
|
||||
|
||||
default: { Result = 0; } break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
KeyCodeHasChar(key_code Code)
|
||||
{
|
||||
bool Result = KeyCodeToChar(Code) != 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
internal key_code
|
||||
CharToKeyCode(char C)
|
||||
{
|
||||
key_code Result = KeyCode_Invalid;
|
||||
|
||||
switch (C)
|
||||
{
|
||||
case ' ': { Result = KeyCode_Space; } break;
|
||||
case '\t': { Result = KeyCode_Tab; } break;
|
||||
case '\n': { Result = KeyCode_Enter; } break;
|
||||
case '\b': { Result = KeyCode_Backspace; } break;
|
||||
|
||||
case 'a': { Result = KeyCode_a; } break;
|
||||
case 'b': { Result = KeyCode_b; } break;
|
||||
case 'c': { Result = KeyCode_c; } break;
|
||||
case 'd': { Result = KeyCode_d; } break;
|
||||
case 'e': { Result = KeyCode_e; } break;
|
||||
case 'f': { Result = KeyCode_f; } break;
|
||||
case 'g': { Result = KeyCode_g; } break;
|
||||
case 'h': { Result = KeyCode_h; } break;
|
||||
case 'i': { Result = KeyCode_i; } break;
|
||||
case 'j': { Result = KeyCode_j; } break;
|
||||
case 'k': { Result = KeyCode_k; } break;
|
||||
case 'l': { Result = KeyCode_l; } break;
|
||||
case 'm': { Result = KeyCode_m; } break;
|
||||
case 'n': { Result = KeyCode_n; } break;
|
||||
case 'o': { Result = KeyCode_o; } break;
|
||||
case 'p': { Result = KeyCode_p; } break;
|
||||
case 'q': { Result = KeyCode_q; } break;
|
||||
case 'r': { Result = KeyCode_r; } break;
|
||||
case 's': { Result = KeyCode_s; } break;
|
||||
case 't': { Result = KeyCode_t; } break;
|
||||
case 'u': { Result = KeyCode_u; } break;
|
||||
case 'v': { Result = KeyCode_v; } break;
|
||||
case 'w': { Result = KeyCode_w; } break;
|
||||
case 'x': { Result = KeyCode_x; } break;
|
||||
case 'y': { Result = KeyCode_y; } break;
|
||||
case 'z': { Result = KeyCode_z; } break;
|
||||
case 'A': { Result = KeyCode_A; } break;
|
||||
case 'B': { Result = KeyCode_B; } break;
|
||||
case 'C': { Result = KeyCode_C; } break;
|
||||
case 'D': { Result = KeyCode_D; } break;
|
||||
case 'E': { Result = KeyCode_E; } break;
|
||||
case 'F': { Result = KeyCode_F; } break;
|
||||
case 'G': { Result = KeyCode_G; } break;
|
||||
case 'H': { Result = KeyCode_H; } break;
|
||||
case 'I': { Result = KeyCode_I; } break;
|
||||
case 'J': { Result = KeyCode_J; } break;
|
||||
case 'K': { Result = KeyCode_K; } break;
|
||||
case 'L': { Result = KeyCode_L; } break;
|
||||
case 'M': { Result = KeyCode_M; } break;
|
||||
case 'N': { Result = KeyCode_N; } break;
|
||||
case 'O': { Result = KeyCode_O; } break;
|
||||
case 'P': { Result = KeyCode_P; } break;
|
||||
case 'Q': { Result = KeyCode_Q; } break;
|
||||
case 'R': { Result = KeyCode_R; } break;
|
||||
case 'S': { Result = KeyCode_S; } break;
|
||||
case 'T': { Result = KeyCode_T; } break;
|
||||
case 'U': { Result = KeyCode_U; } break;
|
||||
case 'V': { Result = KeyCode_V; } break;
|
||||
case 'W': { Result = KeyCode_W; } break;
|
||||
case 'X': { Result = KeyCode_X; } break;
|
||||
case 'Y': { Result = KeyCode_Y; } break;
|
||||
case 'Z': { Result = KeyCode_Z; } break;
|
||||
|
||||
case '0': { Result = KeyCode_0; } break;
|
||||
case '1': { Result = KeyCode_1; } break;
|
||||
case '2': { Result = KeyCode_2; } break;
|
||||
case '3': { Result = KeyCode_3; } break;
|
||||
case '4': { Result = KeyCode_4; } break;
|
||||
case '5': { Result = KeyCode_5; } break;
|
||||
case '6': { Result = KeyCode_6; } break;
|
||||
case '7': { Result = KeyCode_7; } break;
|
||||
case '8': { Result = KeyCode_8; } break;
|
||||
case '9': { Result = KeyCode_9; } break;
|
||||
|
||||
case '!': { Result = KeyCode_Bang; } break;
|
||||
case '@': { Result = KeyCode_At; } break;
|
||||
case '#': { Result = KeyCode_Pound; } break;
|
||||
case '$': { Result = KeyCode_Dollar; } break;
|
||||
case '%': { Result = KeyCode_Percent; } break;
|
||||
case '^': { Result = KeyCode_Carrot; } break;
|
||||
case '&': { Result = KeyCode_Ampersand; } break;
|
||||
case '*': { Result = KeyCode_Star; } break;
|
||||
case '(': { Result = KeyCode_LeftParen; } break;
|
||||
case ')': { Result = KeyCode_RightParen; } break;
|
||||
case '-': { Result = KeyCode_Minus; } break;
|
||||
case '+': { Result = KeyCode_Plus; } break;
|
||||
case '=': { Result = KeyCode_Equals; } break;
|
||||
case '_': { Result = KeyCode_Underscore; } break;
|
||||
case '{': { Result = KeyCode_LeftBrace; } break;
|
||||
case '}': { Result = KeyCode_RightBrace; } break;
|
||||
case '[': { Result = KeyCode_LeftBracket; } break;
|
||||
case ']': { Result = KeyCode_RightBracket; } break;
|
||||
case ':': { Result = KeyCode_Colon; } break;
|
||||
case ';': { Result = KeyCode_SemiColon; } break;
|
||||
case '\'': { Result = KeyCode_SingleQuote; } break;
|
||||
case '"': { Result = KeyCode_DoubleQuote; } break;
|
||||
case '/': { Result = KeyCode_ForwardSlash; } break;
|
||||
case '\\': { Result = KeyCode_Backslash; } break;
|
||||
case '|': { Result = KeyCode_Pipe; } break;
|
||||
case ',': { Result = KeyCode_Comma; } break;
|
||||
case '.': { Result = KeyCode_Period; } break;
|
||||
case '?': { Result = KeyCode_QuestionMark; } break;
|
||||
case '<': { Result = KeyCode_LessThan; } break;
|
||||
case '>': { Result = KeyCode_GreaterThan; } break;
|
||||
case '~': { Result = KeyCode_Tilde; } break;
|
||||
case '`': { Result = KeyCode_BackQuote; } break;
|
||||
|
||||
default: { Result = KeyCode_Invalid; } break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define GS_INPUT_H
|
||||
#endif // GS_INPUT_H
|
|
@ -1592,6 +1592,21 @@ FindLastFromSet(gs_const_string String, char* SetArray)
|
|||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
StringContains(gs_const_string Str, char C)
|
||||
{
|
||||
bool Result = false;
|
||||
for (u32 i = 0; i < Str.Length; i++)
|
||||
{
|
||||
if (Str.Str[i] == C)
|
||||
{
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
StringsEqualUpToLength(gs_const_string A, gs_const_string B, u64 Length)
|
||||
{
|
||||
|
@ -1695,30 +1710,66 @@ CharToUInt(char C, u64 Base)
|
|||
return CharToUInt(C, GetCharSetForBase(Base));
|
||||
}
|
||||
|
||||
internal u64
|
||||
ParseUInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0)
|
||||
struct parse_uint_result
|
||||
{
|
||||
u64 Result = 0;
|
||||
b8 Success;
|
||||
u64 Value;
|
||||
u32 ParsedLength;
|
||||
};
|
||||
|
||||
internal parse_uint_result
|
||||
ValidateAndParseUInt(gs_const_string String, u64 Base = 10)
|
||||
{
|
||||
parse_uint_result Result = {0};
|
||||
|
||||
gs_const_string CharSet = GetCharSetForBase(Base);
|
||||
u64 i = 0;
|
||||
for (; i < String.Length; i++)
|
||||
|
||||
bool StringIsValid = true;
|
||||
for (u32 i = 0; i < String.Length; i++)
|
||||
{
|
||||
u64 CharIndex = FindFirst(CharSet, String.Str[i]);
|
||||
if (CharIndex < CharSet.Length)
|
||||
{
|
||||
Result = CharToUInt(String.Str[i], CharSet) + (Result * Base);
|
||||
}
|
||||
else
|
||||
if (!StringContains(CharSet, String.Str[i]))
|
||||
{
|
||||
StringIsValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ParsedLength != 0)
|
||||
|
||||
if (StringIsValid)
|
||||
{
|
||||
*ParsedLength = i;
|
||||
u64 Acc = 0;
|
||||
u64 i = 0;
|
||||
for (; i < String.Length; i++)
|
||||
{
|
||||
u64 CharIndex = FindFirst(CharSet, String.Str[i]);
|
||||
if (CharIndex < CharSet.Length)
|
||||
{
|
||||
Acc = CharToUInt(String.Str[i], CharSet) + (Acc * Base);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Result.Success = true;
|
||||
Result.Value = Acc;
|
||||
Result.ParsedLength = i;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u64
|
||||
ParseUInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0)
|
||||
{
|
||||
parse_uint_result ParseResult = ValidateAndParseUInt(String, Base);
|
||||
Assert(ParseResult.Success);
|
||||
if (ParsedLength)
|
||||
{
|
||||
*ParsedLength = ParseResult.ParsedLength;
|
||||
}
|
||||
return ParseResult.Value;
|
||||
}
|
||||
internal u64
|
||||
ParseUInt(u64 Length, char* String, u64 Base = 10, u64* ParsedLength = 0)
|
||||
{
|
||||
|
@ -1756,39 +1807,75 @@ ParseInt(char* String, u64 Base = 10, u64* ParsedLength = 0)
|
|||
return ParseInt(LitString(String), Base, ParsedLength);
|
||||
}
|
||||
|
||||
struct parse_float_result
|
||||
{
|
||||
b8 Success;
|
||||
r64 Value;
|
||||
u64 ParsedLength;
|
||||
};
|
||||
|
||||
internal parse_float_result
|
||||
ValidateAndParseFloat(gs_const_string String)
|
||||
{
|
||||
parse_float_result Result = {0};
|
||||
Result.Success = false;
|
||||
|
||||
// Validate
|
||||
bool StringIsValid = true;
|
||||
for (u64 i = 0; i < String.Length; i++)
|
||||
{
|
||||
if (!IsNumericDecimal(String.Str[i]) && String.Str[i] != '-')
|
||||
{
|
||||
StringIsValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (StringIsValid)
|
||||
{
|
||||
u64 DecimalIndex = FindFirst(String, '.');
|
||||
u64 TempParsedLength = 0;
|
||||
u64 PlacesAfterPoint = 0;
|
||||
|
||||
gs_const_string IntegerString = GetStringBefore(String, DecimalIndex);
|
||||
gs_const_string DecimalString = GetStringAfter(String, DecimalIndex + 1);
|
||||
|
||||
r32 Polarity = 1;
|
||||
if (IntegerString.Str[0] == '-')
|
||||
{
|
||||
IntegerString = GetStringAfter(IntegerString, 1);
|
||||
Polarity = -1;
|
||||
}
|
||||
|
||||
Result.Value = (r64)ParseInt(IntegerString, 10, &TempParsedLength);
|
||||
|
||||
if (TempParsedLength == IntegerString.Length)
|
||||
{
|
||||
r64 AfterPoint = (r64)ParseUInt(DecimalString, 10, &PlacesAfterPoint);
|
||||
r64 Decimal = (AfterPoint / PowR64(10, PlacesAfterPoint));
|
||||
Result.Value = Result.Value + Decimal;
|
||||
Result.Value *= Polarity;
|
||||
}
|
||||
|
||||
Result.ParsedLength = TempParsedLength + PlacesAfterPoint;
|
||||
if (DecimalIndex < String.Length) { Result.ParsedLength += 1; }
|
||||
|
||||
Result.Success = true;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal r64
|
||||
ParseFloat(gs_const_string String, u64* ParsedLength = 0)
|
||||
{
|
||||
|
||||
u64 DecimalIndex = FindFirst(String, '.');
|
||||
u64 TempParsedLength = 0;
|
||||
u64 PlacesAfterPoint = 0;
|
||||
|
||||
gs_const_string IntegerString = GetStringBefore(String, DecimalIndex);
|
||||
gs_const_string DecimalString = GetStringAfter(String, DecimalIndex + 1);
|
||||
|
||||
r32 Polarity = 1;
|
||||
if (IntegerString.Str[0] == '-')
|
||||
{
|
||||
IntegerString = GetStringAfter(IntegerString, 1);
|
||||
Polarity = -1;
|
||||
}
|
||||
r64 Result = (r64)ParseInt(IntegerString, 10, &TempParsedLength);
|
||||
|
||||
if (TempParsedLength == IntegerString.Length)
|
||||
{
|
||||
r64 AfterPoint = (r64)ParseUInt(DecimalString, 10, &PlacesAfterPoint);
|
||||
r64 Decimal = (AfterPoint / PowR64(10, PlacesAfterPoint));
|
||||
Result = Result + Decimal;
|
||||
Result *= Polarity;
|
||||
}
|
||||
|
||||
parse_float_result Result = ValidateAndParseFloat(String);
|
||||
Assert(Result.Success);
|
||||
if (ParsedLength != 0)
|
||||
{
|
||||
*ParsedLength = TempParsedLength + PlacesAfterPoint;
|
||||
if (DecimalIndex < String.Length) { *ParsedLength += 1; }
|
||||
*ParsedLength = Result.ParsedLength;
|
||||
}
|
||||
return Result;
|
||||
return Result.Value;
|
||||
}
|
||||
internal r64
|
||||
ParseFloat(char* String, u64* ParsedLength = 0)
|
||||
|
@ -2010,11 +2097,16 @@ PrintFArgsList (gs_string* String, char* Format, va_list Args)
|
|||
FormatAt++;
|
||||
if (IsBase10(FormatAt[0]))
|
||||
{
|
||||
|
||||
PrecisionSpecified = true;
|
||||
|
||||
gs_const_string PrecisionStr = {};
|
||||
PrecisionStr.Str = FormatAt;
|
||||
for (char* C = FormatAt; *FormatAt && IsBase10(*C); C++)
|
||||
{
|
||||
PrecisionStr.Length++;
|
||||
}
|
||||
u64 Parsed = 0;
|
||||
AssertMessage("ParseInt assumes whole string is an integer");
|
||||
Precision = (s32)ParseInt(FormatAt, 10, &Parsed);
|
||||
Precision = (s32)ParseInt(PrecisionStr, 10, &Parsed);
|
||||
FormatAt += Parsed;
|
||||
}
|
||||
else if (FormatAt[0] == '*')
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
//
|
||||
// File: gen_blumen_lumen.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2021-01-06
|
||||
//
|
||||
#ifndef GEN_BLUMEN_LUMEN_CPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "../gs_libs/gs_types.h"
|
||||
#include "../gs_libs/gs_types.cpp"
|
||||
#include "../app/platform_win32/win32_foldhaus_utils.h"
|
||||
#include "../app/platform_win32/win32_foldhaus_memory.h"
|
||||
#include "../app/platform_win32/win32_foldhaus_fileio.h"
|
||||
#include "../app/platform_win32/win32_foldhaus_work_queue.h"
|
||||
|
||||
#include "sculpture_gen.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
v3 CenterStart;
|
||||
v3 CenterEnd;
|
||||
r32 Radius;
|
||||
u32 SegmentsCount;
|
||||
u32 SubsegmentsCount;
|
||||
u32 SubsegmentLeds;
|
||||
|
||||
// Only one of these two values is needed.
|
||||
// If ChannelsArray != 0, then it will be used, and assumed to
|
||||
// have SegmentsCount values
|
||||
// Otherwise, each segment will increment from ChannelStart
|
||||
u32 ChannelStart;
|
||||
u32* ChannelsArray;
|
||||
|
||||
char* ComPort;
|
||||
char* SectionTagValue;
|
||||
char* FlowerTagValue;
|
||||
} loop_desc;
|
||||
|
||||
internal void
|
||||
BuildLoop(gs_string* OutputBuffer, loop_desc Desc)
|
||||
{
|
||||
r32 SegmentsArc = TauR32 / Desc.SegmentsCount;
|
||||
r32 SubsegmentsArc = SegmentsArc / Desc.SubsegmentsCount;
|
||||
|
||||
for (u32 i = 0; i < Desc.SegmentsCount; i++)
|
||||
{
|
||||
r32 ArcBase = SegmentsArc * i;
|
||||
|
||||
u32 Channel = 0;
|
||||
if (Desc.ChannelsArray != 0)
|
||||
{
|
||||
Channel = Desc.ChannelsArray[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
Channel = Desc.ChannelStart + i;
|
||||
}
|
||||
|
||||
WriteLedStripOpen(OutputBuffer, Channel, Desc.ComPort);
|
||||
WriteSegmentSequenceOpen(OutputBuffer, Desc.SubsegmentsCount);
|
||||
|
||||
for (u32 j = 0; j < Desc.SubsegmentsCount; j++)
|
||||
{
|
||||
r32 Arc = ArcBase + (SubsegmentsArc * j);
|
||||
v3 Offset = v3{ SinR32(Arc), 0, CosR32(Arc) } * Desc.Radius;
|
||||
v3 P0 = Desc.CenterStart + Offset;
|
||||
v3 P1 = Desc.CenterEnd + Offset;
|
||||
|
||||
// Swap directions on the middle strip
|
||||
if (j%2 != 0)
|
||||
{
|
||||
v3 Temp = P0;
|
||||
P0 = P1;
|
||||
P1 = Temp;
|
||||
}
|
||||
|
||||
WriteSegmentSequenceSegment(OutputBuffer, P0, P1, Desc.SubsegmentLeds);
|
||||
}
|
||||
|
||||
WriteSegmentSequenceClose(OutputBuffer);
|
||||
WriteSegmentTagsOpen(OutputBuffer, 2);
|
||||
WriteSegmentTag(OutputBuffer, "section", Desc.SectionTagValue);
|
||||
WriteSegmentTag(OutputBuffer, "flower", Desc.FlowerTagValue);
|
||||
WriteSegmentTagsClose(OutputBuffer);
|
||||
WriteLedStripClose(OutputBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
v3 Pos;
|
||||
char* ComPort;
|
||||
char* FlowerTagValue;
|
||||
u32* StemChannels;
|
||||
u32* BloomOuterChannels;
|
||||
u32* BloomInnerChannels;
|
||||
} flower_desc;
|
||||
|
||||
internal void
|
||||
BuildFlower(gs_string* OutputBuffer, flower_desc Desc)
|
||||
{
|
||||
// the flower stem
|
||||
loop_desc FlowerStem = {};
|
||||
FlowerStem.CenterStart = v3{0, -1.5f, 0} + Desc.Pos;
|
||||
FlowerStem.CenterEnd = v3{0, .5f, 0} + Desc.Pos;
|
||||
FlowerStem.Radius = .05f;
|
||||
FlowerStem.SegmentsCount = 6;
|
||||
FlowerStem.SubsegmentsCount = 1;
|
||||
FlowerStem.SubsegmentLeds = 300;
|
||||
//FlowerStem.ChannelStart = 0;
|
||||
FlowerStem.ChannelsArray = Desc.StemChannels;
|
||||
FlowerStem.ComPort = Desc.ComPort;
|
||||
FlowerStem.SectionTagValue = "stem";
|
||||
FlowerStem.FlowerTagValue = Desc.FlowerTagValue;
|
||||
BuildLoop(OutputBuffer, FlowerStem);
|
||||
|
||||
// the bloom stem outer
|
||||
loop_desc BloomStemOuter = {};
|
||||
BloomStemOuter.CenterStart = v3{0, .5f, 0} + Desc.Pos;
|
||||
BloomStemOuter.CenterEnd = v3{0, .9f, 0} + Desc.Pos;
|
||||
BloomStemOuter.Radius = .07f;
|
||||
BloomStemOuter.SegmentsCount = 9;
|
||||
BloomStemOuter.SubsegmentsCount = 3;
|
||||
BloomStemOuter.SubsegmentLeds = 41;
|
||||
//BloomStemOuter.ChannelStart = 7;
|
||||
BloomStemOuter.ChannelsArray = Desc.BloomOuterChannels;
|
||||
BloomStemOuter.ComPort = Desc.ComPort;
|
||||
BloomStemOuter.SectionTagValue = "outer_bloom";
|
||||
BloomStemOuter.FlowerTagValue = Desc.FlowerTagValue;
|
||||
BuildLoop(OutputBuffer, BloomStemOuter);
|
||||
|
||||
// the bloom stem inner
|
||||
loop_desc BloomStemInner = {};
|
||||
BloomStemInner.CenterStart = v3{0, 1.4f, 0} + Desc.Pos;
|
||||
BloomStemInner.CenterEnd = v3{0, .9f, 0} + Desc.Pos;
|
||||
BloomStemInner.Radius = .05f;
|
||||
BloomStemInner.SegmentsCount = 6;
|
||||
BloomStemInner.SubsegmentsCount = 3;
|
||||
BloomStemInner.SubsegmentLeds = 35;
|
||||
//BloomStemInner.ChannelStart = 17;
|
||||
BloomStemInner.ChannelsArray = Desc.BloomInnerChannels;
|
||||
BloomStemInner.ComPort = Desc.ComPort;
|
||||
BloomStemInner.SectionTagValue = "inner_bloom";
|
||||
BloomStemInner.FlowerTagValue = Desc.FlowerTagValue;
|
||||
BuildLoop(OutputBuffer, BloomStemInner);
|
||||
}
|
||||
|
||||
// Just for brevity, no real function provided
|
||||
#define FSC(f,c) FlowerStripToChannel((f), (c))
|
||||
internal u8
|
||||
FlowerStripToChannel(u8 Flower, u8 Channel)
|
||||
{
|
||||
Assert(Flower < 3);
|
||||
Assert(Channel < 8);
|
||||
|
||||
u8 Result = 0;
|
||||
Result |= (Flower & 0x03) << 3;
|
||||
Result |= (Channel & 0x07);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
int main(int ArgCount, char** Args)
|
||||
{
|
||||
gs_thread_context Ctx = Win32CreateThreadContext();
|
||||
|
||||
gs_string OutputBuffer = PushString(Ctx.Transient, MB(4));
|
||||
|
||||
char* ComPort = "\\\\.\\COM8";
|
||||
WriteAssemblyUARTOpen(&OutputBuffer,
|
||||
"Blumen Lumen - Silver Spring",
|
||||
100,
|
||||
v3{0, 0, 0},
|
||||
69,
|
||||
ComPort);
|
||||
|
||||
u32 StemChannels[] = { FSC(2, 1), FSC(2, 2), FSC(2, 3), FSC(2, 4), FSC(2, 5), FSC(2, 6) };
|
||||
u32 BloomOuterChannels[] = { FSC(1, 0), FSC(1, 1), FSC(1, 2), FSC(1, 3), FSC(1, 4), FSC(1, 5), FSC(1, 6), FSC(1, 7), FSC(2, 0) };
|
||||
u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) };
|
||||
flower_desc F0 = {};
|
||||
F0.Pos = v3{-1, 0, 0};
|
||||
F0.ComPort = ComPort;
|
||||
F0.FlowerTagValue = "left";
|
||||
F0.StemChannels = StemChannels;
|
||||
F0.BloomOuterChannels = BloomOuterChannels;
|
||||
F0.BloomInnerChannels = BloomInnerChannels;
|
||||
BuildFlower(&OutputBuffer, F0);
|
||||
|
||||
/*
|
||||
flower_desc F1 = {};
|
||||
F1.Pos = v3{0, 0, 0};
|
||||
F1.FlowerTagValue = "center";
|
||||
F1.StemChannels = StemChannels;
|
||||
F1.BloomInnerChannels = BloomInnerChannels;
|
||||
F1.BloomOuterChannels = BloomOuterChannels;
|
||||
BuildFlower(&OutputBuffer, F1);
|
||||
|
||||
flower_desc F2 = {};
|
||||
F2.Pos = v3{1, 0, 0};
|
||||
F2.FlowerTagValue = "right";
|
||||
F2.StemChannels = StemChannels;
|
||||
F2.BloomInnerChannels = BloomInnerChannels;
|
||||
F2.BloomOuterChannels = BloomOuterChannels;
|
||||
BuildFlower(&OutputBuffer, F2);
|
||||
*/
|
||||
|
||||
printf("%.*s\n", (u32)OutputBuffer.Length, OutputBuffer.Str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define GEN_BLUMEN_LUMEN_CPP
|
||||
#endif // GEN_BLUMEN_LUMEN_CPP
|
|
@ -0,0 +1,102 @@
|
|||
//
|
||||
// File: sculpture_gen.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2021-01-06
|
||||
//
|
||||
#ifndef SCULPTURE_GEN_H
|
||||
|
||||
internal void
|
||||
WriteIndented(gs_string* Buffer, u32 Indent, char* Format, ...)
|
||||
{
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
|
||||
for (u32 i = 0; i < Indent; i++)
|
||||
{
|
||||
OutChar(Buffer, '\t');
|
||||
}
|
||||
|
||||
PrintFArgsList(Buffer, Format, Args);
|
||||
va_end(Args);
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteAssemblyUARTOpen(gs_string* Buffer, char* Name, u32 Scale, v3 Center, u32 StripCount, char* ComPort)
|
||||
{
|
||||
WriteIndented(Buffer, 0, "assembly_name: \"%s\";\n", Name);
|
||||
WriteIndented(Buffer, 0, "assembly_scale: %d;\n", Scale);
|
||||
WriteIndented(Buffer, 0, "assembly_center: (%f, %f, %f);\n", Center.x, Center.y, Center.z);
|
||||
WriteIndented(Buffer, 0, "led_strip_count: %d;\n", StripCount);
|
||||
WriteIndented(Buffer, 0, "output_mode: \"UART\";\n");
|
||||
WriteIndented(Buffer, 0, "com_port: \"%s\";\n", ComPort);
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteLedStripOpen(gs_string* Buffer, u32 Channel, char* ComPort)
|
||||
{
|
||||
WriteIndented(Buffer, 0, "led_strip:\n{\n");
|
||||
WriteIndented(Buffer, 1, "output_uart: {\n");
|
||||
WriteIndented(Buffer, 2, "channel: %d;\n", Channel);
|
||||
WriteIndented(Buffer, 2, "com_port: \"%s\";\n", ComPort);
|
||||
WriteIndented(Buffer, 1, "};\n\n");
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteSegmentSequenceOpen(gs_string* Buffer, u32 SegmentCount)
|
||||
{
|
||||
WriteIndented(Buffer, 1, "segment: {\n");
|
||||
WriteIndented(Buffer, 2, "point_placement_type: \"SegmentSequence\";\n");
|
||||
WriteIndented(Buffer, 2, "segment_sequence:\n");
|
||||
WriteIndented(Buffer, 2, "{\n");
|
||||
WriteIndented(Buffer, 3, "segment_count: %d;\n", SegmentCount);
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteSegmentSequenceSegment(gs_string* Buffer, v3 P0, v3 P1, u32 LedCount)
|
||||
{
|
||||
WriteIndented(Buffer, 3, "segment: {\n");
|
||||
WriteIndented(Buffer, 4, "point_placement_type: \"InterpolatePoints\";\n");
|
||||
WriteIndented(Buffer, 4, "interpolate_points: {\n");
|
||||
WriteIndented(Buffer, 5, "start: (%f, %f, %f);\n", P0.x, P0.y, P0.z);
|
||||
WriteIndented(Buffer, 5, "end: (%f, %f, %f);\n", P1.x, P1.y, P1.z);
|
||||
WriteIndented(Buffer, 5, "led_count: %d;\n", LedCount);
|
||||
WriteIndented(Buffer, 4, "};\n");
|
||||
WriteIndented(Buffer, 3, "};\n");
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteSegmentSequenceClose(gs_string* Buffer)
|
||||
{
|
||||
WriteIndented(Buffer, 2, "};\n");
|
||||
WriteIndented(Buffer, 1, "};\n");
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteSegmentTagsOpen(gs_string* Buffer, u32 TagCount)
|
||||
{
|
||||
WriteIndented(Buffer, 1, "tags_count: %d;\n", TagCount);
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteSegmentTag(gs_string* Buffer, char* TagName, char* TagValue)
|
||||
{
|
||||
WriteIndented(Buffer, 1, "tag: {\n");
|
||||
WriteIndented(Buffer, 2, "name: \"%s\";\n", TagName);
|
||||
WriteIndented(Buffer, 2, "value: \"%s\";\n", TagValue);
|
||||
WriteIndented(Buffer, 1, "};\n");
|
||||
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteSegmentTagsClose(gs_string* Buffer)
|
||||
{
|
||||
}
|
||||
|
||||
internal void
|
||||
WriteLedStripClose(gs_string* Buffer)
|
||||
{
|
||||
WriteIndented(Buffer, 0, "};\n");
|
||||
}
|
||||
|
||||
#define SCULPTURE_GEN_H
|
||||
#endif // SCULPTURE_GEN_H
|
Loading…
Reference in New Issue