Removed Patterns and Channels, rebuilt the file open dialog box, and began implementing a basic text entry system.
This commit is contained in:
parent
d67d041b21
commit
8040479379
|
@ -18,8 +18,7 @@ pushd build
|
|||
|
||||
del *.pdb > NUL 2> NUL
|
||||
|
||||
REM Compile and Run the Preprocessor
|
||||
REM cl %CommonCompilerFlags% ..\meta\foldhaus_meta.cpp /link %CommonLinkerFlags%
|
||||
REM Run the Preprocessor
|
||||
pushd ..\src\
|
||||
..\build\foldhaus_meta.exe C:\projects\foldhaus\src\
|
||||
popd
|
||||
|
@ -35,5 +34,5 @@ del lock.tmp
|
|||
cl %CommonCompilerFlags% ..\src\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib -incremental:no
|
||||
|
||||
C:\programs\ctime\ctime.exe -end C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm %LastError%
|
||||
C:\programs\ctime\ctime.exe -stats C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm
|
||||
REM C:\programs\ctime\ctime.exe -stats C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm
|
||||
popd
|
197
foldhaus_app.cpp
197
foldhaus_app.cpp
|
@ -336,57 +336,6 @@ UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
internal render_texture*
|
||||
PushTexture (app_state* State)
|
||||
{
|
||||
render_texture* Result = 0;
|
||||
|
||||
if (State->LoadedTexturesUsed < State->LoadedTexturesSize)
|
||||
{
|
||||
Result = State->LoadedTextures + State->LoadedTexturesUsed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): Be able to grow this array
|
||||
for (s32 i = 0; i < State->LoadedTexturesUsed; i++)
|
||||
{
|
||||
if (State->LoadedTextures[i].Handle == 0)
|
||||
{
|
||||
Result = State->LoadedTextures + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert(Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal render_texture*
|
||||
StoreTexture (app_state* State, u8* Memory, s32 Width, s32 Height, s32 BytesPerPixel, s32 Stride)
|
||||
{
|
||||
render_texture* Result = PushTexture(State);
|
||||
Result->Memory = Memory;
|
||||
Result->Handle = 0;
|
||||
Result->Width = Width;
|
||||
Result->Height = Height;
|
||||
Result->BytesPerPixel = BytesPerPixel;
|
||||
Result->Stride = Stride;
|
||||
}
|
||||
|
||||
internal void
|
||||
RemoveTexture (app_state* State, s32 Index)
|
||||
{
|
||||
State->LoadedTextures[Index].Handle = 0;
|
||||
// TODO(Peter): Free the memory it was using
|
||||
}
|
||||
|
||||
internal void
|
||||
RemoveTexture (app_state* State, render_texture* Texture)
|
||||
{
|
||||
Texture->Handle = 0;
|
||||
// TODO(Peter): Free the memory it was using
|
||||
}
|
||||
|
||||
RELOAD_STATIC_DATA(ReloadStaticData)
|
||||
{
|
||||
app_state* State = (app_state*)Context.MemoryBase;
|
||||
|
@ -395,13 +344,14 @@ RELOAD_STATIC_DATA(ReloadStaticData)
|
|||
|
||||
if (State->InputCommandRegistry.Size > 0)
|
||||
{
|
||||
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Delete, false, KeyCode_Invalid,
|
||||
DeleteSelectedChannelOrPattern);
|
||||
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_MouseLeftButton, true, KeyCode_Invalid,
|
||||
CameraMouseControl);
|
||||
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_U, false, KeyCode_Invalid, ToggleUniverseDebugView);
|
||||
RegisterMouseWheelCommand(&State->InputCommandRegistry, CameraMouseZoom);
|
||||
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, false, KeyCode_Invalid, AddNode);
|
||||
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Tab, false, KeyCode_Invalid, ToggleNodeDisplay);
|
||||
|
||||
InitializeTextInputCommands(&State->TextEntryCommandRegistry, State->Permanent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,11 +366,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
|
||||
InitMemoryArena(&State->SACNMemory, 0, 0, Context.PlatformAlloc);
|
||||
|
||||
State->LoadedTexturesSize = 8;
|
||||
State->LoadedTextures = PushArray(State->Permanent, render_texture, State->LoadedTexturesSize);
|
||||
State->LoadedTexturesUsed = 0;
|
||||
|
||||
InitializeInputCommandRegistry(&State->InputCommandRegistry, 32, State->Permanent);
|
||||
InitializeInputCommandRegistry(&State->TextEntryCommandRegistry, 32, State->Permanent);
|
||||
State->ActiveCommands = &State->InputCommandRegistry;
|
||||
|
||||
// TODO(Peter): put in InitializeInterface?
|
||||
r32 FontSize = 14;
|
||||
|
@ -498,11 +446,6 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->Camera.Position = v3{0, 0, -250};
|
||||
State->Camera.LookAt = v3{0, 0, 0};
|
||||
|
||||
InitLEDPatternSystem(&State->PatternSystem, State->Permanent,
|
||||
32, Megabytes(4));
|
||||
InitLEDChannelSystem(&State->ChannelSystem, State->Permanent,
|
||||
sizeof(led_channel) * 32);
|
||||
|
||||
#if 1
|
||||
char Path[] = "radialumia.fold";
|
||||
LoadAssembly(State, Context, Path);
|
||||
|
@ -533,6 +476,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
|
||||
State->OutputNode = PushOutputNodeOnList(State->NodeList, v2{500, 250}, State->Permanent);
|
||||
|
||||
State->GeneralPurposeSearch.Backbuffer = PushArray(State->Permanent, char, 256);
|
||||
InitializeEmptyString(&State->GeneralPurposeSearch.Buffer, State->GeneralPurposeSearch.Backbuffer, 256);
|
||||
|
||||
ReloadStaticData(Context, GlobalDebugServices);
|
||||
}
|
||||
|
||||
|
@ -546,14 +492,21 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
// incorrect to clear the arena, and then access the memory later.
|
||||
ClearArena(State->Transient);
|
||||
|
||||
ExecuteAllRegisteredCommands(&State->InputCommandRegistry, Input, State);
|
||||
if (State->ActiveCommands == &State->TextEntryCommandRegistry)
|
||||
{
|
||||
AppendInputToEntryString(State->ActiveTextEntry, Input.New->StringInput, Input.New->StringInputUsed);
|
||||
}
|
||||
ExecuteAllRegisteredCommands(State->ActiveCommands, Input, State);
|
||||
|
||||
UpdateOutputNodeCalculations(State->OutputNode, State->NodeList,
|
||||
State->Permanent, State->Transient,
|
||||
State->LEDBufferList->LEDs,
|
||||
State->LEDBufferList->Colors,
|
||||
State->LEDBufferList->Count,
|
||||
Context.DeltaTime);
|
||||
if (State->LEDBufferList)
|
||||
{
|
||||
UpdateOutputNodeCalculations(State->OutputNode, State->NodeList,
|
||||
State->Permanent, State->Transient,
|
||||
State->LEDBufferList->LEDs,
|
||||
State->LEDBufferList->Colors,
|
||||
State->LEDBufferList->Count,
|
||||
Context.DeltaTime);
|
||||
}
|
||||
|
||||
ClearTransientNodeColorBuffers(State->NodeList);
|
||||
|
||||
|
@ -691,7 +644,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
{
|
||||
DEBUG_TRACK_SCOPE(DrawUniverseOutputDisplay);
|
||||
|
||||
string TitleBarString = InitializeString(PushArray(State->Transient, char, 64), 64);
|
||||
string TitleBarString = InitializeEmptyString(PushArray(State->Transient, char, 64), 64);
|
||||
|
||||
v2 DisplayArea_Dimension = v2{600, 600};
|
||||
v2 DisplayContents_Offset = State->UniverseOutputDisplayOffset;
|
||||
|
@ -772,7 +725,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
if (LoadAssemblyBtn.Pressed)
|
||||
{
|
||||
char FilePath[256];
|
||||
b32 Success = Context.PlatformGetFilePath(FilePath, 256);
|
||||
b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0");
|
||||
if (Success)
|
||||
{
|
||||
LoadAssembly(State, Context, FilePath);
|
||||
|
@ -783,6 +736,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
///////////////////////////////////////
|
||||
// Figuring Out Nodes
|
||||
//////////////////////////////////////
|
||||
if (State->NodeRenderSettings.Display)
|
||||
{
|
||||
v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
|
||||
v2 LastFrameMousePos = v2{(r32)Input.Old->MouseX, (r32)Input.Old->MouseY};
|
||||
|
@ -817,33 +771,35 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
if (State->InterfaceShowNodeList)
|
||||
{
|
||||
v2 TopLeft = State->NodeListMenuPosition;
|
||||
v2 Dimension = v2{300, 30};
|
||||
|
||||
// Title Bar
|
||||
PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y},
|
||||
v4{.3f, .3f, .3f, 1.f});
|
||||
DrawString(RenderBuffer, MakeStringLiteral("Nodes List"), State->Font, 14,
|
||||
v2{TopLeft.x, TopLeft.y - 25}, WhiteV4);
|
||||
TopLeft.y -= 30;
|
||||
|
||||
for (s32 i = 0; i < NodeSpecificationsCount; i++)
|
||||
{
|
||||
node_specification Spec = NodeSpecifications[i];
|
||||
|
||||
button_result Button = EvaluateButton(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y},
|
||||
MakeStringLiteral(Spec.Name), State->Interface, Input);
|
||||
if (Button.Pressed)
|
||||
{
|
||||
PushNodeOnListFromSpecification(State->NodeList, Spec, MousePos, State->Permanent);
|
||||
}
|
||||
|
||||
TopLeft.y -= 30;
|
||||
}
|
||||
search_lister_result NodeListResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension,
|
||||
MakeStringLiteral("Nodes List"),
|
||||
NodeSpecificationsCount, (u8*)NodeSpecifications,
|
||||
State->GeneralPurposeSearchHotItem,
|
||||
NodeListerGetNodeName,
|
||||
&State->GeneralPurposeSearch.Buffer,
|
||||
State->GeneralPurposeSearch.CursorPosition,
|
||||
State->Font, State->Interface, Input);
|
||||
State->GeneralPurposeSearchHotItem = NodeListResult.HotItem;
|
||||
|
||||
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton) ||
|
||||
KeyTransitionedDown(Input, KeyCode_Esc))
|
||||
{
|
||||
State->InterfaceShowNodeList = false;
|
||||
DeactivateTextEntry(State);
|
||||
}
|
||||
|
||||
if (KeyTransitionedDown(Input, KeyCode_Enter))
|
||||
{
|
||||
State->InterfaceShowNodeList = false;
|
||||
if (NodeListResult.HotItem > 0)
|
||||
{
|
||||
PushNodeOnListFromSpecification(State->NodeList, NodeSpecifications[NodeListResult.HotItem],
|
||||
MousePos, State->NodeRenderSettings, State->Permanent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -859,65 +815,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
///////////////////////////////////////
|
||||
// Current Patterns Panel
|
||||
//////////////////////////////////////
|
||||
|
||||
r32 LeftPanelRightEdge = DrawLeftHandInterface(State, Input, Context.WindowHeight - TopBarHeight, RenderBuffer);
|
||||
|
||||
if (State->InterfaceState.ChannelSelected >= 0)
|
||||
{
|
||||
led_channel* ActiveChannel = GetChannelByIndex(State->InterfaceState.ChannelSelected,
|
||||
State->ChannelSystem);
|
||||
|
||||
button_result OperationButtonState = EvaluateButton(
|
||||
RenderBuffer,
|
||||
v2{Context.WindowWidth - 150, 500},
|
||||
v2{Context.WindowWidth - 50, 550},
|
||||
MakeStringLiteral(PatternSelectorOperationsText[ActiveChannel->BlendMode]),
|
||||
State->Interface,
|
||||
Input);
|
||||
|
||||
if (OperationButtonState.Pressed)
|
||||
{
|
||||
State->InterfaceState.ChooseOperationPanelOpen = !State->InterfaceState.ChooseOperationPanelOpen;
|
||||
}
|
||||
|
||||
if (State->InterfaceState.ChooseOperationPanelOpen)
|
||||
{
|
||||
s32 StringLength = 128;
|
||||
s32 OperationsStart = PatternSelectorCombine_Invalid + 1;
|
||||
s32 OperationsOnePastLast = PatternSelectorCombine_Count;
|
||||
s32 OperationsCount = (OperationsOnePastLast - OperationsStart);
|
||||
string* OperationChoices = PushArray(State->Transient, string, OperationsCount);
|
||||
|
||||
for (s32 Choice = OperationsStart;
|
||||
Choice < OperationsOnePastLast;
|
||||
Choice++)
|
||||
{
|
||||
s32 Index = Choice - OperationsStart;
|
||||
PushString(&OperationChoices[Index], State->Transient, StringLength);
|
||||
CopyCharArrayToString(PatternSelectorOperationsText[Choice],
|
||||
&OperationChoices[Index]);
|
||||
}
|
||||
|
||||
v2 Min = v2{Context.WindowWidth - 250, 250};
|
||||
v2 Max = v2{Context.WindowWidth - 50, 500};
|
||||
|
||||
scroll_list_result OperationChoice = DrawSelectableOptionsList(RenderBuffer, Min, Max, OperationChoices, OperationsCount,
|
||||
0, ActiveChannel->BlendMode - 1,
|
||||
State->Interface, Input);
|
||||
if (OperationChoice.IndexSelected + 1 > (int)ChannelBlend_Invalid &&
|
||||
OperationChoice.IndexSelected + 1 < (int)ChannelBlend_Count)
|
||||
{
|
||||
ActiveChannel->BlendMode = (channel_blend_mode)(OperationChoice.IndexSelected + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
DrawDebugInterface(RenderBuffer, 25,
|
||||
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
|
||||
Context.DeltaTime, State->Camera, Input, State->Transient);
|
||||
|
|
|
@ -40,21 +40,10 @@ struct assembly
|
|||
};
|
||||
|
||||
#include "assembly_parser.h"
|
||||
|
||||
// TODO(Peter): remove this, and get pattern_system.h outta here!!
|
||||
typedef struct led_pattern led_pattern;
|
||||
|
||||
#include "foldhaus_node.h"
|
||||
|
||||
#include "foldhaus_patterns.h"
|
||||
#include "foldhaus_channel.h"
|
||||
#include "foldhaus_patterns.cpp"
|
||||
#include "foldhaus_channel.cpp"
|
||||
|
||||
#include "assembly_parser.cpp"
|
||||
|
||||
#include "test_patterns.h"
|
||||
#include "patterns_registry.h"
|
||||
#include "kraftwerks_patterns.h"
|
||||
#include "foldhaus_interface.h"
|
||||
|
||||
typedef struct app_state app_state;
|
||||
|
@ -62,6 +51,9 @@ typedef struct app_state app_state;
|
|||
#include "foldhaus_debug_visuals.h"
|
||||
#include "foldhaus_command_dispatch.h"
|
||||
|
||||
#include "foldhaus_text_entry.h"
|
||||
|
||||
#include "foldhaus_default_nodes.h"
|
||||
#include "generated/foldhaus_nodes_generated.cpp"
|
||||
|
||||
struct app_state
|
||||
|
@ -70,13 +62,18 @@ struct app_state
|
|||
memory_arena* Transient;
|
||||
memory_arena SACNMemory;
|
||||
|
||||
/*
|
||||
render_texture* LoadedTextures;
|
||||
s32 LoadedTexturesSize;
|
||||
s32 LoadedTexturesUsed;
|
||||
*/
|
||||
|
||||
camera Camera;
|
||||
|
||||
input_command_registry InputCommandRegistry;
|
||||
input_command_registry TextEntryCommandRegistry;
|
||||
input_command_registry* ActiveCommands;
|
||||
text_input* ActiveTextEntry;
|
||||
|
||||
streaming_acn SACN;
|
||||
s32 TotalLEDsCount;
|
||||
|
@ -89,10 +86,6 @@ struct app_state
|
|||
assembly AssemblyList[ASSEMBLY_LIST_LENGTH];
|
||||
s32 AssembliesUsed;
|
||||
|
||||
//environment Environment;
|
||||
led_channel_system ChannelSystem;
|
||||
led_pattern_system PatternSystem;
|
||||
|
||||
bitmap_font* Font;
|
||||
interface_state InterfaceState;
|
||||
interface_config Interface;
|
||||
|
@ -114,9 +107,14 @@ struct app_state
|
|||
interface_node* OutputNode;
|
||||
|
||||
v4* ColorPickerEditValue;
|
||||
|
||||
text_input GeneralPurposeSearch;
|
||||
s32 GeneralPurposeSearchHotItem;
|
||||
|
||||
};
|
||||
|
||||
#include "foldhaus_sacn_view.cpp"
|
||||
#include "foldhaus_command_dispatch.cpp"
|
||||
#include "foldhaus_node.cpp"
|
||||
#include "foldhaus_text_entry.cpp"
|
||||
#include "foldhaus_interface.cpp"
|
||||
|
|
|
@ -1,261 +0,0 @@
|
|||
inline void
|
||||
SetTransition(pattern_transition* Transition, r32 Duration, r32 Elapsed)
|
||||
{
|
||||
Transition->Duration = Duration;
|
||||
Transition->TimeElapsed = Elapsed;
|
||||
}
|
||||
|
||||
internal void
|
||||
InitLEDChannelSystem (led_channel_system* System, memory_arena* ParentStorage, s32 StorageSize)
|
||||
{
|
||||
System->Channels = 0;
|
||||
System->ChannelCount = 0;
|
||||
InitMemoryArena(&System->Storage, PushSize(ParentStorage, StorageSize), StorageSize, 0);
|
||||
System->FreeList = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
ResetChannel (led_channel* Channel, led_channel_system* ChannelSystem)
|
||||
{
|
||||
if (Channel->Patterns == 0)
|
||||
{
|
||||
Channel->Patterns = PushArray(&ChannelSystem->Storage,
|
||||
pattern_index_id_key,
|
||||
CHANNEL_MAX_PATTERNS);
|
||||
}
|
||||
Channel->ActivePatterns = 0;
|
||||
Channel->ActivePatternIndex = -1;
|
||||
|
||||
SetTransition(&Channel->Transition, 3, 0);
|
||||
|
||||
Channel->BlendMode = ChannelBlend_Override;
|
||||
Channel->ChannelID = ChannelIDAccumulator++;
|
||||
|
||||
Channel->Next = 0;
|
||||
}
|
||||
|
||||
internal led_channel*
|
||||
AddLEDChannel (led_channel_system* ChannelSystem)
|
||||
{
|
||||
led_channel* Channel = 0;
|
||||
|
||||
if (ChannelSystem->FreeList)
|
||||
{
|
||||
Channel = ChannelSystem->FreeList;
|
||||
ChannelSystem->FreeList = ChannelSystem->FreeList->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
Channel = PushStruct(&ChannelSystem->Storage, led_channel);
|
||||
}
|
||||
ResetChannel(Channel, ChannelSystem);
|
||||
|
||||
Channel->Next = ChannelSystem->Channels;
|
||||
ChannelSystem->Channels = Channel;
|
||||
ChannelSystem->ChannelCount++;
|
||||
|
||||
return Channel;
|
||||
}
|
||||
|
||||
internal b32
|
||||
RemoveLEDChannel_ (led_channel* PrevChannel, led_channel* ToRemove, led_channel_system* ChannelSystem)
|
||||
{
|
||||
b32 Result = true;
|
||||
|
||||
if (PrevChannel->Next == ToRemove)
|
||||
{
|
||||
PrevChannel->Next = ToRemove->Next;
|
||||
ToRemove->Next = ChannelSystem->FreeList;
|
||||
ChannelSystem->FreeList = ToRemove;
|
||||
ChannelSystem->ChannelCount--;
|
||||
Result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = false;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
RemoveLEDChannel (led_channel* Channel, led_channel_system* ChannelSystem)
|
||||
{
|
||||
b32 Result = true;
|
||||
|
||||
led_channel* Cursor = ChannelSystem->Channels;
|
||||
for (s32 i = 0;
|
||||
(Cursor->Next != Channel && i < ChannelSystem->ChannelCount);
|
||||
Cursor = Cursor->Next, i++){}
|
||||
|
||||
Result = RemoveLEDChannel_(Cursor, Channel, ChannelSystem);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
RemoveLEDChannel (s32 Index, led_channel_system* ChannelSystem)
|
||||
{
|
||||
Assert(Index < ChannelSystem->ChannelCount);
|
||||
b32 Result = true;
|
||||
|
||||
if (Index == 0)
|
||||
{
|
||||
led_channel* FirstChannel = ChannelSystem->Channels;
|
||||
ChannelSystem->Channels = FirstChannel->Next;
|
||||
FirstChannel->Next = ChannelSystem->FreeList;
|
||||
ChannelSystem->FreeList = FirstChannel;
|
||||
ChannelSystem->ChannelCount--;
|
||||
Result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
led_channel* PrevChannel = ChannelSystem->Channels;
|
||||
for (s32 i = 0; i < Index - 1; i++)
|
||||
{
|
||||
PrevChannel = PrevChannel->Next;
|
||||
}
|
||||
|
||||
Result = RemoveLEDChannel_(PrevChannel, PrevChannel->Next, ChannelSystem);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal led_channel*
|
||||
GetChannelByIndex (s32 Index, led_channel_system ChannelSystem)
|
||||
{
|
||||
Assert(Index < ChannelSystem.ChannelCount);
|
||||
led_channel* Result = ChannelSystem.Channels;
|
||||
|
||||
for (s32 i = 0; i < Index; i++)
|
||||
{
|
||||
Result = Result->Next;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
AddPatternKeyToChannel (pattern_index_id_key Key, led_channel* Channel)
|
||||
{
|
||||
Assert(Channel->ActivePatterns < CHANNEL_MAX_PATTERNS);
|
||||
Channel->Patterns[Channel->ActivePatterns++] = Key;
|
||||
}
|
||||
|
||||
internal b32
|
||||
RemovePatternKeyFromChannel (pattern_index_id_key Key, led_channel* Channel)
|
||||
{
|
||||
b32 Result = false;
|
||||
|
||||
s32 RemoveFrom = -1;
|
||||
for (s32 i = 0; i < Channel->ActivePatterns; i++)
|
||||
{
|
||||
if (Channel->Patterns[i].ID == Key.ID)
|
||||
{
|
||||
RemoveFrom = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (RemoveFrom >= 0)
|
||||
{
|
||||
for (s32 j = 0; j < Channel->ActivePatterns; j++)
|
||||
{
|
||||
Channel->Patterns[j] = Channel->Patterns[j + 1];
|
||||
}
|
||||
Channel->ActivePatterns--;
|
||||
Result = true;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
PushPatternKeyOnUpdateList (pattern_index_id_key Key,
|
||||
pattern_push_color_proc* PushColorProc,
|
||||
patterns_update_list* UpdateList,
|
||||
memory_arena* Storage)
|
||||
{
|
||||
if (UpdateList->Used >= UpdateList->Size)
|
||||
{
|
||||
if (!UpdateList->Next)
|
||||
{
|
||||
UpdateList->Next = PushStruct(Storage, patterns_update_list);
|
||||
UpdateList->Next->Size = UpdateList->Size;
|
||||
UpdateList->Next->Used = 0;
|
||||
UpdateList->Next->Patterns = PushArray(Storage, pattern_update_list_entry, UpdateList->Next->Size);
|
||||
}
|
||||
PushPatternKeyOnUpdateList(Key, PushColorProc, UpdateList->Next, Storage);
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern_update_list_entry Entry = {};
|
||||
Entry.Key = Key;
|
||||
Entry.PushColorProc = PushColorProc;
|
||||
UpdateList->Patterns[UpdateList->Used++] = Entry;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
UpdateChannel (led_channel* Channel,
|
||||
patterns_update_list* PatternsNeedUpdateList,
|
||||
r32 DeltaTime,
|
||||
memory_arena* Storage)
|
||||
{
|
||||
// Update Transition
|
||||
Channel->Transition.TimeElapsed += DeltaTime;
|
||||
if (Channel->Transition.TimeElapsed >= Channel->Transition.Duration ||
|
||||
(Channel->ActivePatternIndex < 0 && Channel->ActivePatterns > 0))
|
||||
{
|
||||
Channel->Transition.TimeElapsed -= Channel->Transition.Duration;
|
||||
Channel->ActivePatternIndex++;
|
||||
if (Channel->ActivePatternIndex >= Channel->ActivePatterns)
|
||||
{
|
||||
Channel->ActivePatternIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Create Active Pattern List
|
||||
if (Channel->ActivePatterns > 0)
|
||||
{
|
||||
Assert(Channel->ActivePatternIndex >= 0 && Channel->ActivePatternIndex < Channel->ActivePatterns);
|
||||
|
||||
pattern_push_color_proc* PushColorProc = 0;
|
||||
switch (Channel->BlendMode)
|
||||
{
|
||||
case ChannelBlend_Override: { PushColorProc = PushColor_Override; } break;
|
||||
case ChannelBlend_Add: { PushColorProc = PushColor_Add; } break;
|
||||
case ChannelBlend_Multiply: { PushColorProc = PushColor_Multiply; } break;
|
||||
default:
|
||||
{
|
||||
InvalidCodePath;
|
||||
}break;
|
||||
}
|
||||
|
||||
PushPatternKeyOnUpdateList(Channel->Patterns[Channel->ActivePatternIndex],
|
||||
PushColorProc,
|
||||
PatternsNeedUpdateList, Storage);
|
||||
}
|
||||
}
|
||||
|
||||
internal patterns_update_list
|
||||
UpdateAllChannels (led_channel_system* ChannelSystem, r32 DeltaTime, memory_arena* Transient)
|
||||
{
|
||||
patterns_update_list Result = {};
|
||||
// NOTE(Peter): The initial size of this array is ChannelCount * 2 b/c at the moment, in the worst case,
|
||||
// we need to update the two patterns a channel is blending between, and there isn't a case where we'd
|
||||
// update 3 per channel
|
||||
Result.Size = ChannelSystem->ChannelCount * 2;
|
||||
Result.Used = 0;
|
||||
Result.Patterns = PushArray(Transient, pattern_update_list_entry, Result.Size);
|
||||
Result.Next = 0;
|
||||
|
||||
for (led_channel* Channel = ChannelSystem->Channels;
|
||||
Channel;
|
||||
Channel = Channel->Next)
|
||||
{
|
||||
UpdateChannel(Channel, &Result, DeltaTime, Transient);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
#if 0 // USAGE CODE
|
||||
|
||||
{
|
||||
channel* FirstChannel = AddChannel(State, State->Channels);
|
||||
|
||||
channel* ActiveChannel = GetChannelAtIndex(State->Channels, ActiveIndex);
|
||||
AddPattern(State, ActiveChannel, PatternSpec);
|
||||
|
||||
patterns_need_update UpdatePatternsList = UdpateAllChannels(ChannelSystem, State->Transient);
|
||||
|
||||
for (s32 i = 0; i < UpdatePatternsList.Count; i++)
|
||||
{
|
||||
UpdateActivePatterns(State, Patterns, UpdatePatternsList.PatternIDs[i]);
|
||||
}
|
||||
|
||||
pattern* Pattern = ...;
|
||||
DeletePattern(State, Pattern);
|
||||
|
||||
RemoveChannel(FirstChannel, State->Channels);
|
||||
RemoveChannel(2, State->Channels);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct pattern_transition
|
||||
{
|
||||
r32 Duration;
|
||||
r32 TimeElapsed;
|
||||
};
|
||||
|
||||
enum channel_blend_mode
|
||||
{
|
||||
ChannelBlend_Invalid,
|
||||
|
||||
ChannelBlend_Override,
|
||||
ChannelBlend_Add,
|
||||
ChannelBlend_Multiply,
|
||||
|
||||
ChannelBlend_Count,
|
||||
};
|
||||
|
||||
char* METAChannelBlendModeNames[] = {
|
||||
"Invalid", //ChannelBlend_Invalid
|
||||
"Override", //ChannelBlend_Override
|
||||
"Add", // ChannelBlend_Add
|
||||
"Multiply", //ChannelBlend_Multiply
|
||||
"Count", //ChannelBlend_Count
|
||||
};
|
||||
|
||||
global_variable s32 ChannelIDAccumulator;
|
||||
|
||||
// TODO(Peter): This number is gonna have to get bigger
|
||||
#define CHANNEL_MAX_PATTERNS 8
|
||||
struct led_channel
|
||||
{
|
||||
s32 ChannelID;
|
||||
|
||||
pattern_index_id_key* Patterns;
|
||||
// TODO(Peter): Rename this once we get patterns in their own system. All patterns in this
|
||||
// list are active. ATM this is just here for legacy reasons.
|
||||
s32 ActivePatterns;
|
||||
// TODO(Peter): and this should probably be CurrentPatternIndex, or HotPatternIndex
|
||||
s32 ActivePatternIndex;
|
||||
|
||||
// TODO(Peter): extend this to be able to have different kinds of transitions
|
||||
// including, most importantly, being able to fade between patterns
|
||||
pattern_transition Transition;
|
||||
channel_blend_mode BlendMode;
|
||||
|
||||
led_channel* Next;
|
||||
};
|
||||
|
||||
struct led_channel_system
|
||||
{
|
||||
led_channel* Channels;
|
||||
s32 ChannelCount;
|
||||
|
||||
// TODO(Peter): think about ways this can give back to the main pool
|
||||
// Like, if we just stay within initial storage, no problem. But if we grow really big,
|
||||
// then shrink really small, we should probably give some of it back to the main app.
|
||||
// maybe by keeping track of FreeList size...
|
||||
// TODO(Peter): Also need to think about how memory_arenas get bigger...
|
||||
memory_arena Storage;
|
||||
led_channel* FreeList;
|
||||
};
|
||||
|
||||
struct pattern_update_list_entry
|
||||
{
|
||||
pattern_index_id_key Key;
|
||||
pattern_push_color_proc* PushColorProc;
|
||||
};
|
||||
|
||||
struct patterns_update_list
|
||||
{
|
||||
pattern_update_list_entry* Patterns;
|
||||
s32 Size;
|
||||
s32 Used;
|
||||
patterns_update_list* Next;
|
||||
};
|
|
@ -8,7 +8,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
|
|||
|
||||
arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient);
|
||||
|
||||
string DebugString = InitializeString(PushArray(Transient, char, 256), 256);
|
||||
string DebugString = InitializeEmptyString(PushArray(Transient, char, 256), 256);
|
||||
|
||||
if (GlobalDebugServices->Interface.ShowCameraMouse || GlobalDebugServices->Interface.ShowTrackedScopes)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
//////////////////////////////////
|
||||
//
|
||||
// Values
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
NODE_STRUCT(float_value_data)
|
||||
{
|
||||
NODE_IN(r32, Value);
|
||||
NODE_OUT(r32, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(FloatValue, float_value_data)
|
||||
{
|
||||
Data->Result = Data->Value;
|
||||
}
|
||||
|
||||
NODE_STRUCT(vector_data)
|
||||
{
|
||||
NODE_IN(r32, X);
|
||||
NODE_IN(r32, Y);
|
||||
NODE_IN(r32, Z);
|
||||
NODE_IN(r32, W);
|
||||
NODE_OUT(v4, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(VectorValue, vector_data)
|
||||
{
|
||||
Data->Result = v4{Data->X, Data->Y, Data->Z, Data->W};
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Arithmetic
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
NODE_STRUCT(multiply_data)
|
||||
{
|
||||
NODE_IN(r32, A);
|
||||
NODE_IN(r32, B);
|
||||
NODE_OUT(r32, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(MultiplyNodeProc, multiply_data)
|
||||
{
|
||||
Data->Result = Data->A * Data->B;
|
||||
}
|
||||
|
||||
NODE_STRUCT(add_data)
|
||||
{
|
||||
NODE_IN(v4, A);
|
||||
NODE_IN(v4, B);
|
||||
NODE_OUT(v4, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(AddNodeProc, add_data)
|
||||
{
|
||||
Data->Result = Data->A + Data->B;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Animators
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
NODE_STRUCT(sin_wave_data)
|
||||
{
|
||||
NODE_IN(r32, Period);
|
||||
NODE_IN(r32, Min);
|
||||
NODE_IN(r32, Max);
|
||||
NODE_OUT(r32, Result);
|
||||
|
||||
r32 Accumulator;
|
||||
};
|
||||
|
||||
NODE_PROC(SinWave, sin_wave_data)
|
||||
{
|
||||
Data->Accumulator += DeltaTime;
|
||||
if (Data->Period > 0)
|
||||
{
|
||||
while (Data->Accumulator > Data->Period)
|
||||
{
|
||||
Data->Accumulator -= Data->Period;
|
||||
}
|
||||
|
||||
r32 ActualMin = GSMin(Data->Min, Data->Max);
|
||||
r32 ActualMax = GSMax(Data->Min, Data->Max);
|
||||
r32 SinResult = GSSin((Data->Accumulator / Data->Period) * PI * 2);
|
||||
Data->Result = GSRemap(SinResult, -1.f, 1.f, ActualMin, ActualMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data->Result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Pattern Mixing
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
NODE_STRUCT(multiply_patterns_data)
|
||||
{
|
||||
NODE_COLOR_BUFFER_IN(A);
|
||||
NODE_COLOR_BUFFER_IN(B);
|
||||
NODE_COLOR_BUFFER_OUT(Result);
|
||||
};
|
||||
|
||||
NODE_PROC(MultiplyPatterns, multiply_patterns_data)
|
||||
{
|
||||
led* LED = Data->ResultLEDs;
|
||||
for (s32 l = 0; l < Data->ResultLEDCount; l++)
|
||||
{
|
||||
Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount);
|
||||
|
||||
s32 AR = Data->AColors[LED->Index].R;
|
||||
s32 AG = Data->AColors[LED->Index].G;
|
||||
s32 AB = Data->AColors[LED->Index].B;
|
||||
|
||||
s32 BR = Data->BColors[LED->Index].R;
|
||||
s32 BG = Data->BColors[LED->Index].G;
|
||||
s32 BB = Data->BColors[LED->Index].B;
|
||||
|
||||
s32 RCombined = (AR * BR) / 255;
|
||||
s32 GCombined = (AG * BG) / 255;
|
||||
s32 BCombined = (AB * BB) / 255;
|
||||
|
||||
Data->ResultColors[LED->Index].R = (u8)RCombined;
|
||||
Data->ResultColors[LED->Index].G = (u8)GCombined;
|
||||
Data->ResultColors[LED->Index].B = (u8)BCombined;
|
||||
|
||||
LED++;
|
||||
}
|
||||
}
|
|
@ -1,224 +1,3 @@
|
|||
|
||||
|
||||
// NOTE(Peter): returns the rightmost bound of the panel
|
||||
internal r32
|
||||
DrawLeftHandInterface (app_state* State, input Input, r32 WindowHeight, render_command_buffer* RenderBuffer)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
s32 StringLength = 128;
|
||||
|
||||
panel_result LeftHandPanel = EvaluatePanel(RenderBuffer, v2{0, 0}, v2{250, WindowHeight},
|
||||
MakeStringLiteral("Channel Ops"), 0, State->Interface, Input);
|
||||
|
||||
r32 ListHeight = (LeftHandPanel.ChildMax.y - LeftHandPanel.ChildMin.y) / 2;
|
||||
panel_result ChannelListPanel = EvaluatePanel(RenderBuffer, &LeftHandPanel,
|
||||
ListHeight, MakeStringLiteral("Channels"),
|
||||
State->Interface, Input);
|
||||
panel_result PatternsListPanel = EvaluatePanel(RenderBuffer, &LeftHandPanel, ListHeight, MakeStringLiteral("Patterns"),
|
||||
State->Interface, Input);
|
||||
|
||||
// NOTE(Peter): have to do this before we open it otherwise, it'll just close again immediately
|
||||
// due to the mouse being pressed, outside the box, on the frame it is opened;
|
||||
if (State->InterfaceState.AddingPattern &&
|
||||
State->InterfaceState.ChannelSelected >= 0)
|
||||
{
|
||||
v2 PatternSelectorDim = v2{300, 200};
|
||||
v2 PatternSelectorPosition = PatternsListPanel.NextPanelMin;
|
||||
PatternSelectorPosition.y = PatternsListPanel.ChildMax.y - PatternSelectorDim.y;
|
||||
|
||||
panel_result AddPatternPanel = EvaluatePanel(
|
||||
RenderBuffer,
|
||||
PatternSelectorPosition, PatternSelectorPosition + PatternSelectorDim,
|
||||
MakeStringLiteral("Add Pattern"), 0, State->Interface, Input);
|
||||
|
||||
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton) &&
|
||||
!PointIsInRange(v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY},
|
||||
AddPatternPanel.ChildMin, AddPatternPanel.ChildMax))
|
||||
{
|
||||
State->InterfaceState.AddingPattern = false;
|
||||
}
|
||||
|
||||
s32 PatternsCount = sizeof(PatternRegistry)/sizeof(PatternRegistry[0]);
|
||||
string* PatternNames = PushArray(State->Transient, string, PatternsCount);
|
||||
|
||||
for (s32 i = 0; i < PatternsCount; i++)
|
||||
{
|
||||
PushString(&PatternNames[i], State->Transient, StringLength);
|
||||
CopyCharArrayToString(PatternRegistry[i].Name, &PatternNames[i]);
|
||||
}
|
||||
|
||||
scroll_list_result PatternsResult = DrawOptionsList(RenderBuffer, AddPatternPanel.ChildMin,
|
||||
AddPatternPanel.ChildMax,
|
||||
PatternNames,
|
||||
PatternsCount,
|
||||
State->InterfaceState.PatternSelectorStart,
|
||||
State->Interface,
|
||||
Input);
|
||||
if (PatternsResult.IndexSelected >= 0)
|
||||
{
|
||||
led_channel* ActiveChannel = GetChannelByIndex(State->InterfaceState.ChannelSelected,
|
||||
State->ChannelSystem);
|
||||
pattern_index_id_key PatternKey = AddPattern(
|
||||
&State->PatternSystem,
|
||||
&PatternRegistry[PatternsResult.IndexSelected]);
|
||||
AddPatternKeyToChannel(PatternKey, ActiveChannel);
|
||||
}
|
||||
|
||||
State->InterfaceState.PatternSelectorStart = PatternsResult.StartIndex;
|
||||
}
|
||||
|
||||
s32 ChannelCount = State->ChannelSystem.ChannelCount;
|
||||
// NOTE(Peter): adding one to the channel count here so that we can tack on the '+ Add Channel' lable at the end.
|
||||
// NOTE(Peter): I think I've spelled lable as label all throughout here now... oops.
|
||||
s32 ChannelLabelsCount = ChannelCount + 1;
|
||||
string* ChannelTitles = PushArray(State->Transient, string, ChannelLabelsCount);
|
||||
|
||||
led_channel* Channel = State->ChannelSystem.Channels;
|
||||
for (s32 ChannelIdx = 0; ChannelIdx < ChannelCount; ChannelIdx++)
|
||||
{
|
||||
PushString(&ChannelTitles[ChannelIdx], State->Transient, StringLength);
|
||||
PrintF(&ChannelTitles[ChannelIdx], "Channel %d", Channel->ChannelID);
|
||||
Channel = Channel->Next;
|
||||
}
|
||||
|
||||
ChannelTitles[ChannelCount] = MakeStringLiteral("+ Add Channel");
|
||||
|
||||
scroll_list_result ChannelList = DrawSelectableOptionsList(
|
||||
RenderBuffer,
|
||||
ChannelListPanel.ChildMin,
|
||||
ChannelListPanel.ChildMax,
|
||||
ChannelTitles,
|
||||
ChannelLabelsCount,
|
||||
State->InterfaceState.ChannelSelectorStart,
|
||||
State->InterfaceState.ChannelSelected,
|
||||
State->Interface, Input);
|
||||
|
||||
State->InterfaceState.ChannelSelectorStart = ChannelList.StartIndex;
|
||||
if (ChannelList.Selection == Selection_Selected)
|
||||
{
|
||||
if (ChannelList.IndexSelected >= ChannelCount)
|
||||
{
|
||||
led_channel* NewChannel = AddLEDChannel(&State->ChannelSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
State->InterfaceState.SelectionType = InterfaceSelection_Channel;
|
||||
State->InterfaceState.ChannelSelected = ChannelList.IndexSelected;
|
||||
State->InterfaceState.ActiveChannelPatternSelected = -1;
|
||||
}
|
||||
}
|
||||
else if (ChannelList.Selection == Selection_Deselected)
|
||||
{
|
||||
State->InterfaceState.ChannelSelected = -1;
|
||||
State->InterfaceState.ActiveChannelPatternSelected = -1;
|
||||
}
|
||||
|
||||
s32 ActiveChannelPatternCount = 0;
|
||||
s32 PatternLabelsCount = 1;
|
||||
string* PatternTitles = PushArray(State->Transient, string, 1);;
|
||||
|
||||
if (State->InterfaceState.ChannelSelected >= 0)
|
||||
{
|
||||
led_channel* ActiveChannel = GetChannelByIndex(State->InterfaceState.ChannelSelected,
|
||||
State->ChannelSystem);
|
||||
ActiveChannelPatternCount = ActiveChannel->ActivePatterns;
|
||||
|
||||
// NOTE(Peter): We're just growing the PatternTitles array allocated above.
|
||||
// IMPORTANT(Peter): make sure no allocations happen between the PushArray to PatternTitles and this one vvv
|
||||
PushArray(State->Transient, string, ActiveChannelPatternCount);
|
||||
PatternLabelsCount += ActiveChannelPatternCount;
|
||||
|
||||
for (s32 P = 0; P < ActiveChannelPatternCount; P++)
|
||||
{
|
||||
led_pattern* Pattern = FindPatternAndUpdateIDKey(&ActiveChannel->Patterns[P],
|
||||
&State->PatternSystem);
|
||||
|
||||
PushString(&PatternTitles[P], State->Transient, StringLength);
|
||||
PrintF(&PatternTitles[P], "%s %d", Pattern->Name, ActiveChannel->Patterns[P].ID);
|
||||
|
||||
Pattern++;
|
||||
}
|
||||
}
|
||||
|
||||
PatternTitles[ActiveChannelPatternCount]= MakeStringLiteral("+ Add Pattern");
|
||||
|
||||
scroll_list_result PatternsList = DrawSelectableOptionsList(
|
||||
RenderBuffer,
|
||||
PatternsListPanel.ChildMin,
|
||||
PatternsListPanel.ChildMax,
|
||||
PatternTitles,
|
||||
PatternLabelsCount,
|
||||
State->InterfaceState.ActiveChannelPatternSelectorStart,
|
||||
State->InterfaceState.ActiveChannelPatternSelected,
|
||||
State->Interface, Input
|
||||
);
|
||||
|
||||
State->InterfaceState.ActiveChannelPatternSelectorStart = PatternsList.StartIndex;
|
||||
if (PatternsList.Selection == Selection_Selected)
|
||||
{
|
||||
if (PatternsList.IndexSelected >= ActiveChannelPatternCount)
|
||||
{
|
||||
State->InterfaceState.AddingPattern = true;
|
||||
}
|
||||
else if (PatternsList.IndexSelected >= 0)
|
||||
{
|
||||
State->InterfaceState.SelectionType = InterfaceSelection_Pattern;
|
||||
OutputDebugStringA("Pattern\n");
|
||||
State->InterfaceState.ActiveChannelPatternSelected = PatternsList.IndexSelected;
|
||||
}
|
||||
}
|
||||
else if (PatternsList.Selection == Selection_Deselected)
|
||||
{
|
||||
State->InterfaceState.SelectionType = InterfaceSelection_None;
|
||||
OutputDebugStringA("None\n");
|
||||
State->InterfaceState.ActiveChannelPatternSelected = -1;
|
||||
}
|
||||
|
||||
return LeftHandPanel.NextPanelMin.x;
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(DeleteSelectedChannelOrPattern)
|
||||
{
|
||||
if (State->InterfaceState.ChannelSelected >= 0)
|
||||
{
|
||||
switch (State->InterfaceState.SelectionType)
|
||||
{
|
||||
case InterfaceSelection_Channel:
|
||||
{
|
||||
led_channel* DeleteCandidate = GetChannelByIndex(
|
||||
State->InterfaceState.ChannelSelected,
|
||||
State->ChannelSystem);
|
||||
|
||||
for (s32 i = 0; i < DeleteCandidate->ActivePatterns; i++)
|
||||
{
|
||||
RemovePattern(DeleteCandidate->Patterns[i],
|
||||
&State->PatternSystem);
|
||||
}
|
||||
|
||||
RemoveLEDChannel(State->InterfaceState.ChannelSelected, &State->ChannelSystem);
|
||||
State->InterfaceState.ChannelSelected--;
|
||||
|
||||
}break;
|
||||
|
||||
case InterfaceSelection_Pattern:
|
||||
{
|
||||
if (State->InterfaceState.ActiveChannelPatternSelected >= 0)
|
||||
{
|
||||
led_channel* ActiveChannel = GetChannelByIndex(State->InterfaceState.ChannelSelected,
|
||||
State->ChannelSystem);
|
||||
s32 KeyIndex = State->InterfaceState.ActiveChannelPatternSelected;
|
||||
pattern_index_id_key Key = ActiveChannel->Patterns[KeyIndex];
|
||||
if (RemovePattern(Key, &State->PatternSystem))
|
||||
{
|
||||
RemovePatternKeyFromChannel(Key, ActiveChannel);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(CameraMouseControl)
|
||||
{
|
||||
if (State->NodeInteraction.NodeOffset >= 0) { return; }
|
||||
|
@ -275,4 +54,10 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddNode)
|
|||
{
|
||||
State->InterfaceShowNodeList = true;
|
||||
State->NodeListMenuPosition = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
|
||||
ActivateTextEntry(&State->GeneralPurposeSearch, State);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(ToggleNodeDisplay)
|
||||
{
|
||||
State->NodeRenderSettings.Display = !State->NodeRenderSettings.Display;
|
||||
}
|
|
@ -79,6 +79,7 @@ BootstrapRegionOntoMemory (u8* Memory, s32 Size)
|
|||
Result->Base = Memory + sizeof(memory_region);
|
||||
Result->Size = Size - sizeof(memory_region);
|
||||
Result->Used = 0;
|
||||
Result->PreviousRegion = 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -161,6 +162,7 @@ BootstrapArenaIntoMemory (u8* Memory, u32 Size)
|
|||
// NOTE(Peter): takes in a block of memory, places a memory arena at the head, and gives
|
||||
// the arena access to the rest of the block to use.
|
||||
memory_arena* Result = (memory_arena*)Memory;
|
||||
*Result = {};
|
||||
InitMemoryArena(Result, Memory + sizeof(memory_arena), Size - sizeof(memory_arena), 0);
|
||||
return Result;
|
||||
}
|
||||
|
@ -251,6 +253,37 @@ ClearArenaToSnapshot (memory_arena* Arena, arena_snapshot Snapshot)
|
|||
RegionCursor->Used = Snapshot.UsedAtSnapshot;
|
||||
}
|
||||
|
||||
//
|
||||
// Basic Memory Arena
|
||||
// A no-bookkeeping overhead version of the memory_arena above.
|
||||
//
|
||||
|
||||
struct static_memory_arena
|
||||
{
|
||||
u8* Base;
|
||||
u32 Size;
|
||||
u32 Used;
|
||||
};
|
||||
|
||||
static static_memory_arena
|
||||
CreateMemoryArena (u8* Base, u32 Size)
|
||||
{
|
||||
static_memory_arena Result = {};
|
||||
Result.Base = Base;
|
||||
Result.Size = Size;
|
||||
Result.Used = 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
static u8*
|
||||
PushSize_ (static_memory_arena* Arena, u32 Size)
|
||||
{
|
||||
Assert(Arena->Used + Size <= Arena->Size);
|
||||
u8* Result = Arena->Base + Arena->Used;
|
||||
Arena->Used += Size;
|
||||
return Result;
|
||||
}
|
||||
|
||||
//
|
||||
// Tracked Array Implementation
|
||||
//
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
inline s32
|
||||
GetNodeMemorySize (interface_node Node)
|
||||
{
|
||||
|
@ -125,15 +126,22 @@ InitializeNodeConnection (node_connection* Connection, struct_member_type Type,
|
|||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
PushNodeOnListFromSpecification (node_list* List, node_specification Spec, v2 Min, memory_arena* Storage)
|
||||
internal r32
|
||||
CalculateNodeHeight (s32 Members, node_render_settings RenderSettings)
|
||||
{
|
||||
// TODO(Peter): Calculate the size of a node;
|
||||
r32 Result = (RenderSettings.PortStep * Members) + NODE_HEADER_HEIGHT;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
PushNodeOnListFromSpecification (node_list* List, node_specification Spec, v2 Min, node_render_settings RenderSettings, memory_arena* Storage)
|
||||
{
|
||||
r32 NodeHeight = CalculateNodeHeight (Spec.MemberListLength, RenderSettings);
|
||||
interface_node* Node = PushNodeOnList(List,
|
||||
Spec.NameLength,
|
||||
Spec.MemberListLength,
|
||||
Min,
|
||||
v2{150, 150},
|
||||
v2{150, NodeHeight},
|
||||
Storage);
|
||||
Node->Type = Spec.Type;
|
||||
|
||||
|
@ -146,6 +154,7 @@ PushNodeOnListFromSpecification (node_list* List, node_specification Spec, v2 Mi
|
|||
InitializeNodeConnection(Node->Connections + MemberIdx, Member.Type, Member.IsInput);
|
||||
}
|
||||
|
||||
Node->PersistentData = PushArray(Storage, u8, Spec.DataStructSize);
|
||||
}
|
||||
|
||||
internal interface_node*
|
||||
|
@ -182,18 +191,6 @@ GetNodeAtOffset (node_list* List, s32 Offset)
|
|||
return Node;
|
||||
}
|
||||
|
||||
internal node_interaction
|
||||
NewNodeInteraction ()
|
||||
{
|
||||
node_interaction Result = {};
|
||||
Result.NodeOffset = -1;
|
||||
Result.InputPort = -1;
|
||||
Result.InputValue = -1;
|
||||
Result.OutputPort = -1;
|
||||
Result.OutputValue = -1;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect
|
||||
CalculateNodeBounds (interface_node* Node, node_render_settings Settings)
|
||||
{
|
||||
|
@ -273,6 +270,18 @@ CalculateNodeDragHandleBounds (rect NodeBounds, s32 Index, node_render_settings
|
|||
return Result;
|
||||
}
|
||||
|
||||
internal node_interaction
|
||||
NewNodeInteraction ()
|
||||
{
|
||||
node_interaction Result = {};
|
||||
Result.NodeOffset = -1;
|
||||
Result.InputPort = -1;
|
||||
Result.InputValue = -1;
|
||||
Result.OutputPort = -1;
|
||||
Result.OutputValue = -1;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
IsDraggingNode (node_interaction Interaction)
|
||||
{
|
||||
|
@ -658,7 +667,7 @@ PlaceNode (node_list* NodeList, interface_node* Node, v2 Position, b32 Flags)
|
|||
v2 NewPos = CurrPos + Offset;
|
||||
// NOTE(Peter): Have to negate the all downstream component so it doesn't turn around and try
|
||||
// to move this node again.
|
||||
PlaceNode(NodeList, ConnectedNode, NewPos, Flags & ~NodeInteraction_AllDownstream);
|
||||
PlaceNode(NodeList, ConnectedNode, NewPos, Flags & ~NodeInteraction_AllUpstream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -677,7 +686,7 @@ PlaceNode (node_list* NodeList, interface_node* Node, v2 Position, b32 Flags)
|
|||
v2 NewPos = CurrPos + Offset;
|
||||
// NOTE(Peter): Have to negate the all upstream component so it doesn't turn around and try
|
||||
// to move this node again.
|
||||
PlaceNode(NodeList, ConnectedNode, NewPos, Flags & ~NodeInteraction_AllUpstream);
|
||||
PlaceNode(NodeList, ConnectedNode, NewPos, Flags & ~NodeInteraction_AllDownstream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -825,6 +834,7 @@ UpdateNodeCalculation (interface_node* Node, node_list* NodeList,
|
|||
led* LEDs, sacn_pixel* ColorsInit, s32 LEDCount, r32 DeltaTime)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
Assert(Node->PersistentData != 0);
|
||||
|
||||
// NOTE(Peter): Have to subtract one here so that we account for the
|
||||
// NodeType_OutputNode entry in the enum
|
||||
|
@ -839,12 +849,6 @@ UpdateNodeCalculation (interface_node* Node, node_list* NodeList,
|
|||
|
||||
sacn_pixel* Colors = ColorsInit;
|
||||
|
||||
// TODO(Peter): Should do this at node creation time
|
||||
if (Node->PersistentData == 0)
|
||||
{
|
||||
Node->PersistentData = PushArray(Permanent, u8, Spec.DataStructSize);
|
||||
}
|
||||
|
||||
UpdateNodesConnectedUpstream(Node, NodeList, Permanent, Transient, LEDs, Colors, LEDCount, DeltaTime);
|
||||
|
||||
for (s32 ConnectionIdx = 0; ConnectionIdx < Node->ConnectionsCount; ConnectionIdx++)
|
||||
|
@ -1111,3 +1115,11 @@ ResetNodesUpdateState (node_list* NodeList)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
internal char*
|
||||
NodeListerGetNodeName (u8* NodeSpecificationsList, s32 NodeSpecificationsListCount, s32 Offset)
|
||||
{
|
||||
node_specification* Specifications = (node_specification*)NodeSpecificationsList + Offset;
|
||||
char* Result = Specifications->Name;
|
||||
return Result;
|
||||
}
|
|
@ -155,6 +155,7 @@ struct node_render_settings
|
|||
r32 PortStep;
|
||||
v4 PortColors[MemberTypeCount];
|
||||
bitmap_font* Font;
|
||||
b32 Display;
|
||||
};
|
||||
|
||||
v4 DragButtonColors[] = {
|
||||
|
|
|
@ -1,247 +0,0 @@
|
|||
NODE_STRUCT(multiply_data)
|
||||
{
|
||||
NODE_IN(r32, A);
|
||||
NODE_IN(r32, B);
|
||||
NODE_OUT(r32, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(MultiplyNodeProc, multiply_data)
|
||||
{
|
||||
Data->Result = Data->A * Data->B;
|
||||
}
|
||||
|
||||
NODE_STRUCT(add_data)
|
||||
{
|
||||
NODE_IN(v4, A);
|
||||
NODE_IN(v4, B);
|
||||
NODE_OUT(v4, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(AddNodeProc, add_data)
|
||||
{
|
||||
Data->Result = Data->A + Data->B;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
//
|
||||
// OLD - Pre Node System
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
PATTERN_PUSH_COLOR_PROC(PushColor_Override)
|
||||
{
|
||||
Colors[LED->Index].R = R;
|
||||
Colors[LED->Index].G = G;
|
||||
Colors[LED->Index].B = B;
|
||||
}
|
||||
|
||||
PATTERN_PUSH_COLOR_PROC(PushColor_Add)
|
||||
{
|
||||
Colors[LED->Index].R += R;
|
||||
Colors[LED->Index].G += G;
|
||||
Colors[LED->Index].B += B;
|
||||
}
|
||||
|
||||
PATTERN_PUSH_COLOR_PROC(PushColor_Multiply)
|
||||
{
|
||||
Colors[LED->Index].R *= R;
|
||||
Colors[LED->Index].G *= G;
|
||||
Colors[LED->Index].B *= B;
|
||||
}
|
||||
|
||||
inline u32
|
||||
PackColorStruct (u8* Channels)
|
||||
{
|
||||
u32 Result = 0;
|
||||
Result |= (*Channels++ << 24);
|
||||
Result |= (*Channels++ << 16);
|
||||
Result |= (*Channels++ << 8);
|
||||
Result |= (255 << 0); // Alpha
|
||||
return Result;
|
||||
};
|
||||
|
||||
inline u8
|
||||
ToColorU8 (r32 V)
|
||||
{
|
||||
return (u8)(V * 255.f);
|
||||
}
|
||||
|
||||
inline u32
|
||||
PackColorStructFromVector (v4 Color)
|
||||
{
|
||||
u32 Result = ((ToColorU8(Color.r) << 24) |
|
||||
(ToColorU8(Color.g) << 16) |
|
||||
(ToColorU8(Color.b) << 8) |
|
||||
(ToColorU8(Color.a) << 0));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
InitLEDPatternSystem (led_pattern_system* PatternSystem, memory_arena* ParentStorage,
|
||||
s32 MaxPatternsCount, s32 PatternWorkingMemoryStorageSize)
|
||||
{
|
||||
PatternSystem->Patterns = PushArray(ParentStorage, led_pattern, MaxPatternsCount);
|
||||
PatternSystem->PatternsUsed = 0;
|
||||
PatternSystem->PatternsMax = MaxPatternsCount;
|
||||
|
||||
InitMemoryArena(&PatternSystem->PatternWorkingMemoryStorage, PushSize(ParentStorage, PatternWorkingMemoryStorageSize), PatternWorkingMemoryStorageSize, 0);
|
||||
}
|
||||
|
||||
internal pattern_index_id_key
|
||||
AddPattern (led_pattern_system* PatternSystem,
|
||||
pattern_registry_entry* PatternSpec)
|
||||
{
|
||||
Assert(PatternSystem->PatternsUsed < PatternSystem->PatternsMax);
|
||||
|
||||
pattern_index_id_key Result = {};
|
||||
|
||||
led_pattern* NewPattern = &PatternSystem->Patterns[PatternSystem->PatternsUsed];
|
||||
NewPattern->ID = PatternSystem->IDAccumulator++;
|
||||
NewPattern->Name = PatternSpec->Name;
|
||||
NewPattern->UpdateProc = PatternSpec->Update;
|
||||
PatternSpec->Init(NewPattern, &PatternSystem->PatternWorkingMemoryStorage);
|
||||
|
||||
Result.Index = PatternSystem->PatternsUsed++;
|
||||
Result.ID = NewPattern->ID;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
RemovePattern (pattern_index_id_key Key, led_pattern_system* PatternSystem)
|
||||
{
|
||||
b32 Result = false;
|
||||
s32 ActualIndex = -1;
|
||||
|
||||
if (PatternSystem->Patterns[Key.Index].ID == Key.ID)
|
||||
{
|
||||
ActualIndex = Key.Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s32 i = 0; i < PatternSystem->PatternsUsed; i++)
|
||||
{
|
||||
if (PatternSystem->Patterns[i].ID == Key.ID)
|
||||
{
|
||||
ActualIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ActualIndex >= 0)
|
||||
{
|
||||
for (s32 j = ActualIndex; j < PatternSystem->PatternsUsed - 1; j++)
|
||||
{
|
||||
PatternSystem->Patterns[j] = PatternSystem->Patterns[j + 1];
|
||||
}
|
||||
|
||||
PatternSystem->PatternsUsed--;
|
||||
|
||||
Result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = false;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal led_pattern*
|
||||
FindPatternAndUpdateIDKey (pattern_index_id_key* Key, led_pattern_system* PatternSystem)
|
||||
{
|
||||
led_pattern* Result = 0;
|
||||
|
||||
if (Key->Index < PatternSystem->PatternsUsed &&
|
||||
PatternSystem->Patterns[Key->Index].ID == Key->ID)
|
||||
{
|
||||
Result = &PatternSystem->Patterns[Key->Index];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s32 i = 0; i < PatternSystem->PatternsUsed; i++)
|
||||
{
|
||||
if (PatternSystem->Patterns[i].ID == Key->ID)
|
||||
{
|
||||
Result = &PatternSystem->Patterns[i];
|
||||
Key->Index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
internal void
|
||||
UpdateAllPatterns_ (patterns_update_list* UpdateList,
|
||||
led_pattern_system* PatternSystem,
|
||||
pattern_led* LEDs,
|
||||
s32 LEDsCount,
|
||||
r32 DeltaTime,
|
||||
memory_arena* Transient)
|
||||
{
|
||||
pattern_push_color_proc* PushColorProc = 0;
|
||||
|
||||
for (s32 PatternKeyIdx = 0; PatternKeyIdx < UpdateList->Used; PatternKeyIdx++)
|
||||
{
|
||||
pattern_update_list_entry ListEntry = UpdateList->Patterns[PatternKeyIdx];
|
||||
pattern_index_id_key Key = ListEntry.Key;
|
||||
led_pattern* Pattern = FindPatternAndUpdateIDKey(&Key, PatternSystem);
|
||||
|
||||
if (!Pattern)
|
||||
{
|
||||
Pattern = FindPatternAndUpdateIDKey(&Key, PatternSystem);
|
||||
}
|
||||
|
||||
Pattern->UpdateProc(LEDs, LEDsCount,
|
||||
Pattern->Memory,
|
||||
DeltaTime, ListEntry.PushColorProc);
|
||||
}
|
||||
|
||||
if (UpdateList->Next)
|
||||
{
|
||||
UpdateAllPatterns(UpdateList->Next, PatternSystem, LEDs, LEDsCount, DeltaTime, Transient);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal void
|
||||
UpdateAllPatterns (patterns_update_list* UpdateList,
|
||||
led_pattern_system* PatternSystem,
|
||||
led_buffer* LEDBuffer,
|
||||
r32 DeltaTime,
|
||||
memory_arena* Transient)
|
||||
{
|
||||
pattern_push_color_proc* PushColorProc = 0;
|
||||
|
||||
for (s32 PatternKeyIdx = 0; PatternKeyIdx < UpdateList->Used; PatternKeyIdx++)
|
||||
{
|
||||
pattern_update_list_entry ListEntry = UpdateList->Patterns[PatternKeyIdx];
|
||||
pattern_index_id_key Key = ListEntry.Key;
|
||||
led_pattern* Pattern = FindPatternAndUpdateIDKey(&Key, PatternSystem);
|
||||
|
||||
if (!Pattern)
|
||||
{
|
||||
Pattern = FindPatternAndUpdateIDKey(&Key, PatternSystem);
|
||||
}
|
||||
|
||||
led_buffer* LEDBufferIter = LEDBuffer;
|
||||
while(LEDBufferIter)
|
||||
{
|
||||
Pattern->UpdateProc(LEDBufferIter->LEDs, LEDBufferIter->Colors, LEDBufferIter->Count,
|
||||
Pattern->Memory,
|
||||
DeltaTime, ListEntry.PushColorProc);
|
||||
LEDBufferIter = LEDBufferIter->Next;
|
||||
}
|
||||
}
|
||||
|
||||
if (UpdateList->Next)
|
||||
{
|
||||
UpdateAllPatterns(UpdateList->Next, PatternSystem, LEDBuffer, DeltaTime, Transient);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
typedef s32 pattern_id;
|
||||
|
||||
typedef struct pattern_led pattern_led;
|
||||
|
||||
#define PATTERN_INIT_PROC(name) void name(led_pattern* Pattern, memory_arena* Storage)
|
||||
typedef PATTERN_INIT_PROC(pattern_init_proc);
|
||||
|
||||
#define PATTERN_PUSH_COLOR_PROC(name) void name(led* LED, sacn_pixel* Colors, u8 R, u8 G, u8 B)
|
||||
typedef PATTERN_PUSH_COLOR_PROC(pattern_push_color_proc);
|
||||
|
||||
#define PATTERN_UPDATE_PROC(name) void name(led* LEDs, sacn_pixel* Colors, s32 LEDCount, void* Memory, r32 DeltaTime, pattern_push_color_proc PushColor)
|
||||
typedef PATTERN_UPDATE_PROC(pattern_update_proc);
|
||||
|
||||
struct pattern_registry_entry
|
||||
{
|
||||
char* Name;
|
||||
pattern_init_proc* Init;
|
||||
pattern_update_proc* Update;
|
||||
};
|
||||
|
||||
struct pattern_led
|
||||
{
|
||||
s32 LocationInSendBuffer;
|
||||
u32 Color;
|
||||
v3 Position;
|
||||
};
|
||||
|
||||
enum pattern_selector_combine_operation
|
||||
{
|
||||
PatternSelectorCombine_Invalid,
|
||||
|
||||
PatternSelectorCombine_Override,
|
||||
PatternSelectorCombine_Add,
|
||||
PatternSelectorCombine_Multiply,
|
||||
|
||||
PatternSelectorCombine_Count,
|
||||
};
|
||||
|
||||
char* PatternSelectorOperationsText[] = {
|
||||
"Invalid",
|
||||
|
||||
"Override",
|
||||
"Add",
|
||||
"Multiply",
|
||||
|
||||
"Count",
|
||||
};
|
||||
|
||||
struct pattern_index_id_key
|
||||
{
|
||||
s32 Index;
|
||||
pattern_id ID;
|
||||
};
|
||||
|
||||
struct led_pattern
|
||||
{
|
||||
pattern_id ID;
|
||||
|
||||
void* Memory;
|
||||
|
||||
pattern_update_proc* UpdateProc;
|
||||
char* Name;
|
||||
};
|
||||
|
||||
struct led_pattern_system
|
||||
{
|
||||
// TODO(Peter): Need to think about how this grows
|
||||
led_pattern* Patterns;
|
||||
s32 PatternsUsed;
|
||||
s32 PatternsMax;
|
||||
|
||||
// TODO(Peter): Need to think about how this can have a free list as well of some sort.
|
||||
// It might be inexpensive enough to just compress this memory whenever we remove a pattern
|
||||
memory_arena PatternWorkingMemoryStorage;
|
||||
|
||||
|
||||
pattern_id IDAccumulator;
|
||||
};
|
|
@ -139,6 +139,16 @@ struct sacn_pixel
|
|||
u8 B;
|
||||
};
|
||||
|
||||
internal sacn_pixel
|
||||
PackFloatsToSACNPixel (r32 R, r32 G, r32 B)
|
||||
{
|
||||
sacn_pixel Result = {};
|
||||
Result.R = (u8)(GSClamp01(R) * 255);
|
||||
Result.G = (u8)(GSClamp01(G) * 255);
|
||||
Result.B = (u8)(GSClamp01(B) * 255);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
internal sacn_universe*
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntryString)
|
||||
{
|
||||
if (State->GeneralPurposeSearch.CursorPosition > 0)
|
||||
{
|
||||
RemoveCharAt(&State->GeneralPurposeSearch.Buffer,
|
||||
State->GeneralPurposeSearch.CursorPosition - 1);
|
||||
State->GeneralPurposeSearch.CursorPosition--;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
ActivateTextEntry(text_input* ActiveEntryString, app_state* State)
|
||||
{
|
||||
State->ActiveTextEntry = ActiveEntryString;
|
||||
State->ActiveTextEntry->PreviousCommandRegistry = State->ActiveCommands;
|
||||
State->ActiveCommands = &State->TextEntryCommandRegistry;
|
||||
}
|
||||
|
||||
internal void
|
||||
DeactivateTextEntry(app_state* State)
|
||||
{
|
||||
if (State->ActiveTextEntry->PreviousCommandRegistry != 0)
|
||||
{
|
||||
State->ActiveCommands = State->ActiveTextEntry->PreviousCommandRegistry;
|
||||
State->ActiveTextEntry = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
AppendInputToEntryString (text_input* EntryString, char* InputString, s32 InputStringLength)
|
||||
{
|
||||
if (InputStringLength > 0)
|
||||
{
|
||||
for (s32 i = 0; i < InputStringLength; i++)
|
||||
{
|
||||
InsertChar(&EntryString->Buffer, InputString[i], EntryString->CursorPosition);
|
||||
EntryString->CursorPosition++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorRight)
|
||||
{
|
||||
State->ActiveTextEntry->CursorPosition = GSMin(State->ActiveTextEntry->Buffer.Length,
|
||||
State->ActiveTextEntry->CursorPosition + 1);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorLeft)
|
||||
{
|
||||
State->ActiveTextEntry->CursorPosition = GSMax(0,
|
||||
State->ActiveTextEntry->CursorPosition - 1);
|
||||
}
|
||||
|
||||
internal void
|
||||
InitializeTextInputCommands (input_command_registry* SearchCommands, memory_arena* PermanentStorage)
|
||||
{
|
||||
if (SearchCommands->Size > 0)
|
||||
{
|
||||
RegisterKeyPressCommand(SearchCommands, KeyCode_Backspace, false, KeyCode_Invalid, RemoveCharacterFromEntryString);
|
||||
RegisterKeyPressCommand(SearchCommands, KeyCode_LeftArrow, false, KeyCode_Invalid, TextEntryMoveCursorLeft);
|
||||
RegisterKeyPressCommand(SearchCommands, KeyCode_RightArrow, false, KeyCode_Invalid, TextEntryMoveCursorRight);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
struct text_input
|
||||
{
|
||||
char* Backbuffer;
|
||||
string Buffer;
|
||||
s32 CursorPosition;
|
||||
input_command_registry* PreviousCommandRegistry;
|
||||
};
|
|
@ -1,17 +1,33 @@
|
|||
enum node_type
|
||||
{
|
||||
NodeType_OutputNode,
|
||||
NodeType_FloatValue,
|
||||
NodeType_VectorValue,
|
||||
NodeType_MultiplyNodeProc,
|
||||
NodeType_AddNodeProc,
|
||||
NodeType_FloatValueProc,
|
||||
NodeType_SolidColorProc,
|
||||
NodeType_SinWaveProc,
|
||||
NodeType_VectorProc,
|
||||
NodeType_SinWave,
|
||||
NodeType_MultiplyPatterns,
|
||||
NodeType_SwdColorProc,
|
||||
NodeType_SolidColorProc,
|
||||
NodeType_VerticalColorFadeProc,
|
||||
NodeType_RevolvingDiscs,
|
||||
NodeType_MichelleColorProc,
|
||||
NodeType_Count,
|
||||
};
|
||||
|
||||
node_struct_member MemberList_float_value_data[] = {
|
||||
{ MemberType_r32, "Value", (u64)&((float_value_data*)0)->Value, IsInputMember },
|
||||
{ MemberType_r32, "Result", (u64)&((float_value_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_vector_data[] = {
|
||||
{ MemberType_r32, "X", (u64)&((vector_data*)0)->X, IsInputMember },
|
||||
{ MemberType_r32, "Y", (u64)&((vector_data*)0)->Y, IsInputMember },
|
||||
{ MemberType_r32, "Z", (u64)&((vector_data*)0)->Z, IsInputMember },
|
||||
{ MemberType_r32, "W", (u64)&((vector_data*)0)->W, IsInputMember },
|
||||
{ MemberType_v4, "Result", (u64)&((vector_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_multiply_data[] = {
|
||||
{ MemberType_r32, "A", (u64)&((multiply_data*)0)->A, IsInputMember },
|
||||
{ MemberType_r32, "B", (u64)&((multiply_data*)0)->B, IsInputMember },
|
||||
|
@ -24,16 +40,6 @@ node_struct_member MemberList_add_data[] = {
|
|||
{ MemberType_v4, "Result", (u64)&((add_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_float_value_data[] = {
|
||||
{ MemberType_r32, "Value", (u64)&((float_value_data*)0)->Value, IsInputMember },
|
||||
{ MemberType_r32, "Result", (u64)&((float_value_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_solid_color_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((solid_color_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "LEDs", (u64)&((solid_color_data*)0)->LEDs, IsInputMember | IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_sin_wave_data[] = {
|
||||
{ MemberType_r32, "Period", (u64)&((sin_wave_data*)0)->Period, IsInputMember },
|
||||
{ MemberType_r32, "Min", (u64)&((sin_wave_data*)0)->Min, IsInputMember },
|
||||
|
@ -41,20 +47,23 @@ node_struct_member MemberList_sin_wave_data[] = {
|
|||
{ MemberType_r32, "Result", (u64)&((sin_wave_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_vector_data[] = {
|
||||
{ MemberType_r32, "X", (u64)&((vector_data*)0)->X, IsInputMember },
|
||||
{ MemberType_r32, "Y", (u64)&((vector_data*)0)->Y, IsInputMember },
|
||||
{ MemberType_r32, "Z", (u64)&((vector_data*)0)->Z, IsInputMember },
|
||||
{ MemberType_r32, "W", (u64)&((vector_data*)0)->W, IsInputMember },
|
||||
{ MemberType_v4, "Result", (u64)&((vector_data*)0)->Result, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_multiply_patterns_data[] = {
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ALEDs", (u64)&((multiply_patterns_data*)0)->ALEDs, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "BLEDs", (u64)&((multiply_patterns_data*)0)->BLEDs, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((multiply_patterns_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_swd_color_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((swd_color_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_v4, "ColorB", (u64)&((swd_color_data*)0)->ColorB, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "LEDs", (u64)&((swd_color_data*)0)->LEDs, IsInputMember | IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_solid_color_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((solid_color_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "LEDs", (u64)&((solid_color_data*)0)->LEDs, IsInputMember | IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_vertical_color_fade_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((vertical_color_fade_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_r32, "Min", (u64)&((vertical_color_fade_data*)0)->Min, IsInputMember },
|
||||
|
@ -62,29 +71,51 @@ node_struct_member MemberList_vertical_color_fade_data[] = {
|
|||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((vertical_color_fade_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_revolving_discs_data[] = {
|
||||
{ MemberType_r32, "Rotation", (u64)&((revolving_discs_data*)0)->Rotation, IsInputMember },
|
||||
{ MemberType_r32, "ThetaZ", (u64)&((revolving_discs_data*)0)->ThetaZ, IsInputMember },
|
||||
{ MemberType_r32, "ThetaY", (u64)&((revolving_discs_data*)0)->ThetaY, IsInputMember },
|
||||
{ MemberType_r32, "DiscWidth", (u64)&((revolving_discs_data*)0)->DiscWidth, IsInputMember },
|
||||
{ MemberType_r32, "InnerRadius", (u64)&((revolving_discs_data*)0)->InnerRadius, IsInputMember },
|
||||
{ MemberType_r32, "OuterRadius", (u64)&((revolving_discs_data*)0)->OuterRadius, IsInputMember },
|
||||
{ MemberType_v4, "Color", (u64)&((revolving_discs_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((revolving_discs_data*)0)->ResultLEDs, IsOutputMember},
|
||||
};
|
||||
|
||||
node_struct_member MemberList_michelle_data[] = {
|
||||
{ MemberType_v4, "Color", (u64)&((michelle_data*)0)->Color, IsInputMember },
|
||||
{ MemberType_NODE_COLOR_BUFFER, "LEDs", (u64)&((michelle_data*)0)->LEDs, IsInputMember | IsOutputMember},
|
||||
};
|
||||
|
||||
node_specification NodeSpecifications[] = {
|
||||
{ NodeType_FloatValue, "FloatValue", 10, MemberList_float_value_data, 8, 2, false},
|
||||
{ NodeType_VectorValue, "VectorValue", 11, MemberList_vector_data, 32, 5, false},
|
||||
{ NodeType_MultiplyNodeProc, "MultiplyNodeProc", 16, MemberList_multiply_data, 12, 3, false},
|
||||
{ NodeType_AddNodeProc, "AddNodeProc", 11, MemberList_add_data, 48, 3, false},
|
||||
{ NodeType_FloatValueProc, "FloatValueProc", 14, MemberList_float_value_data, 8, 2, false},
|
||||
{ NodeType_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 36, 2, false},
|
||||
{ NodeType_SinWaveProc, "SinWaveProc", 11, MemberList_sin_wave_data, 16, 4, false},
|
||||
{ NodeType_VectorProc, "VectorProc", 10, MemberList_vector_data, 32, 5, false},
|
||||
{ NodeType_SinWave, "SinWave", 7, MemberList_sin_wave_data, 20, 4, false},
|
||||
{ NodeType_MultiplyPatterns, "MultiplyPatterns", 16, MemberList_multiply_patterns_data, 60, 3, false},
|
||||
{ NodeType_SwdColorProc, "SwdColorProc", 12, MemberList_swd_color_data, 52, 3, false},
|
||||
{ NodeType_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 36, 2, false},
|
||||
{ NodeType_VerticalColorFadeProc, "VerticalColorFadeProc", 21, MemberList_vertical_color_fade_data, 44, 4, false},
|
||||
{ NodeType_RevolvingDiscs, "RevolvingDiscs", 14, MemberList_revolving_discs_data, 60, 8, false},
|
||||
{ NodeType_MichelleColorProc, "MichelleColorProc", 17, MemberList_michelle_data, 36, 2, false},
|
||||
};
|
||||
s32 NodeSpecificationsCount = 8;
|
||||
s32 NodeSpecificationsCount = 11;
|
||||
|
||||
internal void CallNodeProc(interface_node* Node, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)
|
||||
{
|
||||
switch (Node->Type)
|
||||
{
|
||||
case NodeType_FloatValue: { FloatValue((float_value_data*)Data, DeltaTime); } break;
|
||||
case NodeType_VectorValue: { VectorValue((vector_data*)Data, DeltaTime); } break;
|
||||
case NodeType_MultiplyNodeProc: { MultiplyNodeProc((multiply_data*)Data, DeltaTime); } break;
|
||||
case NodeType_AddNodeProc: { AddNodeProc((add_data*)Data, DeltaTime); } break;
|
||||
case NodeType_FloatValueProc: { FloatValueProc((float_value_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SolidColorProc: { SolidColorProc((solid_color_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SinWaveProc: { SinWaveProc((sin_wave_data*)Data, DeltaTime); } break;
|
||||
case NodeType_VectorProc: { VectorProc((vector_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SinWave: { SinWave((sin_wave_data*)Data, DeltaTime); } break;
|
||||
case NodeType_MultiplyPatterns: { MultiplyPatterns((multiply_patterns_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SwdColorProc: { SwdColorProc((swd_color_data*)Data, DeltaTime); } break;
|
||||
case NodeType_SolidColorProc: { SolidColorProc((solid_color_data*)Data, DeltaTime); } break;
|
||||
case NodeType_VerticalColorFadeProc: { VerticalColorFadeProc((vertical_color_fade_data*)Data, DeltaTime); } break;
|
||||
case NodeType_RevolvingDiscs: { RevolvingDiscs((revolving_discs_data*)Data, DeltaTime); } break;
|
||||
case NodeType_MichelleColorProc: { MichelleColorProc((michelle_data*)Data, DeltaTime); } break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,11 +171,16 @@ GSMaxDef(r32)
|
|||
GSMaxDef(r64)
|
||||
#undef GSMaxDef
|
||||
|
||||
inline b32 XOR(b32 A, b32 B)
|
||||
{
|
||||
b32 Result = (A == !B);
|
||||
return Result;
|
||||
}
|
||||
#define GSClampDef(type) static type GSClamp(type Min, type V, type Max) { \
|
||||
type Result = V; \
|
||||
if (V < Min) { Result = Min; } \
|
||||
if (V > Max) { Result = Max; } \
|
||||
return Result; \
|
||||
type Result = V; \
|
||||
if (V < Min) { Result = Min; } \
|
||||
if (V > Max) { Result = Max; } \
|
||||
return Result; \
|
||||
}
|
||||
GSClampDef(s8)
|
||||
GSClampDef(s16)
|
||||
|
|
|
@ -81,7 +81,7 @@ typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file);
|
|||
#define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(char* Path, u8* Contents, s32 Size)
|
||||
typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file);
|
||||
|
||||
#define PLATFORM_GET_FILE_PATH(name) b32 name(char* PathBuffer, s32 BufferLength)
|
||||
#define PLATFORM_GET_FILE_PATH(name) b32 name(char* PathBuffer, s32 BufferLength, const char* FilterStrings)
|
||||
typedef PLATFORM_GET_FILE_PATH(platform_get_file_path);
|
||||
|
||||
#define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height)
|
||||
|
@ -233,6 +233,7 @@ KeyTransitionedUp (input Input, key_code Key)
|
|||
{
|
||||
return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key];
|
||||
}
|
||||
|
||||
#endif // GS_INPUT
|
||||
|
||||
internal window PlatformCreateWindow (char* Name, s32 Width, s32 Height);
|
||||
|
|
140
gs_string.h
140
gs_string.h
|
@ -1,3 +1,4 @@
|
|||
#ifndef GS_STRING_H
|
||||
////////////////////////////////////////////////////////////////
|
||||
// String
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -98,9 +99,7 @@ char* TokenNames[] = {
|
|||
struct token
|
||||
{
|
||||
token_type Type;
|
||||
char* Text;
|
||||
s32 TextLength;
|
||||
|
||||
string Text;
|
||||
token* Next;
|
||||
};
|
||||
|
||||
|
@ -150,8 +149,10 @@ static float GSPowF (float N, s32 Power);
|
|||
#define PushString(str, arena, size) (str)->Memory = PushArray(arena, char, size); (str)->Length = 0; (str)->Max = size;
|
||||
#endif
|
||||
|
||||
static void InitializeString (string* String, char* Data, s32 DataSize);
|
||||
static string InitializeString (char* Data, s32 DataSize);
|
||||
static void InitializeEmptyString (string* String, char* Data, s32 DataSize);
|
||||
static void InitializeString(string* String, char* Data, s32 Used, s32 Max);
|
||||
static string InitializeEmptyString (char* Data, s32 DataSize);
|
||||
static string InitializeString (char* Data, s32 Used, s32 Max);
|
||||
static void ClearString (string* String);
|
||||
|
||||
// Character Values
|
||||
|
@ -161,12 +162,13 @@ static bool IsWhitespace (char C);
|
|||
static bool IsAlpha (char C);
|
||||
static bool IsUpper (char C);
|
||||
static bool IsLower (char C);
|
||||
static char ToUpper (char C);
|
||||
static char ToLower (char C);
|
||||
static bool IsNumeric (char C);
|
||||
static bool IsNumericExtended (char C);
|
||||
static bool ToUpper (char C);
|
||||
static bool ToLower (char C);
|
||||
static bool IsAlphaNumeric (char C);
|
||||
static bool IsOperator (char C);
|
||||
static bool CharsEqualCaseInsensitive(char A, char B);
|
||||
|
||||
// Tokenizing
|
||||
static b32 AtValidPosition(tokenizer Tokenizer);
|
||||
|
@ -240,6 +242,11 @@ static s32 LastIndexOfChar(string String, char C);
|
|||
static string Substring (string* String, s32 Start, s32 End);
|
||||
static string Substring (string* String, s32 Start);
|
||||
|
||||
static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength);
|
||||
static b32 StringContainsString(string SearchIn, string SearchFor);
|
||||
static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength);
|
||||
static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor);
|
||||
|
||||
static void NullTerminate (string* String);
|
||||
|
||||
|
||||
|
@ -339,15 +346,23 @@ GSPow (float N, s32 Power)
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
InitializeString (string* String, char* Data, s32 DataSize)
|
||||
InitializeEmptyString (string* String, char* Data, s32 DataSize)
|
||||
{
|
||||
String->Memory = Data;
|
||||
String->Max = DataSize;
|
||||
String->Length = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
InitializeString(string* String, char* Data, s32 Used, s32 Max)
|
||||
{
|
||||
String->Memory = Data;
|
||||
String->Max = Max;
|
||||
String->Length = Used;
|
||||
}
|
||||
|
||||
static string
|
||||
InitializeString (char* Data, s32 DataSize)
|
||||
InitializeEmptyString (char* Data, s32 DataSize)
|
||||
{
|
||||
string Result = {};
|
||||
Result.Memory = Data;
|
||||
|
@ -356,6 +371,16 @@ InitializeString (char* Data, s32 DataSize)
|
|||
return Result;
|
||||
}
|
||||
|
||||
static string
|
||||
InitializeString (char* Data, s32 Used, s32 Max)
|
||||
{
|
||||
string Result = {};
|
||||
Result.Memory = Data;
|
||||
Result.Max = Max;
|
||||
Result.Length = Used;
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void
|
||||
ClearString (string* String)
|
||||
{
|
||||
|
@ -407,6 +432,30 @@ static bool IsOperator (char C)
|
|||
(C == '<') ||
|
||||
(C == '>'));
|
||||
}
|
||||
static char ToUpper (char A)
|
||||
{
|
||||
char Result = A;
|
||||
if (IsLower(A))
|
||||
{
|
||||
Result += 'A' - 'a';
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
static char ToLower (char A)
|
||||
{
|
||||
char Result = A;
|
||||
if (IsUpper(A))
|
||||
{
|
||||
Result -= 'A' - 'a';
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
static bool CharsEqualCaseInsensitive (char A, char B)
|
||||
{
|
||||
b32 Result = (ToLower(A) == ToLower(B));
|
||||
return Result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Tokenizing
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -1050,7 +1099,7 @@ InsertChar (string* String, char Char, s32 Index)
|
|||
Assert(Index >= 0 && Index < String->Max);
|
||||
Assert(String->Length < String->Max);
|
||||
|
||||
char* Src = String->Memory + String->Length;
|
||||
char* Src = String->Memory + String->Length - 1;
|
||||
char* Dst = Src + 1;
|
||||
for (int i = String->Length - 1; i >= Index; i--)
|
||||
{
|
||||
|
@ -1132,6 +1181,74 @@ Substring (string String, s32 Start)
|
|||
return Result;
|
||||
}
|
||||
|
||||
static b32
|
||||
StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength)
|
||||
{
|
||||
b32 Result = false;
|
||||
|
||||
char* SearchInAt = SearchIn.Memory;
|
||||
for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++)
|
||||
{
|
||||
char* InAt = SearchInAt;
|
||||
char* ForAt = SearchFor;
|
||||
s32 LengthMatch = 0;
|
||||
while (*InAt == *ForAt)
|
||||
{
|
||||
InAt++;
|
||||
ForAt++;
|
||||
LengthMatch++;
|
||||
}
|
||||
if (LengthMatch == SearchForLength)
|
||||
{
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
SearchInAt++;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static b32
|
||||
StringContainsString(string SearchIn, string SearchFor)
|
||||
{
|
||||
return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length);
|
||||
}
|
||||
|
||||
static b32
|
||||
StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength)
|
||||
{
|
||||
b32 Result = false;
|
||||
|
||||
char* SearchInAt = SearchIn.Memory;
|
||||
for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++)
|
||||
{
|
||||
char* InAt = SearchInAt;
|
||||
char* ForAt = SearchFor;
|
||||
s32 LengthMatch = 0;
|
||||
while (CharsEqualCaseInsensitive(*InAt, *ForAt))
|
||||
{
|
||||
InAt++;
|
||||
ForAt++;
|
||||
LengthMatch++;
|
||||
}
|
||||
if (LengthMatch == SearchForLength)
|
||||
{
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
SearchInAt++;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static b32
|
||||
StringContainsStringCaseInsensitive(string SearchIn, string SearchFor)
|
||||
{
|
||||
return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length);
|
||||
}
|
||||
|
||||
static void
|
||||
NullTerminate (string* String)
|
||||
{
|
||||
|
@ -2081,3 +2198,6 @@ TestStrings()
|
|||
#endif // DEBUG_GS_STRING
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#define GS_STRING_H
|
||||
#endif // GS_STRING_H
|
21
gs_win32.cpp
21
gs_win32.cpp
|
@ -727,6 +727,27 @@ GetFileLastWriteTime(char* Path)
|
|||
PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile)
|
||||
{
|
||||
b32 Result = false;
|
||||
|
||||
PathBuffer[0] = 0;
|
||||
|
||||
OPENFILENAMEA OpenFileName = {};
|
||||
OpenFileName.lStructSize = sizeof(OpenFileName);
|
||||
OpenFileName.hwndOwner = NULL;
|
||||
OpenFileName.lpstrFilter = FilterStrings;
|
||||
OpenFileName.lpstrCustomFilter = NULL; // NOTE(Peter): for preserving last filter string chosen
|
||||
OpenFileName.nMaxCustFilter = 0; // NOTE(Peter): ignored since we left CustomFilter null
|
||||
OpenFileName.nFilterIndex = 1;
|
||||
OpenFileName.lpstrFile = PathBuffer;
|
||||
OpenFileName.nMaxFile = BufferLength;
|
||||
OpenFileName.lpstrFileTitle = NULL;
|
||||
OpenFileName.nMaxFileTitle = 0; // NOTE(Peter): Ignored since fileTitle is null
|
||||
OpenFileName.lpstrInitialDir = NULL;
|
||||
OpenFileName.lpstrTitle = NULL;
|
||||
OpenFileName.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST;
|
||||
OpenFileName.lpstrDefExt = NULL;
|
||||
|
||||
Result = GetOpenFileNameA (&OpenFileName);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
281
interface.h
281
interface.h
|
@ -1,112 +1,27 @@
|
|||
// NOTE(Peter): This stuff was all a test to see how I could do panel splitting. Thinking about moving away
|
||||
// from that for now. Might return later if necessary
|
||||
// TODO(Peter): Finish this if necessary
|
||||
|
||||
struct interface_region
|
||||
internal v2
|
||||
DrawCharacter (render_quad_batch_constructor* BatchConstructor, char C, bitmap_font Font, v2 Position, v4 Color, r32 FontScale)
|
||||
{
|
||||
v2 Min, Max;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
interface_region* A;
|
||||
interface_region* B;
|
||||
};
|
||||
struct
|
||||
{
|
||||
interface_region* Left;
|
||||
interface_region* Right;
|
||||
};
|
||||
struct
|
||||
{
|
||||
interface_region* Top;
|
||||
interface_region* Bottom;
|
||||
};
|
||||
};
|
||||
};
|
||||
s32 GlyphDataIndex = GetIndexForCodepoint(Font, C);
|
||||
codepoint_bitmap CodepointInfo = Font.CodepointValues[GlyphDataIndex];
|
||||
|
||||
struct interface_tracker
|
||||
{
|
||||
memory_arena* Storage;
|
||||
interface_region RootRegion;
|
||||
};
|
||||
r32 MinX = Position.x + CodepointInfo.XOffset * FontScale;
|
||||
r32 MinY = Position.y + CodepointInfo.YOffset * FontScale;
|
||||
r32 MaxX = MinX + (CodepointInfo.Width) * FontScale;
|
||||
r32 MaxY = MinY + (CodepointInfo.Height) * FontScale;
|
||||
|
||||
enum interface_region_split
|
||||
{
|
||||
InterfaceRegionSplit_Vertical,
|
||||
InterfaceRegionSplit_Horizontal,
|
||||
};
|
||||
PushQuad2DOnBatch(BatchConstructor,
|
||||
v2{MinX, MinY}, v2{MaxX, MinY},
|
||||
v2{MaxX, MaxY}, v2{MinX, MaxY},
|
||||
CodepointInfo.UVMin, CodepointInfo.UVMax,
|
||||
Color);
|
||||
|
||||
inline s32
|
||||
RegionWidth (interface_region Region)
|
||||
{
|
||||
s32 Result = Region.Max.x - Region.Min.x;
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline s32
|
||||
RegionHeight (interface_region Region)
|
||||
{
|
||||
s32 Result = Region.Max.y - Region.Min.y;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
SplitRegion (interface_tracker* Tracker, interface_region* Parent, s32 SplitPosition, interface_region_split SplitDirection)
|
||||
{
|
||||
if (!Parent->A)
|
||||
{
|
||||
interface_region* A = PushStruct(Tracker->Storage, interface_region);
|
||||
A->A = 0;
|
||||
A->B = 0;
|
||||
Parent->A = A;
|
||||
}
|
||||
Parent->A->Min = Parent->Min;
|
||||
Parent->A->Max = Parent->Max;
|
||||
|
||||
if (!Parent->B)
|
||||
{
|
||||
interface_region* B = PushStruct(Tracker->Storage, interface_region);
|
||||
B->A = 0;
|
||||
B->B = 0;
|
||||
Parent->B = B;
|
||||
}
|
||||
Parent->B->Min = Parent->Min;
|
||||
Parent->B->Max = Parent->Max;
|
||||
|
||||
switch (SplitDirection)
|
||||
{
|
||||
case InterfaceRegionSplit_Vertical:
|
||||
{
|
||||
Parent->Left->Max.x = Parent->Min.x + SplitPosition;
|
||||
Parent->Right->Min.x = Parent->Min.x + SplitPosition;
|
||||
}break;
|
||||
|
||||
case InterfaceRegionSplit_Horizontal:
|
||||
{
|
||||
Parent->Bottom->Max.y = Parent->Min.y + SplitPosition;
|
||||
Parent->Top->Min.y = Parent->Min.y + SplitPosition;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
internal interface_tracker
|
||||
CreateInterfaceTracker (memory_arena* Storage, s32 ScreenWidth, s32 ScreenHeight)
|
||||
{
|
||||
interface_tracker Result = {};
|
||||
Result.Storage = Storage;
|
||||
Result.RootRegion.A = 0;
|
||||
Result.RootRegion.B = 0;
|
||||
Result.RootRegion.Min = v2{0, 0};
|
||||
Result.RootRegion.Max = v2{(r32)ScreenWidth, (r32)ScreenHeight};
|
||||
return Result;
|
||||
return v2{Position.x + CodepointInfo.Width * FontScale, Position.y};
|
||||
}
|
||||
|
||||
internal v2
|
||||
DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Font, s32 PointSize, v2 Position, v4 Color)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
v2 LowerRight = Position;
|
||||
|
||||
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length,
|
||||
|
@ -122,21 +37,8 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon
|
|||
char* C = String.Memory;
|
||||
for (s32 i = 0; i < String.Length; i++)
|
||||
{
|
||||
s32 GlyphDataIndex = GetIndexForCodepoint(*Font, *C);
|
||||
codepoint_bitmap CodepointInfo = Font->CodepointValues[GlyphDataIndex];
|
||||
|
||||
r32 MinX = RegisterPosition.x + CodepointInfo.XOffset * FontScale;
|
||||
r32 MinY = RegisterPosition.y + CodepointInfo.YOffset * FontScale;
|
||||
r32 MaxX = MinX + (CodepointInfo.Width) * FontScale;
|
||||
r32 MaxY = MinY + (CodepointInfo.Height) * FontScale;
|
||||
|
||||
PushQuad2DOnBatch(&BatchConstructor,
|
||||
v2{MinX, MinY}, v2{MaxX, MinY},
|
||||
v2{MaxX, MaxY}, v2{MinX, MaxY},
|
||||
CodepointInfo.UVMin, CodepointInfo.UVMax,
|
||||
Color);
|
||||
|
||||
RegisterPosition.x += CodepointInfo.Width * FontScale;
|
||||
v2 PositionAfterCharacter = DrawCharacter(&BatchConstructor, *C, *Font, RegisterPosition, Color, FontScale);
|
||||
RegisterPosition.x = PositionAfterCharacter.x;
|
||||
C++;
|
||||
}
|
||||
|
||||
|
@ -145,6 +47,54 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon
|
|||
return LowerRight;
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawCursor (render_quad_batch_constructor* BatchConstructor, v2 Position, v4 Color, bitmap_font Font, r32 FontScale)
|
||||
{
|
||||
v2 Min = Position;
|
||||
v2 Max = Position + v2{(r32)Font.MaxCharWidth * FontScale, Font.Ascent + Font.Descent * FontScale};
|
||||
PushQuad2DOnBatch(BatchConstructor, Min, Max, Color);
|
||||
}
|
||||
|
||||
internal v2
|
||||
DrawStringWithCursor (render_command_buffer* RenderBuffer, string String, s32 CursorPosition, bitmap_font* Font, s32 PointSize, v2 Position, v4 Color, v4 CursorColor)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
v2 LowerRight = Position;
|
||||
|
||||
// NOTE(Peter): We push this on first so that the cursor will be drawn underneath any character it may overlap with
|
||||
render_quad_batch_constructor CursorBatch = PushRenderQuad2DBatch(RenderBuffer, 1);
|
||||
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length,
|
||||
Font->BitmapMemory,
|
||||
Font->BitmapTextureHandle,
|
||||
Font->BitmapWidth,
|
||||
Font->BitmapHeight,
|
||||
Font->BitmapBytesPerPixel,
|
||||
Font->BitmapStride);
|
||||
|
||||
r32 FontScale = (r32)PointSize / Font->PixelHeight;
|
||||
v2 RegisterPosition = Position;
|
||||
char* C = String.Memory;
|
||||
for (s32 i = 0; i < String.Length; i++)
|
||||
{
|
||||
if (i == CursorPosition)
|
||||
{
|
||||
DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font, FontScale);
|
||||
}
|
||||
|
||||
v2 PositionAfterCharacter = DrawCharacter(&BatchConstructor, *C, *Font, RegisterPosition, Color, FontScale);
|
||||
RegisterPosition.x = PositionAfterCharacter.x;
|
||||
C++;
|
||||
}
|
||||
|
||||
if (CursorPosition == String.Length)
|
||||
{
|
||||
DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font, FontScale);
|
||||
}
|
||||
|
||||
LowerRight.x = RegisterPosition.x;
|
||||
return LowerRight;
|
||||
}
|
||||
|
||||
struct interface_config
|
||||
{
|
||||
v4 PanelBGColors[4];
|
||||
|
@ -162,11 +112,17 @@ struct button_result
|
|||
};
|
||||
|
||||
internal button_result
|
||||
EvaluateButton_ (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Label, interface_config Config, input Input, v4 BGColor)
|
||||
EvaluateButton (render_command_buffer* RenderBuffer,
|
||||
v2 Min, v2 Max, v2 Margin, string Label,
|
||||
v4 IdleBGColor, v4 HotBGColor, v4 IdleTextColor, v4 HotTextColor,
|
||||
bitmap_font* Font, input Input)
|
||||
{
|
||||
button_result Result = {};
|
||||
Result.Pressed = false;
|
||||
|
||||
v4 BGColor = IdleBGColor;
|
||||
v4 TextColor = IdleTextColor;
|
||||
|
||||
v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
|
||||
if (PointIsInRange(MousePos, Min, Max))
|
||||
{
|
||||
|
@ -176,21 +132,26 @@ EvaluateButton_ (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Lab
|
|||
}
|
||||
else
|
||||
{
|
||||
BGColor = Config.ButtonColor_Active;
|
||||
BGColor = HotBGColor;
|
||||
TextColor = HotTextColor;
|
||||
}
|
||||
}
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, Min, Max, BGColor);
|
||||
DrawString(RenderBuffer, Label, Config.Font, Config.Font->PixelHeight, Min + Config.Margin, Config.TextColor);
|
||||
DrawString(RenderBuffer, Label, Font, Font->PixelHeight, Min + Margin, TextColor);
|
||||
|
||||
Result.Advance = (Max.y - Min.y) + Config.Margin.y;
|
||||
Result.Advance = (Max.y - Min.y) + Margin.y;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal button_result
|
||||
EvaluateButton (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Label, interface_config Config, input Input)
|
||||
{
|
||||
button_result Result = EvaluateButton_(RenderBuffer, Min, Max, Label, Config, Input, Config.ButtonColor_Inactive);
|
||||
button_result Result = EvaluateButton(RenderBuffer,
|
||||
Min, Max, Config.Margin, Label,
|
||||
Config.ButtonColor_Inactive, Config.ButtonColor_Active,
|
||||
Config.TextColor, Config.TextColor,
|
||||
Config.Font, Input);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -203,7 +164,11 @@ EvaluateSelectableButton (render_command_buffer* RenderBuffer, v2 Min, v2 Max, s
|
|||
BGColor = Config.ButtonColor_Selected;
|
||||
}
|
||||
|
||||
button_result Result = EvaluateButton_(RenderBuffer, Min, Max, Label, Config, Input, BGColor);
|
||||
button_result Result = EvaluateButton(RenderBuffer,
|
||||
Min, Max, Config.Margin, Label,
|
||||
Config.ButtonColor_Inactive, Config.ButtonColor_Active,
|
||||
Config.TextColor, Config.TextColor,
|
||||
Config.Font, Input);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -593,3 +558,79 @@ EvaluateColorPicker (render_command_buffer* RenderBuffer, v4* Value, v2 PanelMin
|
|||
|
||||
return ShouldClose;
|
||||
}
|
||||
|
||||
struct search_lister_result
|
||||
{
|
||||
s32 HotItem;
|
||||
b32 ShouldRemainOpen;
|
||||
};
|
||||
|
||||
typedef char* search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, s32 Offset);
|
||||
|
||||
internal search_lister_result
|
||||
EvaluateSearchLister (render_command_buffer* RenderBuffer, v2 TopLeft, v2 Dimension, string Title,
|
||||
s32 ListLength, u8* ListMemory, s32 HotItem, search_lister_get_list_item_at_offset* GetListItem,
|
||||
string* SearchString, s32 SearchStringCursorPosition,
|
||||
bitmap_font* Font, interface_config Config, input Input)
|
||||
{
|
||||
Assert(GetListItem != 0);
|
||||
|
||||
search_lister_result Result = {};
|
||||
Result.ShouldRemainOpen = true;
|
||||
Result.HotItem = HotItem;
|
||||
|
||||
// NOTE(Peter): These are direction reversed because going up the list in terms of indicies is
|
||||
// visually displayed as going down.
|
||||
if (KeyTransitionedDown(Input, KeyCode_DownArrow))
|
||||
{
|
||||
Result.HotItem = GSMin(Result.HotItem + 1, ListLength - 1);
|
||||
}
|
||||
if (KeyTransitionedDown(Input, KeyCode_UpArrow))
|
||||
{
|
||||
Result.HotItem = GSMax(0, Result.HotItem - 1);
|
||||
}
|
||||
|
||||
// Title Bar
|
||||
PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}, v4{.3f, .3f, .3f, 1.f});
|
||||
DrawString(RenderBuffer, Title, Font, 14, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4);
|
||||
TopLeft.y -= 30;
|
||||
|
||||
// Search Bar
|
||||
PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}, v4{.3f, .3f, .3f, 1.f});
|
||||
DrawStringWithCursor(RenderBuffer, *SearchString, SearchStringCursorPosition, Font, 14, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4, GreenV4);
|
||||
TopLeft.y -= 30;
|
||||
|
||||
s32 VisibleItemIndex = 0;
|
||||
for (s32 i = 0; i < ListLength; i++)
|
||||
{
|
||||
char* ListItemText = GetListItem(ListMemory, ListLength, i);
|
||||
Assert(ListItemText);
|
||||
string ListItemString = MakeStringLiteral(ListItemText);
|
||||
|
||||
if (SearchString->Length == 0 ||
|
||||
StringContainsStringCaseInsensitive(ListItemString, *SearchString))
|
||||
{
|
||||
v2 Min = v2{TopLeft.x, TopLeft.y - 30};
|
||||
v2 Max = Min + Dimension - v2{0, Config.Margin.y};
|
||||
|
||||
v4 ButtonColor = Config.ButtonColor_Inactive;
|
||||
if (VisibleItemIndex == HotItem)
|
||||
{
|
||||
ButtonColor = Config.ButtonColor_Active;
|
||||
}
|
||||
|
||||
button_result Button = EvaluateButton(RenderBuffer, Min, Max, Config.Margin, ListItemString,
|
||||
ButtonColor, ButtonColor, Config.TextColor, Config.TextColor,
|
||||
Config.Font, Input);
|
||||
if (Button.Pressed)
|
||||
{
|
||||
Result.HotItem = i;
|
||||
}
|
||||
|
||||
TopLeft.y -= 30;
|
||||
VisibleItemIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// This file left empty for SwD Kraftwerks
|
||||
|
||||
|
||||
NODE_STRUCT(swd_color_data)
|
||||
{
|
||||
NODE_IN(v4, Color);
|
||||
NODE_IN(v4, ColorB);
|
||||
NODE_COLOR_BUFFER_INOUT;
|
||||
};
|
||||
|
||||
NODE_PROC(SwdColorProc, swd_color_data)
|
||||
{
|
||||
u8 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f);
|
||||
u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f);
|
||||
u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f);
|
||||
|
||||
led* LED = Data->LEDs;
|
||||
for (s32 l = 0; l < Data->LEDCount; l++)
|
||||
{
|
||||
Assert(LED->Index >= 0 && LED->Index < Data->LEDCount);
|
||||
|
||||
Data->Colors[LED->Index].R = R;
|
||||
Data->Colors[LED->Index].G = R;
|
||||
Data->Colors[LED->Index].B = R;
|
||||
LED++;
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
pattern_registry_entry PatternRegistry[] =
|
||||
{
|
||||
{"Solid", SolidPatternInitProc, SolidPatternUpdateProc},
|
||||
{"Rainbow", InitRainbowPatternProc, RainbowPatternProc},
|
||||
{"Radial", InitRadialProc, UpdateRadialProc},
|
||||
};
|
244
test_patterns.h
244
test_patterns.h
|
@ -1,13 +1,3 @@
|
|||
NODE_STRUCT(float_value_data)
|
||||
{
|
||||
NODE_IN(r32, Value);
|
||||
NODE_OUT(r32, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(FloatValueProc, float_value_data)
|
||||
{
|
||||
Data->Result = Data->Value;
|
||||
}
|
||||
|
||||
NODE_STRUCT(solid_color_data)
|
||||
{
|
||||
|
@ -33,85 +23,6 @@ NODE_PROC(SolidColorProc, solid_color_data)
|
|||
}
|
||||
}
|
||||
|
||||
NODE_STRUCT(sin_wave_data)
|
||||
{
|
||||
NODE_IN(r32, Period);
|
||||
NODE_IN(r32, Min);
|
||||
NODE_IN(r32, Max);
|
||||
NODE_OUT(r32, Result);
|
||||
|
||||
r32 Accumulator;
|
||||
};
|
||||
|
||||
NODE_PROC(SinWaveProc, sin_wave_data)
|
||||
{
|
||||
Data->Accumulator += DeltaTime;
|
||||
if (Data->Period > 0)
|
||||
{
|
||||
while (Data->Accumulator > Data->Period)
|
||||
{
|
||||
Data->Accumulator -= Data->Period;
|
||||
}
|
||||
|
||||
r32 ActualMin = GSMin(Data->Min, Data->Max);
|
||||
r32 ActualMax = GSMax(Data->Min, Data->Max);
|
||||
r32 SinResult = GSSin((Data->Accumulator / Data->Period) * PI * 2);
|
||||
Data->Result = GSRemap(SinResult, -1.f, 1.f, ActualMin, ActualMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data->Result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NODE_STRUCT(vector_data)
|
||||
{
|
||||
NODE_IN(r32, X);
|
||||
NODE_IN(r32, Y);
|
||||
NODE_IN(r32, Z);
|
||||
NODE_IN(r32, W);
|
||||
NODE_OUT(v4, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(VectorProc, vector_data)
|
||||
{
|
||||
Data->Result = v4{Data->X, Data->Y, Data->Z, Data->W};
|
||||
}
|
||||
|
||||
NODE_STRUCT(multiply_patterns_data)
|
||||
{
|
||||
NODE_COLOR_BUFFER_IN(A);
|
||||
NODE_COLOR_BUFFER_IN(B);
|
||||
NODE_COLOR_BUFFER_OUT(Result);
|
||||
};
|
||||
|
||||
NODE_PROC(MultiplyPatterns, multiply_patterns_data)
|
||||
{
|
||||
led* LED = Data->ResultLEDs;
|
||||
for (s32 l = 0; l < Data->ResultLEDCount; l++)
|
||||
{
|
||||
Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount);
|
||||
|
||||
s32 AR = Data->AColors[LED->Index].R;
|
||||
s32 AG = Data->AColors[LED->Index].G;
|
||||
s32 AB = Data->AColors[LED->Index].B;
|
||||
|
||||
s32 BR = Data->BColors[LED->Index].R;
|
||||
s32 BG = Data->BColors[LED->Index].G;
|
||||
s32 BB = Data->BColors[LED->Index].B;
|
||||
|
||||
s32 RCombined = (AR * BR) / 255;
|
||||
s32 GCombined = (AG * BG) / 255;
|
||||
s32 BCombined = (AB * BB) / 255;
|
||||
|
||||
Data->ResultColors[LED->Index].R = (u8)RCombined;
|
||||
Data->ResultColors[LED->Index].G = (u8)GCombined;
|
||||
Data->ResultColors[LED->Index].B = (u8)BCombined;
|
||||
|
||||
LED++;
|
||||
}
|
||||
}
|
||||
|
||||
NODE_STRUCT(vertical_color_fade_data)
|
||||
{
|
||||
NODE_IN(v4, Color);
|
||||
|
@ -143,114 +54,77 @@ NODE_PROC(VerticalColorFadeProc, vertical_color_fade_data)
|
|||
}
|
||||
}
|
||||
|
||||
// ^^^ New ^^^
|
||||
// vvv Old vvv
|
||||
|
||||
PATTERN_INIT_PROC(SolidPatternInitProc)
|
||||
// Original -> DiscPatterns.pde : Revolving Discs
|
||||
NODE_STRUCT(revolving_discs_data)
|
||||
{
|
||||
Pattern->Memory = (void*)PushArray(Storage, u8, 3);
|
||||
|
||||
u8* Color = (u8*)Pattern->Memory;
|
||||
Color[0] = 0;
|
||||
Color[1] = 0;
|
||||
Color[2] = 128;
|
||||
}
|
||||
|
||||
PATTERN_UPDATE_PROC(SolidPatternUpdateProc)
|
||||
{
|
||||
u8* Color = (u8*)Memory;
|
||||
u8 R = Color[0];
|
||||
u8 G = Color[1];
|
||||
u8 B = Color[2];
|
||||
|
||||
led* LED = LEDs;
|
||||
for (s32 l = 0; l < LEDCount; l++)
|
||||
{
|
||||
PushColor(LED++, Colors, R, G, B);
|
||||
}
|
||||
}
|
||||
|
||||
struct rainbow_pattern_memory
|
||||
{
|
||||
r32 TimeAccumulator;
|
||||
r32 Period;
|
||||
NODE_IN(r32, Rotation);
|
||||
NODE_IN(r32, ThetaZ);
|
||||
NODE_IN(r32, ThetaY);
|
||||
NODE_IN(r32, DiscWidth);
|
||||
NODE_IN(r32, InnerRadius);
|
||||
NODE_IN(r32, OuterRadius);
|
||||
NODE_IN(v4, Color);
|
||||
NODE_COLOR_BUFFER_OUT(Result);
|
||||
};
|
||||
|
||||
PATTERN_INIT_PROC(InitRainbowPatternProc)
|
||||
NODE_PROC(RevolvingDiscs, revolving_discs_data)
|
||||
{
|
||||
Pattern->Memory = (void*)PushStruct(Storage, rainbow_pattern_memory);
|
||||
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Pattern->Memory;
|
||||
Mem->TimeAccumulator = 0;
|
||||
Mem->Period = 6.0f;
|
||||
}
|
||||
sacn_pixel Color = PackFloatsToSACNPixel(Data->Color.r, Data->Color.g, Data->Color.b);
|
||||
|
||||
PATTERN_UPDATE_PROC(RainbowPatternProc)
|
||||
{
|
||||
DEBUG_TRACK_SCOPE(RainbowPatternProc);
|
||||
v3 Center = v3{0, 0, 0};
|
||||
v3 Normal = v3{GSCos(Data->ThetaZ), 0, GSSin(Data->ThetaZ)}; // NOTE(Peter): dont' need to normalize. Should always be 1
|
||||
v3 Right = Cross(Normal, v3{0, 1, 0});
|
||||
//Normal = RotateAround(Data->ThetaY, Right);
|
||||
|
||||
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Memory;
|
||||
Mem->TimeAccumulator += DeltaTime;
|
||||
if (Mem->TimeAccumulator >= Mem->Period)
|
||||
v3 FrontCenter = Center + (Normal * Data->DiscWidth);
|
||||
v3 BackCenter = Center - (Normal * Data->DiscWidth);
|
||||
|
||||
led* LED = Data->ResultLEDs;
|
||||
for (s32 l = 0; l < Data->ResultLEDCount; l++)
|
||||
{
|
||||
Mem->TimeAccumulator -= Mem->Period;
|
||||
}
|
||||
v3 Position = LED->Position;
|
||||
|
||||
r32 Percent = Mem->TimeAccumulator / Mem->Period;
|
||||
r32 HueAdd = Percent * 360.0f;
|
||||
v3 ToFront = Normalize(Position + FrontCenter);
|
||||
v3 ToBack = Normalize(Position + BackCenter);
|
||||
|
||||
r32 HueScale = 360.0f / 100;
|
||||
r32 ToFrontDotNormal = Dot(ToFront, Normal);
|
||||
r32 ToBackDotNormal = Dot(ToBack, Normal);
|
||||
|
||||
led* LED = LEDs;
|
||||
for (s32 l = 0; l < LEDCount; l++)
|
||||
{
|
||||
r32 Hue = (LED->Position.y * HueScale) + HueAdd;
|
||||
v4 Color = HSVToRGB(v4{Hue, 1, 1, 1}) * .75f;
|
||||
ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000);
|
||||
ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000);
|
||||
|
||||
PushColor(LED++, Colors, (u8)(Color.r * 255), (u8)(Color.g * 255), (u8)(Color.b * 255));
|
||||
}
|
||||
}
|
||||
|
||||
PATTERN_INIT_PROC(InitRadialProc)
|
||||
{
|
||||
Pattern->Memory = (void*)PushStruct(Storage, rainbow_pattern_memory);
|
||||
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Pattern->Memory;
|
||||
Mem->TimeAccumulator = 0;
|
||||
Mem->Period = 10.0;
|
||||
}
|
||||
|
||||
PATTERN_UPDATE_PROC(UpdateRadialProc)
|
||||
{
|
||||
|
||||
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Memory;
|
||||
Mem->TimeAccumulator += DeltaTime;
|
||||
if (Mem->TimeAccumulator >= Mem->Period)
|
||||
{
|
||||
Mem->TimeAccumulator -= Mem->Period;
|
||||
}
|
||||
|
||||
r32 Percent = Mem->TimeAccumulator / Mem->Period;
|
||||
r32 AngleAdd = Percent * PI * 2;
|
||||
r32 HueAdd = Percent * 360;
|
||||
|
||||
v2 DirectionVector = v2{GSSin(AngleAdd), GSCos(AngleAdd)};
|
||||
|
||||
led* LED = LEDs;
|
||||
for (s32 l = 0; l < LEDCount; l++)
|
||||
{
|
||||
v4 Color = {0, 0, 0, 1};
|
||||
|
||||
if (LED->Position.y >= 70)
|
||||
r32 DistToCenter = Mag(Position);
|
||||
if (DistToCenter < Data->OuterRadius && DistToCenter > Data->InnerRadius)
|
||||
{
|
||||
v2 TwoDPos = v2{LED->Position.x, LED->Position.z};
|
||||
r32 Angle = Dot(Normalize(TwoDPos), DirectionVector) * .25f;
|
||||
r32 Hue = Angle * 360 + HueAdd;
|
||||
Color = HSVToRGB(v4{Hue, 1, 1, 1}) * .9f;
|
||||
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
|
||||
{
|
||||
Data->ResultColors[LED->Index] = Color;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Color = HSVToRGB(v4{HueAdd, 1, 1, 1}) * .9f;
|
||||
}
|
||||
|
||||
PushColor(LED++, Colors, (u8)(Color.r * 255), (u8)(Color.g * 255), (u8)(Color.b * 255));
|
||||
LED++;
|
||||
}
|
||||
}
|
||||
|
||||
NODE_STRUCT(michelle_data)
|
||||
{
|
||||
NODE_IN(v4, Color);
|
||||
NODE_COLOR_BUFFER_INOUT;
|
||||
};
|
||||
|
||||
NODE_PROC(MichelleColorProc, michelle_data)
|
||||
{
|
||||
u8 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f);
|
||||
u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f);
|
||||
u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f);
|
||||
|
||||
led* LED = Data->LEDs;
|
||||
for (s32 l = 0; l < Data->LEDCount; l++)
|
||||
{
|
||||
Assert(LED->Index >= 0 && LED->Index < Data->LEDCount);
|
||||
|
||||
Data->Colors[LED->Index].R = R;
|
||||
Data->Colors[LED->Index].G = G;
|
||||
Data->Colors[LED->Index].B = B;
|
||||
LED++;
|
||||
}
|
||||
}
|
21
todo.txt
21
todo.txt
|
@ -1,9 +1,15 @@
|
|||
TODO FOLDHAUS
|
||||
|
||||
Hardening
|
||||
- input context changes
|
||||
- x don't type into the search bar when its not open
|
||||
- x don't type into the search bar when you press a to open it
|
||||
- - type into text boxes
|
||||
- - shift drag to 10x drag speed
|
||||
- select nodes -> delete nodes
|
||||
|
||||
Name
|
||||
x lumen lab
|
||||
- Splash screen (like blender) (thisll be fun)
|
||||
- x Create Image
|
||||
- - Image importer (stb image? or find a png > bmp converter for the image you have)
|
||||
- - Display on startup
|
||||
|
||||
|
@ -14,12 +20,8 @@ x Keep an eye out.
|
|||
Application
|
||||
- More efficient HSV <-> RGB
|
||||
|
||||
x Load/Unload sculptures
|
||||
- - Make sure that we offload unloading until after all jobs are completed. Otherwise they'll try and write
|
||||
- to data that doesn't exist
|
||||
- Save and load a session
|
||||
- - Serialize Channels
|
||||
- - Serialize Patterns
|
||||
- - Serialize Nodes
|
||||
- Don't render if the window isn't visible
|
||||
|
||||
Development
|
||||
|
@ -39,7 +41,6 @@ Interface
|
|||
Switch To Nodes
|
||||
x basic node elements
|
||||
- - evaluation step (one node at a time)
|
||||
- - search nodes by name
|
||||
- - selector node (has a list of connections that it can switch between)
|
||||
- serialize
|
||||
- delete nodes
|
||||
|
@ -68,10 +69,6 @@ Animation
|
|||
|
||||
Command Line
|
||||
- select a channel/pattern
|
||||
- Channel: Add/remove pattern by name
|
||||
- Channel: Set Blend Mode
|
||||
- Channel: Set Current Pattern
|
||||
- Pattern: Edit parameter values
|
||||
|
||||
Optimization
|
||||
- patterns are asking to be multithreaded
|
||||
|
|
|
@ -394,9 +394,12 @@ HandleWindowMessage (MSG Message, window* Window, input_frame* InputFrame)
|
|||
{
|
||||
int VirtualKey = (int)Message.wParam;
|
||||
bool KeyDown = (Message.lParam & (1 << 31)) == 0;
|
||||
int KeyIndex = Win32GetKeyIndex(VirtualKey, true, false);
|
||||
int KeyIndex = Win32GetKeyIndex(VirtualKey, true, true);
|
||||
if (KeyIndex == WIN32_SHOULD_TRANSLATE_TO_CHAR)
|
||||
{
|
||||
KeyIndex = Win32GetKeyIndex(VirtualKey, true, false);
|
||||
InputFrame->KeysDown[KeyIndex] = KeyDown;
|
||||
|
||||
TranslateMessage(&Message);
|
||||
DispatchMessage(&Message);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue