2
0
Enhex 9 жил өмнө
parent
commit
f0e05cb7e1

+ 6 - 0
Source/Samples/26_ConsoleInput/ConsoleInput.cpp

@@ -83,6 +83,12 @@ void ConsoleInput::Start()
     console->SetCommandInterpreter(GetTypeName());
     console->SetVisible(true);
     console->GetCloseButton()->SetVisible(false);
+    console->AddAutoComplete("help");
+    console->AddAutoComplete("eat");
+    console->AddAutoComplete("hide");
+    console->AddAutoComplete("wait");
+    console->AddAutoComplete("score");
+    console->AddAutoComplete("quit");
 
     // Show OS mouse cursor
     GetSubsystem<Input>()->SetMouseVisible(true);

+ 2 - 0
Source/Urho3D/AngelScript/EngineAPI.cpp

@@ -62,6 +62,8 @@ static void RegisterConsole(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Console", "BorderImage@+ get_background() const", asMETHOD(Console, GetBackground), asCALL_THISCALL);
     engine->RegisterObjectMethod("Console", "LineEdit@+ get_lineEdit() const", asMETHOD(Console, GetLineEdit), asCALL_THISCALL);
     engine->RegisterObjectMethod("Console", "Button@+ get_closeButton() const", asMETHOD(Console, GetCloseButton), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Console", "void AddAutoComplete(const String&in)", asMETHOD(Console, AddAutoComplete), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Console", "void RemoveAutoComplete(const String&in)", asMETHOD(Console, RemoveAutoComplete), asCALL_THISCALL);
     engine->RegisterGlobalFunction("Console@+ get_console()", asFUNCTION(GetConsole), asCALL_CDECL);
 }
 

+ 107 - 4
Source/Urho3D/Engine/Console.cpp

@@ -53,6 +53,7 @@ Console::Console(Context* context) :
     autoVisibleOnError_(false),
     historyRows_(DEFAULT_HISTORY_SIZE),
     historyPosition_(0),
+    autoCompleteIter_(autoComplete_.begin()),
     printing_(false)
 {
     UI* ui = GetSubsystem<UI>();
@@ -89,6 +90,7 @@ Console::Console(Context* context) :
     SetNumRows(DEFAULT_CONSOLE_ROWS);
 
     SubscribeToEvent(interpreters_, E_ITEMSELECTED, URHO3D_HANDLER(Console, HandleInterpreterSelected));
+    SubscribeToEvent(lineEdit_, E_TEXTCHANGED, URHO3D_HANDLER(Console, HandleTextChanged));
     SubscribeToEvent(lineEdit_, E_TEXTFINISHED, URHO3D_HANDLER(Console, HandleTextFinished));
     SubscribeToEvent(lineEdit_, E_UNHANDLEDKEY, URHO3D_HANDLER(Console, HandleLineEditKey));
     SubscribeToEvent(closeButton_, E_RELEASED, URHO3D_HANDLER(Console, HandleCloseButtonPressed));
@@ -274,6 +276,16 @@ const String& Console::GetHistoryRow(unsigned index) const
     return index < history_.Size() ? history_[index] : String::EMPTY;
 }
 
+void Console::AddAutoComplete(const String & option)
+{
+    autoComplete_.insert(option);
+}
+
+void Console::RemoveAutoComplete(const String & option)
+{
+    autoComplete_.erase(option);
+}
+
 bool Console::PopulateInterpreter()
 {
     interpreters_->RemoveAllItems();
@@ -325,6 +337,16 @@ void Console::HandleInterpreterSelected(StringHash eventType, VariantMap& eventD
     lineEdit_->SetFocus(true);
 }
 
+void Console::HandleTextChanged(StringHash eventType, VariantMap & eventData)
+{
+    // Save the original line
+    // Make sure the change isn't caused by auto complete or history
+    if (!historyOrAutoCompleteChange)
+        autoCompleteLine_ = eventData[TextEntry::P_TEXT].GetString();
+
+    historyOrAutoCompleteChange = false;
+}
+
 void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
 {
     using namespace TextFinished;
@@ -352,8 +374,10 @@ void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
             if (history_.Size() > historyRows_)
                 history_.Erase(history_.Begin());
         }
-        
-        historyPosition_ = history_.Size();
+
+        historyPosition_ = history_.Size(); // reset
+
+        autoCompleteIter_ = autoComplete_.end(); // reset
 
         currentRow_.Clear();
         lineEdit_->SetText(currentRow_);
@@ -369,24 +393,95 @@ void Console::HandleLineEditKey(StringHash eventType, VariantMap& eventData)
 
     bool changed = false;
 
+    auto start_iter = autoCompleteIter_;
+
     switch (eventData[P_KEY].GetInt())
     {
     case KEY_UP:
-        if (historyPosition_ > 0)
+        if (autoCompleteIter_ == autoComplete_.begin())
+            autoCompleteIter_ = autoComplete_.end();
+
+        if (autoCompleteIter_ != autoComplete_.end())
+        {
+            auto before_begin = --autoComplete_.begin();
+
+            // Search for auto completion that contains the contents of the line
+            for (--autoCompleteIter_; autoCompleteIter_ != before_begin; --autoCompleteIter_)
+            {
+                if (autoCompleteIter_->StartsWith(autoCompleteLine_))
+                {
+                    historyOrAutoCompleteChange = true;
+                    lineEdit_->SetText(*autoCompleteIter_);
+                    break;
+                }
+            }
+
+            // If not found
+            if (autoCompleteIter_ == before_begin)
+            {
+                // Reset the iterator
+                autoCompleteIter_ = autoComplete_.end();
+                // Reset history position
+                historyPosition_ = history_.Size();
+            }
+        }
+        
+        // If no more auto complete options and history options left
+        if (autoCompleteIter_ == autoComplete_.end() &&
+            historyPosition_ > 0)
         {
+            // If line text is not a history, save the current text value to be restored later
             if (historyPosition_ == history_.Size())
                 currentRow_ = lineEdit_->GetText();
+            // Use the previous option
             --historyPosition_;
             changed = true;
         }
         break;
 
     case KEY_DOWN:
+        // If history options left
         if (historyPosition_ < history_.Size())
         {
+            // Use the next option
             ++historyPosition_;
             changed = true;
         }
+        else
+        {
+            // Loop over
+            if (autoCompleteIter_ == autoComplete_.end())
+                autoCompleteIter_ = autoComplete_.begin();
+            else
+                ++autoCompleteIter_; // If not starting over, skip checking the currently found completion
+
+            auto start_iter = autoCompleteIter_;
+
+            // Search for auto completion that contains the contents of the line
+            for (; autoCompleteIter_ != autoComplete_.end(); ++autoCompleteIter_)
+            {
+                if (autoCompleteIter_->StartsWith(autoCompleteLine_))
+                {
+                    historyOrAutoCompleteChange = true;
+                    lineEdit_->SetText(*autoCompleteIter_);
+                    break;
+                }
+            }
+
+            // Continue to search the complete range
+            if (autoCompleteIter_ == autoComplete_.end())
+            {
+                for (autoCompleteIter_ = autoComplete_.begin(); autoCompleteIter_ != start_iter; ++autoCompleteIter_)
+                {
+                    if (autoCompleteIter_->StartsWith(autoCompleteLine_))
+                    {
+                        historyOrAutoCompleteChange = true;
+                        lineEdit_->SetText(*autoCompleteIter_);
+                        break;
+                    }
+                }
+            }
+        }
         break;
 
     default: break;
@@ -394,10 +489,18 @@ void Console::HandleLineEditKey(StringHash eventType, VariantMap& eventData)
 
     if (changed)
     {
+        historyOrAutoCompleteChange = true;
+        // Set text to history option
         if (historyPosition_ < history_.Size())
             lineEdit_->SetText(history_[historyPosition_]);
-        else
+        else // restore the original line value before it was set to history values
+        {
             lineEdit_->SetText(currentRow_);
+            // Set the auto complete iterator according to the currentRow
+            for (autoCompleteIter_ = autoComplete_.begin(); autoCompleteIter_ != autoComplete_.end(); ++autoCompleteIter_)
+                if (autoCompleteIter_->StartsWith(currentRow_))
+                    break;
+        }
     }
 }
 

+ 29 - 0
Source/Urho3D/Engine/Console.h

@@ -23,6 +23,7 @@
 #pragma once
 
 #include "../Core/Object.h"
+#include <set>
 
 namespace Urho3D
 {
@@ -112,6 +113,12 @@ public:
     /// Return history row at index.
     const String& GetHistoryRow(unsigned index) const;
 
+    /// Add auto complete option
+    void AddAutoComplete(const String& option);
+
+    /// Remove auto complete option
+    void RemoveAutoComplete(const String& option);
+
     /// Return whether automatically focuses the line edit when showing.
     bool GetFocusOnShow() const { return focusOnShow_; }
 
@@ -120,6 +127,8 @@ private:
     bool PopulateInterpreter();
     /// Handle interpreter being selected on the drop down list.
     void HandleInterpreterSelected(StringHash eventType, VariantMap& eventData);
+    /// Handle text change in the line edit.
+    void HandleTextChanged(StringHash eventType, VariantMap& eventData);
     /// Handle enter pressed on the line edit.
     void HandleTextFinished(StringHash eventType, VariantMap& eventData);
     /// Handle unhandled key on the line edit for scrolling the history.
@@ -149,6 +158,7 @@ private:
     SharedPtr<Button> closeButton_;
     /// Last used command interpreter.
     String commandInterpreter_;
+
     /// Command history.
     Vector<String> history_;
     /// Pending log message rows.
@@ -161,6 +171,25 @@ private:
     unsigned historyRows_;
     /// Command history current position.
     unsigned historyPosition_;
+
+    bool historyOrAutoCompleteChange = false;
+
+    /**
+	Command auto complete options.
+
+	down arrow key
+	Unless currently going through history options, will loop through next auto complete options.
+
+	up arrow key
+	Unless currently going through history options, will go through previous auto complete options.
+	When no previous options are left will start going through history options.
+	*/
+    std::set<String> autoComplete_;
+    /// Command auto complete current position.
+    std::set<String>::iterator autoCompleteIter_;
+    /// Store the original line which is being auto-completed
+    String autoCompleteLine_;
+
     /// Flag when printing messages to prevent endless loop.
     bool printing_;
     /// Flag for automatically focusing the line edit on showing the console.

+ 7 - 1
bin/Data/Scripts/26_ConsoleInput.as

@@ -53,7 +53,13 @@ void Start()
     console.numBufferedRows = 2 * console.numRows;
     console.commandInterpreter = "ScriptEventInvoker";
     console.visible = true;
-    console.closeButton.visible = false;
+	console.closeButton.visible = false;
+	console.AddAutoComplete("help");
+	console.AddAutoComplete("eat");
+	console.AddAutoComplete("hide");
+	console.AddAutoComplete("wait");
+	console.AddAutoComplete("score");
+	console.AddAutoComplete("quit");
 
     // Show OS mouse cursor
     input.mouseVisible = true;