diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 705252236..33753d68f 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -8,6 +8,7 @@ extern "C" { #include "engine/behavior_script.h" #include "engine/math_util.h" #include "src/game/moving_texture.h" +#include "src/pc/djui/djui_console.h" } #define FUNCTION_CODE (u32) 0x434E5546 @@ -725,9 +726,23 @@ void Print(const char *aFmt, Args... aArgs) { fflush(stdout); } -#define PrintError(...) { \ +template +void PrintConsole(const char *aFmt, Args... aArgs) { + snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, aFmt, aArgs...); + djui_console_message_create(gDjuiConsoleTmpBuffer); +} + +template +void PrintError(const char *aFmt, Args... aArgs) { + printf(aFmt, aArgs...); + printf("\r\n"); + fflush(stdout); + PrintConsole(aFmt, aArgs...); +} +#define PrintDataError(...) { \ if (aGfxData->mErrorCount == 0) Print(" ERROR!"); \ Print(__VA_ARGS__); \ + PrintConsole(__VA_ARGS__); \ aGfxData->mErrorCount++; \ } diff --git a/data/dynos_bin_actor.cpp b/data/dynos_bin_actor.cpp index 8c21bd0df..4bcb004ba 100644 --- a/data/dynos_bin_actor.cpp +++ b/data/dynos_bin_actor.cpp @@ -16,7 +16,7 @@ void ClearGfxDataNodes(DataNodes &aDataNodes) { static bool DynOS_Actor_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData) { BinFile *_File = BinFile::OpenW(aOutputFilename.c_str()); if (!_File) { - PrintError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); + PrintDataError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); return false; } @@ -182,6 +182,7 @@ static void DynOS_Actor_Generate(const SysPath &aPackFolder, ArraymModelIdentifier); + PrintConsole("%s.bin: Model identifier: %X - Processing... ", _GeoRootName.begin(), _GfxData->mModelIdentifier); DynOS_Geo_Parse(_GfxData, _GeoNode, true); // Init animation data @@ -215,7 +216,7 @@ static void DynOS_Actor_Generate(const SysPath &aPackFolder, ArraymErrorCount == 0) { DynOS_Actor_WriteBinary(_BinFilename, _GfxData); } else { - Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount); + PrintError(" %u error(s): Unable to parse data", _GfxData->mErrorCount); } // Clear data pointers ClearGfxDataNodes(_GfxData->mLights); diff --git a/data/dynos_bin_ambient_t.cpp b/data/dynos_bin_ambient_t.cpp index c409b1fa7..abd5f56bb 100644 --- a/data/dynos_bin_ambient_t.cpp +++ b/data/dynos_bin_ambient_t.cpp @@ -9,7 +9,7 @@ DataNode* DynOS_AmbientT_Parse(GfxData* aGfxData, DataNode // Check tokens count if (aNode->mTokens.Count() < 8) { - PrintError(" ERROR: %s: not enough data", aNode->mName.begin()); + PrintDataError(" ERROR: %s: not enough data", aNode->mName.begin()); return aNode; } diff --git a/data/dynos_bin_animation.cpp b/data/dynos_bin_animation.cpp index b78258ccc..787b11ad1 100644 --- a/data/dynos_bin_animation.cpp +++ b/data/dynos_bin_animation.cpp @@ -7,7 +7,7 @@ static void ScanAnimationDataFile(GfxData *aGfxData, const SysPath &aFilename) { FILE *_File = fopen(aFilename.c_str(), "rb"); if (!_File) { - PrintError(" ERROR: Unable to open file \"%s\"", aFilename.c_str()); + PrintDataError(" ERROR: Unable to open file \"%s\"", aFilename.c_str()); } // Load file into a buffer while removing all comments @@ -70,7 +70,7 @@ static void ScanAnimationDataFile(GfxData *aGfxData, const SysPath &aFilename) { case DATA_TYPE_ANIMATION: { if (_Data.Count() < 10) { - PrintError(" ERROR: %s: Not enough data", _DataName.begin()); + PrintDataError(" ERROR: %s: Not enough data", _DataName.begin()); break; } @@ -104,7 +104,7 @@ static void ScanAnimationDataFile(GfxData *aGfxData, const SysPath &aFilename) { static void ScanAnimationTableFile(GfxData *aGfxData, const SysPath &aFilename) { FILE *_File = fopen(aFilename.c_str(), "rb"); if (!_File) { - PrintError(" ERROR: Unable to open file \"%s\"", aFilename.c_str()); + PrintDataError(" ERROR: Unable to open file \"%s\"", aFilename.c_str()); } // Load file into a buffer while removing all comments diff --git a/data/dynos_bin_behavior.cpp b/data/dynos_bin_behavior.cpp index f148c94d6..454ae39f3 100644 --- a/data/dynos_bin_behavior.cpp +++ b/data/dynos_bin_behavior.cpp @@ -1973,7 +1973,7 @@ static BehaviorScript ParseBehaviorScriptSymbolArg(GfxData *aGfxData, DataNodemTokens[aTokenIndex - 1]; - PrintError(" ERROR: Unknown bhv arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown bhv arg: %s", _Arg.begin()); } return value; } @@ -2262,7 +2262,7 @@ static void ParseBehaviorScriptSymbol(GfxData *aGfxData, DataNode *DynOS_Bhv_Parse(GfxData *aGfxData, DataNode *aNode, bool aDisplayPercent) { @@ -2466,7 +2466,7 @@ static void DynOS_Bhv_Write(BinFile* aFile, GfxData* aGfxData, DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat // Sanity check the files size. The minimum valid size is 9 bytes. // 1 byte for the type, 1 bytes for the name length, 3 bytes for the version, And 4 bytes for the behaviors size. if (aFile->Size() < 9) { - PrintError(" ERROR: Behavior file is smaller then it should be, Rejecting '%s'.", aFile->GetFilename()); + PrintDataError(" ERROR: Behavior file is smaller then it should be, Rejecting '%s'.", aFile->GetFilename()); // We have nothing to return, So return NULL. return NULL; } @@ -2512,7 +2512,7 @@ static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat // we can't read it no matter what. If it's just minor or patch. We might have // code to support it. if (majorVersion != BEHAVIOR_MIN_MAJOR_VER || (minorVersion < BEHAVIOR_MIN_MINOR_VER || patchVersion < BEHAVIOR_MIN_PATCH_VER)) { - PrintError(" ERROR: Behavior file is version %u.%u.%u, which is not supported! Rejecting '%s'.", majorVersion, minorVersion, patchVersion, aFile->GetFilename()); + PrintDataError(" ERROR: Behavior file is version %u.%u.%u, which is not supported! Rejecting '%s'.", majorVersion, minorVersion, patchVersion, aFile->GetFilename()); // We don't return this since we failed to read the behavior. Delete(_Node); // We have nothing to return, So return NULL. @@ -2523,7 +2523,7 @@ static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat // We also check if the specified behavior size is valid for the file. u32 dataSize = aFile->Read(); if (dataSize == 0 || (dataSize > (aFile->Size() - aFile->Offset()))) { - PrintError(" ERROR: Behavior file has a invalid behavior in it! Rejecting '%s'.", aFile->GetFilename()); + PrintDataError(" ERROR: Behavior file has a invalid behavior in it! Rejecting '%s'.", aFile->GetFilename()); // We don't return this since we failed to read the behavior. Delete(_Node); // We have nothing to return, So return NULL. @@ -2537,7 +2537,7 @@ static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat // Read it for (u32 i = 0; i != _Node->mSize; ++i) { if (aFile->EoF()) { - PrintError(" ERROR: Reached EOF when reading file! Expected %llx bytes!", _Node->mSize * sizeof(u32)); + PrintDataError(" ERROR: Reached EOF when reading file! Expected %llx bytes!", _Node->mSize * sizeof(u32)); break; } u32 _Value = aFile->Read(); @@ -2626,13 +2626,14 @@ static void DynOS_Bhv_Generate(const SysPath &aPackFolder, ArraymModelIdentifier); + PrintConsole("%s.bhv: Model identifier: %X - Processing... ", _BhvRootName.begin(), _GfxData->mModelIdentifier); DynOS_Bhv_Parse(_GfxData, _BhvNode, true); // Write if no error if (_GfxData->mErrorCount == 0) { DynOS_Bhv_WriteBinary(_BinFilename, _GfxData); } else { - Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount); + PrintError(" %u error(s): Unable to parse data", _GfxData->mErrorCount); } // Clear data pointers diff --git a/data/dynos_bin_col.cpp b/data/dynos_bin_col.cpp index f630c0e45..3fe618c51 100644 --- a/data/dynos_bin_col.cpp +++ b/data/dynos_bin_col.cpp @@ -42,21 +42,21 @@ struct CollisionValidationData { static void ValidateColSectionChange(GfxData* aGfxData, struct CollisionValidationData& aColValData, u8 section) { if (aColValData.section == COL_SECTION_END) { - PrintError("Found new col section after COL_END"); + PrintDataError("Found new col section after COL_END"); } if (aColValData.section != section) { if (aColValData.vtxAlloc != aColValData.vtxCount) { - PrintError("Improper vtx count found in section. Allocated: %u, Defined: %u", aColValData.vtxAlloc, aColValData.vtxCount); + PrintDataError("Improper vtx count found in section. Allocated: %u, Defined: %u", aColValData.vtxAlloc, aColValData.vtxCount); } if (aColValData.triAlloc != aColValData.triCount) { - PrintError("Improper triangle count found in section. Allocated: %u, Defined: %u", aColValData.triAlloc, aColValData.triCount); + PrintDataError("Improper triangle count found in section. Allocated: %u, Defined: %u", aColValData.triAlloc, aColValData.triCount); } if (aColValData.specialAlloc != aColValData.specialCount) { - PrintError("Improper sepcial count found in section. Allocated: %u, Defined: %u", aColValData.triAlloc, aColValData.triCount); + PrintDataError("Improper sepcial count found in section. Allocated: %u, Defined: %u", aColValData.triAlloc, aColValData.triCount); } if (aColValData.waterBoxAlloc != aColValData.waterBoxCount) { - PrintError("Improper water box count found in section. Allocated: %u, Defined: %u", aColValData.waterBoxAlloc, aColValData.waterBoxCount); + PrintDataError("Improper water box count found in section. Allocated: %u, Defined: %u", aColValData.waterBoxAlloc, aColValData.waterBoxCount); } } @@ -65,17 +65,17 @@ static void ValidateColSectionChange(GfxData* aGfxData, struct CollisionValidati static void ValidateColInit(GfxData* aGfxData, struct CollisionValidationData& aColValData) { if (aColValData.tokenIndex != 0) { - PrintError("COL_INIT found after the first token"); + PrintDataError("COL_INIT found after the first token"); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_VTX); } static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) { if (strcmp(aColValData.lastSymbol, "COL_INIT") != 0) { - PrintError("COL_VERTEX_INIT found outside of vertex section"); + PrintDataError("COL_VERTEX_INIT found outside of vertex section"); } if (arg0 < 0) { - PrintError("COL_VERTEX_INIT with a negative count: %d", arg0); + PrintDataError("COL_VERTEX_INIT with a negative count: %d", arg0); } aColValData.vtxAlloc = arg0; aColValData.vtxCount = 0; @@ -83,14 +83,14 @@ static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationD static void ValidateColVertex(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) { if (aColValData.section != COL_SECTION_VTX) { - PrintError("COL_VERTEX found outside of vertex section"); + PrintDataError("COL_VERTEX found outside of vertex section"); } aColValData.vtxCount++; } static void ValidateColTriInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1) { if (arg1 < 0) { - PrintError("COL_TRI_INIT with a negative count: %d", arg1); + PrintDataError("COL_TRI_INIT with a negative count: %d", arg1); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_TRI); aColValData.triAlloc = arg1; @@ -99,16 +99,16 @@ static void ValidateColTriInit(GfxData* aGfxData, struct CollisionValidationData static void ValidateColTri(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) { if (aColValData.section != COL_SECTION_TRI) { - PrintError("COL_TRI found outside of triangle section"); + PrintDataError("COL_TRI found outside of triangle section"); } if (arg0 < 0 || arg0 > aColValData.vtxCount) { - PrintError("COL_TRI used vertex outside of known range for first param: %d", arg0); + PrintDataError("COL_TRI used vertex outside of known range for first param: %d", arg0); } if (arg1 < 0 || arg1 > aColValData.vtxCount) { - PrintError("COL_TRI used vertex outside of known range for second param: %d", arg1); + PrintDataError("COL_TRI used vertex outside of known range for second param: %d", arg1); } if (arg2 < 0 || arg2 > aColValData.vtxCount) { - PrintError("COL_TRI used vertex outside of known range for third param: %d", arg2); + PrintDataError("COL_TRI used vertex outside of known range for third param: %d", arg2); } aColValData.triCount++; } @@ -127,7 +127,7 @@ static void ValidateColEnd(GfxData* aGfxData, struct CollisionValidationData& aC static void ValidateColSpecialInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) { if (arg0 < 0) { - PrintError("COL_SPECIAL_INIT with a negative count: %d", arg0); + PrintDataError("COL_SPECIAL_INIT with a negative count: %d", arg0); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_SPECIAL); aColValData.specialAlloc = arg0; @@ -136,7 +136,7 @@ static void ValidateColSpecialInit(GfxData* aGfxData, struct CollisionValidation static void ValidateColWaterBoxInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) { if (arg0 < 0) { - PrintError("COL_WATER_BOX_INIT with a negative count: %d", arg0); + PrintDataError("COL_WATER_BOX_INIT with a negative count: %d", arg0); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_WATER_BOX); aColValData.waterBoxAlloc = arg0; @@ -145,28 +145,28 @@ static void ValidateColWaterBoxInit(GfxData* aGfxData, struct CollisionValidatio static void ValidateColWaterBox(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) { if (aColValData.section != COL_SECTION_WATER_BOX) { - PrintError("COL_WATER_BOX found outside of water box section"); + PrintDataError("COL_WATER_BOX found outside of water box section"); } aColValData.waterBoxCount++; } static void ValidateColSpecialObject(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3) { if (aColValData.section != COL_SECTION_SPECIAL) { - PrintError("SPECIAL_OBJECT found outside of special section"); + PrintDataError("SPECIAL_OBJECT found outside of special section"); } aColValData.specialCount++; } static void ValidateColSpecialObjectWithYaw(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4) { if (aColValData.section != COL_SECTION_SPECIAL) { - PrintError("SPECIAL_OBJECT_WITH_YAW found outside of special section"); + PrintDataError("SPECIAL_OBJECT_WITH_YAW found outside of special section"); } aColValData.specialCount++; } static void ValidateColSpecialObjectWithYawAndParam(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) { if (aColValData.section != COL_SECTION_SPECIAL) { - PrintError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM found outside of special section"); + PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM found outside of special section"); } aColValData.specialCount++; } @@ -458,7 +458,7 @@ static s16 ParseColSymbolArg(GfxData* aGfxData, DataNode* aNode, u64& } // Unknown - PrintError(" ERROR: Unknown col arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown col arg: %s", _Arg.begin()); return 0; } @@ -575,7 +575,7 @@ static void ParseCollisionSymbol(GfxData* aGfxData, DataNode* aNode, col_symbol_6(SPECIAL_OBJECT_WITH_YAW_AND_PARAM, ValidateColSpecialObjectWithYawAndParam); // Unknown - PrintError(" ERROR: Unknown col symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown col symbol: %s", _Symbol.begin()); } DataNode* DynOS_Col_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { @@ -595,7 +595,7 @@ DataNode* DynOS_Col_Parse(GfxData* aGfxData, DataNode* aNo } if (colValData.section != COL_SECTION_END) { - PrintError("Collision did not end with COL_END"); + PrintDataError("Collision did not end with COL_END"); } if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); } @@ -603,7 +603,7 @@ DataNode* DynOS_Col_Parse(GfxData* aGfxData, DataNode* aNo aNode->mLoadIndex = aGfxData->mLoadIndex++; if (aGfxData->mErrorCount > 0) { - Print("Failed to parse collision: '%s'", aNode->mName.begin()); + PrintDataError("Failed to parse collision: '%s'", aNode->mName.begin()); } return aNode; @@ -630,7 +630,7 @@ void DynOS_Col_Write(BinFile* aFile, GfxData* aGfxData, DataNode *aNo static bool DynOS_Col_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData, DataNode* _Node) { BinFile *_File = BinFile::OpenW(aOutputFilename.c_str()); if (!_File) { - PrintError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); + PrintDataError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); return false; } @@ -706,13 +706,14 @@ void DynOS_Col_Generate(const SysPath &aPackFolder, Array> _Ac // Parse data PrintNoNewLine("%s.col: Model identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier); + PrintConsole("%s.col: Model identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier); DynOS_Col_Parse(_GfxData, _ColNode, true); // Write if no error if (_GfxData->mErrorCount == 0) { DynOS_Col_WriteBinary(_ColFilename, _GfxData, _ColNode); } else { - Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount); + PrintError(" %u error(s): Unable to parse data", _GfxData->mErrorCount); } // Clear data pointers diff --git a/data/dynos_bin_compress.cpp b/data/dynos_bin_compress.cpp index 6764325aa..879fc8b50 100644 --- a/data/dynos_bin_compress.cpp +++ b/data/dynos_bin_compress.cpp @@ -29,7 +29,7 @@ static inline void DynOS_Bin_Compress_Free() { static inline bool DynOS_Bin_Compress_Check(bool condition, const char *function, const char *filename, const char *message) { if (!condition) { - Print("ERROR: %s: File \"%s\": %s", function, filename, message); + PrintError("ERROR: %s: File \"%s\": %s", function, filename, message); DynOS_Bin_Compress_Free(); return false; } @@ -223,7 +223,7 @@ BinFile *DynOS_Bin_Decompress(const SysPath &aFilename) { uncompressRc == Z_OK, __FUNCTION__, aFilename.c_str(), "Cannot uncompress data" )) { - Print("ERROR: uncompress rc: %d, length uncompressed: %lu, length compressed: %lu, length header: %lu", uncompressRc, sLengthUncompressed, sLengthCompressed, _LengthHeader); + PrintError("ERROR: uncompress rc: %d, length uncompressed: %lu, length compressed: %lu, length header: %lu", uncompressRc, sLengthUncompressed, sLengthCompressed, _LengthHeader); return NULL; } Print("uncompress rc: %d, length uncompressed: %lu, length compressed: %lu, length header: %lu", uncompressRc, sLengthUncompressed, sLengthCompressed, _LengthHeader); diff --git a/data/dynos_bin_geo.cpp b/data/dynos_bin_geo.cpp index ba37877ad..d65d417f3 100644 --- a/data/dynos_bin_geo.cpp +++ b/data/dynos_bin_geo.cpp @@ -148,7 +148,7 @@ static s64 ParseGeoSymbolArg(GfxData* aGfxData, DataNode* aNode, u64& } // Unknown - PrintError(" ERROR: Unknown geo arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown geo arg: %s", _Arg.begin()); return 0; } @@ -405,7 +405,7 @@ static void ParseGeoSymbol(GfxData* aGfxData, DataNode* aNode, GeoLay } // Unknown - PrintError(" ERROR: Unknown geo symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown geo symbol: %s", _Symbol.begin()); } DataNode* DynOS_Geo_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { diff --git a/data/dynos_bin_gfx.cpp b/data/dynos_bin_gfx.cpp index 66f24f460..2d5b164f7 100644 --- a/data/dynos_bin_gfx.cpp +++ b/data/dynos_bin_gfx.cpp @@ -480,7 +480,7 @@ static s64 ParseGfxSymbolArg(GfxData* aGfxData, DataNode* aNode, u64* pToke } // Unknown - PrintError(" ERROR: Unknown gfx arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown gfx arg: %s", _Arg.begin()); return 0; } @@ -673,7 +673,7 @@ static String ConvertSetCombineModeArgToString(GfxData *aGfxData, const String& gfx_set_combine_mode_arg(G_CC_HILITERGBA2); gfx_set_combine_mode_arg(G_CC_HILITERGBDECALA2); gfx_set_combine_mode_arg(G_CC_HILITERGBPASSA2); - PrintError(" ERROR: Unknown gfx gsDPSetCombineMode arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown gfx gsDPSetCombineMode arg: %s", _Arg.begin()); return ""; } @@ -693,7 +693,7 @@ static Array ParseGfxSetCombineMode(GfxData* aGfxData, DataNode* aNode } } if (_Args.Count() < 8) { - PrintError(" ERROR: gsDPSetCombineMode %s: Not enough arguments", _Buffer.begin()); + PrintDataError(" ERROR: gsDPSetCombineMode %s: Not enough arguments", _Buffer.begin()); } return _Args; } @@ -935,7 +935,7 @@ static void ParseGfxSymbol(GfxData* aGfxData, DataNode* aNode, Gfx*& aHead, } // Unknown - PrintError(" ERROR: Unknown gfx symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown gfx symbol: %s", _Symbol.begin()); } DataNode* DynOS_Gfx_Parse(GfxData* aGfxData, DataNode* aNode) { diff --git a/data/dynos_bin_light_t.cpp b/data/dynos_bin_light_t.cpp index e950e1c1e..b342fa06e 100644 --- a/data/dynos_bin_light_t.cpp +++ b/data/dynos_bin_light_t.cpp @@ -9,7 +9,7 @@ DataNode* DynOS_LightT_Parse(GfxData* aGfxData, DataNode* aNod // Check tokens count if (aNode->mTokens.Count() < 12) { - PrintError(" ERROR: %s: not enough data", aNode->mName.begin()); + PrintDataError(" ERROR: %s: not enough data", aNode->mName.begin()); return aNode; } diff --git a/data/dynos_bin_lights.cpp b/data/dynos_bin_lights.cpp index aef7cc010..0be628fb7 100644 --- a/data/dynos_bin_lights.cpp +++ b/data/dynos_bin_lights.cpp @@ -9,13 +9,13 @@ DataNode* DynOS_Lights_Parse(GfxData* aGfxData, DataNode* aNod // Check tokens count if (aNode->mTokens.Count() < 10) { - PrintError(" ERROR: %s: not enough data", aNode->mName.begin()); + PrintDataError(" ERROR: %s: not enough data", aNode->mName.begin()); return aNode; } // Parse def token if (aNode->mTokens[0] != "gdSPDefLights1") { - PrintError(" ERROR: Invalid def token: should be gdSPDefLights1, is %s", aNode->mTokens[0].begin()); + PrintDataError(" ERROR: Invalid def token: should be gdSPDefLights1, is %s", aNode->mTokens[0].begin()); return aNode; } diff --git a/data/dynos_bin_lvl.cpp b/data/dynos_bin_lvl.cpp index 91a9e2854..8e02fe2c6 100644 --- a/data/dynos_bin_lvl.cpp +++ b/data/dynos_bin_lvl.cpp @@ -523,7 +523,7 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNodemTokens[aTokenIndex - 1]; - PrintError(" ERROR: Unknown lvl arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown lvl arg: %s", _Arg.begin()); } return value; } @@ -827,7 +827,7 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode* aNo } // Unknown - PrintError(" ERROR: Unknown lvl symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown lvl symbol: %s", _Symbol.begin()); } DataNode* DynOS_Lvl_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { @@ -884,7 +884,7 @@ static void DynOS_Lvl_Write(BinFile* aFile, GfxData* aGfxData, DataNodemModelIdentifier); + PrintConsole("%s.lvl: Model identifier: %X - Processing... ", _LvlRootName.begin(), _GfxData->mModelIdentifier); DynOS_Lvl_Parse(_GfxData, _LvlRoot, true); // Force all of the movtexs, collisions, and trajectories into the compiled lvl @@ -1102,7 +1103,7 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, ArraymErrorCount == 0) { DynOS_Lvl_WriteBinary(_LvlFilename, _GfxData); } else { - Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount); + PrintError(" %u error(s): Unable to parse data", _GfxData->mErrorCount); } // Clear data pointers diff --git a/data/dynos_bin_macro_object.cpp b/data/dynos_bin_macro_object.cpp index 013fffa06..5090abe5b 100644 --- a/data/dynos_bin_macro_object.cpp +++ b/data/dynos_bin_macro_object.cpp @@ -404,7 +404,7 @@ static s64 ParseMacroObjectSymbolArg(GfxData* aGfxData, DataNode* a } // Unknown - PrintError(" ERROR: Unknown macro object arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown macro object arg: %s", _Arg.begin()); return 0; } @@ -451,7 +451,7 @@ static void ParseMacroObjectSymbol(GfxData* aGfxData, DataNode* aNo macro_object_symbol_0(MACRO_OBJECT_END); // Unknown - PrintError(" ERROR: Unknown macro object symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown macro object symbol: %s", _Symbol.begin()); } DataNode* DynOS_MacroObject_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { diff --git a/data/dynos_bin_movtex.cpp b/data/dynos_bin_movtex.cpp index 9edbc26c8..a7f993e44 100644 --- a/data/dynos_bin_movtex.cpp +++ b/data/dynos_bin_movtex.cpp @@ -40,7 +40,7 @@ static s64 ParseMovtexSymbolArg(GfxData* aGfxData, DataNode* aNode, u64& movtex_constant(NULL); // Unknown - PrintError(" ERROR: Unknown movtex arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown movtex arg: %s", _Arg.begin()); return 0; } @@ -143,7 +143,7 @@ static void ParseMovtexSymbol(GfxData* aGfxData, DataNode* aNode, Movtex } // Unknown - PrintError(" ERROR: Unknown movtex symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown movtex symbol: %s", _Symbol.begin()); } DataNode* DynOS_Movtex_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { diff --git a/data/dynos_bin_movtexqc.cpp b/data/dynos_bin_movtexqc.cpp index 1a8fdc858..9cc78729f 100644 --- a/data/dynos_bin_movtexqc.cpp +++ b/data/dynos_bin_movtexqc.cpp @@ -27,7 +27,7 @@ static Movtex* ParseMovtexQCSymbolArg(GfxData* aGfxData, DataNode* aNo } // Unknown - PrintError(" ERROR: Unknown movtexqc arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown movtexqc arg: %s", _Arg.begin()); return NULL; } diff --git a/data/dynos_bin_pointer.cpp b/data/dynos_bin_pointer.cpp index e7a28fec4..de3a94cae 100644 --- a/data/dynos_bin_pointer.cpp +++ b/data/dynos_bin_pointer.cpp @@ -183,7 +183,7 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) { } } - PrintError("Unable to find pointer %x!", aPtr); + PrintDataError("Unable to find pointer %x!", aPtr); return { "", 0 }; } diff --git a/data/dynos_bin_read.cpp b/data/dynos_bin_read.cpp index e20ced116..4cb85f45f 100644 --- a/data/dynos_bin_read.cpp +++ b/data/dynos_bin_read.cpp @@ -217,7 +217,7 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { } else if (_Buffer == "BehaviorScript") { _DataType = DATA_TYPE_BEHAVIOR_SCRIPT; } else { - PrintError(" ERROR: Unknown type name: %s", _Buffer.begin()); + PrintDataError(" ERROR: Unknown type name: %s", _Buffer.begin()); } _Buffer.Clear(); } @@ -266,7 +266,7 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { if (*c == '=') { pDataStart = c + 1; } else if (*c == ';') { - PrintError(" ERROR: %s: Unexpected end of data", pDataName->begin()); + PrintDataError(" ERROR: %s: Unexpected end of data", pDataName->begin()); } } diff --git a/data/dynos_bin_tex.cpp b/data/dynos_bin_tex.cpp index b6034a4e4..bb023a03c 100644 --- a/data/dynos_bin_tex.cpp +++ b/data/dynos_bin_tex.cpp @@ -52,7 +52,7 @@ static TexData* LoadTextureFromFile(GfxData *aGfxData, const char* aFile) { // The file does not exist in either spot! if (!_File) { - PrintError(" ERROR: Unable to open file at \"%s\" or \"%s\"", _Filename.c_str(), _ActorFilename.c_str()); + PrintDataError(" ERROR: Unable to open file at \"%s\" or \"%s\"", _Filename.c_str(), _ActorFilename.c_str()); return NULL; } } @@ -72,7 +72,7 @@ void DynOS_Tex_ConvertTextureDataToPng(GfxData *aGfxData, TexData* aTexture) { const u8 *_Palette = (aGfxData->mGfxContext.mCurrentPalette ? aGfxData->mGfxContext.mCurrentPalette->mData->mRawData.begin() : NULL); u8 *_Buffer = DynOS_Tex_ConvertToRGBA32(aTexture->mRawData.begin(), aTexture->mRawData.Count(), aTexture->mRawFormat, aTexture->mRawSize, _Palette); if (_Buffer == NULL) { - PrintError(" ERROR: Unknown texture format"); + PrintDataError(" ERROR: Unknown texture format"); return; } @@ -80,7 +80,7 @@ void DynOS_Tex_ConvertTextureDataToPng(GfxData *aGfxData, TexData* aTexture) { s32 _PngLength = 0; u8 *_PngData = stbi_write_png_to_mem(_Buffer, 0, aTexture->mRawWidth, aTexture->mRawHeight, 4, &_PngLength); if (!_PngData || !_PngLength) { - PrintError(" ERROR: Cannot convert texture to PNG"); + PrintDataError(" ERROR: Cannot convert texture to PNG"); return; } @@ -97,7 +97,7 @@ DataNode* DynOS_Tex_Parse(GfxData* aGfxData, DataNode* aNode) // Check tokens Count if (aNode->mTokens.Count() < 1) { - PrintError(" ERROR: %s: not enough data", aNode->mName.begin()); + PrintDataError(" ERROR: %s: not enough data", aNode->mName.begin()); return aNode; } @@ -106,7 +106,7 @@ DataNode* DynOS_Tex_Parse(GfxData* aGfxData, DataNode* aNode) if (i0 != -1) { s32 i1 = aNode->mTokens[0].Find(".inc.c"); if (i1 == -1) { - PrintError(" ERROR: %s: missing .inc.c in String %s", aNode->mName.begin(), aNode->mTokens[0].begin()); + PrintDataError(" ERROR: %s: missing .inc.c in String %s", aNode->mName.begin(), aNode->mTokens[0].begin()); return aNode; } @@ -122,7 +122,7 @@ DataNode* DynOS_Tex_Parse(GfxData* aGfxData, DataNode* aNode) if (dq0 != -1) { s32 dq1 = aNode->mTokens[0].Find('\"', dq0 + 1); if (dq1 == -1) { - PrintError(" ERROR: %s: missing second quote in String %s", aNode->mName.begin(), aNode->mTokens[0].begin()); + PrintDataError(" ERROR: %s: missing second quote in String %s", aNode->mName.begin(), aNode->mTokens[0].begin()); return aNode; } @@ -181,7 +181,7 @@ void DynOS_Tex_Write(BinFile* aFile, GfxData* aGfxData, DataNode *aNode static bool DynOS_Tex_WriteBinary(GfxData* aGfxData, const SysPath &aOutputFilename, String& aName, TexData* aTexData, bool aRawTexture) { BinFile *_File = BinFile::OpenW(aOutputFilename.c_str()); if (!_File) { - PrintError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); + PrintDataError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); return false; } @@ -411,7 +411,7 @@ static void DynOS_Tex_GeneratePack_Recursive(const SysPath &aPackFolder, SysPath aGfxData->mModelIdentifier++; TexData* _TexData = LoadTextureFromFile(aGfxData, _Path.c_str()); if (_TexData == NULL) { - PrintError("Error reading texture from file: %s", _Path.c_str()); + PrintDataError("Error reading texture from file: %s", _Path.c_str()); continue; } diff --git a/data/dynos_bin_texlist.cpp b/data/dynos_bin_texlist.cpp index c0a6fe883..d0e0bac90 100644 --- a/data/dynos_bin_texlist.cpp +++ b/data/dynos_bin_texlist.cpp @@ -13,7 +13,7 @@ static TexData* ParseTexListSymbol(GfxData* aGfxData, DataNode* aNode, } // Unknown - PrintError(" ERROR: Unknown texlist arg: %s", aToken.begin()); + PrintDataError(" ERROR: Unknown texlist arg: %s", aToken.begin()); return NULL; } @@ -56,7 +56,7 @@ void DynOS_TexList_Write(BinFile* aFile, GfxData* aGfxData, DataNode * } } if (!found) { - PrintError("Could not write texture in texlist"); + PrintDataError("Could not write texture in texlist"); } } } @@ -78,7 +78,7 @@ DataNode* DynOS_TexList_Load(BinFile *aFile, GfxData *aGfxData) { u32 _Value = aFile->Read(); void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, &_Node->mFlags); if (_Ptr == NULL) { - PrintError("Could not read texture in texlist"); + PrintDataError("Could not read texture in texlist"); } else { _Node->mData[i] = ((DataNode*)_Ptr)->mData; } diff --git a/data/dynos_bin_trajectory.cpp b/data/dynos_bin_trajectory.cpp index ba4cff5f1..ddd7cbec5 100644 --- a/data/dynos_bin_trajectory.cpp +++ b/data/dynos_bin_trajectory.cpp @@ -28,7 +28,7 @@ static s64 ParseTrajectorySymbolArg(GfxData* aGfxData, DataNode* aNo trajectory_constant(NULL); // Unknown - PrintError(" ERROR: Unknown trajectory arg: %s", _Arg.begin()); + PrintDataError(" ERROR: Unknown trajectory arg: %s", _Arg.begin()); return 0; } @@ -59,7 +59,7 @@ static void ParseTrajectorySymbol(GfxData* aGfxData, DataNode* aNode trajectory_symbol_0(TRAJECTORY_END); // Unknown - PrintError(" ERROR: Unknown trajectory symbol: %s", _Symbol.begin()); + PrintDataError(" ERROR: Unknown trajectory symbol: %s", _Symbol.begin()); } DataNode* DynOS_Trajectory_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { diff --git a/data/dynos_mgr_actor.cpp b/data/dynos_mgr_actor.cpp index d00d51289..2e6fa1cdc 100644 --- a/data/dynos_mgr_actor.cpp +++ b/data/dynos_mgr_actor.cpp @@ -33,14 +33,14 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) { GfxData *_GfxData = DynOS_Actor_LoadFromBinary(aFilename, actorName, aFilename, false); if (!_GfxData) { - Print(" ERROR: Couldn't load Actor Binary \"%s\" from \"%s\"", actorName, aFilename.c_str()); + PrintError(" ERROR: Couldn't load Actor Binary \"%s\" from \"%s\"", actorName, aFilename.c_str()); free(actorName); return; } void* geoLayout = (*(_GfxData->mGeoLayouts.end() - 1))->mData; if (!geoLayout) { - Print(" ERROR: Couldn't load geo layout for \"%s\"", actorName); + PrintError(" ERROR: Couldn't load geo layout for \"%s\"", actorName); free(actorName); return; } @@ -52,7 +52,7 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) { actorGfx.mPackIndex = MOD_PACK_INDEX; actorGfx.mGraphNode = (GraphNode *) DynOS_Model_LoadGeo(&id, MODEL_POOL_SESSION, geoLayout, true); if (!actorGfx.mGraphNode) { - Print(" ERROR: Couldn't load graph node for \"%s\"", actorName); + PrintError(" ERROR: Couldn't load graph node for \"%s\"", actorName); free(actorName); return; } diff --git a/data/dynos_mgr_bhv.cpp b/data/dynos_mgr_bhv.cpp index 061c864d8..51d3b2731 100644 --- a/data/dynos_mgr_bhv.cpp +++ b/data/dynos_mgr_bhv.cpp @@ -105,7 +105,7 @@ void DynOS_Bhv_HookAllCustomBehaviors() { // Theres currently no better place but to do this here. if (smlua_hook_custom_bhv(script, scriptName) == 0) { - PrintError(" ERROR: Failed to add custom behavior '%s'!", scriptName); + PrintDataError(" ERROR: Failed to add custom behavior '%s'!", scriptName); } } } \ No newline at end of file diff --git a/data/dynos_mgr_lvl.cpp b/data/dynos_mgr_lvl.cpp index 8cd5c27e9..e7871689a 100644 --- a/data/dynos_mgr_lvl.cpp +++ b/data/dynos_mgr_lvl.cpp @@ -86,7 +86,7 @@ void DynOS_Lvl_Activate(s32 modIndex, const SysPath &aFilename, const char *aLev auto& newScriptNode = newScripts[newScripts.Count() - 1]; const void* originalScript = DynOS_Builtin_ScriptPtr_GetFromName(newScriptNode->mName.begin()); if (originalScript == NULL) { - Print("Could not find level to override: '%s'", newScriptNode->mName.begin()); + PrintError("Could not find level to override: '%s'", newScriptNode->mName.begin()); return; } @@ -155,7 +155,7 @@ void DynOS_Lvl_LoadBackground(void *aPtr) { double_break: if (foundList == NULL) { - Print("Could not find custom background"); + PrintError("Could not find custom background"); return; } diff --git a/src/pc/djui/djui.c b/src/pc/djui/djui.c index b15acda13..138844031 100644 --- a/src/pc/djui/djui.c +++ b/src/pc/djui/djui.c @@ -5,6 +5,7 @@ #include "djui_panel_pause.h" #include "djui_panel_join.h" #include "djui_panel_join_message.h" +#include "djui_console.h" #include "../debuglog.h" #include "pc/cliopts.h" #include "game/level_update.h" @@ -66,6 +67,10 @@ void djui_init(void) { djui_panel_playerlist_create(NULL); + djui_console_create(); +} + +void djui_init_late(void) { if (gCLIOpts.Network != NT_SERVER) { djui_panel_main_create(NULL); if (configLanguage[0] == '\0') { @@ -130,6 +135,7 @@ void djui_render(void) { } djui_cursor_update(); + djui_base_render(&gDjuiConsole->base); djui_interactable_update(); djui_gfx_displaylist_end(); } diff --git a/src/pc/djui/djui.h b/src/pc/djui/djui.h index 2c7f1f616..2499a8d7d 100644 --- a/src/pc/djui/djui.h +++ b/src/pc/djui/djui.h @@ -40,6 +40,7 @@ extern bool gDjuiDisabled; extern bool gDjuiRenderBehindHud; void djui_init(void); +void djui_init_late(void); void djui_connect_menu_open(void); void djui_lua_error(char* text); void djui_render(void); diff --git a/src/pc/djui/djui_base.c b/src/pc/djui/djui_base.c index f0b98fd71..d8c12aac0 100644 --- a/src/pc/djui/djui_base.c +++ b/src/pc/djui/djui_base.c @@ -414,6 +414,24 @@ void djui_base_destroy_children(struct DjuiBase* base) { base->child = NULL; } +void djui_base_destroy_one_child(struct DjuiBase* base) { + // destroy last child in our linked list + struct DjuiBaseChild* prev = NULL; + struct DjuiBaseChild* child = base->child; + while (child != NULL) { + if (!child->next) { break; } + prev = child; + child = child->next; + } + + if (child) { + child->base->parent = NULL; + djui_base_destroy(child->base); + free(child); + if (prev) { prev->next = NULL; } + } +} + void djui_base_init(struct DjuiBase* parent, struct DjuiBase* base, bool (*render)(struct DjuiBase*), void (*destroy)(struct DjuiBase*)) { memset(base, 0, sizeof(struct DjuiBase)); base->parent = parent; diff --git a/src/pc/djui/djui_base.h b/src/pc/djui/djui_base.h index 04a91fa2c..7be447c1a 100644 --- a/src/pc/djui/djui_base.h +++ b/src/pc/djui/djui_base.h @@ -70,4 +70,5 @@ void djui_base_compute_tree(struct DjuiBase* base); bool djui_base_render(struct DjuiBase* base); void djui_base_destroy(struct DjuiBase* base); void djui_base_destroy_children(struct DjuiBase* base); +void djui_base_destroy_one_child(struct DjuiBase* base); void djui_base_init(struct DjuiBase* parent, struct DjuiBase* base, bool (*render)(struct DjuiBase*), void (*destroy)(struct DjuiBase*)); diff --git a/src/pc/djui/djui_console.c b/src/pc/djui/djui_console.c new file mode 100644 index 000000000..c145892b6 --- /dev/null +++ b/src/pc/djui/djui_console.c @@ -0,0 +1,144 @@ +#include +#include +#include "djui.h" +#include "djui_console.h" + +#define MAX_CONSOLE_MESSAGES 500 + +struct DjuiConsole* gDjuiConsole = NULL; +bool gDjuiConsoleFocus = false; +char gDjuiConsoleTmpBuffer[CONSOLE_MAX_TMP_BUFFER] = ""; +u32 sDjuiConsoleMessages = 0; + +bool djui_console_render(struct DjuiBase* base) { + djui_base_set_size(base, gDjuiRoot->base.width.value, gDjuiRoot->base.height.value * 0.6f); + + djui_rect_render(base); + return true; +} + +static void djui_console_destroy(struct DjuiBase* base) { + struct DjuiConsole* console = (struct DjuiConsole*)base; + free(console); +} + +void djui_console_toggle(void) { + if (gDjuiConsole == NULL) { return; } + gDjuiConsoleFocus = !gDjuiConsoleFocus; + djui_base_set_visible(&gDjuiConsole->base, gDjuiConsoleFocus); + + if (gDjuiConsoleFocus) { + if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); } + djui_interactable_set_input_focus(&gDjuiConsole->base); + } else { + djui_interactable_set_input_focus(NULL); + } +} + +static bool djui_console_on_key_down(UNUSED struct DjuiBase* base, int scancode) { + if (gDjuiConsole == NULL) { return false; } + f32 yMax = gDjuiConsole->base.comp.height - gDjuiConsole->flow->base.height.value; + + f32* yValue = &gDjuiConsole->flow->base.y.value; + bool canScrollUp = (*yValue > yMax); + bool canScrollDown = (*yValue < 0); + f32 pageAmount = gDjuiConsole->base.comp.height * 3.0f / 4.0f; + + switch (scancode) { + case SCANCODE_UP: + if (canScrollUp) { *yValue = fmax(*yValue - 15, yMax); } + break; + case SCANCODE_DOWN: + if (canScrollDown) { *yValue = fmin(*yValue + 15, 0); } + break; + case SCANCODE_PAGE_UP: + if (canScrollUp) { *yValue = fmax(*yValue - pageAmount, yMax); } + break; + case SCANCODE_PAGE_DOWN: + if (canScrollDown) { *yValue = fmin(*yValue + pageAmount, 0); } + break; + case SCANCODE_ESCAPE: djui_console_toggle(); break; + default: break; + } + gDjuiConsole->scrolling = (*yValue != yMax); + return true; +} + +void djui_console_message_create(char* message) { + djui_base_compute_tree(&gDjuiConsole->base); + struct DjuiBase* cfBase = &gDjuiConsole->flow->base; + + f32 maxTextWidth = gDjuiConsole->base.comp.width - gDjuiConsole->base.padding.left.value - gDjuiConsole->base.padding.right.value; + + struct DjuiText* text = djui_text_create(cfBase, message); + struct DjuiBase* tBase = &text->base; + djui_base_set_alignment(tBase, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM); + djui_base_set_size_type(tBase, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(tBase, maxTextWidth, 32); + djui_base_set_color(tBase, 255, 255, 255, 255); + + // figure out chat message height + text->base.comp.width = maxTextWidth; + f32 messageHeight = djui_text_count_lines(text, 10) * (text->font->lineHeight * text->font->defaultFontScale) + 8; + djui_base_set_size(tBase, maxTextWidth, messageHeight); + + f32 heightAdjust = messageHeight + gDjuiConsole->flow->margin.value; + cfBase->height.value += heightAdjust; + + if (gDjuiConsole->scrolling) { + cfBase->y.value -= heightAdjust; + } + + sDjuiConsoleMessages++; + if (sDjuiConsoleMessages >= MAX_CONSOLE_MESSAGES) { + if (cfBase->child) { + heightAdjust = cfBase->child->base->height.value + gDjuiConsole->flow->margin.value; + cfBase->height.value -= heightAdjust; + if (gDjuiConsole->scrolling) { + cfBase->y.value += heightAdjust; + } + } + + djui_base_destroy_one_child(cfBase); + sDjuiConsoleMessages--; + } +} + +struct DjuiConsole* djui_console_create(void) { + if (gDjuiConsole != NULL) { + djui_base_destroy(&gDjuiConsole->base); + gDjuiConsole = NULL; + } + + struct DjuiConsole* console = calloc(1, sizeof(struct DjuiConsole)); + struct DjuiBase* base = &console->base; + + djui_base_init(NULL, base, djui_console_render, djui_console_destroy); + djui_base_set_size_type(base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(base, gDjuiRoot->base.width.value, gDjuiRoot->base.height.value * 0.6f); + djui_base_set_alignment(base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP); + djui_base_set_color(base, 0, 0, 0, 250); + djui_base_set_padding(base, 0, 8, 8, 8); + djui_base_set_visible(base, false); + + djui_interactable_create(base, NULL); + djui_interactable_hook_key(base, djui_console_on_key_down, NULL); + + struct DjuiFlowLayout* flow = djui_flow_layout_create(base); + struct DjuiBase* cfBase = &flow->base; + djui_base_set_alignment(cfBase, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM); + djui_base_set_location(cfBase, 0, 0); + djui_base_set_size_type(cfBase, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(cfBase, 1.0f, 0); + djui_base_set_color(cfBase, 0, 0, 0, 0); + djui_base_set_padding(cfBase, 2, 2, 2, 2); + djui_flow_layout_set_margin(flow, 2); + djui_flow_layout_set_flow_direction(flow, DJUI_FLOW_DIR_UP); + cfBase->addChildrenToHead = true; + cfBase->abandonAfterChildRenderFail = true; + console->flow = flow; + + gDjuiConsole = console; + + return console; +} diff --git a/src/pc/djui/djui_console.h b/src/pc/djui/djui_console.h new file mode 100644 index 000000000..5163830fc --- /dev/null +++ b/src/pc/djui/djui_console.h @@ -0,0 +1,17 @@ +#pragma once +#include "djui.h" + +struct DjuiConsole { + struct DjuiBase base; + struct DjuiFlowLayout* flow; + bool scrolling; +}; + +#define CONSOLE_MAX_TMP_BUFFER 256 +extern struct DjuiConsole* gDjuiConsole; +extern bool gDjuiConsoleFocus; +extern char gDjuiConsoleTmpBuffer[]; + +void djui_console_message_create(char* message); +void djui_console_toggle(void); +struct DjuiConsole* djui_console_create(void); diff --git a/src/pc/djui/djui_cursor.c b/src/pc/djui/djui_cursor.c index 096d36b5d..0438de441 100644 --- a/src/pc/djui/djui_cursor.c +++ b/src/pc/djui/djui_cursor.c @@ -23,10 +23,12 @@ void djui_cursor_set_visible(bool visible) { djui_base_set_visible(&sMouseCursor->base, visible); } - if (configWindow.fullscreen) { - wm_api->set_cursor_visible(false); - } else { - wm_api->set_cursor_visible(!visible); + if (wm_api) { + if (configWindow.fullscreen) { + wm_api->set_cursor_visible(false); + } else { + wm_api->set_cursor_visible(!visible); + } } sSavedMouseX = mouse_window_x; sSavedMouseY = mouse_window_y; diff --git a/src/pc/djui/djui_interactable.c b/src/pc/djui/djui_interactable.c index c5a05e43d..0accb576c 100644 --- a/src/pc/djui/djui_interactable.c +++ b/src/pc/djui/djui_interactable.c @@ -4,6 +4,7 @@ #include "djui_panel_pause.h" #include "djui_panel_modlist.h" #include "djui_panel_playerlist.h" +#include "djui_console.h" #include "src/pc/controller/controller_sdl.h" #include "src/pc/controller/controller_mouse.h" @@ -17,6 +18,8 @@ #define CALL_CALLBACK(x) if (base->interactable->x != NULL) { base->interactable->x(base); } #define CALL_CALLBACK_PARAM(x, y) if (base->interactable->x != NULL) { base->interactable->x(base, y); } +#define SCANCODE_F1 59 + enum PadHoldDirection { PAD_HOLD_DIR_NONE, PAD_HOLD_DIR_UP, PAD_HOLD_DIR_DOWN, PAD_HOLD_DIR_LEFT, PAD_HOLD_DIR_RIGHT }; static enum PadHoldDirection sKeyboardHoldDirection = PAD_HOLD_DIR_NONE; static u16 sKeyboardButtons = 0; @@ -32,6 +35,7 @@ bool gInteractableOverridePad = false; OSContPad gInteractablePad = { 0 }; static OSContPad sLastInteractablePad = { 0 }; static int sLastMouseButtons = 0; +static bool sControlDown = false; static void djui_interactable_update_style(struct DjuiBase* base) { if (base == NULL) { return; } @@ -180,6 +184,10 @@ void djui_interactable_set_binding(struct DjuiBase* base) { } void djui_interactable_set_input_focus(struct DjuiBase* base) { + if (gDjuiConsoleFocus && base != &gDjuiConsole->base) { + return; + } + djui_interactable_on_focus_end(gInteractableFocus); gInteractableFocus = base; djui_interactable_on_focus_begin(base); @@ -195,6 +203,12 @@ bool djui_interactable_on_key_down(int scancode) { return true; } + if (scancode == SCANCODE_CONTROL_LEFT) { + sControlDown = true; + } else if (sControlDown && scancode == SCANCODE_F1) { + djui_console_toggle(); + } + bool keyFocused = (gInteractableFocus != NULL) && (gInteractableFocus->interactable != NULL) && (gInteractableFocus->interactable->on_key_down != NULL); @@ -220,7 +234,7 @@ bool djui_interactable_on_key_down(int scancode) { if (scancode == (int)configKeyChat[i]) { pressChat = true; } } - if (pressChat) { + if (pressChat && !gDjuiConsoleFocus) { djui_chat_box_toggle(); return true; } @@ -273,6 +287,10 @@ void djui_interactable_on_key_up(int scancode) { } } + if (scancode == SCANCODE_CONTROL_LEFT) { + sControlDown = false; + } + if (keyFocused) { gInteractableFocus->interactable->on_key_up(gInteractableFocus, scancode); sKeyboardHoldDirection = PAD_HOLD_DIR_NONE; diff --git a/src/pc/djui/djui_root.c b/src/pc/djui/djui_root.c index 57bfd241c..8270d59e1 100644 --- a/src/pc/djui/djui_root.c +++ b/src/pc/djui/djui_root.c @@ -28,11 +28,8 @@ struct DjuiRoot* djui_root_create(void) { djui_base_init(NULL, base, djui_root_render, djui_root_destroy); - u32 windowWidth, windowHeight; - wm_api->get_dimensions(&windowWidth, &windowHeight); - djui_base_set_location(base, 0, 0); - djui_base_set_size(base, windowWidth, windowHeight); + djui_base_set_size(base, 1280, 720); djui_base_set_color(base, 0, 0, 0, 0); return root; diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index 38ee49116..1293c2332 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -18,9 +18,10 @@ #include "smlua_sync_table.h" #include "pc/debuglog.h" +#include "pc/djui/djui_console.h" -#define LOG_LUA(...) { if (!gSmLuaSuppressErrors) { _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error(); } } -#define LOG_LUA_LINE(...) { if (!gSmLuaSuppressErrors) { _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error(); smlua_logline(); } } +#define LOG_LUA(...) { if (!gSmLuaSuppressErrors) { _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error(), snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, __VA_ARGS__), djui_console_message_create(gDjuiConsoleTmpBuffer); } } +#define LOG_LUA_LINE(...) { if (!gSmLuaSuppressErrors) { _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error(); snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, __VA_ARGS__), djui_console_message_create(gDjuiConsoleTmpBuffer), smlua_logline(); } } #ifdef DEVELOPMENT #define LUA_STACK_CHECK_BEGIN() int __LUA_STACK_TOP = lua_gettop(gLuaState) diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c index b18eb1cfa..59bb5ce0c 100644 --- a/src/pc/lua/smlua_utils.c +++ b/src/pc/lua/smlua_utils.c @@ -752,7 +752,7 @@ void smlua_logline(void) { int level = 0; while (lua_getstack(L, level, &info)) { lua_getinfo(L, "nSl", &info); - LOG_INFO(" [%d] %s:%d -- %s [%s]", + LOG_LUA(" [%d] %s:%d -- %s [%s]", level, info.short_src, info.currentline, (info.name ? info.name : ""), info.what); ++level; diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index f08379acc..4e738a3df 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -290,6 +290,7 @@ void main_func(void) { sync_objects_init_system(); djui_unicode_init(); + djui_init(); mods_init(); // load config @@ -367,7 +368,7 @@ void main_func(void) { audio_api = &audio_null; } - djui_init(); + djui_init_late(); if (gCLIOpts.Network == NT_CLIENT) { network_set_system(NS_SOCKET);