From 802f90bf696d244aca12c4361107d1277bc27742 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 8 Apr 2025 08:16:09 +0100 Subject: [PATCH 01/18] init commit initial commit of templated ParseProperty function TypePoint and TypeRect consoleSetTypes now use the new templated function --- Engine/source/console/propertyParsing.h | 29 +++++ Engine/source/math/mathTypes.cpp | 143 ++++++++++++++++-------- 2 files changed, 128 insertions(+), 44 deletions(-) diff --git a/Engine/source/console/propertyParsing.h b/Engine/source/console/propertyParsing.h index f782df2b4..eab09118b 100644 --- a/Engine/source/console/propertyParsing.h +++ b/Engine/source/console/propertyParsing.h @@ -162,6 +162,35 @@ namespace PropertyInfo bool hex_print(String & string, const S8 & hex); bool default_print(String & result, SimObjectType * const & data); + + template + inline bool ParseProperty(char* str, T(&out)[count]) + { + + size_t index = 0; + char* tok = dStrtok(str, " \t"); + + while (tok && index < count) + { + if constexpr (std::is_same_v || std::is_same_v) + { + out[index++] = dAtoi(tok); + } + else if constexpr (std::is_same_v || std::is_same_v) + { + out[index++] = dAtof(tok); + } + else + { + AssertFatal(sizeof(T) == 0, "Unsupported type in PropertyInfo::ParseProperty"); + } + + tok = dStrtok(nullptr, " \t"); + } + + return index == count; + } + } // Default Scan/print definition diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index ef7616340..600bd7944 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -24,6 +24,7 @@ #include "console/consoleTypes.h" #include "console/console.h" #include "console/engineAPI.h" +#include "console/propertyParsing.h" #include "math/mPoint2.h" #include "math/mPoint3.h" #include "math/mMatrix.h" @@ -178,12 +179,20 @@ ConsoleGetType( TypePoint2I ) ConsoleSetType( TypePoint2I ) { - if(argc == 1) - dSscanf(argv[0], "%d %d", &((Point2I *) dptr)->x, &((Point2I *) dptr)->y); - else if(argc == 2) - *((Point2I *) dptr) = Point2I(dAtoi(argv[0]), dAtoi(argv[1])); - else - Con::printf("Point2I must be set as { x, y } or \"x y\""); + if (argc >= 1) { + S32 parsed[2]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((Point2I*)dptr) = Point2I(parsed[0], parsed[1]); + return; + } + } + + Con::printf("Point2I must be set as { x, y } or \"x y\""); } //----------------------------------------------------------------------------- @@ -203,12 +212,20 @@ ConsoleGetType( TypePoint2F ) ConsoleSetType( TypePoint2F ) { - if(argc == 1) - dSscanf(argv[0], "%g %g", &((Point2F *) dptr)->x, &((Point2F *) dptr)->y); - else if(argc == 2) - *((Point2F *) dptr) = Point2F(dAtof(argv[0]), dAtof(argv[1])); - else - Con::printf("Point2F must be set as { x, y } or \"x y\""); + if (argc >= 1) { + F32 parsed[2]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((Point2F*)dptr) = Point2F(parsed[0], parsed[1]); + return; + } + } + + Con::printf("Point2F must be set as { x, y } or \"x y\""); } //----------------------------------------------------------------------------- @@ -228,12 +245,20 @@ ConsoleGetType( TypePoint3I ) ConsoleSetType( TypePoint3I ) { - if(argc == 1) - dSscanf(argv[0], "%d %d %d", &((Point3I *) dptr)->x, &((Point3I *) dptr)->y, &((Point3I *) dptr)->z); - else if(argc == 3) - *((Point3I *) dptr) = Point3I(dAtoi(argv[0]), dAtoi(argv[1]), dAtoi(argv[2])); - else - Con::printf("Point3I must be set as { x, y, z } or \"x y z\""); + if (argc >= 1) { + S32 parsed[3]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((Point3I*)dptr) = Point3I(parsed[0], parsed[1], parsed[2]); + return; + } + } + + Con::printf("Point3I must be set as { x, y, z } or \"x y z\""); } //----------------------------------------------------------------------------- @@ -253,12 +278,20 @@ ConsoleGetType( TypePoint3F ) ConsoleSetType( TypePoint3F ) { - if(argc == 1) - dSscanf(argv[0], "%g %g %g", &((Point3F *) dptr)->x, &((Point3F *) dptr)->y, &((Point3F *) dptr)->z); - else if(argc == 3) - *((Point3F *) dptr) = Point3F(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])); - else - Con::printf("Point3F must be set as { x, y, z } or \"x y z\""); + if (argc >= 1) { + F32 parsed[3]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((Point3F*)dptr) = Point3F(parsed[0], parsed[1], parsed[2]); + return; + } + } + + Con::printf("Point3F must be set as { x, y, z } or \"x y z\""); } //----------------------------------------------------------------------------- @@ -278,12 +311,20 @@ ConsoleGetType( TypePoint4F ) ConsoleSetType( TypePoint4F ) { - if(argc == 1) - dSscanf(argv[0], "%g %g %g %g", &((Point4F *) dptr)->x, &((Point4F *) dptr)->y, &((Point4F *) dptr)->z, &((Point4F *) dptr)->w); - else if(argc == 4) - *((Point4F *) dptr) = Point4F(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2]), dAtof(argv[3])); - else - Con::printf("Point4F must be set as { x, y, z, w } or \"x y z w\""); + if (argc >= 1) { + F32 parsed[4]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((Point4F*)dptr) = Point4F(parsed[0], parsed[1], parsed[2], parsed[3]); + return; + } + } + + Con::printf("Point4F must be set as { x, y, z, w } or \"x y z w\""); } //----------------------------------------------------------------------------- @@ -304,13 +345,20 @@ ConsoleGetType( TypeRectI ) ConsoleSetType( TypeRectI ) { - if(argc == 1) - dSscanf(argv[0], "%d %d %d %d", &((RectI *) dptr)->point.x, &((RectI *) dptr)->point.y, - &((RectI *) dptr)->extent.x, &((RectI *) dptr)->extent.y); - else if(argc == 4) - *((RectI *) dptr) = RectI(dAtoi(argv[0]), dAtoi(argv[1]), dAtoi(argv[2]), dAtoi(argv[3])); - else - Con::printf("RectI must be set as { x, y, w, h } or \"x y w h\""); + if (argc >= 1) { + S32 parsed[4]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((RectI*)dptr) = RectI(parsed[0], parsed[1], parsed[2], parsed[3]); + return; + } + } + + Con::printf("RectI must be set as { x, y, w, h } or \"x y w h\""); } //----------------------------------------------------------------------------- @@ -331,13 +379,20 @@ ConsoleGetType( TypeRectF ) ConsoleSetType( TypeRectF ) { - if(argc == 1) - dSscanf(argv[0], "%g %g %g %g", &((RectF *) dptr)->point.x, &((RectF *) dptr)->point.y, - &((RectF *) dptr)->extent.x, &((RectF *) dptr)->extent.y); - else if(argc == 4) - *((RectF *) dptr) = RectF(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2]), dAtof(argv[3])); - else - Con::printf("RectF must be set as { x, y, w, h } or \"x y w h\""); + if (argc >= 1) { + F32 parsed[4]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + *((RectF*)dptr) = RectF(parsed[0], parsed[1], parsed[2], parsed[3]); + return; + } + } + + Con::printf("RectF must be set as { x, y, w, h } or \"x y w h\""); } //----------------------------------------------------------------------------- From 1cb2109d6ed8371557eedc1efe62ca171e91f7dd Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 8 Apr 2025 09:51:38 +0100 Subject: [PATCH 02/18] Update mathTypes.cpp update matrix/ang types to use the new function change all print's to warn's --- Engine/source/math/mathTypes.cpp | 202 +++++++++++++++++-------------- 1 file changed, 108 insertions(+), 94 deletions(-) diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 600bd7944..5f01c444a 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -179,7 +179,8 @@ ConsoleGetType( TypePoint2I ) ConsoleSetType( TypePoint2I ) { - if (argc >= 1) { + if (argc >= 1) + { S32 parsed[2]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -192,7 +193,7 @@ ConsoleSetType( TypePoint2I ) } } - Con::printf("Point2I must be set as { x, y } or \"x y\""); + Con::warnf("Point2I must be set as { x, y } or \"x y\""); } //----------------------------------------------------------------------------- @@ -212,7 +213,8 @@ ConsoleGetType( TypePoint2F ) ConsoleSetType( TypePoint2F ) { - if (argc >= 1) { + if (argc >= 1) + { F32 parsed[2]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -225,7 +227,7 @@ ConsoleSetType( TypePoint2F ) } } - Con::printf("Point2F must be set as { x, y } or \"x y\""); + Con::warnf("Point2F must be set as { x, y } or \"x y\""); } //----------------------------------------------------------------------------- @@ -245,7 +247,8 @@ ConsoleGetType( TypePoint3I ) ConsoleSetType( TypePoint3I ) { - if (argc >= 1) { + if (argc >= 1) + { S32 parsed[3]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -258,7 +261,7 @@ ConsoleSetType( TypePoint3I ) } } - Con::printf("Point3I must be set as { x, y, z } or \"x y z\""); + Con::warnf("Point3I must be set as { x, y, z } or \"x y z\""); } //----------------------------------------------------------------------------- @@ -278,7 +281,8 @@ ConsoleGetType( TypePoint3F ) ConsoleSetType( TypePoint3F ) { - if (argc >= 1) { + if (argc >= 1) + { F32 parsed[3]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -291,7 +295,7 @@ ConsoleSetType( TypePoint3F ) } } - Con::printf("Point3F must be set as { x, y, z } or \"x y z\""); + Con::warnf("Point3F must be set as { x, y, z } or \"x y z\""); } //----------------------------------------------------------------------------- @@ -311,7 +315,8 @@ ConsoleGetType( TypePoint4F ) ConsoleSetType( TypePoint4F ) { - if (argc >= 1) { + if (argc >= 1) + { F32 parsed[4]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -324,7 +329,7 @@ ConsoleSetType( TypePoint4F ) } } - Con::printf("Point4F must be set as { x, y, z, w } or \"x y z w\""); + Con::warnf("Point4F must be set as { x, y, z, w } or \"x y z w\""); } //----------------------------------------------------------------------------- @@ -345,7 +350,8 @@ ConsoleGetType( TypeRectI ) ConsoleSetType( TypeRectI ) { - if (argc >= 1) { + if (argc >= 1) + { S32 parsed[4]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -358,7 +364,7 @@ ConsoleSetType( TypeRectI ) } } - Con::printf("RectI must be set as { x, y, w, h } or \"x y w h\""); + Con::warnf("RectI must be set as { x, y, w, h } or \"x y w h\""); } //----------------------------------------------------------------------------- @@ -379,7 +385,8 @@ ConsoleGetType( TypeRectF ) ConsoleSetType( TypeRectF ) { - if (argc >= 1) { + if (argc >= 1) + { F32 parsed[4]; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; @@ -392,7 +399,7 @@ ConsoleSetType( TypeRectF ) } } - Con::printf("RectF must be set as { x, y, w, h } or \"x y w h\""); + Con::warnf("RectF must be set as { x, y, w, h } or \"x y w h\""); } //----------------------------------------------------------------------------- @@ -421,21 +428,24 @@ ConsoleGetType( TypeMatrixF ) ConsoleSetType( TypeMatrixF ) { - if( argc != 1 ) + if (argc == 1) { - Con::errorf( "MatrixF must be set as \"c0x c0y c0z c1x c1y c1z c2x c2y c2z\"" ); - return; - } - - Point3F col0, col1, col2; - dSscanf( argv[ 0 ], "%g %g %g %g %g %g %g %g %g", - &col0.x, &col0.y, &col0.z, &col1.x, &col1.y, &col1.z, &col2.x, &col2.y, &col2.z ); + F32 parsed[9]; - MatrixF* mat = ( MatrixF* ) dptr; - - mat->setColumn( 0, col0 ); - mat->setColumn( 1, col1 ); - mat->setColumn( 2, col2 ); + char* buffer = new char[dStrlen(argv[0])]; + dStrcpy(buffer, argv[0], sizeof(buffer)); + + if (PropertyInfo::ParseProperty(buffer, parsed)) { + MatrixF* mat = (MatrixF*)dptr; + + mat->setColumn(0, Point3F(parsed[0], parsed[1], parsed[2])); + mat->setColumn(1, Point3F(parsed[3], parsed[4], parsed[5])); + mat->setColumn(2, Point3F(parsed[6], parsed[7], parsed[8])); + return; + } + } + + Con::warnf("MatrixF must be set as \"c0x c0y c0z c1x c1y c1z c2x c2y c2z\""); } //----------------------------------------------------------------------------- @@ -457,20 +467,25 @@ ConsoleGetType( TypeMatrixPosition ) ConsoleSetType( TypeMatrixPosition ) { - F32 *col = ((F32 *) dptr) + 3; - if (argc == 1) + if (argc >= 1) { - col[0] = col[4] = col[8] = 0.f; - col[12] = 1.f; - dSscanf(argv[0], "%g %g %g %g", &col[0], &col[4], &col[8], &col[12]); + F32 parsed[4] = { 1.0f }; // default all to 1.0f + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + dStrncpy(buffer, *argv, sizeof(buffer)); + // we dont want to hard fail based on the count. + // this will allow any number of properties to be set. + PropertyInfo::ParseProperty(buffer, parsed); + { + Point4F temp(parsed[0], parsed[1], parsed[2], parsed[3]); + MatrixF* mat = (MatrixF*)dptr; + mat->setColumn(3, temp); + return; + } } - else if (argc <= 4) - { - for (S32 i = 0; i < argc; i++) - col[i << 2] = dAtof(argv[i]); - } - else - Con::printf("Matrix position must be set as { x, y, z, w } or \"x y z w\""); + + Con::warnf("Matrix position must be set as { x, y, z, w } or \"x y z w\""); + } //----------------------------------------------------------------------------- @@ -490,32 +505,29 @@ ConsoleGetType( TypeMatrixRotation ) ConsoleSetType( TypeMatrixRotation ) { - // DMM: Note that this will ONLY SET the ULeft 3x3 submatrix. - // - AngAxisF aa(Point3F(0,0,0),0); - if (argc == 1) + if (argc >= 1) { - dSscanf(argv[0], "%g %g %g %g", &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle); - aa.angle = mDegToRad(aa.angle); - } - else if (argc == 4) - { - for (S32 i = 0; i < argc; i++) - ((F32*)&aa)[i] = dAtof(argv[i]); - aa.angle = mDegToRad(aa.angle); - } - else - Con::printf("Matrix rotation must be set as { x, y, z, angle } or \"x y z angle\""); + F32 parsed[4]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + dStrncpy(buffer, *argv, sizeof(buffer)); - // - MatrixF temp; - aa.setMatrix(&temp); + if (PropertyInfo::ParseProperty(buffer, parsed)) + { + AngAxisF aa(Point3F(parsed[0], parsed[1], parsed[2]), mDegToRad(parsed[3])); + MatrixF temp; + aa.setMatrix(&temp); - F32* pDst = *(MatrixF *)dptr; - const F32* pSrc = temp; - for (U32 i = 0; i < 3; i++) - for (U32 j = 0; j < 3; j++) - pDst[i*4 + j] = pSrc[i*4 + j]; + F32* pDst = *(MatrixF*)dptr; + const F32* pSrc = temp; + for (U32 i = 0; i < 3; i++) + for (U32 j = 0; j < 3; j++) + pDst[i * 4 + j] = pSrc[i * 4 + j]; + return; + } + } + + Con::warnf("Matrix rotation must be set as { x, y, z, angle } or \"x y z angle\""); } //----------------------------------------------------------------------------- @@ -535,22 +547,22 @@ ConsoleGetType( TypeAngAxisF ) ConsoleSetType( TypeAngAxisF ) { - // DMM: Note that this will ONLY SET the ULeft 3x3 submatrix. - // - AngAxisF* aa = ( AngAxisF* ) dptr; - if (argc == 1) + if (argc >= 1) { - dSscanf(argv[0], "%g %g %g %g", &aa->axis.x, &aa->axis.y, &aa->axis.z, &aa->angle); - aa->angle = mDegToRad(aa->angle); + F32 parsed[4]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + dStrncpy(buffer, *argv, sizeof(buffer)); + + if(PropertyInfo::ParseProperty(buffer, parsed)) + { + AngAxisF* aa = (AngAxisF*)dptr; + aa->set(Point3F(parsed[0], parsed[1], parsed[2]), mDegToRad(parsed[3])); + return; + } } - else if (argc == 4) - { - for (S32 i = 0; i < argc; i++) - ((F32*)&aa)[i] = dAtof(argv[i]); - aa->angle = mDegToRad(aa->angle); - } - else - Con::printf("AngAxisF must be set as { x, y, z, angle } or \"x y z angle\""); + + Con::warnf("AngAxisF must be set as { x, y, z, angle } or \"x y z angle\""); } @@ -576,27 +588,29 @@ ConsoleGetType( TypeTransformF ) ConsoleSetType( TypeTransformF ) { - TransformF* aa = ( TransformF* ) dptr; - if( argc == 1 ) + if(argc >= 1) { - U32 count = dSscanf( argv[ 0 ], "%g %g %g %g %g %g %g", - &aa->mPosition.x, &aa->mPosition.y, &aa->mPosition.z, - &aa->mOrientation.axis.x, &aa->mOrientation.axis.y, &aa->mOrientation.axis.z, &aa->mOrientation.angle ); + F32 parsed[7]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + dStrncpy(buffer, *argv, sizeof(buffer)); - aa->mHasRotation = ( count == 7 ); + if (PropertyInfo::ParseProperty(buffer, parsed)) + { + TransformF* aa = (TransformF*)dptr; + aa->mPosition.x = parsed[0]; + aa->mPosition.y = parsed[1]; + aa->mPosition.z = parsed[2]; + aa->mOrientation.axis.x = parsed[3]; + aa->mOrientation.axis.y = parsed[4]; + aa->mOrientation.axis.z = parsed[5]; + aa->mOrientation.angle = parsed[6]; + aa->mHasRotation = true; + return; + } } - else if( argc == 7 ) - { - aa->mPosition.x = dAtof( argv[ 0 ] ); - aa->mPosition.y = dAtof( argv[ 1 ] ); - aa->mPosition.z = dAtof( argv[ 2 ] ); - aa->mOrientation.axis.x = dAtof( argv[ 3 ] ); - aa->mOrientation.axis.y = dAtof( argv[ 4 ] ); - aa->mOrientation.axis.z = dAtof( argv[ 5 ] ); - aa->mOrientation.angle = dAtof( argv[ 6 ] ); - } - else - Con::errorf( "TransformF must be set as { px, py, pz, x, y, z, angle } or \"px py pz x y z angle\""); + + Con::warnf("TransformF must be set as { px, py, pz, x, y, z, angle } or \"px py pz x y z angle\""); } From f30ff6734e589772412636cf076ea8dd1f648104 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Tue, 8 Apr 2025 10:13:48 +0100 Subject: [PATCH 03/18] Update mathTypes.cpp mathtypes.cpp ConsoleSetTypes now converted --- Engine/source/math/mathTypes.cpp | 103 ++++++++++++++++++------------- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 5f01c444a..584a011c9 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -636,19 +636,27 @@ ConsoleGetType( TypeBox3F ) ConsoleSetType( TypeBox3F ) { - Box3F* pDst = (Box3F*)dptr; + if (argc >= 1) + { + F32 parsed[6]; + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + dStrncpy(buffer, *argv, sizeof(buffer)); - if (argc == 1) - { - U32 args = dSscanf(argv[0], "%g %g %g %g %g %g", - &pDst->minExtents.x, &pDst->minExtents.y, &pDst->minExtents.z, - &pDst->maxExtents.x, &pDst->maxExtents.y, &pDst->maxExtents.z); - AssertWarn(args == 6, "Warning, box probably not read properly"); - } - else - { - Con::printf("Box3F must be set as \"xMin yMin zMin xMax yMax zMax\""); + if (PropertyInfo::ParseProperty(buffer, parsed)) + { + Box3F* pDst = (Box3F*)dptr; + pDst->minExtents.x = parsed[0]; + pDst->minExtents.y = parsed[1]; + pDst->minExtents.z = parsed[2]; + pDst->maxExtents.x = parsed[3]; + pDst->maxExtents.y = parsed[4]; + pDst->maxExtents.z = parsed[5]; + return; + } } + + Con::warnf("Box3F must be set as \"xMin yMin zMin xMax yMax zMax\""); } @@ -672,19 +680,26 @@ ConsoleGetType( TypeEaseF ) ConsoleSetType( TypeEaseF ) { - EaseF* pDst = (EaseF*)dptr; + if (argc >= 1) + { + F32 parsed[4]; + parsed[2] = -1.0f; + parsed[3] = -1.0f; - // defaults... - pDst->mParam[0] = -1.0f; - pDst->mParam[1] = -1.0f; - if (argc == 1) { - U32 args = dSscanf(argv[0], "%d %d %f %f", // the two params are optional and assumed -1 if not present... - &pDst->mDir, &pDst->mType, &pDst->mParam[0],&pDst->mParam[1]); - if( args < 2 ) - Con::warnf( "Warning, EaseF probably not read properly" ); - } else { - Con::printf("EaseF must be set as \"dir type [param0 param1]\""); + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + + dStrncpy(buffer, *argv, sizeof(buffer)); + + // same as matrix do not hard fail based on count! + PropertyInfo::ParseProperty(buffer, parsed); + { + ((EaseF*)dptr)->set(mRound(parsed[0]), mRound(parsed[1]), parsed[2], parsed[3]); + return; + } } + + Con::warnf("EaseF must be set as \"dir type [param0 param1]\""); } //----------------------------------------------------------------------------- @@ -715,34 +730,36 @@ ConsoleGetType(TypeRotationF) ConsoleSetType(TypeRotationF) { - if (argc == 1) + if (argc >= 1) { - U32 elements = StringUnit::getUnitCount(argv[0], " \t\n"); + // Combine argv into a single space-separated string if argc > 1 + char buffer[256] = { 0 }; + dStrncpy(buffer, *argv, sizeof(buffer)); + + U32 elements = StringUnit::getUnitCount(buffer, " \t\n"); if (elements == 3) { - EulerF in; - dSscanf(argv[0], "%g %g %g", &in.x, &in.y, &in.z); - ((RotationF *)dptr)->set(in, RotationF::Degrees); + F32 parsed[3]; + if(PropertyInfo::ParseProperty(buffer, parsed)) + { + EulerF in(parsed[0], parsed[1], parsed[2]); + ((RotationF*)dptr)->set(in, RotationF::Degrees); + return; + } } - else + else if (elements == 4) { - AngAxisF in; - dSscanf(argv[0], "%g %g %g %g", &in.axis.x, &in.axis.y, &in.axis.z, &in.angle); - ((RotationF *)dptr)->set(in, RotationF::Degrees); + F32 parsed[4]; + if (PropertyInfo::ParseProperty(buffer, parsed)) + { + AngAxisF in(Point3F(parsed[0], parsed[1], parsed[2]), parsed[3]); + ((RotationF*)dptr)->set(in, RotationF::Degrees); + return; + } } } - else if (argc == 3) - { - EulerF in(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])); - ((RotationF *)dptr)->set(in, RotationF::Degrees); - } - else if (argc == 4) - { - AngAxisF in(Point3F(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])), dAtof(argv[3])); - ((RotationF *)dptr)->set(in, RotationF::Degrees); - } - else - Con::printf("RotationF must be set as { x, y, z, w } or \"x y z w\""); + + Con::warnf("RotationF must be set as { x, y, z, w } or \"x y z w\""); } //----------------------------------------------------------------------------- From b886cbb527effa2631603faae3054fb5b6fea817 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 8 Apr 2025 16:09:54 -0500 Subject: [PATCH 04/18] on balance we'll want to round instead of truncate --- Engine/source/console/propertyParsing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/console/propertyParsing.h b/Engine/source/console/propertyParsing.h index eab09118b..8bffe59b8 100644 --- a/Engine/source/console/propertyParsing.h +++ b/Engine/source/console/propertyParsing.h @@ -174,7 +174,7 @@ namespace PropertyInfo { if constexpr (std::is_same_v || std::is_same_v) { - out[index++] = dAtoi(tok); + out[index++] = mRound(dAtof(tok)); } else if constexpr (std::is_same_v || std::is_same_v) { From d0d2e1f3438fd272a72bc21cd3b60115480c91d0 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 8 Apr 2025 18:30:06 -0500 Subject: [PATCH 05/18] handle relfecting the health of the controlled object players and vehicles can both be the controlobject, or you can control a vehicle *through* a player. set the health bar/text controls to reflect that state --- Engine/source/T3D/fps/guiHealthBarHud.cpp | 5 +++++ Engine/source/T3D/fps/guiHealthTextHud.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Engine/source/T3D/fps/guiHealthBarHud.cpp b/Engine/source/T3D/fps/guiHealthBarHud.cpp index 602d242b1..79b420e3a 100644 --- a/Engine/source/T3D/fps/guiHealthBarHud.cpp +++ b/Engine/source/T3D/fps/guiHealthBarHud.cpp @@ -147,6 +147,11 @@ void GuiHealthBarHud::onRender(Point2I offset, const RectI &updateRect) if (!conn) return; ShapeBase* control = dynamic_cast(conn->getControlObject()); + + //cover the case of a connection controling an object in turn controlling another + if (control && control->getControlObject()) + control = control->getControlObject(); + if (!control || !(control->getTypeMask() & (PlayerObjectType | VehicleObjectType))) return; diff --git a/Engine/source/T3D/fps/guiHealthTextHud.cpp b/Engine/source/T3D/fps/guiHealthTextHud.cpp index 1c202906c..faa798253 100644 --- a/Engine/source/T3D/fps/guiHealthTextHud.cpp +++ b/Engine/source/T3D/fps/guiHealthTextHud.cpp @@ -148,7 +148,12 @@ void GuiHealthTextHud::onRender(Point2I offset, const RectI &updateRect) GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; - ShapeBase* control = dynamic_cast(conn->getControlObject()); + ShapeBase* control = dynamic_cast(conn->getControlObject()); + + //cover the case of a connection controling an object in turn controlling another + if (control && control->getControlObject()) + control = control->getControlObject(); + if (!control || !(control->getTypeMask() & (PlayerObjectType | VehicleObjectType))) return; From 7c3fbfc9d8b34005c24315154c608acdcfbedba9 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 9 Apr 2025 15:14:46 +0100 Subject: [PATCH 06/18] add getter for console get types templated function for getting data from a field --- Engine/source/console/propertyParsing.h | 35 ++++++ Engine/source/math/mathTypes.cpp | 138 +++++++++--------------- 2 files changed, 85 insertions(+), 88 deletions(-) diff --git a/Engine/source/console/propertyParsing.h b/Engine/source/console/propertyParsing.h index 8bffe59b8..2608077c6 100644 --- a/Engine/source/console/propertyParsing.h +++ b/Engine/source/console/propertyParsing.h @@ -163,6 +163,41 @@ namespace PropertyInfo bool default_print(String & result, SimObjectType * const & data); + template + const char* FormatProperty(const void* dataPtr) + { + static const U32 bufSize = 256; + char* buffer = Con::getReturnBuffer(bufSize); + FormatProperty(dataPtr, buffer, bufSize); + return buffer; + } + + template + char* FormatProperty(const void* dataPtr, char* buffer, U32 bufSize) + { + const T* values = reinterpret_cast(dataPtr); + char* ptr = buffer; + + for (size_t i = 0; i < count; ++i) + { + S32 written = 0; + + if constexpr (std::is_same_v || std::is_same_v) + written = dSprintf(ptr, bufSize - (ptr - buffer), "%d", values[i]); + else if constexpr (std::is_same_v || std::is_same_v) + written = dSprintf(ptr, bufSize - (ptr - buffer), "%g", values[i]); + else + AssertFatal(sizeof(T) == 0, "Unsupported type in FormatProperty"); + + ptr += written; + if (i < count - 1) + *ptr++ = ' '; + } + + *ptr = '\0'; + return ptr; // return end of written string for chaining + } + template inline bool ParseProperty(char* str, T(&out)[count]) { diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 584a011c9..c9b36a0e1 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -170,11 +170,8 @@ ImplementConsoleTypeCasters( TypePoint2I, Point2I ) ConsoleGetType( TypePoint2I ) { - Point2I *pt = (Point2I *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%d %d", pt->x, pt->y); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypePoint2I ) @@ -204,11 +201,8 @@ ImplementConsoleTypeCasters( TypePoint2F, Point2F ) ConsoleGetType( TypePoint2F ) { - Point2F *pt = (Point2F *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%g %g", pt->x, pt->y); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypePoint2F ) @@ -238,11 +232,8 @@ ImplementConsoleTypeCasters(TypePoint3I, Point3I) ConsoleGetType( TypePoint3I ) { - Point3I *pt = (Point3I *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%d %d %d", pt->x, pt->y, pt->z); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypePoint3I ) @@ -272,11 +263,8 @@ ImplementConsoleTypeCasters(TypePoint3F, Point3F) ConsoleGetType( TypePoint3F ) { - Point3F *pt = (Point3F *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%g %g %g", pt->x, pt->y, pt->z); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypePoint3F ) @@ -306,11 +294,8 @@ ImplementConsoleTypeCasters( TypePoint4F, Point4F ) ConsoleGetType( TypePoint4F ) { - Point4F *pt = (Point4F *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%g %g %g %g", pt->x, pt->y, pt->z, pt->w); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypePoint4F ) @@ -340,12 +325,8 @@ ImplementConsoleTypeCasters( TypeRectI, RectI ) ConsoleGetType( TypeRectI ) { - RectI *rect = (RectI *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%d %d %d %d", rect->point.x, rect->point.y, - rect->extent.x, rect->extent.y); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypeRectI ) @@ -375,12 +356,8 @@ ImplementConsoleTypeCasters( TypeRectF, RectF ) ConsoleGetType( TypeRectF ) { - RectF *rect = (RectF *) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%g %g %g %g", rect->point.x, rect->point.y, - rect->extent.x, rect->extent.y); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypeRectF ) @@ -413,17 +390,18 @@ ImplementConsoleTypeCasters( TypeMatrixF, MatrixF ) ConsoleGetType( TypeMatrixF ) { - MatrixF* mat = ( MatrixF* ) dptr; - - Point3F col0, col1, col2; - mat->getColumn(0, &col0); - mat->getColumn(1, &col1); - mat->getColumn(2, &col2); static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer,bufSize,"%g %g %g %g %g %g %g %g %g", - col0.x, col0.y, col0.z, col1.x, col1.y, col1.z, col2.x, col2.y, col2.z); - return returnBuffer; + char* buffer = Con::getReturnBuffer(bufSize); + + F32* mat = (F32*)dptr; + buffer = PropertyInfo::FormatProperty(mat + 0, buffer, bufSize); + *buffer++ = ' '; + buffer = PropertyInfo::FormatProperty(mat + 4, buffer, bufSize); + *buffer++ = ' '; + buffer = PropertyInfo::FormatProperty(mat + 8, buffer, bufSize); + *buffer = '\0'; // null-terminate just in case + + return buffer; } ConsoleSetType( TypeMatrixF ) @@ -455,14 +433,9 @@ ConsoleMappedType(MatrixPosition, TypeMatrixPosition, Point3F, MatrixF, "") ConsoleGetType( TypeMatrixPosition ) { - F32 *col = (F32 *) dptr + 3; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - if(col[12] == 1.f) - dSprintf(returnBuffer, bufSize, "%g %g %g", col[0], col[4], col[8]); - else - dSprintf(returnBuffer, bufSize, "%g %g %g %g", col[0], col[4], col[8], col[12]); - return returnBuffer; + F32* mat = (F32*)dptr; + const char* buff = PropertyInfo::FormatProperty(mat + 8); + return buff; } ConsoleSetType( TypeMatrixPosition ) @@ -495,12 +468,11 @@ ConsoleMappedType(MatrixRotation, TypeMatrixRotation, AngAxisF, MatrixF, "") ConsoleGetType( TypeMatrixRotation ) { - AngAxisF aa(*(MatrixF *) dptr); + AngAxisF aa(*(MatrixF*)dptr); aa.axis.normalize(); - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer,bufSize,"%g %g %g %g",aa.axis.x,aa.axis.y,aa.axis.z,mRadToDeg(aa.angle)); - return returnBuffer; + aa.angle = mRadToDeg(aa.angle); + const char* buff = PropertyInfo::FormatProperty(&aa); + return buff; } ConsoleSetType( TypeMatrixRotation ) @@ -539,10 +511,9 @@ ImplementConsoleTypeCasters( TypeAngAxisF, AngAxisF ) ConsoleGetType( TypeAngAxisF ) { AngAxisF* aa = ( AngAxisF* ) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer,bufSize,"%g %g %g %g",aa->axis.x,aa->axis.y,aa->axis.z,mRadToDeg(aa->angle)); - return returnBuffer; + aa->angle = mRadToDeg(aa->angle); + const char* buff = PropertyInfo::FormatProperty(aa); + return buff; } ConsoleSetType( TypeAngAxisF ) @@ -577,13 +548,8 @@ ImplementConsoleTypeCasters( TypeTransformF, TransformF ) ConsoleGetType( TypeTransformF ) { - TransformF* aa = ( TransformF* ) dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf( returnBuffer, bufSize, "%g %g %g %g %g %g %g", - aa->mPosition.x, aa->mPosition.y, aa->mPosition.z, - aa->mOrientation.axis.x, aa->mOrientation.axis.y, aa->mOrientation.axis.z, aa->mOrientation.angle ); - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypeTransformF ) @@ -623,15 +589,8 @@ ImplementConsoleTypeCasters( TypeBox3F, Box3F ) ConsoleGetType( TypeBox3F ) { - const Box3F* pBox = (const Box3F*)dptr; - - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%g %g %g %g %g %g", - pBox->minExtents.x, pBox->minExtents.y, pBox->minExtents.z, - pBox->maxExtents.x, pBox->maxExtents.y, pBox->maxExtents.z); - - return returnBuffer; + const char* buff = PropertyInfo::FormatProperty(dptr); + return buff; } ConsoleSetType( TypeBox3F ) @@ -668,14 +627,16 @@ ImplementConsoleTypeCasters( TypeEaseF, EaseF ) ConsoleGetType( TypeEaseF ) { - const EaseF* pEase = (const EaseF*)dptr; - static const U32 bufSize = 256; - char* returnBuffer = Con::getReturnBuffer(bufSize); - dSprintf(returnBuffer, bufSize, "%d %d %g %g", - pEase->mDir, pEase->mType, pEase->mParam[0], pEase->mParam[1]); + char* buffer = Con::getReturnBuffer(bufSize); - return returnBuffer; + EaseF* pEase = (EaseF*)dptr; + buffer = PropertyInfo::FormatProperty(pEase + 0, buffer, bufSize); + *buffer++ = ' '; + buffer = PropertyInfo::FormatProperty(pEase + 2, buffer, bufSize); + *buffer = '\0'; // null-terminate just in case + + return buffer; } ConsoleSetType( TypeEaseF ) @@ -717,13 +678,14 @@ ConsoleGetType(TypeRotationF) if (pt->mRotationType == RotationF::Euler) { EulerF out = pt->asEulerF(RotationF::Degrees); - dSprintf(returnBuffer, bufSize, "%g %g %g", out.x, out.y, out.z); + returnBuffer = PropertyInfo::FormatProperty(out, returnBuffer, bufSize); } else if (pt->mRotationType == RotationF::AxisAngle) { AngAxisF out = pt->asAxisAngle(RotationF::Degrees); - dSprintf(returnBuffer, bufSize, "%g %g %g %g", out.axis.x, out.axis.y, out.axis.z, out.angle); + returnBuffer = PropertyInfo::FormatProperty(&out, returnBuffer, bufSize); } + *returnBuffer = '\0'; // null-terminate just in case return returnBuffer; } From cd7666bf2af104fb4b472060307e71a77652194c Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 9 Apr 2025 16:05:22 +0100 Subject: [PATCH 07/18] rename overloaded function so linux and mac stop bitching --- Engine/source/console/propertyParsing.h | 4 ++-- Engine/source/math/mathTypes.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Engine/source/console/propertyParsing.h b/Engine/source/console/propertyParsing.h index 2608077c6..dc446d8f1 100644 --- a/Engine/source/console/propertyParsing.h +++ b/Engine/source/console/propertyParsing.h @@ -168,12 +168,12 @@ namespace PropertyInfo { static const U32 bufSize = 256; char* buffer = Con::getReturnBuffer(bufSize); - FormatProperty(dataPtr, buffer, bufSize); + FormatPropertyBuffer(dataPtr, buffer, bufSize); return buffer; } template - char* FormatProperty(const void* dataPtr, char* buffer, U32 bufSize) + char* FormatPropertyBuffer(const void* dataPtr, char* buffer, U32 bufSize) { const T* values = reinterpret_cast(dataPtr); char* ptr = buffer; diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index c9b36a0e1..c1292ec7d 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -394,11 +394,11 @@ ConsoleGetType( TypeMatrixF ) char* buffer = Con::getReturnBuffer(bufSize); F32* mat = (F32*)dptr; - buffer = PropertyInfo::FormatProperty(mat + 0, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(mat + 0, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatProperty(mat + 4, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(mat + 4, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatProperty(mat + 8, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(mat + 8, buffer, bufSize); *buffer = '\0'; // null-terminate just in case return buffer; @@ -631,9 +631,9 @@ ConsoleGetType( TypeEaseF ) char* buffer = Con::getReturnBuffer(bufSize); EaseF* pEase = (EaseF*)dptr; - buffer = PropertyInfo::FormatProperty(pEase + 0, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(pEase + 0, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatProperty(pEase + 2, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(pEase + 2, buffer, bufSize); *buffer = '\0'; // null-terminate just in case return buffer; @@ -678,12 +678,12 @@ ConsoleGetType(TypeRotationF) if (pt->mRotationType == RotationF::Euler) { EulerF out = pt->asEulerF(RotationF::Degrees); - returnBuffer = PropertyInfo::FormatProperty(out, returnBuffer, bufSize); + returnBuffer = PropertyInfo::FormatPropertyBuffer(out, returnBuffer, bufSize); } else if (pt->mRotationType == RotationF::AxisAngle) { AngAxisF out = pt->asAxisAngle(RotationF::Degrees); - returnBuffer = PropertyInfo::FormatProperty(&out, returnBuffer, bufSize); + returnBuffer = PropertyInfo::FormatPropertyBuffer(&out, returnBuffer, bufSize); } *returnBuffer = '\0'; // null-terminate just in case From ee4acc98fee2c91bd4fc84e992bfa179bfc61f93 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Wed, 9 Apr 2025 16:29:03 +0100 Subject: [PATCH 08/18] Update propertyParsing.h bahhh humbug --- Engine/source/console/propertyParsing.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Engine/source/console/propertyParsing.h b/Engine/source/console/propertyParsing.h index dc446d8f1..62b582191 100644 --- a/Engine/source/console/propertyParsing.h +++ b/Engine/source/console/propertyParsing.h @@ -163,15 +163,6 @@ namespace PropertyInfo bool default_print(String & result, SimObjectType * const & data); - template - const char* FormatProperty(const void* dataPtr) - { - static const U32 bufSize = 256; - char* buffer = Con::getReturnBuffer(bufSize); - FormatPropertyBuffer(dataPtr, buffer, bufSize); - return buffer; - } - template char* FormatPropertyBuffer(const void* dataPtr, char* buffer, U32 bufSize) { @@ -198,6 +189,15 @@ namespace PropertyInfo return ptr; // return end of written string for chaining } + template + const char* FormatProperty(const void* dataPtr) + { + static const U32 bufSize = 256; + char* buffer = Con::getReturnBuffer(bufSize); + FormatPropertyBuffer(dataPtr, buffer, bufSize); + return buffer; + } + template inline bool ParseProperty(char* str, T(&out)[count]) { From 2e64d36382db8b0f9444659fd019c67740d47c5b Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 10 Apr 2025 08:13:10 +0100 Subject: [PATCH 09/18] Update mathTypes.cpp fix matrix types, should of been using columns not the rows --- Engine/source/math/mathTypes.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index c1292ec7d..6558786d6 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -390,15 +390,20 @@ ImplementConsoleTypeCasters( TypeMatrixF, MatrixF ) ConsoleGetType( TypeMatrixF ) { + MatrixF* mat = (MatrixF*)dptr; + + Point3F col0, col1, col2; + mat->getColumn(0, &col0); + mat->getColumn(1, &col1); + mat->getColumn(2, &col2); static const U32 bufSize = 256; char* buffer = Con::getReturnBuffer(bufSize); - F32* mat = (F32*)dptr; - buffer = PropertyInfo::FormatPropertyBuffer(mat + 0, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(col0, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatPropertyBuffer(mat + 4, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(col1, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatPropertyBuffer(mat + 8, buffer, bufSize); + buffer = PropertyInfo::FormatPropertyBuffer(col2, buffer, bufSize); *buffer = '\0'; // null-terminate just in case return buffer; @@ -433,16 +438,24 @@ ConsoleMappedType(MatrixPosition, TypeMatrixPosition, Point3F, MatrixF, "") ConsoleGetType( TypeMatrixPosition ) { - F32* mat = (F32*)dptr; - const char* buff = PropertyInfo::FormatProperty(mat + 8); - return buff; + F32* col = (F32*)dptr + 3; + static const U32 bufSize = 256; + char* returnBuffer = Con::getReturnBuffer(bufSize); + Point4F pos(col[0], col[4], col[8], col[12]); + + if (col[12] == 1.0f) + returnBuffer = PropertyInfo::FormatPropertyBuffer(&pos, returnBuffer, bufSize); + else + returnBuffer = PropertyInfo::FormatPropertyBuffer(&pos, returnBuffer, bufSize); + + return returnBuffer; } ConsoleSetType( TypeMatrixPosition ) { if (argc >= 1) { - F32 parsed[4] = { 1.0f }; // default all to 1.0f + F32 parsed[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; // Combine argv into a single space-separated string if argc > 1 char buffer[256] = { 0 }; dStrncpy(buffer, *argv, sizeof(buffer)); From fae5ebb9e817ff6f3776438f6eef3ccc7f7b58cb Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 10 Apr 2025 08:55:42 +0100 Subject: [PATCH 10/18] null termination was wiping buffer --- Engine/source/console/propertyParsing.h | 1 - Engine/source/math/mathTypes.cpp | 19 +++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Engine/source/console/propertyParsing.h b/Engine/source/console/propertyParsing.h index 62b582191..69bdc09f6 100644 --- a/Engine/source/console/propertyParsing.h +++ b/Engine/source/console/propertyParsing.h @@ -185,7 +185,6 @@ namespace PropertyInfo *ptr++ = ' '; } - *ptr = '\0'; return ptr; // return end of written string for chaining } diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 6558786d6..60779b212 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -399,12 +399,11 @@ ConsoleGetType( TypeMatrixF ) static const U32 bufSize = 256; char* buffer = Con::getReturnBuffer(bufSize); - buffer = PropertyInfo::FormatPropertyBuffer(col0, buffer, bufSize); + PropertyInfo::FormatPropertyBuffer(col0, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatPropertyBuffer(col1, buffer, bufSize); + PropertyInfo::FormatPropertyBuffer(col1, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatPropertyBuffer(col2, buffer, bufSize); - *buffer = '\0'; // null-terminate just in case + PropertyInfo::FormatPropertyBuffer(col2, buffer, bufSize); return buffer; } @@ -444,9 +443,9 @@ ConsoleGetType( TypeMatrixPosition ) Point4F pos(col[0], col[4], col[8], col[12]); if (col[12] == 1.0f) - returnBuffer = PropertyInfo::FormatPropertyBuffer(&pos, returnBuffer, bufSize); + PropertyInfo::FormatPropertyBuffer(&pos, returnBuffer, bufSize); else - returnBuffer = PropertyInfo::FormatPropertyBuffer(&pos, returnBuffer, bufSize); + PropertyInfo::FormatPropertyBuffer(&pos, returnBuffer, bufSize); return returnBuffer; } @@ -644,9 +643,9 @@ ConsoleGetType( TypeEaseF ) char* buffer = Con::getReturnBuffer(bufSize); EaseF* pEase = (EaseF*)dptr; - buffer = PropertyInfo::FormatPropertyBuffer(pEase + 0, buffer, bufSize); + PropertyInfo::FormatPropertyBuffer(pEase + 0, buffer, bufSize); *buffer++ = ' '; - buffer = PropertyInfo::FormatPropertyBuffer(pEase + 2, buffer, bufSize); + PropertyInfo::FormatPropertyBuffer(pEase + 2, buffer, bufSize); *buffer = '\0'; // null-terminate just in case return buffer; @@ -691,12 +690,12 @@ ConsoleGetType(TypeRotationF) if (pt->mRotationType == RotationF::Euler) { EulerF out = pt->asEulerF(RotationF::Degrees); - returnBuffer = PropertyInfo::FormatPropertyBuffer(out, returnBuffer, bufSize); + PropertyInfo::FormatPropertyBuffer(out, returnBuffer, bufSize); } else if (pt->mRotationType == RotationF::AxisAngle) { AngAxisF out = pt->asAxisAngle(RotationF::Degrees); - returnBuffer = PropertyInfo::FormatPropertyBuffer(&out, returnBuffer, bufSize); + PropertyInfo::FormatPropertyBuffer(&out, returnBuffer, bufSize); } *returnBuffer = '\0'; // null-terminate just in case From 77a7847eed26d3086009722ea2fa6e1a17a16c69 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 10 Apr 2025 08:56:20 +0100 Subject: [PATCH 11/18] Update mathTypes.cpp --- Engine/source/math/mathTypes.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 60779b212..ff6a3e6dd 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -646,7 +646,6 @@ ConsoleGetType( TypeEaseF ) PropertyInfo::FormatPropertyBuffer(pEase + 0, buffer, bufSize); *buffer++ = ' '; PropertyInfo::FormatPropertyBuffer(pEase + 2, buffer, bufSize); - *buffer = '\0'; // null-terminate just in case return buffer; } From 0ff636e9ca438454474a261b202925e3d7e43a9f Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Thu, 10 Apr 2025 08:56:40 +0100 Subject: [PATCH 12/18] Update mathTypes.cpp --- Engine/source/math/mathTypes.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index ff6a3e6dd..18526267c 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -696,7 +696,6 @@ ConsoleGetType(TypeRotationF) AngAxisF out = pt->asAxisAngle(RotationF::Degrees); PropertyInfo::FormatPropertyBuffer(&out, returnBuffer, bufSize); } - *returnBuffer = '\0'; // null-terminate just in case return returnBuffer; } From 5b2c0c77039ff62ac19a25fc03d18d643ec62952 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Sun, 13 Apr 2025 14:51:30 -0500 Subject: [PATCH 13/18] add a controlmap entry for players, vehicles, and turret datablocks add a client command to setMovemap(%object.getDatablock().controlMap) --- Engine/source/T3D/player.cpp | 5 ++++- Engine/source/T3D/player.h | 2 +- Engine/source/T3D/turret/turretShape.cpp | 3 +++ Engine/source/T3D/turret/turretShape.h | 1 + Engine/source/T3D/vehicles/vehicle.cpp | 6 ++++++ Engine/source/T3D/vehicles/vehicle.h | 1 + .../scripts/client/connectionToServer.tscript | 13 +++++++++++++ .../scripts/server/connectionToClient.tscript | 4 +++- 8 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 801df58df..2e2b9fc34 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -460,6 +460,7 @@ PlayerData::PlayerData() jumpTowardsNormal = true; physicsPlayerType = StringTable->EmptyString(); + mControlMap = StringTable->EmptyString(); dMemset( actionList, 0, sizeof(actionList) ); } @@ -739,7 +740,9 @@ void PlayerData::initPersistFields() endGroup( "Camera" ); addGroup( "Movement" ); - + addField("controlMap", TypeString, Offset(mControlMap, PlayerData), + "@brief movemap used by these types of objects.\n\n"); + addFieldV( "maxStepHeight", TypeRangedF32, Offset(maxStepHeight, PlayerData), &CommonValidators::PositiveFloat, "@brief Maximum height the player can step up.\n\n" "The player will automatically step onto changes in ground height less " diff --git a/Engine/source/T3D/player.h b/Engine/source/T3D/player.h index b80b3f0e5..4c1c27fbe 100644 --- a/Engine/source/T3D/player.h +++ b/Engine/source/T3D/player.h @@ -346,7 +346,7 @@ struct PlayerData: public ShapeBaseData { // Jump off surfaces at their normal rather than straight up bool jumpTowardsNormal; - + StringTableEntry mControlMap; // For use if/when mPhysicsPlayer is created StringTableEntry physicsPlayerType; diff --git a/Engine/source/T3D/turret/turretShape.cpp b/Engine/source/T3D/turret/turretShape.cpp index 8c523588e..5594ce3c0 100644 --- a/Engine/source/T3D/turret/turretShape.cpp +++ b/Engine/source/T3D/turret/turretShape.cpp @@ -127,6 +127,7 @@ TurretShapeData::TurretShapeData() recoilSequence[i] = -1; pitchSequence = -1; headingSequence = -1; + mControlMap = StringTable->EmptyString(); } void TurretShapeData::initPersistFields() @@ -134,6 +135,8 @@ void TurretShapeData::initPersistFields() docsURL; Parent::initPersistFields(); addGroup("Steering"); + addField("controlMap", TypeString, Offset(mControlMap, TurretShapeData), + "@brief movemap used by these types of objects.\n\n"); addField("zRotOnly", TypeBool, Offset(zRotOnly, TurretShapeData), "@brief Should the turret allow only z rotations.\n\n" "True indicates that the turret may only be rotated on its z axis, just like the Item class. " diff --git a/Engine/source/T3D/turret/turretShape.h b/Engine/source/T3D/turret/turretShape.h index b31024e07..a086d79d7 100644 --- a/Engine/source/T3D/turret/turretShape.h +++ b/Engine/source/T3D/turret/turretShape.h @@ -80,6 +80,7 @@ public: bool startLoaded; ///< Should the turret's mounted weapon(s) start in a loaded state? bool zRotOnly; ///< Should the turret allow only z rotations (like an item)? + StringTableEntry mControlMap; public: TurretShapeData(); diff --git a/Engine/source/T3D/vehicles/vehicle.cpp b/Engine/source/T3D/vehicles/vehicle.cpp index cfbd9a876..aa191be29 100644 --- a/Engine/source/T3D/vehicles/vehicle.cpp +++ b/Engine/source/T3D/vehicles/vehicle.cpp @@ -141,6 +141,7 @@ VehicleData::VehicleData() dMemset( damageEmitterOffset, 0, sizeof( damageEmitterOffset ) ); dMemset( damageEmitterIDList, 0, sizeof( damageEmitterIDList ) ); dMemset( damageLevelTolerance, 0, sizeof( damageLevelTolerance ) ); + mControlMap = StringTable->EmptyString(); numDmgEmitterAreas = 0; @@ -321,6 +322,8 @@ void VehicleData::initPersistFields() endGroup("Collision"); addGroup("Steering"); + addField("controlMap", TypeString, Offset(mControlMap, VehicleData), + "@brief movemap used by these types of objects.\n\n"); addFieldV( "jetForce", TypeRangedF32, Offset(jetForce, VehicleData), &CommonValidators::PositiveFloat, "@brief Additional force applied to the vehicle when it is jetting.\n\n" "For WheeledVehicles, the force is applied in the forward direction. For " @@ -726,6 +729,9 @@ void Vehicle::updateMove(const Move* move) if (mDamageState == Enabled) { setImageTriggerState(0,move->trigger[0]); setImageTriggerState(1,move->trigger[1]); + //legacy code has trigger 2 and 3 reserved + setImageTriggerState(2, move->trigger[4]); + setImageTriggerState(3, move->trigger[5]); } // Throttle diff --git a/Engine/source/T3D/vehicles/vehicle.h b/Engine/source/T3D/vehicles/vehicle.h index 402a3109a..746e99a16 100644 --- a/Engine/source/T3D/vehicles/vehicle.h +++ b/Engine/source/T3D/vehicles/vehicle.h @@ -69,6 +69,7 @@ struct VehicleData : public RigidShapeData F32 damageLevelTolerance[ VC_NUM_DAMAGE_LEVELS ]; F32 numDmgEmitterAreas; + StringTableEntry mControlMap; bool enablePhysicsRep; // diff --git a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript index cbd4b46cc..82d00105c 100644 --- a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript +++ b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript @@ -158,3 +158,16 @@ function disconnectedCleanup() moduleExec("onDestroyClientConnection", "Game"); } + +function clientCmdsetMoveMap(%movemap) +{ + if (!isObject(%movemap)) return; + if(isObject(ServerConnection) && isObject(ServerConnection.curMoveMap)) + ServerConnection.curMoveMap.pop(); + + // clear movement + $mvForwardAction = 0; + $mvBackwardAction = 0; + %movemap.push(); + ServerConnection.curMoveMap = %movemap; +} \ No newline at end of file diff --git a/Templates/BaseGame/game/core/clientServer/scripts/server/connectionToClient.tscript b/Templates/BaseGame/game/core/clientServer/scripts/server/connectionToClient.tscript index b804ac046..0e2a11e28 100644 --- a/Templates/BaseGame/game/core/clientServer/scripts/server/connectionToClient.tscript +++ b/Templates/BaseGame/game/core/clientServer/scripts/server/connectionToClient.tscript @@ -275,7 +275,9 @@ function GameConnection::onPostSpawn( %this ) if (%this.numModsNeedingLoaded) callOnObjectList("onPostSpawn", %modulesIdList, %this); else - %this.listener.onPostSpawnComplete(%this); + %this.listener.onPostSpawnComplete(%this); + if (isObject(%this.player.getDatablock().controlMap)) + commandToClient(%this, 'setMoveMap', %this.player.getDatablock().controlMap); } function GameConnectionListener::onPostSpawnComplete(%this, %client) From f0c0f3c42c3862b2e2250d18b19e00d78eccd95b Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Wed, 16 Apr 2025 13:08:39 -0500 Subject: [PATCH 14/18] projectile augs use impactforce to applyimpulse for stock physics too add an optional explodeOnTmeout for nonballistic projectiles, track if they hit something before their armingdelay is up, and delete them next simulation cycle --- Engine/source/T3D/projectile.cpp | 37 ++++++++++++++++++++++++++------ Engine/source/T3D/projectile.h | 4 ++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Engine/source/T3D/projectile.cpp b/Engine/source/T3D/projectile.cpp index 56f8af638..58c6f3aa6 100644 --- a/Engine/source/T3D/projectile.cpp +++ b/Engine/source/T3D/projectile.cpp @@ -56,6 +56,7 @@ #include "T3D/decal/decalData.h" #include "T3D/lightDescription.h" #include "console/engineAPI.h" +#include "T3D/rigidShape.h" IMPLEMENT_CO_DATABLOCK_V1(ProjectileData); @@ -163,6 +164,7 @@ ProjectileData::ProjectileData() scale.set( 1.0f, 1.0f, 1.0f ); isBallistic = false; + mExplodeOnTmeout = false; velInheritFactor = 1.0f; muzzleVelocity = 50; @@ -203,6 +205,7 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G muzzleVelocity = other.muzzleVelocity; impactForce = other.impactForce; isBallistic = other.isBallistic; + mExplodeOnTmeout = other.mExplodeOnTmeout; bounceElasticity = other.bounceElasticity; bounceFriction = other.bounceFriction; gravityMod = other.gravityMod; @@ -285,6 +288,8 @@ void ProjectileData::initPersistFields() addProtectedFieldV("fadeDelay", TypeRangedS32, Offset(fadeDelay, ProjectileData), &setFadeDelay, &getScaledValue, &CommonValidators::NaturalNumber, "@brief Amount of time, in milliseconds, before the projectile begins to fade out.\n\n" "This value must be smaller than the projectile's lifetime to have an affect."); + addField("explodeOnTmeout", TypeBool, Offset(mExplodeOnTmeout, ProjectileData), + "@brief Detetmines if the projectile should explode on timeout"); addField("isBallistic", TypeBool, Offset(isBallistic, ProjectileData), "@brief Detetmines if the projectile should be affected by gravity and whether or not " "it bounces before exploding.\n\n"); @@ -455,13 +460,14 @@ void ProjectileData::packData(BitStream* stream) stream->write(armingDelay); stream->write(fadeDelay); + stream->writeFlag(mExplodeOnTmeout); if(stream->writeFlag(isBallistic)) { stream->write(gravityMod); stream->write(bounceElasticity); stream->write(bounceFriction); } - + } void ProjectileData::unpackData(BitStream* stream) @@ -514,6 +520,7 @@ void ProjectileData::unpackData(BitStream* stream) stream->read(&armingDelay); stream->read(&fadeDelay); + mExplodeOnTmeout = stream->readFlag(); isBallistic = stream->readFlag(); if(isBallistic) { @@ -611,6 +618,7 @@ Projectile::Projectile() mProjectileShape( NULL ), mActivateThread( NULL ), mMaintainThread( NULL ), + mHasHit(false), mHasExploded( false ), mFadeValue( 1.0f ) { @@ -1128,10 +1136,18 @@ void Projectile::processTick( const Move *move ) void Projectile::simulate( F32 dt ) { - if ( isServerObject() && mCurrTick >= mDataBlock->lifetime ) + if ( isServerObject() ) { - deleteObject(); - return; + if (mCurrTick >= (mDataBlock->lifetime - TickMs)) + { + if (mDataBlock->mExplodeOnTmeout) + explode(mCurrPosition, Point3F::UnitZ, VehicleObjectType); + } + if (mCurrTick >= mDataBlock->lifetime || (mHasHit && mCurrTick < mDataBlock->armingDelay)) + { + deleteObject(); + return; + } } if ( mHasExploded ) @@ -1167,9 +1183,16 @@ void Projectile::simulate( F32 dt ) if ( mPhysicsWorld ) hit = mPhysicsWorld->castRay( oldPosition, newPosition, &rInfo, Point3F( newPosition - oldPosition) * mDataBlock->impactForce ); - else + else + { hit = getContainer()->castRay(oldPosition, newPosition, dynamicCollisionMask | staticCollisionMask, &rInfo); - + if (hit && rInfo.object->getTypeMask() & VehicleObjectType) + { + RigidShape* aRigid = dynamic_cast(rInfo.object); + if (aRigid) + aRigid->applyImpulse(rInfo.point, Point3F(newPosition - oldPosition) * mDataBlock->impactForce); + } + } if ( hit ) { // make sure the client knows to bounce @@ -1237,6 +1260,8 @@ void Projectile::simulate( F32 dt ) else { mCurrVelocity = Point3F::Zero; + newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f; + mHasHit = true; } } diff --git a/Engine/source/T3D/projectile.h b/Engine/source/T3D/projectile.h index 671c3f98f..04e91aa60 100644 --- a/Engine/source/T3D/projectile.h +++ b/Engine/source/T3D/projectile.h @@ -87,9 +87,9 @@ public: /// Force imparted on a hit object. F32 impactForce; + bool mExplodeOnTmeout; /// Should it arc? bool isBallistic; - /// How HIGH should it bounce (parallel to normal), [0,1] F32 bounceElasticity; /// How much momentum should be lost when it bounces (perpendicular to normal), [0,1] @@ -274,7 +274,7 @@ protected: LightInfo *mLight; LightState mLightState; - + bool mHasHit; bool mHasExploded; ///< Prevent rendering, lighting, and duplicate explosions. F32 mFadeValue; ///< set in processTick, interpolation between fadeDelay and lifetime ///< in data block From 7b7de1f10fdb0b3d9052202c875008b790b4e51d Mon Sep 17 00:00:00 2001 From: JeffR Date: Tue, 22 Apr 2025 18:20:12 -0500 Subject: [PATCH 15/18] Adjusts the handling of the disconnect call to not utilize package overrides, but instead a callOnModules invoke like most other cross-module calls. This allows the editor to issue a disconnect call properly again. --- .../scripts/client/connectionToServer.tscript | 6 ++- Templates/BaseGame/game/tools/tools.tscript | 9 +++++ .../worldEditor/scripts/editor.ed.tscript | 37 ------------------- 3 files changed, 14 insertions(+), 38 deletions(-) diff --git a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript index cbd4b46cc..94f30857f 100644 --- a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript +++ b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript @@ -111,8 +111,12 @@ function handleConnectionErrorMessage(%msgType, %msgString, %msgError) //----------------------------------------------------------------------------- // Disconnect //----------------------------------------------------------------------------- - function disconnect() +{ + callOnModules("disconnect"); +} + +function Core_ClientServer::disconnect(%this) { // We need to stop the client side simulation // else physics resources will not cleanup properly. diff --git a/Templates/BaseGame/game/tools/tools.tscript b/Templates/BaseGame/game/tools/tools.tscript index 47101f55a..04ce56cad 100644 --- a/Templates/BaseGame/game/tools/tools.tscript +++ b/Templates/BaseGame/game/tools/tools.tscript @@ -23,4 +23,13 @@ function ToolsModule::onCreate(%this) function ToolsModule::onDestroy(%this) { +} + +function ToolsModule::disconnect(%this) +{ + if ( isObject( Editor ) && Editor.isEditorEnabled() ) + { + EditorGui.saveAs = false; //whatever edits we were doing are irrelevent now + Editor.close(MainMenuGui); + } } \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript index ff5696dd5..9f0bc5b77 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript @@ -164,40 +164,3 @@ function toggleEditor(%make) //------------------------------------------------------------------------------ // The editor action maps are defined in editor.bind.tscript GlobalActionMap.bind(keyboard, "f11", fastLoadWorldEdit); - - -// The scenario: -// The editor is open and the user closes the level by any way other than -// the file menu ( exit level ), eg. typing disconnect() in the console. -// -// The problem: -// Editor::close() is not called in this scenario which means onEditorDisable -// is not called on objects which hook into it and also gEditingMission will no -// longer be valid. -// -// The solution: -// Override the stock disconnect() function which is in game scripts from here -// in tools so we avoid putting our code in there. -// -// Disclaimer: -// If you think of a better way to do this feel free. The thing which could -// be dangerous about this is that no one will ever realize this code overriding -// a fairly standard and core game script from a somewhat random location. -// If it 'did' have unforscene sideeffects who would ever find it? - -package EditorDisconnectOverride -{ - function disconnect() - { - if ( isObject( Editor ) && Editor.isEditorEnabled() ) - { - EditorGui.saveAs = false; //whatever edits we were doing are irrelevent now - %mainMenuGUI = ProjectSettings.value("UI/mainMenuName"); - if (isObject( %mainMenuGUI )) - Editor.close( %mainMenuGUI ); - } - - Parent::disconnect(); - } -}; -activatePackage( EditorDisconnectOverride ); From f31acf774ed5a614c3a4f625b4d3e0c3a9931495 Mon Sep 17 00:00:00 2001 From: JeffR Date: Thu, 24 Apr 2025 00:58:20 -0500 Subject: [PATCH 16/18] Adds handling for datablocks to be reloaded if the assets they utilize have their files directly edited. --- Engine/source/T3D/assets/ShapeAsset.h | 8 +++++- Engine/source/T3D/debris.h | 5 +++- Engine/source/T3D/fx/explosion.h | 5 +++- Engine/source/T3D/fx/groundCover.h | 4 ++- Engine/source/T3D/fx/particle.h | 5 +++- Engine/source/T3D/fx/precipitation.h | 10 +++++-- Engine/source/T3D/fx/splash.h | 5 +++- Engine/source/T3D/lightFlareData.h | 5 +++- Engine/source/T3D/physics/physicsDebris.h | 5 +++- Engine/source/T3D/physics/physicsShape.h | 5 +++- Engine/source/T3D/player.h | 7 ++++- Engine/source/T3D/projectile.h | 5 +++- Engine/source/T3D/shapeBase.cpp | 12 ++++++++- Engine/source/T3D/shapeBase.h | 11 +++++--- Engine/source/T3D/vehicles/wheeledVehicle.h | 5 +++- Engine/source/afx/afxMagicMissile.h | 5 +++- Engine/source/afx/ce/afxBillboard.h | 5 +++- Engine/source/afx/ce/afxModel.h | 5 +++- Engine/source/afx/ce/afxZodiac.h | 5 +++- Engine/source/afx/ce/afxZodiacPlane.h | 5 +++- Engine/source/console/simDatablock.cpp | 29 ++++++++++++--------- Engine/source/console/simDatablock.h | 2 ++ Engine/source/forest/forestItem.h | 5 +++- 23 files changed, 121 insertions(+), 37 deletions(-) diff --git a/Engine/source/T3D/assets/ShapeAsset.h b/Engine/source/T3D/assets/ShapeAsset.h index afa39ca57..2d186346d 100644 --- a/Engine/source/T3D/assets/ShapeAsset.h +++ b/Engine/source/T3D/assets/ShapeAsset.h @@ -370,7 +370,7 @@ public: \ #pragma region Arrayed Asset Macros -#define DECLARE_SHAPEASSET_ARRAY(className,name,max) public: \ +#define DECLARE_SHAPEASSET_ARRAY(className,name,max,changeFunc) public: \ static const U32 sm##name##Count = max;\ Resourcem##name[max];\ StringTableEntry m##name##Name[max]; \ @@ -384,6 +384,10 @@ public: \ \ bool _set##name(StringTableEntry _in, const U32& index)\ {\ + if (m##name##Asset[index].notNull())\ + {\ + m##name##Asset[index]->getChangedSignal().remove(this, &className::changeFunc);\ + }\ if(m##name##AssetId[index] != _in || m##name##Name[index] != _in)\ {\ if(index >= sm##name##Count || index < 0)\ @@ -430,6 +434,8 @@ public: \ if (get##name(index) != StringTable->EmptyString() && m##name##Asset[index].notNull())\ {\ m##name[index] = m##name##Asset[index]->getShapeResource();\ + \ + m##name##Asset[index]->getChangedSignal().notify(this, &className::changeFunc);\ }\ else\ {\ diff --git a/Engine/source/T3D/debris.h b/Engine/source/T3D/debris.h index a0ff99520..1d1116031 100644 --- a/Engine/source/T3D/debris.h +++ b/Engine/source/T3D/debris.h @@ -111,7 +111,10 @@ public: void onPerformSubstitutions() override; bool allowSubstitutions() const override { return true; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; //************************************************************************** diff --git a/Engine/source/T3D/fx/explosion.h b/Engine/source/T3D/fx/explosion.h index 447b7747d..0ea4c63d7 100644 --- a/Engine/source/T3D/fx/explosion.h +++ b/Engine/source/T3D/fx/explosion.h @@ -143,7 +143,10 @@ public: ExplosionData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0); bool allowSubstitutions() const override { return true; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/T3D/fx/groundCover.h b/Engine/source/T3D/fx/groundCover.h index b2ef23e05..dcc159096 100644 --- a/Engine/source/T3D/fx/groundCover.h +++ b/Engine/source/T3D/fx/groundCover.h @@ -341,7 +341,7 @@ protected: RectF mBillboardRects[MAX_COVERTYPES]; /// The cover shape filenames. - DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES); + DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES, onShapeChanged); DECLARE_ASSET_ARRAY_NET_SETGET(GroundCover, Shape, -1); /// The cover shape instances. @@ -409,6 +409,8 @@ protected: S32 randSeed ); void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); + + void onShapeChanged(){} }; #endif // _GROUNDCOVER_H_ diff --git a/Engine/source/T3D/fx/particle.h b/Engine/source/T3D/fx/particle.h index 12e6a242a..0f328801a 100644 --- a/Engine/source/T3D/fx/particle.h +++ b/Engine/source/T3D/fx/particle.h @@ -92,7 +92,10 @@ class ParticleData : public SimDataBlock static bool protectedSetSizes(void* object, const char* index, const char* data); static bool protectedSetTimes(void* object, const char* index, const char* data); - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } public: ParticleData(); diff --git a/Engine/source/T3D/fx/precipitation.h b/Engine/source/T3D/fx/precipitation.h index 25aad8e60..a3ca97c40 100644 --- a/Engine/source/T3D/fx/precipitation.h +++ b/Engine/source/T3D/fx/precipitation.h @@ -69,8 +69,14 @@ class PrecipitationData : public GameBaseData void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; - void onDropChanged() {} - void onSplashChanged() {} + void onDropChanged() + { + reloadOnLocalClient(); + } + void onSplashChanged() + { + reloadOnLocalClient(); + } }; struct Raindrop diff --git a/Engine/source/T3D/fx/splash.h b/Engine/source/T3D/fx/splash.h index de98a5bca..0a055ee2f 100644 --- a/Engine/source/T3D/fx/splash.h +++ b/Engine/source/T3D/fx/splash.h @@ -124,7 +124,10 @@ public: DECLARE_IMAGEASSET_ARRAY(SplashData, Texture, NUM_TEX, onTextureChanged); DECLARE_IMAGEASSET_ARRAY_SETGET(SplashData, Texture) - void onTextureChanged() {} + void onTextureChanged() + { + reloadOnLocalClient(); + } ExplosionData* explosion; S32 explosionId; diff --git a/Engine/source/T3D/lightFlareData.h b/Engine/source/T3D/lightFlareData.h index 5239bf3c1..baa74c39b 100644 --- a/Engine/source/T3D/lightFlareData.h +++ b/Engine/source/T3D/lightFlareData.h @@ -106,7 +106,10 @@ protected: void _makePrimBuffer( GFXPrimitiveBufferHandle *pb, U32 count ); void _renderCorona( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } protected: diff --git a/Engine/source/T3D/physics/physicsDebris.h b/Engine/source/T3D/physics/physicsDebris.h index 2626300e9..9b9ae6861 100644 --- a/Engine/source/T3D/physics/physicsDebris.h +++ b/Engine/source/T3D/physics/physicsDebris.h @@ -97,7 +97,10 @@ public: void packData( BitStream *stream ) override; void unpackData( BitStream *stream ) override; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } DECLARE_CONOBJECT( PhysicsDebrisData ); diff --git a/Engine/source/T3D/physics/physicsShape.h b/Engine/source/T3D/physics/physicsShape.h index 144580c31..466e39ebf 100644 --- a/Engine/source/T3D/physics/physicsShape.h +++ b/Engine/source/T3D/physics/physicsShape.h @@ -135,7 +135,10 @@ public: SimObjectRef< ExplosionData > explosion; SimObjectRef< PhysicsShapeData > destroyedShape; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; typedef PhysicsShapeData::SimType PhysicsSimType; diff --git a/Engine/source/T3D/player.h b/Engine/source/T3D/player.h index b80b3f0e5..ab242d862 100644 --- a/Engine/source/T3D/player.h +++ b/Engine/source/T3D/player.h @@ -76,7 +76,7 @@ struct PlayerData: public ShapeBaseData { /// that we don't create a TSThread on the player if we don't /// need to. - DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages); ///< Used to render with mounted images in first person [optional] + DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages, onShapeChanged); ///< Used to render with mounted images in first person [optional] DECLARE_ASSET_ARRAY_SETGET(PlayerData, ShapeFP); StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify @@ -366,6 +366,11 @@ struct PlayerData: public ShapeBaseData { void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; + void onShapeChanged() + { + reloadOnLocalClient(); + } + /// @name Callbacks /// @{ DECLARE_CALLBACK( void, onPoseChange, ( Player* obj, const char* oldPose, const char* newPose ) ); diff --git a/Engine/source/T3D/projectile.h b/Engine/source/T3D/projectile.h index 04e91aa60..2ca827ea7 100644 --- a/Engine/source/T3D/projectile.h +++ b/Engine/source/T3D/projectile.h @@ -154,7 +154,10 @@ public: ProjectileData(const ProjectileData&, bool = false); bool allowSubstitutions() const override { return true; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 968e8fb9b..e164c8394 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -345,7 +345,7 @@ bool ShapeBaseData::preload(bool server, String &errorStr) S32 i; U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); - if (assetStatus == AssetBase::Ok|| assetStatus == AssetBase::UsingFallback) + if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback) { if (!server && !mShape->preloadMaterialList(mShape.getPath()) && NetConnection::filesWereDownloaded()) shapeError = true; @@ -904,7 +904,17 @@ void ShapeBaseData::unpackData(BitStream* stream) silent_bbox_check = stream->readFlag(); } +// +// +void ShapeBaseData::onShapeChanged() +{ + reloadOnLocalClient(); +} +void ShapeBaseData::onDebrisChanged() +{ + reloadOnLocalClient(); +} //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index 706f54b72..131992fa9 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -378,7 +378,7 @@ struct ShapeBaseImageData: public GameBaseData { F32 scriptAnimTransitionTime; ///< The amount of time to transition between the previous sequence and new sequence ///< when the script prefix has changed. - DECLARE_SHAPEASSET_ARRAY(ShapeBaseImageData, Shape, MaxShapes); ///< Name of shape to render. + DECLARE_SHAPEASSET_ARRAY(ShapeBaseImageData, Shape, MaxShapes, onShapeChanged); ///< Name of shape to render. DECLARE_ASSET_ARRAY_SETGET(ShapeBaseImageData, Shape); //DECLARE_SHAPEASSET(ShapeBaseImageData, ShapeFP); ///< Name of shape to render in first person (optional). @@ -505,6 +505,11 @@ struct ShapeBaseImageData: public GameBaseData { void handleStateSoundTrack(const U32& stateId); + void onShapeChanged() + { + reloadOnLocalClient(); + } + /// @} /// @name Callbacks @@ -681,8 +686,8 @@ public: Vector txr_tag_remappings; bool silent_bbox_check; - void onShapeChanged() {} - void onDebrisChanged() {} + void onShapeChanged(); + void onDebrisChanged(); public: ShapeBaseData(const ShapeBaseData&, bool = false); }; diff --git a/Engine/source/T3D/vehicles/wheeledVehicle.h b/Engine/source/T3D/vehicles/wheeledVehicle.h index 45161db12..f208fbf5b 100644 --- a/Engine/source/T3D/vehicles/wheeledVehicle.h +++ b/Engine/source/T3D/vehicles/wheeledVehicle.h @@ -74,7 +74,10 @@ struct WheeledVehicleTire: public SimDataBlock void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/afx/afxMagicMissile.h b/Engine/source/afx/afxMagicMissile.h index e3f6ee755..8aa8f8084 100644 --- a/Engine/source/afx/afxMagicMissile.h +++ b/Engine/source/afx/afxMagicMissile.h @@ -66,7 +66,10 @@ protected: public: enum { MaxLifetimeTicks = 4095 }; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } public: // variables set in datablock definition: diff --git a/Engine/source/afx/ce/afxBillboard.h b/Engine/source/afx/ce/afxBillboard.h index 8918e2f26..81542f716 100644 --- a/Engine/source/afx/ce/afxBillboard.h +++ b/Engine/source/afx/ce/afxBillboard.h @@ -71,7 +71,10 @@ public: static void initPersistFields(); - void onChangeTexture() {} + void onChangeTexture() + { + reloadOnLocalClient(); + } DECLARE_CONOBJECT(afxBillboardData); }; diff --git a/Engine/source/afx/ce/afxModel.h b/Engine/source/afx/ce/afxModel.h index 521409735..de2656b8f 100644 --- a/Engine/source/afx/ce/afxModel.h +++ b/Engine/source/afx/ce/afxModel.h @@ -94,7 +94,10 @@ public: static void initPersistFields(); - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } void onSequenceChanged() {} DECLARE_CONOBJECT(afxModelData); diff --git a/Engine/source/afx/ce/afxZodiac.h b/Engine/source/afx/ce/afxZodiac.h index a7d14c2f1..16f4a8d79 100644 --- a/Engine/source/afx/ce/afxZodiac.h +++ b/Engine/source/afx/ce/afxZodiac.h @@ -56,7 +56,10 @@ public: static void convertGradientRangeFromDegrees(Point2F& gradrange, const Point2F& gradrange_deg); - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } public: DECLARE_IMAGEASSET(afxZodiacData, Texture, onImageChanged, AFX_GFXZodiacTextureProfile); diff --git a/Engine/source/afx/ce/afxZodiacPlane.h b/Engine/source/afx/ce/afxZodiacPlane.h index 13c9879b5..a32a14d26 100644 --- a/Engine/source/afx/ce/afxZodiacPlane.h +++ b/Engine/source/afx/ce/afxZodiacPlane.h @@ -56,7 +56,10 @@ public: FACES_BITS = 3 }; - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } public: DECLARE_IMAGEASSET(afxZodiacPlaneData, Texture, onImageChanged, AFX_GFXZodiacTextureProfile); diff --git a/Engine/source/console/simDatablock.cpp b/Engine/source/console/simDatablock.cpp index d3969a069..fc5070224 100644 --- a/Engine/source/console/simDatablock.cpp +++ b/Engine/source/console/simDatablock.cpp @@ -425,39 +425,42 @@ void SimDataBlock::write(Stream &stream, U32 tabStop, U32 flags) // MARK: ---- API ---- //----------------------------------------------------------------------------- - -DefineEngineMethod( SimDataBlock, reloadOnLocalClient, void, (),, - "Reload the datablock. This can only be used with a local client configuration." ) +void SimDataBlock::reloadOnLocalClient() { // Make sure we're running a local client. GameConnection* localClient = GameConnection::getLocalClientConnection(); - if( !localClient ) + if (!localClient) return; // Do an in-place pack/unpack/preload. - if( !object->preload( true, NetConnection::getErrorBuffer() ) ) + if (!preload(true, NetConnection::getErrorBuffer())) { - Con::errorf( NetConnection::getErrorBuffer() ); + Con::errorf(NetConnection::getErrorBuffer()); return; } - U8 buffer[ 16384 ]; - BitStream stream( buffer, 16384 ); + U8 buffer[16384]; + BitStream stream(buffer, 16384); - object->packData( &stream ); + packData(&stream); stream.setPosition(0); - object->unpackData( &stream ); + unpackData(&stream); - if( !object->preload( false, NetConnection::getErrorBuffer() ) ) + if (!preload(false, NetConnection::getErrorBuffer())) { - Con::errorf( NetConnection::getErrorBuffer() ); + Con::errorf(NetConnection::getErrorBuffer()); return; } // Trigger a post-apply so that change notifications respond. - object->inspectPostApply(); + inspectPostApply(); +} +DefineEngineMethod( SimDataBlock, reloadOnLocalClient, void, (),, + "Reload the datablock. This can only be used with a local client configuration." ) +{ + object->reloadOnLocalClient(); } //----------------------------------------------------------------------------- diff --git a/Engine/source/console/simDatablock.h b/Engine/source/console/simDatablock.h index 1b61822d7..2f5c8efcc 100644 --- a/Engine/source/console/simDatablock.h +++ b/Engine/source/console/simDatablock.h @@ -176,6 +176,8 @@ public: /// Used by the console system to automatically tell datablock classes apart /// from non-datablock classes. static const bool __smIsDatablock = true; + + void reloadOnLocalClient(); protected: struct SubstitutionStatement { diff --git a/Engine/source/forest/forestItem.h b/Engine/source/forest/forestItem.h index 42bf56a5f..64e6eb611 100644 --- a/Engine/source/forest/forestItem.h +++ b/Engine/source/forest/forestItem.h @@ -143,7 +143,10 @@ public: return theSignal; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; typedef Vector ForestItemDataVector; From 24db0305f64c491da382d375e558af9c49c97160 Mon Sep 17 00:00:00 2001 From: JeffR Date: Thu, 24 Apr 2025 13:24:26 -0500 Subject: [PATCH 17/18] Modified callback to ensure that when a shapeAsset changes, groundCovers properly re-initialize to reflect the change --- Engine/source/T3D/fx/groundCover.cpp | 5 ++++- Engine/source/T3D/fx/groundCover.h | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/fx/groundCover.cpp b/Engine/source/T3D/fx/groundCover.cpp index 377f8bb63..072ef6463 100644 --- a/Engine/source/T3D/fx/groundCover.cpp +++ b/Engine/source/T3D/fx/groundCover.cpp @@ -852,8 +852,11 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream ) // It's sloppy, but it works for now. _freeCells(); - if ( isProperlyAdded() ) + if (isProperlyAdded()) + { _initMaterial(); + _initShapes(); + } } } diff --git a/Engine/source/T3D/fx/groundCover.h b/Engine/source/T3D/fx/groundCover.h index dcc159096..af5d02858 100644 --- a/Engine/source/T3D/fx/groundCover.h +++ b/Engine/source/T3D/fx/groundCover.h @@ -410,7 +410,11 @@ protected: void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - void onShapeChanged(){} + void onShapeChanged() + { + _initShapes(); + setMaskBits(U32(-1)); + } }; #endif // _GROUNDCOVER_H_ From 2ae10c7ce13aa58127a513c4c429f5e4d56f39f8 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Sun, 27 Apr 2025 19:49:13 -0500 Subject: [PATCH 18/18] add reload status to onNewDataBlock callback and skip calling onremove/onadd if we're not reloading --- Engine/source/T3D/camera.cpp | 2 +- Engine/source/T3D/debris.cpp | 2 +- Engine/source/T3D/fx/explosion.cpp | 2 +- Engine/source/T3D/fx/lightning.cpp | 2 +- Engine/source/T3D/fx/particleEmitter.cpp | 2 +- Engine/source/T3D/fx/particleEmitterNode.cpp | 2 +- Engine/source/T3D/fx/precipitation.cpp | 2 +- Engine/source/T3D/fx/ribbonNode.cpp | 2 +- Engine/source/T3D/fx/splash.cpp | 2 +- Engine/source/T3D/gameBase/gameBase.cpp | 6 +++--- Engine/source/T3D/gameBase/gameBase.h | 4 ++-- Engine/source/T3D/item.cpp | 2 +- Engine/source/T3D/missionMarker.cpp | 2 +- Engine/source/T3D/pathCamera.cpp | 2 +- Engine/source/T3D/pathShape.cpp | 2 +- Engine/source/T3D/player.cpp | 2 +- Engine/source/T3D/proximityMine.cpp | 2 +- Engine/source/T3D/rigidShape.cpp | 2 +- Engine/source/T3D/staticShape.cpp | 2 +- Engine/source/T3D/trigger.cpp | 2 +- Engine/source/T3D/turret/aiTurretShape.cpp | 2 +- Engine/source/T3D/turret/turretShape.cpp | 2 +- Engine/source/T3D/vehicles/flyingVehicle.cpp | 2 +- Engine/source/T3D/vehicles/hoverVehicle.cpp | 2 +- Engine/source/T3D/vehicles/wheeledVehicle.cpp | 2 +- Engine/source/afx/afxSpellBook.cpp | 2 +- Engine/source/afx/ce/afxParticleEmitter.cpp | 8 ++++---- .../core/utility/scripts/gameObjectManagement.tscript | 6 ++---- 28 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Engine/source/T3D/camera.cpp b/Engine/source/T3D/camera.cpp index 41056f833..3e2408583 100644 --- a/Engine/source/T3D/camera.cpp +++ b/Engine/source/T3D/camera.cpp @@ -345,7 +345,7 @@ bool Camera::onNewDataBlock( GameBaseData *dptr, bool reload ) if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/debris.cpp b/Engine/source/T3D/debris.cpp index 7c05e3ec5..78a1e53cc 100644 --- a/Engine/source/T3D/debris.cpp +++ b/Engine/source/T3D/debris.cpp @@ -601,7 +601,7 @@ bool Debris::onNewDataBlock( GameBaseData *dptr, bool reload ) if (mDataBlock->isTempClone()) return true; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/explosion.cpp b/Engine/source/T3D/fx/explosion.cpp index f10543198..02676be26 100644 --- a/Engine/source/T3D/fx/explosion.cpp +++ b/Engine/source/T3D/fx/explosion.cpp @@ -1127,7 +1127,7 @@ bool Explosion::onNewDataBlock( GameBaseData *dptr, bool reload ) if (mDataBlock->isTempClone()) return true; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/lightning.cpp b/Engine/source/T3D/fx/lightning.cpp index 10447fa6f..44c94b1a8 100644 --- a/Engine/source/T3D/fx/lightning.cpp +++ b/Engine/source/T3D/fx/lightning.cpp @@ -474,7 +474,7 @@ bool Lightning::onNewDataBlock( GameBaseData *dptr, bool reload ) if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index c9887f619..00470eb8a 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/Engine/source/T3D/fx/particleEmitter.cpp @@ -1131,7 +1131,7 @@ bool ParticleEmitter::onNewDataBlock( GameBaseData *dptr, bool reload ) return true; } - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/particleEmitterNode.cpp b/Engine/source/T3D/fx/particleEmitterNode.cpp index 26e8a71b4..5197872a2 100644 --- a/Engine/source/T3D/fx/particleEmitterNode.cpp +++ b/Engine/source/T3D/fx/particleEmitterNode.cpp @@ -254,7 +254,7 @@ bool ParticleEmitterNode::onNewDataBlock( GameBaseData *dptr, bool reload ) return false; // Todo: Uncomment if this is a "leaf" class - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/precipitation.cpp b/Engine/source/T3D/fx/precipitation.cpp index 805e87e43..b56893ea1 100644 --- a/Engine/source/T3D/fx/precipitation.cpp +++ b/Engine/source/T3D/fx/precipitation.cpp @@ -614,7 +614,7 @@ bool Precipitation::onNewDataBlock( GameBaseData *dptr, bool reload ) initMaterials(); } - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/ribbonNode.cpp b/Engine/source/T3D/fx/ribbonNode.cpp index adc846017..fb8af2db6 100644 --- a/Engine/source/T3D/fx/ribbonNode.cpp +++ b/Engine/source/T3D/fx/ribbonNode.cpp @@ -159,7 +159,7 @@ bool RibbonNode::onNewDataBlock( GameBaseData *dptr, bool reload ) return false; // Todo: Uncomment if this is a "leaf" class - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/fx/splash.cpp b/Engine/source/T3D/fx/splash.cpp index 68bbee0c3..77edaae76 100644 --- a/Engine/source/T3D/fx/splash.cpp +++ b/Engine/source/T3D/fx/splash.cpp @@ -451,7 +451,7 @@ bool Splash::onNewDataBlock( GameBaseData *dptr, bool reload ) if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/gameBase/gameBase.cpp b/Engine/source/T3D/gameBase/gameBase.cpp index 8775f94b3..f16dafc06 100644 --- a/Engine/source/T3D/gameBase/gameBase.cpp +++ b/Engine/source/T3D/gameBase/gameBase.cpp @@ -95,7 +95,7 @@ IMPLEMENT_CALLBACK( GameBaseData, onAdd, void, ( GameBase* obj ), ( obj ), "}\n\n" "@endtsexample\n" ); -IMPLEMENT_CALLBACK( GameBaseData, onNewDataBlock, void, ( GameBase* obj ), ( obj ), +IMPLEMENT_CALLBACK( GameBaseData, onNewDataBlock, void, ( GameBase* obj, bool reload), ( obj, reload), "@brief Called when the object has a new datablock assigned.\n\n" "@param obj the GameBase object\n\n" "@see onAdd for an example\n" ); @@ -512,12 +512,12 @@ void GameBase::scriptOnAdd() mDataBlock->onAdd_callback( this ); } -void GameBase::scriptOnNewDataBlock() +void GameBase::scriptOnNewDataBlock(bool reload) { // Script onNewDataBlock() must be called by the leaf class // after everything is loaded. if (mDataBlock && !isGhost()) - mDataBlock->onNewDataBlock_callback( this ); + mDataBlock->onNewDataBlock_callback( this, reload); } void GameBase::scriptOnRemove() diff --git a/Engine/source/T3D/gameBase/gameBase.h b/Engine/source/T3D/gameBase/gameBase.h index 7c175f71e..c18b30196 100644 --- a/Engine/source/T3D/gameBase/gameBase.h +++ b/Engine/source/T3D/gameBase/gameBase.h @@ -115,7 +115,7 @@ public: /// @{ DECLARE_CALLBACK( void, onAdd, ( GameBase* obj ) ); DECLARE_CALLBACK( void, onRemove, ( GameBase* obj ) ); - DECLARE_CALLBACK( void, onNewDataBlock, ( GameBase* obj ) ); + DECLARE_CALLBACK( void, onNewDataBlock, ( GameBase* obj, bool reload) ); DECLARE_CALLBACK( void, onMount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) ); DECLARE_CALLBACK( void, onUnmount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) ); /// @} @@ -299,7 +299,7 @@ public: /// Executes the 'onNewDataBlock' script function for this object. /// /// @note This must be called after everything is loaded. - void scriptOnNewDataBlock(); + void scriptOnNewDataBlock(bool reload = false); /// Executes the 'onRemove' script function for this object. /// @note This must be called while the object is still valid diff --git a/Engine/source/T3D/item.cpp b/Engine/source/T3D/item.cpp index 6c5395452..3681774da 100644 --- a/Engine/source/T3D/item.cpp +++ b/Engine/source/T3D/item.cpp @@ -422,7 +422,7 @@ bool Item::onNewDataBlock( GameBaseData *dptr, bool reload ) return false; if (!mSubclassItemHandlesScene) - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); if ( isProperlyAdded() ) _updatePhysics(); diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index 5fac601ce..a18523ef7 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -142,7 +142,7 @@ bool MissionMarker::onNewDataBlock( GameBaseData *dptr, bool reload ) mDataBlock = dynamic_cast( dptr ); if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) return(false); - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return(true); } diff --git a/Engine/source/T3D/pathCamera.cpp b/Engine/source/T3D/pathCamera.cpp index 3a4ccd578..bb14db972 100644 --- a/Engine/source/T3D/pathCamera.cpp +++ b/Engine/source/T3D/pathCamera.cpp @@ -181,7 +181,7 @@ bool PathCamera::onNewDataBlock( GameBaseData *dptr, bool reload ) if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/pathShape.cpp b/Engine/source/T3D/pathShape.cpp index 846e7bf18..1a903e555 100644 --- a/Engine/source/T3D/pathShape.cpp +++ b/Engine/source/T3D/pathShape.cpp @@ -134,7 +134,7 @@ bool PathShape::onNewDataBlock(GameBaseData* dptr, bool reload) if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 801df58df..bd008d516 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -1923,7 +1923,7 @@ bool Player::onNewDataBlock( GameBaseData *dptr, bool reload ) onScaleChanged(); resetWorldBox(); - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/proximityMine.cpp b/Engine/source/T3D/proximityMine.cpp index 8ce924ea1..fd02fc091 100644 --- a/Engine/source/T3D/proximityMine.cpp +++ b/Engine/source/T3D/proximityMine.cpp @@ -350,7 +350,7 @@ bool ProximityMine::onNewDataBlock( GameBaseData* dptr, bool reload ) if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/rigidShape.cpp b/Engine/source/T3D/rigidShape.cpp index e216e7473..8a453b065 100644 --- a/Engine/source/T3D/rigidShape.cpp +++ b/Engine/source/T3D/rigidShape.cpp @@ -906,7 +906,7 @@ bool RigidShape::onNewDataBlock(GameBaseData* dptr, bool reload) else mRigid.setObjectInertia(mObjBox.maxExtents - mObjBox.minExtents); - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/staticShape.cpp b/Engine/source/T3D/staticShape.cpp index de47194f5..66e9ec454 100644 --- a/Engine/source/T3D/staticShape.cpp +++ b/Engine/source/T3D/staticShape.cpp @@ -219,7 +219,7 @@ bool StaticShape::onNewDataBlock(GameBaseData* dptr, bool reload) if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/trigger.cpp b/Engine/source/T3D/trigger.cpp index dcccd0778..9df293ba5 100644 --- a/Engine/source/T3D/trigger.cpp +++ b/Engine/source/T3D/trigger.cpp @@ -465,7 +465,7 @@ bool Trigger::onNewDataBlock( GameBaseData *dptr, bool reload ) if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/turret/aiTurretShape.cpp b/Engine/source/T3D/turret/aiTurretShape.cpp index 0e5ce0248..5ad3df020 100644 --- a/Engine/source/T3D/turret/aiTurretShape.cpp +++ b/Engine/source/T3D/turret/aiTurretShape.cpp @@ -545,7 +545,7 @@ bool AITurretShape::onNewDataBlock(GameBaseData* dptr, bool reload) mShapeInstance->setTimeScale(mStateAnimThread,0); } - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/turret/turretShape.cpp b/Engine/source/T3D/turret/turretShape.cpp index 8c523588e..b23445294 100644 --- a/Engine/source/T3D/turret/turretShape.cpp +++ b/Engine/source/T3D/turret/turretShape.cpp @@ -440,7 +440,7 @@ bool TurretShape::onNewDataBlock(GameBaseData* dptr, bool reload) if (!mSubclassTurretShapeHandlesScene) { - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); } return true; diff --git a/Engine/source/T3D/vehicles/flyingVehicle.cpp b/Engine/source/T3D/vehicles/flyingVehicle.cpp index efe611b9a..24cf33490 100644 --- a/Engine/source/T3D/vehicles/flyingVehicle.cpp +++ b/Engine/source/T3D/vehicles/flyingVehicle.cpp @@ -407,7 +407,7 @@ bool FlyingVehicle::onNewDataBlock(GameBaseData* dptr, bool reload) mJetThread[i] = 0; } - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/vehicles/hoverVehicle.cpp b/Engine/source/T3D/vehicles/hoverVehicle.cpp index 7e7f748a5..482364bd3 100644 --- a/Engine/source/T3D/vehicles/hoverVehicle.cpp +++ b/Engine/source/T3D/vehicles/hoverVehicle.cpp @@ -549,7 +549,7 @@ bool HoverVehicle::onNewDataBlock(GameBaseData* dptr, bool reload) } // Todo: Uncomment if this is a "leaf" class - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/T3D/vehicles/wheeledVehicle.cpp b/Engine/source/T3D/vehicles/wheeledVehicle.cpp index 88d7f67ce..9f3febd13 100644 --- a/Engine/source/T3D/vehicles/wheeledVehicle.cpp +++ b/Engine/source/T3D/vehicles/wheeledVehicle.cpp @@ -711,7 +711,7 @@ bool WheeledVehicle::onNewDataBlock(GameBaseData* dptr, bool reload) mJetSound = SFX->createSource( mDataBlock->getWheeledVehicleSoundsProfile(WheeledVehicleData::JetSound), &getTransform() ); } - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/afx/afxSpellBook.cpp b/Engine/source/afx/afxSpellBook.cpp index 35d207c57..d902d36ad 100644 --- a/Engine/source/afx/afxSpellBook.cpp +++ b/Engine/source/afx/afxSpellBook.cpp @@ -206,7 +206,7 @@ bool afxSpellBook::onNewDataBlock(GameBaseData* dptr, bool reload) if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) return false; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Engine/source/afx/ce/afxParticleEmitter.cpp b/Engine/source/afx/ce/afxParticleEmitter.cpp index cadf0d3ed..a3bb9e448 100644 --- a/Engine/source/afx/ce/afxParticleEmitter.cpp +++ b/Engine/source/afx/ce/afxParticleEmitter.cpp @@ -1064,7 +1064,7 @@ bool afxParticleEmitter::onNewDataBlock(GameBaseData* dptr, bool reload) if (mDataBlock->isTempClone()) return true; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } @@ -1108,7 +1108,7 @@ bool afxParticleEmitterVector::onNewDataBlock(GameBaseData* dptr, bool reload) if (mDataBlock->isTempClone()) return true; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } @@ -1177,7 +1177,7 @@ bool afxParticleEmitterCone::onNewDataBlock(GameBaseData* dptr, bool reload) if (mDataBlock->isTempClone()) return true; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } @@ -1294,7 +1294,7 @@ bool afxParticleEmitterPath::onNewDataBlock(GameBaseData* dptr, bool reload) if (mDataBlock->isTempClone()) return true; - scriptOnNewDataBlock(); + scriptOnNewDataBlock(reload); return true; } diff --git a/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.tscript b/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.tscript index 64b75e331..51a4566fa 100644 --- a/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.tscript +++ b/Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.tscript @@ -78,17 +78,15 @@ function spawnGameObject(%name, %addToScene) return 0; } -function GameBaseData::onNewDataBlock(%this, %obj) +function GameBaseData::onNewDataBlock(%this, %obj, %reload) { - if (%obj.firstDataCheck) + if (%reload) { if(%this.isMethod("onRemove")) %this.onRemove(%obj); if(%this.isMethod("onAdd")) %this.onAdd(%obj); } - else - %obj.firstDataCheck = true; } function saveGameObject(%name, %tamlPath, %scriptPath)