Pulled the leds out of assemblies and into their own subsystem.
This commit is contained in:
parent
bfd9d6671c
commit
69db4b436c
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
#ifndef FOLDHAUS_ANIMATION
|
#ifndef FOLDHAUS_ANIMATION
|
||||||
|
|
||||||
#define ANIMATION_PROC(name) void name(assembly_led_buffer* Assembly, r32 Time)
|
#define ANIMATION_PROC(name) void name(led_buffer* Assembly, r32 Time)
|
||||||
typedef ANIMATION_PROC(animation_proc);
|
typedef ANIMATION_PROC(animation_proc);
|
||||||
|
|
||||||
struct frame_range
|
struct frame_range
|
||||||
|
@ -39,7 +39,7 @@ struct anim_layer
|
||||||
#define ANIMATION_SYSTEM_BLOCKS_MAX 128
|
#define ANIMATION_SYSTEM_BLOCKS_MAX 128
|
||||||
struct animation_system
|
struct animation_system
|
||||||
{
|
{
|
||||||
memory_arena Storage;
|
memory_arena* Storage;
|
||||||
|
|
||||||
gs_list<animation_block> Blocks;
|
gs_list<animation_block> Blocks;
|
||||||
anim_layer* Layers;
|
anim_layer* Layers;
|
||||||
|
@ -94,7 +94,7 @@ PercentToFrameInRange(r32 Percent, frame_range Range)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal s32
|
internal s32
|
||||||
ClampFrameToRange(s32 Frame, frame_range Range)
|
ClampFrameToRange(s32 Frame, frame_range Range)
|
||||||
{
|
{
|
||||||
s32 Result = Frame;
|
s32 Result = Frame;
|
||||||
|
@ -135,7 +135,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim
|
||||||
internal u32
|
internal u32
|
||||||
AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite)
|
AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite)
|
||||||
{
|
{
|
||||||
// TODO(Peter): If this assert fires its time to make the layer buffer system
|
// TODO(Peter): If this assert fires its time to make the layer buffer system
|
||||||
// resizable.
|
// resizable.
|
||||||
Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax);
|
Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax);
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode =
|
||||||
Result = AnimationSystem->LayersCount++;
|
Result = AnimationSystem->LayersCount++;
|
||||||
anim_layer* NewLayer = AnimationSystem->Layers + Result;
|
anim_layer* NewLayer = AnimationSystem->Layers + Result;
|
||||||
*NewLayer = {0};
|
*NewLayer = {0};
|
||||||
NewLayer->Name = MakeString(PushArray(&AnimationSystem->Storage, char, Name.Length), Name.Length);
|
NewLayer->Name = MakeString(PushArray(AnimationSystem->Storage, char, Name.Length), Name.Length);
|
||||||
CopyStringTo(Name, &NewLayer->Name);
|
CopyStringTo(Name, &NewLayer->Name);
|
||||||
NewLayer->BlendMode = BlendMode;
|
NewLayer->BlendMode = BlendMode;
|
||||||
return Result;
|
return Result;
|
||||||
|
|
|
@ -58,6 +58,8 @@ struct assembly_tokenizer
|
||||||
char* At;
|
char* At;
|
||||||
|
|
||||||
u32 LineNumber;
|
u32 LineNumber;
|
||||||
|
|
||||||
|
bool ParsingIsValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal bool
|
internal bool
|
||||||
|
@ -128,12 +130,12 @@ ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +150,7 @@ ReadFieldEnd(assembly_tokenizer* T)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -228,7 +230,7 @@ ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -243,7 +245,7 @@ ReadFloatField(assembly_field Field, assembly_tokenizer* T)
|
||||||
Result = ReadFloat(T);
|
Result = ReadFloat(T);
|
||||||
if (!ReadFieldEnd(T))
|
if (!ReadFieldEnd(T))
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -258,7 +260,7 @@ ReadIntField(assembly_field Field, assembly_tokenizer* T)
|
||||||
Result = ReadInt(T);
|
Result = ReadInt(T);
|
||||||
if (!ReadFieldEnd(T))
|
if (!ReadFieldEnd(T))
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -279,16 +281,31 @@ ReadV3Field(assembly_field Field, assembly_tokenizer* T)
|
||||||
if (AdvanceIfTokenEquals(T, ","))
|
if (AdvanceIfTokenEquals(T, ","))
|
||||||
{
|
{
|
||||||
Result.z = ReadFloat(T);
|
Result.z = ReadFloat(T);
|
||||||
|
|
||||||
if (AdvanceIfTokenEquals(T, ")"))
|
if (AdvanceIfTokenEquals(T, ")"))
|
||||||
{
|
{
|
||||||
if (!ReadFieldEnd(T))
|
if (!ReadFieldEnd(T))
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T->ParsingIsValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T->ParsingIsValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T->ParsingIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -315,15 +332,15 @@ ReadStructClosing(assembly_tokenizer* T)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal bool
|
||||||
ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
|
ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
|
||||||
{
|
{
|
||||||
Assert(Assembly->Arena.Alloc != 0);
|
|
||||||
Assembly->LedCountTotal = 0;
|
Assembly->LedCountTotal = 0;
|
||||||
|
|
||||||
assembly_tokenizer Tokenizer = {};
|
assembly_tokenizer Tokenizer = {};
|
||||||
Tokenizer.Text = FileText;
|
Tokenizer.Text = FileText;
|
||||||
Tokenizer.At = Tokenizer.Text.Memory;
|
Tokenizer.At = Tokenizer.Text.Memory;
|
||||||
|
Tokenizer.ParsingIsValid = true;
|
||||||
|
|
||||||
Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena);
|
Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena);
|
||||||
Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer);
|
Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer);
|
||||||
|
@ -349,8 +366,7 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
|
||||||
StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer);
|
StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer);
|
||||||
if (!ReadStructClosing(&Tokenizer))
|
if (!ReadStructClosing(&Tokenizer))
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
Tokenizer.ParsingIsValid = false;
|
||||||
InvalidCodePath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,19 +388,27 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
|
||||||
TagAt->ValueHash = HashString(TagValue);
|
TagAt->ValueHash = HashString(TagValue);
|
||||||
if (!ReadStructClosing(&Tokenizer))
|
if (!ReadStructClosing(&Tokenizer))
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
Tokenizer.ParsingIsValid = false;
|
||||||
InvalidCodePath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tokenizer.ParsingIsValid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadStructClosing(&Tokenizer))
|
if (!ReadStructClosing(&Tokenizer))
|
||||||
{
|
{
|
||||||
// TODO(Peter): Error
|
Tokenizer.ParsingIsValid = false;
|
||||||
InvalidCodePath;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tokenizer.ParsingIsValid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Tokenizer.ParsingIsValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ASSEMBLY_PARSER_CPP
|
#define ASSEMBLY_PARSER_CPP
|
||||||
|
|
|
@ -70,13 +70,16 @@ RELOAD_STATIC_DATA(ReloadStaticData)
|
||||||
INITIALIZE_APPLICATION(InitializeApplication)
|
INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
{
|
{
|
||||||
app_state* State = (app_state*)Context.MemoryBase;
|
app_state* State = (app_state*)Context.MemoryBase;
|
||||||
|
*State = {};
|
||||||
|
|
||||||
State->Permanent = {};
|
State->Permanent = {};
|
||||||
State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
State->Permanent.PlatformMemory = Context.PlatformMemory;
|
||||||
State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
|
||||||
State->Transient = {};
|
State->Transient = {};
|
||||||
State->Transient.FindAddressRule = FindAddress_InLastBufferOnly;
|
State->Transient.FindAddressRule = FindAddress_InLastBufferOnly;
|
||||||
State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
State->Transient.PlatformMemory = Context.PlatformMemory;
|
||||||
State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
|
||||||
|
State->Assemblies.CountMax = 8;
|
||||||
|
State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax);
|
||||||
|
|
||||||
State->GlobalLog = PushStruct(&State->Transient, event_log);
|
State->GlobalLog = PushStruct(&State->Transient, event_log);
|
||||||
*State->GlobalLog = {0};
|
*State->GlobalLog = {0};
|
||||||
|
@ -175,6 +178,8 @@ 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};
|
||||||
|
|
||||||
|
State->LedSystem = LedSystemInitialize(Context.PlatformMemory, 128);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold");
|
string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold");
|
||||||
LoadAssembly(State, Context, SculpturePath);
|
LoadAssembly(State, Context, SculpturePath);
|
||||||
|
@ -189,12 +194,12 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
// Setup Operation Modes
|
// Setup Operation Modes
|
||||||
State->Modes.ActiveModesCount = 0;
|
State->Modes.ActiveModesCount = 0;
|
||||||
State->Modes.Arena = {};
|
State->Modes.Arena = {};
|
||||||
State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
State->Modes.Arena.PlatformMemory = Context.PlatformMemory;
|
||||||
State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
|
||||||
State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly;
|
State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly;
|
||||||
|
|
||||||
{ // Animation PLAYGROUND
|
{ // Animation PLAYGROUND
|
||||||
State->AnimationSystem = {};
|
State->AnimationSystem = {};
|
||||||
|
State->AnimationSystem.Storage = &State->Permanent;
|
||||||
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
|
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
|
||||||
State->AnimationSystem.PlayableRange.Min = 0;
|
State->AnimationSystem.PlayableRange.Min = 0;
|
||||||
State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
|
State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
|
||||||
|
@ -273,21 +278,24 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_
|
||||||
}
|
}
|
||||||
|
|
||||||
internal dmx_buffer_list*
|
internal dmx_buffer_list*
|
||||||
CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena)
|
CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, memory_arena* Arena)
|
||||||
{
|
{
|
||||||
DEBUG_TRACK_FUNCTION;
|
DEBUG_TRACK_FUNCTION;
|
||||||
|
|
||||||
|
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex);
|
||||||
|
|
||||||
dmx_buffer_list* Result = 0;
|
dmx_buffer_list* Result = 0;
|
||||||
dmx_buffer_list* Head = 0;
|
dmx_buffer_list* Head = 0;
|
||||||
|
|
||||||
s32 BufferSize = BufferHeaderSize + 512;
|
s32 BufferSize = BufferHeaderSize + 512;
|
||||||
|
|
||||||
for (u32 Range = 0; Range < Assembly.LEDUniverseMapCount; Range++)
|
for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++)
|
||||||
{
|
{
|
||||||
leds_in_universe_range LEDUniverseRange = Assembly.LEDUniverseMap[Range];
|
v2_strip Strip = Assembly.Strips[StripIndex];
|
||||||
|
|
||||||
dmx_buffer_list* NewBuffer = PushStruct(Arena, dmx_buffer_list);
|
dmx_buffer_list* NewBuffer = PushStruct(Arena, dmx_buffer_list);
|
||||||
NewBuffer->Buffer.Universe = LEDUniverseRange.Universe;
|
NewBuffer->Buffer.Universe = Strip.StartUniverse;
|
||||||
|
|
||||||
NewBuffer->Buffer.Base = PushArray(Arena, u8, BufferSize);
|
NewBuffer->Buffer.Base = PushArray(Arena, u8, BufferSize);
|
||||||
NewBuffer->Buffer.TotalSize = BufferSize;
|
NewBuffer->Buffer.TotalSize = BufferSize;
|
||||||
NewBuffer->Buffer.HeaderSize = BufferHeaderSize;
|
NewBuffer->Buffer.HeaderSize = BufferHeaderSize;
|
||||||
|
@ -302,13 +310,12 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena)
|
||||||
Head = NewBuffer;
|
Head = NewBuffer;
|
||||||
|
|
||||||
u8* DestChannel = Head->Buffer.Base + BufferHeaderSize;
|
u8* DestChannel = Head->Buffer.Base + BufferHeaderSize;
|
||||||
for (s32 LEDIdx = LEDUniverseRange.RangeStart;
|
|
||||||
LEDIdx < LEDUniverseRange.RangeOnePastLast;
|
for (u32 i = 0; i < Strip.LedCount; i++)
|
||||||
LEDIdx++)
|
|
||||||
{
|
{
|
||||||
led LED = Assembly.LEDBuffer.LEDs[LEDIdx];
|
u32 LedIndex = Strip.LedLUT[i];
|
||||||
pixel Color = Assembly.LEDBuffer.Colors[LED.Index];
|
led LED = LedBuffer->Leds[LedIndex];
|
||||||
|
pixel Color = LedBuffer->Colors[LED.Index];
|
||||||
|
|
||||||
DestChannel[0] = Color.R;
|
DestChannel[0] = Color.R;
|
||||||
DestChannel[1] = Color.G;
|
DestChannel[1] = Color.G;
|
||||||
|
@ -366,11 +373,11 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
CurrentBlocks[Block.Layer] = Block;
|
CurrentBlocks[Block.Layer] = Block;
|
||||||
}
|
}
|
||||||
|
|
||||||
assembly_led_buffer* LayerLEDBuffers = PushArray(&State->Transient, assembly_led_buffer, CurrentBlocksMax);
|
led_buffer* LayerLEDBuffers = PushArray(&State->Transient, led_buffer, CurrentBlocksMax);
|
||||||
for (u32 AssemblyIndex = 0; AssemblyIndex < State->ActiveAssemblyIndecies.Used; AssemblyIndex++)
|
for (u32 AssemblyIndex = 0; AssemblyIndex < State->Assemblies.Count; AssemblyIndex++)
|
||||||
{
|
{
|
||||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(AssemblyIndex);
|
assembly* Assembly = &State->Assemblies.Values[AssemblyIndex];
|
||||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly->LedBufferIndex);
|
||||||
|
|
||||||
arena_snapshot ResetAssemblyMemorySnapshot = TakeSnapshotOfArena(&State->Transient);
|
arena_snapshot ResetAssemblyMemorySnapshot = TakeSnapshotOfArena(&State->Transient);
|
||||||
|
|
||||||
|
@ -380,8 +387,8 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
animation_block Block = CurrentBlocks[Layer];
|
animation_block Block = CurrentBlocks[Layer];
|
||||||
|
|
||||||
// Prep Temp Buffer
|
// Prep Temp Buffer
|
||||||
LayerLEDBuffers[Layer] = Assembly->LEDBuffer;
|
LayerLEDBuffers[Layer] = *AssemblyLedBuffer;
|
||||||
LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, Assembly->LEDBuffer.LEDCount);
|
LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, AssemblyLedBuffer->LedCount);
|
||||||
|
|
||||||
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
|
||||||
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
|
||||||
|
@ -418,41 +425,41 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
{
|
{
|
||||||
case BlendMode_Overwrite:
|
case BlendMode_Overwrite:
|
||||||
{
|
{
|
||||||
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
|
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
|
||||||
{
|
{
|
||||||
Assembly->LEDBuffer.Colors[LED] = LayerLEDBuffers[Layer].Colors[LED];
|
AssemblyLedBuffer->Colors[LED] = LayerLEDBuffers[Layer].Colors[LED];
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case BlendMode_Add:
|
case BlendMode_Add:
|
||||||
{
|
{
|
||||||
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
|
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
|
||||||
{
|
{
|
||||||
u32 R = (u32)Assembly->LEDBuffer.Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R;
|
u32 R = (u32)AssemblyLedBuffer->Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R;
|
||||||
u32 G = (u32)Assembly->LEDBuffer.Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G;
|
u32 G = (u32)AssemblyLedBuffer->Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G;
|
||||||
u32 B = (u32)Assembly->LEDBuffer.Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B;
|
u32 B = (u32)AssemblyLedBuffer->Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B;
|
||||||
|
|
||||||
Assembly->LEDBuffer.Colors[LED].R = (u8)GSMin(R, (u32)255);
|
AssemblyLedBuffer->Colors[LED].R = (u8)GSMin(R, (u32)255);
|
||||||
Assembly->LEDBuffer.Colors[LED].G = (u8)GSMin(G, (u32)255);
|
AssemblyLedBuffer->Colors[LED].G = (u8)GSMin(G, (u32)255);
|
||||||
Assembly->LEDBuffer.Colors[LED].B = (u8)GSMin(B, (u32)255);
|
AssemblyLedBuffer->Colors[LED].B = (u8)GSMin(B, (u32)255);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case BlendMode_Multiply:
|
case BlendMode_Multiply:
|
||||||
{
|
{
|
||||||
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
|
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
|
||||||
{
|
{
|
||||||
r32 DR = (r32)Assembly->LEDBuffer.Colors[LED].R / 255.f;
|
r32 DR = (r32)AssemblyLedBuffer->Colors[LED].R / 255.f;
|
||||||
r32 DG = (r32)Assembly->LEDBuffer.Colors[LED].G / 255.f;
|
r32 DG = (r32)AssemblyLedBuffer->Colors[LED].G / 255.f;
|
||||||
r32 DB = (r32)Assembly->LEDBuffer.Colors[LED].B / 255.f;
|
r32 DB = (r32)AssemblyLedBuffer->Colors[LED].B / 255.f;
|
||||||
|
|
||||||
r32 SR = (r32)LayerLEDBuffers[Layer].Colors[LED].R / 255.f;
|
r32 SR = (r32)LayerLEDBuffers[Layer].Colors[LED].R / 255.f;
|
||||||
r32 SG = (r32)LayerLEDBuffers[Layer].Colors[LED].G / 255.f;
|
r32 SG = (r32)LayerLEDBuffers[Layer].Colors[LED].G / 255.f;
|
||||||
r32 SB = (r32)LayerLEDBuffers[Layer].Colors[LED].B / 255.f;
|
r32 SB = (r32)LayerLEDBuffers[Layer].Colors[LED].B / 255.f;
|
||||||
|
|
||||||
Assembly->LEDBuffer.Colors[LED].R = (u8)((DR * SR) * 255.f);
|
AssemblyLedBuffer->Colors[LED].R = (u8)((DR * SR) * 255.f);
|
||||||
Assembly->LEDBuffer.Colors[LED].G = (u8)((DG * SG) * 255.f);
|
AssemblyLedBuffer->Colors[LED].G = (u8)((DG * SG) * 255.f);
|
||||||
Assembly->LEDBuffer.Colors[LED].B = (u8)((DB * SB) * 255.f);
|
AssemblyLedBuffer->Colors[LED].B = (u8)((DB * SB) * 255.f);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
@ -464,17 +471,12 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
|
|
||||||
s32 HeaderSize = State->NetworkProtocolHeaderSize;
|
s32 HeaderSize = State->NetworkProtocolHeaderSize;
|
||||||
dmx_buffer_list* DMXBuffers = 0;
|
dmx_buffer_list* DMXBuffers = 0;
|
||||||
// TODO(Peter): Come back and re add this in. It was tanking frame rate after
|
for (u32 i = 0; i < State->Assemblies.Count; i++)
|
||||||
// updates to the assembly file format
|
|
||||||
#if 0
|
|
||||||
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
|
|
||||||
{
|
{
|
||||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
|
assembly* Assembly = &State->Assemblies.Values[i];
|
||||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, &State->LedSystem, HeaderSize, &State->Transient);
|
||||||
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient);
|
|
||||||
DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers);
|
DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//DEBUG_IF(GlobalDebugServices->Interface.SendSACNData)
|
//DEBUG_IF(GlobalDebugServices->Interface.SendSACNData)
|
||||||
{
|
{
|
||||||
|
@ -530,10 +532,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
||||||
{
|
{
|
||||||
DEBUG_TRACK_SCOPE(OverflowChecks);
|
DEBUG_TRACK_SCOPE(OverflowChecks);
|
||||||
AssertAllocationsNoOverflow(State->Permanent);
|
AssertAllocationsNoOverflow(State->Permanent);
|
||||||
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
|
for (u32 i = 0; i < State->Assemblies.Count; i++)
|
||||||
{
|
{
|
||||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
|
assembly* Assembly = &State->Assemblies.Values[i];
|
||||||
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
|
||||||
AssertAllocationsNoOverflow(Assembly->Arena);
|
AssertAllocationsNoOverflow(Assembly->Arena);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,13 +49,6 @@ enum network_protocol
|
||||||
NetworkProtocol_Count,
|
NetworkProtocol_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct led_buffer
|
|
||||||
{
|
|
||||||
led* Leds;
|
|
||||||
pixel* Colors;
|
|
||||||
led_buffer* Next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct app_state
|
struct app_state
|
||||||
{
|
{
|
||||||
rect WindowBounds;
|
rect WindowBounds;
|
||||||
|
@ -68,9 +61,8 @@ struct app_state
|
||||||
|
|
||||||
streaming_acn SACN;
|
streaming_acn SACN;
|
||||||
|
|
||||||
s32 TotalLEDsCount;
|
led_system LedSystem;
|
||||||
gs_list<assembly> AssemblyList;
|
assembly_array Assemblies;
|
||||||
gs_list<gs_list_handle> ActiveAssemblyIndecies;
|
|
||||||
|
|
||||||
camera Camera;
|
camera Camera;
|
||||||
r32 PixelsToWorldScale;
|
r32 PixelsToWorldScale;
|
||||||
|
@ -98,28 +90,28 @@ internal void OpenColorPicker(app_state* State, v4* Address);
|
||||||
|
|
||||||
// BEGIN TEMPORARY PATTERNS
|
// BEGIN TEMPORARY PATTERNS
|
||||||
internal void
|
internal void
|
||||||
TestPatternOne(assembly_led_buffer* Assembly, r32 Time)
|
TestPatternOne(led_buffer* Assembly, r32 Time)
|
||||||
{
|
{
|
||||||
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
|
for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++)
|
||||||
{
|
{
|
||||||
led LED = Assembly->LEDs[LEDIdx];
|
led Led = Assembly->Leds[LedIndex];
|
||||||
if (LED.Position.x < 0)
|
if (Led.Position.x < 0)
|
||||||
{
|
{
|
||||||
Assembly->Colors[LED.Index].R = 255;
|
Assembly->Colors[Led.Index].R = 255;
|
||||||
Assembly->Colors[LED.Index].B = 255;
|
Assembly->Colors[Led.Index].B = 255;
|
||||||
Assembly->Colors[LED.Index].G = 255;
|
Assembly->Colors[Led.Index].G = 255;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Assembly->Colors[LED.Index].R = 0;
|
Assembly->Colors[Led.Index].R = 0;
|
||||||
Assembly->Colors[LED.Index].B = 0;
|
Assembly->Colors[Led.Index].B = 0;
|
||||||
Assembly->Colors[LED.Index].G = 0;
|
Assembly->Colors[Led.Index].G = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
|
TestPatternTwo(led_buffer* Assembly, r32 Time)
|
||||||
{
|
{
|
||||||
r32 PeriodicTime = (Time / PI) * 2;
|
r32 PeriodicTime = (Time / PI) * 2;
|
||||||
|
|
||||||
|
@ -138,11 +130,11 @@ TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
|
||||||
r32 OuterRadiusSquared = 1000000;
|
r32 OuterRadiusSquared = 1000000;
|
||||||
r32 InnerRadiusSquared = 0;
|
r32 InnerRadiusSquared = 0;
|
||||||
|
|
||||||
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
|
for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++)
|
||||||
{
|
{
|
||||||
led LED = Assembly->LEDs[LEDIdx];
|
led Led = Assembly->Leds[LedIndex];
|
||||||
|
|
||||||
v4 Position = LED.Position;
|
v4 Position = Led.Position;
|
||||||
|
|
||||||
v4 ToFront = Position + FrontCenter;
|
v4 ToFront = Position + FrontCenter;
|
||||||
v4 ToBack = Position + BackCenter;
|
v4 ToBack = Position + BackCenter;
|
||||||
|
@ -158,22 +150,22 @@ TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
|
||||||
{
|
{
|
||||||
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
|
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
|
||||||
{
|
{
|
||||||
Assembly->Colors[LED.Index] = Color;
|
Assembly->Colors[Led.Index] = Color;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Assembly->Colors[LED.Index] = {};
|
//Assembly->Colors[Led.Index] = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Assembly->Colors[LED.Index] = {};
|
//Assembly->Colors[Led.Index] = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
TestPatternThree(assembly_led_buffer* Assembly, r32 Time)
|
TestPatternThree(led_buffer* Assembly, r32 Time)
|
||||||
{
|
{
|
||||||
v4 GreenCenter = v4{0, 0, 150, 1};
|
v4 GreenCenter = v4{0, 0, 150, 1};
|
||||||
r32 GreenRadius = GSAbs(GSSin(Time)) * 200;
|
r32 GreenRadius = GSAbs(GSSin(Time)) * 200;
|
||||||
|
@ -184,25 +176,25 @@ TestPatternThree(assembly_led_buffer* Assembly, r32 Time)
|
||||||
r32 FadeDist = 35;
|
r32 FadeDist = 35;
|
||||||
|
|
||||||
|
|
||||||
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
|
for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++)
|
||||||
{
|
{
|
||||||
led LED = Assembly->LEDs[LEDIdx];
|
led Led = Assembly->Leds[LedIndex];
|
||||||
u8 Red = 0;
|
u8 Red = 0;
|
||||||
u8 Green = 0;
|
u8 Green = 0;
|
||||||
u8 Blue = 0;
|
u8 Blue = 0;
|
||||||
|
|
||||||
r32 GreenDist = GSAbs(Mag(LED.Position - GreenCenter) - GreenRadius);
|
r32 GreenDist = GSAbs(Mag(Led.Position - GreenCenter) - GreenRadius);
|
||||||
r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist);
|
r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist);
|
||||||
Green = (u8)(GreenBrightness * 255);
|
Green = (u8)(GreenBrightness * 255);
|
||||||
|
|
||||||
r32 TealDist = GSAbs(Mag(LED.Position - TealCenter) - TealRadius);
|
r32 TealDist = GSAbs(Mag(Led.Position - TealCenter) - TealRadius);
|
||||||
r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist);
|
r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist);
|
||||||
Red = (u8)(TealBrightness * 255);
|
Red = (u8)(TealBrightness * 255);
|
||||||
Blue = (u8)(TealBrightness * 255);
|
Blue = (u8)(TealBrightness * 255);
|
||||||
|
|
||||||
Assembly->Colors[LED.Index].R = Red;
|
Assembly->Colors[Led.Index].R = Red;
|
||||||
Assembly->Colors[LED.Index].B = Green;
|
Assembly->Colors[Led.Index].B = Green;
|
||||||
Assembly->Colors[LED.Index].G = Green;
|
Assembly->Colors[Led.Index].G = Green;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,38 +5,106 @@
|
||||||
//
|
//
|
||||||
#ifndef FOLDHAUS_ASSEMBLY_CPP
|
#ifndef FOLDHAUS_ASSEMBLY_CPP
|
||||||
|
|
||||||
internal void
|
// Led System
|
||||||
ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition)
|
|
||||||
|
internal led_system
|
||||||
|
LedSystemInitialize(platform_memory_handler PlatformMemory, u32 BuffersMax)
|
||||||
{
|
{
|
||||||
Assembly->LEDBuffer.LEDCount = 0;
|
led_system Result = {};
|
||||||
Assembly->LEDBuffer.Colors = PushArray(&Assembly->Arena, pixel, Assembly->LedCountTotal);
|
Result.PlatformMemory = PlatformMemory;
|
||||||
Assembly->LEDBuffer.LEDs = PushArray(&Assembly->Arena, led, Assembly->LedCountTotal);
|
// TODO(Peter): Since we have access to PlatformMemory, just realloc Buffers when we fill it up
|
||||||
Assembly->LEDUniverseMapCount = Assembly->LedCountTotal;
|
Result.BuffersCountMax = BuffersMax;
|
||||||
Assembly->LEDUniverseMap = PushArray(&Assembly->Arena, leds_in_universe_range, Assembly->LedCountTotal);
|
Result.Buffers = PlatformAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u32
|
||||||
|
LedSystemTakeFreeBuffer(led_system* System, u32 LedCount)
|
||||||
|
{
|
||||||
|
s32 Result = -1;
|
||||||
|
|
||||||
// Add LEDs
|
if (System->BuffersCount < System->BuffersCountMax)
|
||||||
|
{
|
||||||
|
Result = System->BuffersCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE(Peter): Look for a buffer that's flagged as empty
|
||||||
|
for (u32 i = 0; i < System->BuffersCount; i++)
|
||||||
|
{
|
||||||
|
if (System->Buffers[i].LedCount == 0
|
||||||
|
&& System->Buffers[i].Colors == 0
|
||||||
|
&& System->Buffers[i].Leds == 0)
|
||||||
|
{
|
||||||
|
Result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert(Result >= 0); // NOTE(Peter): We ran out of room for led buffers
|
||||||
|
}
|
||||||
|
|
||||||
|
led_buffer* Buffer = &System->Buffers[Result];
|
||||||
|
Buffer->LedCount = LedCount;
|
||||||
|
Buffer->Colors = PlatformAllocArray(System->PlatformMemory, pixel, Buffer->LedCount);
|
||||||
|
Buffer->Leds = PlatformAllocArray(System->PlatformMemory, led, Buffer->LedCount);
|
||||||
|
|
||||||
|
System->LedsCountTotal += LedCount;
|
||||||
|
|
||||||
|
return (u32)Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
LedSystemFreeBuffer(led_system* System, u32 BufferIndex)
|
||||||
|
{
|
||||||
|
Assert(BufferIndex < System->BuffersCountMax);
|
||||||
|
led_buffer* Buffer = &System->Buffers[BufferIndex];
|
||||||
|
PlatformFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount);
|
||||||
|
PlatformFreeArray(System->PlatformMemory, Buffer->Leds, led, Buffer->LedCount);
|
||||||
|
System->LedsCountTotal -= Buffer->LedCount;
|
||||||
|
*Buffer = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal led_buffer*
|
||||||
|
LedSystemGetBuffer(led_system* System, u32 Index)
|
||||||
|
{
|
||||||
|
led_buffer* Result = &System->Buffers[Index];
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position)
|
||||||
|
{
|
||||||
|
Assert(Led < Buffer->LedCount);
|
||||||
|
Buffer->Leds[Led].Position = Position;
|
||||||
|
Buffer->Leds[Led].Index = Led;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assembly
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition, led_system* LedSystem)
|
||||||
|
{
|
||||||
|
Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal);
|
||||||
|
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex);
|
||||||
|
|
||||||
|
// Add Leds
|
||||||
|
u32 LedsAdded = 0;
|
||||||
for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++)
|
for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++)
|
||||||
{
|
{
|
||||||
//led_strip_definition StripDef = Definition.LEDStrips[StripIdx];
|
//led_strip_definition StripDef = Definition.LedStrips[StripIdx];
|
||||||
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
||||||
|
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
|
||||||
leds_in_universe_range* LEDUniverseRange = &Assembly->LEDUniverseMap[StripIdx];
|
|
||||||
|
|
||||||
LEDUniverseRange->Universe = StripAt->StartUniverse;
|
|
||||||
LEDUniverseRange->RangeStart = Assembly->LEDBuffer.LEDCount;
|
|
||||||
LEDUniverseRange->RangeOnePastLast = Assembly->LEDBuffer.LEDCount + StripAt->LedCount;
|
|
||||||
|
|
||||||
v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1);
|
v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1);
|
||||||
v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1);
|
v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1);
|
||||||
s32 LEDsInStripCount = StripAt->LedCount;
|
|
||||||
|
|
||||||
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)LEDsInStripCount;
|
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount;
|
||||||
for (s32 Step = 0; Step < LEDsInStripCount; Step++)
|
for (u32 Step = 0; Step < StripAt->LedCount; Step++)
|
||||||
{
|
{
|
||||||
s32 LEDIndex = Assembly->LEDBuffer.LEDCount;
|
s32 LedIndex = LedsAdded++;
|
||||||
Assembly->LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step);
|
v4 LedPosition = WS_StripStart + (SingleStep * Step);
|
||||||
Assembly->LEDBuffer.LEDs[LEDIndex].Index = LEDIndex;
|
LedBufferSetLed(LedBuffer, LedIndex, LedPosition);
|
||||||
Assembly->LEDBuffer.LEDCount += 1;
|
StripAt->LedLUT[Step] = LedIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,30 +115,33 @@ ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 Roo
|
||||||
static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} };
|
static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} };
|
||||||
s32 TempAssemblyOffsetsCount = 3;
|
s32 TempAssemblyOffsetsCount = 3;
|
||||||
|
|
||||||
|
// TODO(Peter): Don't reference State, pull back to the Led buffer and Assembly Array
|
||||||
internal void
|
internal void
|
||||||
LoadAssembly (app_state* State, context Context, string Path)
|
LoadAssembly (app_state* State, context Context, string Path)
|
||||||
{
|
{
|
||||||
platform_memory_result AssemblyFile = ReadEntireFile(Context, Path);
|
platform_memory_result AssemblyFile = ReadEntireFile(Context, Path);
|
||||||
if (AssemblyFile.Error == PlatformMemory_NoError)
|
if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Size > 0)
|
||||||
{
|
{
|
||||||
string AssemblyFileText = MakeString((char*)AssemblyFile.Base);
|
string AssemblyFileText = MakeString((char*)AssemblyFile.Base);
|
||||||
|
|
||||||
|
Assert(State->Assemblies.Count < State->Assemblies.CountMax);
|
||||||
|
assembly* NewAssembly = &State->Assemblies.Values[State->Assemblies.Count++];
|
||||||
|
|
||||||
s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\');
|
s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\');
|
||||||
string FileName = Substring(Path, IndexOfLastSlash + 1);
|
string FileName = Substring(Path, IndexOfLastSlash + 1);
|
||||||
|
|
||||||
assembly NewAssembly = {};
|
NewAssembly->Arena.PlatformMemory = Context.PlatformMemory;
|
||||||
NewAssembly.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
if (ParseAssemblyFile(NewAssembly, AssemblyFileText, &State->Transient))
|
||||||
NewAssembly.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
{
|
||||||
ParseAssemblyFile(&NewAssembly, AssemblyFileText, &State->Transient);
|
v4 Offset = TempAssemblyOffsets[State->Assemblies.Count % TempAssemblyOffsetsCount];
|
||||||
|
ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, &State->LedSystem);
|
||||||
v4 Offset = TempAssemblyOffsets[State->ActiveAssemblyIndecies.Used % TempAssemblyOffsetsCount];
|
PlatformFree(Context.PlatformMemory, AssemblyFile.Base, AssemblyFile.Size);
|
||||||
ConstructAssemblyFromDefinition(&NewAssembly, FileName, Offset);
|
}
|
||||||
gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly);
|
else
|
||||||
|
{
|
||||||
State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle);
|
FreeMemoryArena(&NewAssembly->Arena);
|
||||||
State->TotalLEDsCount += NewAssembly.LEDBuffer.LEDCount;
|
State->Assemblies.Count -= 1;
|
||||||
|
}
|
||||||
Context.PlatformFree(AssemblyFile.Base, AssemblyFile.Size);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -81,20 +152,12 @@ LoadAssembly (app_state* State, context Context, string Path)
|
||||||
internal void
|
internal void
|
||||||
UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context)
|
UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context)
|
||||||
{
|
{
|
||||||
assembly* Assembly = State->AssemblyList.GetElementAtIndex(AssemblyIndex);
|
Assert(AssemblyIndex < State->Assemblies.Count);
|
||||||
State->TotalLEDsCount -= Assembly->LEDBuffer.LEDCount;
|
assembly* Assembly = &State->Assemblies.Values[AssemblyIndex];
|
||||||
FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree);
|
LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex);
|
||||||
|
FreeMemoryArena(&Assembly->Arena);
|
||||||
State->AssemblyList.FreeElementAtIndex(AssemblyIndex);
|
u32 LastAssemblyIndex = --State->Assemblies.Count;
|
||||||
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
|
State->Assemblies.Values[AssemblyIndex] = State->Assemblies.Values[LastAssemblyIndex];
|
||||||
{
|
|
||||||
gs_list_handle Handle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
|
|
||||||
if (Handle.Index == AssemblyIndex)
|
|
||||||
{
|
|
||||||
State->ActiveAssemblyIndecies.FreeElementAtIndex(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
struct led
|
struct led
|
||||||
{
|
{
|
||||||
|
// TODO(Peter): Pretty sure we don't need this. led and pixel are always parallel arrays
|
||||||
s32 Index;
|
s32 Index;
|
||||||
v4 Position;
|
v4 Position;
|
||||||
};
|
};
|
||||||
|
@ -22,22 +23,22 @@ union pixel
|
||||||
u8 Channels[3];
|
u8 Channels[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(Peter): This structure is so we can keep track of
|
struct led_buffer
|
||||||
// what LEDs output to which DMX universe. You don't need
|
|
||||||
// to use it anywhere else, as all the data for patterns,
|
|
||||||
// colors, and groups is/will be stored elsewhere.
|
|
||||||
struct leds_in_universe_range
|
|
||||||
{
|
{
|
||||||
s32 RangeStart;
|
u32 LedCount;
|
||||||
s32 RangeOnePastLast;
|
pixel* Colors;
|
||||||
s32 Universe;
|
led* Leds;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assembly_led_buffer
|
struct led_system
|
||||||
{
|
{
|
||||||
u32 LEDCount;
|
platform_memory_handler PlatformMemory;
|
||||||
pixel* Colors;
|
|
||||||
led* LEDs;
|
u32 BuffersCountMax;
|
||||||
|
u32 BuffersCount;
|
||||||
|
led_buffer* Buffers;
|
||||||
|
|
||||||
|
u32 LedsCountTotal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v2_tag
|
struct v2_tag
|
||||||
|
@ -49,6 +50,7 @@ struct v2_tag
|
||||||
struct v2_strip
|
struct v2_strip
|
||||||
{
|
{
|
||||||
s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore
|
s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore
|
||||||
|
// TODO(Peter): Add in info for Serial, ArtNet, etc.
|
||||||
s32 StartUniverse;
|
s32 StartUniverse;
|
||||||
s32 StartChannel;
|
s32 StartChannel;
|
||||||
|
|
||||||
|
@ -72,17 +74,19 @@ struct assembly
|
||||||
string FilePath;
|
string FilePath;
|
||||||
|
|
||||||
r32 Scale;
|
r32 Scale;
|
||||||
|
s32 LedCountTotal;
|
||||||
|
u32 LedBufferIndex;
|
||||||
|
|
||||||
u32 StripCount;
|
u32 StripCount;
|
||||||
v2_strip* Strips;
|
v2_strip* Strips;
|
||||||
|
|
||||||
s32 LedCountTotal;
|
|
||||||
assembly_led_buffer LEDBuffer;
|
|
||||||
|
|
||||||
u32 LEDUniverseMapCount;
|
|
||||||
leds_in_universe_range* LEDUniverseMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct assembly_array
|
||||||
|
{
|
||||||
|
u32 CountMax;
|
||||||
|
u32 Count;
|
||||||
|
assembly* Values;
|
||||||
|
};
|
||||||
|
|
||||||
#define FOLDHAUS_ASSEMBLY_H
|
#define FOLDHAUS_ASSEMBLY_H
|
||||||
#endif // FOLDHAUS_ASSEMBLY_H
|
#endif // FOLDHAUS_ASSEMBLY_H
|
|
@ -88,15 +88,6 @@ struct system_path
|
||||||
s32 IndexOfLastSlash;
|
s32 IndexOfLastSlash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PLATFORM_ALLOC(name) u8* name(s32 Size)
|
|
||||||
typedef PLATFORM_ALLOC(platform_alloc);
|
|
||||||
|
|
||||||
#define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size)
|
|
||||||
typedef PLATFORM_FREE(platform_free);
|
|
||||||
|
|
||||||
#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize)
|
|
||||||
typedef PLATFORM_REALLOC(platform_realloc);
|
|
||||||
|
|
||||||
#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path)
|
#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path)
|
||||||
typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file);
|
typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file);
|
||||||
|
|
||||||
|
@ -264,10 +255,7 @@ struct context
|
||||||
// Platform Services
|
// Platform Services
|
||||||
work_queue* GeneralWorkQueue;
|
work_queue* GeneralWorkQueue;
|
||||||
|
|
||||||
platform_alloc* PlatformAlloc;
|
platform_memory_handler PlatformMemory;
|
||||||
platform_free* PlatformFree;
|
|
||||||
platform_realloc* PlatformRealloc;
|
|
||||||
|
|
||||||
platform_file_handler FileHandler;
|
platform_file_handler FileHandler;
|
||||||
|
|
||||||
platform_write_entire_file* PlatformWriteEntireFile;
|
platform_write_entire_file* PlatformWriteEntireFile;
|
||||||
|
|
|
@ -37,14 +37,14 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
|
||||||
|
|
||||||
u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1;
|
u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1;
|
||||||
u32 LinesDrawn = 0;
|
u32 LinesDrawn = 0;
|
||||||
u32 AssembliesToDraw = GSMin(LineCount, State->ActiveAssemblyIndecies.Used);
|
u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count);
|
||||||
for (; LinesDrawn < AssembliesToDraw; LinesDrawn++)
|
for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++)
|
||||||
{
|
{
|
||||||
rect Bounds = ui_ReserveElementBounds(&Layout);
|
rect Bounds = ui_ReserveElementBounds(&Layout);
|
||||||
v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, LinesDrawn);
|
v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, AssemblyIndex);
|
||||||
ui_FillRect(&State->Interface_, Bounds, ListItemBGColor);
|
ui_FillRect(&State->Interface_, Bounds, ListItemBGColor);
|
||||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(LinesDrawn);
|
|
||||||
assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
assembly Assembly = State->Assemblies.Values[AssemblyIndex];
|
||||||
PrintF(&TempString, "%S", Assembly.Name);
|
PrintF(&TempString, "%S", Assembly.Name);
|
||||||
|
|
||||||
ui_layout ItemLayout = ui_CreateLayout(State->Interface_, Bounds);
|
ui_layout ItemLayout = ui_CreateLayout(State->Interface_, Bounds);
|
||||||
|
@ -53,10 +53,12 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
|
||||||
ui_LayoutDrawString(&State->Interface_, &ItemLayout, TempString, State->Interface_.Style.TextColor);
|
ui_LayoutDrawString(&State->Interface_, &ItemLayout, TempString, State->Interface_.Style.TextColor);
|
||||||
if (ui_LayoutButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), ListItemBGColor, ListItemHover, ListItemSelected))
|
if (ui_LayoutButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), ListItemBGColor, ListItemHover, ListItemSelected))
|
||||||
{
|
{
|
||||||
UnloadAssembly(AssemblyHandle.Index, State, Context);
|
UnloadAssembly(AssemblyIndex, State, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui_EndRow(&ItemLayout);
|
ui_EndRow(&ItemLayout);
|
||||||
|
|
||||||
|
LinesDrawn += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LinesDrawn < LineCount)
|
if (LinesDrawn < LineCount)
|
||||||
|
|
|
@ -54,7 +54,7 @@ global_variable s32 SculptureView_CommandsCount = 1;
|
||||||
|
|
||||||
GSMetaTag(panel_init);
|
GSMetaTag(panel_init);
|
||||||
GSMetaTag(panel_type_sculpture_view);
|
GSMetaTag(panel_type_sculpture_view);
|
||||||
internal void
|
internal void
|
||||||
SculptureView_Init(panel* Panel, app_state* State)
|
SculptureView_Init(panel* Panel, app_state* State)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ SculptureView_Init(panel* Panel, app_state* State)
|
||||||
|
|
||||||
GSMetaTag(panel_cleanup);
|
GSMetaTag(panel_cleanup);
|
||||||
GSMetaTag(panel_type_sculpture_view);
|
GSMetaTag(panel_type_sculpture_view);
|
||||||
internal void
|
internal void
|
||||||
SculptureView_Cleanup(panel* Panel, app_state* State)
|
SculptureView_Cleanup(panel* Panel, app_state* State)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
|
||||||
|
|
||||||
GSMetaTag(panel_render);
|
GSMetaTag(panel_render);
|
||||||
GSMetaTag(panel_type_sculpture_view);
|
GSMetaTag(panel_type_sculpture_view);
|
||||||
internal void
|
internal void
|
||||||
SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
|
SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
|
||||||
{
|
{
|
||||||
DEBUG_TRACK_SCOPE(RenderSculpture);
|
DEBUG_TRACK_SCOPE(RenderSculpture);
|
||||||
|
@ -154,21 +154,21 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
|
||||||
FaceCameraMatrix = FaceCameraMatrix;
|
FaceCameraMatrix = FaceCameraMatrix;
|
||||||
|
|
||||||
u32 MaxLEDsPerJob = 2048;
|
u32 MaxLEDsPerJob = 2048;
|
||||||
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount);
|
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal);
|
||||||
|
|
||||||
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
|
for (u32 i = 0; i < State->Assemblies.Count; i++)
|
||||||
{
|
{
|
||||||
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
|
assembly Assembly = State->Assemblies.Values[i];
|
||||||
assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
|
led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex);
|
||||||
u32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDBuffer.LEDCount, MaxLEDsPerJob);
|
u32 JobsNeeded = IntegerDivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob);
|
||||||
|
|
||||||
for (u32 Job = 0; Job < JobsNeeded; Job++)
|
for (u32 Job = 0; Job < JobsNeeded; Job++)
|
||||||
{
|
{
|
||||||
draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data);
|
draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data);
|
||||||
JobData->LEDs = Assembly.LEDBuffer.LEDs;
|
JobData->LEDs = LedBuffer->Leds;
|
||||||
JobData->Colors = Assembly.LEDBuffer.Colors;
|
JobData->Colors = LedBuffer->Colors;
|
||||||
JobData->StartIndex = Job * MaxLEDsPerJob;
|
JobData->StartIndex = Job * MaxLEDsPerJob;
|
||||||
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDBuffer.LEDCount);
|
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount);
|
||||||
JobData->Batch = &RenderLEDsBatch;
|
JobData->Batch = &RenderLEDsBatch;
|
||||||
JobData->FaceCameraMatrix;
|
JobData->FaceCameraMatrix;
|
||||||
JobData->ModelViewMatrix = ModelViewMatrix;
|
JobData->ModelViewMatrix = ModelViewMatrix;
|
||||||
|
|
|
@ -663,9 +663,9 @@ WinMain (
|
||||||
|
|
||||||
// Platform functions
|
// Platform functions
|
||||||
Context.GeneralWorkQueue = &WorkQueue;
|
Context.GeneralWorkQueue = &WorkQueue;
|
||||||
Context.PlatformAlloc = Win32Alloc;
|
Context.PlatformMemory.Alloc = Win32Alloc;
|
||||||
Context.PlatformFree = Win32Free;
|
Context.PlatformMemory.Free = Win32Free;
|
||||||
Context.PlatformRealloc = Win32Realloc;
|
Context.PlatformMemory.Realloc = Win32Realloc;
|
||||||
Context.FileHandler.ReadEntireFile = Win32ReadEntireFile;
|
Context.FileHandler.ReadEntireFile = Win32ReadEntireFile;
|
||||||
Context.FileHandler.WriteEntireFile = Win32WriteEntireFile;
|
Context.FileHandler.WriteEntireFile = Win32WriteEntireFile;
|
||||||
Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile;
|
Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile;
|
||||||
|
|
|
@ -133,6 +133,8 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile)
|
||||||
|
|
||||||
Result = GetOpenFileNameA (&OpenFileName);
|
Result = GetOpenFileNameA (&OpenFileName);
|
||||||
|
|
||||||
|
PathBuffer->Length = CharArrayLength(PathBuffer->Memory);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// Description: Single header file library that defines a push-only memory arena
|
// Description: Single header file library that defines a push-only memory arena
|
||||||
// Author: Peter Slattery
|
// Author: Peter Slattery
|
||||||
// Date Created: 2019-12-22
|
// Date Created: 2019-12-22
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// -----------------
|
// -----------------
|
||||||
// Set Up
|
// Set Up
|
||||||
// -----------------
|
// -----------------
|
||||||
|
@ -16,26 +16,26 @@
|
||||||
// Simply create a memory_arena and use PushSize, PushStruct, or PushArray
|
// Simply create a memory_arena and use PushSize, PushStruct, or PushArray
|
||||||
// to allocate out of it.
|
// to allocate out of it.
|
||||||
// See Example Program below.
|
// See Example Program below.
|
||||||
//
|
//
|
||||||
// While there are options you can set (see Options below), the library adheres
|
// While there are options you can set (see Options below), the library adheres
|
||||||
// to a 'zero-is-initialization' policy, that is, a memory_arena initialized to
|
// to a 'zero-is-initialization' policy, that is, a memory_arena initialized to
|
||||||
// zero, under all default options, will 'just work'.
|
// zero, under all default options, will 'just work'.
|
||||||
//
|
//
|
||||||
// Alignment:
|
// Alignment:
|
||||||
// By default, the Push functions use 4 byte alignment
|
// By default, the Push functions use 4 byte alignment
|
||||||
// If you need to control the alignment of an allocation, there are variants of the
|
// If you need to control the alignment of an allocation, there are variants of the
|
||||||
// Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned
|
// Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned
|
||||||
// These functions simply take a final parameter which specifies the alignment.
|
// These functions simply take a final parameter which specifies the alignment.
|
||||||
// Note: Alignment must be a power of two
|
// Note: Alignment must be a power of two
|
||||||
//
|
//
|
||||||
// -----------------
|
// -----------------
|
||||||
// Options
|
// Options
|
||||||
// -----------------
|
// -----------------
|
||||||
//
|
//
|
||||||
// DEBUG:
|
// DEBUG:
|
||||||
// Define DEBUG for debug functionality.
|
// Define DEBUG for debug functionality.
|
||||||
//
|
//
|
||||||
// To override the default assert function define GSMem_Assert(expression)
|
// To override the default assert function define GSMem_Assert(expression)
|
||||||
// before inluding this file.
|
// before inluding this file.
|
||||||
//
|
//
|
||||||
// GS_MEMORY_NO_STD_LIBS:
|
// GS_MEMORY_NO_STD_LIBS:
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
// this file
|
// this file
|
||||||
//
|
//
|
||||||
// GS_MEMORY_TRACK_ALLOCATIONS:
|
// GS_MEMORY_TRACK_ALLOCATIONS:
|
||||||
// If you want to keep records of each allocation performed in every arena, define
|
// If you want to keep records of each allocation performed in every arena, define
|
||||||
// GS_MEMORY_TRACK_ALLOCATIONS before including this file.
|
// GS_MEMORY_TRACK_ALLOCATIONS before including this file.
|
||||||
// When defined, memory arenas gain fields that allow them to keep a list of every
|
// When defined, memory arenas gain fields that allow them to keep a list of every
|
||||||
// allocation they contain. It also adds a footer on the end of each allocation that
|
// allocation they contain. It also adds a footer on the end of each allocation that
|
||||||
// can be checked to ensure there are no writes to allocations that overflow their bounds
|
// can be checked to ensure there are no writes to allocations that overflow their bounds
|
||||||
|
@ -78,8 +78,8 @@
|
||||||
|
|
||||||
// Places the characters 'gs' at the end of each allocation. This would allow for an external
|
// Places the characters 'gs' at the end of each allocation. This would allow for an external
|
||||||
// function to check that we haven't written past the end of an allocation
|
// function to check that we haven't written past the end of an allocation
|
||||||
void* MallocWrapper(gs_mem_u32 Size)
|
void* MallocWrapper(gs_mem_u32 Size)
|
||||||
{
|
{
|
||||||
int SizeWithFooter = Size + (sizeof(char) * 2);
|
int SizeWithFooter = Size + (sizeof(char) * 2);
|
||||||
void* Result = malloc(SizeWithFooter);
|
void* Result = malloc(SizeWithFooter);
|
||||||
char* Footer = (char*)(Result + Size);
|
char* Footer = (char*)(Result + Size);
|
||||||
|
@ -88,17 +88,17 @@ void* MallocWrapper(gs_mem_u32 Size)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* ReallocWrapper(void* Address, gs_mem_u32 Size)
|
void* ReallocWrapper(void* Address, gs_mem_u32 Size)
|
||||||
{
|
{
|
||||||
return realloc(Address, Size);
|
return realloc(Address, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int ArgCount, char** Args)
|
main(int ArgCount, char** Args)
|
||||||
{
|
{
|
||||||
memory_arena Arena = {};
|
memory_arena Arena = {};
|
||||||
// Uncomment these lines for an example of how you can implement custom allocation functions
|
// Uncomment these lines for an example of how you can implement custom allocation functions
|
||||||
// Arena.Alloc = MallocWrapper;
|
// Arena.Alloc = MallocWrapper;
|
||||||
// Arena.Realloc = ReallocWrapper;
|
// Arena.Realloc = ReallocWrapper;
|
||||||
|
|
||||||
int ArrayLength = 10;
|
int ArrayLength = 10;
|
||||||
|
@ -139,9 +139,9 @@ main(int ArgCount, char** Args)
|
||||||
#ifndef GS_MEMORY_NO_STD_LIBS
|
#ifndef GS_MEMORY_NO_STD_LIBS
|
||||||
|
|
||||||
// NOTE(Peter): We use this so that we can fall back on malloc and realloc
|
// NOTE(Peter): We use this so that we can fall back on malloc and realloc
|
||||||
// in the event that a memory_arena needs to grow but doesn't have a
|
// in the event that a memory_arena needs to grow but doesn't have a
|
||||||
// alloc or realloc function pointer assigned to it.
|
// alloc or realloc function pointer assigned to it.
|
||||||
//
|
//
|
||||||
// See GrowArena to see where this is used
|
// See GrowArena to see where this is used
|
||||||
//
|
//
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -177,13 +177,13 @@ enum gs_memory_expansion_rule
|
||||||
|
|
||||||
// NOTE(Peter):
|
// NOTE(Peter):
|
||||||
// This rule is only here to allow for taking arena snapshots. The problem this solves
|
// This rule is only here to allow for taking arena snapshots. The problem this solves
|
||||||
// is if you take a snapshot while there are 'holes' in memory_buffers behind the
|
// is if you take a snapshot while there are 'holes' in memory_buffers behind the
|
||||||
// most recently added memory_buffer, take a snapshot of that arena, then push something
|
// most recently added memory_buffer, take a snapshot of that arena, then push something
|
||||||
// on that fits in one of those holes, we will fill the hole and be unable to track/free
|
// on that fits in one of those holes, we will fill the hole and be unable to track/free
|
||||||
// that addition via the snapshot construct.
|
// that addition via the snapshot construct.
|
||||||
//
|
//
|
||||||
// By requiring that allocations in a buffer only come from the most recent memory_buffer
|
// By requiring that allocations in a buffer only come from the most recent memory_buffer
|
||||||
// we can very easily rewind the buffer to the correct location.
|
// we can very easily rewind the buffer to the correct location.
|
||||||
// Hence FindAddress_InLastBufferOnly
|
// Hence FindAddress_InLastBufferOnly
|
||||||
enum gs_memory_find_address_rule
|
enum gs_memory_find_address_rule
|
||||||
{
|
{
|
||||||
|
@ -192,9 +192,21 @@ enum gs_memory_find_address_rule
|
||||||
FindAddress_Count,
|
FindAddress_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void* gs_memory_alloc(gs_mem_u32 Size);
|
#define PLATFORM_ALLOC(name) u8* name(s32 Size)
|
||||||
typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize);
|
typedef PLATFORM_ALLOC(platform_alloc);
|
||||||
typedef void gs_memory_free(void* Address, gs_mem_u32 Size);
|
|
||||||
|
#define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size)
|
||||||
|
typedef PLATFORM_FREE(platform_free);
|
||||||
|
|
||||||
|
#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize)
|
||||||
|
typedef PLATFORM_REALLOC(platform_realloc);
|
||||||
|
|
||||||
|
struct platform_memory_handler
|
||||||
|
{
|
||||||
|
platform_alloc* Alloc;
|
||||||
|
platform_free* Free;
|
||||||
|
platform_realloc* Realloc;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef GS_MEMORY_BUFFER_SIZE
|
#ifndef GS_MEMORY_BUFFER_SIZE
|
||||||
#define GS_MEMORY_BUFFER_SIZE 1024
|
#define GS_MEMORY_BUFFER_SIZE 1024
|
||||||
|
@ -237,8 +249,8 @@ struct memory_arena
|
||||||
|
|
||||||
gs_memory_find_address_rule FindAddressRule;
|
gs_memory_find_address_rule FindAddressRule;
|
||||||
gs_memory_expansion_rule ExpansionRule;
|
gs_memory_expansion_rule ExpansionRule;
|
||||||
gs_memory_alloc* Alloc;
|
|
||||||
gs_memory_realloc* Realloc;
|
platform_memory_handler PlatformMemory;
|
||||||
|
|
||||||
#ifdef GS_MEMORY_TRACK_ALLOCATIONS
|
#ifdef GS_MEMORY_TRACK_ALLOCATIONS
|
||||||
tracked_allocation_buffer** AllocationBuffers;
|
tracked_allocation_buffer** AllocationBuffers;
|
||||||
|
@ -266,31 +278,62 @@ struct arena_snapshot
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PlatformFreeArray(platform, base, type, count) PlatformFree((platform), (gs_mem_u8*)(base), sizeof(type) * (count))
|
||||||
|
#define ArenaFree(arena, base, size) PlatformFree((arena).PlatformMemory, (gs_mem_u8*)(base), (gs_mem_u32)(size))
|
||||||
static void
|
static void
|
||||||
FreeMemoryArena(memory_arena* Arena, gs_memory_free* Free = 0)
|
PlatformFree(platform_memory_handler Platform, gs_mem_u8* Base, gs_mem_u32 Size)
|
||||||
{
|
{
|
||||||
if (Free)
|
Assert(Platform.Free != 0);
|
||||||
|
Platform.Free(Base, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PlatformAllocArray(platform, type, size) (type*)PlatformAlloc((platform), sizeof(type) * (size))
|
||||||
|
#define ArenaAlloc(arena, size) PlatformAlloc((arena).PlatformMemory, (gs_mem_u32)(size))
|
||||||
|
#define ArenaAllocStruct(arena, type) (type*)PlatformAlloc((arena).PlatformMemory, sizeof(type))
|
||||||
|
#define ArenaAllocArray(arena, type, size) (type*)PlatformAlloc((arena).PlatformMemory, sizeof(type) * (size))
|
||||||
|
static gs_mem_u8*
|
||||||
|
PlatformAlloc(platform_memory_handler Platform, gs_mem_u32 Size)
|
||||||
|
{
|
||||||
|
Assert(Platform.Alloc != 0);
|
||||||
|
gs_mem_u8* Result = Platform.Alloc(Size);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ArenaRealloc(arena, base, oldSize, newSize) PlatformRealloc((arena).PlatformMemory, (gs_mem_u8*)(base), (gs_mem_u32)(oldSize), (gs_mem_u32)(newSize))
|
||||||
|
#define ArenaReallocArray(arena, base, type, oldCount, newCount) (type*)PlatformRealloc((arena).PlatformMemory, (gs_mem_u8*)(base), sizeof(type) * oldCount, sizeof(type) * newCount)
|
||||||
|
static gs_mem_u8*
|
||||||
|
PlatformRealloc(platform_memory_handler Platform, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize)
|
||||||
|
{
|
||||||
|
gs_mem_u8* Result = 0;
|
||||||
|
if (Platform.Realloc != 0)
|
||||||
{
|
{
|
||||||
for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++)
|
Result = Platform.Realloc(Head, OldSize, NewSize);
|
||||||
|
}
|
||||||
|
else if (Platform.Alloc != 0 && Platform.Free != 0)
|
||||||
|
{
|
||||||
|
Result = PlatformAlloc(Platform, NewSize);
|
||||||
|
if (Head != 0 && OldSize != 0)
|
||||||
{
|
{
|
||||||
memory_buffer* Buffer = Arena->Buffers + i;
|
GSMemCopy(Head, Result, OldSize);
|
||||||
Free(Buffer->Buffer, Buffer->Size);
|
PlatformFree(Platform, Head, OldSize);
|
||||||
}
|
}
|
||||||
Free(Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef GS_MEMORY_NO_STD_LIBS
|
InvalidCodePath;
|
||||||
GSMem_Assert(0);
|
|
||||||
#else
|
|
||||||
for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++)
|
|
||||||
{
|
|
||||||
memory_buffer* Buffer = Arena->Buffers + i;
|
|
||||||
free(Buffer->Buffer);
|
|
||||||
}
|
|
||||||
free(Arena->Buffers);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FreeMemoryArena(memory_arena* Arena)
|
||||||
|
{
|
||||||
|
for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++)
|
||||||
|
{
|
||||||
|
memory_buffer* Buffer = Arena->Buffers + i;
|
||||||
|
PlatformFree(Arena->PlatformMemory, Buffer->Buffer, Buffer->Size);
|
||||||
|
}
|
||||||
|
PlatformFree(Arena->PlatformMemory, (u8*)Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0))
|
#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0))
|
||||||
|
@ -340,53 +383,7 @@ FindAlignedAddressInBufferWithRoom(memory_arena* Arena, gs_mem_u32 Size, gs_mem_
|
||||||
Result = AddressInCurrentBuffer;
|
Result = AddressInCurrentBuffer;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gs_mem_u8*
|
|
||||||
ArenaAlloc(memory_arena* Arena, gs_mem_u32 Size)
|
|
||||||
{
|
|
||||||
gs_mem_u8* Result = 0;
|
|
||||||
|
|
||||||
if (Arena->Alloc)
|
|
||||||
{
|
|
||||||
Result = (gs_mem_u8*)Arena->Alloc(sizeof(gs_mem_u8) * Size);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef GS_MEMORY_NO_STD_LIBS
|
|
||||||
// NOTE(Peter): If you specify no std libs AND don't supply a allocation function
|
|
||||||
// we should assert as this is an invalid codepath
|
|
||||||
GSMem_Assert(0);
|
|
||||||
#else
|
|
||||||
Result = (gs_mem_u8*)malloc(sizeof(gs_mem_u8) * Size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gs_mem_u8*
|
|
||||||
ArenaRealloc(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize)
|
|
||||||
{
|
|
||||||
gs_mem_u8* Result = 0;
|
|
||||||
|
|
||||||
if (Arena->Realloc != 0)
|
|
||||||
{
|
|
||||||
Result = (gs_mem_u8*)Arena->Realloc(Head, OldSize, NewSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef GS_MEMORY_NO_STD_LIBS
|
|
||||||
// NOTE(Peter): If you specify no std libs AND don't supply a reallocation function
|
|
||||||
// we should assert as this is an invalid codepath
|
|
||||||
GSMem_Assert(0);
|
|
||||||
#else
|
|
||||||
Result = (gs_mem_u8*)realloc(Head, NewSize);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,15 +391,13 @@ static memory_buffer*
|
||||||
GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded)
|
GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded)
|
||||||
{
|
{
|
||||||
GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed);
|
GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed);
|
||||||
if (Arena->ExpansionRule == MemoryExpansion_OnlyIfFunctionsProvided)
|
|
||||||
{
|
|
||||||
GSMem_Assert((Arena->Alloc != 0) && (Arena->Realloc != 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1);
|
gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1);
|
||||||
|
#if 0
|
||||||
gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount;
|
gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount;
|
||||||
gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount;
|
gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount;
|
||||||
Arena->Buffers = (memory_buffer*)ArenaRealloc(Arena, (gs_mem_u8*)Arena->Buffers, OldBuffersSize, NewBuffersSize);
|
#endif
|
||||||
|
Arena->Buffers = ArenaReallocArray(*Arena, Arena->Buffers, memory_buffer, Arena->BuffersCount, NewBuffersCount);
|
||||||
Arena->BuffersCount = NewBuffersCount;
|
Arena->BuffersCount = NewBuffersCount;
|
||||||
|
|
||||||
memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1);
|
memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1);
|
||||||
|
@ -412,7 +407,7 @@ GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded)
|
||||||
NewBuffer->Size = SizeNeeded;
|
NewBuffer->Size = SizeNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
NewBuffer->Buffer = ArenaAlloc(Arena, sizeof(gs_mem_u8) * NewBuffer->Size);
|
NewBuffer->Buffer = ArenaAllocArray(*Arena, gs_mem_u8, NewBuffer->Size);
|
||||||
NewBuffer->Used = 0;
|
NewBuffer->Used = 0;
|
||||||
|
|
||||||
Arena->TotalSize += NewBuffer->Size;
|
Arena->TotalSize += NewBuffer->Size;
|
||||||
|
@ -433,14 +428,20 @@ TrackAllocation(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 Size, char* Fil
|
||||||
if (Arena->AllocationsUsed >= AllocationsMax)
|
if (Arena->AllocationsUsed >= AllocationsMax)
|
||||||
{
|
{
|
||||||
gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1;
|
gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1;
|
||||||
Arena->AllocationBuffers = (tracked_allocation_buffer**)ArenaRealloc(Arena,
|
#if 0
|
||||||
(gs_mem_u8*)Arena->AllocationBuffers,
|
gs_mem_u32 OldSize = Arena->AllocationBuffersCount * sizeof(void*);
|
||||||
Arena->AllocationBuffersCount * sizeof(void*),
|
gs_mem_u32 NewSize = NewAllocationBuffersCount * sizeof(void*);
|
||||||
NewAllocationBuffersCount * sizeof(void*));
|
Arena->AllocationBuffers = (tracked_allocation_buffer**)PlatformRealloc(Arena->PlatformMemory,
|
||||||
|
(gs_mem_u8*)Arena->AllocationBuffers,
|
||||||
|
OldSize, NewSize);
|
||||||
|
#else
|
||||||
|
Arena->AllocationBuffers = ArenaReallocArray(*Arena, Arena->AllocationBuffers, tracked_allocation_buffer*, Arena->AllocationBuffersCount, NewAllocationBuffersCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
Arena->AllocationBuffersCount = NewAllocationBuffersCount;
|
Arena->AllocationBuffersCount = NewAllocationBuffersCount;
|
||||||
|
|
||||||
gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1;
|
gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1;
|
||||||
Arena->AllocationBuffers[NewBufferIndex] = (tracked_allocation_buffer*)ArenaAlloc(Arena, sizeof(tracked_allocation_buffer));
|
Arena->AllocationBuffers[NewBufferIndex] = ArenaAllocStruct(*Arena, tracked_allocation_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++;
|
gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++;
|
||||||
|
@ -474,8 +475,8 @@ VerifyAllocationNoOverflow (tracked_allocation Allocation)
|
||||||
static void
|
static void
|
||||||
AssertAllocationsNoOverflow (memory_arena Arena)
|
AssertAllocationsNoOverflow (memory_arena Arena)
|
||||||
{
|
{
|
||||||
for (gs_mem_u32 AllocationIndex = 0;
|
for (gs_mem_u32 AllocationIndex = 0;
|
||||||
AllocationIndex< Arena.AllocationsUsed;
|
AllocationIndex< Arena.AllocationsUsed;
|
||||||
AllocationIndex++)
|
AllocationIndex++)
|
||||||
{
|
{
|
||||||
gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE;
|
gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE;
|
||||||
|
@ -502,7 +503,7 @@ AssertAllocationsNoOverflow (memory_arena Arena)
|
||||||
#define ClearAllocationsUsed(arena)
|
#define ClearAllocationsUsed(arena)
|
||||||
#define ClearAllocationsUsedToSnapshot(arena, snapshot)
|
#define ClearAllocationsUsedToSnapshot(arena, snapshot)
|
||||||
|
|
||||||
#define TrackAllocation(arena, head, size, filename, linenumber)
|
#define TrackAllocation(arena, head, size, filename, linenumber)
|
||||||
|
|
||||||
#define PushSize(arena, size) PushSize_((arena), (size))
|
#define PushSize(arena, size) PushSize_((arena), (size))
|
||||||
#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length)
|
#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length)
|
||||||
|
@ -517,7 +518,7 @@ static gs_mem_u8*
|
||||||
PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0)
|
PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0)
|
||||||
{
|
{
|
||||||
// ie. Alignment = 4 = 100 (binary)
|
// ie. Alignment = 4 = 100 (binary)
|
||||||
// 4 - 1 = 3
|
// 4 - 1 = 3
|
||||||
// 100 - 1 = 011 which is a mask of the bits we don't want set in the start address
|
// 100 - 1 = 011 which is a mask of the bits we don't want set in the start address
|
||||||
GSMem_Assert(IsPowerOfTwo(Alignment));
|
GSMem_Assert(IsPowerOfTwo(Alignment));
|
||||||
gs_mem_u32 AlignmentMask = Alignment - 1;
|
gs_mem_u32 AlignmentMask = Alignment - 1;
|
||||||
|
@ -560,7 +561,7 @@ ClearArena(memory_arena* Arena)
|
||||||
{
|
{
|
||||||
memory_buffer* At = Arena->Buffers + i;
|
memory_buffer* At = Arena->Buffers + i;
|
||||||
At->Used = 0;
|
At->Used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena->TotalUsed = 0;
|
Arena->TotalUsed = 0;
|
||||||
ClearAllocationsUsed(Arena);
|
ClearAllocationsUsed(Arena);
|
||||||
|
|
Loading…
Reference in New Issue