// // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #include using namespace tb; #include "../Core/Timer.h" #include "../Graphics/Graphics.h" #include "../IO/Log.h" #include "../Input/Input.h" #include "../Input/InputEvents.h" #include "UI.h" #include "UIEvents.h" #include "UIOffscreenView.h" namespace Atomic { MODIFIER_KEYS GetModifierKeys(int qualifiers, bool superKey) { MODIFIER_KEYS code = TB_MODIFIER_NONE; if (qualifiers & QUAL_ALT) code |= TB_ALT; if (qualifiers & QUAL_CTRL) code |= TB_CTRL; if (qualifiers & QUAL_SHIFT) code |= TB_SHIFT; if (superKey) code |= TB_SUPER; return code; } SPECIAL_KEY GetSpecialKey(int keycode) { SPECIAL_KEY specialKey; switch (keycode) { case KEY_RETURN: case KEY_RETURN2: case KEY_KP_ENTER: specialKey = TB_KEY_ENTER; break; case KEY_F1: specialKey = TB_KEY_F1; break; case KEY_F2: specialKey = TB_KEY_F2; break; case KEY_F3: specialKey = TB_KEY_F3; break; case KEY_F4: specialKey = TB_KEY_F4; break; case KEY_F5: specialKey = TB_KEY_F5; break; case KEY_F6: specialKey = TB_KEY_F6; break; case KEY_F7: specialKey = TB_KEY_F7; break; case KEY_F8: specialKey = TB_KEY_F8; break; case KEY_F9: specialKey = TB_KEY_F9; break; case KEY_F10: specialKey = TB_KEY_F10; break; case KEY_F11: specialKey = TB_KEY_F11; break; case KEY_F12: specialKey = TB_KEY_F12; break; case KEY_LEFT: specialKey = TB_KEY_LEFT; break; case KEY_UP: specialKey = TB_KEY_UP; break; case KEY_RIGHT: specialKey = TB_KEY_RIGHT; break; case KEY_DOWN: specialKey = TB_KEY_DOWN; break; case KEY_PAGEUP: specialKey = TB_KEY_PAGE_UP; break; case KEY_PAGEDOWN: specialKey = TB_KEY_PAGE_DOWN; break; case KEY_HOME: specialKey = TB_KEY_HOME; break; case KEY_END: specialKey = TB_KEY_END; break; case KEY_INSERT: specialKey = TB_KEY_INSERT; break; case KEY_TAB: specialKey = TB_KEY_TAB; break; case KEY_DELETE: specialKey = TB_KEY_DELETE; break; case KEY_BACKSPACE: specialKey = TB_KEY_BACKSPACE; break; case KEY_ESCAPE: specialKey = TB_KEY_ESC; break; default: specialKey = TB_KEY_UNDEFINED; break; } return specialKey; } // @return Return the upper case of a ascii charcter. Only for shortcut handling. static int toupr_ascii(int ascii) { if (ascii >= 'a' && ascii <= 'z') return ascii + 'A' - 'a'; return ascii; } UIOffscreenView* UI::GetOffscreenViewAtScreenPosition(const IntVector2& screenPos, IntVector2& viewPos) { for (HashSet::Iterator it = offscreenViews_.Begin(); it != offscreenViews_.End(); ++it) { UIOffscreenView* osView = *it; IntRect rect = osView->inputRect_; Camera* camera = osView->inputCamera_; Octree* octree = osView->inputOctree_; Drawable* drawable = osView->inputDrawable_; bool rectIsDefault = rect == IntRect::ZERO; if (!camera || !octree || !drawable || (!rectIsDefault && !rect.IsInside(screenPos))) continue; Vector2 normPos(screenPos.x_ - rect.left_, screenPos.y_ - rect.top_); normPos /= rectIsDefault ? Vector2(graphics_->GetWidth(), graphics_->GetHeight()) : Vector2(rect.Width(), rect.Height()); Ray ray(camera->GetScreenRay(normPos.x_, normPos.y_)); PODVector queryResultVector; RayOctreeQuery query(queryResultVector, ray, RAY_TRIANGLE_UV, M_INFINITY, DRAWABLE_GEOMETRY, DEFAULT_VIEWMASK); octree->RaycastSingle(query); if (queryResultVector.Empty()) continue; RayQueryResult& queryResult(queryResultVector.Front()); if (queryResult.drawable_ != drawable) continue; Vector2& uv = queryResult.textureUV_; viewPos = IntVector2(uv.x_ * osView->GetWidth(), uv.y_ * osView->GetHeight()); return osView; } return nullptr; } tb::TBWidget* UI::GetInternalWidgetProjectedPosition(const IntVector2& screenPos, IntVector2& viewPos) { UIOffscreenView* osView = GetOffscreenViewAtScreenPosition(screenPos, viewPos); if (osView) return osView->GetInternalWidget(); viewPos = screenPos; return rootWidget_; } void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData) { if (inputDisabled_ || consoleVisible_) return; using namespace MouseButtonDown; unsigned button = eventData[P_BUTTON].GetUInt(); IntVector2 pos; pos = GetSubsystem()->GetMousePosition(); Input* input = GetSubsystem(); int qualifiers = input->GetQualifiers(); #ifdef ATOMIC_PLATFORM_WINDOWS bool superdown = input->GetKeyDown(KEY_LCTRL) || input->GetKeyDown(KEY_RCTRL); #else bool superdown = input->GetKeyDown(KEY_LGUI) || input->GetKeyDown(KEY_RGUI); #endif MODIFIER_KEYS mod = GetModifierKeys(qualifiers, superdown); static double last_time = 0; static int counter = 1; Time* t = GetSubsystem