fixed error causing crashes when you exit the file viewer without selecting a file. Issue was when we tried to check if a string that had no data pointer was null terminated

This commit is contained in:
PS 2021-01-16 19:45:13 -08:00
parent 3c1110adfd
commit 99c62292a4
7 changed files with 205 additions and 259 deletions

View File

@ -115,203 +115,6 @@ Editor_Update(app_state* State, context* Context, input_queue InputQueue)
Editor_HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context);
}
internal void
Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ClippingBox, v4 Color)
{
gs_string Temp = PushString(State->Transient, 256);
PrintF(&Temp, "%d", Widget.Id.Id);
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer,
Widget.String.Length,
State->Interface.Style.Font->BitmapMemory,
State->Interface.Style.Font->BitmapTextureHandle,
State->Interface.Style.Font->BitmapWidth,
State->Interface.Style.Font->BitmapHeight,
State->Interface.Style.Font->BitmapBytesPerPixel,
State->Interface.Style.Font->BitmapStride);
v2 RegisterPosition = Widget.Bounds.Min + State->Interface.Style.Margin;
switch (Widget.Alignment)
{
case Align_Left:
{
RegisterPosition = DrawStringLeftAligned(&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color);
}break;
case Align_Right:
{
RegisterPosition = DrawStringRightAligned(&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color);
}break;
InvalidDefaultCase;
}
}
internal void
Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ParentClipBounds)
{
rect2 WidgetParentUnion = Widget.Bounds;
WidgetParentUnion = Rect2Union(Widget.Bounds, ParentClipBounds);
if (!Widget.Parent || (Rect2Area(WidgetParentUnion) > 0))
{
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawBackground))
{
v4 Color = State->Interface.Style.ButtonColor_Inactive;
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.HotWidget))
{
Color = State->Interface.Style.ButtonColor_Active;
}
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget))
{
Color = State->Interface.Style.ButtonColor_Selected;
}
PushRenderQuad2DClipped(RenderBuffer, Widget.Bounds, WidgetParentUnion, Color);
}
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
{
v4 Color = State->Interface.Style.TextColor;
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, WidgetParentUnion, Color);
}
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) ||
ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawVerticalFill))
{
v4 Color = State->Interface.Style.ButtonColor_Selected;
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.HotWidget) ||
ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget))
{
Color = WhiteV4;
}
rect2 FillBounds = {};
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill))
{
FillBounds.Min.y = Widget.Bounds.Min.y;
FillBounds.Max.y = Widget.Bounds.Max.y;
r32 FillToPoint = LerpR32(Widget.FillPercent, Widget.Bounds.Min.x, Widget.Bounds.Max.x);
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillReversed))
{
FillBounds.Min.x = FillToPoint;
FillBounds.Max.x = Widget.Bounds.Max.x;
}
else if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillAsHandle))
{
FillBounds.Min.x = FillToPoint - 5;
FillBounds.Max.x = FillToPoint + 5;
}
else
{
FillBounds.Min.x = Widget.Bounds.Min.x;
FillBounds.Max.x = FillToPoint;
}
}
else if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawVerticalFill))
{
FillBounds.Min.x = Widget.Bounds.Min.x;
FillBounds.Max.x = Widget.Bounds.Max.x;
r32 FillToPoint = LerpR32(Widget.FillPercent, Widget.Bounds.Min.y, Widget.Bounds.Max.y);
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillReversed))
{
FillBounds.Min.y = FillToPoint;
FillBounds.Max.y = Widget.Bounds.Max.y;
}
else if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillAsHandle))
{
FillBounds.Min.y = FillToPoint - 5;
FillBounds.Max.y = FillToPoint + 5;
}
else
{
FillBounds.Min.y = Widget.Bounds.Min.y;
FillBounds.Max.y = FillToPoint;
}
}
rect2 ClippedFillBounds = Rect2Union(FillBounds, WidgetParentUnion);
PushRenderQuad2D(RenderBuffer, ClippedFillBounds, Color);
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
{
// TODO(pjs): add this color to the style
v4 TextColor = BlackV4;
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, ClippedFillBounds, TextColor);
}
}
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawOutline))
{
// TODO(pjs): replace these with values from the style
r32 Thickness = 1.0f;
v4 Color = WhiteV4;
PushRenderBoundingBox2D(RenderBuffer, WidgetParentUnion.Min, WidgetParentUnion.Max, Thickness, Color);
}
}
if (Widget.ChildrenRoot)
{
Editor_DrawWidget(State, Context, RenderBuffer, *Widget.ChildrenRoot, WidgetParentUnion);
}
if (Widget.Next)
{
Editor_DrawWidget(State, Context, RenderBuffer, *Widget.Next, ParentClipBounds);
}
}
#include "../interface_test.cpp"
FOLDHAUS_INPUT_COMMAND_PROC(ActiveWidget_TypeCharacter)
{
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
ui_widget_retained_state* WidgetState = ui_GetRetainedState(&State->Interface, ActiveWidget->Id);
if (WidgetState)
{
char AsciiValue = CharacterFromKeyCode(Event.Key);
if (AsciiValue)
{
OutChar(&WidgetState->EditString, AsciiValue);
}
}
}
FOLDHAUS_INPUT_COMMAND_PROC(ActiveWidget_DeleteBackwards)
{
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
ui_widget_retained_state* WidgetState = ui_GetRetainedState(&State->Interface, ActiveWidget->Id);
if (WidgetState)
{
WidgetState->EditString.Length -= 1;
}
}
FOLDHAUS_INPUT_COMMAND_PROC(ActiveWidget_EndTypingMode)
{
DeactivateCurrentOperationMode(&State->Modes);
}
OPERATION_RENDER_PROC(ActiveWidget_EndTypingMode)
{
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
ui_widget* LastActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.LastActiveWidget);
if (ActiveWidget == 0 && LastActiveWidget != 0)
{
// if there was an active widget last frame that was typable, we want to deactivate the typing mode
DeactivateCurrentOperationMode(&State->Modes);
}
}
input_command InterfaceTypingCommands [] = {
{ KeyCode_A, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
{ KeyCode_B, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
{ KeyCode_C, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
{ KeyCode_D, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
{ KeyCode_E, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_TypeCharacter },
{ KeyCode_Enter, KeyCode_Invalid, Command_Began, ActiveWidget_EndTypingMode },
{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, ActiveWidget_DeleteBackwards },
};
internal void
Editor_Render(app_state* State, context* Context, render_command_buffer* RenderBuffer)
{
@ -319,45 +122,30 @@ Editor_Render(app_state* State, context* Context, render_command_buffer* RenderB
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
PushRenderClearScreen(RenderBuffer);
#if 0
InterfaceTest_Render(State, Context, RenderBuffer);
#else
ui_InterfaceReset(&State->Interface);
State->Interface.RenderBuffer = RenderBuffer;
ui_PushLayout(&State->Interface, Context->WindowBounds, LayoutDirection_TopDown, MakeString("Editor Layout"));
DrawAllPanels(State->PanelSystem, RenderBuffer, &Context->Mouse, State, *Context);
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
{
operation_mode OperationMode = State->Modes.ActiveModes[m];
if (OperationMode.Render != 0)
DrawAllPanels(State->PanelSystem, RenderBuffer, &Context->Mouse, State, *Context);
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
{
OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context);
operation_mode OperationMode = State->Modes.ActiveModes[m];
if (OperationMode.Render != 0)
{
OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context);
}
}
}
ui_PopLayout(&State->Interface, MakeString("Editor Layout"));
#endif
// Draw the Interface
if (State->Interface.DrawOrderRoot != 0)
{
ui_widget Widget = *State->Interface.DrawOrderRoot;
Editor_DrawWidget(State, Context, RenderBuffer, Widget, Context->WindowBounds);
#if 0
// TODO(pjs): got distracted halfway through getting typing input into the interface
if (ui_WidgetIdsEqual(State->Interface.ActiveWidget, State->Interface.LastActiveWidget))
{
ui_widget* ActiveWidget = ui_InterfaceGetWidgetWithId(&State->Interface, State->Interface.ActiveWidget);
if (ActiveWidget != 0 &&
ui_WidgetIsFlagSet(*ActiveWidget, UIWidgetFlag_Typable))
{
operation_mode* TypingMode = ActivateOperationModeWithCommands(&State->Modes, InterfaceTypingCommands, ActiveWidget_EndTypingMode);
}
}
#endif
}
Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext);

View File

@ -0,0 +1,151 @@
//
// File: foldhaus_editor_draw.h
// Author: Peter Slattery
// Creation Date: 2021-01-16
//
#ifndef FOLDHAUS_EDITOR_DRAW_H
internal void
Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ClippingBox, v4 Color)
{
gs_string Temp = PushString(State->Transient, 256);
PrintF(&Temp, "%d", Widget.Id.Id);
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer,
Widget.String.Length,
State->Interface.Style.Font->BitmapMemory,
State->Interface.Style.Font->BitmapTextureHandle,
State->Interface.Style.Font->BitmapWidth,
State->Interface.Style.Font->BitmapHeight,
State->Interface.Style.Font->BitmapBytesPerPixel,
State->Interface.Style.Font->BitmapStride);
v2 RegisterPosition = Widget.Bounds.Min + State->Interface.Style.Margin;
switch (Widget.Alignment)
{
case Align_Left:
{
RegisterPosition = DrawStringLeftAligned(&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color);
}break;
case Align_Right:
{
RegisterPosition = DrawStringRightAligned(&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color);
}break;
InvalidDefaultCase;
}
}
enum widget_fill_dir
{
WidgetFill_Horizontal = 0,
WidgetFill_Vertical = 1,
};
internal rect2
Editor_GetWidgetFillBounds(ui_widget Widget)
{
Assert(ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) || ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawVerticalFill));
rect2 Result = {};
widget_fill_dir Dir = WidgetFill_Horizontal;
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill)) { Dir = WidgetFill_Vertical; }
widget_fill_dir OtherDir = (widget_fill_dir)(WidgetFill_Vertical - Dir);
Result.Min.E[Dir] = Widget.Bounds.Min.E[Dir];
Result.Max.E[Dir] = Widget.Bounds.Max.E[Dir];
r32 FillToPoint = LerpR32(Widget.FillPercent, Widget.Bounds.Min.E[OtherDir], Widget.Bounds.Max.E[OtherDir]);
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillReversed))
{
Result.Min.E[OtherDir] = FillToPoint;
Result.Max.E[OtherDir] = Widget.Bounds.Max.E[OtherDir];
}
else if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillAsHandle))
{
Result.Min.E[OtherDir] = FillToPoint - 5;
Result.Max.E[OtherDir] = FillToPoint + 5;
}
else
{
Result.Min.E[OtherDir] = Widget.Bounds.Min.E[OtherDir];
Result.Max.E[OtherDir] = FillToPoint;
}
return Result;
}
internal void
Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ParentClipBounds)
{
rect2 WidgetParentUnion = Widget.Bounds;
WidgetParentUnion = Rect2Union(Widget.Bounds, ParentClipBounds);
if (!Widget.Parent || (Rect2Area(WidgetParentUnion) > 0))
{
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawBackground))
{
v4 Color = State->Interface.Style.ButtonColor_Inactive;
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.HotWidget))
{
Color = State->Interface.Style.ButtonColor_Active;
}
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget))
{
Color = State->Interface.Style.ButtonColor_Selected;
}
PushRenderQuad2DClipped(RenderBuffer, Widget.Bounds, WidgetParentUnion, Color);
}
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
{
v4 Color = State->Interface.Style.TextColor;
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, WidgetParentUnion, Color);
}
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) ||
ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawVerticalFill))
{
v4 Color = State->Interface.Style.ButtonColor_Selected;
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.HotWidget) ||
ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget))
{
Color = WhiteV4;
}
rect2 FillBounds = Editor_GetWidgetFillBounds(Widget);
rect2 ClippedFillBounds = Rect2Union(FillBounds, WidgetParentUnion);
PushRenderQuad2D(RenderBuffer, ClippedFillBounds, Color);
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
{
// TODO(pjs): add this color to the style
v4 TextColor = BlackV4;
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, ClippedFillBounds, TextColor);
}
}
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawOutline))
{
// TODO(pjs): replace these with values from the style
r32 Thickness = 1.0f;
v4 Color = WhiteV4;
PushRenderBoundingBox2D(RenderBuffer, WidgetParentUnion.Min, WidgetParentUnion.Max, Thickness, Color);
}
}
if (Widget.ChildrenRoot)
{
Editor_DrawWidget(State, Context, RenderBuffer, *Widget.ChildrenRoot, WidgetParentUnion);
}
if (Widget.Next)
{
Editor_DrawWidget(State, Context, RenderBuffer, *Widget.Next, ParentClipBounds);
}
}
#define FOLDHAUS_EDITOR_DRAW_H
#endif // FOLDHAUS_EDITOR_DRAW_H

View File

@ -338,14 +338,16 @@ HandleMousePanelInteraction(panel_system* PanelSystem, rect2 WindowBounds, mouse
}
internal void
DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, v4 Color, mouse_state* Mouse, render_command_buffer* RenderBuffer)
DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, mouse_state* Mouse, render_command_buffer* RenderBuffer)
{
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);
v4 Color = BlackV4;
PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color);
v4 HighlightColor = v4{.3f, .3f, .3f, 1.f};
r32 HighlightThickness = 1;
if (MouseLeftEdgeDistance < PANEL_EDGE_CLICK_MAX_DISTANCE)
@ -428,6 +430,7 @@ RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_
internal void
DrawPanelRecursive(panel* Panel, render_command_buffer* RenderBuffer, mouse_state* Mouse, app_state* State, context Context)
{
rect2 Bounds = Panel->Bounds;
switch (Panel->SplitDirection)
{
case PanelSplit_Horizontal:
@ -440,11 +443,9 @@ DrawPanelRecursive(panel* Panel, render_command_buffer* RenderBuffer, mouse_stat
case PanelSplit_NoSplit:
{
panel* OverridePanel = Panel_GetModalOverride(Panel);
RenderPanel(OverridePanel, OverridePanel->Bounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse);
v4 BorderColor = v4{0, 0, 0, 1};
RenderPanel(OverridePanel, Bounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse);
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
DrawPanelBorder(*OverridePanel, OverridePanel->Bounds.Min, OverridePanel->Bounds.Max, BorderColor, Mouse, RenderBuffer);
DrawPanelBorder(*OverridePanel, Bounds.Min, Bounds.Max, Mouse, RenderBuffer);
}break;
InvalidDefaultCase;

View File

@ -94,6 +94,8 @@ AssemblyDebug_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren
InterfaceAssert(Interface->PerFrameMemory);
}
ui_RangeSlider(Interface, MakeString("Test"), .5f, 0, 1);
ui_PopLayout(Interface, MakeString("Assembly Debug Layout"));
}

View File

@ -89,38 +89,41 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu
{
file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state);
ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout"));
if (ui_Button(&State->Interface, MakeString("Exit")))
{
FileView_Exit_(Panel, State, Context);
}
// Header
ui_Label(&State->Interface, FileViewState->WorkingDirectory);
// File Display
for (u32 i = 0; i < FileViewState->FileNames.Count; i++)
{
gs_file_info File = FileViewState->FileNames.Values[i];
u32 LastSlashIndex = FindLast(File.Path, '\\');
gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length);
gs_string PathString = PushString(State->Transient, FileName.Length);
PrintF(&PathString, "%S", FileName);
if (ui_LayoutListButton(&State->Interface, PathString, i))
if (ui_Button(&State->Interface, MakeString("Exit")))
{
if (File.IsDirectory)
FileView_Exit_(Panel, State, Context);
}
// Header
ui_Label(&State->Interface, FileViewState->WorkingDirectory);
// File Display
ui_BeginList(&State->Interface, MakeString("Files"), 10, FileViewState->FileNames.Count);
for (u32 i = 0; i < FileViewState->FileNames.Count; i++)
{
gs_file_info File = FileViewState->FileNames.Values[i];
u32 LastSlashIndex = FindLast(File.Path, '\\');
gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length);
gs_string PathString = PushString(State->Transient, FileName.Length);
PrintF(&PathString, "%S", FileName);
if (ui_LayoutListButton(&State->Interface, PathString, i))
{
FileViewUpdateWorkingDirectory(File.Path, FileViewState, Context);
}
else
{
FileViewState->SelectedFile = File;
FileView_Exit_(Panel, State, Context);
if (File.IsDirectory)
{
FileViewUpdateWorkingDirectory(File.Path, FileViewState, Context);
}
else
{
FileViewState->SelectedFile = File;
FileView_Exit_(Panel, State, Context);
}
}
}
ui_EndList(&State->Interface);
}
ui_PopLayout(&State->Interface, MakeString("FileView Layout"));
}

View File

@ -95,14 +95,10 @@ EndCurrentOperationMode(app_state* State)
#include "editor/panels/foldhaus_panel_hierarchy.h"
#include "editor/panels/foldhaus_panel_assembly_debug.h"
#include "editor/panels/foldhaus_panel_types.cpp"
//#include "generated/foldhaus_panels_generated.h"
#include "editor/foldhaus_interface.cpp"
#include "../meta/gs_meta_include.cpp"
#include "editor/foldhaus_editor_draw.h"
#include "editor/foldhaus_editor.cpp"
#define FOLDHAUS_APP_H

View File

@ -1440,7 +1440,12 @@ CharArrayLength (char* CS)
internal bool
IsNullTerminated(gs_const_string String)
{
return (String.Str[String.Length] == 0);
bool Result = false;
if (String.Str)
{
Result = (String.Str[String.Length] == 0);
}
return Result;
}
internal bool
IsNullTerminated(gs_string String)