# pragma region License
/*
License ( OLC - 3 )
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Copyright 2024 Joshua Sigona < sigonasr2 @ gmail . com >
Redistribution and use in source and binary forms , with or without modification ,
are permitted provided that the following conditions are met :
1. Redistributions or derivations of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice . This list of conditions and the following disclaimer must be
reproduced in the documentation and / or other materials provided with the distribution .
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND ANY
EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED
TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR
BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE .
Portions of this software are copyright © 2024 The FreeType
Project ( www . freetype . org ) . Please see LICENSE_FT . txt for more information .
All rights reserved .
*/
# pragma endregion
# pragma once
# include "Item.h"
# include "AdventuresInLestoria.h"
# include "MenuLabel.h"
INCLUDE_game
INCLUDE_GFX
namespace PriceLabel {
enum PriceLabel {
NONE ,
BUY_LABEL ,
SELL_LABEL ,
CRAFTABLE ,
UPGRADEABLE ,
} ;
}
class RowItemDisplay : public MenuComponent {
friend class RowInventoryScrollableWindowComponent ;
std : : string itemNameLabelName ;
std : : string itemDescriptionLabelName ;
CompactText compact = NON_COMPACT ;
bool showQuantity = true ;
PriceLabel : : PriceLabel priceLabel = PriceLabel : : NONE ;
bool fadeOutIfMissingRequirements = false ;
bool hideLabelWhileLocked = false ;
bool itemIsSelected = false ;
protected :
std : : weak_ptr < Item > itemRef ;
public :
inline RowItemDisplay ( geom2d : : rect < float > rect , const std : : weak_ptr < Item > itemRef , MenuFunc onClick , std : : string itemNameLabelName , std : : string itemDescriptionLabelName , ButtonAttr attributes = ButtonAttr : : NONE )
: MenuComponent ( rect , " " , onClick , attributes ) , itemNameLabelName ( itemNameLabelName ) , itemDescriptionLabelName ( itemDescriptionLabelName ) , itemRef ( itemRef ) {
if ( itemRef . lock ( ) - > IsEquippable ( ) ) SetShowQuantity ( false ) ;
}
virtual inline void DrawDecal ( ViewPort & window , bool focused ) override {
bool canEnhance = itemRef . lock ( ) - > CanEnhanceItem ( ) ;
bool locked = fadeOutIfMissingRequirements & & itemRef . lock ( ) - > EnhancementIsPossible ( ) & & itemRef . lock ( ) - > GetEnhancementInfo ( ) [ 0 ] . chapterAvailable > game - > GetCurrentChapter ( ) ;
MenuComponent : : DrawDecal ( window , focused ) ;
if ( ! canEnhance & & fadeOutIfMissingRequirements ) {
Pixel col = PixelLerp ( VERY_DARK_GREY , DARK_GREY , hoverEffect / " ThemeGlobal.HighlightTime " _F ) ;
window . FillRectDecal ( rect . pos + vf2d { 1 , 1 } , rect . size - vf2d { 1 , 1 } , col ) ;
}
if ( locked ) {
Pixel col = PixelLerp ( BLACK , VERY_DARK_GREY , hoverEffect / " ThemeGlobal.HighlightTime " _F ) ;
window . FillRectDecal ( rect . pos + vf2d { 1 , 1 } , rect . size - vf2d { 1 , 1 } , col ) ;
}
float scaleFactor = ( rect . size . y - 4 ) / 24 ;
vf2d iconSize = vf2d { scaleFactor , scaleFactor } * 24.f ;
Pixel tint = WHITE ;
if ( locked ) {
window . FillRectDecal ( rect . pos + vf2d { 2 , 2 } , iconSize ) ;
tint = BLACK ;
}
window . DrawDecal ( rect . pos + vf2d { 2 , 2 } , const_cast < Decal * > ( itemRef . lock ( ) - > Icon ( ) . Decal ( ) ) , { scaleFactor , scaleFactor } , tint ) ;
window . DrawRectDecal ( rect . pos + vf2d { 2 , 2 } , iconSize , borderCol ) ;
if ( itemIsSelected ) {
window . FillRectDecal ( rect . pos + V ( A : : DRAW_OFFSET ) + vf2d { 0.f , 1.f } , { rect . size . x + 1 , 1 } , YELLOW ) ;
window . FillRectDecal ( rect . pos + V ( A : : DRAW_OFFSET ) + vf2d { 1.f , 0.f } , { 1 , rect . size . y + 1 } , YELLOW ) ;
window . FillRectDecal ( rect . pos + V ( A : : DRAW_OFFSET ) + vf2d { - 1.f , 0.f } + vf2d { rect . size . x - 1 + 1 , 0 } , { 1 , rect . size . y + 1 } , YELLOW ) ;
window . FillRectDecal ( rect . pos + V ( A : : DRAW_OFFSET ) + vf2d { 0.f , - 1.f } + vf2d { 0 , rect . size . y - 1 + 1 } , { rect . size . x + 1 , 1 } , YELLOW ) ;
}
# pragma region Item Name Display
std : : string itemName = itemRef . lock ( ) - > DisplayName ( ) ;
vf2d scaledSize = { std : : min ( 1.f , ( rect . size . x - 6 - iconSize . x ) / game - > GetTextSizeProp ( itemName ) . x ) , 1 } ;
bool missingRequirements = ! canEnhance & & fadeOutIfMissingRequirements ;
if ( locked & & hideLabelWhileLocked ) std : : for_each ( itemName . begin ( ) , itemName . end ( ) , [ ] ( char & c ) { if ( c > = ' 0 ' & & c < = ' z ' ) { c = ' ? ' ; } } ) ;
Pixel itemNameTextCol { itemRef . lock ( ) - > GetDisplayNameColor ( ) } ;
if ( missingRequirements ) {
itemNameTextCol = DARK_GREY ;
}
window . DrawShadowStringPropDecal ( rect . pos + vf2d { 4 , 4 } + vf2d { iconSize . x , iconSize . y / 2 - 4 } , itemName , itemNameTextCol , BLACK , scaledSize ) ;
# pragma endregion
if ( showQuantity & & itemRef . lock ( ) - > Amt ( ) ! = INFINITE ) {
std : : string quantityText = std : : format ( " x{} " , itemRef . lock ( ) - > Amt ( ) ) ;
float qtyTextScale = 0.75f ;
vf2d qtyTextSize = vf2d ( game - > GetTextSizeProp ( quantityText ) ) * qtyTextScale ;
window . DrawShadowStringPropDecal ( rect . pos + rect . size - vf2d { 1 , 1 } + vf2d { - qtyTextSize . x , - qtyTextSize . y } , quantityText , WHITE , BLACK , { qtyTextScale , qtyTextScale } ) ;
}
borderCol = itemRef . lock ( ) - > HasEnchant ( ) ? itemRef . lock ( ) - > GetEnchant ( ) . value ( ) . DisplayCol ( ) : WHITE ;
if ( priceLabel ! = PriceLabel : : NONE ) {
switch ( priceLabel ) {
case PriceLabel : : CRAFTABLE : {
if ( ! canEnhance & & fadeOutIfMissingRequirements ) {
vf2d craftableTextSize = vf2d ( game - > GetTextSizeProp ( " Item.Missing Upgradeable Item Text " _S ) ) * vf2d { 1.f , 0.85f } ;
window . DrawShadowStringPropDecal ( rect . pos + vf2d { rect . size . x - craftableTextSize . x - 1 , 3 } , " Item.Missing Upgradeable Item Text " _S , " Item.Missing Upgradeable Item Text Color " _Pixel , BLACK , { 1.f , 0.85f } ) ;
borderCol = GREEN ;
} else {
vf2d craftableTextSize = vf2d ( game - > GetTextSizeProp ( " Item.Craftable Item Text " _S ) ) * vf2d { 1.f , 0.85f } ;
window . DrawShadowStringPropDecal ( rect . pos + vf2d { rect . size . x - craftableTextSize . x - 1 , 3 } , " Item.Craftable Item Text " _S , " Item.Craftable Item Text Color " _Pixel , BLACK , { 1.f , 0.85f } ) ;
borderCol = GREEN ;
}
} break ;
case PriceLabel : : UPGRADEABLE : {
uint8_t nextLevel = std : : min ( itemRef . lock ( ) - > EnhancementLevel ( ) + 1 , " Item.Item Max Enhancement Level " _I ) ;
bool lockedDueToChapterReq = itemRef . lock ( ) - > GetEnhancementInfo ( ) [ nextLevel ] . chapterAvailable > game - > GetCurrentChapter ( ) | | itemRef . lock ( ) - > EnhancementLevel ( ) = = " Item.Item Max Enhancement Level " _I ;
if ( lockedDueToChapterReq ) {
vf2d craftableTextSize = vf2d ( game - > GetTextSizeProp ( " Item.Maxed Item Text " _S ) ) * vf2d { 1.f , 0.85f } ;
window . DrawShadowStringPropDecal ( rect . pos + vf2d { rect . size . x - craftableTextSize . x - 1 , 3 } , " Item.Maxed Item Text " _S , " Item.Maxed Item Text Color " _Pixel , BLACK , { 1.f , 0.85f } ) ;
borderCol = " Item.Maxed Item Text Color " _Pixel ;
} else
if ( ! canEnhance & & fadeOutIfMissingRequirements ) {
vf2d craftableTextSize = vf2d ( game - > GetTextSizeProp ( " Item.Missing Upgradeable Item Text " _S ) ) * vf2d { 1.f , 0.85f } ;
window . DrawShadowStringPropDecal ( rect . pos + vf2d { rect . size . x - craftableTextSize . x - 1 , 3 } , " Item.Missing Upgradeable Item Text " _S , " Item.Missing Upgradeable Item Text Color " _Pixel , BLACK , { 1.f , 0.85f } ) ;
borderCol = GREY ;
} else {
vf2d craftableTextSize = vf2d ( game - > GetTextSizeProp ( " Item.Upgradeable Item Text " _S ) ) * vf2d { 1.f , 0.85f } ;
window . DrawShadowStringPropDecal ( rect . pos + vf2d { rect . size . x - craftableTextSize . x - 1 , 3 } , " Item.Upgradeable Item Text " _S , " Item.Upgradeable Item Text Color " _Pixel , BLACK , { 1.f , 0.85f } ) ;
borderCol = " Item.Upgradeable Item Text Color " _Pixel ;
}
} break ;
case PriceLabel : : SELL_LABEL : {
std : : string priceText = std : : to_string ( itemRef . lock ( ) - > SellValue ( ) ) ;
if ( itemRef . lock ( ) - > SellValue ( ) = = 0 ) priceText = " Cannot Sell " ;
vf2d priceTextSize = vf2d ( game - > GetTextSize ( priceText ) ) ;
if ( itemRef . lock ( ) - > SellValue ( ) ! = 0 ) {
window . DrawShadowStringDecal ( rect . pos + vf2d { rect . size . x - priceTextSize . x - 15 , 3 } , priceText ) ;
window . DrawDecal ( rect . pos + vf2d { rect . size . x - 14 , 1 } , GFX [ " currency_coin.png " ] . Decal ( ) , { 0.5f , 0.5f } ) ;
} else {
vf2d priceTextSize = vf2d ( game - > GetTextSizeProp ( priceText ) ) * vf2d { 0.5f , 0.85f } ;
window . DrawShadowStringPropDecal ( rect . pos + vf2d { rect . size . x - priceTextSize . x - 1 , 3 } , priceText , WHITE , BLACK , { 0.5f , 0.85f } ) ;
}
} break ;
case PriceLabel : : BUY_LABEL : {
std : : string priceText = std : : to_string ( itemRef . lock ( ) - > BuyValue ( ) ) ;
vf2d priceTextSize = vf2d ( game - > GetTextSize ( priceText ) ) ;
window . DrawShadowStringDecal ( rect . pos + vf2d { rect . size . x - priceTextSize . x - 15 , 3 } , priceText ) ;
window . DrawDecal ( rect . pos + vf2d { rect . size . x - 14 , 1 } , GFX [ " currency_coin.png " ] . Decal ( ) , { 0.5f , 0.5f } ) ;
} break ;
}
}
if ( Inventory : : GetSlotEquippedIn ( itemRef ) ! = EquipSlot : : NONE ) {
window . DrawShadowStringDecal ( rect . pos + vf2d { 2 , 2 } + iconSize - vf2d { 8 , 8 } , " E " , GREEN , VERY_DARK_GREEN ) ;
}
}
virtual inline void Update ( AiL * game ) override {
MenuComponent : : Update ( game ) ;
valid = ! ISBLANK ( itemRef ) & & itemRef . lock ( ) - > Amt ( ) > 0 ;
if ( hovered ) {
UpdateLabel ( ) ;
}
}
inline void SetCompactDescriptions ( CompactText compact ) {
this - > compact = compact ;
}
virtual inline void OnMouseOut ( ) override {
if ( itemNameLabelName ! = " " ) {
Component < MenuLabel > ( parentMenu , itemNameLabelName ) - > Disable ( ) ;
}
if ( itemDescriptionLabelName ! = " " ) {
Component < MenuLabel > ( parentMenu , itemDescriptionLabelName ) - > Disable ( ) ;
}
}
virtual inline void SetShowQuantity ( bool showQuantity ) {
this - > showQuantity = showQuantity ;
}
virtual inline const std : : weak_ptr < Item > GetItem ( ) {
return itemRef ;
}
virtual inline void SetItem ( const std : : weak_ptr < Item > itemRef ) {
this - > itemRef = itemRef ;
}
void UpdateLabel ( ) {
if ( ISBLANK ( itemRef ) ) return ;
std : : string labelNameText ;
std : : string labelDescriptionText ;
if ( valid ) {
labelNameText = itemRef . lock ( ) - > DisplayName ( ) ;
labelDescriptionText = itemRef . lock ( ) - > Description ( compact ) ;
} else {
labelNameText = " " ;
labelDescriptionText = " " ;
}
if ( hideLabelWhileLocked & & itemRef . lock ( ) - > GetEnhancementInfo ( ) [ 0 ] . chapterAvailable > game - > GetCurrentChapter ( ) ) {
std : : for_each ( labelNameText . begin ( ) , labelNameText . end ( ) , [ ] ( char & c ) { if ( c > = ' 0 ' & & c < = ' z ' ) { c = ' ? ' ; } } ) ;
std : : for_each ( labelDescriptionText . begin ( ) , labelDescriptionText . end ( ) , [ ] ( char & c ) { if ( c > = ' 0 ' & & c < = ' z ' ) { c = ' ? ' ; } } ) ;
}
if ( itemNameLabelName ! = " " ) {
Component < MenuLabel > ( parentMenu , itemNameLabelName ) - > SetLabel ( labelNameText ) ;
Component < MenuLabel > ( parentMenu , itemNameLabelName ) - > Enable ( ) ;
}
if ( itemDescriptionLabelName ! = " " ) {
Component < MenuLabel > ( parentMenu , itemDescriptionLabelName ) - > SetLabel ( labelDescriptionText ) ;
Component < MenuLabel > ( parentMenu , itemDescriptionLabelName ) - > Enable ( ) ;
}
}
virtual inline void OnHover ( ) override {
UpdateLabel ( ) ;
}
inline void SetPriceLabelType ( PriceLabel : : PriceLabel labelType ) {
this - > priceLabel = labelType ;
}
inline void SetCheckCraftingRequirements ( bool check ) {
this - > fadeOutIfMissingRequirements = check ;
}
inline void SetHideLabelWhileLocked ( bool hideWhileLocked ) {
hideLabelWhileLocked = hideWhileLocked ;
}
} ;