// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" // #include "instance_map_deco.h" #include "r2_config.h" #include "tool.h" // #include "../interface_v3/ctrl_quad.h" #include "../interface_v3/group_container.h" // #include "nel/misc/i18n.h" // #include "game_share/scenario_entry_points.h" using namespace NLMISC; namespace R2 { // ********************************************************************************************************* void CInstanceMapDeco::CCtrlButtonEntity::getContextHelp(ucstring &help) const { //H_AUTO(R2_CCtrlButtonEntity_getContextHelp) help = _Instance.getDisplayName(); if (help == NLMISC::CI18N::get("uiR2EDNoName")) help.clear(); } // ********************************************************************************************************* bool CInstanceMapDeco::CCtrlButtonEntity::handleEvent(const NLGUI::CEventDescriptor &/* event */) { //H_AUTO(R2_CCtrlButtonEntity_handleEvent) return false; // just a display with tooltip capability } // ********************************************************************************************************* CInstanceMapDeco::CInstanceMapDeco() { //H_AUTO(R2_CInstanceMapDeco_CInstanceMapDeco) _Main = NULL; _Over = NULL; _OverInvalid = NULL; _Orient = NULL; _GlowStar[0] = _GlowStar[1] = NULL; _GlowStarActive = false; _OrientBlendFactor = 0.f; _LastCloseView = false; _Instance = NULL; _AddedToMap = false; _Orientable = false; _Active = true; _InvalidPos = false; } // ********************************************************************************************************* void CInstanceMapDeco::setDisplayedInstance(CInstance *instance, bool orientable) { //H_AUTO(R2_CInstanceMapDeco_setDisplayedInstance) nlassert(instance); nlassert(!_Instance); // should be called once only _Instance = instance; _Orientable = orientable; } // ********************************************************************************************************* CVector2f CInstanceMapDeco::getWorldPos() const { //H_AUTO(R2_CInstanceMapDeco_getWorldPos) nlassert(_Instance); CDisplayerVisual *vd = _Instance->getDisplayerVisual(); if (!vd) return CVector2f::Null; return vd->getWorldPos2f(); } // ********************************************************************************************************* void CInstanceMapDeco::invalidateCoords() { //H_AUTO(R2_CInstanceMapDeco_invalidateCoords) nlassert(_Instance); nlassert(_Main); nlassert(_Over); nlassert(_OverInvalid); _Main->invalidateCoords(); _Over->invalidateCoords(); _OverInvalid->invalidateCoords(); if (_GlowStar[0]) { _GlowStar[0]->invalidateCoords(); _GlowStar[1]->invalidateCoords(); } if (_Orient) _Orient->invalidateCoords(); } // ********************************************************************************************************* CCtrlQuad *CInstanceMapDeco::newQuad(CGroupMap &owner) { //H_AUTO(R2_CInstanceMapDeco_newQuad) nlassert(_Instance); CCtrlQuad *q = new CCtrlQuad; q->setActive(false); q->setModulateGlobalColor(false); owner.addCtrl(q); q->setParent(&owner); return q; } // ********************************************************************************************************* void CInstanceMapDeco::onAdd(CGroupMap &owner) { //H_AUTO(R2_CInstanceMapDeco_onAdd) nlassert(_Instance); nlassert(!_Main); nlassert(!_Over); nlassert(!_OverInvalid); _Main = new CCtrlButtonEntity(*_Instance); _Main->setPosRef(Hotspot_MM); _Main->setParentPosRef(Hotspot_BL); _Main->setModulateGlobalColorAll(false); owner.addCtrl(_Main); _Main->setParent(&owner); _Main->setRenderLayer(2); _Main->setId(owner.getId() + ":" + _Instance->getId()); _Main->setActive(_Active); // _Over = newQuad(owner); _Over->setRenderLayer(3); _Over->setActive(_Active); // _OverInvalid = newQuad(owner); _OverInvalid->setRenderLayer(4); _OverInvalid->setActive(_Active && _InvalidPos); // if (_Orientable) { _Orient = newQuad(owner); _Orient->setTexture(CV_MapEntityOrientTexture.get()); _Orient->setRenderLayer(3); _Orient->setActive(_Active); } // CInterfaceGroup *window = owner.getParentContainer(); if (window) { for(uint k = 0; k < 2; ++k) { _GlowStar[k] = new CCtrlQuad; _GlowStar[k]->setActive(false); _GlowStar[k]->setModulateGlobalColor(false); window->addCtrl(_GlowStar[k]); _GlowStar[k]->setParent(window); _GlowStar[k]->setAdditif(true); _GlowStar[k]->setTexture(CV_MapGlowStarTexture.get()); } } _AddedToMap = true; } // ********************************************************************************************************* void CInstanceMapDeco::onRemove(CGroupMap &owner) { //H_AUTO(R2_CInstanceMapDeco_onRemove) nlassert(_Instance); nlassert(_Main); nlassert(_Over); nlassert(_OverInvalid); owner.delCtrl(_Main); _Main = NULL; owner.delCtrl(_Over); _Over = NULL; owner.delCtrl(_OverInvalid); _OverInvalid = NULL; if (_Orient) { owner.delCtrl(_Orient); _Orient = NULL; } if (_GlowStar[0]) { _GlowStar[0]->getParent()->delCtrl(_GlowStar[0]); _GlowStar[0] = NULL; _GlowStar[1]->getParent()->delCtrl(_GlowStar[1]); _GlowStar[1] = NULL; } _AddedToMap = false; _Instance = NULL; } // ********************************************************************************************************* void CInstanceMapDeco::onPreRender(CGroupMap &groupMap) { //H_AUTO(R2_CInstanceMapDeco_onPreRender) if (!_Active) return; nlassert(_Instance); if (_GlowStarActive) { if (_GlowStar[0]) { // draw glowing stars on the edge to signal position well for(uint k = 0; k < 2; ++k) { _GlowStar[k]->setActive(true); _GlowStar[k]->setQuad(_GlowStarPos, CV_MapGlowStarSize.get(), (float) (CV_MapGlowStarSpeed[k].get() * 0.001 * (double) T1)); _GlowStar[k]->updateCoords(); } } } // if (_Orient) { bool closeView = groupMap.getMeterPerPixel() < CV_MapEntityCloseDist.get(); CDisplayerVisual *vd = _Instance->getDisplayerVisual(); if (vd) { if (_LastCloseView!= closeView) { _OrientBlendFactor = closeView ? 0.5f : 0.f; } if (vd->getRotateInProgress()) { _OrientBlendFactor = 1.f; } else { // fade to default alpha NLMISC::incrementalBlend(_OrientBlendFactor, closeView ? 0.5f : 0.f, DT * 1000.f / favoid0(CV_MapEntityOrientBlendTimeInMs.get())); } } else { _OrientBlendFactor = 0.f; } if (_OrientBlendFactor == 0.f) { _Orient->setActive(false); } else { _Orient->setActive(true); _Orient->setColorRGBA(CRGBA(255, 255, 255, (uint8) (255 * _OrientBlendFactor))); CVector2f worldPos = getWorldPos(); sint32 x; sint32 y; groupMap.worldToWindowSnapped(x, y, getWorldPos()); _Orient->setQuad(CV_MapEntityOrientTexture.get(), CVector((float) x, (float) y, 0.f), vd->getAngle(), closeView ? CV_MapEntityOrientOriginDist.get() : CV_MapEntityOrientOriginDistSmall.get()); _Orient->updateCoords(); } _LastCloseView = closeView; } if (_OverInvalid->getActive()) { _OverInvalid->setColorRGBA(CTool::getInvalidPosColor()); } } // ********************************************************************************************************* void CInstanceMapDeco::onUpdate(CGroupMap &groupMap) { //H_AUTO(R2_CInstanceMapDeco_onUpdate) if (!_Active) return; nlassert(_Instance); _GlowStarActive = false; if (!_Main || !_Over || !_OverInvalid) return; sint32 x; sint32 y; CVector2f worldPos = getWorldPos(); // if not in current map then don't disply anything CIslandCollision &col = getEditor().getIslandCollision(); R2::CScenarioEntryPoints::CCompleteIsland *currIsland = col.getCurrIslandDesc(); if (currIsland) { if (!currIsland->isIn(worldPos)) { setActive(false); return; } } groupMap.worldToWindowSnapped(x, y, getWorldPos()); _Main->setX(x); _Main->setY(y); CDisplayerVisual *vd = _Instance->getDisplayerVisual(); if (!vd) { _Over->setActive(false); _OverInvalid->setActive(false); return; } // bool closeView = _CloseTexture.empty() ? false : groupMap.getMeterPerPixel() < CV_MapEntityCloseDist.get(); // bool selected = vd->getDisplayFlag(CDisplayerVisual::FlagSelected); bool hasFocus = vd->getDisplayFlag(CDisplayerVisual::FlagHasFocus); // setTextureAndFit(closeView ? _CloseTexture : CV_MapEntitySmallTexture.get()); _Main->setColor((selected && ! closeView) ? CV_MapEntitySelectColor.get() : vd->getDisplayModeColorInMap()); // if small icon, then change the icon color directly, because no over will be displayed // if (selected || hasFocus) { // if the selection is out of the window, then draw an arrow to locate it const CVector2f &wmin = groupMap.getVisibleWorldMin(); const CVector2f &wmax = groupMap.getVisibleWorldMax(); if (worldPos.x < wmin.x || worldPos.x > wmax.x || worldPos.y < wmin.y || worldPos.y > wmax.y) { // OUT OF VISIBLE REGION CASE _Over->setActive(true); _Over->setColorRGBA(selected ? CV_MapEntitySelectColor.get() : CV_MapEntityHighlightColor.get()); // out of the visible portion, so draw an arrow instead _Over->setTexture(CV_MapEntityFarTexture.get()); // snap position to inner visible world rect CVector2f m = 0.5f * (wmin + wmax); CVector2f dir = worldPos - m; CVector2f inter; float d0; float d1; if (dir.x > 0.f) { d0 = (wmax.x - m.x) / dir.x; if (dir.y > 0.f) { d1 = (wmax.y - m.y) / dir.y; inter = m + std::min(d0, d1) * dir; } else if (dir.y < 0.f) { d1 = (wmin.y - m.y) / dir.y; inter = m + std::min(d0, d1) * dir; } else { inter.set(wmax.x, m.y); } } else if (dir.x < 0.f) { d0 = (wmin.x - m.x) / dir.x; if (dir.y > 0.f) { d1 = (wmax.y - m.y) / dir.y; inter = m + std::min(d0, d1) * dir; } else if (dir.y < 0.f) { d1 = (wmin.y - m.y) / dir.y; inter = m + std::min(d0, d1) * dir; } else { inter.set(wmin.x, m.y); } } else { if (dir.y > 0.f) { inter.set(m.x, wmax.y); } else if (dir.y < 0.f) { inter.set(m.x, wmin.y); } else { inter = m; } } float size = CV_MapEntityFarArrowSize.get(); // TMP TMP size = size; float bias = 1.f; dir.normalize(); CVector2f winInter; groupMap.worldToWindow(winInter, inter); _Over->setRenderLayer(3); _Over->setQuad(winInter - (size + bias) * dir, winInter - bias * dir, 0.5f * size); // if (_GlowStar[0]) { sint32 screenInterX, screenInterY; groupMap.windowToScreen(screenInterX, screenInterY, (sint32) winInter.x, (sint32) winInter.y); sint32 refCornerX, refCornerY; _GlowStar[0]->getParent()->getCorner(refCornerX, refCornerY, Hotspot_BL); _GlowStarPos.set((float) (screenInterX - refCornerX), (float) (screenInterY - refCornerY), 0.f); _GlowStarActive = true; } } else { // VISIBLE CASE _GlowStar[0]->setActive(false); _GlowStar[1]->setActive(false); if (closeView || hasFocus) { _Over->setActive(true); if (!closeView) { _Over->setColorRGBA(CV_MapEntitySelectColor.get()); } else { _Over->setColorRGBA(selected ? CV_MapEntitySelectColor.get() : CV_MapEntityHighlightColor.get()); } const std::string &tex = closeView ? CV_MapEntitySelectTexture.get() : CV_MapEntitySmallHighlightTexture.get(); _Over->setTexture(tex); _Over->setRenderLayer(2); _Over->setQuad(tex, CVector((float) x, (float) y, 0.f)); } else { _Over->setActive(false); } } } else { // no focus _Over->setActive(false); _GlowStar[0]->setActive(false); _GlowStar[1]->setActive(false); } // update 'quad that signal invalid pos' if (_OverInvalid->getActive()) { const std::string &tex = closeView ? CV_MapEntityInvalidTexture.get() : CV_MapEntityInvalidTextureSmall.get(); _OverInvalid->setTexture(tex); _OverInvalid->setQuad(tex, CVector((float) x, (float) y, 0.f)); } } // ********************************************************************************************************* void CInstanceMapDeco::setTextureAndFit(const std::string &bitmapName) { //H_AUTO(R2_CInstanceMapDeco_setTextureAndFit) nlassert(_Instance); nlassert(_Main); _Main->setTexture(bitmapName); if (!_Main->isTextureValid()) { _Main->setTexture(CV_MapEntityDefaultTexture.get()); _Main->setX(14); _Main->setY(14); } else { _Main->fitTexture(); } } // ********************************************************************************************************* void CInstanceMapDeco::setActive(bool active) { //H_AUTO(R2_CInstanceMapDeco_setActive) if (active == _Active) return; if (_Main) _Main->setActive(active); if (_Over) _Over->setActive(active); if (_GlowStar[0]) _GlowStar[0]->setActive(active); if (_GlowStar[1]) _GlowStar[1]->setActive(active); if (_Orient) _Orient->setActive(active); _Active = active; } // ********************************************************************************************************* void CInstanceMapDeco::setInvalidPosFlag(bool invalid) { //H_AUTO(R2_CInstanceMapDeco_setInvalidPosFlag) _InvalidPos = invalid; if (_OverInvalid) { _OverInvalid->setActive(_Active && _InvalidPos); } } } // R2