Removed Patterns and Channels, rebuilt the file open dialog box, and began implementing a basic text entry system.

This commit is contained in:
Peter Slattery 2019-08-18 14:56:18 +02:00
parent d67d041b21
commit 8040479379
27 changed files with 846 additions and 1474 deletions

View File

@ -18,8 +18,7 @@ pushd build
del *.pdb > NUL 2> NUL del *.pdb > NUL 2> NUL
REM Compile and Run the Preprocessor REM Run the Preprocessor
REM cl %CommonCompilerFlags% ..\meta\foldhaus_meta.cpp /link %CommonLinkerFlags%
pushd ..\src\ pushd ..\src\
..\build\foldhaus_meta.exe C:\projects\foldhaus\src\ ..\build\foldhaus_meta.exe C:\projects\foldhaus\src\
popd 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 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 -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 popd

View File

@ -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) RELOAD_STATIC_DATA(ReloadStaticData)
{ {
app_state* State = (app_state*)Context.MemoryBase; app_state* State = (app_state*)Context.MemoryBase;
@ -395,13 +344,14 @@ RELOAD_STATIC_DATA(ReloadStaticData)
if (State->InputCommandRegistry.Size > 0) if (State->InputCommandRegistry.Size > 0)
{ {
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_Delete, false, KeyCode_Invalid,
DeleteSelectedChannelOrPattern);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_MouseLeftButton, true, KeyCode_Invalid, RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_MouseLeftButton, true, KeyCode_Invalid,
CameraMouseControl); CameraMouseControl);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_U, false, KeyCode_Invalid, ToggleUniverseDebugView); RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_U, false, KeyCode_Invalid, ToggleUniverseDebugView);
RegisterMouseWheelCommand(&State->InputCommandRegistry, CameraMouseZoom); RegisterMouseWheelCommand(&State->InputCommandRegistry, CameraMouseZoom);
RegisterKeyPressCommand(&State->InputCommandRegistry, KeyCode_A, false, KeyCode_Invalid, AddNode); 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); 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->InputCommandRegistry, 32, State->Permanent);
InitializeInputCommandRegistry(&State->TextEntryCommandRegistry, 32, State->Permanent);
State->ActiveCommands = &State->InputCommandRegistry;
// TODO(Peter): put in InitializeInterface? // TODO(Peter): put in InitializeInterface?
r32 FontSize = 14; r32 FontSize = 14;
@ -498,11 +446,6 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->Camera.Position = v3{0, 0, -250}; State->Camera.Position = v3{0, 0, -250};
State->Camera.LookAt = v3{0, 0, 0}; 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 #if 1
char Path[] = "radialumia.fold"; char Path[] = "radialumia.fold";
LoadAssembly(State, Context, Path); LoadAssembly(State, Context, Path);
@ -533,6 +476,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->OutputNode = PushOutputNodeOnList(State->NodeList, v2{500, 250}, State->Permanent); 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); ReloadStaticData(Context, GlobalDebugServices);
} }
@ -546,14 +492,21 @@ UPDATE_AND_RENDER(UpdateAndRender)
// incorrect to clear the arena, and then access the memory later. // incorrect to clear the arena, and then access the memory later.
ClearArena(State->Transient); 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);
if (State->LEDBufferList)
{
UpdateOutputNodeCalculations(State->OutputNode, State->NodeList, UpdateOutputNodeCalculations(State->OutputNode, State->NodeList,
State->Permanent, State->Transient, State->Permanent, State->Transient,
State->LEDBufferList->LEDs, State->LEDBufferList->LEDs,
State->LEDBufferList->Colors, State->LEDBufferList->Colors,
State->LEDBufferList->Count, State->LEDBufferList->Count,
Context.DeltaTime); Context.DeltaTime);
}
ClearTransientNodeColorBuffers(State->NodeList); ClearTransientNodeColorBuffers(State->NodeList);
@ -691,7 +644,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
{ {
DEBUG_TRACK_SCOPE(DrawUniverseOutputDisplay); 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 DisplayArea_Dimension = v2{600, 600};
v2 DisplayContents_Offset = State->UniverseOutputDisplayOffset; v2 DisplayContents_Offset = State->UniverseOutputDisplayOffset;
@ -772,7 +725,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
if (LoadAssemblyBtn.Pressed) if (LoadAssemblyBtn.Pressed)
{ {
char FilePath[256]; char FilePath[256];
b32 Success = Context.PlatformGetFilePath(FilePath, 256); b32 Success = Context.PlatformGetFilePath(FilePath, 256, "Foldhaus Files\0*.fold\0\0");
if (Success) if (Success)
{ {
LoadAssembly(State, Context, FilePath); LoadAssembly(State, Context, FilePath);
@ -783,6 +736,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
/////////////////////////////////////// ///////////////////////////////////////
// Figuring Out Nodes // Figuring Out Nodes
////////////////////////////////////// //////////////////////////////////////
if (State->NodeRenderSettings.Display)
{ {
v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY}; v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
v2 LastFrameMousePos = v2{(r32)Input.Old->MouseX, (r32)Input.Old->MouseY}; v2 LastFrameMousePos = v2{(r32)Input.Old->MouseX, (r32)Input.Old->MouseY};
@ -817,33 +771,35 @@ UPDATE_AND_RENDER(UpdateAndRender)
if (State->InterfaceShowNodeList) if (State->InterfaceShowNodeList)
{ {
v2 TopLeft = State->NodeListMenuPosition; v2 TopLeft = State->NodeListMenuPosition;
v2 Dimension = v2{300, 30};
// Title Bar search_lister_result NodeListResult = EvaluateSearchLister (RenderBuffer, TopLeft, Dimension,
PushRenderQuad2D(RenderBuffer, v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}, MakeStringLiteral("Nodes List"),
v4{.3f, .3f, .3f, 1.f}); NodeSpecificationsCount, (u8*)NodeSpecifications,
DrawString(RenderBuffer, MakeStringLiteral("Nodes List"), State->Font, 14, State->GeneralPurposeSearchHotItem,
v2{TopLeft.x, TopLeft.y - 25}, WhiteV4); NodeListerGetNodeName,
TopLeft.y -= 30; &State->GeneralPurposeSearch.Buffer,
State->GeneralPurposeSearch.CursorPosition,
for (s32 i = 0; i < NodeSpecificationsCount; i++) State->Font, State->Interface, Input);
{ State->GeneralPurposeSearchHotItem = NodeListResult.HotItem;
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;
}
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton) || if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton) ||
KeyTransitionedDown(Input, KeyCode_Esc)) KeyTransitionedDown(Input, KeyCode_Esc))
{ {
State->InterfaceShowNodeList = false; 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, DrawDebugInterface(RenderBuffer, 25,
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
Context.DeltaTime, State->Camera, Input, State->Transient); Context.DeltaTime, State->Camera, Input, State->Transient);

View File

@ -40,21 +40,10 @@ struct assembly
}; };
#include "assembly_parser.h" #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_node.h"
#include "foldhaus_patterns.h"
#include "foldhaus_channel.h"
#include "foldhaus_patterns.cpp"
#include "foldhaus_channel.cpp"
#include "assembly_parser.cpp" #include "assembly_parser.cpp"
#include "test_patterns.h" #include "test_patterns.h"
#include "patterns_registry.h" #include "kraftwerks_patterns.h"
#include "foldhaus_interface.h" #include "foldhaus_interface.h"
typedef struct app_state app_state; typedef struct app_state app_state;
@ -62,6 +51,9 @@ typedef struct app_state app_state;
#include "foldhaus_debug_visuals.h" #include "foldhaus_debug_visuals.h"
#include "foldhaus_command_dispatch.h" #include "foldhaus_command_dispatch.h"
#include "foldhaus_text_entry.h"
#include "foldhaus_default_nodes.h"
#include "generated/foldhaus_nodes_generated.cpp" #include "generated/foldhaus_nodes_generated.cpp"
struct app_state struct app_state
@ -70,13 +62,18 @@ struct app_state
memory_arena* Transient; memory_arena* Transient;
memory_arena SACNMemory; memory_arena SACNMemory;
/*
render_texture* LoadedTextures; render_texture* LoadedTextures;
s32 LoadedTexturesSize; s32 LoadedTexturesSize;
s32 LoadedTexturesUsed; s32 LoadedTexturesUsed;
*/
camera Camera; camera Camera;
input_command_registry InputCommandRegistry; input_command_registry InputCommandRegistry;
input_command_registry TextEntryCommandRegistry;
input_command_registry* ActiveCommands;
text_input* ActiveTextEntry;
streaming_acn SACN; streaming_acn SACN;
s32 TotalLEDsCount; s32 TotalLEDsCount;
@ -89,10 +86,6 @@ struct app_state
assembly AssemblyList[ASSEMBLY_LIST_LENGTH]; assembly AssemblyList[ASSEMBLY_LIST_LENGTH];
s32 AssembliesUsed; s32 AssembliesUsed;
//environment Environment;
led_channel_system ChannelSystem;
led_pattern_system PatternSystem;
bitmap_font* Font; bitmap_font* Font;
interface_state InterfaceState; interface_state InterfaceState;
interface_config Interface; interface_config Interface;
@ -114,9 +107,14 @@ struct app_state
interface_node* OutputNode; interface_node* OutputNode;
v4* ColorPickerEditValue; v4* ColorPickerEditValue;
text_input GeneralPurposeSearch;
s32 GeneralPurposeSearchHotItem;
}; };
#include "foldhaus_sacn_view.cpp" #include "foldhaus_sacn_view.cpp"
#include "foldhaus_command_dispatch.cpp" #include "foldhaus_command_dispatch.cpp"
#include "foldhaus_node.cpp" #include "foldhaus_node.cpp"
#include "foldhaus_text_entry.cpp"
#include "foldhaus_interface.cpp" #include "foldhaus_interface.cpp"

View File

@ -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;
}

View File

@ -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;
};

View File

@ -8,7 +8,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient); 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) if (GlobalDebugServices->Interface.ShowCameraMouse || GlobalDebugServices->Interface.ShowTrackedScopes)
{ {

137
foldhaus_default_nodes.h Normal file
View File

@ -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++;
}
}

View File

@ -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) FOLDHAUS_INPUT_COMMAND_PROC(CameraMouseControl)
{ {
if (State->NodeInteraction.NodeOffset >= 0) { return; } if (State->NodeInteraction.NodeOffset >= 0) { return; }
@ -275,4 +54,10 @@ FOLDHAUS_INPUT_COMMAND_PROC(AddNode)
{ {
State->InterfaceShowNodeList = true; State->InterfaceShowNodeList = true;
State->NodeListMenuPosition = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY}; 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;
} }

View File

@ -79,6 +79,7 @@ BootstrapRegionOntoMemory (u8* Memory, s32 Size)
Result->Base = Memory + sizeof(memory_region); Result->Base = Memory + sizeof(memory_region);
Result->Size = Size - sizeof(memory_region); Result->Size = Size - sizeof(memory_region);
Result->Used = 0; Result->Used = 0;
Result->PreviousRegion = 0;
return Result; 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 // 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. // the arena access to the rest of the block to use.
memory_arena* Result = (memory_arena*)Memory; memory_arena* Result = (memory_arena*)Memory;
*Result = {};
InitMemoryArena(Result, Memory + sizeof(memory_arena), Size - sizeof(memory_arena), 0); InitMemoryArena(Result, Memory + sizeof(memory_arena), Size - sizeof(memory_arena), 0);
return Result; return Result;
} }
@ -251,6 +253,37 @@ ClearArenaToSnapshot (memory_arena* Arena, arena_snapshot Snapshot)
RegionCursor->Used = Snapshot.UsedAtSnapshot; 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 // Tracked Array Implementation
// //

View File

@ -1,3 +1,4 @@
inline s32 inline s32
GetNodeMemorySize (interface_node Node) GetNodeMemorySize (interface_node Node)
{ {
@ -125,15 +126,22 @@ InitializeNodeConnection (node_connection* Connection, struct_member_type Type,
} }
} }
internal void internal r32
PushNodeOnListFromSpecification (node_list* List, node_specification Spec, v2 Min, memory_arena* Storage) 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, interface_node* Node = PushNodeOnList(List,
Spec.NameLength, Spec.NameLength,
Spec.MemberListLength, Spec.MemberListLength,
Min, Min,
v2{150, 150}, v2{150, NodeHeight},
Storage); Storage);
Node->Type = Spec.Type; 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); InitializeNodeConnection(Node->Connections + MemberIdx, Member.Type, Member.IsInput);
} }
Node->PersistentData = PushArray(Storage, u8, Spec.DataStructSize);
} }
internal interface_node* internal interface_node*
@ -182,18 +191,6 @@ GetNodeAtOffset (node_list* List, s32 Offset)
return Node; 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 internal rect
CalculateNodeBounds (interface_node* Node, node_render_settings Settings) CalculateNodeBounds (interface_node* Node, node_render_settings Settings)
{ {
@ -273,6 +270,18 @@ CalculateNodeDragHandleBounds (rect NodeBounds, s32 Index, node_render_settings
return Result; 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 internal b32
IsDraggingNode (node_interaction Interaction) IsDraggingNode (node_interaction Interaction)
{ {
@ -658,7 +667,7 @@ PlaceNode (node_list* NodeList, interface_node* Node, v2 Position, b32 Flags)
v2 NewPos = CurrPos + Offset; v2 NewPos = CurrPos + Offset;
// NOTE(Peter): Have to negate the all downstream component so it doesn't turn around and try // NOTE(Peter): Have to negate the all downstream component so it doesn't turn around and try
// to move this node again. // 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; v2 NewPos = CurrPos + Offset;
// NOTE(Peter): Have to negate the all upstream component so it doesn't turn around and try // NOTE(Peter): Have to negate the all upstream component so it doesn't turn around and try
// to move this node again. // 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) led* LEDs, sacn_pixel* ColorsInit, s32 LEDCount, r32 DeltaTime)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
Assert(Node->PersistentData != 0);
// NOTE(Peter): Have to subtract one here so that we account for the // NOTE(Peter): Have to subtract one here so that we account for the
// NodeType_OutputNode entry in the enum // NodeType_OutputNode entry in the enum
@ -839,12 +849,6 @@ UpdateNodeCalculation (interface_node* Node, node_list* NodeList,
sacn_pixel* Colors = ColorsInit; 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); UpdateNodesConnectedUpstream(Node, NodeList, Permanent, Transient, LEDs, Colors, LEDCount, DeltaTime);
for (s32 ConnectionIdx = 0; ConnectionIdx < Node->ConnectionsCount; ConnectionIdx++) 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;
}

View File

@ -155,6 +155,7 @@ struct node_render_settings
r32 PortStep; r32 PortStep;
v4 PortColors[MemberTypeCount]; v4 PortColors[MemberTypeCount];
bitmap_font* Font; bitmap_font* Font;
b32 Display;
}; };
v4 DragButtonColors[] = { v4 DragButtonColors[] = {

View File

@ -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);
}
}

View File

@ -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;
};

View File

@ -139,6 +139,16 @@ struct sacn_pixel
u8 B; 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* internal sacn_universe*

63
foldhaus_text_entry.cpp Normal file
View File

@ -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);
}
}

7
foldhaus_text_entry.h Normal file
View File

@ -0,0 +1,7 @@
struct text_input
{
char* Backbuffer;
string Buffer;
s32 CursorPosition;
input_command_registry* PreviousCommandRegistry;
};

View File

@ -1,17 +1,33 @@
enum node_type enum node_type
{ {
NodeType_OutputNode, NodeType_OutputNode,
NodeType_FloatValue,
NodeType_VectorValue,
NodeType_MultiplyNodeProc, NodeType_MultiplyNodeProc,
NodeType_AddNodeProc, NodeType_AddNodeProc,
NodeType_FloatValueProc, NodeType_SinWave,
NodeType_SolidColorProc,
NodeType_SinWaveProc,
NodeType_VectorProc,
NodeType_MultiplyPatterns, NodeType_MultiplyPatterns,
NodeType_SwdColorProc,
NodeType_SolidColorProc,
NodeType_VerticalColorFadeProc, NodeType_VerticalColorFadeProc,
NodeType_RevolvingDiscs,
NodeType_MichelleColorProc,
NodeType_Count, 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[] = { node_struct_member MemberList_multiply_data[] = {
{ MemberType_r32, "A", (u64)&((multiply_data*)0)->A, IsInputMember }, { MemberType_r32, "A", (u64)&((multiply_data*)0)->A, IsInputMember },
{ MemberType_r32, "B", (u64)&((multiply_data*)0)->B, 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}, { 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[] = { node_struct_member MemberList_sin_wave_data[] = {
{ MemberType_r32, "Period", (u64)&((sin_wave_data*)0)->Period, IsInputMember }, { MemberType_r32, "Period", (u64)&((sin_wave_data*)0)->Period, IsInputMember },
{ MemberType_r32, "Min", (u64)&((sin_wave_data*)0)->Min, 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}, { 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[] = { node_struct_member MemberList_multiply_patterns_data[] = {
{ MemberType_NODE_COLOR_BUFFER, "ALEDs", (u64)&((multiply_patterns_data*)0)->ALEDs, IsInputMember }, { 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, "BLEDs", (u64)&((multiply_patterns_data*)0)->BLEDs, IsInputMember },
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((multiply_patterns_data*)0)->ResultLEDs, IsOutputMember}, { 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[] = { node_struct_member MemberList_vertical_color_fade_data[] = {
{ MemberType_v4, "Color", (u64)&((vertical_color_fade_data*)0)->Color, IsInputMember }, { MemberType_v4, "Color", (u64)&((vertical_color_fade_data*)0)->Color, IsInputMember },
{ MemberType_r32, "Min", (u64)&((vertical_color_fade_data*)0)->Min, 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}, { 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[] = { 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_MultiplyNodeProc, "MultiplyNodeProc", 16, MemberList_multiply_data, 12, 3, false},
{ NodeType_AddNodeProc, "AddNodeProc", 11, MemberList_add_data, 48, 3, false}, { NodeType_AddNodeProc, "AddNodeProc", 11, MemberList_add_data, 48, 3, false},
{ NodeType_FloatValueProc, "FloatValueProc", 14, MemberList_float_value_data, 8, 2, false}, { NodeType_SinWave, "SinWave", 7, MemberList_sin_wave_data, 20, 4, 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_MultiplyPatterns, "MultiplyPatterns", 16, MemberList_multiply_patterns_data, 60, 3, 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_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) internal void CallNodeProc(interface_node* Node, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)
{ {
switch (Node->Type) 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_MultiplyNodeProc: { MultiplyNodeProc((multiply_data*)Data, DeltaTime); } break;
case NodeType_AddNodeProc: { AddNodeProc((add_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_SinWave: { SinWave((sin_wave_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_MultiplyPatterns: { MultiplyPatterns((multiply_patterns_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_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;
} }
} }

View File

@ -171,6 +171,11 @@ GSMaxDef(r32)
GSMaxDef(r64) GSMaxDef(r64)
#undef GSMaxDef #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) { \ #define GSClampDef(type) static type GSClamp(type Min, type V, type Max) { \
type Result = V; \ type Result = V; \
if (V < Min) { Result = Min; } \ if (V < Min) { Result = Min; } \

View File

@ -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) #define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(char* Path, u8* Contents, s32 Size)
typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); 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); typedef PLATFORM_GET_FILE_PATH(platform_get_file_path);
#define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) #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]; return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key];
} }
#endif // GS_INPUT #endif // GS_INPUT
internal window PlatformCreateWindow (char* Name, s32 Width, s32 Height); internal window PlatformCreateWindow (char* Name, s32 Width, s32 Height);

View File

@ -1,3 +1,4 @@
#ifndef GS_STRING_H
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// String // String
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -98,9 +99,7 @@ char* TokenNames[] = {
struct token struct token
{ {
token_type Type; token_type Type;
char* Text; string Text;
s32 TextLength;
token* Next; 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; #define PushString(str, arena, size) (str)->Memory = PushArray(arena, char, size); (str)->Length = 0; (str)->Max = size;
#endif #endif
static void InitializeString (string* String, char* Data, s32 DataSize); static void InitializeEmptyString (string* String, char* Data, s32 DataSize);
static string InitializeString (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); static void ClearString (string* String);
// Character Values // Character Values
@ -161,12 +162,13 @@ static bool IsWhitespace (char C);
static bool IsAlpha (char C); static bool IsAlpha (char C);
static bool IsUpper (char C); static bool IsUpper (char C);
static bool IsLower (char C); static bool IsLower (char C);
static char ToUpper (char C);
static char ToLower (char C);
static bool IsNumeric (char C); static bool IsNumeric (char C);
static bool IsNumericExtended (char C); static bool IsNumericExtended (char C);
static bool ToUpper (char C);
static bool ToLower (char C);
static bool IsAlphaNumeric (char C); static bool IsAlphaNumeric (char C);
static bool IsOperator (char C); static bool IsOperator (char C);
static bool CharsEqualCaseInsensitive(char A, char B);
// Tokenizing // Tokenizing
static b32 AtValidPosition(tokenizer Tokenizer); 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, s32 End);
static string Substring (string* String, s32 Start); 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); static void NullTerminate (string* String);
@ -339,15 +346,23 @@ GSPow (float N, s32 Power)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
static void static void
InitializeString (string* String, char* Data, s32 DataSize) InitializeEmptyString (string* String, char* Data, s32 DataSize)
{ {
String->Memory = Data; String->Memory = Data;
String->Max = DataSize; String->Max = DataSize;
String->Length = 0; 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 static string
InitializeString (char* Data, s32 DataSize) InitializeEmptyString (char* Data, s32 DataSize)
{ {
string Result = {}; string Result = {};
Result.Memory = Data; Result.Memory = Data;
@ -356,6 +371,16 @@ InitializeString (char* Data, s32 DataSize)
return Result; 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 static void
ClearString (string* String) ClearString (string* String)
{ {
@ -407,6 +432,30 @@ static bool IsOperator (char C)
(C == '<') || (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 // Tokenizing
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -1050,7 +1099,7 @@ InsertChar (string* String, char Char, s32 Index)
Assert(Index >= 0 && Index < String->Max); Assert(Index >= 0 && Index < String->Max);
Assert(String->Length < String->Max); Assert(String->Length < String->Max);
char* Src = String->Memory + String->Length; char* Src = String->Memory + String->Length - 1;
char* Dst = Src + 1; char* Dst = Src + 1;
for (int i = String->Length - 1; i >= Index; i--) for (int i = String->Length - 1; i >= Index; i--)
{ {
@ -1132,6 +1181,74 @@ Substring (string String, s32 Start)
return Result; 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 static void
NullTerminate (string* String) NullTerminate (string* String)
{ {
@ -2081,3 +2198,6 @@ TestStrings()
#endif // DEBUG_GS_STRING #endif // DEBUG_GS_STRING
#endif // DEBUG #endif // DEBUG
#define GS_STRING_H
#endif // GS_STRING_H

View File

@ -727,6 +727,27 @@ GetFileLastWriteTime(char* Path)
PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile)
{ {
b32 Result = false; 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; return Result;
} }

View File

@ -1,112 +1,27 @@
// NOTE(Peter): This stuff was all a test to see how I could do panel splitting. Thinking about moving away internal v2
// from that for now. Might return later if necessary DrawCharacter (render_quad_batch_constructor* BatchConstructor, char C, bitmap_font Font, v2 Position, v4 Color, r32 FontScale)
// TODO(Peter): Finish this if necessary {
s32 GlyphDataIndex = GetIndexForCodepoint(Font, C);
codepoint_bitmap CodepointInfo = Font.CodepointValues[GlyphDataIndex];
struct interface_region r32 MinX = Position.x + CodepointInfo.XOffset * FontScale;
{ r32 MinY = Position.y + CodepointInfo.YOffset * FontScale;
v2 Min, Max; r32 MaxX = MinX + (CodepointInfo.Width) * FontScale;
union r32 MaxY = MinY + (CodepointInfo.Height) * FontScale;
{
struct
{
interface_region* A;
interface_region* B;
};
struct
{
interface_region* Left;
interface_region* Right;
};
struct
{
interface_region* Top;
interface_region* Bottom;
};
};
};
struct interface_tracker PushQuad2DOnBatch(BatchConstructor,
{ v2{MinX, MinY}, v2{MaxX, MinY},
memory_arena* Storage; v2{MaxX, MaxY}, v2{MinX, MaxY},
interface_region RootRegion; CodepointInfo.UVMin, CodepointInfo.UVMax,
}; Color);
enum interface_region_split return v2{Position.x + CodepointInfo.Width * FontScale, Position.y};
{
InterfaceRegionSplit_Vertical,
InterfaceRegionSplit_Horizontal,
};
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;
} }
internal v2 internal v2
DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Font, s32 PointSize, v2 Position, v4 Color) DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Font, s32 PointSize, v2 Position, v4 Color)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
v2 LowerRight = Position; v2 LowerRight = Position;
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length, 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; char* C = String.Memory;
for (s32 i = 0; i < String.Length; i++) for (s32 i = 0; i < String.Length; i++)
{ {
s32 GlyphDataIndex = GetIndexForCodepoint(*Font, *C); v2 PositionAfterCharacter = DrawCharacter(&BatchConstructor, *C, *Font, RegisterPosition, Color, FontScale);
codepoint_bitmap CodepointInfo = Font->CodepointValues[GlyphDataIndex]; RegisterPosition.x = PositionAfterCharacter.x;
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;
C++; C++;
} }
@ -145,6 +47,54 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon
return LowerRight; 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 struct interface_config
{ {
v4 PanelBGColors[4]; v4 PanelBGColors[4];
@ -162,11 +112,17 @@ struct button_result
}; };
internal 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 = {}; button_result Result = {};
Result.Pressed = false; Result.Pressed = false;
v4 BGColor = IdleBGColor;
v4 TextColor = IdleTextColor;
v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY}; v2 MousePos = v2{(r32)Input.New->MouseX, (r32)Input.New->MouseY};
if (PointIsInRange(MousePos, Min, Max)) if (PointIsInRange(MousePos, Min, Max))
{ {
@ -176,21 +132,26 @@ EvaluateButton_ (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Lab
} }
else else
{ {
BGColor = Config.ButtonColor_Active; BGColor = HotBGColor;
TextColor = HotTextColor;
} }
} }
PushRenderQuad2D(RenderBuffer, Min, Max, BGColor); 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; return Result;
} }
internal button_result internal button_result
EvaluateButton (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Label, interface_config Config, input Input) 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; return Result;
} }
@ -203,7 +164,11 @@ EvaluateSelectableButton (render_command_buffer* RenderBuffer, v2 Min, v2 Max, s
BGColor = Config.ButtonColor_Selected; 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; return Result;
} }
@ -593,3 +558,79 @@ EvaluateColorPicker (render_command_buffer* RenderBuffer, v4* Value, v2 PanelMin
return ShouldClose; 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;
}

27
kraftwerks_patterns.h Normal file
View File

@ -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++;
}
}

View File

@ -1,6 +0,0 @@
pattern_registry_entry PatternRegistry[] =
{
{"Solid", SolidPatternInitProc, SolidPatternUpdateProc},
{"Rainbow", InitRainbowPatternProc, RainbowPatternProc},
{"Radial", InitRadialProc, UpdateRadialProc},
};

View File

@ -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) 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_STRUCT(vertical_color_fade_data)
{ {
NODE_IN(v4, Color); NODE_IN(v4, Color);
@ -143,114 +54,77 @@ NODE_PROC(VerticalColorFadeProc, vertical_color_fade_data)
} }
} }
// ^^^ New ^^^ // Original -> DiscPatterns.pde : Revolving Discs
// vvv Old vvv NODE_STRUCT(revolving_discs_data)
PATTERN_INIT_PROC(SolidPatternInitProc)
{ {
Pattern->Memory = (void*)PushArray(Storage, u8, 3); NODE_IN(r32, Rotation);
NODE_IN(r32, ThetaZ);
u8* Color = (u8*)Pattern->Memory; NODE_IN(r32, ThetaY);
Color[0] = 0; NODE_IN(r32, DiscWidth);
Color[1] = 0; NODE_IN(r32, InnerRadius);
Color[2] = 128; NODE_IN(r32, OuterRadius);
} NODE_IN(v4, Color);
NODE_COLOR_BUFFER_OUT(Result);
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;
}; };
PATTERN_INIT_PROC(InitRainbowPatternProc) NODE_PROC(RevolvingDiscs, revolving_discs_data)
{ {
Pattern->Memory = (void*)PushStruct(Storage, rainbow_pattern_memory); sacn_pixel Color = PackFloatsToSACNPixel(Data->Color.r, Data->Color.g, Data->Color.b);
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Pattern->Memory;
Mem->TimeAccumulator = 0; v3 Center = v3{0, 0, 0};
Mem->Period = 6.0f; 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);
v3 FrontCenter = Center + (Normal * Data->DiscWidth);
v3 BackCenter = Center - (Normal * Data->DiscWidth);
led* LED = Data->ResultLEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++)
{
v3 Position = LED->Position;
v3 ToFront = Normalize(Position + FrontCenter);
v3 ToBack = Normalize(Position + BackCenter);
r32 ToFrontDotNormal = Dot(ToFront, Normal);
r32 ToBackDotNormal = Dot(ToBack, Normal);
ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000);
ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000);
r32 DistToCenter = Mag(Position);
if (DistToCenter < Data->OuterRadius && DistToCenter > Data->InnerRadius)
{
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
{
Data->ResultColors[LED->Index] = Color;
} }
PATTERN_UPDATE_PROC(RainbowPatternProc)
{
DEBUG_TRACK_SCOPE(RainbowPatternProc);
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Memory;
Mem->TimeAccumulator += DeltaTime;
if (Mem->TimeAccumulator >= Mem->Period)
{
Mem->TimeAccumulator -= Mem->Period;
} }
LED++;
r32 Percent = Mem->TimeAccumulator / Mem->Period;
r32 HueAdd = Percent * 360.0f;
r32 HueScale = 360.0f / 100;
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;
PushColor(LED++, Colors, (u8)(Color.r * 255), (u8)(Color.g * 255), (u8)(Color.b * 255));
} }
} }
PATTERN_INIT_PROC(InitRadialProc) NODE_STRUCT(michelle_data)
{ {
Pattern->Memory = (void*)PushStruct(Storage, rainbow_pattern_memory); NODE_IN(v4, Color);
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Pattern->Memory; NODE_COLOR_BUFFER_INOUT;
Mem->TimeAccumulator = 0; };
Mem->Period = 10.0;
}
PATTERN_UPDATE_PROC(UpdateRadialProc) 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);
rainbow_pattern_memory* Mem = (rainbow_pattern_memory*)Memory; led* LED = Data->LEDs;
Mem->TimeAccumulator += DeltaTime; for (s32 l = 0; l < Data->LEDCount; l++)
if (Mem->TimeAccumulator >= Mem->Period)
{ {
Mem->TimeAccumulator -= Mem->Period; Assert(LED->Index >= 0 && LED->Index < Data->LEDCount);
}
r32 Percent = Mem->TimeAccumulator / Mem->Period; Data->Colors[LED->Index].R = R;
r32 AngleAdd = Percent * PI * 2; Data->Colors[LED->Index].G = G;
r32 HueAdd = Percent * 360; Data->Colors[LED->Index].B = B;
LED++;
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)
{
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;
}
else
{
Color = HSVToRGB(v4{HueAdd, 1, 1, 1}) * .9f;
}
PushColor(LED++, Colors, (u8)(Color.r * 255), (u8)(Color.g * 255), (u8)(Color.b * 255));
} }
} }

View File

@ -1,9 +1,15 @@
TODO FOLDHAUS 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 Name
x lumen lab
- Splash screen (like blender) (thisll be fun) - 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) - - Image importer (stb image? or find a png > bmp converter for the image you have)
- - Display on startup - - Display on startup
@ -14,12 +20,8 @@ x Keep an eye out.
Application Application
- More efficient HSV <-> RGB - 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 - Save and load a session
- - Serialize Channels - - Serialize Nodes
- - Serialize Patterns
- Don't render if the window isn't visible - Don't render if the window isn't visible
Development Development
@ -39,7 +41,6 @@ Interface
Switch To Nodes Switch To Nodes
x basic node elements x basic node elements
- - evaluation step (one node at a time) - - evaluation step (one node at a time)
- - search nodes by name
- - selector node (has a list of connections that it can switch between) - - selector node (has a list of connections that it can switch between)
- serialize - serialize
- delete nodes - delete nodes
@ -68,10 +69,6 @@ Animation
Command Line Command Line
- select a channel/pattern - select a channel/pattern
- Channel: Add/remove pattern by name
- Channel: Set Blend Mode
- Channel: Set Current Pattern
- Pattern: Edit parameter values
Optimization Optimization
- patterns are asking to be multithreaded - patterns are asking to be multithreaded

View File

@ -394,9 +394,12 @@ HandleWindowMessage (MSG Message, window* Window, input_frame* InputFrame)
{ {
int VirtualKey = (int)Message.wParam; int VirtualKey = (int)Message.wParam;
bool KeyDown = (Message.lParam & (1 << 31)) == 0; 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) if (KeyIndex == WIN32_SHOULD_TRANSLATE_TO_CHAR)
{ {
KeyIndex = Win32GetKeyIndex(VirtualKey, true, false);
InputFrame->KeysDown[KeyIndex] = KeyDown;
TranslateMessage(&Message); TranslateMessage(&Message);
DispatchMessage(&Message); DispatchMessage(&Message);
} }