Browse Source

Enhance Console class to support multiple command line interpreterers.

Yao Wei Tjong 姚伟忠 11 years ago
parent
commit
3748375f67

+ 3 - 3
Bin/Data/LuaScripts/26_ConsoleInput.lua

@@ -34,6 +34,9 @@ function Start()
     -- Execute the common startup for samples
     -- Execute the common startup for samples
     SampleStart()
     SampleStart()
     
     
+    -- Disable default execution of Lua from the console
+    SetExecuteConsoleCommands(false)
+
     -- Subscribe to console commands and the frame update
     -- Subscribe to console commands and the frame update
     SubscribeToEvent("ConsoleCommand", "HandleConsoleCommand")
     SubscribeToEvent("ConsoleCommand", "HandleConsoleCommand")
     SubscribeToEvent("Update", "HandleUpdate")
     SubscribeToEvent("Update", "HandleUpdate")
@@ -51,9 +54,6 @@ function Start()
     -- Show OS mouse cursor
     -- Show OS mouse cursor
     input.mouseVisible = true
     input.mouseVisible = true
 
 
-    -- Disable default execution of Lua from the console
-    SetExecuteConsoleCommands(false)
-
     -- Open the operating system console window (for stdin / stdout) if not open yet
     -- Open the operating system console window (for stdin / stdout) if not open yet
     OpenConsoleWindow()
     OpenConsoleWindow()
 
 

+ 3 - 3
Bin/Data/Scripts/26_ConsoleInput.as

@@ -35,6 +35,9 @@ void Start()
     // Execute the common startup for samples
     // Execute the common startup for samples
     SampleStart();
     SampleStart();
     
     
+    // Disable default execution of AngelScript from the console
+    script.executeConsoleCommands = false;
+
     // Subscribe to console commands and the frame update
     // Subscribe to console commands and the frame update
     SubscribeToEvent("ConsoleCommand", "HandleConsoleCommand");
     SubscribeToEvent("ConsoleCommand", "HandleConsoleCommand");
     SubscribeToEvent("Update", "HandleUpdate");
     SubscribeToEvent("Update", "HandleUpdate");
@@ -52,9 +55,6 @@ void Start()
     // Show OS mouse cursor
     // Show OS mouse cursor
     input.mouseVisible = true;
     input.mouseVisible = true;
 
 
-    // Disable default execution of AngelScript from the console
-    script.executeConsoleCommands = false;
-
     // Open the operating system console window (for stdin / stdout) if not open yet
     // Open the operating system console window (for stdin / stdout) if not open yet
     OpenConsoleWindow();
     OpenConsoleWindow();
 
 

+ 47 - 18
Source/Engine/Engine/Console.cpp

@@ -24,6 +24,7 @@
 #include "Console.h"
 #include "Console.h"
 #include "Context.h"
 #include "Context.h"
 #include "CoreEvents.h"
 #include "CoreEvents.h"
+#include "DropDownList.h"
 #include "EngineEvents.h"
 #include "EngineEvents.h"
 #include "Font.h"
 #include "Font.h"
 #include "Graphics.h"
 #include "Graphics.h"
@@ -61,7 +62,7 @@ Console::Console(Context* context) :
     // By default prevent the automatic showing of the screen keyboard
     // By default prevent the automatic showing of the screen keyboard
     focusOnShow_ = !ui->GetUseScreenKeyboard();
     focusOnShow_ = !ui->GetUseScreenKeyboard();
 
 
-    background_ = new BorderImage(context_);
+    background_ = uiRoot->CreateChild<BorderImage>();
     background_->SetBringToBack(false);
     background_->SetBringToBack(false);
     background_->SetClipChildren(true);
     background_->SetClipChildren(true);
     background_->SetEnabled(true);
     background_->SetEnabled(true);
@@ -69,16 +70,16 @@ Console::Console(Context* context) :
     background_->SetPriority(200); // Show on top of the debug HUD
     background_->SetPriority(200); // Show on top of the debug HUD
     background_->SetLayout(LM_VERTICAL);
     background_->SetLayout(LM_VERTICAL);
 
 
-    rowContainer_ = new ListView(context_);
+    rowContainer_ = background_->CreateChild<ListView>();
     rowContainer_->SetHighlightMode(HM_ALWAYS);
     rowContainer_->SetHighlightMode(HM_ALWAYS);
     rowContainer_->SetMultiselect(true);
     rowContainer_->SetMultiselect(true);
-    background_->AddChild(rowContainer_);
 
 
-    lineEdit_ = new LineEdit(context_);
-    lineEdit_->SetFocusMode(FM_FOCUSABLE); // Do not allow defocus with ESC
-    background_->AddChild(lineEdit_);
-
-    uiRoot->AddChild(background_);
+    commandLine_ = background_->CreateChild<UIElement>();
+    commandLine_->SetLayoutMode(LM_HORIZONTAL);
+    commandLine_->SetLayoutSpacing(1);
+    interpreters_ = commandLine_->CreateChild<DropDownList>();
+    lineEdit_ = commandLine_->CreateChild<LineEdit>();
+    lineEdit_->SetFocusMode(FM_FOCUSABLE);  // Do not allow defocus with ESC
 
 
     SetNumRows(DEFAULT_CONSOLE_ROWS);
     SetNumRows(DEFAULT_CONSOLE_ROWS);
 
 
@@ -101,11 +102,12 @@ void Console::SetDefaultStyle(XMLFile* style)
 
 
     background_->SetDefaultStyle(style);
     background_->SetDefaultStyle(style);
     background_->SetStyle("ConsoleBackground");
     background_->SetStyle("ConsoleBackground");
-    rowContainer_->SetStyle("ListView");
-
+    rowContainer_->SetStyleAuto();
     for (unsigned i = 0; i < rowContainer_->GetNumItems(); ++i)
     for (unsigned i = 0; i < rowContainer_->GetNumItems(); ++i)
         rowContainer_->GetItem(i)->SetStyle("ConsoleText");
         rowContainer_->GetItem(i)->SetStyle("ConsoleText");
-    
+    interpreters_->SetStyleAuto();
+    for (unsigned i = 0; i < interpreters_->GetNumItems(); ++i)
+        interpreters_->GetItem(i)->SetStyle("ConsoleText");
     lineEdit_->SetStyle("ConsoleLineEdit");
     lineEdit_->SetStyle("ConsoleLineEdit");
     
     
     UpdateElements();
     UpdateElements();
@@ -117,11 +119,10 @@ void Console::SetVisible(bool enable)
     background_->SetVisible(enable);
     background_->SetVisible(enable);
     if (enable)
     if (enable)
     {
     {
-        // Check if we have handler for E_CONSOLECOMMAND every time here in case the handler is being added later dynamically
-        bool hasConsoleCommandEventHandler = context_->GetEventReceivers(this, E_CONSOLECOMMAND) != 0 ||
-            context_->GetEventReceivers(E_CONSOLECOMMAND) != 0;
-        lineEdit_->SetVisible(hasConsoleCommandEventHandler);
-        if (hasConsoleCommandEventHandler && focusOnShow_)
+        // Check if we have receivers for E_CONSOLECOMMAND every time here in case the handler is being added later dynamically
+        bool hasInterpreter = PopulateInterpreter();
+        commandLine_->SetVisible(hasInterpreter);
+        if (hasInterpreter && focusOnShow_)
             GetSubsystem<UI>()->SetFocusElement(lineEdit_);
             GetSubsystem<UI>()->SetFocusElement(lineEdit_);
 
 
         // Ensure the background has no empty space when shown without the lineedit
         // Ensure the background has no empty space when shown without the lineedit
@@ -133,6 +134,7 @@ void Console::SetVisible(bool enable)
     }
     }
     else
     else
     {
     {
+        interpreters_->SetFocus(false);
         lineEdit_->SetFocus(false);
         lineEdit_->SetFocus(false);
 
 
         // Restore OS mouse visibility
         // Restore OS mouse visibility
@@ -211,11 +213,11 @@ void Console::UpdateElements()
     int width = GetSubsystem<Graphics>()->GetWidth();
     int width = GetSubsystem<Graphics>()->GetWidth();
     const IntRect& border = background_->GetLayoutBorder();
     const IntRect& border = background_->GetLayoutBorder();
     const IntRect& panelBorder = rowContainer_->GetScrollPanel()->GetClipBorder();
     const IntRect& panelBorder = rowContainer_->GetScrollPanel()->GetClipBorder();
-    background_->SetFixedWidth(width);
-    background_->SetHeight(background_->GetMinHeight());
     rowContainer_->SetFixedWidth(width - border.left_ - border.right_);
     rowContainer_->SetFixedWidth(width - border.left_ - border.right_);
     rowContainer_->SetFixedHeight(displayedRows_ * rowContainer_->GetItem((unsigned)0)->GetHeight() + panelBorder.top_ + panelBorder.bottom_ +
     rowContainer_->SetFixedHeight(displayedRows_ * rowContainer_->GetItem((unsigned)0)->GetHeight() + panelBorder.top_ + panelBorder.bottom_ +
         (rowContainer_->GetHorizontalScrollBar()->IsVisible() ? rowContainer_->GetHorizontalScrollBar()->GetHeight() : 0));
         (rowContainer_->GetHorizontalScrollBar()->IsVisible() ? rowContainer_->GetHorizontalScrollBar()->GetHeight() : 0));
+    background_->SetFixedWidth(width);
+    background_->SetHeight(background_->GetMinHeight());
 }
 }
 
 
 XMLFile* Console::GetDefaultStyle() const
 XMLFile* Console::GetDefaultStyle() const
@@ -243,6 +245,32 @@ const String& Console::GetHistoryRow(unsigned index) const
     return index < history_.Size() ? history_[index] : String::EMPTY;
     return index < history_.Size() ? history_[index] : String::EMPTY;
 }
 }
 
 
+bool Console::PopulateInterpreter()
+{
+    interpreters_->RemoveAllItems();
+
+    HashSet<Object*>* receivers = context_->GetEventReceivers(E_CONSOLECOMMAND);
+    if (!receivers || receivers->Empty())
+        return false;
+
+    for (HashSet<Object*>::ConstIterator iter = receivers->Begin(); iter != receivers->End(); ++iter)
+    {
+        const String& name = (*iter)->GetTypeName();
+        Text* text = new Text(context_);
+        text->SetStyle("ConsoleText");
+        text->SetText(name);
+        interpreters_->AddItem(text);
+    }
+
+    const IntRect& border = interpreters_->GetPopup()->GetLayoutBorder();
+    interpreters_->SetMaxWidth(interpreters_->GetListView()->GetContentElement()->GetWidth() + border.left_ + border.right_);
+    bool enabled = interpreters_->GetNumItems() > 1;
+    interpreters_->SetEnabled(enabled);
+    interpreters_->SetFocusMode(enabled ? FM_FOCUSABLE_DEFOCUSABLE : FM_NOTFOCUSABLE);
+
+    return true;
+}
+
 void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
 void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace TextFinished;
     using namespace TextFinished;
@@ -255,6 +283,7 @@ void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
 
 
         VariantMap& eventData = GetEventDataMap();
         VariantMap& eventData = GetEventDataMap();
         eventData[P_COMMAND] = line;
         eventData[P_COMMAND] = line;
+        eventData[P_ID] = static_cast<Text*>(interpreters_->GetSelectedItem())->GetText();
         SendEvent(E_CONSOLECOMMAND, eventData);
         SendEvent(E_CONSOLECOMMAND, eventData);
 
 
         // Store to history, then clear the lineedit
         // Store to history, then clear the lineedit

+ 8 - 0
Source/Engine/Engine/Console.h

@@ -28,11 +28,13 @@ namespace Urho3D
 {
 {
 
 
 class BorderImage;
 class BorderImage;
+class DropDownList;
 class Engine;
 class Engine;
 class Font;
 class Font;
 class LineEdit;
 class LineEdit;
 class ListView;
 class ListView;
 class Text;
 class Text;
+class UIElement;
 class XMLFile;
 class XMLFile;
 
 
 /// %Console window with log history and command line prompt.
 /// %Console window with log history and command line prompt.
@@ -91,6 +93,8 @@ public:
     bool GetFocusOnShow() const { return focusOnShow_; }
     bool GetFocusOnShow() const { return focusOnShow_; }
 
 
 private:
 private:
+    /// Populate the command line interpreters that could handle the console command.
+    bool PopulateInterpreter();
     /// Handle enter pressed on the line edit.
     /// Handle enter pressed on the line edit.
     void HandleTextFinished(StringHash eventType, VariantMap& eventData);
     void HandleTextFinished(StringHash eventType, VariantMap& eventData);
     /// Handle unhandled key on the line edit for scrolling the history.
     /// Handle unhandled key on the line edit for scrolling the history.
@@ -108,6 +112,10 @@ private:
     SharedPtr<BorderImage> background_;
     SharedPtr<BorderImage> background_;
     /// Container for text rows.
     /// Container for text rows.
     SharedPtr<ListView> rowContainer_;
     SharedPtr<ListView> rowContainer_;
+    /// Container for the command line.
+    SharedPtr<UIElement> commandLine_;
+    /// Interpreter drop down list.
+    SharedPtr<DropDownList> interpreters_;
     /// Line edit.
     /// Line edit.
     SharedPtr<LineEdit> lineEdit_;
     SharedPtr<LineEdit> lineEdit_;
     /// Command history.
     /// Command history.

+ 2 - 1
Source/Engine/Engine/EngineEvents.h

@@ -27,10 +27,11 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-/// A command has been entered on the console
+/// A command has been entered on the console.
 EVENT(E_CONSOLECOMMAND, ConsoleCommand)
 EVENT(E_CONSOLECOMMAND, ConsoleCommand)
 {
 {
     PARAM(P_COMMAND, Command);              // String
     PARAM(P_COMMAND, Command);              // String
+    PARAM(P_ID, Id);                        // String
 }
 }
 
 
 }
 }

+ 9 - 3
Source/Engine/LuaScript/LuaScript.cpp

@@ -270,7 +270,14 @@ void LuaScript::ScriptUnsubscribeFromEvents(void* sender)
 
 
 void LuaScript::SetExecuteConsoleCommands(bool enable)
 void LuaScript::SetExecuteConsoleCommands(bool enable)
 {
 {
+    if (enable == executeConsoleCommands_)
+        return;
+
     executeConsoleCommands_ = enable;
     executeConsoleCommands_ = enable;
+    if (enable)
+        SubscribeToEvent(E_CONSOLECOMMAND, HANDLER(LuaScript, HandleConsoleCommand));
+    else
+        UnsubscribeFromEvent(E_CONSOLECOMMAND);
 }
 }
 
 
 void LuaScript::RegisterLoader()
 void LuaScript::RegisterLoader()
@@ -355,7 +362,7 @@ int LuaScript::Print(lua_State *L)
         lua_pop(L, 1);
         lua_pop(L, 1);
     }
     }
 
 
-    LOGRAW(string);
+    LOGRAW(string + "\n");
 
 
     return 0;
     return 0;
 }
 }
@@ -436,8 +443,7 @@ void LuaScript::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
 void LuaScript::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
 void LuaScript::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace ConsoleCommand;
     using namespace ConsoleCommand;
-    
-    if (executeConsoleCommands_)
+    if (eventData[P_ID].GetString() == GetTypeName())
         ExecuteString(eventData[P_COMMAND].GetString());
         ExecuteString(eventData[P_COMMAND].GetString());
 }
 }
 
 

+ 8 - 2
Source/Engine/Script/Script.cpp

@@ -267,7 +267,14 @@ void Script::SetDefaultScene(Scene* scene)
 
 
 void Script::SetExecuteConsoleCommands(bool enable)
 void Script::SetExecuteConsoleCommands(bool enable)
 {
 {
+    if (enable == executeConsoleCommands_)
+        return;
+
     executeConsoleCommands_ = enable;
     executeConsoleCommands_ = enable;
+    if (enable)
+        SubscribeToEvent(E_CONSOLECOMMAND, HANDLER(Script, HandleConsoleCommand));
+    else
+        UnsubscribeFromEvent(E_CONSOLECOMMAND);
 }
 }
 
 
 void Script::DumpAPI(DumpMode mode)
 void Script::DumpAPI(DumpMode mode)
@@ -715,8 +722,7 @@ void Script::OutputAPIRow(DumpMode mode, const String& row, bool removeReference
 void Script::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
 void Script::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace ConsoleCommand;
     using namespace ConsoleCommand;
-
-    if (executeConsoleCommands_)
+    if (eventData[P_ID].GetString() == GetTypeName())
         Execute(eventData[P_COMMAND].GetString());
         Execute(eventData[P_COMMAND].GetString());
 }
 }
 
 

+ 1 - 7
Source/Tools/Urho3DPlayer/Urho3DPlayer.cpp

@@ -133,13 +133,7 @@ void Urho3DPlayer::Start()
         /// \hack If we are running the editor, also instantiate Lua subsystem to enable editing Lua ScriptInstances
         /// \hack If we are running the editor, also instantiate Lua subsystem to enable editing Lua ScriptInstances
 #ifdef URHO3D_LUA
 #ifdef URHO3D_LUA
         if (scriptFileName_.Contains("Editor.as", false))
         if (scriptFileName_.Contains("Editor.as", false))
-        {
-            LuaScript* luaScript = new LuaScript(context_);
-            // Ensure we only have one console command line interpreter, only use AngelScript command line interpreter for now
-            // todo Should probably add an option in Editor to let user switch interpreter and show a unique command line prompt to indicate which scripting language is currently in effect
-            luaScript->UnsubscribeFromEvent(E_CONSOLECOMMAND);
-            context_->RegisterSubsystem(luaScript);
-        }
+            context_->RegisterSubsystem(new LuaScript(context_));
 #endif
 #endif
         // If script loading is successful, proceed to main loop
         // If script loading is successful, proceed to main loop
         if (scriptFile_ && scriptFile_->Execute("void Start()"))
         if (scriptFile_ && scriptFile_->Execute("void Start()"))