From 4cfb3c4f04bb5ab0c239bc733508295ae1a6c16a Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Wed, 22 Sep 2021 20:28:39 -0400 Subject: [PATCH 01/16] * [Linux] BugFix: Corrections to allow the Linux win console (Ie. the terminal you ran the game from) to act as a console input. --- Engine/source/platformX86UNIX/x86UNIXConsole.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Engine/source/platformX86UNIX/x86UNIXConsole.cpp b/Engine/source/platformX86UNIX/x86UNIXConsole.cpp index 88e17f38e..85828b202 100644 --- a/Engine/source/platformX86UNIX/x86UNIXConsole.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXConsole.cpp @@ -41,7 +41,10 @@ StdConsole *stdConsole = NULL; DefineEngineFunction(enableWinConsole, void, (bool _enable),, "enableWinConsole(bool);") { if (stdConsole) - stdConsole->enable(_enable); + { + stdConsole->enable(_enable); + stdConsole->enableInput(_enable); + } } void StdConsole::create() @@ -141,6 +144,9 @@ StdConsole::StdConsole() stdIn = dup(0); stdErr = dup(2); + // Ensure in buffer is null terminated after allocation + inbuf[0] = 0x00; + iCmdIndex = 0; stdConsoleEnabled = false; stdConsoleInputEnabled = false; @@ -195,11 +201,14 @@ void StdConsole::processConsoleLine(const char *consoleLine) { if(stdConsoleEnabled) { - inbuf[inpos] = 0; if(lineOutput) printf("%s\n", consoleLine); else - printf("%c%s\n%s%s", '\r', consoleLine, Con::getVariable("Con::Prompt"), inbuf); + { + // Clear current line before outputting the console line. This prevents prompt text from overflowing onto normal output. + printf("%c[2K", 27); + printf("%c%s\n%s%s", '\r', consoleLine, Con::getVariable("Con::Prompt"), inbuf); + } } } @@ -323,6 +332,7 @@ void StdConsole::process() printf("%s", Con::getVariable("Con::Prompt")); inpos = outpos = 0; + inbuf[0] = 0x00; // Ensure inbuf is NULL terminated after sending out command break; case 27: // JMQTODO: are these magic numbers keyboard map specific? From 55063601e6aacc6aca62855a2c575450666a57ea Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Thu, 23 Sep 2021 22:58:25 -0400 Subject: [PATCH 02/16] * [Projectile] BugFix: Correct the onAdd callback not being raised for projectiles. --- Engine/source/T3D/projectile.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Engine/source/T3D/projectile.cpp b/Engine/source/T3D/projectile.cpp index 739daf4a5..b21fe9542 100644 --- a/Engine/source/T3D/projectile.cpp +++ b/Engine/source/T3D/projectile.cpp @@ -786,6 +786,8 @@ bool Projectile::onAdd() // If we're on the server, we need to inherit some of our parent's velocity // mCurrTick = 0; + + scriptOnAdd(); } else { From 12f4af51f557cc76a4d018fe262b816eae58b119 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Fri, 24 Sep 2021 17:58:17 -0400 Subject: [PATCH 03/16] * [Editor] BugFix: Fix a crash that sometimes occurs when groups of objects are deleted in the world editor. --- Engine/source/gui/worldEditor/worldEditor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index d6642cd1c..dfccf8533 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -1993,12 +1993,12 @@ void WorldEditor::on3DMouseMove(const Gui3DMouseEvent & event) if ( !mHitObject ) { SceneObject *hitObj = NULL; - if ( collide(event, &hitObj) && hitObj->isSelectionEnabled() && !objClassIgnored(hitObj) ) + if ( collide(event, &hitObj) && !hitObj->isDeleted() && hitObj->isSelectionEnabled() && !objClassIgnored(hitObj) ) { mHitObject = hitObj; } } - + mLastMouseEvent = event; } From d7919950bfbe217650fbb457f13fe31bcbf6e4a0 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Fri, 24 Sep 2021 18:34:57 -0400 Subject: [PATCH 04/16] * [Editor] BugFix: Correct an object spawning error when attempting to drag and drop datablocks from the asset browser where they would always spawn at origin. --- .../game/tools/worldEditor/scripts/editors/creator.ed.tscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.tscript index 08bd46598..8fce4a3fd 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.tscript @@ -227,7 +227,7 @@ function EWCreatorWindow::createObject( %this, %cmd ) %this.setNewObjectGroup( getScene(0) ); pushInstantGroup(); - %objId = eval(%cmd); + %objId = eval("return " @ %cmd); popInstantGroup(); if( isObject( %objId ) ) From f1ee4f781b2ead4f881665784cd4751d7b87cb69 Mon Sep 17 00:00:00 2001 From: Jeff Hutchinson Date: Fri, 24 Sep 2021 19:09:43 -0400 Subject: [PATCH 05/16] Material editor fixes from eval cleanup. --- .../scripts/materialEditor.ed.tscript | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.tscript b/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.tscript index bdca293da..8a21c9907 100644 --- a/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.tscript +++ b/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.tscript @@ -1097,9 +1097,6 @@ function MaterialEditorGui::updateActiveMaterial(%this, %propertyField, %value, { MaterialEditorGui.setMaterialDirty(); - if(%value $= "") - %value = "\"\""; - // Here is where we handle undo actions with slider controls. We want to be able to // undo every onMouseUp; so we overrite the same undo action when necessary in order // to achieve this desired effect. @@ -1130,7 +1127,7 @@ function MaterialEditorGui::updateActiveMaterial(%this, %propertyField, %value, if (MaterialEditorGui.livePreview == true) { - MaterialEditorGui.setFieldValue(%propertyField, %value); + MaterialEditorGui.currentMaterial.setFieldValue(%propertyField, %value); MaterialEditorGui.currentMaterial.flush(); MaterialEditorGui.currentMaterial.reload(); } @@ -1263,8 +1260,8 @@ function MaterialEditorGui::doUpdateTextureMap( %this, %assetId ) %bitmap = strreplace(%bitmap,"tools/materialEditor/scripts/",""); %bitmapCtrl.setBitmap(%bitmap); %textCtrl.setText(%assetId); - MaterialEditorGui.updateActiveMaterial(%type @ "Map[" @ %layer @ "]","\"\""); - MaterialEditorGui.updateActiveMaterial(%type @ "MapAsset[" @ %layer @ "]","\"" @ %assetId @ "\""); + MaterialEditorGui.updateActiveMaterial(%type @ "Map[" @ %layer @ "]",""); + MaterialEditorGui.updateActiveMaterial(%type @ "MapAsset[" @ %layer @ "]", %assetId); } } @@ -1276,7 +1273,7 @@ function MaterialEditorGui::updateDetailScale(%this,%newScale) { %layer = MaterialEditorGui.currentLayer; - %detailScale = "\"" @ %newScale SPC %newScale @ "\""; + %detailScale = %newScale SPC %newScale; MaterialEditorGui.updateActiveMaterial("detailScale[" @ %layer @ "]", %detailScale); } @@ -1284,7 +1281,7 @@ function MaterialEditorGui::updateDetailNormalStrength(%this,%newStrength) { %layer = MaterialEditorGui.currentLayer; - %detailStrength = "\"" @ %newStrength @ "\""; + %detailStrength = %newStrength; MaterialEditorGui.updateActiveMaterial("detailNormalMapStrength[" @ %layer @ "]", %detailStrength); } @@ -1295,7 +1292,7 @@ function MaterialEditorGui::updateRotationOffset(%this, %isSlider, %onMouseUp) %Y = MaterialEditorPropertiesWindow-->RotationTextEditV.getText(); MaterialEditorPropertiesWindow-->RotationCrosshair.setPosition(45*mAbs(%X)-2, 45*mAbs(%Y)-2); - MaterialEditorGui.updateActiveMaterial("rotPivotOffset[" @ %layer @ "]","\"" @ %X SPC %Y @ "\"",%isSlider,%onMouseUp); + MaterialEditorGui.updateActiveMaterial("rotPivotOffset[" @ %layer @ "]", %X SPC %Y,%isSlider,%onMouseUp); } function MaterialEditorGui::updateRotationSpeed(%this, %isSlider, %onMouseUp) @@ -1457,7 +1454,7 @@ function MaterialEditorGui::syncGuiColor(%this, %guiCtrl, %propname, %color) %a = getWord(%color,3); %colorSwatch = (%r SPC %g SPC %b SPC %a); - %color = "\"" @ %r SPC %g SPC %b SPC %a @ "\""; + %color = %r SPC %g SPC %b SPC %a; %guiCtrl.color = %colorSwatch; MaterialEditorGui.updateActiveMaterial(%propName, %color); From 755bbacaa0ee10a5b91c27ab29e604947c7a4adb Mon Sep 17 00:00:00 2001 From: Jeff Hutchinson Date: Fri, 24 Sep 2021 19:32:57 -0400 Subject: [PATCH 06/16] Fix specific usage of Con::executef where it was not being assigned to a ConsoleValue before getting it's data out of it. --- Engine/source/Verve/Core/Persistence/VPersistence.h | 5 +++-- Engine/source/afx/afxEffectron.cpp | 3 ++- Engine/source/afx/afxSelectron.cpp | 6 ++++-- Engine/source/console/arrayObject.cpp | 6 ++++-- Engine/source/console/simObjectList.cpp | 3 ++- Engine/source/environment/editors/guiRiverEditorCtrl.cpp | 3 ++- Engine/source/forest/editor/forestBrushTool.cpp | 5 +++-- Engine/source/gui/controls/guiTreeViewCtrl.cpp | 4 +++- Engine/source/gui/editor/guiPopupMenuCtrl.cpp | 4 +++- Engine/source/gui/editor/popupMenu.cpp | 3 ++- Engine/source/gui/worldEditor/worldEditor.cpp | 4 +++- Engine/source/module/moduleManager.cpp | 6 ++++-- Engine/source/util/messaging/scriptMsgListener.cpp | 4 ---- 13 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Engine/source/Verve/Core/Persistence/VPersistence.h b/Engine/source/Verve/Core/Persistence/VPersistence.h index edbc892c8..a350005fc 100644 --- a/Engine/source/Verve/Core/Persistence/VPersistence.h +++ b/Engine/source/Verve/Core/Persistence/VPersistence.h @@ -250,8 +250,9 @@ namespace VPersistence if ( object->isMethod( "onAdd" ) ) { // Callback. - const char *retValue = Con::executef( object, "onAdd" ); - if ( !dAtob( retValue ) ) + ConsoleValue cValue = Con::executef( object, "onAdd" ); + + if ( !cValue.getBool() ) { // Delete. object->deleteObject(); diff --git a/Engine/source/afx/afxEffectron.cpp b/Engine/source/afx/afxEffectron.cpp index 1c68256c1..f90d20f73 100644 --- a/Engine/source/afx/afxEffectron.cpp +++ b/Engine/source/afx/afxEffectron.cpp @@ -989,9 +989,10 @@ afxEffectron::start_effect(afxEffectronData* datablock, SimObject* extra) } // CALL SCRIPT afxEffectronData::onPreactivate(%params, %extra) - const char* result = Con::executef(datablock, "onPreactivate", + ConsoleValue cValue = Con::executef(datablock, "onPreactivate", Con::getIntArg(param_holder->getId()), (extra) ? Con::getIntArg(extra->getId()) : ""); + const char* result = cValue.getString(); if (result && result[0] != '\0' && !dAtob(result)) { #if defined(TORQUE_DEBUG) diff --git a/Engine/source/afx/afxSelectron.cpp b/Engine/source/afx/afxSelectron.cpp index 63157a4f1..1b6194b9a 100644 --- a/Engine/source/afx/afxSelectron.cpp +++ b/Engine/source/afx/afxSelectron.cpp @@ -1068,9 +1068,11 @@ afxSelectron::start_selectron(SceneObject* picked, U8 subcode, SimObject* extra) } // CALL SCRIPT afxSelectronData::onPreactivate(%params, %extra) - const char* result = Con::executef(datablock, "onPreactivate", + ConsoleValue cValue = Con::executef(datablock, "onPreactivate", Con::getIntArg(param_holder->getId()), - (extra) ? Con::getIntArg(extra->getId()) : "").getString(); + (extra) ? Con::getIntArg(extra->getId()) : ""); + + const char* result = cValue.getString(); if (result && result[0] != '\0' && !dAtob(result)) { #if defined(TORQUE_DEBUG) diff --git a/Engine/source/console/arrayObject.cpp b/Engine/source/console/arrayObject.cpp index 92458852d..68b34059e 100644 --- a/Engine/source/console/arrayObject.cpp +++ b/Engine/source/console/arrayObject.cpp @@ -103,7 +103,8 @@ S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare( const void* a, const void* ArrayObject::Element* ea = ( ArrayObject::Element* )( a ); ArrayObject::Element* eb = ( ArrayObject::Element* )( b ); - S32 result = dAtoi(Con::executef((const char*)smCompareFunction, ea->key, eb->key)); + ConsoleValue cValue = Con::executef((const char*)smCompareFunction, ea->key, eb->key); + S32 result = cValue.getInt(); S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); return ( smDecreasing ? -res : res ); } @@ -113,7 +114,8 @@ S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare( const void* a, const void ArrayObject::Element* ea = ( ArrayObject::Element* )( a ); ArrayObject::Element* eb = ( ArrayObject::Element* )( b ); - S32 result = dAtoi( Con::executef( (const char*)smCompareFunction, ea->value, eb->value ) ); + ConsoleValue cValue = Con::executef( (const char*)smCompareFunction, ea->value, eb->value ); + S32 result = cValue.getInt(); S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); return ( smDecreasing ? -res : res ); } diff --git a/Engine/source/console/simObjectList.cpp b/Engine/source/console/simObjectList.cpp index 8388f6e9d..ac286f22b 100644 --- a/Engine/source/console/simObjectList.cpp +++ b/Engine/source/console/simObjectList.cpp @@ -118,7 +118,8 @@ S32 QSORT_CALLBACK SimObjectList::_callbackSort( const void *a, const void *b ) static char idB[64]; dSprintf( idB, sizeof( idB ), "%d", objB->getId() ); - return dAtoi( Con::executef( (const char*)smSortScriptCallbackFn, idA, idB ) ); + ConsoleValue cValue = Con::executef( (const char*)smSortScriptCallbackFn, idA, idB ); + return cValue.getInt(); } void SimObjectList::scriptSort( const String &scriptCallback ) diff --git a/Engine/source/environment/editors/guiRiverEditorCtrl.cpp b/Engine/source/environment/editors/guiRiverEditorCtrl.cpp index ae9084588..e650fdf59 100644 --- a/Engine/source/environment/editors/guiRiverEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiRiverEditorCtrl.cpp @@ -438,7 +438,8 @@ void GuiRiverEditorCtrl::_process3DMouseDown( const Gui3DMouseEvent& event ) return; } - const char *res = Con::executef( this, "createRiver" ); + ConsoleValue cValue = Con::executef( this, "createRiver" ); + const char* res = cValue.getString(); River *newRiver; if ( !Sim::findObject( res, newRiver ) ) diff --git a/Engine/source/forest/editor/forestBrushTool.cpp b/Engine/source/forest/editor/forestBrushTool.cpp index d0d64d517..5b9278ea6 100644 --- a/Engine/source/forest/editor/forestBrushTool.cpp +++ b/Engine/source/forest/editor/forestBrushTool.cpp @@ -588,7 +588,8 @@ void ForestBrushTool::_collectElements() if ( !Sim::findObject( "ForestEditBrushTree", brushTree ) ) return; - const char* objectIdList = Con::executef( brushTree, "getSelectedObjectList" ); + ConsoleValue cValue = Con::executef( brushTree, "getSelectedObjectList" ); + const char* objectIdList = cValue.getString(); // Collect those objects in a vector and mark them as selected. @@ -685,4 +686,4 @@ bool ForestBrushTool::getGroundAt( const Point3F &worldPt, F32 *zValueOut, Vecto DefineEngineMethod( ForestBrushTool, collectElements, void, (), , "" ) { object->collectElements(); -} \ No newline at end of file +} diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index e2804b1f1..aaed67a78 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -637,7 +637,9 @@ void GuiTreeViewCtrl::Item::getTooltipText(U32 bufLen, char *buf) method += pClassName; if(mParentControl->isMethod(method.c_str())) { - const char* tooltip = Con::executef( mParentControl, method.c_str(), pObject->getIdString() ); + ConsoleValue cValue = Con::executef( mParentControl, method.c_str(), pObject->getIdString() ); + const char* tooltip = cValue.getString(); + dsize_t len = dStrlen(buf); S32 newBufLen = bufLen-len; if(dStrlen(tooltip) > 0 && newBufLen > 0) diff --git a/Engine/source/gui/editor/guiPopupMenuCtrl.cpp b/Engine/source/gui/editor/guiPopupMenuCtrl.cpp index 7c63ebe52..ba04467c2 100644 --- a/Engine/source/gui/editor/guiPopupMenuCtrl.cpp +++ b/Engine/source/gui/editor/guiPopupMenuCtrl.cpp @@ -226,7 +226,9 @@ void GuiPopupMenuTextListCtrl::onMouseUp(const GuiEvent &event) if (item) { if (item->mEnabled) - dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), item->mText.isNotEmpty() ? item->mText : "")); + { + Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), item->mText.isNotEmpty() ? item->mText : ""); + } } } diff --git a/Engine/source/gui/editor/popupMenu.cpp b/Engine/source/gui/editor/popupMenu.cpp index 14fff6844..6e7cb39ee 100644 --- a/Engine/source/gui/editor/popupMenu.cpp +++ b/Engine/source/gui/editor/popupMenu.cpp @@ -288,7 +288,8 @@ bool PopupMenu::canHandleID(U32 id) bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */) { - return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : "")); + ConsoleValue cValue = Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : ""); + return cValue.getBool(); } ////////////////////////////////////////////////////////////////////////// diff --git a/Engine/source/gui/worldEditor/worldEditor.cpp b/Engine/source/gui/worldEditor/worldEditor.cpp index d6642cd1c..d2aa75c4d 100644 --- a/Engine/source/gui/worldEditor/worldEditor.cpp +++ b/Engine/source/gui/worldEditor/worldEditor.cpp @@ -461,7 +461,9 @@ bool WorldEditor::pasteSelection( bool dropSel ) SimGroup *targetGroup = NULL; if( isMethod( "getNewObjectGroup" ) ) { - const char* targetGroupName = Con::executef( this, "getNewObjectGroup" ); + ConsoleValue cValue = Con::executef( this, "getNewObjectGroup" ); + const char* targetGroupName = cValue.getString(); + if( targetGroupName && targetGroupName[ 0 ] && !Sim::findObject( targetGroupName, targetGroup) ) Con::errorf( "WorldEditor::pasteSelection() - no SimGroup called '%s'", targetGroupName ); } diff --git a/Engine/source/module/moduleManager.cpp b/Engine/source/module/moduleManager.cpp index f91ae060d..08db0da6c 100644 --- a/Engine/source/module/moduleManager.cpp +++ b/Engine/source/module/moduleManager.cpp @@ -397,7 +397,8 @@ bool ModuleManager::loadModuleGroup( const char* pModuleGroup ) if ( pLoadReadyModuleDefinition->getModuleScriptFilePath() != StringTable->EmptyString() ) { // Yes, so execute the script file. - const bool scriptFileExecuted = dAtob( Con::executef("exec", pLoadReadyModuleDefinition->getModuleScriptFilePath() ) ); + ConsoleValue cValue = Con::executef("exec", pLoadReadyModuleDefinition->getModuleScriptFilePath()); + const bool scriptFileExecuted = cValue.getBool(); // Did we execute the script file? if ( scriptFileExecuted ) @@ -784,7 +785,8 @@ bool ModuleManager::loadModuleExplicit( const char* pModuleId, const U32 version if ( pLoadReadyModuleDefinition->getModuleScriptFilePath() != StringTable->EmptyString() ) { // Yes, so execute the script file. - const bool scriptFileExecuted = dAtob( Con::executef("exec", pLoadReadyModuleDefinition->getModuleScriptFilePath() ) ); + ConsoleValue cValue = Con::executef("exec", pLoadReadyModuleDefinition->getModuleScriptFilePath()); + const bool scriptFileExecuted = cValue.getBool(); // Did we execute the script file? if ( !scriptFileExecuted ) diff --git a/Engine/source/util/messaging/scriptMsgListener.cpp b/Engine/source/util/messaging/scriptMsgListener.cpp index fa47b7e7c..f64d2a6b2 100644 --- a/Engine/source/util/messaging/scriptMsgListener.cpp +++ b/Engine/source/util/messaging/scriptMsgListener.cpp @@ -121,7 +121,6 @@ IMPLEMENT_CALLBACK( ScriptMsgListener, onMessageReceived, bool, ( const char* qu bool ScriptMsgListener::onMessageReceived(StringTableEntry queue, const char* event, const char* data) { return onMessageReceived_callback(queue, event, data); - //return dAtob(Con::executef(this, "onMessageReceived", queue, event, data)); } IMPLEMENT_CALLBACK( ScriptMsgListener, onMessageObjectReceived, bool, ( const char* queue, Message *msg ), ( queue, msg ), @@ -135,7 +134,6 @@ IMPLEMENT_CALLBACK( ScriptMsgListener, onMessageObjectReceived, bool, ( const ch bool ScriptMsgListener::onMessageObjectReceived(StringTableEntry queue, Message *msg) { return onMessageObjectReceived_callback(queue, msg); - //return dAtob(Con::executef(this, "onMessageObjectReceived", queue, Con::getIntArg(msg->getId()))); } //----------------------------------------------------------------------------- @@ -150,7 +148,6 @@ IMPLEMENT_CALLBACK( ScriptMsgListener, onAddToQueue, void, ( const char* queue), void ScriptMsgListener::onAddToQueue(StringTableEntry queue) { - //Con::executef(this, "onAddToQueue", queue); onAddToQueue_callback(queue); IMLParent::onAddToQueue(queue); } @@ -176,7 +173,6 @@ IMPLEMENT_CALLBACK( ScriptMsgListener, onRemoveFromQueue, void, ( const char* qu void ScriptMsgListener::onRemoveFromQueue(StringTableEntry queue) { - //Con::executef(this, "onRemoveFromQueue", queue); onRemoveFromQueue_callback(queue); IMLParent::onRemoveFromQueue(queue); } From 58a79e0105a6a88848e4f21c77cf3b6220b2d1b3 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Fri, 24 Sep 2021 22:55:59 -0400 Subject: [PATCH 07/16] inputTest Module Update Updates the input event monitor to work with the current BaseGame template. --- Templates/Modules/inputTest/inputTest.tscript | 17 +++++++++++------ .../inputTest/scripts/gui/inputMonitor.gui | 2 +- .../inputTest/scripts/menuButtons.tscript | 8 +++++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Templates/Modules/inputTest/inputTest.tscript b/Templates/Modules/inputTest/inputTest.tscript index 7dad50618..07f27fc9f 100644 --- a/Templates/Modules/inputTest/inputTest.tscript +++ b/Templates/Modules/inputTest/inputTest.tscript @@ -4,6 +4,11 @@ function inputTest::create( %this ) { + // If addToMainMenu is true, a button to display the input monitor will be + // added to the MainMenu gui. If false, you will need to call + // "$GameCanvas.pushDialog(InputMonitorDlg);" from the console or add a + // shortcut somewhere else to access the Input Event Monitor. + %this.addToMainMenu = true; } function inputTest::destroy( %this ) @@ -13,12 +18,12 @@ function inputTest::destroy( %this ) function inputTest::initClient( %this ) { - %this.queueExec("/scripts/customProfiles." @ $TorqueScriptFileExtension); - %this.queueExec("/scripts/inputMonitor." @ $TorqueScriptFileExtension); - %this.queueExec("/scripts/gui/inputMonitor.gui"); - %this.queueExec("/scripts/joystickSettings." @ $TorqueScriptFileExtension); - %this.queueExec("/scripts/gui/joystickSettings.gui"); - %this.queueExec("/scripts/menuButtons." @ $TorqueScriptFileExtension); + %this.queueExec("./scripts/customProfiles." @ $TorqueScriptFileExtension); + %this.queueExec("./scripts/inputMonitor." @ $TorqueScriptFileExtension); + %this.queueExec("./scripts/gui/inputMonitor.gui"); + %this.queueExec("./scripts/joystickSettings." @ $TorqueScriptFileExtension); + %this.queueExec("./scripts/gui/joystickSettings.gui"); + %this.queueExec("./scripts/menuButtons." @ $TorqueScriptFileExtension); } function onSDLDeviceConnected(%sdlIndex, %deviceName, %deviceType) diff --git a/Templates/Modules/inputTest/scripts/gui/inputMonitor.gui b/Templates/Modules/inputTest/scripts/gui/inputMonitor.gui index 67708cf2e..c695016af 100644 --- a/Templates/Modules/inputTest/scripts/gui/inputMonitor.gui +++ b/Templates/Modules/inputTest/scripts/gui/inputMonitor.gui @@ -55,7 +55,7 @@ $guiContent = new GuiControl(InputMonitorDlg) { canSaveDynamicFields = "0"; }; new GuiChunkedBitmapCtrl() { - bitmap = "data/ui/art/hudfill.png"; + bitmap = "data/ui/images/hudfill.png"; useVariable = "0"; tile = "0"; position = "0 0"; diff --git a/Templates/Modules/inputTest/scripts/menuButtons.tscript b/Templates/Modules/inputTest/scripts/menuButtons.tscript index 471676a07..8f97d2262 100644 --- a/Templates/Modules/inputTest/scripts/menuButtons.tscript +++ b/Templates/Modules/inputTest/scripts/menuButtons.tscript @@ -2,6 +2,8 @@ // Add buttons to the MainMenu after all other scripts have been exec'ed. //----------------------------------------------------------------------------- +function inputTest::addMenuButton( %this ) +{ if (isObject(MainMenuGui)) { %testBtn = new GuiButtonCtrl() { @@ -56,4 +58,8 @@ } MMTestContainer.add(%testBtn); - } \ No newline at end of file + } +} + +if (inputTest.addToMainMenu) + inputTest.addMenuButton(); \ No newline at end of file From 666065ce6c59b917700c0c606843beb424212fe4 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Sat, 25 Sep 2021 02:48:30 -0400 Subject: [PATCH 08/16] GuiGameListMenuCtrl Update Methods to simplify managing localized option lists. Adds a text key to each option in an option row. Adds methods for getting the current selections index or key value. Adds methods for setting the current selection by index or key value. This change is backward compatible. If the new methods are not called, the control behavior is unaffected. --- .../gui/controls/guiGameListMenuCtrl.cpp | 144 +++++++++++++++++- .../source/gui/controls/guiGameListMenuCtrl.h | 54 ++++++- 2 files changed, 189 insertions(+), 9 deletions(-) diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index 61833a8d0..72b3d02f2 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -237,7 +237,7 @@ void GuiGameListMenuCtrl::onRenderListOption(Row* row, Point2I currentOffset) // calculate text to be at the center between the arrows GFont* font = profile->mFont; - StringTableEntry text = row->mOptions[row->mSelectedOption]; + StringTableEntry text = row->mOptions[row->mSelectedOption].mDisplayText; S32 textWidth = font->getStrWidth(text); S32 columnWidth = profile->mHitAreaLowerRight.x * xScale - profile->mRightPad - columnSplit; S32 columnCenter = columnSplit + (columnWidth >> 1); @@ -489,15 +489,18 @@ void GuiGameListMenuCtrl::addRow(const char* label, const char* optionsList, boo { static StringTableEntry DELIM = StringTable->insert("\t", true); Row* row = new Row(); - Vector options(__FILE__, __LINE__); + Vector options(__FILE__, __LINE__); S32 defaultOption = 0; S32 count = StringUnit::getUnitCount(optionsList, DELIM); for (S32 i = 0; i < count; ++i) { + OptionEntry e; const char* option = StringUnit::getUnit(optionsList, i, DELIM); - options.push_back(StringTable->insert(option, true)); + e.mDisplayText = StringTable->insert(option, true); + e.mKeyString = e.mDisplayText; + options.push_back(e); if (String::compare(option, defaultValue) == 0) defaultOption = options.size() - 1; @@ -1075,12 +1078,38 @@ StringTableEntry GuiGameListMenuCtrl::getCurrentOption(S32 rowIndex) const Row* row = (Row*)mRows[rowIndex]; if (row->mSelectedOption != NO_OPTION) { - return row->mOptions[row->mSelectedOption]; + return row->mOptions[row->mSelectedOption].mDisplayText; } } return StringTable->insert("", false); } +StringTableEntry GuiGameListMenuCtrl::getCurrentOptionKey(S32 rowIndex) const +{ + if (isValidRowIndex(rowIndex)) + { + Row* row = (Row*)mRows[rowIndex]; + if (row->mSelectedOption != NO_OPTION) + { + return row->mOptions[row->mSelectedOption].mKeyString; + } + } + return StringTable->insert("", false); +} + +S32 GuiGameListMenuCtrl::getCurrentOptionIndex(S32 rowIndex) const +{ + if (isValidRowIndex(rowIndex)) + { + Row* row = (Row*)mRows[rowIndex]; + if (row->mSelectedOption != NO_OPTION) + { + return row->mSelectedOption; + } + } + return S32(-1); +} + bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption) { if (!isValidRowIndex(rowIndex)) @@ -1090,9 +1119,9 @@ bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption) Row* row = (Row*)mRows[rowIndex]; - for (Vector::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption) + for (Vector::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption) { - if (String::compare(*anOption, theOption) == 0) + if (String::compare((*anOption).mDisplayText, theOption) == 0) { S32 newIndex = anOption - row->mOptions.begin(); row->mSelectedOption = newIndex; @@ -1103,6 +1132,45 @@ bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption) return false; } +bool GuiGameListMenuCtrl::selectOptionByKey(S32 rowIndex, const char* optionKey) +{ + if (!isValidRowIndex(rowIndex)) + { + return false; + } + + Row* row = (Row*)mRows[rowIndex]; + + for (Vector::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption) + { + if (String::compare((*anOption).mKeyString, optionKey) == 0) + { + S32 newIndex = anOption - row->mOptions.begin(); + row->mSelectedOption = newIndex; + return true; + } + } + + return false; +} + +bool GuiGameListMenuCtrl::selectOptionByIndex(S32 rowIndex, S32 optionIndex) +{ + if (!isValidRowIndex(rowIndex) || (optionIndex < 0)) + { + return false; + } + + Row* row = (Row*)mRows[rowIndex]; + if (optionIndex < row->mOptions.size()) + { + row->mSelectedOption = optionIndex; + return true; + } + + return false; +} + void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList) { static StringTableEntry DELIM = StringTable->insert("\t", true); @@ -1119,7 +1187,10 @@ void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList) for (S32 i = 0; i < count; ++i) { const char* option = StringUnit::getUnit(optionsList, i, DELIM); - row->mOptions[i] = StringTable->insert(option, true); + OptionEntry e; + e.mDisplayText = StringTable->insert(option, true); + e.mKeyString = e.mDisplayText; + row->mOptions[i] = e; } if (row->mSelectedOption >= row->mOptions.size()) @@ -1128,6 +1199,21 @@ void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList) } } +void GuiGameListMenuCtrl::addOption(S32 rowIndex, const char* displayText, const char* keyText) +{ + if (!isValidRowIndex(rowIndex)) + { + return; + } + + OptionEntry e; + e.mDisplayText = StringTable->insert(displayText, true); + e.mKeyString = (keyText[0] == '\0') ? e.mDisplayText : StringTable->insert(keyText, true); + + Row* row = (Row*)mRows[rowIndex]; + row->mOptions.push_back(e); +} + void GuiGameListMenuCtrl::clickOption(Row* row, S32 xPos) { GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile; @@ -1566,6 +1652,22 @@ DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOption, const char*, (S32 row) return object->getCurrentOption(row); } +DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOptionKey, const char*, (S32 row), , + "Gets the key string for the currently selected option of the given row.\n\n" + "@param row Index of the row to get the option from.\n" + "@return The key (or id) that was assigned to the selected option on the given row. If there is no selected option then the empty string is returned.") +{ + return object->getCurrentOptionKey(row); +} + +DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOptionIndex, S32, (S32 row), , + "Gets the index into the option list for the currently selected option of the given row.\n\n" + "@param row Index of the row to get the option from.\n" + "@return The index of the selected option on the given row. If there is no selected option then -1 is returned.") +{ + return object->getCurrentOptionIndex(row); +} + DefineEngineMethod(GuiGameListMenuCtrl, selectOption, bool, (S32 row, const char* option), , "Set the row's current option to the one specified\n\n" "@param row Index of the row to set an option on.\n" @@ -1575,6 +1677,24 @@ DefineEngineMethod(GuiGameListMenuCtrl, selectOption, bool, (S32 row, const char return object->selectOption(row, option); } +DefineEngineMethod(GuiGameListMenuCtrl, selectOptionByKey, bool, (S32 row, const char* optionKey), , + "Set the row's current option to the one with the specified key.\n\n" + "@param row Index of the row to set an option on.\n" + "@param optionKey The key string that was assigned to the option to be made active.\n" + "@return True if the row contained the key and the option and was set, false otherwise.") +{ + return object->selectOptionByKey(row, optionKey); +} + +DefineEngineMethod(GuiGameListMenuCtrl, selectOptionByIndex, bool, (S32 row, S32 optionIndex), , + "Set the row's current option to the one at the specified index.\n\n" + "@param row Index of the row to set an option on.\n" + "@param optionIndex The index of the option to be made active.\n" + "@return True if the index was valid and the option and was set, false otherwise.") +{ + return object->selectOptionByIndex(row, optionIndex); +} + DefineEngineMethod(GuiGameListMenuCtrl, setOptions, void, (S32 row, const char* optionsList), , "Sets the list of options on the given row.\n\n" "@param row Index of the row to set options on." @@ -1583,6 +1703,16 @@ DefineEngineMethod(GuiGameListMenuCtrl, setOptions, void, (S32 row, const char* object->setOptions(row, optionsList); } +DefineEngineMethod(GuiGameListMenuCtrl, addOption, void, (S32 row, const char* displayText, const char* keyText), (""), + "Adds an option to the list of options on the given row.\n\n" + "@param row Index of the row to add the option on.\n" + "@param displayText The text to display for this option.\n" + "@param keyText [Optional] The id string to associate with this value. " + "If unset, the id will be the same as the display text.\n") +{ + object->addOption(row, displayText, keyText); +} + DefineEngineMethod(GuiGameListMenuCtrl, getValue, F32, (S32 row), , "Sets the list of options on the given row.\n\n" "@param row Index of the row to set options on." diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.h b/Engine/source/gui/controls/guiGameListMenuCtrl.h index 15bbf49a3..3e6c3c7b0 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.h +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.h @@ -37,6 +37,18 @@ public: typedef GuiGameListMenuProfile Profile; protected: + + /// \struct OptionEntry + /// Display text and ID key for each entry in an option row. + struct OptionEntry + { + StringTableEntry mDisplayText; ///< The text that is displayed for the option + StringTableEntry mKeyString; ///< Key value that is associated with this option + OptionEntry() : mDisplayText(StringTable->EmptyString()), mKeyString(StringTable->EmptyString()) {} + virtual ~OptionEntry() {} + }; + + /// \struct Row /// Internal data representation of a single row in the control. struct Row @@ -60,7 +72,7 @@ protected: Mode mMode; //List options - Vector mOptions; ///< Collection of options available to display + Vector mOptions; ///< Collection of options available to display S32 mSelectedOption; ///< Index into mOptions pointing at the selected option bool mWrapOptions; ///< Determines if options should "wrap around" at the ends @@ -174,13 +186,43 @@ public: /// string is returned. StringTableEntry getCurrentOption(S32 rowIndex) const; + /// Gets the key string for the currently selected option of the given row + /// + /// \param rowIndex Index of the row to get the option from. + /// \return The key (or id) that was assigned to the selected option on the + /// given row. If there is no selected option then the empty string is returned. + StringTableEntry getCurrentOptionKey(S32 rowIndex) const; + + /// Gets the index into the option list for the currently selected option of the given row. + /// + /// \param rowIndex Index of the row to get the option from. + /// \return The index of the selected option on the given row. If there is no + /// selected option then -1 is returned. + S32 getCurrentOptionIndex(S32 rowIndex) const; + /// Attempts to set the given row to the specified selected option. The option /// will only be set if the option exists in the control. /// /// \param rowIndex Index of the row to set an option on. /// \param option The option to be made active. /// \return True if the row contained the option and was set, false otherwise. - bool selectOption(S32 rowIndex, StringTableEntry option); + bool selectOption(S32 rowIndex, const char* option); + + /// Attempts to set the given row to the option with the specified key. The + /// option will only be set if the key exists in the control. + /// + /// \param rowIndex Index of the row to set an option on. + /// \param optionKey The key string that was assigned to the option to be made active. + /// \return True if the row contained the key and the option and was set, false otherwise. + bool selectOptionByKey(S32 rowIndex, const char* optionKey); + + /// Attempts to set the given row to the option at the specified index. The option + /// will only be set if the index is valid. + /// + /// \param rowIndex Index of the row to set an option on. + /// \param optionIndex The index of the option to be made active. + /// \return True if the index was valid and the option and was set, false otherwise. + bool selectOptionByIndex(S32 rowIndex, S32 optionIndex); /// Sets the list of options on the given row. /// @@ -188,6 +230,14 @@ public: /// \param optionsList A tab separated list of options for the control. void setOptions(S32 rowIndex, const char* optionsList); + /// Adds an option to the list of options on the given row. + /// + /// \param rowIndex Index of the row to set options on. + /// \param displayText The text to display for this option. + /// \param keyText The id string to associate with this value. If NULL the + /// id will be the same as the display text. + void addOption(S32 rowIndex, const char* displayText, const char* keyText); + /// Activates the current row. The script callback of the current row will /// be called (if it has one). virtual void activateRow(); From 737fd70c6946f4fa6763d4597c14962bf738c28d Mon Sep 17 00:00:00 2001 From: Areloch Date: Mon, 27 Sep 2021 18:46:20 -0500 Subject: [PATCH 09/16] Adjusted handling of field converts in the project importer to deal with fields that didn't contain quotation marks --- .../scripts/projectImporter.tscript | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript b/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript index 039a71238..eca0e0b07 100644 --- a/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript +++ b/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript @@ -516,31 +516,24 @@ function testFilenameExtensions(%filename) function processLegacyField(%line, %originalFieldName, %newFieldName) { - if(!strIsMatchExpr("*"@%originalFieldName@"=*\"*\";*", %line) && - !strIsMatchExpr("*"@%originalFieldName@"[*=*\"*\";*", %line) && - !strIsMatchExpr("*"@%originalFieldName@" *=*\"*\";*", %line)) + if(!strIsMatchExpr("*"@%originalFieldName@"=*;*", %line) && + !strIsMatchExpr("*"@%originalFieldName@"[*=*;*", %line) && + !strIsMatchExpr("*"@%originalFieldName@" *=*;*", %line)) return %line; %outLine = strreplace(%line, %originalFieldName, %newFieldName); //get the value %value = ""; - %pos = strpos(%outLine, "= \""); + %pos = strpos(%outLine, "="); if(%pos != -1) { - %endPos = strpos(%outLine, "\";", %pos); + %endPos = strpos(%outLine, ";", %pos); + %value = getSubStr(%outLine, %pos+1, %endPos-%pos-1); - %value = getSubStr(%outLine, %pos+3, %endPos-%pos-3); - } - else - { - %pos = strpos(%outLine, "=\""); - if(%pos != -1) - { - %endPos = strpos(%outLine, "\";", %pos); - - %value = getSubStr(%outLine, %pos+2, %endPos-%pos-2); - } + %originalValue = %value; + %value = trim(%value); + %value = strreplace(%value, "\"", ""); } if(%outLine !$= %line && %pos != -1 && %endPos != -1 && %value !$= "") @@ -557,8 +550,13 @@ function processLegacyField(%line, %originalFieldName, %newFieldName) if(isObject(%targetFilename)) { - if(%originalFieldName $= "soundProfile") + //likely a material name, so handle it that way + %assetId = MaterialAsset::getAssetIdByMaterialName(%targetFilename); + + if(%assetId $= "" || %assetId $= "Core_Rendering:NoMaterial") { + //if not, just do a lookup directly to see if it was another asset by that name + //e.g. sound profiles when converted will match names $ProjectImporter::assetQuery.clear(); %foundAssets = AssetDatabase.findAssetName($ProjectImporter::assetQuery, %targetFilename); if(%foundAssets != 0) @@ -566,11 +564,6 @@ function processLegacyField(%line, %originalFieldName, %newFieldName) %assetId = $ProjectImporter::assetQuery.getAsset(0); } } - else - { - //likely a material name, so handle it that way - %assetId = MaterialAsset::getAssetIdByMaterialName(%targetFilename); - } } else { @@ -605,6 +598,11 @@ function processLegacyField(%line, %originalFieldName, %newFieldName) if(%assetId !$= "" && AssetDatabase.isDeclaredAsset(%assetId)) { echo("Legacy Project Importer - processing of legacy field line's value: " @ %value @ " has found a matching AssetId: " @ %assetId); + + //double check if this already had the quotes around the value or not + if(!strIsMatchExpr("*\"*\"*", %originalValue)) + %assetId = "\"" @ %assetId @ "\""; + //if (%assetId.getStatusString() $= "Ok") %outLine = strReplace(%outLine, %value, %assetId); //else From e035aa911481d237a40c0467089df536f00883c0 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Tue, 28 Sep 2021 05:38:17 -0400 Subject: [PATCH 10/16] GuiCanvas Callbacks Adds handler modes for keyboard translations and native accelerators. This is needed so APIs that provide software keyboards can be notified when controls that require text input become active. This was previously hardcoded in OpenVROverlay, but is also needed by Steam Input and Big Picture so moving to GuiCanvas will make it accessible there as well. Handler mode for both settings default to "Platform" so there is no change to the default behavior. If the setting is changed to "Callback", callbacks will be triggered to allow script to determine if the request should fall through to the platform window. The script callback is also the appropriate place to display a software keyboard and attach it to the input control. --- Engine/source/gui/core/guiCanvas.cpp | 60 +++++++++++++++++++++++++--- Engine/source/gui/core/guiCanvas.h | 19 +++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 967c3e7d7..8ad674474 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -94,6 +94,33 @@ ConsoleDocClass( GuiCanvas, "@ingroup GuiCore\n"); + ImplementEnumType(KeyboardTranslationMode, + "Modes for handling keyboard translation or native accelerator requests.\n\n") + { GuiCanvas::TranslationMode_Platform, "Platform", + "Requests will be passed to the platform window for handling." }, + { GuiCanvas::TranslationMode_Callback, "Callback", + "Script callbacks will be issued to notify and allow override of these events." }, + { GuiCanvas::TranslationMode_Ignore, "Ignore", + "Requsts to enable/disable keyboard translations or native accelerators will be ignored " + "with no callback triggered." }, + EndImplementEnumType; + + IMPLEMENT_CALLBACK(GuiCanvas, onSetKeyboardTranslationEnabled, bool, (bool enable), (enable), + "Called when the canvas receives an enableKeyboardTranslation request. This is usually the " + "result of a GuitTextInputCtrl gaining or losing focus. Return false to allow the request " + "to be passed to the platform window. Return true to override the request and handle it in script.\n\n" + "@note This callback is only issued if keyTranslationMode is set to \"Callback\" for this canvas.\n" + "@param enable Requested keyboard translation state.\n" + "@see KeyboardTranslationMode\n"); + + IMPLEMENT_CALLBACK(GuiCanvas, onSetNativeAcceleratorsEnabled, bool, (bool enable), (enable), + "Called when the canvas receives a setNativeAcceleratorsEnabled request. This is usually the " + "result of a GuitTextInputCtrl gaining or losing focus. Return false to allow the request to " + "be passed to the platform window. Return true to override the request and handle it in script.\n\n" + "@note This callback is only issued if nativeAcceleratorMode is set to \"Callback\" for this canvas.\n" + "@param enable Requested accelerator state.\n" + "@see KeyboardTranslationMode\n"); + ColorI gCanvasClearColor( 255, 0, 255 ); ///< For GFX->clear extern InputModifiers convertModifierBits(const U32 in); @@ -127,6 +154,8 @@ GuiCanvas::GuiCanvas(): GuiControl(), mHoverPositionSet(false), mLeftMouseLast(false), mHoverLeftControlTime(0), + mKeyTranslationMode(TranslationMode_Platform), + mNativeAcceleratorMode(TranslationMode_Platform), mMiddleMouseLast(false), mRightMouseLast(false), mMouseDownPoint(0.0f,0.0f), @@ -183,6 +212,13 @@ void GuiCanvas::initPersistFields() addField("displayWindow", TypeBool, Offset(mDisplayWindow, GuiCanvas), "Controls if the canvas window is rendered or not." ); endGroup("Canvas Rendering"); + addGroup("KeyboardMode Callbacks"); + addField("keyTranslationMode", TYPEID< KeyTranslationMode >(), Offset(mKeyTranslationMode, GuiCanvas), + "How to handle enable/disable keyboard translation requests. \"Platform\", \"Callback\" or \"Ignore\".\n"); + addField("nativeAcceleratorMode", TYPEID< KeyTranslationMode >(), Offset(mNativeAcceleratorMode, GuiCanvas), + "How to handle enable/disable native accelerator requests. \"Platform\", \"Callback\" or \"Ignore\".\n"); + endGroup("KeyboardMode Callbacks"); + Parent::initPersistFields(); } @@ -442,20 +478,32 @@ Point2I GuiCanvas::getWindowSize() void GuiCanvas::enableKeyboardTranslation() { - AssertISV(mPlatformWindow, "GuiCanvas::enableKeyboardTranslation - no window present!"); - mPlatformWindow->setKeyboardTranslation(true); + if ((mKeyTranslationMode == TranslationMode_Platform) || + ((mKeyTranslationMode == TranslationMode_Callback) && onSetKeyboardTranslationEnabled_callback(true))) + { + AssertISV(mPlatformWindow, "GuiCanvas::enableKeyboardTranslation - no window present!"); + mPlatformWindow->setKeyboardTranslation(true); + } } void GuiCanvas::disableKeyboardTranslation() { - AssertISV(mPlatformWindow, "GuiCanvas::disableKeyboardTranslation - no window present!"); - mPlatformWindow->setKeyboardTranslation(false); + if ((mKeyTranslationMode == TranslationMode_Platform) || + ((mKeyTranslationMode == TranslationMode_Callback) && onSetKeyboardTranslationEnabled_callback(false))) + { + AssertISV(mPlatformWindow, "GuiCanvas::disableKeyboardTranslation - no window present!"); + mPlatformWindow->setKeyboardTranslation(false); + } } void GuiCanvas::setNativeAcceleratorsEnabled( bool enabled ) { - AssertISV(mPlatformWindow, "GuiCanvas::setNativeAcceleratorsEnabled - no window present!"); - mPlatformWindow->setAcceleratorsEnabled( enabled ); + if ((mNativeAcceleratorMode == TranslationMode_Platform) || + ((mNativeAcceleratorMode == TranslationMode_Callback) && onSetNativeAcceleratorsEnabled_callback(enabled))) + { + AssertISV(mPlatformWindow, "GuiCanvas::setNativeAcceleratorsEnabled - no window present!"); + mPlatformWindow->setAcceleratorsEnabled(enabled); + } } void GuiCanvas::setForceMouseToGUI(bool onOff) diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index f9f4a37af..fdb1cfd25 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -178,6 +178,19 @@ protected: bool mHoverPositionSet; U32 mHoverLeftControlTime; +public: + /// Setting for how to handle 'enableKeyboardTranslation' and 'setNativeAcceleratorsEnabled' requests. + enum KeyTranslationMode + { + TranslationMode_Platform, + TranslationMode_Callback, + TranslationMode_Ignore, + }; + +protected: + KeyTranslationMode mKeyTranslationMode; + KeyTranslationMode mNativeAcceleratorMode; + /// @} // Internal event handling callbacks for use with PlatformWindow. @@ -454,6 +467,10 @@ public: virtual void setWindowTitle(const char *newTitle); + DECLARE_CALLBACK(bool, onSetKeyboardTranslationEnabled, (bool enable)); + DECLARE_CALLBACK(bool, onSetNativeAcceleratorsEnabled, (bool enable)); + + private: static const U32 MAX_GAMEPADS = 4; ///< The maximum number of supported gamepads protected: @@ -464,5 +481,7 @@ private: void setConsumeLastInputEvent(bool flag) { mConsumeLastInputEvent = flag; } bool getLastCursorPoint(Point2I& pt) const { pt = mLastCursorPt; return mLastCursorEnabled; } }; +typedef GuiCanvas::KeyTranslationMode KeyboardTranslationMode; +DefineEnumType(KeyboardTranslationMode); #endif From 37c924512c4bb7856de65d35b8fa8ff4204214b1 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Tue, 28 Sep 2021 05:52:45 -0400 Subject: [PATCH 11/16] Corrects console documentation. --- Engine/source/gui/core/guiCanvas.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 8ad674474..96022edaa 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -107,16 +107,16 @@ ConsoleDocClass( GuiCanvas, IMPLEMENT_CALLBACK(GuiCanvas, onSetKeyboardTranslationEnabled, bool, (bool enable), (enable), "Called when the canvas receives an enableKeyboardTranslation request. This is usually the " - "result of a GuitTextInputCtrl gaining or losing focus. Return false to allow the request " - "to be passed to the platform window. Return true to override the request and handle it in script.\n\n" + "result of a GuitTextInputCtrl gaining or losing focus. Return true to allow the request " + "to be passed to the platform window. Return false to override the request and handle it in script.\n\n" "@note This callback is only issued if keyTranslationMode is set to \"Callback\" for this canvas.\n" "@param enable Requested keyboard translation state.\n" "@see KeyboardTranslationMode\n"); IMPLEMENT_CALLBACK(GuiCanvas, onSetNativeAcceleratorsEnabled, bool, (bool enable), (enable), "Called when the canvas receives a setNativeAcceleratorsEnabled request. This is usually the " - "result of a GuitTextInputCtrl gaining or losing focus. Return false to allow the request to " - "be passed to the platform window. Return true to override the request and handle it in script.\n\n" + "result of a GuitTextInputCtrl gaining or losing focus. Return true to allow the request to " + "be passed to the platform window. Return false to override the request and handle it in script.\n\n" "@note This callback is only issued if nativeAcceleratorMode is set to \"Callback\" for this canvas.\n" "@param enable Requested accelerator state.\n" "@see KeyboardTranslationMode\n"); From c5d5a9135645bd87920cd4d2e091711c2e12b8dd Mon Sep 17 00:00:00 2001 From: Areloch Date: Tue, 28 Sep 2021 18:17:49 -0500 Subject: [PATCH 12/16] Add handling to RotationF's addRotation function to ensure formatted return --- Engine/source/math/mRotation.cpp | 11 +++++++++-- Engine/source/math/mathTypes.cpp | 12 ++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Engine/source/math/mRotation.cpp b/Engine/source/math/mRotation.cpp index 43b696d4a..18114c58d 100644 --- a/Engine/source/math/mRotation.cpp +++ b/Engine/source/math/mRotation.cpp @@ -325,14 +325,21 @@ TEST(Maths, RotationF_Calculations) }; #endif -DefineEngineFunction(AddRotation, RotationF, (RotationF a, RotationF b), , +DefineEngineFunction(AddRotation, RotationF, (RotationF a, RotationF b, const char* returnType), ("Euler"), "Adds two rotations together.\n" "@param a Rotation one." "@param b Rotation two." "@returns v sum of both rotations." "@ingroup Math") { - return a + b; + RotationF ret; + RotationF sum = a + b; + if (String(returnType) == String("Euler")) + ret.set(sum.asEulerF()); + else + ret.set(sum.asAxisAngle()); + + return ret; } DefineEngineFunction(SubtractRotation, RotationF, (RotationF a, RotationF b), , diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index 14c7335e8..70ac9adf7 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -620,8 +620,16 @@ ConsoleGetType(TypeRotationF) static const U32 bufSize = 256; char* returnBuffer = Con::getReturnBuffer(bufSize); - EulerF out = pt->asEulerF(RotationF::Degrees); - dSprintf(returnBuffer, bufSize, "%g %g %g", out.x, out.y, out.z); + if (pt->mRotationType == RotationF::Euler) + { + EulerF out = pt->asEulerF(RotationF::Degrees); + dSprintf(returnBuffer, bufSize, "%g %g %g", out.x, out.y, out.z); + } + 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); + } return returnBuffer; } From 1676d102f35cc588bf717897ff5e5bc35125a046 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Sat, 2 Oct 2021 16:22:55 -0400 Subject: [PATCH 13/16] * [AssetBrowser] BugFix: Correct a logic error in the filtering of the asset browser causing tags queries to display all assets. --- .../game/tools/assetBrowser/scripts/assetBrowser.tscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript index 747d3e86d..660577c78 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript @@ -1802,7 +1802,7 @@ function matchesSearch(%assetName, %assetType) } else { - if(%assetName.tags !$= %word) + if(strstr(strlwr(%assetName.tags), strlwr(%word)) != -1) %matchTags = true; } } From 5e88ab25708cb9771d99fb5b1e5c02d94586a9d6 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Fri, 1 Oct 2021 21:34:45 -0400 Subject: [PATCH 14/16] * BugFix: Fix AL device listing so that functions like sfxGetAvailableDevices return the actual devices on the system. --- Engine/source/sfx/openal/aldlist.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Engine/source/sfx/openal/aldlist.cpp b/Engine/source/sfx/openal/aldlist.cpp index a453579e3..8f7c0d4a6 100644 --- a/Engine/source/sfx/openal/aldlist.cpp +++ b/Engine/source/sfx/openal/aldlist.cpp @@ -56,7 +56,7 @@ ALDeviceList::ALDeviceList( const OPENALFNTABLE &oalft ) // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices if (ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) { - devices = (char *)ALFunction.alcGetString(NULL, ALC_DEVICE_SPECIFIER); + devices = (char *)ALFunction.alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); index = 0; // go through device list (each device terminated with a single NULL, list terminated with double NULL) @@ -70,7 +70,7 @@ ALDeviceList::ALDeviceList( const OPENALFNTABLE &oalft ) if (context) { ALFunction.alcMakeContextCurrent(context); // if new actual device name isn't already in the list, then add it... - actualDeviceName = ALFunction.alcGetString(device, ALC_DEVICE_SPECIFIER); + actualDeviceName = devices; bool bNewName = true; for (int i = 0; i < GetNumDevices(); i++) { if (String::compare(GetDeviceName(i), actualDeviceName) == 0) { @@ -313,4 +313,4 @@ unsigned int ALDeviceList::GetMaxNumSources() } return iSourceCount; -} \ No newline at end of file +} From 43630c31c2938efb107eca01494fd73633e56fea Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Sat, 2 Oct 2021 22:24:11 -0400 Subject: [PATCH 15/16] * BugFix: Tweaks to the ALC device listing logic to be more consistent with the AL API. --- Engine/source/sfx/openal/aldlist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/sfx/openal/aldlist.cpp b/Engine/source/sfx/openal/aldlist.cpp index 8f7c0d4a6..51f5a3b51 100644 --- a/Engine/source/sfx/openal/aldlist.cpp +++ b/Engine/source/sfx/openal/aldlist.cpp @@ -55,9 +55,9 @@ ALDeviceList::ALDeviceList( const OPENALFNTABLE &oalft ) defaultDeviceIndex = 0; // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices - if (ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) { + if (ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { devices = (char *)ALFunction.alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); - defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); + defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); index = 0; // go through device list (each device terminated with a single NULL, list terminated with double NULL) while (*devices != 0) { From 6a94946e5b1621b2e0e2bdce45e016816f247b21 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Sat, 2 Oct 2021 22:29:34 -0400 Subject: [PATCH 16/16] * BugFix: Fallback to ALC_ENUMERATION_EXT if ALC_ENUMERATE_ALL_EXT is not available. --- Engine/source/sfx/openal/aldlist.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Engine/source/sfx/openal/aldlist.cpp b/Engine/source/sfx/openal/aldlist.cpp index 51f5a3b51..73307f50b 100644 --- a/Engine/source/sfx/openal/aldlist.cpp +++ b/Engine/source/sfx/openal/aldlist.cpp @@ -55,9 +55,20 @@ ALDeviceList::ALDeviceList( const OPENALFNTABLE &oalft ) defaultDeviceIndex = 0; // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices - if (ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { - devices = (char *)ALFunction.alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); - defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); + const bool enumerationExtensionPresent = ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); + const bool enumerateAllExtensionPresent = ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"); + if (enumerateAllExtensionPresent || enumerationExtensionPresent) { + if (enumerateAllExtensionPresent) + { + devices = (char *)ALFunction.alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); + defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); + } + else + { + devices = (char *)ALFunction.alcGetString(NULL, ALC_DEVICE_SPECIFIER); + defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); + } + index = 0; // go through device list (each device terminated with a single NULL, list terminated with double NULL) while (*devices != 0) {