From 0f220c608dcc48b47ee6273bf9b14623d5474e39 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sun, 21 Jul 2019 23:30:53 -0700 Subject: [PATCH] Got OpenGL kind of working again. Lots of other work recreating functionality as well, but none of its done yet. --- build.bat | 39 ++ foldhaus_app.cpp | 57 ++- foldhaus_debug_visuals.h | 10 +- foldhaus_platform.h | 11 +- foldhaus_renderer.cpp | 12 +- foldhaus_renderer.h | 67 ++- gs_font.h | 101 ++++ gs_input.h | 4 - gs_platform.h | 100 +++- gs_string.h | 15 +- gs_vector_matrix.h | 67 ++- gs_win32.cpp | 974 +++++++++++++++++++++++++++++++++++++++ gs_win32.h | 834 +-------------------------------- interface.h | 31 +- testmain.cpp | 16 + win32_foldhaus.cpp | 101 ++-- 16 files changed, 1508 insertions(+), 931 deletions(-) create mode 100644 build.bat create mode 100644 gs_win32.cpp create mode 100644 testmain.cpp diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..3cb6479 --- /dev/null +++ b/build.bat @@ -0,0 +1,39 @@ +@echo off + +set ProjectDevRoot=C:\projects +set ProjectName=foldhaus +set ProjectDevPath=%ProjectDevRoot%\%ProjectName% + +pushd %ProjectDevPath% + +IF NOT EXIST .\build\ mkdir .\build + +C:\programs\ctime\ctime.exe -begin %ProjectDevPath%\build\win32_foldhaus_build_time.ctm + +set CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except- +set CommonCompilerFlags=-wd4127 -wd4702 -wd4101 -wd4505 -wd4100 -wd4189 -wd4244 -wd4201 -wd4996 -I%CommonLibs% -O2 %CommonCompilerFlags% +set CommonLinkerFlags= -opt:ref + +pushd build + +del *.pdb > NUL 2> NUL + +REM Compile and Run the Preprocessor +REM cl %CommonCompilerFlags% ..\meta\foldhaus_meta.cpp /link %CommonLinkerFlags% +pushd ..\src\ +REM ..\build\foldhaus_meta.exe C:\projects\foldhaus\src\ +popd + +REM cl %CommonCompilerFlags% F:\src\foldhaus_util_radialumia_file_converter.cpp /link %CommonLinkerFlags% +REM foldhaus_util_radialumia_file_converter.exe + +echo WAITING FOR PDB TO WRITE > lock.tmp +cl %CommonCompilerFlags% ..\src\foldhaus_app.cpp /Fefoldhaus.dll /LD /link %CommonLinkerFlags% /EXPORT:InitializeApplication /EXPORT:UpdateAndRender /EXPORT:CleanupApplication /EXPORT:ReloadStaticData +set LastError=%ERRORLEVEL% +del lock.tmp + +cl %CommonCompilerFlags% ..\src\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib -incremental:no + +C:\programs\ctime\ctime.exe -end C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm %LastError% +C:\programs\ctime\ctime.exe -stats C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm +popd \ No newline at end of file diff --git a/foldhaus_app.cpp b/foldhaus_app.cpp index e275087..02124bb 100644 --- a/foldhaus_app.cpp +++ b/foldhaus_app.cpp @@ -249,8 +249,8 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData) v4 P2 = ModelMatrix * P2_In; v4 P3 = ModelMatrix * P3_In; - PushTri3DOnBatch(Data->Batch, P0, P1, P2, UV0, UV1, UV2, Color); - PushTri3DOnBatch(Data->Batch, P0, P2, P3, UV0, UV2, UV3, Color); + PushTri3DOnBatch(Data->Batch, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); + PushTri3DOnBatch(Data->Batch, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color); LED++; } @@ -418,11 +418,49 @@ INITIALIZE_APPLICATION(InitializeApplication) if (stbtt_InitFont(&StbFont, FontFile.Base, stbtt_GetFontOffsetForIndex(FontFile.Base, 0))) { bitmap_font* Font = PushStruct(State->Permanent, bitmap_font); - Font->Atlas = PushTexture(State); - RenderStbttToBitmapFont(Font, StbFont, FontSize, 512, State->Permanent, State->Transient ); + + + Font->BitmapWidth = 512; + Font->BitmapHeight = 512; + Font->BitmapBytesPerPixel = 4; + Font->BitmapMemory = PushArray(State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel);; + Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel; + + platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", 14); + Font->PixelHeight = FontInfo.PixelHeight; + Font->Ascent = FontInfo.Ascent; + Font->Descent = FontInfo.Descent; + Font->Leading = FontInfo.Leading; + Font->MaxCharWidth = FontInfo.MaxCharWidth; + + Font->CodepointDictionarySize = (FontInfo.CodepointOnePastLast - FontInfo.CodepointStart); + Font->CodepointDictionaryCount = 0; + Font->CodepointKeys = PushArray(State->Permanent, char, Font->CodepointDictionarySize); + Font->CodepointValues = PushArray(State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize); + + for (s32 Codepoint = FontInfo.CodepointStart; + Codepoint < FontInfo.CodepointOnePastLast; + Codepoint++) + { + u32 CodepointX, CodepointY; + GetNextCodepointOffset(Font, &CodepointX, &CodepointY); + + u32 CodepointW, CodepointH; + Context.PlatformDrawFontCodepoint( + Font->BitmapMemory, + Font->BitmapWidth, + Font->BitmapHeight, + CodepointX, CodepointY, + (char)Codepoint, FontInfo, + &CodepointW, &CodepointH); + + AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY); + } + State->Interface.Font = Font; State->Font = Font; - Font->Atlas->Handle = Context.PlatformGetGPUTextureHandle(Font->Atlas->Memory, Font->Atlas->Width, Font->Atlas->Height); + Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, + Font->BitmapWidth, Font->BitmapHeight); } } else {} } @@ -570,12 +608,9 @@ UPDATE_AND_RENDER(UpdateAndRender) m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); - RenderBuffer->ViewWidth = Context.WindowWidth; - RenderBuffer->ViewHeight = Context.WindowHeight; - r32 LEDHalfWidth = .5f; - PushRenderPerspective(RenderBuffer, Context.WindowWidth, Context.WindowHeight, State->Camera); + PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight, State->Camera); PushRenderClearScreen(RenderBuffer); DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle @@ -634,7 +669,7 @@ UPDATE_AND_RENDER(UpdateAndRender) DEBUG_TRACK_SCOPE(DrawInterface); - PushRenderOrthographic(RenderBuffer, Context.WindowWidth, Context.WindowHeight); + PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight); // Universe Data View if (State->DrawUniverseOutputDisplay) @@ -698,7 +733,7 @@ UPDATE_AND_RENDER(UpdateAndRender) v2{Context.WindowWidth, Context.WindowHeight}, 0, State->Interface, Input); - v2 ButtonDim = v2{200, State->Interface.Font->NewLineYOffset + 10}; + v2 ButtonDim = v2{200, (r32)NewLineYOffset(*State->Interface.Font) + 10}; v2 ButtonPos = v2{State->Interface.Margin.x, Context.WindowHeight - (ButtonDim.y + 10)}; button_result LoadAssemblyBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, MakeStringLiteral("Load Assembly"), diff --git a/foldhaus_debug_visuals.h b/foldhaus_debug_visuals.h index 7b9e7ed..07179f1 100644 --- a/foldhaus_debug_visuals.h +++ b/foldhaus_debug_visuals.h @@ -3,7 +3,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c { DEBUG_TRACK_SCOPE(DrawDebugInterface); - v2 TopOfDebugView = v2{StartX, WindowHeight - (Interface.Font->NewLineYOffset + 5)}; + v2 TopOfDebugView = v2{StartX, WindowHeight - (NewLineYOffset(*Interface.Font) + 5)}; v2 TopOfScreenLinePos = TopOfDebugView; arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient); @@ -24,7 +24,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c (u32)FramesPerSecond); DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, WhiteV4); - v2 ButtonDim = v2{200, Interface.Font->NewLineYOffset + 10}; + v2 ButtonDim = v2{200, (r32)NewLineYOffset(*Interface.Font) + 10}; TopOfScreenLinePos.y -= ButtonDim.y + 10; v2 ButtonPos = TopOfScreenLinePos; button_result CameraBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, @@ -52,7 +52,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c button_result SendSACNDataBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, SACNButtonString, Interface, Input); - TopOfScreenLinePos.y -= Interface.Font->NewLineYOffset + 10; + TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font) + 10; if (CameraBtn.Pressed) { @@ -85,7 +85,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c 3, Camera.LookAt.y, 3, Camera.LookAt.z); DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, v4{1.0f, 1.0f, 1.0f, 1.0f}); - TopOfScreenLinePos.y -= Interface.Font->NewLineYOffset; + TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); } if (GlobalDebugServices->Interface.ShowTrackedScopes) @@ -127,7 +127,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c Register, WhiteV4).x; Register.x += GSMax(ColumnFourX - Register.x, 200.f); - TopOfScreenLinePos.y -= Interface.Font->NewLineYOffset; + TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); } diff --git a/foldhaus_platform.h b/foldhaus_platform.h index cb3087e..e8a95b9 100644 --- a/foldhaus_platform.h +++ b/foldhaus_platform.h @@ -30,6 +30,14 @@ typedef CLEANUP_APPLICATION(cleanup_application); // Platform Functions +typedef struct platform_font_info platform_font_info; + +#define GET_FONT_INFO(name) platform_font_info name(char* FontName, s32 PixelHeight) +typedef GET_FONT_INFO(platform_get_font_info); + +#define DRAW_FONT_CODEPOINT(name) void name(u8* DestBuffer, s32 DestBufferWidth, s32 DestBufferHeight, u32 XOffset, u32 YOffset, char Codepoint, platform_font_info FontInfo, u32* OutWidth, u32* OutHeight) +typedef DRAW_FONT_CODEPOINT(platform_draw_font_codepoint); + // Worker Threads #define THREADED_WORK_PROC(name) void name(s32 ThreadID, void* Data) @@ -106,7 +114,8 @@ struct context 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_get_send_address* PlatformGetSendAddress; platform_set_socket_option* PlatformSetSocketOption; diff --git a/foldhaus_renderer.cpp b/foldhaus_renderer.cpp index ce4e736..7968bea 100644 --- a/foldhaus_renderer.cpp +++ b/foldhaus_renderer.cpp @@ -18,7 +18,7 @@ Render3DQuadBatch (u8* CommandData, s32 TriCount) v4* Colors = (v4*)(CommandData + BATCH_3D_COLORS_OFFSET(TriCount)); #if IMMEDIATE_MODE_RENDERING - glBegin(GL_TRIANGLES); + for (s32 Tri = 0; Tri < TriCount; Tri++) { v4 P0 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 0)]; @@ -33,9 +33,8 @@ Render3DQuadBatch (u8* CommandData, s32 TriCount) OpenGLDraw3DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); } - glEnd(); #else - OpenGLRenderTriBuffer((u8*)Vertecies, 4, UVs, 2, Colors, 4, TriCount * 3); + OpenGLRenderTriBuffer((u8*)Vertecies, 4, (u8*)UVs, 2, (u8*)Colors, 4, TriCount * 3); #endif } @@ -67,7 +66,7 @@ Render2DQuadBatch (u8* CommandData, s32 QuadCount) } } #else - OpenGLRenderTriBuffer((u8*)Vertecies, 2, UVs, 2, Colors, 4, QuadCount * 2 * 3); + OpenGLRenderTriBuffer((u8*)Vertecies, 2, (u8*)UVs, 2, (u8*)Colors, 4, QuadCount * 2 * 3); #endif } @@ -76,8 +75,6 @@ RenderCommandBuffer (render_command_buffer CommandBuffer) { DEBUG_TRACK_FUNCTION; - glViewport(0, 0, CommandBuffer.ViewWidth, CommandBuffer.ViewHeight); - glMatrixMode(GL_TEXTURE_2D); glLoadIdentity(); @@ -100,6 +97,9 @@ RenderCommandBuffer (render_command_buffer CommandBuffer) { render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1); + glViewport(Command->ViewOffsetX, Command->ViewOffsetY, + Command->ViewWidth, Command->ViewHeight); + LoadModelView(Command->ModelView.E); LoadProjection(Command->Projection.E); diff --git a/foldhaus_renderer.h b/foldhaus_renderer.h index b286c57..b42c8d6 100644 --- a/foldhaus_renderer.h +++ b/foldhaus_renderer.h @@ -181,6 +181,7 @@ struct render_command_set_render_mode { m44 ModelView; m44 Projection; + r32 ViewOffsetX, ViewOffsetY; r32 ViewWidth, ViewHeight; b32 UseDepthBuffer; }; @@ -280,7 +281,10 @@ ThreadSafeIncrementQuadConstructorCount (render_quad_batch_constructor* Construc } inline void -PushTri3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v2 UV0, v2 UV1, v2 UV2, v4 Color) +PushTri3DOnBatch (render_quad_batch_constructor* Constructor, + v4 P0, v4 P1, v4 P2, + v2 UV0, v2 UV1, v2 UV2, + v4 C0, v4 C1, v4 C2) { s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor); // Vertecies @@ -292,17 +296,28 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 1)] = UV1; Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 2)] = UV1; // Color V0 - Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 0)] = Color; - Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 1)] = Color; - Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 2)] = Color; + Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 0)] = C0; + Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 1)] = C1; + Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 2)] = C2; }; 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 < Constructor->Max); - PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color); - PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color); + 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); +} + +internal void +PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, + v4 P0, v4 P1, v4 P2, v4 P3, + v2 UV0, v2 UV1, v2 UV2, v2 UV3, + v4 C0, v4 C1, v4 C2, v4 C3) +{ + 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); } internal void @@ -418,19 +433,26 @@ PushRenderCommand_ (render_command_buffer* CommandBuffer, render_command_type Co return Result; } -internal void -PushRenderPerspective (render_command_buffer* Buffer, s32 ViewWidth, s32 ViewHeight, camera Camera) +internal render_command_set_render_mode* +PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, s32 ViewWidth, s32 ViewHeight, camera Camera) { render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); + Command->ModelView = GetCameraModelViewMatrix(Camera); Command->Projection = GetCameraPerspectiveProjectionMatrix(Camera); - Command->ViewWidth; - Command->ViewHeight; + + Command->ViewOffsetX = (r32)OffsetX; + Command->ViewOffsetY = (r32)OffsetY; + Command->ViewWidth = (r32)ViewWidth; + Command->ViewHeight = (r32)ViewHeight; + Command->UseDepthBuffer = true; + + return Command; } internal void -PushRenderOrthographic (render_command_buffer* Buffer, s32 ViewWidth, s32 ViewHeight) +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{ @@ -448,8 +470,12 @@ PushRenderOrthographic (render_command_buffer* Buffer, s32 ViewWidth, s32 ViewHe 0, 0, 1, 0, -1, -1, 0, 1 }; - Command->ViewWidth; - Command->ViewHeight; + + Command->ViewOffsetX = (r32)OffsetX; + Command->ViewOffsetY = (r32)OffsetY; + Command->ViewWidth = ViewWidth; + Command->ViewHeight = ViewHeight; + Command->UseDepthBuffer = false;; } @@ -531,6 +557,21 @@ PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount, return Result; } +internal render_quad_batch_constructor +PushRenderTexture2DBatch (render_command_buffer* Buffer, s32 QuadCount, + u8* TextureMemory, s32 TextureHandle, s32 TextureWidth, s32 TextureHeight, + s32 TextureBytesPerPixel, s32 TextureStride) +{ + render_texture Texture = render_texture{ + TextureMemory, + TextureHandle, + TextureWidth, + TextureHeight, + TextureBytesPerPixel, + TextureStride}; + return PushRenderTexture2DBatch(Buffer, QuadCount, Texture); +} + internal void PushRenderTexture2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color, v2 UVMin, v2 UVMax, diff --git a/gs_font.h b/gs_font.h index 95f3e70..3d175af 100644 --- a/gs_font.h +++ b/gs_font.h @@ -1,6 +1,107 @@ #ifndef GS_FONT_H +struct codepoint_bitmap +{ + s32 XOffset, YOffset; + s32 Width, Height; + s32 BitmapX, BitmapY; +}; +struct bitmap_font +{ + char* Name; + s32 PixelHeight; + s32 Ascent; + s32 Descent; + s32 Leading; + s32 MaxCharWidth; + + u32 CodepointDictionarySize; + u32 CodepointDictionaryCount; + char* CodepointKeys; + codepoint_bitmap* CodepointValues; + + u8* BitmapMemory; + u32 BitmapWidth; + u32 BitmapHeight; + u32 BitmapBytesPerPixel; + u32 BitmapStride; + s32 BitmapTextureHandle; +}; + +internal bitmap_font +InitializeTextFont (s32 CodepointCount, u8* CodepointMemory, s32 CodepointMemorySize) +{ + bitmap_font Result = {}; + + Result.CodepointDictionarySize = CodepointCount; + Result.CodepointDictionaryCount = 0; + Assert(CodepointMemorySize >= (sizeof(char) + sizeof(codepoint_bitmap)) * CodepointCount); + Result.CodepointKeys = (char*)CodepointMemory; + Result.CodepointValues = (codepoint_bitmap*)(CodepointMemory + (sizeof(char) * CodepointCount)); +} + +#define GLYPH_SKIRT 1 +internal void +GetNextCodepointOffset (bitmap_font* Font, u32* X, u32* Y) +{ + s32 LastCodepointIndex = Font->CodepointDictionaryCount - 1; + if (LastCodepointIndex >= 0) + { + codepoint_bitmap BitmapInfo = Font->CodepointValues[LastCodepointIndex]; + u32 TempX = BitmapInfo.XOffset + BitmapInfo.Width + GLYPH_SKIRT; + u32 TempY = BitmapInfo.YOffset; + if (TempX + Font->MaxCharWidth > Font->BitmapWidth) + { + TempX = 0; + TempY -= BitmapInfo.Height + GLYPH_SKIRT; + } + *X = TempX; + *Y = TempY; + } + else + { + *X = 0; + *Y = 0; + } +} + +internal void +AddCodepointToFont (bitmap_font* Font, char Codepoint, + s32 XOffset, s32 YOffset, s32 Width, s32 Height, + s32 BitmapX, s32 BitmapY) +{ + Assert(Font->CodepointDictionaryCount < Font->CodepointDictionarySize); + + char* Key = Font->CodepointKeys + Font->CodepointDictionaryCount; + codepoint_bitmap* Value = Font->CodepointValues + Font->CodepointDictionaryCount; + Font->CodepointDictionaryCount++; + + *Key = Codepoint; + *Value = {XOffset, YOffset, Width, Height, BitmapX, BitmapY}; +} + +internal s32 +GetIndexForCodepoint (bitmap_font Font, char Codepoint) +{ + s32 Result = -1; + for (u32 i = 0; i < Font.CodepointDictionaryCount; i++) + { + if (Font.CodepointKeys[i] == Codepoint) + { + Result = i; + break; + } + } + return Result; +} + +inline s32 +NewLineYOffset (bitmap_font Font) +{ + s32 Result = Font.Ascent - Font.Descent; + return Result; +} #define GS_FONT_H #endif \ No newline at end of file diff --git a/gs_input.h b/gs_input.h index df008e5..e69de29 100644 --- a/gs_input.h +++ b/gs_input.h @@ -1,4 +0,0 @@ -#ifndef GS_INPUT_H - -#define GS_INPUT_H -#endif diff --git a/gs_platform.h b/gs_platform.h index b958ea2..80538c0 100644 --- a/gs_platform.h +++ b/gs_platform.h @@ -1,5 +1,51 @@ #ifndef GS_PLATFORM_H +#ifndef GS_LANGUAGE_H +// Types +typedef signed char b8; +typedef short int b16; +typedef int b32; +typedef long long int b64; + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned int u32; +typedef unsigned long long int u64; + +typedef signed char s8; +typedef short int s16; +typedef int s32; +typedef long long int s64; + +typedef float r32; +typedef double r64; + +#define internal static +#define local_persist static +#define global_variable static + +#ifdef DEBUG +#define Assert(condition) if(!(condition)) { *((int *)0) = 5; } +#define InvalidCodePath Assert(0) +#define InvalidDefaultCase default: { InvalidCodePath; } +#endif + +#endif + +#ifdef PLATFORM_WINDOWS +#include "gs_win32.h" +#endif + +struct window_info +{ + char* Name; + s32 Width; + s32 Height; +}; + +typedef struct window window; + +#define PLATFORM_MEMORY_NO_ERROR 0 struct platform_memory_result { u8* Base; @@ -7,7 +53,21 @@ struct platform_memory_result s32 Error; }; -#define PLATFORM_MEMORY_NO_ERROR 0 +struct texture_buffer +{ + u8* Memory; + s32 Width; + s32 Height; + s32 Pitch; + s32 BytesPerPixel; +}; + +struct system_path +{ + char* Path; + s32 PathLength; + s32 IndexOfLastSlash; +}; #define PLATFORM_ALLOC(name) platform_memory_result name(s32 Size) typedef PLATFORM_ALLOC(platform_alloc); @@ -21,28 +81,32 @@ typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file); #define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(char* Path, u8* Contents, s32 Size) typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); -#define PLATFORM_GET_FILE_PATH(name) +#define PLATFORM_GET_FILE_PATH(name) b32 name(char* PathBuffer, s32 BufferLength) typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); -#define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) +#define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height) typedef PLATFORM_GET_GPU_TEXTURE_HANDLE(platform_get_gpu_texture_handle); -#define PLATFORM_GET_SOCKET_HANDLE(name) +typedef s32 platform_socket_handle; +typedef s32 platform_network_address_handle; + +#define PLATFORM_GET_SOCKET_HANDLE(name) platform_socket_handle name(s32 AddressFamily, s32 Type, s32 Protocol) typedef PLATFORM_GET_SOCKET_HANDLE(platform_get_socket_handle); -#define PLATFORM_GET_SEND_ADDRESS(name) -typedef PLATFORM_GET_SEND_ADDRESS(platform_get_send_address); +#define PLATFORM_GET_SEND_ADDRESS_HANDLE(name) platform_network_address_handle name(s32 AddressFamily, u16 Port, u32 Address) +typedef PLATFORM_GET_SEND_ADDRESS_HANDLE(platform_get_send_address); -#define PLATFORM_SET_SOCKET_OPTION(name) +#define PLATFORM_SET_SOCKET_OPTION(name) s32 name(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) typedef PLATFORM_SET_SOCKET_OPTION(platform_set_socket_option); -#define PLATFORM_SEND_TO(name) +#define PLATFORM_SEND_TO(name) s32 name(platform_socket_handle SocketHandle, platform_network_address_handle AddressHandle, const char* Buffer, s32 BufferLength, s32 Flags) typedef PLATFORM_SEND_TO(platform_send_to); -#define PLATFORM_CLOSE_SOCKET(name) +#define PLATFORM_CLOSE_SOCKET(name) void name(platform_socket_handle SocketHandle) typedef PLATFORM_CLOSE_SOCKET(platform_close_socket); - +#ifndef GS_INPUT +#define GS_INPUT enum key_code { KeyCode_Invalid, @@ -119,6 +183,7 @@ struct input_frame b32 KeysDown[(int)KeyCode_Count]; s32 StringInputUsed; char StringInput[INPUT_FRAME_STRING_LENGTH]; + s32 MouseX, MouseY, MouseScroll; }; struct input @@ -126,6 +191,7 @@ struct input input_frame Frames[2]; input_frame* New; input_frame* Old; + s32 MouseDownX, MouseDownY; }; internal void InitializeInput (input* Input); @@ -167,5 +233,19 @@ KeyTransitionedUp (input Input, key_code Key) { return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key]; } +#endif // GS_INPUT + +internal window PlatformCreateWindow (char* Name, s32 Width, s32 Height); + + +// Time + +internal r32 +GetSecondsElapsed (s64 Start, s64 End, s64 PerformanceCountFrequency) +{ + r32 Result = ((r32)(End - Start) / (r32) PerformanceCountFrequency); + return Result; +} + #define GS_PLATFORM_H #endif // GS_PLATFORM_H \ No newline at end of file diff --git a/gs_string.h b/gs_string.h index 13ec4cf..4118ac9 100644 --- a/gs_string.h +++ b/gs_string.h @@ -243,9 +243,8 @@ static s32 IntToString (s32 Int, char* String, s32 Length, s32 Offset); static float ParseFloat (char* String, s32 Length); static s32 FloatToString(float Float, char *String, s32 Length, s32 AfterPoint); -// Print F - -#define PrintString(str, format, ...) snprintf(str.Memory, str.Max, format, __VA_ARGS__); str.Length = CharArrayLength(str.Memory); +// PrintF +static s32 PrintF(string* String, char* Format, ...); //////////////////////////////////////////////////////////////// // String Memory Function Declarations @@ -1278,11 +1277,12 @@ FloatToString(float Float, char *String, s32 Length, s32 AfterPoint) internal s32 -PrintStringF(char* Format, char* Destination, s32 DestLength, ...) +PrintF (string* String, char* Format, ...) { va_list Args; - va_start(Args, DestLength); + va_start(Args, Format); +#if 0 s32 LengthPrinted = 0; char* DestChar = Destination; @@ -1334,9 +1334,10 @@ PrintStringF(char* Format, char* Destination, s32 DestLength, ...) } *(Destination + LengthPrinted) = 0; - va_end(Args); +#endif - return LengthPrinted; + va_end(Args); + return 0; } diff --git a/gs_vector_matrix.h b/gs_vector_matrix.h index adb478b..d127297 100644 --- a/gs_vector_matrix.h +++ b/gs_vector_matrix.h @@ -66,6 +66,15 @@ union v4 r32 E[4]; }; +#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} + ////////////////////////////////////// // MATRIX ///////////////////////////////////// @@ -99,8 +108,8 @@ union m44 struct rect { - v2 LowerLeft; - v2 UpperRight; + v2 Min; + v2 Max; }; @@ -187,6 +196,19 @@ V4OpV4Def(*) #undef V3OpV3Def #undef V4OpV4Def +#define V2RefOpV2Def(op) v2 operator##op (v2& A, v2 B) { return v2{ A.x op B.x, A.y op B.y };} +#define V3RefOpV3Def(op) v3 operator##op (v3& A, v3 B) { return v3{ A.x op B.x, A.y op B.y, A.z op B.z };} +#define V4RefOpScalarDef(op) v4 operator##op (v4& A, v4 B) { return v4{ A.x op B.x, A.y op B.y, A.z op B.z, A.w op B.w };} +V2RefOpV2Def(+=) +V2RefOpV2Def(-=) +V3RefOpV3Def(+=) +V3RefOpV3Def(-=) +V4RefOpScalarDef(+=) +V4RefOpScalarDef(-=) +#undef V2RefOpV2Def +#undef V3RefOpV3Def +#undef V4RefOpV4Def + #define V2OpScalarDef(op) v2 operator##op (v2 A, r32 B) { return v2{ A.x op B, A.y op B };} #define V3OpScalarDef(op) v3 operator##op (v3 A, r32 B) { return v3{ A.x op B, A.y op B, A.z op B };} #define V4OpScalarDef(op) v4 operator##op (v4 A, r32 B) { return v4{ A.x op B, A.y op B, A.z op B, A.w op B };} @@ -201,9 +223,9 @@ V4OpScalarDef(/) #undef V4POpScalarDef -#define V2POpScalarDef(op) v2 operator##op (v2* A, r32 B) { return v2{ A->x op B, A->y op B };} -#define V3POpScalarDef(op) v3 operator##op (v3* A, r32 B) { return v3{ A->x op B, A->y op B, A->z op B };} -#define V4POpScalarDef(op) v4 operator##op (v4* A, r32 B) { return v4{ A->x op B, A->y op B, A->z op B, A->w op B };} +#define V2POpScalarDef(op) v2 operator##op (v2& A, r32 B) { return v2{ A->x op B, A->y op B };} +#define V3POpScalarDef(op) v3 operator##op (v3& A, r32 B) { return v3{ A->x op B, A->y op B, A->z op B };} +#define V4POpScalarDef(op) v4 operator##op (v4& A, r32 B) { return v4{ A->x op B, A->y op B, A->z op B, A->w op B };} V2OpScalarDef(*=) V2OpScalarDef(/=) V3OpScalarDef(*=) @@ -613,6 +635,39 @@ PointToPercentRange (v2 P, v2 Min, v2 Max) return Result; } +////////////////////////////////////// +// RECT +////////////////////////////////////// + +inline r32 +Width (rect Rect) +{ + s32 Result = Rect.Max.x - Rect.Min.x; + return Result; +} + +inline r32 +Height (rect Rect) +{ + s32 Result = Rect.Max.y - Rect.Min.y; + return Result; +} + +inline v2 +CalculateRectCenter (rect Rect) +{ + v2 Result = (Rect.Min + Rect.Max) / 2.0f; + return Result; +} + +inline b32 +PointIsInRect (v2 Point, rect Rect) +{ + b32 Result = ((Point.x >= Rect.Min.x && Point.x <= Rect.Max.x) && + (Point.y >= Rect.Min.y && Point.y <= Rect.Max.y)); + return Result; +} + ////////////////////////////////////// // MATRIX ////////////////////////////////////// @@ -778,8 +833,6 @@ Transpose (m44 M) static m44 GetPositionM44 (v4 Position) { - DEBUG_TRACK_SCOPE(GetPositionM44); - #if 1 return m44{ 1, 0, 0, 0, diff --git a/gs_win32.cpp b/gs_win32.cpp new file mode 100644 index 0000000..8874683 --- /dev/null +++ b/gs_win32.cpp @@ -0,0 +1,974 @@ +#ifndef GS_WIN32_CPP + +struct win32_state +{ + b32 Initialized; + b32 Running; +}; + +struct win32_opengl_window_info +{ + s32 ColorBits; + s32 AlphaBits; + s32 DepthBits; + HGLRC RenderContext; +}; + +struct window +{ + char* Name; + char* ClassName; + s32 Width; + s32 Height; + WNDPROC WindowEventHandler; + + WNDCLASS Class; + HWND Handle; + HDC DeviceContext; + + // TODO(peter): Make this a union? + win32_opengl_window_info OpenGLInfo; +}; + +struct handle_window_msg_result +{ + b32 NeedsUpdate; +#ifdef DEBUG + char MessageType[128]; +#endif +}; + +global_variable win32_state GlobalWin32State; + +// Utility +internal s32 Win32StringLength(char* String); +internal s32 Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest); + +// Windowing & Graphics +struct win32_offscreen_buffer +{ + texture_buffer Buffer; + BITMAPINFO Info; +}; + +LRESULT CALLBACK Win32HandleWindowsEvents (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam); +internal handle_window_msg_result HandleWindowsMessage (HWND WindowHandle, MSG Message); +internal void Win32UpdateWindowDimension(window* Window); +internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height); +internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, window Window); + +// Memory + +internal PLATFORM_ALLOC(Win32Alloc); +internal PLATFORM_FREE(Win32Free); + +// File IO +internal PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile); +internal PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile); +internal FILETIME Win32GetFileLastWriteTime; + +// DLL +struct win32_dll_refresh +{ + FILETIME LastWriteTime; + HMODULE DLL; + + b32 IsValid; + + char SourceDLLPath[MAX_PATH]; + char WorkingDLLPath[MAX_PATH]; + char LockFilePath[MAX_PATH]; +}; + +internal b32 LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult); +internal void UnloadApplicationDLL(win32_dll_refresh* DLL); +internal win32_dll_refresh InitializeDLLHotReloading(char* SourceDLLName, char* WorkingDLLFileName, char* LockFileName); +internal b32 HotLoadDLL(win32_dll_refresh* DLL); + +// Networking + +/// +// Utils +/// + +internal s32 +Win32StringLength(char* String) +{ + char* At = String; + while (*At) { At++; }; + return At - String; +} + +internal s32 +Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest) +{ + char* Dst = Dest; + char* AAt = A; + for (s32 a = 0; a < ALen; a++) + { + *Dst++ = *AAt++; + } + char* BAt = B; + for (s32 b = 0; b < BLen; b++) + { + *Dst++ = *BAt++; + } + return Dst - Dest; +} + +/// +// Windowing +/// + +internal window +Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height, + WNDPROC WindowEventHandler) +{ + window Result = {}; + Result.Name = WindowName; + Result.ClassName = WindowName; + Result.Width = Width; + Result.Height = Height; + Result.WindowEventHandler = WindowEventHandler; + + Result.Class = {}; + Result.Class.style = CS_HREDRAW | CS_VREDRAW; + Result.Class.lpfnWndProc = WindowEventHandler; + Result.Class.hInstance = HInstance; + Result.Class.lpszClassName = WindowName; + + if (RegisterClass(&Result.Class)) + { + Result.Handle = CreateWindowEx( + 0, + Result.Class.lpszClassName, + WindowName, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + Width, + Height, + 0, + 0, + HInstance, + 0); + Result.DeviceContext = GetDC(Result.Handle); + } + + return Result; +}; + +internal window +PlatformCreateWindow (char* WindowName, s32 Width, s32 Height) +{ + HINSTANCE HInstance = GetModuleHandle(NULL); + return Win32CreateWindow(HInstance, WindowName, Width, Height, Win32HandleWindowsEvents); +} + +internal void +CreateOpenGLWindowContext (win32_opengl_window_info Info, window* Window) +{ + // Setup pixel format + { + PIXELFORMATDESCRIPTOR PixelFormatDesc = { 0 }; + // TODO: Program seems to work perfectly fine without all other params except dwFlags. + // Can we skip other params for the sake of brevity? + PixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); + PixelFormatDesc.nVersion = 1; + PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; + PixelFormatDesc.iPixelType = PFD_TYPE_RGBA;// TODO(Peter): include this in win32_opengl_window_info? + PixelFormatDesc.cColorBits = Info.ColorBits; + PixelFormatDesc.cAlphaBits = Info.AlphaBits; + PixelFormatDesc.cDepthBits = Info.DepthBits; + PixelFormatDesc.dwLayerMask = PFD_MAIN_PLANE; // TODO(Peter): include this in win32_opengl_window_info? + // + + s32 PixelFormat = ChoosePixelFormat(Window->DeviceContext, &PixelFormatDesc); + if (!PixelFormat) { InvalidCodePath; } // TODO: Log: Choose pixel format failed + if (!SetPixelFormat(Window->DeviceContext, PixelFormat, &PixelFormatDesc)) { InvalidCodePath; } // TODO: Log: Set pixel format failed + } + + // Create rendering context + { + // TODO: Create "proper" context? + // https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation + + Info.RenderContext = wglCreateContext(Window->DeviceContext); + wglMakeCurrent(Window->DeviceContext, Info.RenderContext); + + // TODO(Peter): do we want this? + /* + glGetIntegerv(GL_MAJOR_VERSION, ); + glGetIntegerv(GL_MINOR_VERSION, ); + (char*)glGetString(GL_VENDOR); + (char*)glGetString(GL_RENDERER); + */ + } + + Window->OpenGLInfo = Info; +} + +struct handle_window_event_result +{ + LRESULT Result; + b32 Handled; +}; + +internal void +Win32UpdateInputFrameMouseButtonState (input_frame* InputFrame, key_code KeyCode, int Win32VirtualKey) +{ + InputFrame->KeysDown[KeyCode] = (GetKeyState(Win32VirtualKey) & (1 << 15)) != 0; +} + +internal void +Win32UpdateInputFrameMouseState (input_frame* InputFrame) +{ + Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseLeftButton, VK_LBUTTON); + Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseMiddleButton, VK_MBUTTON); + Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseRightButton, VK_RBUTTON); + // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are + // VK_XBUTTON1 and VK_XBUTTON2 +} + +internal void +Win32UpdateInputFrameMouseWheelDelta (input_frame* InputFrame, MSG Message) +{ + int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); + InputFrame->MouseScroll = MouseWheel; +} + +internal handle_window_event_result +HandleWindowEventUnlessWouldUseDefault (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + handle_window_event_result Result = {}; + Result.Handled = false; + + switch (Msg) + { + case WM_SIZE: + { + + Result.Handled = true; + }break; + + case WM_CLOSE: + { + Result.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); + Result.Handled = true; + }break; + + case WM_DESTROY: + { + GlobalWin32State.Running = false; + Result.Handled = true; + }break; + + case WM_PAINT: + { + PAINTSTRUCT PaintStruct; + HDC DeviceContext; + b32 PaintResult; + + DeviceContext = BeginPaint(WindowHandle, &PaintStruct); + PaintResult = EndPaint(WindowHandle, &PaintStruct); + Result.Handled = true; + }break; + } + + return Result; +} + +LRESULT CALLBACK +Win32HandleWindowsEvents ( +HWND WindowHandle, +UINT Msg, +WPARAM wParam, +LPARAM lParam +) +{ + handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault( + WindowHandle, + Msg, + wParam, + lParam); + + if (!EventResult.Handled) + { + EventResult.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); + } + + return EventResult.Result; +} + +#define WIN32_SHOULD_TRANSLATE_TO_CHAR -1 + +static int +Win32GetKeyIndex (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar) +{ + int Result = WIN32_SHOULD_TRANSLATE_TO_CHAR; + + if (Win32VirtualKey == VK_ESCAPE) { Result = (int)KeyCode_Esc; } + + if (!TranslateToChar) + { + if (Win32VirtualKey == VK_SPACE) { Result = (int)KeyCode_Space; } + + } + + if (Win32VirtualKey == VK_CAPITAL) { Result = (int)KeyCode_CapsLock; } + else if (Win32VirtualKey == VK_TAB) { Result = (int)KeyCode_Tab; } + else if (Win32VirtualKey == VK_LSHIFT) { Result = (int)KeyCode_LeftShift; } + else if (Win32VirtualKey == VK_RSHIFT) { Result = (int)KeyCode_RightShift; } + else if (Win32VirtualKey == VK_LCONTROL) { Result = (int)KeyCode_LeftCtrl; } + else if (Win32VirtualKey == VK_RCONTROL) { Result = (int)KeyCode_RightCtrl; } + + // TODO(Peter): support the function key? + //else if (Win32VirtualKey == VK_) { Result = (int)KeyCode_Fn; } + + else if (Win32VirtualKey == VK_MENU) { Result = (int)KeyCode_Alt; } + else if (Win32VirtualKey == VK_PRIOR) { Result = (int)KeyCode_PageUp; } + else if (Win32VirtualKey == VK_NEXT) { Result = (int)KeyCode_PageDown; } + else if (Win32VirtualKey == VK_BACK) { Result = (int)KeyCode_Backspace; } + else if (Win32VirtualKey == VK_DELETE) { Result = (int)KeyCode_Delete; } + else if (Win32VirtualKey == VK_RETURN) { Result = (int)KeyCode_Enter; } + + else if (Win32VirtualKey == VK_F1) { Result = (int)KeyCode_F1; } + else if (Win32VirtualKey == VK_F2) { Result = (int)KeyCode_F2; } + else if (Win32VirtualKey == VK_F3) { Result = (int)KeyCode_F3; } + else if (Win32VirtualKey == VK_F4) { Result = (int)KeyCode_F4; } + else if (Win32VirtualKey == VK_F5) { Result = (int)KeyCode_F5; } + else if (Win32VirtualKey == VK_F6) { Result = (int)KeyCode_F6; } + else if (Win32VirtualKey == VK_F7) { Result = (int)KeyCode_F7; } + else if (Win32VirtualKey == VK_F8) { Result = (int)KeyCode_F8; } + else if (Win32VirtualKey == VK_F9) { Result = (int)KeyCode_F9; } + else if (Win32VirtualKey == VK_F10) { Result = (int)KeyCode_F10; } + else if (Win32VirtualKey == VK_F11) { Result = (int)KeyCode_F11; } + else if (Win32VirtualKey == VK_F12) { Result = (int)KeyCode_F12; } + + if (!TranslateToChar) + { + if (Win32VirtualKey == 0x30) { Result = (int)KeyCode_0; } + else if (Win32VirtualKey == 0x31) { Result = (int)KeyCode_1; } + else if (Win32VirtualKey == 0x32) { Result = (int)KeyCode_2; } + else if (Win32VirtualKey == 0x33) { Result = (int)KeyCode_3; } + else if (Win32VirtualKey == 0x34) { Result = (int)KeyCode_4; } + else if (Win32VirtualKey == 0x35) { Result = (int)KeyCode_5; } + else if (Win32VirtualKey == 0x36) { Result = (int)KeyCode_6; } + else if (Win32VirtualKey == 0x37) { Result = (int)KeyCode_7; } + else if (Win32VirtualKey == 0x38) { Result = (int)KeyCode_8; } + else if (Win32VirtualKey == 0x39) { Result = (int)KeyCode_9; } + + else if (Win32VirtualKey == 0x41) { Result = (int)KeyCode_A; } + else if (Win32VirtualKey == 0x42) { Result = (int)KeyCode_B; } + else if (Win32VirtualKey == 0x43) { Result = (int)KeyCode_C; } + else if (Win32VirtualKey == 0x44) { Result = (int)KeyCode_D; } + else if (Win32VirtualKey == 0x45) { Result = (int)KeyCode_E; } + else if (Win32VirtualKey == 0x46) { Result = (int)KeyCode_F; } + else if (Win32VirtualKey == 0x47) { Result = (int)KeyCode_G; } + else if (Win32VirtualKey == 0x48) { Result = (int)KeyCode_H; } + else if (Win32VirtualKey == 0x49) { Result = (int)KeyCode_I; } + else if (Win32VirtualKey == 0x4A) { Result = (int)KeyCode_J; } + else if (Win32VirtualKey == 0x4B) { Result = (int)KeyCode_K; } + else if (Win32VirtualKey == 0x4C) { Result = (int)KeyCode_L; } + else if (Win32VirtualKey == 0x4D) { Result = (int)KeyCode_M; } + else if (Win32VirtualKey == 0x4E) { Result = (int)KeyCode_N; } + else if (Win32VirtualKey == 0x4F) { Result = (int)KeyCode_O; } + else if (Win32VirtualKey == 0x50) { Result = (int)KeyCode_P; } + else if (Win32VirtualKey == 0x51) { Result = (int)KeyCode_Q; } + else if (Win32VirtualKey == 0x52) { Result = (int)KeyCode_R; } + else if (Win32VirtualKey == 0x53) { Result = (int)KeyCode_S; } + else if (Win32VirtualKey == 0x54) { Result = (int)KeyCode_T; } + else if (Win32VirtualKey == 0x55) { Result = (int)KeyCode_U; } + else if (Win32VirtualKey == 0x56) { Result = (int)KeyCode_V; } + else if (Win32VirtualKey == 0x57) { Result = (int)KeyCode_W; } + else if (Win32VirtualKey == 0x58) { Result = (int)KeyCode_X; } + else if (Win32VirtualKey == 0x59) { Result = (int)KeyCode_Y; } + else if (Win32VirtualKey == 0x5A) { Result = (int)KeyCode_Z; } + } + + if (NumpadValid) + { + if (Win32VirtualKey == VK_NUMPAD0) { Result = (int)KeyCode_Num0; } + else if (Win32VirtualKey == VK_NUMPAD1) { Result = (int)KeyCode_Num1; } + else if (Win32VirtualKey == VK_NUMPAD2) { Result = (int)KeyCode_Num2; } + else if (Win32VirtualKey == VK_NUMPAD3) { Result = (int)KeyCode_Num3; } + else if (Win32VirtualKey == VK_NUMPAD4) { Result = (int)KeyCode_Num4; } + else if (Win32VirtualKey == VK_NUMPAD5) { Result = (int)KeyCode_Num5; } + else if (Win32VirtualKey == VK_NUMPAD6) { Result = (int)KeyCode_Num6; } + else if (Win32VirtualKey == VK_NUMPAD7) { Result = (int)KeyCode_Num7; } + else if (Win32VirtualKey == VK_NUMPAD8) { Result = (int)KeyCode_Num8; } + else if (Win32VirtualKey == VK_NUMPAD9) { Result = (int)KeyCode_Num9; } + } + + if (Win32VirtualKey == VK_UP) { Result = (int)KeyCode_UpArrow; } + else if (Win32VirtualKey == VK_DOWN) { Result = (int)KeyCode_DownArrow; } + else if (Win32VirtualKey == VK_LEFT) { Result = (int)KeyCode_LeftArrow; } + else if (Win32VirtualKey == VK_RIGHT) { Result = (int)KeyCode_RightArrow; } + + return Result; +} + +internal handle_window_msg_result +HandleWindowsMessage ( +HWND WindowHandle, +MSG Message) +{ + handle_window_msg_result Result = {}; + Result.NeedsUpdate = 0; + + switch (Message.message) + { + case WM_HOTKEY: + { + }break; + + case WM_MOUSEWHEEL: + { + int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); + /* + Input.New->MouseScroll = MouseWheel; + Result.NeedsUpdate = true; + */ + }break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + { + /* + Input.New->KeyStates[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0; + Input.New->KeyStates[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0; + Input.New->KeyStates[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0; + // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are + // VK_XBUTTON1 and VK_XBUTTON2 + + if (KeyTransitionedDown(KeyCode_MouseLeftButton, Input)) + { + Input.MouseDownX = Input.New->MouseX; + Input.MouseDownY = Input.New->MouseY; + } + Result.NeedsUpdate = true;*/ + }break; + + case WM_MOUSEMOVE: + { + POINT MousePos; + GetCursorPos(&MousePos); + ScreenToClient(WindowHandle, &MousePos); + + /* + Input.New->MouseX = MousePos.x; + Input.New->MouseY = App.WindowHeight - MousePos.y; + + Result.NeedsUpdate = true; + */ + }break; + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYDOWN: + case WM_KEYUP: + { + int VirtualKey = (int)Message.wParam; + bool KeyDown = (Message.lParam & (1 << 31)) == 0; + int KeyIndex = Win32GetKeyIndex(VirtualKey, true, true); + /* + if (KeyIndex >= 0) + { + DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); + Input.New->KeyStates[KeyIndex] = KeyDown; + Result.NeedsUpdate = true; + } + else + { + if (Input.TranslateInputToCharValues && KeyDown) + { + // NOTE(Peter): Took this out b/c we're translating the WM_CHAR messages + // in the message pump, and if we do it here as well, character producing + // key messages get put on the message queue twice + TranslateMessage(&Message); + DispatchMessage(&Message); + } + else + { + DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); + // NOTE(Peter): This is so that when you lift up a key that was generating a WM_CHAR, + // the app still has a chance to respond to it. + Result.NeedsUpdate = true; + } + } + */ + }break; + + case WM_CHAR: + { + /* + char TranslatedChar = (char)Message.wParam; + int KeyIndex = GetKeyIndexFromChar(TranslatedChar); + + if (KeyIndex >= 0) + { + // 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 + // get registered correctly. + Input.New->KeyStates[KeyIndex] = true; + Result.NeedsUpdate = true; + } + else + { + printf("Translated Char Not Recognized: %c\n", TranslatedChar); + //InvalidCodePath; + } + */ + }break; + + default: + { + TranslateMessage(&Message); + DispatchMessage(&Message); + }break; + } + + return Result; +} + +internal void +Win32UpdateWindowDimension(window* Window) +{ + RECT ClientRect; + GetClientRect(Window->Handle, &ClientRect); + Window->Width = ClientRect.right - ClientRect.left; + Window->Height = ClientRect.bottom - ClientRect.top; +} + +internal void +Win32ResizeDIBSection(win32_offscreen_buffer *Win32Buffer, int Width, int Height) +{ + if(Win32Buffer->Buffer.Memory) + { + VirtualFree(Win32Buffer->Buffer.Memory, 0, MEM_RELEASE); + } + + Win32Buffer->Buffer.Width = Width; + Win32Buffer->Buffer.Height = Height; + + int BytesPerPixel = 4; + Win32Buffer->Buffer.BytesPerPixel = BytesPerPixel; + + Win32Buffer->Info.bmiHeader.biSize = sizeof(Win32Buffer->Info.bmiHeader); + Win32Buffer->Info.bmiHeader.biWidth = Win32Buffer->Buffer.Width; + Win32Buffer->Info.bmiHeader.biHeight = -Win32Buffer->Buffer.Height; // Top down, not bottom up + Win32Buffer->Info.bmiHeader.biPlanes = 1; + Win32Buffer->Info.bmiHeader.biBitCount = 32; + Win32Buffer->Info.bmiHeader.biCompression = BI_RGB; + + int BitmapMemorySize = (Win32Buffer->Buffer.Width * Win32Buffer->Buffer.Height)*BytesPerPixel; + Win32Buffer->Buffer.Memory = (u8*)VirtualAlloc(0, BitmapMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + Win32Buffer->Buffer.Pitch = Width*BytesPerPixel; +} + +internal void +Win32DisplayBufferInWindow(win32_offscreen_buffer* Win32Buffer, window Window) +{ + StretchDIBits(Window.DeviceContext, + 0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height, + 0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height, + Win32Buffer->Buffer.Memory, + &Win32Buffer->Info, + DIB_RGB_COLORS, SRCCOPY); +} + +/// +// Memory +/// + +internal u8* +Win32BasicAlloc (s32 Size) +{ + return (u8*)VirtualAlloc(NULL, Size, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); +} + +PLATFORM_ALLOC(Win32Alloc) +{ + platform_memory_result Result = {}; + Result.Error = PLATFORM_MEMORY_NO_ERROR; + + Result.Base = Win32BasicAlloc(Size); + if (Result.Base) + { + Result.Size = Size; + } + else + { + Result.Error = 1; + } + + return Result; +} + +PLATFORM_FREE(Win32Free) +{ + b32 Result = VirtualFree(Base, Size, MEM_RELEASE); + return Result; +} + +// File IO +PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile) +{ + platform_memory_result Result = {}; + Result.Error = PLATFORM_MEMORY_NO_ERROR; + + HANDLE FileHandle = CreateFileA ( + Path, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (FileHandle != INVALID_HANDLE_VALUE) + { + DWORD FileSize = GetFileSize(FileHandle, NULL); + Result.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + if (Result.Base) + { + Result.Size = FileSize; + + s32 BytesRead = 0; + if (ReadFile(FileHandle, (LPVOID)Result.Base, FileSize, (LPDWORD)(&BytesRead), NULL)) + { + + } + else + { + Result.Size = 0; + Result.Error = 1; + } + } + CloseHandle(FileHandle); + } + else + { + // TODO(Peter): failure + } + + return Result; +} + +PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile) +{ + b32 Result = false; + HANDLE FileHandle = CreateFileA ( + Path, + 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): Error handling + } + + return Result; +} + +PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) +{ + b32 Result = false; + return Result; +} + +/// +// DLL +/// + +internal void +GetApplicationPath(system_path* Result) +{ + Assert(Result->Path); + Result->PathLength = GetModuleFileNameA(0, Result->Path, Result->PathLength); + + u32 CharactersScanned = 0; + u32 IndexOfLastSlash = 0; + char *Scan = Result->Path; + while(*Scan) + { + if (*Scan == '\\') + { + Result->IndexOfLastSlash = CharactersScanned + 1; + } + Scan++; + CharactersScanned++; + } +} + +internal b32 +LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult) +{ + b32 Success = false; + Assert(DLLResult->DLL == 0); + + DLLResult->DLL = LoadLibraryA(DLLName); // TODO(Peter): Error checking + if (DLLResult->DLL) + { + Success = true; + DLLResult->IsValid = true; + } + + return Success; +} + +internal void +UnloadApplicationDLL(win32_dll_refresh* DLL) +{ + if (DLL->DLL) + { + FreeLibrary(DLL->DLL); + } + DLL->DLL = 0; + DLL->IsValid = false; +} + +internal win32_dll_refresh +InitializeDLLHotReloading(char* SourceDLLName, + char* WorkingDLLFileName, + char* LockFileName) +{ + win32_dll_refresh Result = {}; + Result.IsValid = false; + + system_path ExePath = {}; + ExePath.PathLength = MAX_PATH; + ExePath.Path = (char*)Win32BasicAlloc(ExePath.PathLength); + GetApplicationPath(&ExePath); + + Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32StringLength(SourceDLLName), SourceDLLName, + MAX_PATH, Result.SourceDLLPath); + Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32StringLength(WorkingDLLFileName), WorkingDLLFileName, + MAX_PATH, Result.WorkingDLLPath); + Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, + Win32StringLength(LockFileName), LockFileName, + MAX_PATH, Result.LockFilePath); + + Win32Free((u8*)ExePath.Path, ExePath.PathLength); + return Result; + +} + +internal b32 +HotLoadDLL(win32_dll_refresh* DLL) +{ + b32 DidReload = false; + + FILETIME UpdatedLastWriteTime = GetFileLastWriteTime(DLL->SourceDLLPath); + if (CompareFileTime(&UpdatedLastWriteTime, &DLL->LastWriteTime)) + { + WIN32_FILE_ATTRIBUTE_DATA Ignored; + if (!GetFileAttributesEx(DLL->LockFilePath, GetFileExInfoStandard, &Ignored)) + { + UnloadApplicationDLL(DLL); + CopyFileA(DLL->SourceDLLPath, DLL->WorkingDLLPath, FALSE); + LoadApplicationDLL(DLL->WorkingDLLPath, DLL); + DLL->LastWriteTime = UpdatedLastWriteTime; + DidReload = true; + } + } + + return DidReload; +} + +///////////////////////////////////////// +// +// Timing +// +///////////////////////////////////////// + +internal s64 +GetPerformanceFrequency () +{ + LARGE_INTEGER Frequency; + if (!QueryPerformanceFrequency(&Frequency)) + { + s32 Error = GetLastError(); + InvalidCodePath; + } + return (s64)Frequency.QuadPart; +} + +internal s64 +GetWallClock () +{ + LARGE_INTEGER Time; + if (!QueryPerformanceCounter(&Time)) + { + s32 Error = GetLastError(); + InvalidCodePath; + } + return (s64)Time.QuadPart; +} + +///////////////////////////////////////// +// +// Open GL +// +///////////////////////////////////////// + + +internal void +OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements, + u8* UVs, s32 UVElements, + u8* Colors, s32 ColorsElements, + s32 TriCount) +{ + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(VertexElements, GL_FLOAT, VertexElements * sizeof(r32), Vertecies); + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(UVElements, GL_FLOAT, UVElements * sizeof(r32), UVs); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(ColorsElements, GL_FLOAT, ColorsElements * sizeof(r32), Colors); + + glDrawArrays(GL_TRIANGLES, 0, TriCount); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); +} + +internal void +OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2, + v2 UV0, v2 UV1, v2 UV2, + v4 C0, v4 C1, v4 C2) +{ + glBegin(GL_TRIANGLES); + + glTexCoord2f(UV0.x, UV0.y); + glColor4f(C0.r, C0.g, C0.b, C0.a); + glVertex4f(P0.x, P0.y, P0.z, P0.w); + + glTexCoord2f(UV1.x, UV1.y); + glColor4f(C1.r, C1.g, C1.b, C1.a); + glVertex4f(P1.x, P1.y, P1.z, P1.w); + + glTexCoord2f(UV2.x, UV2.y); + glColor4f(C2.r, C2.g, C2.b, C2.a); + glVertex4f(P2.x, P2.y, P2.z, P2.w); + + glEnd(); +} + +internal void +OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2, + v2 UV0, v2 UV1, v2 UV2, + v4 C0, v4 C1, v4 C2) +{ + glBegin(GL_TRIANGLES); + + glTexCoord2f(UV0.x, UV0.y); + glColor4f(C0.r, C0.g, C0.b, C0.a); + glVertex2f(P0.x, P0.y); + + glTexCoord2f(UV1.x, UV1.y); + glColor4f(C1.r, C1.g, C1.b, C1.a); + glVertex2f(P1.x, P1.y); + + glTexCoord2f(UV2.x, UV2.y); + glColor4f(C2.r, C2.g, C2.b, C2.a); + glVertex2f(P2.x, P2.y); + + glEnd(); +} + +internal void +LoadModelView (r32 Matrix[16]) +{ + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(Matrix); +} + +internal void +LoadProjection (r32 Matrix[16]) +{ + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(Matrix); +} + +internal void +ClearRenderBuffer () +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +s32 NextTextureHandle = 1; +internal s32 +SubmitTexture (u8* Memory, s32 Width, s32 Height) +{ + s32 TextureHandle = NextTextureHandle++; + glBindTexture(GL_TEXTURE_2D, TextureHandle); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory); + return TextureHandle; +} + +internal void +BindTexture (s32 TextureHandle) +{ + glBindTexture(GL_TEXTURE_2D, TextureHandle); +} + +#define GS_WIN32_CPP +#endif // GS_WIN32_CPP \ No newline at end of file diff --git a/gs_win32.h b/gs_win32.h index dbc113d..347d2c8 100644 --- a/gs_win32.h +++ b/gs_win32.h @@ -1,831 +1,17 @@ #ifndef GS_WIN32_H -#ifdef DEBUG -#define DEBUG_GET_MESSAGE_NAME(string, message) sprintf(string, message); -#else -#define DEBUG_GET_MESSAGE_NAME(string, message) -#endif - -struct win32_state +struct platform_font_info { - b32 Initialized; - b32 Running; + s32 PixelHeight; + s32 Ascent, Descent, Leading; + s32 MaxCharWidth; + s32 CodepointStart; + s32 CodepointOnePastLast; + + HDC DrawingDC; + HBITMAP Bitmap; + HFONT Font; }; -struct win32_window_info -{ - char* Name; - char* ClassName; - s32 Width; - s32 Height; - WNDPROC WindowEventsHandler; // If this is left null, Win32HandleWindowsEvents will be used -}; - -struct win32_opengl_window_info -{ - s32 ColorBits; - s32 AlphaBits; - s32 DepthBits; - HGLRC RenderContext; -}; - -struct win32_window -{ - win32_window_info Info; - - WNDCLASS Class; - HWND Handle; - HDC DeviceContext; - - // TODO(peter): Make this a union? - win32_opengl_window_info OpenGLInfo; -}; - -struct handle_window_msg_result -{ - b32 NeedsUpdate; -#ifdef DEBUG - char MessageType[128]; -#endif -}; - -global_variable win32_state GlobalWin32State; - -// Utility -internal s32 Win32StringLength(char* String); -internal s32 Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest); - -// Windowing & Graphics -struct win32_offscreen_buffer -{ - u8* Memory; - s32 Width; - s32 Height; - s32 Pitch; - s32 BytesPerPixel; - BITMAPINFO Info; -}; - -internal void InitializeWin32(); -internal win32_window CreateWin32Window (char* WindowName, char* WindowClassName, s32 Width, s32 Height); -LRESULT CALLBACK Win32HandleWindowsEvents (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam); -internal handle_window_msg_result HandleWindowsMessage (HWND WindowHandle, MSG Message); -internal void Win32UpdateWindowDimension(win32_window* Window); -internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height); -internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, win32_window Window); - -// Memory - -internal platform_memory_result Win32Alloc(s32 Size); -internal b32 Win32Free(u8* Base, s32 Size); - -// File IO -internal platform_memory_result ReadEntireFile(char* Path); -internal b32 WriteEntireFile(char* Path, u8* Contents, s32 Size); -internal FILETIME GetFileLastWriteTime(char* Path); - -// DLL -struct win32_dll_refresh -{ - FILETIME LastWriteTime; - HMODULE DLL; - - b32 IsValid; - - char SourceDLLPath[MAX_PATH]; - char WorkingDLLPath[MAX_PATH]; - char LockFilePath[MAX_PATH]; -}; - -struct executable_path -{ - char Path[MAX_PATH]; - s32 PathLength; - s32 IndexOfLastSlash; -}; - -internal executable_path GetApplicationPath(); -internal b32 LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult); -internal void UnloadApplicationDLL(win32_dll_refresh* DLL); -internal win32_dll_refresh InitializeDLLHotReloading(char* SourceDLLName, char* WorkingDLLFileName, char* LockFileName); -internal b32 HotLoadDLL(win32_dll_refresh* DLL); - -/// -// Utils -/// - -internal s32 -Win32StringLength(char* String) -{ - char* At = String; - while (*At) { At++; }; - return At - String; -} - -internal s32 -Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest) -{ - char* Dst = Dest; - char* AAt = A; - for (s32 a = 0; a < ALen; a++) - { - *Dst++ = *AAt++; - } - char* BAt = B; - for (s32 b = 0; b < BLen; b++) - { - *Dst++ = *BAt++; - } - return Dst - Dest; -} - -/// -// Windowing -/// - -internal void -InitializeWin32 () -{ - GlobalWin32State = {}; - GlobalWin32State.Running = false; - GlobalWin32State.Initialized = true; -} - -internal win32_window -CreateWin32Window (HINSTANCE HInstance, win32_window_info Info) -{ - win32_window Result = {}; - Result.Info = Info; - - Result.Class = {}; - Result.Class.style = CS_HREDRAW | CS_VREDRAW; - if (Info.WindowEventsHandler) - { - Result.Class.lpfnWndProc = Info.WindowEventsHandler; - } - else - { - Result.Class.lpfnWndProc = Win32HandleWindowsEvents; - } - Result.Class.hInstance = HInstance; - Result.Class.lpszClassName = Info.ClassName; - - if (RegisterClass(&Result.Class)) - { - Result.Handle = CreateWindowEx( - 0, - Result.Class.lpszClassName, - Info.Name, - WS_OVERLAPPEDWINDOW | WS_VISIBLE, - CW_USEDEFAULT, - CW_USEDEFAULT, - Info.Width, - Info.Height, - 0, - 0, - HInstance, - 0); - Result.DeviceContext = GetDC(Result.Handle); - } - - return Result; -}; - -internal void -CreateOpenGLWindowContext (win32_opengl_window_info Info, win32_window* Window) -{ - // Setup pixel format - { - PIXELFORMATDESCRIPTOR PixelFormatDesc = { 0 }; - // TODO: Program seems to work perfectly fine without all other params except dwFlags. - // Can we skip other params for the sake of brevity? - PixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); - PixelFormatDesc.nVersion = 1; - PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; - PixelFormatDesc.iPixelType = PFD_TYPE_RGBA;// TODO(Peter): include this in win32_opengl_window_info? - PixelFormatDesc.cColorBits = Info.ColorBits; - PixelFormatDesc.cAlphaBits = Info.AlphaBits; - PixelFormatDesc.cDepthBits = Info.DepthBits; - PixelFormatDesc.dwLayerMask = PFD_MAIN_PLANE; // TODO(Peter): include this in win32_opengl_window_info? - // - - s32 PixelFormat = ChoosePixelFormat(Window->DeviceContext, &PixelFormatDesc); - if (!PixelFormat) { InvalidCodePath; } // TODO: Log: Choose pixel format failed - if (!SetPixelFormat(Window->DeviceContext, PixelFormat, &PixelFormatDesc)) { InvalidCodePath; } // TODO: Log: Set pixel format failed - } - - // Create rendering context - { - // TODO: Create "proper" context? - // https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation - - Info.RenderContext = wglCreateContext(Window->DeviceContext); - wglMakeCurrent(Window->DeviceContext, Info.RenderContext); - - // TODO(Peter): do we want this? - /* - glGetIntegerv(GL_MAJOR_VERSION, ); - glGetIntegerv(GL_MINOR_VERSION, ); - (char*)glGetString(GL_VENDOR); - (char*)glGetString(GL_RENDERER); - */ - } - - Window->OpenGLInfo = Info; -} - -struct handle_window_event_result -{ - LRESULT Result; - b32 Handled; -}; - -internal handle_window_event_result -HandleWindowEventUnlessWouldUseDefault (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - handle_window_event_result Result = {}; - Result.Handled = false; - - switch (Msg) - { - case WM_SIZE: - { - //ResizeDIBSection(); - Result.Handled = true; - }break; - - case WM_CLOSE: - { - Result.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); - Result.Handled = true; - }break; - - case WM_DESTROY: - { - GlobalWin32State.Running = false; - Result.Handled = true; - }break; - - case WM_PAINT: - { - PAINTSTRUCT PaintStruct; - HDC DeviceContext; - b32 PaintResult; - - DeviceContext = BeginPaint(WindowHandle, &PaintStruct); - PaintResult = EndPaint(WindowHandle, &PaintStruct); - Result.Handled = true; - }break; - } - - return Result; -} - -LRESULT CALLBACK -Win32HandleWindowsEvents ( -HWND WindowHandle, -UINT Msg, -WPARAM wParam, -LPARAM lParam -) -{ - handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault( - WindowHandle, - Msg, - wParam, - lParam); - - if (!EventResult.Handled) - { - EventResult.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam); - } - - return EventResult.Result; -} - -#define WIN32_SHOULD_TRANSLATE_TO_CHAR -1 - -static int -Win32GetKeyIndex (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar) -{ - int Result = WIN32_SHOULD_TRANSLATE_TO_CHAR; - - if (Win32VirtualKey == VK_ESCAPE) { Result = (int)KeyCode_Esc; } - - if (!TranslateToChar) - { - if (Win32VirtualKey == VK_SPACE) { Result = (int)KeyCode_Space; } - - } - - if (Win32VirtualKey == VK_CAPITAL) { Result = (int)KeyCode_CapsLock; } - else if (Win32VirtualKey == VK_TAB) { Result = (int)KeyCode_Tab; } - else if (Win32VirtualKey == VK_LSHIFT) { Result = (int)KeyCode_LeftShift; } - else if (Win32VirtualKey == VK_RSHIFT) { Result = (int)KeyCode_RightShift; } - else if (Win32VirtualKey == VK_LCONTROL) { Result = (int)KeyCode_LeftCtrl; } - else if (Win32VirtualKey == VK_RCONTROL) { Result = (int)KeyCode_RightCtrl; } - - // TODO(Peter): support the function key? - //else if (Win32VirtualKey == VK_) { Result = (int)KeyCode_Fn; } - - else if (Win32VirtualKey == VK_MENU) { Result = (int)KeyCode_Alt; } - else if (Win32VirtualKey == VK_PRIOR) { Result = (int)KeyCode_PageUp; } - else if (Win32VirtualKey == VK_NEXT) { Result = (int)KeyCode_PageDown; } - else if (Win32VirtualKey == VK_BACK) { Result = (int)KeyCode_Backspace; } - else if (Win32VirtualKey == VK_DELETE) { Result = (int)KeyCode_Delete; } - else if (Win32VirtualKey == VK_RETURN) { Result = (int)KeyCode_Enter; } - - else if (Win32VirtualKey == VK_F1) { Result = (int)KeyCode_F1; } - else if (Win32VirtualKey == VK_F2) { Result = (int)KeyCode_F2; } - else if (Win32VirtualKey == VK_F3) { Result = (int)KeyCode_F3; } - else if (Win32VirtualKey == VK_F4) { Result = (int)KeyCode_F4; } - else if (Win32VirtualKey == VK_F5) { Result = (int)KeyCode_F5; } - else if (Win32VirtualKey == VK_F6) { Result = (int)KeyCode_F6; } - else if (Win32VirtualKey == VK_F7) { Result = (int)KeyCode_F7; } - else if (Win32VirtualKey == VK_F8) { Result = (int)KeyCode_F8; } - else if (Win32VirtualKey == VK_F9) { Result = (int)KeyCode_F9; } - else if (Win32VirtualKey == VK_F10) { Result = (int)KeyCode_F10; } - else if (Win32VirtualKey == VK_F11) { Result = (int)KeyCode_F11; } - else if (Win32VirtualKey == VK_F12) { Result = (int)KeyCode_F12; } - - if (!TranslateToChar) - { - if (Win32VirtualKey == 0x30) { Result = (int)KeyCode_0; } - else if (Win32VirtualKey == 0x31) { Result = (int)KeyCode_1; } - else if (Win32VirtualKey == 0x32) { Result = (int)KeyCode_2; } - else if (Win32VirtualKey == 0x33) { Result = (int)KeyCode_3; } - else if (Win32VirtualKey == 0x34) { Result = (int)KeyCode_4; } - else if (Win32VirtualKey == 0x35) { Result = (int)KeyCode_5; } - else if (Win32VirtualKey == 0x36) { Result = (int)KeyCode_6; } - else if (Win32VirtualKey == 0x37) { Result = (int)KeyCode_7; } - else if (Win32VirtualKey == 0x38) { Result = (int)KeyCode_8; } - else if (Win32VirtualKey == 0x39) { Result = (int)KeyCode_9; } - - else if (Win32VirtualKey == 0x41) { Result = (int)KeyCode_A; } - else if (Win32VirtualKey == 0x42) { Result = (int)KeyCode_B; } - else if (Win32VirtualKey == 0x43) { Result = (int)KeyCode_C; } - else if (Win32VirtualKey == 0x44) { Result = (int)KeyCode_D; } - else if (Win32VirtualKey == 0x45) { Result = (int)KeyCode_E; } - else if (Win32VirtualKey == 0x46) { Result = (int)KeyCode_F; } - else if (Win32VirtualKey == 0x47) { Result = (int)KeyCode_G; } - else if (Win32VirtualKey == 0x48) { Result = (int)KeyCode_H; } - else if (Win32VirtualKey == 0x49) { Result = (int)KeyCode_I; } - else if (Win32VirtualKey == 0x4A) { Result = (int)KeyCode_J; } - else if (Win32VirtualKey == 0x4B) { Result = (int)KeyCode_K; } - else if (Win32VirtualKey == 0x4C) { Result = (int)KeyCode_L; } - else if (Win32VirtualKey == 0x4D) { Result = (int)KeyCode_M; } - else if (Win32VirtualKey == 0x4E) { Result = (int)KeyCode_N; } - else if (Win32VirtualKey == 0x4F) { Result = (int)KeyCode_O; } - else if (Win32VirtualKey == 0x50) { Result = (int)KeyCode_P; } - else if (Win32VirtualKey == 0x51) { Result = (int)KeyCode_Q; } - else if (Win32VirtualKey == 0x52) { Result = (int)KeyCode_R; } - else if (Win32VirtualKey == 0x53) { Result = (int)KeyCode_S; } - else if (Win32VirtualKey == 0x54) { Result = (int)KeyCode_T; } - else if (Win32VirtualKey == 0x55) { Result = (int)KeyCode_U; } - else if (Win32VirtualKey == 0x56) { Result = (int)KeyCode_V; } - else if (Win32VirtualKey == 0x57) { Result = (int)KeyCode_W; } - else if (Win32VirtualKey == 0x58) { Result = (int)KeyCode_X; } - else if (Win32VirtualKey == 0x59) { Result = (int)KeyCode_Y; } - else if (Win32VirtualKey == 0x5A) { Result = (int)KeyCode_Z; } - } - - if (NumpadValid) - { - if (Win32VirtualKey == VK_NUMPAD0) { Result = (int)KeyCode_Num0; } - else if (Win32VirtualKey == VK_NUMPAD1) { Result = (int)KeyCode_Num1; } - else if (Win32VirtualKey == VK_NUMPAD2) { Result = (int)KeyCode_Num2; } - else if (Win32VirtualKey == VK_NUMPAD3) { Result = (int)KeyCode_Num3; } - else if (Win32VirtualKey == VK_NUMPAD4) { Result = (int)KeyCode_Num4; } - else if (Win32VirtualKey == VK_NUMPAD5) { Result = (int)KeyCode_Num5; } - else if (Win32VirtualKey == VK_NUMPAD6) { Result = (int)KeyCode_Num6; } - else if (Win32VirtualKey == VK_NUMPAD7) { Result = (int)KeyCode_Num7; } - else if (Win32VirtualKey == VK_NUMPAD8) { Result = (int)KeyCode_Num8; } - else if (Win32VirtualKey == VK_NUMPAD9) { Result = (int)KeyCode_Num9; } - } - - if (Win32VirtualKey == VK_UP) { Result = (int)KeyCode_UpArrow; } - else if (Win32VirtualKey == VK_DOWN) { Result = (int)KeyCode_DownArrow; } - else if (Win32VirtualKey == VK_LEFT) { Result = (int)KeyCode_LeftArrow; } - else if (Win32VirtualKey == VK_RIGHT) { Result = (int)KeyCode_RightArrow; } - - return Result; -} - -internal handle_window_msg_result -HandleWindowsMessage ( -HWND WindowHandle, -MSG Message) -{ - handle_window_msg_result Result = {}; - Result.NeedsUpdate = 0; - - switch (Message.message) - { - case WM_HOTKEY: - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_HOTKEY "); - }break; - - case WM_MOUSEWHEEL: - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_MOUSEWHEEL "); - int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); - /* - Input.New->MouseScroll = MouseWheel; - Result.NeedsUpdate = true; - */ - }break; - - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_MOUSEBUTTON "); - - /* - Input.New->KeyStates[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0; - Input.New->KeyStates[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0; - Input.New->KeyStates[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0; - // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are - // VK_XBUTTON1 and VK_XBUTTON2 - - if (KeyTransitionedDown(KeyCode_MouseLeftButton, Input)) - { - Input.MouseDownX = Input.New->MouseX; - Input.MouseDownY = Input.New->MouseY; - } - Result.NeedsUpdate = true;*/ - }break; - - case WM_MOUSEMOVE: - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_MOUSEMOVE "); - POINT MousePos; - GetCursorPos(&MousePos); - ScreenToClient(WindowHandle, &MousePos); - - /* - Input.New->MouseX = MousePos.x; - Input.New->MouseY = App.WindowHeight - MousePos.y; - - Result.NeedsUpdate = true; - */ - }break; - - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - case WM_KEYDOWN: - case WM_KEYUP: - { - int VirtualKey = (int)Message.wParam; - bool KeyDown = (Message.lParam & (1 << 31)) == 0; - int KeyIndex = Win32GetKeyIndex(VirtualKey, true, true); - /* - if (KeyIndex >= 0) - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); - Input.New->KeyStates[KeyIndex] = KeyDown; - Result.NeedsUpdate = true; - } - else - { - if (Input.TranslateInputToCharValues && KeyDown) - { - // NOTE(Peter): Took this out b/c we're translating the WM_CHAR messages - // in the message pump, and if we do it here as well, character producing - // key messages get put on the message queue twice - TranslateMessage(&Message); - DispatchMessage(&Message); - } - else - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent "); - // NOTE(Peter): This is so that when you lift up a key that was generating a WM_CHAR, - // the app still has a chance to respond to it. - Result.NeedsUpdate = true; - } - } - */ - }break; - - case WM_CHAR: - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_CHAR "); - /* - char TranslatedChar = (char)Message.wParam; - int KeyIndex = GetKeyIndexFromChar(TranslatedChar); - - if (KeyIndex >= 0) - { - // 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 - // get registered correctly. - Input.New->KeyStates[KeyIndex] = true; - Result.NeedsUpdate = true; - } - else - { - printf("Translated Char Not Recognized: %c\n", TranslatedChar); - //InvalidCodePath; - } - */ - }break; - - default: - { - DEBUG_GET_MESSAGE_NAME(Result.MessageType, "Unhandled WM Event "); - TranslateMessage(&Message); - DispatchMessage(&Message); - }break; - } - - return Result; -} - -internal void -Win32UpdateWindowDimension(win32_window* Window) -{ - RECT ClientRect; - GetClientRect(Window->Handle, &ClientRect); - Window->Info.Width = ClientRect.right - ClientRect.left; - Window->Info.Height = ClientRect.bottom - ClientRect.top; -} - -internal void -Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height) -{ - if(Buffer->Memory) - { - VirtualFree(Buffer->Memory, 0, MEM_RELEASE); - } - - Buffer->Width = Width; - Buffer->Height = Height; - - int BytesPerPixel = 4; - Buffer->BytesPerPixel = BytesPerPixel; - - Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader); - Buffer->Info.bmiHeader.biWidth = Buffer->Width; - Buffer->Info.bmiHeader.biHeight = -Buffer->Height; // Top down, not bottom up - Buffer->Info.bmiHeader.biPlanes = 1; - Buffer->Info.bmiHeader.biBitCount = 32; - Buffer->Info.bmiHeader.biCompression = BI_RGB; - - int BitmapMemorySize = (Buffer->Width*Buffer->Height)*BytesPerPixel; - Buffer->Memory = (u8*)VirtualAlloc(0, BitmapMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - Buffer->Pitch = Width*BytesPerPixel; -} - -internal void -Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, win32_window Window) -{ - StretchDIBits(Window.DeviceContext, - 0, 0, Buffer->Width, Buffer->Height, - 0, 0, Buffer->Width, Buffer->Height, - Buffer->Memory, - &Buffer->Info, - DIB_RGB_COLORS, SRCCOPY); -} - -/// -// Memory -/// - -internal win32_memory_op_result -Win32Alloc(s32 Size) -{ - win32_memory_op_result Result = {}; - Result.Success = false; - - Result.Base = (u8*)VirtualAlloc(NULL, Size, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - if (Result.Base) - { - Result.Size = Size; - Result.Success = true; - } - - return Result; -} - -internal b32 -Win32Free(u8* Base, s32 Size) -{ - b32 Result = VirtualFree(Base, Size, MEM_RELEASE); - return Result; -} - -// File IO -internal win32_memory_op_result -ReadEntireFile(char* Path) -{ - win32_memory_op_result Result = {}; - Result.Success = false; - - HANDLE FileHandle = CreateFileA ( - Path, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (FileHandle != INVALID_HANDLE_VALUE) - { - DWORD FileSize = GetFileSize(FileHandle, NULL); - Result.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - if (Result.Base) - { - Result.Size = FileSize; - - s32 BytesRead = 0; - if (ReadFile(FileHandle, (LPVOID)Result.Base, FileSize, (LPDWORD)(&BytesRead), NULL)) - { - Result.Success = true; - } - else - { - Result.Size = 0; - } - } - CloseHandle(FileHandle); - } - else - { - // TODO(Peter): failure - } - - return Result; -} - -internal b32 -WriteEntireFile (char* Path, u8* Contents, s32 Size) -{ - b32 Result = false; - HANDLE FileHandle = CreateFileA ( - Path, - 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): Error handling - } - - return Result; -} - -/// -// DLL -/// - -internal executable_path -GetApplicationPath() -{ - executable_path ExePath = {}; - ExePath.PathLength = GetModuleFileNameA(0, ExePath.Path, MAX_PATH); - - u32 CharactersScanned = 0; - u32 IndexOfLastSlash = 0; - char *Scan = ExePath.Path; - while(*Scan) - { - if (*Scan == '\\') - { - ExePath.IndexOfLastSlash = CharactersScanned + 1; - } - Scan++; - CharactersScanned++; - } - - return ExePath; -} - -internal b32 -LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult) -{ - b32 Success = false; - Assert(DLLResult->DLL == 0); - - DLLResult->DLL = LoadLibraryA(DLLName); // TODO(Peter): Error checking - if (DLLResult->DLL) - { - Success = true; - DLLResult->IsValid = true; - } - - return Success; -} - -internal void -UnloadApplicationDLL(win32_dll_refresh* DLL) -{ - if (DLL->DLL) - { - FreeLibrary(DLL->DLL); - } - DLL->DLL = 0; - DLL->IsValid = false; -} - -internal win32_dll_refresh -InitializeDLLHotReloading(char* SourceDLLName, - char* WorkingDLLFileName, - char* LockFileName) -{ - win32_dll_refresh Result = {}; - Result.IsValid = false; - - executable_path ExePath = GetApplicationPath(); - - Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32StringLength(SourceDLLName), SourceDLLName, - MAX_PATH, Result.SourceDLLPath); - Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32StringLength(WorkingDLLFileName), WorkingDLLFileName, - MAX_PATH, Result.WorkingDLLPath); - Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path, - Win32StringLength(LockFileName), LockFileName, - MAX_PATH, Result.LockFilePath); - - return Result; - -} - -internal b32 -HotLoadDLL(win32_dll_refresh* DLL) -{ - b32 DidReload = false; - - FILETIME UpdatedLastWriteTime = GetFileLastWriteTime(DLL->SourceDLLPath); - if (CompareFileTime(&UpdatedLastWriteTime, &DLL->LastWriteTime)) - { - WIN32_FILE_ATTRIBUTE_DATA Ignored; - if (!GetFileAttributesEx(DLL->LockFilePath, GetFileExInfoStandard, &Ignored)) - { - UnloadApplicationDLL(DLL); - CopyFileA(DLL->SourceDLLPath, DLL->WorkingDLLPath, FALSE); - LoadApplicationDLL(DLL->WorkingDLLPath, DLL); - DLL->LastWriteTime = UpdatedLastWriteTime; - DidReload = true; - } - } - - return DidReload; -} - #define GS_WIN32_H #endif // GS_WIN32_H diff --git a/interface.h b/interface.h index cb1dfb1..752e3bf 100644 --- a/interface.h +++ b/interface.h @@ -110,24 +110,31 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon v2 LowerRight = Position; render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length, - *Font->Atlas); + Font->BitmapMemory, + Font->BitmapTextureHandle, + Font->BitmapWidth, + Font->BitmapHeight, + Font->BitmapBytesPerPixel, + Font->BitmapStride); r32 FontScale = (r32)PointSize / Font->PixelHeight; v2 RegisterPosition = Position; char* C = String.Memory; for (s32 i = 0; i < String.Length; i++) { - s32 GlyphDataIndex = GetCharacterIndexInFont(*C, Font); - character_data Data = Font->CharacterLUT_Values[GlyphDataIndex]; + s32 GlyphDataIndex = GetIndexForCodepoint(*Font, *C); + codepoint_bitmap CodepointInfo = Font->CodepointValues[GlyphDataIndex]; - r32 MinX = RegisterPosition.x + Data.RegisterXOffset * FontScale; - r32 MinY = RegisterPosition.y + Data.BaselineYOffset * FontScale; - r32 MaxX = MinX + (Data.X1 - Data.X0) * FontScale; - r32 MaxY = MinY + (Data.Y1 - Data.Y0) * FontScale; + r32 MinX = RegisterPosition.x + CodepointInfo.XOffset * FontScale; + r32 MinY = RegisterPosition.y + CodepointInfo.YOffset * FontScale; + r32 MaxX = MinX + (CodepointInfo.Width) * FontScale; + r32 MaxY = MinY + (CodepointInfo.Height) * FontScale; - PushQuad2DOnBatch(&BatchConstructor, v2{MinX, MinY}, v2{MaxX, MinY}, v2{MaxX, MaxY}, v2{MinX, MaxY}, Data.AtlasMinUV, Data.AtlasMaxUV, Color); + v2 MinUV = v2{(r32)CodepointInfo.BitmapX, (r32)CodepointInfo.BitmapY}; + v2 MaxUV = MinUV + v2{(r32)CodepointInfo.Width, (r32)CodepointInfo.Height}; + PushQuad2DOnBatch(&BatchConstructor, v2{MinX, MinY}, v2{MaxX, MinY}, v2{MaxX, MaxY}, v2{MinX, MaxY}, MinUV, MaxUV, Color); - RegisterPosition.x += Data.Advance * Font->FontScale * FontScale; + RegisterPosition.x += CodepointInfo.Width * FontScale; C++; } @@ -352,7 +359,7 @@ EvaluatePanel (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Label v2 TextPos = v2{ Min.x + Config.Margin.x, - Max.y - (Config.Font->NewLineYOffset + Config.Margin.y) + Max.y - ((r32)NewLineYOffset(*Config.Font) + Config.Margin.y) }; DrawString(RenderBuffer, Label, Config.Font, 14, TextPos, Config.TextColor); Result.ChildMax = v2{Max.x, TextPos.y} - Config.Margin; @@ -396,7 +403,7 @@ DrawOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max, Result.StartIndex = Start; Result.Selection = Selection_None; - r32 OptionHeight = Config.Font->NewLineYOffset + (2 * Config.Margin.y); + r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y); r32 OptionOffset = OptionHeight + Config.Margin.y; s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2; @@ -453,7 +460,7 @@ DrawSelectableOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max, Result.StartIndex = Start; Result.Selection = Selection_None; - r32 OptionHeight = Config.Font->NewLineYOffset + (2 * Config.Margin.y); + r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y); r32 OptionOffset = OptionHeight + Config.Margin.y; s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2; diff --git a/testmain.cpp b/testmain.cpp new file mode 100644 index 0000000..0c9350c --- /dev/null +++ b/testmain.cpp @@ -0,0 +1,16 @@ +#include +#include "gs_platform.h" +#include "gs_win32.h" + +int main (int ArgCount, char** Args) +{ + window MainWindow = PlatformCreateWindow("Test Window", 1024, 768); + + win32_opengl_window_info OpenGLInfo = {}; + OpenGLInfo.ColorBits = 32; + OpenGLInfo.AlphaBits = 8; + Win32CreateOpenGLContext(OpenGLInfo, MainWindow); + + + return 0; +} \ No newline at end of file diff --git a/win32_foldhaus.cpp b/win32_foldhaus.cpp index 1dd9f51..f20bded 100644 --- a/win32_foldhaus.cpp +++ b/win32_foldhaus.cpp @@ -1,12 +1,12 @@ #include #include #include +#include +#include #include "foldhaus_platform.h" -#include "gs_win32.h" - -#include "gs_opengl.h" +#include "gs_win32.cpp" #include "foldhaus_renderer.cpp" global_variable b32 Running = false; @@ -16,7 +16,7 @@ char DLLName[] = "foldhaus.dll"; char WorkingDLLName[] = "foldhaus_temp.dll"; char DLLLockFileName[] = "lock.tmp"; -win32_window MainWindow; +window MainWindow; struct worker_thread_entry { @@ -116,7 +116,7 @@ WorkerThreadProc (LPVOID InputThreadInfo) PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle) { - s32 Handle = SubmitTexture(Width, Height, Memory); + s32 Handle = SubmitTexture(Memory, Width, Height); return Handle; } @@ -186,7 +186,7 @@ PLATFORM_GET_SEND_ADDRESS_HANDLE(Win32GetSendAddress) Assert(Win32NetworkAddressHandleCount < Win32NetworkAddressHandleMax); s32 NewAddressIndex = Win32NetworkAddressHandleCount++; - NetworkAddressValues[NewAddressIndex].sin_family = Family; + NetworkAddressValues[NewAddressIndex].sin_family = AddressFamily; NetworkAddressValues[NewAddressIndex].sin_port = HostToNetU16(Port); NetworkAddressValues[NewAddressIndex].sin_addr.s_addr = HostToNetU32(Address); @@ -233,6 +233,50 @@ PLATFORM_CLOSE_SOCKET(Win32CloseSocket) closesocket(SocketValues[SocketIndex].Socket); } +GET_FONT_INFO(Win32GetFontInfo) +{ + platform_font_info Result = {}; + + Result.DrawingDC = CreateCompatibleDC(NULL); + SetBkColor(Result.DrawingDC, RGB(0, 0, 0)); + SetTextColor(Result.DrawingDC, RGB(255, 255, 255)); + Result.Bitmap = CreateCompatibleBitmap(NULL, PixelHeight * 2, PixelHeight * 2); + SelectObject(Result.DrawingDC, Result.Bitmap); + + Result.Font= CreateFont(PixelHeight, 0, 0, 0, + // TODO(Peter): Font weight, need a platform way to request others + FW_NORMAL, + FALSE, // Italic + FALSE, // Underling + FALSE, // Strikeout, + ANSI_CHARSET, + OUT_OUTLINE_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + FIXED_PITCH, + FontName); + SelectFont(Result.DrawingDC, Result.Font); + + TEXTMETRIC WindowsFontMetrics = {}; + if (GetTextMetrics(Result.DrawingDC, &WindowsFontMetrics)) + { + Result.PixelHeight = WindowsFontMetrics.tmHeight; + Result.Ascent = WindowsFontMetrics.tmAscent; + Result.Descent = WindowsFontMetrics.tmDescent; + Result.Leading = WindowsFontMetrics.tmExternalLeading; + Result.MaxCharWidth = WindowsFontMetrics.tmMaxCharWidth; + Result.CodepointStart = WindowsFontMetrics.tmFirstChar; + Result.CodepointOnePastLast = WindowsFontMetrics.tmLastChar + 1; + } + + return Result; +} + +DRAW_FONT_CODEPOINT(Win32DrawFontCodepoint) +{ + +} + LRESULT CALLBACK HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam) { @@ -281,14 +325,13 @@ HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam) } internal void -HandleWindowMessage (MSG Message, win32_window* Window, input_frame* InputFrame) +HandleWindowMessage (MSG Message, window* Window, input_frame* InputFrame) { switch (Message.message) { case WM_MOUSEWHEEL: { - int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); - InputFrame->MouseScroll = MouseWheel; + Win32UpdateInputFrameMouseWheelDelta(InputFrame, Message); }break; case WM_LBUTTONDOWN: @@ -298,11 +341,7 @@ HandleWindowMessage (MSG Message, win32_window* Window, input_frame* InputFrame) case WM_RBUTTONDOWN: case WM_RBUTTONUP: { - InputFrame->KeysDown[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0; - InputFrame->KeysDown[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0; - InputFrame->KeysDown[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0; - // NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are - // VK_XBUTTON1 and VK_XBUTTON2 + Win32UpdateInputFrameMouseState(InputFrame); }break; case WM_SYSKEYDOWN: @@ -342,9 +381,10 @@ internal void DebugPrint (char* Format, ...) { char Buffer[256]; + string StringBuffer = MakeString(Buffer, 256); va_list Args; va_start(Args, Format); - PrintFInternal(Buffer, 256, Format, Args); + PrintF(&StringBuffer, Format, Args); OutputDebugStringA(Buffer); va_end(Args); } @@ -376,14 +416,7 @@ PSTR CmdLineArgs, INT NCmdShow ) { - win32_window_info MainWindowInfo = {}; - MainWindowInfo.Name = "Foldhaus"; - MainWindowInfo.ClassName = "Foldhaus Window Class"; - MainWindowInfo.Width = 1440; - MainWindowInfo.Height = 768; - MainWindowInfo.WindowEventsHandler = HandleWindowEvents; - - MainWindow = CreateWin32Window (HInstance, MainWindowInfo); + MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents); Win32UpdateWindowDimension(&MainWindow); win32_opengl_window_info OpenGLWindowInfo = {}; @@ -393,6 +426,10 @@ INT NCmdShow CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); s64 PerformanceCountFrequency = GetPerformanceFrequency(); + s64 LastFrameEnd = GetWallClock(); + r32 TargetSecondsPerFrame = 1 / 60.0f; + r32 LastFrameSecondsElapsed = 0.0f; + GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services)); InitDebugServices(GlobalDebugServices, (u8*)malloc(Megabytes(8)), Megabytes(8), 1000, PerformanceCountFrequency); GlobalDebugServices->GetWallClock = GetWallClock; @@ -431,21 +468,23 @@ INT NCmdShow context Context = {}; Context.MemorySize = InitialMemory.Size; Context.MemoryBase = InitialMemory.Base; - Context.WindowWidth = MainWindow.Info.Width; - Context.WindowHeight = MainWindow.Info.Height; + Context.WindowWidth = MainWindow.Width; + Context.WindowHeight = MainWindow.Height; // Platform functions Context.GeneralWorkQueue = &WorkQueue; Context.PlatformAlloc = Win32Alloc; Context.PlatformFree = Win32Free; - Context.PlatformReadEntireFile = ReadEntireFile; - Context.PlatformWriteEntireFile = WriteEntireFile; - Context.PlatformGetFilePath = Win32SystemDialogOpenFile; + Context.PlatformReadEntireFile = Win32ReadEntireFile; + Context.PlatformWriteEntireFile = Win32WriteEntireFile; + Context.PlatformGetFilePath = Win32SystemDialogueOpenFile; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle; Context.PlatformGetSendAddress = Win32GetSendAddress; Context.PlatformSetSocketOption = Win32SetSocketOption; Context.PlatformCloseSocket = Win32CloseSocket; + Context.PlatformGetFontInfo = Win32GetFontInfo; + Context.PlatformDrawFontCodepoint = Win32DrawFontCodepoint; win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName); if (HotLoadDLL(&DLLRefresh)) @@ -490,7 +529,7 @@ INT NCmdShow GetCursorPos (&MousePos); ScreenToClient(MainWindow.Handle, &MousePos); Input.New->MouseX = MousePos.x; - Input.New->MouseY = MainWindow.Info.Height - MousePos.y; + Input.New->MouseY = MainWindow.Height - MousePos.y; if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton)) { @@ -501,8 +540,8 @@ INT NCmdShow // TODO(Peter): We shouldn't need to do this translation. the platform layer knows about win32_windows. We should just make that the interface // to all windows. - Context.WindowWidth = MainWindow.Info.Width; - Context.WindowHeight = MainWindow.Info.Height; + Context.WindowWidth = MainWindow.Width; + Context.WindowHeight = MainWindow.Height; Context.DeltaTime = LastFrameSecondsElapsed; Context.UpdateAndRender(Context, Input, &RenderBuffer);