From e4d07c7e8df3b571cc7da93fb616764582cb79af Mon Sep 17 00:00:00 2001 From: JeffR Date: Fri, 4 Oct 2024 00:10:26 -0500 Subject: [PATCH] Adds utility function and method to be able to enact a load of subscenes at a specific world position Adds loadIf conditional logic to evaluate if a subscene is 'allowed' to load when tested Adds isAlwaysActive to GameMode to be able to flag a gamemode as being defaulted to on and used automatically Updated GetGameModesList function to return an arrayObject of the gamemodes found Overhauled CallGameModeFunction to utilize the gamemodes list with active/alwaysActive modes being called against, rather than level-scanning Updated ChooseLevelMenu to be able to toggle on/off multiple gamemodes with an image indicator if it's active or not --- Engine/source/T3D/Scene.cpp | 21 +++ Engine/source/T3D/Scene.h | 2 + Engine/source/T3D/SubScene.cpp | 16 +- Engine/source/T3D/SubScene.h | 1 + Engine/source/T3D/gameMode.cpp | 40 +++- Engine/source/T3D/gameMode.h | 4 + .../game/core/utility/scripts/scene.tscript | 58 ++---- .../game/data/UI/guis/ChooseLevelMenu.gui | 27 +-- .../game/data/UI/guis/ChooseLevelMenu.tscript | 173 +++++++++++++----- .../game/data/UI/images/toggleMarker.png | Bin 0 -> 6747 bytes .../game/data/UI/images/toggleMarker_h.png | Bin 0 -> 6759 bytes .../UI/images/toggleMarker_h_image.asset.taml | 3 + .../UI/images/toggleMarker_image.asset.taml | 3 + .../scripts/assetTypes/gameMode.tscript | 107 +++-------- 14 files changed, 258 insertions(+), 197 deletions(-) create mode 100644 Templates/BaseGame/game/data/UI/images/toggleMarker.png create mode 100644 Templates/BaseGame/game/data/UI/images/toggleMarker_h.png create mode 100644 Templates/BaseGame/game/data/UI/images/toggleMarker_h_image.asset.taml create mode 100644 Templates/BaseGame/game/data/UI/images/toggleMarker_image.asset.taml diff --git a/Engine/source/T3D/Scene.cpp b/Engine/source/T3D/Scene.cpp index d8061f32be..0d7908fe34 100644 --- a/Engine/source/T3D/Scene.cpp +++ b/Engine/source/T3D/Scene.cpp @@ -391,6 +391,21 @@ Vector Scene::getObjectsByClass(String className) return Vector(); } +void Scene::loadAtPosition(const Point3F& position) +{ + for (U32 i = 0; i < mSubScenes.size(); i++) + { + Box3F testBox = Box3F(0.5); + testBox.setCenter(position); + + if (mSubScenes[i]->testBox(testBox)) + { + mSubScenes[i]->setUnloadTimeMS(-1); + mSubScenes[i]->load(); + } + } +} + DefineEngineFunction(getScene, Scene*, (U32 sceneId), (0), "Get the root Scene object that is loaded.\n" "@return The id of the Root Scene. Will be 0 if no root scene is loaded") @@ -489,3 +504,9 @@ DefineEngineMethod(Scene, save, bool, (const char* fileName), (""), { return object->saveScene(StringTable->insert(fileName)); } + +DefineEngineMethod(Scene, loadAtPosition, void, (Point3F position), (Point3F::Zero), + "Loads any subscenes at a given point by force.\n") +{ + object->loadAtPosition(position); +} diff --git a/Engine/source/T3D/Scene.h b/Engine/source/T3D/Scene.h index d99b1f4b96..8f48b80b12 100644 --- a/Engine/source/T3D/Scene.h +++ b/Engine/source/T3D/Scene.h @@ -93,6 +93,8 @@ class Scene : public NetObject, public virtual ITickable template Vector getObjectsByClass(); + void loadAtPosition(const Point3F& position); + static Scene *getRootScene() { if (Scene::smSceneList.empty()) diff --git a/Engine/source/T3D/SubScene.cpp b/Engine/source/T3D/SubScene.cpp index 5b93c473d3..59f68d3dd2 100644 --- a/Engine/source/T3D/SubScene.cpp +++ b/Engine/source/T3D/SubScene.cpp @@ -49,6 +49,7 @@ void SubScene::initPersistFields() addGroup("SubScene"); addField("isGlobalLayer", TypeBool, Offset(mGlobalLayer, SubScene), ""); INITPERSISTFIELD_LEVELASSET(Level, SubScene, "The level asset to load."); + addField("loadIf", TypeCommand, Offset(mLoadIf, SubScene), "evaluation condition (true/false)"); addField("gameModes", TypeGameModeList, Offset(mGameModesNames, SubScene), "The game modes that this subscene is associated with."); endGroup("SubScene"); @@ -143,9 +144,18 @@ bool SubScene::testBox(const Box3F& testBox) if (mGlobalLayer) return true; - bool isOverlapped = getWorldBox().isOverlapped(testBox); - - return getWorldBox().isOverlapped(testBox); + bool passes = getWorldBox().isOverlapped(testBox); + if (passes && !mLoadIf.isEmpty()) + { + //test the mapper plugged in condition line + String resVar = getIdString() + String(".result"); + Con::setBoolVariable(resVar.c_str(), false); + String command = resVar + "=" + mLoadIf + ";"; + Con::evaluatef(command.c_str()); + passes = Con::getBoolVariable(resVar.c_str()); + } + + return passes; } void SubScene::write(Stream& stream, U32 tabStop, U32 flags) diff --git a/Engine/source/T3D/SubScene.h b/Engine/source/T3D/SubScene.h index 5347a08b78..53c8b12967 100644 --- a/Engine/source/T3D/SubScene.h +++ b/Engine/source/T3D/SubScene.h @@ -38,6 +38,7 @@ class SubScene : public SceneGroup S32 mStartUnloadTimerMS; bool mLoaded; + String mLoadIf; bool mGlobalLayer; public: diff --git a/Engine/source/T3D/gameMode.cpp b/Engine/source/T3D/gameMode.cpp index 404f136242..0032b12ad1 100644 --- a/Engine/source/T3D/gameMode.cpp +++ b/Engine/source/T3D/gameMode.cpp @@ -4,6 +4,8 @@ #include "gui/containers/guiDynamicCtrlArrayCtrl.h" #endif +#include "console/arrayObject.h" + IMPLEMENT_CONOBJECT(GameMode); IMPLEMENT_CALLBACK(GameMode, onActivated, void, (), (), @@ -47,7 +49,9 @@ ConsoleSetType(TypeGameModeList) GameMode::GameMode() : mGameModeName(StringTable->EmptyString()), - mGameModeDesc(StringTable->EmptyString()) + mGameModeDesc(StringTable->EmptyString()), + mIsActive(false), + mIsAlwaysActive(false) { INIT_ASSET(PreviewImage); } @@ -62,6 +66,7 @@ void GameMode::initPersistFields() INITPERSISTFIELD_IMAGEASSET(PreviewImage, GameMode, "Preview Image"); addField("active", TypeBool, Offset(mIsActive, GameMode), "Is the gamemode active"); + addField("alwaysActive", TypeBool, Offset(mIsAlwaysActive, GameMode), "Is the gamemode always active"); } bool GameMode::onAdd() @@ -110,6 +115,11 @@ void GameMode::setActive(const bool& active) onDeactivated_callback(); } +void GameMode::setAlwaysActive(const bool& alwaysActive) +{ + mIsAlwaysActive = alwaysActive; +} + DefineEngineMethod(GameMode, isActive, bool, (), , "Returns if the GameMode is currently active.\n" "@return The active status of the GameMode") @@ -124,24 +134,38 @@ DefineEngineMethod(GameMode, setActive, void, (bool active), (true), object->setActive(active); } -DefineEngineFunction(getGameModesList, const char*, (), , "") +DefineEngineMethod(GameMode, isALwaysActive, bool, (), , + "Returns if the GameMode is currently active.\n" + "@return The active status of the GameMode") +{ + return object->isActive(); +} + +DefineEngineMethod(GameMode, setAlwaysActive, void, (bool alwaysActive), (true), + "Sets the active state of the GameMode.\n" + "@param active A bool of the state the GameMode should be set to") +{ + object->setAlwaysActive(alwaysActive); +} + +DefineEngineFunction(getGameModesList, ArrayObject*, (), , "") { - char* returnBuffer = Con::getReturnBuffer(1024); + ArrayObject* dictionary = new ArrayObject(); + dictionary->registerObject(); - String formattedList; + char activeValBuffer[16]; for (SimGroup::iterator itr = Sim::getRootGroup()->begin(); itr != Sim::getRootGroup()->end(); itr++) { GameMode* gm = dynamic_cast(*itr); if (gm) { - formattedList += String(gm->getName()) + ";"; + dSprintf(activeValBuffer, 16, "%d", (gm->mIsActive || gm->mIsAlwaysActive)); + dictionary->push_back(gm->getName(), activeValBuffer); } } - dSprintf(returnBuffer, 1024, "%s", formattedList.c_str()); - - return returnBuffer; + return dictionary; } //----------------------------------------------------------------------------- diff --git a/Engine/source/T3D/gameMode.h b/Engine/source/T3D/gameMode.h index 85958620ef..9ebde69edb 100644 --- a/Engine/source/T3D/gameMode.h +++ b/Engine/source/T3D/gameMode.h @@ -22,6 +22,7 @@ class GameMode : public SimObject DECLARE_ASSET_SETGET(GameMode, PreviewImage); bool mIsActive; + bool mIsAlwaysActive; public: @@ -34,6 +35,9 @@ class GameMode : public SimObject bool isActive() { return mIsActive; } void setActive(const bool& active); + bool isAlwaysActive() { return mIsAlwaysActive; } + void setAlwaysActive(const bool& alwaysActive); + DECLARE_CONOBJECT(GameMode); static void findGameModes(const char* gameModeList, Vector* outGameModes); diff --git a/Templates/BaseGame/game/core/utility/scripts/scene.tscript b/Templates/BaseGame/game/core/utility/scripts/scene.tscript index 4062c47491..2d8897dee8 100644 --- a/Templates/BaseGame/game/core/utility/scripts/scene.tscript +++ b/Templates/BaseGame/game/core/utility/scripts/scene.tscript @@ -1,52 +1,22 @@ function callGamemodeFunction(%gameModeFuncName, %arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %arg6) { - %activeSceneCount = getSceneCount(); - - %hasGameMode = 0; - for(%i=0; %i < %activeSceneCount; %i++) + %validGameModeCall = false; + %gamemodeList = getGameModesList(); + %gameModeCount = %gamemodeList.count(); + for(%i=0; %i < %gameModeCount; %i++) { - %gamemodeName = getScene(%i).gameModeName; - if(%gamemodeName !$= "") + %gameModeObj = %gamemodeList.getKey(%i); + %active = %gamemodeList.getValue(%i); + + if(!isObject(%gameModeObj) || !%active) + continue; + + if(%gameModeObj.isMethod(%gameModeFuncName)) { - //if the scene defines a game mode, go ahead and envoke it here - if(isObject(%gamemodeName) && %gamemodeName.isMethod(%gameModeFuncName)) - { - eval(%gamemodeName @ "."@%gameModeFuncName@"(\""@%arg0@"\", \""@%arg1@"\", \""@%arg2@"\", \""@%arg3@"\", \""@%arg4@"\", \""@%arg5@"\", \""@%arg6@"\");" ); - %hasGameMode = 1; - } - else - { - //if we don't have an object, attempt the static call - if(isMethod(%gamemodeName, %gameModeFuncName)) - { - eval(%gamemodeName @ "::"@%gameModeFuncName@"(\""@%arg0@"\", \""@%arg1@"\", \""@%arg2@"\", \""@%arg3@"\", \""@%arg4@"\", \""@%arg5@"\", \""@%arg6@"\");" ); - %hasGameMode = 1; - } - } + eval(%gameModeObj @ "."@%gameModeFuncName@"(\""@%arg0@"\", \""@%arg1@"\", \""@%arg2@"\", \""@%arg3@"\", \""@%arg4@"\", \""@%arg5@"\", \""@%arg6@"\");" ); + %validGameModeCall = true; } } - //if none of our scenes have gamemodes, we need to kick off a default - if(%hasGameMode == 0) - { - %defaultModeName = ProjectSettings.value("Gameplay/GameModes/defaultModeName"); - if(%defaultModeName !$= "") - { - if(isObject(%defaultModeName) && %defaultModeName.isMethod(%gameModeFuncName)) - { - eval(%defaultModeName @ "."@%gameModeFuncName@"(\""@%arg0@"\", \""@%arg1@"\", \""@%arg2@"\", \""@%arg3@"\", \""@%arg4@"\", \""@%arg5@"\", \""@%arg6@"\");" ); - %hasGameMode = 1; - } - else - { - if(isMethod(%defaultModeName, %gameModeFuncName)) - { - eval(%defaultModeName @ "::"@%gameModeFuncName@"(\""@%arg0@"\", \""@%arg1@"\", \""@%arg2@"\", \""@%arg3@"\", \""@%arg4@"\", \""@%arg5@"\", \""@%arg6@"\");" ); - %hasGameMode = 1; - } - } - } - } - - return %hasGameMode; + return %validGameModeCall; } \ No newline at end of file diff --git a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui index 7bc4850019..8fb0928e2c 100644 --- a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui +++ b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.gui @@ -11,7 +11,6 @@ $guiContent = new GuiControl(ChooseLevelMenu) { canSaveDynamicFields = "1"; currentMenuIdx = "0"; launchInEditor = "0"; - previewButtonSize = "445 120"; new GuiInputCtrl(ChooseLevelInputHandler) { ignoreMouseEvents = "1"; @@ -40,8 +39,8 @@ $guiContent = new GuiControl(ChooseLevelMenu) { new GuiStackControl(ChooseLevelMenuTabList) { stackingType = "Horizontal"; padding = "10"; - position = "405 61"; - extent = "470 41"; + position = "485 61"; + extent = "310 41"; horizSizing = "center"; profile = "GuiDefaultProfile"; tooltipProfile = "GuiToolTipProfile"; @@ -73,10 +72,12 @@ $guiContent = new GuiControl(ChooseLevelMenu) { position = "320 0"; extent = "150 41"; profile = "GuiMenuButtonProfile"; + visible = "0"; command = "ChooseLevelMenu.openMenu(2);"; tooltipProfile = "GuiToolTipProfile"; internalName = "ConfigBtn"; class = "ChooseLevelMenuButton"; + hidden = "1"; }; }; new GuiControl(ChooseLevelMenuNavButtonOverlay) { @@ -89,7 +90,7 @@ $guiContent = new GuiControl(ChooseLevelMenu) { new GuiBitmapCtrl(ChooseLevelMenuPrevNavIcon) { BitmapAsset = "UI:Keyboard_Black_Q_image"; - position = "405 24"; + position = "485 24"; extent = "40 40"; vertSizing = "top"; profile = "GuiNonModalDefaultProfile"; @@ -97,7 +98,7 @@ $guiContent = new GuiControl(ChooseLevelMenu) { }; new GuiBitmapCtrl(ChooseLevelMenuNextNavIcon) { BitmapAsset = "UI:Keyboard_Black_E_image"; - position = "515 24"; + position = "595 24"; extent = "40 40"; vertSizing = "top"; profile = "GuiNonModalDefaultProfile"; @@ -121,8 +122,8 @@ $guiContent = new GuiControl(ChooseLevelMenu) { new GuiStackControl(GameModePreviewArray) { padding = "5"; - position = "0 1"; - extent = "445 120"; + position = "1 1"; + extent = "443 60"; horizSizing = "width"; vertSizing = "height"; profile = "GuiMenuDefaultProfile"; @@ -130,15 +131,16 @@ $guiContent = new GuiControl(ChooseLevelMenu) { }; }; new GuiBitmapCtrl(GameModePreviewBitmap) { - BitmapAsset = "UI:no_preview_image"; position = "448 0"; extent = "440 440"; horizSizing = "left"; profile = "GuiNonModalDefaultProfile"; + visible = "0"; tooltipProfile = "GuiToolTipProfile"; + hidden = "1"; }; new GuiTextCtrl(GameModeNameText) { - text = "Example Level"; + text = "DeathMatchGame"; position = "448 445"; extent = "440 20"; horizSizing = "left"; @@ -175,7 +177,7 @@ $guiContent = new GuiControl(ChooseLevelMenu) { new GuiStackControl(LevelPreviewArray) { padding = "5"; position = "0 1"; - extent = "445 120"; + extent = "445 60"; horizSizing = "width"; vertSizing = "height"; profile = "GuiMenuDefaultProfile"; @@ -277,6 +279,7 @@ $guiContent = new GuiControl(ChooseLevelMenu) { tooltipProfile = "GuiToolTipProfile"; }; new GuiTextEditCtrl(serverNameCTRL) { + text = "Torque 3D Server"; position = "606 4"; extent = "295 22"; horizSizing = "left"; @@ -374,8 +377,8 @@ $guiContent = new GuiControl(ChooseLevelMenu) { profile = "GuiMenuPanelProfile"; tooltipProfile = "GuiToolTipProfile"; - new GuiIconButtonCtrl(ChooseLevelStartBtn) { - BitmapAsset = "UI:Keyboard_Black_Space_image"; + new GuiIconButtonCtrl(ChooseLevelNextBtn) { + BitmapAsset = "UI:Keyboard_Black_Blank_image"; sizeIconToButton = "1"; makeIconSquare = "1"; textLocation = "Center"; diff --git a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript index 3d949d8709..ac1b9d7828 100644 --- a/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript +++ b/Templates/BaseGame/game/data/UI/guis/ChooseLevelMenu.tscript @@ -25,7 +25,7 @@ function ChooseLevelMenu::onAdd( %this ) if(!isObject(ChooseLevelAssetQuery)) new AssetQuery(ChooseLevelAssetQuery); - %this.previewButtonSize = "445 120"; + $LevelPreviewButtonSize = "445 60"; } function ChooseLevelMenu::fillPrefEntries( %this ) @@ -40,9 +40,9 @@ function ChooseLevelMenu::fillPrefEntries( %this ) function ChooseLevelMenu::onWake(%this) { %this.fillPrefEntries(); - LevelPreviewArray.clear(); refreshGameModesList(); + refreshLevelsList(); if(!$pref::HostMultiPlayer) ChooseLevelTitleText.setText("SINGLE PLAYER"); @@ -66,35 +66,48 @@ function refreshGameModesList() //popilate the gamemodes list first %gamemodeList = getGameModesList(); - for(%i=0; %i < getTokenCount(%gamemodeList, ";"); %i++) + %gameModeCount = %gamemodeList.count(); + + for (%i=0; %i<%gameModeCount; %i++) { - %gameModeObj = getToken(%gamemodeList, ";", %i); - + %gameModeObj = %gamemodeList.getKey(%i); if(isObject(%gameModeObj)) { %gameModeName = %gameModeObj.gameModeName; if(%gameModeName $= "") %gameModeName = %gameModeObj.getName(); - %preview = new GuiButtonCtrl() { - position = "0 0"; - extent = ChooseLevelMenu.previewButtonSize; - buttonType = "PushButton"; - profile = GuiMenuButtonLeftJustProfile; - horizSizing = "right"; - vertSizing = "bottom"; - internalName = "button"; - class = "GameModePreviewButton"; - //command = "ChooseGameModeBegin(" @ %i @ ");"; - altCommand = "ChooseGameModeBegin(" @ %i @ ");"; //allow doubleclick to quick action it - text = %gameModeName; - gameModeObj = %gameModeObj; - gameModeDesc = %gameModeObj.description; - previewImage = %gameModeObj.previewImage; - textMargin = 120; - groupNum = 2; - cansave = false; - }; + %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"; + 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); } @@ -122,6 +135,7 @@ function refreshLevelsList() } //filter the levelAssets by the gamemode selected + %filteredIndex = 0; for(%i=0; %i < %count; %i++) { %assetId = ChooseLevelAssetQuery.getAsset(%i); @@ -142,21 +156,26 @@ function refreshLevelsList() //filter for selected gamemode %levelGameModes = %levelAsset.gameModesNames; - echo("LevelAsset gamemodes: " @ %levelGameModes); - %foundGameModeMatch = false; for(%gm = 0; %gm < getTokenCount(%levelGameModes, ";"); %gm++) { %gameModeName = getToken(%levelGameModes, ";", %gm); - echo("testing gamemode: " @ %gameModeName); - echo("selected gamemode: " @ $pref::Server::GameMode.getName()); - - if(%gameModeName $= $pref::Server::GameMode.getName()) + for(%g=0; %g < GameModePreviewArray.getCount(); %g++) { - %foundGameModeMatch = true; - break; + %gmb = GameModePreviewArray.getObject(%g); + if(!isObject(%gmb.gameModeObj) || (!%gmb.gameModeObj.active && !%gmb.gameModeObj.alwaysActive)) + continue; + + if(%gameModeName $= %gmb.gameModeObj.getName()) + { + %foundGameModeMatch = true; + break; + } } + + if(%foundGameModeMatch) + break; } if(!%foundGameModeMatch) @@ -169,7 +188,7 @@ function refreshLevelsList() %preview = new GuiIconButtonCtrl() { position = "0 0"; - extent = ChooseLevelMenu.previewButtonSize; + extent = $LevelPreviewButtonSize; buttonType = "PushButton"; profile = GuiMenuButtonLeftJustProfile; horizSizing = "right"; @@ -177,7 +196,7 @@ function refreshLevelsList() internalName = "button"; class = "LevelPreviewButton"; //command = "$selectedLevelAsset = " @ %assetId @ ";"; - altCommand = "ChooseLevelBegin(" @ %i @ ");"; //allow doubleclick to quick action it + altCommand = "ChooseLevelBegin(" @ %filteredIndex @ ");"; //allow doubleclick to quick action it text = %levelAsset.levelName; bitmapAsset = %levelPreviewImg; levelAsset = %levelAsset; @@ -192,8 +211,11 @@ function refreshLevelsList() }; LevelPreviewArray.add(%preview); + + %filteredIndex++; } - + + GameModePreviewArray.listPosition = 0; LevelPreviewArray.listPosition = 0; // Also add the new level mission as defined in the world editor settings @@ -236,10 +258,31 @@ function ChooseLevelMenu::syncGUI(%this) ChooseLevelBackBtn.setBitmap(BaseUIActionMap.getCommandButtonBitmap(%device, "BaseUIBackOut")); - ChooseLevelStartBtn.setBitmap(ChooseLevelActionMap.getCommandButtonBitmap(%device, "ChooseLevelBegin")); + if(ChooseLevelMenu.currentMenuIdx == 0) + ChooseLevelNextBtn.text = "Toggle Mode"; + else + ChooseLevelNextBtn.text = "Start Game"; + + ChooseLevelNextBtn.setBitmap(ChooseLevelActionMap.getCommandButtonBitmap(%device, "ChooseLevelMenuOption")); ChooseLevelMenuPrevNavIcon.setBitmap(ChooseLevelActionMap.getCommandButtonBitmap(%device, "ChooseLevelMenuPrevMenu")); ChooseLevelMenuNextNavIcon.setBitmap(ChooseLevelActionMap.getCommandButtonBitmap(%device, "ChooseLevelMenuNextMenu")); + + %hasActiveGameMode = false; + for(%i=0; %i < GameModePreviewArray.getCount(); %i++) + { + %btn = GameModePreviewArray.getObject(%i); + if(!isObject(%btn.gameModeObj)) + continue; + + if((%btn.gameModeObj.isActive() || %btn.gameModeObj.isAlwaysActive()) == true) + { + %hasActiveGameMode = true; + break; + } + } + + ChooseLevelMenuTabList-->LevelBtn.active = %hasActiveGameMode; } function LevelPreviewArray::syncGUI(%this) @@ -252,10 +295,19 @@ function LevelPreviewArray::syncGUI(%this) function GameModePreviewArray::syncGUI(%this) { + for(%i=0; %i < %this.getCount(); %i++) + { + %btn = %this.getObject(%i); + %btn-->button.setHighlighted(false); + + %bitmapAst = (%btn.gameModeObj.active || %btn.gameModeObj.alwaysActive) ? "UI:toggleMarker_h_image" : "UI:toggleMarker_image"; + %btn-->checkbox.setBitmap(%bitmapAst); + } + %btn = %this.getObject(%this.listPosition); - %btn.setHighlighted(true); + %btn-->button.setHighlighted(true); - $pref::Server::GameMode = %btn.gameModeObject; + //$pref::Server::GameMode = %btn.gameModeObject; } function ChooseLevelMenuPrevMenu(%val) @@ -270,6 +322,13 @@ function ChooseLevelMenuPrevMenu(%val) %endIndex = 2; ChooseLevelMenu.currentMenuIdx = mClamp(ChooseLevelMenu.currentMenuIdx, 0, %endIndex); + + //bail if we're trying to step into a hidden or disabled menu + if(!ChooseLevelMenu.isMenuAvailable(ChooseLevelMenu.currentMenuIdx)) + { + ChooseLevelMenu.currentMenuIdx = %currentIdx; + return; + } if(%currentIdx == ChooseLevelMenu.currentMenuIdx) return; @@ -290,6 +349,13 @@ function ChooseLevelMenuNextMenu(%val) %endIndex = 2; ChooseLevelMenu.currentMenuIdx = mClamp(ChooseLevelMenu.currentMenuIdx, 0, %endIndex); + + //bail if we're trying to step into a hidden or disabled menu + if(!ChooseLevelMenu.isMenuAvailable(ChooseLevelMenu.currentMenuIdx)) + { + ChooseLevelMenu.currentMenuIdx = %currentIdx; + return; + } if(%currentIdx == ChooseLevelMenu.currentMenuIdx) return; @@ -319,33 +385,48 @@ function ChooseLevelMenu::openMenu(%this, %menuIdx) %this.syncGui(); } +function ChooseLevelMenu::isMenuAvailable(%this, %menuIdx) +{ + if(%menuIdx == 0) + %btn = %this-->GameModeBtn; + else if(%menuIdx == 1) + %btn = %this-->LevelBtn; + else if(%menuIdx == 2) + %btn = %this-->ConfigBtn; + + return %btn.isActive() && %btn.isVisible(); +} + function ChooseLevelMenuOption(%val) { if(%val) { if(ChooseLevelMenu.currentMenuIdx == 0) - ChooseGameModeBegin(ChooseLevelMenu.listPosition); + ToggleGameMode(ChooseLevelMenu.listPosition); else if(ChooseLevelMenu.currentMenuIdx == 1) ChooseLevelBegin(ChooseLevelMenu.listPosition); } } -function ChooseGameModeBegin(%index) +function ToggleGameMode(%index) { + if(%index $= "") + %index = $MenuList.listPosition; + %entry = GameModePreviewArray.getObject(%index); if(!isObject(%entry) || !isObject(%entry.gameModeObj)) { MessageBoxOK("Error", "Selected game mode does not have a valid mode"); return; } - - $pref::Server::GameMode = %entry.gameModeObj; - - ChooseLevelMenuTabList-->LevelBtn.active = true; + + %entry.gameModeObj.active = !%entry.gameModeObj.active; refreshLevelsList(); - ChooseLevelMenu.openMenu(1); + $MenuList.syncGui(); + ChooseLevelMenu.syncGui(); + } function ChooseLevelBegin(%index) @@ -399,7 +480,7 @@ function GameModePreviewButton::onHighlighted(%this, %highlighted) { if(%highlighted) { - $MenuList.listPosition = $MenuList.getObjectIndex(%this); + $MenuList.listPosition = $MenuList.getObjectIndex(%this.getParent()); GameModePreviewBitmap.bitmapAsset = %this.previewImage; diff --git a/Templates/BaseGame/game/data/UI/images/toggleMarker.png b/Templates/BaseGame/game/data/UI/images/toggleMarker.png new file mode 100644 index 0000000000000000000000000000000000000000..6d3a0dfd4a94b584cc7e14ea2d639778720b1cd7 GIT binary patch literal 6747 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 v{+4C diff --git a/Templates/BaseGame/game/data/UI/images/toggleMarker_image.asset.taml b/Templates/BaseGame/game/data/UI/images/toggleMarker_image.asset.taml new file mode 100644 index 0000000000..d8b681616b --- /dev/null +++ b/Templates/BaseGame/game/data/UI/images/toggleMarker_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/gameMode.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/gameMode.tscript index e58be2c7fd..ae5e59b3e2 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/gameMode.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/gameMode.tscript @@ -1,96 +1,35 @@ -function AssetBrowser::createGameMode(%this) +AssetBrowser::registerObjectType("GameModeType", "Gamemode Objects", "Gamemode"); + +function GameModeType::setupCreateNew() { - %moduleName = AssetBrowser.newAssetSettings.moduleName; - %moduleDef = ModuleDatabase.findModule(%moduleName, 1); - - %assetName = AssetBrowser.newAssetSettings.assetName; - %assetPath = NewAssetTargetAddress.getText() @ "/"; - %scriptPath = %assetPath @ %assetName @ "." @ $TorqueScriptFileExtension; - %fullScriptPath = makeFullPath(%scriptPath); +} - %file = new FileObject(); - %templateFile = new FileObject(); - - %postFXTemplateCodeFilePath = %this.templateFilesPath @ "gameMode." @ $TorqueScriptFileExtension @ ".template"; +function GameModeType::onCreateNew() +{ - if(%file.openForWrite(%fullScriptPath) && %templateFile.openForRead(%postFXTemplateCodeFilePath)) - { - while( !%templateFile.isEOF() ) - { - %line = %templateFile.readline(); - %line = strreplace( %line, "@@", %assetName ); - - %file.writeline(%line); - } - - %file.close(); - %templateFile.close(); - } - else - { - %file.close(); - %templateFile.close(); - - warnf("createGameMode - Something went wrong and we couldn't write the gameMode script file!"); - } +} - %localScriptPath = strReplace(%scriptPath, "data/" @ %moduleName @ "/", "./"); - %execLine = " %this.queueExec(\"" @ %localScriptPath @ "\");"; - - %moduleScriptPath = makeFullPath(%moduleDef.ModuleScriptFilePath @ "." @ $TorqueScriptFileExtension); - - echo("Attempting exec insert for file: " @ %moduleScriptPath); - - %lineIdx = Tools::findInFile(%moduleScriptPath, "*function*" @ %moduleName @ "::initClient*"); - if(%lineIdx != -1) - { - echo("INIT CLIENT FUNCTION LINE FOUND ON: " @ %lineIdx); - - %insertLineIdx = Tools::findInFunction(%moduleScriptPath, %moduleName, "initClient", "*//--FILE EXEC END--*"); - echo("FILE EXEC END LINE FOUND ON: " @ %insertLineIdx); - - if(%insertLineIdx == -1) - { - //If there are not 'blocking' comments, then just slap the exec on the end of the function def - //as it doesn't really matter now - Tools::appendLineToFunction(%moduleScriptPath, %moduleName, "initClient", %execLine); - } - else - { - Tools::insertInFile(%moduleScriptPath, %insertLineIdx, %execLine, true); - } - } +function GameModeType::buildBrowserElement(%this, %className, %previewData) +{ + //echo("DatablockObjectType::buildBrowserElement() - " @ %datablock @ ", " @ %name @ ", " @ %previewData); + %previewData.assetName = %this.getName(); + %previewData.assetPath = %this.getFileName(); - %lineIdx = Tools::findInFile(%moduleScriptPath, "*function*" @ %moduleName @ "::initServer*"); - if(%lineIdx != -1) - { - echo("INIT SERVER FUNCTION LINE FOUND ON: " @ %lineIdx); - - %insertLineIdx = Tools::findInFunction(%moduleScriptPath, %moduleName, "initServer", "*//--FILE EXEC END--*"); - echo("FILE EXEC END LINE FOUND ON: " @ %insertLineIdx); - - if(%insertLineIdx == -1) - { - //If there are not 'blocking' comments, then just slap the exec on the end of the function def - //as it doesn't really matter now - Tools::appendLineToFunction(%moduleScriptPath, %moduleName, "initServer", %execLine); - } - else - { - Tools::insertInFile(%moduleScriptPath, %insertLineIdx, %execLine, true); - } - } + %previewData.previewImage = "ToolsModule:genericAssetIcon_image"; - //and we'll go ahead and force execute the script file so the gamemode is 'available' for use immediately - exec(%scriptPath); + //Lets see if we have a icon for specifically for this datablock type + %dataClass = %this.getClassName(); + %dataClass = strreplace(%dataClass, "Data", ""); - if(isObject(%assetName)) + %previewImage = "tools/classIcons/" @ %dataClass @ ".png"; + if(isFile(%previewImage)) { - //it's possible it got moved to an instant group upon execution, so we'll just - //shove it back to the RootGroup by force to be 100% sure - RootGroup.add(%assetName); + %previewData.previewImage = %previewImage; } - return %scriptPath; + //%previewData.assetFriendlyName = %assetDef.assetName; + %previewData.assetDesc = %this; + %previewData.tooltip = "\nGameMode Name: " @ %previewData.assetName @ + "\nPath: " @ %previewData.assetPath; } \ No newline at end of file