diff --git a/build/build_app_msvc_win32_debug.bat b/build/build_app_msvc_win32_debug.bat index e38e31d..6151e16 100644 --- a/build/build_app_msvc_win32_debug.bat +++ b/build/build_app_msvc_win32_debug.bat @@ -16,7 +16,7 @@ pushd %BuildPath% del *.pdb > NUL 2> NUL REM Run the Preprocessor -%MetaProgramPath%\foldhaus_meta.exe %SourceCodePath%\foldhaus_app.cpp +REM %MetaProgramPath%\foldhaus_meta.exe %SourceCodePath%\foldhaus_app.cpp echo WAITING FOR PDB TO WRITE > lock.tmp diff --git a/src/app/animation/foldhaus_animation.h b/src/app/animation/foldhaus_animation.h index 0c22ee7..613a940 100644 --- a/src/app/animation/foldhaus_animation.h +++ b/src/app/animation/foldhaus_animation.h @@ -31,7 +31,7 @@ enum blend_mode struct anim_layer { - string Name; + gs_string Name; blend_mode BlendMode; }; @@ -39,7 +39,7 @@ struct anim_layer #define ANIMATION_SYSTEM_BLOCKS_MAX 128 struct animation_system { - memory_arena* Storage; + gs_memory_arena* Storage; gs_list Blocks; anim_layer* Layers; @@ -75,7 +75,7 @@ FrameIsInRange(s32 Frame, frame_range Range) internal u32 GetFrameCount(frame_range Range) { - u32 Result = (u32)GSMax(0, Range.Max - Range.Min); + u32 Result = (u32)Max(0, Range.Max - Range.Min); return Result; } @@ -133,7 +133,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim // Layers internal u32 -AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) +AddLayer (gs_string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite) { // NOTE(Peter): If this assert fires its time to make the layer buffer system // resizable. @@ -144,7 +144,7 @@ AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = anim_layer* NewLayer = AnimationSystem->Layers + Result; *NewLayer = {0}; NewLayer->Name = MakeString(PushArray(AnimationSystem->Storage, char, Name.Length), Name.Length); - CopyStringTo(Name, &NewLayer->Name); + PrintF(&NewLayer->Name, "%S", Name); NewLayer->BlendMode = BlendMode; return Result; } diff --git a/src/app/assembly_parser.cpp b/src/app/assembly_parser.cpp index 4b06fc7..8e229e0 100644 --- a/src/app/assembly_parser.cpp +++ b/src/app/assembly_parser.cpp @@ -28,7 +28,7 @@ enum assembly_field AssemblyField_Count, }; -global_variable char* AssemblyFieldIdentifiers[] = { +global char* AssemblyFieldIdentifiers[] = { "assembly_name", // AssemblyField_AssemblyName "assembly_scale", // AssemblyField_AssemblyScale "led_strip_count", // AssemblyField_LedStripCount @@ -52,20 +52,32 @@ global_variable char* AssemblyFieldIdentifiers[] = { "value", // AssemblyField_Value }; +struct assembly_error_list +{ + gs_string String; + assembly_error_list* Next; +}; + struct assembly_tokenizer { - string Text; + gs_string Text; char* At; + gs_const_string FileName; u32 LineNumber; bool ParsingIsValid; + + gs_memory_arena* ErrorArena; + assembly_error_list* ErrorsRoot; + assembly_error_list* ErrorsTail; }; internal bool AtValidPosition(assembly_tokenizer* T) { - bool Result = ((T->At - T->Text.Memory) < T->Text.Length); + u64 Offset = T->At - T->Text.Str; + bool Result = (Offset < T->Text.Length); return Result; } @@ -88,6 +100,16 @@ EatWhitespace(assembly_tokenizer* T) } } +internal void +EatToNewLine(assembly_tokenizer* T) +{ + while(AtValidPosition(T) && !IsNewline(T->At[0])) + { + AdvanceChar(T); + } + EatWhitespace(T); +} + internal bool AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value) { @@ -118,6 +140,22 @@ AdvanceIfTokenEquals(assembly_tokenizer* T, char* Value) return Result; } +internal void +TokenizerPushError(assembly_tokenizer* T, char* ErrorString) +{ + // NOTE(Peter): We can make this more expressive if we need to + assembly_error_list* Error = PushStruct(T->ErrorArena, assembly_error_list); + Error->String = PushString(T->ErrorArena, 512); + PrintF(&Error->String, "%S(%d): %s", T->FileName, T->LineNumber, ErrorString); + SLLPushOrInit(T->ErrorsRoot, T->ErrorsTail, Error); + T->ParsingIsValid = false; + + // NOTE(Peter): I'm not sure this is the best idea, but at least this way, + // if there's multiple errors, you'll get a number of them, rather than + // a bunch of erroneous errors happening on the same line + EatToNewLine(T); +} + internal bool ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) { @@ -130,12 +168,12 @@ ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T) } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Field identifier is missing a colon"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Field Identifier Invalid"); } return Result; } @@ -150,15 +188,15 @@ ReadFieldEnd(assembly_tokenizer* T) } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Missing a semicolon"); } return Result; } -internal string +internal gs_string ReadString(assembly_tokenizer* T) { - string Result = {}; + gs_string Result = {}; if (AdvanceIfTokenEquals(T, "\"")) { char* StringStart = T->At; @@ -166,32 +204,36 @@ ReadString(assembly_tokenizer* T) { T->At++; } - Result.Memory = StringStart; - Result.Max = T->At - StringStart; - Result.Length = Result.Max; + Result.Str = StringStart; + Result.Size = T->At - StringStart; + Result.Length = Result.Size; if (AdvanceIfTokenEquals(T, "\"")) { // Success } else { - // TODO(Peter): Error + TokenizerPushError(T, "String not closed with a \""); } } + else + { + TokenizerPushError(T, "Expecting a string, but none was found"); + } return Result; } -internal string +internal gs_string GetNumberString(assembly_tokenizer* T) { - string Result = {}; - Result.Memory = T->At; + gs_string Result = {}; + Result.Str = T->At; while(AtValidPosition(T) && IsNumericExtended(T->At[0])) { AdvanceChar(T); } - Result.Length = T->At - Result.Memory; - Result.Max = Result.Length; + Result.Length = T->At - Result.Str; + Result.Size = Result.Length; return Result; } @@ -199,9 +241,8 @@ internal r32 ReadFloat(assembly_tokenizer* T) { r32 Result = 0; - string NumberString = GetNumberString(T); - parse_result ParsedFloat = ParseFloat(StringExpand(NumberString)); - Result = ParsedFloat.FloatValue; + gs_string NumberString = GetNumberString(T); + Result = (r32)ParseFloat(NumberString.ConstString); return Result; } @@ -209,28 +250,23 @@ internal s32 ReadInt(assembly_tokenizer* T) { s32 Result = 0; - string NumberString = GetNumberString(T); - parse_result ParsedInt = ParseSignedInt(StringExpand(NumberString)); - Result = ParsedInt.SignedIntValue; + gs_string NumberString = GetNumberString(T); + Result = (r32)ParseInt(NumberString.ConstString); return Result; } -internal string -ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena) +internal gs_string +ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena) { - string Result = {}; + gs_string Result = {}; if (ReadFieldIdentifier(Field, T)) { - string ExistingString = ReadString(T); + gs_string ExistingString = ReadString(T); if (ReadFieldEnd(T)) { // Success Result = PushString(Arena, ExistingString.Length); - CopyStringTo(ExistingString, &Result); - } - else - { - T->ParsingIsValid = false; + PrintF(&Result, "%S", ExistingString); } } return Result; @@ -290,22 +326,22 @@ ReadV3Field(assembly_field Field, assembly_tokenizer* T) } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3 doesn't end with a ')'"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3: unable to read a field"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3: unable to read a field"); } } else { - T->ParsingIsValid = false; + TokenizerPushError(T, "Vector 3: unable to read a field"); } } return Result; @@ -333,14 +369,18 @@ ReadStructClosing(assembly_tokenizer* T) } internal bool -ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) +ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient) { Assembly->LedCountTotal = 0; + r32 Value = ParseFloat(ConstString("-2.355")); + assembly_tokenizer Tokenizer = {}; Tokenizer.Text = FileText; - Tokenizer.At = Tokenizer.Text.Memory; + Tokenizer.At = Tokenizer.Text.Str; Tokenizer.ParsingIsValid = true; + Tokenizer.ErrorArena = Transient; + Tokenizer.FileName = FileName; Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena); Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer); @@ -358,7 +398,7 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) StripAt->StartChannel = ReadIntField(AssemblyField_StartChannel, &Tokenizer); // TODO(Peter): Need to store this - string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); + gs_string PointPlacementType = ReadStringField(AssemblyField_PointPlacementType, &Tokenizer, &Assembly->Arena); // TODO(Peter): Switch on value of PointPlacementType if (ReadStructOpening(AssemblyField_InterpolatePoints, &Tokenizer)) { @@ -367,6 +407,10 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) if (!ReadStructClosing(&Tokenizer)) { Tokenizer.ParsingIsValid = false; + // TODO(Peter): @ErrorHandling + // Have this function prepend the filename and line number. + // Create an error display popup window, or an error log window that takes over a panel automatically + // TokenizerPushError(&Tokenizer, "Unable to read } } @@ -380,31 +424,31 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient) v2_tag* TagAt = StripAt->Tags + Tag; if (ReadStructOpening(AssemblyField_Tag, &Tokenizer)) { - // TODO(Peter): Need to store the string somewhere we can look it up for display in the interface + // TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface // right now they are stored in temp memory and won't persist - string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); - string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); - TagAt->NameHash = HashString(TagName); - TagAt->ValueHash = HashString(TagValue); + gs_string TagName = ReadStringField(AssemblyField_Name, &Tokenizer, Transient); + gs_string TagValue = ReadStringField(AssemblyField_Value, &Tokenizer, Transient); + TagAt->NameHash = HashDJB2ToU32(StringExpand(TagName)); + TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue)); if (!ReadStructClosing(&Tokenizer)) { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } else { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); } } if (!ReadStructClosing(&Tokenizer)) { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Struct doesn't close where expected"); } } else { - Tokenizer.ParsingIsValid = false; + TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found"); } } diff --git a/src/app/foldhaus_default_nodes.h b/src/app/deprecated/foldhaus_default_nodes.h similarity index 90% rename from src/app/foldhaus_default_nodes.h rename to src/app/deprecated/foldhaus_default_nodes.h index 7083ce2..3fddaa0 100644 --- a/src/app/foldhaus_default_nodes.h +++ b/src/app/deprecated/foldhaus_default_nodes.h @@ -100,10 +100,10 @@ NODE_PROC(SinWave, sin_wave_data) 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); + r32 ActualMin = Min(Data->Min, Data->Max); + r32 ActualMax = Max(Data->Min, Data->Max); + r32 SinResult = SinR32((Data->Accumulator / Data->Period) * PiR32 * 2); + Data->Result = RemapR32(SinResult, -1.f, 1.f, ActualMin, ActualMax); } else { diff --git a/src/app/panels/foldhaus_panel_node_graph.h b/src/app/deprecated/foldhaus_panel_node_graph.h similarity index 92% rename from src/app/panels/foldhaus_panel_node_graph.h rename to src/app/deprecated/foldhaus_panel_node_graph.h index 80aa175..6830d2f 100644 --- a/src/app/panels/foldhaus_panel_node_graph.h +++ b/src/app/deprecated/foldhaus_panel_node_graph.h @@ -15,7 +15,7 @@ struct visual_port { gs_list_handle SparseNodeHandle; u32 PortIndex; - rect PortBounds; + rect2 PortBounds; }; struct visual_connection @@ -57,7 +57,7 @@ struct node_graph_state { v2 ViewOffset; - memory_arena LayoutMemory; + gs_memory_arena LayoutMemory; node_layout Layout; b32 LayoutIsDirty; @@ -128,7 +128,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndConnectNodesOperation) for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++) { visual_port VisualPort = GraphState->Layout.VisualPorts[p]; - rect ViewAdjustedBounds = gs_RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset); + rect2 ViewAdjustedBounds = gs_RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset); if (gs_PointIsInRect(Mouse.Pos, ViewAdjustedBounds)) { visual_port UpstreamPort = (OpState->IsInput & IsInputMember) ? VisualPort : OpState->VisualPort; @@ -196,7 +196,7 @@ NodeGraph_Cleanup(panel* Panel, app_state* State) } internal void -DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer* RenderBuffer) +DrawGrid (v2 Offset, v2 GridSquareDim, rect2 PanelBounds, render_command_buffer* RenderBuffer) { r32 LineValue = .16f; v4 LineColor = v4{LineValue, LineValue, LineValue, 1.f}; @@ -232,9 +232,9 @@ DrawGrid (v2 Offset, v2 GridSquareDim, rect PanelBounds, render_command_buffer* } internal void -DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, r32 LineHeight, string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse) +DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, r32 LineHeight, gs_string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse) { - rect PortBounds = rect{v2{0, 0}, v2{6, 6}}; + rect2 PortBounds = rect2{v2{0, 0}, v2{6, 6}}; v2 LinePosition = Position; for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++) @@ -244,7 +244,7 @@ DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, { // TODO(Peter): Can we make this rely on the same data that we use to // render the actual connection points? - string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); + gs_string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign); LinePosition.y -= LineHeight; } @@ -252,7 +252,7 @@ DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, } internal void -DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle NodeHandle, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse, memory_arena* Scratch) +DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle NodeHandle, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse, gs_memory_arena* Scratch) { gsm_struct_type_info NodeDataTypeInfo = StructTypes[NodeSpecification.DataType]; @@ -264,13 +264,13 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod if (MemberIsInput(Member)) { InputMembers++; } if (MemberIsOutput(Member)) { OutputMembers++; } } - u32 LineCount = 1 + GSMax(InputMembers, OutputMembers); + u32 LineCount = 1 + Max(InputMembers, OutputMembers); v2 NodeDim = v2{ NodeWidth, (LineHeight * LineCount) + Interface.Margin.y, }; - rect NodeBounds = rect{ + rect2 NodeBounds = rect2{ v2{ Position.x, Position.y - NodeDim.y }, v2{ Position.x + NodeDim.x, Position.y }, }; @@ -282,7 +282,7 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod PushRenderQuad2D(RenderBuffer, LinePosition, LinePosition + v2{NodeWidth, LineHeight}, v4{1.f, .24f, .39f, 1.f}); - string NodePrintName = MakeString(PushArray(Scratch, char, 256), 0, 256); + gs_string NodePrintName = MakeString(PushArray(Scratch, char, 256), 0, 256); PrintF(&NodePrintName, "%S [%d]", NodeSpecification.Identifier, NodeHandle.Index); DrawString(RenderBuffer, NodePrintName, Interface.Font, LinePosition + TextOffset, WhiteV4); LinePosition.y -= LineHeight; @@ -293,7 +293,7 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++) { gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i]; - string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); + gs_string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); // TODO(Peter): Can we make this rely on the same data that we use to // render the actual connection points? @@ -329,7 +329,7 @@ GetVisualPortIndexForNode(gs_list_handle SparseNodeHandle, u32 PortIndex, node_l } internal node_layout -ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, r32 LineHeight, memory_arena* Storage, app_state* State) +ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, r32 LineHeight, gs_memory_arena* Storage, app_state* State) { node_layout Result = {}; @@ -373,7 +373,7 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, { gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[p]; - rect PortBounds = {0}; + rect2 PortBounds = {0}; v2 PortDim = v2{8, 8}; PortBounds.Min = VisualNode->Position + v2{0, PortDim.y / 2}; if (MemberIsInput(Member)) @@ -420,16 +420,16 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, GSMetaTag(panel_render); GSMetaTag(panel_type_node_graph); internal void -NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +NodeGraph_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { node_graph_state* GraphState = (node_graph_state*)Panel.PanelStateMemory; b32 MouseHandled = false; - rect NodeSelectionWindowBounds = rect{ + rect2 NodeSelectionWindowBounds = rect2{ PanelBounds.Min, v2{PanelBounds.Min.x + 300, PanelBounds.Max.y}, }; - rect GraphBounds = rect{ + rect2 GraphBounds = rect2{ v2{NodeSelectionWindowBounds.Max.x, PanelBounds.Min.y}, PanelBounds.Max, }; @@ -513,18 +513,18 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf List.TextColor = WhiteV4; List.ListBounds = NodeSelectionWindowBounds; List.ListElementDimensions = v2{ - gs_Width(NodeSelectionWindowBounds), + Rect2Width(NodeSelectionWindowBounds), ui_GetTextLineHeight(State->Interface) }; List.ElementLabelIndent = v2{10, 4}; - string TitleString = MakeStringLiteral("Available Nodes"); - DrawListElement(TitleString, &List, Context.Mouse, RenderBuffer, State->Interface.Style); + gs_string Titlegs_string = MakeStringLiteral("Available Nodes"); + DrawListElement(Titlegs_string, &List, Context.Mouse, RenderBuffer, State->Interface.Style); for (u32 i = 0; i < NodeType_Count; i++) { node_specification_ Spec = NodeSpecifications[i]; - rect ElementBounds = DrawListElement(Spec.Identifier, &List, Context.Mouse, RenderBuffer, State->Interface.Style); + rect2 ElementBounds = DrawListElement(Spec.Identifier, &List, Context.Mouse, RenderBuffer, State->Interface.Style); if (MouseButtonTransitionedDown(Context.Mouse.LeftButtonState) && gs_PointIsInRect(Context.Mouse.DownPos, ElementBounds)) diff --git a/src/app/foldhaus_search_lister.cpp b/src/app/deprecated/foldhaus_search_lister.cpp similarity index 68% rename from src/app/foldhaus_search_lister.cpp rename to src/app/deprecated/foldhaus_search_lister.cpp index 78734b5..cb0725b 100644 --- a/src/app/foldhaus_search_lister.cpp +++ b/src/app/deprecated/foldhaus_search_lister.cpp @@ -6,7 +6,7 @@ #ifndef FOLDHAUS_SEARCH_LISTER_CPP internal b32 -NamePassesFilter (string Target, string Filter) +NamePassesFilter (gs_string Target, gs_string Filter) { return (Filter.Length == 0 || StringContainsStringCaseInsensitive(Target, Filter)); } @@ -21,14 +21,14 @@ FilterSearchLister (search_lister* SearchLister) for (s32 i = 0; i < SearchLister->SourceListCount; i++) { - string* NameString = SearchLister->SourceList + i; - if (NamePassesFilter(*NameString, SearchLister->Filter)) + gs_string* Namegs_string = SearchLister->SourceList + i; + if (NamePassesFilter(*Namegs_string, SearchLister->Filter)) { SearchLister->FilteredIndexLUT[SearchLister->FilteredListCount++] = i; } } - SearchLister->HotItem = GSClamp(0, SearchLister->HotItem, SearchLister->FilteredListCount - 1); + SearchLister->HotItem = Clamp(0, SearchLister->HotItem, SearchLister->FilteredListCount - 1); if (SearchLister->FilteredListCount == 0) { @@ -39,14 +39,14 @@ FilterSearchLister (search_lister* SearchLister) internal s32 GetNextFilteredItem (search_lister SearchLister) { - s32 Result = GSMin(SearchLister.HotItem + 1, SearchLister.FilteredListCount - 1); + s32 Result = Min(SearchLister.HotItem + 1, SearchLister.FilteredListCount - 1); return Result; } internal s32 GetPrevFilteredItem (search_lister SearchLister) { - s32 Result = GSMax(SearchLister.HotItem - 1, 0); + s32 Result = Max(SearchLister.HotItem - 1, 0); return Result; } diff --git a/src/app/foldhaus_search_lister.h b/src/app/deprecated/foldhaus_search_lister.h similarity index 81% rename from src/app/foldhaus_search_lister.h rename to src/app/deprecated/foldhaus_search_lister.h index 8cc4d15..e2d502e 100644 --- a/src/app/foldhaus_search_lister.h +++ b/src/app/deprecated/foldhaus_search_lister.h @@ -8,11 +8,11 @@ struct search_lister { // TODO(Peter): Giving up trying to just use the source list for now. At the moment - // we are copying the strings you want to filter from and storing them here. Come back + // we are copying the gs_strings you want to filter from and storing them here. Come back // once its working and make the memory efficient version (ie store the existing memory // location, the element stride and the offset to the char*) s32 SourceListCount; - string* SourceList; + gs_string* SourceList; // NOTE(Peter): stores the source indecies of each filtered item // For example: @@ -23,7 +23,7 @@ struct search_lister s32* FilteredIndexLUT; s32 HotItem; - string Filter; + gs_string Filter; }; diff --git a/src/app/foldhaus_text_entry.cpp b/src/app/deprecated/foldhaus_text_entry.cpp similarity index 88% rename from src/app/foldhaus_text_entry.cpp rename to src/app/deprecated/foldhaus_text_entry.cpp index 1d59e10..7deb830 100644 --- a/src/app/foldhaus_text_entry.cpp +++ b/src/app/deprecated/foldhaus_text_entry.cpp @@ -17,15 +17,14 @@ PipeSearchStringToDestination (text_entry* Input) { switch (Input->Destination.Type) { - case TextTranslateTo_String: + case TextTranslateTo_gs_string: { - CopyStringTo(Input->Buffer, Input->Destination.StringDest); + PrintF(Input->Destination.StringDest, "%S", Input->Buffer); }break; case TextTranslateTo_R32: { - parse_result FloatParseResult = ParseFloat(StringExpand(Input->Buffer)); - *Input->Destination.FloatDest = FloatParseResult.FloatValue; + *Input->Destination.FloatDest = (r32)ParseFloat(Input->Buffer.ConstString); }break; InvalidDefaultCase; @@ -37,19 +36,22 @@ RemoveCharacterAtCursor (text_entry* TextEntry) { if (TextEntry->CursorPosition > 0) { - RemoveCharAt(&TextEntry->Buffer, - TextEntry->CursorPosition - 1); + for (u32 i = TextEntry->CursorPosition - 1; i < TextEntry->Buffer.Length; i++) + { + Assert(i + 1 < TextEntry->Buffer.Size); + TextEntry->Buffer.Str[i] = TextEntry->Buffer.Str[i + 1]; + } TextEntry->CursorPosition--; } } -internal void -SetTextInputDestinationToString (text_entry* TextInput, string* DestinationString) +internal void +SetTextInputDestinationToString (text_entry* TextInput, gs_string* DestinationString) { ResetTextInput(TextInput); - TextInput->Destination.Type = TextTranslateTo_String; + TextInput->Destination.Type = TextTranslateTo_gs_string; TextInput->Destination.StringDest = DestinationString; - CopyStringTo(*DestinationString, &TextInput->Buffer); + PrintF(&TextInput->Buffer, "%S", *DestinationString); } internal void @@ -69,14 +71,13 @@ SetTextInputDestinationToFloat (text_entry* TextInput, r32* DestinationFloat) internal void MoveCursorRight (text_entry* TextEntry) { - TextEntry->CursorPosition = GSMin(TextEntry->Buffer.Length, - TextEntry->CursorPosition + 1); + TextEntry->CursorPosition = Min(TextEntry->Buffer.Length, TextEntry->CursorPosition + 1); } internal void MoveCursorLeft (text_entry* TextEntry) { - TextEntry->CursorPosition = GSMax(0, TextEntry->CursorPosition - 1); + TextEntry->CursorPosition = Max(0, TextEntry->CursorPosition - 1); } FOLDHAUS_INPUT_COMMAND_PROC(TextEntryInsertChar) @@ -88,12 +89,21 @@ FOLDHAUS_INPUT_COMMAND_PROC(TextEntryInsertChar) Char += ('a' - 'A'); } - InsertChar(&State->ActiveTextEntry.Buffer, Char, State->ActiveTextEntry.CursorPosition); + // Shift string forward + Assert(State->ActiveTextEntry.Buffer.Length < State->ActiveTextEntry.Buffer.Size); + for (u32 i = State->ActiveTextEntry.Buffer.Length; + i > (u32)State->ActiveTextEntry.CursorPosition; + i--) + { + State->ActiveTextEntry.Buffer.Str[i] = State->ActiveTextEntry.Buffer.Str[i - 1]; + } + // Insert new Character + State->ActiveTextEntry.Buffer.Str[State->ActiveTextEntry.CursorPosition] = Char; State->ActiveTextEntry.CursorPosition++; PipeSearchStringToDestination(&State->ActiveTextEntry); } -FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntryString) +FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntrygs_string) { RemoveCharacterAtCursor(&State->ActiveTextEntry); } @@ -109,11 +119,11 @@ FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorLeft) } internal void -InitializeTextInputCommands (input_command_registry* Commands, memory_arena* PermanentStorage) +InitializeTextInputCommands (input_command_registry* Commands, gs_memory_arena* PermanentStorage) { if (Commands->Size > 0) { - RegisterKeyPressCommand(Commands, KeyCode_Backspace, Command_Began | Command_Held, KeyCode_Invalid, RemoveCharacterFromEntryString); + RegisterKeyPressCommand(Commands, KeyCode_Backspace, Command_Began | Command_Held, KeyCode_Invalid, RemoveCharacterFromEntrygs_string); RegisterKeyPressCommand(Commands, KeyCode_LeftArrow, Command_Began | Command_Held, KeyCode_Invalid, TextEntryMoveCursorLeft); RegisterKeyPressCommand(Commands, KeyCode_RightArrow, Command_Began | Command_Held, KeyCode_Invalid, TextEntryMoveCursorRight); @@ -126,7 +136,7 @@ InitializeTextInputCommands (input_command_registry* Commands, memory_arena* Per } #define DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY \ -{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, RemoveCharacterFromEntryString }, \ +{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, RemoveCharacterFromEntrygs_string }, \ { KeyCode_LeftArrow, KeyCode_Invalid, Command_Began | Command_Held, TextEntryMoveCursorLeft }, \ { KeyCode_RightArrow, KeyCode_Invalid, Command_Began | Command_Held, TextEntryMoveCursorRight }, \ { KeyCode_a, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \ diff --git a/src/app/foldhaus_text_entry.h b/src/app/deprecated/foldhaus_text_entry.h similarity index 81% rename from src/app/foldhaus_text_entry.h rename to src/app/deprecated/foldhaus_text_entry.h index dd8ba00..e25608f 100644 --- a/src/app/foldhaus_text_entry.h +++ b/src/app/deprecated/foldhaus_text_entry.h @@ -7,7 +7,7 @@ enum text_translation_type { - TextTranslateTo_String, + TextTranslateTo_gs_string, TextTranslateTo_R32, TextTranslateTo_S32, TextTranslateTo_U32, @@ -17,7 +17,7 @@ struct text_entry_destination { text_translation_type Type; union { - string* StringDest; + gs_string* StringDest; r32* FloatDest; s32* SignedIntDest; u32* UnsignedIntDest; @@ -26,7 +26,7 @@ struct text_entry_destination struct text_entry { - string Buffer; + gs_string Buffer; s32 CursorPosition; text_entry_destination Destination; diff --git a/src/app/node/foldhaus_node_interface.cpp b/src/app/deprecated/node/foldhaus_node_interface.cpp similarity index 90% rename from src/app/node/foldhaus_node_interface.cpp rename to src/app/deprecated/node/foldhaus_node_interface.cpp index 0b4c3e4..f4e3b39 100644 --- a/src/app/node/foldhaus_node_interface.cpp +++ b/src/app/deprecated/node/foldhaus_node_interface.cpp @@ -18,7 +18,7 @@ struct node_lister_operation_state }; internal void -RenderNodeLister(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderNodeLister(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { node_lister_operation_state* OpState = (node_lister_operation_state*)Operation.OpStateMemory; @@ -30,7 +30,7 @@ RenderNodeLister(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf FilterSearchLister(&OpState->SearchLister); // Display Search Lister - search_lister_result NodeListerResult = EvaluateSearchLister (&State->Interface_, TopLeft, Dimension, + search_lister_result NodeListerResult = EvaluateSearchLister (&State->Interface_, TopLeft, Dimension, MakeStringLiteral("Nodes List"), OpState->SearchLister.SourceList, OpState->SearchLister.FilteredIndexLUT, @@ -85,12 +85,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) AddNodeOperation->Render = RenderNodeLister; - node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation, - &State->Modes, + node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation, + &State->Modes, node_lister_operation_state); { OpState->SearchLister.SourceListCount = NodeSpecificationsCount; - OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, string, OpState->SearchLister.SourceListCount); + OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, gs_string, OpState->SearchLister.SourceListCount); { for (s32 i = 0; i < OpState->SearchLister.SourceListCount; i++) { @@ -107,7 +107,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister) } OpState->ListPosition = Mouse.Pos; - SetTextInputDestinationToString(&State->ActiveTextEntry, &OpState->SearchLister.Filter); + SetTextInputDestinationTogs_string(&State->ActiveTextEntry, &OpState->SearchLister.Filter); } //////////////////////////////////////// @@ -133,12 +133,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(CloseColorPickerCommand) } internal void -RenderColorPicker(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderColorPicker(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { color_picker_operation_state* OpState = (color_picker_operation_state*)Operation.OpStateMemory; - b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr, + b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr, v2{200, 200}, State->Interface, Mouse); if (ShouldClose) @@ -157,8 +157,8 @@ OpenColorPicker(app_state* State, node_connection* Connection) operation_mode* ColorPickerMode = ActivateOperationModeWithCommands(&State->Modes, ColorPickerCommands); ColorPickerMode->Render = RenderColorPicker; - color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode, - &State->Modes, + color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode, + &State->Modes, color_picker_operation_state); OpState->ValueAddr = Connection->V4ValuePtr; } @@ -184,7 +184,7 @@ input_command NodeFieldTextEditCommands [] = { internal void BeginNodeFieldTextEdit(app_state* State, node_connection* Connection) { - operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes, + operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes, NodeFieldTextEditCommands); SetTextInputDestinationToFloat(&State->ActiveTextEntry, Connection->R32ValuePtr); @@ -202,10 +202,10 @@ struct drag_node_port_operation_state }; internal void -RenderDraggingNodePort(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderDraggingNodePort(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { drag_node_port_operation_state* OpState = (drag_node_port_operation_state*)Operation.OpStateMemory; - UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList, + UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, RenderBuffer); } @@ -225,12 +225,12 @@ internal void BeginDraggingNodePort(app_state* State, node_interaction Interaction) { operation_mode* DragNodePortMode = ActivateOperationModeWithCommands( - &State->Modes, + &State->Modes, DragNodePortInputCommands); DragNodePortMode->Render = RenderDraggingNodePort; - drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode, - &State->Modes, + drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode, + &State->Modes, drag_node_port_operation_state); OpState->Interaction = Interaction; } @@ -242,16 +242,16 @@ BeginDraggingNodePort(app_state* State, node_interaction Interaction) /////////////////////////////////////// internal void -RenderDragNodeField(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderDragNodeField(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { - // TODO(Peter): + // TODO(Peter): //UpdateDraggingNodeValue(Mouse.Pos, Mouse.OldPos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, State); } internal void BeginInteractWithNodeField(app_state* State, node_interaction Interaction) { - // TODO(Peter): + // TODO(Peter): } //////////////////////////////////////// @@ -266,10 +266,10 @@ struct drag_node_operation_state }; internal void -RenderDraggingNode(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderDraggingNode(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { drag_node_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_operation_state); - UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList, + UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList, State->NodeRenderSettings); } @@ -286,12 +286,12 @@ internal void BeginDraggingNode(app_state* State, node_interaction Interaction) { operation_mode* DragNodeMode = ActivateOperationModeWithCommands( - &State->Modes, + &State->Modes, DragNodeInputCommands); DragNodeMode->Render = RenderDraggingNode; - drag_node_operation_state* OpState = CreateOperationState(DragNodeMode, - &State->Modes, + drag_node_operation_state* OpState = CreateOperationState(DragNodeMode, + &State->Modes, drag_node_operation_state); OpState->Interaction = Interaction; } @@ -314,8 +314,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction) node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.DownPos, State->NodeRenderSettings); if (Node) { - node_interaction NewInteraction = GetNodeInteractionType(Node, - Mouse.Pos, + node_interaction NewInteraction = GetNodeInteractionType(Node, + Mouse.Pos, State->NodeRenderSettings); if (IsDraggingNodePort(NewInteraction)) { @@ -324,7 +324,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction) else if(IsDraggingNodeValue(NewInteraction)) { // TODO(Peter): This probably wants to live in a mouse held action - // the first frame we realize we're held over a field, just transition to + // the first frame we realize we're held over a field, just transition to // drag node field //BeginInteractWithNodeField(State, NewInteraction, State->NodeRenderSettings); } @@ -347,8 +347,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction) node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.Pos, State->NodeRenderSettings); if (Node) { - node_interaction NewInteraction = GetNodeInteractionType(Node, - Mouse.Pos, + node_interaction NewInteraction = GetNodeInteractionType(Node, + Mouse.Pos, State->NodeRenderSettings); if(IsDraggingNodeValue(NewInteraction)) { @@ -368,7 +368,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction) } internal void -RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) +RenderNodeView(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse) { node_view_operation_state* OpState = (node_view_operation_state*)Operation.OpStateMemory; @@ -383,7 +383,7 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer { node_header* Node = NodeIter.At; - rect NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings); + rect2 NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings); b32 DrawFields = PointIsInRect(Mouse.Pos, NodeBounds); if (Node == SelectedNode) @@ -394,8 +394,8 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.5f, .5f, .5f, 1.f}); // TODO(Peter): This is just for debug purposes. We can remove and go back to just having - // Node->Name in DrawString - string NodeName = GetNodeName(*Node); + // Node->Name in Drawgs_string + gs_string NodeName = GetNodeName(*Node); PrintF(&NodeHeaderBuffer, "%.*s: %d", NodeName.Length, NodeName.Memory, Node->Handle); DrawString(RenderBuffer, NodeHeaderBuffer, State->NodeRenderSettings.Font, v2{NodeBounds.Min.x + 5, NodeBounds.Max.y - (State->NodeRenderSettings.Font->PixelHeight + NODE_HEADER_HEIGHT + 5)}, @@ -408,12 +408,12 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer // Inputs if (ConnectionIsInput(Node, Connection)) { - rect PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings); + rect2 PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings); DrawPort(RenderBuffer, PortBounds, PortColor); // // TODO(Peter): I don't like excluding OutputNode, feels too much like a special case - // but I don't want to get in to the meta programming right now. + // but I don't want to get in to the meta programming right now. // We should just generate a spec and struct member types for NodeType_OutputNode // // :ExcludingOutputNodeSpecialCase @@ -422,21 +422,21 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer { node_specification Spec = NodeSpecifications[Node->Type]; node_struct_member Member = Spec.MemberList[Connection]; - DrawString(RenderBuffer, MakeString(Member.Name), + DrawString(RenderBuffer, MakeString(Member.Name), State->NodeRenderSettings.Font, v2{PortBounds.Min.x - 8, PortBounds.Min.y}, WhiteV4, Align_Right); } - rect ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings); + rect2 ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings); DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); // NOTE(Peter): its way easier to draw the connection on the input port b/c its a 1:1 relationship, // whereas output ports might have many connections, they really only know about the most recent one - // Not sure if this is a problem. We mostly do everything backwards here, starting at the + // Not sure if this is a problem. We mostly do everything backwards here, starting at the // most downstream node and working back up to find dependencies. if (ConnectionHasUpstreamConnection(Node, Connection)) { - rect ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings); + rect2 ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings); v2 InputCenter = CalculateRectCenter(PortBounds); v2 OutputCenter = CalculateRectCenter(ConnectedPortBounds); PushRenderLine2D(RenderBuffer, OutputCenter, InputCenter, 1, WhiteV4); @@ -446,25 +446,25 @@ RenderNodeView(panel Panel, rect PanelBounds, render_command_buffer* RenderBufer // Outputs if (ConnectionIsOutput(Node, Connection)) { - rect PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings); + rect2 PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings); DrawPort(RenderBuffer, PortBounds, PortColor); if (DrawFields) { node_specification Spec = NodeSpecifications[Node->Type]; node_struct_member Member = Spec.MemberList[Connection]; - DrawString(RenderBuffer, MakeString(Member.Name), + DrawString(RenderBuffer, MakeString(Member.Name), State->NodeRenderSettings.Font, v2{PortBounds.Max.x + 8, PortBounds.Min.y}, WhiteV4); } - rect ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings); + rect2 ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings); DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font); } for (s32 Button = 0; Button < 3; Button++) { - rect ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings); + rect2 ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings); PushRenderQuad2D(RenderBuffer, ButtonRect.Min, ButtonRect.Max, DragButtonColors[Button]); } } @@ -501,8 +501,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeView) operation_mode* NodeViewMode = ActivateOperationModeWithCommands(&State->Modes, NodeViewCommands); NodeViewMode->Render = RenderNodeView; - node_view_operation_state* OpState = CreateOperationState(NodeViewMode, - &State->Modes, + node_view_operation_state* OpState = CreateOperationState(NodeViewMode, + &State->Modes, node_view_operation_state); OpState->SelectedNodeHandle = 0; diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index c3b9cb1..5d05907 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -8,27 +8,6 @@ #include "foldhaus_platform.h" #include "foldhaus_app.h" -internal v4 -MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds) -{ - DEBUG_TRACK_SCOPE(MouseToWorldRay); - r32 X = ((2.0f * MouseX) / gs_Width(WindowBounds)) - 1; - r32 Y = ((2.0f * MouseY) / gs_Height(WindowBounds)) - 1; - - v4 ScreenPos = v4{X, Y, -1, 1}; - - m44 InverseProjection = {}; - Inverse(GetCameraPerspectiveProjectionMatrix(*Camera), &InverseProjection); - - m44 InverseModelView = {}; - Inverse(GetCameraModelViewMatrix(*Camera), &InverseModelView); - InverseModelView = Transpose(InverseModelView); - - v4 ClipSpacePos = InverseProjection * ScreenPos; - v4 WorldPosition = InverseModelView * ClipSpacePos; - return WorldPosition; -} - struct send_sacn_job_data { @@ -72,11 +51,8 @@ INITIALIZE_APPLICATION(InitializeApplication) app_state* State = (app_state*)Context.MemoryBase; *State = {}; - State->Permanent = {}; - State->Permanent.PlatformMemory = Context.PlatformMemory; - State->Transient = {}; - State->Transient.FindAddressRule = FindAddress_InLastBufferOnly; - State->Transient.PlatformMemory = Context.PlatformMemory; + State->Permanent = CreateMemoryArena(Context.ThreadContext.Allocator); + State->Transient = CreateMemoryArena(Context.ThreadContext.Allocator); State->Assemblies.CountMax = 8; State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax); @@ -90,13 +66,11 @@ INITIALIZE_APPLICATION(InitializeApplication) CommandQueueSize); State->CommandQueue = InitializeCommandQueue(CommandQueueMemory, CommandQueueSize); - State->ActiveTextEntry.Buffer = MakeString(PushArray(&State->Permanent, char, 256), 0, 256); - // TODO(Peter): put in InitializeInterface? r32 FontSize = 14; { - platform_memory_result FontFile = ReadEntireFile(Context, MakeStringLiteral("data/Anonymous Pro.ttf")); - if (!FontFile.Error) + gs_file FontFile = ReadEntireFile(Context.ThreadContext.FileHandler, ConstString("data/Anonymous Pro.ttf")); + if (FileNoError(FontFile)) { bitmap_font* Font = PushStruct(&State->Permanent, bitmap_font); @@ -105,7 +79,7 @@ INITIALIZE_APPLICATION(InitializeApplication) Font->BitmapBytesPerPixel = 4; Font->BitmapMemory = PushArray(&State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel); Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; - GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight); + ZeroMemoryBlock(Font->BitmapMemory, Font->BitmapStride * Font->BitmapHeight); platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", FontSize, FontWeight_Normal, false, false, false); Font->PixelHeight = FontInfo.PixelHeight; @@ -169,17 +143,18 @@ INITIALIZE_APPLICATION(InitializeApplication) State->SACN = InitializeSACN(Context); State->NetworkProtocolHeaderSize = STREAM_HEADER_SIZE; - State->Camera.FieldOfView = DegreesToRadians(45.0f); - State->Camera.AspectRatio = gs_AspectRatio(State->WindowBounds); - State->Camera.Near = 1.0f; - State->Camera.Far = 100.0f; - State->Camera.Position = v3{0, 0, -250}; - State->Camera.LookAt = v3{0, 0, 0}; + State->Camera.FieldOfView = 45.0f; + State->Camera.AspectRatio = RectAspectRatio(State->WindowBounds); + State->Camera.Near = .1f; + State->Camera.Far = 800.0f; + State->Camera.Position = v3{0, 0, 400}; + State->Camera.LookAt = v3{0, 0, 0 + }; - State->LedSystem = LedSystemInitialize(Context.PlatformMemory, 128); + State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128); #if 1 - string SculpturePath = MakeStringLiteral("data/radialumia_v2.fold"); + gs_const_string SculpturePath = ConstString("data/radialumia_v2.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, SculpturePath, State->GlobalLog); #endif @@ -189,11 +164,7 @@ INITIALIZE_APPLICATION(InitializeApplication) ReloadStaticData(Context, GlobalDebugServices); - // Setup Operation Modes - State->Modes.ActiveModesCount = 0; - State->Modes.Arena = {}; - State->Modes.Arena.PlatformMemory = Context.PlatformMemory; - State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly; + State->Modes = OperationModeSystemInit(&State->Permanent, Context.ThreadContext); { // Animation PLAYGROUND State->AnimationSystem = {}; @@ -203,9 +174,9 @@ INITIALIZE_APPLICATION(InitializeApplication) State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem); State->AnimationSystem.LayersMax = 32; State->AnimationSystem.Layers = PushArray(&State->Permanent, anim_layer, State->AnimationSystem.LayersMax); - AddLayer(MakeStringLiteral("Base Layer"), &State->AnimationSystem, BlendMode_Overwrite); - AddLayer(MakeStringLiteral("Color Layer"), &State->AnimationSystem, BlendMode_Multiply); - AddLayer(MakeStringLiteral("Sparkles"), &State->AnimationSystem, BlendMode_Add); + AddLayer(MakeString("Base Layer"), &State->AnimationSystem, BlendMode_Overwrite); + AddLayer(MakeString("Color Layer"), &State->AnimationSystem, BlendMode_Multiply); + AddLayer(MakeString("Sparkles"), &State->AnimationSystem, BlendMode_Add); } // End Animation Playground @@ -215,7 +186,7 @@ INITIALIZE_APPLICATION(InitializeApplication) } internal void -HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_state Mouse) +HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse) { DEBUG_TRACK_FUNCTION; @@ -274,7 +245,7 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_ } internal dmx_buffer_list* -CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, memory_arena* Arena) +CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, gs_memory_arena* Arena) { DEBUG_TRACK_FUNCTION; @@ -322,6 +293,10 @@ CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, return Result; } + +#define HANDMADE_MATH_IMPLEMENTATION +#include "handmade_math.h" + UPDATE_AND_RENDER(UpdateAndRender) { DEBUG_TRACK_FUNCTION; @@ -334,6 +309,9 @@ UPDATE_AND_RENDER(UpdateAndRender) ClearArena(&State->Transient); Context->Mouse.CursorType = CursorType_Arrow; + PushRenderClearScreen(RenderBuffer); + State->Camera.AspectRatio = RectAspectRatio(Context->WindowBounds); + HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse); if (State->AnimationSystem.TimelineShouldAdvance) { @@ -355,7 +333,7 @@ UPDATE_AND_RENDER(UpdateAndRender) u32 CurrentBlocksMax = State->AnimationSystem.LayersCount; b8* CurrentBlocksFilled = PushArray(&State->Transient, b8, CurrentBlocksMax); - GSZeroArray(CurrentBlocksFilled, b8, CurrentBlocksMax); + ZeroArray(CurrentBlocksFilled, b8, CurrentBlocksMax); animation_block* CurrentBlocks = PushArray(&State->Transient, animation_block, CurrentBlocksMax); for (u32 i = 0; i < State->AnimationSystem.Blocks.Used; i++) @@ -432,9 +410,9 @@ UPDATE_AND_RENDER(UpdateAndRender) u32 G = (u32)AssemblyLedBuffer->Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G; u32 B = (u32)AssemblyLedBuffer->Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B; - AssemblyLedBuffer->Colors[LED].R = (u8)GSMin(R, (u32)255); - AssemblyLedBuffer->Colors[LED].G = (u8)GSMin(G, (u32)255); - AssemblyLedBuffer->Colors[LED].B = (u8)GSMin(B, (u32)255); + AssemblyLedBuffer->Colors[LED].R = (u8)Min(R, (u32)255); + AssemblyLedBuffer->Colors[LED].G = (u8)Min(G, (u32)255); + AssemblyLedBuffer->Colors[LED].B = (u8)Min(B, (u32)255); } }break; @@ -502,7 +480,7 @@ UPDATE_AND_RENDER(UpdateAndRender) - PushRenderOrthographic(RenderBuffer, 0, 0, gs_Width(State->WindowBounds), gs_Height(State->WindowBounds)); + PushRenderOrthographic(RenderBuffer, State->WindowBounds); PushRenderClearScreen(RenderBuffer); State->WindowBounds = Context->WindowBounds; @@ -521,7 +499,7 @@ UPDATE_AND_RENDER(UpdateAndRender) } } - Context->GeneralWorkQueue->DoQueueWorkUntilDone(Context->GeneralWorkQueue, 0); + Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext); Context->GeneralWorkQueue->ResetWorkQueue(Context->GeneralWorkQueue); // Checking for overflows diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index a33d179..cadf625 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -20,13 +20,8 @@ #include "foldhaus_assembly.h" #include "assembly_parser.cpp" - -#include "foldhaus_node.h" - typedef struct app_state app_state; -#include "test_patterns.h" - // TODO(Peter): something we can do later is to remove all reliance on app_state and context // from foldhaus_pane.h. It should just emit lists of things that the app can iterate over and // perform operations on, like panel_draw_requests = { bounds, panel* } etc. @@ -37,10 +32,6 @@ typedef struct app_state app_state; #include "animation/foldhaus_animation.h" -#include "foldhaus_text_entry.h" - -#include "foldhaus_search_lister.h" - enum network_protocol { NetworkProtocol_SACN, @@ -51,10 +42,11 @@ enum network_protocol struct app_state { - rect WindowBounds; + r32 CameraTheta; // TODO(Peter): @TEMPORARY + rect2 WindowBounds; - memory_arena Permanent; - memory_arena Transient; + gs_memory_arena Permanent; + gs_memory_arena Transient; s32 NetworkProtocolHeaderSize; network_protocol NetworkProtocol; @@ -69,7 +61,6 @@ struct app_state operation_mode_system Modes; input_command_queue CommandQueue; - text_entry ActiveTextEntry; ui_interface Interface; @@ -80,7 +71,7 @@ struct app_state panel_system PanelSystem; panel* HotPanel; - pattern_node_workspace NodeWorkspace; + //pattern_node_workspace NodeWorkspace; event_log* GlobalLog; }; @@ -94,8 +85,8 @@ TestPatternOne(led_buffer* Assembly, r32 Time) for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++) { v4 LedPosition = Assembly->Positions[LedIndex]; - float PercentX = GSRemap(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); - float PercentY = GSRemap(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); + float PercentX = RemapClampedR32(LedPosition.x, -150.0f, 150.0f, 0.0f, 1.0f); + float PercentY = RemapClampedR32(LedPosition.y, -150.0f, 150.0f, 0.0f, 1.0f); Assembly->Colors[LedIndex].R = (u8)(PercentX * 255); Assembly->Colors[LedIndex].G = (u8)(PercentY * 255); } @@ -104,16 +95,16 @@ TestPatternOne(led_buffer* Assembly, r32 Time) internal void TestPatternTwo(led_buffer* Assembly, r32 Time) { - r32 PeriodicTime = (Time / PI) * 2; + r32 PeriodicTime = (Time / PiR32) * 2; - r32 ZeroOneSin = (GSSin(PeriodicTime) * .5f) + .5f; - r32 ZeroOneCos = (GSCos(PeriodicTime) * .5f) + .5f; + r32 ZeroOneSin = (SinR32(PeriodicTime) * .5f) + .5f; + r32 ZeroOneCos = (CosR32(PeriodicTime) * .5f) + .5f; pixel Color = { (u8)(ZeroOneSin * 255), 0, (u8)(ZeroOneCos * 255) }; v4 Center = v4{0, 0, 0, 1}; r32 ThetaZ = Time / 2; - v4 Normal = v4{GSCos(ThetaZ), 0, GSSin(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 - v4 Right = Cross(Normal, v4{0, 1, 0, 0}); + v4 Normal = v4{CosR32(ThetaZ), 0, SinR32(ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 + v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); v4 FrontCenter = Center + (Normal * 25); v4 BackCenter = Center - (Normal * 25); @@ -128,13 +119,13 @@ TestPatternTwo(led_buffer* Assembly, r32 Time) v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; - r32 ToFrontDotNormal = Dot(ToFront, Normal); - r32 ToBackDotNormal = Dot(ToBack, Normal); + r32 ToFrontDotNormal = V4Dot(ToFront, Normal); + r32 ToBackDotNormal = V4Dot(ToBack, Normal); - ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000); - ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000); + ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); + ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); - r32 SqDistToCenter = MagSqr(Position); + r32 SqDistToCenter = V4MagSquared(Position); if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) @@ -157,10 +148,10 @@ internal void TestPatternThree(led_buffer* Assembly, r32 Time) { v4 GreenCenter = v4{0, 0, 150, 1}; - r32 GreenRadius = GSAbs(GSSin(Time)) * 200; + r32 GreenRadius = Abs(SinR32(Time)) * 200; v4 TealCenter = v4{0, 0, 150, 1}; - r32 TealRadius = GSAbs(GSSin(Time + 1.5)) * 200; + r32 TealRadius = Abs(SinR32(Time + 1.5)) * 200; r32 FadeDist = 35; @@ -172,12 +163,12 @@ TestPatternThree(led_buffer* Assembly, r32 Time) u8 Green = 0; u8 Blue = 0; - r32 GreenDist = GSAbs(Mag(LedPosition - GreenCenter) - GreenRadius); - r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist); + r32 GreenDist = Abs(V4Mag(LedPosition - GreenCenter) - GreenRadius); + r32 GreenBrightness = Clamp(0.f, FadeDist - Abs(GreenDist), FadeDist); Green = (u8)(GreenBrightness * 255); - r32 TealDist = GSAbs(Mag(LedPosition - TealCenter) - TealRadius); - r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist); + r32 TealDist = Abs(V4Mag(LedPosition - TealCenter) - TealRadius); + r32 TealBrightness = Clamp(0.f, FadeDist - Abs(TealDist), FadeDist); Red = (u8)(TealBrightness * 255); Blue = (u8)(TealBrightness * 255); @@ -191,17 +182,6 @@ TestPatternThree(led_buffer* Assembly, r32 Time) #include "foldhaus_assembly.cpp" -#include "foldhaus_text_entry.cpp" -#include "foldhaus_search_lister.cpp" - -#include "foldhaus_default_nodes.h" - -#include "./generated/gs_meta_generated_typeinfo.h" -#include "generated/foldhaus_nodes_generated.h" - - -#include "foldhaus_node.cpp" - FOLDHAUS_INPUT_COMMAND_PROC(EndCurrentOperationMode) { DeactivateCurrentOperationMode(&State->Modes); @@ -213,7 +193,7 @@ typedef PANEL_INIT_PROC(panel_init_proc); #define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State) typedef PANEL_CLEANUP_PROC(panel_cleanup_proc); -#define PANEL_RENDER_PROC(name) void name(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +#define PANEL_RENDER_PROC(name) void name(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) typedef PANEL_RENDER_PROC(panel_render_proc); // NOTE(Peter): This is used by the meta system to generate panel type info @@ -233,7 +213,6 @@ struct panel_definition #include "panels/foldhaus_panel_dmx_view.h" #include "panels/foldhaus_panel_animation_timeline.h" #include "panels/foldhaus_panel_hierarchy.h" -#include "panels/foldhaus_panel_node_graph.h" #include "panels/foldhaus_panel_file_view.h" #include "generated/foldhaus_panels_generated.h" diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index ea74af2..0d7ae9a 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -6,13 +6,13 @@ #ifndef FOLDHAUS_ASSEMBLY_CPP internal led_system -LedSystemInitialize(platform_memory_handler PlatformMemory, u32 BuffersMax) +LedSystemInitialize(gs_allocator PlatformMemory, u32 BuffersMax) { led_system Result = {}; Result.PlatformMemory = PlatformMemory; // TODO(Peter): Since we have access to PlatformMemory, just realloc Buffers when we fill it up Result.BuffersCountMax = BuffersMax; - Result.Buffers = PlatformAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax); + Result.Buffers = AllocatorAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax); return Result; } @@ -43,8 +43,8 @@ LedSystemTakeFreeBuffer(led_system* System, u32 LedCount) led_buffer* Buffer = &System->Buffers[Result]; Buffer->LedCount = LedCount; - Buffer->Colors = PlatformAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); - Buffer->Positions = PlatformAllocArray(System->PlatformMemory, v4, Buffer->LedCount); + Buffer->Colors = AllocatorAllocArray(System->PlatformMemory, pixel, Buffer->LedCount); + Buffer->Positions = AllocatorAllocArray(System->PlatformMemory, v4, Buffer->LedCount); System->LedsCountTotal += LedCount; @@ -56,8 +56,8 @@ 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->Positions, v4, Buffer->LedCount); + AllocatorFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount); + AllocatorFreeArray(System->PlatformMemory, Buffer->Positions, v4, Buffer->LedCount); System->LedsCountTotal -= Buffer->LedCount; *Buffer = {}; } @@ -77,7 +77,7 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position) } internal void -ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition, led_system* LedSystem) +ConstructAssemblyFromDefinition (assembly* Assembly, gs_const_string AssemblyName, v4 RootPosition, led_system* LedSystem) { Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal); led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex); @@ -90,8 +90,8 @@ ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 Roo v2_strip* StripAt = &Assembly->Strips[StripIdx]; StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount); - v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1); - v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1); + v4 WS_StripStart = RootPosition + ToV4Point(StripAt->StartPosition * Assembly->Scale); + v4 WS_StripEnd = RootPosition + ToV4Point(StripAt->EndPosition * Assembly->Scale); v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount; for (u32 Step = 0; Step < StripAt->LedCount; Step++) @@ -111,25 +111,25 @@ static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, s32 TempAssemblyOffsetsCount = 3; internal void -LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, memory_arena* Scratch, context Context, string Path, event_log* GlobalLog) +LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena* Scratch, context Context, gs_const_string Path, event_log* GlobalLog) { - platform_memory_result AssemblyFile = ReadEntireFile(Context, Path); - if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Data.Size > 0) + gs_file AssemblyFile = ReadEntireFile(Context.ThreadContext.FileHandler, Path); + if (FileNoError(AssemblyFile)) { - string AssemblyFileText = MakeString((char*)AssemblyFile.Data.Base); + gs_string AssemblyFileText = MakeString((char*)AssemblyFile.Memory); Assert(Assemblies->Count < Assemblies->CountMax); assembly* NewAssembly = &Assemblies->Values[Assemblies->Count++]; - s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\'); - string FileName = Substring(Path, IndexOfLastSlash + 1); + s32 IndexOfLastSlash = FindLast(Path, '\\'); + gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length); - NewAssembly->Arena.PlatformMemory = Context.PlatformMemory; - if (ParseAssemblyFile(NewAssembly, AssemblyFileText, Scratch)) + NewAssembly->Arena = CreateMemoryArena(Context.ThreadContext.Allocator); + if (ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch)) { v4 Offset = v4{0,0,0,0}; //TempAssemblyOffsets[Assemblies->Count % TempAssemblyOffsetsCount]; ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, LedSystem); - PlatformFree(Context.PlatformMemory, AssemblyFile.Data.Base, AssemblyFile.Data.Size); + AllocatorFree(Context.ThreadContext.Allocator, AssemblyFile.Memory, AssemblyFile.Size); } else { diff --git a/src/app/foldhaus_assembly.h b/src/app/foldhaus_assembly.h index 97c153a..7b47451 100644 --- a/src/app/foldhaus_assembly.h +++ b/src/app/foldhaus_assembly.h @@ -25,7 +25,7 @@ struct led_buffer struct led_system { - platform_memory_handler PlatformMemory; + gs_allocator PlatformMemory; u32 BuffersCountMax; u32 BuffersCount; @@ -62,10 +62,10 @@ struct v2_strip struct assembly { - memory_arena Arena; + gs_memory_arena Arena; - string Name; - string FilePath; + gs_string Name; + gs_string FilePath; r32 Scale; s32 LedCountTotal; diff --git a/src/app/foldhaus_command_dispatch.h b/src/app/foldhaus_command_dispatch.h index 2a7fc1e..3b2d8aa 100644 --- a/src/app/foldhaus_command_dispatch.h +++ b/src/app/foldhaus_command_dispatch.h @@ -8,7 +8,7 @@ #define FOLDHAUS_INPUT_COMMAND_PROC(name) void name(app_state* State, input_entry Event, mouse_state Mouse) typedef FOLDHAUS_INPUT_COMMAND_PROC(input_command_proc); -// NOTE(Peter): Helper function so I don't have to remember the parameters to this define +// NOTE(Peter): Helper function so I don't have to remember the parameters to this define #define ExecFoldhausCommand(cmd) cmd(State, Event, Mouse) enum input_command_flags @@ -55,7 +55,7 @@ struct input_command_queue internal void InitializeInputCommandRegistry (input_command_registry* CommandRegistry, s32 Size, - memory_arena* Storage) + gs_memory_arena* Storage) { CommandRegistry->Commands = PushArray(Storage, input_command, Size); CommandRegistry->Size = Size; @@ -115,8 +115,8 @@ internal void RemoveCommandFromQueue(input_command_queue* Queue, s32 Index) { s32 CommandIndex = Index; - if (CommandIndex < Queue->Used) - { + if (CommandIndex < Queue->Used) + { Queue->Used -= 1; for (; CommandIndex < Queue->Used; CommandIndex++) @@ -132,9 +132,9 @@ RemoveCommandFromQueue(input_command_queue* Queue, input_command Command, input_ s32 CommandIndex = GetCommandIndexInQueue(Queue, Command, Event); // NOTE(Peter): If we made it through the queue without finding an event, there wasn't one - // to remove. This happens when we've changed command registries as a result of an input command, + // to remove. This happens when we've changed command registries as a result of an input command, // and the command exists in the new registry. - // For example: + // For example: // clicking a mouse button triggers a command to switch registries // the new registry tracks mouse drag (persist until release) // when the mouse is released, the event fires, but there is no mouse down event to remove diff --git a/src/app/foldhaus_debug.h b/src/app/foldhaus_debug.h index c987469..c45ad69 100644 --- a/src/app/foldhaus_debug.h +++ b/src/app/foldhaus_debug.h @@ -30,7 +30,7 @@ struct collated_scope_record struct scope_name { u32 Hash; - string Name; + gs_string Name; char Buffer[SCOPE_NAME_BUFFER_LENGTH]; }; @@ -82,7 +82,7 @@ typedef u8* debug_realloc(u8* Memory, s32 OldSize, s32 NewSize); struct debug_histogram_entry { char ScopeName_[SCOPE_NAME_LENGTH]; - string ScopeName; + gs_string ScopeName; u32 PerFrame_Cycles[HISTOGRAM_DEPTH]; u32 PerFrame_CallCount[HISTOGRAM_DEPTH]; @@ -168,12 +168,12 @@ StartDebugFrame(debug_frame* Frame, debug_services* Services) } internal void -InitDebugServices (debug_services* Services, - s64 PerformanceCountFrequency, - debug_alloc* Alloc, - debug_realloc* Realloc, - debug_timing_proc* GetWallClock, - debug_get_thread_id* GetThreadId, +InitDebugServices (debug_services* Services, + s64 PerformanceCountFrequency, + debug_alloc* Alloc, + debug_realloc* Realloc, + debug_timing_proc* GetWallClock, + debug_get_thread_id* GetThreadId, s32 ThreadCount) { Services->Alloc = Alloc; @@ -233,7 +233,7 @@ GetIndexForNameHash(debug_frame* Frame, u32 NameHash) } // NOTE(Peter): Its not technically wrong to return a -1 here, just means we didn't find it. - // At the time of writing however, this function is only being called in contexts where we + // At the time of writing however, this function is only being called in contexts where we // know there should be an entry in the Name table, so a -1 actually indicates a problem. Assert(Result >= 0); return Result; @@ -359,9 +359,9 @@ BeginTrackingScopeAndGetNameHash (debug_services* Services, char* ScopeName) if (Entry->Hash == 0) // If its new { Entry->Hash = NameHash; - // TODO(Peter): need to initialize all entry name strings to point at the buffer + // TODO(Peter): need to initialize all entry name gs_strings to point at the buffer // This will break eventually. when it does, do this ^^^^ when on startup - CopyCharArrayToString(ScopeName, &Entry->Name); + PrintF(&Entry->Name, "%s", ScopeName); } return NameHash; @@ -402,7 +402,7 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre #define DEBUG_TRACK_FUNCTION scope_tracker ScopeTracker ((char*)__func__, GlobalDebugServices) #define DEBUG_TRACK_SCOPE(name) scope_tracker ScopeTracker_##name (#name, GlobalDebugServices) #else -#define DEBUG_TRACK_FUNCTION +#define DEBUG_TRACK_FUNCTION #define DEBUG_TRACK_SCOPE(name) #endif struct scope_tracker diff --git a/src/app/foldhaus_interface.cpp b/src/app/foldhaus_interface.cpp index f9345cb..e5e4e43 100644 --- a/src/app/foldhaus_interface.cpp +++ b/src/app/foldhaus_interface.cpp @@ -41,7 +41,7 @@ OPERATION_STATE_DEF(drag_panel_border_operation_state) // NOTE(Peter): InitialPanelBounds is the bounds of the panel we are modifying, // it stores the value calculated when the operation mode is kicked off. - rect InitialPanelBounds; + rect2 InitialPanelBounds; panel_split_direction PanelEdgeDirection; panel_edit_mode PanelEditMode; }; @@ -49,7 +49,7 @@ OPERATION_STATE_DEF(drag_panel_border_operation_state) OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder) { drag_panel_border_operation_state* OpState = (drag_panel_border_operation_state*)Operation.OpStateMemory; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; if (OpState->PanelEditMode == PanelEdit_Modify) { @@ -72,10 +72,10 @@ OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder) } else if (OpState->PanelEditMode == PanelEdit_Destroy) { - rect PanelToDeleteBounds = {}; + rect2 PanelToDeleteBounds = {}; if (OpState->PanelEdgeDirection == PanelSplit_Horizontal) { - r32 SplitY = GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, OpState->Panel->SplitPercent); + r32 SplitY = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); if (Mouse.Pos.y > SplitY) { PanelToDeleteBounds = GetTopPanelBounds(OpState->Panel, PanelBounds); @@ -87,7 +87,7 @@ OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder) } else if (OpState->PanelEdgeDirection == PanelSplit_Vertical) { - r32 SplitX = GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, OpState->Panel->SplitPercent); + r32 SplitX = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); if (Mouse.Pos.x > SplitX) { PanelToDeleteBounds = GetRightPanelBounds(OpState->Panel, PanelBounds); @@ -106,7 +106,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) { drag_panel_border_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_panel_border_operation_state); panel* Panel = OpState->Panel; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; if (OpState->PanelEditMode == PanelEdit_Modify) { @@ -123,7 +123,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else { - Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / gs_Height(PanelBounds); + Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / Rect2Height(PanelBounds); } } else if (Panel->SplitDirection == PanelSplit_Vertical) @@ -139,7 +139,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else { - Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / gs_Width(PanelBounds); + Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / Rect2Width(PanelBounds); } } } @@ -147,7 +147,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) { if (OpState->PanelEdgeDirection == PanelSplit_Horizontal) { - r32 SplitY = GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, OpState->Panel->SplitPercent); + r32 SplitY = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); if (Mouse.Pos.y > SplitY) { ConsolidatePanelsKeepOne(Panel, Panel->Bottom, &State->PanelSystem); @@ -159,7 +159,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else if (OpState->PanelEdgeDirection == PanelSplit_Vertical) { - r32 SplitX = GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, OpState->Panel->SplitPercent); + r32 SplitX = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); if (Mouse.Pos.x > SplitX) { ConsolidatePanelsKeepOne(Panel, Panel->Left, &State->PanelSystem); @@ -180,7 +180,7 @@ input_command DragPanelBorderCommands[] = { }; internal void -BeginDragPanelBorder(panel* Panel, panel_edit_mode PanelEditMode, rect PanelBounds, panel_split_direction PanelEdgeDirection, mouse_state Mouse, app_state* State) +BeginDragPanelBorder(panel* Panel, panel_edit_mode PanelEditMode, rect2 PanelBounds, panel_split_direction PanelEdgeDirection, mouse_state Mouse, app_state* State) { operation_mode* DragPanelBorder = ActivateOperationModeWithCommands(&State->Modes, DragPanelBorderCommands, UpdateAndRenderDragPanelBorder); drag_panel_border_operation_state* OpState = CreateOperationState(DragPanelBorder, &State->Modes, drag_panel_border_operation_state); @@ -202,17 +202,17 @@ OPERATION_STATE_DEF(split_panel_operation_state) // NOTE(Peter): InitialPanelBounds is the bounds of the panel we are modifying, // it stores the value calculated when the operation mode is kicked off. - rect InitialPanelBounds; + rect2 InitialPanelBounds; }; OPERATION_RENDER_PROC(UpdateAndRenderSplitPanel) { split_panel_operation_state* OpState = (split_panel_operation_state*)Operation.OpStateMemory; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; v4 EdgePreviewColor = v4{.3f, .3f, .3f, 1.f}; - r32 MouseDeltaX = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); - r32 MouseDeltaY = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); + r32 MouseDeltaX = Abs(Mouse.Pos.x - Mouse.DownPos.x); + r32 MouseDeltaY = Abs(Mouse.Pos.y - Mouse.DownPos.y); v2 EdgePreviewMin = {}; v2 EdgePreviewMax = {}; @@ -234,19 +234,19 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) { split_panel_operation_state* OpState = GetCurrentOperationState(State->Modes, split_panel_operation_state); panel* Panel = OpState->Panel; - rect PanelBounds = OpState->InitialPanelBounds; + rect2 PanelBounds = OpState->InitialPanelBounds; - r32 XDistance = GSAbs(Mouse.Pos.x - Mouse.DownPos.x); - r32 YDistance = GSAbs(Mouse.Pos.y - Mouse.DownPos.y); + r32 XDistance = Abs(Mouse.Pos.x - Mouse.DownPos.x); + r32 YDistance = Abs(Mouse.Pos.y - Mouse.DownPos.y); if (XDistance > YDistance) { - r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / gs_Width(PanelBounds); + r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / Rect2Width(PanelBounds); SplitPanelVertically(Panel, XPercent, &State->PanelSystem); } else { - r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / gs_Height(PanelBounds); + r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / Rect2Height(PanelBounds); SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem); } @@ -264,7 +264,7 @@ input_command SplitPanelCommands[] = { }; internal void -BeginSplitPanelOperation(panel* Panel, rect PanelBounds, mouse_state Mouse, app_state* State) +BeginSplitPanelOperation(panel* Panel, rect2 PanelBounds, mouse_state Mouse, app_state* State) { operation_mode* SplitPanel = ActivateOperationModeWithCommands(&State->Modes, SplitPanelCommands, UpdateAndRenderSplitPanel); split_panel_operation_state* OpState = CreateOperationState(SplitPanel, &State->Modes, split_panel_operation_state); @@ -278,20 +278,22 @@ BeginSplitPanelOperation(panel* Panel, rect PanelBounds, mouse_state Mouse, app_ #define PANEL_EDGE_CLICK_MAX_DISTANCE 6 internal b32 -HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, rect PanelBounds, mouse_state Mouse, app_state* State) +HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, rect2 PanelBounds, mouse_state Mouse, app_state* State) { b32 HandledMouseInput = false; + rect2 PanelSplitButtonBounds = rect2{ PanelBounds.Min, PanelBounds.Min + v2{25, 25} }; + if (Panel->SplitDirection == PanelSplit_NoSplit - && PointIsInRange(Mouse.DownPos, PanelBounds.Min, PanelBounds.Min + v2{25, 25})) + && PointIsInRect(PanelSplitButtonBounds, Mouse.DownPos)) { BeginSplitPanelOperation(Panel, PanelBounds, Mouse, State); HandledMouseInput = true; } else if (Panel->SplitDirection == PanelSplit_Horizontal) { - r32 SplitY = GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, Panel->SplitPercent); - r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.y - SplitY); + r32 SplitY = LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y); + r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.y - SplitY); if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE) { BeginDragPanelBorder(Panel, PanelEditMode, PanelBounds, PanelSplit_Horizontal, Mouse, State); @@ -299,13 +301,13 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } else { - rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - if (gs_PointIsInRect(Mouse.DownPos, BottomPanelBounds)) + rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); + rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + if (PointIsInRect(BottomPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelEditMode, BottomPanelBounds, Mouse, State); } - if (gs_PointIsInRect(Mouse.DownPos, TopPanelBounds)) + if (PointIsInRect(TopPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Top->Panel, PanelEditMode, TopPanelBounds, Mouse, State); } @@ -313,8 +315,8 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } else if (Panel->SplitDirection == PanelSplit_Vertical) { - r32 SplitX = GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, Panel->SplitPercent); - r32 ClickDistanceFromSplit = GSAbs(Mouse.DownPos.x - SplitX); + r32 SplitX = LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x); + r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.x - SplitX); if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE) { BeginDragPanelBorder(Panel, PanelEditMode, PanelBounds, PanelSplit_Vertical, Mouse, State); @@ -322,13 +324,13 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } else { - rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - if (gs_PointIsInRect(Mouse.DownPos, LeftPanelBounds)) + rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); + rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + if (PointIsInRect(LeftPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Left->Panel, PanelEditMode, LeftPanelBounds, Mouse, State); } - if (gs_PointIsInRect(Mouse.DownPos, RightPanelBounds)) + if (PointIsInRect(RightPanelBounds, Mouse.DownPos)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Right->Panel, PanelEditMode, RightPanelBounds, Mouse, State); } @@ -339,7 +341,7 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit } internal b32 -HandleMousePanelInteraction(panel_system* PanelSystem, rect WindowBounds, mouse_state Mouse, app_state* State) +HandleMousePanelInteraction(panel_system* PanelSystem, rect2 WindowBounds, mouse_state Mouse, app_state* State) { b32 HandledMouseInput = false; @@ -359,10 +361,10 @@ HandleMousePanelInteraction(panel_system* PanelSystem, rect WindowBounds, mouse_ internal void DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state* Mouse, render_command_buffer* RenderBuffer) { - r32 MouseLeftEdgeDistance = GSAbs(Mouse->Pos.x - PanelMin.x); - r32 MouseRightEdgeDistance = GSAbs(Mouse->Pos.x - PanelMax.x); - r32 MouseTopEdgeDistance = GSAbs(Mouse->Pos.y - PanelMax.y); - r32 MouseBottomEdgeDistance = GSAbs(Mouse->Pos.y - PanelMin.y); + r32 MouseLeftEdgeDistance = Abs(Mouse->Pos.x - PanelMin.x); + r32 MouseRightEdgeDistance = Abs(Mouse->Pos.x - PanelMax.x); + r32 MouseTopEdgeDistance = Abs(Mouse->Pos.y - PanelMax.y); + r32 MouseBottomEdgeDistance = Abs(Mouse->Pos.y - PanelMin.y); PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color); v4 HighlightColor = v4{.3f, .3f, .3f, 1.f}; @@ -398,41 +400,46 @@ DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state* Mo } internal void -DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBounds, mouse_state Mouse, app_state* State) +DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterBounds, mouse_state Mouse, app_state* State) { PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f}); PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4); - rect PanelSelectBtnBounds = gs_MakeRectMinWidth(FooterBounds.Min + v2{30, 1}, v2{100, 23}); + rect2 PanelSelectBtnBounds = MakeRect2MinDim(FooterBounds.Min + v2{30, 1}, v2{100, 23}); if (Panel->PanelSelectionMenuOpen) { - rect ButtonBounds = gs_MakeRectMinWidth(v2{ PanelSelectBtnBounds.Min.x, FooterBounds.Max.y }, v2{ 100, 25 }); + rect2 ButtonBounds = MakeRect2MinDim(v2{ PanelSelectBtnBounds.Min.x, FooterBounds.Max.y }, v2{ 100, 25 }); + + rect2 MenuBounds = rect2 + { + ButtonBounds.Min, + v2{ + ButtonBounds.Min.x + Rect2Width(ButtonBounds), ButtonBounds.Min.y + (Rect2Height(ButtonBounds) * GlobalPanelDefsCount) + }, + }; - v2 MenuMin = ButtonBounds.Min; - v2 MenuMax = v2{ButtonBounds.Min.x + gs_Width(ButtonBounds), ButtonBounds.Min.y + (gs_Height(ButtonBounds) * GlobalPanelDefsCount)}; if (MouseButtonTransitionedDown(Mouse.LeftButtonState) - && !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax)) + && !PointIsInRect(MenuBounds, Mouse.DownPos)) { Panel->PanelSelectionMenuOpen = false; } - for (s32 i = 0; i < GlobalPanelDefsCount; i++) { panel_definition Def = GlobalPanelDefs[i]; - string DefName = MakeString(Def.PanelName, Def.PanelNameLength); + gs_string DefName = MakeString(Def.PanelName, Def.PanelNameLength); if (ui_Button(&State->Interface, DefName, ButtonBounds)) { SetPanelDefinition(Panel, i, State); Panel->PanelSelectionMenuOpen = false; } - ButtonBounds = gs_TranslateRectY(ButtonBounds, gs_Height(ButtonBounds)); + ButtonBounds = Rect2TranslateY(ButtonBounds, Rect2Height(ButtonBounds)); } } - if (ui_Button(&State->Interface, MakeStringLiteral("Select"), PanelSelectBtnBounds)) + if (ui_Button(&State->Interface, MakeString("Select"), PanelSelectBtnBounds)) { Panel->PanelSelectionMenuOpen = !Panel->PanelSelectionMenuOpen; } @@ -440,15 +447,15 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo } internal void -RenderPanel(panel* Panel, rect PanelBounds, rect WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) +RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse) { Assert(Panel->PanelDefinitionIndex >= 0); - rect FooterBounds = rect{ + rect2 FooterBounds = rect2{ PanelBounds.Min, v2{PanelBounds.Max.x, PanelBounds.Min.y + 25}, }; - rect PanelViewBounds = rect{ + rect2 PanelViewBounds = rect2{ v2{PanelBounds.Min.x, FooterBounds.Max.y}, PanelBounds.Max, }; @@ -456,7 +463,7 @@ RenderPanel(panel* Panel, rect PanelBounds, rect WindowBounds, render_command_bu panel_definition Definition = GlobalPanelDefs[Panel->PanelDefinitionIndex]; Definition.Render(*Panel, PanelViewBounds, RenderBuffer, State, Context); - PushRenderOrthographic(RenderBuffer, WindowBounds.Min.x, WindowBounds.Min.y, WindowBounds.Max.x, WindowBounds.Max.y); + PushRenderOrthographic(RenderBuffer, WindowBounds); DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State); } @@ -467,12 +474,12 @@ DrawAllPanels(panel_layout PanelLayout, render_command_buffer* RenderBuffer, mou { panel_with_layout PanelWithLayout = PanelLayout.Panels[i]; panel* Panel = PanelWithLayout.Panel; - rect PanelBounds = PanelWithLayout.Bounds; + rect2 PanelBounds = PanelWithLayout.Bounds; RenderPanel(Panel, PanelBounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse); v4 BorderColor = v4{0, 0, 0, 1}; - PushRenderOrthographic(RenderBuffer, State->WindowBounds.Min.x, State->WindowBounds.Min.y, State->WindowBounds.Max.x, State->WindowBounds.Max.y); + PushRenderOrthographic(RenderBuffer, State->WindowBounds); DrawPanelBorder(*Panel, PanelBounds.Min, PanelBounds.Max, BorderColor, Mouse, RenderBuffer); } } diff --git a/src/app/foldhaus_log.h b/src/app/foldhaus_log.h index 12ed933..0cffd1a 100644 --- a/src/app/foldhaus_log.h +++ b/src/app/foldhaus_log.h @@ -13,7 +13,7 @@ enum log_entry_type struct log_entry { - string Message; + gs_string Message; log_entry_type Type; }; @@ -25,11 +25,11 @@ struct event_log u32 NextEntry; }; -#define LogMessage(_Log, _Message) PushLogEntry(_Log, MakeStringLiteral(_Message), LogEntry_Message) -#define LogError(_Log, _Message) PushLogEntry(_Log, MakeStringLiteral(_Message), LogEntry_Error) +#define LogMessage(_Log, _Message) PushLogEntry(_Log, MakeString(_Message), LogEntry_Message) +#define LogError(_Log, _Message) PushLogEntry(_Log, MakeString(_Message), LogEntry_Error) internal void -PushLogEntry(event_log* Log, string Message, log_entry_type Type) +PushLogEntry(event_log* Log, gs_string Message, log_entry_type Type) { u32 NewLogIndex = Log->NextEntry++; if (Log->NextEntry >= LOG_ENTRIES_MAX) diff --git a/src/app/foldhaus_node.cpp b/src/app/foldhaus_node.cpp index 29e93a9..092d55f 100644 --- a/src/app/foldhaus_node.cpp +++ b/src/app/foldhaus_node.cpp @@ -45,7 +45,7 @@ SortNodeNeighbors(u32 ContiguousNodeIndex, gs_list_handle NodeHandle, adjacency_ u32 ContiguousNeighborNodeIndex = SparseToContiguousNodeMap[Neighbor->NodeHandle.Index]; if (!NodesVisited[ContiguousNeighborNodeIndex]) { - SortedNodesCount = SortNodeNeighbors(ContiguousNeighborNodeIndex, Neighbor->NodeHandle, NeighborsLists, NodesVisited, SortedNodeHandles, SortedNodesCount, SparseToContiguousNodeMap); + SortedNodesCount = SortNodeNeighbors(ContiguousNeighborNodeIndex, Neighbor->NodeHandle, NeighborsLists, NodesVisited, SortedNodeHandles, SortedNodesCount, SparseToContiguousNodeMap); } Neighbor = Neighbor->Next; } @@ -55,7 +55,7 @@ SortNodeNeighbors(u32 ContiguousNodeIndex, gs_list_handle NodeHandle, adjacency_ } internal s32* -CreateSparseToContiguousMap (pattern_node_workspace Workspace, memory_arena* Scratch) +CreateSparseToContiguousMap (pattern_node_workspace Workspace, gs_memory_arena* Scratch) { s32* Result = PushArray(Scratch, s32, Workspace.Nodes.OnePastLastUsed); s32 ContiguousIndex = 0; @@ -71,7 +71,7 @@ CreateSparseToContiguousMap (pattern_node_workspace Workspace, memory_arena* Scr } internal void -UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) +UpdateSortedNodes(pattern_node_workspace* Workspace, gs_memory_arena* Scratch) { ClearNodeWorkspaceStorage(Workspace); @@ -81,7 +81,7 @@ UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) s32* SparseToContiguousNodeMap = CreateSparseToContiguousMap(*Workspace, &Workspace->Storage); // NOTE(Peter): We need to sort this later on so I'm just storing list lengths in this format - // to begin with. + // to begin with. // NeighborsListLengths[n].Radix = the number of neighbors for the node // NeighborsListLengths[n].ID = the sparse array index of the node gs_radix_entry* NeighborsListLengths = PushArray(Scratch, gs_radix_entry, NodeCount); @@ -119,24 +119,24 @@ UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) RadixSortInPlace(NeighborsListLengths, Workspace->Nodes.Used); char* OutputCharArray = PushArray(Scratch, char, 1024); - string OutputString = MakeString(OutputCharArray, 0, 1024); + gs_string Outputgs_string = MakeString(OutputCharArray, 0, 1024); - PrintF(&OutputString, "Neighbors Lists: \n"); + PrintF(&Outputgs_string, "Neighbors Lists: \n"); for (u32 d = 0; d < Workspace->Nodes.Used; d++) { - PrintF(&OutputString, " %d: Node [ %d ] : neighbors { ", d, NeighborsListLengths[d].ID); + PrintF(&Outputgs_string, " %d: Node [ %d ] : neighbors { ", d, NeighborsListLengths[d].ID); adjacency_list* Neighbors = NeighborsLists[d]; while (Neighbors) { - PrintF(&OutputString, "%d, ", Neighbors->NodeHandle.Index); + PrintF(&Outputgs_string, "%d, ", Neighbors->NodeHandle.Index); Neighbors = Neighbors->Next; } - PrintF(&OutputString, " }\n"); + PrintF(&Outputgs_string, " }\n"); } - NullTerminate(&OutputString); + NullTerminate(&Outputgs_string); - // This is a contiguous array. + // This is a contiguous array. b8* NodesVisited = PushArray(Scratch, b8, NodeCount); GSZeroArray(NodesVisited, b8, NodeCount); @@ -163,7 +163,7 @@ UpdateSortedNodes(pattern_node_workspace* Workspace, memory_arena* Scratch) } internal void -PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspace, memory_arena* Scratch) +PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspace, gs_memory_arena* Scratch) { pattern_node* NewNode = Workspace->Nodes.TakeElement(); NewNode->SpecificationIndex = NodeSpecificationIndex; @@ -172,13 +172,13 @@ PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspac } internal void -PushNodeConnectionOnWorkspace(gs_list_handle UpstreamNodeHandle, u32 UpstreamPortIndex, gs_list_handle DownstreamNodeHandle, u32 DownstreamPortIndex, pattern_node_workspace* Workspace, memory_arena* Scratch) +PushNodeConnectionOnWorkspace(gs_list_handle UpstreamNodeHandle, u32 UpstreamPortIndex, gs_list_handle DownstreamNodeHandle, u32 DownstreamPortIndex, pattern_node_workspace* Workspace, gs_memory_arena* Scratch) { pattern_node_connection Connection = {}; - Connection.UpstreamNodeHandle = UpstreamNodeHandle; - Connection.DownstreamNodeHandle = DownstreamNodeHandle; - Connection.UpstreamPortIndex = UpstreamPortIndex; - Connection.DownstreamPortIndex = DownstreamPortIndex; + Connection.UpstreamNodeHandle = UpstreamNodeHandle; + Connection.DownstreamNodeHandle = DownstreamNodeHandle; + Connection.UpstreamPortIndex = UpstreamPortIndex; + Connection.DownstreamPortIndex = DownstreamPortIndex; Workspace->Connections.PushElementOnBucket(Connection); UpdateSortedNodes(Workspace, Scratch); diff --git a/src/app/foldhaus_node.h b/src/app/foldhaus_node.h index 17a6c7b..b286b28 100644 --- a/src/app/foldhaus_node.h +++ b/src/app/foldhaus_node.h @@ -59,7 +59,7 @@ struct node_specification struct node_specification_ { node_type Type; - string Identifier; + gs_string Identifier; gsm_struct_type DataType; }; @@ -92,7 +92,7 @@ struct pattern_node_workspace // This is storage for all the structures which follow. // It is cleared when new nodes are added so that the // acceleration structures can be recalculated - memory_arena Storage; + gs_memory_arena Storage; s32* SparseToSortedNodeMap; gs_list_handle* SortedNodeHandles; }; diff --git a/src/app/foldhaus_operation_mode.h b/src/app/foldhaus_operation_mode.h index 49d71bd..80c1641 100644 --- a/src/app/foldhaus_operation_mode.h +++ b/src/app/foldhaus_operation_mode.h @@ -16,6 +16,7 @@ struct operation_mode { input_command_registry Commands; operation_render_proc* Render; + gs_memory_cursor Memory; u8* OpStateMemory; }; @@ -24,28 +25,66 @@ struct operation_mode_system { s32 ActiveModesCount; operation_mode ActiveModes[OPERATION_MODES_MAX]; - arena_snapshot ModeMemorySnapshots[OPERATION_MODES_MAX]; + //arena_snapshot ModeMemorySnapshots[OPERATION_MODES_MAX]; + gs_data_array ModeMemoryPagesFreeList; // NOTE(Peter): This acts as mode scoped memory. When a mode gets activated, it can allocate // temporary memory which then gets freed when the mode is deactivated - memory_arena Arena; + gs_memory_arena Arena; }; +internal operation_mode_system +OperationModeSystemInit(gs_memory_arena* Storage, gs_thread_context ThreadContext) +{ + operation_mode_system Result = {0}; + // TODO(Peter): Do we really need an arena? Can this just operate in constant memory footprint? + Result.Arena.Allocator = ThreadContext.Allocator; + + Result.ModeMemoryPagesFreeList.CountMax = 16; // TODO(Peter): Static number of modes that can be active simultaneously + Result.ModeMemoryPagesFreeList.Data = PushArray(Storage, gs_data, Result.ModeMemoryPagesFreeList.CountMax); + for (u32 Page = 0; Page < Result.ModeMemoryPagesFreeList.CountMax; Page++) + { + // TODO(Peter): 4k pages = page size on windows + Result.ModeMemoryPagesFreeList.Data[Page] = PushSizeToData(Storage, KB(4)); + } + Result.ModeMemoryPagesFreeList.Count = Result.ModeMemoryPagesFreeList.CountMax; + + return Result; +} + +internal gs_data +OperationModeTakeMemoryPage(operation_mode_system* System) +{ + Assert(System->ModeMemoryPagesFreeList.Count > 0); + gs_data Result = {0}; + System->ModeMemoryPagesFreeList.Count -= 1; + u64 LastIndex = System->ModeMemoryPagesFreeList.Count; + Result = System->ModeMemoryPagesFreeList.Data[LastIndex]; + return Result; +} + +internal void +OperationModeFreeMemoryPage(operation_mode_system* System, gs_data Data) +{ + Assert(System->ModeMemoryPagesFreeList.Count < System->ModeMemoryPagesFreeList.CountMax); + u64 LastIndex = System->ModeMemoryPagesFreeList.Count; + System->ModeMemoryPagesFreeList.Count += 1; + System->ModeMemoryPagesFreeList.Data[LastIndex] = Data; +} + internal operation_mode* ActivateOperationMode (operation_mode_system* System, operation_render_proc* RenderProc) { - operation_mode* Result = 0; - Assert(System->ActiveModesCount < OPERATION_MODES_MAX); + operation_mode* Result = 0; s32 ModeIndex = System->ActiveModesCount++; - System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); - - operation_mode NewMode = {}; - System->ActiveModes[ModeIndex] = NewMode; + //System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena); Result = &System->ActiveModes[ModeIndex]; + Result->Memory = CreateMemoryCursor(OperationModeTakeMemoryPage(System)); Result->Render = RenderProc; + return Result; } @@ -57,13 +96,18 @@ ActivateOperationModeWithCommands_(operation_mode_system* System, input_command* { operation_mode* NewMode = ActivateOperationMode(System, RenderProc); +#if 0 InitializeInputCommandRegistry(&NewMode->Commands, CommandsCount, &System->Arena); for (s32 i = 0; i < CommandsCount; i++) { input_command Command = Commands[i]; RegisterKeyPressCommand(&NewMode->Commands, Command.Key, Command.Flags, Command.Mdfr, Command.Proc); } - +#else + NewMode->Commands.Commands = Commands; + NewMode->Commands.Size = CommandsCount; + NewMode->Commands.Used = CommandsCount; +#endif return NewMode; } @@ -72,7 +116,8 @@ DeactivateCurrentOperationMode (operation_mode_system* System) { Assert(System->ActiveModesCount > 0); s32 ModeIndex = --System->ActiveModesCount; - ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); + OperationModeFreeMemoryPage(System, System->ActiveModes[ModeIndex].Memory.Data); + //ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]); } #define CreateOperationState(mode, modeSystem, stateType) \ @@ -85,8 +130,12 @@ DeactivateCurrentOperationMode (operation_mode_system* System) internal u8* CreateOperationState_ (operation_mode* Mode, operation_mode_system* System, s32 StateSize) { - Mode->OpStateMemory = PushSize(&System->Arena, StateSize); - return Mode->OpStateMemory; + // NOTE(Peter): This isn't a problem if this fires, it just means our page size is too small, + // and its time to make the pages dynamically sized + Assert(Mode->Memory.Data.Size >= StateSize); + u8* Result = PushSizeOnCursor(&Mode->Memory, StateSize).Memory; + Mode->OpStateMemory = Result; + return Result; } diff --git a/src/app/foldhaus_panel.h b/src/app/foldhaus_panel.h index 2929c8b..53415f1 100644 --- a/src/app/foldhaus_panel.h +++ b/src/app/foldhaus_panel.h @@ -72,7 +72,7 @@ struct panel_system struct panel_with_layout { panel* Panel; - rect Bounds; + rect2 Bounds; }; struct panel_layout @@ -205,56 +205,56 @@ ConsolidatePanelsKeepOne(panel* Parent, panel_entry* PanelEntryToKeep, panel_sys // ///////////////////////////////// -internal rect -GetTopPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetTopPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = v2{ PanelBounds.Min.x, - GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, Panel->SplitPercent) + LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y) }; Result.Max = PanelBounds.Max; return Result; } -internal rect -GetBottomPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetBottomPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = PanelBounds.Min; Result.Max = v2{ PanelBounds.Max.x, - GSLerp(PanelBounds.Min.y, PanelBounds.Max.y, Panel->SplitPercent) + LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y) }; return Result; } -internal rect -GetRightPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetRightPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = v2{ - GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, Panel->SplitPercent), + LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x), PanelBounds.Min.y }; Result.Max = PanelBounds.Max; return Result; } -internal rect -GetLeftPanelBounds(panel* Panel, rect PanelBounds) +internal rect2 +GetLeftPanelBounds(panel* Panel, rect2 PanelBounds) { - rect Result = {}; + rect2 Result = {}; Result.Min = PanelBounds.Min; Result.Max = v2{ - GSLerp(PanelBounds.Min.x, PanelBounds.Max.x, Panel->SplitPercent), + LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x), PanelBounds.Max.y }; return Result; } internal void -LayoutPanel(panel* Panel, rect PanelBounds, panel_layout* Layout) +LayoutPanel(panel* Panel, rect2 PanelBounds, panel_layout* Layout) { if (Panel->SplitDirection == PanelSplit_NoSplit) { @@ -264,22 +264,22 @@ LayoutPanel(panel* Panel, rect PanelBounds, panel_layout* Layout) } else if (Panel->SplitDirection == PanelSplit_Horizontal) { - rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); + rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); LayoutPanel(&Panel->Top->Panel, TopPanelBounds, Layout); LayoutPanel(&Panel->Bottom->Panel, BottomPanelBounds, Layout); } else if (Panel->SplitDirection == PanelSplit_Vertical) { - rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); + rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); LayoutPanel(&Panel->Left->Panel, LeftPanelBounds, Layout); LayoutPanel(&Panel->Right->Panel, RightPanelBounds, Layout); } } internal panel_layout -GetPanelLayout(panel_system* System, rect WindowBounds, memory_arena* Storage) +GetPanelLayout(panel_system* System, rect2 WindowBounds, gs_memory_arena* Storage) { panel_layout Result = {}; Result.PanelsMax = System->PanelsUsed; @@ -293,11 +293,11 @@ GetPanelLayout(panel_system* System, rect WindowBounds, memory_arena* Storage) struct panel_and_bounds { panel* Panel; - rect Bounds; + rect2 Bounds; }; internal panel_and_bounds -GetPanelContainingPoint(v2 Point, panel* Panel, rect PanelBounds) +GetPanelContainingPoint(v2 Point, panel* Panel, rect2 PanelBounds) { panel_and_bounds Result = {0}; @@ -308,28 +308,28 @@ GetPanelContainingPoint(v2 Point, panel* Panel, rect PanelBounds) } else if (Panel->SplitDirection == PanelSplit_Horizontal) { - rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); - rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); + rect2 TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); + rect2 BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - if (PointIsInRange(Point, TopPanelBounds.Min, TopPanelBounds.Max)) + if (PointIsInRect(TopPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Top->Panel, TopPanelBounds); } - else if (PointIsInRange(Point, BottomPanelBounds.Min, BottomPanelBounds.Max)) + else if (PointIsInRect(BottomPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Bottom->Panel, BottomPanelBounds); } } else if (Panel->SplitDirection == PanelSplit_Vertical) { - rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); - rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); + rect2 LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); + rect2 RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - if (PointIsInRange(Point, LeftPanelBounds.Min, LeftPanelBounds.Max)) + if (PointIsInRect(LeftPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Left->Panel, LeftPanelBounds); } - else if (PointIsInRange(Point, RightPanelBounds.Min, RightPanelBounds.Max)) + else if (PointIsInRect(RightPanelBounds, Point)) { Result = GetPanelContainingPoint(Point, &Panel->Right->Panel, RightPanelBounds); } @@ -339,7 +339,7 @@ GetPanelContainingPoint(v2 Point, panel* Panel, rect PanelBounds) } internal panel_and_bounds -GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect WindowBounds) +GetPanelContainingPoint(v2 Point, panel_system* PanelSystem, rect2 WindowBounds) { panel_and_bounds Result = {0}; if (PanelSystem->PanelsUsed > 0) diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index f8f801c..4f066d4 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -7,22 +7,30 @@ #include -#define GS_LANGUAGE_NO_PROFILER_DEFINES -#include "..\gs_libs\gs_language.h" +#include // TODO Remove -#include "..\gs_libs\gs_radix_sort.h" +#include "..\gs_libs\gs_types.h" +#include "..\gs_libs\gs_types.cpp" + +//#define GS_LANGUAGE_NO_PROFILER_DEFINES +//#include "..\gs_libs\gs_language.h" + + +//#include "..\gs_libs\gs_radix_sort.h" #include "..\gs_libs\gs_list.h" #include "..\gs_libs\gs_bucket.h" -#define GS_MEMORY_TRACK_ALLOCATIONS -#include "..\gs_libs\gs_memory_arena.h" +//#define GS_MEMORY_TRACK_ALLOCATIONS +//#include "..\gs_libs\gs_memory_arena.h" #include "..\gs_libs\gs_string.h" -#include "foldhaus_debug.h" -global_variable debug_services* GlobalDebugServices; -#include "..\gs_libs\gs_vector_matrix.h" + +#include "foldhaus_debug.h" +global debug_services* GlobalDebugServices; + +//#include "..\gs_libs\gs_vector_matrix.h" #include "..\gs_libs\gs_input.h" #include "foldhaus_renderer.h" @@ -75,15 +83,6 @@ struct platform_memory_result platform_memory_error Error; }; -struct texture_buffer -{ - u8* Memory; - s32 Width; - s32 Height; - s32 Pitch; - s32 BytesPerPixel; -}; - struct system_path { char* Path; @@ -91,20 +90,13 @@ struct system_path s32 IndexOfLastSlash; }; -#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path) -typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file); - -#define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(string Path, u8* Contents, s32 Size) -typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); - -#define PLATFORM_GET_FILE_PATH(name) b32 name(string* PathBuffer, const char* FilterStrings) -typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); - -struct platform_file_handler +struct texture_buffer { - platform_read_entire_file* ReadEntireFile; - platform_write_entire_file* WriteEntireFile; - platform_get_file_path* GetFilePath; + u8* Memory; + s32 Width; + s32 Height; + s32 Pitch; + s32 BytesPerPixel; }; #define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) @@ -169,50 +161,11 @@ typedef DRAW_FONT_CODEPOINT(platform_draw_font_codepoint); #define PLATFORM_THREAD_COUNT 4 -#define THREADED_WORK_PROC(name) void name(s32 ThreadID, void* Data) -typedef THREADED_WORK_PROC(threaded_work_proc); - -typedef struct work_queue work_queue; - -#define PUSH_WORK_ON_QUEUE(name) void name(work_queue* Queue, threaded_work_proc* WorkProc, void* Data, char* JobName) -typedef PUSH_WORK_ON_QUEUE(push_work_on_queue); - -#define DO_QUEUE_WORK_UNTIL_DONE(name) void name(work_queue* Queue, s32 ThreadID) -typedef DO_QUEUE_WORK_UNTIL_DONE(do_queue_work_until_done); - -#define RESET_WORK_QUEUE(name) void name(work_queue* Queue) -typedef RESET_WORK_QUEUE(reset_work_queue); - -struct worker_thread_job -{ - void* Data; - threaded_work_proc* WorkProc; -#ifdef DEBUG - char* JobName; -#endif -}; - -struct work_queue -{ - void* SemaphoreHandle; - - u32 JobsMax; - u32 volatile JobsCount; - u32 volatile NextJobIndex; - u32 volatile JobsCompleted; - worker_thread_job* Jobs; - - // Work Queue - push_work_on_queue* PushWorkOnQueue; - do_queue_work_until_done* DoQueueWorkUntilDone; - reset_work_queue* ResetWorkQueue; -}; - RESET_WORK_QUEUE(ResetWorkQueue) { for (u32 i = 0; i < Queue->JobsMax; i++) { - Queue->Jobs[i].Data = 0; + Queue->Jobs[i].Data = {0}; Queue->Jobs[i].WorkProc = 0; } @@ -232,11 +185,13 @@ GetSecondsElapsed (s64 Start, s64 End, s64 PerformanceCountFrequency) struct context { + gs_thread_context ThreadContext; + u8* MemoryBase; u32 MemorySize; b32 WindowIsVisible; - rect WindowBounds; + rect2 WindowBounds; r32 DeltaTime; mouse_state Mouse; @@ -247,59 +202,18 @@ struct context cleanup_application* CleanupApplication; // Platform Services - work_queue* GeneralWorkQueue; + gs_work_queue* GeneralWorkQueue; - platform_memory_handler PlatformMemory; - platform_file_handler FileHandler; - - platform_write_entire_file* PlatformWriteEntireFile; - platform_get_file_path* PlatformGetFilePath; platform_get_gpu_texture_handle* PlatformGetGPUTextureHandle; platform_get_font_info* PlatformGetFontInfo; platform_draw_font_codepoint* PlatformDrawFontCodepoint; + platform_get_socket_handle* PlatformGetSocketHandle; platform_set_socket_option* PlatformSetSocketOption; platform_send_to* PlatformSendTo; platform_close_socket* PlatformCloseSocket; }; -// File Handler -internal platform_memory_result -ReadEntireFile(platform_file_handler FileHandler, string Path) -{ - platform_memory_result Result = FileHandler.ReadEntireFile(Path); - return Result; -} -internal platform_memory_result -ReadEntireFile(context Context, string Path) -{ - return ReadEntireFile(Context.FileHandler, Path); -} - -internal b32 -WriteEntireFile(platform_file_handler FileHandler, string Path, u8* Contents, u32 Size) -{ - b32 Result = FileHandler.WriteEntireFile(Path, Contents, Size); - return Result; -} -internal b32 -WriteEntireFile(context Context, string Path, u8* Contents, u32 Size) -{ - return WriteEntireFile(Context.FileHandler, Path, Contents, Size); -} - -internal b32 -GetFilePath(platform_file_handler FileHandler, string* PathBuffer, char* FilterStrings) -{ - b32 Result = FileHandler.GetFilePath(PathBuffer, (const char*)FilterStrings); - return Result; -} -internal b32 -GetFilePath(context Context, string* PathBuffer, char* FilterStrings) -{ - return GetFilePath(Context.FileHandler, PathBuffer, FilterStrings); -} - #define FOLDHAUS_PLATFORM_H #endif // FOLDHAUS_PLATFORM_H \ No newline at end of file diff --git a/src/app/foldhaus_renderer.cpp b/src/app/foldhaus_renderer.cpp index 7988e3e..ece4ee7 100644 --- a/src/app/foldhaus_renderer.cpp +++ b/src/app/foldhaus_renderer.cpp @@ -64,7 +64,7 @@ Render2DQuadBatch (u8* CommandData, s32 QuadCount) v2 P1 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 1)]; v2 P2 = Vertecies[BATCH_2D_VERTEX_INDEX(Quad, Tri, 2)]; v2 UV0 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 0)]; - v2 UV1 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 1)]; + v2 UV1 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 1)]; v2 UV2 = UVs[BATCH_2D_UV_INDEX(Quad, Tri, 2)]; v4 C0 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 0)]; v4 C1 = Colors[BATCH_2D_COLOR_INDEX(Quad, Tri, 1)]; @@ -107,11 +107,11 @@ RenderCommandBuffer (render_command_buffer CommandBuffer) render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1); - glViewport(Command->ViewOffsetX, Command->ViewOffsetY, + glViewport(Command->ViewOffsetX, Command->ViewOffsetY, Command->ViewWidth, Command->ViewHeight); - LoadModelView(Command->ModelView.E); - LoadProjection(Command->Projection.E); + LoadModelView(Command->ModelView.Array); + LoadProjection(Command->Projection.Array); if (Command->UseDepthBuffer) { diff --git a/src/app/foldhaus_renderer.h b/src/app/foldhaus_renderer.h index facfb22..d563cf8 100644 --- a/src/app/foldhaus_renderer.h +++ b/src/app/foldhaus_renderer.h @@ -19,65 +19,71 @@ struct camera inline m44 GetCameraModelViewMatrix (camera Camera) { -#if 0 - // Forward - v4 CamForward = V4(Normalize(Camera.Position - Camera.LookAt), 0); - // Right - v4 CamRight = Normalize(Cross(v4{0, 1, 0, 0}, CamForward)); - // Up - v4 CamUp = Normalize(Cross(CamForward, CamRight)); - - r32 X = Camera.Position.x; - r32 Y = Camera.Position.y; - r32 Z = Camera.Position.z; - - m44 RotationMatrix = M44( - CamRight.x, CamUp.x, CamForward.x, 0, - CamRight.y, CamUp.y, CamForward.y, 0, - CamRight.z, CamUp.z, CamForward.z, 0, - 0, 0, 0, 1); - - m44 PositionMatrix = M44( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - -X, -Y, -Z, 1 - ); -#else - m44 RotationMatrix = GetLookAtMatrix(V4(Camera.Position, 1), V4(Camera.LookAt, 1)); - m44 PositionMatrix = GetPositionM44(V4(Camera.Position, 1)); -#endif - - m44 ModelViewMatrix = PositionMatrix * RotationMatrix; - + m44 RotationMatrix = M44LookAt(ToV4Point(Camera.Position), ToV4Point(Camera.LookAt)); + m44 PositionMatrix = M44Translation(ToV4Point(-Camera.Position)); + m44 ModelViewMatrix = RotationMatrix * PositionMatrix; return ModelViewMatrix; } inline m44 GetCameraPerspectiveProjectionMatrix(camera Camera) { - r32 Top = Camera.Near * GSTan((Camera.FieldOfView / 2.0f)); - r32 Bottom = -Top; - r32 Right = Top * Camera.AspectRatio; - r32 Left = -Right; + m44 Result = M44ProjectionPerspective(Camera.FieldOfView, Camera.AspectRatio, Camera.Near, Camera.Far); + return Result; +} + +internal m44 +GetCameraMatrix(camera Camera) +{ + m44 ModelView = GetCameraModelViewMatrix(Camera); + m44 Projection = GetCameraPerspectiveProjectionMatrix(Camera); + m44 Result = Projection * ModelView; + return Result; +} + +internal v2 +ProjectWorldPointToScreen(v4 WorldSpacePoint, camera Camera, rect2 WindowBounds) +{ + v2 WindowExtents = v2{Rect2Width(WindowBounds), Rect2Height(WindowBounds)}; + v4 ProjectedPosition = GetCameraMatrix(Camera) * WorldSpacePoint; + ProjectedPosition.xyz /= ProjectedPosition.w; + v2 ScreenPosition = V2MultiplyPairwise(ProjectedPosition.xy, (WindowExtents / 2)) + (WindowExtents / 2); - r32 A = ((Right + Left) / (Right - Left)); - r32 B = ((Top + Bottom) / (Top - Bottom)); - r32 C = -((Camera.Far + Camera.Near) / (Camera.Far - Camera.Near)); - r32 D = -((2 * Camera.Far * Camera.Near) / (Camera.Far - Camera.Near)); + return ScreenPosition; +} + +internal v4_ray +ProjectScreenPointToWorldRay(v2 ScreenPoint, camera Camera, rect2 WindowBounds) +{ + v4_ray Result = {0}; - r32 E = ((2 * Camera.Near) / (Right - Left)); - r32 F = ((2 * Camera.Near) / (Top - Bottom)); + r32 TanFOVOverTwo = TanR32(DegToRadR32(Camera.FieldOfView / 2.0f)); + r32 Aspect = RectAspectRatio(WindowBounds); - m44 PerspectiveProjectionMatrix = - { - E, 0, A, 0, - 0, F, B, 0, - 0, 0, C, D, - 0, 0, -1, 0 - }; + r32 NormalizedX = ScreenPoint.x / Rect2Width(WindowBounds); + r32 NormalizedY = ScreenPoint.y / Rect2Height(WindowBounds); - return PerspectiveProjectionMatrix; + r32 CenteredX = (2.0f * NormalizedX) - 1.0f; + r32 CenteredY = (2.0f * NormalizedY) - 1.0f; + + r32 ScaledX = CenteredX * Aspect; + r32 ScaledY = CenteredY; + + r32 CameraX = ScaledX * TanFOVOverTwo; + r32 CameraY = ScaledY * TanFOVOverTwo; + + r32 Near = Camera.Near; + r32 Far = Camera.Far; + v3 MousePointOnNearPlane = v3{CameraX, CameraY, -1} * Near; + v3 MousePointOnFarPlane = v3{CameraX, CameraY, -1} * Far; + + v4 MouseRayDirection = ToV4Vec(V3Normalize(MousePointOnFarPlane - MousePointOnNearPlane)); + m44 CameraTransform = M44Transpose(M44LookAt(ToV4Point(Camera.Position), ToV4Point(Camera.LookAt))); + + Result.Origin = ToV4Point(Camera.Position); + Result.Direction = CameraTransform * MouseRayDirection; + + return Result; } // Render Commands @@ -200,7 +206,7 @@ struct render_command_set_render_mode typedef u8* renderer_realloc(u8* Base, s32 CurrentSize, s32 NewSize); -#define COMMAND_BUFFER_MIN_GROW_SIZE Megabytes(2) +#define COMMAND_BUFFER_MIN_GROW_SIZE MB(2) struct render_command_buffer { @@ -257,7 +263,7 @@ ResizeBufferIfNecessary(render_command_buffer* Buffer, s32 DataSize) // NewSize = Buffer->CommandMemorySize + (2 * DataSize); s32 SpaceAvailable = Buffer->CommandMemorySize - Buffer->CommandMemoryUsed; s32 SpaceNeeded = DataSize - SpaceAvailable; // This is known to be positive at this point - s32 AdditionSize = GSMax(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); + s32 AdditionSize = Max(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE); s32 NewSize = Buffer->CommandMemorySize + AdditionSize; Buffer->CommandMemory = Buffer->Realloc(Buffer->CommandMemory, Buffer->CommandMemorySize, @@ -285,7 +291,7 @@ PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* C internal s32 PushQuad2DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, s32 QuadCount, s32 DataSize, u8* MemStart) { - GSZeroMemory(MemStart, DataSize); + ZeroMemoryBlock(MemStart, DataSize); Constructor->Max = QuadCount; Constructor->Count = 0; @@ -316,6 +322,15 @@ struct quad_batch_constructor_reserved_range s32 OnePastLast; }; +internal quad_batch_constructor_reserved_range +ReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 TrisNeeded) +{ + quad_batch_constructor_reserved_range Result = {}; + Result.OnePastLast = Constructor->Count + TrisNeeded; + Result.Start = Result.OnePastLast - TrisNeeded; + return Result; +} + internal quad_batch_constructor_reserved_range ThreadSafeReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 TrisNeeded) { @@ -331,6 +346,8 @@ SetTri3DInBatch (render_quad_batch_constructor* Constructor, s32 TriIndex, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { + //Assert(P0.w != 0 && P1.w != 0 && P2.w != 0); // Passing vectors, rather than positions. Will draw wrong + // Vertecies Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 0)] = P0; Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 1)] = P1; @@ -355,6 +372,7 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, v4 C0, v4 C1, v4 C2) { DEBUG_TRACK_FUNCTION; + // TODO(Peter): I think we avoid doing cross thread filling of a batch so do we need this? s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor); SetTri3DInBatch(Constructor, Tri, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); }; @@ -362,7 +380,7 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, internal void PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v2 UVMin, v2 UVMax, v4 Color) { - Assert(Constructor->Count + 2 < Constructor->Max); + Assert(Constructor->Count + 2 <= Constructor->Max); PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color, Color, Color); PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color, Color, Color); } @@ -373,7 +391,7 @@ PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v2 UV0, v2 UV1, v2 UV2, v2 UV3, v4 C0, v4 C1, v4 C2, v4 C3) { - Assert(Constructor->Count < Constructor->Max); + Assert(Constructor->Count <= Constructor->Max); PushTri3DOnBatch(Constructor, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); PushTri3DOnBatch(Constructor, P0, P2, P3, UV0, UV2, UV3, C0, C2, C3); } @@ -472,7 +490,7 @@ internal void PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32 Thickness, v4 Color) { r32 HalfThickness = Thickness / 2.0f; - v2 Perpendicular = Normalize(PerpendicularCCW(P1 - P0)) * HalfThickness; + v2 Perpendicular = V2Normalize(V2PerpendicularCCW(P1 - P0)) * HalfThickness; PushQuad2DOnBatch(Constructor, P0 - Perpendicular, P1 - Perpendicular, P1 + Perpendicular, P0 + Perpendicular, v2{0, 0}, v2{1, 1}, Color); @@ -501,8 +519,8 @@ PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, { render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); - Command->ModelView = GetCameraModelViewMatrix(Camera); - Command->Projection = GetCameraPerspectiveProjectionMatrix(Camera); + Command->ModelView = M44Transpose(GetCameraModelViewMatrix(Camera)); + Command->Projection = M44Transpose(GetCameraPerspectiveProjectionMatrix(Camera)); Command->ViewOffsetX = (r32)OffsetX; Command->ViewOffsetY = (r32)OffsetY; @@ -514,25 +532,18 @@ PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, return Command; } +internal void +PushRenderPerspective(render_command_buffer* Buffer, rect2 Viewport, camera Camera) +{ + PushRenderPerspective(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport), Camera); +} + internal void PushRenderOrthographic (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, s32 ViewWidth, s32 ViewHeight) { render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); - Command->ModelView = m44{ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - - r32 a = 2.0f / ViewWidth; - r32 b = 2.0f / ViewHeight; - Command->Projection = m44{ - a, 0, 0, 0, - 0, b, 0, 0, - 0, 0, 1, 0, - -1, -1, 0, 1 - }; + Command->ModelView = M44Identity(); + Command->Projection = M44ProjectionOrtho((r32)ViewWidth, (r32)ViewHeight, 0, 100, ViewWidth, 0, ViewHeight, 0); Command->ViewOffsetX = (r32)OffsetX; Command->ViewOffsetY = (r32)OffsetY; @@ -542,6 +553,12 @@ PushRenderOrthographic (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, Command->UseDepthBuffer = false;; } +internal void +PushRenderOrthographic(render_command_buffer* Buffer, rect2 Viewport) +{ + PushRenderOrthographic(Buffer, Viewport.Min.x, Viewport.Min.y, Rect2Width(Viewport), Rect2Height(Viewport)); +} + internal void PushRenderClearScreen (render_command_buffer* Buffer) { @@ -571,6 +588,13 @@ PushRenderQuad2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color) PushQuad2DOnBatch(&Batch, Min, Max, Color); } +internal void +PushRenderQuad2D(render_command_buffer* Buffer, v2 P0, v2 P1, v2 P2, v2 P3, v4 Color) +{ + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(Buffer, 1); + PushQuad2DOnBatch(&Batch, P0, P1, P2, P3, v2{0,0}, v2{1,1}, Color); +} + internal void PushRenderLine2D (render_command_buffer* Buffer, v2 P0, v2 P1, r32 Thickness, v4 Color) { diff --git a/src/app/foldhaus_util_radialumia_file_converter.cpp b/src/app/foldhaus_util_radialumia_file_converter.cpp index 32945dd..d03074f 100644 --- a/src/app/foldhaus_util_radialumia_file_converter.cpp +++ b/src/app/foldhaus_util_radialumia_file_converter.cpp @@ -10,42 +10,42 @@ #include #include -#include +#include #include "gs/gs_language.h" #include "gs/gs_string.h" #include "../meta/gs_meta_lexer.h" #include "gs/gs_vector.h" -#define STRING_BUFFER_SIZE 512 -struct string_buffer +#define gs_string_BUFFER_SIZE 512 +struct gs_string_buffer { char* Memory; s32 Size; - string_buffer* Next; + gs_string_buffer* Next; }; -struct string_writer +struct gs_string_writer { char* Cursor; - s32 UsedInString; - string_buffer* Buffer; + s32 UsedIngs_string; + gs_string_buffer* Buffer; }; -internal string_buffer* -GrowStringBuffer (string_buffer* Buffer) +internal gs_string_buffer* +Growgs_stringBuffer (gs_string_buffer* Buffer) { - string_buffer* Result; + gs_string_buffer* Result; if (Buffer->Next) { - Result = GrowStringBuffer(Buffer->Next); + Result = Growgs_stringBuffer(Buffer->Next); } else { - Result = (string_buffer*)malloc(sizeof(string_buffer)); - Result->Memory = (char*)malloc(sizeof(char) * STRING_BUFFER_SIZE); - memset(Result->Memory, 0, STRING_BUFFER_SIZE); - Result->Size = STRING_BUFFER_SIZE; + Result = (gs_string_buffer*)malloc(sizeof(gs_string_buffer)); + Result->Memory = (char*)malloc(sizeof(char) * gs_string_BUFFER_SIZE); + memset(Result->Memory, 0, gs_string_BUFFER_SIZE); + Result->Size = gs_string_BUFFER_SIZE; Result->Next = 0; Buffer->Next = Result; @@ -54,28 +54,28 @@ GrowStringBuffer (string_buffer* Buffer) } internal void -WriteString(string_writer* Writer, char* String, s32 Length) +Writegs_string(gs_string_writer* Writer, char* gs_string, s32 Length) { - char* Src = String; + char* Src = gs_string; char* Dst = Writer->Cursor; s32 LengthWritten = 0; - while (*Src && Writer->UsedInString < Writer->Buffer->Size &&LengthWritten < Length) + while (*Src && Writer->UsedIngs_string < Writer->Buffer->Size &&LengthWritten < Length) { LengthWritten++; *Dst++ = *Src++; - Writer->UsedInString++; + Writer->UsedIngs_string++; } Writer->Cursor = Dst; - if (*Src && Writer->UsedInString == Writer->Buffer->Size) + if (*Src && Writer->UsedIngs_string == Writer->Buffer->Size) { *(Dst - 1) = 0; // Null terminate the buffer - Writer->Buffer = GrowStringBuffer(Writer->Buffer); + Writer->Buffer = Growgs_stringBuffer(Writer->Buffer); Writer->Cursor = Writer->Buffer->Memory; - Writer->UsedInString = 0; - WriteString(Writer, (Src - 1), (Length - LengthWritten) + 1); + Writer->UsedIngs_string = 0; + Writegs_string(Writer, (Src - 1), (Length - LengthWritten) + 1); } } @@ -141,15 +141,15 @@ int main(int ArgCount, char* Args[]) control_box_pairs* StartPair = NextControlBoxPair; s32 PairsCount = 0; - if (StringsEqual(Tokenizer.At, "EOF")) + if (gs_stringsEqual(Tokenizer.At, "EOF")) { break; } EatToCharacterInclusive(&Tokenizer, '{'); EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "neighbors: [")); - Tokenizer.At += StringLength("neighbors: ["); + Assert(gs_stringsEqual(Tokenizer.At, "neighbors: [")); + Tokenizer.At += gs_stringLength("neighbors: ["); // Parse Neighbors while(*Tokenizer.At && *Tokenizer.At != ']') @@ -177,8 +177,8 @@ int main(int ArgCount, char* Args[]) EatWhitespace(&Tokenizer); //Parse IP - Assert(StringsEqual(Tokenizer.At, "ip: ")); - Tokenizer.At += StringLength("ip: "); + Assert(gs_stringsEqual(Tokenizer.At, "ip: ")); + Tokenizer.At += gs_stringLength("ip: "); NextControlBox->Address = (char*)malloc(sizeof(char) * 13); memcpy(NextControlBox->Address, Tokenizer.At, 13); Tokenizer.At += 13; @@ -186,27 +186,27 @@ int main(int ArgCount, char* Args[]) // Parse X EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "x: ")); - Tokenizer.At += StringLength("x: "); + Assert(gs_stringsEqual(Tokenizer.At, "x: ")); + Tokenizer.At += gs_stringLength("x: "); NextControlBox->X = ParseFloat(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); // Parse Y EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "y: ")); - Tokenizer.At += StringLength("y: "); + Assert(gs_stringsEqual(Tokenizer.At, "y: ")); + Tokenizer.At += gs_stringLength("y: "); NextControlBox->Y = ParseFloat(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); // Parse Z EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "z: ")); - Tokenizer.At += StringLength("z: "); + Assert(gs_stringsEqual(Tokenizer.At, "z: ")); + Tokenizer.At += gs_stringLength("z: "); NextControlBox->Z = ParseFloat(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); // Parse ID EatWhitespace(&Tokenizer); - Assert(StringsEqual(Tokenizer.At, "id: ")); - Tokenizer.At += StringLength("id: "); + Assert(gs_stringsEqual(Tokenizer.At, "id: ")); + Tokenizer.At += gs_stringLength("id: "); NextControlBox->ID = ParseSignedInt(Tokenizer.At); EatToCharacterInclusive(&Tokenizer, ';'); @@ -278,36 +278,36 @@ int main(int ArgCount, char* Args[]) } - string_buffer OutputFileBuffer = {}; - OutputFileBuffer.Memory = (char*)malloc(sizeof(char) * STRING_BUFFER_SIZE); - OutputFileBuffer.Size = STRING_BUFFER_SIZE; + gs_string_buffer OutputFileBuffer = {}; + OutputFileBuffer.Memory = (char*)malloc(sizeof(char) * gs_string_BUFFER_SIZE); + OutputFileBuffer.Size = gs_string_BUFFER_SIZE; OutputFileBuffer.Next = 0; - string_writer RefWriter = {}; + gs_string_writer RefWriter = {}; RefWriter.Cursor = OutputFileBuffer.Memory; - RefWriter.UsedInString = 0; + RefWriter.UsedIngs_string = 0; RefWriter.Buffer = &OutputFileBuffer; - string_writer* Writer = &RefWriter; + gs_string_writer* Writer = &RefWriter; - char StringBuffer[512]; + char gs_stringBuffer[512]; s32 Len = 0; - Len = sprintf_s(StringBuffer, 512, "control_box_count %d\n", ControlBoxesUsed); - WriteString(Writer, StringBuffer, Len); - Len = sprintf_s(StringBuffer, 512, "led_strip_count %d\n\n", ControlBoxPairsUsed); - WriteString(Writer, StringBuffer, Len); + Len = sprintf_s(gs_stringBuffer, 512, "control_box_count %d\n", ControlBoxesUsed); + Writegs_string(Writer, gs_stringBuffer, Len); + Len = sprintf_s(gs_stringBuffer, 512, "led_strip_count %d\n\n", ControlBoxPairsUsed); + Writegs_string(Writer, gs_stringBuffer, Len); for (s32 c = 0; c < ControlBoxesUsed; c++) { control_box* Box = ControlBoxes + c; - Len = sprintf_s(StringBuffer, 512, + Len = sprintf_s(gs_stringBuffer, 512, "control_box { %d, \"%s\", (%f, %f, %f) }\n", Box->ID, Box->Address, Box->X, Box->Y, Box->Z); - WriteString(Writer, StringBuffer, Len); + Writegs_string(Writer, gs_stringBuffer, Len); } - WriteString(Writer, "\n", 1); + Writegs_string(Writer, "\n", 1); #define UNIVERSES_PER_BOX 25 s32 UniversesPerBox[64]; @@ -316,7 +316,7 @@ int main(int ArgCount, char* Args[]) UniversesPerBox[u] = UNIVERSES_PER_BOX * u; } - char LEDStripFormatString[] = "led_strip { %d, %d, %d, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 144 } \n"; + char LEDStripFormatgs_string[] = "led_strip { %d, %d, %d, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 144 } \n"; for (s32 s = 0; s < ControlBoxPairsUsed; s++) { control_box_pairs* Pair = ControlBoxPairs + s; @@ -332,15 +332,15 @@ int main(int ArgCount, char* Args[]) r32 EndY = ControlBoxes[Pair->End].Y; r32 EndZ = ControlBoxes[Pair->End].Z; - Len = sprintf_s(StringBuffer, 512, - LEDStripFormatString, + Len = sprintf_s(gs_stringBuffer, 512, + LEDStripFormatgs_string, Pair->Start, Universe, 0, StartX, StartY, StartZ, EndX, EndY, EndZ); - WriteString(Writer, StringBuffer, Len); + Writegs_string(Writer, gs_stringBuffer, Len); } - WriteString(Writer, "\n", 1); + Writegs_string(Writer, "\n", 1); for (s32 sp = 0; sp < ExtraStripsUsed; sp++) { @@ -349,20 +349,20 @@ int main(int ArgCount, char* Args[]) s32 Universe = UniversesPerBox[Strip->BoxID]; UniversesPerBox[Strip->BoxID]++; - Len = sprintf_s(StringBuffer, 512, - LEDStripFormatString, + Len = sprintf_s(gs_stringBuffer, 512, + LEDStripFormatgs_string, Strip->BoxID, Universe, 0, Strip->Start.x, Strip->Start.y, Strip->Start.z, Strip->End.x, Strip->End.y, Strip->End.z); - WriteString(Writer, StringBuffer, Len); + Writegs_string(Writer, gs_stringBuffer, Len); } - WriteString(Writer, "END_OF_ASSEMBLY_FILE", StringLength("END_OF_ASSEMBLY_FILE")); + Writegs_string(Writer, "END_OF_ASSEMBLY_FILE", gs_stringLength("END_OF_ASSEMBLY_FILE")); *Writer->Cursor = 0; FILE* OutputFile = fopen("F:/data/radialumia.fold", "w"); - string_buffer* BufferCursor = &OutputFileBuffer; + gs_string_buffer* BufferCursor = &OutputFileBuffer; while(BufferCursor) { fprintf(OutputFile, BufferCursor->Memory); diff --git a/src/app/generated/foldhaus_panels_generated.h b/src/app/generated/foldhaus_panels_generated.h index 48610ca..67ca2a3 100644 --- a/src/app/generated/foldhaus_panels_generated.h +++ b/src/app/generated/foldhaus_panels_generated.h @@ -1,19 +1,18 @@ enum panel_type { -PanelType_FileView, -PanelType_SculptureView, -PanelType_AnimationTimeline, -PanelType_DMXView, -PanelType_HierarchyView, -PanelType_NodeGraph, -PanelType_ProfilerView, + PanelType_FileView, + PanelType_SculptureView, + PanelType_AnimationTimeline, + PanelType_DMXView, + PanelType_HierarchyView, + PanelType_NodeGraph, + PanelType_ProfilerView, }; -global_variable s32 GlobalPanelDefsCount = 7; -global_variable panel_definition GlobalPanelDefs[] = { -{ "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, -{ "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, -{ "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount }, -{ "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, -{ "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, -{ "Node Graph", 10, NodeGraph_Init, NodeGraph_Cleanup, NodeGraph_Render, NodeGraph_Commands, NodeGraph_CommandsCount }, -{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, +global s32 GlobalPanelDefsCount = 6; +global panel_definition GlobalPanelDefs[] = { + { "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount }, + { "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount }, + { "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount }, + { "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount }, + { "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount }, + { "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount }, }; diff --git a/src/app/generated/gs_meta_generated_typeinfo.h b/src/app/generated/gs_meta_generated_typeinfo.h index fd1d779..9477f54 100644 --- a/src/app/generated/gs_meta_generated_typeinfo.h +++ b/src/app/generated/gs_meta_generated_typeinfo.h @@ -1,40 +1,41 @@ enum gsm_meta_tag_type { -MetaTag_panel_type_file_view, -MetaTag_panel_type_node_graph, -MetaTag_node_output, -MetaTag_node_struct, -MetaTag_panel_cleanup, -MetaTag_node_input, -MetaTag_panel_init, -MetaTag_panel_type_animation_timeline, -MetaTag_panel_commands, -MetaTag_panel_type_sculpture_view, -MetaTag_node_proc, -MetaTag_panel_type_hierarchy, -MetaTag_panel_type_profiler, -MetaTag_panel_render, -MetaTag_panel_type_dmx_view, + MetaTag_panel_type_file_view, + MetaTag_panel_type_node_graph, + MetaTag_node_output, + MetaTag_node_struct, + MetaTag_panel_cleanup, + MetaTag_node_input, + MetaTag_panel_init, + MetaTag_panel_type_animation_timeline, + MetaTag_panel_commands, + MetaTag_panel_type_sculpture_view, + MetaTag_node_proc, + MetaTag_panel_type_hierarchy, + MetaTag_panel_type_profiler, + MetaTag_panel_render, + MetaTag_panel_type_dmx_view, }; -gsm_meta_tag MetaTagStrings[] = { -{ "panel_type_file_view", 20 }, -{ "panel_type_node_graph", 21 }, -{ "node_output", 11 }, -{ "node_struct", 11 }, -{ "panel_cleanup", 13 }, -{ "node_input", 10 }, -{ "panel_init", 10 }, -{ "panel_type_animation_timeline", 29 }, -{ "panel_commands", 14 }, -{ "panel_type_sculpture_view", 25 }, -{ "node_proc", 9 }, -{ "panel_type_hierarchy", 20 }, -{ "panel_type_profiler", 19 }, -{ "panel_render", 12 }, -{ "panel_type_dmx_view", 19 }, +gsm_meta_tag MetaTaggs_strings[] = { + { "panel_type_file_view", 20 }, + { "panel_type_node_graph", 21 }, + { "node_output", 11 }, + { "node_struct", 11 }, + { "panel_cleanup", 13 }, + { "node_input", 10 }, + { "panel_init", 10 }, + { "panel_type_animation_timeline", 29 }, + { "panel_commands", 14 }, + { "panel_type_sculpture_view", 25 }, + { "node_proc", 9 }, + { "panel_type_hierarchy", 20 }, + { "panel_type_profiler", 19 }, + { "panel_render", 12 }, + { "panel_type_dmx_view", 19 }, }; enum gsm_struct_type { + gsm_StructType_r32, gsm_StructType_solid_color_data, gsm_StructType_v4, gsm_StructType_float, @@ -42,85 +43,68 @@ enum gsm_struct_type gsm_StructType_pixel, gsm_StructType_u8, gsm_StructType_s32, - gsm_StructType_sin_wave_data, - gsm_StructType_r32, gsm_StructType_revolving_discs_data, gsm_StructType_vertical_color_fade_data, - gsm_StructType_multiply_patterns_data, gsm_StructType_Count, }; static gsm_struct_member_type_info StructMembers_v4[] = { -{ "x", 1, (u64)&((v4*)0)->x, {}, 0}, -{ "y", 1, (u64)&((v4*)0)->y, {}, 0}, -{ "z", 1, (u64)&((v4*)0)->z, {}, 0}, -{ "w", 1, (u64)&((v4*)0)->w, {}, 0}, -{ "r", 1, (u64)&((v4*)0)->r, {}, 0}, -{ "g", 1, (u64)&((v4*)0)->g, {}, 0}, -{ "b", 1, (u64)&((v4*)0)->b, {}, 0}, -{ "a", 1, (u64)&((v4*)0)->a, {}, 0}, -{ "xy", 2, (u64)&((v4*)0)->xy, {}, 0}, -{ "yz", 2, (u64)&((v4*)0)->yz, {}, 0}, -{ "xyz", 3, (u64)&((v4*)0)->xyz, {}, 0}, -{ "z", 1, (u64)&((v4*)0)->z, {}, 0}, -{ "E", 1, (u64)&((v4*)0)->E, {}, 0}, + { "x", 1, (u64)&((v4*)0)->x, {}, 0}, + { "y", 1, (u64)&((v4*)0)->y, {}, 0}, + { "z", 1, (u64)&((v4*)0)->z, {}, 0}, + { "w", 1, (u64)&((v4*)0)->w, {}, 0}, + { "r", 1, (u64)&((v4*)0)->r, {}, 0}, + { "g", 1, (u64)&((v4*)0)->g, {}, 0}, + { "b", 1, (u64)&((v4*)0)->b, {}, 0}, + { "a", 1, (u64)&((v4*)0)->a, {}, 0}, + { "xy", 2, (u64)&((v4*)0)->xy, {}, 0}, + { "yz", 2, (u64)&((v4*)0)->yz, {}, 0}, + { "xyz", 3, (u64)&((v4*)0)->xyz, {}, 0}, + { "z", 1, (u64)&((v4*)0)->z, {}, 0}, + { "E", 1, (u64)&((v4*)0)->E, {}, 0}, }; static gsm_struct_member_type_info StructMembers_pixel[] = { -{ "R", 1, (u64)&((pixel*)0)->R, {}, 0}, -{ "G", 1, (u64)&((pixel*)0)->G, {}, 0}, -{ "B", 1, (u64)&((pixel*)0)->B, {}, 0}, -{ "Channels", 8, (u64)&((pixel*)0)->Channels, {}, 0}, + { "R", 1, (u64)&((pixel*)0)->R, {}, 0}, + { "G", 1, (u64)&((pixel*)0)->G, {}, 0}, + { "B", 1, (u64)&((pixel*)0)->B, {}, 0}, + { "Channels", 8, (u64)&((pixel*)0)->Channels, {}, 0}, }; static gsm_struct_member_type_info StructMembers_color_buffer[] = { -{ "LedPositions", 12, (u64)&((color_buffer*)0)->LedPositions, {}, 0}, -{ "Colors", 6, (u64)&((color_buffer*)0)->Colors, {}, 0}, -{ "LEDCount", 8, (u64)&((color_buffer*)0)->LEDCount, {}, 0}, + { "LedPositions", 12, (u64)&((color_buffer*)0)->LedPositions, {}, 0}, + { "Colors", 6, (u64)&((color_buffer*)0)->Colors, {}, 0}, + { "LEDCount", 8, (u64)&((color_buffer*)0)->LEDCount, {}, 0}, }; static gsm_struct_member_type_info StructMembers_solid_color_data[] = { -{ "Color", 5, (u64)&((solid_color_data*)0)->Color, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((solid_color_data*)0)->Result, {MetaTag_node_output, }, 1}, -}; -static gsm_struct_member_type_info StructMembers_sin_wave_data[] = { -{ "Period", 6, (u64)&((sin_wave_data*)0)->Period, {MetaTag_node_input, }, 1}, -{ "Min", 3, (u64)&((sin_wave_data*)0)->Min, {MetaTag_node_input, }, 1}, -{ "Max", 3, (u64)&((sin_wave_data*)0)->Max, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((sin_wave_data*)0)->Result, {MetaTag_node_input, }, 1}, -{ "Accumulator", 11, (u64)&((sin_wave_data*)0)->Accumulator, {}, 0}, + { "Color", 5, (u64)&((solid_color_data*)0)->Color, {MetaTag_node_input, }, 1}, + { "Result", 6, (u64)&((solid_color_data*)0)->Result, {MetaTag_node_output, }, 1}, }; static gsm_struct_member_type_info StructMembers_revolving_discs_data[] = { -{ "Rotation", 8, (u64)&((revolving_discs_data*)0)->Rotation, {MetaTag_node_input, }, 1}, -{ "ThetaZ", 6, (u64)&((revolving_discs_data*)0)->ThetaZ, {MetaTag_node_input, }, 1}, -{ "ThetaY", 6, (u64)&((revolving_discs_data*)0)->ThetaY, {MetaTag_node_input, }, 1}, -{ "DiscWidth", 9, (u64)&((revolving_discs_data*)0)->DiscWidth, {MetaTag_node_input, }, 1}, -{ "InnerRadius", 11, (u64)&((revolving_discs_data*)0)->InnerRadius, {MetaTag_node_input, }, 1}, -{ "OuterRadius", 11, (u64)&((revolving_discs_data*)0)->OuterRadius, {MetaTag_node_input, }, 1}, -{ "Color", 5, (u64)&((revolving_discs_data*)0)->Color, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((revolving_discs_data*)0)->Result, {MetaTag_node_output, }, 1}, + { "Rotation", 8, (u64)&((revolving_discs_data*)0)->Rotation, {MetaTag_node_input, }, 1}, + { "ThetaZ", 6, (u64)&((revolving_discs_data*)0)->ThetaZ, {MetaTag_node_input, }, 1}, + { "ThetaY", 6, (u64)&((revolving_discs_data*)0)->ThetaY, {MetaTag_node_input, }, 1}, + { "DiscWidth", 9, (u64)&((revolving_discs_data*)0)->DiscWidth, {MetaTag_node_input, }, 1}, + { "InnerRadius", 11, (u64)&((revolving_discs_data*)0)->InnerRadius, {MetaTag_node_input, }, 1}, + { "OuterRadius", 11, (u64)&((revolving_discs_data*)0)->OuterRadius, {MetaTag_node_input, }, 1}, + { "Color", 5, (u64)&((revolving_discs_data*)0)->Color, {MetaTag_node_input, }, 1}, + { "Result", 6, (u64)&((revolving_discs_data*)0)->Result, {MetaTag_node_output, }, 1}, }; static gsm_struct_member_type_info StructMembers_vertical_color_fade_data[] = { -{ "Color", 5, (u64)&((vertical_color_fade_data*)0)->Color, {MetaTag_node_input, }, 1}, -{ "Min", 3, (u64)&((vertical_color_fade_data*)0)->Min, {MetaTag_node_input, }, 1}, -{ "Max", 3, (u64)&((vertical_color_fade_data*)0)->Max, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((vertical_color_fade_data*)0)->Result, {MetaTag_node_output, }, 1}, -}; -static gsm_struct_member_type_info StructMembers_multiply_patterns_data[] = { -{ "A", 1, (u64)&((multiply_patterns_data*)0)->A, {MetaTag_node_input, }, 1}, -{ "B", 1, (u64)&((multiply_patterns_data*)0)->B, {MetaTag_node_input, }, 1}, -{ "Result", 6, (u64)&((multiply_patterns_data*)0)->Result, {MetaTag_node_output, }, 1}, + { "Color", 5, (u64)&((vertical_color_fade_data*)0)->Color, {MetaTag_node_input, }, 1}, + { "Min", 3, (u64)&((vertical_color_fade_data*)0)->Min, {MetaTag_node_input, }, 1}, + { "Max", 3, (u64)&((vertical_color_fade_data*)0)->Max, {MetaTag_node_input, }, 1}, + { "Result", 6, (u64)&((vertical_color_fade_data*)0)->Result, {MetaTag_node_output, }, 1}, }; static gsm_struct_type_info StructTypes[] = { -{ gsm_StructType_solid_color_data, "solid_color_data", 16, 36, 0, 0, StructMembers_solid_color_data, 2 }, -{ gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 5 }, -{ gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, -{ gsm_StructType_color_buffer, "color_buffer", 12, 20, 0, 0, StructMembers_color_buffer, 3 }, -{ gsm_StructType_pixel, "pixel", 5, 3, 0, 0, StructMembers_pixel, 2 }, -{ gsm_StructType_u8, "u8", 2, 1, 0, 0, 0, 0 }, -{ gsm_StructType_s32, "s32", 3, 4, 0, 0, 0, 0 }, -{ gsm_StructType_sin_wave_data, "sin_wave_data", 13, 20, 0, 0, StructMembers_sin_wave_data, 5 }, -{ gsm_StructType_r32, "r32", 3, 4, 0, 0, 0, 0 }, -{ gsm_StructType_revolving_discs_data, "revolving_discs_data", 20, 60, 0, 0, StructMembers_revolving_discs_data, 8 }, -{ gsm_StructType_vertical_color_fade_data, "vertical_color_fade_data", 24, 44, 0, 0, StructMembers_vertical_color_fade_data, 4 }, -{ gsm_StructType_multiply_patterns_data, "multiply_patterns_data", 22, 60, 0, 0, StructMembers_multiply_patterns_data, 3 }, + { gsm_StructType_r32, "r32", 3, 4, 0, 0, 0, 0 }, + { gsm_StructType_solid_color_data, "solid_color_data", 16, 32, 0, 0, StructMembers_solid_color_data, 2 }, + { gsm_StructType_v4, "v4", 2, 16, 0, 0, StructMembers_v4, 5 }, + { gsm_StructType_float, "float", 5, 4, 0, 0, 0, 0 }, + { gsm_StructType_color_buffer, "color_buffer", 12, 16, 0, 0, StructMembers_color_buffer, 3 }, + { gsm_StructType_pixel, "pixel", 5, 0, 0, 0, StructMembers_pixel, 2 }, + { gsm_StructType_u8, "u8", 2, 0, 0, 0, 0, 0 }, + { gsm_StructType_s32, "s32", 3, 0, 0, 0, 0, 0 }, + { gsm_StructType_revolving_discs_data, "revolving_discs_data", 20, 56, 0, 0, StructMembers_revolving_discs_data, 8 }, + { gsm_StructType_vertical_color_fade_data, "vertical_color_fade_data", 24, 40, 0, 0, StructMembers_vertical_color_fade_data, 4 }, }; static gsm_u32 StructTypesCount = 12; diff --git a/src/app/gs_osx_window.mm b/src/app/gs_osx_window.mm index 3b0d29c..eefafd3 100644 --- a/src/app/gs_osx_window.mm +++ b/src/app/gs_osx_window.mm @@ -67,7 +67,7 @@ gsosx_CreateWindow(NSApplication* App, int Width, int Height, id Title) [App setMainMenu: MenuBar]; NSMenu* AppMenu = [NSMenu alloc]; - id QuitTitle = [@"Quit " stringByAppendingString: Title]; + id QuitTitle = [@"Quit " gs_stringByAppendinggs_string: Title]; id QuitMenuItem = [[NSMenuItem alloc] initWithTitle: QuitTitle action: @selector(terminate:) keyEquivalent: @"q"]; [AppMenu addItem: QuitMenuItem]; [AppMenuItem setSubmenu: AppMenu]; diff --git a/src/app/handmade_math.h b/src/app/handmade_math.h new file mode 100644 index 0000000..049dfdb --- /dev/null +++ b/src/app/handmade_math.h @@ -0,0 +1,3239 @@ +/* + HandmadeMath.h v1.11.0 + + This is a single header file with a bunch of useful functions for game and + graphics math operations. + + ============================================================================= + + You MUST + + #define HANDMADE_MATH_IMPLEMENTATION + + in EXACTLY one C or C++ file that includes this header, BEFORE the + include, like this: + + #define HANDMADE_MATH_IMPLEMENTATION + #include "HandmadeMath.h" + + All other files should just #include "HandmadeMath.h" without the #define. + + ============================================================================= + + To disable SSE intrinsics, you MUST + + #define HANDMADE_MATH_NO_SSE + + in EXACTLY one C or C++ file that includes this header, BEFORE the + include, like this: + + #define HANDMADE_MATH_IMPLEMENTATION + #define HANDMADE_MATH_NO_SSE + #include "HandmadeMath.h" + + ============================================================================= + + If you would prefer not to use the HMM_ prefix on function names, you can + + #define HMM_PREFIX + + To use a custom prefix instead, you can + + #define HMM_PREFIX(name) YOUR_PREFIX_##name + + ============================================================================= + + To use HandmadeMath without the CRT, you MUST + + #define HMM_SINF MySinF + #define HMM_COSF MyCosF + #define HMM_TANF MyTanF + #define HMM_SQRTF MySqrtF + #define HMM_EXPF MyExpF + #define HMM_LOGF MyLogF + #define HMM_ACOSF MyACosF + #define HMM_ATANF MyATanF + #define HMM_ATAN2F MYATan2F + + Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, + ExpF, and LogF in EXACTLY one C or C++ file that includes this header, + BEFORE the include, like this: + + #define HMM_SINF MySinF + #define HMM_COSF MyCosF + #define HMM_TANF MyTanF + #define HMM_SQRTF MySqrtF + #define HMM_EXPF MyExpF + #define HMM_LOGF MyLogF + #define HMM_ACOSF MyACosF + #define HMM_ATANF MyATanF + #define HMM_ATAN2F MyATan2F + #define HANDMADE_MATH_IMPLEMENTATION + #include "HandmadeMath.h" + + If you do not define all of these, HandmadeMath.h will use the + versions of these functions that are provided by the CRT. + + ============================================================================= + + LICENSE + + This software is in the public domain. Where that dedication is not + recognized, you are granted a perpetual, irrevocable license to copy, + distribute, and modify this file as you see fit. + + CREDITS + + Written by Zakary Strange (strangezak@gmail.com && @strangezak) + + Functionality: + Matt Mascarenhas (@miblo_) + Aleph + FieryDrake (@fierydrake) + Gingerbill (@TheGingerBill) + Ben Visness (@bvisness) + Trinton Bullard (@Peliex_Dev) + @AntonDan + + Fixes: + Jeroen van Rijn (@J_vanRijn) + Kiljacken (@Kiljacken) + Insofaras (@insofaras) + Daniel Gibson (@DanielGibson) +*/ + +// Dummy macros for when test framework is not present. +#ifndef COVERAGE +#define COVERAGE(a, b) +#endif + +#ifndef ASSERT_COVERED +#define ASSERT_COVERED(a) +#endif + +/* let's figure out if SSE is really available (unless disabled anyway) + (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support) + => only use "#ifdef HANDMADE_MATH__USE_SSE" to check for SSE support below this block! */ +#ifndef HANDMADE_MATH_NO_SSE + +# ifdef _MSC_VER +/* MSVC supports SSE in amd64 mode or _M_IX86_FP >= 1 (2 means SSE2) */ +# if defined(_M_AMD64) || ( defined(_M_IX86_FP) && _M_IX86_FP >= 1 ) +# define HANDMADE_MATH__USE_SSE 1 +# endif +# else /* not MSVC, probably GCC, clang, icc or something that doesn't support SSE anyway */ +# ifdef __SSE__ /* they #define __SSE__ if it's supported */ +# define HANDMADE_MATH__USE_SSE 1 +# endif /* __SSE__ */ +# endif /* not _MSC_VER */ + +#endif /* #ifndef HANDMADE_MATH_NO_SSE */ + +#ifdef HANDMADE_MATH__USE_SSE +#include +#endif + +#ifndef HANDMADE_MATH_H +#define HANDMADE_MATH_H + +#ifdef _MSC_VER +#pragma warning(disable:4201) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 8) +#pragma GCC diagnostic ignored "-Wmissing-braces" +#endif +#ifdef __clang__ +#pragma GCC diagnostic ignored "-Wgnu-anonymous-struct" +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define HMM_DEPRECATED(msg) __attribute__((deprecated(msg))) +#elif defined(_MSC_VER) +#define HMM_DEPRECATED(msg) __declspec(deprecated(msg)) +#else +#define HMM_DEPRECATED(msg) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define HMM_INLINE static inline +#define HMM_EXTERN extern + +#if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \ + !defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \ + !defined(HMM_ACOSF) || !defined(HMM_ATANF)|| !defined(HMM_ATAN2F) +#include +#endif + +#ifndef HMM_SINF +#define HMM_SINF sinf +#endif + +#ifndef HMM_COSF +#define HMM_COSF cosf +#endif + +#ifndef HMM_TANF +#define HMM_TANF tanf +#endif + +#ifndef HMM_SQRTF +#define HMM_SQRTF sqrtf +#endif + +#ifndef HMM_EXPF +#define HMM_EXPF expf +#endif + +#ifndef HMM_LOGF +#define HMM_LOGF logf +#endif + +#ifndef HMM_ACOSF +#define HMM_ACOSF acosf +#endif + +#ifndef HMM_ATANF +#define HMM_ATANF atanf +#endif + +#ifndef HMM_ATAN2F +#define HMM_ATAN2F atan2f +#endif + +#define HMM_PI32 3.14159265359f +#define HMM_PI 3.14159265358979323846 + +#define HMM_MIN(a, b) (a) > (b) ? (b) : (a) +#define HMM_MAX(a, b) (a) < (b) ? (b) : (a) +#define HMM_ABS(a) ((a) > 0 ? (a) : -(a)) +#define HMM_MOD(a, m) ((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)) +#define HMM_SQUARE(x) ((x) * (x)) + +#ifndef HMM_PREFIX +#define HMM_PREFIX(name) HMM_##name +#endif + + typedef union hmm_vec2 + { + struct + { + float X, Y; + }; + + struct + { + float U, V; + }; + + struct + { + float Left, Right; + }; + + struct + { + float Width, Height; + }; + + float Elements[2]; + +#ifdef __cplusplus + inline float &operator[](const int &Index) + { + return Elements[Index]; + } +#endif + } hmm_vec2; + + typedef union hmm_vec3 + { + struct + { + float X, Y, Z; + }; + + struct + { + float U, V, W; + }; + + struct + { + float R, G, B; + }; + + struct + { + hmm_vec2 XY; + float Ignored0_; + }; + + struct + { + float Ignored1_; + hmm_vec2 YZ; + }; + + struct + { + hmm_vec2 UV; + float Ignored2_; + }; + + struct + { + float Ignored3_; + hmm_vec2 VW; + }; + + float Elements[3]; + +#ifdef __cplusplus + inline float &operator[](const int &Index) + { + return Elements[Index]; + } +#endif + } hmm_vec3; + + typedef union hmm_vec4 + { + struct + { + union + { + hmm_vec3 XYZ; + struct + { + float X, Y, Z; + }; + }; + + float W; + }; + struct + { + union + { + hmm_vec3 RGB; + struct + { + float R, G, B; + }; + }; + + float A; + }; + + struct + { + hmm_vec2 XY; + float Ignored0_; + float Ignored1_; + }; + + struct + { + float Ignored2_; + hmm_vec2 YZ; + float Ignored3_; + }; + + struct + { + float Ignored4_; + float Ignored5_; + hmm_vec2 ZW; + }; + + float Elements[4]; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 InternalElementsSSE; +#endif + +#ifdef __cplusplus + inline float &operator[](const int &Index) + { + return Elements[Index]; + } +#endif + } hmm_vec4; + + typedef union hmm_mat4 + { + float Elements[4][4]; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Columns[4]; + + HMM_DEPRECATED("Our matrices are column-major, so this was named incorrectly. Use Columns instead.") + __m128 Rows[4]; +#endif + +#ifdef __cplusplus + inline hmm_vec4 operator[](const int &Index) + { + float* col = Elements[Index]; + + hmm_vec4 result; + result.Elements[0] = col[0]; + result.Elements[1] = col[1]; + result.Elements[2] = col[2]; + result.Elements[3] = col[3]; + + return result; + } +#endif + } hmm_mat4; + + typedef union hmm_quaternion + { + struct + { + union + { + hmm_vec3 XYZ; + struct + { + float X, Y, Z; + }; + }; + + float W; + }; + + float Elements[4]; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 InternalElementsSSE; +#endif + } hmm_quaternion; + + typedef signed int hmm_bool; + + typedef hmm_vec2 hmm_v2; + typedef hmm_vec3 hmm_v3; + typedef hmm_vec4 hmm_v4; + typedef hmm_mat4 hmm_m4; + + + /* + * Floating-point math functions + */ + + COVERAGE(HMM_SinF, 1) + HMM_INLINE float HMM_PREFIX(SinF)(float Radians) + { + ASSERT_COVERED(HMM_SinF); + + float Result = HMM_SINF(Radians); + + return (Result); + } + + COVERAGE(HMM_CosF, 1) + HMM_INLINE float HMM_PREFIX(CosF)(float Radians) + { + ASSERT_COVERED(HMM_CosF); + + float Result = HMM_COSF(Radians); + + return (Result); + } + + COVERAGE(HMM_TanF, 1) + HMM_INLINE float HMM_PREFIX(TanF)(float Radians) + { + ASSERT_COVERED(HMM_TanF); + + float Result = HMM_TANF(Radians); + + return (Result); + } + + COVERAGE(HMM_ACosF, 1) + HMM_INLINE float HMM_PREFIX(ACosF)(float Radians) + { + ASSERT_COVERED(HMM_ACosF); + + float Result = HMM_ACOSF(Radians); + + return (Result); + } + + COVERAGE(HMM_ATanF, 1) + HMM_INLINE float HMM_PREFIX(ATanF)(float Radians) + { + ASSERT_COVERED(HMM_ATanF); + + float Result = HMM_ATANF(Radians); + + return (Result); + } + + COVERAGE(HMM_ATan2F, 1) + HMM_INLINE float HMM_PREFIX(ATan2F)(float Left, float Right) + { + ASSERT_COVERED(HMM_ATan2F); + + float Result = HMM_ATAN2F(Left, Right); + + return (Result); + } + + COVERAGE(HMM_ExpF, 1) + HMM_INLINE float HMM_PREFIX(ExpF)(float Float) + { + ASSERT_COVERED(HMM_ExpF); + + float Result = HMM_EXPF(Float); + + return (Result); + } + + COVERAGE(HMM_LogF, 1) + HMM_INLINE float HMM_PREFIX(LogF)(float Float) + { + ASSERT_COVERED(HMM_LogF); + + float Result = HMM_LOGF(Float); + + return (Result); + } + + COVERAGE(HMM_SquareRootF, 1) + HMM_INLINE float HMM_PREFIX(SquareRootF)(float Float) + { + ASSERT_COVERED(HMM_SquareRootF); + + float Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 In = _mm_set_ss(Float); + __m128 Out = _mm_sqrt_ss(In); + Result = _mm_cvtss_f32(Out); +#else + Result = HMM_SQRTF(Float); +#endif + + return(Result); + } + + COVERAGE(HMM_RSquareRootF, 1) + HMM_INLINE float HMM_PREFIX(RSquareRootF)(float Float) + { + ASSERT_COVERED(HMM_RSquareRootF); + + float Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 In = _mm_set_ss(Float); + __m128 Out = _mm_rsqrt_ss(In); + Result = _mm_cvtss_f32(Out); +#else + Result = 1.0f/HMM_PREFIX(SquareRootF)(Float); +#endif + + return(Result); + } + + HMM_EXTERN float HMM_PREFIX(Power)(float Base, int Exponent); + + COVERAGE(HMM_PowerF, 1) + HMM_INLINE float HMM_PREFIX(PowerF)(float Base, float Exponent) + { + ASSERT_COVERED(HMM_PowerF); + + float Result = HMM_EXPF(Exponent * HMM_LOGF(Base)); + + return (Result); + } + + + /* + * Utility functions + */ + + COVERAGE(HMM_ToRadians, 1) + HMM_INLINE float HMM_PREFIX(ToRadians)(float Degrees) + { + ASSERT_COVERED(HMM_ToRadians); + + float Result = Degrees * (HMM_PI32 / 180.0f); + + return (Result); + } + + COVERAGE(HMM_Lerp, 1) + HMM_INLINE float HMM_PREFIX(Lerp)(float A, float Time, float B) + { + ASSERT_COVERED(HMM_Lerp); + + float Result = (1.0f - Time) * A + Time * B; + + return (Result); + } + + COVERAGE(HMM_Clamp, 1) + HMM_INLINE float HMM_PREFIX(Clamp)(float Min, float Value, float Max) + { + ASSERT_COVERED(HMM_Clamp); + + float Result = Value; + + if(Result < Min) + { + Result = Min; + } + else if(Result > Max) + { + Result = Max; + } + + return (Result); + } + + + /* + * Vector initialization + */ + + COVERAGE(HMM_Vec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2)(float X, float Y) + { + ASSERT_COVERED(HMM_Vec2); + + hmm_vec2 Result; + + Result.X = X; + Result.Y = Y; + + return (Result); + } + + COVERAGE(HMM_Vec2i, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2i)(int X, int Y) + { + ASSERT_COVERED(HMM_Vec2i); + + hmm_vec2 Result; + + Result.X = (float)X; + Result.Y = (float)Y; + + return (Result); + } + + COVERAGE(HMM_Vec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3)(float X, float Y, float Z) + { + ASSERT_COVERED(HMM_Vec3); + + hmm_vec3 Result; + + Result.X = X; + Result.Y = Y; + Result.Z = Z; + + return (Result); + } + + COVERAGE(HMM_Vec3i, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3i)(int X, int Y, int Z) + { + ASSERT_COVERED(HMM_Vec3i); + + hmm_vec3 Result; + + Result.X = (float)X; + Result.Y = (float)Y; + Result.Z = (float)Z; + + return (Result); + } + + COVERAGE(HMM_Vec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4)(float X, float Y, float Z, float W) + { + ASSERT_COVERED(HMM_Vec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); +#else + Result.X = X; + Result.Y = Y; + Result.Z = Z; + Result.W = W; +#endif + + return (Result); + } + + COVERAGE(HMM_Vec4i, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4i)(int X, int Y, int Z, int W) + { + ASSERT_COVERED(HMM_Vec4i); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps((float)X, (float)Y, (float)Z, (float)W); +#else + Result.X = (float)X; + Result.Y = (float)Y; + Result.Z = (float)Z; + Result.W = (float)W; +#endif + + return (Result); + } + + COVERAGE(HMM_Vec4v, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4v)(hmm_vec3 Vector, float W) + { + ASSERT_COVERED(HMM_Vec4v); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W); +#else + Result.XYZ = Vector; + Result.W = W; +#endif + + return (Result); + } + + + /* + * Binary vector operations + */ + + COVERAGE(HMM_AddVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(AddVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_AddVec2); + + hmm_vec2 Result; + + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + + return (Result); + } + + COVERAGE(HMM_AddVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(AddVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_AddVec3); + + hmm_vec3 Result; + + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + Result.Z = Left.Z + Right.Z; + + return (Result); + } + + COVERAGE(HMM_AddVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(AddVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_AddVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + Result.Z = Left.Z + Right.Z; + Result.W = Left.W + Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_SubtractVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(SubtractVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_SubtractVec2); + + hmm_vec2 Result; + + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + + return (Result); + } + + COVERAGE(HMM_SubtractVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(SubtractVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_SubtractVec3); + + hmm_vec3 Result; + + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + Result.Z = Left.Z - Right.Z; + + return (Result); + } + + COVERAGE(HMM_SubtractVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(SubtractVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_SubtractVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + Result.Z = Left.Z - Right.Z; + Result.W = Left.W - Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_MultiplyVec2); + + hmm_vec2 Result; + + Result.X = Left.X * Right.X; + Result.Y = Left.Y * Right.Y; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec2f, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2f)(hmm_vec2 Left, float Right) + { + ASSERT_COVERED(HMM_MultiplyVec2f); + + hmm_vec2 Result; + + Result.X = Left.X * Right; + Result.Y = Left.Y * Right; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_MultiplyVec3); + + hmm_vec3 Result; + + Result.X = Left.X * Right.X; + Result.Y = Left.Y * Right.Y; + Result.Z = Left.Z * Right.Z; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec3f, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3f)(hmm_vec3 Left, float Right) + { + ASSERT_COVERED(HMM_MultiplyVec3f); + + hmm_vec3 Result; + + Result.X = Left.X * Right; + Result.Y = Left.Y * Right; + Result.Z = Left.Z * Right; + + return (Result); + } + + COVERAGE(HMM_MultiplyVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_MultiplyVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X * Right.X; + Result.Y = Left.Y * Right.Y; + Result.Z = Left.Z * Right.Z; + Result.W = Left.W * Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyVec4f, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4f)(hmm_vec4 Left, float Right) + { + ASSERT_COVERED(HMM_MultiplyVec4f); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Right); + Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X * Right; + Result.Y = Left.Y * Right; + Result.Z = Left.Z * Right; + Result.W = Left.W * Right; +#endif + + return (Result); + } + + COVERAGE(HMM_DivideVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_DivideVec2); + + hmm_vec2 Result; + + Result.X = Left.X / Right.X; + Result.Y = Left.Y / Right.Y; + + return (Result); + } + + COVERAGE(HMM_DivideVec2f, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2f)(hmm_vec2 Left, float Right) + { + ASSERT_COVERED(HMM_DivideVec2f); + + hmm_vec2 Result; + + Result.X = Left.X / Right; + Result.Y = Left.Y / Right; + + return (Result); + } + + COVERAGE(HMM_DivideVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_DivideVec3); + + hmm_vec3 Result; + + Result.X = Left.X / Right.X; + Result.Y = Left.Y / Right.Y; + Result.Z = Left.Z / Right.Z; + + return (Result); + } + + COVERAGE(HMM_DivideVec3f, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3f)(hmm_vec3 Left, float Right) + { + ASSERT_COVERED(HMM_DivideVec3f); + + hmm_vec3 Result; + + Result.X = Left.X / Right; + Result.Y = Left.Y / Right; + Result.Z = Left.Z / Right; + + return (Result); + } + + COVERAGE(HMM_DivideVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_DivideVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + Result.X = Left.X / Right.X; + Result.Y = Left.Y / Right.Y; + Result.Z = Left.Z / Right.Z; + Result.W = Left.W / Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_DivideVec4f, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4f)(hmm_vec4 Left, float Right) + { + ASSERT_COVERED(HMM_DivideVec4f); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Right); + Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X / Right; + Result.Y = Left.Y / Right; + Result.Z = Left.Z / Right; + Result.W = Left.W / Right; +#endif + + return (Result); + } + + COVERAGE(HMM_EqualsVec2, 1) + HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec2)(hmm_vec2 Left, hmm_vec2 Right) + { + ASSERT_COVERED(HMM_EqualsVec2); + + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y); + + return (Result); + } + + COVERAGE(HMM_EqualsVec3, 1) + HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec3)(hmm_vec3 Left, hmm_vec3 Right) + { + ASSERT_COVERED(HMM_EqualsVec3); + + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z); + + return (Result); + } + + COVERAGE(HMM_EqualsVec4, 1) + HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec4)(hmm_vec4 Left, hmm_vec4 Right) + { + ASSERT_COVERED(HMM_EqualsVec4); + + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W); + + return (Result); + } + + COVERAGE(HMM_DotVec2, 1) + HMM_INLINE float HMM_PREFIX(DotVec2)(hmm_vec2 VecOne, hmm_vec2 VecTwo) + { + ASSERT_COVERED(HMM_DotVec2); + + float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y); + + return (Result); + } + + COVERAGE(HMM_DotVec3, 1) + HMM_INLINE float HMM_PREFIX(DotVec3)(hmm_vec3 VecOne, hmm_vec3 VecTwo) + { + ASSERT_COVERED(HMM_DotVec3); + + float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z); + + return (Result); + } + + COVERAGE(HMM_DotVec4, 1) + HMM_INLINE float HMM_PREFIX(DotVec4)(hmm_vec4 VecOne, hmm_vec4 VecTwo) + { + ASSERT_COVERED(HMM_DotVec4); + + float Result; + + // NOTE(zak): IN the future if we wanna check what version SSE is support + // we can use _mm_dp_ps (4.3) but for now we will use the old way. + // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3 +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEResultOne = _mm_mul_ps(VecOne.InternalElementsSSE, VecTwo.InternalElementsSSE); + __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + _mm_store_ss(&Result, SSEResultOne); +#else + Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z) + (VecOne.W * VecTwo.W); +#endif + + return (Result); + } + + COVERAGE(HMM_Cross, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(Cross)(hmm_vec3 VecOne, hmm_vec3 VecTwo) + { + ASSERT_COVERED(HMM_Cross); + + hmm_vec3 Result; + + Result.X = (VecOne.Y * VecTwo.Z) - (VecOne.Z * VecTwo.Y); + Result.Y = (VecOne.Z * VecTwo.X) - (VecOne.X * VecTwo.Z); + Result.Z = (VecOne.X * VecTwo.Y) - (VecOne.Y * VecTwo.X); + + return (Result); + } + + + /* + * Unary vector operations + */ + + COVERAGE(HMM_LengthSquaredVec2, 1) + HMM_INLINE float HMM_PREFIX(LengthSquaredVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_LengthSquaredVec2); + + float Result = HMM_PREFIX(DotVec2)(A, A); + + return (Result); + } + + COVERAGE(HMM_LengthSquaredVec3, 1) + HMM_INLINE float HMM_PREFIX(LengthSquaredVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_LengthSquaredVec3); + + float Result = HMM_PREFIX(DotVec3)(A, A); + + return (Result); + } + + COVERAGE(HMM_LengthSquaredVec4, 1) + HMM_INLINE float HMM_PREFIX(LengthSquaredVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_LengthSquaredVec4); + + float Result = HMM_PREFIX(DotVec4)(A, A); + + return (Result); + } + + COVERAGE(HMM_LengthVec2, 1) + HMM_INLINE float HMM_PREFIX(LengthVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_LengthVec2); + + float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec2)(A)); + + return (Result); + } + + COVERAGE(HMM_LengthVec3, 1) + HMM_INLINE float HMM_PREFIX(LengthVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_LengthVec3); + + float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec3)(A)); + + return (Result); + } + + COVERAGE(HMM_LengthVec4, 1) + HMM_INLINE float HMM_PREFIX(LengthVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_LengthVec4); + + float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec4)(A)); + + return(Result); + } + + COVERAGE(HMM_NormalizeVec2, 2) + HMM_INLINE hmm_vec2 HMM_PREFIX(NormalizeVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_NormalizeVec2); + + hmm_vec2 Result = {0}; + + float VectorLength = HMM_PREFIX(LengthVec2)(A); + + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ + if (VectorLength != 0.0f) + { + ASSERT_COVERED(HMM_NormalizeVec2); + + Result.X = A.X * (1.0f / VectorLength); + Result.Y = A.Y * (1.0f / VectorLength); + } + + return (Result); + } + + COVERAGE(HMM_NormalizeVec3, 2) + HMM_INLINE hmm_vec3 HMM_PREFIX(NormalizeVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_NormalizeVec3); + + hmm_vec3 Result = {0}; + + float VectorLength = HMM_PREFIX(LengthVec3)(A); + + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ + if (VectorLength != 0.0f) + { + ASSERT_COVERED(HMM_NormalizeVec3); + + Result.X = A.X * (1.0f / VectorLength); + Result.Y = A.Y * (1.0f / VectorLength); + Result.Z = A.Z * (1.0f / VectorLength); + } + + return (Result); + } + + COVERAGE(HMM_NormalizeVec4, 2) + HMM_INLINE hmm_vec4 HMM_PREFIX(NormalizeVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_NormalizeVec4); + + hmm_vec4 Result = {0}; + + float VectorLength = HMM_PREFIX(LengthVec4)(A); + + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ + if (VectorLength != 0.0f) + { + ASSERT_COVERED(HMM_NormalizeVec4); + + float Multiplier = 1.0f / VectorLength; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEMultiplier = _mm_set1_ps(Multiplier); + Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); +#else + Result.X = A.X * Multiplier; + Result.Y = A.Y * Multiplier; + Result.Z = A.Z * Multiplier; + Result.W = A.W * Multiplier; +#endif + } + + return (Result); + } + + COVERAGE(HMM_FastNormalizeVec2, 1) + HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalizeVec2)(hmm_vec2 A) + { + ASSERT_COVERED(HMM_FastNormalizeVec2); + + return HMM_PREFIX(MultiplyVec2f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec2)(A, A))); + } + + COVERAGE(HMM_FastNormalizeVec3, 1) + HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalizeVec3)(hmm_vec3 A) + { + ASSERT_COVERED(HMM_FastNormalizeVec3); + + return HMM_PREFIX(MultiplyVec3f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec3)(A, A))); + } + + COVERAGE(HMM_FastNormalizeVec4, 1) + HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalizeVec4)(hmm_vec4 A) + { + ASSERT_COVERED(HMM_FastNormalizeVec4); + + return HMM_PREFIX(MultiplyVec4f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec4)(A, A))); + } + + + /* + * SSE stuff + */ + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_LinearCombineSSE, 1) + HMM_INLINE __m128 HMM_PREFIX(LinearCombineSSE)(__m128 Left, hmm_mat4 Right) + { + ASSERT_COVERED(HMM_LinearCombineSSE); + + __m128 Result; + Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Columns[0]); + Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Columns[1])); + Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Columns[2])); + Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Columns[3])); + + return (Result); + } +#endif + + + /* + * Matrix functions + */ + + COVERAGE(HMM_Mat4, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4)(void) + { + ASSERT_COVERED(HMM_Mat4); + + hmm_mat4 Result = {0}; + + return (Result); + } + + COVERAGE(HMM_Mat4d, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4d)(float Diagonal) + { + ASSERT_COVERED(HMM_Mat4d); + + hmm_mat4 Result = HMM_PREFIX(Mat4)(); + + Result.Elements[0][0] = Diagonal; + Result.Elements[1][1] = Diagonal; + Result.Elements[2][2] = Diagonal; + Result.Elements[3][3] = Diagonal; + + return (Result); + } + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_Transpose, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) + { + ASSERT_COVERED(HMM_Transpose); + + hmm_mat4 Result = Matrix; + + _MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix); +#endif + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_AddMat4, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) + { + ASSERT_COVERED(HMM_AddMat4); + + hmm_mat4 Result; + + Result.Columns[0] = _mm_add_ps(Left.Columns[0], Right.Columns[0]); + Result.Columns[1] = _mm_add_ps(Left.Columns[1], Right.Columns[1]); + Result.Columns[2] = _mm_add_ps(Left.Columns[2], Right.Columns[2]); + Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right); +#endif + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_SubtractMat4, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) + { + ASSERT_COVERED(HMM_SubtractMat4); + + hmm_mat4 Result; + + Result.Columns[0] = _mm_sub_ps(Left.Columns[0], Right.Columns[0]); + Result.Columns[1] = _mm_sub_ps(Left.Columns[1], Right.Columns[1]); + Result.Columns[2] = _mm_sub_ps(Left.Columns[2], Right.Columns[2]); + Result.Columns[3] = _mm_sub_ps(Left.Columns[3], Right.Columns[3]); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right); +#endif + + HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right); + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_MultiplyMat4f, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) + { + ASSERT_COVERED(HMM_MultiplyMat4f); + + hmm_mat4 Result; + + __m128 SSEScalar = _mm_set1_ps(Scalar); + Result.Columns[0] = _mm_mul_ps(Matrix.Columns[0], SSEScalar); + Result.Columns[1] = _mm_mul_ps(Matrix.Columns[1], SSEScalar); + Result.Columns[2] = _mm_mul_ps(Matrix.Columns[2], SSEScalar); + Result.Columns[3] = _mm_mul_ps(Matrix.Columns[3], SSEScalar); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar); +#endif + + HMM_EXTERN hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector); + +#ifdef HANDMADE_MATH__USE_SSE + COVERAGE(HMM_DivideMat4f, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) + { + ASSERT_COVERED(HMM_DivideMat4f); + + hmm_mat4 Result; + + __m128 SSEScalar = _mm_set1_ps(Scalar); + Result.Columns[0] = _mm_div_ps(Matrix.Columns[0], SSEScalar); + Result.Columns[1] = _mm_div_ps(Matrix.Columns[1], SSEScalar); + Result.Columns[2] = _mm_div_ps(Matrix.Columns[2], SSEScalar); + Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar); + + return (Result); + } +#else + HMM_EXTERN hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar); +#endif + + + /* + * Common graphics transformations + */ + + COVERAGE(HMM_Orthographic, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Orthographic)(float Left, float Right, float Bottom, float Top, float Near, float Far) + { + ASSERT_COVERED(HMM_Orthographic); + + hmm_mat4 Result = HMM_PREFIX(Mat4)(); + + Result.Elements[0][0] = 2.0f / (Right - Left); + Result.Elements[1][1] = 2.0f / (Top - Bottom); + Result.Elements[2][2] = 2.0f / (Near - Far); + Result.Elements[3][3] = 1.0f; + + Result.Elements[3][0] = (Left + Right) / (Left - Right); + Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top); + Result.Elements[3][2] = (Far + Near) / (Near - Far); + + return (Result); + } + + COVERAGE(HMM_Perspective, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Perspective)(float FOV, float AspectRatio, float Near, float Far) + { + ASSERT_COVERED(HMM_Perspective); + + hmm_mat4 Result = HMM_PREFIX(Mat4)(); + + // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml + + float Cotangent = 1.0f / HMM_PREFIX(TanF)(FOV * (HMM_PI32 / 360.0f)); + + Result.Elements[0][0] = Cotangent / AspectRatio; + Result.Elements[1][1] = Cotangent; + Result.Elements[2][3] = -1.0f; + Result.Elements[2][2] = (Near + Far) / (Near - Far); + Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far); + Result.Elements[3][3] = 0.0f; + + return (Result); + } + + COVERAGE(HMM_Translate, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Translate)(hmm_vec3 Translation) + { + ASSERT_COVERED(HMM_Translate); + + hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); + + Result.Elements[3][0] = Translation.X; + Result.Elements[3][1] = Translation.Y; + Result.Elements[3][2] = Translation.Z; + + return (Result); + } + + HMM_EXTERN hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis); + + COVERAGE(HMM_Scale, 1) + HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale) + { + ASSERT_COVERED(HMM_Scale); + + hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); + + Result.Elements[0][0] = Scale.X; + Result.Elements[1][1] = Scale.Y; + Result.Elements[2][2] = Scale.Z; + + return (Result); + } + + HMM_EXTERN hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up); + + + /* + * Quaternion operations + */ + + COVERAGE(HMM_Quaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(Quaternion)(float X, float Y, float Z, float W) + { + ASSERT_COVERED(HMM_Quaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); +#else + Result.X = X; + Result.Y = Y; + Result.Z = Z; + Result.W = W; +#endif + + return (Result); + } + + COVERAGE(HMM_QuaternionV4, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(QuaternionV4)(hmm_vec4 Vector) + { + ASSERT_COVERED(HMM_QuaternionV4); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = Vector.InternalElementsSSE; +#else + Result.X = Vector.X; + Result.Y = Vector.Y; + Result.Z = Vector.Z; + Result.W = Vector.W; +#endif + + return (Result); + } + + COVERAGE(HMM_AddQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(AddQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_AddQuaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + + Result.X = Left.X + Right.X; + Result.Y = Left.Y + Right.Y; + Result.Z = Left.Z + Right.Z; + Result.W = Left.W + Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_SubtractQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(SubtractQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_SubtractQuaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); +#else + + Result.X = Left.X - Right.X; + Result.Y = Left.Y - Right.Y; + Result.Z = Left.Z - Right.Z; + Result.W = Left.W - Right.W; +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_MultiplyQuaternion); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f)); + __m128 SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(0, 1, 2, 3)); + __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne); + + SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(1, 0, 3, 2)); + SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + + SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + + SSEResultOne = _mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(3, 3, 3, 3)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(3, 2, 1, 0)); + Result.InternalElementsSSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); +#else + Result.X = (Left.X * Right.W) + (Left.Y * Right.Z) - (Left.Z * Right.Y) + (Left.W * Right.X); + Result.Y = (-Left.X * Right.Z) + (Left.Y * Right.W) + (Left.Z * Right.X) + (Left.W * Right.Y); + Result.Z = (Left.X * Right.Y) - (Left.Y * Right.X) + (Left.Z * Right.W) + (Left.W * Right.Z); + Result.W = (-Left.X * Right.X) - (Left.Y * Right.Y) - (Left.Z * Right.Z) + (Left.W * Right.W); +#endif + + return (Result); + } + + COVERAGE(HMM_MultiplyQuaternionF, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternionF)(hmm_quaternion Left, float Multiplicative) + { + ASSERT_COVERED(HMM_MultiplyQuaternionF); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Multiplicative); + Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X * Multiplicative; + Result.Y = Left.Y * Multiplicative; + Result.Z = Left.Z * Multiplicative; + Result.W = Left.W * Multiplicative; +#endif + + return (Result); + } + + COVERAGE(HMM_DivideQuaternionF, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(DivideQuaternionF)(hmm_quaternion Left, float Dividend) + { + ASSERT_COVERED(HMM_DivideQuaternionF); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 Scalar = _mm_set1_ps(Dividend); + Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); +#else + Result.X = Left.X / Dividend; + Result.Y = Left.Y / Dividend; + Result.Z = Left.Z / Dividend; + Result.W = Left.W / Dividend; +#endif + + return (Result); + } + + HMM_EXTERN hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left); + + COVERAGE(HMM_DotQuaternion, 1) + HMM_INLINE float HMM_PREFIX(DotQuaternion)(hmm_quaternion Left, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_DotQuaternion); + + float Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); + __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + _mm_store_ss(&Result, SSEResultOne); +#else + Result = (Left.X * Right.X) + (Left.Y * Right.Y) + (Left.Z * Right.Z) + (Left.W * Right.W); +#endif + + return (Result); + } + + COVERAGE(HMM_NormalizeQuaternion, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(NormalizeQuaternion)(hmm_quaternion Left) + { + ASSERT_COVERED(HMM_NormalizeQuaternion); + + hmm_quaternion Result; + + float Length = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); + Result = HMM_PREFIX(DivideQuaternionF)(Left, Length); + + return (Result); + } + + COVERAGE(HMM_NLerp, 1) + HMM_INLINE hmm_quaternion HMM_PREFIX(NLerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) + { + ASSERT_COVERED(HMM_NLerp); + + hmm_quaternion Result; + +#ifdef HANDMADE_MATH__USE_SSE + __m128 ScalarLeft = _mm_set1_ps(1.0f - Time); + __m128 ScalarRight = _mm_set1_ps(Time); + __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, ScalarLeft); + __m128 SSEResultTwo = _mm_mul_ps(Right.InternalElementsSSE, ScalarRight); + Result.InternalElementsSSE = _mm_add_ps(SSEResultOne, SSEResultTwo); +#else + Result.X = HMM_PREFIX(Lerp)(Left.X, Time, Right.X); + Result.Y = HMM_PREFIX(Lerp)(Left.Y, Time, Right.Y); + Result.Z = HMM_PREFIX(Lerp)(Left.Z, Time, Right.Z); + Result.W = HMM_PREFIX(Lerp)(Left.W, Time, Right.W); +#endif + Result = HMM_PREFIX(NormalizeQuaternion)(Result); + + return (Result); + } + + HMM_EXTERN hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right); + HMM_EXTERN hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left); + HMM_EXTERN hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 Left); + HMM_EXTERN hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +COVERAGE(HMM_LengthVec2CPP, 1) +HMM_INLINE float HMM_PREFIX(Length)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_LengthVec2CPP); + + float Result = HMM_PREFIX(LengthVec2)(A); + + return (Result); +} + +COVERAGE(HMM_LengthVec3CPP, 1) +HMM_INLINE float HMM_PREFIX(Length)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_LengthVec3CPP); + + float Result = HMM_PREFIX(LengthVec3)(A); + + return (Result); +} + +COVERAGE(HMM_LengthVec4CPP, 1) +HMM_INLINE float HMM_PREFIX(Length)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_LengthVec4CPP); + + float Result = HMM_PREFIX(LengthVec4)(A); + + return (Result); +} + +COVERAGE(HMM_LengthSquaredVec2CPP, 1) +HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_LengthSquaredVec2CPP); + + float Result = HMM_PREFIX(LengthSquaredVec2)(A); + + return (Result); +} + +COVERAGE(HMM_LengthSquaredVec3CPP, 1) +HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_LengthSquaredVec3CPP); + + float Result = HMM_PREFIX(LengthSquaredVec3)(A); + + return (Result); +} + +COVERAGE(HMM_LengthSquaredVec4CPP, 1) +HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_LengthSquaredVec4CPP); + + float Result = HMM_PREFIX(LengthSquaredVec4)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Normalize)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_NormalizeVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(NormalizeVec2)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Normalize)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_NormalizeVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(NormalizeVec3)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Normalize)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_NormalizeVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(NormalizeVec4)(A); + + return (Result); +} + +COVERAGE(HMM_FastNormalizeVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalize)(hmm_vec2 A) +{ + ASSERT_COVERED(HMM_FastNormalizeVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(FastNormalizeVec2)(A); + + return (Result); +} + +COVERAGE(HMM_FastNormalizeVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalize)(hmm_vec3 A) +{ + ASSERT_COVERED(HMM_FastNormalizeVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(FastNormalizeVec3)(A); + + return (Result); +} + +COVERAGE(HMM_FastNormalizeVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalize)(hmm_vec4 A) +{ + ASSERT_COVERED(HMM_FastNormalizeVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(FastNormalizeVec4)(A); + + return (Result); +} + +COVERAGE(HMM_NormalizeQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Normalize)(hmm_quaternion A) +{ + ASSERT_COVERED(HMM_NormalizeQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(NormalizeQuaternion)(A); + + return (Result); +} + +COVERAGE(HMM_DotVec2CPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec2 VecOne, hmm_vec2 VecTwo) +{ + ASSERT_COVERED(HMM_DotVec2CPP); + + float Result = HMM_PREFIX(DotVec2)(VecOne, VecTwo); + + return (Result); +} + +COVERAGE(HMM_DotVec3CPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec3 VecOne, hmm_vec3 VecTwo) +{ + ASSERT_COVERED(HMM_DotVec3CPP); + + float Result = HMM_PREFIX(DotVec3)(VecOne, VecTwo); + + return (Result); +} + +COVERAGE(HMM_DotVec4CPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec4 VecOne, hmm_vec4 VecTwo) +{ + ASSERT_COVERED(HMM_DotVec4CPP); + + float Result = HMM_PREFIX(DotVec4)(VecOne, VecTwo); + + return (Result); +} + +COVERAGE(HMM_DotQuaternionCPP, 1) +HMM_INLINE float HMM_PREFIX(Dot)(hmm_quaternion QuatOne, hmm_quaternion QuatTwo) +{ + ASSERT_COVERED(HMM_DotQuaternionCPP); + + float Result = HMM_PREFIX(DotQuaternion)(QuatOne, QuatTwo); + + return (Result); +} + +COVERAGE(HMM_AddVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Add)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_AddVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Add)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_AddVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Add)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_AddVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddMat4CPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Add)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4CPP); + + hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Add)(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_AddQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Subtract)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_SubtractVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Subtract)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_SubtractVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Subtract)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_SubtractVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractMat4CPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Subtract)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4CPP); + + hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Subtract)(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_SubtractQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2fCPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fCPP); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3fCPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fCPP); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4fCPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fCPP); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4CPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4CPP); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4fCPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fCPP); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4ByVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_mat4 Matrix, hmm_vec4 Vector) +{ + ASSERT_COVERED(HMM_MultiplyMat4ByVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionCPP); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionFCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFCPP); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec2CPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_DivideVec2CPP); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec2fCPP, 1) +HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec2fCPP); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3CPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_DivideVec3CPP); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3fCPP, 1) +HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec3fCPP); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4CPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_DivideVec4CPP); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4fCPP, 1) +HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec4fCPP); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideMat4fCPP, 1) +HMM_INLINE hmm_mat4 HMM_PREFIX(Divide)(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideMat4fCPP); + + hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideQuaternionFCPP, 1) +HMM_INLINE hmm_quaternion HMM_PREFIX(Divide)(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_DivideQuaternionFCPP); + + hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_EqualsVec2CPP, 1) +HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_EqualsVec2CPP); + + hmm_bool Result = HMM_PREFIX(EqualsVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_EqualsVec3CPP, 1) +HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_EqualsVec3CPP); + + hmm_bool Result = HMM_PREFIX(EqualsVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_EqualsVec4CPP, 1) +HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_EqualsVec4CPP); + + hmm_bool Result = HMM_PREFIX(EqualsVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec2Op, 1) +HMM_INLINE hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_AddVec2Op); + + hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec3Op, 1) +HMM_INLINE hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_AddVec3Op); + + hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec4Op, 1) +HMM_INLINE hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_AddVec4Op); + + hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddMat4Op, 1) +HMM_INLINE hmm_mat4 operator+(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4Op); + + hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddQuaternionOp, 1) +HMM_INLINE hmm_quaternion operator+(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_AddQuaternionOp); + + hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec2Op, 1) +HMM_INLINE hmm_vec2 operator-(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_SubtractVec2Op); + + hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec3Op, 1) +HMM_INLINE hmm_vec3 operator-(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_SubtractVec3Op); + + hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractVec4Op, 1) +HMM_INLINE hmm_vec4 operator-(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_SubtractVec4Op); + + hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractMat4Op, 1) +HMM_INLINE hmm_mat4 operator-(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4Op); + + hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_SubtractQuaternionOp, 1) +HMM_INLINE hmm_quaternion operator-(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_SubtractQuaternionOp); + + hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2Op, 1) +HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2Op); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3Op, 1) +HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3Op); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4Op, 1) +HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4Op); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4Op, 1) +HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4Op); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionOp, 1) +HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionOp); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2fOp, 1) +HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fOp); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3fOp, 1) +HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fOp); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4fOp, 1) +HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fOp); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4fOp, 1) +HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fOp); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionFOp, 1) +HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFOp); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec2fOpLeft, 1) +HMM_INLINE hmm_vec2 operator*(float Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fOpLeft); + + hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec3fOpLeft, 1) +HMM_INLINE hmm_vec3 operator*(float Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fOpLeft); + + hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyVec4fOpLeft, 1) +HMM_INLINE hmm_vec4 operator*(float Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fOpLeft); + + hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4fOpLeft, 1) +HMM_INLINE hmm_mat4 operator*(float Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fOpLeft); + + hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyQuaternionFOpLeft, 1) +HMM_INLINE hmm_quaternion operator*(float Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFOpLeft); + + hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Right, Left); + + return (Result); +} + +COVERAGE(HMM_MultiplyMat4ByVec4Op, 1) +HMM_INLINE hmm_vec4 operator*(hmm_mat4 Matrix, hmm_vec4 Vector) +{ + ASSERT_COVERED(HMM_MultiplyMat4ByVec4Op); + + hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); + + return (Result); +} + +COVERAGE(HMM_DivideVec2Op, 1) +HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_DivideVec2Op); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3Op, 1) +HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_DivideVec3Op); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4Op, 1) +HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_DivideVec4Op); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec2fOp, 1) +HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec2fOp); + + hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec3fOp, 1) +HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec3fOp); + + hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideVec4fOp, 1) +HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec4fOp); + + hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideMat4fOp, 1) +HMM_INLINE hmm_mat4 operator/(hmm_mat4 Left, float Right) +{ + ASSERT_COVERED(HMM_DivideMat4fOp); + + hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_DivideQuaternionFOp, 1) +HMM_INLINE hmm_quaternion operator/(hmm_quaternion Left, float Right) +{ + ASSERT_COVERED(HMM_DivideQuaternionFOp); + + hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); + + return (Result); +} + +COVERAGE(HMM_AddVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator+=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_AddVec2Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator+=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_AddVec3Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator+=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_AddVec4Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddMat4Assign, 1) +HMM_INLINE hmm_mat4 &operator+=(hmm_mat4 &Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4Assign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_AddQuaternionAssign, 1) +HMM_INLINE hmm_quaternion &operator+=(hmm_quaternion &Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_AddQuaternionAssign); + + return (Left = Left + Right); +} + +COVERAGE(HMM_SubtractVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator-=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_SubtractVec2Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator-=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_SubtractVec3Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator-=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_SubtractVec4Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractMat4Assign, 1) +HMM_INLINE hmm_mat4 &operator-=(hmm_mat4 &Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4Assign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_SubtractQuaternionAssign, 1) +HMM_INLINE hmm_quaternion &operator-=(hmm_quaternion &Left, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_SubtractQuaternionAssign); + + return (Left = Left - Right); +} + +COVERAGE(HMM_MultiplyVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2Assign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3Assign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4Assign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec2fAssign, 1) +HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec2fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec3fAssign, 1) +HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec3fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyVec4fAssign, 1) +HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyVec4fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyMat4fAssign, 1) +HMM_INLINE hmm_mat4 &operator*=(hmm_mat4 &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4fAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_MultiplyQuaternionFAssign, 1) +HMM_INLINE hmm_quaternion &operator*=(hmm_quaternion &Left, float Right) +{ + ASSERT_COVERED(HMM_MultiplyQuaternionFAssign); + + return (Left = Left * Right); +} + +COVERAGE(HMM_DivideVec2Assign, 1) +HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_DivideVec2Assign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec3Assign, 1) +HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_DivideVec3Assign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec4Assign, 1) +HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_DivideVec4Assign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec2fAssign, 1) +HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec2fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec3fAssign, 1) +HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec3fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideVec4fAssign, 1) +HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideVec4fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideMat4fAssign, 1) +HMM_INLINE hmm_mat4 &operator/=(hmm_mat4 &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideMat4fAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_DivideQuaternionFAssign, 1) +HMM_INLINE hmm_quaternion &operator/=(hmm_quaternion &Left, float Right) +{ + ASSERT_COVERED(HMM_DivideQuaternionFAssign); + + return (Left = Left / Right); +} + +COVERAGE(HMM_EqualsVec2Op, 1) +HMM_INLINE hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_EqualsVec2Op); + + return HMM_PREFIX(EqualsVec2)(Left, Right); +} + +COVERAGE(HMM_EqualsVec3Op, 1) +HMM_INLINE hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_EqualsVec3Op); + + return HMM_PREFIX(EqualsVec3)(Left, Right); +} + +COVERAGE(HMM_EqualsVec4Op, 1) +HMM_INLINE hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_EqualsVec4Op); + + return HMM_PREFIX(EqualsVec4)(Left, Right); +} + +COVERAGE(HMM_EqualsVec2OpNot, 1) +HMM_INLINE hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right) +{ + ASSERT_COVERED(HMM_EqualsVec2OpNot); + + return !HMM_PREFIX(EqualsVec2)(Left, Right); +} + +COVERAGE(HMM_EqualsVec3OpNot, 1) +HMM_INLINE hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right) +{ + ASSERT_COVERED(HMM_EqualsVec3OpNot); + + return !HMM_PREFIX(EqualsVec3)(Left, Right); +} + +COVERAGE(HMM_EqualsVec4OpNot, 1) +HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) +{ + ASSERT_COVERED(HMM_EqualsVec4OpNot); + + return !HMM_PREFIX(EqualsVec4)(Left, Right); +} + +#endif /* __cplusplus */ + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif /* HANDMADE_MATH_H */ + +#ifdef HANDMADE_MATH_IMPLEMENTATION + +COVERAGE(HMM_Power, 2) +float HMM_PREFIX(Power)(float Base, int Exponent) +{ + ASSERT_COVERED(HMM_Power); + + float Result = 1.0f; + float Mul = Exponent < 0 ? 1.f / Base : Base; + int X = Exponent < 0 ? -Exponent : Exponent; + while (X) + { + if (X & 1) + { + ASSERT_COVERED(HMM_Power); + + Result *= Mul; + } + + Mul *= Mul; + X >>= 1; + } + + return (Result); +} + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_Transpose, 1) +hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) +{ + ASSERT_COVERED(HMM_Transpose); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows]; + } + } + + return (Result); +} +#endif + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_AddMat4, 1) +hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_AddMat4); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] + Right.Elements[Columns][Rows]; + } + } + + return (Result); +} +#endif + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_SubtractMat4, 1) +hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_SubtractMat4); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] - Right.Elements[Columns][Rows]; + } + } + + return (Result); +} +#endif + +COVERAGE(HMM_MultiplyMat4, 1) +hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right) +{ + ASSERT_COVERED(HMM_MultiplyMat4); + + hmm_mat4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.Columns[0] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[0], Left); + Result.Columns[1] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[1], Left); + Result.Columns[2] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[2], Left); + Result.Columns[3] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[3], Left); +#else + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + float Sum = 0; + int CurrentMatrice; + for(CurrentMatrice = 0; CurrentMatrice < 4; ++CurrentMatrice) + { + Sum += Left.Elements[CurrentMatrice][Rows] * Right.Elements[Columns][CurrentMatrice]; + } + + Result.Elements[Columns][Rows] = Sum; + } + } +#endif + + return (Result); +} + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_MultiplyMat4f, 1) +hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) +{ + ASSERT_COVERED(HMM_MultiplyMat4f); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] * Scalar; + } + } + + return (Result); +} +#endif + +COVERAGE(HMM_MultiplyMat4ByVec4, 1) +hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector) +{ + ASSERT_COVERED(HMM_MultiplyMat4ByVec4); + + hmm_vec4 Result; + +#ifdef HANDMADE_MATH__USE_SSE + Result.InternalElementsSSE = HMM_PREFIX(LinearCombineSSE)(Vector.InternalElementsSSE, Matrix); +#else + int Columns, Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + float Sum = 0; + for(Columns = 0; Columns < 4; ++Columns) + { + Sum += Matrix.Elements[Columns][Rows] * Vector.Elements[Columns]; + } + + Result.Elements[Rows] = Sum; + } +#endif + + return (Result); +} + +#ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_DivideMat4f, 1); +hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) +{ + ASSERT_COVERED(HMM_DivideMat4f); + + hmm_mat4 Result; + + int Columns; + for(Columns = 0; Columns < 4; ++Columns) + { + int Rows; + for(Rows = 0; Rows < 4; ++Rows) + { + Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] / Scalar; + } + } + + return (Result); +} +#endif + +COVERAGE(HMM_Rotate, 1) +hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis) +{ + ASSERT_COVERED(HMM_Rotate); + + hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); + + Axis = HMM_PREFIX(NormalizeVec3)(Axis); + + float SinTheta = HMM_PREFIX(SinF)(HMM_PREFIX(ToRadians)(Angle)); + float CosTheta = HMM_PREFIX(CosF)(HMM_PREFIX(ToRadians)(Angle)); + float CosValue = 1.0f - CosTheta; + + Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta; + Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta); + Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta); + + Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta); + Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta; + Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta); + + Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta); + Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta); + Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta; + + return (Result); +} + +COVERAGE(HMM_LookAt, 1) +hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) +{ + ASSERT_COVERED(HMM_LookAt); + + hmm_mat4 Result; + + hmm_vec3 F = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(SubtractVec3)(Center, Eye)); + hmm_vec3 S = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(Cross)(F, Up)); + hmm_vec3 U = HMM_PREFIX(Cross)(S, F); + + Result.Elements[0][0] = S.X; + Result.Elements[0][1] = U.X; + Result.Elements[0][2] = -F.X; + Result.Elements[0][3] = 0.0f; + + Result.Elements[1][0] = S.Y; + Result.Elements[1][1] = U.Y; + Result.Elements[1][2] = -F.Y; + Result.Elements[1][3] = 0.0f; + + Result.Elements[2][0] = S.Z; + Result.Elements[2][1] = U.Z; + Result.Elements[2][2] = -F.Z; + Result.Elements[2][3] = 0.0f; + + Result.Elements[3][0] = -HMM_PREFIX(DotVec3)(S, Eye); + Result.Elements[3][1] = -HMM_PREFIX(DotVec3)(U, Eye); + Result.Elements[3][2] = HMM_PREFIX(DotVec3)(F, Eye); + Result.Elements[3][3] = 1.0f; + + return (Result); +} + +COVERAGE(HMM_InverseQuaternion, 1) +hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left) +{ + ASSERT_COVERED(HMM_InverseQuaternion); + + hmm_quaternion Conjugate; + hmm_quaternion Result; + float Norm = 0; + float NormSquared = 0; + + Conjugate.X = -Left.X; + Conjugate.Y = -Left.Y; + Conjugate.Z = -Left.Z; + Conjugate.W = Left.W; + + Norm = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); + NormSquared = Norm * Norm; + + Result = HMM_PREFIX(DivideQuaternionF)(Conjugate, NormSquared); + + return (Result); +} + +COVERAGE(HMM_Slerp, 1) +hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) +{ + ASSERT_COVERED(HMM_Slerp); + + hmm_quaternion Result; + hmm_quaternion QuaternionLeft; + hmm_quaternion QuaternionRight; + + float Cos_Theta = HMM_PREFIX(DotQuaternion)(Left, Right); + float Angle = HMM_PREFIX(ACosF)(Cos_Theta); + + float S1 = HMM_PREFIX(SinF)((1.0f - Time) * Angle); + float S2 = HMM_PREFIX(SinF)(Time * Angle); + float Is = 1.0f / HMM_PREFIX(SinF)(Angle); + + QuaternionLeft = HMM_PREFIX(MultiplyQuaternionF)(Left, S1); + QuaternionRight = HMM_PREFIX(MultiplyQuaternionF)(Right, S2); + + Result = HMM_PREFIX(AddQuaternion)(QuaternionLeft, QuaternionRight); + Result = HMM_PREFIX(MultiplyQuaternionF)(Result, Is); + + return (Result); +} + +COVERAGE(HMM_QuaternionToMat4, 1) +hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left) +{ + ASSERT_COVERED(HMM_QuaternionToMat4); + + hmm_mat4 Result; + + hmm_quaternion NormalizedQuaternion = HMM_PREFIX(NormalizeQuaternion)(Left); + + float XX, YY, ZZ, + XY, XZ, YZ, + WX, WY, WZ; + + XX = NormalizedQuaternion.X * NormalizedQuaternion.X; + YY = NormalizedQuaternion.Y * NormalizedQuaternion.Y; + ZZ = NormalizedQuaternion.Z * NormalizedQuaternion.Z; + XY = NormalizedQuaternion.X * NormalizedQuaternion.Y; + XZ = NormalizedQuaternion.X * NormalizedQuaternion.Z; + YZ = NormalizedQuaternion.Y * NormalizedQuaternion.Z; + WX = NormalizedQuaternion.W * NormalizedQuaternion.X; + WY = NormalizedQuaternion.W * NormalizedQuaternion.Y; + WZ = NormalizedQuaternion.W * NormalizedQuaternion.Z; + + Result.Elements[0][0] = 1.0f - 2.0f * (YY + ZZ); + Result.Elements[0][1] = 2.0f * (XY + WZ); + Result.Elements[0][2] = 2.0f * (XZ - WY); + Result.Elements[0][3] = 0.0f; + + Result.Elements[1][0] = 2.0f * (XY - WZ); + Result.Elements[1][1] = 1.0f - 2.0f * (XX + ZZ); + Result.Elements[1][2] = 2.0f * (YZ + WX); + Result.Elements[1][3] = 0.0f; + + Result.Elements[2][0] = 2.0f * (XZ + WY); + Result.Elements[2][1] = 2.0f * (YZ - WX); + Result.Elements[2][2] = 1.0f - 2.0f * (XX + YY); + Result.Elements[2][3] = 0.0f; + + Result.Elements[3][0] = 0.0f; + Result.Elements[3][1] = 0.0f; + Result.Elements[3][2] = 0.0f; + Result.Elements[3][3] = 1.0f; + + return (Result); +} + +// This method taken from Mike Day at Insomniac Games. +// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf +// +// Note that as mentioned at the top of the paper, the paper assumes the matrix +// would be *post*-multiplied to a vector to rotate it, meaning the matrix is +// the transpose of what we're dealing with. But, because our matrices are +// stored in column-major order, the indices *appear* to match the paper. +// +// For example, m12 in the paper is row 1, column 2. We need to transpose it to +// row 2, column 1. But, because the column comes first when referencing +// elements, it looks like M.Elements[1][2]. +// +// Don't be confused! Or if you must be confused, at least trust this +// comment. :) +COVERAGE(HMM_Mat4ToQuaternion, 4) +hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M) +{ + float T; + hmm_quaternion Q; + + if (M.Elements[2][2] < 0.0f) { + if (M.Elements[0][0] > M.Elements[1][1]) { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + T, + M.Elements[0][1] + M.Elements[1][0], + M.Elements[2][0] + M.Elements[0][2], + M.Elements[1][2] - M.Elements[2][1] + ); + } else { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + M.Elements[0][1] + M.Elements[1][0], + T, + M.Elements[1][2] + M.Elements[2][1], + M.Elements[2][0] - M.Elements[0][2] + ); + } + } else { + if (M.Elements[0][0] < -M.Elements[1][1]) { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + M.Elements[2][0] + M.Elements[0][2], + M.Elements[1][2] + M.Elements[2][1], + T, + M.Elements[0][1] - M.Elements[1][0] + ); + } else { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + + T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2]; + Q = HMM_PREFIX(Quaternion)( + M.Elements[1][2] - M.Elements[2][1], + M.Elements[2][0] - M.Elements[0][2], + M.Elements[0][1] - M.Elements[1][0], + T + ); + } + } + + Q = HMM_PREFIX(MultiplyQuaternionF)(Q, 0.5f / HMM_PREFIX(SquareRootF)(T)); + + return Q; +} + +COVERAGE(HMM_QuaternionFromAxisAngle, 1) +hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation) +{ + ASSERT_COVERED(HMM_QuaternionFromAxisAngle); + + hmm_quaternion Result; + + hmm_vec3 AxisNormalized = HMM_PREFIX(NormalizeVec3)(Axis); + float SineOfRotation = HMM_PREFIX(SinF)(AngleOfRotation / 2.0f); + + Result.XYZ = HMM_PREFIX(MultiplyVec3f)(AxisNormalized, SineOfRotation); + Result.W = HMM_PREFIX(CosF)(AngleOfRotation / 2.0f); + + return (Result); +} + +#endif /* HANDMADE_MATH_IMPLEMENTATION */ \ No newline at end of file diff --git a/src/app/interface.h b/src/app/interface.h index 33a50ac..d382f4c 100644 --- a/src/app/interface.h +++ b/src/app/interface.h @@ -5,7 +5,7 @@ // #ifndef INTERFACE_H -enum string_alignment +enum gs_string_alignment { Align_Left, Align_Center, @@ -60,10 +60,10 @@ DrawCharacterRightAligned (render_quad_batch_constructor* BatchConstructor, char } internal v2 -DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* String, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) +DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) { v2 RegisterPosition = InitialRegisterPosition; - char* C = String; + char* C = gs_string; for (s32 i = 0; i < Length; i++) { v2 PositionAfterCharacter = DrawCharacterLeftAligned(BatchConstructor, *C, *Font, RegisterPosition, Color); @@ -74,10 +74,10 @@ DrawStringLeftAligned (render_quad_batch_constructor* BatchConstructor, s32 Leng } internal v2 -DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* String, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) +DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Length, char* gs_string, v2 InitialRegisterPosition, bitmap_font* Font, v4 Color) { v2 RegisterPosition = InitialRegisterPosition; - char* C = String + Length - 1; + char* C = gs_string + Length - 1; for (s32 i = Length - 1; i >= 0; i--) { v2 PositionAfterCharacter = DrawCharacterRightAligned(BatchConstructor, *C, *Font, RegisterPosition, Color); @@ -88,7 +88,7 @@ DrawStringRightAligned (render_quad_batch_constructor* BatchConstructor, s32 Len } internal v2 -DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Font, v2 Position, v4 Color, string_alignment Alignment = Align_Left) +DrawString(render_command_buffer* RenderBuffer, gs_string String, bitmap_font* Font, v2 Position, v4 Color, gs_string_alignment Alignment = Align_Left) { DEBUG_TRACK_FUNCTION; v2 LowerRight = Position; @@ -129,7 +129,7 @@ DrawCursor (render_quad_batch_constructor* BatchConstructor, v2 Position, v4 Col } internal v2 -DrawStringWithCursor (render_command_buffer* RenderBuffer, string String, s32 CursorPosition, bitmap_font* Font, v2 Position, v4 Color, v4 CursorColor, string_alignment Alignment = Align_Left) +Drawgs_stringWithCursor (render_command_buffer* RenderBuffer, gs_string String, s32 CursorPosition, bitmap_font* Font, v2 Position, v4 Color, v4 CursorColor, gs_string_alignment Alignment = Align_Left) { DEBUG_TRACK_FUNCTION; v2 LowerRight = Position; @@ -153,21 +153,21 @@ DrawStringWithCursor (render_command_buffer* RenderBuffer, string String, s32 Cu { RegisterPosition = DrawStringLeftAligned(&BatchConstructor, String.Length - CursorPosition, - String.Memory + CursorPosition, + String.Str + CursorPosition, RegisterPosition, Font, Color); } } else if (Alignment == Align_Right) { RegisterPosition = DrawStringRightAligned(&BatchConstructor, - CursorPosition, String.Memory, + CursorPosition, String.Str, RegisterPosition, Font, Color); DrawCursor(&CursorBatch, RegisterPosition, GreenV4, *Font); if (String.Length - CursorPosition > 0) { RegisterPosition = DrawStringRightAligned(&BatchConstructor, String.Length - CursorPosition, - String.Memory + CursorPosition, + String.Str + CursorPosition, RegisterPosition, Font, Color); } } @@ -201,7 +201,7 @@ struct interface_config struct ui_layout { - rect Bounds; + rect2 Bounds; v2 Margin; r32 RowHeight; r32 RowYAt; @@ -220,7 +220,7 @@ struct ui_interface }; static ui_layout -ui_CreateLayout(ui_interface Interface, rect Bounds) +ui_CreateLayout(ui_interface Interface, rect2 Bounds) { ui_layout Result = {0}; Result.Bounds = Bounds; @@ -263,7 +263,7 @@ ui_EndRow(ui_layout* Layout) } static b32 -ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) +ui_TryReserveElementBounds(ui_layout* Layout, rect2* Bounds) { b32 Result = true; if (!Layout->DrawHorizontal) @@ -289,7 +289,7 @@ ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) } else { - r32 ElementWidth = gs_Width(Layout->Bounds) / Layout->ColumnsMax; + r32 ElementWidth = Rect2Width(Layout->Bounds) / Layout->ColumnsMax; Bounds->Min = { Layout->Bounds.Min.x + (ElementWidth * Layout->ColumnsCount) + Layout->Margin.x, Layout->RowYAt @@ -309,18 +309,18 @@ ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) return Result; } -static rect -ui_ReserveTextLineBounds(ui_interface Interface, string Text, ui_layout* Layout) +static rect2 +ui_ReserveTextLineBounds(ui_interface Interface, gs_string Text, ui_layout* Layout) { - rect Bounds = {0}; + rect2 Bounds = {0}; return Bounds; } -static rect +static rect2 ui_ReserveElementBounds(ui_layout* Layout) { - rect Bounds = {0}; + rect2 Bounds = {0}; if (!ui_TryReserveElementBounds(Layout, &Bounds)) { InvalidCodePath; @@ -328,10 +328,10 @@ ui_ReserveElementBounds(ui_layout* Layout) return Bounds; } -static rect +static rect2 ui_LayoutRemaining(ui_layout Layout) { - rect Result = Layout.Bounds; + rect2 Result = Layout.Bounds; Result.Max.y = Layout.RowYAt; if (Layout.DrawHorizontal) { @@ -352,19 +352,19 @@ ui_GetTextLineHeight(ui_interface Interface) } static void -ui_FillRect(ui_interface* Interface, rect Bounds, v4 Color) +ui_FillRect(ui_interface* Interface, rect2 Bounds, v4 Color) { - PushRenderQuad2D(Interface->RenderBuffer, gs_RectExpand(Bounds), Color); + PushRenderQuad2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Color); } static void -ui_OutlineRect(ui_interface* Interface, rect Bounds, r32 Thickness, v4 Color) +ui_OutlineRect(ui_interface* Interface, rect2 Bounds, r32 Thickness, v4 Color) { PushRenderBoundingBox2D(Interface->RenderBuffer, Bounds.Min, Bounds.Max, Thickness, Color); } internal void -ui_DrawString(ui_interface* Interface, string String, rect Bounds, v4 Color, string_alignment Alignment = Align_Left) +ui_DrawString(ui_interface* Interface, gs_string String, rect2 Bounds, v4 Color, gs_string_alignment Alignment = Align_Left) { DEBUG_TRACK_FUNCTION; render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(Interface->RenderBuffer, @@ -392,9 +392,9 @@ ui_DrawString(ui_interface* Interface, string String, rect Bounds, v4 Color, str } static void -ui_LayoutDrawString(ui_interface* Interface, ui_layout* Layout, string String, v4 Color, string_alignment Alignment = Align_Left) +ui_LayoutDrawString(ui_interface* Interface, ui_layout* Layout, gs_string String, v4 Color, gs_string_alignment Alignment = Align_Left) { - rect Bounds = {0}; + rect2 Bounds = {0}; if (!ui_TryReserveElementBounds(Layout, &Bounds)) { // TODO(NAME): Not invalid, just haven't implemented yet. @@ -405,18 +405,18 @@ ui_LayoutDrawString(ui_interface* Interface, ui_layout* Layout, string String, v } static void -ui_TextBox(ui_interface* Interface, rect Bounds, string Text, v4 BGColor, v4 TextColor) +ui_TextBox(ui_interface* Interface, rect2 Bounds, gs_string Text, v4 BGColor, v4 TextColor) { ui_FillRect(Interface, Bounds, BGColor); ui_DrawString(Interface, Text, Bounds, TextColor); } static b32 -ui_Button(ui_interface* Interface, string Text, rect Bounds, v4 InactiveColor, v4 HoverColor, v4 ClickedColor) +ui_Button(ui_interface* Interface, gs_string Text, rect2 Bounds, v4 InactiveColor, v4 HoverColor, v4 ClickedColor) { b32 Pressed = false; v4 ButtonBG = InactiveColor; - if (gs_PointIsInRect(Interface->Mouse.Pos, Bounds)) + if (PointIsInRect(Bounds, Interface->Mouse.Pos)) { ButtonBG = HoverColor; if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) @@ -430,7 +430,7 @@ ui_Button(ui_interface* Interface, string Text, rect Bounds, v4 InactiveColor, v } static b32 -ui_Button(ui_interface* Interface, string Text, rect Bounds) +ui_Button(ui_interface* Interface, gs_string Text, rect2 Bounds) { v4 BGColor = Interface->Style.ButtonColor_Inactive; v4 HoverColor = Interface->Style.ButtonColor_Active; @@ -463,16 +463,16 @@ ui_GetListItemColors(ui_interface* Interface, u32 ListItemIndex) } static b32 -ui_ListButton(ui_interface* Interface, string Text, rect Bounds, u32 ListItemIndex) +ui_ListButton(ui_interface* Interface, gs_string Text, rect2 Bounds, u32 ListItemIndex) { list_item_colors Colors = ui_GetListItemColors(Interface, ListItemIndex); return ui_Button(Interface, Text, Bounds, Colors.Hover, Colors.Selected, Colors.BGColor); } static b32 -ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text, v4 BGColor, v4 HoverColor, v4 SelectColor) +ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, gs_string Text, v4 BGColor, v4 HoverColor, v4 SelectColor) { - rect ButtonBounds = {0}; + rect2 ButtonBounds = {0}; if (!ui_TryReserveElementBounds(Layout, &ButtonBounds)) { ButtonBounds = ui_ReserveTextLineBounds(*Interface, Text, Layout); @@ -481,7 +481,7 @@ ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text, v4 BGCo } static b32 -ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text) +ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, gs_string Text) { v4 BGColor = Interface->Style.ButtonColor_Inactive; v4 HoverColor = Interface->Style.ButtonColor_Active; @@ -490,16 +490,16 @@ ui_LayoutButton(ui_interface* Interface, ui_layout* Layout, string Text) } static b32 -ui_LayoutListButton(ui_interface* Interface, ui_layout* Layout, string Text, u32 ListItemIndex) +ui_LayoutListButton(ui_interface* Interface, ui_layout* Layout, gs_string Text, u32 ListItemIndex) { list_item_colors Colors = ui_GetListItemColors(Interface, ListItemIndex); return ui_LayoutButton(Interface, Layout, Text, Colors.Hover, Colors.Selected, Colors.BGColor); } static b32 -ui_LayoutListEntry(ui_interface* Interface, ui_layout* Layout, string Text, u32 Index) +ui_LayoutListEntry(ui_interface* Interface, ui_layout* Layout, gs_string Text, u32 Index) { - rect Bounds = {0}; + rect2 Bounds = {0}; if (!ui_TryReserveElementBounds(Layout, &Bounds)) { // TODO(Peter): this isn't really invalid, but I don't have a concrete use case @@ -527,7 +527,7 @@ enum selection_state struct interface_list { - rect ListBounds; + rect2 ListBounds; v2 ListElementDimensions; v2 ElementLabelIndent; @@ -540,10 +540,10 @@ struct interface_list s32 ListElementsCount; }; -internal rect +internal rect2 DrawListElementBackground(interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer) { - rect LineBounds = {}; + rect2 LineBounds = {}; LineBounds.Min = v2{ List->ListBounds.Min.x, List->ListBounds.Max.y - (List->ListElementDimensions.y * (List->ListElementsCount + 1)) @@ -551,7 +551,7 @@ DrawListElementBackground(interface_list* List, mouse_state Mouse, render_comman LineBounds.Max = LineBounds.Min + List->ListElementDimensions; v4 Color = List->LineBGColors[List->ListElementsCount % List->LineBGColorsCount]; - if (PointIsInRange(Mouse.Pos, LineBounds.Min, LineBounds.Max)) + if (PointIsInRect(LineBounds, Mouse.Pos)) { Color = List->LineBGHoverColor; } @@ -560,10 +560,10 @@ DrawListElementBackground(interface_list* List, mouse_state Mouse, render_comman return LineBounds; } -internal rect -DrawListElement(string Label, interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer, interface_config Interface) +internal rect2 +DrawListElement(gs_string Label, interface_list* List, mouse_state Mouse, render_command_buffer* RenderBuffer, interface_config Interface) { - rect Bounds = DrawListElementBackground(List, Mouse, RenderBuffer); + rect2 Bounds = DrawListElementBackground(List, Mouse, RenderBuffer); v2 LabelPosition = Bounds.Min + List->ElementLabelIndent; DrawString(RenderBuffer, Label, Interface.Font, LabelPosition, List->TextColor); @@ -578,27 +578,34 @@ EvaluateColorChannelSlider (render_command_buffer* RenderBuffer, v4 ChannelMask, { r32 Result = Current; + // TODO(Peter): Can this come from outside the function? Would rather pass rect around than min/max + rect2 Rect = rect2{ Min, Max }; + render_quad_batch_constructor Batch = PushRenderQuad2DBatch(RenderBuffer, 2); v4 LeftColor = ChannelMask * 0; LeftColor.a = 1.f; v4 RightColor = ChannelMask; PushQuad2DOnBatch(&Batch, - Min, v2{Max.x, Min.y}, Max, v2{Min.x, Max.y}, + RectBottomLeft(Rect), RectBottomRight(Rect), + RectTopRight(Rect), RectTopLeft(Rect), v2{0, 0}, v2{1, 0}, v2{1, 1}, v2{0, 1}, LeftColor, RightColor, RightColor, LeftColor); if (MouseButtonTransitionedDown(Mouse.LeftButtonState)) { - if (PointIsInRange(Mouse.DownPos, Min, Max)) + if (PointIsInRect(Rect, Mouse.DownPos)) { Result = ((r32)Mouse.Pos.x - Min.x) / (Max.x - Min.x); - Result = GSClamp01(Result); + Result = Clamp01(Result); } } r32 DragBarWidth = 8; - v2 DragBarMin = v2{GSLerp(Min.x, Max.x, Result) - (DragBarWidth / 2), Min.y - 2}; + v2 DragBarMin = v2{ + LerpR32(Result, Min.x, Max.x) - (DragBarWidth / 2), + Min.y - 2 + }; v2 DragBarMax = DragBarMin + v2{DragBarWidth, (Max.y - Min.y) + 4}; PushQuad2DOnBatch(&Batch, DragBarMin, DragBarMax, v4{.3f, .3f, .3f, 1.f}); @@ -612,16 +619,18 @@ EvaluateColorPicker (render_command_buffer* RenderBuffer, v4* Value, v2 PanelMin b32 ShouldClose = false; v2 PanelMax = v2{400, 500}; - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && !PointIsInRange(Mouse.Pos, PanelMin, PanelMax)) + // TODO(Peter): Can this get passed from outside? rather pass rect2 than min/max pairs + rect2 PanelRect = rect2{PanelMin, PanelMax}; + if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && !PointIsInRect(PanelRect, Mouse.Pos)) { ShouldClose = true; } else { - PushRenderQuad2D(RenderBuffer, PanelMin, PanelMax, v4{.5f, .5f, .5f, 1.f}); + PushRenderQuad2D(RenderBuffer, PanelRect.Min, PanelRect.Max, v4{.5f, .5f, .5f, 1.f}); - v2 TitleMin = v2{PanelMin.x + 5, PanelMax.y - (Config.Font->PixelHeight + 5)}; - DrawString(RenderBuffer, MakeStringLiteral("Color Picker"), Config.Font, + v2 TitleMin = v2{PanelRect.Min.x + 5, PanelRect.Max.y - (Config.Font->PixelHeight + 5)}; + DrawString(RenderBuffer, MakeString("Color Picker"), Config.Font, TitleMin, WhiteV4); v2 SliderDim = v2{(PanelMax.x - PanelMin.x) - 20, 32}; @@ -650,13 +659,13 @@ struct search_lister_result b32 ShouldRemainOpen; }; -typedef string search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, string SearchString, s32 Offset); +typedef gs_string search_lister_get_list_item_at_offset(u8* ListMemory, s32 ListLength, gs_string Searchgs_string, s32 Offset); internal search_lister_result -EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, string Title, - string* ItemList, s32* ListLUT, s32 ListLength, +EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, gs_string Title, + gs_string* ItemList, s32* ListLUT, s32 ListLength, s32 HotItem, - string* SearchString, s32 SearchStringCursorPosition) + gs_string* Searchgs_string, s32 Searchgs_stringCursorPosition) { search_lister_result Result = {}; Result.ShouldRemainOpen = true; @@ -666,24 +675,24 @@ EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, string InvalidCodePath; #if 0 // Title Bar - rect TitleBarBounds = rect{v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}}; + rect2 TitleBarBounds = rect2{v2{TopLeft.x, TopLeft.y - 30}, v2{TopLeft.x + 300, TopLeft.y}}; ui_FillRect(Interface, TitleBarBounds, v4{.3f, .3f, .3f, 1.f}); - ui_DrawString(Interface, Title, TitleBarBounds, Interface->Style.TextColor); + ui_Drawgs_string(Interface, Title, TitleBarBounds, Interface->Style.TextColor); - MakeStringBuffer(DebugString, 256); - PrintF(&DebugString, "Hot Item: %d | Filtered Items: %d", HotItem, ListLength); - rect DebugBounds = MakeRectMinWidth(v2{ TopLeft.x + 256, TopLeft.y - 25}, v2{256, Interface->Style.LineHeight}); - ui_DrawString(Interface, DebugString, DebugBounds, Interface->Style.TextColor); + MakeStringBuffer(Debuggs_string, 256); + PrintF(&Debuggs_string, "Hot Item: %d | Filtered Items: %d", HotItem, ListLength); + rect2 DebugBounds = MakeRectMinWidth(v2{ TopLeft.x + 256, TopLeft.y - 25}, v2{256, Interface->Style.LineHeight}); + ui_Drawgs_string(Interface, Debuggs_string, DebugBounds, Interface->Style.TextColor); // 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, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4, GreenV4); + Drawgs_stringWithCursor(RenderBuffer, *Searchgs_string, Searchgs_stringCursorPosition, Font, v2{TopLeft.x, TopLeft.y - 25}, WhiteV4, GreenV4); TopLeft.y -= 30; for (s32 i = 0; i < ListLength; i++) { s32 FilteredIndex = ListLUT[i]; - string ListItemString = ItemList[FilteredIndex]; + gs_string ListItemgs_string = ItemList[FilteredIndex]; v2 Min = v2{TopLeft.x, TopLeft.y - 30}; v2 Max = Min + Dimension - v2{0, Config.Margin.y}; @@ -694,7 +703,7 @@ EvaluateSearchLister (ui_interface* Interface, v2 TopLeft, v2 Dimension, string ButtonColor = Config.ButtonColor_Active; } - if (ui_Button(Interface, ListItemString, rect{Min, Max})) + if (ui_Button(Interface, ListItemgs_string, rect2{Min, Max})) { Result.SelectedItem = i; } diff --git a/src/app/panels/foldhaus_panel_animation_timeline.h b/src/app/panels/foldhaus_panel_animation_timeline.h index 0f5e9b6..fcbf0c1 100644 --- a/src/app/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/panels/foldhaus_panel_animation_timeline.h @@ -6,7 +6,7 @@ #ifndef FOLDHAUS_PANEL_ANIMATION_TIMELINE_H // Colors -global_variable v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; +global v4 TimeSliderColor = v4{.36f, .52f, .78f, 1.f}; // struct animation_timeline_state @@ -15,7 +15,7 @@ struct animation_timeline_state }; inline u32 -GetFrameFromPointInAnimationPanel(v2 Point, rect PanelBounds, frame_range VisibleRange) +GetFrameFromPointInAnimationPanel(v2 Point, rect2 PanelBounds, frame_range VisibleRange) { r32 HorizontalPercentOfBounds = (Point.x - PanelBounds.Min.x) / (PanelBounds.Max.x - PanelBounds.Min.x); u32 VisibleFramesCount = GetFrameCount(VisibleRange); @@ -24,10 +24,10 @@ GetFrameFromPointInAnimationPanel(v2 Point, rect PanelBounds, frame_range Visibl } inline s32 -GetXPositionFromFrameInAnimationPanel (u32 Frame, rect PanelBounds, frame_range VisibleRange) +GetXPositionFromFrameInAnimationPanel (u32 Frame, rect2 PanelBounds, frame_range VisibleRange) { r32 PercentOfTimeline = (r32)(Frame - VisibleRange.Min) / (r32)GetFrameCount(VisibleRange); - s32 XPositionAtFrame = (PercentOfTimeline * gs_Width(PanelBounds)) + PanelBounds.Min.x; + s32 XPositionAtFrame = (PercentOfTimeline * Rect2Width(PanelBounds)) + PanelBounds.Min.x; return XPositionAtFrame; } @@ -67,7 +67,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(DeleteAnimationBlockCommand) OPERATION_STATE_DEF(drag_time_marker_operation_state) { - rect TimelineBounds; + rect2 TimelineBounds; s32 StartFrame; s32 EndFrame; }; @@ -90,7 +90,7 @@ input_command DragTimeMarkerCommands [] = { }; internal void -StartDragTimeMarker(rect TimelineBounds, frame_range VisibleFrames, app_state* State) +StartDragTimeMarker(rect2 TimelineBounds, frame_range VisibleFrames, app_state* State) { operation_mode* DragTimeMarkerMode = ActivateOperationModeWithCommands(&State->Modes, DragTimeMarkerCommands, UpdateDragTimeMarker); @@ -112,7 +112,7 @@ StartDragTimeMarker(rect TimelineBounds, frame_range VisibleFrames, app_state* S OPERATION_STATE_DEF(drag_animation_clip_state) { - rect TimelineBounds; + rect2 TimelineBounds; frame_range VisibleRange; frame_range ClipRange; }; @@ -122,7 +122,7 @@ AttemptToSnapPosition(u32 SnappingFrame, u32 SnapToFrame) { u32 Result = SnappingFrame; s32 SnapDistance = 5; - if (GSAbs((s32)SnappingFrame - (s32)SnapToFrame) <= SnapDistance) + if (Abs((s32)SnappingFrame - (s32)SnapToFrame) <= SnapDistance) { Result = SnapToFrame; } @@ -134,13 +134,13 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) drag_animation_clip_state* OpState = (drag_animation_clip_state*)Operation.OpStateMemory; r32 ClipInitialStartFrameXPercent = FrameToPercentRange(OpState->ClipRange.Min, OpState->VisibleRange); - u32 ClipInitialStartFrameXPosition = GSLerp(OpState->TimelineBounds.Min.x, - OpState->TimelineBounds.Max.x, - ClipInitialStartFrameXPercent); + u32 ClipInitialStartFrameXPosition = LerpR32(ClipInitialStartFrameXPercent, + OpState->TimelineBounds.Min.x, + OpState->TimelineBounds.Max.x); r32 ClipInitialEndFrameXPercent = FrameToPercentRange(OpState->ClipRange.Max, OpState->VisibleRange); - u32 ClipInitialEndFrameXPosition = GSLerp(OpState->TimelineBounds.Min.x, - OpState->TimelineBounds.Max.x, - ClipInitialEndFrameXPercent); + u32 ClipInitialEndFrameXPosition = LerpR32(ClipInitialEndFrameXPercent, + OpState->TimelineBounds.Min.x, + OpState->TimelineBounds.Max.x); u32 FrameAtMouseDownX = GetFrameFromPointInAnimationPanel(Mouse.DownPos, OpState->TimelineBounds, OpState->VisibleRange); @@ -154,7 +154,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) return; } - if (GSAbs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) + if (Abs(Mouse.DownPos.x - ClipInitialStartFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) { s32 NewStartFrame = OpState->ClipRange.Min + FrameOffset; if (FrameOffset < 0) @@ -176,7 +176,7 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) } AnimationBlock->Range.Min = NewStartFrame; } - else if (GSAbs(Mouse.DownPos.x - ClipInitialEndFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) + else if (Abs(Mouse.DownPos.x - ClipInitialEndFrameXPosition) < CLICK_ANIMATION_BLOCK_EDGE_MAX_SCREEN_DISTANCE) { r32 NewEndFrame = OpState->ClipRange.Max + FrameOffset; if (FrameOffset > 0) @@ -228,8 +228,8 @@ OPERATION_RENDER_PROC(UpdateDragAnimationClip) s32 PlayableStartFrame = State->AnimationSystem.PlayableRange.Min; s32 PlayableEndFrame = State->AnimationSystem.PlayableRange.Max; - AnimationBlock->Range.Min = (u32)GSClamp(PlayableStartFrame, (s32)AnimationBlock->Range.Min, PlayableEndFrame); - AnimationBlock->Range.Max = (u32)GSClamp(PlayableStartFrame, (s32)AnimationBlock->Range.Max, PlayableEndFrame); + AnimationBlock->Range.Min = (u32)Clamp(PlayableStartFrame, (s32)AnimationBlock->Range.Min, PlayableEndFrame); + AnimationBlock->Range.Max = (u32)Clamp(PlayableStartFrame, (s32)AnimationBlock->Range.Max, PlayableEndFrame); } input_command DragAnimationClipCommands [] = { @@ -237,7 +237,7 @@ input_command DragAnimationClipCommands [] = { }; internal void -SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range VisibleRange, rect TimelineBounds, app_state* State) +SelectAndBeginDragAnimationBlock(gs_list_handle BlockHandle, frame_range VisibleRange, rect2 TimelineBounds, app_state* State) { SelectAnimationBlock(BlockHandle, State); @@ -289,20 +289,20 @@ AnimationTimeline_Cleanup(panel* Panel, app_state* State) } internal void -DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, frame_range VisibleFrames, rect BarBounds, mouse_state Mouse, app_state* State) +DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBuffer, frame_range VisibleFrames, rect2 BarBounds, mouse_state Mouse, app_state* State) { - string TempString = PushString(&State->Transient, 256); + gs_string TempString = PushString(&State->Transient, 256); s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min; - r32 BarHeight = gs_Height(BarBounds); - r32 BarWidth = gs_Width(BarBounds); + r32 BarHeight = Rect2Height(BarBounds); + r32 BarWidth = Rect2Width(BarBounds); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); + PushRenderQuad2D(RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); // Mouse clicked inside frame nubmer bar -> change current frame on timeline if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - PointIsInRange(Mouse.DownPos, gs_RectExpand(BarBounds))) + PointIsInRect(BarBounds, Mouse.DownPos)) { StartDragTimeMarker(BarBounds, VisibleFrames, State); } @@ -315,7 +315,7 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu u32 Frame = PercentToFrameInRange(Percent, VisibleFrames); PrintF(&TempString, "%d", Frame); r32 FramePercent = FrameToPercentRange(Frame, VisibleFrames); - r32 FrameX = GSLerp(BarBounds.Min.x, BarBounds.Max.x, FramePercent); + r32 FrameX = LerpR32(FramePercent, BarBounds.Min.x, BarBounds.Max.x); v2 FrameTextPos = v2{FrameX, BarBounds.Min.y + 2}; DrawString(RenderBuffer, TempString, State->Interface.Style.Font, FrameTextPos, WhiteV4); } @@ -324,29 +324,28 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu if (FrameIsInRange(AnimationSystem->CurrentFrame, VisibleFrames)) { r32 FrameAtPercentVisibleRange = FrameToPercentRange(AnimationSystem->CurrentFrame, VisibleFrames); - r32 SliderX = GSLerp(BarBounds.Min.x, BarBounds.Max.x, FrameAtPercentVisibleRange); + r32 SliderX = LerpR32(FrameAtPercentVisibleRange, BarBounds.Min.x, BarBounds.Max.x); + + PrintF(&TempString, "%d", AnimationSystem->CurrentFrame); - u32 FrameNumberCharCount = GetU32NumberOfCharactersNeeded(AnimationSystem->CurrentFrame); // space for each character + a margin on either side - r32 SliderWidth = (8 * FrameNumberCharCount) + 8; + r32 SliderWidth = (8 * TempString.Length) + 8; r32 SliderHalfWidth = SliderWidth / 2.f; v2 HeadMin = v2{SliderX - SliderHalfWidth, BarBounds.Min.y}; v2 HeadMax = v2{SliderX + SliderHalfWidth, BarBounds.Max.y}; PushRenderQuad2D(RenderBuffer, HeadMin, HeadMax, TimeSliderColor); - - PrintF(&TempString, "%d", AnimationSystem->CurrentFrame); DrawString(RenderBuffer, TempString, State->Interface.Style.Font, HeadMin + v2{6, 4}, WhiteV4); } } internal frame_range -DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, render_command_buffer* RenderBuffer, rect BarBounds, mouse_state Mouse) +DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_state* TimelineState, render_command_buffer* RenderBuffer, rect2 BarBounds, mouse_state Mouse) { frame_range Result = {0}; - r32 BarHeight = gs_Height(BarBounds); - r32 BarWidth = gs_Width(BarBounds); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); + r32 BarHeight = Rect2Height(BarBounds); + r32 BarWidth = Rect2Width(BarBounds); + PushRenderQuad2D(RenderBuffer, BarBounds.Min, BarBounds.Max, v4{.16f, .16f, .16f, 1.f}); r32 PlayableFrames = (r32)GetFrameCount(AnimationSystem->PlayableRange); v2 SliderBarDim = v2{25, BarHeight}; @@ -354,22 +353,24 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat // Convert Frames To Pixels r32 VisibleMinPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Min, AnimationSystem->PlayableRange); r32 VisibleMaxPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Max, AnimationSystem->PlayableRange); - v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * gs_Width(BarBounds)), BarBounds.Min.y}; - v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * gs_Width(BarBounds)) - 25, BarBounds.Min.y}; + v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * Rect2Width(BarBounds)), BarBounds.Min.y}; + v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * Rect2Width(BarBounds)) - 25, BarBounds.Min.y}; + + rect2 SliderBarRange = rect2{ RangeMinSliderMin, RangeMinSliderMin + SliderBarDim }; if (MouseButtonHeldDown(Mouse.LeftButtonState) || MouseButtonTransitionedUp(Mouse.LeftButtonState)) { v2 MouseDragOffset = Mouse.Pos - Mouse.DownPos; - if (PointIsInRange(Mouse.DownPos, RangeMinSliderMin, RangeMinSliderMin + SliderBarDim)) + if (PointIsInRect(SliderBarRange, Mouse.DownPos)) { r32 NewSliderX = RangeMinSliderMin.x + MouseDragOffset.x; - RangeMinSliderMin.x = GSClamp(BarBounds.Min.x, NewSliderX, RangeMaxSliderMin.x - SliderBarDim.x); + RangeMinSliderMin.x = Clamp(BarBounds.Min.x, NewSliderX, RangeMaxSliderMin.x - SliderBarDim.x); } - if (PointIsInRange(Mouse.DownPos, RangeMaxSliderMin, RangeMaxSliderMin + SliderBarDim)) + if (PointIsInRect(SliderBarRange, Mouse.DownPos)) { r32 NewSliderX = RangeMaxSliderMin.x + MouseDragOffset.x; - RangeMaxSliderMin.x = GSClamp(RangeMinSliderMin.x + SliderBarDim.x, NewSliderX, BarBounds.Max.x - SliderBarDim.x); + RangeMaxSliderMin.x = Clamp(RangeMinSliderMin.x + SliderBarDim.x, NewSliderX, BarBounds.Max.x - SliderBarDim.x); } } @@ -396,19 +397,19 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat #define LAYER_HEIGHT 52 internal void -DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) +DrawLayerMenu(animation_system* AnimationSystem, rect2 PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) { - v2 LayerDim = { gs_Width(PanelDim), LAYER_HEIGHT }; + v2 LayerDim = { Rect2Width(PanelDim), LAYER_HEIGHT }; v2 LayerListMin = PanelDim.Min + v2{0, 24}; for (u32 LayerIndex = 0; LayerIndex < AnimationSystem->LayersCount; LayerIndex++) { anim_layer* Layer = AnimationSystem->Layers + LayerIndex; - rect LayerBounds = {0}; + rect2 LayerBounds = {0}; LayerBounds.Min = { LayerListMin.x, LayerListMin.y + (LayerDim.y * LayerIndex) }; LayerBounds.Max = LayerBounds.Min + LayerDim; if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - gs_PointIsInRect(Mouse.Pos, LayerBounds)) + PointIsInRect(LayerBounds, Mouse.Pos)) { State->SelectedAnimationLayer = LayerIndex; } @@ -416,18 +417,18 @@ DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_b v2 LayerTextPos = { LayerBounds.Min.x + 6, LayerBounds.Max.y - 16}; if (State->SelectedAnimationLayer == LayerIndex) { - PushRenderBoundingBox2D(RenderBuffer, gs_RectExpand(LayerBounds), 1, WhiteV4); + PushRenderBoundingBox2D(RenderBuffer, LayerBounds.Min, LayerBounds.Max, 1, WhiteV4); } DrawString(RenderBuffer, Layer->Name, State->Interface.Style.Font, LayerTextPos, WhiteV4); } } -internal rect -DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect TimelineBounds, render_command_buffer* RenderBuffer) +internal rect2 +DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range VisibleFrames, rect2 TimelineBounds, render_command_buffer* RenderBuffer) { - rect BlockBounds = {}; + rect2 BlockBounds = {}; - r32 TimelineWidth = gs_Width(TimelineBounds); + r32 TimelineWidth = Rect2Width(TimelineBounds); u32 ClampedBlockStartFrame = ClampFrameToRange(AnimationBlock.Range.Min, VisibleFrames); r32 StartFramePercent = FrameToPercentRange(ClampedBlockStartFrame, VisibleFrames); @@ -448,18 +449,18 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V } internal gs_list_handle -DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) +DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_state* TimelineState, rect2 PanelBounds, gs_list_handle SelectedBlockHandle, ui_interface* Interface, app_state* State) { - string TempString = PushString(&State->Transient, 256); + gs_string Tempgs_string = PushString(&State->Transient, 256); gs_list_handle Result = SelectedBlockHandle; - rect LayerMenuBounds, TimelineBounds; - gs_VSplitRectAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); + rect2 LayerMenuBounds, TimelineBounds; + RectVSplitAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); // In Top To Bottom Order - rect TimelineFrameBarBounds, TimelineBlockDisplayBounds, TimelineRangeBarBounds; - gs_HSplitRectAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); - gs_HSplitRectAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); + rect2 TimelineFrameBarBounds, TimelineBlockDisplayBounds, TimelineRangeBarBounds; + RectHSplitAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); + RectHSplitAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); // TODO(Peter): Clean Up DrawLayerMenu(AnimationSystem, LayerMenuBounds, Interface->RenderBuffer, State, Interface->Mouse); @@ -500,8 +501,8 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta BlockColor = PinkV4; } // TODO(Peter): Clean Up - rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); - if (gs_PointIsInRect(Interface->Mouse.Pos, BlockBounds)) + rect2 BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); + if (PointIsInRect(BlockBounds, Interface->Mouse.Pos)) { DragBlockHandle = CurrentBlockHandle; } @@ -519,8 +520,8 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta if (FrameIsInRange(AnimationSystem->CurrentFrame, AdjustedViewRange)) { r32 FrameAtPercentVisibleRange = FrameToPercentRange(AnimationSystem->CurrentFrame, AdjustedViewRange); - r32 SliderX = GSLerp(TimelineBounds.Min.x, TimelineBounds.Max.x, FrameAtPercentVisibleRange); - rect SliderBounds = { + r32 SliderX = LerpR32(FrameAtPercentVisibleRange, TimelineBounds.Min.x, TimelineBounds.Max.x); + rect2 SliderBounds = { v2{ SliderX, TimelineBounds.Min.y }, v2{ SliderX + 1, TimelineBounds.Max.y } }; @@ -531,7 +532,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta ui_OutlineRect(Interface, TimelineFrameBarBounds, 1.f, RedV4); ui_OutlineRect(Interface, TimelineBlockDisplayBounds, 1.f, RedV4); - if (MouseDownAndNotHandled && gs_PointIsInRect(Interface->Mouse.Pos, TimelineBounds)) + if (MouseDownAndNotHandled && PointIsInRect(TimelineBounds, Interface->Mouse.Pos)) { DeselectCurrentAnimationBlock(State); } @@ -554,13 +555,13 @@ animation_clip GlobalAnimationClips[] = { }; internal void -DrawAnimationClipsList(rect PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayer, animation_system* AnimationSystem) +DrawAnimationClipsList(rect2 PanelBounds, ui_interface* Interface, u32 SelectedAnimationLayer, animation_system* AnimationSystem) { ui_layout Layout = ui_CreateLayout(*Interface, PanelBounds); for (s32 i = 0; i < GlobalAnimationClipsCount; i++) { animation_clip Clip = GlobalAnimationClips[i]; - string ClipName = MakeString(Clip.Name, Clip.NameLength); + gs_string ClipName = MakeString(Clip.Name, Clip.NameLength); if (ui_LayoutListEntry(Interface, &Layout, ClipName, i)) { AddAnimationBlockAtCurrentTime(i + 1, SelectedAnimationLayer, AnimationSystem); @@ -572,7 +573,7 @@ DrawAnimationClipsList(rect PanelBounds, ui_interface* Interface, u32 SelectedAn GSMetaTag(panel_render); GSMetaTag(panel_type_animation_timeline); internal void -AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +AnimationTimeline_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { animation_timeline_state* TimelineState = (animation_timeline_state*)Panel.PanelStateMemory; gs_list_handle SelectedBlockHandle = State->SelectedAnimationBlockHandle; @@ -580,24 +581,24 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R ui_interface* Interface = &State->Interface; animation_system* AnimationSystem = &State->AnimationSystem; - rect TitleBarBounds, PanelContentsBounds; - gs_HSplitRectAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); - rect AnimationListBounds, TimelineBounds; - gs_VSplitRectAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); + rect2 TitleBarBounds, PanelContentsBounds; + RectHSplitAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); + rect2 AnimationListBounds, TimelineBounds; + RectVSplitAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); ui_FillRect(Interface, TitleBarBounds, Interface->Style.PanelBGColors[0]); ui_layout TitleBarLayout = ui_CreateLayout(*Interface, TitleBarBounds); ui_StartRow(&TitleBarLayout, 3); { - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeStringLiteral("Pause"))) + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Pause"))) { State->AnimationSystem.TimelineShouldAdvance = true; } - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeStringLiteral("Play"))) + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Play"))) { State->AnimationSystem.TimelineShouldAdvance = false; } - if (ui_LayoutButton(Interface, &TitleBarLayout, MakeStringLiteral("Stop"))) + if (ui_LayoutButton(Interface, &TitleBarLayout, MakeString("Stop"))) { State->AnimationSystem.TimelineShouldAdvance = false; State->AnimationSystem.CurrentFrame = 0; @@ -605,7 +606,7 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R } ui_EndRow(&TitleBarLayout); - if (gs_Height(TimelineBounds) > 0) + if (Rect2Height(TimelineBounds) > 0) { SelectedBlockHandle = DrawAnimationTimeline(AnimationSystem, TimelineState, TimelineBounds, SelectedBlockHandle, Interface, State); DrawAnimationClipsList(AnimationListBounds, Interface, State->SelectedAnimationLayer, &State->AnimationSystem); diff --git a/src/app/panels/foldhaus_panel_dmx_view.h b/src/app/panels/foldhaus_panel_dmx_view.h index 8d5acce..56d0352 100644 --- a/src/app/panels/foldhaus_panel_dmx_view.h +++ b/src/app/panels/foldhaus_panel_dmx_view.h @@ -74,7 +74,7 @@ DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDr GSMetaTag(panel_render); GSMetaTag(panel_type_dmx_view); internal void -DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +DMXView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { #if 0 // :NoLongerFunctionalSACNCodeButThatsOk @@ -82,7 +82,7 @@ DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffe universe_view_operation_state* OpState = (universe_view_operation_state*)Operation.OpStateMemory; - string TitleBarString = InitializeEmptyString(PushArray(State->Transient, char, 64), 64); + gs_string TitleBargs_string = InitializeEmptygs_string(PushArray(State->Transient, char, 64), 64); v2 DisplayArea_Dimension = v2{600, 600}; @@ -120,8 +120,8 @@ DMXView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffe if (OpState->Zoom > .5f) { v2 TitleDisplayStart = UniverseDisplayTopLeft + v2{0, 12}; - PrintF(&TitleBarString, "Universe %d", Universe->Universe); - DrawString(RenderBuffer, TitleBarString, State->Interface.Font, + PrintF(&TitleBargs_string, "Universe %d", Universe->Universe); + DrawString(RenderBuffer, TitleBargs_string, State->Interface.Font, TitleDisplayStart, WhiteV4); } diff --git a/src/app/panels/foldhaus_panel_file_view.h b/src/app/panels/foldhaus_panel_file_view.h index bfcd34e..2fd2953 100644 --- a/src/app/panels/foldhaus_panel_file_view.h +++ b/src/app/panels/foldhaus_panel_file_view.h @@ -7,7 +7,7 @@ struct file_view_state { - string WorkingDirectory; + gs_string WorkingDirectory; }; input_command* FileView_Commands = 0; @@ -36,18 +36,18 @@ FileView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_file_view); internal void -FileView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +FileView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - rect HeaderBounds = {0}; + rect2 HeaderBounds = {0}; HeaderBounds.Min = {PanelBounds.Min.x, PanelBounds.Max.y - 32}; HeaderBounds.Max = PanelBounds.Max; - rect ListBounds = {0}; + rect2 ListBounds = {0}; ListBounds.Min = PanelBounds.Min; - ListBounds.Max = gs_BottomRight(HeaderBounds); + ListBounds.Max = RectBottomRight(HeaderBounds); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(HeaderBounds), PinkV4); - PushRenderQuad2D(RenderBuffer, gs_RectExpand(ListBounds), RedV4); + PushRenderQuad2D(RenderBuffer, HeaderBounds.Min, HeaderBounds.Max, PinkV4); + PushRenderQuad2D(RenderBuffer, ListBounds.Min, ListBounds.Max, RedV4); } diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 043caa0..5d0cca7 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -27,13 +27,13 @@ HierarchyView_Cleanup(panel* Panel, app_state* State) GSMetaTag(panel_render); GSMetaTag(panel_type_hierarchy); internal void -HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +HierarchyView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { ui_layout Layout = ui_CreateLayout(State->Interface, PanelBounds); - string TempString = PushString(&State->Transient, 256); - u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; - u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count); - rect* LineBounds = PushArray(&State->Transient, rect, LineCount); + gs_string Tempgs_string = PushString(&State->Transient, 256); + u32 LineCount = (u32)(Rect2Height(PanelBounds) / Layout.RowHeight) + 1; + u32 AssembliesToDraw = Min(LineCount, State->Assemblies.Count); + rect2* LineBounds = PushArray(&State->Transient, rect2, LineCount); // Fill in alternating color rows for the backgrounds for (u32 Line = 0; Line < LineCount; Line++) @@ -46,13 +46,13 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++) { assembly Assembly = State->Assemblies.Values[AssemblyIndex]; - PrintF(&TempString, "%S", Assembly.Name); + PrintF(&Tempgs_string, "%S", Assembly.Name); ui_layout ItemLayout = ui_CreateLayout(State->Interface, LineBounds[AssemblyIndex]); ui_StartRow(&ItemLayout, 2); { - ui_LayoutDrawString(&State->Interface, &ItemLayout, TempString, State->Interface.Style.TextColor); - if (ui_LayoutListButton(&State->Interface, &ItemLayout, MakeStringLiteral("X"), AssemblyIndex)) + ui_LayoutDrawString(&State->Interface, &ItemLayout, Tempgs_string, State->Interface.Style.TextColor); + if (ui_LayoutListButton(&State->Interface, &ItemLayout, MakeString("X"), AssemblyIndex)) { UnloadAssembly(AssemblyIndex, State, Context); } @@ -63,15 +63,22 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende if (AssembliesToDraw < LineCount) { // NOTE(Peter): Add assembly button - PrintF(&TempString, "+ Add Assembly"); - if (ui_ListButton(&State->Interface, TempString, LineBounds[AssembliesToDraw], AssembliesToDraw)) + PrintF(&Tempgs_string, "+ Add Assembly"); + if (ui_ListButton(&State->Interface, Tempgs_string, LineBounds[AssembliesToDraw], AssembliesToDraw)) { - string FilePath = PushString(&State->Transient, 256); + gs_string FilePath = PushString(&State->Transient, 256); + + // TODO(Peter): Took out file opening temporarily while I get things back up and running. + // Ideally we can just write our own file lister using the new filehandler so that + // execution doesn't suspend while we try and open a file + InvalidCodePath; +#if 0 b32 Success = GetFilePath(Context, &FilePath, "Foldhaus Files\0*.fold\0\0"); if (Success) { - LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath, State->GlobalLog); + LoadAssembly(&State->Assemblies, &State->LedSystem, &State->Transient, Context, FilePath.ConstString, State->GlobalLog); } +#endif } } } diff --git a/src/app/panels/foldhaus_panel_profiler.h b/src/app/panels/foldhaus_panel_profiler.h index 75c010a..bc18748 100644 --- a/src/app/panels/foldhaus_panel_profiler.h +++ b/src/app/panels/foldhaus_panel_profiler.h @@ -25,7 +25,7 @@ ProfilerView_Cleanup(panel* Panel, app_state* State) } internal void -RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, memory_arena* Memory) +RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, gs_memory_arena* Memory) { v4 ThreadColors[] = { v4{.73f, .33f, .83f, 1}, @@ -35,8 +35,8 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb v4{.74f, .40f, .25f, 1}, }; - rect Bounds = ui_LayoutRemaining(Layout); - r32 Width = gs_Width(Bounds); + rect2 Bounds = ui_LayoutRemaining(Layout); + r32 Width = Rect2Width(Bounds); r32 DepthHeight = 64; s64 FrameStartCycles = VisibleFrame->FrameStartCycles; @@ -48,7 +48,8 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb scope_record* HotRecord = 0; scope_name* HotRecordName = 0; - MakeStringBuffer(String, 256); + char Backbuffer[256]; + gs_string String = MakeString(Backbuffer, 0, 256); for (s32 i = 0; i < ThreadScopeCalls->Count; i++) { scope_record* Record = ThreadScopeCalls->Calls + i; @@ -59,14 +60,14 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb r32 PixelStart = Bounds.Min.x + (Width * PercentStart); r32 PixelEnd = Bounds.Min.x + (Width * PercentEnd); r32 MinY = Bounds.Max.y - ((Record->CallDepth + 1) * DepthHeight); - rect ScopeBounds = { + rect2 ScopeBounds = { v2{ PixelStart, MinY }, v2{ PixelEnd, MinY + (DepthHeight - 4) } }; - if (gs_Width(ScopeBounds) >= 1) + if (Rect2Width(ScopeBounds) >= 1) { v4 Color = ThreadColors[0]; - if (gs_PointIsInRect(Interface->Mouse.Pos, ScopeBounds)) + if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos)) { Color = GreenV4; HotRecord = Record; @@ -81,23 +82,26 @@ RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, deb if (HotRecord != 0) { PrintF(&String, "%S : %d - %d", HotRecordName->Name, HotRecord->StartCycles, HotRecord->EndCycles); - ui_TextBox(Interface, gs_MakeRectMinWidth(Interface->Mouse.Pos, v2{256, 32}), String, BlackV4, WhiteV4); + + rect2 TextBounds = MakeRect2MinDim(Interface->Mouse.Pos, v2{256, 32}); + ui_TextBox(Interface, TextBounds, String, BlackV4, WhiteV4); } } internal void -RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, memory_arena* Memory) +RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, gs_memory_arena* Memory) { - MakeStringBuffer(String, 256); + char Backbuffer[256]; + gs_string String = MakeString(Backbuffer, 0, 256); r32 ColumnWidths[] = {256, 128, 128, 128, 128}; ui_StartRow(&Layout, 5, &ColumnWidths[0]); { - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Procedure"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("% Frame"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Seconds"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Cycles"), Interface->Style.TextColor); - ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Calls"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Procedure"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("% Frame"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Seconds"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Cycles"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeString("Calls"), Interface->Style.TextColor); } ui_EndRow(&Layout); @@ -133,40 +137,43 @@ RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debu GSMetaTag(panel_render); GSMetaTag(panel_type_profiler); internal void -ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +ProfilerView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { - memory_arena* Memory = &State->Transient; - string String = InitializeEmptyString(PushArray(Memory, char, 256), 256); + gs_memory_arena* Memory = &State->Transient; + gs_string String = PushString(Memory, 256); v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; r32 FrameListHeight = 64; - rect FrameListBounds, ProcListBounds; - gs_HSplitRectAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); - rect FrameListInner = gs_InsetRect(FrameListBounds, 4); + rect2 FrameListBounds, ProcListBounds; + RectHSplitAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); + rect2 FrameListInner = RectInset(FrameListBounds, 4); - r32 SingleFrameStep = gs_Width(FrameListInner) / DEBUG_FRAME_COUNT; + r32 SingleFrameStep = Rect2Width(FrameListInner) / DEBUG_FRAME_COUNT; r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4); - if (gs_PointIsInRect(Context.Mouse.Pos, FrameListBounds) && MouseButtonHeldDown(Context.Mouse.LeftButtonState)) + if (MouseButtonHeldDown(Context.Mouse.LeftButtonState)) { - v2 LocalMouse = gs_TransformPointIntoRectSpace(Context.Mouse.Pos, FrameListBounds); - s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); - if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) + if (PointIsInRect(FrameListBounds, Context.Mouse.Pos)) { - GlobalDebugServices->RecordFrames = false; - GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; + v2 LocalMouse = Rect2GetRectLocalPoint(FrameListBounds, Context.Mouse.Pos); + s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); + if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) + { + GlobalDebugServices->RecordFrames = false; + GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex; + } } } - rect FrameBounds = gs_MakeRectMinWidth(FrameListInner.Min, v2{SingleFrameWidth, gs_Height(FrameListInner)}); + rect2 FrameBounds = MakeRect2MinDim(FrameListInner.Min, v2{SingleFrameWidth, Rect2Height(FrameListInner)}); for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++) { - rect PositionedFrameBounds = gs_TranslateRectX(FrameBounds, F * SingleFrameStep); + rect2 PositionedFrameBounds = Rect2TranslateX(FrameBounds, F * SingleFrameStep); s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } - v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)]; + v4 Color = FrameColors[Clamp(0, FramesAgo, 3)]; ui_FillRect(&State->Interface, PositionedFrameBounds, Color); } diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index 304fff6..b9a31af 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -18,11 +18,11 @@ OPERATION_RENDER_PROC(Update3DViewMouseRotate) v2 TotalDeltaPos = Mouse.Pos - Mouse.DownPos; - m44 XRotation = GetXRotation(-TotalDeltaPos.y * State->PixelsToWorldScale); - m44 YRotation = GetYRotation(TotalDeltaPos.x * State->PixelsToWorldScale); + m44 XRotation = M44RotationX(-TotalDeltaPos.y * State->PixelsToWorldScale); + m44 YRotation = M44RotationY(TotalDeltaPos.x * State->PixelsToWorldScale); m44 Combined = XRotation * YRotation; - State->Camera.Position = V3(Combined * OpState->CameraStartPos); + State->Camera.Position = (Combined * OpState->CameraStartPos).xyz; } FOLDHAUS_INPUT_COMMAND_PROC(End3DViewMouseRotate) @@ -40,17 +40,17 @@ FOLDHAUS_INPUT_COMMAND_PROC(Begin3DViewMouseRotate) mouse_rotate_view_operation_state* OpState = CreateOperationState(RotateViewMode, &State->Modes, mouse_rotate_view_operation_state); - OpState->CameraStartPos = V4(State->Camera.Position, 1); + OpState->CameraStartPos = ToV4Point(State->Camera.Position); } // ---------------- GSMetaTag(panel_commands); GSMetaTag(panel_type_sculpture_view); -global_variable input_command SculptureView_Commands[] = { +global input_command SculptureView_Commands[] = { { KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate }, }; -global_variable s32 SculptureView_CommandsCount = 1; +global s32 SculptureView_CommandsCount = 1; GSMetaTag(panel_init); GSMetaTag(panel_type_sculpture_view); @@ -76,23 +76,26 @@ struct draw_leds_job_data s32 StartIndex; s32 OnePastLastIndex; render_quad_batch_constructor* Batch; - m44 ModelViewMatrix; + quad_batch_constructor_reserved_range BatchReservedRange; r32 LEDHalfWidth; }; internal void -DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) +DrawLEDsInBufferRangeJob (gs_thread_context Context, gs_data JobData) { DEBUG_TRACK_FUNCTION; - draw_leds_job_data* Data = (draw_leds_job_data*)JobData; + draw_leds_job_data* Data = (draw_leds_job_data*)JobData.Memory; s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex; +#if 0 // TODO(Peter): Why are we doing this here? Shouldn't we be able to tell what the range // needs to be at the time of creation? That way its all on one thread and we're not // worried about locking up. quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2); +#endif + s32 TrisUsed = 0; r32 HalfWidth = Data->LEDHalfWidth; @@ -113,77 +116,101 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f}; v4 Position = Data->LedBuffer.Positions[LedIndex]; - m44 FaceCameraMatrix = GetLookAtMatrix(Position, Data->CameraPosition); - v4 PositionOffset = V4(Position.xyz, 0); // Ensure PositionOffset is a vector, not a point + m44 FaceCameraMatrix = M44LookAt(Position, Data->CameraPosition); + v4 PositionOffset = ToV4Vec(Position.xyz); v4 P0 = (FaceCameraMatrix * P0_In) + PositionOffset; v4 P1 = (FaceCameraMatrix * P1_In) + PositionOffset; v4 P2 = (FaceCameraMatrix * P2_In) + PositionOffset; v4 P3 = (FaceCameraMatrix * P3_In) + PositionOffset; - SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, + SetTri3DInBatch(Data->Batch, Data->BatchReservedRange.Start + TrisUsed++, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); - SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++, + SetTri3DInBatch(Data->Batch, Data->BatchReservedRange.Start + TrisUsed++, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); } } +internal void +DrawQuad(render_command_buffer* RenderBuffer, v4 C, r32 Rad, v4 Color) +{ + v4 P0 = C + v4{-Rad,-Rad,0,0}; + v4 P1 = C + v4{ Rad,-Rad,0,0}; + v4 P2 = C + v4{ Rad,Rad,0,0}; + v4 P3 = C + v4{ -Rad,Rad,0,0}; + PushRenderQuad3D(RenderBuffer, P0, P1, P2, P3, Color); +} + GSMetaTag(panel_render); GSMetaTag(panel_type_sculpture_view); internal void -SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) +SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context) { DEBUG_TRACK_SCOPE(RenderSculpture); - r32 PanelWidth = PanelBounds.Max.x - PanelBounds.Min.x; - r32 PanelHeight = PanelBounds.Max.y - PanelBounds.Min.y; - State->Camera.AspectRatio = PanelWidth / PanelHeight; + // TODO(Peter): @MajorFix + // NOTE(Peter): Just returning from this function to make sure that this isn't a problem as I go and try to fix + // the other panels + return; - m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); - m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); - r32 LEDHalfWidth = .5f; + State->Camera.AspectRatio = RectAspectRatio(PanelBounds); - PushRenderPerspective(RenderBuffer, PanelBounds.Min.x, PanelBounds.Min.y, PanelWidth, PanelHeight, State->Camera); - - m44 FaceCameraMatrix = GetLookAtMatrix(v4{0, 0, 0, 1}, V4(State->Camera.Position, 1)); + PushRenderPerspective(RenderBuffer, PanelBounds, State->Camera); u32 MaxLEDsPerJob = 2048; render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal); u32 FocusPixel = 256; - for (u32 i = 0; i < State->Assemblies.Count; i++) + for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++) { - assembly Assembly = State->Assemblies.Values[i]; - led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex); - u32 JobsNeeded = IntegerDivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); - - // TODO(Peter): TEMPORARY - identify this pixel - LedBuffer->Colors[FocusPixel] = pixel{ 255, 0, 255 }; + led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex); + u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob); +#if 1 + u32 NextLEDIndex = 0; for (u32 Job = 0; Job < JobsNeeded; Job++) { - draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data); + gs_data Data = PushSizeToData(&State->Transient, sizeof(draw_leds_job_data)); + draw_leds_job_data* JobData = (draw_leds_job_data*)Data.Memory; JobData->LedBuffer = *LedBuffer; - JobData->StartIndex = Job * MaxLEDsPerJob; - JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); + JobData->StartIndex = NextLEDIndex; + JobData->OnePastLastIndex = Min(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount); + s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; JobData->Batch = &RenderLEDsBatch; - JobData->ModelViewMatrix = ModelViewMatrix; - JobData->LEDHalfWidth = LEDHalfWidth; + JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); + JobData->LEDHalfWidth = .5f; - JobData->CameraPosition = V4(State->Camera.Position, 1); + JobData->CameraPosition = ToV4Point(State->Camera.Position); - Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, DrawLEDsInBufferRangeJob, JobData, "Sculpture Draw LEDS"); + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); + + NextLEDIndex = JobData->OnePastLastIndex; } +#else + gs_data Data = PushSizeToData(&State->Transient, sizeof(draw_leds_job_data)); + draw_leds_job_data* JobData = (draw_leds_job_data*)Data.Memory; + JobData->LedBuffer = *LedBuffer; + JobData->StartIndex = 0; + JobData->OnePastLastIndex = LedBuffer->LedCount; + s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex; + JobData->Batch = &RenderLEDsBatch; + JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2); + JobData->LEDHalfWidth = .5f; + + JobData->CameraPosition = ToV4Point(State->Camera.Position); + + Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS")); +#endif + + u32 f = 0; } // TODO(Peter): I don't like the fact that setting an orthographic view inside a panel render function // needs to relyon the window bounds rather than the panel bounds. Ideally the panel only needs to know where // itself is, and nothing else. - PushRenderOrthographic(RenderBuffer, - State->WindowBounds.Min.x, State->WindowBounds.Min.y, - State->WindowBounds.Max.x, State->WindowBounds.Max.y); + PushRenderOrthographic(RenderBuffer, State->WindowBounds); if (State->Assemblies.Count > 0) { @@ -196,9 +223,9 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende v4 LedProjectedPosition = Matrix * LedPosition; v2 LedOnScreenPosition = LedProjectedPosition.xy; - string TempString = PushString(&State->Transient, 256); - PrintF(&TempString, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); - DrawString(RenderBuffer, TempString, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); + gs_string Tempgs_string = PushString(&State->Transient, 256); + PrintF(&Tempgs_string, "%f %f", LedOnScreenPosition.x, LedOnScreenPosition.y); + DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4); v2 BoxHalfDim = v2{ 25, 25 }; v2 BoxMin = LedOnScreenPosition - BoxHalfDim; @@ -206,7 +233,7 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende PushRenderBoundingBox2D(RenderBuffer, BoxMin, BoxMax, 2.0f, TealV4); } - Context.GeneralWorkQueue->DoQueueWorkUntilDone(Context.GeneralWorkQueue, 0); + Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext); } #define FOLDHAUS_PANEL_SCULPTURE_VIEW_H diff --git a/src/app/sacn/sacn.h b/src/app/sacn/sacn.h index 47adaa2..a871cea 100644 --- a/src/app/sacn/sacn.h +++ b/src/app/sacn/sacn.h @@ -160,11 +160,11 @@ VHD_PackLength_(u8* Buffer, u32 Length, b32 IncludeLength) } internal cid -StringToCID_ (const char* String) +gs_stringToCID_ (const char* gs_string) { cid Result = {}; - const char* Src = String; + const char* Src = gs_string; u8* Dest = &Result.Bytes[0]; b32 FirstNibble = true; @@ -215,7 +215,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, Cursor = PackB2(Cursor, RLP_PREAMBLE_SIZE); Cursor = PackB2(Cursor, RLP_POSTAMBLE_SIZE); - GSMemCopy(ACN_IDENTIFIER, Cursor, ACN_IDENTIFIER_SIZE); + CopyMemoryTo(ACN_IDENTIFIER, Cursor, ACN_IDENTIFIER_SIZE); Cursor += ACN_IDENTIFIER_SIZE; // TODO(Peter): If you never use this anywhere else, go back and remove the parameters @@ -243,7 +243,7 @@ InitStreamHeader (u8* Buffer, s32 BufferSize, // framing source name // :Check - GSMemCopy(SourceName, (char*)Cursor, SOURCE_NAME_SIZE); + CopyMemoryTo(SourceName, (char*)Cursor, SOURCE_NAME_SIZE); Cursor[SOURCE_NAME_SIZE - 1] = '\0'; Cursor += SOURCE_NAME_SIZE; @@ -298,7 +298,7 @@ InitializeSACN (context Context) s32 Multicast_TimeToLive = 20; SACN.SendSocket = Context.PlatformGetSocketHandle(Multicast_TimeToLive); - SACN.CID = StringToCID_ ("{67F9D986-544E-4abb-8986-D5F79382586C}"); + SACN.CID = gs_stringToCID_ ("{67F9D986-544E-4abb-8986-D5F79382586C}"); return SACN; } diff --git a/src/app/test_patterns.h b/src/app/test_patterns.h index 51da616..6d4d0c6 100644 --- a/src/app/test_patterns.h +++ b/src/app/test_patterns.h @@ -18,9 +18,9 @@ struct solid_color_data GSMetaTag(node_proc); // :TagParamsForNodeParamStructs void SolidColorProc(solid_color_data* 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); + u8 R = (u8)Clamp(0.f, (Data->Color.r * 255), 255.f); + u8 G = (u8)Clamp(0.f, (Data->Color.g * 255), 255.f); + u8 B = (u8)Clamp(0.f, (Data->Color.b * 255), 255.f); for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++) { @@ -64,7 +64,7 @@ void VerticalColorFadeProc(vertical_color_fade_data* Data) v4 LedPosition = Data->Result.LedPositions[LedIndex]; r32 Amount = (LedPosition.y - Data->Min) / Range; - Amount = GSClamp01(1.0f - Amount); + Amount = Clamp01(1.0f - Amount); Data->Result.Colors[LedIndex].R = (u8)(R * Amount); Data->Result.Colors[LedIndex].G = (u8)(G * Amount); @@ -107,14 +107,14 @@ void RevolvingDiscs(revolving_discs_data* Data) DEBUG_TRACK_FUNCTION; pixel Color = { - (u8)(GSClamp01(Data->Color.r) * 255), - (u8)(GSClamp01(Data->Color.g) * 255), - (u8)(GSClamp01(Data->Color.b) * 255), + (u8)(Clamp01(Data->Color.r) * 255), + (u8)(Clamp01(Data->Color.g) * 255), + (u8)(Clamp01(Data->Color.b) * 255), }; v4 Center = v4{0, 0, 0, 1}; - v4 Normal = v4{GSCos(Data->ThetaZ), 0, GSSin(Data->ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 - v4 Right = Cross(Normal, v4{0, 1, 0, 0}); + v4 Normal = v4{CosR32(Data->ThetaZ), 0, SinR32(Data->ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1 + v4 Right = V4Cross(Normal, v4{0, 1, 0, 0}); v4 FrontCenter = Center + (Normal * Data->DiscWidth); v4 BackCenter = Center - (Normal * Data->DiscWidth); @@ -129,13 +129,13 @@ void RevolvingDiscs(revolving_discs_data* Data) v4 ToFront = Position + FrontCenter; v4 ToBack = Position + BackCenter; - r32 ToFrontDotNormal = Dot(ToFront, Normal); - r32 ToBackDotNormal = Dot(ToBack, Normal); + r32 ToFrontDotNormal = V4Dot(ToFront, Normal); + r32 ToBackDotNormal = V4Dot(ToBack, Normal); - ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000); - ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000); + ToFrontDotNormal = Clamp01(ToFrontDotNormal * 1000); + ToBackDotNormal = Clamp01(ToBackDotNormal * 1000); - r32 SqDistToCenter = MagSqr(Position); + r32 SqDistToCenter = V4MagSquared(Position); if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared) { if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) diff --git a/src/app/win32_foldhaus.cpp b/src/app/win32_foldhaus.cpp index 88ff2d9..65df438 100644 --- a/src/app/win32_foldhaus.cpp +++ b/src/app/win32_foldhaus.cpp @@ -16,14 +16,13 @@ #include "../gs_libs/gs_win32.cpp" #include "win32_foldhaus_memory.h" -#include "win32_foldhaus_fileio.h" #include "win32_foldhaus_dll.h" #include "win32_foldhaus_timing.h" #include "foldhaus_renderer.cpp" -global_variable b32 Running = false; -global_variable b32 WindowIsActive = false; +global b32 Running = false; +global b32 WindowIsActive = false; char DLLName[] = "foldhaus.dll"; char WorkingDLLName[] = "foldhaus_temp.dll"; @@ -31,6 +30,317 @@ char DLLLockFileName[] = "lock.tmp"; window MainWindow; +// Utils + +internal gs_string +Win32DumpErrorAndPrepareMessageBoxString(gs_memory_arena* Arena, char* Format, ...) +{ + s32 Error = GetLastError(); + gs_string ErrorDump = PushString(Arena, 4096); + PrintF(&ErrorDump, + R"FOO(Win32 Error: %s\n +Error Code: %d\n + )FOO", + __FUNCTION__, + Error); + + va_list Args; + va_start(Args, Format); + PrintFArgsList(&ErrorDump, Format, Args); + va_end(Args); + + gs_data ErrorDumpData = StringToData(ErrorDump); + + HANDLE FileHandle = CreateFileA("./crashdump.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesWritten = 0; + if (WriteFile(FileHandle, ErrorDumpData.Memory, ErrorDumpData.Size, &BytesWritten, NULL)) + { + + } + CloseHandle(FileHandle); + } + + AppendPrintF(&ErrorDump, "Program will attempt to continue. See crashdump.txt for info"); + NullTerminate(&ErrorDump); + + return ErrorDump; +} + +DEBUG_PRINT(Win32DebugPrint) +{ + Assert(IsNullTerminated(Message)); + OutputDebugStringA(Message.Str); +} + +#define PrintLastError() PrintLastError_(__FILE__, __LINE__) +internal void +PrintLastError_(char* File, u32 Line) +{ + char DebugStringData[256]; + gs_string DebugString = MakeString(DebugStringData, 0, 256); + u32 Error = GetLastError(); + PrintF(&DebugString, "%s Line %d: Win32 Error %d\n\0", File, Line, Error); + OutputDebugStringA(DebugString.Str); +} + + +internal HINSTANCE +GetHInstance() +{ + HINSTANCE Result = GetModuleHandle(NULL); + if (Result == NULL) + { + PrintLastError(); + } + return Result; +} + +/////////////////////// +// +// Fie I/O + +internal u64 +Win32HighLowToU64(u32 LowPart, u32 HighPart) +{ + ULARGE_INTEGER Time = {}; + Time.LowPart = LowPart; + Time.HighPart = HighPart; + u64 Result = Time.QuadPart; + return Result; +} + +internal u64 +Win32FileTimeToU64(FILETIME FileTime) +{ + u64 Result = Win32HighLowToU64(FileTime.dwLowDateTime, FileTime.dwHighDateTime); + return Result; +} + +GET_FILE_INFO(Win32GetFileInfo) +{ + Assert(IsNullTerminated(Path)); + gs_file_info Result = {}; + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + Result.Path = Path; + Result.FileSize = (u64)GetFileSize(FileHandle, NULL) + 1; + FILETIME CreationTime, LastWriteTime; + if (GetFileTime(FileHandle, &CreationTime, (LPFILETIME)0, &LastWriteTime)) + { + Result.CreationTime = Win32FileTimeToU64(CreationTime); + Result.LastWriteTime = Win32FileTimeToU64(LastWriteTime); + } + else + { + PrintLastError(); + } + CloseHandle(FileHandle); + } + return Result; +} + +READ_ENTIRE_FILE(Win32ReadEntireFile) +{ + Assert(DataIsNonEmpty(Memory)); + Assert(IsNullTerminated(Path)); + + gs_file Result = {0}; + u32 Error = 0; + Result.FileInfo.Path = Path; + + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesRead = 0; + if (ReadFile(FileHandle, (LPVOID)Memory.Memory, Memory.Size - 1, (LPDWORD)(&BytesRead), NULL)) + { + Memory.Memory[Memory.Size - 1] = 0; + Result.Data = Memory; + + gs_string AbsolutePath = PushString(FileHandler.Transient, 512); + AbsolutePath.Length = GetFullPathNameA(Path.Str, AbsolutePath.Size, AbsolutePath.Str, NULL); + if (AbsolutePath.Length == 0) + { + Error = GetLastError(); + InvalidCodePath; + } + Result.FileInfo.AbsolutePath = AbsolutePath.ConstString; + } + else + { + // NOTE(Peter): If we get to this error case, it means that the file exists, + // and was successfully opened, but we can't read from it. I'm choosing to + // treat this as a legitimate error at this point. + gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to read file: %S", Path); + if (MessageBox(NULL, Message.Str, "Error", MB_OK) == IDOK) + { + PostQuitMessage(-1); + } + } + CloseHandle(FileHandle); + } + else + { + + } + + return Result; +} + +WRITE_ENTIRE_FILE(Win32WriteEntireFile) +{ + Assert(DataIsNonEmpty(Data)); + Assert(IsNullTerminated(Path)); + + bool Success = false; + HANDLE FileHandle = CreateFileA(Path.Str, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD BytesWritten = 0; + if (WriteFile(FileHandle, Data.Memory, Data.Size, &BytesWritten, NULL)) + { + Success = (BytesWritten == Data.Size); + } + else + { + gs_string Message = Win32DumpErrorAndPrepareMessageBoxString(FileHandler.Transient, "Attempting to write to file: %S", Path); + MessageBox(NULL, Message.Str, "Error", MB_OK); + } + CloseHandle(FileHandle); + } + else + { + + } + + return Success; +} + +internal FILETIME +GetFileLastWriteTime(char* Path) +{ + FILETIME Result = {}; + + WIN32_FIND_DATA FindData = {}; + HANDLE FileHandle = FindFirstFileA(Path, &FindData); + + if (FileHandle != INVALID_HANDLE_VALUE) + { + Result = FindData.ftLastWriteTime; + FindClose(FileHandle); + } + else + { + // TODO(Peter): :ErrorLogging + } + + return Result; +} + +struct temp_file_list_entry +{ + gs_file_info Info; + temp_file_list_entry* Next; +}; + +struct temp_file_list +{ + temp_file_list_entry* First; + temp_file_list_entry* Last; +}; + +internal u32 +Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags) +{ + u32 FilesCount = 0; + + u32 IndexOfLastSlash = FindLastFromSet(Path, "\\/"); + gs_const_string SearchPath = Substring(Path, 0, IndexOfLastSlash + 1); + + WIN32_FIND_DATA FindFileData; + HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData); + if (SearchHandle != INVALID_HANDLE_VALUE) + { + do + { + if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) + { + if (HasFlag(Flags, EnumerateDirectory_Recurse)) + { + gs_const_string SubDirName = ConstString(FindFileData.cFileName); + if (!StringsEqual(SubDirName, ConstString(".")) && + !StringsEqual(SubDirName, ConstString(".."))) + { + gs_string SubDirectoryPath = PushString(FileHandler.Transient, SearchPath.Length + SubDirName.Length + 3); + PrintF(&SubDirectoryPath, "%S%S/*\0", SearchPath, SubDirName); + FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString, Storage, Flags); + } + } + + if (HasFlag(Flags, EnumerateDirectory_IncludeDirectories)) + { + FilesCount += 1; + } + } + else + { + temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry); + File->Info.FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh); + File->Info.CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime); + File->Info.LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime); + File->Next = 0; + + u32 FileNameLength = CharArrayLength(FindFileData.cFileName); + + // NOTE(Peter): String Storage + // Storing the string in the final storage means we don't have to copy the string later, and all + // strings will be continguous in memory at the calling site, though they will be before the array + gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1); + PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName); + NullTerminate(&FileName); + File->Info.Path = FileName.ConstString; + + SLLPushOrInit(TempList->First, TempList->Last, File); + FilesCount += 1; + } + }while(FindNextFile(SearchHandle, &FindFileData)); + } + else + { + PrintLastError(); + } + + return FilesCount; +} + +ENUMERATE_DIRECTORY(Win32EnumerateDirectory) +{ + Assert(IsNullTerminated(Path)); + gs_file_info_array Result = {}; + + temp_file_list TempList = {}; + Result.MaxCount = Win32EnumerateDirectoryIntoTempList(FileHandler, &TempList, Path, Storage, Flags); + + Result.Values = PushArray(Storage, gs_file_info, Result.MaxCount); + for (temp_file_list_entry* FileAt = TempList.First; + FileAt != 0; + FileAt = FileAt->Next) + { + // NOTE(Peter): We don't copy the file name here because its already in Storage. + // See String Storage note above ^^ + Result.Values[Result.Count++] = FileAt->Info; + } + + return Result; +} + +/////////////////////// +// +// Job System + struct worker_thread_entry { b32 IsValid; @@ -39,11 +349,42 @@ struct worker_thread_entry struct worker_thread_info { - s32 ID; + gs_thread_context ThreadContext; HANDLE Handle; - work_queue* Queue; + gs_work_queue* Queue; }; +internal s32 +Win32GetThreadId() +{ + s32 Result = GetCurrentThreadId(); + return Result; +} + +internal gs_thread_context +Win32CreateThreadContext(gs_memory_arena* Transient = 0) +{ + gs_thread_context Result = {0}; + Result.ThreadInfo.ThreadID = Win32GetThreadId(); + Result.Allocator = CreateAllocator(Win32Alloc, Win32Free); + if (Transient != 0) + { + Result.Transient = Transient; + } + else + { + Result.Transient = (gs_memory_arena*)AllocatorAlloc(Result.Allocator, sizeof(gs_memory_arena)).Memory; + *Result.Transient = CreateMemoryArena(Result.Allocator); + } + Result.FileHandler = CreateFileHandler(Win32GetFileInfo, + Win32ReadEntireFile, + Win32WriteEntireFile, + Win32EnumerateDirectory, + Result.Transient); + + return Result; +} + PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) { #ifdef DEBUG @@ -51,18 +392,18 @@ PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) // overflowing the buffer if (Queue->JobsCount >= Queue->JobsMax) { - string DebugString = MakeString((char*)malloc(256), 256); + gs_string DebugString = MakeString((char*)malloc(256), 256); for (u32 i = 0; i < Queue->JobsCount; i++) { PrintF(&DebugString, "%d %s\n", i, Queue->Jobs[i].JobName); NullTerminate(&DebugString); - OutputDebugStringA(DebugString.Memory); + OutputDebugStringA(DebugString.Str); } } #endif Assert(Queue->JobsCount < Queue->JobsMax); - worker_thread_job* Job = Queue->Jobs + Queue->JobsCount; + gs_threaded_job* Job = Queue->Jobs + Queue->JobsCount; Job->WorkProc = WorkProc; Job->Data = Data; #ifdef DEBUG @@ -78,7 +419,7 @@ PUSH_WORK_ON_QUEUE(Win32PushWorkOnQueue) } internal worker_thread_entry -CompleteAndTakeNextJob(work_queue* Queue, worker_thread_entry Completed) +CompleteAndTakeNextJob(gs_work_queue* Queue, worker_thread_entry Completed, gs_thread_context Context) { if (Completed.IsValid) { @@ -106,16 +447,16 @@ CompleteAndTakeNextJob(work_queue* Queue, worker_thread_entry Completed) return Result; } -DO_QUEUE_WORK_UNTIL_DONE(Win32DoQueueWorkUntilDone) +COMPLETE_QUEUE_WORK(Win32DoQueueWorkUntilDone) { worker_thread_entry Entry = {}; Entry.IsValid = false; while (Queue->JobsCompleted < Queue->JobsCount) { - Entry = CompleteAndTakeNextJob(Queue, Entry); + Entry = CompleteAndTakeNextJob(Queue, Entry, Context); if (Entry.IsValid) { - Queue->Jobs[Entry.Index].WorkProc(ThreadID, Queue->Jobs[Entry.Index].Data); + Queue->Jobs[Entry.Index].WorkProc(Context, Queue->Jobs[Entry.Index].Data); } } } @@ -124,15 +465,17 @@ DWORD WINAPI WorkerThreadProc (LPVOID InputThreadInfo) { worker_thread_info* ThreadInfo = (worker_thread_info*)InputThreadInfo; + ThreadInfo->ThreadContext = Win32CreateThreadContext(); worker_thread_entry Entry = {}; Entry.IsValid = false; while (true) { - Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry); + ClearArena(ThreadInfo->ThreadContext.Transient); + Entry = CompleteAndTakeNextJob(ThreadInfo->Queue, Entry, ThreadInfo->ThreadContext); if (Entry.IsValid) { - ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ID, + ThreadInfo->Queue->Jobs[Entry.Index].WorkProc(ThreadInfo->ThreadContext, ThreadInfo->Queue->Jobs[Entry.Index].Data); } else @@ -188,13 +531,13 @@ PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle) { s32 NewDictionaryMax = Win32SocketHandleMax + SOCKET_DICTIONARY_GROW_SIZE; s32 NewDictionaryDataSize = NewDictionaryMax * sizeof(win32_socket); - u8* DictionaryMemory = Win32Alloc(NewDictionaryDataSize); + u8* DictionaryMemory = (u8*)Win32Alloc(NewDictionaryDataSize, 0); Assert(DictionaryMemory); win32_socket* NewValues = (win32_socket*)(DictionaryMemory); if (SocketValues) { - GSMemCopy(SocketValues, NewValues, sizeof(win32_socket) * NewDictionaryMax); + CopyMemoryTo(SocketValues, NewValues, sizeof(win32_socket) * NewDictionaryMax); Win32Free((u8*)SocketValues, sizeof(win32_socket) * Win32SocketHandleCount); } SocketValues = NewValues; @@ -512,7 +855,7 @@ internal void DebugPrint (char* Format, ...) { char Buffer[256]; - string StringBuffer = MakeString(Buffer, 256); + gs_string StringBuffer = MakeString(Buffer, 256); va_list Args; va_start(Args, Format); PrintF(&StringBuffer, Format, Args); @@ -521,7 +864,7 @@ DebugPrint (char* Format, ...) } internal void -SetApplicationLinks (context* Context, win32_dll_refresh DLL, work_queue* WorkQueue) +SetApplicationLinks (context* Context, win32_dll_refresh DLL, gs_work_queue* WorkQueue) { if (DLL.IsValid) { @@ -539,27 +882,22 @@ SetApplicationLinks (context* Context, win32_dll_refresh DLL, work_queue* WorkQu } } +// TODO(Peter): :Redundant remove internal u8* DEBUGAlloc(s32 ElementSize, s32 ElementCount) { - return Win32Alloc(ElementSize * ElementCount); + return (u8*)Win32Alloc(ElementSize * ElementCount, 0); } +// TODO(Peter): :Redundant remove internal u8* Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize) { - u8* NewMemory = Win32Alloc(NewSize); - GSMemCopy(Buf, NewMemory, OldSize); + u8* NewMemory = (u8*)Win32Alloc(NewSize, 0); + CopyMemoryTo(Buf, NewMemory, OldSize); return NewMemory; } -internal s32 -Win32GetThreadId() -{ - s32 Result = GetCurrentThreadId(); - return Result; -} - // NOTE(Peter): Only meant to take one of the values specified below: // IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, // IDC_ICON, IDC_NO, IDC_SIZE, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, @@ -577,6 +915,36 @@ Win32LoadSystemCursor(char* CursorIdentifier) return Result; } +internal void +PrintMatrix(m44 M, gs_thread_context Context) +{ + gs_string PrintString = AllocatorAllocString(Context.Allocator, 256); + PrintF(&PrintString, "[\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n]\n", + M.Array[0], M.Array[1], M.Array[2], M.Array[3], + M.Array[4], M.Array[5], M.Array[6], M.Array[7], + M.Array[8], M.Array[9], M.Array[10], M.Array[11], + M.Array[12], M.Array[13], M.Array[14], M.Array[15]); + NullTerminate(&PrintString); + OutputDebugStringA(PrintString.Str); +} + +v4 PerspectiveDivide(v4 A) +{ + v4 Result = {0, 0, 0, 1}; + Result.x = A.x / A.w; + Result.y = A.y / A.w; + Result.z = A.z / A.w; + Result.w = A.w; + return Result; +} +v4 ToScreen(v4 P, rect2 WindowBounds) +{ + v4 Result = P; + Result.x = RemapR32(P.x, -1, 1, WindowBounds.Min.x, WindowBounds.Max.x); + Result.y = RemapR32(P.y, -1, 1, WindowBounds.Min.y, WindowBounds.Max.y); + return Result; +} + int WINAPI WinMain ( HINSTANCE HInstance, @@ -585,6 +953,171 @@ WinMain ( INT NCmdShow ) { + gs_thread_context ThreadContext = Win32CreateThreadContext(); + + { + m44 Before = m44{ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15 + }; + m44 After = M44Transpose(Before); + OutputDebugStringA("Before:\n"); + PrintMatrix(Before, ThreadContext); + OutputDebugStringA("\n\n"); + OutputDebugStringA("After:\n"); + PrintMatrix(After, ThreadContext); + OutputDebugStringA("\n\n"); + + } + + { + v4 Before = {1, 2, 3, 4}; + m44 Transform = {}; + for (u32 i = 0; i < 16; i++) + { + Transform.Array[i] = i + 1; + } + v4 After = Transform * Before; + Assert(V4Mag(After - v4{30, 70, 110, 150}) < .00000001f); + } + + { // Translation + v4 Before = {0, 0, 0, 1}; + m44 Translation = M44Translation(v4{5, 5, 5, 0}); + v4 After = Translation * Before; + Assert((After == v4{5, 5, 5, 1})); + } + + { // X Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44RotationX(HalfPiR32); + m44 Backward = M44RotationX(-HalfPiR32); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Y Rotation + v4 Before = {5, 0, 0, 1}; + m44 Forward = M44RotationY(HalfPiR32); + m44 Backward = M44RotationY(-HalfPiR32); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Z Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44RotationZ(HalfPiR32); + m44 Backward = M44RotationZ(-HalfPiR32); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{-5, 0, 0, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{5, 0, 0, 1}) < .000001f); + } + + { // Combined X Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44Rotation(v3{HalfPiR32, 0, 0}); + m44 Backward = M44Rotation(v3{-HalfPiR32, 0, 0}); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Combined Y Rotation + v4 Before = {5, 0, 0, 1}; + m44 Forward = M44Rotation(v3{0, HalfPiR32, 0}); + m44 Backward = M44Rotation(v3{0, -HalfPiR32, 0}); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{0, 0, -5, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{0, 0, 5, 1}) < .000001f); + } + + { // Combined Z Rotation + v4 Before = {0, 5, 0, 1}; + m44 Forward = M44Rotation(v3{0, 0, HalfPiR32}); + m44 Backward = M44Rotation(v3{0, 0, -HalfPiR32}); + v4 After = Forward * Before; + Assert(V4Mag(After - v4{-5, 0, 0, 1}) < .000001f); + After = Backward * Before; + Assert(V4Mag(After - v4{5, 0, 0, 1}) < .000001f); + } + + { // Translate then Rotate + v4 Before = v4{0, 0, 0, 1}; + + m44 Translation = M44Translation(v4{5, 0, 0, 0}); + m44 Rotation = M44Rotation(v3{0, 0, HalfPiR32}); + m44 Composite = Rotation * Translation; + + v4 Inbetween = Translation * Before; + v4 After = Rotation * Inbetween; + Assert(V4Mag(After - v4{0, 5, 0, 1}) < .000001f); + + After = Composite * Before; + Assert(V4Mag(After - v4{0, 5, 0, 1}) < .000001f); + } + + { // Two translations + v4 Before = v4{0, 0, 0, 1}; + m44 TranslationA = M44Translation(v4{5, 0, 0, 0}); + m44 TranslationB = M44Translation(v4{0, 5, 0, 0}); + v4 After = TranslationB * TranslationA * Before; + Assert(V4Mag(After - v4{5, 5, 0, 1}) < .000001f); + } + + { // Perspective Transform + rect2 WindowBounds = rect2{ + v2{0, 0}, + v2{1440.0f, 768.0f}, + }; + + m44 Matrix = M44Translation(v4{0, 0, -200, 0}) * M44Rotation(v3{0, DegToRadR32(45), 0}); + m44 Projection = M44ProjectionPerspective(45, RectAspectRatio(WindowBounds), 0.1f, 500); + + r32 Rad = 25; + v4 P0 = Matrix * v4{-Rad, -Rad, 0, 1}; + v4 P1 = Matrix * v4{Rad, -Rad, 0, 1}; + v4 P2 = Matrix * v4{Rad, Rad, 0, 1}; + v4 P3 = Matrix * v4{-Rad, Rad, 0, 1}; + + v4 P0P = Projection * P0; + v4 P1P = Projection * P1; + v4 P2P = Projection * P2; + v4 P3P = Projection * P3; + + v4 P0PD = PerspectiveDivide(P0P); + v4 P1PD = PerspectiveDivide(P1P); + v4 P2PD = PerspectiveDivide(P2P); + v4 P3PD = PerspectiveDivide(P3P); + + v4 P0S = ToScreen(P0PD, WindowBounds); + P0S.w = 1; + + v4 P1S = ToScreen(P1PD, WindowBounds); + P1S.w = 1; + + v4 P2S = ToScreen(P2PD, WindowBounds); + P2S.w = 1; + + v4 P3S = ToScreen(P3PD, WindowBounds); + P3S.w = 1; + + Assert(V4Mag(P0S - v4{630.11401, 256.88202, 0.99930286, 1}) < 0.00001f); + Assert(V4Mag(P1S - v4{795.28662, 277.52859, 0.99948108, 1}) < 0.00001f); + Assert(V4Mag(P2S - v4{795.28662, 490.47144, 0.99948108, 1}) < 0.00001f); + Assert(V4Mag(P3S - v4{630.11401, 511.11798, 0.99930286, 1}) < 0.00001f); + + //PushRenderQuad2D(RenderBuffer, P0S.xy, P1S.xy, P2S.xy, P3S.xy, WhiteV4); + } + MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); Win32UpdateWindowDimension(&MainWindow); @@ -612,7 +1145,7 @@ WinMain ( input_queue InputQueue; { s32 InputQueueMemorySize = sizeof(input_entry) * 32; - u8* InputQueueMemory = Win32Alloc(InputQueueMemorySize); + u8* InputQueueMemory = (u8*)Win32Alloc(InputQueueMemorySize, 0); InputQueue = InitializeInputQueue(InputQueueMemory, InputQueueMemorySize); } @@ -625,31 +1158,31 @@ WinMain ( WorkerThreads = (worker_thread_info*)malloc(sizeof(worker_thread_info) * PLATFORM_THREAD_COUNT); } - work_queue WorkQueue = {}; - WorkQueue.SemaphoreHandle = CreateSemaphoreEx(0, 0, PLATFORM_THREAD_COUNT, 0, 0, SEMAPHORE_ALL_ACCESS); + HANDLE WorkQueueSemaphoreHandle = CreateSemaphoreEx(0, 0, PLATFORM_THREAD_COUNT, 0, 0, SEMAPHORE_ALL_ACCESS); + + gs_work_queue WorkQueue = {}; + WorkQueue.SemaphoreHandle = &WorkQueueSemaphoreHandle; WorkQueue.JobsMax = 512; - WorkQueue.Jobs = (worker_thread_job*)Win32Alloc(sizeof(worker_thread_job) * WorkQueue.JobsMax); + WorkQueue.Jobs = (gs_threaded_job*)Win32Alloc(sizeof(gs_threaded_job) * WorkQueue.JobsMax, 0); WorkQueue.NextJobIndex = 0; WorkQueue.PushWorkOnQueue = Win32PushWorkOnQueue; - WorkQueue.DoQueueWorkUntilDone = Win32DoQueueWorkUntilDone; + WorkQueue.CompleteQueueWork = Win32DoQueueWorkUntilDone; WorkQueue.ResetWorkQueue = ResetWorkQueue; - OutputDebugStringA("Hellooooo\n"); - for (s32 i = 0; i < PLATFORM_THREAD_COUNT; i++) { // ID = 0 is reserved for this thread - WorkerThreads[i].ID = i + 1; WorkerThreads[i].Queue = &WorkQueue; WorkerThreads[i].Handle = CreateThread(0, 0, &WorkerThreadProc, (void*)&WorkerThreads[i], 0, 0); } - s32 InitialMemorySize = Megabytes(64); - u8* InitialMemory = Win32Alloc(InitialMemorySize); + s32 InitialMemorySize = MB(64); + u8* InitialMemory = (u8*)Win32Alloc(InitialMemorySize, 0); context Context = {}; + Context.ThreadContext = ThreadContext; Context.MemorySize = InitialMemorySize; Context.MemoryBase = InitialMemory; - Context.WindowBounds = rect{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; Context.Mouse = {0}; // Cursors @@ -663,12 +1196,6 @@ WinMain ( // Platform functions Context.GeneralWorkQueue = &WorkQueue; - Context.PlatformMemory.Alloc = Win32Alloc; - Context.PlatformMemory.Free = Win32Free; - Context.PlatformMemory.Realloc = Win32Realloc; - Context.FileHandler.ReadEntireFile = Win32ReadEntireFile; - Context.FileHandler.WriteEntireFile = Win32WriteEntireFile; - Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle; Context.PlatformSetSocketOption = Win32SetSocketOption; @@ -692,8 +1219,8 @@ WinMain ( WSADATA WSAData; WSAStartup(MAKEWORD(2, 2), &WSAData); - s32 RenderMemorySize = Megabytes(12); - u8* RenderMemory = Win32Alloc(RenderMemorySize); + s32 RenderMemorySize = MB(12); + u8* RenderMemory = (u8*)Win32Alloc(RenderMemorySize, 0); render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory, RenderMemorySize, Win32Realloc); Context.InitializeApplication(Context); @@ -733,7 +1260,7 @@ WinMain ( HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse); } - Context.WindowBounds = rect{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; + Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}}; RenderBuffer.ViewWidth = MainWindow.Width; RenderBuffer.ViewHeight = MainWindow.Height; Context.DeltaTime = LastFrameSecondsElapsed; diff --git a/src/app/win32_foldhaus_dll.h b/src/app/win32_foldhaus_dll.h index 01b6bea..26071e6 100644 --- a/src/app/win32_foldhaus_dll.h +++ b/src/app/win32_foldhaus_dll.h @@ -22,15 +22,15 @@ struct win32_dll_refresh }; internal int -Win32DLLStringLength(char* String) +Win32DLLgs_stringLength(char* gs_string) { - char* At = String; + char* At = gs_string; while (*At) { At++; }; - return At - String; + return At - gs_string; } internal int -Win32DLLConcatStrings(int ALength, char* A, int BLength, char* B, int DestLength, char* Dest) +Win32DLLConcatgs_strings(int ALength, char* A, int BLength, char* B, int DestLength, char* Dest) { char* Dst = Dest; char* AAt = A; @@ -112,14 +112,14 @@ InitializeDLLHotReloading(char* SourceDLLName, ExePath.Path = (char*)VirtualAlloc(NULL, ExePath.PathLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); GetApplicationPath(&ExePath); - Win32DLLConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLStringLength(SourceDLLName), SourceDLLName, + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(SourceDLLName), SourceDLLName, MAX_PATH, Result.SourceDLLPath); - Win32DLLConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLStringLength(WorkingDLLFileName), WorkingDLLFileName, + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(WorkingDLLFileName), WorkingDLLFileName, MAX_PATH, Result.WorkingDLLPath); - Win32DLLConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32DLLStringLength(LockFileName), LockFileName, + Win32DLLConcatgs_strings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32DLLgs_stringLength(LockFileName), LockFileName, MAX_PATH, Result.LockFilePath); Win32Free((u8*)ExePath.Path, ExePath.PathLength); diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/win32_foldhaus_fileio.h index 46a109a..a45c25e 100644 --- a/src/app/win32_foldhaus_fileio.h +++ b/src/app/win32_foldhaus_fileio.h @@ -8,138 +8,5 @@ // #ifndef WIN32_FOLDHAUS_FILEIO_H -PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) -{ - platform_memory_result Result = {}; - Result.Error = PlatformMemory_NoError; - - Assert(IsNullTerminated(Path)); - HANDLE FileHandle = CreateFileA (Path.Memory, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD FileSize = GetFileSize(FileHandle, NULL); - Result.Data.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (Result.Data.Base) - { - Result.Data.Size = FileSize; - - s32 BytesRead = 0; - if (ReadFile(FileHandle, (LPVOID)Result.Data.Base, FileSize, (LPDWORD)(&BytesRead), NULL)) - { - - } - else - { - u32 Error = GetLastError(); - VirtualFree(Result.Data.Base, 0, MEM_RELEASE); - Result.Data.Size = 0; - Result.Error = PlatformMemory_UnknownError; - } - } - else - { - Result.Error = PlatformMemory_UnknownError; - } - CloseHandle(FileHandle); - } - else - { - Result.Error = PlatformMemory_FileNotFound; - } - - return Result; -} - -PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile) -{ - Assert(IsNullTerminated(Path)); - b32 Result = false; - HANDLE FileHandle = CreateFileA ( - Path.Memory, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD BytesWritten = 0; - - b32 WriteSuccess = WriteFile(FileHandle, - Contents, Size, - &BytesWritten, - NULL); - - if (WriteSuccess && BytesWritten == (u32)Size) - { - CloseHandle(FileHandle); - Result = true; - } - else - { - Result = false; - } - } - else - { - Result = false; - } - - return Result; -} - -internal FILETIME -GetFileLastWriteTime(char* Path) -{ - FILETIME Result = {}; - - WIN32_FIND_DATA FindData = {}; - HANDLE FileHandle = FindFirstFileA(Path, &FindData); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - Result = FindData.ftLastWriteTime; - FindClose(FileHandle); - } - else - { - // TODO(Peter): :ErrorLogging - } - - return Result; -} - -PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) -{ - b32 Result = false; - - PathBuffer->Memory[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->Memory; - OpenFileName.nMaxFile = PathBuffer->Max; - 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); - - PathBuffer->Length = CharArrayLength(PathBuffer->Memory); - - return Result; -} - #define WIN32_FOLDHAUS_FILEIO_H #endif // WIN32_FOLDHAUS_FILEIO_H \ No newline at end of file diff --git a/src/app/win32_foldhaus_memory.h b/src/app/win32_foldhaus_memory.h index c1c8c1c..100dd1a 100644 --- a/src/app/win32_foldhaus_memory.h +++ b/src/app/win32_foldhaus_memory.h @@ -8,17 +8,21 @@ // #ifndef WIN32_FOLDHAUS_MEMORY_H -PLATFORM_ALLOC(Win32Alloc) +ALLOCATOR_ALLOC(Win32Alloc) { u8* Result = (u8*)VirtualAlloc(NULL, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (ResultSize != 0) + { + *ResultSize = Size; + } return Result; } -PLATFORM_FREE(Win32Free) +ALLOCATOR_FREE(Win32Free) { - b32 Result = VirtualFree(Base, 0, MEM_RELEASE); + b32 Result = VirtualFree(Ptr, 0, MEM_RELEASE); if (!Result) { s32 Error = GetLastError(); @@ -26,18 +30,6 @@ PLATFORM_FREE(Win32Free) // to know what it could possibly be. InvalidCodePath; } - return Result; -} - -PLATFORM_REALLOC(Win32Realloc) -{ - u8* NewMemory = Win32Alloc(NewSize); - if (Base) - { - GSMemCopy(Base, NewMemory, OldSize); - Win32Free(Base, OldSize); - } - return NewMemory; } #define WIN32_FOLDHAUS_MEMORY_H diff --git a/src/gs_libs/gs_language.h b/src/gs_libs/gs_language.h index 9e12e25..b95b246 100644 --- a/src/gs_libs/gs_language.h +++ b/src/gs_libs/gs_language.h @@ -1,5 +1,6 @@ #ifndef GS_LANGUAGE_H +#if 0 #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) #include @@ -7,7 +8,7 @@ #include #elif defined(__APPLE__) && defined(__MAC__) -// TODO(Peter): +// TODO(Peter): #else // Std lib #include @@ -42,6 +43,8 @@ typedef long long int s64; typedef float r32; typedef double r64; +#endif + #ifndef _STDINT #define INT8_MIN (-128) @@ -268,15 +271,15 @@ GSLerpDef(r32) GSLerpDef(r64) #undef GSLerpDef -static r32 GSSqrt(r32 V) -{ +static r32 GSSqrt(r32 V) +{ r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; + return Result; } #if 0 // TODO(Peter): Need a way to split the input into two f32's to supply to _mm_sqrt_sd -static r64 GSSqrt(r64 V) -{ +static r64 GSSqrt(r64 V) +{ r64 Result = _mm_cvtsd_f64(_mm_sqrt_sd(_mm_set_sd(V))); return Result; } @@ -366,9 +369,9 @@ RoundToNearestPowerOfTwo (u8 V) { u8 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { @@ -387,9 +390,9 @@ RoundToNearestPowerOfTwo (u16 V) { u16 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { @@ -409,9 +412,9 @@ RoundToNearestPowerOfTwo (u32 V) { u32 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { @@ -432,9 +435,9 @@ RoundToNearestPowerOfTwo (u64 V) { u64 Result = 0; - if (IsPowerOfTwo(V)) - { - Result = V; + if (IsPowerOfTwo(V)) + { + Result = V; } else { diff --git a/src/gs_libs/gs_memory_arena.h b/src/gs_libs/gs_memory_arena.h index 119656c..4fbeb3b 100644 --- a/src/gs_libs/gs_memory_arena.h +++ b/src/gs_libs/gs_memory_arena.h @@ -314,7 +314,7 @@ PlatformRealloc(platform_memory_handler Platform, gs_mem_u8* Head, gs_mem_u32 Ol Result = PlatformAlloc(Platform, NewSize); if (Head != 0 && OldSize != 0) { - GSMemCopy(Head, Result, OldSize); + CopyMemoryTo(Head, Result, OldSize); PlatformFree(Platform, Head, OldSize); } } @@ -336,8 +336,6 @@ FreeMemoryArena(memory_arena* Arena) PlatformFree(Arena->PlatformMemory, (u8*)Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount); } -#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0)) - inline gs_mem_u32 GetAlignmentOffset (gs_mem_u64 Address, gs_mem_u32 Alignment, gs_mem_u32 AlignmentMask) { diff --git a/src/gs_libs/gs_string.h b/src/gs_libs/gs_string.h index 9b3f4c0..6b4efca 100644 --- a/src/gs_libs/gs_string.h +++ b/src/gs_libs/gs_string.h @@ -6,18 +6,6 @@ #ifndef GS_STRING_H #include -//////////////////////////////////////////////////////////////// -// String -//////////////////////////////////////////////////////////////// - -struct string -{ - char* Memory; - s32 Length; - // TODO(Peter): Max -> LengthMax for clarity - s32 Max; -}; - //////////////////////////////////////////////////////////////// // String Tokenizing //////////////////////////////////////////////////////////////// @@ -115,75 +103,14 @@ struct token { token_type Type; u32 LineNumber; - string Text; + gs_string Text; token* Next; // TODO(Peter): Get rid of this }; -//////////////////////////////////////////////////////////////// -// String Memory -//////////////////////////////////////////////////////////////// - -struct slot_header -{ - slot_header* Next; - s32 Size; -}; - -struct slot_arena -{ - u8* Memory; - s32 SlotSize; - s32 SlotCount; - slot_header* FreeList; -}; - -struct contiguous_slot_count_result -{ - s32 Count; - slot_header* LastContiguousSlot; -}; - - //////////////////////////////////////////////////////////////// // String Function Declarations //////////////////////////////////////////////////////////////// -// Utility -#if !defined GS_LANGUAGE_H - -static void GSZeroMemory (u8* Memory, s32 Size); -static s32 GSMin (s32 A, s32 B); -static s32 GSAbs (s32 A); -static float GSAbsF (float A); -static float GSPowF (float N, s32 Power); - -#endif - -// Setup -#define PushString(arena, size) MakeString(PushArray(arena, char, size), 0, size); - -static void InitializeEmptyString (string* String, char* Data, s32 DataSize); -static void InitializeString(string* String, char* Data, s32 Used, s32 Max); -static string InitializeEmptyString (char* Data, s32 DataSize); -static string InitializeString (char* Data, s32 Used, s32 Max); -static void ClearString (string* String); - -// Character Values -static bool IsSlash (char C); -static bool IsNewline (char C); -static bool IsWhitespace (char C); -static bool IsNewlineOrWhitespace (char C); -static bool IsAlpha (char C); -static bool IsUpper (char C); -static bool IsLower (char C); -static char ToUpper (char C); -static char ToLower (char C); -static bool IsNumeric (char C); -static bool IsNumericExtended (char C); -static bool IsAlphaNumeric (char C); -static bool IsOperator (char C); -static bool CharsEqualCaseInsensitive(char A, char B); - // Tokenizing static void EatChar(tokenizer* T); static b32 AtValidPosition(tokenizer Tokenizer); @@ -205,290 +132,6 @@ static s32 EatPastCharacter(tokenizer* T, char Char); static char* EatNumber(char* C); static s32 EatNumber(tokenizer* T); -// Char/Char Array -static u32 CharToUInt (char C); -static s32 CharArrayLength (char* CharArray); -static bool CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength); -static bool CharArraysEqualUnsafe (char* A, char* B); -static void ReverseCharArray (char* Array, s32 Length); -#define FirstIndexOfCharInCharArray(array, find) IndexOfChar(array, 0, find) -static s32 IndexOfChar (char* Array, s32 Start, char Find); -#define FastLastIndexOfCharInCharArray(array, len, find) FastReverseIndexOfChar(array, len, 0, find) -static s32 FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find); -#define LastIndexOfCharInCharArray(array, find) ReverseIndexOfChar(array, 0, find) -static s32 ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find); -static b32 CharArrayContains(char* Array, char* CheckFor); -static b32 CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength); - -// String - -#define MakeStringBuffer(name, size) char name##Backbuffer[(size)]; string name = MakeString(name##Backbuffer, size); - -static string MakeString (char* Array, s32 Length, s32 Max); -static string MakeString (char* Array, s32 Length); -static string MakeString (char* Array); -static string MakeStringLiteral(char* Data); - -static bool StringsEqual (string A, string B); -static bool StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength); -static bool StringEqualsCharArray (string String, char* CharArray); -static s32 FindFirstChar (string String, char C); - -static void SetStringToChar (string* Dest, char C, s32 Count); -static void SetStringToCharArray (string* Dest, char* Source); - -static void ConcatString (string Source, string* Dest); -static void ConcatString (string Source, s32 Length, string* Dest); -static void ConcatCharToString(string* Dest, char C); -static void ConcatCharArrayToString (char* Source, string* Dest); -static void ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest); - -static void CopyStringTo (string Source, string* Dest); -static s32 CopyStringToCharArray (string Source, char* Dest, s32 DestLength); -static void CopyCharArrayToString (char* Src, string* Dest); -static void CopyCharArrayToString (char* Src, s32 SrcLength, string* Dest); -static s32 CopyCharArray (char* Source, char* Dest, s32 DestLength); -static s32 CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset); - -static void InsertChar (string* String, char Char, s32 Index); -static void InsertStringAt (string* Dest, string Source, s32 At); -static void RemoveCharAt (string* String, s32 Index); - -static s32 IndexOfChar(string String, char C); -static s32 LastIndexOfChar(string String, char C); -static s32 SearchForCharInSet(string String, char* Set); -static s32 ReverseSearchForCharInSet(string String, char* Set); -static string Substring (string* String, s32 Start, s32 End); -static string Substring (string* String, s32 Start); - -static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsString(string SearchIn, string SearchFor); -static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength); -static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor); - -static void NullTerminate (string* String); - -static u32 HashString(string String); - -// Parsing -enum parse_type -{ - ParseType_UnsignedInt, - ParseType_SignedInt, - ParseType_Float, -}; - -struct parse_result -{ - parse_type Type; - char* OnePastLast; - union - { - u32 UnsignedIntValue; - s32 SignedIntValue; - r32 FloatValue; - }; -}; - -enum format_flags -{ - FormatFlags_LeftJustify = 0x1, - FormatFlags_ForceSign = 0x2, - FormatFlags_ForceSpaceInsteadOfSign = 0x4, - FormatFlags_ForceDecimalOrPrependOx = 0x8, - FormatFlags_PadWithZeroesInsteadOfSpaces = 0x16, -}; - -static parse_result ParseUnsignedInt (s32 Length, char* String); -static parse_result ParseSignedInt (s32 Length, char* String); -static parse_result ParseFloat (s32 Length, char* String); - -// PrintF - -#define StringExpand(str) (str).Length, (str).Memory -static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args); -static void PrintF(string* String, char* Format, ...); - -// Printing Helper Functions -static u32 GetU32NumberOfCharactersNeeded(u32 Value, u32 Base = 10); -static u32 GetS32NumberOfCharactersNeeded(u32 Value, s32 Base = 10); - -//////////////////////////////////////////////////////////////// -// String Memory Function Declarations -//////////////////////////////////////////////////////////////// - -static s32 CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize); -static bool SlotsAreContiguous (slot_header* First, slot_header* Second); -static contiguous_slot_count_result CountContiguousSlots (slot_header* First); -static slot_header* GetSlotAtOffset(slot_header* First, s32 Offset); -static slot_header* InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart); -static void AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage); -static string AllocStringFromStringArena (s32 Size, slot_arena* Storage); -static void FreeToStringArena (string* String, slot_arena* Storage); -static void ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage); - -//////////////////////////////////////////////////////////////// -// String Utility Functions -//////////////////////////////////////////////////////////////// - -#if !defined GS_LANGUAGE_H - -static void -GSZeroMemory (u8* Memory, s32 Size) -{ - for (int i = 0; i < Size; i++) { Memory[i] = 0; } -} - -static s32 -GSMin (s32 A, s32 B) -{ - return (A < B ? A : B); -} - -static s32 -GSAbs (s32 A) -{ - return (A < 0 ? -A : A); -} - -static float -GSAbs (float A) -{ - return (A < 0 ? -A : A); -} - -static float -GSPow (float N, s32 Power) -{ - float Result = N; - for(s32 i = 1; i < Power; i++) { Result *= N; } - return Result; -} - -#endif - -//////////////////////////////////////////////////////////////// -// Init and Clear -//////////////////////////////////////////////////////////////// - -static void -InitializeEmptyString (string* String, char* Data, s32 DataSize) -{ - String->Memory = Data; - String->Max = DataSize; - String->Length = 0; -} - -static void -InitializeString(string* String, char* Data, s32 Used, s32 Max) -{ - String->Memory = Data; - String->Max = Max; - String->Length = Used; -} - -static string -InitializeEmptyString (char* Data, s32 DataSize) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = DataSize; - Result.Length = 0; - return Result; -} - -static string -InitializeString (char* Data, s32 Used, s32 Max) -{ - string Result = {}; - Result.Memory = Data; - Result.Max = Max; - Result.Length = Used; - return Result; -} - -static void -ClearString (string* String) -{ - String->Memory = 0; - String->Max = 0; - String->Length = 0; -} - -//////////////////////////////////////////////////////////////// -// Char Value Types -//////////////////////////////////////////////////////////////// - -static bool IsNullTerminated(string Str) -{ - char LastChar = Str.Memory[Str.Length]; - bool Result = (LastChar == 0); - return Result; -} -static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } -static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } -static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t'); } -static bool IsNewlineOrWhitespace (char C) { return (IsWhitespace(C) || IsNewline(C)); } -static bool IsAlpha (char C) -{ - // TODO(Peter): support UTF8 chars - return ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || (C == '_'); -} -static bool IsUpper (char C) -{ - return ((C >= 'A') && (C <= 'Z')); -} -static bool IsLower (char C) -{ - return ((C >= 'a') && (C <= 'z')); -} -static bool IsNumeric (char C) -{ - return (C >= '0') && (C <= '9'); -} -static bool IsNumericExtended (char C) -{ - return (IsNumeric(C) || (C == '-') || (C == 'x') || (C == 'f') || (C == '.')); -} -static bool IsAlphaNumeric (char C) -{ - return IsAlpha(C) || IsNumeric(C); -} -static bool IsOperator (char C) -{ - return ((C == '+') || - (C == '-') || - (C == '*') || - (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 //////////////////////////////////////////////////////////////// @@ -669,1765 +312,7 @@ EatNumber(tokenizer* T) return T->At - TStart; } -//////////////////////////////////////////////////////////////// -// Basic Char Operations -//////////////////////////////////////////////////////////////// - -static u32 CharToUInt (char C) { - u32 Result = (C - '0'); - return Result; -} - -static s32 -CharArrayLength (char* Array) -{ - char* C = Array; - s32 Result = 0; - while (*C) - { - *C++; - Result++; - } - return Result; -} - -static s32 -NullTerminatedCharArrayLength (char* CharArray) -{ - char* Iter = CharArray; - while (*Iter) - { - *Iter++; - } - return (Iter - CharArray); -} - -static bool -CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength) -{ - bool Result = false; - if (ALength == BLength) - { - Result = true; - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < ALength; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - return Result; -} - -static bool -CharArraysEqualUnsafe (char* A, char* B) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - while(*AIter && *BIter) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - if((*AIter && !*BIter) || (!*AIter && *BIter)) - { - Result = false; - } - - return Result; -} - -static bool -CharArraysEqualUpToLength (char* A, char* B, s32 Length) -{ - bool Result = true; - - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < Length; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - return Result; -} - -static void -ReverseCharArray (char* Array, s32 Length) -{ - char* ForwardIter = Array; - char* BackwardIter = Array + Length - 1; - for (s32 i = 0; i < (Length / 2); i++) - { - char F = *ForwardIter; - char B = *BackwardIter; - *ForwardIter++ = B; - *BackwardIter-- = F; - } -} - -static s32 -IndexOfChar (char* Array, s32 After, char Find) -{ - s32 Result = -1; - - s32 Counter = After; - char* Iter = Array + After; - while (*Iter) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - Counter++; - *Iter++; - } - - return Result; -} - -static s32 -FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find) -{ - s32 Result = -1; - - s32 Counter = Length - OffsetFromEnd; - char* Iter = Array + Length - OffsetFromEnd; - for (int i = 0; i < (Length - OffsetFromEnd); i++) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - - *Iter--; - Counter--; - } - - return Result; -} - -static s32 -ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find) -{ - s32 StringLength = NullTerminatedCharArrayLength(Array); - return FastReverseIndexOfChar(Array, StringLength, OffsetFromEnd, Find); -} - -static b32 -CharArrayContains(char* Array, char* CheckFor) -{ - b32 Result = false; - - char* Src = Array; - while (*Src) - { - if (*Src == *CheckFor) - { - char* A = CheckFor; - char* B = Src; - while (*B && *A && *A == *B) - { - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - - return Result; -} - -static b32 -CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength) -{ - b32 Result = false; - - if (ArrayLength >= CheckForLength) - { - char* Src = Array; - for (s32 s = 0; s < ArrayLength; s++) - { - if (*Src == *CheckFor && (s + CheckForLength <= ArrayLength)) - { - char* A = CheckFor; - char* B = Src; - for (s32 d = 0; d < CheckForLength; d++) - { - if (*B != *A) { break; } - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - } - - return Result; -} - -//////////////////////////////////////////////////////////////// -// Basic String Operations -//////////////////////////////////////////////////////////////// - -static bool -StringsEqual (string A, string B) -{ - bool Result = false; - - if (A.Length == B.Length) - { - Result = true; - char* AIter = A.Memory; - char* BIter = B.Memory; - for (s32 i = 0; i < A.Length; i++) - { - if (*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static string -MakeString (char* Array, s32 Length, s32 Max) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Max; - return Result; -} - -static string -MakeString (char* Array, s32 Length) -{ - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Length; - return Result; -} - -static string -MakeString (char* Array) -{ - s32 Length = CharArrayLength (Array); - return MakeString(Array, Length); -} - -static string -MakeStringLiteral (char* String) -{ - string Result = {}; - Result.Memory = String; - Result.Max = CharArrayLength(String); - Result.Length = Result.Max; - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength) -{ - bool Result = false; - - if (CharArrayLength == String.Length) - { - Result = true; - - char* S = String.Memory; - char* C = CharArray; - for (s32 i = 0; i < String.Length; i++) - { - if (*C++ != *S++) - { - Result = false; - break; - } - } - } - - return Result; -} - -static bool -StringEqualsCharArray (string String, char* CharArray) -{ - s32 CLength = CharArrayLength(CharArray); - return StringEqualsCharArray(String, CharArray, CLength); -} - -static s32 -FindFirstChar (string String, char C) -{ - s32 Result = -1; - - char* Iter = String.Memory; - for (int i = 0; i < String.Length; i++) - { - if (*Iter++ == C) - { - Result = i; - break; - } - } - - return Result; -} - -static void -SetStringToChar (string* Dest, char C, s32 Count) -{ - Assert(Count <= Dest->Max); - - char* Iter = Dest->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = C; - } - Dest->Length = Count; -} - -static void -SetStringToCharArray (string* Dest, char* Source) -{ - Dest->Length = 0; - - char* Src = Source; - char* Dst = Dest->Memory; - while (*Src && Dest->Length < Dest->Max) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, string* Dest) -{ - Assert((Dest->Length + Source.Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Source.Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatString (string Source, s32 Length, string* Dest) -{ - Assert(Length <= Source.Length); - Assert((Dest->Length + Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharToString (string* Dest, char C) -{ - Assert(Dest->Length + 1 <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - *Dst = C; - Dest->Length++; -} - -static void -ConcatCharArrayToString (char* Source, string* Dest) -{ - Assert(CharArrayLength(Source) + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - while (Dest->Length < Dest->Max && - *Src) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - for (int i = 0; i < SourceLength && Dest->Length < Dest->Max; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } -} - -static void -CopyStringTo (string Source, string* Dest) -{ - char* Src = Source.Memory; - char* Dst = Dest->Memory; - s32 CopyLength = GSMin(Source.Length, Dest->Max); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - Dest->Length = Source.Length; -} - -static s32 -CopyStringToCharArray (string Source, char* Dest, s32 DestLength) -{ - char* Src = Source.Memory; - char* Dst = Dest; - s32 CopyLength = GSMin(Source.Length, DestLength); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - return CopyLength; -} - -static void -CopyCharArrayToString (char* Source, string* Dest) -{ - char* Src = Source; - char* Dst = Dest->Memory; - s32 Copied = 0; - while (*Src && Copied < Dest->Max) - { - *Dst++ = *Src++; - Copied++; - } - *Dst++ = 0; - Dest->Length = Copied; -} - -static void -CopyCharArrayToString (char* Source, s32 SourceLength, string* Dest) -{ - Assert(SourceLength <= Dest->Max); - - char* Src = Source; - char* Dst = Dest->Memory; - for (s32 i = 0; i < SourceLength; i++) - { - *Dst++ = *Src++; - } - *Dst++ = 0; - Dest->Length = SourceLength; -} - -static s32 -CopyCharArray (char* Source, char* Dest, s32 DestLength) -{ - char* Src = Source; - char* Dst = Dest; - s32 i = 0; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i; -} - -static s32 -CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset) -{ - Assert(Offset < DestLength); - - char* Src = Source; - char* Dst = Dest + Offset; - s32 i = Offset; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i - Offset; -} - -static void -InsertChar (string* String, char Char, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - Assert(String->Length < String->Max); - - char* Src = String->Memory + String->Length - 1; - char* Dst = Src + 1; - for (int i = String->Length - 1; i >= Index; i--) - { - *Dst-- = *Src--; - } - - *(String->Memory + Index) = Char; - String->Length++; -} - -static void -RemoveCharAt (string* String, s32 Index) -{ - Assert(Index >= 0 && Index < String->Max); - - char* Dst = String->Memory + Index; - char* Src = Dst + 1; - for (int i = Index; i < String->Length; i++) - { - *Dst++ = *Src++; - } - *Dst = 0; - String->Length--; -} - -static s32 -IndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = i; - break; - } - At++; - } - return Result; -} - -static s32 -LastIndexOfChar(string String, char C) -{ - s32 Result = -1; - char* At = String.Memory + String.Length - 1; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = String.Length - i; - break; - } - At--; - } - return Result; -} - -static s32 -SearchForCharInSet(string String, char* Set) -{ - s32 Index = -1; - - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - char* Needle = Set; - while (*Needle) - { - if (*At == *Needle) - { - Index = String.Length - i; - break; - } - - Needle++; - } - - if (Index >= 0) - { - break; - } - - At++; - } - - return Index; -} - -static s32 -ReverseSearchForCharInSet(string String, char* Set) -{ - s32 Index = -1; - - for (s32 i = String.Length - 1; i >= 0; i--) - { - char* Needle = Set; - while (*Needle) - { - if (String.Memory[i] == *Needle) - { - Index = i; - break; - } - - Needle++; - } - - if (Index >= 0) - { - break; - } - } - - return Index; -} - -static string -Substring (string String, s32 Start, s32 End) -{ - Assert(Start >= 0 && End > Start && End <= String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = End - Start; - return Result; -} - -static string -Substring (string String, s32 Start) -{ - Assert(Start >= 0 && Start < String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = String.Length - Start; - return Result; -} - -static b32 -StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (*InAt == *ForAt) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsString(string SearchIn, string SearchFor) -{ - return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static b32 -StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength) -{ - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (CharsEqualCaseInsensitive(*InAt, *ForAt)) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; -} - -static b32 -StringContainsStringCaseInsensitive(string SearchIn, string SearchFor) -{ - return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length); -} - -static void -NullTerminate (string* String) -{ - Assert(String->Length + 1 <= String->Max); - *(String->Memory + String->Length) = 0; - String->Length++; -} - -// http://www.cse.yorku.ca/~oz/hash.html -// djb2 hash -static u32 -HashString(string String) -{ - u32 Hash = 5381; - for (s32 i = 0; i < String.Length; i++) - { - Hash = ((Hash << 5) + Hash) + (u32)String.Memory[i]; /* hash * 33 + c */ - } - return Hash; -} - -static void -InsertStringAt (string* Dest, string Source, s32 At) -{ - Assert(At + Source.Length < Dest->Max); - Assert(At < Dest->Length); - - char* Src = Dest->Memory + Dest->Length; - char* Dst = Dest->Memory + Source.Length + Dest->Length; - for (s32 i = Dest->Length - 1; i >= At; i--) - { - *--Dst = *--Src; - } - - Src = Source.Memory; - Dst = Dest->Memory + At; - for (s32 j = 0; j < Source.Length; j++) - { - *Dst++ = *Src++; - } - - Dest->Length += Source.Length; -} - -//////////////////////////////////////////////////////////////// -// String Parsing -//////////////////////////////////////////////////////////////// - -// NOTE(Peter): parameters are all in order Length, String because -// that matches the order of C's printf %.*s format specifier. This -// is convenient because you can use StringExpand to parse a string -// struct -// :StringExpandNote -static parse_result -ParseUnsignedInt (s32 Length, char* String) -{ - Assert(IsNumeric(*String)); - parse_result Result = {}; - Result.Type = ParseType_UnsignedInt; - - char* Iter = String; - u32 ResultValue = 0; - for (s32 i = 0; i < Length; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - Result.UnsignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseUnsignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseUnsignedInt(End - Start, String); -} - -// :StringExpandNote -static parse_result -ParseSignedInt (s32 Length, char* String) -{ - Assert(Length > 0); - parse_result Result = {}; - Result.Type = ParseType_SignedInt; - - s32 Negative = 1; - s32 LengthRemaining = Length; - s32 ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - ResultValue *= Negative; - - Result.SignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseSignedIntUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseSignedInt(End - Start, String); -} - -// :StringExpandNote -static parse_result -ParseFloat (s32 Length, char* String) -{ - parse_result Result = {}; - Result.Type = ParseType_Float; - - s32 Negative = 1; - s32 LengthRemaining = Length; - float ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10); - } - else if (*Iter == '.' || *Iter == 0) - { - LengthRemaining -= i; - break; - } - } - - if (*Iter == '.') - { - *Iter++; - float AfterPoint = 0; - s32 PlacesAfterPoint = 0; - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - AfterPoint = (float)CharToUInt(*Iter++) + (AfterPoint * 10); - PlacesAfterPoint++; - } - else - { - break; - } - } - - AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint); - ResultValue += AfterPoint; - } - - ResultValue *= Negative; - - Result.FloatValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; -} - -static parse_result -ParseFloatUnsafe (char* String) -{ - char* Start = String; - char* End = EatNumber(String + 1); - return ParseFloat(End - Start, String); -} - -static s32 -UIntToString (u32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - char* Iter = String; - while (Remaining > 0 && (Iter - String) < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - } - s32 CharsCopied = Iter - String; - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) -{ - s32 Remaining = Int; - s32 CharsCopied = 0; - - char* Iter = String; - - bool Negative = Remaining < 0; - Remaining = GSAbs(Remaining); - - if (Remaining > 0) - { - while (Remaining > 0 && CharsCopied < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - CharsCopied++; - } - } - else if (Remaining == 0) - { - *Iter++ = '0'; - } - - if (Negative) - { - *Iter++ = '-'; - CharsCopied++; - } - - ReverseCharArray(String, CharsCopied); - return CharsCopied; -} - -static s32 -IntToString (s32 Int, char* String, s32 MaxLength, s32 Offset, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - char* StringStart = String + Offset; - s32 LengthWritten = IntToString(Int, StringStart, MaxLength - Offset); - return LengthWritten; -} - -static s32 -FloatToString(float Float, char *String, s32 MaxLength, s32 AfterPoint = 0, b32 FormatFlags = 0, s32 MinimumWidth = 0) -{ - s32 IPart = (s32)Float; - float FPart = GSAbs(Float - (float)IPart); - - s32 i = IntToString(IPart, String, MaxLength); - - if (AfterPoint > 1) - { - String[i++] = '.'; - - s32 FPartInt = FPart * GSPow(10, AfterPoint); - i += IntToString(FPartInt, String, MaxLength, i, 0, 0); - } - - return i; -} - -//////////////////////////////////////////////////////////////// -// PrintF -//////////////////////////////////////////////////////////////// - -static void -OutChar (string* String, char C) -{ - if (String->Length < String->Max) - { - String->Memory[String->Length] = C; - String->Length++; - } -} - -char OctalDigits[] = "01234567"; -char DecimalDigits[] = "0123456789"; -char HexDigits[] = "0123456789ABCDEF"; - -static void -U64ToASCII (string* String, u64 Value, s32 Base, char* Digits) -{ - u64 ValueRemaining = Value; - char* Start = String->Memory + String->Length; - do { - s32 DigitsIndex = ValueRemaining % Base; - char Digit = Digits[DigitsIndex]; - OutChar(String, Digit); - ValueRemaining /= Base; - }while (ValueRemaining); - char* End = String->Memory + String->Length; - - while (Start < End) - { - End--; - char Temp = *End; - *End = *Start; - *Start = Temp; - *Start++; - } -} - -static void -F64ToASCII (string* String, r64 Value, s32 Precision) -{ - if (Value < 0) - { - OutChar(String, '-'); - Value = -Value; - } - - u64 IntegerPart = (u64)Value; - Value -= IntegerPart; - - U64ToASCII(String, IntegerPart, 10, DecimalDigits); - - OutChar(String, '.'); - - for (s32 i = 0; i < Precision; i++) - { - Value *= 10.f; - u32 DecimalPlace = Value; - Value -= DecimalPlace; - OutChar(String, DecimalDigits[DecimalPlace]); - } -} - -internal s64 -ReadVarArgsSignedInteger (s32 Width, va_list* Args) -{ - s64 Result = 0; - switch (Width) - { - case 1: { Result = (s64)va_arg(*Args, s8); } break; - case 2: { Result = (s64)va_arg(*Args, s16); } break; - case 4: { Result = (s64)va_arg(*Args, s32); } break; - case 8: { Result = (s64)va_arg(*Args, s64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) -{ - u64 Result = 0; - switch (Width) - { - case 1: { Result = (u64)va_arg(*Args, u8); } break; - case 2: { Result = (u64)va_arg(*Args, u16); } break; - case 4: { Result = (u64)va_arg(*Args, u32); } break; - case 8: { Result = (u64)va_arg(*Args, u64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal r64 -ReadVarArgsFloat (s32 Width, va_list* Args) -{ - r64 Result = 0; - switch (Width) - { - case 4: { Result = (r64)va_arg(*Args, r64); } break; - case 8: { Result = (r64)va_arg(*Args, r64); } break; - InvalidDefaultCase; - } - return Result; -} - -internal s32 -PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) -{ - char* DestAt = Dest; - - char* FormatAt = Format; - while (*FormatAt) - { - if (FormatAt[0] != '%') - { - *DestAt++ = *FormatAt++; - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - *DestAt++ = '%'; - FormatAt += 2; - } - else - { - FormatAt++; - - // Flags - if (FormatAt[0] == '-') - { - FormatAt++; - } - else if (FormatAt[0] == '+') - { - FormatAt++; - } - else if (FormatAt[0] == ' ') - { - FormatAt++; - } - else if (FormatAt[0] == '#') - { - FormatAt++; - } - else if (FormatAt[0] == '0') - { - FormatAt++; - } - - // Width - b32 WidthSpecified = false; - s32 Width = 0; - - if (IsNumeric(FormatAt[0])) - { - WidthSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Width = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - WidthSpecified = true; - Width = va_arg(Args, s32); - Assert(Width >= 0); - FormatAt++; - } - - // Precision - b32 PrecisionSpecified = false; - s32 Precision = 0; - - if (FormatAt[0] == '.') - { - FormatAt++; - if (IsNumeric(FormatAt[0])) - { - PrecisionSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Precision = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - PrecisionSpecified = true; - Precision = va_arg(Args, s32); - Assert(Precision >= 0); - FormatAt++; - } - } - - // Length - b32 LengthSpecified = false; - s32 Length = 4; - - if (FormatAt[0] == 'h' && FormatAt[1] == 'h') - { - LengthSpecified = true; - LengthSpecified = 1; - FormatAt += 2; - } - else if (FormatAt[0] == 'h') - { - LengthSpecified = true; - LengthSpecified = 2; - FormatAt++; - } - else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt += 2; - } - else if (FormatAt[0] == 'l') - { - LengthSpecified = true; - LengthSpecified = 4; - FormatAt++; - } - else if (FormatAt[0] == 'j') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt++; - } - else if (FormatAt[0] == 'z') - { - FormatAt++; - } - else if (FormatAt[0] == 't') - { - FormatAt++; - } - else if (FormatAt[0] == 'L') - { - FormatAt++; - } - - // Format Specifier - s32 DestLengthRemaining = DestMax - (DestAt - Dest); - - char Temp[64]; - string TempDest = MakeString(Temp, 0, 64); - - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&TempDest, '-'); - SignedInt *= -1; - } - U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'u') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 8, OctalDigits); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 16, HexDigits); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - F64ToASCII(&TempDest, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, char); - OutChar(&TempDest, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CharArrayLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = GSMin(InsertStringLength, Precision); - } - InsertStringLength = GSMin(DestLengthRemaining, InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&TempDest, *InsertString++); - } - } - else if (FormatAt[0] == 'S') - { - string InsertString = va_arg(Args, string); - - for (s32 c = 0; c < InsertString.Length; c++) - { - OutChar(&TempDest, InsertString.Memory[c]); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - for (s32 i = 0; i < TempDest.Length; i++) - { - *DestAt++ = TempDest.Memory[i]; - } - - *FormatAt++; - } - } - - s32 FormattedLength = DestAt - Dest; - return FormattedLength; -} - -static void -PrintF (string* String, char* Format, ...) -{ - va_list Args; - va_start(Args, Format); - String->Length = 0; - String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); - va_end(Args); -} - -static void -AppendPrintF (string* String, char* Format, ...) -{ - va_list Args; - va_start(Args, Format); - String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); - va_end(Args); -} - -// Printing Helper Functions -static u32 -GetU32NumberOfCharactersNeeded(u32 Value, u32 Base) -{ - u32 Result = 0; - u32 ValueLeft = Value; - // NOTE(Peter): This is in a do while loop because even if the number is 0, - // it'll still take one character to display that. - do - { - Result += 1; - ValueLeft /= Base; - }while (ValueLeft > 0); - return Result; -} - -static u32 -GetS32NumberOfCharactersNeeded(s32 Value, s32 Base) -{ - u32 Result = 0; - s32 ValueLeft = Value; - if (Value < 0) - { - Result += 1; - ValueLeft = Value * -1; - } - // NOTE(Peter): This is in a do while loop because even if the number is 0, - // it'll still take one character to display that. - do - { - Result += 1; - ValueLeft /= Base; - }while (ValueLeft > 0); - return Result; -} - -//////////////////////////////////////////////////////////////// -// String Memory Function Definitions -//////////////////////////////////////////////////////////////// - -static s32 -CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize) -{ - s32 SlotCount = RequestedSize / SlotSize; - if (SlotCount * SlotSize < RequestedSize) - { - SlotCount += 1; - } - return SlotCount; -} - -static bool -SlotsAreContiguous (slot_header* First, slot_header* Second) -{ - bool Result = false; - u8* FirstSlotNextAddress = (u8*)First + First->Size; - u8* SecondAddress = (u8*)Second; - Result = FirstSlotNextAddress == SecondAddress; - return Result; -} - -static contiguous_slot_count_result -CountContiguousSlots (slot_header* First) -{ - Assert(First != 0); - - contiguous_slot_count_result Result = {}; - Result.Count = 1; - - slot_header* IterPrev = First; - slot_header* Iter = First->Next; - while (Iter && SlotsAreContiguous(IterPrev, Iter)) - { - Result.Count++; - IterPrev = Iter; - Iter = Iter->Next; - } - - Result.LastContiguousSlot = IterPrev; - return Result; -} - -static slot_header* -GetSlotAtOffset(slot_header* First, s32 Offset) -{ - slot_header* Iter = First; - s32 Count = 0; - while (Count < Offset && Iter) - { - Iter = Iter->Next; - Count++; - } - return Iter; -} - -static slot_header* -InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart) -{ - slot_header* List = ListStart; - if (NewSlot < List) - { - NewSlot->Next = List; - List = NewSlot; - } - else - { - slot_header* PrevIter = List; - slot_header* Iter = List->Next; - while (Iter && NewSlot > Iter) - { - PrevIter = Iter; - Iter = Iter->Next; - } - - Assert(PrevIter); - if (PrevIter) - { - PrevIter->Next = NewSlot; - } - - if (Iter) - { - NewSlot->Next = Iter; - } - } - return List; -} - -static void -AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage) -{ - s32 SlotCount = CalculateSlotCountFromSize(Size, Storage->SlotSize); - slot_header* Slot = Storage->FreeList; - slot_header* PrevSlot = 0; - while (Slot) - { - contiguous_slot_count_result ContiguousSlots = CountContiguousSlots(Slot); - if (ContiguousSlots.Count >= SlotCount) - { - slot_header* NextStartSlot = GetSlotAtOffset(Slot, SlotCount); - if (PrevSlot) - { - PrevSlot->Next = NextStartSlot; - } - else - { - Storage->FreeList = NextStartSlot; - } - break; - } - else - { - PrevSlot = Slot; - Slot = Slot->Next; - } - } - - if (Slot) - { - String->Memory = (char*)Slot; - GSZeroMemory((u8*)String->Memory, SlotCount * Storage->SlotSize); - String->Max = SlotCount * Storage->SlotSize; - String->Length = 0; - } -} - -static string -AllocStringFromStringArena (s32 Size, slot_arena* Storage) -{ - string Result = {0}; - AllocStringFromStringArena(&Result, Size, Storage); - return Result; -} - -static void -FreeToStringArena (string* String, slot_arena* Storage) -{ - u8* Base = (u8*)(String->Memory); - u8* End = Base + String->Max - 1; - u8* MemoryEnd = Storage->Memory + (Storage->SlotSize * Storage->SlotCount); - Assert((Base >= Storage->Memory) && (End < MemoryEnd)); - Assert((String->Max % Storage->SlotSize) == 0); - - s32 SizeReclaimed = 0; - slot_header* Slot = (slot_header*)Base; - while (SizeReclaimed < String->Max) - { - Slot->Size = Storage->SlotSize; - Storage->FreeList = InsertSlotIntoList(Slot, Storage->FreeList); - SizeReclaimed += Storage->SlotSize; - Slot = (slot_header*)(Base + SizeReclaimed); - } - - String->Memory = 0; - String->Length = 0; - String->Max = 0; -} - -static void -ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage) -{ - string NewString = AllocStringFromStringArena(NewSize, Storage); - CopyStringTo(*String, &NewString); - FreeToStringArena(String, Storage); - *String = NewString; -} - -#if defined(DEBUG) - -void DEBUGPrintChars (string* String, s32 Count) -{ - char* Iter = String->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = (char)('A' + i); - } - String->Length = Count; -} - -#ifdef DEBUG_GS_STRING - -#include - -static void -TestStrings() -{ - - slot_arena StringArena = {}; - - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Strings\n\n\n"); - - //////////////////////////////////////////////////////////////// - // Char Functions - - char ForwardArray[] = "Hello, Sailor"; - char BackwardArray[] = "roliaS ,olleH"; - TestClean(CharArraysEqual(ForwardArray, 13, ForwardArray, 13), "String Equality"); - TestClean(!CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "String Equality"); - - TestClean(IndexOfChar(ForwardArray, 0, ',') == 5, "Index Of Char"); - TestClean(IndexOfChar(ForwardArray, 5, 'l') == 10, "Index of Char (skipping first 5)"); - TestClean(FastReverseIndexOfChar(ForwardArray, 13, 0, 'o') == 11, "Fast Reverse Index Of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 0, 'o') == 11, "Reverse Index of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 3, 'o') == 4, "Reverse Index of Char (skipping last 3)"); - TestClean(LastIndexOfChar(ForwardArray, 'o') == 11, "Last Index of Char"); - - ReverseCharArray(ForwardArray, 13); - TestClean(CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "Reversing Char Array"); - - char UIntString[] = "1234"; - u32 UIntValue = 1234; - u32 ParsedUInt = ParseUnsignedInt(UIntString, 4); - TestClean((ParsedUInt == UIntValue), "String To U32"); - char StringifiedUInt[4] = {}; - UIntToString(UIntValue, StringifiedUInt, 4); - TestClean(CharArraysEqual(UIntString, 4, StringifiedUInt, 4), "U32 To String"); - - char IntString[] = "-1234"; - s32 IntValue = -1234; - s32 ParsedInt = ParseSignedInt(IntString, 5); - TestClean((ParsedInt == IntValue), "String To S32"); - char StringifiedInt[5] = {}; - IntToString(IntValue, StringifiedInt, 5); - TestClean(CharArraysEqual(IntString, 5, StringifiedInt, 5), "S32 to String"); - - char FloatString[] = "-1234.125"; - float FloatValue = -1234.125f; - float ParsedFloat = ParseFloat(FloatString, 8); - TestClean((ParsedFloat == FloatValue), "String To Float"); - char StringifiedFloat[10] = {}; - FloatToString(FloatValue, StringifiedFloat, 10, 3); - TestClean(CharArraysEqual(FloatString, 8, StringifiedFloat, 8), "Float To String"); - - - //////////////////////////////////////////////////////////////// - // - - StringArena.SlotSize = 256; - StringArena.SlotCount = 32; - StringArena.Memory = malloc(StringArena.SlotSize * StringArena.SlotCount); - slot_header* PrevSlotHeader = 0; - for (int i = StringArena.SlotCount - 1; i >= 0; i--) - { - u8* SlotBase = StringArena.Memory + (i * StringArena.SlotSize); - slot_header* SlotHeader = (slot_header*)SlotBase; - SlotHeader->Size = StringArena.SlotSize; - SlotHeader->Next = PrevSlotHeader; - - // TEST(peter): Should be true always, except on the first iteration, when there is no next slot - bool Contiguity = SlotsAreContiguous(SlotHeader, PrevSlotHeader); - TestClean((Contiguity || SlotHeader->Next == 0), "Contiguous Arenas"); - - PrevSlotHeader = SlotHeader; - } - StringArena.FreeList = PrevSlotHeader; - - // TEST(peter): Count Should equal StringArena.SlotCount - s32 ContiguousSlotsCountBefore = CountContiguousSlots(StringArena.FreeList).Count; - TestClean((ContiguousSlotsCountBefore == StringArena.SlotCount), "Contiguous Arenas"); - - // TEST(peter): Should be false - bool Contiguity = SlotsAreContiguous(StringArena.FreeList, StringArena.FreeList->Next->Next); - Contiguity = SlotsAreContiguous(StringArena.FreeList->Next->Next, StringArena.FreeList); - TestClean(!Contiguity, "Non Contiguous Arenas"); - - s32 Slots = CalculateSlotCountFromSize(10, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(256, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(345, 256); - TestClean(Slots == 2, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(1024, 256); - TestClean(Slots == 4, "Slot Sizing"); - - slot_header* HeaderTen = GetSlotAtOffset(StringArena.FreeList, 10); - slot_header* HeaderThree = GetSlotAtOffset(StringArena.FreeList, 3); - slot_header* HeaderFive = GetSlotAtOffset(StringArena.FreeList, 5); - - string StringA = AllocStringFromStringArena(10, &StringArena); - string StringB = AllocStringFromStringArena(345, &StringArena); - -#if 0 - // TEST(peter): Should TestClean - u8* RandomMemory = (u8*)malloc(256); - string RandomMemString = {}; - RandomMemString.Memory = (char*)RandomMemory; - RandomMemString.Max = 256; - FreeToStringArena(&RandomMemString, &StringArena); -#endif - FreeToStringArena(&StringA, &StringArena); - FreeToStringArena(&StringB, &StringArena); - // TEST(peter): After freeing both allocations, ContiguousSlotCountBefore and ContiguousSlotCountAfter should be equal - s32 ContiguousSlotCountAfter = CountContiguousSlots(StringArena.FreeList).Count; - TestClean(ContiguousSlotCountAfter == ContiguousSlotsCountBefore, "Add and REmove Slots from Arena"); - - // TEST(peter): Set up a free list where the first element is too small, so it has to traverse to find an appropriately - // sized block - // The slots will look list [256][used][256][256][256] etc.. - StringA = AllocStringFromStringArena(256, &StringArena); - StringB = AllocStringFromStringArena(256, &StringArena); - FreeToStringArena(&StringA, &StringArena); - u32 Contiguous = CountContiguousSlots(StringArena.FreeList).Count; // Should = 1; - string StringC = AllocStringFromStringArena(512, &StringArena); - slot_header* HeaderC = (slot_header*)(StringC.Memory); - - string ReallocTestString = AllocStringFromStringArena(256, &StringArena); - DEBUGPrintChars(&ReallocTestString, 24); - ReallocFromStringArena(&ReallocTestString, 512, &StringArena); - - - string TestString = AllocStringFromStringArena(10, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 20, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 10, &StringArena); - FreeToStringArena(&TestString, &StringArena); - - string EqualityStringA = AllocStringFromStringArena(345, &StringArena); - string EqualityStringB = AllocStringFromStringArena(415, &StringArena); - // Equality should succeed despite length differences - string EqualityStringC = AllocStringFromStringArena(256, &StringArena); - string EqualityStringD = AllocStringFromStringArena(256, &StringArena); // Equality should fail - string EqualityStringEmpty = {}; - - DEBUGPrintChars(&EqualityStringA, 24); - DEBUGPrintChars(&EqualityStringB, 24); - DEBUGPrintChars(&EqualityStringC, 24); - DEBUGPrintChars(&EqualityStringD, 12); - - bool ABEquality = StringsEqual(EqualityStringA, EqualityStringB); // Should Succeed - bool ACEquality = StringsEqual(EqualityStringA, EqualityStringC); // Should Succeed - bool ADEquality = StringsEqual(EqualityStringA, EqualityStringD); // Should Fail - bool AEEquality = StringsEqual(EqualityStringA, EqualityStringEmpty); // Should Fail - - TestClean(ABEquality, "String Equality"); - TestClean(ACEquality, "String Equality"); - TestClean(!ADEquality, "String Equality"); - TestClean(!AEEquality, "String Equality"); - - string CatStringA = AllocStringFromStringArena(256, &StringArena); - SetStringToCharArray(&CatStringA, "Hello "); - string CatStringB = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringB, "Sailor!"); - string CatStringResult = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringResult, "Hello Sailor!"); - ConcatString(&CatStringA, CatStringB); - TestClean(StringsEqual(CatStringA, CatStringResult), "Cat Strings"); - - s32 FirstSpaceIndex = FindFirstChar(CatStringA, ' '); - TestClean(FirstSpaceIndex == 5, "First Index"); - - SetStringToChar(&CatStringB, 'B', 5); - TestClean(StringEqualsCharArray(CatStringB, "BBBBB"), "SetStringToChar"); - - - DebugPrint("Results: Passed %d / %d\n\n\n", SuccessCount, TestCount); -} -#endif // DEBUG_GS_STRING - -#endif // DEBUG - #define GS_STRING_H -#endif // GS_STRING_H \ No newline at end of file +#endif // GS_STRING_H + + diff --git a/src/gs_libs/gs_string_builder.h b/src/gs_libs/gs_string_builder.h index e6e5df0..1102e97 100644 --- a/src/gs_libs/gs_string_builder.h +++ b/src/gs_libs/gs_string_builder.h @@ -37,7 +37,7 @@ GrowStringBuilder(string_builder* StringBuilder) { StringBuilder->Buffers = NewBuffer; StringBuilder->Head = NewBuffer; - } + } else { StringBuilder->Head->Next = NewBuffer; @@ -60,7 +60,7 @@ Write(string Text, string_builder* StringBuilder) // Copy what there is room for s32 SpaceAvailable = StringBuilder->Head->String.Max - StringBuilder->Head->String.Length; - ConcatString(TextLeft, GSMin(SpaceAvailable, TextLeft.Length), &StringBuilder->Head->String); + ConcatString(TextLeft, Min(SpaceAvailable, TextLeft.Length), &StringBuilder->Head->String); TextLeft.Memory += SpaceAvailable; TextLeft.Length -= SpaceAvailable; @@ -93,7 +93,7 @@ WriteStringBuilderToFile(string_builder StringBuilder, FILE* WriteFile) while (BufferAt) { string String = BufferAt->String; - fwrite(String.Memory, 1, String.Length, WriteFile); + fwrite(String.Str, 1, String.Length, WriteFile); BufferAt = BufferAt->Next; } } diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp new file mode 100644 index 0000000..d775d1e --- /dev/null +++ b/src/gs_libs/gs_types.cpp @@ -0,0 +1,3383 @@ +// +// File: gs_types.cpp +// Author: Peter Slattery +// Creation Date: 2020-04-18 +// +#ifndef GS_TYPES_CPP + +internal u32 +U32DivideRoundUp (u32 A, u32 B) +{ + r32 Result = (r32)A / (r32)B; + Result += .99999f; + return (u32)Result; +} + +inline bool XOR(bool A, bool B) { return (A == !B); } +inline bool XOR(b8 A, b8 B) { return (A == !B); } +inline bool XOR(b32 A, b32 B) { return (A == !B); } +inline bool XOR(b64 A, b64 B) { return (A == !B); } + +internal u32 +RoundUpToMultiple(u32 Value, u32 MultipleOf) +{ + u32 Result = Value; + if (MultipleOf != 0) + { + u32 Remainder = Value % MultipleOf; + Result = Value + (MultipleOf - Remainder); + } + return Result; +} +internal u32 +RoundUpToPow2U32(u32 Value) +{ + u32 Result = Value - 1; + Result |= Result >> 1; + Result |= Result >> 2; + Result |= Result >> 4; + Result |= Result >> 8; + Result |= Result >> 16; + Result++; + return Result; +} +internal u32 +RoundUpToPow2U64(u64 Value) +{ + u64 Result = Value - 1; + Result |= Result >> 1; + Result |= Result >> 2; + Result |= Result >> 4; + Result |= Result >> 8; + Result |= Result >> 16; + Result |= Result >> 32; + Result++; + return Result; +} +internal u64 +RoundUpTo64(u64 Value, u64 Alignment) +{ + Value += Alignment - 1; + Value -= Value % Alignment; + return Value; +} + +internal u8 +PowU8(u8 X, u32 Power) +{ + u8 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal u16 +PowU16(u16 X, u32 Power) +{ + u16 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal u32 +PowU32(u32 X, u32 Power) +{ + u32 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal u64 +PowU64(u64 X, u32 Power) +{ + u64 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal s8 +PowS8(s8 X, u32 Power) +{ + s8 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal s16 +PowS16(s16 X, u32 Power) +{ + s16 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal s32 +PowS32(s32 X, u32 Power) +{ + s32 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal s64 +PowS64(s64 X, u32 Power) +{ + s64 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal r32 +PowR32(r32 X, u32 Power) +{ + r32 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} +internal r64 +PowR64(r64 X, u32 Power) +{ + r64 Result = X; + for (u32 i = 1; i < Power; i++) { Result *= X; } + return Result; +} + +internal u8 +LerpU8(r32 T, u8 A, u8 B) +{ + return (u8)((A * (1.0f - T)) + (B * T)); +} +internal u16 +LerpU16(r32 T, u16 A, u16 B) +{ + return (u16)((A * (1.0f - T)) + (B * T)); +} +internal u32 +LerpU32(r32 T, u32 A, u32 B) +{ + return (u32)((A * (1.0f - T)) + (B * T)); +} +internal u64 +LerpU64(r32 T, u64 A, u64 B) +{ + return (u64)((A * (1.0f - T)) + (B * T)); +} +internal s8 +LerpS8(r32 T, s8 A, s8 B) +{ + return (s8)((A * (1.0f - T)) + (B * T)); +} +internal s16 +LerpS16(r32 T, s16 A, s16 B) +{ + return (s16)((A * (1.0f - T)) + (B * T)); +} +internal s32 +LerpS32(r32 T, s32 A, s32 B) +{ + return (s32)((A * (1.0f - T)) + (B * T)); +} +internal s64 +LerpS64(r32 T, s64 A, s64 B) +{ + return (s64)((A * (1.0f - T)) + (B * T)); +} +internal r32 +LerpR32(r32 T, r32 A, r32 B) +{ + return (r32)((A * (1.0f - T)) + (B * T)); +} +internal r64 +LerpR64(r32 T, r64 A, r64 B) +{ + return (r64)((A * (1.0f - T)) + (B * T)); +} + +internal u8 +UnlerpU8(u8 Value, u8 Min, u8 Max) +{ + return (u8)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal u16 +UnlerpU16(u16 Value, u16 Min, u16 Max) +{ + return (u16)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal u32 +UnlerpU32(u32 Value, u32 Min, u32 Max) +{ + return (u32)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal u64 +UnlerpU64(u64 Value, u64 Min, u64 Max) +{ + return (u64)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal s8 +UnlerpS8(s8 Value, s8 Min, s8 Max) +{ + return (s8)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal s16 +UnlerpS16(s16 Value, s16 Min, s16 Max) +{ + return (s16)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal s32 +UnlerpS32(s32 Value, s32 Min, s32 Max) +{ + return (s32)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal s64 +UnlerpS64(s64 Value, s64 Min, s64 Max) +{ + return (s64)((r64)(Value - Min) / (r64)(Max - Min)); +} +internal r32 +UnlerpR32(r32 Value, r32 Min, r32 Max) +{ + return (Value - Min) / (Max - Min); +} +internal r64 +UnlerpR64(r64 Value, r64 Min, r64 Max) +{ + return (Value - Min) / (Max - Min); +} + + +internal u8 +RemapU8(u8 Value, u8 OldMin, u8 OldMax, u8 NewMin, u8 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u8 Result = (u8)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal u16 +RemapU16(u16 Value, u16 OldMin, u16 OldMax, u16 NewMin, u16 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u16 Result = (u16)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal u32 +RemapU32(u32 Value, u32 OldMin, u32 OldMax, u32 NewMin, u32 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u32 Result = (u32)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal u64 +RemapU64(u64 Value, u64 OldMin, u64 OldMax, u64 NewMin, u64 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + u64 Result = (u64)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal s8 +RemapS8(s8 Value, s8 OldMin, s8 OldMax, s8 NewMin, s8 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s8 Result = (s8)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal s16 +RemapS16(s16 Value, s16 OldMin, s16 OldMax, s16 NewMin, s16 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s16 Result = (s16)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal s32 +RemapS32(s32 Value, s32 OldMin, s32 OldMax, s32 NewMin, s32 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s32 Result = (s32)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal s64 +RemapS64(s64 Value, s64 OldMin, s64 OldMax, s64 NewMin, s64 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + s64 Result = (s64)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal r32 +RemapR32(r32 Value, r32 OldMin, r32 OldMax, r32 NewMin, r32 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r32 Result = (r32)((A * (NewMax - NewMin)) + NewMin); + return Result; +} +internal r64 +RemapR64(r64 Value, r64 OldMin, r64 OldMax, r64 NewMin, r64 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 Result = (r64)((A * (NewMax - NewMin)) + NewMin); + return Result; +} + +internal u8 +RemapClampedU8(u8 Value, u8 OldMin, u8 OldMax, u8 NewMin, u8 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u8 Result = (u8)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal u16 +RemapClampedU16(u16 Value, u16 OldMin, u16 OldMax, u16 NewMin, u16 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u16 Result = (u16)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal u32 +RemapClampedU32(u32 Value, u32 OldMin, u32 OldMax, u32 NewMin, u32 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u32 Result = (u32)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal u64 +RemapClampedU64(u64 Value, u64 OldMin, u64 OldMax, u64 NewMin, u64 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + u64 Result = (u64)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal s8 +RemapClampedS8(s8 Value, s8 OldMin, s8 OldMax, s8 NewMin, s8 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s8 Result = (s8)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal s16 +RemapClampedS16(s16 Value, s16 OldMin, s16 OldMax, s16 NewMin, s16 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s16 Result = (s16)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal s32 +RemapClampedS32(s32 Value, s32 OldMin, s32 OldMax, s32 NewMin, s32 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s32 Result = (s32)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal s64 +RemapClampedS64(s64 Value, s64 OldMin, s64 OldMax, s64 NewMin, s64 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + s64 Result = (s64)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal r32 +RemapClampedR32(r32 Value, r32 OldMin, r32 OldMax, r32 NewMin, r32 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + r32 Result = (r32)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} +internal r64 +RemapClampedR64(r64 Value, r64 OldMin, r64 OldMax, r64 NewMin, r64 NewMax) +{ + r64 A = (r64)(Value - OldMin) / (r64)(OldMax - OldMin); + r64 AClamped = Clamp01(A); + r64 UnclampedResult = ((AClamped * (NewMax - NewMin)) + NewMin); + r64 Result = (r64)Clamp(NewMin, UnclampedResult, NewMax); + return Result; +} + +internal r32 +FloorR32(r32 V) +{ + return (r32)((s64)V); +} +internal r64 +FloorR64(r64 V) +{ + return (r64)((s64)V); +} + +internal r32 +FractR32(r32 V) +{ + return V - FloorR32(V); +} +internal r64 +FractR64(r64 V) +{ + return V - FloorR64(V); +} + +internal r32 +SqrtR32(r32 V) +{ + return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); +} +internal u32 +SqrtU32(u32 V) +{ + return sqrt(V); +} + +internal r32 +SinR32(r32 Rad) +{ + return sinf(Rad); +} +internal r64 +SinR64(r64 Rad) +{ + return sin(Rad); +} + +internal r32 +CosR32(r32 Rad) +{ + return cosf(Rad); +} +internal r64 +CosR64(r64 Rad) +{ + return cos(Rad); +} + +internal r32 +TanR32(r32 Rad) +{ + return tanf(Rad); +} +internal r64 +TanR64(r64 Rad) +{ + return tan(Rad); +} + +internal r32 +ASinR32(r32 Rad) +{ + return asinf(Rad); +} +internal r64 +ASinR64(r64 Rad) +{ + return asin(Rad); +} + +internal r32 +ACosR32(r32 Rad) +{ + return acosf(Rad); +} +internal r64 +ACosR64(r64 Rad) +{ + return acos(Rad); +} + +internal r32 +ATanR32(r32 Rad) +{ + return atanf(Rad); +} +internal r64 +ATanR64(r64 Rad) +{ + return atan(Rad); +} + +/////////////////////////// +// +// Vector + +internal v2 +V2MultiplyPairwise(v2 A, v2 B) +{ + v2 Result = v2{ + A.x * B.x, + A.y * B.y, + }; + return Result; +} + +internal v3 +V3MultiplyPairwise(v3 A, v3 B) +{ + v3 Result = v3{ + A.x * B.x, + A.y * B.y, + A.z * B.z, + }; + return Result; +} + +internal v4 +V4MultiplyPairwise(v4 A, v4 B) +{ + v4 Result = v4{ + A.x * B.x, + A.y * B.y, + A.z * B.z, + A.w * B.w, + }; + return Result; +} + + +v2 operator- (v2 A) { return { -A.x, -A.y }; } +v3 operator- (v3 A) { return { -A.x, -A.y, -A.z }; } +v4 operator- (v4 A) { return { -A.x, -A.y, -A.z, -A.w }; } + +v2 operator+ (v2 A, v2 B) { return { A.x + B.x, A.y + B.y }; } +v3 operator+ (v3 A, v3 B) { return { A.x + B.x, A.y + B.y, A.z + B.z }; } +v4 operator+ (v4 A, v4 B) { return { A.x + B.x, A.y + B.y, A.z + B.z, A.w + B.w }; } + +v2 operator- (v2 A, v2 B) { return { A.x - B.x, A.y - B.y }; } +v3 operator- (v3 A, v3 B) { return { A.x - B.x, A.y - B.y, A.z - B.z }; } +v4 operator- (v4 A, v4 B) { return { A.x - B.x, A.y - B.y, A.z - B.z, A.w - B.w }; } + +void operator+= (v2& A, v2 B) { A.x += B.x; A.y += B.y; } +void operator+= (v3& A, v3 B) { A.x += B.x; A.y += B.y; A.z += B.z; } +void operator+= (v4& A, v4 B) { A.x += B.x; A.y += B.y; A.z += B.z; A.w += B.w; } + +void operator-= (v2& A, v2 B) { A.x -= B.x; A.y -= B.y; } +void operator-= (v3& A, v3 B) { A.x -= B.x; A.y -= B.y; A.z -= B.z; } +void operator-= (v4& A, v4 B) { A.x -= B.x; A.y -= B.y; A.z -= B.z; A.w -= B.w; } + +v2 operator* (v2 A, r32 B) { return { A.x * B, A.y * B }; } +v3 operator* (v3 A, r32 B) { return { A.x * B, A.y * B, A.z * B }; } +v4 operator* (v4 A, r32 B) { return { A.x * B, A.y * B, A.z * B, A.w * B }; } + +v2 operator/ (v2 A, r32 B) { return { A.x / B, A.y / B }; } +v3 operator/ (v3 A, r32 B) { return { A.x / B, A.y / B, A.z / B }; } +v4 operator/ (v4 A, r32 B) { return { A.x / B, A.y / B, A.z / B, A.w / B }; } + +void operator*= (v2& A, r32 B) { A.x *= B; A.y *= B; } +void operator*= (v3& A, r32 B) { A.x *= B; A.y *= B; A.z *= B; } +void operator*= (v4& A, r32 B) { A.x *= B; A.y *= B; A.z *= B; A.w *= B; } + +void operator/= (v2& A, r32 B) { A.x /= B; A.y /= B; } +void operator/= (v3& A, r32 B) { A.x /= B; A.y /= B; A.z /= B; } +void operator/= (v4& A, r32 B) { A.x /= B; A.y /= B; A.z /= B; A.w /= B; } + +bool operator == (v2 A, v2 B) { return ((A.x == B.x) && (A.y == B.y)); } +bool operator == (v3 A, v3 B) { return ((A.x == B.x) && (A.y == B.y) && (A.z == B.z)); } +bool operator == (v4 A, v4 B) { return ((A.x == B.x) && (A.y == B.y) && (A.z == B.z) && (A.w == B.w)); } + +bool operator != (v2 A, v2 B) { return !((A.x == B.x) && (A.y == B.y)); } +bool operator != (v3 A, v3 B) { return !((A.x == B.x) && (A.y == B.y) && (A.z == B.z)); } +bool operator != (v4 A, v4 B) { return !((A.x == B.x) && (A.y == B.y) && (A.z == B.z) && (A.w == B.w)); } + +internal v3 ToV3(v2 V, r32 Z = 0) { return v3{V.x, V.y, Z}; } +internal v4 V2ToV4(v2 V, r32 Z = 0, r32 W = 0) { return v4{V.x, V.y, Z, W}; } +internal v4 ToV4_(v3 V, r32 W) +{ + return v4{V.x, V.y, V.z, W}; +} +#define ToV4Point(v) ToV4_((v), 1.0f) // all points have a w value of 1 +#define ToV4Vec(v) ToV4_((v), 0.0f) // all vectors have a w value of 0 ie. they cannot be translated + +internal r32 V2MagSquared(v2 V) { return ((V.x * V.x) + (V.y * V.y)); } +internal r32 V3MagSquared(v3 V) { return ((V.x * V.x) + (V.y * V.y) + (V.z * V.z)); } +internal r32 V4MagSquared(v4 V) { return ((V.x * V.x) + (V.y * V.y) + (V.z * V.z) + (V.w * V.w)); } + +internal r32 V2Mag(v2 V) { return SqrtR32((V.x * V.x) + (V.y * V.y)); } +internal r32 V3Mag(v3 V) { return SqrtR32((V.x * V.x) + (V.y * V.y) + (V.z * V.z)); } +internal r32 V4Mag(v4 V) { return SqrtR32((V.x * V.x) + (V.y * V.y) + (V.z * V.z) + (V.w * V.w)); } + +internal r32 V2DistanceSquared(v2 A, v2 B) { return V2MagSquared(A - B); } +internal r32 V3DistanceSquared(v3 A, v3 B) { return V3MagSquared(A - B); } +internal r32 V4DistanceSquared(v4 A, v4 B) { return V4MagSquared(A - B); } + +internal r32 V2Distance(v2 A, v2 B) { return V2Mag(A - B); } +internal r32 V3Distance(v3 A, v3 B) { return V3Mag(A - B); } +internal r32 V4Distance(v4 A, v4 B) { return V4Mag(A - B); } + +internal v2 +V2Normalize(v2 A) +{ + r32 Magnitude = V2Mag(A); + return A / Magnitude; +} +internal v3 +V3Normalize(v3 A) +{ + r32 Magnitude = V3Mag(A); + return A / Magnitude; +} +internal v4 +V4Normalize(v4 A) +{ + r32 Magnitude = V4Mag(A); + return A / Magnitude; +} + +internal r32 V2Dot(v2 A, v2 B) { return ((A.x * B.x) + (A.y * B.y)); } +internal r32 V3Dot(v3 A, v3 B) { return ((A.x * B.x) + (A.y * B.y) + (A.z * B.z)); } +internal r32 V4Dot(v4 A, v4 B) { return ((A.x * B.x) + (A.y * B.y) + (A.z * B.z) + (A.w * B.w)); } + +internal v2 V2PerpendicularCW(v2 A) { return v2{A.y, -A.x}; } +internal v2 V2PerpendicularCCW(v2 A) { return v2{A.y, A.x}; } + +internal r32 +V2Cross(v2 A, v2 B) +{ + return ((A.x * B.y) - (A.y * B.x)); +} + +internal v3 +V3Cross(v3 A, v3 B) +{ + v3 Result = { + (A.y * B.z) - (A.z * B.y), + (A.z * B.x) - (A.x * B.z), + (A.x * B.y) - (A.y * B.x) + }; + return Result; +} + +internal v4 +V4Cross(v4 A, v4 B) +{ + v4 Result = { + (A.y * B.z) - (A.z * B.y), + (A.z * B.x) - (A.x * B.z), + (A.x * B.y) - (A.y * B.x), + 0 + }; + return Result; +} + +internal v2 +V2Lerp(v2 A, v2 B, r32 T) +{ + v2 Result = v2{ + LerpR32(A.x, B.x, T), + LerpR32(A.y, B.y, T), + }; + return Result; +} + +internal v3 +V3Lerp(v3 A, v3 B, r32 T) +{ + v3 Result = v3{ + LerpR32(A.x, B.x, T), + LerpR32(A.y, B.y, T), + LerpR32(A.z, B.z, T), + }; + return Result; +} + +internal v4 +V4Lerp(v4 A, v4 B, r32 T) +{ + v4 Result = v4{ + LerpR32(A.x, B.x, T), + LerpR32(A.y, B.y, T), + LerpR32(A.z, B.z, T), + LerpR32(A.w, B.w, T), + }; + return Result; +} + +internal v2 +V2Remap(v2 P, v2 OldMin, v2 OldMax, v2 NewMin, v2 NewMax) +{ + v2 Result = {0}; + Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); + Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); + return Result; +} + +internal v3 +V3Remap(v3 P, v3 OldMin, v3 OldMax, v3 NewMin, v3 NewMax) +{ + v3 Result = {0}; + Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); + Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); + Result.z = RemapR32(P.z, OldMin.z, OldMax.z, NewMin.z, NewMax.z); + return Result; +} + +internal v4 +V4Remap(v4 P, v4 OldMin, v4 OldMax, v4 NewMin, v4 NewMax) +{ + v4 Result = {0}; + Result.x = RemapR32(P.x, OldMin.x, OldMax.x, NewMin.x, NewMax.x); + Result.y = RemapR32(P.y, OldMin.y, OldMax.y, NewMin.y, NewMax.y); + Result.z = RemapR32(P.z, OldMin.z, OldMax.z, NewMin.z, NewMax.z); + Result.w = RemapR32(P.w, OldMin.w, OldMax.w, NewMin.w, NewMax.w); + return Result; +} + +internal v4 +V4RemapAsV3(v4 P, v4 OldMin, v4 OldMax, v4 NewMin, v4 NewMax) +{ + v4 Result = {0}; + Result.xyz = V3Remap(P.xyz, OldMin.xyz, OldMax.xyz, NewMin.xyz, NewMax.xyz); + Result.w = P.w; + return Result; +} + +/////////////////////////// +// +// Ranges + +internal rect2 MakeRect2MinDim(v2 Min, v2 Dim) +{ + rect2 Result = {0}; + Result.Min = Min; + Result.Max = Min + Dim; + return Result; +} + +internal b32 ValueInRangeR32(r32 Min, r32 Max, r32 V) +{ + return ((V >= Min) && (V <= Max)); +} + +internal b32 ValueInRange1(range1 Range, r32 V) +{ + return ValueInRangeR32(Range.Min, Range.Max, V); +} +internal b32 ValueInRange2(range2 Range, v2 V) +{ + return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && + ValueInRangeR32(Range.Min.y, Range.Max.y, V.y)); +} +internal b32 ValueInRange3(range3 Range, v3 V) +{ + return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && + ValueInRangeR32(Range.Min.y, Range.Max.y, V.y) && + ValueInRangeR32(Range.Min.z, Range.Max.z, V.z)); +} +internal b32 ValueInRange4(range4 Range, v4 V) +{ + return (ValueInRangeR32(Range.Min.x, Range.Max.x, V.x) && + ValueInRangeR32(Range.Min.y, Range.Max.y, V.y) && + ValueInRangeR32(Range.Min.z, Range.Max.z, V.z) && + ValueInRangeR32(Range.Min.w, Range.Max.w, V.w)); +} + +#define PointIsInRect(range, point) ValueInRange2((range), (point)) + +internal r32 Range1SizeX(range1 Range) { return Range.Max - Range.Min; } +internal r32 Range2SizeX(range2 Range) { return Range.Max.x - Range.Min.x; } +internal r32 Range3SizeX(range3 Range) { return Range.Max.x - Range.Min.x; } +internal r32 Range4SizeX(range4 Range) { return Range.Max.x - Range.Min.x; } + +#define Rect2Width(r) Range2SizeX((r)) + +internal r32 Range2SizeY(range2 Range) { return Range.Max.y - Range.Min.y; } +internal r32 Range3SizeY(range3 Range) { return Range.Max.y - Range.Min.y; } +internal r32 Range4SizeY(range4 Range) { return Range.Max.y - Range.Min.y; } + +#define Rect2Height(r) Range2SizeY((r)) + +internal r32 Range3SizeZ(range3 Range) { return Range.Max.z - Range.Min.z; } +internal r32 Range4SizeZ(range4 Range) { return Range.Max.z - Range.Min.z; } + +internal r32 Range4SizeW(range4 Range) { return Range.Max.w - Range.Min.w; } + +internal r32 Range1Center(range1 Range) { return (Range.Max + Range.Min) / 2.0f; } +internal v2 Range2Center(range2 Range) { return (Range.Max + Range.Min) / 2.0f; } +internal v3 Range3Center(range3 Range) { return (Range.Max + Range.Min) / 2.0f; } +internal v4 Range4Center(range4 Range) { return (Range.Max + Range.Min) / 2.0f; } + +#define Rect2Center(r) Range2Center((r)) + +internal range1 Range1Offset(range1 Range, r32 Delta) { return range1{ Range.Min + Delta, Range.Max + Delta }; } +internal range2 Range2Offset(range2 Range, v2 Delta) { return range2{ Range.Min + Delta, Range.Max + Delta }; } +internal range3 Range3Offset(range3 Range, v3 Delta) { return range3{ Range.Min + Delta, Range.Max + Delta }; } +internal range4 Range4Offset(range4 Range, v4 Delta) { return range4{ Range.Min + Delta, Range.Max + Delta }; } + +#define Rect2Translate(r, d) Range2Offset((r), (d)) +#define Rect2TranslateX(r, dx) Range2Offset((r), v2{(dx), 0}) +#define Rect2TranslateY(r, dy) Range2Offset((r), v2{0, (dy)}) + +internal v2 RectTopLeft(rect2 Rect) +{ + return v2{ Rect.Min.x, Rect.Max.y }; +} +internal v2 RectTopRight(rect2 Rect) +{ + return Rect.Max; +} +internal v2 RectBottomLeft(rect2 Rect) +{ + return Rect.Min; +} +internal v2 RectBottomRight(rect2 Rect) +{ + return v2{ Rect.Max.x, Rect.Min.y }; +} + +internal r32 AspectRatio(r32 Width, r32 Height) { return Width / Height; } +internal r32 RectAspectRatio(rect2 Rect) { return Range2SizeX(Rect) / Range2SizeY(Rect); } + +internal void +RectHSplit(rect2 Rect, r32 YValue, rect2* Top, rect2* Bottom) +{ + r32 ClampedYValue = Clamp(Rect.Min.y, YValue, Rect.Max.y); + Top->Max = Rect.Max; + Top->Min = { Rect.Min.x, ClampedYValue }; + Bottom->Max = { Rect.Max.x, ClampedYValue }; + Bottom->Min = Rect.Min; +} +internal void +RectVSplit(rect2 Rect, r32 XValue, rect2* Left, rect2* Right) +{ + r32 ClampedXValue = Clamp(Rect.Min.x, XValue, Rect.Max.x); + Left->Max = { ClampedXValue, Rect.Max.y}; + Left->Min = Rect.Min; + Right->Max = Rect.Max; + Right->Min = { ClampedXValue, Rect.Min.y }; +} + +internal void +RectHSplitAtDistanceFromTop(rect2 Rect, r32 YDist, rect2* Top, rect2* Bottom) +{ + RectHSplit(Rect, Rect.Max.y - YDist, Top, Bottom); +} +internal void +RectHSplitAtDistanceFromBottom(rect2 Rect, r32 YDist, rect2* Top, rect2* Bottom) +{ + RectHSplit(Rect, Rect.Min.y + YDist, Top, Bottom); +} +internal void +RectVSplitAtDistanceFromRight(rect2 Rect, r32 XDist, rect2* Left, rect2* Right) +{ + RectVSplit(Rect, Rect.Max.x - XDist, Left, Right); +} +internal void +RectVSplitAtDistanceFromLeft(rect2 Rect, r32 XDist, rect2* Left, rect2* Right) +{ + RectVSplit(Rect, Rect.Min.x + XDist, Left, Right); +} +internal void +RectHSplitAtPercent(rect2 Rect, r32 YPercent, rect2* Top, rect2* Bottom) +{ + RectHSplit(Rect, LerpR32(YPercent, Rect.Min.y, Rect.Max.y), Top, Bottom); +} +internal void +RectVSplitAtPercent(rect2 Rect, r32 XPercent, rect2* Left, rect2* Right) +{ + RectVSplit(Rect, LerpR32(XPercent, Rect.Min.x, Rect.Max.x), Left, Right); +} + +internal rect2 +RectInset(rect2 Outer, v2 Amount) +{ + rect2 Result = { Outer.Min + Amount, Outer.Max - Amount }; + return Result; +} +internal rect2 +RectInset(rect2 Outer, r32 UniformAmount) +{ + return RectInset(Outer, v2{UniformAmount, UniformAmount}); +} + + +internal range1 +Range1Union(range1 A, range1 B) +{ + range1 Result = {}; + Result.Min = Max(A.Min, B.Min); + Result.Max = Min(A.Max, B.Max); + return Result; +} +#define Rect2Union(a,b) Range2Union((a), (b)) +internal range2 +Range2Union(range2 A, range2 B) +{ + range2 Result = {}; + Result.Min.x = Max(A.Min.x, B.Min.x); + Result.Min.y = Max(A.Min.y, B.Min.y); + Result.Max.x = Min(A.Max.x, B.Max.x); + Result.Max.y = Min(A.Max.y, B.Max.y); + return Result; +} +internal range3 +Range3Union(range3 A, range3 B) +{ + range3 Result = {}; + Result.Min.x = Max(A.Min.x, B.Min.x); + Result.Min.y = Max(A.Min.y, B.Min.y); + Result.Min.z = Max(A.Min.z, B.Min.z); + Result.Max.x = Min(A.Max.x, B.Max.x); + Result.Max.y = Min(A.Max.y, B.Max.y); + Result.Max.z = Min(A.Max.z, B.Max.z); + return Result; +} + +internal v2 +Rect2GetRectLocalPoint(rect2 Rect, v2 Point) +{ + v2 Result = Point - Rect.Min; + return Result; +} + +/////////////////////////// +// +// Ray + +internal v4 +RayGetPointAlong(v4 RayOrigin, v4 RayDirection, r32 T) +{ + v4 Result = RayOrigin + (RayDirection * T); + return Result; +} + +internal r32 +RayPlaneIntersectionDistance(v4 RayOrigin, v4 RayDirection, v4 PlanePoint, v4 PlaneNormal) +{ + r32 T = 0.0f; + float Denominator = V4Dot(PlaneNormal, RayDirection); + if (Abs(Denominator) > 0.00001f) + { + T = V4Dot(PlanePoint - RayDirection, PlaneNormal) / Denominator; + } + return T; +} + +internal v4 +GetRayPlaneIntersectionPoint(v4 RayOrigin, v4 RayDirection, v4 PlanePoint, v4 PlaneNormal) +{ + v4 Result = {0}; + r32 T = RayPlaneIntersectionDistance(RayOrigin, RayDirection, PlanePoint, PlaneNormal); + if (T >= 0) + { + Result = RayGetPointAlong(RayOrigin, RayDirection, T); + } + return Result; +} +internal v4 +GetRayPlaneIntersectionPoint(v4_ray Ray, v4 PlanePoint, v4 PlaneNormal) +{ + return GetRayPlaneIntersectionPoint(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal); +} + +internal bool +RayIntersectsPlane(v4 RayOrigin, v4 RayDirection, v4 PlanePoint, v4 PlaneNormal, v4* OutPoint) +{ + bool Result = false; + r32 T = RayPlaneIntersectionDistance(RayOrigin, RayDirection, PlanePoint, PlaneNormal); + if (T >= 0) + { + Result = true; + *OutPoint = RayGetPointAlong(RayOrigin, RayDirection, T); + } + return Result; +} +internal bool +RayIntersectsPlane(v4_ray Ray, v4 PlanePoint, v4 PlaneNormal, v4* OutPoint) +{ + return RayIntersectsPlane(Ray.Origin, Ray.Direction, PlanePoint, PlaneNormal, OutPoint); +} + +/////////////////////////// +// +// Matrices + +internal m44 +M44Identity() +{ + m44 M = {0}; + M.AXx = 1.0f; + M.AYy = 1.0f; + M.AZz = 1.0f; + M.Tw = 1.0f; + return M; +} + +internal m44 +M44Transpose(m44 M) +{ + m44 Result = {0}; + for (u32 Y = 0; Y < 4; Y++) + { + for (u32 X = 0; X < 4; X++) + { + Result.Array[(X * 4) + Y] = M.Array[(Y * 4) + X]; + } + } + return Result; +} + +// Matrix * Matrix + +m44 operator* (m44 L, m44 R) +{ + m44 M = {0}; + + // ci ic ci ic ci ic i ic + M.AXx = (L.AXx * R.AXx) + (L.AYx * R.AXy) + (L.AZx * R.AXz) + (L.Tx * R.AXw); + M.AXy = (L.AXy * R.AXx) + (L.AYy * R.AXy) + (L.AZy * R.AXz) + (L.Ty * R.AXw); + M.AXz = (L.AXz * R.AXx) + (L.AYz * R.AXy) + (L.AZz * R.AXz) + (L.Tz * R.AXw); + M.AXw = (L.AXw * R.AXx) + (L.AYw * R.AXy) + (L.AZw * R.AXz) + (L.Tw * R.AXw); + + M.AYx = (L.AXx * R.AYx) + (L.AYx * R.AYy) + (L.AZx * R.AYz) + (L.Tx * R.AYw); + M.AYy = (L.AXy * R.AYx) + (L.AYy * R.AYy) + (L.AZy * R.AYz) + (L.Ty * R.AYw); + M.AYz = (L.AXz * R.AYx) + (L.AYz * R.AYy) + (L.AZz * R.AYz) + (L.Tz * R.AYw); + M.AYz = (L.AXw * R.AYx) + (L.AYw * R.AYy) + (L.AZw * R.AYz) + (L.Tw * R.AYw); + + M.AZx = (L.AXx * R.AZx) + (L.AYx * R.AZy) + (L.AZx * R.AZz) + (L.Tx * R.AZw); + M.AZy = (L.AXy * R.AZx) + (L.AYy * R.AZy) + (L.AZy * R.AZz) + (L.Ty * R.AZw); + M.AZz = (L.AXz * R.AZx) + (L.AYz * R.AZy) + (L.AZz * R.AZz) + (L.Tz * R.AZw); + M.AZw = (L.AXw * R.AZx) + (L.AYw * R.AZy) + (L.AZw * R.AZz) + (L.Tw * R.AZw); + + M.Tx = (L.AXx * R.Tx) + (L.AYx * R.Ty) + (L.AZx * R.Tz) + (L.Tx * R.Tw); + M.Ty = (L.AXy * R.Tx) + (L.AYy * R.Ty) + (L.AZy * R.Tz) + (L.Ty * R.Tw); + M.Tz = (L.AXz * R.Tx) + (L.AYz * R.Ty) + (L.AZz * R.Tz) + (L.Tz * R.Tw); + M.Tw = (L.AXw * R.Tx) + (L.AYw * R.Ty) + (L.AZw * R.Tz) + (L.Tw * R.Tw); + + return M; +} + +// Matrix * Vector + +v4 operator* (m44 M, v4 V) +{ + v4 Result = {0}; + Result.x = (V.x * M.AXx) + (V.y * M.AYx) + (V.z * M.AZx) + (V.w * M.Tx); + Result.y = (V.x * M.AXy) + (V.y * M.AYy) + (V.z * M.AZy) + (V.w * M.Ty); + Result.z = (V.x * M.AXz) + (V.y * M.AYz) + (V.z * M.AZz) + (V.w * M.Tz); + Result.w = (V.x * M.AXw) + (V.y * M.AYw) + (V.z * M.AZw) + (V.w * M.Tw); + return Result; +} + +internal m44 +M44Translation(v4 Offset) +{ + m44 Result = M44Identity(); + Result.Tx = Offset.x; + Result.Ty = Offset.y; + Result.Tz = Offset.z; + return Result; +} + +internal m44 +M44RotationX(r32 Radians) +{ + r32 CosRad = CosR32(Radians); + r32 SinRad = SinR32(Radians); + m44 Result = M44Identity(); + Result.AYy = CosRad; + Result.AZy = SinRad; + Result.AYz = -SinRad; + Result.AZz = CosRad; + return Result; +} + +internal m44 +M44RotationY(r32 Radians) +{ + r32 CosRad = CosR32(Radians); + r32 SinRad = SinR32(Radians); + m44 Result = M44Identity(); + Result.AXx = CosRad; + Result.AZx = SinRad; + Result.AXz = -SinRad; + Result.AZz = CosRad; + return Result; +} + +internal m44 +M44RotationZ(r32 Radians) +{ + r32 CosRad = CosR32(Radians); + r32 SinRad = SinR32(Radians); + m44 Result = M44Identity(); + Result.AXx = CosRad; + Result.AYx = -SinRad; + Result.AXy = SinRad; + Result.AYy = CosRad; + return Result; +} + +internal m44 +M44Rotation(v3 Radians) +{ + r32 CosX = CosR32(Radians.x); + r32 SinX = SinR32(Radians.x); + r32 CosY = CosR32(Radians.y); + r32 SinY = SinR32(Radians.y); + r32 CosZ = CosR32(Radians.z); + r32 SinZ = SinR32(Radians.z); + + m44 Result = {0}; + Result.AXx = CosY * CosZ; + Result.AXy = -(SinX * SinY * CosZ) + (CosX * SinZ); + Result.AXz = -(CosX * SinY * CosZ) - (SinX * SinZ); + Result.AXw = 0; + + Result.AYx = -(SinZ * CosY); + Result.AYy = (SinX * SinY * SinZ) + (CosX * CosZ); + Result.AYz = (CosX * SinY * SinZ) - (SinX * CosZ); + Result.AYw = 0; + + Result.AZx = SinY; + Result.AZy = SinX * CosY; + Result.AZz = CosX * CosY; + Result.AZw = 0; + + Result.Tx = 0; + Result.Ty = 0; + Result.Tz = 0; + Result.Tw = 1; + + return Result; +} + +internal m44 +M44Scale(v3 Scale) +{ + m44 Result = M44Identity(); + Result.AXx = Scale.x; + Result.AYy = Scale.y; + Result.AZz = Scale.z; + return Result; +} + +internal m44 +M44ScaleUniform(r32 Scale) +{ + m44 Result = M44Identity(); + Result.AXx = Scale; + Result.AYy = Scale; + Result.AZz = Scale; + return Result; +} + +internal m44 +M44CoordinateFrame(v4 Forward, v4 Right, v4 Up) +{ + m44 Result = {0}; + Result.AXx = Right.x; + Result.AYx = Right.y; + Result.AZx = Right.z; + Result.Tx = Right.w; + + Result.AXy = Up.x; + Result.AYy = Up.y; + Result.AZy = Up.z; + Result.Ty = Up.w; + + Result.AXz = Forward.x; + Result.AYz = Forward.y; + Result.AZz = Forward.z; + Result.Tz = Forward.w; + + Result.Tw = 1.0f; + return Result; +} + +internal m44 +M44ModelMatrix(v4 Forward, v4 Right, v4 Up, v4 Position) +{ + m44 RotationMatrix = M44CoordinateFrame(Forward, Right, Up); + m44 PositionMatrix = M44Translation(-Position); + m44 ModelViewMatrix = PositionMatrix * RotationMatrix; + return ModelViewMatrix; +} + +internal m44 +M44ProjectionOrtho(r32 Width, r32 Height, r32 Near, r32 Far, r32 Right, r32 Left, r32 Top, r32 Bottom) +{ + m44 Result = {0}; + Result.AXx = 2.0f / Width; + Result.AYy = 2.0f / Height; + Result.AZz = 2.0f / (Near - Far); + Result.AXw = -(Right + Left) / (Right - Left); + Result.AYw = -(Top + Bottom) / (Top - Bottom); + Result.AZw = -(Far + Near) / (Far - Near); + Result.Tw = 1; + return Result; +} + +internal m44 +M44ProjectionOrtho(r32 Aspect, r32 Scale, r32 Near, r32 Far) +{ + m44 Result = {0}; + r32 Width = Scale * Aspect; + r32 Height = Scale; + r32 Right = Width / 2.0f; + r32 Left = -Right; + r32 Top = Height / 2.0f; + r32 Bottom = -Top; + Result = M44ProjectionOrtho(Width, Height, Near, Far, Right, Left, Top, Bottom); + return Result; +} + +internal m44 +M44ProjectionInterfaceOrtho(r32 Width, r32 Height, r32 Near, r32 Far) +{ + m44 Result = {0}; + r32 Aspect = Width / Height; + r32 Right = Width; + r32 Left = 0; + r32 Top = Height; + r32 Bottom = 0; + Result = M44ProjectionOrtho(Width, Height, Near, Far, Right, Left, Top, Bottom); + return Result; +} + +internal m44 +M44ProjectionPerspective(r32 FieldOfViewDegrees, r32 AspectRatio, r32 Near, r32 Far) +{ + m44 Result = M44Identity(); + + // The perspective divide step involves dividing x and y by -z + // Making Tz = -1 will make Tw of the result = -z + Result.Tw = 0; + Result.AZw = -1; + + // Remap z' from the range [near clip : far clip] to [0 : 1] + r32 ViewRange = Far - Near; + Result.AZz = -((Far + Near) / ViewRange); + Result.Tz = -(2 * Near * Far) / ViewRange; + + // Adjust for field of view - adjust the x' and y coordinates based + // on how + r32 FovBasedScale = TanR32(DegToRadR32(FieldOfViewDegrees / 2)); + r32 Top = Near * FovBasedScale; + r32 Bottom = -Top; + r32 Right = Top * AspectRatio; + r32 Left = -Right; + Result.AXx = (2 * Near) / (Right - Left); + Result.AZx = (Right + Left) / (Right - Left); + Result.AYy = (2 * Near) / (Top - Bottom); + Result.AZy = (Top + Bottom) / (Top - Bottom); + + return Result; +} + +internal m44 +M44LookAt(v4 Position, v4 Target) +{ + // NOTE(Peter): the camera usually points along the -z axis, hence + // Forward = a ray that points from the target back towards your position + v4 Forward = V4Normalize(Position - Target); + v4 Right = V4Normalize(V4Cross(v4{0, 1, 0, 0}, Forward)); + v4 Up = V4Normalize(V4Cross(Forward, Right)); + m44 Result = M44CoordinateFrame(Forward, Right, Up); + return Result; +} + +/////////////////////////// +// +// Strings + +internal gs_const_string ConstString(char* Data, u64 Length) { return gs_const_string{Data, Length}; } +internal gs_const_string ConstString(char* Data) { return gs_const_string{Data, CStringLength(Data)}; } +internal gs_string MakeString(char* Data, u64 Length, u64 Size) +{ + Assert(Length <= Size); + gs_string Result = {0}; + Result.Str = Data; + Result.Length = Length; + Result.Size = Size; + return Result; +} +internal gs_string MakeString(char* Data, u64 Length) +{ + return MakeString(Data, Length, Length); +} +internal gs_string MakeString(char* Data) +{ + u64 StringLength = CStringLength(Data); + return MakeString(Data, StringLength, StringLength); +} +internal gs_string MakeString(gs_const_string ConstString) +{ + return MakeString(ConstString.Str, ConstString.Length); +} + +internal gs_data StringToData(gs_const_string String) +{ + gs_data Result = gs_data{0}; + Result.Memory = (u8*)String.Str; + Result.Size = String.Length * sizeof(char); + return Result; +} +internal gs_data StringToData(gs_string String) +{ + return StringToData(String.ConstString); +} + +internal bool IsSlash(char C) { return ((C == '/') || (C == '\\')); } +internal bool IsUpper(char C) { return(('A' <= C) && (C <= 'Z')); } +internal bool IsLower(char C) { return(('a' <= C) && (C <= 'z')); } +internal bool IsWhitespace(char C) { return (C == ' ' || C == '\n' || C == '\r' || C == '\t' || C == '\f' || C == '\v'); } +internal bool IsNewline(char C) { return (C == '\n') || (C == '\r'); } +internal bool IsNewlineOrWhitespace (char C) { return IsNewline(C) || IsWhitespace(C); } +internal bool IsBase8(char C) { return (C >= '0' && C <= '7'); } +internal bool IsBase10(char C) { return (C >= '0' && C <= '9'); } +internal bool IsBase16(char C) { return (C >= '0' && C <= '9') || (C >= 'A' && C <= 'F'); } +internal bool IsNumericDecimal(char C) { return IsBase10(C) || (C == '.'); } +internal bool IsNumericExtended(char C) { return IsNumericDecimal(C) || (C == 'x') || (C == 'f') || (C == '-'); } +internal bool IsAlpha(char C) { return( (('a' <= C) && (C <= 'z')) || (('A' <= C) && (C <= 'Z')) || C == '_'); } +internal bool IsAlphaNumeric(char C) { return((('a' <= C) && (C <= 'z')) || (('A' <= C) && (C <= 'Z')) || (('0' <= C) && (C <= '9')) || C == '_'); } +internal bool IsOperator(char C) { + return ((C == '+') || (C == '-') || (C == '*') || (C == '/') || + (C == '=') || (C == '%') || (C == '<') || (C == '>')); +} + +internal char +ToUpper(char C) +{ + if ((C >= 'a') && (C <= 'z')) + { + C -= 'a' - 'A'; + } + return C; +} +internal char +ToLower(char C) +{ + if ((C >= 'A') && (C <= 'Z')) + { + C += 'a' - 'A'; + } + return C; +} +internal bool CharsEqualCaseInsensitive(char A, char B) { return ToLower(A) == ToLower(B); } + +internal u64 +CharArrayLength (char* CS) +{ + char* At = CS; + while (*At) { At++; } + return (u64)(At - CS); +} + +internal bool +IsNullTerminated(gs_const_string String) +{ + return (String.Str[String.Length - 1] != 0); +} +internal bool +IsNullTerminated(gs_string String) +{ + return IsNullTerminated(String.ConstString); +} + +internal char +GetChar(gs_const_string String, u64 I) +{ + char Result = 0; + if (I < String.Length) + { + Result = String.Str[I]; + } + return Result; +} +internal char +GetChar(gs_string String, u64 I) +{ + char Result = 0; + if (I < String.Length) + { + Result = String.Str[I]; + } + return Result; +} + +internal gs_const_string +GetStringPrefix(gs_const_string String, u64 Size) +{ + gs_const_string Result = String; + Result.Length = Min(Size, String.Length); + return Result; +} +internal gs_const_string +GetStringPostfix(gs_const_string String, u64 Size) +{ + gs_const_string Result = String; + u64 PostfixSize = Min(Size, String.Length); + Result.Str += (Result.Length - PostfixSize); + Result.Length = PostfixSize; + return Result; +} +internal gs_const_string +GetStringAfter(gs_const_string String, u64 Cut) +{ + gs_const_string Result = String; + u64 CutSize = Min(Cut, String.Length); + Result.Str += CutSize; + Result.Length -= CutSize; + return Result; +} +internal gs_string +GetStringAfter(gs_string String, u64 Cut) +{ + gs_string Result = {0}; + Result.ConstString = GetStringAfter(String.ConstString, Cut); + Result.Size = String.Size - Cut; + return Result; +} +internal gs_const_string +GetStringBefore(gs_const_string String, u64 Cut) +{ + gs_const_string Result = String; + Result.Length = Min(Cut, String.Length); + return Result; +} +internal gs_const_string +Substring(gs_const_string String, u64 First, u64 Last) +{ + gs_const_string Result = {0}; + Result.Str = String.Str + Min(First, String.Length); + Result.Length = Min(Last - First, String.Length); + return Result; +} +internal u64 +FindFirst(gs_const_string String, u64 StartIndex, char C) +{ + u64 Result = StartIndex; + for(; Result < String.Length && C != String.Str[Result]; Result++); + return Result; +} +internal u64 +FindFirst(gs_const_string String, char C) +{ + return FindFirst(String, 0, C); +} +internal u64 +FindLast(gs_const_string String, char C) +{ + s64 Result = String.Length - 1; + for(; Result >= 0 && C != String.Str[Result]; Result--); + return (u64)Result; +} +internal u64 +FindFirstFromSet(gs_const_string String, char* SetArray) +{ + gs_const_string Set = ConstString(SetArray); + u64 Result = String.Length - 1; + for(u64 At = 0; At < String.Length; At++) + { + char CharAt = String.Str[At]; + for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) + { + if (CharAt == Set.Str[SetAt]) + { + Result = At; + // NOTE(Peter): The alternative to this goto is a break in the inner loop + // followed by an if check in the outer loop, that must be evaluated + // every character you check. This is more efficient + goto find_last_from_set_complete; + } + } + } + find_last_from_set_complete: + return Result; +} + +internal u64 +FindLastFromSet(gs_const_string String, char* SetArray) +{ + gs_const_string Set = ConstString(SetArray); + u64 Result = String.Length - 1; + for(s64 At = Result; At >= 0; At--) + { + char CharAt = String.Str[At]; + for (u64 SetAt = 0; SetAt < Set.Length; SetAt++) + { + if (CharAt == Set.Str[SetAt]) + { + Result = (u64)At; + // NOTE(Peter): The alternative to this goto is a break in the inner loop + // followed by an if check in the outer loop, that must be evaluated + // every character you check. This is more efficient + goto find_first_from_set_complete; + } + } + } + find_first_from_set_complete: + return Result; +} + +internal bool +StringsEqualUpToLength(gs_const_string A, gs_const_string B, u64 Length) +{ + bool Result = false; + if (A.Length >= Length && B.Length >= Length) + { + Result = true; + Length = Min(Length, A.Length); + for (u64 i = 0; i < Length; i++) + { + if (A.Str[i] != B.Str[i]) + { + Result = false; + break; + } + } + } + return Result; +} +internal bool +StringsEqual(gs_const_string A, gs_const_string B) +{ + bool Result = false; + if (A.Length == B.Length) + { + Result = StringsEqualUpToLength(A, B, A.Length); + } + return Result; +} +internal bool +StringEqualsCharArray(gs_const_string A, char* B, u64 Length) +{ + gs_const_string BStr = ConstString(B, Length); + return StringsEqual(A, BStr); +} +internal bool +StringsEqualUpToLength(gs_string A, gs_string B, u64 Length) +{ + return StringsEqualUpToLength(A.ConstString, B.ConstString, Length); +} +internal bool +StringsEqual(gs_string A, gs_string B) +{ + return StringsEqual(A.ConstString, B.ConstString); +} +internal bool +StringEqualsCharArray(gs_string A, char* B, u64 Length) +{ + gs_string BStr = MakeString(B, Length); + return StringsEqual(A, BStr); +} + +internal u64 +StringSizeLeft(gs_string String) +{ + u64 Result = String.Size - String.Length; + return Result; +} + +internal void +ReverseStringInPlace(gs_string* String) +{ + char* Start = String->Str; + char* End = String->Str + String->Length; + while (Start < End) + { + End--; + char Temp = End[0]; + End[0] = Start[0]; + Start[0] = Temp; + Start++; + } +} + +internal gs_const_string +GetCharSetForBase(u64 Base) +{ + gs_const_string Result = {0}; + switch(Base) + { + case 8: { Result = Base8Chars; }break; + case 10: { Result = Base10Chars; }break; + case 16: { Result = Base16Chars; }break; + InvalidDefaultCase; + } + return Result; +} +internal u64 +CharToUInt(char C, gs_const_string CharSet) +{ + return (u64)FindFirst(CharSet, C); +} +internal u64 +CharToUInt(char C) +{ + return (u64)CharToUInt(C, Base10Chars); +} +internal u64 +CharToUInt(char C, u64 Base) +{ + return CharToUInt(C, GetCharSetForBase(Base)); +} + +internal u64 +ParseUInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0) +{ + u64 Result = 0; + gs_const_string CharSet = GetCharSetForBase(Base); + u64 i = 0; + for (; i < String.Length; i++) + { + u64 CharIndex = FindFirst(CharSet, String.Str[i]); + if (CharIndex < CharSet.Length) + { + Result = CharToUInt(String.Str[i], CharSet) + (Result * Base); + } + else + { + break; + } + } + if (ParsedLength != 0) + { + *ParsedLength = i; + } + return Result; +} +internal u64 +ParseUInt(u64 Length, char* String, u64 Base = 10, u64* ParsedLength = 0) +{ + return ParseUInt(ConstString(String, Length), Base, ParsedLength); +} +internal u64 +ParseUInt(char* String, u64 Base = 10, u64* ParsedLength = 0) +{ + return ParseUInt(LitString(String), Base, ParsedLength); +} + +internal s64 +ParseInt(gs_const_string String, u64 Base = 10, u64* ParsedLength = 0) +{ + s64 Result = 0; + u64 TempParsedLength = 0; + if (String.Str[0] == '-') + { + Result = -1 * (s64)ParseUInt(GetStringAfter(String, 1), Base, &TempParsedLength); + TempParsedLength += 1; + } + else + { + Result = (s64)ParseUInt(String, Base, &TempParsedLength); + } + if (ParsedLength != 0) + { + *ParsedLength = TempParsedLength; + } + return Result; +} +internal s64 +ParseInt(char* String, u64 Base = 10, u64* ParsedLength = 0) +{ + return ParseInt(LitString(String), Base, ParsedLength); +} + +internal r64 +ParseFloat(gs_const_string String, u64* ParsedLength = 0) +{ + + u64 DecimalIndex = FindFirst(String, '.'); + u64 TempParsedLength = 0; + u64 PlacesAfterPoint = 0; + + gs_const_string IntegerString = GetStringBefore(String, DecimalIndex); + gs_const_string DecimalString = GetStringAfter(String, DecimalIndex + 1); + + r32 Polarity = 1; + if (IntegerString.Str[0] == '-') + { + IntegerString = GetStringAfter(IntegerString, 1); + Polarity = -1; + } + r64 Result = (r64)ParseInt(IntegerString, 10, &TempParsedLength); + + if (TempParsedLength == IntegerString.Length) + { + r64 AfterPoint = (r64)ParseUInt(DecimalString, 10, &PlacesAfterPoint); + r64 Decimal = (AfterPoint / PowR64(10, PlacesAfterPoint)); + Result = Result + Decimal; + Result *= Polarity; + } + + if (ParsedLength != 0) + { + *ParsedLength = TempParsedLength + PlacesAfterPoint; + if (DecimalIndex < String.Length) { *ParsedLength += 1; } + } + return Result; +} +internal r64 +ParseFloat(char* String, u64* ParsedLength = 0) +{ + return ParseFloat(LitString(String), ParsedLength); +} + +internal u64 +AppendString(gs_string* Base, gs_const_string Appendix) +{ + u64 StartIndex = Base->Length; + u64 LengthAvailable = Base->Size - Base->Length; + u64 Written = 0; + for (; Written < Min(LengthAvailable, Appendix.Length); Written++) + { + Base->Str[StartIndex + Written] = Appendix.Str[Written]; + } + Base->Length += Written; + Assert(Base->Length <= Base->Size); + return Written; +} +internal u64 +AppendString(gs_string* Base, gs_string Appendix) +{ + return AppendString(Base, Appendix.ConstString); +} +internal void +NullTerminate(gs_string* String) +{ + if (String->Length < String->Size) + { + String->Str[String->Length] = 0; + } + else + { + String->Str[String->Length - 1] = 0; + } +} + +internal void +OutChar(gs_string* String, char C) +{ + if (String->Length < String->Size) + { + String->Str[String->Length++] = C; + } +} + +internal void +U64ToASCII(gs_string* String, u64 Value, u64 Base, gs_const_string Digits) +{ + u64 ValueRemaining = Value; + u64 At = 0; + do { + u64 Index = ValueRemaining % Base; + char Digit = Digits.Str[Index]; + OutChar(String, Digit); + ValueRemaining /= Base; + }while(ValueRemaining); + char* End = String->Str + String->Length; + ReverseStringInPlace(String); +} + +internal void +U64ToASCII(gs_string* String, u64 Value, u64 Base) +{ + U64ToASCII(String, Value, Base, GetCharSetForBase(Base)); +} + +internal void +R64ToASCII(gs_string* String, r64 Value, u64 Precision) +{ + if (Value < 0) + { + OutChar(String, '-'); + Value = Abs(Value); + } + u64 IntegerPart = (u64)Value; + // NOTE(Peter): If we don't use the inner string, when U64ToASCII reverses the characters + // it'll put the negative sign at the end. + gs_string IntegerString = GetStringAfter(*String, String->Length); + U64ToASCII(&IntegerString, IntegerPart, 10); + String->Length += IntegerString.Length; + Value -= IntegerPart; + if (Value > 0) + { + OutChar(String, '.'); + for (u64 i = 0; i < Precision; i++) + { + Value *= 10.0f; + u64 DecimalPlace = (u64)Value; + Value -= DecimalPlace; + OutChar(String, Base10Chars.Str[DecimalPlace]); + } + } +} + +internal s64 +ReadVarArgsSignedInteger (s32 Width, va_list* Args) +{ + s64 Result = 0; + switch (Width) + { + // NOTE(Peter): For Width lower than 4 bytes, the C++ spec specifies + // that it will get promoted to an int anyways + case 1: { Result = (s64)va_arg(*Args, s32); } break; + case 2: { Result = (s64)va_arg(*Args, s32); } break; + case 4: { Result = (s64)va_arg(*Args, s32); } break; + case 8: { Result = (s64)va_arg(*Args, s64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal r64 +ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) +{ + u64 Result = 0; + switch (Width) + { + // NOTE(Peter): For Width lower than 4 bytes, the C++ spec specifies + // that it will get promoted to an int anyways + case 1: { Result = (u64)va_arg(*Args, u32); } break; + case 2: { Result = (u64)va_arg(*Args, u32); } break; + case 4: { Result = (u64)va_arg(*Args, u32); } break; + case 8: { Result = (u64)va_arg(*Args, u64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal r64 +ReadVarArgsFloat (s32 Width, va_list* Args) +{ + r64 Result = 0; + switch (Width) + { + case 4: { Result = (r64)va_arg(*Args, r64); } break; + case 8: { Result = (r64)va_arg(*Args, r64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal s32 +PrintFArgsList (gs_string* String, char* Format, va_list Args) +{ + char* FormatAt = Format; + while (*FormatAt) + { + if (FormatAt[0] != '%') + { + if (FormatAt[0] == '\\') + { + FormatAt++; + Assert(IsBase8(FormatAt[0]) || // Octal Escape Sequences - \0 is in this set + FormatAt[0] == '\'' || + FormatAt[0] == '\"' || + FormatAt[0] == '\?' || + FormatAt[0] == '\\' || + FormatAt[0] == 'a' || // Audible Bell + FormatAt[0] == 'b' || // Backspace + FormatAt[0] == 'f' || // Form Feed - New Page + FormatAt[0] == 'n' || // Line Feed - New Line + FormatAt[0] == 'r' || // Carriage Return + FormatAt[0] == 't' || // Tab + FormatAt[0] == 'v'); // Vertical Tab + + // Not Handled (see cpp spec) \nnn \xnn \unnnn \Unnnnnnnn + Assert(FormatAt[0] != 'x' || FormatAt[0] != 'u' || FormatAt[0] != 'U'); + + if (IsBase8(FormatAt[0])) + { + // TODO(Peter): this should keep going until it finds a non-octal character code + // but the only one we really need is \0 atm so I'm just handling that one + Assert(FormatAt[0] == '0'); + OutChar(String, (char)0); + FormatAt++; + } + else + { + OutChar(String, *FormatAt++); + } + } + else + { + OutChar(String, *FormatAt++); + } + } + else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol + { + OutChar(String, '%'); + FormatAt += 2; + } + else + { + FormatAt++; + + // Flags + if (FormatAt[0] == '-') + { + FormatAt++; + } + else if (FormatAt[0] == '+') + { + FormatAt++; + } + else if (FormatAt[0] == ' ') + { + FormatAt++; + } + else if (FormatAt[0] == '#') + { + FormatAt++; + } + else if (FormatAt[0] == '0') + { + FormatAt++; + } + + // Width + b32 WidthSpecified = false; + s32 Width = 0; + + if (IsBase10(FormatAt[0])) + { + WidthSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Width = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + else if (FormatAt[0] == '*') + { + WidthSpecified = true; + Width = va_arg(Args, s32); + Assert(Width >= 0); + FormatAt++; + } + + // Precision + b32 PrecisionSpecified = false; + s32 Precision = 0; + + if (FormatAt[0] == '.') + { + FormatAt++; + if (IsBase10(FormatAt[0])) + { + + PrecisionSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Precision = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + else if (FormatAt[0] == '*') + { + PrecisionSpecified = true; + Precision = va_arg(Args, s32); + Assert(Precision >= 0); + FormatAt++; + } + } + + // Length + b32 LengthSpecified = false; + s32 Length = 4; + + if (FormatAt[0] == 'h' && FormatAt[1] == 'h') + { + LengthSpecified = true; + LengthSpecified = 1; + FormatAt += 2; + } + else if (FormatAt[0] == 'h') + { + LengthSpecified = true; + LengthSpecified = 2; + FormatAt++; + } + else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') + { + LengthSpecified = true; + LengthSpecified = 8; + FormatAt += 2; + } + else if (FormatAt[0] == 'l') + { + LengthSpecified = true; + LengthSpecified = 4; + FormatAt++; + } + else if (FormatAt[0] == 'j') + { + LengthSpecified = true; + LengthSpecified = 8; + FormatAt++; + } + else if (FormatAt[0] == 'z') + { + FormatAt++; + } + else if (FormatAt[0] == 't') + { + FormatAt++; + } + else if (FormatAt[0] == 'L') + { + FormatAt++; + } + + // Format Specifiers + gs_string StringRemaining = GetStringAfter(*String, String->Length); + Assert(StringRemaining.Length == 0); + if (FormatAt[0] == 'd' || FormatAt[0] == 'i') + { + s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); + if (SignedInt < 0) + { + OutChar(&StringRemaining, '-'); + SignedInt *= -1; + } + U64ToASCII(&StringRemaining, (u64)SignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'u') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'o') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 8, Base8Chars); + } + else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 16, Base16Chars); + } + else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') + { + r64 Float = ReadVarArgsFloat(Length, &Args); + s32 AfterPoint = 6; + if (PrecisionSpecified) + { + AfterPoint = Precision; + } + R64ToASCII(&StringRemaining, Float, AfterPoint); + } + else if (FormatAt[0] == 'c') + { + char InsertChar = va_arg(Args, s32); + OutChar(&StringRemaining, InsertChar); + } + else if (FormatAt[0] == 's') + { + char* InsertString = va_arg(Args, char*); + + s32 InsertStringLength = CStringLength(InsertString); + if (PrecisionSpecified) + { + InsertStringLength = Min(InsertStringLength, Precision); + } + InsertStringLength = Min(StringSizeLeft(StringRemaining), InsertStringLength); + + for (s32 c = 0; c < InsertStringLength; c++) + { + OutChar(&StringRemaining, InsertString[c]); + } + } + else if (FormatAt[0] == 'S') + { + gs_const_string InsertString = va_arg(Args, gs_const_string); + + for (s32 c = 0; c < InsertString.Length; c++) + { + OutChar(&StringRemaining, InsertString.Str[c]); + } + } + else if (FormatAt[0] == 'p') + { + // TODO(Peter): Pointer Address + } + else + { + // NOTE(Peter): Non-specifier character found + InvalidCodePath; + } + + String->Length += StringRemaining.Length; + FormatAt++; + } + } + + return String->Length; +} + +internal void +PrintF (gs_string* String, char* Format, ...) +{ + va_list Args; + va_start(Args, Format); + String->Length = 0; + PrintFArgsList(String, Format, Args); + va_end(Args); +} +internal void +PrintF (gs_string* String, const char* Format, ...) +{ + // NOTE(Peter): This variant is here for clang/gcc - C++ spec doesn't allow + // implicit conversion from a const char* (a static c string) to char*, so this + // version of the function just provides the conversion so the compiler will be quiet + // without removing the other implementation, which is more useful + va_list Args; + va_start(Args, Format); + String->Length = 0; + PrintFArgsList(String, (char*)Format, Args); + va_end(Args); +} + +internal void +AppendPrintF (gs_string* String, char* Format, ...) +{ + va_list Args; + va_start(Args, Format); + PrintFArgsList(String, Format, Args); + va_end(Args); +} +internal void +AppendPrintF (gs_string* String, const char* Format, ...) +{ + // NOTE(Peter): This variant is here for clang/gcc - C++ spec doesn't allow + // implicit conversion from a const char* (a static c string) to char*, so this + // version of the function just provides the conversion so the compiler will be quiet + // without removing the other implementation, which is more useful + va_list Args; + va_start(Args, Format); + PrintFArgsList(String, (char*)Format, Args); + va_end(Args); +} + +/////////////////////////// +// +// Memory + +internal gs_data +CreateData(u8* Memory, u64 Size) +{ + gs_data Result = {Memory, Size}; + return Result; +} +internal bool +DataIsNonEmpty(gs_data Data) +{ + return ((Data.Size > 0) && (Data.Memory != 0)); +} + +internal void* AllocatorAlloc_NoOp(u64 Size, u64* SizeResult) { + *SizeResult = 0; + return 0; +} +internal void AllocatorFree_NoOp(void* Base, u64 Size) { return; } + +internal gs_allocator +CreateAllocator_(allocator_allocate* Alloc, allocator_free* Free) +{ + if (Alloc == 0) + { + Alloc = AllocatorAlloc_NoOp; + } + if (Free == 0) + { + Free = AllocatorFree_NoOp; + } + gs_allocator Result = {0}; + Result.Alloc = Alloc; + Result.Free = Free; + return Result; +} +#define CreateAllocator(a, f) CreateAllocator_((allocator_allocate*)(a), (allocator_free*)(f)) + +internal gs_data +AllocatorAlloc_(gs_allocator Allocator, u64 Size, char* Location) +{ + // TODO(Peter): Memory Profiling with Location + u64 SizeResult = 0; + void* Memory = Allocator.Alloc(Size, &SizeResult); + return CreateData((u8*)Memory, SizeResult); +} +internal void +AllocatorFree_(gs_allocator Allocator, void* Base, u64 Size, char* Location) +{ + // TODO(Peter): Memory Profiling with Location + if (Base != 0 && Size != 0) + { + Allocator.Free(Base, Size); + } +} + +#define AllocatorAlloc(alloc,size) AllocatorAlloc_((alloc), (size), FileNameAndLineNumberString) +#define AllocatorAllocStruct(alloc, type) (type*)(AllocatorAlloc((alloc), sizeof(type)).Memory) +#define AllocatorAllocArray(alloc, type, count) (type*)(AllocatorAlloc((alloc), sizeof(type) * (count)).Memory) +#define AllocatorAllocString(alloc, size) gs_string{ AllocatorAllocArray((alloc), char, (size)), 0, (size) } +#define AllocatorFree(alloc,base,size) AllocatorFree_((alloc), (base), (size), FileNameAndLineNumberString) +#define AllocatorFreeArray(alloc,base,type,count) AllocatorFree_((alloc), (base), sizeof(type) * count, FileNameAndLineNumberString) +internal gs_memory_cursor +CreateMemoryCursor(u8* Base, u64 Size) +{ + gs_memory_cursor Result = {0}; + Result.Data.Memory = Base; + Result.Data.Size = Size; + return Result; +}; +internal gs_memory_cursor +CreateMemoryCursor(gs_data Data) +{ + return CreateMemoryCursor(Data.Memory, Data.Size); +} +internal gs_memory_cursor +CreateMemoryCursor(gs_allocator Allocator, u64 Size) +{ + gs_data Data = AllocatorAlloc(Allocator, Size); + return CreateMemoryCursor(Data); +} +internal bool +CursorHasRoom(gs_memory_cursor Cursor, u64 Size) +{ + bool Result = ((Cursor.Position + Size) <= Cursor.Data.Size); + return Result; +} +internal gs_data +PushSizeOnCursor_(gs_memory_cursor* Cursor, u64 Size, char* Location) +{ + gs_data Result = {0}; + if (CursorHasRoom(*Cursor, Size)) + { + Result.Memory = Cursor->Data.Memory + Cursor->Position; + Result.Size = Size; + Cursor->Position += Size; + } + return Result; +} + +#define PushSizeOnCursor(cursor,size) PushSizeOnCursor_((cursor), (size), FileNameAndLineNumberString) +#define PushStructOnCursor(cursor,type) (type*)PushSizeOnCursor_((cursor), sizeof(type), FileNameAndLineNumberString).Memory +#define PushArrayOnCursor(cursor,type,count) (type*)PushSizeOnCursor_((cursor), sizeof(type) * (count), FileNameAndLineNumberString).Memory + +internal void +PopSizeOnCursor(gs_memory_cursor* Cursor, u64 Size) +{ + if (Cursor->Position > Size) + { + Cursor->Position -= Size; + } + else + { + Cursor->Position = 0; + } +} +internal gs_data +AlignCursor(gs_memory_cursor* Cursor, u64 Alignment) +{ + u64 Position = RoundUpTo64(Cursor->Position, Alignment); + Position = Min(Position, Cursor->Data.Size); + u64 NewSize = Position - Cursor->Position; + return PushSizeOnCursor(Cursor, NewSize); +} +internal void +ClearCursor(gs_memory_cursor* Cursor) +{ + Cursor->Position = 0; +} + +internal void +FreeCursorListEntry(gs_allocator Allocator, gs_memory_cursor_list* CursorEntry) +{ + AllocatorFree(Allocator, CursorEntry, CursorEntry->Cursor.Data.Size + sizeof(gs_memory_cursor)); +} + +internal gs_memory_arena +CreateMemoryArena_(arena_type ArenaType, gs_allocator Allocator, u64 ChunkSize, u64 Alignment, gs_memory_arena* ParentArena) +{ + // we only want a parent arena if the type is Arena_SubArena + Assert(((ArenaType == Arena_BaseArena) && (ParentArena == 0)) || + ((ArenaType == Arena_SubArena) && (ParentArena != 0))); + + gs_memory_arena Arena = {}; + Arena.Type = ArenaType; + Arena.Allocator = Allocator; + Arena.Parent = ParentArena; + Arena.MemoryChunkSize = ChunkSize; + Arena.MemoryAlignment = Alignment; + return Arena; +} + +internal gs_memory_arena +CreateMemoryArena(gs_allocator Allocator, u64 ChunkSize = KB(32), u64 Alignment = Bytes(8)) +{ + return CreateMemoryArena_(Arena_BaseArena, Allocator, ChunkSize, Alignment, 0); +} +internal gs_memory_arena +CreateMemorySubArena(gs_memory_arena* Parent, u64 ChunkSize = KB(32), u64 Alignment = Bytes(8)) +{ + return CreateMemoryArena_(Arena_SubArena, Parent->Allocator, ChunkSize, Alignment, Parent); +} + +internal gs_data PushSize_(gs_memory_arena* Arena, u64 Size, char* Location); + +internal void +FreeCursorList(gs_memory_cursor_list* List, gs_allocator Allocator) +{ + gs_memory_cursor_list* CursorAt = List; + while (CursorAt != 0) + { + gs_memory_cursor_list* Prev = CursorAt->Prev; + FreeCursorListEntry(Allocator, CursorAt); + CursorAt = Prev; + } +} + +internal gs_memory_cursor_list* +MemoryArenaNewCursor(gs_memory_arena* Arena, u64 MinSize, char* Location) +{ + // Allocate enough spcae for the minimum size needed + sizeo for the cursor list + u64 AllocSize = Max(MinSize, Arena->MemoryChunkSize) + sizeof(gs_memory_cursor_list); + + gs_data Data = {0}; + switch (Arena->Type) + { + case Arena_SubArena: + { + Data = PushSize_(Arena->Parent, AllocSize, Location); + }break; + + case Arena_BaseArena: + { + Data = AllocatorAlloc_(Arena->Allocator, AllocSize, Location); + }break; + + InvalidDefaultCase; + } + + // Fit the memory cursor into the region allocated + Assert(MinSize + sizeof(gs_memory_cursor_list) <= Data.Size); + gs_memory_cursor_list* Result = (gs_memory_cursor_list*)Data.Memory; + u8* CursorMemoryStart = (u8*)(Result + 1); + u64 CursorMemorySize = Data.Size - sizeof(gs_memory_cursor_list); + Result->Cursor = CreateMemoryCursor(CursorMemoryStart, CursorMemorySize); + + Result->Prev = Arena->CursorList; + Result->Next = 0; + if (Arena->CursorList != 0) + { + Arena->CursorList->Next = Result; + } + Arena->CursorList = Result; + return Result; +} + +internal gs_data +PushSize_(gs_memory_arena* Arena, u64 Size, char* Location) +{ + gs_data Result = {0}; + if (Size > 0) + { + gs_memory_cursor_list* CursorEntry = Arena->CursorList; + if (CursorEntry == 0) + { + CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); + } + if (!CursorHasRoom(CursorEntry->Cursor, Size)) + { + while ((CursorEntry != 0) && !CursorHasRoom(CursorEntry->Cursor, Size)) + { + CursorEntry = CursorEntry->Next; + } + if (CursorEntry == 0) + { + CursorEntry = MemoryArenaNewCursor(Arena, Size, Location); + } + } + Assert(CursorEntry != 0); + Result = PushSizeOnCursor_(&CursorEntry->Cursor, Size, Location); + Assert(Result.Memory != 0); + + gs_data Alignment = AlignCursor(&CursorEntry->Cursor, Arena->MemoryAlignment); + Result.Size += Alignment.Size; + } + + // TODO(Peter): @Cleanup @Efficiency + // There is a case I want to handle at some point: + // You have a Cursor that is empty, but the size you want to allocate is bigger + // than the cursor. So you create a new cursor, of the exact size you need, + // immediately fill it up, and push it onto the head of the cursor list. Now, + // the list looks like this: + // [root] [cursor] ... [empty cursor] [full cursor] [new, empty cursor] + // and you'll never use the memory in 'empty cursor' + // What I'd like to do is, when you fill up a cursor, it gets pushed back until + // the next cursor is more full + // NOTE: Thought on this tho - you don't want this behavior in a scratch arena + // where usage across frames could change drastically. This matters way more in + // a permanent storage (i think) + return Result; +} + +internal void +PopSize(gs_memory_arena* Arena, u64 Size) +{ + gs_allocator Allocator = Arena->Allocator; + gs_memory_cursor_list* CursorEntry = Arena->CursorList; + for (gs_memory_cursor_list* Prev = 0; + CursorEntry != 0 && Size != 0; + CursorEntry = Prev) + { + Prev = CursorEntry->Prev; + if (Size >= CursorEntry->Cursor.Position) + { + Size -= CursorEntry->Cursor.Position; + FreeCursorListEntry(Allocator, CursorEntry); + } + else + { + PopSizeOnCursor(&CursorEntry->Cursor, Size); + break; + } + } + Arena->CursorList = CursorEntry; +} +internal void +FreeMemoryArena(gs_memory_arena* Arena) +{ + gs_allocator Allocator = Arena->Allocator; + gs_memory_cursor_list* CursorEntry = Arena->CursorList; + for (gs_memory_cursor_list* Prev = 0; + CursorEntry != 0; + CursorEntry = Prev) + { + Prev = CursorEntry->Prev; + if (CursorEntry != 0) + { + FreeCursorListEntry(Allocator, CursorEntry); + } + } +} + +#define PushSizeToData(arena, size) PushSize_((arena), (size), FileNameAndLineNumberString) +#define PushSize(arena, size) PushSize_((arena), (size), FileNameAndLineNumberString).Memory +#define PushStruct(arena, type) (type*)(PushSize_((arena), sizeof(type), FileNameAndLineNumberString).Memory) +#define PushArray(arena, type, count) (type*)(PushSize_((arena), sizeof(type) * (count), FileNameAndLineNumberString).Memory) +#define PushString(arena, length) MakeString(PushArray((arena), char, (length)), 0, (length)); + +internal void +ClearArena(gs_memory_arena* Arena) +{ + gs_memory_cursor_list* First = 0; + for (gs_memory_cursor_list* CursorEntry = Arena->CursorList; + CursorEntry != 0; + CursorEntry = CursorEntry->Prev) + { + First = CursorEntry; + CursorEntry->Cursor.Position = 0; + } + Arena->CursorList = First; +} + +internal void +FreeArena(gs_memory_arena* Arena) +{ + FreeCursorList(Arena->CursorList, Arena->Allocator); +} + +/////////////////////////// +// +// Debug Print + +inline void +DebugPrint(debug_output Output, gs_const_string Message) +{ + Output.Print(Output, Message); +} + +inline void +DebugPrint(debug_output Output, char* Message) +{ + gs_const_string String = ConstString(Message); + Output.Print(Output, String); +} + +internal void +DebugPrintF(debug_output Output, char* Format, ...) +{ + gs_string Message = PushString(Output.Storage, 1024); + va_list Args; + va_start(Args, Format); + PrintFArgsList(&Message, Format, Args); + NullTerminate(&Message); + Output.Print(Output, Message.ConstString); +} + +/////////////////////////// +// +// Dynamic Array + +internal gs_dynarray +CreateDynarrayWithStorage(gs_memory_arena Storage, u32 ElementSize, u32 ElementsPerBuffer) +{ + gs_dynarray Result = {}; + Result.Arena = Storage; + Result.ElementSize = ElementSize; + Result.ElementsPerBuffer = ElementsPerBuffer; + Result.ElementCount = 0; + return Result; +} + +internal gs_dynarray +CreateDynarray_(gs_allocator Allocator, u32 ElementSize, u32 ElementsPerBuffer) +{ + gs_memory_arena Storage = CreateMemoryArena(Allocator, ElementSize * ElementsPerBuffer); + return CreateDynarrayWithStorage(Storage, ElementSize, ElementsPerBuffer); +}; + +internal gs_dynarray +CreateDynarray_(gs_memory_arena* Arena, u32 ElementSize, u32 ElementsPerBuffer) +{ + gs_memory_arena Storage = CreateMemorySubArena(Arena, ElementSize * ElementsPerBuffer); + return CreateDynarrayWithStorage(Storage, ElementSize, ElementsPerBuffer); +}; + +internal u64 +CalculateBufferSize(gs_dynarray Array) +{ + u64 Result = Array.ElementsPerBuffer * Array.ElementSize; + return Result; +} + +internal void +GrowDynarray(gs_dynarray* Array) +{ + gs_dynarray_buffer* OldBufferList = Array->Buffers; + u64 NewBuffersCount = Array->BuffersCount + 1; + gs_dynarray_buffer* NewBufferList = AllocatorAllocArray(Array->Arena.Allocator, gs_dynarray_buffer, NewBuffersCount); + if (OldBufferList) + { + CopyArray(OldBufferList, NewBufferList, gs_dynarray_buffer, Array->BuffersCount); + AllocatorFree(Array->Arena.Allocator, OldBufferList, sizeof(gs_dynarray_buffer) * Array->BuffersCount); + } + u64 BufferSize = CalculateBufferSize(*Array); + NewBufferList[Array->BuffersCount].Memory = PushSize(&Array->Arena, BufferSize); + Array->Buffers = NewBufferList; + Array->BuffersCount = NewBuffersCount; +} +internal u64 +DynarraySize(gs_dynarray Array) +{ + u64 Result = Array.BuffersCount * Array.ElementsPerBuffer; + return Result; +} +internal gs_dynarray_handle +IndexToHandle(gs_dynarray* Array, u64 Index) +{ + gs_dynarray_handle Result = {0}; + Result.BufferIndex = Index / Array->ElementsPerBuffer; + Result.IndexInBuffer = Index % Array->ElementsPerBuffer; + return Result; +} +internal u64 +HandleToIndex(gs_dynarray Array, gs_dynarray_handle Handle) +{ + u64 Result = Handle.IndexInBuffer + (Handle.BufferIndex * Array.ElementsPerBuffer); + return Result; +} +internal gs_dynarray_handle +TakeFreeElement(gs_dynarray* Array) +{ + gs_dynarray_handle Result = {0}; + if (Array->ElementCount >= DynarraySize(*Array)) + { + GrowDynarray(Array); + } + Assert(Array->ElementCount < DynarraySize(*Array)); + u64 ElementIndex = Array->ElementCount++; + Result = IndexToHandle(Array, ElementIndex); + return Result; +} +internal bool +HandleIsValid(gs_dynarray Array, gs_dynarray_handle Handle) +{ + bool Result = Handle.IndexInBuffer < Array.ElementsPerBuffer; + Result &= Handle.BufferIndex < Array.BuffersCount; + return Result; +} +internal bool +IndexIsValid(gs_dynarray Array, u64 Index) +{ + bool Result = Index < DynarraySize(Array); + return Result; +} +internal gs_data +GetElementInList_(gs_dynarray* Array, gs_dynarray_handle Handle, u64 SizeRequested) +{ + Assert(SizeRequested == Array->ElementSize); + Assert(HandleIsValid(*Array, Handle)); + gs_dynarray_buffer Buffer = Array->Buffers[Handle.BufferIndex]; + + gs_data Result = {0}; + Result.Memory = Buffer.Memory + (Handle.IndexInBuffer * Array->ElementSize); + Result.Size = SizeRequested; + + return Result; +} +internal gs_data +GetElementInList_(gs_dynarray* Array, u64 Index, u64 SizeRequested) +{ + gs_dynarray_handle Handle = IndexToHandle(Array, Index); + return GetElementInList_(Array, Handle, SizeRequested); +} +internal void +FreeDynarray(gs_dynarray* Array) +{ + gs_allocator Allocator = Array->Arena.Allocator; + u64 BufferSize = CalculateBufferSize(*Array); + for (u64 i = 0; i < Array->BuffersCount; i++) + { + AllocatorFree(Allocator, Array->Buffers[i].Memory, BufferSize); + } + AllocatorFree(Allocator, Array->Buffers, sizeof(gs_dynarray_buffer) * Array->BuffersCount); +} + +#define HandlesAreEqual(ha, hb) ((ha.IndexInBuffer == hb.IndexInBuffer) && (ha.BufferIndex == hb.BufferIndex)) + +#define CreateDynarray(allocator,type,elePerBuf) CreateDynarray_((allocator), sizeof(type), (elePerBuf)) +#define GetElement_(array,type,size,indexOrHandle) (type*)GetElementInList_(array, indexOrHandle, size).Memory +#define GetElement(array,type,indexOrHandle) GetElement_(array, type, sizeof(type), indexOrHandle) + +/////////////////////////// +// +// String Builder + +internal void +GrowStringBuilder_(gs_string_builder* StringBuilder) +{ + gs_string_builder_buffer* NewBuffer = PushStruct(StringBuilder->Arena, gs_string_builder_buffer); + NewBuffer->String = PushString(StringBuilder->Arena, StringBuilder->BufferSize); + SLLPushOrInit(StringBuilder->Root, StringBuilder->Head, NewBuffer); +} + +internal void +OutChar(gs_string_builder* Builder, char C) +{ + if (Builder->Head == 0 || Builder->Head->String.Length >= Builder->Head->String.Size) + { + GrowStringBuilder_(Builder); + } + OutChar(&Builder->Head->String, C); +} + +#if 0 +// TODO: If you need a string builder come back here, otherwise this can stay 0'd out +// was getting in the way +internal void +StringBuilderWriteFArgsList(gs_string_builder* Builder, char* Format, va_list Args) +{ + char* FormatAt = Format; + while (*FormatAt) + { + if (FormatAt[0] != '%') + { + if (FormatAt[0] == '\\') + { + FormatAt++; + Assert(IsBase8(FormatAt[0]) || // Octal Escape Sequences - \0 is in this set + FormatAt[0] == '\'' || + FormatAt[0] == '\"' || + FormatAt[0] == '\?' || + FormatAt[0] == '\\' || + FormatAt[0] == 'a' || // Audible Bell + FormatAt[0] == 'b' || // Backspace + FormatAt[0] == 'f' || // Form Feed - New Page + FormatAt[0] == 'n' || // Line Feed - New Line + FormatAt[0] == 'r' || // Carriage Return + FormatAt[0] == 't' || // Tab + FormatAt[0] == 'v'); // Vertical Tab + + // Not Handled (see cpp spec) \nnn \xnn \unnnn \Unnnnnnnn + Assert(FormatAt[0] != 'x' || FormatAt[0] != 'u' || FormatAt[0] != 'U'); + + if (IsBase8(FormatAt[0])) + { + // TODO(Peter): this should keep going until it finds a non-octal character code + // but the only one we really need is \0 atm so I'm just handling that one + Assert(FormatAt[0] == '0'); + OutChar(Builder, (char)0); + FormatAt++; + } + else + { + OutChar(Builder, *FormatAt++); + } + } + else + { + OutChar(Builder, *FormatAt++); + } + } + else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol + { + OutChar(Builder, '%'); + FormatAt += 2; + } + else + { + FormatAt++; + + // Flags + if (FormatAt[0] == '-') + { + FormatAt++; + } + else if (FormatAt[0] == '+') + { + FormatAt++; + } + else if (FormatAt[0] == ' ') + { + FormatAt++; + } + else if (FormatAt[0] == '#') + { + FormatAt++; + } + else if (FormatAt[0] == '0') + { + FormatAt++; + } + + // Width + b32 WidthSpecified = false; + s32 Width = 0; + + if (IsBase10(FormatAt[0])) + { + WidthSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Width = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + else if (FormatAt[0] == '*') + { + WidthSpecified = true; + Width = va_arg(Args, s32); + Assert(Width >= 0); + FormatAt++; + } + + // Precision + b32 PrecisionSpecified = false; + s32 Precision = 0; + + if (FormatAt[0] == '.') + { + FormatAt++; + if (IsBase10(FormatAt[0])) + { + + PrecisionSpecified = true; + u64 Parsed = 0; + AssertMessage("ParseInt assumes whole string is an integer"); + Precision = (s32)ParseInt(FormatAt, 10, &Parsed); + FormatAt += Parsed; + } + else if (FormatAt[0] == '*') + { + PrecisionSpecified = true; + Precision = va_arg(Args, s32); + Assert(Precision >= 0); + FormatAt++; + } + } + + // Length + b32 LengthSpecified = false; + s32 Length = 4; + + if (FormatAt[0] == 'h' && FormatAt[1] == 'h') + { + LengthSpecified = true; + LengthSpecified = 1; + FormatAt += 2; + } + else if (FormatAt[0] == 'h') + { + LengthSpecified = true; + LengthSpecified = 2; + FormatAt++; + } + else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') + { + LengthSpecified = true; + LengthSpecified = 8; + FormatAt += 2; + } + else if (FormatAt[0] == 'l') + { + LengthSpecified = true; + LengthSpecified = 4; + FormatAt++; + } + else if (FormatAt[0] == 'j') + { + LengthSpecified = true; + LengthSpecified = 8; + FormatAt++; + } + else if (FormatAt[0] == 'z') + { + FormatAt++; + } + else if (FormatAt[0] == 't') + { + FormatAt++; + } + else if (FormatAt[0] == 'L') + { + FormatAt++; + } + + // Format Specifiers + gs_string StringRemaining = GetStringAfter(*String, String->Length); + Assert(StringRemaining.Length == 0); + if (FormatAt[0] == 'd' || FormatAt[0] == 'i') + { + s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); + if (SignedInt < 0) + { + OutChar(&StringRemaining, '-'); + SignedInt *= -1; + } + U64ToASCII(&StringRemaining, (u64)SignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'u') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 10, Base10Chars); + } + else if (FormatAt[0] == 'o') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 8, Base8Chars); + } + else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&StringRemaining, UnsignedInt, 16, Base16Chars); + } + else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') + { + r64 Float = ReadVarArgsFloat(Length, &Args); + s32 AfterPoint = 6; + if (PrecisionSpecified) + { + AfterPoint = Precision; + } + R64ToASCII(&StringRemaining, Float, AfterPoint); + } + else if (FormatAt[0] == 'c') + { + char InsertChar = va_arg(Args, s32); + OutChar(&StringRemaining, InsertChar); + } + else if (FormatAt[0] == 's') + { + char* InsertString = va_arg(Args, char*); + + s32 InsertStringLength = CStringLength(InsertString); + if (PrecisionSpecified) + { + InsertStringLength = Min(InsertStringLength, Precision); + } + InsertStringLength = Min(StringSizeLeft(StringRemaining), InsertStringLength); + + for (s32 c = 0; c < InsertStringLength; c++) + { + OutChar(&StringRemaining, InsertString[c]); + } + } + else if (FormatAt[0] == 'S') + { + gs_const_string InsertString = va_arg(Args, gs_const_string); + + for (s32 c = 0; c < InsertString.Length; c++) + { + OutChar(&StringRemaining, InsertString.Str[c]); + } + } + else if (FormatAt[0] == 'p') + { + // TODO(Peter): Pointer Address + } + else + { + // NOTE(Peter): Non-specifier character found + InvalidCodePath; + } + + String->Length += StringRemaining.Length; + FormatAt++; + } + } + + return String->Length; +} + +internal void +StringBuilderWriteF(gs_string_builder* Builder, char* Format, ...) +{ + va_list Args; + va_start(Args, Format); + StringBuilderWriteFArgsList(Builder, Format, Args); + va_end(Args); +} + +#endif // String builder + +/////////////////////////// +// +// File Handler + +internal u64 +FileHandlerGetFileInfo_NoOp(gs_file_handler FileHandler, gs_const_string Path) +{ + return 0; +} + +internal gs_file +FileHandlerReadFile_NoOp(gs_const_string Path) +{ + return gs_file{0}; +} + +internal bool +FileHandlerWriteFile_NoOp(gs_const_string Path, gs_data Data) +{ + return false; +} + +internal gs_const_string_array +FileHandlerEnumerateDirectory_NoOp(gs_const_string Path, bool Recursive, bool IncludeDirs) +{ + return gs_const_string_array{0}; +} + +internal gs_file_handler +CreateFileHandler(file_handler_get_file_info* GetFileInfo, + file_handler_read_entire_file* ReadEntireFile, + file_handler_write_entire_file* WriteEntireFile, + file_handler_enumerate_directory* EnumerateDirectory, + gs_memory_arena* Transient) +{ + if (GetFileInfo == 0) + { + GetFileInfo = (file_handler_get_file_info*)FileHandlerGetFileInfo_NoOp; + } + if (ReadEntireFile == 0) + { + ReadEntireFile = (file_handler_read_entire_file*)FileHandlerReadFile_NoOp; + } + if (WriteEntireFile == 0) + { + WriteEntireFile = (file_handler_write_entire_file*)FileHandlerWriteFile_NoOp; + } + if (EnumerateDirectory == 0) + { + EnumerateDirectory = (file_handler_enumerate_directory*)FileHandlerEnumerateDirectory_NoOp; + } + gs_file_handler Result = {0}; + Result.GetFileInfo = GetFileInfo; + Result.ReadEntireFile = ReadEntireFile; + Result.WriteEntireFile = WriteEntireFile; + Result.EnumerateDirectory = EnumerateDirectory; + Result.Transient = Transient; + + return Result; +} + +internal gs_const_string +GetNullTerminatedPath(gs_file_handler FileHandler, gs_const_string Path) +{ + gs_const_string NullTermPath = Path; + if (!IsNullTerminated(NullTermPath)) + { + AssertMessage("need to allocate a new string, Path to it, and null terminate"); + // TODO(Peter): Probably want to have some sort of temp memory, + // or be passing in a thread context, etc. + } + return NullTermPath; +} + +internal gs_file_info +GetFileInfo(gs_file_handler FileHandler, gs_const_string Path) +{ + Assert(FileHandler.GetFileInfo != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + gs_file_info Result = FileHandler.GetFileInfo(FileHandler, Path); + return Result; +} + +internal gs_file +ReadEntireFile(gs_file_handler FileHandler, gs_const_string Path, gs_data Memory) +{ + Assert(FileHandler.ReadEntireFile != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + gs_file Result = FileHandler.ReadEntireFile(FileHandler, Path, Memory); + return Result; +} + +internal gs_file +ReadEntireFile(gs_file_handler FileHandler, gs_const_string Path) +{ + Assert(FileHandler.GetFileInfo != 0); + Assert(FileHandler.ReadEntireFile != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + gs_file Result = {0}; + gs_file_info FileInfo = FileHandler.GetFileInfo(FileHandler, Path); + if (FileInfo.FileSize > 0) + { + gs_data FileMemory = PushSizeToData(FileHandler.Transient, FileInfo.FileSize); + Result = ReadEntireFile(FileHandler, Path, FileMemory); + } + return Result; +} + +internal bool +WriteEntireFile(gs_file_handler FileHandler, gs_const_string Path, gs_data Memory) +{ + Assert(FileHandler.WriteEntireFile != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + return FileHandler.WriteEntireFile(FileHandler, Path, Memory); +} + +internal gs_file_info_array +EnumerateDirectory(gs_file_handler FileHandler, gs_memory_arena* Storage, gs_const_string Path, u32 Flags) +{ + Assert(FileHandler.EnumerateDirectory != 0); + + Path = GetNullTerminatedPath(FileHandler, Path); + return FileHandler.EnumerateDirectory(FileHandler, Storage, Path, Flags); +} + +internal bool +FileNoError(gs_file File) +{ + bool Result = (File.Size > 0); + return Result; +} + +////////////////////////// +// +// Timing + +internal s64 +TimeHandlerGetWallClock(gs_time_handler TimeHandler) +{ + s64 Result = TimeHandler.GetWallClock(); + return Result; +} + +internal s64 +TimeHandlerGetSecondsElapsed(gs_time_handler TimeHandler, s64 StartCycles, s64 EndCycles) +{ + s64 Result = TimeHandler.GetSecondsElapsed(StartCycles, EndCycles); + return Result; +} + +/////////////////////////// +// +// Hashes + +internal u32 +HashDJB2ToU32(char* String) +{ + u32 Hash = 5381; + char* C = String; + while(*C) + { + Hash = ((Hash << 5) + Hash) + *C++; + } + return Hash; +} +internal u32 +HashDJB2ToU32(u32 Length, char* String) +{ + u32 Hash = 5381; + for (u32 i = 0; i < Length; i++) + { + Hash = ((Hash << 5) + Hash) + String[i]; + } + return Hash; +} + +internal u64 +HashDJB2ToU64(char* String) +{ + u64 Hash = 5381; + char* C = String; + while(*C) + { + Hash = ((Hash << 5) + Hash) + *C++; + } + return Hash; +} +internal u64 +HashDJB2ToU64(u32 Length, char* String) +{ + u64 Hash = 5381; + for (u32 i = 0; i < Length; i++) + { + Hash = ((Hash << 5) + Hash) + String[i]; + } + return Hash; +} + +/////////////////////////// +// +// Random Series + +internal gs_random_series +InitRandomSeries(u32 Seed) +{ + gs_random_series Result = {0}; + Result.Value = Seed; + return Result; +} + +internal u32 +NextRandom(gs_random_series* Series) +{ + u32 Result = Series->Value; + Result ^= Result << 13; + Result ^= Result >> 17; + Result ^= Result << 5; + Series->Value = Result; + return Result; +} + +internal r32 +NextRandomUnilateral(gs_random_series* Series) +{ + r32 Result = (r32)NextRandom(Series) / (r32)UINT32_MAX; + return Result; +} + +internal r32 +NextRandomBilateral(gs_random_series* Series) +{ + r32 Result = (r32)NextRandom(Series); + Result = Result / (r32)0xFFFFFFFF; + Result = (Result * 2.0f) - 1.0f; + return Result; +} + + +/////////////////////////// +// +// Sort + + +static void +RadixSortInPlace_ (gs_radix_list* List, u32 Start, u32 End, u32 Iteration) +{ + u32 Shift = Iteration; + u32 ZerosBoundary = Start; + u32 OnesBoundary = End - 1; + + for (u32 d = Start; d < End; d++) + { + u64 CurrentIndex = ZerosBoundary; + u64 Radix = List->Radixes.Values[CurrentIndex]; + u64 Place = (Radix >> Shift) & 0x1; + if (Place) + { + u64 EvictedIndex = OnesBoundary; + u64 EvictedRadix = List->Radixes.Values[EvictedIndex]; + u64 EvictedID = List->IDs.Values[EvictedIndex]; + + List->Radixes.Values[EvictedIndex] = Radix; + List->IDs.Values[EvictedIndex] = List->IDs.Values[CurrentIndex]; + + List->Radixes.Values[CurrentIndex] = EvictedRadix; + List->IDs.Values[CurrentIndex] = EvictedID; + + OnesBoundary -= 1; + } + else + { + ZerosBoundary += 1; + } + } + + if (Iteration > 0) + { + RadixSortInPlace_(List, Start, ZerosBoundary, Iteration - 1); + RadixSortInPlace_(List, ZerosBoundary, End, Iteration - 1); + } +} + +static void +RadixSortInPlace (gs_radix_list* List) +{ + u32 Highest = 0; + for (u32 i = 0; i < List->Radixes.Count; i++) + { + if (List->Radixes.Values[i] > Highest) + { + Highest = List->Radixes.Values[i]; + } + } + + u32 Iterations = 0; + while (Highest > 1) + { + ++Iterations; + Highest = Highest >> 1; + } + + RadixSortInPlace_(List, 0, List->Radixes.Count, Iterations); +} + + +/////////////////////////// +// +// Input + +inline bool +KeyIsMouseButton(gs_key Key) +{ + bool Result = (Key >= gs_Key_MouseLeftButton); + Result = Result && Key <= gs_Key_MouseRightButton; + return Result; +} +inline u32 +GetMouseButtonIndex(gs_key Button) +{ + Assert(KeyIsMouseButton(Button)); + u32 Result = Button - gs_Key_MouseLeftButton; + return Result; +} +inline bool +MouseButtonTransitionedDown(gs_mouse_state Mouse, u32 Index) +{ + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + bool WasDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_WasDownBit)) != 0; + return IsDown && !WasDown; +} +inline bool +MouseButtonTransitionedDown(gs_mouse_state Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonTransitionedDown(Mouse, Index); +} +inline bool +MouseButtonIsDown(gs_mouse_state Mouse, u32 Index) +{ + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + return IsDown; +} +inline bool +MouseButtonIsDown(gs_mouse_state Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonIsDown(Mouse, Index); +} +inline bool +MouseButtonTransitionedUp(gs_mouse_state Mouse, u32 Index) +{ + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + bool WasDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_WasDownBit)) != 0; + return !IsDown && WasDown; +} +inline bool +MouseButtonTransitionedUp(gs_mouse_state Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonTransitionedUp(Mouse, Index); +} +inline bool +MouseButtonIsUp(gs_mouse_state Mouse, u32 Index) +{ + bool IsDown = (Mouse.ButtonStates[Index] & (1 << MouseButton_IsDownBit)) != 0; + return !IsDown; +} +inline bool +MouseButtonIsUp(gs_mouse_state Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + return MouseButtonIsUp(Mouse, Index); +} +internal void +SetMouseButtonTransitionedDown(gs_mouse_state* Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + + Mouse->ButtonStates[Index] = 0; + Mouse->ButtonStates[Index] |= MouseButton_IsDown << MouseButton_IsDownBit; + Mouse->ButtonStates[Index] |= MouseButton_WasNotDown << MouseButton_WasDownBit; +} +internal void +SetMouseButtonTransitionedUp(gs_mouse_state* Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + + Mouse->ButtonStates[Index] = 0; + Mouse->ButtonStates[Index] |= MouseButton_IsNotDown << MouseButton_IsDownBit; + Mouse->ButtonStates[Index] |= MouseButton_WasDown << MouseButton_WasDownBit; +} +internal void +AdvanceMouseButtonState(gs_mouse_state* Mouse, gs_key Button) +{ + u32 Index = GetMouseButtonIndex(Button); + + if (MouseButtonIsDown(*Mouse, Index)) + { + Mouse->ButtonStates[Index] |= MouseButton_WasDown << MouseButton_WasDownBit; + } + else + { + Mouse->ButtonStates[Index] &= MouseButton_WasNotDown << MouseButton_WasDownBit; + } +} +internal void +AdvanceMouseButtonsState(gs_mouse_state* Mouse) +{ + AdvanceMouseButtonState(Mouse, gs_Key_MouseLeftButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseMiddleButton); + AdvanceMouseButtonState(Mouse, gs_Key_MouseRightButton); +} + +/////////////////////////// +// +// Network + + +static u32 +HostToNetU32(u32 In) +{ + unsigned char *s = (unsigned char *)&In; + u32 Result = (u32)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]); + return Result; +} + +static u16 +HostToNetU16(u16 In) +{ + unsigned char *s = (unsigned char *)&In; + u16 Result = (u16)(s[0] << 8 | s[1]); + return Result; +} + + + + + + + + + + +#define GS_TYPES_CPP +#endif // GS_TYPES_CPP \ No newline at end of file diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h new file mode 100644 index 0000000..8a9736e --- /dev/null +++ b/src/gs_libs/gs_types.h @@ -0,0 +1,1053 @@ +// +// File: gs_types.h +// Author: Peter Slattery +// Creation Date: 2020-04-18 +// +#ifndef GS_TYPES_H + +#if defined(__clang__) +# pragma GCC diagnostic ignored "-Wunused-value" +# pragma GCC diagnostic ignored "-Wvarargs" +# pragma GCC diagnostic ignored "-Wwritable-strings" +#endif + +#if defined(_MSC_VER) +# include +#endif + +// Someday, we home to remove these includes +#include +#if !defined(GUESS_INTS) +# include +#endif // !defined(GUESS_INTS) + +#include + +#define Glue_(a,b) a##b +#define Glue(a,b) Glue_(a,b) + +#define Stringify_(a) #a +#define Stringify(a) Stringify_(a) + +#define internal static +#define local_persist static +#define global static +#define local_const static const +#define global_const static const +#define external extern "C" + +#if defined(GUESS_INTS) +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +#else +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +#endif + +typedef s8 b8; +typedef s32 b32; +typedef s64 b64; + +typedef float r32; +typedef double r64; + +enum gs_basic_type +{ + gs_BasicType_char, + gs_BasicType_b8, + gs_BasicType_b32, + gs_BasicType_b64, + gs_BasicType_u8, + gs_BasicType_u16, + gs_BasicType_u32, + gs_BasicType_u64, + gs_BasicType_s8, + gs_BasicType_s16, + gs_BasicType_s32, + gs_BasicType_s64, + gs_BasicType_r32, + gs_BasicType_r64, + + gs_BasicType_Count, +}; + +global_const u64 gs_BasicTypeSizes[] = +{ + sizeof(char), + sizeof(b8), + sizeof(b32), + sizeof(b64), + sizeof(u8), + sizeof(u16), + sizeof(u32), + sizeof(u64), + sizeof(s8), + sizeof(s16), + sizeof(s32), + sizeof(s64), + sizeof(r32), + sizeof(r64), +}; + +internal u64 +BasicTypeSize(gs_basic_type Type) +{ + return gs_BasicTypeSizes[(u32)Type]; +} + +global_const u8 MaxU8 = 0xFF; +global_const u16 MaxU16 = 0xFFFF; +global_const u32 MaxU32 = 0xFFFFFFFF; +global_const u64 MaxU64 = 0xFFFFFFFFFFFFFFFF; + +global_const s8 MaxS8 = 127; +global_const s16 MaxS16 = 32767; +global_const s32 MaxS32 = 2147483647; +global_const s64 MaxS64 = 9223372036854775807; + +global_const s8 MinS8 = -127 - 1; +global_const s16 MinS16 = -32767 - 1; +global_const s32 MinS32 = -2147483647 - 1; +global_const s64 MinS64 = -9223372036854775807 - 1; + +global_const r32 MaxR32 = 3.402823466e+38f; +global_const r32 MinR32 = -MaxR32; +global_const r32 SmallestPositiveR32 = 1.1754943508e-38f; +global_const r32 EpsilonR32 = 5.96046448e-8f; + +global_const r32 PiR32 = 3.14159265359f; +global_const r32 HalfPiR32 = 1.5707963267f; +global_const r32 TauR32 = 6.28318530717f; + +global_const r64 MaxR64 = 1.79769313486231e+308; +global_const r64 MinR64 = -MaxR64; +global_const r64 SmallestPositiveR64 = 4.94065645841247e-324; +global_const r64 EpsilonR64 = 1.11022302462515650e-16; + +// TODO: va_start and va_arg replacements + +internal r32 +DegToRadR32(r32 Degrees) +{ + return (Degrees * (PiR32 / 180.0f)); +} + +internal r32 +RadToDegR32(r32 Radians) +{ + return (Radians * (180.0f / PiR32)); +} + +struct s8_array +{ + s8* Values; + u32 Count; + u32 CountMax; +}; + +struct s16_array +{ + s16* Values; + u32 Count; + u32 CountMax; +}; + +struct s32_array +{ + s32* Values; + u32 Count; + u32 CountMax; +}; + +struct s64_array +{ + s64* Values; + u32 Count; + u32 CountMax; +}; + +struct u8_array +{ + u8* Values; + u32 Count; + u32 CountMax; +}; + +struct u16_array +{ + u16* Values; + u32 Count; + u32 CountMax; +}; + +struct u32_array +{ + u32* Values; + u32 Count; + u32 CountMax; +}; + +struct u64_array +{ + u64* Values; + u32 Count; + u32 CountMax; +}; + + +#define PointerDifference(a,b) ((u8*)(a) - (u8*)(b)) +#define PointerToInt(a) PointerDifference(a, 0) +#define Member(type,member) (((type*)0)->member) +#define MemberOffset(type,member) PointerToInt(&Member(type,member)) + +// NOTE(Peter): Makes sure that s doesn't expand in some way that invalidates +// a nested if statement. +#define Statement(s) do{ s }while(0) + +// +// Asserts +// +// AssertAlways and AssertMessageAlways should be used sparingly, because they'll +// still assert in the final build +#define AssertBreak(m) (*((volatile s32*)0) = 0xFFFF) +#define AssertAlways(c) Statement( if (!(c)) { AssertBreak(c); } ) +#define AssertMessageAlways(m) AssertBreak(m) + +#if !SHIP_MODE +# define Assert(c) AssertAlways(c) +# define AssertMessage(m) AssertBreak(m) +# define InvalidDefaultCase default: { AssertBreak("invalid default case"); } break; +# define StaticAssert(c) \ +enum { \ +Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \ +} +#else +# define Assert(c) +# define AssertMessage(m) +# define InvalidDefaultCase default: {} break; +# define StaticAssert(c) +#endif + +#define AssertImplies(a,b) Statement(if(a) { Assert(b); }) +#define InvalidCodePath AssertMessage("invalid code path") +#define NotImplemented AssertMessage("not implemented") +#define DontCompile ImAfraidICantDoThat + +#define LineNumberString Stringify(__LINE__) +#define FileNameAndLineNumberString_ __FILE__ ":" LineNumberString ":" +#define FileNameAndLineNumberString (char*)FileNameAndLineNumberString_ + +// + +#define Bytes(x) (x) +#define KB(x) ((x) << 10) +#define MB(x) ((x) << 20) +#define GB(x) ((x) << 30) +#define TB(x) (((u64)x) << 40) + +#define HasFlag(data, flag) (((data) & (flag)) != 0) +#define HasFlagOnly(data, flag) (((data) & (flag)) == (data)) +#define AddFlag(data, flag) ((data) |= (flag)) +#define RemoveFlag(data, flag) ((data) &= (~(flag))) + +#define Max(a,b) (((a) > (b)) ? (a) : (b)) +#define Min(a,b) (((a) > (b)) ? (b) : (a)) +#define Clamp_(a,x,b) ((x < a) ? a : ((x > b) ? b : x)) +#define Clamp(a,x,b) Clamp_((a), (x), (b)) +#define Clamp01(x) Clamp_(0.0f, (x), 1.0f) +#define Abs(x) (((x) < 0) ? ((x) * -1) : x) +#define Sign(x) ((x) < 0) ? -1 : 1; +#define IsPowerOfTwo(x) (((x) & ((x) - 1)) == 0) +#define IsOdd(x) (((x) & 1) != 0) + +internal void +ZeroMemory_(u8* Memory, u64 Size) +{ + for (u64 i = 0; i < Size; i++) + { + Memory[i] = 0; + } +} + +internal void +CopyMemory_(u8* From, u8* To, u64 Size) +{ + for (u64 i = 0; i < Size; i++) + { + To[i] = From[i]; + } +} + +#define StaticArrayLength(arr) sizeof(arr) / sizeof((arr)[0]) +#define ZeroMemoryBlock(mem,size) ZeroMemory_((u8*)(mem), (size)) +#define ZeroStruct(str) ZeroMemory_((str), sizeof(str)) +#define ZeroArray(arr, type, count) ZeroMemory_((u8*)(arr), sizeof(type) * (count)) + +#define CopyArray(from, to, type, count) CopyMemory_((u8*)(from), (u8*)(to), sizeof(type) * (count)) +#define CopyMemoryTo(from, to, size) CopyMemory_((u8*)(from), (u8*)(to), (size)) +// Singly Linked List Utilities + +#define SLLPush_(list_tail,new_ele) list_tail->Next = new_ele, list_tail = new_ele +#define SLLPush(list_tail,new_ele) (SLLPush_((list_tail), (new_ele))) + +#define SLLPop_(list_tail) list_tail=list_tail=list_tail->next +#define SLLPop(list_tail) (SLLPop_((list_tail))) + +#define SLLNext(ele_at) ele_at = ele_at->Next; +#define SLLPrev(ele_at) ele_at = ele_at->Prev; + +#define SLLInit(head,tail,first_ele) head=first_ele, tail=first_ele; + +#define SLLPushOrInit(first,last,new_ele) \ +if (last) { SLLPush(last, new_ele); } \ +else { SLLInit(first,last,new_ele); } + +// Vectors + +union v2 +{ + struct + { + r32 x; + r32 y; + }; + r32 E[2]; +}; + +union v3 +{ + struct + { + r32 x; + r32 y; + r32 z; + }; + struct + { + r32 r; + r32 g; + r32 b; + }; + struct + { + v2 xy; + r32 _z0; + }; + struct + { + r32 _x0; + v2 yz; + }; + r32 E[3]; +}; + +union v4 +{ + struct + { + r32 x; + r32 y; + r32 z; + r32 w; + }; + struct + { + r32 r; + r32 g; + r32 b; + r32 a; + }; + struct + { + v2 xy; + v2 zw; + }; + struct + { + r32 _x0; + v2 yz; + r32 _w0; + }; + struct + { + v3 xyz; + r32 _w1; + }; + r32 E[4]; +}; + +struct v4_ray +{ + v4 Origin; + v4 Direction; +}; + +#define WhiteV4 v4{1, 1, 1, 1} +#define BlackV4 v4{0, 0, 0, 1} +#define RedV4 v4{1, 0, 0, 1} +#define GreenV4 v4{0, 1, 0, 1} +#define BlueV4 v4{0, 0, 1, 1} +#define YellowV4 v4{1, 1, 0, 1} +#define TealV4 v4{0, 1, 1, 1} +#define PinkV4 v4{1, 0, 1, 1} + +#define V2Expand(v) v.x, v.y +#define V3Expand(v) v.x, v.y, v.z +#define V4Expand(v) v.x, v.y, v.z, v.w + +struct v2_array +{ + v2* Vectors; + u32 Count; + u32 CountMax; +}; + +struct v3_array +{ + v3* Vectors; + u32 Count; + u32 CountMax; +}; + +struct v4_array +{ + v4* Vectors; + u32 Count; + u32 CountMax; +}; + +struct range1 +{ + r32 Min; + r32 Max; +}; + +struct range2 +{ + v2 Min; + v2 Max; +}; +typedef range2 rect2; + +struct range3 +{ + v3 Min; + v3 Max; +}; + +struct range4 +{ + v4 Min; + v4 Max; +}; + +struct range1_array +{ + range1* Ranges; + u32 Count; + u32 CountMax; +}; + +struct range2_array +{ + range2* Ranges; + u32 Count; + u32 CountMax; +}; + +struct range3_array +{ + range3* Ranges; + u32 Count; + u32 CountMax; +}; + +struct range4_array +{ + range4* Ranges; + u32 Count; + u32 CountMax; +}; + +#define Range1Expand(r) (r).Min, (r).Max +#define Range2Expand(r) (r).Min, (r).Max +#define Rect2Expand(r) (r).Min (r).Max +#define Range3Expand(r) (r).Min, (r).Max +#define Range4Expand(r) (r).Min, (r).Max + +// Matrices +// NOTE(Peter): All matrices are stored in row major order + +union m33 +{ + float Array[9]; + struct + { + r32 AXx; r32 AYx; r32 AZx; + r32 AXy; r32 AYy; r32 AZy; + r32 AXz; r32 AYz; r32 AZz; + }; +}; + +union m44 +{ + float Array[16]; + struct + { + r32 AXx; r32 AYx; r32 AZx; r32 Tx; + r32 AXy; r32 AYy; r32 AZy; r32 Ty; + r32 AXz; r32 AYz; r32 AZz; r32 Tz; + r32 AXw; r32 AYw; r32 AZw; r32 Tw; + }; +}; + +struct m33_array +{ + m33* Matrices; + u32 Count; + u32 CountMax; +}; + +struct m44_array +{ + m44* Matrices; + u32 Count; + u32 CountMax; +}; + +////////////////////////// +// +// Strings + +struct gs_const_string +{ + union + { + char* Str; + u8* Data;; + }; + u64 Length; +}; + +struct gs_string +{ + union + { + gs_const_string ConstString; + struct + { + char* Str; + u64 Length; + }; + }; + u64 Size; +}; + +struct gs_const_string_array +{ + gs_const_string* Strings; + u64 Count; + u64 Used; +}; + +struct gs_string_array +{ + gs_string* Strings; + u64 Count; + u64 CountMax; +}; + +internal u64 +CStringLength(char* Str) +{ + char* At = Str; + while (*At) { At++; } + return PointerDifference(At, Str); +} + +#define StringExpand(str) (int)(str).Length, (str).Str +#define LitString(cstr) gs_const_string{(char*)(cstr), CStringLength((char*)cstr) } + +// The index of the character in these arrays corresponds to its value as a number in +// the relevant base, so you can do FindFirst on them with a char to get the int value +// ie. 3 is at index 3 in Base10Chars. +// ie. C is at index 12 in Base16Chars. +global_const gs_const_string Base8Chars = LitString("01234567"); +global_const gs_const_string Base10Chars = LitString("0123456789"); +global_const gs_const_string Base16Chars = LitString("0123456789ABCDEF"); + +////////////////////////// +// +// Thread Context + +typedef struct gs_thread_context gs_thread_context; + +////////////////////////// +// +// Memory + +struct gs_data +{ + u8* Memory; + u64 Size; +}; + +struct gs_data_array +{ + gs_data* Data; + u64 Count; + u64 CountMax; +}; + +enum gs_access_flag +{ + gs_AccessFlag_Read = 1 << 0, + gs_AccessFlag_Write = 1 << 1, + gs_AccessFlag_Exec = 1 << 2, +}; + +typedef s32 gs_scan_direction; +enum +{ + gs_Scan_Backward = -1, + gs_Scan_Forward = 1, +}; + +#define ALLOCATOR_ALLOC(name) void* name(u64 Size, u64* ResultSize) +typedef ALLOCATOR_ALLOC(allocator_allocate); + +#define ALLOCATOR_FREE(name) void name(void* Ptr, u64 Size) +typedef ALLOCATOR_FREE(allocator_free); + +struct gs_allocator +{ + allocator_allocate* Alloc; + allocator_free* Free; +}; + +struct gs_memory_cursor +{ + gs_data Data; + u64 Position; +}; + +struct gs_memory_cursor_list +{ + gs_memory_cursor Cursor; + gs_memory_cursor_list* Next; + gs_memory_cursor_list* Prev; +}; + +enum arena_type +{ + Arena_BaseArena, + Arena_SubArena, +}; + +struct gs_memory_arena +{ + arena_type Type; + gs_allocator Allocator; + gs_memory_arena* Parent; + + gs_memory_cursor_list* CursorList; + u64 MemoryChunkSize; + u64 MemoryAlignment; +}; + +struct gs_memory_arena_array +{ + gs_memory_arena* Arenas; + u32 Count; + u32 Size; +}; + +/////////////////////////////// +// +// String Builder +// + +struct gs_string_builder_buffer +{ + gs_string String; + gs_string_builder_buffer* Next; +}; + +struct gs_string_builder +{ + gs_memory_arena* Arena; + u32 BufferSize; + gs_string_builder_buffer* Root; + gs_string_builder_buffer* Head; +}; + +/////////////////////////////// +// +// Debug Output +// + +typedef struct debug_output debug_output; + +#define DEBUG_PRINT(name) void name(debug_output Output, gs_const_string Message) +typedef DEBUG_PRINT(debug_print); + +struct debug_output +{ + gs_memory_arena* Storage; + debug_print* Print; +}; + +/////////////////////////////// +// +// Dynamic Array +// +// I like having constant lookup times, along with growable arrays. :) +// NOTE(Peter): If you're using this, you probably want to write a Get +// procedure to auto cast the result to the type you want. I'm even providing a +// debug check for you to make sure that you're requesting a size that matches +// the ElementSize for extra safety. + +struct gs_dynarray_buffer +{ + u8* Memory; +}; + +struct gs_dynarray +{ + gs_memory_arena Arena; + + gs_dynarray_buffer* Buffers; + u64 BuffersCount; + u64 ElementCount; + + u64 ElementSize; + u64 ElementsPerBuffer; +}; + +struct gs_dynarray_handle +{ + u64 BufferIndex; + u64 IndexInBuffer; +}; + +#define INVALID_DYNARRAY_HANDLE gs_dynarray_handle{0, 0} + +struct gs_dynarray_handle_list +{ + gs_dynarray_handle* Handles; + u32 Count; + u32 Size; +}; + +/////////////////////////////// +// +// File IO + +// TODO(Peter): Error Handling Thought +// The gs_file_handler, gs_allocator, etc should contain pointers to a central error buffer +// where errors can be logged + +enum enumerate_directory_flag +{ + EnumerateDirectory_Recurse = 1 << 0, + EnumerateDirectory_IncludeDirectories = 1 << 1, +}; + +struct gs_file_info +{ + gs_const_string Path; + gs_const_string AbsolutePath; + u64 FileSize; + u64 CreationTime; + u64 LastWriteTime; +}; + +struct gs_file_info_array +{ + gs_file_info* Values; + u32 Count; + u32 MaxCount; +}; + +struct gs_file +{ + union + { + gs_data Data; + struct + { + u8* Memory; + u64 Size; + }; + }; + gs_file_info FileInfo; +}; + +typedef struct gs_file_handler gs_file_handler; + +#define GET_FILE_INFO(name) gs_file_info name(gs_file_handler FileHandler, gs_const_string Path) +typedef GET_FILE_INFO(file_handler_get_file_info); + +#define READ_ENTIRE_FILE(name) gs_file name(gs_file_handler FileHandler, gs_const_string Path, gs_data Memory) +typedef READ_ENTIRE_FILE(file_handler_read_entire_file); + +#define WRITE_ENTIRE_FILE(name) bool name(gs_file_handler FileHandler, gs_const_string Path, gs_data Data) +typedef WRITE_ENTIRE_FILE(file_handler_write_entire_file); + +#define ENUMERATE_DIRECTORY(name) gs_file_info_array name(gs_file_handler FileHandler, gs_memory_arena* Storage, gs_const_string Path, u32 Flags) +typedef ENUMERATE_DIRECTORY(file_handler_enumerate_directory); + +struct gs_file_handler +{ + file_handler_get_file_info* GetFileInfo; + file_handler_read_entire_file* ReadEntireFile; + file_handler_write_entire_file* WriteEntireFile; + file_handler_enumerate_directory* EnumerateDirectory; + gs_memory_arena* Transient; +}; + + +////////////////////////// +// +// Timing + +#define GET_WALL_CLOCK(name) s64 name() +typedef GET_WALL_CLOCK(get_wall_clock); + +#define GET_SECONDS_ELAPSED(name) r64 name(u64 StartCycles, u64 EndCycles) +typedef GET_SECONDS_ELAPSED(get_seconds_elapsed); + +struct gs_time_handler +{ + get_wall_clock* GetWallClock; + get_seconds_elapsed* GetSecondsElapsed; +}; + +/////////////////////////////// +// +// Random + +struct gs_random_series +{ + u32 Value; +}; + +/////////////////////////////// +// +// Sort + +struct gs_radix_list +{ + u64_array Radixes; + u64_array IDs; +}; + + +/////////////////////////////// +// +// Mouse/Keyboard Input + +enum gs_event_type +{ + gs_EventType_Unknown, + + // Reached end of event stream + gs_EventType_NoMoreEvents, + // There was an event but it requires no action from the using program + gs_EventType_NoEvent, + + gs_EventType_KeyPressed, + gs_EventType_KeyReleased, + + gs_EventType_MouseMoved, + gs_EventType_MouseWheel, + + gs_EventType_Count, +}; + +enum gs_key +{ + gs_Key_Invalid, + + gs_Key_Esc, + + gs_Key_Space, + gs_Key_Tab, + gs_Key_CapsLock, + gs_Key_Shift, gs_Key_LeftShift, gs_Key_RightShift, + gs_Key_Control, gs_Key_LeftCtrl, gs_Key_RightCtrl, + gs_Key_Fn, + gs_Key_Alt, + gs_Key_PageUp, gs_Key_PageDown, + gs_Key_End, gs_Key_Home, gs_Key_Select, + gs_Key_Backspace, gs_Key_Delete, + gs_Key_Enter, + + // Function Keys + gs_Key_F0, gs_Key_F1, gs_Key_F2, gs_Key_F3, gs_Key_F4, gs_Key_F5, gs_Key_F6, gs_Key_F7, + gs_Key_F8, gs_Key_F9, gs_Key_F10, gs_Key_F11, gs_Key_F12, + + // Letters + gs_Key_a, gs_Key_b, gs_Key_c, gs_Key_d, gs_Key_e, gs_Key_f, gs_Key_g, gs_Key_h, + gs_Key_i, gs_Key_j, gs_Key_k, gs_Key_l, gs_Key_m, gs_Key_n, gs_Key_o, gs_Key_p, + gs_Key_q, gs_Key_r, gs_Key_s, gs_Key_t, gs_Key_u, gs_Key_v, gs_Key_w, gs_Key_x, + gs_Key_y, gs_Key_z, + + gs_Key_A, gs_Key_B, gs_Key_C, gs_Key_D, gs_Key_E, gs_Key_F, gs_Key_G, gs_Key_H, + gs_Key_I, gs_Key_J, gs_Key_K, gs_Key_L, gs_Key_M, gs_Key_N, gs_Key_O, gs_Key_P, + gs_Key_Q, gs_Key_R, gs_Key_S, gs_Key_T, gs_Key_U, gs_Key_V, gs_Key_W, gs_Key_X, + gs_Key_Y, gs_Key_Z, + + // Numbers + gs_Key_0, gs_Key_1, gs_Key_2, gs_Key_3, gs_Key_4, gs_Key_5, gs_Key_6, gs_Key_7, + gs_Key_8, gs_Key_9, + + gs_Key_Num0, gs_Key_Num1, gs_Key_Num2, gs_Key_Num3, gs_Key_Num4, gs_Key_Num5, + gs_Key_Num6, gs_Key_Num7, gs_Key_Num8, gs_Key_Num9, + + // Symbols + gs_Key_Bang, gs_Key_At, gs_Key_Pound, gs_Key_Dollar, gs_Key_Percent, gs_Key_Carrot, + gs_Key_Ampersand, gs_Key_Star, gs_Key_LeftParen, gs_Key_RightParen, gs_Key_Minus, gs_Key_Plus, + gs_Key_Equals, gs_Key_Underscore, gs_Key_OpenSquareBracket, gs_Key_CloseSquareBracket, gs_Key_OpenCurlyBracket, + gs_Key_CloseCurlyBracket, gs_Key_Colon, gs_Key_SemiColon, gs_Key_SingleQuote, gs_Key_DoubleQuote, + gs_Key_ForwardSlash, gs_Key_Backslash, gs_Key_Pipe, gs_Key_Comma, gs_Key_Period, + gs_Key_QuestionMark, gs_Key_LessThan, gs_Key_GreaterThan, gs_Key_Tilde, gs_Key_BackQuote, + + // Arrows + gs_Key_UpArrow, + gs_Key_DownArrow, + gs_Key_LeftArrow, + gs_Key_RightArrow, + + // Mouse + // NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions + gs_Key_MouseLeftButton, + gs_Key_MouseMiddleButton, + gs_Key_MouseRightButton, + gs_Key_MouseX1Button, + gs_Key_MouseX2Button, + + gs_Key_Count, +}; + +enum gs_modifier_key_flags +{ + gs_ModifierKeyFlag_Shift = 1 << 0, + gs_ModifierKeyFlag_Ctrl = 1 << 1, + gs_ModifierKeyFlag_Alt = 1 << 2, +}; + +struct gs_input_event +{ + gs_event_type Type; + gs_key Key; + v2 Position; + r32 Amount; + b32 Modifiers; +}; + +struct gs_input_event_buffer +{ + gs_input_event* Values; + u32 Count; + u32 MaxCount; +}; + +struct gs_mouse_state +{ + v2 Position; + b32 ButtonStates[3]; + v2 DownPosition; +}; + +#define MouseButton_IsDownBit 0 +#define MouseButton_WasDownBit 1 +#define MouseButton_IsDown 1 +#define MouseButton_IsNotDown 0 +#define MouseButton_WasDown 1 +#define MouseButton_WasNotDown 0 + +////////////////////////// +// +// Thread Context + +struct gs_thread_info +{ + u32 ThreadID; +}; + +struct gs_thread_context +{ + gs_thread_info ThreadInfo; + + // TODO(Peter): Pull these handlers out into just a gs_context struct so + // they can be shared across threads. + // specifically the allocator + gs_allocator Allocator; + gs_file_handler FileHandler; + debug_output DebugOutput; + gs_time_handler TimeHandler; + + gs_memory_arena* Transient; +}; + +// Threads & Work Queue + +typedef struct gs_work_queue gs_work_queue; + +struct gs_worker_thread +{ + gs_thread_context Context; + gs_work_queue* Queue; + b32 ShouldExit; +}; + +#define THREAD_PROC(name) void name(gs_thread_context Context, gs_data Data) +typedef THREAD_PROC(thread_proc); + +struct gs_threaded_job +{ + thread_proc* WorkProc; + gs_data Data; + gs_const_string JobName; +}; + +#define PUSH_WORK_ON_QUEUE(name) void name(gs_work_queue* Queue, thread_proc* WorkProc, gs_data Data, gs_const_string JobName) +typedef PUSH_WORK_ON_QUEUE(push_work_on_queue); + +#define COMPLETE_QUEUE_WORK(name) void name(gs_work_queue* Queue, gs_thread_context Context) +typedef COMPLETE_QUEUE_WORK(complete_queue_work); + +#define RESET_WORK_QUEUE(name) void name(gs_work_queue* Queue) +typedef RESET_WORK_QUEUE(reset_work_queue); + +struct gs_work_queue +{ + void* SemaphoreHandle; + + u32 JobsMax; + u32 volatile JobsCount; + u32 volatile NextJobIndex; + u32 volatile JobsCompleted; + gs_threaded_job* Jobs; + + // Work Queue + push_work_on_queue* PushWorkOnQueue; + complete_queue_work* CompleteQueueWork; + reset_work_queue* ResetWorkQueue; +}; + +#define GS_TYPES_H +#endif // GS_TYPES_H \ No newline at end of file diff --git a/src/gs_libs/gs_vector_matrix.h b/src/gs_libs/gs_vector_matrix.h index 1f187bc..c089100 100644 --- a/src/gs_libs/gs_vector_matrix.h +++ b/src/gs_libs/gs_vector_matrix.h @@ -105,25 +105,12 @@ union v4 union m33 { - struct - { - float a; float b; float c; - float d; float e; float f; - float g; float h; float i; - }; - float E[9]; + float E[3][3]; }; union m44 { - struct - { - float a; float b; float c; float d; - float e; float f; float g; float h; - float i; float j; float k; float l; - float m; float n; float o; float p; - }; - float E[16]; + float E[4][4]; }; ////////////////////////////////////// @@ -648,10 +635,10 @@ PointIsInRange (v2 _P, v2 _Min, v2 _Max) static bool PointIsInRangeSafe (v2 _P, v2 _Min, v2 _Max) { - s32 MinX = GSMin(_Min.x, _Max.x); - s32 MinY = GSMin(_Min.y, _Max.y); - s32 MaxX = GSMax(_Min.x, _Max.x); - s32 MaxY = GSMax(_Min.y, _Max.y); + s32 MinX = Min(_Min.x, _Max.x); + s32 MinY = Min(_Min.y, _Max.y); + s32 MaxX = Max(_Min.x, _Max.x); + s32 MaxY = Max(_Min.y, _Max.y); return (_P.x >= MinX && _P.x <= MaxX && _P.y >= MinY && _P.y <= MaxY); @@ -1438,11 +1425,11 @@ void TestVectorMatrixMultiplication () // Utility Functions TestClean((GSSqrt(4.f) == 2.f), "Vector Square Root"); - TestClean((GSLerp(0.f, 1.f, .5f) == .5f), "Vector Lerp"); - TestClean((GSMin(-.25f, 5.f) == -.25f), "Vector Min"); - TestClean((GSMax(-.25f, 5.f) == 5.f), "Vector Max"); - TestClean((GSClamp(-2.f, -3.f, 5.f) == -2.f), "Vector Clamp, Lower Than Range"); - TestClean((GSClamp(-2.f, 6.f, 5.f) == 5.f), "Vector Clamp, Higher Than Range"); + TestClean((Lerp(0.f, 1.f, .5f) == .5f), "Vector Lerp"); + TestClean((Min(-.25f, 5.f) == -.25f), "Vector Min"); + TestClean((Max(-.25f, 5.f) == 5.f), "Vector Max"); + TestClean((Clamp(-2.f, -3.f, 5.f) == -2.f), "Vector Clamp, Lower Than Range"); + TestClean((Clamp(-2.f, 6.f, 5.f) == 5.f), "Vector Clamp, Higher Than Range"); ////////////////////////////// // Vector Functions diff --git a/src/gs_libs/gs_win32.cpp b/src/gs_libs/gs_win32.cpp index e2df025..b96ae2e 100644 --- a/src/gs_libs/gs_win32.cpp +++ b/src/gs_libs/gs_win32.cpp @@ -27,7 +27,7 @@ struct window char* ClassName; s32 Width; s32 Height; - WNDPROC WindowEventHandler; + WNDPROC WindowEventHandler; WNDCLASS Class; HWND Handle; @@ -45,7 +45,7 @@ struct handle_window_msg_result #endif }; -global_variable win32_state GlobalWin32State; +global win32_state GlobalWin32State; // Utility internal s32 Win32StringLength(char* String); @@ -66,15 +66,14 @@ internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer // Memory -internal PLATFORM_ALLOC(Win32Alloc); -internal PLATFORM_FREE(Win32Free); -internal PLATFORM_REALLOC(Win32Realloc); +internal ALLOCATOR_ALLOC(Win32Alloc); +internal ALLOCATOR_FREE(Win32Free); /// // Utils /// -internal s32 +internal s32 Win32StringLength(char* String) { char* At = String; @@ -82,7 +81,7 @@ Win32StringLength(char* String) return At - String; } -internal s32 +internal s32 Win32ConcatStrings(s32 ALength, char* A, s32 BLength, char* B, s32 DestLength, char* Dest) { char* Dst = Dest; @@ -110,7 +109,7 @@ Win32ConcatStrings(s32 ALength, char* A, s32 BLength, char* B, s32 DestLength, c /// internal window -Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, +Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, WNDPROC WindowEventHandler) { window Result = {}; @@ -131,14 +130,14 @@ Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, Result.Handle = CreateWindowEx( 0, Result.Class.lpszClassName, - WindowName, + WindowName, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, 0, - 0, + 0, HInstance, 0); Result.DeviceContext = GetDC(Result.Handle); @@ -276,9 +275,9 @@ Win32HandleWindowsEvents ( ) { handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault( - WindowHandle, - Msg, - wParam, + WindowHandle, + Msg, + wParam, lParam); if (!EventResult.Handled) @@ -298,92 +297,92 @@ Win32GetKeyCode (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar) if (!TranslateToChar) { - if (Win32VirtualKey == VK_SPACE) { Result = KeyCode_Space; } + if (Win32VirtualKey == VK_SPACE) { Result = KeyCode_Space; } } if (Win32VirtualKey == VK_CAPITAL) { Result = KeyCode_CapsLock; } else if (Win32VirtualKey == VK_TAB) { Result = KeyCode_Tab; } - else if (Win32VirtualKey == VK_LSHIFT) { Result = KeyCode_LeftShift; } + else if (Win32VirtualKey == VK_LSHIFT) { Result = KeyCode_LeftShift; } else if (Win32VirtualKey == VK_RSHIFT) { Result = KeyCode_RightShift; } - else if (Win32VirtualKey == VK_LCONTROL) { Result = KeyCode_LeftCtrl; } + else if (Win32VirtualKey == VK_LCONTROL) { Result = KeyCode_LeftCtrl; } else if (Win32VirtualKey == VK_RCONTROL) { Result = KeyCode_RightCtrl; } // TODO(Peter): support the function key? - //else if (Win32VirtualKey == VK_) { Result = KeyCode_Fn; } + //else if (Win32VirtualKey == VK_) { Result = KeyCode_Fn; } - else if (Win32VirtualKey == VK_MENU) { Result = KeyCode_Alt; } - else if (Win32VirtualKey == VK_PRIOR) { Result = KeyCode_PageUp; } + else if (Win32VirtualKey == VK_MENU) { Result = KeyCode_Alt; } + else if (Win32VirtualKey == VK_PRIOR) { Result = KeyCode_PageUp; } else if (Win32VirtualKey == VK_NEXT) { Result = KeyCode_PageDown; } - else if (Win32VirtualKey == VK_BACK) { Result = KeyCode_Backspace; } + else if (Win32VirtualKey == VK_BACK) { Result = KeyCode_Backspace; } else if (Win32VirtualKey == VK_DELETE) { Result = KeyCode_Delete; } else if (Win32VirtualKey == VK_RETURN) { Result = KeyCode_Enter; } - else if (Win32VirtualKey == VK_F1) { Result = KeyCode_F1; } - else if (Win32VirtualKey == VK_F2) { Result = KeyCode_F2; } - else if (Win32VirtualKey == VK_F3) { Result = KeyCode_F3; } - else if (Win32VirtualKey == VK_F4) { Result = KeyCode_F4; } - else if (Win32VirtualKey == VK_F5) { Result = KeyCode_F5; } - else if (Win32VirtualKey == VK_F6) { Result = KeyCode_F6; } + else if (Win32VirtualKey == VK_F1) { Result = KeyCode_F1; } + else if (Win32VirtualKey == VK_F2) { Result = KeyCode_F2; } + else if (Win32VirtualKey == VK_F3) { Result = KeyCode_F3; } + else if (Win32VirtualKey == VK_F4) { Result = KeyCode_F4; } + else if (Win32VirtualKey == VK_F5) { Result = KeyCode_F5; } + else if (Win32VirtualKey == VK_F6) { Result = KeyCode_F6; } else if (Win32VirtualKey == VK_F7) { Result = KeyCode_F7; } - else if (Win32VirtualKey == VK_F8) { Result = KeyCode_F8; } - else if (Win32VirtualKey == VK_F9) { Result = KeyCode_F9; } - else if (Win32VirtualKey == VK_F10) { Result = KeyCode_F10; } - else if (Win32VirtualKey == VK_F11) { Result = KeyCode_F11; } - else if (Win32VirtualKey == VK_F12) { Result = KeyCode_F12; } + else if (Win32VirtualKey == VK_F8) { Result = KeyCode_F8; } + else if (Win32VirtualKey == VK_F9) { Result = KeyCode_F9; } + else if (Win32VirtualKey == VK_F10) { Result = KeyCode_F10; } + else if (Win32VirtualKey == VK_F11) { Result = KeyCode_F11; } + else if (Win32VirtualKey == VK_F12) { Result = KeyCode_F12; } if (!TranslateToChar) { - if (Win32VirtualKey == 0x30) { Result = KeyCode_0; } - else if (Win32VirtualKey == 0x31) { Result = KeyCode_1; } - else if (Win32VirtualKey == 0x32) { Result = KeyCode_2; } - else if (Win32VirtualKey == 0x33) { Result = KeyCode_3; } - else if (Win32VirtualKey == 0x34) { Result = KeyCode_4; } - else if (Win32VirtualKey == 0x35) { Result = KeyCode_5; } - else if (Win32VirtualKey == 0x36) { Result = KeyCode_6; } + if (Win32VirtualKey == 0x30) { Result = KeyCode_0; } + else if (Win32VirtualKey == 0x31) { Result = KeyCode_1; } + else if (Win32VirtualKey == 0x32) { Result = KeyCode_2; } + else if (Win32VirtualKey == 0x33) { Result = KeyCode_3; } + else if (Win32VirtualKey == 0x34) { Result = KeyCode_4; } + else if (Win32VirtualKey == 0x35) { Result = KeyCode_5; } + else if (Win32VirtualKey == 0x36) { Result = KeyCode_6; } else if (Win32VirtualKey == 0x37) { Result = KeyCode_7; } - else if (Win32VirtualKey == 0x38) { Result = KeyCode_8; } + else if (Win32VirtualKey == 0x38) { Result = KeyCode_8; } else if (Win32VirtualKey == 0x39) { Result = KeyCode_9; } - else if (Win32VirtualKey == 0x41) { Result = KeyCode_A; } - else if (Win32VirtualKey == 0x42) { Result = KeyCode_B; } - else if (Win32VirtualKey == 0x43) { Result = KeyCode_C; } - else if (Win32VirtualKey == 0x44) { Result = KeyCode_D; } - else if (Win32VirtualKey == 0x45) { Result = KeyCode_E; } - else if (Win32VirtualKey == 0x46) { Result = KeyCode_F; } - else if (Win32VirtualKey == 0x47) { Result = KeyCode_G; } + else if (Win32VirtualKey == 0x41) { Result = KeyCode_A; } + else if (Win32VirtualKey == 0x42) { Result = KeyCode_B; } + else if (Win32VirtualKey == 0x43) { Result = KeyCode_C; } + else if (Win32VirtualKey == 0x44) { Result = KeyCode_D; } + else if (Win32VirtualKey == 0x45) { Result = KeyCode_E; } + else if (Win32VirtualKey == 0x46) { Result = KeyCode_F; } + else if (Win32VirtualKey == 0x47) { Result = KeyCode_G; } else if (Win32VirtualKey == 0x48) { Result = KeyCode_H; } - else if (Win32VirtualKey == 0x49) { Result = KeyCode_I; } - else if (Win32VirtualKey == 0x4A) { Result = KeyCode_J; } - else if (Win32VirtualKey == 0x4B) { Result = KeyCode_K; } - else if (Win32VirtualKey == 0x4C) { Result = KeyCode_L; } - else if (Win32VirtualKey == 0x4D) { Result = KeyCode_M; } - else if (Win32VirtualKey == 0x4E) { Result = KeyCode_N; } - else if (Win32VirtualKey == 0x4F) { Result = KeyCode_O; } - else if (Win32VirtualKey == 0x50) { Result = KeyCode_P; } - else if (Win32VirtualKey == 0x51) { Result = KeyCode_Q; } - else if (Win32VirtualKey == 0x52) { Result = KeyCode_R; } - else if (Win32VirtualKey == 0x53) { Result = KeyCode_S; } - else if (Win32VirtualKey == 0x54) { Result = KeyCode_T; } - else if (Win32VirtualKey == 0x55) { Result = KeyCode_U; } - else if (Win32VirtualKey == 0x56) { Result = KeyCode_V; } - else if (Win32VirtualKey == 0x57) { Result = KeyCode_W; } - else if (Win32VirtualKey == 0x58) { Result = KeyCode_X; } - else if (Win32VirtualKey == 0x59) { Result = KeyCode_Y; } + else if (Win32VirtualKey == 0x49) { Result = KeyCode_I; } + else if (Win32VirtualKey == 0x4A) { Result = KeyCode_J; } + else if (Win32VirtualKey == 0x4B) { Result = KeyCode_K; } + else if (Win32VirtualKey == 0x4C) { Result = KeyCode_L; } + else if (Win32VirtualKey == 0x4D) { Result = KeyCode_M; } + else if (Win32VirtualKey == 0x4E) { Result = KeyCode_N; } + else if (Win32VirtualKey == 0x4F) { Result = KeyCode_O; } + else if (Win32VirtualKey == 0x50) { Result = KeyCode_P; } + else if (Win32VirtualKey == 0x51) { Result = KeyCode_Q; } + else if (Win32VirtualKey == 0x52) { Result = KeyCode_R; } + else if (Win32VirtualKey == 0x53) { Result = KeyCode_S; } + else if (Win32VirtualKey == 0x54) { Result = KeyCode_T; } + else if (Win32VirtualKey == 0x55) { Result = KeyCode_U; } + else if (Win32VirtualKey == 0x56) { Result = KeyCode_V; } + else if (Win32VirtualKey == 0x57) { Result = KeyCode_W; } + else if (Win32VirtualKey == 0x58) { Result = KeyCode_X; } + else if (Win32VirtualKey == 0x59) { Result = KeyCode_Y; } else if (Win32VirtualKey == 0x5A) { Result = KeyCode_Z; } } if (NumpadValid) { - if (Win32VirtualKey == VK_NUMPAD0) { Result = KeyCode_Num0; } - else if (Win32VirtualKey == VK_NUMPAD1) { Result = KeyCode_Num1; } - else if (Win32VirtualKey == VK_NUMPAD2) { Result = KeyCode_Num2; } - else if (Win32VirtualKey == VK_NUMPAD3) { Result = KeyCode_Num3; } - else if (Win32VirtualKey == VK_NUMPAD4) { Result = KeyCode_Num4; } - else if (Win32VirtualKey == VK_NUMPAD5) { Result = KeyCode_Num5; } - else if (Win32VirtualKey == VK_NUMPAD6) { Result = KeyCode_Num6; } - else if (Win32VirtualKey == VK_NUMPAD7) { Result = KeyCode_Num7; } - else if (Win32VirtualKey == VK_NUMPAD8) { Result = KeyCode_Num8; } + if (Win32VirtualKey == VK_NUMPAD0) { Result = KeyCode_Num0; } + else if (Win32VirtualKey == VK_NUMPAD1) { Result = KeyCode_Num1; } + else if (Win32VirtualKey == VK_NUMPAD2) { Result = KeyCode_Num2; } + else if (Win32VirtualKey == VK_NUMPAD3) { Result = KeyCode_Num3; } + else if (Win32VirtualKey == VK_NUMPAD4) { Result = KeyCode_Num4; } + else if (Win32VirtualKey == VK_NUMPAD5) { Result = KeyCode_Num5; } + else if (Win32VirtualKey == VK_NUMPAD6) { Result = KeyCode_Num6; } + else if (Win32VirtualKey == VK_NUMPAD7) { Result = KeyCode_Num7; } + else if (Win32VirtualKey == VK_NUMPAD8) { Result = KeyCode_Num8; } else if (Win32VirtualKey == VK_NUMPAD9) { Result = KeyCode_Num9; } } @@ -501,14 +500,14 @@ HandleWindowsMessage ( // NOTE(Peter): Always setting this to true becuase windows is stupid and doesn't // pass the press/release bit through correctly. So now the KEYDOWN/KEYUP Messages above // only translate the message to a WM_CHAR message if its a key down. Since we clear all - // keystates to false at the beginning of an input frame, this will make transitions + // keystates to false at the beginning of an input frame, this will make transitions // get registered correctly. Input.New->KeyStates[KeyIndex] = true; Result.NeedsUpdate = true; } else { - printf("Translated Char Not Recognized: %c\n", TranslatedChar); + printf("Translated Char Not Recognized: %c\n", TranslatedChar); } */ }break; @@ -570,14 +569,14 @@ Win32DisplayBufferInWindow(win32_offscreen_buffer* Win32Buffer, window Window) } ///////////////////////////////////////// -// +// // Open GL // ///////////////////////////////////////// -internal void -OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, +internal void +OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, u8* UVs, s32 UVElements, u8* Colors, s32 ColorsElements, s32 TriCount) @@ -599,7 +598,7 @@ OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, } internal void -OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, +OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { @@ -621,7 +620,7 @@ OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, } internal void -OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2, +OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2, v2 UV0, v2 UV1, v2 UV2, v4 C0, v4 C1, v4 C2) { @@ -668,14 +667,14 @@ SubmitTexture (u8* Memory, s32 Width, s32 Height) { s32 TextureHandle = NextTextureHandle++; glBindTexture(GL_TEXTURE_2D, TextureHandle); - glTexImage2D(GL_TEXTURE_2D, + glTexImage2D(GL_TEXTURE_2D, 0, // mip map level - GL_RGBA8, - Width, - Height, + GL_RGBA8, + Width, + Height, 0, // border - GL_RGBA, - GL_UNSIGNED_BYTE, + GL_RGBA, + GL_UNSIGNED_BYTE, Memory); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/src/meta/foldhaus_meta.cpp b/src/meta/foldhaus_meta.cpp index 3206405..47eb1a1 100644 --- a/src/meta/foldhaus_meta.cpp +++ b/src/meta/foldhaus_meta.cpp @@ -12,7 +12,7 @@ internal void GenerateNodeMetaInfo (gsm_code_generator* NodeTypeGen, string_builder* NodeSpecificationGen, string_builder* CallNodeProcGen, gs_meta_preprocessor Meta) { // TODO(Peter): Create a FilterTypesByTag function to create a contiguous array - // of type_definition** + // of type_definition** WriteF(NodeSpecificationGen, "static node_specification_ NodeSpecifications[] = {\n"); @@ -218,8 +218,8 @@ GeneratePanelMetaInfo(gs_meta_preprocessor Meta, string_builder* PanelEnumGen, s } WriteF(PanelEnumGen, "enum panel_type {\n"); - WriteF(PanelCodeGen, "global_variable s32 GlobalPanelDefsCount = %d;\n", Panels.Used); - WriteF(PanelCodeGen, "global_variable panel_definition GlobalPanelDefs[] = {\n"); + WriteF(PanelCodeGen, "global s32 GlobalPanelDefsCount = %d;\n", Panels.Used); + WriteF(PanelCodeGen, "global panel_definition GlobalPanelDefs[] = {\n"); for (u32 i = 0; i < Panels.Used; i++) { panel_elements* Panel = Panels.GetElementAtIndex(i); diff --git a/src/meta/gs_meta_error.h b/src/meta/gs_meta_error.h index 2648959..f4f1c68 100644 --- a/src/meta/gs_meta_error.h +++ b/src/meta/gs_meta_error.h @@ -14,13 +14,32 @@ struct errors u32 Used; }; -internal void +#define ErrorReallocArray(base, type, oldcount, newcount) (type*)ErrorRealloc_((u8*)(base), (u64)(sizeof(type) * oldcount), (u64)(sizeof(type) * newcount)) +internal u8* +ErrorRealloc_(u8* Base, u64 OldSize, u64 NewSize) +{ + Assert(NewSize > 0); + u8* Result = (u8*)malloc(NewSize); + if (Base != 0 && OldSize > 0) + { + GSMemCopy(Base, Result, OldSize); + free(Base); + } + return Result; +} + +internal void PushFError (errors* Errors, char* Format, ...) { if (Errors->Used >= (Errors->BuffersCount * ERROR_BUFFER_SIZE)) { +#if 0 Errors->BuffersCount += 1; Errors->Buffers = (error_buffer*)realloc(Errors->Buffers, sizeof(error_buffer*) * Errors->BuffersCount); +#else + Errors->Buffers = ErrorReallocArray(Errors->Buffers, error_buffer, Errors->BuffersCount, Errors->BuffersCount + 1); + Errors->BuffersCount += 1; +#endif error_buffer* NewBuffer = Errors->Buffers + (Errors->BuffersCount - 1); NewBuffer->Backbuffer = (char*)malloc(sizeof(char) * ERROR_MAX_LENGTH * ERROR_BUFFER_SIZE); @@ -28,8 +47,8 @@ PushFError (errors* Errors, char* Format, ...) for (u32 i = 0; i < ERROR_BUFFER_SIZE; i++) { - NewBuffer->Contents[i].Memory = NewBuffer->Backbuffer + (i * ERROR_MAX_LENGTH); - NewBuffer->Contents[i].Max = ERROR_MAX_LENGTH; + NewBuffer->Contents[i].Str = NewBuffer->Backbuffer + (i * ERROR_MAX_LENGTH); + NewBuffer->Contents[i].Size = ERROR_MAX_LENGTH; NewBuffer->Contents[i].Length = 0; } } diff --git a/src/meta/gs_meta_lexer.h b/src/meta/gs_meta_lexer.h index 557f245..60e6647 100644 --- a/src/meta/gs_meta_lexer.h +++ b/src/meta/gs_meta_lexer.h @@ -1,7 +1,7 @@ struct token_selection_spec { b32 MatchText; - string Text; + gs_string Text; }; internal s32 @@ -59,7 +59,7 @@ EatIdentifier (tokenizer* Tokenizer) { s32 Length = 0; - while (Tokenizer->At[0] && + while (Tokenizer->At[0] && (IsAlpha(Tokenizer->At[0]) || IsNumericExtended(Tokenizer->At[0]))) { ++Tokenizer->At; @@ -135,7 +135,7 @@ GetNextToken (tokenizer* Tokenizer) char C = Tokenizer->At[0]; ++Tokenizer->At; - if (C == 0) { Result.Type = Token_EndOfStream; } + if (C == 0) { Result.Type = Token_EndOfStream; } else if (C == '(') { Result.Type = Token_LeftParen; } else if (C == ')') { Result.Type = Token_RightParen; } else if (C == '[') { Result.Type = Token_LeftSquareBracket; } @@ -145,9 +145,9 @@ GetNextToken (tokenizer* Tokenizer) else if (C == ';') { Result.Type = Token_Semicolon; } else if (C == ',') { Result.Type = Token_Comma; } else if (C == '.') { Result.Type = Token_Period; } - else if (C == '-' && Tokenizer->At[0] && Tokenizer->At[0] == '>') - { - Result.Type = Token_PointerReference; + else if (C == '-' && Tokenizer->At[0] && Tokenizer->At[0] == '>') + { + Result.Type = Token_PointerReference; Result.Text.Length = 2; ++Tokenizer->At; } @@ -157,72 +157,72 @@ GetNextToken (tokenizer* Tokenizer) EatWhitespace(Tokenizer); if (TokenAtEquals(Tokenizer, "define")) - { - Result.Type = Token_PoundDefine; + { + Result.Type = Token_PoundDefine; EatPreprocessor(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "undef")) - { - Result.Type = Token_PoundUndef; + { + Result.Type = Token_PoundUndef; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "include")) - { - Result.Type = Token_PoundInclude; - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + { + Result.Type = Token_PoundInclude; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "ifdef")) - { - Result.Type = Token_PoundIfDef; + { + Result.Type = Token_PoundIfDef; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "ifndef")) - { - Result.Type = Token_PoundIfNDef; + { + Result.Type = Token_PoundIfNDef; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "if")) - { - Result.Type = Token_PoundIf; + { + Result.Type = Token_PoundIf; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "elif")) - { - Result.Type = Token_PoundElif; + { + Result.Type = Token_PoundElif; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "else")) - { - Result.Type = Token_PoundElse; + { + Result.Type = Token_PoundElse; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "endif")) - { - Result.Type = Token_PoundEndif; + { + Result.Type = Token_PoundEndif; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "error")) - { - Result.Type = Token_PoundError; + { + Result.Type = Token_PoundError; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } else if (TokenAtEquals(Tokenizer, "pragma")) - { - Result.Type = Token_PoundPragma; + { + Result.Type = Token_PoundPragma; EatToNewLine(Tokenizer); - Result.Text.Length = Tokenizer->At - Result.Text.Memory; + Result.Text.Length = Tokenizer->At - Result.Text.Str; } } - else if (IsNumeric(C)) + else if (IsNumericExtended(C)) { Result.Type = Token_Number; @@ -233,7 +233,7 @@ GetNextToken (tokenizer* Tokenizer) else if (C == '\'') { Result.Type = Token_Char; - Result.Text.Memory = Tokenizer->At; + Result.Text.Str = Tokenizer->At; if (Tokenizer->At[0] && Tokenizer->At[0] == '\\') { ++Tokenizer->At; @@ -245,7 +245,7 @@ GetNextToken (tokenizer* Tokenizer) { Result.Type = Token_String; // replace the length added by the quote - Result.Text.Memory = Tokenizer->At; + Result.Text.Str = Tokenizer->At; Result.Text.Length = EatString(Tokenizer); } // NOTE(Peter): This is after comment parsing so that the division operator diff --git a/src/meta/gs_meta_type_table.h b/src/meta/gs_meta_type_table.h index 3eb2140..d0d32d9 100644 --- a/src/meta/gs_meta_type_table.h +++ b/src/meta/gs_meta_type_table.h @@ -10,7 +10,7 @@ enum type_definition_type TypeDef_Invalid, // NOTE(Peter): tokens with this type require fixup later - TypeDef_Unknown, + TypeDef_Unknown, TypeDef_Enum, TypeDef_Struct, TypeDef_Union, @@ -59,7 +59,7 @@ struct meta_tag struct variable_decl { - // NOTE(Peter): Because of the way the tokenizer works, we don't lex and parse + // NOTE(Peter): Because of the way the tokenizer works, we don't lex and parse // at the same time. This means that not all types will be able to be matched // up on the first pass through. A TypeIndex of -1 means we need to fixup that // type at a later time @@ -161,7 +161,7 @@ HashIdentifier(string Identifier) u32 IdentHash = HashString(Identifier); if (IdentHash == 0) { - // NOTE(Peter): We are excluding a has of zero so taht + // NOTE(Peter): We are excluding a has of zero so taht // the type_table_handle where BucketIndex and IndexInBucket // are both zero is an invalid handle IdentHash += 1; @@ -301,7 +301,7 @@ FindSlotForTypeIdentifier(u32 IdentHash, type_table* TypeTable) Result.IndexInBucket = Index; } - // NOTE(Peter): Because we are growing the hashtable, this should never be an invalid + // NOTE(Peter): Because we are growing the hashtable, this should never be an invalid // type handle Assert(TypeHandleIsValid(Result)); return Result; @@ -391,7 +391,7 @@ PushMetaTagOnTable(meta_tag Tag, type_table* TypeTable) } // Guaranteed to return a valid result -internal type_definition* +internal type_definition* GetTypeDefinition(type_table_handle Handle, type_table TypeTable) { Assert(TypeHandleIsValid(Handle)); @@ -404,7 +404,7 @@ GetTypeDefinition(type_table_handle Handle, type_table TypeTable) } // May return zero -internal type_definition* +internal type_definition* GetTypeDefinitionUnsafe(type_table_handle Handle, type_table TypeTable) { type_definition* Result = 0; @@ -426,7 +426,7 @@ GetMetaTag(type_table_handle Handle, type_table TypeTable) return Result; } -internal type_definition* +internal type_definition* GetTypeDefinition(string Identifier, type_table TypeTable) { type_definition* Result = 0; @@ -588,21 +588,21 @@ internal void FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_table TypeTable, errors* Errors) { // NOTE(Peter): There are a lot of cases where struct members which are pointers - // to other structs cause interesting behavior here. + // to other structs cause interesting behavior here. // For example: // struct foo { foo* Next; } // could cause infinite loops if we try and fixup all structs with a size of 0 - // which would happen in this case, because we wouldn't have parsed foo's size + // which would happen in this case, because we wouldn't have parsed foo's size // yet, but would begin fixing up foo because of the type of Next // Another example: // typedef struct bar bar; // struct foo { bar* Bar; } // struct bar { foo* Foo; } - // causes the exact same problem, but we cant detect it by just excluding - // fixing up StructIndex recursively. - // + // causes the exact same problem, but we cant detect it by just excluding + // fixing up StructIndex recursively. + // // TL;DR - // The solution I've chosen to go with is just exclude all pointer members from + // The solution I've chosen to go with is just exclude all pointer members from // causing recursive fixups. Those types should be fixed up at some point in the // process, and we already know how big a pointer is in memory, no matter the type if (!Member->Pointer) @@ -617,7 +617,7 @@ FixupStructMember (variable_decl* Member, type_definition* MemberTypeDef, type_t { FixUpUnionSize(Member->TypeHandle, TypeTable, Errors); } - else + else { if (MemberTypeDef->Type == TypeDef_Unknown) { @@ -672,7 +672,7 @@ FixUpStructSize (type_table_handle TypeHandle, type_table TypeTable, errors* Err { // NOTE(Peter): Because its recursive (it makes sure all type sizes become known // if it needs them) we should never get to the end of this function and not have - // the ability to tell how big something is. + // the ability to tell how big something is. // TODO(Peter): We don't parse all types yet however, so for now, this is just an alert, // not an assert; #if 0