From 2f883ddb1d7f07d9e072a9fa0918ce4ac4da5ef3 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 22 May 2019 15:52:23 +0300 Subject: [PATCH] Changed: Display stat buff and enchant info on item icon --HG-- branch : feature-item-icon-buffs --- .../client/src/interface_v3/dbctrl_sheet.cpp | 429 ++++++++++++------ .../client/src/interface_v3/dbctrl_sheet.h | 56 ++- .../src/interface_v3/inventory_manager.h | 17 +- .../src/interface_v3/item_info_waiter.h | 39 ++ 4 files changed, 390 insertions(+), 151 deletions(-) create mode 100644 code/ryzom/client/src/interface_v3/item_info_waiter.h diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 1b9a7d720..f94a7f180 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -75,52 +75,52 @@ const uint64 NOTIFY_ANIM_MS_DURATION = 1000; // *************************************************************************** - - -// ********************************************************************************************************** -class CControlSheetTooltipInfoWaiter : public IItemInfoWaiter +void CControlSheetInfoWaiter::sendRequest() { -public: - // The item used to open this window - CDBCtrlSheet* CtrlSheet; - string LuaMethodName; -public: - ucstring infoValidated(CDBCtrlSheet* ctrlSheet, string luaMethodName); - virtual void infoReceived(); -}; -static CControlSheetTooltipInfoWaiter ControlSheetTooltipUpdater; + Requesting = true; + getInventory().addItemInfoWaiter(this); +} -void CControlSheetTooltipInfoWaiter::infoReceived() +void CControlSheetInfoWaiter::infoReceived() { - getInventory().removeItemInfoWaiter(&ControlSheetTooltipUpdater); - infoValidated(CtrlSheet, LuaMethodName); + if (!Requesting) { + return; + } + + getInventory().removeItemInfoWaiter(this); + infoValidated(); + CtrlSheet->infoReceived(); + Requesting = false; } -ucstring CControlSheetTooltipInfoWaiter::infoValidated(CDBCtrlSheet* ctrlSheet, string luaMethodName) +ucstring CControlSheetInfoWaiter::infoValidated() const { ucstring help; - // delegate setup of context he help ( & window ) to lua - CInterfaceManager *im = CInterfaceManager::getInstance(); - CLuaState *ls= CLuaManager::getInstance().getLuaState(); + if (CtrlSheet && !LuaMethodName.empty()) { - CLuaStackRestorer lsr(ls, 0); + // delegate setup of context he help ( & window ) to lua + CInterfaceManager *im = CInterfaceManager::getInstance(); + CLuaState *ls= CLuaManager::getInstance().getLuaState(); + { + CLuaStackRestorer lsr(ls, 0); - CLuaIHM::pushReflectableOnStack(*ls, (CReflectableRefPtrTarget *)ctrlSheet); - ls->pushGlobalTable(); - CLuaObject game(*ls); - game = game["game"]; - game.callMethodByNameNoThrow(luaMethodName.c_str(), 1, 1); + CLuaIHM::pushReflectableOnStack(*ls, (CReflectableRefPtrTarget *)CtrlSheet); + ls->pushGlobalTable(); + CLuaObject game(*ls); + game = game["game"]; + game.callMethodByNameNoThrow(LuaMethodName.c_str(), 1, 1); - // retrieve result from stack - if (!ls->empty()) - { - CLuaIHM::pop(*ls, help); - } - else - { - nlwarning(toString("Ucstring result expected when calling '%s', possible script error", luaMethodName.c_str()).c_str()); + // retrieve result from stack + if (!ls->empty()) + { + CLuaIHM::pop(*ls, help); + } + else + { + nlwarning(toString("Ucstring result expected when calling '%s', possible script error", LuaMethodName.c_str()).c_str()); + } } } @@ -137,7 +137,7 @@ int CDBCtrlSheet::luaGetDraggedSheet(CLuaState &ls) // *************************************************************************** int CDBCtrlSheet::luaGetItemInfo(CLuaState &ls) { - CDBCtrlSheet *ctrlSheet = const_cast(this); + CDBCtrlSheet *ctrlSheet = const_cast(this); uint32 itemSlotId = getInventory().getItemSlotId(ctrlSheet); CClientItemInfo itemInfo = getInventory().getItemInfo(itemSlotId); @@ -203,7 +203,7 @@ int CDBCtrlSheet::luaGetCreatorName(CLuaState &ls) ucstring creatorName; STRING_MANAGER::CStringManagerClient::instance()->getString(itemInfo.CreatorName, creatorName); CLuaIHM::push(ls, creatorName); - + return 1; } @@ -236,7 +236,6 @@ int CDBCtrlSheet::luaWaitInfo(CLuaState &ls) // *************************************************************************** int CDBCtrlSheet::luaBuildCrystallizedSpellListBrick(CLuaState &ls) { - CDBCtrlSheet *ctrlSheet = const_cast(this); uint32 itemSlotId= getInventory().getItemSlotId(ctrlSheet); @@ -257,7 +256,7 @@ int CDBCtrlSheet::luaBuildCrystallizedSpellListBrick(CLuaState &ls) } } - + // Reset other to 0. for(;;currentBrick++) { @@ -505,6 +504,7 @@ CCtrlDraggable(param) _Useable= true; _GrayedLink= NULL; _NeedSetup= true; + _ItemInfoChanged = true; _IconW = 0; _IconH = 0; _SetupInit= false; @@ -528,6 +528,11 @@ CCtrlDraggable(param) _ItemRMClassType= NULL; _ItemRMFaberStatType= NULL; _NotifyAnimEndTime = 0; + + _HpBuffIcon = "ico_heal.tga"; + _SapBuffIcon = "ico_sap.tga"; + _StaBuffIcon = "ico_stamina.tga"; + _FocusBuffIcon = "ico_focus.tga"; } // ---------------------------------------------------------------------------- @@ -535,6 +540,11 @@ CDBCtrlSheet::~CDBCtrlSheet() { NL3D::UDriver *Driver = CViewRenderer::getInstance()->getDriver(); + if (_ItemInfoWaiter.Requesting) + { + getInventory().removeItemInfoWaiter(&_ItemInfoWaiter); + } + if (_GuildBack) { if (Driver) @@ -613,6 +623,22 @@ bool CDBCtrlSheet::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup) prop = (char*) xmlGetProp( cur, (xmlChar*)"slot" ); if(prop) _DrawSlot= CInterfaceElement::convertBool(prop); + // + _HpBuffIcon = "ico_heal.tga"; + prop = (char*) xmlGetProp( cur, (xmlChar*)"hp_buff_icon" ); + if (prop) _HpBuffIcon = string((const char *)prop); + + _SapBuffIcon = "ico_sap.tga"; + prop = (char*) xmlGetProp( cur, (xmlChar*)"sap_buff_icon" ); + if (prop) _SapBuffIcon = string((const char *)prop); + + _StaBuffIcon = "ico_stamina.tga"; + prop = (char*) xmlGetProp( cur, (xmlChar*)"sta_buff_icon" ); + if (prop) _StaBuffIcon = string((const char *)prop); + + _FocusBuffIcon = "ico_focus.tga"; + prop = (char*) xmlGetProp( cur, (xmlChar*)"focus_buff_icon" ); + if (prop) _FocusBuffIcon = string((const char *)prop); updateActualType(); // Init size for Type @@ -1040,6 +1066,64 @@ void CDBCtrlSheet::updateIconSize() } } +// *************************************************************************** +void CDBCtrlSheet::infoReceived() +{ + if (!_ItemSheet) + { + return; + } + + const CClientItemInfo *itemInfo = getInventory().getItemInfoCache(getItemSerial(), getItemCreateTime()); + if (itemInfo == NULL) + { + // schedule for recheck on next draw() + _ItemInfoChanged = true; + return; + } + + // crystallized spell + { + _EnchantIcons.clear(); + CViewRenderer &rVR = *CViewRenderer::getInstance(); + CSBrickManager *pBM= CSBrickManager::getInstance(); + for(uint i=0; iEnchantment.Bricks.size(); ++i) + { + const CSBrickSheet *brick = pBM->getBrick(itemInfo->Enchantment.Bricks[i]); + if (brick) + { + if (!brick->isRoot() && !brick->isCredit() && !brick->isParameter()) + { + _EnchantIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(brick->getIcon()), brick->IconColor)); + rVR.getTextureSizeFromId(_EnchantIcons.back().TextureId, _EnchantIcons.back().IconW, _EnchantIcons.back().IconH); + } + else if (brick->isRoot()) + { + // there should be single root icon and it should be first one + _EnchantIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(brick->getIconBack()), brick->IconBackColor)); + rVR.getTextureSizeFromId(_EnchantIcons.back().TextureId, _EnchantIcons.back().IconW, _EnchantIcons.back().IconH); + } + } + } + } + + // buff icons + { + _BuffIcons.clear(); + CViewRenderer &rVR = *CViewRenderer::getInstance(); + + if (itemInfo->HpBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_HpBuffIcon))); + if (itemInfo->SapBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_SapBuffIcon))); + if (itemInfo->StaBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_StaBuffIcon))); + if (itemInfo->FocusBuff > 0) _BuffIcons.push_back(SBuffIcon(rVR.getTextureIdFromName(_FocusBuffIcon))); + + // update sizes + for(uint i = 0; i < _BuffIcons.size(); ++i) + { + rVR.getTextureSizeFromId(_BuffIcons[i].TextureId, _BuffIcons[i].IconW, _BuffIcons[i].IconH); + } + } +} // *************************************************************************** void CDBCtrlSheet::setupPact() @@ -1103,6 +1187,7 @@ void CDBCtrlSheet::setupItem () CInterfaceManager *pIM= CInterfaceManager::getInstance(); sint32 sheet = _SheetId.getSInt32(); + // If this is the same sheet, need to resetup if (_LastSheetId != sheet || _NeedSetup) { @@ -1203,6 +1288,9 @@ void CDBCtrlSheet::setupItem () // Special Item requirement updateItemCharacRequirement(_LastSheetId); + + // update item info markers + _ItemInfoChanged = true; } else { @@ -1277,6 +1365,13 @@ void CDBCtrlSheet::setupItem () _Useable = CSkillManager::getInstance()->checkBaseSkillMetRequirement(_ItemSheet->RequiredSkill, _ItemSheet->RequiredSkillLevel); } */ + + // at each frame, update item info icon if changed + if (_ItemInfoChanged) + { + _ItemInfoChanged = false; + setupItemInfoWaiter(); + } } @@ -1857,7 +1952,7 @@ void CDBCtrlSheet::draw() CInterfaceManager *pIM = CInterfaceManager::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance(); - + if (_Type != SheetType_Macro) { if (_LastSheetId != _SheetId.getSInt32()) @@ -1949,13 +2044,13 @@ void CDBCtrlSheet::draw() rVR.getTextureSizeFromId(frontTex, texWidth, texHeight); CQuadUV regenTris[5]; - uint numTris = buildPie(regenTris, 0.f, amount, texWidth); + uint numTris = buildPie(regenTris, 0.f, amount, texWidth); nlassert(numTris <= sizeofarray(regenTris)); for (uint tri = 0; tri < numTris; ++tri) { rVR.drawQuad(_RenderLayer + 1, regenTris[tri], frontTex, CRGBA::White, false); } - numTris = buildPie(regenTris, amount, 1.f, texWidth); + numTris = buildPie(regenTris, amount, 1.f, texWidth); nlassert(numTris <= sizeofarray(regenTris)); for (uint tri = 0; tri < numTris; ++tri) { @@ -1977,7 +2072,7 @@ void CDBCtrlSheet::draw() if (texId != -1) { sint32 texWidth, texHeight; - rVR.getTextureSizeFromId(texId, texWidth, texHeight); + rVR.getTextureSizeFromId(texId, texWidth, texHeight); const float freq0 = 1.f; const float phase0 = 0.f; const float freq1 = -1.f; @@ -1994,20 +2089,20 @@ void CDBCtrlSheet::draw() // ---------------------------------------------------------------------------- void CDBCtrlSheet::drawRotatedQuad(CViewRenderer &vr, float angle, float scale, uint renderLayer, uint32 texId, sint32 texWidth, sint32 texHeight) { - NLMISC::CQuadUV quv; + NLMISC::CQuadUV quv; float cosA = cosf(angle); float sinA = sinf(angle); // - quv.V0.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA + sinA), + quv.V0.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA + sinA), _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (- sinA - cosA), 0.5f); // - quv.V1.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA + sinA), + quv.V1.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA + sinA), _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA - cosA), 0.5f); // - quv.V2.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA - sinA), - _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA + cosA), 0.5f); + quv.V2.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (cosA - sinA), + _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (sinA + cosA), 0.5f); // - quv.V3.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA - sinA), + quv.V3.set(_XReal + 0.5f * _WReal + 0.5f * scale * texWidth * (- cosA - sinA), _YReal + 0.5f * _HReal + 0.5f * scale * texHeight * (- sinA + cosA), 0.5f); // quv.Uv0.set(0.f, 0.f); @@ -2022,13 +2117,13 @@ void CDBCtrlSheet::drawRotatedQuad(CViewRenderer &vr, float angle, float scale, // ---------------------------------------------------------------------------- inline void CDBCtrlSheet::uvToScreen(float x, float y, CVector &screenPos, uint texSize) const { - screenPos.set(_XReal + texSize * x, _YReal + texSize * (1.f - y), 0.5f); + screenPos.set(_XReal + texSize * x, _YReal + texSize * (1.f - y), 0.5f); } // ---------------------------------------------------------------------------- void CDBCtrlSheet::buildPieCorner(float angle, CUV &uv, CVector &pos, uint texSize) const -{ +{ float radAngle = angle * 2.f * float(NLMISC::Pi); // angle origin is at 12'o'clock float x = cosf(0.5f * float(NLMISC::Pi) - radAngle); @@ -2061,33 +2156,33 @@ void CDBCtrlSheet::buildPieCorner(float angle, CUV &uv, CVector &pos, uint texSi y /= -x; x = -1.f; } - } + } // remap to unit quad // (well we could have worked with tan() too, I find it simpler this way ....) uv.set(0.5f * x + 0.5f, 0.5f - 0.5f * y); - uvToScreen(uv.U, uv.V, pos, texSize); + uvToScreen(uv.U, uv.V, pos, texSize); } // ---------------------------------------------------------------------------- uint CDBCtrlSheet::buildPie(CQuadUV *triPtr, float startAngle, float endAngle, uint texSize) -{ +{ static volatile bool exit1 = false; nlassert(startAngle <= endAngle); - const sint32 factor = 65536; - const float invFactor = 1.f / factor; + const sint32 factor = 65536; + const float invFactor = 1.f / factor; sint32 iCurr = (uint32) (startAngle * factor) ; sint32 iEnd = (uint32) (endAngle * factor); clamp(iCurr, 0, factor); clamp(iEnd, 0, factor); uint triCount = 0; CVector quadCenter; - uvToScreen(0.5f, 0.5f, quadCenter, texSize); + uvToScreen(0.5f, 0.5f, quadCenter, texSize); while (iCurr != iEnd) { sint32 iNext = iCurr + (factor / 4); - iNext -= ((iNext - factor / 8) % (factor / 4)); // snap to nearest corner - iNext = std::min(iNext, iEnd); + iNext -= ((iNext - factor / 8) % (factor / 4)); // snap to nearest corner + iNext = std::min(iNext, iEnd); // well, not really a quad, but we don't have yet simple triangles rendering in the ui triPtr->Uv0.set(0.5f, 0.5f); triPtr->V0 = quadCenter; @@ -2220,6 +2315,69 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, _DispOver2BmpId, fastMulRGB(curSheetColor, _IconOver2Color)); } + if (!_BuffIcons.empty()) + { + // there is max 4 icons + sint32 hArea = (hSheet / 4); + sint32 xIcon = x; + sint32 yIcon = y; + for (uint i = 0; i < _BuffIcons.size(); ++i) + { + sint32 wIcon = _BuffIcons[i].IconW; + sint32 hIcon = _BuffIcons[i].IconH; + if (hIcon > hArea) + { + wIcon = wIcon * ((float)hArea / hIcon); + hIcon = hArea; + } + rVR.drawRotFlipBitmap (_RenderLayer+1, xIcon, yIcon, wIcon, hIcon, 0, false, _BuffIcons[i].TextureId, fastMulRGB(curSheetColor, _BuffIcons[i].Color)); + xIcon += wIcon; + // move up the row for 3rd/4th icon + if (i % 3 == 1) { + xIcon = x; + yIcon += hIcon; + } + } + } + + // Is the item enchanted ? + sint32 enchant = _Enchant.getSInt32(); + if (enchant > 0) + { + // Yes draw the additionnal bitmap and the charge (number of enchanted spell we can launch with the enchanted item) + enchant--; + rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::ItemEnchantedTexture), curSheetColor); + drawNumber(x+1, y-2+hSheet-rVR.getFigurTextureH(), wSheet, hSheet, numberColor, enchant, false); + } + + if (!_EnchantIcons.empty()) + { + // should only only 2 icons at most + // draw them in single line, top-right + sint32 hArea = (hSheet / 3); + sint32 xIcon = x + wSheet - 1; + sint32 yIcon = y + hSheet - 1/* - hArea*/; + // 0 is expected to be background + for (uint i = 1; i < _EnchantIcons.size(); ++i) + { + sint32 wIcon = _EnchantIcons[i].IconW; + sint32 hIcon = _EnchantIcons[i].IconH; + if (hIcon > hArea) + { + wIcon = wIcon * ((float)hArea / hIcon); + hIcon = hArea; + } + // need to move x before draw because of right aligned + if (i == 1) + { + xIcon -= wIcon; + } + yIcon -= hIcon; + rVR.drawRotFlipBitmap(_RenderLayer + 1, xIcon, yIcon, wIcon, hIcon, 0, false, _EnchantIcons[0].TextureId, fastMulRGB(curSheetColor, _EnchantIcons[0].Color)); + rVR.drawRotFlipBitmap(_RenderLayer+1, xIcon, yIcon, wIcon, hIcon, 0, false, _EnchantIcons[i].TextureId, fastMulRGB(curSheetColor, _EnchantIcons[i].Color)); + } + } + // Draw Quality. -1 for lookandfeel. Draw it with global color if (_DispQuality != -1) { @@ -2242,15 +2400,6 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti } drawNumber(x+1+crossW, y+1, wSheet, hSheet, curSheetColor, quantity, false); } - // Is the item enchanted ? - sint32 enchant = _Enchant.getSInt32(); - if (enchant > 0) - { - // Yes draw the additionnal bitmap and the charge (number of enchanted spell we can launch with the enchanted item) - enchant--; - rVR.draw11RotFlipBitmap (_RenderLayer+2, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::ItemEnchantedTexture), curSheetColor); - drawNumber(x+1, y-2+hSheet-rVR.getFigurTextureH(), wSheet, hSheet, numberColor, enchant, false); - } // if a raw material for example, must add special icon text. displayCharBitmaps(_RenderLayer+2, x, y, curSheetColor); @@ -2348,8 +2497,8 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti case SheetType_SPhrase : setupSPhrase(); break; default: nlassert(true); break; } - - + + bool showOutOfRangeSymbol = false; bool forceGrayed = false; @@ -2361,15 +2510,15 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti { CSPhraseManager *pPM= CSPhraseManager::getInstance(); const CSPhraseCom &phrase= pPM->getPhrase(phraseId); - // get the phrase Data version, to check if it had changed. + // get the phrase Data version, to check if it had changed. uint32 totalActionMalus = pPM->getTotalActionMalus(phrase); uint8 targetSlot = UserEntity->targetSlot(); if (targetSlot < CLFECOMMON::INVALID_SLOT) { CEntityCL *target = EntitiesMngr.entity(targetSlot); if (target && UserEntity) - { - double dist2 = (target->pos() - UserEntity->pos()).sqrnorm(); + { + double dist2 = (target->pos() - UserEntity->pos()).sqrnorm(); CSBrickManager *pBM= CSBrickManager::getInstance(); CSBrickSheet *rootBrick= NULL; if(phrase.Bricks.size()) @@ -2396,7 +2545,7 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti break; } } - + if (!isPrimalMagic) { forceGrayed = !(target->isPlayer() && target->isFriend()); @@ -2405,21 +2554,21 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti { forceGrayed = false; } - + } - + if (!forceGrayed) { sint phraseRange; sint rangeMalus; pPM->getPhraseMagicRange(phrase, totalActionMalus, phraseRange, rangeMalus); - double rangeDist = (float) (phraseRange + rangeMalus); + double rangeDist = (float) (phraseRange + rangeMalus); if (phraseRange != 0) // if range is '0' then it is a 'self' action { - rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius + rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius if (dist2 > rangeDist * rangeDist) { - showOutOfRangeSymbol = true; + showOutOfRangeSymbol = true; } } } @@ -2451,11 +2600,11 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti if (isTaunt && !forceGrayed) { - double rangeDist = (float) maxRange; - rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius + double rangeDist = (float) maxRange; + rangeDist += 0.5 + target->getSheetScale() * target->getSheetColRadius(); // player radius if (dist2 > rangeDist * rangeDist) { - showOutOfRangeSymbol = true; + showOutOfRangeSymbol = true; } } } @@ -2522,15 +2671,15 @@ void CDBCtrlSheet::drawSheet (sint32 x, sint32 y, bool draging, bool showSelecti // if the pointer is over the button if (_Over) // Draw -1,-1 because the slot over is 26x26 - rVR.draw11RotFlipBitmap (_RenderLayer+1, x-1, y-1, 0, false, _TextureIdOver, curSheetColor ); + rVR.draw11RotFlipBitmap (_RenderLayer+1, x-1, y-1, 0, false, _TextureIdOver, curSheetColor ); } if (showOutOfRangeSymbol) - { + { rVR.draw11RotFlipBitmap (_RenderLayer+1, x, y, 0, false, rVR.getSystemTextureId(CViewRenderer::OutOfRangeTexture), CRGBA::White); - } + } } - break; + break; case CCtrlSheetInfo::SheetType_OutpostBuilding: setupOutpostBuilding(); if (_DispBackBmpId != -1) @@ -3114,6 +3263,53 @@ const COutpostBuildingSheet *CDBCtrlSheet::asOutpostBuildingSheet() const return NULL; } +// *************************************************************************** +void CDBCtrlSheet::setupItemInfoWaiter() +{ + const CItemSheet *item = asItemSheet(); + if(!item) + return; + + if (!useItemInfoForFamily(item->Family)) + return; + + if (getItemSerial() == 0 || getItemCreateTime() == 0) + return; + + string luaMethodName = ((item->Family == ITEMFAMILY::CRYSTALLIZED_SPELL) ? "updateCrystallizedSpellTooltip" : "updateBuffItemTooltip"); + CDBCtrlSheet *ctrlSheet = const_cast(this); + uint itemSlotId = getInventory().getItemSlotId(ctrlSheet); + + // Prepare the waiter for tooltips + _ItemInfoWaiter.ItemSheet= ctrlSheet->getSheetId(); + _ItemInfoWaiter.LuaMethodName = luaMethodName; + _ItemInfoWaiter.ItemSlotId= itemSlotId; + _ItemInfoWaiter.CtrlSheet = ctrlSheet; + + // send out request only if cache is not set + const CClientItemInfo *itemInfo = getInventory().getItemInfoCache(getItemSerial(), getItemCreateTime()); + if (itemInfo) + { + infoReceived(); + } + else + { + // Using isInventoryPresent/Available() will fail for packers when out of range + // Getting server item however will work correctly for packer/room/guild + const CItemImage *itemImage = getInventory().getServerItem(itemSlotId); + if (itemImage) + { + _ItemInfoWaiter.sendRequest(); + } + else + { + // schedule for next draw() - if inventory should not be available (ie guild), + // but user opens it anyway, then this will loop back here on every draw() + _ItemInfoChanged = true; + } + } +} + // *************************************************************************** void CDBCtrlSheet::getContextHelp(ucstring &help) const { @@ -3177,34 +3373,17 @@ void CDBCtrlSheet::getContextHelp(ucstring &help) const { if (useItemInfoForFamily(item->Family)) { - string luaMethodName = ( (item->Family == ITEMFAMILY::CRYSTALLIZED_SPELL) ? "updateCrystallizedSpellTooltip" : "updateBuffItemTooltip"); - CDBCtrlSheet *ctrlSheet = const_cast(this); - CCtrlBase *ctrlBase = const_cast(this); - if ( ! getInventory().isItemInfoUpToDate(getInventory().getItemSlotId(ctrlSheet))) - { - // Prepare the waiter - ControlSheetTooltipUpdater.ItemSheet= ctrlSheet->getSheetId(); - ControlSheetTooltipUpdater.LuaMethodName = luaMethodName; - ControlSheetTooltipUpdater.ItemSlotId= getInventory().getItemSlotId(ctrlSheet); - ControlSheetTooltipUpdater.CtrlSheet = ctrlSheet; - - // Add the waiter - getInventory().addItemInfoWaiter(&ControlSheetTooltipUpdater); - } - - if (!_ContextHelp.empty()) - { - help= _ContextHelp; - ctrlBase->setDefaultContextHelp(ucstring()); - } - else - help = ControlSheetTooltipUpdater.infoValidated(ctrlSheet, luaMethodName); + // call lua function to update tooltip window + help = _ItemInfoWaiter.infoValidated(); + } + else if (!_ContextHelp.empty()) + { + help = _ContextHelp; } else - if (!_ContextHelp.empty()) - help= _ContextHelp; - else - help= getItemActualName(); + { + help = getItemActualName(); + } } else help= _ContextHelp; @@ -3247,18 +3426,18 @@ void CDBCtrlSheet::getContextHelp(ucstring &help) const } else { - // delegate setup of context he help ( & window ) to lua + // delegate setup of context he help ( & window ) to lua CInterfaceManager *im = CInterfaceManager::getInstance(); CLuaState *ls= CLuaManager::getInstance().getLuaState(); { CLuaStackRestorer lsr(ls, 0); - CSPhraseManager *pPM= CSPhraseManager::getInstance(); + CSPhraseManager *pPM= CSPhraseManager::getInstance(); _PhraseAdapter = new CSPhraseComAdpater; _PhraseAdapter->Phrase = pPM->getPhrase(phraseId); CLuaIHM::pushReflectableOnStack(*ls, _PhraseAdapter); - ls->pushGlobalTable(); + ls->pushGlobalTable(); CLuaObject game(*ls); - game = game["game"]; + game = game["game"]; game.callMethodByNameNoThrow("updatePhraseTooltip", 1, 1); // retrieve result from stack help = ucstring(); @@ -3322,21 +3501,7 @@ void CDBCtrlSheet::getContextHelpToolTip(ucstring &help) const { if (useItemInfoForFamily(item->Family)) { - string luaMethodName = (item->Family == ITEMFAMILY::CRYSTALLIZED_SPELL) ? "updateCrystallizedSpellTooltip" : "updateBuffItemTooltip"; - CDBCtrlSheet *ctrlSheet = const_cast(this); - if ( ! getInventory().isItemInfoUpToDate(getInventory().getItemSlotId(ctrlSheet))) - { - // Prepare the waiter - ControlSheetTooltipUpdater.ItemSheet= ctrlSheet->getSheetId(); - ControlSheetTooltipUpdater.LuaMethodName = luaMethodName; - ControlSheetTooltipUpdater.ItemSlotId= getInventory().getItemSlotId(ctrlSheet); - ControlSheetTooltipUpdater.CtrlSheet = ctrlSheet; - - // Add the waiter - getInventory().addItemInfoWaiter(&ControlSheetTooltipUpdater); - } - - help = ControlSheetTooltipUpdater.infoValidated(ctrlSheet, luaMethodName); + help = _ItemInfoWaiter.infoValidated(); return; } } @@ -3551,6 +3716,10 @@ void CDBCtrlSheet::resetAllTexIDs() _Stackable= 1; _IconW = 0; _IconH = 0; + + _ItemInfoChanged = true; + _EnchantIcons.clear(); + _BuffIcons.clear(); } diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h index ac2f2c3aa..1d185d9f4 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h @@ -37,7 +37,7 @@ #include "game_share/item_family.h" // #include "../time_client.h" - +#include "item_info_waiter.h" class CItemSheet; class CPactSheet; @@ -53,6 +53,25 @@ namespace NLGUI class CViewRenderer; } +class CDBCtrlSheet; + +// *************************************************************************** +// Item info request from server +class CControlSheetInfoWaiter : public IItemInfoWaiter +{ +public: + CDBCtrlSheet* CtrlSheet; + string LuaMethodName; + bool Requesting; + CControlSheetInfoWaiter() + : IItemInfoWaiter(), Requesting(false) + { } +public: + ucstring infoValidated() const; + void sendRequest(); + virtual void infoReceived(); +}; + // *************************************************************************** /** Common info for CDBCtrlSheet and CDBGroupListSheet @@ -576,12 +595,14 @@ public: // For auras, powers, etc. set the range of ticks during which regen occurs void setRegenTickRange(const CTickRange &tickRange); const CTickRange &getRegenTickRange() const { return _RegenTickRange; } - + // start notify anim (at the end of regen usually) void startNotifyAnim(); -protected: + // callback from info waiter + void infoReceived(); +protected: inline bool useItemInfoForFamily(ITEMFAMILY::EItemFamily family) const; void setupItem(); @@ -622,6 +643,7 @@ protected: NLMISC::CCDBNodeLeaf *_ItemRMFaberStatType; mutable sint32 _LastSheetId; + bool _ItemInfoChanged; /// Display sint32 _DispSlotBmpId; // Display slot bitmap id @@ -632,6 +654,26 @@ protected: sint32 _DispOverBmpId; // Over Icon sint32 _DispOver2BmpId; // Over Icon N0 2 for bricks / items. Useful for items when _DispOverBmpId is used to paint user color on the item. + std::string _HpBuffIcon; + std::string _SapBuffIcon; + std::string _StaBuffIcon; + std::string _FocusBuffIcon; + + // texture ids to show + struct SBuffIcon + { + SBuffIcon(sint32 txid, NLMISC::CRGBA col=NLMISC::CRGBA::White) + :TextureId(txid), Color(col), IconW(0), IconH(0) + { } + + sint32 TextureId; + NLMISC::CRGBA Color; + sint32 IconW; + sint32 IconH; + }; + std::vector _BuffIcons; + std::vector _EnchantIcons; + // Level Brick or Quality union { @@ -751,6 +793,7 @@ protected: sint64 _NotifyAnimEndTime; + CControlSheetInfoWaiter _ItemInfoWaiter; private: mutable TSheetType _ActualType; @@ -769,17 +812,20 @@ private: // special for items void updateItemCharacRequirement(sint32 sheetId); + // Send ITEM_INFO:GET request to server to fetch Buffs, Enchant info + void setupItemInfoWaiter(); + // update armour color, and cache void updateArmourColor(sint8 col); // setup sheet DB. _DbBranchName must be ok, and _SecondIndexInDb and _IndexInDb as well void setupSheetDbLinks (); - + // 'regen' rendering // convert from uv coordinates in the [0, 1] x [0, 1] range to screen coords inline void uvToScreen(float x, float y, NLMISC::CVector &screenPos, uint texSize) const; - // from an angle in the [0, 1] range, return both uv & screen coords for that angle + // from an angle in the [0, 1] range, return both uv & screen coords for that angle // (angle is projected on the side of rectangle of the 'regen' texture) void buildPieCorner(float angle, NLMISC::CUV &uv, NLMISC::CVector &pos, uint texSize) const; // from a start and end angle in the [0, 1] range, build the set of uv mapped triangles necessary diff --git a/code/ryzom/client/src/interface_v3/inventory_manager.h b/code/ryzom/client/src/interface_v3/inventory_manager.h index 7659409ca..8cc9f85d2 100644 --- a/code/ryzom/client/src/interface_v3/inventory_manager.h +++ b/code/ryzom/client/src/interface_v3/inventory_manager.h @@ -31,7 +31,7 @@ namespace NLMISC{ class CCDBNodeBranch; } class CDBCtrlSheet; - +class IItermInfoWaiter; const uint MAX_TEMPINV_ENTRIES = INVENTORIES::NbTempInvSlots; const uint MAX_BAGINV_ENTRIES = INVENTORIES::NbBagSlots; @@ -153,21 +153,6 @@ private: TItemInfoCacheMap _ItemInfoCacheMap; }; -class IItemInfoWaiter -{ -public: - IItemInfoWaiter() {ItemSlotId= 0; ItemSheet= 0;} - virtual ~IItemInfoWaiter() {} - // The item SheetId. If differ from current sheet in the SlotId, the infos are not updated / requested - uint ItemSheet; - // The item SlotId to retrieve info. - uint ItemSlotId; - - // Called when the info is received for this slot. - virtual void infoReceived() =0; -}; - - // *************************************************************************** /** This manager gives direct access to inventory slots (bag, temporary inventory, hands, and equip inventory) * This also give access to player money diff --git a/code/ryzom/client/src/interface_v3/item_info_waiter.h b/code/ryzom/client/src/interface_v3/item_info_waiter.h new file mode 100644 index 000000000..7976f94f2 --- /dev/null +++ b/code/ryzom/client/src/interface_v3/item_info_waiter.h @@ -0,0 +1,39 @@ +// 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 . + + + +#ifndef RZ_ITEM_INFO_WAITER_H +#define RZ_ITEM_INFO_WAITER_H + +class IItemInfoWaiter +{ +public: + IItemInfoWaiter() {ItemSlotId= 0; ItemSheet= 0;} + virtual ~IItemInfoWaiter() {} + // The item SheetId. If differ from current sheet in the SlotId, the infos are not updated / requested + uint ItemSheet; + // The item SlotId to retrieve info. + uint ItemSlotId; + + // Called when the info is received for this slot. + virtual void infoReceived() =0; +}; + +#endif // RZ_DBCTRL_SHEET_INFO_WAITER_H + +/* End of item_info_waiter.h */ +