Explorar o código

Applied OS cursor shape patch from Paul Noome.

Lasse Öörni %!s(int64=12) %!d(string=hai) anos
pai
achega
53d2404aee
Modificáronse 8 ficheiros con 71 adicións e 22 borrados
  1. 1 0
      Docs/ScriptAPI.dox
  2. 1 0
      Docs/Urho3D.dox
  3. 1 0
      Engine/Script/UIAPI.cpp
  4. 1 2
      Engine/UI/Cursor.h
  5. 50 5
      Engine/UI/UI.cpp
  6. 6 4
      Engine/UI/UI.h
  7. 10 11
      Engine/UI/Window.cpp
  8. 1 0
      Readme.txt

+ 1 - 0
Docs/ScriptAPI.dox

@@ -5522,6 +5522,7 @@ Properties:<br>
 - String category (readonly)
 - Cursor@ cursor
 - IntVector2 cursorPosition (readonly)
+- CursorShape cursorShape (writeonly)
 - UIElement@ focusElement
 - UIElement@ frontElement (readonly)
 - UIElement@ root (readonly)

+ 1 - 0
Docs/Urho3D.dox

@@ -59,6 +59,7 @@ Urho3D development, contributions and bugfixes by:
 - Aster Jian
 - Jason Kinzer
 - Pete Leigh
+- Paul Noome
 - Vladimir Pobedinsky
 - Miika Santala
 - Firegorilla

+ 1 - 0
Engine/Script/UIAPI.cpp

@@ -574,6 +574,7 @@ static void RegisterUI(asIScriptEngine* engine)
     engine->RegisterObjectMethod("UI", "void set_cursor(Cursor@+)", asMETHOD(UI, SetCursor), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "Cursor@+ get_cursor() const", asMETHOD(UI, GetCursor), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "IntVector2 get_cursorPosition() const", asMETHOD(UI, GetCursorPosition), asCALL_THISCALL);
+    engine->RegisterObjectMethod("UI", "void set_cursorShape(CursorShape)", asMETHOD(UI, SetCursorShape), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "void set_focusElement(UIElement@+)", asMETHOD(UI, SetFocusElement), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "UIElement@+ get_focusElement() const", asMETHOD(UI, GetFocusElement), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "UIElement@+ get_frontElement() const", asMETHOD(UI, GetFrontElement), asCALL_THISCALL);

+ 1 - 2
Engine/UI/Cursor.h

@@ -77,7 +77,6 @@ public:
     void DefineShape(CursorShape shape, Image* image, const IntRect& imageRect, const IntVector2& hotSpot, bool osMouseVisible = false);
     /// Set current shape.
     void SetShape(CursorShape shape);
-    
     /// Get current shape.
     CursorShape GetShape() const { return shape_; }
     
@@ -85,7 +84,7 @@ public:
     void SetShapesAttr(VariantVector value);
     /// Return shapes attribute.
     VariantVector GetShapesAttr() const;
-    
+
 protected:
     /// Current shape index.
     CursorShape shape_;

+ 50 - 5
Engine/UI/UI.cpp

@@ -57,6 +57,19 @@
 namespace Urho3D
 {
 
+/// OS cursor shape lookup table matching the %Cursor CursorShape enumeration
+static const int osCursorLookup[CS_MAX_SHAPES] =
+{
+    SDL_SYSTEM_CURSOR_ARROW,    // CS_NORMAL
+    SDL_SYSTEM_CURSOR_SIZENS,   // CS_RESIZEVERTICAL
+    SDL_SYSTEM_CURSOR_SIZENESW, // CS_RESIZEDIAGONAL_TOPRIGHT
+    SDL_SYSTEM_CURSOR_SIZEWE,   // CS_RESIZEHORIZONTAL
+    SDL_SYSTEM_CURSOR_SIZENWSE, // CS_RESIZEDIAGONAL_TOPLEFT
+    SDL_SYSTEM_CURSOR_HAND,     // CS_ACCEPTDROP
+    SDL_SYSTEM_CURSOR_NO,       // CS_REJECTDROP
+    SDL_SYSTEM_CURSOR_WAIT      // CS_BUSY
+};
+
 ShortStringHash VAR_ORIGIN("Origin");
 const ShortStringHash VAR_ORIGINAL_PARENT("OriginalParent");
 const ShortStringHash VAR_ORIGINAL_CHILD_INDEX("OriginalChildIndex");
@@ -85,6 +98,12 @@ UI::UI(Context* context) :
     rootElement_->SetTraversalMode(TM_DEPTH_FIRST);
     rootModalElement_->SetTraversalMode(TM_DEPTH_FIRST);
     clickTimer_ = new Timer();
+
+    // Nullify OS cursor shapes
+    for (unsigned i = 0; i < CS_MAX_SHAPES; ++i)
+    {
+        osCursorShapes_[i] = 0;
+    }
     
     // Register UI library object factories
     RegisterUILibrary(context_);
@@ -107,6 +126,16 @@ UI::UI(Context* context) :
 UI::~UI()
 {
     delete clickTimer_;
+
+    for (unsigned i = 0; i < CS_MAX_SHAPES; ++i)
+    {
+        if (osCursorShapes_[i]) 
+        {
+            // Free OS cursor and nullify
+            SDL_FreeCursor(osCursorShapes_[i]);
+            osCursorShapes_[i] = 0;
+        }
+    }
 }
 
 void UI::SetCursor(Cursor* cursor)
@@ -466,6 +495,11 @@ void UI::SetNonFocusedMouseWheel(bool nonFocusedMouseWheel)
     nonFocusedMouseWheel_ = nonFocusedMouseWheel;
 }
 
+IntVector2 UI::GetCursorPosition() const
+{
+    return cursor_ ? cursor_->GetPosition() : GetSubsystem<Input>()->GetMousePosition();
+}
+
 UIElement* UI::GetElementAt(const IntVector2& position, bool enabledOnly)
 {
     UIElement* result = 0;
@@ -501,11 +535,6 @@ UIElement* UI::GetFrontElement() const
     return front;
 }
 
-IntVector2 UI::GetCursorPosition() const
-{
-    return cursor_ ? cursor_->GetPosition() : GetSubsystem<Input>()->GetMousePosition();
-}
-
 bool UI::HasModalElement() const
 {
     return rootModalElement_->GetNumChildren() > 0;
@@ -790,6 +819,22 @@ void UI::SetCursorShape(CursorShape shape)
 {
     if (cursor_)
         cursor_->SetShape(shape);
+    else
+    {
+        // Check now: Cursor's SetShape does this check too, so avoids checking twice.
+        if (shape < CS_NORMAL || shape >= CS_MAX_SHAPES)
+            return;
+        
+        if (!osCursorShapes_[shape])
+        {
+            // Create OS cursor corresponding to specified CursorShape
+            osCursorShapes_[shape] = SDL_CreateSystemCursor((SDL_SystemCursor)osCursorLookup[shape]);
+            if (!osCursorShapes_[shape])
+                LOGERROR("Could not create system cursor!");
+        }
+        
+        SDL_SetCursor(osCursorShapes_[shape]);
+    }
 }
 
 void UI::SendDragEvent(StringHash eventType, UIElement* element, const IntVector2& screenPos)

+ 6 - 4
Engine/UI/UI.h

@@ -51,6 +51,8 @@ public:
 
     /// Set cursor UI element.
     void SetCursor(Cursor* cursor);
+    /// Set active cursor's shape if it exists, system OS cursor shape otherwise.
+    void SetCursorShape(CursorShape shape);
     /// Set focused UI element.
     void SetFocusElement(UIElement* element);
     /// Set modal element. Until all the modal elements are dismissed, all the inputs and events are only sent to them. Return true when successful.
@@ -87,6 +89,8 @@ public:
     UIElement* GetRootModalElement() const { return rootModalElement_; }
     /// Return cursor.
     Cursor* GetCursor() const { return cursor_; }
+    /// Return cursor position.
+    IntVector2 GetCursorPosition() const;
     /// Return UI element at screen coordinates.
     UIElement* GetElementAt(const IntVector2& position, bool enabledOnly = true);
     /// Return UI element at screen coordinates.
@@ -95,8 +99,6 @@ public:
     UIElement* GetFocusElement() const { return focusElement_; }
     /// Return topmost enabled root-level non-modal element.
     UIElement* GetFrontElement() const;
-    /// Return cursor position.
-    IntVector2 GetCursorPosition() const;
     /// Return clipboard text.
     const String& GetClipBoardText() const { return clipBoard_; }
     /// Return UI element double click interval in seconds.
@@ -123,8 +125,6 @@ private:
     UIElement* GetFocusableElement(UIElement* element);
     /// Return cursor position and visibility either from the cursor element, or the Input subsystem.
     void GetCursorPositionAndVisible(IntVector2& pos, bool& visible);
-    /// Set cursor shape if it exists.
-    void SetCursorShape(CursorShape shape);
     /// Send a UI element drag event.
     void SendDragEvent(StringHash eventType, UIElement* element, const IntVector2& screenPos);
     /// Handle screen mode event.
@@ -172,6 +172,8 @@ private:
     SharedPtr<UIElement> rootModalElement_;
     /// Cursor.
     SharedPtr<Cursor> cursor_;
+    /// OS cursor shapes.
+    SDL_Cursor* osCursorShapes_[CS_MAX_SHAPES];
     /// UI element being dragged.
     WeakPtr<UIElement> dragElement_;
     /// Currently focused element

+ 10 - 11
Engine/UI/Window.cpp

@@ -304,39 +304,38 @@ WindowDragMode Window::GetDragMode(const IntVector2& position) const
 
 void Window::SetCursorShape(WindowDragMode mode, Cursor* cursor) const
 {
-    if (!cursor)
-        return;
+    CursorShape shape = CS_NORMAL;
 
     switch (mode)
     {
-    case DRAG_NONE:
-    case DRAG_MOVE:
-        cursor->SetShape(CS_NORMAL);
-        break;
-
     case DRAG_RESIZE_TOP:
     case DRAG_RESIZE_BOTTOM:
-        cursor->SetShape(CS_RESIZEVERTICAL);
+        shape = CS_RESIZEVERTICAL;
         break;
 
     case DRAG_RESIZE_LEFT:
     case DRAG_RESIZE_RIGHT:
-        cursor->SetShape(CS_RESIZEHORIZONTAL);
+        shape = CS_RESIZEHORIZONTAL;
         break;
 
     case DRAG_RESIZE_TOPRIGHT:
     case DRAG_RESIZE_BOTTOMLEFT:
-        cursor->SetShape(CS_RESIZEDIAGONAL_TOPRIGHT);
+        shape = CS_RESIZEDIAGONAL_TOPRIGHT;
         break;
 
     case DRAG_RESIZE_TOPLEFT:
     case DRAG_RESIZE_BOTTOMRIGHT:
-        cursor->SetShape(CS_RESIZEDIAGONAL_TOPLEFT);
+        shape = CS_RESIZEDIAGONAL_TOPLEFT;
         break;
 
     default:
         break;
     }
+
+    if (cursor)
+        cursor->SetShape(shape);
+    else
+        GetSubsystem<UI>()->SetCursorShape(shape);
 }
 
 void Window::ValidatePosition()

+ 1 - 0
Readme.txt

@@ -21,6 +21,7 @@ Urho3D development, contributions and bugfixes by:
 - Aster Jian
 - Jason Kinzer
 - Pete Leigh
+- Paul Noome
 - Vladimir Pobedinsky
 - Miika Santala
 - Firegorilla