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)