1 // 2 // Copyright (c) 2008-2017 the Urho3D project. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 // 22 23 #pragma once 24 25 #include "../Core/Object.h" 26 #include "../UI/Cursor.h" 27 #include "../UI/UIBatch.h" 28 29 namespace Urho3D 30 { 31 32 /// Font hinting level (only used for FreeType fonts) 33 enum FontHintLevel 34 { 35 /// Completely disable font hinting. Output will be blurrier but more "correct". 36 FONT_HINT_LEVEL_NONE = 0, 37 38 /// Light hinting. FreeType will pixel-align fonts vertically, but not horizontally. 39 FONT_HINT_LEVEL_LIGHT, 40 41 /// Full hinting, using either the font's own hinting or FreeType's auto-hinter. 42 FONT_HINT_LEVEL_NORMAL 43 }; 44 45 class Cursor; 46 class Graphics; 47 class ResourceCache; 48 class Timer; 49 class UIBatch; 50 class UIElement; 51 class VertexBuffer; 52 class XMLElement; 53 class XMLFile; 54 55 /// %UI subsystem. Manages the graphical user interface. 56 class URHO3D_API UI : public Object 57 { 58 URHO3D_OBJECT(UI, Object); 59 60 public: 61 /// Construct. 62 UI(Context* context); 63 /// Destruct. 64 virtual ~UI(); 65 66 /// Set cursor UI element. 67 void SetCursor(Cursor* cursor); 68 /// Set focused UI element. 69 void SetFocusElement(UIElement* element, bool byKey = false); 70 /// Set modal element. Until all the modal elements are dismissed, all the inputs and events are only sent to them. Return true when successful. 71 /// Only the modal element can clear its modal status or when it is being destructed. 72 bool SetModalElement(UIElement* modalElement, bool enable); 73 /// Clear the UI (excluding the cursor.) 74 void Clear(); 75 /// Update the UI logic. Called by HandlePostUpdate(). 76 void Update(float timeStep); 77 /// Update the UI for rendering. Called by HandleRenderUpdate(). 78 void RenderUpdate(); 79 /// Render the UI. If resetRenderTargets is true, is assumed to be the default UI render to backbuffer called by Engine, and will be performed only once. Additional UI renders to a different rendertarget may be triggered from the renderpath. 80 void Render(bool resetRenderTargets = true); 81 /// Debug draw a UI element. 82 void DebugDraw(UIElement* element); 83 /// Load a UI layout from an XML file. Optionally specify another XML file for element style. Return the root element. 84 SharedPtr<UIElement> LoadLayout(Deserializer& source, XMLFile* styleFile = 0); 85 /// Load a UI layout from an XML file. Optionally specify another XML file for element style. Return the root element. 86 SharedPtr<UIElement> LoadLayout(XMLFile* file, XMLFile* styleFile = 0); 87 /// Save a UI layout to an XML file. Return true if successful. 88 bool SaveLayout(Serializer& dest, UIElement* element); 89 /// Set clipboard text. 90 void SetClipboardText(const String& text); 91 /// Set UI element double click interval in seconds. 92 void SetDoubleClickInterval(float interval); 93 /// Set UI drag event start interval in seconds. 94 void SetDragBeginInterval(float interval); 95 /// Set UI drag event start distance threshold in pixels. 96 void SetDragBeginDistance(int pixels); 97 /// Set tooltip default display delay in seconds. 98 void SetDefaultToolTipDelay(float delay); 99 /// Set maximum font face texture size. Must be a power of two. Default is 2048. 100 void SetMaxFontTextureSize(int size); 101 /// Set whether mouse wheel can control also a non-focused element. 102 void SetNonFocusedMouseWheel(bool nonFocusedMouseWheel); 103 /// Set whether to use system clipboard. Default false. 104 void SetUseSystemClipboard(bool enable); 105 /// Set whether to show the on-screen keyboard (if supported) when a %LineEdit is focused. Default true on mobile devices. 106 void SetUseScreenKeyboard(bool enable); 107 /// Set whether to use mutable (eraseable) glyphs to ensure a font face never expands to more than one texture. Default false. 108 void SetUseMutableGlyphs(bool enable); 109 /// Set whether to force font autohinting instead of using FreeType's TTF bytecode interpreter. 110 void SetForceAutoHint(bool enable); 111 /// Set the hinting level used by FreeType fonts. 112 void SetFontHintLevel(FontHintLevel level); 113 /// Set the font subpixel threshold. Below this size, if the hint level is LIGHT or NONE, fonts will use subpixel positioning plus oversampling for higher-quality rendering. Has no effect at hint level NORMAL. 114 void SetFontSubpixelThreshold(float threshold); 115 /// Set the oversampling (horizonal stretching) used to improve subpixel font rendering. Only affects fonts smaller than the subpixel limit. 116 void SetFontOversampling(int oversampling); 117 /// Set %UI scale. 1.0 is default (pixel perfect). Resize the root element to match. 118 void SetScale(float scale); 119 /// Scale %UI to the specified width in pixels. 120 void SetWidth(float width); 121 /// Scale %UI to the specified height in pixels. 122 void SetHeight(float height); 123 /// Set custom size of the root element. This disables automatic resizing of the root element according to window size. Set custom size 0,0 to return to automatic resizing. 124 void SetCustomSize(const IntVector2& size); 125 /// Set custom size of the root element. 126 void SetCustomSize(int width, int height); 127 128 /// Return root UI element. GetRoot()129 UIElement* GetRoot() const { return rootElement_; } 130 131 /// Return root modal element. GetRootModalElement()132 UIElement* GetRootModalElement() const { return rootModalElement_; } 133 134 /// Return cursor. GetCursor()135 Cursor* GetCursor() const { return cursor_; } 136 137 /// Return cursor position. 138 IntVector2 GetCursorPosition() const; 139 /// Return UI element at screen coordinates. By default returns only input-enabled elements. 140 UIElement* GetElementAt(const IntVector2& position, bool enabledOnly = true); 141 /// Return UI element at screen coordinates. By default returns only input-enabled elements. 142 UIElement* GetElementAt(int x, int y, bool enabledOnly = true); 143 144 /// Return focused element. GetFocusElement()145 UIElement* GetFocusElement() const { return focusElement_; } 146 147 /// Return topmost enabled root-level non-modal element. 148 UIElement* GetFrontElement() const; 149 /// Return currently dragged elements. 150 const Vector<UIElement*> GetDragElements(); 151 152 /// Return the number of currently dragged elements. GetNumDragElements()153 unsigned GetNumDragElements() const { return (unsigned)dragConfirmedCount_; } 154 155 /// Return the drag element at index. 156 UIElement* GetDragElement(unsigned index); 157 /// Return clipboard text. 158 const String& GetClipboardText() const; 159 160 /// Return UI element double click interval in seconds. GetDoubleClickInterval()161 float GetDoubleClickInterval() const { return doubleClickInterval_; } 162 163 /// Return UI drag start event interval in seconds. GetDragBeginInterval()164 float GetDragBeginInterval() const { return dragBeginInterval_; } 165 166 /// Return UI drag start event distance threshold in pixels. GetDragBeginDistance()167 int GetDragBeginDistance() const { return dragBeginDistance_; } 168 169 /// Return tooltip default display delay in seconds. GetDefaultToolTipDelay()170 float GetDefaultToolTipDelay() const { return defaultToolTipDelay_; } 171 172 /// Return font texture maximum size. GetMaxFontTextureSize()173 int GetMaxFontTextureSize() const { return maxFontTextureSize_; } 174 175 /// Return whether mouse wheel can control also a non-focused element. IsNonFocusedMouseWheel()176 bool IsNonFocusedMouseWheel() const { return nonFocusedMouseWheel_; } 177 178 /// Return whether is using the system clipboard. GetUseSystemClipboard()179 bool GetUseSystemClipboard() const { return useSystemClipboard_; } 180 181 /// Return whether focusing a %LineEdit will show the on-screen keyboard. GetUseScreenKeyboard()182 bool GetUseScreenKeyboard() const { return useScreenKeyboard_; } 183 184 /// Return whether is using mutable (eraseable) glyphs for fonts. GetUseMutableGlyphs()185 bool GetUseMutableGlyphs() const { return useMutableGlyphs_; } 186 187 /// Return whether is using forced autohinting. GetForceAutoHint()188 bool GetForceAutoHint() const { return forceAutoHint_; } 189 190 /// Return the current FreeType font hinting level. GetFontHintLevel()191 FontHintLevel GetFontHintLevel() const { return fontHintLevel_; } 192 193 /// Get the font subpixel threshold. Below this size, if the hint level is LIGHT or NONE, fonts will use subpixel positioning plus oversampling for higher-quality rendering. Has no effect at hint level NORMAL. GetFontSubpixelThreshold()194 float GetFontSubpixelThreshold() const { return fontSubpixelThreshold_; } 195 196 /// Get the oversampling (horizonal stretching) used to improve subpixel font rendering. Only affects fonts smaller than the subpixel limit. GetFontOversampling()197 int GetFontOversampling() const { return fontOversampling_; } 198 199 /// Return true when UI has modal element(s). 200 bool HasModalElement() const; 201 202 /// Return whether a drag is in progress. IsDragging()203 bool IsDragging() const { return dragConfirmedCount_ > 0; }; 204 205 /// Return current UI scale. GetScale()206 float GetScale() const { return uiScale_; } 207 208 /// Return root element custom size. Returns 0,0 when custom size is not being used and automatic resizing according to window size is in use instead (default.) GetCustomSize()209 const IntVector2& GetCustomSize() const { return customSize_; } 210 211 /// Data structure used to represent the drag data associated to a UIElement. 212 struct DragData 213 { 214 /// Which button combo initiated the drag. 215 int dragButtons; 216 /// How many buttons initiated the drag. 217 int numDragButtons; 218 /// Sum of all touch locations 219 IntVector2 sumPos; 220 /// Flag for a drag start event pending. 221 bool dragBeginPending; 222 /// Timer used to trigger drag begin event. 223 Timer dragBeginTimer; 224 /// Drag start position. 225 IntVector2 dragBeginSumPos; 226 }; 227 228 private: 229 /// Initialize when screen mode initially set. 230 void Initialize(); 231 /// Update UI element logic recursively. 232 void Update(float timeStep, UIElement* element); 233 /// Upload UI geometry into a vertex buffer. 234 void SetVertexData(VertexBuffer* dest, const PODVector<float>& vertexData); 235 /// Render UI batches. Geometry must have been uploaded first. 236 void Render 237 (bool resetRenderTargets, VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigned batchStart, unsigned batchEnd); 238 /// Generate batches from an UI element recursively. Skip the cursor element. 239 void GetBatches(UIElement* element, IntRect currentScissor); 240 /// Return UI element at screen position recursively. 241 void GetElementAt(UIElement*& result, UIElement* current, const IntVector2& position, bool enabledOnly); 242 /// Return the first element in hierarchy that can alter focus. 243 UIElement* GetFocusableElement(UIElement* element); 244 /// Return cursor position and visibility either from the cursor element, or the Input subsystem. 245 void GetCursorPositionAndVisible(IntVector2& pos, bool& visible); 246 /// Set active cursor's shape. 247 void SetCursorShape(CursorShape shape); 248 /// Force release of font faces when global font properties change. 249 void ReleaseFontFaces(); 250 /// Handle button or touch hover. 251 void ProcessHover(const IntVector2& cursorPos, int buttons, int qualifiers, Cursor* cursor); 252 /// Handle button or touch begin. 253 void 254 ProcessClickBegin(const IntVector2& cursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible); 255 /// Handle button or touch end. 256 void ProcessClickEnd(const IntVector2& cursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible); 257 /// Handle mouse or touch move. 258 void ProcessMove(const IntVector2& cursorPos, const IntVector2& cursorDeltaPos, int buttons, int qualifiers, Cursor* cursor, 259 bool cursorVisible); 260 /// Send a UI element drag or hover begin event. 261 void SendDragOrHoverEvent 262 (StringHash eventType, UIElement* element, const IntVector2& screenPos, const IntVector2& deltaPos, UI::DragData* dragData); 263 /// Send a UI click or double click event. 264 void SendClickEvent 265 (StringHash eventType, UIElement* beginElement, UIElement* endElement, const IntVector2& pos, int button, int buttons, 266 int qualifiers); 267 /// Handle screen mode event. 268 void HandleScreenMode(StringHash eventType, VariantMap& eventData); 269 /// Handle mouse button down event. 270 void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData); 271 /// Handle mouse button up event. 272 void HandleMouseButtonUp(StringHash eventType, VariantMap& eventData); 273 /// Handle mouse move event. 274 void HandleMouseMove(StringHash eventType, VariantMap& eventData); 275 /// Handle mouse wheel event. 276 void HandleMouseWheel(StringHash eventType, VariantMap& eventData); 277 /// Handle touch begin event. 278 void HandleTouchBegin(StringHash eventType, VariantMap& eventData); 279 /// Handle touch end event. 280 void HandleTouchEnd(StringHash eventType, VariantMap& eventData); 281 /// Handle touch move event. 282 void HandleTouchMove(StringHash eventType, VariantMap& eventData); 283 /// Handle keypress event. 284 void HandleKeyDown(StringHash eventType, VariantMap& eventData); 285 /// Handle text input event. 286 void HandleTextInput(StringHash eventType, VariantMap& eventData); 287 /// Handle frame begin event. 288 void HandleBeginFrame(StringHash eventType, VariantMap& eventData); 289 /// Handle logic post-update event. 290 void HandlePostUpdate(StringHash eventType, VariantMap& eventData); 291 /// Handle render update event. 292 void HandleRenderUpdate(StringHash eventType, VariantMap& eventData); 293 /// Handle a file being drag-dropped into the application window. 294 void HandleDropFile(StringHash eventType, VariantMap& eventData); 295 /// Remove drag data and return next iterator. 296 HashMap<WeakPtr<UIElement>, DragData*>::Iterator DragElementErase(HashMap<WeakPtr<UIElement>, DragData*>::Iterator dragElement); 297 /// Handle clean up on a drag cancel. 298 void ProcessDragCancel(); 299 /// Sum touch positions and return the begin position ready to send. 300 IntVector2 SumTouchPositions(UI::DragData* dragData, const IntVector2& oldSendPos); 301 /// Resize root element to effective size. 302 void ResizeRootElement(); 303 /// Return effective size of the root element, according to UI scale and resolution / custom size. 304 IntVector2 GetEffectiveRootElementSize(bool applyScale = true) const; 305 306 /// Graphics subsystem. 307 WeakPtr<Graphics> graphics_; 308 /// UI root element. 309 SharedPtr<UIElement> rootElement_; 310 /// UI root modal element. 311 SharedPtr<UIElement> rootModalElement_; 312 /// Cursor. 313 SharedPtr<Cursor> cursor_; 314 /// Currently focused element. 315 WeakPtr<UIElement> focusElement_; 316 /// UI rendering batches. 317 PODVector<UIBatch> batches_; 318 /// UI rendering vertex data. 319 PODVector<float> vertexData_; 320 /// UI rendering batches for debug draw. 321 PODVector<UIBatch> debugDrawBatches_; 322 /// UI rendering vertex data for debug draw. 323 PODVector<float> debugVertexData_; 324 /// UI vertex buffer. 325 SharedPtr<VertexBuffer> vertexBuffer_; 326 /// UI debug geometry vertex buffer. 327 SharedPtr<VertexBuffer> debugVertexBuffer_; 328 /// UI element query vector. 329 PODVector<UIElement*> tempElements_; 330 /// Clipboard text. 331 mutable String clipBoard_; 332 /// Seconds between clicks to register a double click. 333 float doubleClickInterval_; 334 /// Seconds from mouse button down to begin a drag if there has been no movement exceeding pixel threshold. 335 float dragBeginInterval_; 336 /// Tooltip default display delay in seconds. 337 float defaultToolTipDelay_; 338 /// Drag begin event distance threshold in pixels. 339 int dragBeginDistance_; 340 /// Mouse buttons held down. 341 int mouseButtons_; 342 /// Last mouse button pressed. 343 int lastMouseButtons_; 344 /// Qualifier keys held down. 345 int qualifiers_; 346 /// Font texture maximum size. 347 int maxFontTextureSize_; 348 /// Initialized flag. 349 bool initialized_; 350 /// Touch used flag. 351 bool usingTouchInput_; 352 /// Flag to switch mouse wheel event to be sent to non-focused element at cursor. 353 bool nonFocusedMouseWheel_; 354 /// Flag for using operating system clipboard instead of internal. 355 bool useSystemClipboard_; 356 /// Flag for showing the on-screen keyboard on focusing a %LineEdit. 357 bool useScreenKeyboard_; 358 /// Flag for using mutable (erasable) font glyphs. 359 bool useMutableGlyphs_; 360 /// Flag for forcing FreeType auto hinting. 361 bool forceAutoHint_; 362 /// FreeType hinting level (default is FONT_HINT_LEVEL_NORMAL). 363 FontHintLevel fontHintLevel_; 364 /// Maxmimum font size for subpixel glyph positioning and oversampling (default is 12). 365 float fontSubpixelThreshold_; 366 /// Horizontal oversampling for subpixel fonts (default is 2). 367 int fontOversampling_; 368 /// Flag for UI already being rendered this frame. 369 bool uiRendered_; 370 /// Non-modal batch size (used internally for rendering). 371 unsigned nonModalBatchSize_; 372 /// Timer used to trigger double click. 373 Timer clickTimer_; 374 /// UI element last clicked for tracking double clicks. 375 WeakPtr<UIElement> doubleClickElement_; 376 /// Currently hovered elements. 377 HashMap<WeakPtr<UIElement>, bool> hoveredElements_; 378 /// Currently dragged elements. 379 HashMap<WeakPtr<UIElement>, DragData*> dragElements_; 380 /// Number of elements in dragElements_. 381 int dragElementsCount_; 382 /// Number of elements in dragElements_ with dragPending = false. 383 int dragConfirmedCount_; 384 /// UI elements that are being touched with touch input. 385 HashMap<WeakPtr<UIElement>, int> touchDragElements_; 386 /// Confirmed drag elements cache. 387 Vector<UIElement*> dragElementsConfirmed_; 388 /// Current scale of UI. 389 float uiScale_; 390 /// Root element custom size. 0,0 for automatic resizing (default.) 391 IntVector2 customSize_; 392 }; 393 394 /// Register UI library objects. 395 void URHO3D_API RegisterUILibrary(Context* context); 396 397 } 398