From bf9692a451bcaebb00a3e993be9a32bb36627e84 Mon Sep 17 00:00:00 2001 From: JeffR Date: Sun, 15 Dec 2024 23:48:16 -0600 Subject: [PATCH] Updates DecalRoad, MeshRoad and River to be able to write out via persistManager using specialityField functions, similar to ConvexShape Fixes behavior with gamemode selection in ChooseLevelMenu so if there is only one gamemode, it is auto-selected and advances to the level selection Update ExampleLevel in ExampleModule to have updated gamemodes field name --- Engine/source/T3D/convexShape.cpp | 2 + Engine/source/environment/decalRoad.cpp | 32 ++++++- Engine/source/environment/decalRoad.h | 3 + Engine/source/environment/meshRoad.cpp | 58 +++++++++++- Engine/source/environment/meshRoad.h | 3 + Engine/source/environment/river.cpp | 35 ++++++- Engine/source/environment/river.h | 3 + .../ExampleModule/levels/ExampleLevel.mis | 2 +- .../game/data/UI/guis/ChooseLevelMenu.gui | 4 +- .../game/data/UI/guis/ChooseLevelMenu.tscript | 92 ++++++++++++------- 10 files changed, 192 insertions(+), 42 deletions(-) diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index 0021ff37a..f5c773293 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -545,6 +545,8 @@ const char* ConvexShape::getSpecialFieldOut(StringTableEntry fieldName, const U3 return StringTable->insert(buffer); } + + return NULL; } void ConvexShape::onScaleChanged() diff --git a/Engine/source/environment/decalRoad.cpp b/Engine/source/environment/decalRoad.cpp index b5ba0c8d4..97003e80e 100644 --- a/Engine/source/environment/decalRoad.cpp +++ b/Engine/source/environment/decalRoad.cpp @@ -322,7 +322,7 @@ void DecalRoad::initPersistFields() addGroup( "Internal" ); addProtectedField( "node", TypeString, 0, &addNodeFromField, &emptyStringProtectedGetFn, - "Do not modify, for internal use." ); + "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors | AbstractClassRep::FIELD_SpecialtyArrayField); endGroup( "Internal" ); @@ -473,6 +473,36 @@ bool DecalRoad::writeField( StringTableEntry fieldname, const char *value ) return Parent::writeField( fieldname, value ); } +U32 DecalRoad::getSpecialFieldSize(StringTableEntry fieldName) +{ + if (fieldName == StringTable->insert("node")) + { + return mNodes.size(); + } + + return 0; +} + +const char* DecalRoad::getSpecialFieldOut(StringTableEntry fieldName, const U32& index) +{ + if (fieldName == StringTable->insert("node")) + { + if (index >= mNodes.size()) + return NULL; + + const RoadNode& node = mNodes[index]; + + char buffer[1024]; + dMemset(buffer, 0, 1024); + dSprintf(buffer, 1024, "%f %f %f %f", node.point.x, node.point.y, node.point.z, node.width); + + return StringTable->insert(buffer); + } + + return NULL; +} + + void DecalRoad::onEditorEnable() { } diff --git a/Engine/source/environment/decalRoad.h b/Engine/source/environment/decalRoad.h index f1aecf187..481e5b92a 100644 --- a/Engine/source/environment/decalRoad.h +++ b/Engine/source/environment/decalRoad.h @@ -169,6 +169,9 @@ public: void onStaticModified(const char* slotName, const char*newValue = NULL) override; void writeFields(Stream &stream, U32 tabStop) override; bool writeField( StringTableEntry fieldname, const char *value ) override; + + U32 getSpecialFieldSize(StringTableEntry fieldName) override; + const char* getSpecialFieldOut(StringTableEntry fieldName, const U32& index) override; // NetObject U32 packUpdate(NetConnection *, U32, BitStream *) override; diff --git a/Engine/source/environment/meshRoad.cpp b/Engine/source/environment/meshRoad.cpp index 93593df7a..6785db065 100644 --- a/Engine/source/environment/meshRoad.cpp +++ b/Engine/source/environment/meshRoad.cpp @@ -956,10 +956,10 @@ void MeshRoad::initPersistFields() addGroup( "Internal" ); addProtectedField( "Node", TypeString, 0, &addNodeFromField, &emptyStringProtectedGetFn, - "Do not modify, for internal use." ); + "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors | AbstractClassRep::FIELD_SpecialtyArrayField); addProtectedField( "ProfileNode", TypeString, 0, &addProfileNodeFromField, &emptyStringProtectedGetFn, - "Do not modify, for internal use." ); + "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors | AbstractClassRep::FIELD_SpecialtyArrayField); endGroup( "Internal" ); @@ -1168,6 +1168,60 @@ bool MeshRoad::writeField( StringTableEntry fieldname, const char *value ) return Parent::writeField( fieldname, value ); } +U32 MeshRoad::getSpecialFieldSize(StringTableEntry fieldName) +{ + if (fieldName == StringTable->insert("Node")) + { + return mNodes.size(); + } + else if (fieldName == StringTable->insert("ProfileNode")) + { + return mSideProfile.mNodes.size(); + } + + return 0; +} + +const char* MeshRoad::getSpecialFieldOut(StringTableEntry fieldName, const U32& index) +{ + if (fieldName == StringTable->insert("Node")) + { + if (index >= mNodes.size()) + return NULL; + + const MeshRoadNode& node = mNodes[index]; + + char buffer[1024]; + dMemset(buffer, 0, 1024); + dSprintf(buffer, 1024, "Node = \"%g %g %g %g %g %g %g %g\";", node.point.x, node.point.y, node.point.z, node.width, node.depth, node.normal.x, node.normal.y, node.normal.z); + + return StringTable->insert(buffer); + } + else if (fieldName == StringTable->insert("ProfileNode")) + { + Point3F nodePos = mSideProfile.mNodes[index].getPosition(); + U8 smooth, mtrl; + + if (index) + mtrl = mSideProfile.mSegMtrls[index - 1]; + else + mtrl = 0; + + if (mSideProfile.mNodes[index].isSmooth()) + smooth = 1; + else + smooth = 0; + + char buffer[1024]; + dMemset(buffer, 0, 1024); + dSprintf(buffer, 1024, "ProfileNode = \"%.6f %.6f %d %d\";", nodePos.x, nodePos.y, smooth, mtrl); + + return StringTable->insert(buffer); + } + + return NULL; +} + void MeshRoad::onEditorEnable() { } diff --git a/Engine/source/environment/meshRoad.h b/Engine/source/environment/meshRoad.h index 17747e83b..437d76a6d 100644 --- a/Engine/source/environment/meshRoad.h +++ b/Engine/source/environment/meshRoad.h @@ -525,6 +525,9 @@ public: void writeFields(Stream &stream, U32 tabStop) override; bool writeField( StringTableEntry fieldname, const char *value ) override; + U32 getSpecialFieldSize(StringTableEntry fieldName) override; + const char* getSpecialFieldOut(StringTableEntry fieldName, const U32& index) override; + // NetObject U32 packUpdate(NetConnection *, U32, BitStream *) override; void unpackUpdate(NetConnection *, BitStream *) override; diff --git a/Engine/source/environment/river.cpp b/Engine/source/environment/river.cpp index 725f4a350..98088f737 100644 --- a/Engine/source/environment/river.cpp +++ b/Engine/source/environment/river.cpp @@ -648,7 +648,8 @@ void River::initPersistFields() addGroup( "Internal" ); - addProtectedField( "Node", TypeString, 0, &addNodeFromField, &emptyStringProtectedGetFn, "For internal use, do not modify." ); + addProtectedField( "Node", TypeString, 0, &addNodeFromField, &emptyStringProtectedGetFn, "For internal use, do not modify.", + AbstractClassRep::FIELD_HideInInspectors | AbstractClassRep::FIELD_SpecialtyArrayField); endGroup( "Internal" ); @@ -785,6 +786,38 @@ bool River::writeField( StringTableEntry fieldname, const char *value ) return Parent::writeField( fieldname, value ); } +U32 River::getSpecialFieldSize(StringTableEntry fieldName) +{ + if (fieldName == StringTable->insert("node")) + { + return mNodes.size(); + } + + return 0; +} + +const char* River::getSpecialFieldOut(StringTableEntry fieldName, const U32& index) +{ + if (fieldName == StringTable->insert("node")) + { + if (index >= mNodes.size()) + return NULL; + + const RiverNode& node = mNodes[index]; + + char buffer[1024]; + dMemset(buffer, 0, 1024); + dSprintf(buffer, 1024, "Node = \"%f %f %f %f %f %f %f %f\";", node.point.x, node.point.y, node.point.z, + node.width, + node.depth, + node.normal.x, node.normal.y, node.normal.z); + + return StringTable->insert(buffer); + } + + return NULL; +} + void River::innerRender( SceneRenderState *state ) { GFXDEBUGEVENT_SCOPE( River_innerRender, ColorI( 255, 0, 0 ) ); diff --git a/Engine/source/environment/river.h b/Engine/source/environment/river.h index ded0e7e37..5676b7505 100644 --- a/Engine/source/environment/river.h +++ b/Engine/source/environment/river.h @@ -394,6 +394,9 @@ public: void writeFields(Stream &stream, U32 tabStop) override; bool writeField( StringTableEntry fieldname, const char *value ) override; + U32 getSpecialFieldSize(StringTableEntry fieldName) override; + const char* getSpecialFieldOut(StringTableEntry fieldName, const U32& index) override; + // NetObject U32 packUpdate(NetConnection *, U32, BitStream *) override; void unpackUpdate(NetConnection *, BitStream *) override; diff --git a/Templates/BaseGame/game/data/ExampleModule/levels/ExampleLevel.mis b/Templates/BaseGame/game/data/ExampleModule/levels/ExampleLevel.mis index 1a27a6576..40bffd526 100644 --- a/Templates/BaseGame/game/data/ExampleModule/levels/ExampleLevel.mis +++ b/Templates/BaseGame/game/data/ExampleModule/levels/ExampleLevel.mis @@ -1,7 +1,7 @@ //--- OBJECT WRITE BEGIN --- new Scene(ExampleLevel) { Enabled = "1"; - gameModeName="ExampleGameMode"; + gameModes="ExampleGameMode"; new LevelInfo(theLevelInfo) { fogColor = "0.6 0.6 0.7 1"; diff --git a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui index 8fb0928e2..a1fcf3a46 100644 --- a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui +++ b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui @@ -185,7 +185,7 @@ $guiContent = new GuiControl(ChooseLevelMenu) { }; }; new GuiBitmapCtrl(LevelPreviewBitmap) { - BitmapAsset = "UI:no_preview_image"; + BitmapAsset = ""; position = "448 0"; extent = "440 440"; horizSizing = "left"; @@ -193,7 +193,7 @@ $guiContent = new GuiControl(ChooseLevelMenu) { tooltipProfile = "GuiToolTipProfile"; }; new GuiTextCtrl(LevelNameText) { - text = "Example Level"; + text = ""; position = "448 445"; extent = "440 20"; horizSizing = "left"; diff --git a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript index f25ddff52..ff9599e64 100644 --- a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript +++ b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript @@ -54,7 +54,29 @@ function ChooseLevelMenu::onWake(%this) ChooseLevelMenuTabList.visible = true;//$pref::HostMultiPlayer; ChooseLevelMenuNavButtonOverlay.visible = true;//$pref::HostMultiPlayer; - %this.schedule(32, openMenu, 0); + //If we've only got one gamemode, just force it to use that one, as we can + //assume that is THE game's gamemode + %gamemodeList = getGameModesList(); + if(%gamemodeList.count() == 1) + { + %gameModeObj = %gamemodeList.getKey(0); + if(isObject(%gameModeObj)) + { + %gameModeObj.active = true; + + ChooseLevelMenuTabList-->LevelBtn.active = true; + ChooseLevelMenuTabList-->GameModeBtn.active = false; + + ChooseLevelMenu.openMenu(1); + + return; + } + } + else + { + //Otherwise open the gamemode list as normal + %this.schedule(32, openMenu, 0); + } } function refreshGameModesList() @@ -77,36 +99,36 @@ function refreshGameModesList() if(%gameModeName $= "") %gameModeName = %gameModeObj.getName(); - %preview = new GuiContainer() { - position = "0 0"; - extent = $LevelPreviewButtonSize; + %preview = new GuiContainer() { + position = "0 0"; + extent = $LevelPreviewButtonSize; + horizSizing = "right"; + vertSizing = "bottom"; + gameModeObj = %gameModeObj; + gameModeDesc = %gameModeObj.description; + previewImage = %gameModeObj.previewImage; + cansave = false; + + new GuiToggleButtonCtrl() { + position = $LevelPreviewButtonSize.y SPC 0; + extent = $LevelPreviewButtonSize.x - $LevelPreviewButtonSize.y - 5 SPC $LevelPreviewButtonSize.y; + profile = GuiMenuButtonProfile; horizSizing = "right"; vertSizing = "bottom"; - gameModeObj = %gameModeObj; - gameModeDesc = %gameModeObj.description; - previewImage = %gameModeObj.previewImage; - cansave = false; - - new GuiToggleButtonCtrl() { - position = $LevelPreviewButtonSize.y SPC 0; - extent = $LevelPreviewButtonSize.x - $LevelPreviewButtonSize.y - 5 SPC $LevelPreviewButtonSize.y; - profile = GuiMenuButtonProfile; - horizSizing = "right"; - vertSizing = "bottom"; - internalName = "button"; - class = "GameModePreviewButton"; - text = %gameModeName; - command = "ToggleGameMode(" @ %i @ ");"; //allow doubleclick to quick action it - textMargin = 120; - }; - - new GuiBitmapCtrl() { - position = "0 0"; - extent = $LevelPreviewButtonSize.y SPC $LevelPreviewButtonSize.y; - internalName = "checkbox"; - bitmapAsset = "UI:toggleMarker_image"; - }; + internalName = "button"; + class = "GameModePreviewButton"; + text = %gameModeName; + command = "ToggleGameMode(" @ %i @ ");"; //allow doubleclick to quick action it + textMargin = 120; }; + + new GuiBitmapCtrl() { + position = "0 0"; + extent = $LevelPreviewButtonSize.y SPC $LevelPreviewButtonSize.y; + internalName = "checkbox"; + bitmapAsset = "UI:toggleMarker_image"; + }; + }; GameModePreviewArray.add(%preview); @@ -134,6 +156,8 @@ function refreshLevelsList() return; } + %gameModesList = getGameModesList(); + //filter the levelAssets by the gamemode selected %filteredIndex = 0; for(%i=0; %i < %count; %i++) @@ -168,14 +192,14 @@ function refreshLevelsList() for(%gm = 0; %gm < getTokenCount(%levelGameModes, ";"); %gm++) { %gameModeName = getToken(%levelGameModes, ";", %gm); - - for(%g=0; %g < GameModePreviewArray.getCount(); %g++) + for(%g=0; %g < %gameModesList.count(); %g++) { - %gmb = GameModePreviewArray.getObject(%g); - if(!isObject(%gmb.gameModeObj) || (!%gmb.gameModeObj.active && !%gmb.gameModeObj.alwaysActive)) + %gameModeObj = %gameModesList.getKey(%g); + + if(!isObject(%gameModeObj) || (!%gameModeObj.active && !%gameModeObj.alwaysActive && %gameModesList.count() > 1)) continue; - if(%gameModeName $= %gmb.gameModeObj.getName()) + if(%gameModeName $= %gameModeObj.getName()) { %foundGameModeMatch = true; break; @@ -315,8 +339,6 @@ function GameModePreviewArray::syncGUI(%this) %btn = %this.getObject(%this.listPosition); %btn-->button.setHighlighted(true); - - //$pref::Server::GameMode = %btn.gameModeObject; } function ChooseLevelMenuPrevMenu(%val)