diff --git a/src/DRenderer.cpp b/src/DRenderer.cpp index dbdab42..c40004a 100644 --- a/src/DRenderer.cpp +++ b/src/DRenderer.cpp @@ -17,6 +17,8 @@ #define DQN_IMPLEMENTATION #include "dqn.h" +#include + #define DR_DEBUG 1 typedef struct DRFont { @@ -43,10 +45,13 @@ typedef struct DRState typedef struct DRDebug { - i32 setPixelsPerFrame; - i32 totalSetPixels; + DRFont *font; + DqnV2 displayP; + i32 displayYOffset; + + u64 setPixelsPerFrame; + u64 totalSetPixels; - i32 displayYOffset; } DRDebug; FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color) @@ -106,6 +111,101 @@ FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer, globalDebug.setPixelsPerFrame++; } +FILE_SCOPE void DrawText(PlatformRenderBuffer *const renderBuffer, + const DRFont font, DqnV2 pos, const char *const text, + DqnV4 color = DqnV4_4f(255, 255, 255, 255), i32 len = -1) +{ + if (!text) return; + if (len == -1) len = Dqn_strlen(text); + + i32 index = 0; + color = PreMultiplyAlpha(color); + while (index < len) + { + if (text[index] < font.codepointRange.min && + text[index] > font.codepointRange.max) + { + return; + } + + i32 charIndex = text[index++] - (i32)font.codepointRange.min; + DQN_ASSERT(charIndex >= 0 && + charIndex < (i32)(font.codepointRange.max - + font.codepointRange.min)); + + stbtt_aligned_quad alignedQuad = {}; + stbtt_GetPackedQuad(font.atlas, font.bitmapDim.w, font.bitmapDim.h, + charIndex, &pos.x, &pos.y, &alignedQuad, true); + + DqnRect fontRect = {}; + fontRect.min = DqnV2_2f(alignedQuad.s0 * font.bitmapDim.w, alignedQuad.t1 * font.bitmapDim.h); + fontRect.max = DqnV2_2f(alignedQuad.s1 * font.bitmapDim.w, alignedQuad.t0 * font.bitmapDim.h); + + DqnRect screenRect = {}; + screenRect.min = DqnV2_2f(alignedQuad.x0, alignedQuad.y0); + screenRect.max = DqnV2_2f(alignedQuad.x1, alignedQuad.y1); + + // TODO: Assumes 1bpp and pitch of font bitmap + const u32 fontPitch = font.bitmapDim.w; + u32 fontOffset = (u32)(fontRect.min.x + (fontRect.max.y * fontPitch)); + u8 *fontPtr = font.bitmap + fontOffset; + + DQN_ASSERT(sizeof(u32) == renderBuffer->bytesPerPixel); + + // NOTE(doyle): This offset, yOffset and flipping t1, t0 is necessary + // for reversing the order of the font since its convention is 0,0 top + // left and -ve Y. + stbtt_packedchar *const charData = font.atlas + charIndex; + f32 fontHeightOffset = charData->yoff2 + charData->yoff; + + u32 screenOffset = (u32)(screenRect.min.x + (screenRect.min.y - fontHeightOffset) * renderBuffer->width); + u32 *screenPtr = ((u32 *)renderBuffer->memory) + screenOffset; + + i32 fontWidth = DQN_ABS((i32)(fontRect.min.x - fontRect.max.x)); + i32 fontHeight = DQN_ABS((i32)(fontRect.min.y - fontRect.max.y)); + for (i32 y = 0; y < fontHeight; y++) + { + for (i32 x = 0; x < fontWidth; x++) + { + i32 yOffset = fontHeight - y; + u8 srcA = fontPtr[x + (yOffset * fontPitch)]; + if (srcA == 0) continue; + + f32 srcANorm = srcA / 255.0f; + DqnV4 resultColor = {}; + resultColor.r = color.r * srcANorm; + resultColor.g = color.g * srcANorm; + resultColor.b = color.b * srcANorm; + resultColor.a = color.a * srcANorm; + + i32 actualX = (i32)(screenRect.min.x + x); + i32 actualY = (i32)(screenRect.min.y + y - fontHeightOffset); + SetPixel(renderBuffer, actualX, actualY, resultColor); + } + } + } +} + +FILE_SCOPE void DebugPushText(PlatformRenderBuffer *const renderBuffer, + const char *const formatStr, ...) +{ +#ifdef DR_DEBUG + DRDebug *const debug = &globalDebug; + char str[1024] = {}; + + va_list argList; + va_start(argList, formatStr); + { + i32 numCopied = Dqn_vsprintf(str, formatStr, argList); + DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(str)); + } + va_end(argList); + + DrawText(renderBuffer, *debug->font, debug->displayP, str); + debug->displayP.y += globalDebug.displayYOffset; +#endif +} + FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a, DqnV2i b, DqnV4 color) { @@ -166,12 +266,64 @@ FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a, } } -FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, - const DqnV2 p1, const DqnV2 p2, const DqnV2 p3, - DqnV4 color) +FILE_SCOPE void TransformVertexes(const DqnV2 origin, DqnV2 *const vertexList, + const i32 numVertexes, const DqnV2 scale, + const f32 rotation) { - color = PreMultiplyAlpha(color); + if (!vertexList || numVertexes == 0) return; + DqnV2 xAxis = (DqnV2_2f(cosf(rotation), sinf(rotation))); + DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x); + xAxis *= scale.x; + yAxis *= scale.y; + + for (i32 i = 0; i < numVertexes; i++) + { + DqnV2 p = vertexList[i]; + vertexList[i] = origin + (xAxis * p.x) + (yAxis * p.y); + } +} + +FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1, + DqnV2 p2, DqnV2 p3, DqnV4 color, + DqnV2 scale = DqnV2_1f(1.0f), f32 rotation = 0, + DqnV2 anchor = DqnV2_1f(0.5f)) +{ + f32 area2Times = ((p2.x - p1.x) * (p2.y + p1.y)) + + ((p3.x - p2.x) * (p3.y + p2.y)) + + ((p1.x - p3.x) * (p1.y + p3.y)); + if (area2Times < 0) + { + // Counter-clockwise, do nothing this is what we want. + } + else + { + // Clockwise swap any point to make it clockwise + DQN_SWAP(DqnV2, p2, p3); + } + + // Transform vertexes +#if 1 + { + DqnV2 max = DqnV2_2f(DQN_MAX(DQN_MAX(p1.x, p2.x), p3.x), + DQN_MAX(DQN_MAX(p1.y, p2.y), p3.y)); + DqnV2 min = DqnV2_2f(DQN_MIN(DQN_MIN(p1.x, p2.x), p3.x), + DQN_MIN(DQN_MIN(p1.y, p2.y), p3.y)); + + DqnV2 boundsDim = DqnV2_2f(max.x - min.x, max.y - min.y); + DQN_ASSERT(boundsDim.w > 0 && boundsDim.h > 0); + DqnV2 origin = DqnV2_2f(min.x + (anchor.x * boundsDim.w), min.y + (anchor.y * boundsDim.h)); + + DqnV2 vertexList[3] = {p1 - origin, p2 - origin, p3 - origin}; + TransformVertexes(origin, vertexList, DQN_ARRAY_COUNT(vertexList), + scale, rotation); + p1 = vertexList[0]; + p2 = vertexList[1]; + p3 = vertexList[2]; + } +#endif + + color = PreMultiplyAlpha(color); DqnV2i max = DqnV2i_2f(DQN_MAX(DQN_MAX(p1.x, p2.x), p3.x), DQN_MAX(DQN_MAX(p1.y, p2.y), p3.y)); DqnV2i min = DqnV2i_2f(DQN_MIN(DQN_MIN(p1.x, p2.x), p3.x), @@ -183,26 +335,12 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, max.x = DQN_MIN(max.x, renderBuffer->width - 1); max.y = DQN_MIN(max.y, renderBuffer->height - 1); +#if 1 DrawLine(renderBuffer, DqnV2i_2i(min.x, min.y), DqnV2i_2i(min.x, max.y), color); DrawLine(renderBuffer, DqnV2i_2i(min.x, max.y), DqnV2i_2i(max.x, max.y), color); DrawLine(renderBuffer, DqnV2i_2i(max.x, max.y), DqnV2i_2i(max.x, min.y), color); DrawLine(renderBuffer, DqnV2i_2i(max.x, min.y), DqnV2i_2i(min.x, min.y), color); - - DqnV2 a = p1; - DqnV2 b = p2; - DqnV2 c = p3; - - f32 area2Times = ((b.x - a.x) * (b.y + a.y)) + ((c.x - b.x) * (c.y + b.y)) + - ((a.x - c.x) * (a.y + c.y)); - if (area2Times < 0) - { - // Counter-clockwise, do nothing this is what we want. - } - else - { - // Clockwise swap any point to make it clockwise - DQN_SWAP(DqnV2, b, c); - } +#endif /* ///////////////////////////////////////////////////////////////////////// @@ -310,6 +448,10 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, BaryCentricB(P) = (SignedArea(P) with vertex C and A)/SignedArea(with the orig triangle vertex) */ + const DqnV2 a = p1; + const DqnV2 b = p2; + const DqnV2 c = p3; + DqnV2i scanP = DqnV2i_2i(min.x, min.y); f32 signedArea1 = ((b.x - a.x) * (scanP.y - a.y)) - ((b.y - a.y) * (scanP.x - a.x)); f32 signedArea1DeltaX = a.y - b.y; @@ -348,84 +490,90 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, signedArea2 += signedArea2DeltaY; signedArea3 += signedArea3DeltaY; } -} -FILE_SCOPE void DrawText(PlatformRenderBuffer *const renderBuffer, - const DRFont font, DqnV2 pos, const char *const text, - DqnV4 color = DqnV4_4f(255, 255, 255, 255), i32 len = -1) -{ - if (!text) return; - if (len == -1) len = Dqn_strlen(text); - - i32 index = 0; - color = PreMultiplyAlpha(color); - while (index < len) +#if 1 { - if (text[index] < font.codepointRange.min && - text[index] > font.codepointRange.max) + DqnV2 xAxis = DqnV2_2f(cosf(rotation), sinf(rotation)) * scale.x; + DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x) * scale.y; + + DqnV2 vertexList[3] = {p1, p2, p3}; + DqnRect bounds = {}; + bounds.min = vertexList[0]; + bounds.max = vertexList[0]; + for (i32 i = 1; i < DQN_ARRAY_COUNT(vertexList); i++) { - return; + const DqnV2 p = vertexList[i]; + bounds.min = DqnV2_2f(DQN_MIN(p.x, bounds.min.x), + DQN_MIN(p.y, bounds.min.y)); + bounds.max = DqnV2_2f(DQN_MAX(p.x, bounds.max.x), + DQN_MAX(p.y, bounds.max.y)); } - i32 charIndex = text[index++] - (i32)font.codepointRange.min; - DQN_ASSERT(charIndex >= 0 && - charIndex < (i32)(font.codepointRange.max - - font.codepointRange.min)); + DqnV2 boundsDim = DqnRect_GetSizeV2(bounds); + DqnV2 origin = DqnV2_2f(bounds.min.x + (anchor.x * boundsDim.w), + bounds.min.y + (anchor.y * boundsDim.h)); - stbtt_aligned_quad alignedQuad = {}; - stbtt_GetPackedQuad(font.atlas, font.bitmapDim.w, font.bitmapDim.h, - charIndex, &pos.x, &pos.y, &alignedQuad, true); + DqnV4 coordSysColor = DqnV4_4f(0, 255, 255, 255); + i32 axisLen = 50; + DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(xAxis * axisLen), coordSysColor); + DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(yAxis * axisLen), coordSysColor); + } +#endif +} - DqnRect fontRect = {}; - fontRect.min = DqnV2_2f(alignedQuad.s0 * font.bitmapDim.w, alignedQuad.t1 * font.bitmapDim.h); - fontRect.max = DqnV2_2f(alignedQuad.s1 * font.bitmapDim.w, alignedQuad.t0 * font.bitmapDim.h); +FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer, + DqnV2 min, DqnV2 max, DqnV4 color, + const DqnV2 scale = DqnV2_1f(1.0f), + const f32 rotation = 0, + const DqnV2 anchor = DqnV2_1f(0.5f)) +{ + // TODO(doyle): Do edge test for quads + if (rotation > 0) + { + DqnV2 p1 = min; + DqnV2 p2 = DqnV2_2f(max.x, min.y); + DqnV2 p3 = max; + DqnV2 p4 = DqnV2_2f(min.x, max.y); + DrawTriangle(renderBuffer, p1, p2, p3, color, scale, rotation, anchor); + DrawTriangle(renderBuffer, p1, p3, p4, color, scale, rotation, anchor); + return; + } - DqnRect screenRect = {}; - screenRect.min = DqnV2_2f(alignedQuad.x0, alignedQuad.y0); - screenRect.max = DqnV2_2f(alignedQuad.x1, alignedQuad.y1); + // Transform vertexes + { + DqnV2 dim = DqnV2_2f(max.x - min.x, max.y - min.y); + DQN_ASSERT(dim.w > 0 && dim.h > 0); + DqnV2 origin = DqnV2_2f(min.x + (anchor.x * dim.w), min.y + (anchor.y * dim.h)); - // TODO: Assumes 1bpp and pitch of font bitmap - const u32 fontPitch = font.bitmapDim.w; - u32 fontOffset = (u32)(fontRect.min.x + (fontRect.max.y * fontPitch)); - u8 *fontPtr = font.bitmap + fontOffset; + DqnV2 p1 = min - origin; + DqnV2 p2 = max - origin; + DqnV2 vertexList[4] = {p1, p2}; + TransformVertexes(origin, vertexList, DQN_ARRAY_COUNT(vertexList), + scale, rotation); + min = vertexList[0]; + max = vertexList[1]; + } - DQN_ASSERT(sizeof(u32) == renderBuffer->bytesPerPixel); + color = PreMultiplyAlpha(color); - // NOTE(doyle): This offset, yOffset and flipping t1, t0 is necessary - // for reversing the order of the font since its convention is 0,0 top - // left and -ve Y. - stbtt_packedchar *const charData = font.atlas + charIndex; - f32 fontHeightOffset = charData->yoff2 + charData->yoff; + DqnRect rect = DqnRect_4f(min.x, min.y, max.x, max.y); + DqnRect clip = DqnRect_4i(0, 0, renderBuffer->width, renderBuffer->height); - u32 screenOffset = (u32)(screenRect.min.x + (screenRect.min.y - fontHeightOffset) * renderBuffer->width); - u32 *screenPtr = ((u32 *)renderBuffer->memory) + screenOffset; + DqnRect clippedRect = DqnRect_ClipRect(rect, clip); + DqnV2 clippedSize = DqnRect_GetSizeV2(clippedRect); - i32 fontWidth = DQN_ABS((i32)(fontRect.min.x - fontRect.max.x)); - i32 fontHeight = DQN_ABS((i32)(fontRect.min.y - fontRect.max.y)); - for (i32 y = 0; y < fontHeight; y++) + DebugPushText(renderBuffer, "ClippedSized: %5.2f, %5.2f", clippedSize.w, clippedSize.h); + for (i32 y = 0; y < clippedSize.w; y++) + { + i32 bufferY = (i32)clippedRect.min.y + y; + for (i32 x = 0; x < clippedSize.h; x++) { - for (i32 x = 0; x < fontWidth; x++) - { - i32 yOffset = fontHeight - y; - u8 srcA = fontPtr[x + (yOffset * fontPitch)]; - if (srcA == 0) continue; - - f32 srcANorm = srcA / 255.0f; - DqnV4 resultColor = {}; - resultColor.r = color.r * srcANorm; - resultColor.g = color.g * srcANorm; - resultColor.b = color.b * srcANorm; - resultColor.a = color.a * srcANorm; - - i32 actualX = (i32)(screenRect.min.x + x); - i32 actualY = (i32)(screenRect.min.y + y - fontHeightOffset); - SetPixel(renderBuffer, actualX, actualY, resultColor); - } + i32 bufferX = (i32)clippedRect.min.x + x; + SetPixel(renderBuffer, bufferX, bufferY, color); } } } - FILE_SCOPE void ClearRenderBuffer(PlatformRenderBuffer *const renderBuffer, DqnV3 color) { if (!renderBuffer) return; @@ -489,6 +637,8 @@ FILE_SCOPE void BitmapFontCreate(const PlatformAPI api, DQN_ASSERT(stbtt_PackBegin(&fontPackContext, font->bitmap, bitmapDim.w, bitmapDim.h, 0, 1, NULL) == 1); { + // stbtt_PackSetOversampling(&fontPackContext, 2, 2); + i32 numCodepoints = (i32)((codepointRange.max + 1) - codepointRange.min); @@ -649,52 +799,50 @@ void DebugDisplayMemBuffer(PlatformRenderBuffer *const renderBuffer, size_t totalWastedKb = totalWasted / 1024; char str[128] = {}; - Dqn_sprintf(str, "%s: %d block(s): %dkb/%dkb", name, numBlocks, - totalUsedKb, totalSizeKb); + Dqn_sprintf(str, "%s: %d block(s): %_$lld/%_$lld", name, numBlocks, totalUsed, + totalSize); DrawText(renderBuffer, font, *debugP, str); debugP->y += globalDebug.displayYOffset; } void DebugUpdate(PlatformRenderBuffer *const renderBuffer, - PlatformInput *const input, PlatformMemory *const memory, - const DRFont font) + PlatformInput *const input, PlatformMemory *const memory) { +#ifdef DR_DEBUG DRDebug *const debug = &globalDebug; - globalDebug.displayYOffset = -(i32)(font.sizeInPt + 0.5f); - DQN_ASSERT(globalDebug.displayYOffset < 0); - - DqnV2 debugP = DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset); - debug->totalSetPixels += debug->setPixelsPerFrame; debug->totalSetPixels = DQN_MAX(0, debug->totalSetPixels); // totalSetPixels { char str[128] = {}; - Dqn_sprintf(str, "%s: %d", "TotalSetPixels", debug->totalSetPixels); - DrawText(renderBuffer, font, debugP, str); - debugP.y += globalDebug.displayYOffset; + Dqn_sprintf(str, "%s: %'lld", "TotalSetPixels", debug->totalSetPixels); + DrawText(renderBuffer, *debug->font, debug->displayP, str); + debug->displayP.y += globalDebug.displayYOffset; } // setPixelsPerFrame { char str[128] = {}; - Dqn_sprintf(str, "%s: %d", "SetPixelsPerFrame", debug->setPixelsPerFrame); - DrawText(renderBuffer, font, debugP, str); - debugP.y += globalDebug.displayYOffset; + Dqn_sprintf(str, "%s: %'lld", "SetPixelsPerFrame", debug->setPixelsPerFrame); + DrawText(renderBuffer, *debug->font, debug->displayP, str); + debug->displayP.y += globalDebug.displayYOffset; } // memory { DebugDisplayMemBuffer(renderBuffer, "PermBuffer", - &memory->permanentBuffer, &debugP, font); + &memory->permanentBuffer, &debug->displayP, *debug->font); DebugDisplayMemBuffer(renderBuffer, "TransBuffer", - &memory->transientBuffer, &debugP, font); + &memory->transientBuffer, &debug->displayP, *debug->font); } debug->setPixelsPerFrame = 0; + debug->displayP = + DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset); +#endif } extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer, @@ -711,16 +859,27 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer, DQN_ASSERT(memory->context); state = (DRState *)memory->context; - BitmapFontCreate(input->api, memory, &state->font, "consola.ttf", - DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 18); + BitmapFontCreate(input->api, memory, &state->font, "Roboto-bold.ttf", + DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 16); DQN_ASSERT(BitmapLoad(input->api, &state->bitmap, "lune_logo.png", &memory->transientBuffer)); } +#ifdef DR_DEBUG + if (input->executableReloaded || !memory->isInit) + { + globalDebug.font = &state->font; + globalDebug.displayYOffset = -(i32)(state->font.sizeInPt + 0.5f); + globalDebug.displayP = + DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset); + DQN_ASSERT(globalDebug.displayYOffset < 0); + } +#endif + ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0)); DqnV4 colorRed = DqnV4_4i(50, 0, 0, 255); DqnV2i bufferMidP = DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f); - i32 boundsOffset = 50; + i32 boundsOffset = 100; DqnV2 t0[3] = {DqnV2_2i(10, 70), DqnV2_2i(50, 160), DqnV2_2i(70, 80)}; DqnV2 t1[3] = {DqnV2_2i(180, 50), DqnV2_2i(150, 1), DqnV2_2i(70, 180)}; @@ -753,11 +912,18 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer, DrawTriangle(renderBuffer, t2[0], t2[1], t2[2], colorRed); DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 190); - DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA); + LOCAL_PERSIST f32 rotation = 0; + rotation += input->deltaForFrame * 0.25f; + DqnV2 scale = DqnV2_1f(1.0f); + DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA, scale, + rotation, DqnV2_1f(0.5f)); + + DrawRectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f), colorRed, + DqnV2_1f(1.0f), rotation); DqnV2 fontP = DqnV2_2i(200, 180); DrawText(renderBuffer, state->font, fontP, "hello world!"); - DrawBitmap(renderBuffer, &state->bitmap, 700, 400); - DebugUpdate(renderBuffer, input, memory, state->font); + DrawBitmap(renderBuffer, &state->bitmap, 300, 250); + DebugUpdate(renderBuffer, input, memory); } diff --git a/src/DRendererPlatform.h b/src/DRendererPlatform.h index ce0ac65..a66f93a 100644 --- a/src/DRendererPlatform.h +++ b/src/DRendererPlatform.h @@ -69,8 +69,9 @@ typedef struct KeyState typedef struct PlatformInput { - f32 deltaForFrame; - f64 timeNowInS; + f32 deltaForFrame; + f64 timeNowInS; + bool executableReloaded; PlatformAPI api; union { diff --git a/src/Win32DRenderer.cpp b/src/Win32DRenderer.cpp index 1573ea8..b513210 100644 --- a/src/Win32DRenderer.cpp +++ b/src/Win32DRenderer.cpp @@ -129,13 +129,11 @@ FILE_SCOPE void Win32DisplayRenderBitmap(Win32RenderBitmap renderBitmap, FILETIME Win32GetLastWriteTime(const char *const srcName) { - WIN32_FIND_DATA findData = {}; - FILETIME lastWriteTime = {}; - HANDLE findHandle = FindFirstFileA(srcName, &findData); - if (findHandle != INVALID_HANDLE_VALUE) + FILETIME lastWriteTime = {}; + WIN32_FILE_ATTRIBUTE_DATA attribData = {}; + if (GetFileAttributesEx(srcName, GetFileExInfoStandard, &attribData) != 0) { - lastWriteTime = findData.ftLastWriteTime; - FindClose(findHandle); + lastWriteTime = attribData.ftLastWriteTime; } return lastWriteTime; @@ -150,7 +148,7 @@ FILE_SCOPE Win32ExternalCode Win32LoadExternalDLL(const char *const srcPath, CopyFile(srcPath, tmpPath, false); DR_UpdateFunction *updateFunction = NULL; - result.dll = LoadLibraryA(tmpPath); + result.dll = LoadLibraryA(tmpPath); if (result.dll) { updateFunction = @@ -158,7 +156,6 @@ FILE_SCOPE Win32ExternalCode Win32LoadExternalDLL(const char *const srcPath, if (updateFunction) result.DR_Update = updateFunction; } - return result; } @@ -519,15 +516,16 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, //////////////////////////////////////////////////////////////////////// f64 startFrameTimeInS = DqnTime_NowInS(); - FILETIME lastWriteTime = Win32GetLastWriteTime(dllPath); + PlatformInput platformInput = {}; + FILETIME lastWriteTime = Win32GetLastWriteTime(dllPath); if (CompareFileTime(&lastWriteTime, &dllCode.lastWriteTime) != 0) { Win32UnloadExternalDLL(&dllCode); dllCode = Win32LoadExternalDLL(dllPath, dllTmpPath, lastWriteTime); + platformInput.executableReloaded = true; } { - PlatformInput platformInput = {}; platformInput.timeNowInS = DqnTime_NowInS(); platformInput.deltaForFrame = (f32)frameTimeInS; platformInput.api = platformAPI; diff --git a/src/dqn.h b/src/dqn.h index a576fdd..51c0761 100644 --- a/src/dqn.h +++ b/src/dqn.h @@ -432,8 +432,8 @@ typedef union DqnV2 { f32 e[2]; } DqnV2; - DQN_FILE_SCOPE DqnV2 DqnV2_2i(i32 x, i32 y); // Typecasts 2 integers to 2 floats +DQN_FILE_SCOPE DqnV2 DqnV2_1f(f32 xy); DQN_FILE_SCOPE DqnV2 DqnV2_2f(f32 x, f32 y); DQN_FILE_SCOPE DqnV2 DqnV2_Add (DqnV2 a, DqnV2 b); @@ -473,6 +473,7 @@ typedef union DqnV2i { DQN_FILE_SCOPE DqnV2i DqnV2i_2i(i32 x, i32 y); DQN_FILE_SCOPE DqnV2i DqnV2i_2f(f32 x, f32 y); // Typecasts 2 floats to 2 integers +DQN_FILE_SCOPE DqnV2i DqnV2i_V2(DqnV2 a); DQN_FILE_SCOPE DqnV2i DqnV2i_Add (DqnV2i a, DqnV2i b); DQN_FILE_SCOPE DqnV2i DqnV2i_Sub (DqnV2i a, DqnV2i b); @@ -619,10 +620,12 @@ DQN_FILE_SCOPE bool Dqn_StrReverse (char *buf, const i32 bufSize); DQN_FILE_SCOPE i32 Dqn_StrFindFirstOccurence(const char *const src, const i32 srcLen, const char *const find, const i32 findLen); DQN_FILE_SCOPE bool Dqn_StrHasSubstring (const char *const src, const i32 srcLen, const char *const find, const i32 findLen); -#define DQN_I32_TO_STR_MAX_BUF_SIZE 11 -DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize); -// Return the len of the derived string -DQN_FILE_SCOPE i32 Dqn_I32ToStr(i32 value, char *buf, i32 bufSize); +#define DQN_32BIT_NUM_MAX_STR_SIZE 11 +#define DQN_64BIT_NUM_MAX_STR_SIZE 20 +// Return the len of the derived string. If buf is NULL and or bufSize is 0 the +// function returns the required string length for the integer. +DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 value, char *const buf, const i32 bufSize); +DQN_FILE_SCOPE i64 Dqn_StrToI64(const char *const buf, const i32 bufSize); // Both return the number of bytes read, return 0 if invalid codepoint or UTF8 DQN_FILE_SCOPE u32 Dqn_UCSToUTF8(u32 *dest, u32 character); @@ -1717,6 +1720,15 @@ DQN_FILE_SCOPE DqnV2 DqnV2_2f(f32 x, f32 y) return result; } +DQN_FILE_SCOPE DqnV2 DqnV2_1f(f32 xy) +{ + DqnV2 result = {}; + result.x = xy; + result.y = xy; + + return result; +} + DQN_FILE_SCOPE DqnV2 DqnV2_2i(i32 x, i32 y) { DqnV2 result = DqnV2_2f((f32)x, (f32)y); @@ -1873,6 +1885,14 @@ DQN_FILE_SCOPE DqnV2i DqnV2i_2f(f32 x, f32 y) return result; } +DQN_FILE_SCOPE DqnV2i DqnV2i_V2(DqnV2 a) +{ + DqnV2i result = {}; + result.x = (i32)a.x; + result.y = (i32)a.y; + return result; +} + DQN_FILE_SCOPE DqnV2i DqnV2i_Add(DqnV2i a, DqnV2i b) { DqnV2i result = {}; @@ -2475,7 +2495,64 @@ DQN_FILE_SCOPE bool Dqn_StrHasSubstring(const char *const src, const i32 srcLen, return true; } -DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize) +DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 value, char *const buf, const i32 bufSize) +{ + bool validBuffer = true; + if (!buf || bufSize == 0) validBuffer = false; + + if (value == 0) + { + if (validBuffer) buf[0] = '0'; + return 1; + } + + // NOTE(doyle): Max 32bit integer (+-)2147483647 + i32 charIndex = 0; + bool negative = false; + if (value < 0) negative = true; + + if (negative) + { + if (validBuffer) buf[charIndex] = '-'; + charIndex++; + } + + i32 val = DQN_ABS(value); + if (validBuffer) + { + while (val != 0 && charIndex < bufSize) + { + i32 rem = val % 10; + buf[charIndex++] = (u8)rem + '0'; + val /= 10; + } + + // NOTE(doyle): If string is negative, we only want to reverse starting + // from the second character, so we don't put the negative sign at the + // end + if (negative) + { + Dqn_StrReverse(buf + 1, charIndex - 1); + } + else + { + Dqn_StrReverse(buf, charIndex); + } + } + else + { + while (val != 0) + { + i32 rem = val % 10; + val /= 10; + charIndex++; + } + } + + return charIndex; +} + +DQN_FILE_SCOPE i64 Dqn_StrToI64(const char *const buf, const i32 bufSize) { if (!buf || bufSize == 0) return 0; @@ -2491,7 +2568,7 @@ DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize) return 0; } - i32 result = 0; + i64 result = 0; for (i32 i = index; i < bufSize; i++) { if (DqnChar_IsDigit(buf[i])) @@ -2510,45 +2587,6 @@ DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize) return result; } -DQN_FILE_SCOPE i32 Dqn_I32ToStr(i32 value, char *buf, i32 bufSize) -{ - if (!buf || bufSize == 0) return 0; - - if (value == 0) - { - buf[0] = '0'; - return 0; - } - - // NOTE(doyle): Max 32bit integer (+-)2147483647 - i32 charIndex = 0; - bool negative = false; - if (value < 0) negative = true; - - if (negative) buf[charIndex++] = '-'; - - i32 val = DQN_ABS(value); - while (val != 0 && charIndex < bufSize) - { - i32 rem = val % 10; - buf[charIndex++] = (u8)rem + '0'; - val /= 10; - } - - // NOTE(doyle): If string is negative, we only want to reverse starting - // from the second character, so we don't put the negative sign at the end - if (negative) - { - Dqn_StrReverse(buf + 1, charIndex - 1); - } - else - { - Dqn_StrReverse(buf, charIndex); - } - - return charIndex; -} - /* Encoding The following byte sequences are used to represent a character. The sequence