#include "GRoot.h" #include "AudioEngine.h" #include "UIConfig.h" #include "UIPackage.h" NS_FGUI_BEGIN USING_NS_CC; #if COCOS2D_VERSION < 0x00040000 using namespace cocos2d::experimental; #endif GRoot* GRoot::_inst = nullptr; bool GRoot::_soundEnabled = true; float GRoot::_soundVolumeScale = 1.0f; int GRoot::contentScaleLevel = 0; GRoot* GRoot::create(Scene* scene, int zOrder) { GRoot* pRet = new GRoot(); if (pRet->initWithScene(scene, zOrder)) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = nullptr; return nullptr; } } GRoot::GRoot() : _windowSizeListener(nullptr), _inputProcessor(nullptr), _modalLayer(nullptr), _modalWaitPane(nullptr), _tooltipWin(nullptr), _defaultTooltipWin(nullptr) { } GRoot::~GRoot() { delete _inputProcessor; CC_SAFE_RELEASE(_modalWaitPane); CC_SAFE_RELEASE(_defaultTooltipWin); CC_SAFE_RELEASE(_modalLayer); CALL_LATER_CANCEL(GRoot, doShowTooltipsWin); if (_windowSizeListener) Director::getInstance()->getEventDispatcher()->removeEventListener(_windowSizeListener); } void GRoot::showWindow(Window* win) { addChild(win); adjustModalLayer(); } void GRoot::hideWindow(Window* win) { win->hide(); } void GRoot::hideWindowImmediately(Window* win) { if (win->getParent() == this) removeChild(win); adjustModalLayer(); } void GRoot::bringToFront(Window* win) { int cnt = numChildren(); int i; if (_modalLayer->getParent() != nullptr && !win->isModal()) i = getChildIndex(_modalLayer) - 1; else i = cnt - 1; for (; i >= 0; i--) { GObject* g = getChildAt(i); if (g == win) return; if (dynamic_cast(g)) break; } if (i >= 0) setChildIndex(win, i); } void GRoot::closeAllExceptModals() { Vector map(_children); for (const auto& child : map) { if (dynamic_cast(child) && !((Window*)child)->isModal()) hideWindowImmediately((Window*)child); } } void GRoot::closeAllWindows() { Vector map(_children); for (const auto& child : map) { if (dynamic_cast(child)) hideWindowImmediately((Window*)child); } } Window* GRoot::getTopWindow() { int cnt = numChildren(); for (int i = cnt - 1; i >= 0; i--) { GObject* child = getChildAt(i); if (dynamic_cast(child)) { return (Window*)child; } } return nullptr; } GGraph* GRoot::getModalLayer() { if (_modalLayer == nullptr) createModalLayer(); return _modalLayer; } void GRoot::createModalLayer() { _modalLayer = GGraph::create(); _modalLayer->retain(); _modalLayer->drawRect(getWidth(), getHeight(), 0, Color4F::WHITE, UIConfig::modalLayerColor); _modalLayer->addRelation(this, RelationType::Size); } void GRoot::adjustModalLayer() { if (_modalLayer == nullptr) createModalLayer(); int cnt = numChildren(); if (_modalWaitPane != nullptr && _modalWaitPane->getParent() != nullptr) setChildIndex(_modalWaitPane, cnt - 1); for (int i = cnt - 1; i >= 0; i--) { GObject* child = getChildAt(i); if (dynamic_cast(child) && ((Window*)child)->isModal()) { if (_modalLayer->getParent() == nullptr) addChildAt(_modalLayer, i); else setChildIndexBefore(_modalLayer, i); return; } } if (_modalLayer->getParent() != nullptr) removeChild(_modalLayer); } bool GRoot::hasModalWindow() { return _modalLayer != nullptr && _modalLayer->getParent() != nullptr; } void GRoot::showModalWait() { getModalWaitingPane(); if (_modalWaitPane) addChild(_modalWaitPane); } void GRoot::closeModalWait() { if (_modalWaitPane != nullptr && _modalWaitPane->getParent() != nullptr) removeChild(_modalWaitPane); } GObject* GRoot::getModalWaitingPane() { if (!UIConfig::globalModalWaiting.empty()) { if (_modalWaitPane == nullptr) { _modalWaitPane = UIPackage::createObjectFromURL(UIConfig::globalModalWaiting); _modalWaitPane->setSortingOrder(INT_MAX); _modalWaitPane->retain(); } _modalWaitPane->setSize(getWidth(), getHeight()); _modalWaitPane->addRelation(this, RelationType::Size); return _modalWaitPane; } else return nullptr; } bool GRoot::isModalWaiting() { return (_modalWaitPane != nullptr) && _modalWaitPane->onStage(); } cocos2d::Vec2 GRoot::getTouchPosition(int touchId) { return _inputProcessor->getTouchPosition(touchId); } GObject* GRoot::getTouchTarget() { return _inputProcessor->getRecentInput()->getTarget(); } cocos2d::Vec2 GRoot::worldToRoot(const cocos2d::Vec2 &pt) { cocos2d::Vec2 pos = _displayObject->convertToNodeSpace(pt); pos.y = getHeight() - pos.y; return pos; } cocos2d::Vec2 GRoot::rootToWorld(const cocos2d::Vec2 &pt) { cocos2d::Vec2 pos = pt; pos.y = getHeight() - pos.y; pos = _displayObject->convertToWorldSpace(pos); return pos; } void GRoot::showPopup(GObject* popup) { showPopup(popup, nullptr, PopupDirection::AUTO); } void GRoot::showPopup(GObject* popup, GObject* target, PopupDirection dir) { if (!_popupStack.empty()) hidePopup(popup); _popupStack.push_back(WeakPtr(popup)); if (target != nullptr) { GObject* p = target; while (p != nullptr) { if (p->getParent() == this) { if (popup->getSortingOrder() < p->getSortingOrder()) { popup->setSortingOrder(p->getSortingOrder()); } break; } p = p->getParent(); } } addChild(popup); adjustModalLayer(); if (dynamic_cast(popup) && target == nullptr && dir == PopupDirection::AUTO) return; Vec2 pos = getPoupPosition(popup, target, dir); popup->setPosition(pos.x, pos.y); } void GRoot::togglePopup(GObject* popup) { togglePopup(popup, nullptr, PopupDirection::AUTO); } void GRoot::togglePopup(GObject* popup, GObject* target, PopupDirection dir) { if (std::find(_justClosedPopups.cbegin(), _justClosedPopups.cend(), popup) != _justClosedPopups.cend()) return; showPopup(popup, target, dir); } void GRoot::hidePopup() { hidePopup(nullptr); } void GRoot::hidePopup(GObject* popup) { if (popup != nullptr) { auto it = std::find(_popupStack.cbegin(), _popupStack.cend(), popup); if (it != _popupStack.cend()) { int k = (int)(it - _popupStack.cbegin()); for (int i = (int)_popupStack.size() - 1; i >= k; i--) { closePopup(_popupStack.back().ptr()); _popupStack.pop_back(); } } } else { for (const auto& it : _popupStack) closePopup(it.ptr()); _popupStack.clear(); } } void GRoot::closePopup(GObject* target) { if (target && target->getParent() != nullptr) { if (dynamic_cast(target)) ((Window*)target)->hide(); else removeChild(target); } } void GRoot::checkPopups() { _justClosedPopups.clear(); if (!_popupStack.empty()) { GObject* mc = _inputProcessor->getRecentInput()->getTarget(); bool handled = false; while (mc != this && mc != nullptr) { auto it = std::find(_popupStack.cbegin(), _popupStack.cend(), mc); if (it != _popupStack.cend()) { int k = (int)(it - _popupStack.cbegin()); for (int i = (int)_popupStack.size() - 1; i > k; i--) { closePopup(_popupStack.back().ptr()); _popupStack.pop_back(); } handled = true; break; } mc = mc->findParent(); } if (!handled) { for (int i = (int)_popupStack.size() - 1; i >= 0; i--) { GObject* popup = _popupStack[i].ptr(); if (popup) { _justClosedPopups.push_back(WeakPtr(popup)); closePopup(popup); } } _popupStack.clear(); } } } bool GRoot::hasAnyPopup() { return !_popupStack.empty(); } cocos2d::Vec2 GRoot::getPoupPosition(GObject* popup, GObject* target, PopupDirection dir) { Vec2 pos; Vec2 size; if (target != nullptr) { pos = target->localToGlobal(Vec2::ZERO); pos = this->globalToLocal(pos); size = target->localToGlobal(target->getSize()); size = this->globalToLocal(size); size -= pos; } else { pos = globalToLocal(_inputProcessor->getRecentInput()->getPosition()); } float xx, yy; xx = pos.x; if (xx + popup->getWidth() > getWidth()) xx = xx + size.x - popup->getWidth(); yy = pos.y + size.y; if ((dir == PopupDirection::AUTO && yy + popup->getHeight() > getHeight()) || dir == PopupDirection::UP) { yy = pos.y - popup->getHeight() - 1; if (yy < 0) { yy = 0; xx += size.x / 2; } } return Vec2(round(xx), round(yy)); } void GRoot::showTooltips(const std::string& msg) { if (_defaultTooltipWin == nullptr) { const std::string& resourceURL = UIConfig::tooltipsWin; if (resourceURL.empty()) { CCLOGWARN("FairyGUI: UIConfig.tooltipsWin not defined"); return; } _defaultTooltipWin = UIPackage::createObjectFromURL(resourceURL); _defaultTooltipWin->setTouchable(false); _defaultTooltipWin->retain(); } _defaultTooltipWin->setText(msg); showTooltipsWin(_defaultTooltipWin); } void GRoot::showTooltipsWin(GObject* tooltipWin) { hideTooltips(); _tooltipWin = tooltipWin; CALL_LATER(GRoot, doShowTooltipsWin, 0.1f); } void GRoot::doShowTooltipsWin() { if (_tooltipWin == nullptr) return; Vec2 pt = _inputProcessor->getRecentInput()->getPosition(); float xx = pt.x + 10; float yy = pt.y + 20; pt = globalToLocal(Vec2(xx, yy)); xx = pt.x; yy = pt.y; if (xx + _tooltipWin->getWidth() > getWidth()) xx = xx - _tooltipWin->getWidth(); if (yy + _tooltipWin->getHeight() > getHeight()) { yy = yy - _tooltipWin->getHeight() - 1; if (yy < 0) yy = 0; } _tooltipWin->setPosition(round(xx), round(yy)); addChild(_tooltipWin); } void GRoot::hideTooltips() { if (_tooltipWin != nullptr) { if (_tooltipWin->getParent() != nullptr) removeChild(_tooltipWin); _tooltipWin = nullptr; } } void GRoot::playSound(const std::string& url, float volumnScale) { if (!_soundEnabled) return; PackageItem* pi = UIPackage::getItemByURL(url); if (pi) AudioEngine::play2d(pi->file, false, _soundVolumeScale * volumnScale); } void GRoot::setSoundEnabled(bool value) { _soundEnabled = value; } void GRoot::setSoundVolumeScale(float value) { _soundVolumeScale = value; } void GRoot::onTouchEvent(int eventType) { if (eventType == UIEventType::TouchBegin) { if (_tooltipWin != nullptr) hideTooltips(); checkPopups(); } } void GRoot::handlePositionChanged() { _displayObject->setPosition(0, _size.height); } void GRoot::onEnter() { GComponent::onEnter(); _inst = this; } void GRoot::onExit() { GComponent::onExit(); if (_inst == this) _inst = nullptr; } bool GRoot::initWithScene(cocos2d::Scene* scene, int zOrder) { if (!GComponent::init()) return false; if (_inst == nullptr) _inst = this; _inputProcessor = new InputProcessor(this); _inputProcessor->setCaptureCallback(CC_CALLBACK_1(GRoot::onTouchEvent, this)); #ifdef CC_PLATFORM_PC _windowSizeListener = Director::getInstance()->getEventDispatcher()->addCustomEventListener(GLViewImpl::EVENT_WINDOW_RESIZED, CC_CALLBACK_0(GRoot::onWindowSizeChanged, this)); #endif onWindowSizeChanged(); scene->addChild(_displayObject, zOrder); return true; } void GRoot::onWindowSizeChanged() { const cocos2d::Size& rs = Director::getInstance()->getOpenGLView()->getDesignResolutionSize(); setSize(rs.width, rs.height); updateContentScaleLevel(); } void GRoot::updateContentScaleLevel() { float ss = Director::getInstance()->getContentScaleFactor(); if (ss >= 3.5f) contentScaleLevel = 3; //x4 else if (ss >= 2.5f) contentScaleLevel = 2; //x3 else if (ss >= 1.5f) contentScaleLevel = 1; //x2 else contentScaleLevel = 0; } NS_FGUI_END