From eb885c97b39bfee8fb1d575acfaebea21ba66004 Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Fri, 25 Oct 2019 23:04:28 +1100 Subject: [PATCH] tlac: move drawing to utilities as its own class (rather than littering the components namespace), simplify menu coordinates management of pause --- .../source/plugins/TLAC/Components/Drawing.h | 374 ------------------ .../source/plugins/TLAC/Components/Pause.cpp | 157 ++++---- .../source/plugins/TLAC/Components/Pause.h | 3 + source-code/source/plugins/TLAC/Constants.h | 3 + source-code/source/plugins/TLAC/TLAC.vcxproj | 3 +- .../source/plugins/TLAC/TLAC.vcxproj.filters | 5 +- .../source/plugins/TLAC/Utilities/Drawing.cpp | 160 ++++++++ .../source/plugins/TLAC/Utilities/Drawing.h | 269 +++++++++++++ 8 files changed, 526 insertions(+), 448 deletions(-) delete mode 100644 source-code/source/plugins/TLAC/Components/Drawing.h create mode 100644 source-code/source/plugins/TLAC/Utilities/Drawing.cpp create mode 100644 source-code/source/plugins/TLAC/Utilities/Drawing.h diff --git a/source-code/source/plugins/TLAC/Components/Drawing.h b/source-code/source/plugins/TLAC/Components/Drawing.h deleted file mode 100644 index c446540..0000000 --- a/source-code/source/plugins/TLAC/Components/Drawing.h +++ /dev/null @@ -1,374 +0,0 @@ -#pragma once -#include -#include -#include - -namespace TLAC::Components -{ -#pragma pack(push, 1) - struct Point - { - float x; - float y; - }; - struct RectangleBounds - { - float x; - float y; - float width; - float height; - }; - - struct RawFont - { - uint32_t sprId; // ? - uint8_t width1; // glyph? - uint8_t height1; // glyph? - uint8_t width2; // advance? - uint8_t height2; // advance? - uint8_t metric08; // or flag? - uint8_t metric09; // or flag? - uint8_t padding0a[0x06]; - float metric08divby09; - uint64_t _0x10; - int64_t dataBegin; - int64_t dataEnd; - int64_t dataCapacityEnd; - uint8_t padding38[0x8]; - }; - - struct RawFontHolderIdk // ...SeemsPrettyPointlessTbh - { - RawFont* rawfont; - uint16_t width1; - uint16_t height1; - uint16_t zero1; // ? - uint16_t zero2; // ? - uint8_t zero3; // some kind of flag, but seems unused - }; - - struct FontInfo - { - uint32_t fontId; - uint8_t padding04[0x4]; - RawFont* rawfont; - uint16_t flag10; // (zero3 != 0 && padding38[0] != 0) ? 2 : (metric08 != metric09 ? 1 : 0) - uint8_t padding12[0x02]; - float width1; - float height1; - float width2; - float height2; - float userSizeWidth; - float userSizeHeight; - float userSizeWidthMultiplier; // userSizeWidth / width1 - float userSizeHeightMultiplier; // userSizeHeight / width2 - float zero1; // ? - float zero2; // ? - - void setSize(float width, float height) - { - ((void(*)(FontInfo* fi, float width, float height))0x140199e60)(this, width, height); - } - - FontInfo(uint32_t id) - { - ((FontInfo*(*)(FontInfo* fi, uint32_t id))0x140196510)(this, id); - } - }; - - FontInfo*(*getFont)(FontInfo* fi, uint32_t id) = (FontInfo*(*)(FontInfo* fi, uint32_t id))0x140196510; - void(*fontSize)(FontInfo* fi, float width, float height) = (void(*)(FontInfo* fi, float width, float height))0x140199e60; - - struct DrawParams - { - uint32_t colour; // RGBA byte array?, so set as 0xAABBGGRR - uint32_t fillColour; // ?? RGBA byte array?, so set as 0xAABBGGRR - uint8_t clip; - uint8_t unk09[0x3]; - RectangleBounds clipRect; - uint32_t layer; // 8 seems similar to default but higher - // 0x18 is below 0x19 but still seems to be above any game elements - // 0x19 is startup screen (below dwgui) - // I noticed some use different scaling - uint32_t unk20; - uint32_t unk24; - uint32_t unk28; - Point textCurrentLoc; - Point lineOriginLoc; // must be set for newlines to work as expected - uint8_t padding3c[0x4]; - uint64_t lineLength; // in characters - FontInfo* font; - uint16_t unk50; - - DrawParams(FontInfo* fi) - { - colour = 0xffffffff; - fillColour = 0xff808080; // except it's not? - clip = 0; - clipRect = { 0, 0, 0, 0 }; - layer = 0x7; - unk20 = 0x0; - unk24 = 0xd; - unk28 = 0; - textCurrentLoc = { 0, 0 }; - lineOriginLoc = { 0, 0 }; - lineLength = 0; - font = fi; - unk50 = 0x25a1; - } - - DrawParams() - { - DrawParams((FontInfo*)0x140eda860); - } - }; - - enum drawTextFlags : uint32_t - { - DRAWTEXT_ENABLE_XADVANCE = 1, - DRAWTEXT_ALIGN_RIGHT = 2, - DRAWTEXT_ALIGN_SCREEN_CENTRE = 4, - DRAWTEXT_ALIGN_CENTRE = 8, - DRAWTEXT_ENABLE_CLIP = 0x200, - DRAWTEXT_SCALING_OPTIMISED = 0x400, // ? -- seems to be set if the requested font size doesn't match the original font, and the internal width/height 1 and 2 match - // maybe it's just required for any scaling though - DRAWTEXT_STROKE = 0x10000, - }; - - void drawText(DrawParams* dtParam, drawTextFlags flags, std::string str) - { - ((void(*)(DrawParams*, uint32_t, const char*, int64_t))0x140198500)(dtParam, flags, str.c_str(), str.length()); - } - void drawTextW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) - { - const wchar_t* ptrs[2]; - ptrs[0] = str.c_str(); - ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); - - ((void(*)(DrawParams*, uint32_t, const wchar_t**))0x140198380)(dtParam, flags, &ptrs[0]); - } - - void drawTextFormattedW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) - { - const wchar_t* ptrs[2]; - ptrs[0] = str.c_str(); - ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); - - ((void(*)(uint32_t, const wchar_t**, DrawParams*))0x1404c2aa0)(flags, &ptrs[0], dtParam); - } - - void drawTextWithSpritesW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) - { - const wchar_t* ptrs[2]; - ptrs[0] = str.c_str(); - ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); - - ((void(*)(uint32_t, const wchar_t**, DrawParams*))0x1404c2cf0)(flags, &ptrs[0], dtParam); - } - - - void(*fillRectangle)(DrawParams* dtParam, const RectangleBounds &rect) = (void(*)(DrawParams* dtParam, const RectangleBounds &rect))0x140198d80; - - // draws only a border -- use fillRectangle to fill contained pixels - void drawRectangle(DrawParams* dtParam, const RectangleBounds &rect) - { - ((void(*)(DrawParams*, const RectangleBounds&))0x140198320)(dtParam, rect); - } - - // draws only a border -- use fillRectangle to fill contained pixels - void drawRectangle(DrawParams* dtParam, const RectangleBounds &rect, float thickness) - { - uint32_t oldFillColour = dtParam->fillColour; - dtParam->fillColour = dtParam->colour; - - // yes this seems pretty dodgy, but sega does it this way so... I guess it's the only way - RectangleBounds tempRect = { rect.x, rect.y, thickness, rect.height }; // left side - fillRectangle(dtParam, tempRect); - - tempRect.x = rect.x + rect.width - thickness; // right side - fillRectangle(dtParam, tempRect); - - tempRect = { rect.x + thickness, rect.y, rect.width - (thickness * 2), thickness }; // top side - fillRectangle(dtParam, tempRect); - - tempRect.y = rect.y + rect.height - thickness; // left side - fillRectangle(dtParam, tempRect); - - dtParam->fillColour = oldFillColour; - } - - - void drawLine(DrawParams* dtParam, const Point &p1, const Point &p2) - { - ((void(*)(DrawParams*, const RectangleBounds&))0x140198080)(dtParam, { p1.x, p1.y, p2.x, p2.y }); - } - // draw from the top left corner of rect to the bottom left - void drawLine(DrawParams* dtParam, const RectangleBounds &rect) - { - drawLine(dtParam, { rect.x, rect.y }, { rect.x + rect.width, rect.y + rect.height }); - } - - void drawPolyline(DrawParams* dtParam, const std::vector points) - { - ((void(*)(DrawParams*, const Point*, uint64_t))0x1401980e0)(dtParam, points.data(), points.size()); - } - - - struct MsString { - union { - char* string_ptr; - char string_buf[16]; - }; - uint64_t len; - uint64_t bufsize; - - char* GetCharBuf() - { - if (bufsize > 0xf && string_ptr != nullptr) - return string_ptr; - else - return string_buf; - }; - - void SetCharBuf(char* newcontent) - { - len = strlen(newcontent); - bufsize = len; - if (len > 0xf) - { - string_ptr = _strdup(newcontent); - } - else - { - strcpy_s(string_buf, newcontent); - } - } - }; - - /* struct MsStringW { - union { - wchar_t* string_ptr; - wchar_t string_buf[8]; - }; - uint64_t len; - uint64_t bufsize; - - wchar_t* GetCharBuf() - { - if (bufsize > 0x7 && string_ptr != nullptr) - return string_ptr; - else - return string_buf; - }; - - void SetCharBuf(wchar_t* newcontent) - { - len = wcslen(newcontent); - bufsize = len; - if (len > 0xf) - { - string_ptr = wcsdup(newcontent); - } - else - { - wcscpy_s(string_buf, newcontent); - } - } - }; */ - - struct AetDebugFileInfo - { - MsString name1; - int32_t gameId; - char unk[4]; // seems to be some kind of mode prefix (eg. "GAM_") - MsString name2; // same as name1??? - MsString filename; - int32_t dbId1; // not sure what the db ids are... this one might be a position - int32_t dbId12; - }; - - struct AetFileInfo - { - int32_t id1; - char unk1[4]; // seems to be some kind of mode prefix (eg. "GAM_") - int32_t id2; // same as id1??? - int32_t unk2; - MsString name; - int32_t unk3; - int32_t unk4; // might be related to sprites? - }; - - /* - int findAetDebugFileId(std::string name) - { - AetDebugFileInfo* aetArray = *(AetDebugFileInfo**)AET_DEBUG_ARRAY_POINTER_ADDRESS; - AetDebugFileInfo* aetArrayEndAddress = *(AetDebugFileInfo**)(AET_DEBUG_ARRAY_POINTER_ADDRESS + 0x08); - - int id = 0; - while (&aetArray[id] < aetArrayEndAddress) - { - if (name == aetArray[id].name2.GetCharBuf()) // dwgui enum uses name2, so this should too I guess - return aetArray[id].gameId; - else - id++; - } - return -1; - } - */ - // gets a file ID for use with createAetLayer - // returns -1 if the file was not found - // note: names are a little different to in 2dauth test -- it seems like they have "_MAIN" appended - - int findAetFileId(std::string name) - { - AetFileInfo* aetArray = *(AetFileInfo**)AET_ARRAY_POINTER_ADDRESS; - AetFileInfo* aetArrayEndAddress = *(AetFileInfo**)(AET_ARRAY_POINTER_ADDRESS + 0x08); - - int id = 0; - while (&aetArray[id] < aetArrayEndAddress) - { - if (name == aetArray[id].name.GetCharBuf()) // dwgui enum uses name2, so this should too I guess - return aetArray[id].id1; - else - id++; - } - return -1; - } - - enum createAetFlags : uint32_t - { - CREATEAET_20000 = 0x20000, - }; - - // draw an aet layer (with all settings) - // aetSpeedCallback is actually a pointer to a class or struct with the callback address at offset +0x8 - int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, int32_t unk2, const char* animation, const char* animation2, float animationInTime, float animationOutTime, const Point &scale, const void* aetSpeedCallback) - { - return ((int(*)(int32_t, uint32_t, createAetFlags, const char*, const Point&, int32_t, const char*, const char*, float, float, const Point&, const void*))0x14013be60)(fileId, drawLayer, flags, name, loc, unk2, animation, animation2, animationInTime, animationOutTime, scale, aetSpeedCallback); - } - // draw an aet layer (with animation timing override) - int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, float animationInTime, float animationOutTime) - { - return createAetLayer(fileId, drawLayer, flags, name, loc, 0, 0, 0, animationInTime, animationOutTime, *(Point*)0, 0); - } - // draw an aet layer (with scale) - int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, const Point &scale) - { - return createAetLayer(fileId, drawLayer, flags, name, loc, 0, 0, 0, -1, -1, scale, 0); - } - // draw an aet layer - int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc) - { - return createAetLayer(fileId, drawLayer, flags, name, loc, 0, 0, 0, -1, -1, *(Point*)0, 0); - } - - void destroyAetLayer(int &layer) - { - if (layer != 0) - { - ((void(*)(int layer))0x14019d570)(layer); - layer = 0; - } - } -#pragma pack(pop) -} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Components/Pause.cpp b/source-code/source/plugins/TLAC/Components/Pause.cpp index 115c8ac..c4c6d51 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.cpp +++ b/source-code/source/plugins/TLAC/Components/Pause.cpp @@ -1,7 +1,7 @@ #include "Pause.h" #include "../Constants.h" #include "GameState.h" -#include "Drawing.h" +#include "../Utilities/Drawing.h" #include "GL/glut.h" #include "detours.h" #include @@ -10,6 +10,7 @@ namespace TLAC::Components { + using TLAC::Utilities::Drawing; bool Pause::pause = false; bool Pause::isPaused = false; bool Pause::giveUp = false; @@ -150,15 +151,15 @@ namespace TLAC::Components { // clear these from the screen too /* - destroyAetLayer(selResultAet1); - destroyAetLayer(selResultAet2); - destroyAetLayer(selResultAet3); - destroyAetLayer(selResultAet4); + Drawing::destroyAetLayer(selResultAet1); + Drawing::destroyAetLayer(selResultAet2); + Drawing::destroyAetLayer(selResultAet3); + Drawing::destroyAetLayer(selResultAet4); */ - destroyAetLayer(triangleAet); - destroyAetLayer(squareAet); - destroyAetLayer(crossAet); - destroyAetLayer(circleAet); + Drawing::destroyAetLayer(triangleAet); + Drawing::destroyAetLayer(squareAet); + Drawing::destroyAetLayer(crossAet); + Drawing::destroyAetLayer(circleAet); } } @@ -224,15 +225,15 @@ namespace TLAC::Components } /* - destroyAetLayer(selResultAet1); - destroyAetLayer(selResultAet2); - destroyAetLayer(selResultAet3); - destroyAetLayer(selResultAet4); + Drawing::destroyAetLayer(selResultAet1); + Drawing::destroyAetLayer(selResultAet2); + Drawing::destroyAetLayer(selResultAet3); + Drawing::destroyAetLayer(selResultAet4); */ - destroyAetLayer(triangleAet); - destroyAetLayer(squareAet); - destroyAetLayer(crossAet); - destroyAetLayer(circleAet); + Drawing::destroyAetLayer(triangleAet); + Drawing::destroyAetLayer(squareAet); + Drawing::destroyAetLayer(crossAet); + Drawing::destroyAetLayer(circleAet); isPaused = false; } @@ -258,16 +259,35 @@ namespace TLAC::Components inputState->IntervalTapped.Buttons = (JvsButtons)(inputState->IntervalTapped.Buttons & ~filteredButtons); } + // returns the midpoint of a menu button + Drawing::Point Pause::getMenuItemCoord(menusets set, int pos) + { + const float slant = 35.0f / 199.0f; + + int menuOriginY = menuY - (menuItemTotalHeight * menu[set].items.size() - menuItemPadding) / 2 + menuItemHeight / 2; + if (set != MENUSET_MAIN) + { + menuOriginY += menuItemTotalHeight * 1.2 / 2; + } + int menuOriginX = menuX + (menuY - menuOriginY) * slant; + + Drawing::Point out; + out.x = menuOriginX - (menuItemTotalHeight * pos * slant); + out.y = menuOriginY + menuItemTotalHeight * pos; + + return out; + } + void Pause::UpdateDraw2D() { if (isPaused && showUI) { // setup draw objects - FontInfo fontInfo(0x11); - DrawParams dtParams(&fontInfo); + Drawing::FontInfo fontInfo(0x11); + Drawing::DrawParams dtParams(&fontInfo); dtParams.layer = bgLayer; - Point aetScale = { 0.65, 0.65 }; - Point aetLoc = { (1280 - aetScale.x * 1280) / 2, (720 - aetScale.y * 720) / 2 }; + Drawing::Point aetScale = { 0.65, 0.65 }; + Drawing::Point aetLoc = { (1280 - aetScale.x * 1280) / 2, (720 - aetScale.y * 720) / 2 }; // get aspect ratio float aspect = *(float*)UI_ASPECT_RATIO; @@ -276,11 +296,11 @@ namespace TLAC::Components // bg rect float bgWidth = aspect * 720 + 2; // add a couple of pixels to protect against rounding errors float bgLeft = -(bgWidth - 1280) / 2; // 0,0 is in the corner of a 720p view.. half of the extra over 1280 wide is the horizontal offset to centre the bg - RectangleBounds rect; + Drawing::RectangleBounds rect; rect = { bgLeft, 0, bgWidth, 720 }; dtParams.colour = 0xc0000000; dtParams.fillColour = dtParams.colour; - fillRectangle(&dtParams, rect); + Drawing::fillRectangle(&dtParams, rect); // pause icon @@ -299,9 +319,9 @@ namespace TLAC::Components dtParams.colour = 0x80ffffff; dtParams.fillColour = 0x80ffffff; rect = { pauseX1, pauseY1, pausePartWidth, pauseHeight }; - fillRectangle(&dtParams, &rect); + Drawing::fillRectangle(&dtParams, &rect); rect = { pauseX2, pauseY1, pausePartWidth, pauseHeight }; - fillRectangle(&dtParams, &rect); + Drawing::fillRectangle(&dtParams, &rect); */ @@ -312,30 +332,30 @@ namespace TLAC::Components static int selResultFile = 0; if (selResultFile == 0) { - //keyWinFile = findAetFileId("AET_KEY_WIN_MAIN"); - selResultFile = findAetFileId("AET_SEL_RESULT_MAIN"); + //keyWinFile = Drawing::findAetFileId("AET_KEY_WIN_MAIN"); + selResultFile = Drawing::findAetFileId("AET_SEL_RESULT_MAIN"); //printf("keyWinFile: %d\n", keyWinFile); } - destroyAetLayer(selResultAet1); - destroyAetLayer(selResultAet2); - destroyAetLayer(selResultAet3); - destroyAetLayer(selResultAet4); + Drawing::destroyAetLayer(selResultAet1); + Drawing::destroyAetLayer(selResultAet2); + Drawing::destroyAetLayer(selResultAet3); + Drawing::destroyAetLayer(selResultAet4); if (selResultFile != -1) { - //keyWinAet = createAetLayer(keyWinFile, dtParams.layer, CREATEAET_20000, "win_in", aetLoc, 0, nullptr, nullptr, 3.7, 3.7, aetScale, 0); + //keyWinAet = Drawing::createAetLayer(keyWinFile, dtParams.layer, CREATEAET_20000, "win_in", aetLoc, 0, nullptr, nullptr, 3.7, 3.7, aetScale, 0); aetScale = { 0.47f, 0.47f }; aetLoc = { (1280 - aetScale.x * 1280) / 2, (720 - aetScale.y * 720) / 2 + 72 * aetScale.y }; float animPos = 7.2; - selResultAet1 = createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); - selResultAet2 = createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); - selResultAet3 = createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); - selResultAet4 = createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); + selResultAet1 = Drawing::createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); + selResultAet2 = Drawing::createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); + selResultAet3 = Drawing::createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); + selResultAet4 = Drawing::createAetLayer(selResultFile, dtParams.layer, CREATEAET_20000, "window_in", aetLoc, 0, nullptr, nullptr, animPos, animPos, aetScale, 0); } */ dtParams.colour = 0xffffff00; - drawPolyline(&dtParams, { + Drawing::drawPolyline(&dtParams, { { 537, 255 }, { 794, 255 }, { 759, 454 }, @@ -344,7 +364,7 @@ namespace TLAC::Components { 522, 267 }, { 537, 255 }, }); - drawPolyline(&dtParams, { + Drawing::drawPolyline(&dtParams, { { 537 - .7f, 255 - 2 }, { 794 + 2.38f, 255 - 2 }, { 759 + 2.1f, 454 + 1.15f }, @@ -353,7 +373,7 @@ namespace TLAC::Components { 522 - 2.1f, 267 - 1.15f }, { 537 - .7f, 255 - 2 }, }); - drawPolyline(&dtParams, { + Drawing::drawPolyline(&dtParams, { { 548, 258 }, { 768, 258 }, { 774, 265 }, @@ -374,26 +394,22 @@ namespace TLAC::Components }); - const float slant = 35.0f / 199.0f; + Drawing::Point menuCoords = getMenuItemCoord(curMenuSet, curMenuPos); // selection cursor - int menuOriginY = menuY - menuItemTotalHeight * (menu[curMenuSet].items.size() / 2.0) + menuItemTotalHeight / 2 - menuTextSize / 2; - if (curMenuSet != MENUSET_MAIN) - { - menuOriginY += menuItemTotalHeight * 1.2 / 2; - } - int menuOriginX = menuX + (menuY - menuOriginY + menuTextSize / 2) * slant; const float selectBoxWidth = 150; const float selectBoxHeight = menuItemHeight; const float selectBoxThickness = 2; - float selectBoxX = menuOriginX - (menuItemTotalHeight * curMenuPos * slant) - selectBoxWidth / 2; - float selectBoxY = menuOriginY - (menuItemHeight - menuTextSize) / 2 + menuItemTotalHeight * curMenuPos; + float selectBoxX = menuCoords.x - selectBoxWidth / 2; + float selectBoxY = menuCoords.y - menuItemHeight / 2; - //rect = { selectBoxX, selectBoxY, selectBoxWidth, selectBoxHeight }; dtParams.colour = 0xc0ffff00; dtParams.fillColour = 0xc0ffff00; - //drawRectangle(&dtParams, rect, selectBoxThickness); - drawPolyline(&dtParams, { + //rect = { selectBoxX, selectBoxY, selectBoxWidth, selectBoxHeight }; + //Drawing::drawRectangle(&dtParams, rect, selectBoxThickness); + + const float slant = 35.0f / 199.0f; + Drawing::drawPolyline(&dtParams, { { selectBoxX + (selectBoxHeight - 8) * slant + 8 * 15 / 12, selectBoxY }, { selectBoxX + selectBoxWidth, selectBoxY }, { selectBoxX + selectBoxWidth - (selectBoxHeight - 8) * slant, selectBoxY + selectBoxHeight - 8 }, @@ -402,7 +418,7 @@ namespace TLAC::Components { selectBoxX + (selectBoxHeight - 8) * slant, selectBoxY + 8 }, { selectBoxX + (selectBoxHeight - 8) * slant + 8 * 15 / 12, selectBoxY }, }); - drawPolyline(&dtParams, { + Drawing::drawPolyline(&dtParams, { { selectBoxX + (selectBoxHeight - 8) * slant + 8 * 15 / 12 - .7f, selectBoxY - 2 }, { selectBoxX + selectBoxWidth + 2.38f, selectBoxY - 2 }, { selectBoxX + selectBoxWidth - (selectBoxHeight - 8) * slant + 2.1f, selectBoxY + selectBoxHeight - 8 + 1.15f }, @@ -421,14 +437,14 @@ namespace TLAC::Components dtParams.textCurrentLoc = { menuX + 90 * slant, menuY - 90 }; dtParams.lineOriginLoc.y = dtParams.textCurrentLoc.y; dtParams.colour = 0xffffffff; - drawText(&dtParams, (drawTextFlags)(DRAWTEXT_ALIGN_CENTRE | DRAWTEXT_STROKE), menu[curMenuSet].name); + Drawing::drawText(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ALIGN_CENTRE | Drawing::DRAWTEXT_STROKE), menu[curMenuSet].name); } - dtParams.textCurrentLoc = { (float)menuOriginX, (float)menuOriginY }; - dtParams.lineOriginLoc = dtParams.textCurrentLoc; - for (int i = 0; i < menu[curMenuSet].items.size(); i++) { + menuCoords = getMenuItemCoord(curMenuSet, i); + dtParams.textCurrentLoc = { menuCoords.x, menuCoords.y - menuTextSize / 2 }; + dtParams.lineOriginLoc = dtParams.textCurrentLoc; if (i == curMenuPos) { uint8_t alpha = (cosf(getMenuAnimPos() * 6.283185f) * 0.15 + 0.85) * 255; @@ -439,18 +455,15 @@ namespace TLAC::Components dtParams.colour = 0xffffffff; } - drawText(&dtParams, (drawTextFlags)(DRAWTEXT_ALIGN_CENTRE), menu[curMenuSet].items[i].name); - dtParams.textCurrentLoc.x -= (menuItemTotalHeight * slant); - dtParams.textCurrentLoc.y += menuItemTotalHeight; - dtParams.lineOriginLoc = dtParams.textCurrentLoc; + Drawing::drawText(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ALIGN_CENTRE), menu[curMenuSet].items[i].name); } // key legend - destroyAetLayer(triangleAet); - destroyAetLayer(squareAet); - destroyAetLayer(crossAet); - destroyAetLayer(circleAet); + Drawing::destroyAetLayer(triangleAet); + Drawing::destroyAetLayer(squareAet); + Drawing::destroyAetLayer(crossAet); + Drawing::destroyAetLayer(circleAet); float textLeft; if (aspect > 16.0f / 9.0f) @@ -467,25 +480,25 @@ namespace TLAC::Components aetScale = { spriteSize / 64, spriteSize / 64 }; // just approximated dtParams.colour = 0xffffffff; - drawTextW(&dtParams, (drawTextFlags)(DRAWTEXT_ENABLE_XADVANCE), L"L/R:Move "); + Drawing::drawTextW(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ENABLE_XADVANCE), L"L/R:Move "); aetLoc.x = dtParams.textCurrentLoc.x + halfSpriteSize; - squareAet = createAetLayer(3, dtParams.layer, CREATEAET_20000, "button_shikaku", aetLoc, 0, nullptr, nullptr, 0, 0, aetScale, nullptr); + squareAet = Drawing::createAetLayer(3, dtParams.layer, Drawing::CREATEAET_20000, "button_shikaku", aetLoc, 0, nullptr, nullptr, 0, 0, aetScale, nullptr); dtParams.textCurrentLoc.x += spriteSize; - drawTextW(&dtParams, (drawTextFlags)(DRAWTEXT_ENABLE_XADVANCE), L":Hide Menu "); + Drawing::drawTextW(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ENABLE_XADVANCE), L":Hide Menu "); aetLoc.x = dtParams.textCurrentLoc.x + halfSpriteSize; - crossAet = createAetLayer(3, dtParams.layer, CREATEAET_20000, "button_batsu", aetLoc, 0, nullptr, nullptr, 0, 0, aetScale, nullptr); + crossAet = Drawing::createAetLayer(3, dtParams.layer, Drawing::CREATEAET_20000, "button_batsu", aetLoc, 0, nullptr, nullptr, 0, 0, aetScale, nullptr); dtParams.textCurrentLoc.x += spriteSize; if (curMenuSet == MENUSET_MAIN) - drawTextW(&dtParams, (drawTextFlags)(DRAWTEXT_ENABLE_XADVANCE), L":Close "); + Drawing::drawTextW(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ENABLE_XADVANCE), L":Close "); else - drawTextW(&dtParams, (drawTextFlags)(DRAWTEXT_ENABLE_XADVANCE), L":Back "); + Drawing::drawTextW(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ENABLE_XADVANCE), L":Back "); aetLoc.x = dtParams.textCurrentLoc.x + halfSpriteSize; - circleAet = createAetLayer(3, dtParams.layer, CREATEAET_20000, "button_maru", aetLoc, 0, nullptr, nullptr, 0, 0, aetScale, nullptr); + circleAet = Drawing::createAetLayer(3, dtParams.layer, Drawing::CREATEAET_20000, "button_maru", aetLoc, 0, nullptr, nullptr, 0, 0, aetScale, nullptr); dtParams.textCurrentLoc.x += spriteSize; - drawTextW(&dtParams, (drawTextFlags)(DRAWTEXT_ENABLE_XADVANCE), L":Select"); + Drawing::drawTextW(&dtParams, (Drawing::drawTextFlags)(Drawing::DRAWTEXT_ENABLE_XADVANCE), L":Select"); } } diff --git a/source-code/source/plugins/TLAC/Components/Pause.h b/source-code/source/plugins/TLAC/Components/Pause.h index 90e5f4c..98287b7 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.h +++ b/source-code/source/plugins/TLAC/Components/Pause.h @@ -3,6 +3,7 @@ #include "EmulatorComponent.h" #include "PlayerData.h" #include "GameState.h" +#include "../Utilities/Drawing.h" #include "Input/InputState.h" #include "Input/TouchSliderState.h" #include @@ -123,5 +124,7 @@ namespace TLAC::Components static void setMenuPos(menusets set, int pos); static float getMenuAnimPos(); + + static TLAC::Utilities::Drawing::Point getMenuItemCoord(menusets set, int pos); }; } diff --git a/source-code/source/plugins/TLAC/Constants.h b/source-code/source/plugins/TLAC/Constants.h index e54237c..91c2c89 100644 --- a/source-code/source/plugins/TLAC/Constants.h +++ b/source-code/source/plugins/TLAC/Constants.h @@ -114,6 +114,9 @@ constexpr uint64_t DSC_UNPAUSE_FUNC_ADDRESS = 0x0000000140129590; constexpr uint64_t PV_GAME_BASE_ADDRESS = 0x000000014CC95270; constexpr uint64_t GIVEUP_FUNC_ADDRESS = 0x000000014010EF00; +constexpr uint64_t AET_DEBUG_ARRAY_POINTER_ADDRESS = 0x0000000140EC5430 + 0x98; +constexpr uint64_t AET_ARRAY_POINTER_ADDRESS = 0x0000000140EC5430 + 0xD8; + #define XINPUT_A 0x00 #define XINPUT_B 0x01 diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj b/source-code/source/plugins/TLAC/TLAC.vcxproj index 2c61ae9..f8bf08e 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj @@ -111,7 +111,6 @@ - @@ -163,6 +162,7 @@ + @@ -211,6 +211,7 @@ + diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters index 6ec4726..79143c4 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters @@ -198,7 +198,7 @@ Header Files - + Header Files @@ -338,5 +338,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Utilities/Drawing.cpp b/source-code/source/plugins/TLAC/Utilities/Drawing.cpp new file mode 100644 index 0000000..2df6676 --- /dev/null +++ b/source-code/source/plugins/TLAC/Utilities/Drawing.cpp @@ -0,0 +1,160 @@ +#pragma once +#include +#include +#include +#include "Drawing.h" +#include "../Constants.h" + +namespace TLAC::Utilities +{ +#pragma pack(push, 1) + Drawing::FontInfo*(*Drawing::getFont)(FontInfo* fi, uint32_t id) = (FontInfo*(*)(FontInfo* fi, uint32_t id))0x140196510; + void(*Drawing::fontSize)(FontInfo* fi, float width, float height) = (void(*)(FontInfo* fi, float width, float height))0x140199e60; + + void Drawing::drawText(DrawParams* dtParam, drawTextFlags flags, std::string str) + { + ((void(*)(DrawParams*, uint32_t, const char*, int64_t))0x140198500)(dtParam, flags, str.c_str(), str.length()); + } + void Drawing::drawTextW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) + { + const wchar_t* ptrs[2]; + ptrs[0] = str.c_str(); + ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); + + ((void(*)(DrawParams*, uint32_t, const wchar_t**))0x140198380)(dtParam, flags, &ptrs[0]); + } + + void Drawing::drawTextFormattedW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) + { + const wchar_t* ptrs[2]; + ptrs[0] = str.c_str(); + ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); + + ((void(*)(uint32_t, const wchar_t**, DrawParams*))0x1404c2aa0)(flags, &ptrs[0], dtParam); + } + + void Drawing::drawTextWithSpritesW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) + { + const wchar_t* ptrs[2]; + ptrs[0] = str.c_str(); + ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); + + ((void(*)(uint32_t, const wchar_t**, DrawParams*))0x1404c2cf0)(flags, &ptrs[0], dtParam); + } + + + void(*Drawing::fillRectangle)(DrawParams* dtParam, const RectangleBounds &rect) = (void(*)(DrawParams* dtParam, const RectangleBounds &rect))0x140198d80; + + // draws only a border -- use fillRectangle to fill contained pixels + void Drawing::drawRectangle(DrawParams* dtParam, const RectangleBounds &rect) + { + ((void(*)(DrawParams*, const RectangleBounds&))0x140198320)(dtParam, rect); + } + + // draws only a border -- use fillRectangle to fill contained pixels + void Drawing::drawRectangle(DrawParams* dtParam, const RectangleBounds &rect, float thickness) + { + uint32_t oldFillColour = dtParam->fillColour; + dtParam->fillColour = dtParam->colour; + + // yes this seems pretty dodgy, but sega does it this way so... I guess it's the only way + RectangleBounds tempRect = { rect.x, rect.y, thickness, rect.height }; // left side + fillRectangle(dtParam, tempRect); + + tempRect.x = rect.x + rect.width - thickness; // right side + fillRectangle(dtParam, tempRect); + + tempRect = { rect.x + thickness, rect.y, rect.width - (thickness * 2), thickness }; // top side + fillRectangle(dtParam, tempRect); + + tempRect.y = rect.y + rect.height - thickness; // left side + fillRectangle(dtParam, tempRect); + + dtParam->fillColour = oldFillColour; + } + + + void Drawing::drawLine(DrawParams* dtParam, const Point &p1, const Point &p2) + { + ((void(*)(DrawParams*, const RectangleBounds&))0x140198080)(dtParam, { p1.x, p1.y, p2.x, p2.y }); + } + // draw from the top left corner of rect to the bottom left + void Drawing::drawLine(DrawParams* dtParam, const RectangleBounds &rect) + { + drawLine(dtParam, { rect.x, rect.y }, { rect.x + rect.width, rect.y + rect.height }); + } + + void Drawing::drawPolyline(DrawParams* dtParam, const std::vector points) + { + ((void(*)(DrawParams*, const Point*, uint64_t))0x1401980e0)(dtParam, points.data(), points.size()); + } + + /* + int Drawing::findAetDebugFileId(std::string name) + { + AetDebugFileInfo* aetArray = *(AetDebugFileInfo**)AET_DEBUG_ARRAY_POINTER_ADDRESS; + AetDebugFileInfo* aetArrayEndAddress = *(AetDebugFileInfo**)(AET_DEBUG_ARRAY_POINTER_ADDRESS + 0x08); + + int id = 0; + while (&aetArray[id] < aetArrayEndAddress) + { + if (name == aetArray[id].name2.GetCharBuf()) // dwgui enum uses name2, so this should too I guess + return aetArray[id].gameId; + else + id++; + } + return -1; + } + */ + + // gets a file ID for use with createAetLayer + // returns -1 if the file was not found + // note: names are a little different to in 2dauth test -- it seems like they have "_MAIN" appended + int Drawing::findAetFileId(std::string name) + { + AetFileInfo* aetArray = *(AetFileInfo**)AET_ARRAY_POINTER_ADDRESS; + AetFileInfo* aetArrayEndAddress = *(AetFileInfo**)(AET_ARRAY_POINTER_ADDRESS + 0x08); + + int id = 0; + while (&aetArray[id] < aetArrayEndAddress) + { + if (name == aetArray[id].name.GetCharBuf()) // dwgui enum uses name2, so this should too I guess + return aetArray[id].id1; + else + id++; + } + return -1; + } + + // draw an aet layer (with all settings) + // aetSpeedCallback is actually a pointer to a class or struct with the callback address at offset +0x8 + int Drawing::createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, int32_t unk2, const char* animation, const char* animation2, float animationInTime, float animationOutTime, const Point &scale, const void* aetSpeedCallback) + { + return ((int(*)(int32_t, uint32_t, createAetFlags, const char*, const Point&, int32_t, const char*, const char*, float, float, const Point&, const void*))0x14013be60)(fileId, drawLayer, flags, name, loc, unk2, animation, animation2, animationInTime, animationOutTime, scale, aetSpeedCallback); + } + // draw an aet layer (with animation timing override) + int Drawing::createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, float animationInTime, float animationOutTime) + { + return createAetLayer(fileId, drawLayer, flags, name, loc, 0, 0, 0, animationInTime, animationOutTime, *(Point*)0, 0); + } + // draw an aet layer (with scale) + int Drawing::createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, const Point &scale) + { + return createAetLayer(fileId, drawLayer, flags, name, loc, 0, 0, 0, -1, -1, scale, 0); + } + // draw an aet layer + int Drawing::createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc) + { + return createAetLayer(fileId, drawLayer, flags, name, loc, 0, 0, 0, -1, -1, *(Point*)0, 0); + } + + void Drawing::destroyAetLayer(int &layer) + { + if (layer != 0) + { + ((void(*)(int layer))0x14019d570)(layer); + layer = 0; + } + } +#pragma pack(pop) +} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Utilities/Drawing.h b/source-code/source/plugins/TLAC/Utilities/Drawing.h new file mode 100644 index 0000000..4f6b5a5 --- /dev/null +++ b/source-code/source/plugins/TLAC/Utilities/Drawing.h @@ -0,0 +1,269 @@ +#pragma once +#include +#include +#include + +namespace TLAC::Utilities +{ + class Drawing + { + public: +#pragma pack(push, 1) + struct Point + { + float x; + float y; + }; + struct RectangleBounds + { + float x; + float y; + float width; + float height; + }; + + struct RawFont + { + uint32_t sprId; // ? + uint8_t width1; // glyph? + uint8_t height1; // glyph? + uint8_t width2; // advance? + uint8_t height2; // advance? + uint8_t metric08; // or flag? + uint8_t metric09; // or flag? + uint8_t padding0a[0x06]; + float metric08divby09; + uint64_t _0x10; + int64_t dataBegin; + int64_t dataEnd; + int64_t dataCapacityEnd; + uint8_t padding38[0x8]; + }; + + struct RawFontHolderIdk // ...SeemsPrettyPointlessTbh + { + RawFont* rawfont; + uint16_t width1; + uint16_t height1; + uint16_t zero1; // ? + uint16_t zero2; // ? + uint8_t zero3; // some kind of flag, but seems unused + }; + + struct FontInfo + { + uint32_t fontId; + uint8_t padding04[0x4]; + RawFont* rawfont; + uint16_t flag10; // (zero3 != 0 && padding38[0] != 0) ? 2 : (metric08 != metric09 ? 1 : 0) + uint8_t padding12[0x02]; + float width1; + float height1; + float width2; + float height2; + float userSizeWidth; + float userSizeHeight; + float userSizeWidthMultiplier; // userSizeWidth / width1 + float userSizeHeightMultiplier; // userSizeHeight / width2 + float zero1; // ? + float zero2; // ? + + void setSize(float width, float height) + { + ((void(*)(FontInfo* fi, float width, float height))0x140199e60)(this, width, height); + } + + FontInfo(uint32_t id) + { + ((FontInfo*(*)(FontInfo* fi, uint32_t id))0x140196510)(this, id); + } + }; + + static FontInfo*(*getFont)(FontInfo* fi, uint32_t id); + static void(*fontSize)(FontInfo* fi, float width, float height); + + struct DrawParams + { + uint32_t colour; // RGBA byte array?, so set as 0xAABBGGRR + uint32_t fillColour; // ?? RGBA byte array?, so set as 0xAABBGGRR + uint8_t clip; + uint8_t unk09[0x3]; + RectangleBounds clipRect; + uint32_t layer; // 8 seems similar to default but higher + // 0x18 is below 0x19 but still seems to be above any game elements + // 0x19 is startup screen (below dwgui) + // I noticed some use different scaling + uint32_t unk20; + uint32_t unk24; + uint32_t unk28; + Point textCurrentLoc; + Point lineOriginLoc; // must be set for newlines to work as expected + uint8_t padding3c[0x4]; + uint64_t lineLength; // in characters + FontInfo* font; + uint16_t unk50; + + DrawParams(FontInfo* fi) + { + colour = 0xffffffff; + fillColour = 0xff808080; // except it's not? + clip = 0; + clipRect = { 0, 0, 0, 0 }; + layer = 0x7; + unk20 = 0x0; + unk24 = 0xd; + unk28 = 0; + textCurrentLoc = { 0, 0 }; + lineOriginLoc = { 0, 0 }; + lineLength = 0; + font = fi; + unk50 = 0x25a1; + } + + DrawParams() + { + DrawParams((FontInfo*)0x140eda860); + } + }; + + enum drawTextFlags : uint32_t + { + DRAWTEXT_ENABLE_XADVANCE = 1, + DRAWTEXT_ALIGN_RIGHT = 2, + DRAWTEXT_ALIGN_SCREEN_CENTRE = 4, + DRAWTEXT_ALIGN_CENTRE = 8, + DRAWTEXT_ENABLE_CLIP = 0x200, + DRAWTEXT_SCALING_OPTIMISED = 0x400, // ? -- seems to be set if the requested font size doesn't match the original font, and the internal width/height 1 and 2 match + // maybe it's just required for any scaling though + DRAWTEXT_STROKE = 0x10000, + }; + + static void drawText(DrawParams* dtParam, drawTextFlags flags, std::string str); + static void drawTextW(DrawParams* dtParam, drawTextFlags flags, std::wstring str); + static void drawTextFormattedW(DrawParams* dtParam, drawTextFlags flags, std::wstring str); + static void drawTextWithSpritesW(DrawParams* dtParam, drawTextFlags flags, std::wstring str); + + static void(*fillRectangle)(DrawParams* dtParam, const RectangleBounds &rect); + // draws only a border -- use fillRectangle to fill contained pixels + static void drawRectangle(DrawParams* dtParam, const RectangleBounds &rect); + // draws only a border -- use fillRectangle to fill contained pixels + static void drawRectangle(DrawParams* dtParam, const RectangleBounds &rect, float thickness); + + static void drawLine(DrawParams* dtParam, const Point &p1, const Point &p2); + // draw from the top left corner of rect to the bottom left + static void drawLine(DrawParams* dtParam, const RectangleBounds &rect); + + static void drawPolyline(DrawParams* dtParam, const std::vector points); + + + struct MsString { + union { + char* string_ptr; + char string_buf[16]; + }; + uint64_t len; + uint64_t bufsize; + + char* GetCharBuf() + { + if (bufsize > 0xf && string_ptr != nullptr) + return string_ptr; + else + return string_buf; + }; + + void SetCharBuf(char* newcontent) + { + len = strlen(newcontent); + bufsize = len; + if (len > 0xf) + { + string_ptr = _strdup(newcontent); + } + else + { + strcpy_s(string_buf, newcontent); + } + } + }; + + /* struct MsStringW { + union { + wchar_t* string_ptr; + wchar_t string_buf[8]; + }; + uint64_t len; + uint64_t bufsize; + + wchar_t* GetCharBuf() + { + if (bufsize > 0x7 && string_ptr != nullptr) + return string_ptr; + else + return string_buf; + }; + + void SetCharBuf(wchar_t* newcontent) + { + len = wcslen(newcontent); + bufsize = len; + if (len > 0xf) + { + string_ptr = wcsdup(newcontent); + } + else + { + wcscpy_s(string_buf, newcontent); + } + } + }; */ + + struct AetDebugFileInfo + { + MsString name1; + int32_t gameId; + char unk[4]; // seems to be some kind of mode prefix (eg. "GAM_") + MsString name2; // same as name1??? + MsString filename; + int32_t dbId1; // not sure what the db ids are... this one might be a position + int32_t dbId12; + }; + + struct AetFileInfo + { + int32_t id1; + char unk1[4]; // seems to be some kind of mode prefix (eg. "GAM_") + int32_t id2; // same as id1??? + int32_t unk2; + MsString name; + int32_t unk3; + int32_t unk4; // might be related to sprites? + }; + + + // int findAetDebugFileId(std::string name); + + // gets a file ID for use with createAetLayer + // returns -1 if the file was not found + // note: names are a little different to in 2dauth test -- it seems like they have "_MAIN" appended + static int findAetFileId(std::string name); + + enum createAetFlags : uint32_t + { + CREATEAET_20000 = 0x20000, + }; + + // draw an aet layer (with all settings) + // aetSpeedCallback is actually a pointer to a class or struct with the callback address at offset +0x8 + static int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, int32_t unk2, const char* animation, const char* animation2, float animationInTime, float animationOutTime, const Point &scale, const void* aetSpeedCallback); + // draw an aet layer (with animation timing override) + static int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, float animationInTime, float animationOutTime); + // draw an aet layer (with scale) + static int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc, const Point &scale); + // draw an aet layer + static int createAetLayer(int32_t fileId, uint32_t drawLayer, createAetFlags flags, const char* name, const Point &loc); + + static void destroyAetLayer(int &layer); +#pragma pack(pop) + }; +} \ No newline at end of file