#ifndef UTILS_H #define UTILS_H #include "enums.h" #include "QtZlib/zlib.h" #include "qdir.h" #include "qicon.h" #include #include #include class Utils : public QObject { Q_OBJECT public: enum AssetType { ASSET_NONE = 0x00, ASSET_RAWFILE = 0x01, ASSET_SCRIPT_PARSE_TREE = 0x02, ASSET_FX = 0x03, ASSET_SOUND_CURVE = 0x04, ASSET_Animation = 0x05, ASSET_COLLISION_MAP = 0x06, ASSET_STRINGTABLE = 0x07, ASSET_XMODEL_SURFS = 0x08, ASSET_TECHNIQUE_SET = 0x09, ASSET_GFX_MAP = 0x11, ASSET_D3DBSP = 0x15, ASSET_GAME_MAP_SP = 0x17, ASSET_COL_MAP_SP = 0x18, ASSET_PHYSPRESET = 0x19, ASSET_DESTRUCTIBLE = 0x20, ASSET_LOCALIZE_ENTRY = 0x21, ASSET_SHADER = 0x22, ASSET_MP_MAP = 0x23, ASSET_SP_MAP = 0x24, ASSET_SNDDRIVER_GLOBALS = 0x26, ASSET_AI_TYPE = 0x27, ASSET_COMPUTE_SHADER_SET = 0x29, ASSET_LIGHT_DESCRIPTION = 0x30, ASSET_BIT_FIELD = 0x31, ASSET_STRUCTURED_TABLE = 0x32, ASSET_LEADERBOARD_DEF = 0x33, ASSET_DDL = 0x34, ASSET_KEY_VALUE_PAIRS = 0x35, ASSET_SCRIPT_BUNDLE = 0x36, ASSET_SCRIPT_BUNDLE_LIST = 0x37, ASSET_MAP_TABLE = 0x38, ASSET_MAP_TABLE_LOADING_IMAGES = 0x39, ASSET_SURFACE_SOUND_DEF = 0x40, ASSET_SURFACE_FX_TABLE = 0x41, ASSET_RUMBLE = 0x42, ASSET_AIM_TABLE = 0x43, ASSET_MEDAL = 0x44, ASSET_MEDAL_TABLE = 0x45, ASSET_OBJECTIVE = 0x46, ASSET_OBJECTIVE_LIST = 0x47, ASSET_LASER = 0x48, ASSET_BEAM = 0x49, ASSET_STREAMER_HINT = 0x50, ASSET_ANIM_SELECTOR_TABLE = 0x51, ASSET_ANIM_MAPPING_TABLE = 0x52, ASSET_ANIM_STATE_MACHINE = 0x53, ASSET_BEHAVIOR_TREE = 0x54, ASSET_BEHAVIOR_STATE_MACHINE = 0x55, ASSET_FOOTSTEP_TABLE = 0x56, ASSET_ENTITY_FX_IMPACTS = 0x57, ASSET_ENTITY_SOUND_IMPACTS = 0x58, ASSET_VEHICLE_FX_DEF = 0x59, ASSET_VEHICLE_SOUND_DEF = 0x60, ASSET_VEHICLE = 0x61, ASSET_VEHICLE_TRACER = 0x62, ASSET_PLAYER_SOUNDS_TABLE = 0x63, ASSET_PLAYER_FX_TABLE = 0x64, ASSET_SHARED_WEAPON_SOUNDS = 0x65, ASSET_ATTACHMENT = 0x66, ASSET_ATTACHMENT_UNIQUE = 0x67, ASSET_WEAPON_CAMO = 0x68, ASSET_CUSTOMIZATION_TABLE = 0x69, ASSET_CUSTOMIZATION_TABLE_FEIMAGES = 0x70, ASSET_CUSTOMIZATION_TABLE_COLOR = 0x71, ASSET_PHYS_CONSTRAINTS = 0x72, ASSET_DESTRUCTIBLE_DEF = 0x73, ASSET_XMODEL_MESH = 0x74, ASSET_S_ANIM = 0x75, ASSET_FONT_ICON = 0x76, ASSET_CG_MEDIA_TABLE = 0x77, ASSET_SHOCK_FILE = 0x78, ASSET_ZONE_FILE = 0x79, ASSET_FAST_FILE = 0x80, ASSET_SOUND_DRIVER_GLOBALS = 0x81, ASSET_XMODELPIECES = 0x82, ASSET_XMODEL = 0x85, ASSET_MATERIAL = 0x86, ASSET_PIXELSHADER = 0x87, ASSET_IMAGE = 0x89, ASSET_SOUND = 0x90, ASSET_LOADED_SOUND = 0x92, ASSET_CLIPMAP = 0x93, ASSET_CLIPMAP_PVS = 0x94, ASSET_COMWORLD = 0x95, ASSET_GAMEWORLD_SP = 0x96, ASSET_GAMEWORLD_MP = 0x97, ASSET_MAP_ENTS = 0x98, ASSET_GFXWORLD = 0x99, ASSET_LIGHT_DEF = 0x100, ASSET_UI_MAP = 0x101, ASSET_FONT = 0x102, ASSET_MENULIST = 0x103, ASSET_MENU = 0x104, ASSET_WEAPON = 0x106, ASSET_IMPACT_FX = 0x109, ASSET_AITYPE = 0x110, ASSET_MPTYPE = 0x111, ASSET_CHARACTER = 0x112, ASSET_XMODELALIAS = 0x113, ASSET_COUNT = 0x116, ASSET_STRING = 0x117, ASSET_ASSETLIST = 0x118, ASSET_PHYSCOLLMAP = 0x119, ASSET_CLIPMAP_SP = 0x120, ASSET_CLIPMAP_MP = 0x121, ASSET_FXWORLD = 0x122, ASSET_LEADERBOARD = 0x123, ASSET_STRUCTURED_DATA_DEF = 0x124, ASSET_TRACER = 0x125, ASSET_ADDON_MAP_ENTS = 0x126, ASSET_GLASSWORLD = 0x127, ASSET_PATHDATA = 0x128, ASSET_VEHICLE_TRACK = 0x129, ASSET_SURFACE_FX = 0x130, ASSET_SCRIPTFILE = 0x131, ASSET_SOUND_SUBMIX = 0x132, ASSET_SOUND_EVENT = 0x133, ASSET_LPF_CURVE = 0x134, ASSET_REVERB_CURVE = 0x135, ASSET_GFXWORLD_TRANSIENT_ZONE = 0x136, ASSET_ANIMCLASS = 0x137, ASSET_NET_CONST_STRINGS = 0x138, ASSET_REVERB_PRESET = 0x139, ASSET_LUA_FILE = 0x140, ASSET_SCRIPTABLE = 0x141, ASSET_EQUIPMENT_SND_TABLE = 0x142, ASSET_DOPPLER_PRESET = 0x143, ASSET_SKELETON_SCRIPT = 0x144, ASSET_PHYSCONSTRAINTS = 0x145, ASSET_DESTRUCTIBLEDEF = 0x146, ASSET_SOUND_PATCH = 0x147, ASSET_WEAPONDEF = 0x148, ASSET_WEAPON_VARIANT = 0x149, ASSET_MPBODY = 0x150, ASSET_MPHEAD = 0x151, ASSET_PACK_INDEX = 0x152, ASSET_XGLOBALS = 0x153, ASSET_GLASSES = 0x154, ASSET_EMBLEMSET = 0x155 }; Q_ENUM(AssetType) static QString AssetTypeToStr(Utils::AssetType aAssetType) { const QMetaObject &mo = Utils::staticMetaObject; int index = mo.indexOfEnumerator("AssetType"); QMetaEnum metaEnum = mo.enumerator(index); return QString::fromLatin1(metaEnum.valueToKey(aAssetType)); } static bool ExportData(const QString aFileName, const QByteArray aData) { QDir workingDir = QDir::currentPath(); workingDir.mkdir("exports"); QFile testFile("exports/" + aFileName); if(!testFile.open(QIODevice::WriteOnly)) { return false; } testFile.write(aData); testFile.close(); return true; } static quint8 ReverseBits(quint8 b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; } static QIcon CreateAssetIcon(Utils::AssetType aAssetType, QColor color = QColor()) { const QString assetTypeStr = AssetTypeToStr(aAssetType); QString name; const QStringList parts = assetTypeStr.split('_').mid(1); foreach (const QString part, parts) { name += part[0]; } if (parts.size() == 1) { name += parts.first()[1]; } return CreateAssetIcon(name, color); } static QIcon CreateAssetIcon(const QString& name, QColor color = QColor()) { constexpr int iconSize = 32; constexpr int padding = 4; QImage result(iconSize, iconSize, QImage::Format_ARGB32); result.fill(Qt::transparent); if (!color.isValid()) { color = Utils::StringToColor(name); } QPainter painter(&result); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::TextAntialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); // Draw background QBrush brush(color); brush.setStyle(Qt::SolidPattern); painter.setBrush(color); painter.setPen(Qt::NoPen); painter.drawRoundedRect(0, 0, iconSize, iconSize, 4, 4); // Set base font QFont font("Heavitas"); font.setPixelSize(iconSize); // Start large painter.setFont(font); // Adjust font size to fit text width (only reduce, not increase) QFontMetrics fm(font); int textWidth = fm.horizontalAdvance(name); while (textWidth > iconSize - 2 * padding && font.pixelSize() > 1) { font.setPixelSize(font.pixelSize() - 1); painter.setFont(font); fm = QFontMetrics(font); textWidth = fm.horizontalAdvance(name); } // Calculate vertical scaling factor qreal scaleY = 1.2 * iconSize / fm.height(); // Apply transform: scale vertically, center align painter.save(); painter.translate(iconSize / 2.0, iconSize / 2.0); painter.scale(1.0, scaleY); painter.translate(-iconSize / 2.0, -iconSize / 2.0); QRect textRect(0, 0, iconSize, iconSize); // Draw stroke painter.setPen(Qt::black); for (int dx = 0; dx <= 1; ++dx) { for (int dy = 0; dy <= 1; ++dy) { if (dx || dy) painter.drawText(textRect.translated(dx, dy), Qt::AlignCenter, name); } } // Draw main text painter.setPen(Qt::white); painter.drawText(textRect, Qt::AlignCenter, name); painter.restore(); // Debug output QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/"); result.save(QDir().absoluteFilePath(".") + "/icons/" + name + ".png"); return QIcon(QPixmap::fromImage(result)); } static QIcon CreateGameIcon(const int gameNum, QColor color = QColor()) { constexpr int size = 32; constexpr int padding = 4; // pixels of padding on all sides const int contentSize = size - 2 * padding; QImage result(size, size, QImage::Format_ARGB32); result.fill(Qt::transparent); if (!color.isValid()) { color = Utils::StringToColor(QString("COD%1").arg(gameNum)); } QPainter painter(&result); painter.setRenderHint(QPainter::Antialiasing, false); painter.setRenderHint(QPainter::TextAntialiasing, false); painter.setRenderHint(QPainter::SmoothPixmapTransform, false); // Draw background painter.setBrush(color); painter.setPen(Qt::NoPen); painter.drawRoundedRect(0, 0, size, size, 4, 4); // === Font Setup === QFont codFont("Heavitas"); codFont.setPixelSize(contentSize * 0.40); QFont numFont("Heavitas"); numFont.setPixelSize(contentSize); // === Layout Areas (inside padding) === const QRect contentRect(padding, padding, contentSize, contentSize); const int col1 = contentRect.left(); const int col2 = contentRect.left() + contentRect.width() / 3; const int thirdH = contentRect.height() / 3; const QRect codRects[] = { QRect(col1, 2 + contentRect.top(), contentRect.width() / 3, thirdH), QRect(col1, contentRect.top() + thirdH, contentRect.width() / 3, thirdH), QRect(col1, -2 + contentRect.top() + 2 * thirdH, contentRect.width() / 3, thirdH), }; const QRect numRect(col2, contentRect.top(), contentRect.width() * 2 / 3, contentRect.height()); const QString codLetters[] = { "C", "O", "D" }; const QString numText = QString::number(gameNum); // === Stroke pass === for (int dx = -1; dx <= 2; ++dx) { for (int dy = -1; dy <= 2; ++dy) { if (dx == 0 && dy == 0) continue; painter.setPen(Qt::black); painter.setFont(codFont); for (int i = 0; i < 3; ++i) painter.drawText(codRects[i].translated(dx, dy), Qt::AlignCenter, codLetters[i]); painter.setFont(numFont); painter.drawText(numRect.translated(dx, dy), Qt::AlignCenter, numText); } } // === Fill pass === painter.setPen(Qt::white); painter.setFont(codFont); for (int i = 0; i < 3; ++i) painter.drawText(codRects[i], Qt::AlignCenter, codLetters[i]); painter.setFont(numFont); painter.drawText(numRect, Qt::AlignCenter, numText); // Save & return icon QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/"); result.save(QDir().absoluteFilePath(".") + QString("/icons/COD%1.png").arg(gameNum)); return QIcon(QPixmap::fromImage(result)); } static QColor StringToColor(const QString& str) { // 1. Hash the string using Qt's built-in hash (MD5, SHA1, or any) QByteArray hash = QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5); // 2. Use first 3 bytes of hash for RGB // This guarantees same string = same color every time int r = static_cast(hash[0]); int g = static_cast(hash[1]); int b = static_cast(hash[2]); // 3. Optionally adjust brightness or saturation to avoid too dark/light colors QColor color(r, g, b); if (color.value() < 128) { // brighten if too dark color = color.lighter(150); } return color; } static bool ReadUntilString(QDataStream* stream, const QString& targetString) { if (!stream || targetString.isEmpty()) { return false; // Invalid input } QByteArray buffer; QByteArray targetBytes = targetString.toUtf8(); // Handle multibyte characters const int targetLength = targetBytes.size(); qDebug() << targetBytes << targetLength; // Read as unsigned bytes to handle all possible values (0-255) unsigned char byte; while (!stream->atEnd()) { // Read one byte at a time *stream >> byte; buffer.append(static_cast(byte)); // Append as char for QByteArray // Keep buffer size limited to the target length if (buffer.size() > targetLength) { buffer.remove(0, 1); } // Check if the buffer matches the target string in raw bytes if (buffer == targetBytes) { // Backup to the start of the matched string stream->device()->seek(stream->device()->pos() - targetLength); return true; } } // Target string not found return false; } static bool ReadUntilHex(QDataStream* stream, const QString& hexString) { if (!stream || hexString.isEmpty() || hexString.size() % 2 != 0) { return false; // Invalid input } // Convert hex string to byte array QByteArray targetBytes = QByteArray::fromHex(hexString.toUtf8()); const int targetLength = targetBytes.size(); QByteArray buffer; unsigned char byte; while (!stream->atEnd()) { // Read one byte at a time *stream >> byte; buffer.append(static_cast(byte)); // Append as char for QByteArray // Keep buffer size limited to the target length if (buffer.size() > targetLength) { buffer.remove(0, 1); } // Check if the buffer matches the target byte sequence if (buffer == targetBytes) { // Backup to the start of the matched sequence stream->device()->seek(stream->device()->pos() - targetLength); return true; } } // Target sequence not found return false; } /* LumpTypeToString() Convert BSP lump type to desc string */ static QString LumpTypeToString(LUMP_TYPE aLumpType) { switch (aLumpType) { case LUMP_MATERIALS: return "LUMP_MATERIALS"; case LUMP_LIGHTBYTES: return "LUMP_LIGHTBYTES"; case LUMP_LIGHTGRIDENTRIES: return "LUMP_LIGHTGRIDENTRIES"; case LUMP_LIGHTGRIDCOLORS: return "LUMP_LIGHTGRIDCOLORS"; case LUMP_PLANES: return "LUMP_PLANES"; case LUMP_BRUSHSIDES: return "LUMP_BRUSHSIDES"; case LUMP_BRUSHSIDEEDGECOUNTS: return "LUMP_BRUSHSIDEEDGECOUNTS"; case LUMP_BRUSHEDGES: return "LUMP_BRUSHEDGES"; case LUMP_BRUSHES: return "LUMP_BRUSHES"; case LUMP_TRIANGLES: return "LUMP_TRIANGLES"; case LUMP_DRAWVERTS: return "LUMP_DRAWVERTS"; case LUMP_DRAWINDICES: return "LUMP_DRAWINDICES"; case LUMP_CULLGROUPS: return "LUMP_CULLGROUPS"; case LUMP_CULLGROUPINDICES: return "LUMP_CULLGROUPINDICES"; case LUMP_OBSOLETE_1: return "LUMP_OBSOLETE_1"; case LUMP_OBSOLETE_2: return "LUMP_OBSOLETE_2"; case LUMP_OBSOLETE_3: return "LUMP_OBSOLETE_3"; case LUMP_OBSOLETE_4: return "LUMP_OBSOLETE_4"; case LUMP_OBSOLETE_5: return "LUMP_OBSOLETE_5"; case LUMP_PORTALVERTS: return "LUMP_PORTALVERTS"; case LUMP_OBSOLETE_6: return "LUMP_OBSOLETE_6"; case LUMP_UINDS: return "LUMP_UINDS"; case LUMP_BRUSHVERTSCOUNTS: return "LUMP_BRUSHVERTSCOUNTS"; case LUMP_BRUSHVERTS: return "LUMP_BRUSHVERTS"; case LUMP_AABBTREES: return "LUMP_AABBTREES"; case LUMP_CELLS: return "LUMP_CELLS"; case LUMP_PORTALS: return "LUMP_PORTALS"; case LUMP_NODES: return "LUMP_NODES"; case LUMP_LEAFS: return "LUMP_LEAFS"; case LUMP_LEAFBRUSHES: return "LUMP_LEAFBRUSHES"; case LUMP_LEAFSURFACES: return "LUMP_LEAFSURFACES"; case LUMP_COLLISIONVERTS: return "LUMP_COLLISIONVERTS"; case LUMP_COLLISIONTRIS: return "LUMP_COLLISIONTRIS"; case LUMP_COLLISIONEDGEWALKABLE: return "LUMP_COLLISIONEDGEWALKABLE"; case LUMP_COLLISIONBORDERS: return "LUMP_COLLISIONBORDERS"; case LUMP_COLLISIONPARTITIONS: return "LUMP_COLLISIONPARTITIONS"; case LUMP_COLLISIONAABBS: return "LUMP_COLLISIONAABBS"; case LUMP_MODELS: return "LUMP_MODELS"; case LUMP_VISIBILITY: return "LUMP_VISIBILITY"; case LUMP_ENTITIES: return "LUMP_ENTITIES"; case LUMP_PATHCONNECTIONS: return "LUMP_PATHCONNECTIONS"; case LUMP_REFLECTION_PROBES: return "LUMP_REFLECTION_PROBES"; case LUMP_VERTEX_LAYER_DATA: return "LUMP_VERTEX_LAYER_DATA"; case LUMP_PRIMARY_LIGHTS: return "LUMP_PRIMARY_LIGHTS"; case LUMP_LIGHTGRIDHEADER: return "LUMP_LIGHTGRIDHEADER"; case LUMP_LIGHTGRIDROWS: return "LUMP_LIGHTGRIDROWS"; case LUMP_OBSOLETE_10: return "LUMP_OBSOLETE_10"; case LUMP_UNLAYERED_TRIANGLES: return "LUMP_UNLAYERED_TRIANGLES"; case LUMP_UNLAYERED_DRAWVERTS: return "LUMP_UNLAYERED_DRAWVERTS"; case LUMP_UNLAYERED_DRAWINDICES: return "LUMP_UNLAYERED_DRAWINDICES"; case LUMP_UNLAYERED_CULLGROUPS: return "LUMP_UNLAYERED_CULLGROUPS"; case LUMP_UNLAYERED_AABBTREES: return "LUMP_UNLAYERED_AABBTREES"; case LUMP_WATERHEADER: return "LUMP_WATERHEADER"; case LUMP_WATERCELLS: return "LUMP_WATERCELLS"; case LUMP_WATERCELLDATA: return "LUMP_WATERCELLDATA"; case LUMP_BURNABLEHEADER: return "LUMP_BURNABLEHEADER"; case LUMP_BURNABLECELLS: return "LUMP_BURNABLECELLS"; case LUMP_BURNABLECELLDATA: return "LUMP_BURNABLECELLDATA"; case LUMP_SIMPLELIGHTMAPBYTES: return "LUMP_SIMPLELIGHTMAPBYTES"; case LUMP_LODCHAINS: return "LUMP_LODCHAINS"; case LUMP_LODINFOS: return "LUMP_LODINFOS"; case LUMP_LODSURFACES: return "LUMP_LODSURFACES"; case LUMP_LIGHTREGIONS: return "LUMP_LIGHTREGIONS"; case LUMP_LIGHTREGION_HULLS: return "LUMP_LIGHTREGION_HULLS"; case LUMP_LIGHTREGION_AXES: return "LUMP_LIGHTREGION_AXES"; case LUMP_WIILIGHTGRID: return "LUMP_WIILIGHTGRID"; case LUMP_LIGHTGRID2D_LIGHTS: return "LUMP_LIGHTGRID2D_LIGHTS"; case LUMP_LIGHTGRID2D_INDICES: return "LUMP_LIGHTGRID2D_INDICES"; case LUMP_LIGHTGRID2D_POINTS: return "LUMP_LIGHTGRID2D_POINTS"; case LUMP_LIGHTGRID2D_CELLS: return "LUMP_LIGHTGRID2D_CELLS"; case LUMP_LIGHT_CORONAS: return "LUMP_LIGHT_CORONAS"; case LUMP_SHADOWMAP_VOLUMES: return "LUMP_SHADOWMAP_VOLUMES"; case LUMP_SHADOWMAP_VOLUME_PLANES: return "LUMP_SHADOWMAP_VOLUME_PLANES"; case LUMP_EXPOSURE_VOLUMES: return "LUMP_EXPOSURE_VOLUMES"; case LUMP_EXPOSURE_VOLUME_PLANES: return "LUMP_EXPOSURE_VOLUME_PLANES"; case LUMP_OCCLUDERS: return "LUMP_OCCLUDERS"; case LUMP_OUTDOORBOUNDS: return "LUMP_OUTDOORBOUNDS"; case LUMP_HERO_ONLY_LIGHTS: return "LUMP_HERO_ONLY_LIGHTS"; default: return "Unknown Lump Type"; } return "Unknown Lump Type"; } static QString ZLibErrorToString(int result) { switch (result) { case Z_ERRNO: return "Encountered file operation error!"; case Z_STREAM_ERROR: return "Stream was not initialized properly!"; case Z_DATA_ERROR: return "The input data was corrupted or incomplete!"; case Z_MEM_ERROR: return "There was not enough memory!"; case Z_BUF_ERROR: return "There was not enough room in the output buffer!"; case Z_VERSION_ERROR: return "Linked libraries are out of date!"; } return ""; } static quint32 PadInt4(quint32 size) { return (size + 3) & ~3; // Align size to 4 bytes } static quint32 PaddingSize(quint32 size) { return PadInt4(size) - size; } static QString CompanyEnumToStr(FF_COMPANY aCompany) { switch (aCompany) { case COMPANY_NONE: return "None"; case COMPANY_INFINITY_WARD: return "Infinity Ward"; case COMPANY_TREYARCH: return "Treyarch"; case COMPANY_SLEDGEHAMMER: return "Sledgehammer"; case COMPANY_NEVERSOFT: return "Neversoft"; } return "None"; } static QString FileTypeEnumToStr(FF_FILETYPE aFileType) { switch (aFileType) { case FILETYPE_NONE: return "None"; case FILETYPE_FAST_FILE: return "Fast File"; } return "None"; } static QString SignageEnumToStr(FF_SIGNAGE aSignage) { switch (aSignage) { case SIGNAGE_NONE: return "None"; case SIGNAGE_SIGNED: return "Signed"; case SIGNAGE_UNSIGNED: return "Unsigned"; } return "None"; } static QString MenuVAlignToStr(MENU_V_ALIGNMENT align) { if (align == VERTICAL_ALIGN_SUBTOP) { return "VERTICAL_ALIGN_SUBTOP"; } else if (align == VERTICAL_ALIGN_TOP) { return "VERTICAL_ALIGN_TOP"; } else if (align == VERTICAL_ALIGN_CENTER) { return "VERTICAL_ALIGN_CENTER"; } else if (align == VERTICAL_ALIGN_BOTTOM) { return "VERTICAL_ALIGN_BOTTOM"; } else if (align == VERTICAL_ALIGN_FULLSCREEN) { return "VERTICAL_ALIGN_FULLSCREEN"; } else if (align == VERTICAL_ALIGN_NOSCALE) { return "VERTICAL_ALIGN_NOSCALE"; } else if (align == VERTICAL_ALIGN_TO480) { return "VERTICAL_ALIGN_TO480"; } else if (align == VERTICAL_ALIGN_CENTER_SAFEAREA) { return "VERTICAL_ALIGN_CENTER_SAFEAREA"; } else if (align == VERTICAL_ALIGN_MAX) { return "VERTICAL_ALIGN_CENTER_SAFEAREA"; } else if (align == VERTICAL_ALIGN_DEFAULT) { return "VERTICAL_ALIGN_SUBTOP"; } return "VERTICAL_ALIGN_SUBTOP"; } static QString MenuHAlignToStr(MENU_H_ALIGNMENT align) { if (align == HORIZONTAL_ALIGN_SUBLEFT) { return "HORIZONTAL_ALIGN_SUBLEFT"; } else if (align == HORIZONTAL_ALIGN_LEFT) { return "HORIZONTAL_ALIGN_LEFT"; } else if (align == HORIZONTAL_ALIGN_CENTER) { return "HORIZONTAL_ALIGN_CENTER"; } else if (align == HORIZONTAL_ALIGN_RIGHT) { return "HORIZONTAL_ALIGN_RIGHT"; } else if (align == HORIZONTAL_ALIGN_FULLSCREEN) { return "HORIZONTAL_ALIGN_FULLSCREEN"; } else if (align == HORIZONTAL_ALIGN_NOSCALE) { return "HORIZONTAL_ALIGN_NOSCALE"; } else if (align == HORIZONTAL_ALIGN_TO640) { return "HORIZONTAL_ALIGN_TO640"; } else if (align == HORIZONTAL_ALIGN_CENTER_SAFEAREA) { return "HORIZONTAL_ALIGN_CENTER_SAFEAREA"; } else if (align == HORIZONTAL_ALIGN_MAX) { return "HORIZONTAL_ALIGN_CENTER_SAFEAREA"; } else if (align == HORIZONTAL_ALIGN_DEFAULT) { return "HORIZONTAL_ALIGN_SUBLEFT"; } return "HORIZONTAL_ALIGN_SUBLEFT"; } static QColor ColorFromNormalized(float r, float g, float b, float a) { // Ensure values are clamped between 0 and 1 r = qBound(0.0f, r, 1.0f); g = qBound(0.0f, g, 1.0f); b = qBound(0.0f, b, 1.0f); a = qBound(0.0f, a, 1.0f); // Convert to 0-255 scale int red = static_cast(r * 255); int green = static_cast(g * 255); int blue = static_cast(b * 255); int alpha = static_cast(a * 255); return QColor(red, green, blue, alpha); } }; #endif // UTILS_H