summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorKitty Barnett <develop@catznip.com>2024-09-03 18:14:06 +0200
committerKitty Barnett <develop@catznip.com>2024-09-03 18:14:22 +0200
commitdb8916454457e3e4856fddcbbafe66b3766e4ffa (patch)
tree359eb0fff468c9b401e8fc6b6e430d4cb77891dd /indra
parent4f7eb9b12e9c7eeb9f3ee0980bd4616df7d678b6 (diff)
Add the RLVa console
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/rlvdefines.h1
-rw-r--r--indra/newview/rlvfloaters.cpp95
-rw-r--r--indra/newview/rlvfloaters.h40
-rw-r--r--indra/newview/rlvhandler.cpp6
-rw-r--r--indra/newview/rlvhandler.h15
-rw-r--r--indra/newview/rlvhelper.cpp38
-rw-r--r--indra/newview/rlvhelper.h5
-rw-r--r--indra/newview/skins/default/xui/en/floater_rlv_console.xml73
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml5
11 files changed, 255 insertions, 27 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a7bbadfd86..e3f675cb8e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -728,6 +728,7 @@ set(viewer_SOURCE_FILES
pipeline.cpp
rlvactions.cpp
rlvcommon.cpp
+ rlvfloaters.cpp
rlvhelper.cpp
rlvhandler.cpp
)
@@ -1393,6 +1394,7 @@ set(viewer_HEADER_FILES
rlvdefines.h
rlvactions.h
rlvcommon.h
+ rlvfloaters.h
rlvhelper.h
rlvhandler.h
roles_constants.h
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 9bdd246129..e41d8c44fb 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -175,6 +175,7 @@
#include "llpreviewtexture.h"
#include "llscriptfloater.h"
#include "llsyswellwindow.h"
+#include "rlvfloaters.h"
// *NOTE: Please add files in alphabetical order to keep merges easy.
@@ -480,6 +481,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("region_debug_console", "floater_region_debug_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionDebugConsole>);
LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>);
LLFloaterReg::add("region_restarting", "floater_region_restarting.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionRestarting>);
+ LLFloaterReg::add("rlv_console", "floater_rlv_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<Rlv::FloaterConsole>);
LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index c36512007b..88dffa1127 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -52,6 +52,7 @@ namespace Rlv
namespace Constants
{
constexpr char CmdPrefix = '@';
+ constexpr char ConsolePrompt[] = "> ";
constexpr std::string_view OptionSeparator = ";";
}
}
diff --git a/indra/newview/rlvfloaters.cpp b/indra/newview/rlvfloaters.cpp
new file mode 100644
index 0000000000..8d107b2540
--- /dev/null
+++ b/indra/newview/rlvfloaters.cpp
@@ -0,0 +1,95 @@
+#include "llviewerprecompiledheaders.h"
+
+#include "llagentdata.h"
+#include "llchatentry.h"
+#include "lltexteditor.h"
+#include "lltrans.h"
+#include "llvoavatarself.h"
+
+#include "rlvfloaters.h"
+#include "rlvhandler.h"
+
+using namespace Rlv;
+
+// ============================================================================
+// FloaterConsole
+//
+
+bool FloaterConsole::postBuild()
+{
+ mInputEdit = getChild<LLChatEntry>("console_input");
+ mInputEdit->setCommitCallback(std::bind(&FloaterConsole::onInput, this));
+ mInputEdit->setTextExpandedCallback(std::bind(&FloaterConsole::reshapeLayoutPanel, this));
+ mInputEdit->setFocus(true);
+ mInputEdit->setCommitOnFocusLost(false);
+
+ mInputPanel = getChild<LLLayoutPanel>("input_panel");
+ mInputEditPad = mInputPanel->getRect().getHeight() - mInputEdit->getRect().getHeight();
+
+ mOutputText = getChild<LLTextEditor>("console_output");
+ mOutputText->appendText(Constants::ConsolePrompt, false);
+
+ if (RlvHandler::isEnabled())
+ {
+ mCommandOutputConn = RlvHandler::instance().setCommandOutputCallback([this](const RlvCommand& rlvCmd, S32, const std::string strText)
+ {
+ if (rlvCmd.getObjectID() == gAgentID)
+ {
+ mOutputText->appendText(rlvCmd.getBehaviour() + ": ", true);
+ mOutputText->appendText(strText, false);
+ }
+ });
+ }
+
+ return true;
+}
+
+void FloaterConsole::onClose(bool fQuitting)
+{
+ if (RlvHandler::isEnabled())
+ {
+ RlvHandler::instance().processCommand(gAgentID, "clear", true);
+ }
+}
+
+void FloaterConsole::onInput()
+{
+ if (!isAgentAvatarValid())
+ {
+ return;
+ }
+
+ std::string strText = mInputEdit->getText();
+ LLStringUtil::trim(strText);
+
+ mOutputText->appendText(strText, false);
+ mInputEdit->setText(LLStringUtil::null);
+
+ if (!RlvHandler::isEnabled())
+ {
+ mOutputText->appendText(LLTrans::getString("RlvConsoleDisable"), true);
+ }
+ else if (strText.length() <= 3 || Constants::CmdPrefix != strText[0])
+ {
+ mOutputText->appendText(LLTrans::getString("RlvConsoleInvalidCmd"), true);
+ }
+ else
+ {
+ LLChat chat;
+ chat.mFromID = gAgentID;
+ chat.mChatType = CHAT_TYPE_OWNER;
+
+ RlvHandler::instance().handleSimulatorChat(strText, chat, gAgentAvatarp);
+
+ mOutputText->appendText(strText, true);
+ }
+
+ mOutputText->appendText(Constants::ConsolePrompt, true);
+}
+
+void FloaterConsole::reshapeLayoutPanel()
+{
+ mInputPanel->reshape(mInputPanel->getRect().getWidth(), mInputEdit->getRect().getHeight() + mInputEditPad, false);
+}
+
+// ============================================================================
diff --git a/indra/newview/rlvfloaters.h b/indra/newview/rlvfloaters.h
new file mode 100644
index 0000000000..a599bb051a
--- /dev/null
+++ b/indra/newview/rlvfloaters.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "llfloater.h"
+
+#include "rlvdefines.h"
+
+class LLChatEntry;
+class LLLayoutPanel;
+class LLTextEditor;
+class RlvCommand;
+class RlvHandler;
+
+namespace Rlv
+{
+ // ============================================================================
+ // FloaterConsole - debug console to allow command execution without the need for a script
+ //
+
+ class FloaterConsole : public LLFloater
+ {
+ friend class LLFloaterReg;
+ FloaterConsole(const LLSD& sdKey) : LLFloater(sdKey) {}
+
+ public:
+ bool postBuild() override;
+ void onClose(bool fQuitting) override;
+ protected:
+ void onInput();
+ void reshapeLayoutPanel();
+
+ private:
+ boost::signals2::scoped_connection mCommandOutputConn;
+ int mInputEditPad = 0;
+ LLLayoutPanel* mInputPanel = nullptr;
+ LLChatEntry* mInputEdit = nullptr;
+ LLTextEditor* mOutputText = nullptr;
+ };
+
+ // ============================================================================
+};
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index 8b2620cf48..0a0da0e25d 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -1,6 +1,5 @@
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
-#include "llappviewer.h"
#include "llstartup.h"
#include "llviewercontrol.h"
#include "llviewerobject.h"
@@ -38,7 +37,7 @@ bool RlvHandler::handleSimulatorChat(std::string& message, const LLChat& chat, c
message.erase(0, 1);
LLStringUtil::toLower(message);
- CommandDbgOut cmdDbgOut(message);
+ CommandDbgOut cmdDbgOut(message, chatObj->getID() == gAgentID);
boost_tokenizer tokens(message, boost::char_separator<char>(",", "", boost::drop_empty_tokens));
for (const std::string& strCmd : tokens)
@@ -128,7 +127,7 @@ ECmdRet CommandHandlerBaseImpl<EParamType::Reply>::processCommand(const RlvComma
{
// Sanity check - <param> should specify a - valid - reply channel
S32 nChannel;
- if (!LLStringUtil::convertToS32(rlvCmd.getParam(), nChannel) || !Util::isValidReplyChannel(nChannel, rlvCmd.getObjectID() == gAgent.getID()))
+ if (!LLStringUtil::convertToS32(rlvCmd.getParam(), nChannel) || !Util::isValidReplyChannel(nChannel, rlvCmd.getObjectID() == gAgentID))
return ECmdRet::FailedParam;
std::string strReply;
@@ -141,6 +140,7 @@ ECmdRet CommandHandlerBaseImpl<EParamType::Reply>::processCommand(const RlvComma
{
Util::sendChatReply(nChannel, strReply);
}
+ RlvHandler::instance().mOnCommandOutput(rlvCmd, nChannel, strReply);
return eRet;
}
diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h
index a5e91548ef..7fa4da767a 100644
--- a/indra/newview/rlvhandler.h
+++ b/indra/newview/rlvhandler.h
@@ -13,6 +13,8 @@ class LLViewerObject;
class RlvHandler : public LLSingleton<RlvHandler>
{
+ template<Rlv::EParamType> friend struct Rlv::CommandHandlerBaseImpl;
+
LLSINGLETON_EMPTY_CTOR(RlvHandler);
/*
@@ -25,12 +27,25 @@ public:
protected:
Rlv::ECmdRet processCommand(std::reference_wrapper<const RlvCommand> rlvCmdRef, bool fromObj);
+ /*
+ * Helper functions
+ */
public:
// Initialization (deliberately static so they can safely be called in tight loops)
static bool canEnable();
static bool isEnabled() { return mIsEnabled; }
static bool setEnabled(bool enable);
+ /*
+ * Event handling
+ */
+public:
+ // The command output signal is triggered whenever a command produces channel or debug output
+ using command_output_signal_t = boost::signals2::signal<void (const RlvCommand&, S32, const std::string&)>;
+ boost::signals2::connection setCommandOutputCallback(const command_output_signal_t::slot_type& cb) { return mOnCommandOutput.connect(cb); }
+
+protected:
+ command_output_signal_t mOnCommandOutput;
private:
static bool mIsEnabled;
};
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
index aad615d813..ecb76a1db3 100644
--- a/indra/newview/rlvhelper.cpp
+++ b/indra/newview/rlvhelper.cpp
@@ -250,21 +250,13 @@ namespace Rlv
void CommandDbgOut::add(std::string strCmd, ECmdRet eRet)
{
- ECmdRet resultBucket;
-
- // Successful and retained commands are added as-is
- if (isReturnCodeSuccess(eRet))
- resultBucket = ECmdRet::Success;
- else if (ECmdRet::Retained == eRet)
- resultBucket = ECmdRet::Retained;
- else
- {
- // Failed commands get the failure reason appended to help troubleshooting
- resultBucket = ECmdRet::Failed;
- strCmd.append(llformat(" (%s)", getReturnCodeString(eRet).c_str()));
- }
+ const std::string strSuffix = getReturnCodeString(eRet);
+ if (!strSuffix.empty())
+ strCmd.append(llformat(" (%s)", strSuffix.c_str()));
+ else if (mForConsole)
+ return; // Only show console feedback on successful commands when there's an informational notice
- std::string& strResult = mCommandResults[resultBucket];
+ std::string& strResult = mCommandResults[isReturnCodeSuccess(eRet) ? ECmdRet::Success : (ECmdRet::Retained == eRet ? ECmdRet::Retained : ECmdRet::Failed)];
if (!strResult.empty())
strResult.append(", ");
strResult.append(strCmd);
@@ -273,23 +265,25 @@ namespace Rlv
std::string CommandDbgOut::get() const {
std::ostringstream result;
- if (1 == mCommandResults.size())
+ if (1 == mCommandResults.size() && !mForConsole)
{
auto it = mCommandResults.begin();
- result << " " << getDebugVerbFromReturnCode(it->first) << ": @" << it->second;;
+ result << " " << getDebugVerbFromReturnCode(it->first) << ": @" << it->second;
}
- else if (mCommandResults.size() > 1)
+ else if (!mCommandResults.empty())
{
auto appendResult = [&](ECmdRet eRet, const std::string& name)
{
auto it = mCommandResults.find(eRet);
if (it == mCommandResults.end()) return;
- result << "\n - " << LLTrans::getString(name) << ": @" << it->second;
+ if (!mForConsole) result << "\n - ";
+ result << LLTrans::getString(name) << ": @" << it->second;
};
- result << ": @" << mOrigCmd;
- appendResult(ECmdRet::Success, "RlvDebugExecuted");
- appendResult(ECmdRet::Failed, "RlvDebugFailed");
- appendResult(ECmdRet::Retained, "RlvDebugRetained");
+ if (!mForConsole)
+ result << ": @" << mOrigCmd;
+ appendResult(ECmdRet::Success, !mForConsole ? "RlvDebugExecuted" : "RlvConsoleExecuted");
+ appendResult(ECmdRet::Failed, !mForConsole ? "RlvDebugFailed" : "RlvConsoleFailed");
+ appendResult(ECmdRet::Retained, !mForConsole ? "RlvDebugRetained" : "RlvConsoleRetained");
}
return result.str();
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
index 802b1cbadd..644cd0ee22 100644
--- a/indra/newview/rlvhelper.h
+++ b/indra/newview/rlvhelper.h
@@ -141,7 +141,7 @@ namespace Rlv
template<EBehaviour templBhvr> using ForceHandler = CommandHandler<EParamType::Force, templBhvr>;
template<EBehaviour templBhvr> using ReplyHandler = CommandHandler<EParamType::Reply, templBhvr>;
- // List of shared handlers
+ // List of shared handlers
using VersionReplyHandler = ReplyHandler<EBehaviour::Version>; // Shared between @version and @versionnew
//
@@ -192,7 +192,7 @@ namespace Rlv
struct CommandDbgOut
{
- CommandDbgOut(const std::string& orig_cmd) : mOrigCmd(orig_cmd) {}
+ CommandDbgOut(const std::string& orig_cmd, bool for_console) : mOrigCmd(orig_cmd), mForConsole(for_console) {}
void add(std::string strCmd, ECmdRet eRet);
std::string get() const;
static std::string getDebugVerbFromReturnCode(ECmdRet eRet);
@@ -200,6 +200,7 @@ namespace Rlv
private:
std::string mOrigCmd;
std::map<ECmdRet, std::string> mCommandResults;
+ bool mForConsole = false;
};
}
diff --git a/indra/newview/skins/default/xui/en/floater_rlv_console.xml b/indra/newview/skins/default/xui/en/floater_rlv_console.xml
new file mode 100644
index 0000000000..928d50cb41
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_rlv_console.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ min_height="300"
+ min_width="300"
+ name="rlv_console"
+ title="RLVa console"
+ width="600"
+ >
+ <layout_stack
+ animate="false"
+ bottom="-1"
+ default_tab_group="2"
+ follows="all"
+ left="5"
+ layout="topleft"
+ mouse_opaque="false"
+ name="main_stack"
+ right="-5"
+ orientation="vertical"
+ tab_group="1"
+ top="1"
+ >
+ <layout_panel
+ name="body_panel"
+ height="235">
+ <text_editor
+ follows="all"
+ left="1"
+ right="-1"
+ top="0"
+ length="1"
+ font="Monospace"
+ bottom="-1"
+ ignore_tab="false"
+ layout="topleft"
+ max_length="65536"
+ name="console_output"
+ read_only="true"
+ track_end="true"
+ type="string"
+ word_wrap="true"
+ >
+ </text_editor>
+ </layout_panel>
+
+ <layout_panel
+ height="26"
+ auto_resize="false"
+ name="input_panel">
+ <chat_editor
+ layout="topleft"
+ expand_lines_count="5"
+ follows="left|right|bottom"
+ font="SansSerifSmall"
+ height="20"
+ is_expandable="true"
+ text_tentative_color="TextFgTentativeColor"
+ name="console_input"
+ max_length="1023"
+ spellcheck="true"
+ tab_group="3"
+ bottom_delta="20"
+ left="1"
+ top="1"
+ right="-1"
+ wrap="true"
+ />
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 39a663298a..cebe1ff6c3 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4377,6 +4377,11 @@ and report the problem.
</string>
<!-- RLVa -->
+ <string name="RlvConsoleDisable">RLVa is disabled</string>
+ <string name="RlvConsoleInvalidCmd">Invalid command</string>
+ <string name="RlvConsoleExecuted">INFO</string>
+ <string name="RlvConsoleFailed">ERR</string>
+ <string name="RlvConsoleRetained">RET</string>
<string name="RlvDebugExecuted">executed</string>
<string name="RlvDebugFailed">failed</string>
<string name="RlvDebugRetained">retained</string>