struct InventoryItemDisplayData
{
	var m_itemID : ItemID;
	var m_equipmentArea : gamedataEquipmentArea;
	var m_slotIndex : Int32;
}

class InventoryItemDisplayController extends BaseButtonView
{
	protected editable var m_widgetWrapper : inkWidgetRef;
	protected editable var m_itemName : inkTextRef;
	protected editable var m_itemPrice : inkTextRef;
	protected editable var m_itemRarity : inkWidgetRef;
	protected editable var m_commonModsRoot : inkCompoundRef;
	protected editable var m_itemImage : inkImageRef;
	protected editable var m_itemFallbackImage : inkImageRef;
	protected editable var m_itemEmptyImage : inkImageRef;
	protected editable var m_itemEmptyIcon : inkImageRef;
	protected editable var m_cyberwareEmptyImage : inkImageRef;
	protected editable var m_itemSelectedArrow : inkWidgetRef;
	protected editable var m_quantintyAmmoIcon : inkWidgetRef;
	protected editable var m_quantityWrapper : inkCompoundRef;
	protected editable var m_quantityText : inkTextRef;
	protected editable var m_weaponType : inkTextRef;
	protected const editable var m_highlightFrames : array< inkWidgetRef >;
	protected const editable var m_equippedWidgets : array< inkWidgetRef >;
	protected const editable var m_hideWhenEquippedWidgets : array< inkWidgetRef >;
	protected const editable var m_hideWhenCyberwareInInventory : array< inkWidgetRef >;
	protected const editable var m_showWhenCyberwareInInventory : array< inkWidgetRef >;
	protected const editable var m_showInEmptyWidgets : array< inkWidgetRef >;
	protected const editable var m_hideInEmptyWidgets : array< inkWidgetRef >;
	protected const editable var m_backgroundFrames : array< inkWidgetRef >;
	protected editable var m_equippedMarker : inkWidgetRef;
	protected editable var m_requirementsWrapper : inkWidgetRef;
	protected editable var m_iconicTint : inkWidgetRef;
	protected editable var m_transmogContainer : inkCompoundRef;
	protected editable var m_rarityWrapper : inkWidgetRef;
	protected editable var m_rarityCommonWrapper : inkWidgetRef;
	protected editable var m_weaponTypeImage : inkImageRef;
	protected editable var m_questItemMaker : inkWidgetRef;
	protected editable var m_labelsContainer : inkCompoundRef;
	protected editable var m_backgroundBlueprint : inkWidgetRef;
	protected editable var m_iconBlueprint : inkWidgetRef;
	protected editable var m_fluffBlueprint : inkImageRef;
	protected editable var m_lootitemflufficon : inkWidgetRef;
	protected editable var m_lootitemtypeicon : inkImageRef;
	protected editable var m_slotItemsCountWrapper : inkWidgetRef;
	protected editable var m_slotItemsCount : inkTextRef;
	protected editable var m_iconErrorIndicator : inkWidgetRef;
	protected editable var m_newItemsWrapper : inkWidgetRef;
	protected editable var m_newItemsCounter : inkTextRef;
	protected editable var m_lockIcon : inkWidgetRef;
	protected editable var m_transmogedIcon : inkWidgetRef;
	protected editable var m_iconWardrobeDisabled : inkWidgetRef;
	protected editable var m_comparisionArrow : inkWidgetRef;
	protected editable var m_iconTransmog : inkWidgetRef;
	protected editable var m_wardrobeInfoContainer : inkWidgetRef;
	protected editable var m_wardrobeInfoText : inkTextRef;
	protected editable var m_perkWrapper : inkWidgetRef;
	protected editable var m_perkIcon : inkImageRef;
	protected editable var m_playerFavouriteWidget : inkWidgetRef;
	protected var m_inventoryDataManager : InventoryDataManagerV2;
	protected var m_inventoryScriptableSystem : UIInventoryScriptableSystem;
	protected var m_uiScriptableSystem : weak< UIScriptableSystem >;
	protected var m_itemID : ItemID;
	protected var m_itemData : InventoryItemData;
	protected var m_recipeData : RecipeData;
	protected var m_equipmentArea : gamedataEquipmentArea;
	default m_equipmentArea = gamedataEquipmentArea.Invalid;
	protected var m_itemType : gamedataItemType;
	default m_itemType = gamedataItemType.Invalid;
	protected var m_emptySlotImage : CName;
	protected var m_slotName : String;
	protected var m_slotIndex : Int32;
	protected var m_attachmentsDisplay : array< weak< InventoryItemModSlotDisplay > >;
	private var m_transmogItem : ItemID;
	protected var m_slotID : TweakDBID;
	private var m_itemDisplayContext : ItemDisplayContext;
	protected var m_labelsContainerController : weak< ItemLabelContainerController >;
	protected var m_defaultFallbackImage : CName;
	default m_defaultFallbackImage = 'undefined';
	protected var m_defaultEmptyImage : CName;
	default m_defaultEmptyImage = 'icon_add';
	protected var m_defaultEmptyImageAtlas : String;
	default m_defaultEmptyImageAtlas = "base\gameplay\gui\fullscreen\inventory\inventory4_atlas.inkatlas";
	protected var m_emptyImage : CName;
	protected var m_emptyImageAtlas : String;
	protected var m_isEnoughMoney : Bool;
	protected var m_owned : Bool;
	protected var m_requirementsMet : Bool;
	protected var m_tooltipData : InventoryTooltipData;
	protected var m_isNew : Bool;
	private var m_isNewOverriden : Bool;
	protected var m_isPlayerFavourite : Bool;
	private var m_isQuestBought : Bool;
	protected var m_newItemsIDs : array< ItemID >;
	protected var m_newItemsFetched : Bool;
	protected var m_isBuybackStack : Bool;
	protected var m_isDLCNewItem : Bool;
	protected var m_parentItemData : weak< gameItemData >;
	protected var m_isLocked : Bool;
	protected var m_visibleWhenLocked : Bool;
	default m_visibleWhenLocked = true;
	protected var m_isTransmoged : Bool;
	protected var m_isWardrobeDisabled : Bool;
	protected var m_isUpgradable : Bool;
	protected var m_overrideQuantity : Int32;
	protected var m_hasAvailableItems : Bool;
	default m_hasAvailableItems = true;
	private var m_isSlotTransmogged : Bool;
	protected var m_wardrobeOutfitIndex : Int32;
	default m_wardrobeOutfitIndex = -1;
	private var m_additionalData : IScriptable;
	private var m_isBound : Bool;
	private var m_disableItemCounter : Bool;
	private var m_isCyberwarePreviewInInventory : Bool;
	private var m_isPerkRequiredCyberware : Bool;
	default m_isPerkRequiredCyberware = false;
	private var m_delayProxy : inkAnimProxy;
	private var m_delayAnimation : inkAnimDef;
	private var m_hoverTarget : weak< inkWidget >;
	private var m_upgradeProxy : inkAnimProxy;
	private var m_selectedCWProxy : inkAnimProxy;
	protected var DEBUG_isIconError : Bool;
	protected var DEBUG_iconErrorInfo : DEBUG_IconErrorInfo;
	protected var DEBUG_resolvedIconName : String;
	protected var DEBUG_recordItemName : String;
	protected var DEBUG_innerItemName : String;
	protected var DEBUG_isIconManuallySet : Bool;
	protected var DEBUG_iconsNameResolverIsDebug : Bool;
	protected var m_uiInventoryItem : weak< UIInventoryItem >;
	protected var m_displayContextData : weak< ItemDisplayContextData >;

	public function DEBUG_GetIconErrorInfo() : DEBUG_IconErrorInfo
	{
		return DEBUG_iconErrorInfo;
	}

	protected event OnInitialize()
	{
		super.OnInitialize();
		RegisterToCallback( 'OnHoverOver', this, 'OnDisplayHoverOver' );
		RegisterToCallback( 'OnHoverOut', this, 'OnDisplayHoverOut' );
		RegisterToCallback( 'OnPress', this, 'OnDisplayPressed' );
		RegisterToCallback( 'OnRelease', this, 'OnDisplayClicked' );
		RegisterToCallback( 'OnHold', this, 'OnDisplayHold' );
		m_labelsContainerController = ( ( weak< weak< ItemLabelContainerController > > )( inkCompoundRef.GetController( m_labelsContainer ) ) );
		inkWidgetRef.SetVisible( m_perkWrapper, false );
		inkWidgetRef.SetVisible( m_newItemsWrapper, false );
		inkImageRef.SetVisible( m_cyberwareEmptyImage, false );
		m_emptyImage = m_defaultEmptyImage;
		m_emptyImageAtlas = m_defaultEmptyImageAtlas;
	}

	protected event OnUninitialize()
	{
		var evt : inkPointerEvent;
		OnDisplayHoverOut( evt );
	}

	protected event OnDisplayHoverOver( evt : inkPointerEvent )
	{
		if( evt.GetCurrentTarget() == GetRootWidget() )
		{
			if( m_delayProxy )
			{
				m_delayProxy.Stop( true );
				m_delayProxy = NULL;
			}
			if( !( m_delayAnimation ) )
			{
				m_delayAnimation = GetDelayAnimation();
			}
			m_delayProxy = GetRootWidget().PlayAnimation( m_delayAnimation );
			m_delayProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnDelayedHoverOver' );
			m_hoverTarget = evt.GetTarget();
		}
	}

	protected event OnDelayedHoverOver( proxy : inkAnimProxy )
	{
		var hoverOverEvent : ItemDisplayHoverOverEvent;
		var DLCAddedHoverOverEvent : DLCAddedItemDisplayHoverOverEvent;
		var parentButton : weak< inkButtonController >;
		hoverOverEvent = new ItemDisplayHoverOverEvent;
		hoverOverEvent.itemData = GetItemData();
		hoverOverEvent.display = ( ( weak< weak< InventoryItemDisplayController > > )( this ) );
		hoverOverEvent.widget = m_hoverTarget;
		hoverOverEvent.isBuybackStack = m_isBuybackStack;
		hoverOverEvent.isQuestBought = m_isQuestBought;
		hoverOverEvent.transmogItem = m_transmogItem;
		hoverOverEvent.uiInventoryItem = GetUIInventoryItem();
		hoverOverEvent.displayContextData = m_displayContextData;
		QueueEvent( hoverOverEvent );
		parentButton = GetParentButton();
		if( !( parentButton.GetAutoUpdateWidgetState() ) && !( hoverOverEvent.toggleVisibilityControll ) )
		{
			GetRootWidget().SetState( 'Hover' );
		}
		if( m_isNew )
		{
			SetIsNew( false );
		}
		if( m_isDLCNewItem )
		{
			SetDLCNewIndicator( false );
			DLCAddedHoverOverEvent = new DLCAddedItemDisplayHoverOverEvent;
			DLCAddedHoverOverEvent.itemTDBID = ItemID.GetTDBID( GetItemID() );
			QueueEvent( DLCAddedHoverOverEvent );
		}
		m_delayProxy = NULL;
	}

	protected event OnDisplayHoverOut( evt : inkPointerEvent )
	{
		var hoverOutEvent : ItemDisplayHoverOutEvent;
		var parentButton : weak< inkButtonController >;
		if( m_delayProxy )
		{
			m_delayProxy.Stop( true );
			m_delayProxy = NULL;
		}
		hoverOutEvent = new ItemDisplayHoverOutEvent;
		QueueEvent( hoverOutEvent );
		parentButton = GetParentButton();
		if( !( parentButton.GetAutoUpdateWidgetState() ) )
		{
			GetRootWidget().SetState( 'Default' );
		}
	}

	protected event OnDisplayPressed( evt : inkPointerEvent )
	{
		var pressEvent : ItemDisplayPressEvent;
		pressEvent = new ItemDisplayPressEvent;
		pressEvent.actionName = evt.GetActionName();
		pressEvent.display = ( ( weak< weak< InventoryItemDisplayController > > )( this ) );
		QueueEvent( pressEvent );
	}

	protected event OnDisplayClicked( evt : inkPointerEvent )
	{
		var clickEvent : ItemDisplayClickEvent;
		clickEvent = new ItemDisplayClickEvent;
		clickEvent.itemData = GetItemData();
		clickEvent.actionName = evt.GetActionName();
		clickEvent.displayContext = m_itemDisplayContext;
		clickEvent.isBuybackStack = m_isBuybackStack;
		clickEvent.isQuestBought = m_isQuestBought;
		clickEvent.transmogItem = m_transmogItem;
		clickEvent.display = ( ( weak< weak< InventoryItemDisplayController > > )( this ) );
		clickEvent.uiInventoryItem = GetUIInventoryItem();
		clickEvent.displayContextData = m_displayContextData;
		HandleLocalClick( evt );
		QueueEvent( clickEvent );
	}

	protected function HandleLocalClick( evt : inkPointerEvent )
	{
		if( m_itemDisplayContext == ItemDisplayContext.Vendor && !( m_requirementsMet ) )
		{
			PlayLibraryAnimationOnTargets( 'itemDisplayRequirements_OnClick', SelectWidgets( GetRootWidget() ) );
		}
	}

	protected event OnDisplayHold( evt : inkPointerEvent )
	{
		var holdEvent : ItemDisplayHoldEvent;
		if( evt.GetHoldProgress() >= 1.0 )
		{
			holdEvent = new ItemDisplayHoldEvent;
			holdEvent.itemData = GetItemData();
			holdEvent.actionName = evt.GetActionName();
			holdEvent.display = ( ( weak< weak< InventoryItemDisplayController > > )( this ) );
			holdEvent.uiInventoryItem = GetUIInventoryItem();
			holdEvent.displayContextData = m_displayContextData;
			holdEvent.display = this;
			QueueEvent( holdEvent );
		}
	}

	public virtual function Setup( inventoryItem : weak< UIInventoryItem >, optional slotIndex : Int32 )
	{
		m_uiInventoryItem = inventoryItem;
		m_slotIndex = slotIndex;
		NewRefreshUI( inventoryItem );
	}

	public virtual function Setup( inventoryItem : weak< UIInventoryItem >, displayContextData : weak< ItemDisplayContextData >, optional isEnoughMoney : Bool, optional owned : Bool, optional isUpgradable : Bool, optional overrideQuantity : Int32 )
	{
		m_displayContextData = displayContextData;
		m_isEnoughMoney = isEnoughMoney;
		m_owned = owned;
		m_isUpgradable = isUpgradable;
		m_overrideQuantity = overrideQuantity;
		m_equipmentArea = inventoryItem.GetEquipmentArea();
		Setup( inventoryItem );
	}

	public virtual function Setup( inventoryItem : weak< UIInventoryItem >, equipmentArea : gamedataEquipmentArea, optional slotName : String, optional slotIndex : Int32, displayContextData : weak< ItemDisplayContextData > )
	{
		m_equipmentArea = equipmentArea;
		m_slotName = slotName;
		m_slotIndex = slotIndex;
		m_displayContextData = displayContextData;
		Setup( inventoryItem, slotIndex );
	}

	public virtual function Setup( inventoryItem : weak< UIInventoryItem >, equipmentArea : gamedataEquipmentArea, optional slotName : String, optional slotIndex : Int32, optional displayContext : ItemDisplayContext )
	{
		m_equipmentArea = equipmentArea;
		m_slotName = slotName;
		m_slotIndex = slotIndex;
		SetDisplayContext( displayContext, NULL );
		Setup( inventoryItem, slotIndex );
	}

	private function OnItemUpdate( itemData : weak< UIInventoryItem > )
	{
		m_uiInventoryItem = itemData;
		if( itemData != NULL )
		{
			m_isPlayerFavourite = itemData.IsPlayerFavourite();
		}
		else
		{
			m_isPlayerFavourite = false;
		}
		NewRefreshUI( itemData );
	}

	public function GetUIInventoryItem() : weak< UIInventoryItem >
	{
		return m_uiInventoryItem;
	}

	protected virtual function NewRefreshUI( itemData : UIInventoryItem )
	{
		var isVisualsEquipped : Bool;
		NewUpdateIcon( itemData );
		NewUpdateRarity( itemData );
		NewUpdateEmptyWidgets( itemData );
		NewUpdateQuantity( itemData );
		NewUpdateIsNewIndicator( itemData );
		NewUpdateMods( itemData );
		NewUpdateEquipped( itemData );
		NewUpdateIndicators( itemData );
		NewUpdateBlueprint( itemData );
		NewUpdateLocked( itemData );
		NewUpdateWeaponType( itemData );
		NewUpdateRequirements( itemData );
		NewUpdateTransmoged();
		NewUpdateWardrobeDisabled();
		UpdatePlayerFavourite();
		m_isSlotTransmogged = m_inventoryDataManager.IsSlotOverriden( m_equipmentArea ) && m_itemDisplayContext == ItemDisplayContext.GearPanel;
		if( inkWidgetRef.IsValid( m_iconTransmog ) )
		{
			isVisualsEquipped = itemData.IsTransmogItem();
			inkWidgetRef.SetVisible( m_iconTransmog, isVisualsEquipped || m_isSlotTransmogged );
		}
	}

	protected virtual function NewUpdateIcon( itemData : UIInventoryItem )
	{
		var iconName : String;
		var emptyIcon : CName;
		inkImageRef.SetVisible( m_itemFallbackImage, false );
		iconName = itemData.GetIconPath();
		if( iconName != "None" && iconName != "" )
		{
			DEBUG_resolvedIconName = iconName;
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, false );
			if( m_equipmentArea == gamedataEquipmentArea.Outfit )
			{
				inkImageRef.SetScale( m_itemImage, Vector2( 0.5, 0.5 ) );
			}
			else
			{
				inkImageRef.SetScale( m_itemImage, ( ( itemData.GetItemType() == gamedataItemType.Clo_Outfit ) ? ( Vector2( 0.5, 0.5 ) ) : ( Vector2( 1.0, 1.0 ) ) ) );
			}
			InkImageUtils.RequestSetImage( this, m_itemImage, iconName, 'OnIconCallback' );
		}
		else
		{
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, true );
			emptyIcon = UIItemsHelper.GetSlotShadowIcon( GetSlotID(), GetItemType(), GetEquipmentArea() );
			InkImageUtils.RequestSetImage( this, m_itemEmptyImage, emptyIcon );
		}
	}

	protected virtual function NewUpdateRarity( itemData : UIInventoryItem )
	{
		var quality : CName;
		var visible, isIconic : Bool;
		inkWidgetRef.SetVisible( m_rarityWrapper, true );
		if( itemData.GetItemData().HasTag( 'ChimeraMod' ) )
		{
			quality = UIItemsHelper.QualityEnumToName( gamedataQuality.Iconic );
		}
		else
		{
			quality = UIItemsHelper.QualityEnumToName( itemData.GetQuality() );
		}
		visible = quality != '';
		inkWidgetRef.SetVisible( m_itemRarity, visible );
		inkWidgetRef.SetVisible( m_rarityCommonWrapper, !( visible ) );
		inkWidgetRef.SetState( m_itemRarity, quality );
		isIconic = itemData.IsIconic();
		inkWidgetRef.SetVisible( m_iconicTint, isIconic );
	}

	protected virtual function NewUpdateEmptyWidgets( itemData : UIInventoryItem )
	{
		var i, showSize, hideSize : Int32;
		var isEmpty : Bool;
		showSize = m_showInEmptyWidgets.Size();
		hideSize = m_hideInEmptyWidgets.Size();
		isEmpty = itemData == NULL;
		for( i = 0; i < showSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_showInEmptyWidgets[ i ], isEmpty );
		}
		for( i = 0; i < hideSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_hideInEmptyWidgets[ i ], !( isEmpty ) );
		}
	}

	protected virtual function NewUpdateQuantity( itemData : UIInventoryItem )
	{
		var displayQuantityText : Bool;
		var quantityText : String;
		var countTreshold : Int32;
		var quantity : Int32;
		var itemType : gamedataItemType;
		displayQuantityText = false;
		inkWidgetRef.SetVisible( m_quantintyAmmoIcon, false );
		itemType = itemData.GetItemData().GetItemType();
		countTreshold = ( ( m_itemDisplayContext == ItemDisplayContext.DPAD_RADIAL ) ? ( 0 ) : ( 1 ) );
		if( itemData != NULL )
		{
			quantity = ( ( m_overrideQuantity > 0 ) ? ( m_overrideQuantity ) : ( itemData.GetQuantity() ) );
			if( ( quantity > countTreshold ) || itemData.GetItemType() == gamedataItemType.Con_Ammo )
			{
				quantityText = ( ( quantity > 9999 ) ? ( "9999+" ) : ( IntToString( quantity ) ) );
				inkTextRef.SetText( m_quantityText, quantityText );
				displayQuantityText = true;
			}
			else if( itemData.IsWeapon() )
			{
				if( itemData.GetWeaponType() == WeaponType.Melee || itemData.IsRecipe() )
				{
					displayQuantityText = false;
				}
				else
				{
					quantity = itemData.GetAmmo();
					quantityText = ( ( quantity > 999 ) ? ( "999+" ) : ( IntToString( quantity ) ) );
					inkWidgetRef.SetVisible( m_quantintyAmmoIcon, true );
					inkTextRef.SetText( m_quantityText, quantityText );
					displayQuantityText = true;
				}
			}
		}
		if( ( ( itemType == gamedataItemType.Con_Inhaler || itemType == gamedataItemType.Con_Injector ) || itemType == gamedataItemType.Gad_Grenade ) || itemType == gamedataItemType.Cyb_Ability )
		{
			displayQuantityText = false;
		}
		inkCompoundRef.SetVisible( m_quantityWrapper, displayQuantityText );
	}

	protected virtual function NewUpdateMods( itemData : weak< UIInventoryItem > )
	{
		var modsManager : weak< UIInventoryItemModsManager >;
		var canUseHacks : Bool;
		var item : weak< InventoryItemModSlotDisplay >;
		var i, targetSize : Int32;
		if( !( inkCompoundRef.Get( m_commonModsRoot ) ) )
		{
			return;
		}
		modsManager = itemData.GetModsManager();
		canUseHacks = itemData.IsCyberdeck() || itemData.GetItemType() == gamedataItemType.Cyb_NanoWires;
		targetSize = ( ( itemData.IsWeapon() || itemData.IsClothing() ) ? ( modsManager.GetModsSize() ) : ( 0 ) );
		if( canUseHacks )
		{
			targetSize = modsManager.GetAttachmentsSize();
		}
		while( m_attachmentsDisplay.Size() > targetSize )
		{
			inkCompoundRef.RemoveChild( m_commonModsRoot, m_attachmentsDisplay.PopBack().GetRootWidget() );
		}
		for( i = 0; i < targetSize; i += 1 )
		{
			if( m_attachmentsDisplay.Size() <= i )
			{
				item = ( ( InventoryItemModSlotDisplay )( SpawnFromLocal( inkCompoundRef.Get( m_commonModsRoot ), 'itemModSlot' ).GetController() ) );
				m_attachmentsDisplay.PushBack( item );
			}
			m_attachmentsDisplay[ i ].Setup( ( ( canUseHacks ) ? ( modsManager.GetAttachment( i ) ) : ( modsManager.GetMod( i ) ) ) );
		}
	}

	protected virtual function NewUpdateEquipped( itemData : UIInventoryItem )
	{
		var i : Int32;
		var showEquipped : Bool;
		showEquipped = itemData.IsEquipped() || ( m_wardrobeOutfitIndex >= 0 );
		for( i = 0; i < m_equippedWidgets.Size(); i += 1 )
		{
			inkWidgetRef.SetVisible( m_equippedWidgets[ i ], showEquipped );
		}
		for( i = 0; i < m_hideWhenEquippedWidgets.Size(); i += 1 )
		{
			inkWidgetRef.SetVisible( m_hideWhenEquippedWidgets[ i ], !( showEquipped ) );
		}
	}

	protected virtual function NewUpdateIndicators( itemData : UIInventoryItem )
	{
		inkWidgetRef.SetVisible( m_questItemMaker, ( ( itemData ) ? ( itemData.IsQuestItem() ) : ( false ) ) );
		if( m_labelsContainerController )
		{
			m_labelsContainerController.Clear();
			if( m_owned && m_displayContextData.GetDisplayContext() == ItemDisplayContext.VendorPlayer )
			{
				m_labelsContainerController.Add( ItemLabelType.Owned );
			}
			if( m_isBuybackStack )
			{
				m_labelsContainerController.Add( ItemLabelType.Buyback );
			}
			if( m_isNewOverriden )
			{
				if( m_isNew )
				{
					m_labelsContainerController.Add( ItemLabelType.New );
				}
			}
		}
	}

	protected virtual function NewUpdateBlueprint( itemData : UIInventoryItem )
	{
		var quality : CName;
		var showBlueprint : Bool;
		showBlueprint = ( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData ) || itemData.IsRecipe();
		inkWidgetRef.SetVisible( m_backgroundBlueprint, showBlueprint );
		inkWidgetRef.SetVisible( m_iconBlueprint, showBlueprint );
		if( showBlueprint )
		{
			if( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData )
			{
				quality = UIItemsHelper.QualityEnumToName( m_recipeData.id.Quality().Type() );
			}
			else
			{
				quality = itemData.GetQualityName();
			}
			inkWidgetRef.SetState( m_backgroundBlueprint, quality );
			inkImageRef.SetState( m_fluffBlueprint, quality );
			inkImageRef.SetState( m_itemImage, quality );
			inkImageRef.Get( m_itemImage ).DisableAllEffectsByType( inkEffectType.ColorFill );
			inkImageRef.Get( m_itemImage ).SetEffectEnabled( inkEffectType.ColorFill, quality, true );
		}
		else
		{
			inkImageRef.SetState( m_itemImage, 'Default' );
			inkImageRef.Get( m_itemImage ).DisableAllEffectsByType( inkEffectType.ColorFill );
		}
	}

	protected virtual function NewUpdateLocked( itemData : UIInventoryItem )
	{
		var i : Int32;
		var shouldBeGray, hasNoItems : Bool;
		hasNoItems = ( itemData == NULL ) && !( m_hasAvailableItems );
		shouldBeGray = m_isLocked || hasNoItems;
		inkWidgetRef.SetState( m_widgetWrapper, ( ( shouldBeGray ) ? ( 'Locked' ) : ( 'Default' ) ) );
		inkWidgetRef.SetVisible( m_lockIcon, m_isLocked );
		for( i = 0; i < m_backgroundFrames.Size(); i += 1 )
		{
			inkWidgetRef.SetState( m_backgroundFrames[ i ], ( ( shouldBeGray ) ? ( 'Locked' ) : ( 'Default' ) ) );
		}
	}

	protected virtual function NewUpdateTransmoged()
	{
		inkWidgetRef.SetVisible( m_transmogedIcon, m_isTransmoged );
	}

	protected virtual function NewUpdateWardrobeDisabled()
	{
		inkWidgetRef.SetVisible( m_iconWardrobeDisabled, m_isWardrobeDisabled );
	}

	protected virtual function NewUpdateWeaponType( itemData : UIInventoryItem )
	{
		if( itemData.GetEquipmentArea() == gamedataEquipmentArea.Weapon && !( itemData.IsRecipe() ) )
		{
			inkTextRef.SetLocalizedTextScript( m_weaponType, UIItemsHelper.GetItemTypeKey( itemData.GetItemType() ) );
			inkTextRef.SetVisible( m_weaponType, true );
			InkImageUtils.RequestSetImage( this, m_weaponTypeImage, UIItemsHelper.GetWeaponTypeIcon( itemData.GetItemType() ) );
			inkImageRef.SetVisible( m_weaponTypeImage, true );
			if( itemData.IsIconic() == true )
			{
				inkTextRef.SetState( m_weaponType, 'Iconic' );
				inkImageRef.SetState( m_weaponTypeImage, 'Iconic' );
			}
			else
			{
				inkTextRef.SetState( m_weaponType, 'Default' );
				inkImageRef.SetState( m_weaponTypeImage, 'Default' );
			}
		}
		else
		{
			inkTextRef.SetVisible( m_weaponType, false );
			inkImageRef.SetVisible( m_weaponTypeImage, false );
		}
	}

	protected virtual function NewUpdateRequirements( itemData : UIInventoryItem )
	{
		var requirementsMananger : weak< UIInventoryItemRequirementsManager >;
		requirementsMananger = itemData.GetRequirementsManager( m_displayContextData.GetPlayer() );
		if( m_displayContextData.GetDisplayContext() == ItemDisplayContext.Vendor && !( m_isEnoughMoney ) )
		{
			inkWidgetRef.SetState( m_requirementsWrapper, 'Money' );
		}
		else if( requirementsMananger.IsAnyItemDisplayRequirementNotMet() )
		{
			inkWidgetRef.SetState( m_requirementsWrapper, 'Requirements' );
		}
		else
		{
			inkWidgetRef.SetState( m_requirementsWrapper, 'Default' );
		}
	}

	public virtual function Setup( const itemData : ref< InventoryItemData >, slotID : TweakDBID, optional displayContext : ItemDisplayContext )
	{
		var hasItemsCounter : Bool;
		SetDisplayContext( displayContext, NULL );
		if( TDBID.IsValid( slotID ) )
		{
			m_slotID = slotID;
		}
		m_itemData = itemData;
		if( m_itemDisplayContext == ItemDisplayContext.Attachment )
		{
			hasItemsCounter = UpdateItemsCounter( m_itemData, m_slotID, m_itemType, m_equipmentArea );
			UpdateNewItemsIndicator( m_itemData, m_slotID, m_itemType, m_equipmentArea );
			m_hasAvailableItems = m_newItemsIDs.Size() > 0;
			inkWidgetRef.SetVisible( m_slotItemsCountWrapper, true );
			inkWidgetRef.SetState( m_slotItemsCountWrapper, ( ( hasItemsCounter ) ? ( 'Default' ) : ( 'NoItems' ) ) );
		}
		Setup( itemData );
	}

	public virtual function Setup( inventoryDataManager : InventoryDataManagerV2, const itemData : ref< InventoryItemData >, slotID : TweakDBID, optional displayContext : ItemDisplayContext, optional forceUpdateCounter : Bool )
	{
		var hasItemsCounter : Bool;
		var iconName : CName;
		m_inventoryDataManager = inventoryDataManager;
		SetDisplayContext( displayContext, NULL );
		if( TDBID.IsValid( slotID ) )
		{
			m_slotID = slotID;
		}
		m_itemData = itemData;
		iconName = UIItemsHelper.GetSlotShadowIcon( GetSlotID(), GetItemType(), GetEquipmentArea() );
		if( m_itemDisplayContext == ItemDisplayContext.Attachment )
		{
			hasItemsCounter = UpdateItemsCounter( m_itemData, m_slotID, m_itemType, m_equipmentArea, forceUpdateCounter );
			UpdateNewItemsIndicator( m_itemData, m_slotID, m_itemType, m_equipmentArea, forceUpdateCounter );
			m_hasAvailableItems = m_newItemsIDs.Size() > 0;
			inkWidgetRef.SetVisible( m_slotItemsCountWrapper, true );
			if( InventoryItemData.IsEmpty( m_itemData ) && iconName != 'UIIcon.ItemShadow_Program' )
			{
				inkWidgetRef.SetState( m_slotItemsCountWrapper, ( ( hasItemsCounter ) ? ( 'Default' ) : ( 'NoItems' ) ) );
				inkWidgetRef.SetVisible( m_slotItemsCountWrapper, true );
			}
			else
			{
				inkWidgetRef.SetVisible( m_slotItemsCountWrapper, false );
			}
		}
		Setup( itemData );
	}

	public virtual function Setup( tooltipData : InventoryTooltipData )
	{
		if( m_tooltipData != tooltipData )
		{
			m_tooltipData = tooltipData;
		}
		if( m_itemData != tooltipData.inventoryItemData )
		{
			m_itemData = tooltipData.inventoryItemData;
		}
		RefreshUI();
	}

	public virtual function Setup( const itemData : ref< InventoryItemData >, optional slotIndex : Int32 )
	{
		m_itemData = itemData;
		m_slotIndex = slotIndex;
		RefreshUI();
	}

	public virtual function Setup( recipeData : RecipeData, optional displayContext : ItemDisplayContext )
	{
		SetDisplayContext( displayContext, recipeData );
		m_isUpgradable = m_recipeData.isCraftable;
		RefreshUI();
	}

	public virtual function Setup( const itemData : ref< InventoryItemData >, displayContext : ItemDisplayContext, optional isEnoughMoney : Bool, optional owned : Bool, optional isUpgradable : Bool )
	{
		SetDisplayContext( displayContext, NULL );
		m_isEnoughMoney = isEnoughMoney;
		m_owned = owned;
		m_isUpgradable = isUpgradable;
		Setup( itemData );
	}

	public virtual function Setup( const itemData : ref< InventoryItemData >, equipmentArea : gamedataEquipmentArea, optional slotName : String, optional slotIndex : Int32, optional displayContext : ItemDisplayContext )
	{
		m_equipmentArea = equipmentArea;
		m_slotName = slotName;
		m_slotIndex = slotIndex;
		SetDisplayContext( displayContext, NULL );
		Setup( itemData, slotIndex );
	}

	public virtual function Bind( inventoryDataManager : InventoryDataManagerV2, equipmentArea : gamedataEquipmentArea, optional slotIndex : Int32, optional displayContext : ItemDisplayContext, optional setWardrobeOutfit : Bool, optional wardrobeOutfitIndex : Int32 )
	{
		if( setWardrobeOutfit )
		{
			m_wardrobeOutfitIndex = wardrobeOutfitIndex;
		}
		m_equipmentArea = equipmentArea;
		m_slotIndex = slotIndex;
		m_inventoryDataManager = inventoryDataManager;
		SetDisplayContext( displayContext, NULL );
		m_isBound = true;
		OnItemUpdate( m_inventoryDataManager.GetEquippedItemIdInArea( m_equipmentArea, m_slotIndex ) );
	}

	public virtual function Bind( inventoryScriptableSystem : UIInventoryScriptableSystem, equipmentArea : gamedataEquipmentArea, optional slotIndex : Int32, displayContext : ItemDisplayContext )
	{
		m_equipmentArea = equipmentArea;
		m_slotIndex = slotIndex;
		m_inventoryScriptableSystem = inventoryScriptableSystem;
		SetDisplayContext( displayContext, NULL );
		m_isBound = true;
		OnItemUpdate( m_inventoryScriptableSystem.GetPlayerAreaItem( m_equipmentArea, m_slotIndex ) );
	}

	public virtual function BindVisualSlot( equipmentArea : gamedataEquipmentArea, itemsAmount : Int32, optional inventoryItemData : InventoryItemData, optional slotIndex : Int32, optional displayContext : ItemDisplayContext ) {}

	public virtual function InvalidateVisualContent( const inventoryItemData : ref< InventoryItemData >, itemsAmount : Int32, equipped : Bool ) {}

	public virtual function SetParentItem( parentItemData : gameItemData )
	{
		m_parentItemData = parentItemData;
	}

	public virtual function BindComparisonAndScriptableSystem( uiScriptableSystem : weak< UIScriptableSystem >, comparisonResolver : weak< ItemPreferredComparisonResolver > )
	{
		var hasNewItems : Bool;
		m_uiScriptableSystem = uiScriptableSystem;
		UpdateItemsCounter( m_itemData, m_slotID, m_itemType, m_equipmentArea );
		hasNewItems = UpdateNewItemsIndicator( m_itemData, m_slotID, m_itemType, m_equipmentArea );
		if( hasNewItems )
		{
			inkWidgetRef.SetVisible( m_slotItemsCountWrapper, false );
		}
		if( m_isBound )
		{
			SetIsPlayerFavourite( m_uiScriptableSystem.IsItemPlayerFavourite( m_itemID ) );
		}
	}

	public function BindUIScriptableSystem( uiScriptableSystem : weak< UIScriptableSystem > )
	{
		m_uiScriptableSystem = uiScriptableSystem;
		if( m_isBound )
		{
			SetIsPlayerFavourite( m_uiScriptableSystem.IsItemPlayerFavourite( m_itemID ) );
		}
	}

	public function SetLocked( value : Bool, visibleWhenLocked : Bool )
	{
		m_isLocked = value;
		m_visibleWhenLocked = visibleWhenLocked;
		UpdateLocked();
	}

	public function SetTransmoged( value : Bool )
	{
		m_isTransmoged = value;
		UpdateTransmoged();
	}

	public function SetItemCounterDisabled( value : Bool )
	{
		m_disableItemCounter = value;
	}

	public function SetWardrobeDisabled( value : Bool )
	{
		m_isWardrobeDisabled = value;
		UpdateWardrobeDisabled();
	}

	public function IsLocked() : Bool
	{
		return m_isLocked;
	}

	public function SetHUDMode( inHUD : Bool )
	{
		GetRootWidget().SetState( ( ( inHUD ) ? ( 'HUD' ) : ( 'Default' ) ) );
	}

	protected function SetDisplayContext( context : ItemDisplayContext, recipeData : RecipeData )
	{
		var itemInventory : InventoryItemData;
		m_itemDisplayContext = context;
		m_recipeData = recipeData;
		if( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData )
		{
			InventoryItemData.SetEmpty( itemInventory, false );
			InventoryItemData.SetID( itemInventory, ItemID.CreateQuery( m_recipeData.id.GetID() ) );
		}
	}

	public function GetDisplayContext() : ItemDisplayContext
	{
		return m_itemDisplayContext;
	}

	public virtual function InvalidateContent( optional setWardrobeOutfit : Bool, optional wardrobeOutfitIndex : Int32 )
	{
		if( setWardrobeOutfit )
		{
			m_wardrobeOutfitIndex = wardrobeOutfitIndex;
		}
		if( m_inventoryScriptableSystem )
		{
			OnItemUpdate( m_inventoryScriptableSystem.GetPlayerAreaItem( m_equipmentArea, m_slotIndex ) );
			return;
		}
		OnItemUpdate( m_inventoryDataManager.GetEquippedItemIdInArea( m_equipmentArea, m_slotIndex ) );
	}

	public function InvalidateQuantity()
	{
		NewUpdateQuantity( m_uiInventoryItem );
	}

	private function OnItemUpdate( itemID : ItemID )
	{
		var hasNewItems : Bool;
		m_itemID = itemID;
		m_itemData = m_inventoryDataManager.GetItemDataFromIDInLoadout( itemID );
		UpdateItemsCounter( m_itemData, m_slotID, m_itemType, m_equipmentArea, true );
		hasNewItems = UpdateNewItemsIndicator( m_itemData, m_slotID, m_itemType, m_equipmentArea );
		if( ItemID.IsValid( m_itemID ) )
		{
			m_isPlayerFavourite = m_uiScriptableSystem.IsItemPlayerFavourite( m_itemID );
		}
		else
		{
			m_isPlayerFavourite = false;
		}
		if( hasNewItems )
		{
			inkWidgetRef.SetVisible( m_slotItemsCountWrapper, false );
		}
		RefreshUI();
	}

	public virtual function UpdateThisSlotItems( optional item : InventoryItemData, optional slotID : TweakDBID, optional itemType : gamedataItemType, optional equipmentArea : gamedataEquipmentArea, optional force : Bool )
	{
		if( !( m_newItemsFetched ) || force )
		{
			m_newItemsIDs.Clear();
			if( ( slotID == T"AttachmentSlots.Scope" ) || ( slotID == T"AttachmentSlots.PowerModule" ) )
			{
				m_inventoryDataManager.GetPlayerItemsIDsFast( m_parentItemData.GetID(), slotID, itemType, equipmentArea, true, m_newItemsIDs );
			}
			else
			{
				m_inventoryDataManager.GetPlayerItemsIDs( item, slotID, itemType, equipmentArea, true, m_newItemsIDs );
			}
			if( equipmentArea == gamedataEquipmentArea.Consumable )
			{
				m_newItemsIDs = m_inventoryDataManager.FilterHotkeyConsumables( m_newItemsIDs );
			}
			if( InventoryDataManagerV2.IsProgramSlot( slotID ) )
			{
				m_newItemsIDs = m_inventoryDataManager.DistinctPrograms( m_newItemsIDs );
			}
			m_newItemsFetched = true;
		}
	}

	public virtual function UpdateItemsCounter( optional item : InventoryItemData, optional slotID : TweakDBID, optional itemType : gamedataItemType, optional equipmentArea : gamedataEquipmentArea, optional force : Bool ) : Bool
	{
		var itemsCount : Int32;
		if( ( !( ItemID.IsValid( m_itemID ) ) && InventoryItemData.IsEmpty( m_itemData ) ) && !( m_disableItemCounter ) )
		{
			UpdateThisSlotItems( item, slotID, itemType, equipmentArea, force );
			itemsCount = m_newItemsIDs.Size();
			inkTextRef.SetText( m_slotItemsCount, IntToString( itemsCount ) );
			inkWidgetRef.SetVisible( m_slotItemsCountWrapper, itemsCount > 0 );
			return itemsCount > 0;
		}
		else
		{
			inkTextRef.SetText( m_slotItemsCount, IntToString( 0 ) );
			inkWidgetRef.SetVisible( m_slotItemsCountWrapper, false );
		}
		return false;
	}

	private function IsInRestrictedNewArea( equipmentArea : gamedataEquipmentArea ) : Bool
	{
		return ( ( equipmentArea == gamedataEquipmentArea.AbilityCW || equipmentArea == gamedataEquipmentArea.Gadget ) || equipmentArea == gamedataEquipmentArea.QuickSlot ) || equipmentArea == gamedataEquipmentArea.Consumable;
	}

	private function IsItemIconic() : Bool
	{
		if( m_itemDisplayContext == ItemDisplayContext.Attachment && m_parentItemData )
		{
			return InventoryUtils.GetInnerItemStatValueByType( m_parentItemData, m_slotID, gamedataStatType.IsItemIconic ) > 0.0;
		}
		return RPGManager.IsItemIconic( InventoryItemData.GetGameItemData( m_itemData ) );
	}

	protected virtual function UpdateNewItemsIndicator( optional item : InventoryItemData, optional slotID : TweakDBID, optional itemType : gamedataItemType, optional equipmentArea : gamedataEquipmentArea, optional force : Bool ) : Bool
	{
		var i, itemsCount : Int32;
		if( ( equipmentArea == gamedataEquipmentArea.Weapon && ( m_slotIndex != 0 ) ) || IsInRestrictedNewArea( equipmentArea ) )
		{
			inkWidgetRef.SetVisible( m_newItemsWrapper, false );
			return false;
		}
		if( m_uiScriptableSystem != NULL )
		{
			UpdateThisSlotItems( item, slotID, itemType, equipmentArea, force );
			for( i = 0; i < m_newItemsIDs.Size(); i += 1 )
			{
				if( m_uiScriptableSystem.IsInventoryItemNew( m_newItemsIDs[ i ] ) )
				{
					itemsCount += 1;
				}
			}
			inkTextRef.SetText( m_newItemsCounter, IntToString( itemsCount ) );
			inkWidgetRef.SetVisible( m_newItemsWrapper, itemsCount > 0 );
			return itemsCount > 0;
		}
		else
		{
			inkWidgetRef.SetVisible( m_newItemsWrapper, false );
		}
		return false;
	}

	public virtual function SetDefaultShadowIcon( textureAtlasPart : CName, optional textureAtlas : String )
	{
		m_emptyImage = textureAtlasPart;
		if( IsStringValid( textureAtlas ) )
		{
			m_emptyImageAtlas = textureAtlas;
		}
		else
		{
			m_emptyImageAtlas = m_defaultEmptyImageAtlas;
		}
	}

	protected virtual function RefreshUI()
	{
		var equipmentArea : gamedataEquipmentArea;
		var isVisualsEquipped : Bool;
		var isEmpty : Bool;
		UpdateIcon();
		UpdateRarity();
		UpdateMods();
		UpdateQuantity();
		UpdateEmptyWidgets();
		UpdateEquipped();
		UpdateItemName();
		UpdatePrice();
		UpdateIndicators();
		UpdateIsNewIndicator();
		UpdateRequirements();
		UpdateBlueprint();
		UpdateLoot();
		UpdateLocked();
		UpdateTransmoged();
		UpdateWardrobeDisabled();
		UpdatePlayerFavourite();
		if( m_wardrobeOutfitIndex >= 0 )
		{
			inkWidgetRef.SetVisible( m_wardrobeInfoContainer, true );
			inkTextRef.SetText( m_wardrobeInfoText, IntToString( m_wardrobeOutfitIndex + 1 ) );
		}
		else
		{
			inkWidgetRef.SetVisible( m_wardrobeInfoContainer, false );
		}
		equipmentArea = InventoryItemData.GetEquipmentArea( m_itemData );
		if( equipmentArea == gamedataEquipmentArea.Weapon )
		{
			inkTextRef.SetLocalizedTextScript( m_weaponType, InventoryItemData.GetLocalizedItemType( m_itemData ) );
			inkTextRef.SetVisible( m_weaponType, true );
			InkImageUtils.RequestSetImage( this, m_weaponTypeImage, UIItemsHelper.GetWeaponTypeIcon( InventoryItemData.GetItemType( m_itemData ) ) );
			inkImageRef.SetVisible( m_weaponTypeImage, true );
			if( IsItemIconic() )
			{
				inkTextRef.SetState( m_weaponType, 'Iconic' );
				inkImageRef.SetState( m_weaponTypeImage, 'Iconic' );
			}
			else
			{
				inkTextRef.SetState( m_weaponType, 'Default' );
				inkImageRef.SetState( m_weaponTypeImage, 'Default' );
			}
		}
		else
		{
			inkTextRef.SetLocalizedTextScript( m_weaponType, InventoryItemData.GetLocalizedItemType( m_itemData ) );
			inkTextRef.SetVisible( m_weaponType, false );
			inkImageRef.SetVisible( m_weaponTypeImage, false );
		}
		isEmpty = InventoryItemData.IsEmpty( m_itemData );
		if( isEmpty )
		{
			inkWidgetRef.SetVisible( m_comparisionArrow, false );
		}
		else
		{
			inkWidgetRef.SetVisible( m_comparisionArrow, InventoryDataManagerV2.IsEquipmentAreaComparable( equipmentArea ) );
		}
		m_isSlotTransmogged = m_inventoryDataManager.IsSlotOverriden( m_equipmentArea ) && m_itemDisplayContext == ItemDisplayContext.GearPanel;
		if( m_inventoryDataManager.IsTransmogEnabled() )
		{
			if( inkWidgetRef.IsValid( m_iconTransmog ) )
			{
				isVisualsEquipped = InventoryItemData.IsVisualsEquipped( m_itemData );
				inkWidgetRef.SetVisible( m_iconTransmog, isVisualsEquipped || m_isSlotTransmogged );
			}
			if( m_itemDisplayContext == ItemDisplayContext.GearPanel )
			{
				UpdateTransmogControls( isEmpty );
			}
		}
	}

	private function UpdateTransmogControls( isEmpty : Bool )
	{
		if( !( inkCompoundRef.IsValid( m_transmogContainer ) ) )
		{
			return;
		}
		if( !( isEmpty ) && m_inventoryDataManager.IsSlotOverriden( m_equipmentArea ) )
		{
			m_transmogItem = m_inventoryDataManager.GetVisualItemInSlot( m_equipmentArea );
		}
		else
		{
			m_transmogItem = ItemID.None();
		}
	}

	protected virtual function UpdateEmptyWidgets()
	{
		var i, showSize, hideSize : Int32;
		var isEmpty : Bool;
		showSize = m_showInEmptyWidgets.Size();
		hideSize = m_hideInEmptyWidgets.Size();
		isEmpty = ( ( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData ) ? ( false ) : ( InventoryItemData.IsEmpty( m_itemData ) ) );
		if( m_wardrobeOutfitIndex >= 0 )
		{
			isEmpty = false;
		}
		for( i = 0; i < showSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_showInEmptyWidgets[ i ], isEmpty );
		}
		for( i = 0; i < hideSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_hideInEmptyWidgets[ i ], !( isEmpty ) );
		}
	}

	protected virtual function UpdateLocked()
	{
		var i : Int32;
		var shouldBeGray, hasNoItems : Bool;
		var hideLocked : Bool;
		if( m_isPerkRequiredCyberware )
		{
			return;
		}
		hasNoItems = InventoryItemData.IsEmpty( m_itemData ) && !( m_hasAvailableItems );
		shouldBeGray = m_isLocked || hasNoItems;
		hideLocked = !( m_visibleWhenLocked ) && m_isLocked;
		inkWidgetRef.SetState( m_widgetWrapper, ( ( shouldBeGray ) ? ( 'Locked' ) : ( 'Default' ) ) );
		inkWidgetRef.SetVisible( m_lockIcon, m_isLocked );
		if( hideLocked )
		{
			inkWidgetRef.SetOpacity( m_widgetWrapper, 0.0 );
			inkWidgetRef.SetOpacity( m_lockIcon, 0.0 );
		}
		for( i = 0; i < m_backgroundFrames.Size(); i += 1 )
		{
			inkWidgetRef.SetState( m_backgroundFrames[ i ], ( ( shouldBeGray ) ? ( 'Locked' ) : ( 'Default' ) ) );
			if( hideLocked )
			{
				inkWidgetRef.SetOpacity( m_backgroundFrames[ i ], 0.0 );
			}
		}
	}

	protected virtual function UpdateTransmoged()
	{
		inkWidgetRef.SetVisible( m_transmogedIcon, m_isTransmoged );
	}

	protected virtual function UpdateWardrobeDisabled()
	{
		inkWidgetRef.SetVisible( m_iconWardrobeDisabled, m_isWardrobeDisabled );
	}

	protected virtual function UpdateLoot()
	{
		if( InventoryItemData.GetLootItemType( m_itemData ) == LootItemType.Default )
		{
			inkWidgetRef.SetVisible( m_lootitemflufficon, true );
			inkImageRef.SetVisible( m_lootitemtypeicon, false );
		}
		else if( InventoryItemData.GetLootItemType( m_itemData ) == LootItemType.Quest )
		{
			inkWidgetRef.SetVisible( m_lootitemflufficon, false );
			inkImageRef.SetTexturePart( m_lootitemtypeicon, 'quest' );
			inkImageRef.SetVisible( m_lootitemtypeicon, true );
		}
		else if( InventoryItemData.GetLootItemType( m_itemData ) == LootItemType.Shard )
		{
			inkWidgetRef.SetVisible( m_lootitemflufficon, false );
			inkImageRef.SetTexturePart( m_lootitemtypeicon, 'shard' );
			inkImageRef.SetVisible( m_lootitemtypeicon, true );
		}
	}

	protected virtual function UpdateBlueprint()
	{
		var quality : CName;
		var showBlueprint : Bool;
		var localItemData : gameItemData;
		localItemData = InventoryItemData.GetGameItemData( m_itemData );
		showBlueprint = ( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData ) || ( localItemData && localItemData.HasTag( 'Recipe' ) );
		inkWidgetRef.SetVisible( m_backgroundBlueprint, showBlueprint );
		inkWidgetRef.SetVisible( m_iconBlueprint, showBlueprint );
		if( showBlueprint )
		{
			if( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData )
			{
				quality = UIItemsHelper.QualityEnumToName( m_recipeData.id.Quality().Type() );
			}
			else
			{
				quality = InventoryItemData.GetQuality( m_itemData );
			}
			inkWidgetRef.SetState( m_backgroundBlueprint, quality );
			inkImageRef.SetState( m_fluffBlueprint, quality );
			inkImageRef.SetState( m_itemImage, quality );
			inkImageRef.Get( m_itemImage ).DisableAllEffectsByType( inkEffectType.ColorFill );
			inkImageRef.Get( m_itemImage ).SetEffectEnabled( inkEffectType.ColorFill, quality, true );
		}
		else
		{
			inkImageRef.SetState( m_itemImage, 'Default' );
			inkImageRef.Get( m_itemImage ).DisableAllEffectsByType( inkEffectType.ColorFill );
		}
	}

	protected virtual function UpdateRequirements()
	{
		var requirement : Bool;
		var moneyRequirementFail : Bool;
		var streetCredRequirementMet : Bool;
		var requirementData : SItemStackRequirementData;
		var localItemData : gameItemData;
		requirement = true;
		moneyRequirementFail = m_itemDisplayContext == ItemDisplayContext.Vendor && !( m_isEnoughMoney );
		streetCredRequirementMet = true;
		m_requirementsMet = true;
		inkWidgetRef.SetState( m_requirementsWrapper, 'Default' );
		localItemData = InventoryItemData.GetGameItemData( m_itemData );
		if( ( localItemData && ( localItemData.GetStatValueByType( gamedataStatType.Strength ) > 0.0 ) ) && ( InventoryItemData.GetPlayerStrenght( m_itemData ) < RoundF( localItemData.GetStatValueByType( gamedataStatType.Strength ) ) ) )
		{
			requirement = false;
		}
		else if( ( InventoryItemData.GetRequiredLevel( m_itemData ) > 0 ) && ( InventoryItemData.GetPlayerLevel( m_itemData ) < InventoryItemData.GetRequiredLevel( m_itemData ) ) )
		{
			requirement = false;
		}
		if( !( InventoryItemData.IsRequirementMet( m_itemData ) ) )
		{
			requirementData = InventoryItemData.GetRequirement( m_itemData );
			if( requirementData.statType == gamedataStatType.StreetCred && ( InventoryItemData.GetPlayerStreetCred( m_itemData ) < RoundF( requirementData.requiredValue ) ) )
			{
				streetCredRequirementMet = false;
			}
			requirement = false;
		}
		else if( !( InventoryItemData.IsEquippable( m_itemData ) ) )
		{
			requirement = false;
		}
		if( !( streetCredRequirementMet ) )
		{
			inkWidgetRef.SetState( m_requirementsWrapper, 'StreetCred' );
			m_requirementsMet = false;
		}
		else if( moneyRequirementFail )
		{
			inkWidgetRef.SetState( m_requirementsWrapper, 'Money' );
			m_requirementsMet = false;
		}
		else if( !( requirement ) )
		{
			if( !( InventoryItemData.IsEquipped( m_itemData ) ) && !( EquipmentSystem.IsItemCyberdeck( InventoryItemData.GetID( m_itemData ) ) ) )
			{
				inkWidgetRef.SetState( m_requirementsWrapper, 'Requirements' );
				m_requirementsMet = false;
			}
		}
		if( m_itemDisplayContext == ItemDisplayContext.Crafting )
		{
			inkWidgetRef.SetState( m_requirementsWrapper, ( ( !( m_isUpgradable ) ) ? ( 'NoCraftable' ) : ( 'Default' ) ) );
		}
	}

	protected virtual function UpdateIndicators()
	{
		var localData : gameItemData;
		if( m_labelsContainerController )
		{
			m_labelsContainerController.Clear();
		}
		if( m_owned && m_itemDisplayContext == ItemDisplayContext.VendorPlayer )
		{
			if( m_labelsContainerController )
			{
				m_labelsContainerController.Add( ItemLabelType.Owned );
			}
		}
		if( m_isBuybackStack )
		{
			m_labelsContainerController.Add( ItemLabelType.Buyback );
		}
		if( m_isDLCNewItem )
		{
			m_labelsContainerController.Add( ItemLabelType.DLCNew );
		}
		localData = InventoryItemData.GetGameItemData( m_itemData );
		if( localData )
		{
			inkWidgetRef.SetVisible( m_questItemMaker, localData.HasTag( 'Quest' ) || localData.HasTag( 'UnequipBlocked' ) );
		}
		else
		{
			inkWidgetRef.SetVisible( m_questItemMaker, false );
		}
	}

	protected virtual function UpdateIsNewIndicator()
	{
		if( m_isNew )
		{
			m_labelsContainerController.Add( ItemLabelType.New );
		}
		else
		{
			m_labelsContainerController.Remove( ItemLabelType.New );
		}
	}

	protected virtual function NewUpdateIsNewIndicator( itemData : weak< UIInventoryItem > )
	{
		var isNew : Bool;
		if( m_isNewOverriden )
		{
			isNew = m_isNew;
		}
		else
		{
			isNew = itemData.IsNew();
		}
		if( isNew )
		{
			m_labelsContainerController.Add( ItemLabelType.New );
		}
		else
		{
			m_labelsContainerController.Remove( ItemLabelType.New );
		}
	}

	protected function UpdatePlayerFavourite()
	{
		inkWidgetRef.SetVisible( m_playerFavouriteWidget, m_isPlayerFavourite );
	}

	protected virtual function IsEquippedContext( context : ItemDisplayContext ) : Bool
	{
		return ( ( ( context == ItemDisplayContext.VendorPlayer || context == ItemDisplayContext.Backpack ) || context == ItemDisplayContext.GearPanel ) || context == ItemDisplayContext.Ripperdoc ) || context == ItemDisplayContext.Crafting;
	}

	protected virtual function ShouldShowEquipped() : Bool
	{
		if( m_itemDisplayContext == ItemDisplayContext.Attachment )
		{
			return !( InventoryItemData.IsEmpty( m_itemData ) );
		}
		else
		{
			return InventoryItemData.IsEquipped( m_itemData ) && IsEquippedContext( m_itemDisplayContext );
		}
	}

	public function SetCyberwarePrieviewInInventroy()
	{
		var i, hideSize, showSize : Int32;
		m_isCyberwarePreviewInInventory = true;
		hideSize = m_hideWhenCyberwareInInventory.Size();
		showSize = m_showWhenCyberwareInInventory.Size();
		for( i = 0; i < hideSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_hideWhenCyberwareInInventory[ i ], false );
		}
		for( i = 0; i < showSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_showWhenCyberwareInInventory[ i ], true );
			inkWidgetRef.SetState( m_showWhenCyberwareInInventory[ i ], 'ReadOnly' );
			inkWidgetRef.SetOpacity( m_showWhenCyberwareInInventory[ i ], 0.05 );
		}
		inkWidgetRef.SetOpacity( m_rarityWrapper, 0.2 );
		for( i = 0; i < m_backgroundFrames.Size(); i += 1 )
		{
			inkWidgetRef.SetOpacity( m_backgroundFrames[ i ], 0.1 );
		}
	}

	public function SetCyberwareEmptyInInventroy()
	{
		var i, hideSize : Int32;
		hideSize = m_hideWhenCyberwareInInventory.Size();
		for( i = 0; i < hideSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_hideWhenCyberwareInInventory[ i ], false );
		}
		inkImageRef.SetVisible( m_itemEmptyImage, false );
		inkImageRef.SetVisible( m_cyberwareEmptyImage, !( inkWidgetRef.IsVisible( m_perkWrapper ) ) );
	}

	public function SetUpgradableCyberware( isUpgradable : Bool )
	{
		var playbackOptions : inkAnimOptions;
		if( m_upgradeProxy != NULL )
		{
			m_upgradeProxy.GotoStartAndStop();
		}
		if( isUpgradable )
		{
			playbackOptions.loopInfinite = true;
			playbackOptions.loopType = inkanimLoopType.Cycle;
			m_upgradeProxy = PlayLibraryAnimation( 'itemDisplay_upgrade', playbackOptions );
		}
	}

	public function SetPerkRequiredCyberware( area : gamedataEquipmentArea )
	{
		var i : Int32;
		m_isPerkRequiredCyberware = true;
		inkImageRef.SetVisible( m_itemEmptyImage, false );
		inkImageRef.SetVisible( m_cyberwareEmptyImage, false );
		inkWidgetRef.SetVisible( m_perkWrapper, true );
		m_isLocked = true;
		inkWidgetRef.SetState( m_widgetWrapper, 'Locked' );
		for( i = 0; i < m_backgroundFrames.Size(); i += 1 )
		{
			inkWidgetRef.SetState( m_backgroundFrames[ i ], 'Locked' );
		}
		if( area == gamedataEquipmentArea.MusculoskeletalSystemCW )
		{
			inkImageRef.SetTexturePart( m_perkIcon, 'Tech_Central_Milestone_3' );
		}
		if( area == gamedataEquipmentArea.HandsCW )
		{
			inkImageRef.SetTexturePart( m_perkIcon, 'coldblood_area_06_perk3' );
		}
	}

	public function IsPerkRequiredCyberware() : Bool
	{
		return m_isPerkRequiredCyberware;
	}

	public function PlayUpgradeFeedback()
	{
		PlayLibraryAnimation( 'itemDisplay_upgraded' );
	}

	public function PlayEquipFeedback()
	{
		PlayLibraryAnimation( 'Equip_Item_Display' );
	}

	protected virtual function UpdateEquipped()
	{
		var i, showSize, hideSize : Int32;
		var showEquipped : Bool;
		showSize = m_equippedWidgets.Size();
		hideSize = m_hideWhenEquippedWidgets.Size();
		showEquipped = InventoryItemData.IsEquipped( m_itemData ) || ( m_wardrobeOutfitIndex >= 0 );
		for( i = 0; i < showSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_equippedWidgets[ i ], showEquipped || m_isCyberwarePreviewInInventory );
		}
		for( i = 0; i < hideSize; i += 1 )
		{
			inkWidgetRef.SetVisible( m_hideWhenEquippedWidgets[ i ], !( showEquipped ) );
		}
	}

	protected virtual function UpdateQuantity()
	{
		var displayQuantityText : Bool;
		var quantityText : String;
		var itemInventory : InventoryItemData;
		var countTreshold : Int32;
		var itemType : gamedataItemType;
		displayQuantityText = false;
		itemInventory = GetItemData();
		itemType = InventoryItemData.GetItemType( itemInventory );
		inkWidgetRef.SetVisible( m_quantintyAmmoIcon, false );
		countTreshold = ( ( m_itemDisplayContext == ItemDisplayContext.DPAD_RADIAL ) ? ( 0 ) : ( 1 ) );
		if( !( InventoryItemData.IsEmpty( itemInventory ) ) )
		{
			if( ( InventoryItemData.GetQuantity( itemInventory ) > countTreshold ) || itemType == gamedataItemType.Con_Ammo )
			{
				quantityText = ( ( InventoryItemData.GetQuantity( itemInventory ) > 9999 ) ? ( "9999+" ) : ( IntToString( InventoryItemData.GetQuantity( itemInventory ) ) ) );
				inkTextRef.SetText( m_quantityText, quantityText );
				displayQuantityText = true;
			}
			else if( InventoryItemData.GetEquipmentArea( itemInventory ) == gamedataEquipmentArea.Weapon )
			{
				if( InventoryItemData.GetGameItemData( itemInventory ).HasTag( WeaponObject.GetMeleeWeaponTag() ) )
				{
					displayQuantityText = false;
				}
				else
				{
					quantityText = ( ( InventoryItemData.GetAmmo( itemInventory ) > 999 ) ? ( "999+" ) : ( IntToString( InventoryItemData.GetAmmo( itemInventory ) ) ) );
					inkWidgetRef.SetVisible( m_quantintyAmmoIcon, true );
					inkTextRef.SetText( m_quantityText, quantityText );
					displayQuantityText = true;
				}
			}
		}
		if( ( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData ) && itemType == gamedataItemType.Con_Ammo )
		{
			quantityText = IntToString( CraftingSystem.GetAmmoBulletAmount( ItemID.GetTDBID( InventoryItemData.GetID( m_recipeData.inventoryItem ) ) ) );
			inkTextRef.SetText( m_quantityText, quantityText );
			inkWidgetRef.SetVisible( m_quantintyAmmoIcon, true );
			displayQuantityText = true;
		}
		if( ( ( itemType == gamedataItemType.Con_Inhaler || itemType == gamedataItemType.Con_Injector ) || itemType == gamedataItemType.Gad_Grenade ) || itemType == gamedataItemType.Cyb_Launcher )
		{
			if( m_itemDisplayContext == ItemDisplayContext.DPAD_RADIAL || m_itemDisplayContext == ItemDisplayContext.GearPanel )
			{
				quantityText = IntToString( InventoryItemData.GetQuantity( itemInventory ) );
				inkTextRef.SetText( m_quantityText, quantityText );
				displayQuantityText = true;
			}
			else
			{
				displayQuantityText = false;
			}
		}
		if( itemType == gamedataItemType.Cyb_Ability )
		{
			displayQuantityText = false;
		}
		inkTextRef.SetVisible( m_quantityText, displayQuantityText );
		inkCompoundRef.SetVisible( m_quantityWrapper, displayQuantityText );
	}

	protected virtual function UpdateItemName()
	{
		var itemInventory : InventoryItemData;
		if( inkTextRef.Get( m_itemName ) )
		{
			if( ItemID.IsValid( m_tooltipData.itemID ) )
			{
				inkTextRef.SetText( m_itemName, m_tooltipData.itemName );
			}
			else
			{
				itemInventory = GetItemData();
				inkTextRef.SetText( m_itemName, InventoryItemData.GetName( itemInventory ) );
			}
		}
	}

	protected virtual function GetPriceText() : String
	{
		var price, vendorPrice, stackPrice, vendorStackPrice : String;
		var euroDolarText : String;
		euroDolarText = GetLocalizedText( "Common-Characters-EuroDollar" );
		if( !( InventoryItemData.IsEmpty( m_itemData ) ) )
		{
			if( InventoryItemData.IsVendorItem( m_itemData ) )
			{
				vendorPrice = ( RoundF( InventoryItemData.GetBuyPrice( m_itemData ) ) + " " ) + euroDolarText;
				if( InventoryItemData.GetQuantity( m_itemData ) > 1 )
				{
					vendorStackPrice = ( ( RoundF( InventoryItemData.GetBuyPrice( m_itemData ) ) * InventoryItemData.GetQuantity( m_itemData ) ) + " " ) + euroDolarText;
					return ( ( vendorStackPrice + " (" ) + vendorPrice ) + ")";
				}
				return vendorPrice;
			}
			else
			{
				price = ( RoundF( InventoryItemData.GetPrice( m_itemData ) ) + " " ) + euroDolarText;
				if( InventoryItemData.GetQuantity( m_itemData ) > 1 )
				{
					stackPrice = ( ( RoundF( InventoryItemData.GetPrice( m_itemData ) ) * InventoryItemData.GetQuantity( m_itemData ) ) + " " ) + euroDolarText;
					return ( ( stackPrice + " (" ) + price ) + ")";
				}
				return price;
			}
		}
		return "";
	}

	protected virtual function UpdatePrice()
	{
		if( inkTextRef.Get( m_itemPrice ) )
		{
			if( m_itemDisplayContext == ItemDisplayContext.Vendor )
			{
				inkTextRef.SetText( m_itemPrice, GetPriceText() );
			}
			else
			{
				inkTextRef.SetText( m_itemPrice, "" );
			}
		}
	}

	protected virtual function UpdateIcon()
	{
		var iconName : String;
		var emptyIcon : CName;
		var tweakId : TweakDBID;
		var iconsNameResolver : IconsNameResolver;
		var localData : gameItemData;
		var localItemRecord : Item_Record;
		var isCrafting : Bool;
		var iconGender : ItemIconGender;
		if( m_wardrobeOutfitIndex >= 0 )
		{
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, true );
			inkImageRef.SetVisible( m_itemFallbackImage, false );
			InkImageUtils.RequestSetImage( this, m_itemEmptyImage, 'UIIcon.WardrobeOutfitSilhouette' );
			return;
		}
		iconsNameResolver = IconsNameResolver.GetIconsNameResolver();
		isCrafting = m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData;
		DEBUG_iconsNameResolverIsDebug = iconsNameResolver.IsInDebugMode();
		inkImageRef.SetVisible( m_itemFallbackImage, false );
		localData = InventoryItemData.GetGameItemData( m_itemData );
		if( localData && localData.HasTag( 'Recipe' ) )
		{
			UpdateRecipeIcon();
			return;
		}
		DEBUG_innerItemName = "";
		DEBUG_recordItemName = "";
		if( isCrafting )
		{
			DEBUG_recordItemName = TDBID.ToStringDEBUG( m_recipeData.id.GetID() );
		}
		else
		{
			localItemRecord = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( InventoryItemData.GetID( m_itemData ) ) );
			if( localItemRecord )
			{
				DEBUG_recordItemName = TDBID.ToStringDEBUG( localItemRecord.GetID() );
			}
			else
			{
				DEBUG_recordItemName = "";
			}
		}
		if( !( IsStringValid( DEBUG_recordItemName ) ) )
		{
			DEBUG_recordItemName = "Cannot get valid record ID";
		}
		iconName = ( ( isCrafting ) ? ( m_recipeData.id.IconPath() ) : ( InventoryItemData.GetIconPath( m_itemData ) ) );
		if( IsStringValid( iconName ) )
		{
			DEBUG_isIconManuallySet = true;
		}
		else
		{
			tweakId = ( ( isCrafting ) ? ( m_recipeData.id.GetID() ) : ( ItemID.GetTDBID( InventoryItemData.GetID( m_itemData ) ) ) );
			iconGender = ( ( isCrafting ) ? ( m_recipeData.iconGender ) : ( InventoryItemData.GetIconGender( m_itemData ) ) );
			iconName = NameToString( iconsNameResolver.TranslateItemToIconName( tweakId, iconGender == ItemIconGender.Male ) );
			DEBUG_isIconManuallySet = false;
		}
		if( iconName != "None" && iconName != "" )
		{
			DEBUG_resolvedIconName = iconName;
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, false );
			if( m_equipmentArea == gamedataEquipmentArea.Outfit )
			{
				inkImageRef.SetScale( m_itemImage, Vector2( 1.0, 1.0 ) );
			}
			else
			{
				inkImageRef.SetScale( m_itemImage, ( ( InventoryItemData.GetEquipmentArea( m_itemData ) == gamedataEquipmentArea.Outfit ) ? ( Vector2( 0.5, 0.5 ) ) : ( Vector2( 1.0, 1.0 ) ) ) );
			}
			InkImageUtils.RequestSetImage( this, m_itemImage, "UIIcon." + iconName, 'OnIconCallback' );
		}
		else
		{
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, true );
			emptyIcon = UIItemsHelper.GetSlotShadowIcon( GetSlotID(), GetItemType(), GetEquipmentArea() );
			InkImageUtils.RequestSetImage( this, m_itemEmptyImage, emptyIcon );
		}
	}

	protected virtual function UpdateRecipeIcon()
	{
		var iconName : String;
		var emptyIcon : CName;
		var iconsNameResolver : IconsNameResolver;
		var recipeRecord : weak< ItemRecipe_Record >;
		var craftingResult : weak< CraftingResult_Record >;
		var itemRecord : weak< Item_Record >;
		var itemScale : Vector2;
		iconsNameResolver = IconsNameResolver.GetIconsNameResolver();
		recipeRecord = TweakDBInterface.GetItemRecipeRecord( ItemID.GetTDBID( InventoryItemData.GetID( m_itemData ) ) );
		craftingResult = recipeRecord.CraftingResult();
		if( craftingResult )
		{
			itemRecord = craftingResult.Item();
		}
		DEBUG_recordItemName = TDBID.ToStringDEBUG( ItemID.GetTDBID( InventoryItemData.GetID( m_itemData ) ) );
		if( !( IsStringValid( DEBUG_recordItemName ) ) )
		{
			DEBUG_recordItemName = "Cannot get valid record ID";
		}
		DEBUG_innerItemName = TDBID.ToStringDEBUG( itemRecord.GetID() );
		if( !( IsStringValid( DEBUG_innerItemName ) ) )
		{
			DEBUG_innerItemName = "Cannot get valid record ID";
		}
		if( itemRecord && IsStringValid( itemRecord.IconPath() ) )
		{
			iconName = itemRecord.IconPath();
			DEBUG_isIconManuallySet = true;
		}
		else
		{
			iconName = NameToString( iconsNameResolver.TranslateItemToIconName( itemRecord.GetID(), InventoryItemData.GetIconGender( m_itemData ) == ItemIconGender.Male ) );
			DEBUG_isIconManuallySet = false;
		}
		if( iconName != "None" && iconName != "" )
		{
			DEBUG_resolvedIconName = iconName;
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, false );
			if( itemRecord.EquipArea().Type() == gamedataEquipmentArea.Outfit )
			{
				itemScale = Vector2( 0.5, 0.5 );
			}
			else if( itemRecord.EquipArea().Type() == gamedataEquipmentArea.Weapon )
			{
				itemScale = Vector2( 0.33000001, 0.33000001 );
			}
			else
			{
				itemScale = Vector2( 1.0, 1.0 );
			}
			inkImageRef.SetScale( m_itemImage, itemScale );
			InkImageUtils.RequestSetImage( this, m_itemImage, "UIIcon." + iconName, 'OnIconCallback' );
		}
		else
		{
			inkImageRef.SetVisible( m_itemImage, false );
			inkImageRef.SetVisible( m_itemEmptyImage, true );
			emptyIcon = UIItemsHelper.GetSlotShadowIcon( GetSlotID(), GetItemType(), GetEquipmentArea() );
			InkImageUtils.RequestSetImage( this, m_itemEmptyImage, emptyIcon );
		}
	}

	protected event OnIconCallback( e : iconAtlasCallbackData )
	{
		inkImageRef.SetVisible( m_itemImage, e.loadResult == inkIconResult.Success );
		if( DEBUG_iconsNameResolverIsDebug )
		{
			switch( e.loadResult )
			{
				case inkIconResult.Success:
					inkWidgetRef.SetVisible( m_iconErrorIndicator, false );
				DEBUG_iconErrorInfo = NULL;
				return false;
				case inkIconResult.AtlasResourceNotFound:
					inkWidgetRef.SetTintColor( m_iconErrorIndicator, Color( 255, 0, 0, 255 ) );
				inkWidgetRef.SetVisible( m_iconErrorIndicator, true );
				break;
				case inkIconResult.UnknownIconTweak:
					inkWidgetRef.SetTintColor( m_iconErrorIndicator, Color( 0, 255, 0, 255 ) );
				inkWidgetRef.SetVisible( m_iconErrorIndicator, true );
				break;
				case inkIconResult.PartNotFoundInAtlas:
					inkWidgetRef.SetTintColor( m_iconErrorIndicator, Color( 0, 0, 255, 255 ) );
				inkWidgetRef.SetVisible( m_iconErrorIndicator, true );
				break;
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_iconErrorIndicator, false );
		}
		DEBUG_iconErrorInfo = new DEBUG_IconErrorInfo;
		DEBUG_iconErrorInfo.itemName = DEBUG_recordItemName;
		DEBUG_iconErrorInfo.innerItemName = DEBUG_innerItemName;
		DEBUG_iconErrorInfo.resolvedIconName = DEBUG_resolvedIconName;
		DEBUG_iconErrorInfo.errorMessage = e.errorMsg;
		DEBUG_iconErrorInfo.errorType = e.loadResult;
		DEBUG_iconErrorInfo.isManuallySet = DEBUG_isIconManuallySet;
	}

	protected virtual function UpdateRarity()
	{
		var quality : CName;
		var visible : Bool;
		var itemRecord : weak< Item_Record >;
		inkWidgetRef.SetVisible( m_rarityWrapper, true );
		if( InventoryItemData.GetGameItemData( m_itemData ).HasTag( 'ChimeraMod' ) )
		{
			quality = UIItemsHelper.QualityEnumToName( gamedataQuality.Iconic );
		}
		else
		{
			if( m_itemDisplayContext == ItemDisplayContext.Crafting && m_recipeData )
			{
				if( m_recipeData.id.TagsContains( 'ChimeraMod' ) )
				{
					quality = UIItemsHelper.QualityEnumToName( gamedataQuality.Iconic );
				}
				else
				{
					quality = UIItemsHelper.QualityEnumToName( GetQualityRounded( m_recipeData.quality ) );
				}
			}
			else
			{
				if( InventoryItemData.GetGameItemData( m_itemData ) && !( InventoryItemData.IsPart( m_itemData ) ) )
				{
					quality = UIItemsHelper.QualityEnumToName( RPGManager.GetItemDataQuality( InventoryItemData.GetGameItemData( m_itemData ) ) );
				}
				else
				{
					itemRecord = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( InventoryItemData.GetID( m_itemData ) ) );
					if( ( itemRecord != NULL ) && itemRecord.TagsContains( 'ChimeraMod' ) )
					{
						quality = UIItemsHelper.QualityEnumToName( gamedataQuality.Iconic );
					}
					else
					{
						quality = InventoryItemData.GetQuality( m_itemData );
					}
				}
			}
		}
		visible = quality != '';
		inkWidgetRef.SetVisible( m_itemRarity, visible );
		inkWidgetRef.SetVisible( m_rarityCommonWrapper, !( visible ) );
		inkWidgetRef.SetState( m_itemRarity, quality );
		inkWidgetRef.SetVisible( m_iconicTint, IsItemIconic() );
	}

	protected function GetQualityRounded( itemQuality : gamedataQuality ) : gamedataQuality
	{
		switch( itemQuality )
		{
			case gamedataQuality.Common:
			case gamedataQuality.CommonPlus:
				return gamedataQuality.Common;
			case gamedataQuality.Uncommon:
			case gamedataQuality.UncommonPlus:
				return gamedataQuality.Uncommon;
			case gamedataQuality.Rare:
			case gamedataQuality.RarePlus:
				return gamedataQuality.Rare;
			case gamedataQuality.Epic:
			case gamedataQuality.EpicPlus:
				return gamedataQuality.Epic;
			case gamedataQuality.Legendary:
			case gamedataQuality.LegendaryPlus:
			case gamedataQuality.LegendaryPlusPlus:
				return gamedataQuality.Legendary;
			default:
				return gamedataQuality.Common;
		}
	}

	protected virtual function UpdateNewRarity( itemData : UIInventoryItem )
	{
		var quality : CName;
		var visible : Bool;
		inkWidgetRef.SetVisible( m_rarityWrapper, true );
		quality = UIItemsHelper.QualityEnumToName( itemData.GetQuality() );
		visible = quality != '';
		inkWidgetRef.SetVisible( m_itemRarity, visible );
		inkWidgetRef.SetVisible( m_rarityCommonWrapper, !( visible ) );
		inkWidgetRef.SetState( m_itemRarity, quality );
		inkWidgetRef.SetVisible( m_iconicTint, IsItemIconic() );
	}

	public virtual function SetComparisonState( comparisonState : ItemComparisonState )
	{
		inkWidgetRef.SetVisible( m_comparisionArrow, true );
		switch( comparisonState )
		{
			case ItemComparisonState.Better:
				inkWidgetRef.SetState( m_comparisionArrow, 'Better' );
			inkWidgetRef.SetRotation( m_comparisionArrow, 0.0 );
			break;
			case ItemComparisonState.Worse:
				inkWidgetRef.SetState( m_comparisionArrow, 'Worse' );
			inkWidgetRef.SetRotation( m_comparisionArrow, 180.0 );
			break;
			default:
				inkWidgetRef.SetState( m_comparisionArrow, 'Default' );
		}
	}

	public virtual function SetBuybackStack( value : Bool )
	{
		m_isBuybackStack = value;
		if( m_uiInventoryItem )
		{
			NewUpdateIndicators( m_uiInventoryItem );
		}
		else
		{
			UpdateIndicators();
		}
	}

	public virtual function SetDLCNewIndicator( value : Bool )
	{
		m_isDLCNewItem = value;
		if( m_uiInventoryItem )
		{
			NewUpdateIndicators( m_uiInventoryItem );
		}
		else
		{
			UpdateIndicators();
		}
	}


	private var m_parrentWrappedDataObject : weak< WrappedInventoryItemData >;

	public virtual function SetIsNew( value : Bool, optional parrentWrappedDataObject : weak< WrappedInventoryItemData > )
	{
		m_isNew = value;
		if( parrentWrappedDataObject )
		{
			m_parrentWrappedDataObject = parrentWrappedDataObject;
		}
		m_parrentWrappedDataObject.IsNew = m_isNew;
		UpdateIsNewIndicator();
	}

	public function SetIsNewOverride( value : Bool )
	{
		m_isNewOverriden = true;
		m_isNew = value;
		UpdateIsNewIndicator();
	}

	public virtual function SetIsPlayerFavourite( value : Bool )
	{
		m_isPlayerFavourite = value;
		UpdatePlayerFavourite();
	}

	public function SetQuestBought( value : Bool )
	{
		m_isQuestBought = value;
	}

	public function IsQuestBought() : Bool
	{
		return m_isQuestBought;
	}

	public function SetAdditionalData( additionalData : IScriptable )
	{
		m_additionalData = additionalData;
	}

	public function GetAdditionalData() : IScriptable
	{
		return m_additionalData;
	}

	protected virtual function GetShadowIconFromEquipmentArea( equipmentArea : gamedataEquipmentArea ) : CName
	{
		return m_emptyImage;
	}

	protected virtual function GetShadowIconAtlas( equipmentArea : gamedataEquipmentArea ) : String
	{
		return m_emptyImageAtlas;
	}

	protected virtual function GetMods( onlyGeneric : Bool ) : array< InventoryItemAttachments >
	{
		var itemData : InventoryItemData;
		var result : array< InventoryItemAttachments >;
		var i : Int32;
		var attachmentsSize : Int32;
		var attachments : InventoryItemAttachments;
		itemData = GetItemData();
		attachmentsSize = InventoryItemData.GetAttachmentsSize( itemData );
		for( i = 0; i < attachmentsSize; i += 1 )
		{
			attachments = InventoryItemData.GetAttachment( itemData, i );
			if( onlyGeneric )
			{
				if( attachments.SlotType != InventoryItemAttachmentType.Generic )
				{
					continue;
				}
			}
			result.PushBack( attachments );
		}
		return result;
	}

	protected virtual function UpdateMods()
	{
		var attachments : array< InventoryItemAttachments >;
		var item : weak< InventoryItemModSlotDisplay >;
		var i, targetSize : Int32;
		if( !( inkCompoundRef.Get( m_commonModsRoot ) ) )
		{
			return;
		}
		attachments = GetMods( true );
		targetSize = attachments.Size();
		while( m_attachmentsDisplay.Size() > targetSize )
		{
			inkCompoundRef.RemoveChild( m_commonModsRoot, m_attachmentsDisplay.PopBack().GetRootWidget() );
		}
		for( i = 0; i < targetSize; i += 1 )
		{
			if( m_attachmentsDisplay.Size() <= i )
			{
				item = ( ( InventoryItemModSlotDisplay )( SpawnFromLocal( inkCompoundRef.Get( m_commonModsRoot ), 'itemModSlot' ).GetController() ) );
				m_attachmentsDisplay.PushBack( item );
			}
			m_attachmentsDisplay[ i ].Setup( attachments[ i ].ItemData );
		}
	}

	public virtual function Unselect() {}

	public virtual function Select() {}

	public function GetItemDisplayData() : InventoryItemDisplayData
	{
		var data : InventoryItemDisplayData;
		if( m_uiInventoryItem != NULL )
		{
			data.m_itemID = m_uiInventoryItem.GetID();
		}
		else
		{
			data.m_itemID = GetItemID();
		}
		data.m_equipmentArea = GetEquipmentArea();
		data.m_slotIndex = GetSlotIndex();
		return data;
	}

	public function GetItemData() : InventoryItemData
	{
		return m_itemData;
	}

	public function GetItemID() : ItemID
	{
		return InventoryItemData.GetID( m_itemData );
	}

	public function GetItemCategory() : String
	{
		return InventoryItemData.GetCategoryName( m_itemData );
	}

	public function GetItemType() : gamedataItemType
	{
		return InventoryItemData.GetItemType( m_itemData );
	}

	public function GetEquipmentArea() : gamedataEquipmentArea
	{
		return m_equipmentArea;
	}

	public function GetSlotName() : String
	{
		if( IsStringValid( m_slotName ) )
		{
			return m_slotName;
		}
		return UIItemsHelper.GetSlotName( GetSlotID(), GetItemType(), GetEquipmentArea() );
	}

	public function GetSlotIndex() : Int32
	{
		return m_slotIndex;
	}

	public function GetWardrobeOutfitIndex() : Int32
	{
		return m_wardrobeOutfitIndex;
	}

	public function GetIsPlayerFavourite() : Bool
	{
		return m_isPlayerFavourite;
	}

	public function SelectItem() {}

	public function UnselectItem() {}

	public virtual function SetHighlighted( value : Bool )
	{
		var i : Int32;
		for( i = 0; i < m_highlightFrames.Size(); i += 1 )
		{
			inkWidgetRef.SetVisible( m_highlightFrames[ i ], value );
		}
	}

	public function SetHighlightColor( color : CName )
	{
		var i : Int32;
		for( i = 0; i < m_highlightFrames.Size(); i += 1 )
		{
			inkWidgetRef.Get( m_highlightFrames[ i ] ).BindProperty( 'tintColor', color );
		}
	}

	public virtual function SetHighlightedCyberwareSlot( show : Bool )
	{
		var playbackOptions : inkAnimOptions;
		if( m_selectedCWProxy != NULL )
		{
			m_selectedCWProxy.GotoEndAndStop();
		}
		inkImageRef.SetState( m_itemEmptyIcon, 'Default' );
		inkWidgetRef.SetOpacity( m_equippedMarker, 1.0 );
		if( m_uiInventoryItem != NULL )
		{
			NewUpdateEquipped( m_uiInventoryItem );
		}
		else
		{
			UpdateEquipped();
		}
		if( show )
		{
			playbackOptions.loopInfinite = true;
			playbackOptions.loopType = inkanimLoopType.Cycle;
			playbackOptions.executionDelay = 0.30000001;
			m_selectedCWProxy = PlayLibraryAnimation( 'CW_selected_slot', playbackOptions );
			inkImageRef.SetState( m_itemEmptyIcon, 'Selected' );
			inkWidgetRef.SetVisible( m_equippedMarker, true );
		}
	}

	public virtual function ShowSelectionArrow()
	{
		inkWidgetRef.SetVisible( m_itemSelectedArrow, true );
	}

	public virtual function HideSelectionArrow()
	{
		inkWidgetRef.SetVisible( m_itemSelectedArrow, false );
	}

	public virtual function GetSlotID() : TweakDBID
	{
		if( TDBID.IsValid( m_slotID ) )
		{
			return m_slotID;
		}
		return TDBID.None();
	}

	public virtual function SetInteractive( value : Bool )
	{
		inkWidgetRef.SetInteractive( m_widgetWrapper, value );
	}

	public virtual function GetDisplayType() : ItemDisplayType
	{
		return ItemDisplayType.Item;
	}

	public virtual function GetAttachmentsSize() : Int32
	{
		return InventoryItemData.GetAttachmentsSize( m_itemData );
	}

	public virtual function GetParentItemData() : weak< gameItemData >
	{
		return m_parentItemData;
	}

	public virtual function GetNewItems() : Int32
	{
		return m_newItemsIDs.Size();
	}

	public virtual function IsEmpty() : Bool
	{
		return InventoryItemData.IsEmpty( m_itemData );
	}

	private function GetDelayAnimation() : inkAnimDef
	{
		var delayAnimation : inkAnimDef;
		var transparencyInterpolator : inkAnimTransparency;
		delayAnimation = new inkAnimDef;
		transparencyInterpolator = new inkAnimTransparency;
		transparencyInterpolator.SetDuration( 0.125 );
		transparencyInterpolator.SetStartTransparency( 1.0 );
		transparencyInterpolator.SetEndTransparency( 1.0 );
		delayAnimation.AddInterpolator( transparencyInterpolator );
		return delayAnimation;
	}

}

enum ItemDisplayType
{
	Item = 0,
	Weapon = 1,
}

import enum ItemDisplayContext
{
	None,
	Vendor,
	Tooltip,
	VendorPlayer,
	GearPanel,
	Backpack,
	DPAD_RADIAL,
	Attachment,
	Ripperdoc,
	Crafting,
}

class ItemDisplayHoverOverEvent extends Event
{
	var itemData : InventoryItemData;
	var display : weak< InventoryItemDisplayController >;
	var widget : weak< inkWidget >;
	var isBuybackStack : Bool;
	var isQuestBought : Bool;
	var toggleVisibilityControll : Bool;
	var isItemHidden : Bool;
	var transmogItem : ItemID;
	var uiInventoryItem : weak< UIInventoryItem >;
	var displayContextData : weak< ItemDisplayContextData >;
}

class DLCAddedItemDisplayHoverOverEvent extends Event
{
	var itemTDBID : TweakDBID;
}

class ItemDisplayHoverOutEvent extends Event
{
}

class ItemDisplayClickEvent extends Event
{
	var itemData : InventoryItemData;
	var displayContext : ItemDisplayContext;
	var display : weak< InventoryItemDisplayController >;
	var isBuybackStack : Bool;
	var isQuestBought : Bool;
	var toggleVisibilityRequest : Bool;
	var transmogItem : ItemID;
	var uiInventoryItem : UIInventoryItem;
	var displayContextData : weak< ItemDisplayContextData >;
	var additionalData : IScriptable;
	var evt : inkPointerEvent;
	var actionName : inkActionName;
}

class ItemDisplayHoldEvent extends Event
{
	var itemData : InventoryItemData;
	var display : weak< InventoryItemDisplayController >;
	var uiInventoryItem : UIInventoryItem;
	var displayContextData : weak< ItemDisplayContextData >;
	var actionName : inkActionName;
}

class ItemDisplayPressEvent extends Event
{
	var display : weak< InventoryItemDisplayController >;
	var actionName : inkActionName;
}

class ItemDisplayContextData
{
	private var m_player : weak< GameObject >;
	private var m_displayContext : ItemDisplayContext;
	private var m_displayComparison : Bool;
	private var m_tags : array< CName >;

	public static function Make() : ItemDisplayContextData
	{
		var instance : ItemDisplayContextData;
		instance = new ItemDisplayContextData;
		instance.m_displayContext = ItemDisplayContext.None;
		return instance;
	}

	public static function Make( player : weak< GameObject >, displayContext : ItemDisplayContext, optional displayComparison : Bool ) : ItemDisplayContextData
	{
		var instance : ItemDisplayContextData;
		instance = new ItemDisplayContextData;
		instance.m_player = player;
		instance.m_displayContext = displayContext;
		instance.m_displayComparison = displayComparison;
		return instance;
	}

	public function Copy() : ItemDisplayContextData
	{
		var instance : ItemDisplayContextData;
		instance = new ItemDisplayContextData;
		instance.m_player = m_player;
		instance.m_displayContext = m_displayContext;
		instance.m_displayComparison = m_displayComparison;
		instance.m_tags = m_tags;
		return instance;
	}

	public function SetDisplayComparison( value : Bool ) : ItemDisplayContextData
	{
		m_displayComparison = value;
		return this;
	}

	public function GetPlayer() : weak< GameObject >
	{
		return m_player;
	}

	public function GetPlayerAsPuppet() : weak< PlayerPuppet >
	{
		return ( ( weak< weak< PlayerPuppet > > )( m_player ) );
	}

	public function GetDisplayContext() : ItemDisplayContext
	{
		return m_displayContext;
	}

	public function GetDisplayComparison() : Bool
	{
		return m_displayComparison;
	}

	public function GetTooltipDisplayContext() : InventoryTooltipDisplayContext
	{
		switch( m_displayContext )
		{
			case ItemDisplayContext.None:
				return InventoryTooltipDisplayContext.Default;
			case ItemDisplayContext.Vendor:
				return InventoryTooltipDisplayContext.Vendor;
			case ItemDisplayContext.Tooltip:
				return InventoryTooltipDisplayContext.Default;
			case ItemDisplayContext.VendorPlayer:
				return InventoryTooltipDisplayContext.Vendor;
			case ItemDisplayContext.GearPanel:
				return InventoryTooltipDisplayContext.Default;
			case ItemDisplayContext.Backpack:
				return InventoryTooltipDisplayContext.Default;
			case ItemDisplayContext.DPAD_RADIAL:
				return InventoryTooltipDisplayContext.HUD;
			case ItemDisplayContext.Attachment:
				return InventoryTooltipDisplayContext.Attachment;
			case ItemDisplayContext.Ripperdoc:
			case ItemDisplayContext.Crafting:
				return InventoryTooltipDisplayContext.Crafting;
		}
		return InventoryTooltipDisplayContext.Default;
	}

	public function IsVendorItem() : Bool
	{
		return m_displayContext == ItemDisplayContext.Vendor;
	}

	public function IsCraftingItem() : Bool
	{
		return m_displayContext == ItemDisplayContext.Crafting;
	}

	public function HasTag( tag : CName ) : Bool
	{
		return m_tags.Contains( tag );
	}

	public function AddTag( tag : CName )
	{
		m_tags.PushBack( tag );
	}

	public function RemoveTag( tag : CName )
	{
		m_tags.Remove( tag );
	}

}

