class EventEquipSlotSelectDelayedInventoryEvent extends Event
{
	var controller : weak< InventoryItemDisplayController >;
}

class EventInventorySlotSelectDelayedInventoryEvent extends Event
{
	var controller : InventoryItemData;
	var target : weak< inkWidget >;
}

class gameuiInventoryGameController extends gameuiMenuGameController
{
	private editable var m_TooltipsManagerRef : inkWidgetRef;
	private editable var m_buttonHintsManagerRef : inkWidgetRef;
	private editable var m_itemModeControllerRef : inkWidgetRef;
	private editable var m_defaultWrapper : inkWidgetRef;
	private editable var m_itemWrapper : inkWidgetRef;
	private editable var m_cyberwareSlotRootRefs : inkCompoundRef;
	private editable var m_cyberwareHolder : inkWidgetRef;
	private editable var m_cyberdeckInventoryStatsContainer : inkCompoundRef;
	private editable var m_paperDollWidget : inkWidgetRef;
	private editable var m_sortingButton : inkWidgetRef;
	private editable var m_sortingDropdown : inkWidgetRef;
	private editable var m_notificationRoot : inkWidgetRef;
	private editable var m_playerStatsWidget : inkWidgetRef;
	private editable var m_btnBackpack : inkWidgetRef;
	private editable var m_btnCyberware : inkWidgetRef;
	private editable var m_btnCrafting : inkWidgetRef;
	private editable var m_btnStats : inkWidgetRef;
	private editable var m_btnSets : inkWidgetRef;
	private editable var m_itemNotificationRoot : inkWidgetRef;
	private var m_TooltipsManager : weak< gameuiTooltipsManager >;
	private var m_menuEventDispatcher : weak< inkMenuEventDispatcher >;
	private var m_buttonHintsController : weak< ButtonHints >;
	private var m_player : weak< PlayerPuppet >;
	private var m_mode : InventoryModes;
	private var m_itemViewMode : ItemViewModes;
	private var m_itemModeLogicController : weak< InventoryItemModeLogicController >;
	private var m_animationProxy : inkAnimProxy;
	private var m_animDef : inkAnimDef;
	private var m_itemModeProxy : inkAnimProxy;
	private var m_itemModeOutroProxy : inkAnimProxy;
	private var m_paperDollProxy : inkAnimProxy;
	private var m_targetPaperDollVisibility : Bool;
	private var m_refreshUIRequested : Bool;
	default m_refreshUIRequested = false;
	private var m_InventoryList : array< weak< InventoryItemDisplay > >;
	private var m_WeaponsList : array< weak< InventoryItemDisplayController > >;
	private var m_EquipmentList : array< weak< InventoryItemDisplayController > >;
	private var m_CyberwareList : array< weak< InventoryItemDisplayController > >;
	private var m_PocketList : array< weak< InventoryItemDisplayController > >;
	private var m_ConsumablesList : array< weak< InventoryItemDisplayController > >;
	private var m_animationList : array< weak< InventoryItemDisplayController > >;
	private var m_InventoryManager : InventoryDataManagerV2;
	private var m_uiScriptableSystem : weak< UIScriptableSystem >;
	private var m_comparisonResolver : ItemPreferredComparisonResolver;
	private var m_equipmentSystem : weak< EquipmentSystem >;
	private var m_EquipAreas : array< gamedataEquipmentArea >;
	private var m_CyberwareAreas : array< gamedataEquipmentArea >;
	private var m_WeaponAreas : array< gamedataItemType >;
	private var m_PocketAreas : array< gamedataEquipmentArea >;
	private var m_ConsumablesAreas : array< gamedataEquipmentArea >;
	protected var m_UIBBEquipment : UI_EquipmentDef;
	protected var m_UIBBItemMod : UI_ItemModSystemDef;
	private var m_DisassembleCallback : UI_CraftingDef;
	protected var m_UIBBEquipmentBlackboard : weak< IBlackboard >;
	protected var m_UIBBItemModBlackbord : weak< IBlackboard >;
	private var m_DisassembleBlackboard : weak< IBlackboard >;
	private var m_InventoryBBID : CallbackHandle;
	private var m_EquipmentBBID : CallbackHandle;
	private var m_SubEquipmentBBID : CallbackHandle;
	private var m_ItemModBBID : CallbackHandle;
	private var m_DisassembleBBID : CallbackHandle;
	private var m_isE3Demo : Bool;
	private var m_inventoryStatsListener : InventoryStatsListener;
	private var m_quantityPickerPopupToken : inkGameNotificationToken;
	private var m_psmBlackboard : weak< IBlackboard >;
	private var m_cyberdeckInventoryStatsController : weak< CyberdeckInventoryStatsController >;
	private var m_equipmentAreaCategoryEventQueue : array< EquipmentAreaCategoryCreated >;
	private var m_cyberwareItems : array< InventoryItemData >;
	private var m_equipmentAreaCategories : array< EquipmentAreaCategory >;
	private var m_wardrobeOutfitAreas : array< gamedataEquipmentArea >;
	private var m_lastClothingSetIndex : Int32;
	default m_lastClothingSetIndex = -1;
	private var telemetrySystem : weak< TelemetrySystem >;
	private var m_CyberwareScreenUserData : CyberwareDisplayWrapper;
	private var m_openItemMode : Bool;

	protected event OnInitialize()
	{
		var playerPuppet : weak< GameObject >;
		SpawnFromLocal( inkWidgetRef.Get( m_notificationRoot ), 'notification_layer' );
		PlayLibraryAnimation( 'menu_intro' );
		SpawnFromExternal( inkWidgetRef.Get( m_itemNotificationRoot ), R"base\gameplay\gui\widgets\activity_log\activity_log_panels.inkwidget", 'RootVert' );
		playerPuppet = ( ( PlayerPuppet )( GetOwnerEntity() ) );
		m_psmBlackboard = GetPSMBlackboard( playerPuppet );
		AT_AddATID( GetRootWidget(), "InventoryScreen_MainScreen" );
		super.OnInitialize();
	}

	protected event OnSetUserData( userData : IScriptable )
	{
		m_CyberwareScreenUserData = ( ( CyberwareDisplayWrapper )( userData ) );
		m_player = ( ( PlayerPuppet )( GameInstance.GetPlayerSystem( GetPlayerControlledObject().GetGame() ).GetLocalPlayerMainGameObject() ) );
		m_isE3Demo = GameInstance.GetQuestsSystem( m_player.GetGame() ).GetFact( 'e3_2020' ) > 0;
		m_InventoryManager = new InventoryDataManagerV2;
		m_InventoryManager.Initialize( m_player );
		m_comparisonResolver = ItemPreferredComparisonResolver.Make( m_InventoryManager );
		m_uiScriptableSystem = UIScriptableSystem.GetInstance( m_player.GetGame() );
		m_equipmentSystem = ( ( EquipmentSystem )( GameInstance.GetScriptableSystemsContainer( m_player.GetGame() ).Get( 'EquipmentSystem' ) ) );
		m_EquipAreas = InventoryDataManagerV2.GetInventoryEquipmentAreas();
		m_CyberwareAreas = InventoryDataManagerV2.GetInventoryCyberwareAreas();
		m_WeaponAreas = InventoryDataManagerV2.GetInventoryWeaponTypes();
		m_PocketAreas = InventoryDataManagerV2.GetInventoryPocketAreas();
		m_TooltipsManager = ( ( gameuiTooltipsManager )( inkWidgetRef.GetControllerByType( m_TooltipsManagerRef, 'gameuiTooltipsManager' ) ) );
		m_TooltipsManager.Setup( ETooltipsStyle.Menus );
		m_buttonHintsController = ( ( ButtonHints )( SpawnFromExternal( inkWidgetRef.Get( m_buttonHintsManagerRef ), R"base\gameplay\gui\common\buttonhints.inkwidget", 'Root' ).GetController() ) );
		m_buttonHintsController.AddButtonHint( 'back', GetLocalizedText( "Common-Access-Close" ) );
		m_buttonHintsController.AddCharacterRoatateButtonHint();
		m_itemModeLogicController = ( ( InventoryItemModeLogicController )( inkWidgetRef.GetController( m_itemModeControllerRef ) ) );
		m_itemModeLogicController.SetupData( m_buttonHintsController, m_TooltipsManager, m_InventoryManager, m_player );
		inkCompoundRef.RemoveAllChildren( m_cyberwareSlotRootRefs );
		RegisterToBB();
		inkWidgetRef.SetOpacity( m_itemWrapper, 0.0 );
		OpenDefaultMode( true );
		RefreshUI();
		HandlePostInitializeQueue();
		inkWidgetRef.RegisterToCallback( m_sortingButton, 'OnRelease', this, 'OnSortingButtonClicked' );
		UpdateDropdownContext( DropdownDisplayContext.Default );
		SetupPlayerStats( m_player, GetPlayerControlledObject().GetGame() );
		if( m_CyberwareScreenUserData )
		{
			m_openItemMode = true;
			OpenItemMode( m_CyberwareScreenUserData.displayData );
			inkWidgetRef.SetOpacity( m_itemWrapper, 1.0 );
			inkWidgetRef.SetVisible( m_defaultWrapper, false );
		}
		HubMenuUtils.SetMenuHyperlinkData( m_btnStats, HubMenuItems.Stats, HubMenuItems.Inventory, 'temp_stats', 'ico_stats_hub', 'UI-PanelNames-STATS' );
		HubMenuUtils.SetMenuHyperlinkData( m_btnSets, HubMenuItems.VisualSets, HubMenuItems.Inventory, 'wardrobe', 'ico_wardrobe', 'Gameplay-Devices-DisplayNames-Wardrobe' );
		HubMenuUtils.SetMenuHyperlinkData( m_btnCyberware, HubMenuItems.Cyberware, HubMenuItems.Inventory, 'cyberware_equip', 'ico_deck_hub', 'UI-PanelNames-CYBERWARE' );
		HubMenuUtils.SetMenuHyperlinkData( m_btnBackpack, HubMenuItems.Backpack, HubMenuItems.Inventory, 'backpack', 'ico_backpack', 'UI-PanelNames-BACKPACK' );
		if( HubMenuUtility.IsCraftingAvailable( m_player ) )
		{
			HubMenuUtils.SetMenuHyperlinkData( m_btnCrafting, HubMenuItems.Crafting, HubMenuItems.Inventory, 'crafting_main', 'ico_cafting', 'Gameplay-RPG-Skills-CraftingName' );
		}
		else
		{
			inkWidgetRef.SetVisible( m_btnCrafting, false );
		}
		SetupSetButton();
		if( m_player )
		{
			telemetrySystem = GameInstance.GetTelemetrySystem( m_player.GetGame() );
		}
	}

	private function SetupSetButton()
	{
		var set : ClothingSet;
		var btnConrtoller : weak< MenuItemController >;
		var setLabel : String;
		set = EquipmentSystem.GetActiveWardrobeSet( m_player );
		if( ( set != NULL ) && !( ClothingSet.IsEmpty( set ) ) )
		{
			btnConrtoller = ( ( MenuItemController )( inkWidgetRef.GetController( m_btnSets ) ) );
			setLabel = "#" + ( ( String )( set.setID ) );
			btnConrtoller.UpdateButton( setLabel, set.iconID );
		}
	}

	private function RefreshPlayerCyberware()
	{
		var allFilters : array< gamedataEquipmentArea >;
		var i, limit, slotsToSpawn : Int32;
		var itemId : ItemID;
		var slotSpawnData : CyberwareSlotSpawnData;
		var itemData : InventoryItemData;
		allFilters.PushBack( gamedataEquipmentArea.SystemReplacementCW );
		allFilters.PushBack( gamedataEquipmentArea.ArmsCW );
		allFilters.PushBack( gamedataEquipmentArea.HandsCW );
		m_cyberwareItems.Clear();
		inkCompoundRef.RemoveAllChildren( m_cyberwareSlotRootRefs );
		for( i = 0, limit = allFilters.Size(); i < limit; i += 1 )
		{
			itemId = EquipmentSystem.GetData( GetPlayerControlledObject() ).GetActiveItem( allFilters[ i ] );
			itemData = m_InventoryManager.GetItemDataFromIDInLoadout( itemId );
			if( !( itemData.Empty ) )
			{
				m_cyberwareItems.PushBack( itemData );
			}
		}
		slotsToSpawn = m_cyberwareItems.Size();
		for( i = 0, limit = slotsToSpawn - inkCompoundRef.GetNumChildren( m_cyberwareSlotRootRefs ); i < limit; i += 1 )
		{
			inkCompoundRef.RemoveChildByIndex( m_cyberwareSlotRootRefs, 0 );
		}
		for( i = 0, limit = slotsToSpawn; i < limit; i += 1 )
		{
			slotSpawnData = new CyberwareSlotSpawnData;
			slotSpawnData.index = i;
			ItemDisplayUtils.SpawnCommonSlotAsync( this, m_cyberwareSlotRootRefs, 'itemDisplay', 'OnSlotSpawned', slotSpawnData );
		}
		inkWidgetRef.SetVisible( m_cyberwareHolder, slotsToSpawn > 0 );
	}

	protected event OnSlotSpawned( widget : inkWidget, userData : IScriptable )
	{
		var data : CyberwareSlotSpawnData;
		var controller : InventoryItemDisplayController;
		var itemData : InventoryItemData;
		controller = ( ( InventoryItemDisplayController )( widget.GetController() ) );
		data = ( ( CyberwareSlotSpawnData )( userData ) );
		itemData = m_cyberwareItems[ data.index ];
		controller.Setup( itemData, InventoryItemData.GetEquipmentArea( itemData ) );
	}

	private function OpenCyberwareModificationScreen( displayData : InventoryItemDisplayData )
	{
		OpenItemMode( displayData );
	}

	private function OpenCyberwareMenu()
	{
		var evt : OpenMenuRequest;
		var prevEvt : OpenMenuRequest;
		var menuData : PreviousMenuData;
		evt = new OpenMenuRequest;
		evt.m_menuName = 'cyberware_equip';
		evt.m_eventData.m_overrideDefaultUserData = true;
		evt.m_jumpBack = true;
		evt.m_isMainMenu = true;
		menuData = new PreviousMenuData;
		menuData.openMenuRequest = prevEvt;
		evt.m_eventData.userData = menuData;
		QueueBroadcastEvent( evt );
	}

	protected event OnItemChooserItemChanged( e : ItemChooserItemChanged )
	{
		if( InventoryItemData.GetEquipmentArea( e.itemData ) == gamedataEquipmentArea.Weapon )
		{
			UpdateDropdownContext( DropdownDisplayContext.ItemChooserWeapon );
		}
		else
		{
			UpdateDropdownContext( DropdownDisplayContext.Default );
		}
	}

	protected function HandlePostInitializeQueue()
	{
		while( m_equipmentAreaCategoryEventQueue.Size() > 0 )
		{
			OnEquipmentAreaCategoryCreated( m_equipmentAreaCategoryEventQueue.PopBack() );
		}
	}

	protected event OnUninitialize()
	{
		m_menuEventDispatcher.UnregisterFromEvent( 'OnBack', this, 'OnBack' );
		m_menuEventDispatcher.UnregisterFromEvent( 'OnCloseMenu', this, 'OnCloseMenu' );
		m_InventoryManager.UnInitialize();
		UnregisterFromBB();
		if( m_inventoryStatsListener )
		{
			GameInstance.GetStatsSystem( m_player.GetGame() ).UnregisterListener( m_player.GetEntityID(), m_inventoryStatsListener );
			m_inventoryStatsListener = NULL;
		}
		super.OnUninitialize();
	}

	private function RegisterToBB()
	{
		m_UIBBEquipment = GetAllBlackboardDefs().UI_Equipment;
		m_UIBBEquipmentBlackboard = GetBlackboardSystem().Get( m_UIBBEquipment );
		m_UIBBItemMod = GetAllBlackboardDefs().UI_ItemModSystem;
		m_UIBBItemModBlackbord = GetBlackboardSystem().Get( m_UIBBItemMod );
		m_DisassembleCallback = GetAllBlackboardDefs().UI_Crafting;
		m_DisassembleBlackboard = GetBlackboardSystem().Get( m_DisassembleCallback );
		if( m_UIBBEquipmentBlackboard )
		{
			m_EquipmentBBID = m_UIBBEquipmentBlackboard.RegisterDelayedListenerVariant( m_UIBBEquipment.itemEquipped, this, 'OnRefreshUI' );
		}
		if( m_UIBBItemModBlackbord )
		{
			m_ItemModBBID = m_UIBBItemModBlackbord.RegisterDelayedListenerVariant( m_UIBBItemMod.ItemModSystemUpdated, this, 'OnRefreshUI' );
		}
		if( m_DisassembleBlackboard )
		{
			m_DisassembleBBID = m_DisassembleBlackboard.RegisterDelayedListenerVariant( m_DisassembleCallback.lastIngredients, this, 'OnDisassembleComplete', true );
		}
	}

	private function UnregisterFromBB()
	{
		if( m_UIBBEquipmentBlackboard )
		{
			m_UIBBEquipmentBlackboard.UnregisterDelayedListener( m_UIBBEquipment.itemEquipped, m_EquipmentBBID );
		}
		if( m_UIBBItemModBlackbord )
		{
			m_UIBBItemModBlackbord.UnregisterDelayedListener( m_UIBBItemMod.ItemModSystemUpdated, m_ItemModBBID );
		}
		if( m_DisassembleBlackboard )
		{
			m_DisassembleBlackboard.UnregisterDelayedListener( m_DisassembleCallback.lastIngredients, m_DisassembleBBID );
		}
	}

	private function SetupPlayerStats( player : weak< PlayerPuppet >, game : GameInstance )
	{
		var controller : InventoryStatsController;
		controller = ( ( InventoryStatsController )( inkWidgetRef.GetController( m_playerStatsWidget ) ) );
		if( m_inventoryStatsListener )
		{
			GameInstance.GetStatsSystem( game ).UnregisterListener( player.GetEntityID(), m_inventoryStatsListener );
			m_inventoryStatsListener = NULL;
		}
		m_inventoryStatsListener = new InventoryStatsListener;
		m_inventoryStatsListener.m_owner = ( ( GameObject )( player ) );
		m_inventoryStatsListener.m_controller = controller;
		GameInstance.GetStatsSystem( game ).RegisterListener( player.GetEntityID(), m_inventoryStatsListener );
		controller.Setup( player );
	}

	private function UpdateDropdownContext( context : DropdownDisplayContext )
	{
		var controller : DropdownListController;
		var sortingButtonController : DropdownButtonController;
		controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
		sortingButtonController = ( ( DropdownButtonController )( inkWidgetRef.GetController( m_sortingButton ) ) );
		if( context != controller.GetDisplayContext() )
		{
			controller.Setup( this, context, sortingButtonController );
			sortingButtonController.SetData( SortingDropdownData.GetDropdownOption( controller.GetData(), ItemSortMode.Default ) );
		}
	}

	protected event OnDropdownItemClickedEvent( evt : DropdownItemClickedEvent )
	{
		var identifier : ItemSortMode;
		var sortingButtonController : DropdownButtonController;
		var data : DropdownItemData;
		identifier = ( ( ItemSortMode )evt.identifier );
		data = SortingDropdownData.GetDropdownOption( ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) ).GetData(), identifier );
		if( data )
		{
			sortingButtonController = ( ( DropdownButtonController )( inkWidgetRef.GetController( m_sortingButton ) ) );
			sortingButtonController.SetData( data );
			m_itemModeLogicController.SetSortMode( identifier );
		}
	}

	protected event OnSortingButtonClicked( evt : inkPointerEvent )
	{
		var controller : DropdownListController;
		if( evt.IsAction( 'click' ) )
		{
			PlaySound( 'Button', 'OnPress' );
			controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
			controller.Toggle();
		}
	}

	protected function GetEquipmentAreas( iw : weak< inkCompoundWidget >, levels : Int32 ) : array< weak< inkCompoundWidget > >
	{
		var result : array< weak< inkCompoundWidget > >;
		var innerResult : array< weak< inkCompoundWidget > >;
		var child : weak< inkCompoundWidget >;
		var i, j : Int32;
		for( i = 0; i < iw.GetNumChildren(); i += 1 )
		{
			child = ( ( inkCompoundWidget )( iw.GetWidgetByIndex( i ) ) );
			if( child )
			{
				if( levels > 1 )
				{
					innerResult = GetEquipmentAreas( child, levels - 1 );
					for( j = 0; j < innerResult.Size(); j += 1 )
					{
						if( ( ( InventoryItemDisplayEquipmentArea )( innerResult[ j ].GetController() ) ) )
						{
							result.PushBack( ( ( inkCompoundWidget )( innerResult[ j ] ) ) );
						}
					}
				}
			}
			if( ( ( InventoryItemDisplayEquipmentArea )( child.GetController() ) ) )
			{
				result.PushBack( ( ( inkCompoundWidget )( child ) ) );
			}
		}
		return result;
	}

	protected event OnRefreshUI( value : Variant )
	{
		if( !( m_refreshUIRequested ) )
		{
			QueueEvent( new DelayedRefreshUI );
			m_refreshUIRequested = true;
		}
	}

	protected event OnDelayedRefreshUI( evt : DelayedRefreshUI )
	{
		m_refreshUIRequested = false;
		m_InventoryManager.MarkToRebuild();
		RefreshUI();
	}

	private function RefreshUI()
	{
		var i, j, k : Int32;
		var displays : array< InventoryItemDisplayController >;
		var categoryAreas : array< weak< InventoryItemDisplayEquipmentArea > >;
		var equipmentAreas : array< gamedataEquipmentArea >;
		var isLockedArea : Bool;
		var isOutfitEquipped, isOutfitSlot : Bool;
		var wardrbeSetChanged : Bool;
		var outfit : ItemID;
		var clothingSet : gameWardrobeClothingSetIndex;
		var equippedClothingSetIndex : Int32;
		outfit = m_InventoryManager.GetEquippedItemIdInArea( gamedataEquipmentArea.Outfit );
		isOutfitEquipped = ItemID.IsValid( outfit );
		HideTooltips();
		RefreshEquippedWardrobeItems();
		clothingSet = GameInstance.GetWardrobeSystem( m_player.GetGame() ).GetActiveClothingSetIndex();
		equippedClothingSetIndex = WardrobeSystem.WardrobeClothingSetIndexToNumber( clothingSet );
		wardrbeSetChanged = equippedClothingSetIndex != m_lastClothingSetIndex;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			isLockedArea = false;
			displays = m_equipmentAreaCategories[ i ].GetDisplays();
			categoryAreas = m_equipmentAreaCategories[ i ].parentCategory.GetCategoryAreas();
			for( j = 0; j < categoryAreas.Size(); j += 1 )
			{
				equipmentAreas = categoryAreas[ j ].GetEquipmentAreas();
				for( k = 0; k < equipmentAreas.Size(); k += 1 )
				{
					if( IsAreaLockedByOutfit( equipmentAreas[ k ] ) )
					{
						isLockedArea = true;
					}
				}
			}
			for( j = 0; j < displays.Size(); j += 1 )
			{
				isOutfitSlot = displays[ j ].GetEquipmentArea() == gamedataEquipmentArea.Outfit;
				if( isOutfitSlot || !( wardrbeSetChanged ) )
				{
					displays[ j ].InvalidateContent( isOutfitSlot, equippedClothingSetIndex );
				}
				displays[ j ].SetLocked( isOutfitEquipped && isLockedArea, true );
				displays[ j ].SetTransmoged( m_wardrobeOutfitAreas.Contains( displays[ j ].GetEquipmentArea() ) );
			}
		}
		m_lastClothingSetIndex = equippedClothingSetIndex;
	}

	private function RefreshedEquippedItemData( equippedItem : InventoryItemData )
	{
		equippedItem = m_InventoryManager.GetInventoryItemData( m_InventoryManager.GetExternalGameItemData( m_player.GetEntityID(), InventoryItemData.GetID( equippedItem ) ) );
	}

	private function RefreshEquippedWardrobeItems()
	{
		var clothingSet : ClothingSet;
		clothingSet = GameInstance.GetWardrobeSystem( m_player.GetGame() ).GetActiveClothingSet();
		m_wardrobeOutfitAreas.Clear();
		if( clothingSet )
		{
			m_wardrobeOutfitAreas.PushBack( gamedataEquipmentArea.Head );
			m_wardrobeOutfitAreas.PushBack( gamedataEquipmentArea.Face );
			m_wardrobeOutfitAreas.PushBack( gamedataEquipmentArea.OuterChest );
			m_wardrobeOutfitAreas.PushBack( gamedataEquipmentArea.InnerChest );
			m_wardrobeOutfitAreas.PushBack( gamedataEquipmentArea.Legs );
			m_wardrobeOutfitAreas.PushBack( gamedataEquipmentArea.Feet );
		}
	}

	protected event OnDisassembleComplete( value : Variant )
	{
		var disassembledIngredientData : array< IngredientData >;
		disassembledIngredientData = ( ( array< IngredientData > )value );
		if( disassembledIngredientData.Size() > 0 )
		{
			m_InventoryManager.MarkToRebuild();
			RefreshUI();
		}
	}

	private function SwapMode( mode : InventoryModes )
	{
		var isComparisionDisabled : Bool;
		m_mode = mode;
		m_buttonHintsController.ClearButtonHints();
		if( m_mode == InventoryModes.Item )
		{
			m_buttonHintsController.AddButtonHint( 'back', GetLocalizedText( "UI-UserActions-NavigateBack" ) );
			isComparisionDisabled = m_uiScriptableSystem.IsComparisionTooltipDisabled();
			m_buttonHintsController.AddButtonHint( 'toggle_comparison_tooltip', GetLocalizedText( ( ( isComparisionDisabled ) ? ( "UI-UserActions-EnableComparison" ) : ( "UI-UserActions-DisableComparison" ) ) ) );
		}
		else
		{
			m_buttonHintsController.AddButtonHint( 'back', GetLocalizedText( "Common-Access-Close" ) );
		}
	}

	private function OpenDefaultMode( optional openingMenu : Bool )
	{
		var controller : DropdownListController;
		SwapMode( InventoryModes.Default );
		m_itemModeLogicController.m_isShown = false;
		StartModeTransitionAnimation();
		controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
		controller.Close();
	}

	public function GetEquipementAreaDisplays( equipmentArea : gamedataEquipmentArea ) : EquipmentAreaDisplays
	{
		var i, j, k : Int32;
		var equipmentAreas : array< EquipmentAreaDisplays >;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			equipmentAreas = m_equipmentAreaCategories[ i ].areaDisplays;
			for( j = 0; j < equipmentAreas.Size(); j += 1 )
			{
				for( k = 0; k < equipmentAreas[ j ].equipmentAreas.Size(); k += 1 )
				{
					if( equipmentAreas[ j ].equipmentAreas[ k ] == equipmentArea )
					{
						return equipmentAreas[ j ];
					}
				}
			}
		}
		return NULL;
	}

	private function GetEquipmentCategory( equipmentCategory : InventoryItemDisplayCategoryArea ) : EquipmentAreaCategory
	{
		var i, j, k : Int32;
		var passed : Bool;
		var areaDisplays : array< EquipmentAreaDisplays >;
		var targetCategoryAreas : array< weak< InventoryItemDisplayEquipmentArea > >;
		var equipmentAreas : array< gamedataEquipmentArea >;
		var areaDisplaysEquipmnetAreas, targetCategoryEquipmentAreas : array< gamedataEquipmentArea >;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			areaDisplays = m_equipmentAreaCategories[ i ].areaDisplays;
			targetCategoryAreas = equipmentCategory.GetCategoryAreas();
			if( ( areaDisplays.Size() == targetCategoryAreas.Size() ) && ( areaDisplays.Size() > 0 ) )
			{
				passed = true;
				areaDisplaysEquipmnetAreas.Clear();
				targetCategoryEquipmentAreas.Clear();
				for( j = 0; j < areaDisplays.Size(); j += 1 )
				{
					for( k = 0; k < areaDisplays[ j ].equipmentAreas.Size(); k += 1 )
					{
						areaDisplaysEquipmnetAreas.PushBack( areaDisplays[ j ].equipmentAreas[ k ] );
					}
					equipmentAreas.Clear();
					equipmentAreas = targetCategoryAreas[ j ].GetEquipmentAreas();
					for( k = 0; k < equipmentAreas.Size(); k += 1 )
					{
						targetCategoryEquipmentAreas.PushBack( equipmentAreas[ k ] );
					}
				}
				for( j = 0; j < areaDisplaysEquipmnetAreas.Size(); j += 1 )
				{
					if( !( targetCategoryEquipmentAreas.Contains( areaDisplaysEquipmnetAreas[ j ] ) ) )
					{
						passed = false;
						break;
					}
				}
				if( !( passed ) )
				{
					continue;
				}
				return m_equipmentAreaCategories[ i ];
			}
		}
		return NULL;
	}

	private function GetEquipmentCategoryByArea( equipmentArea : gamedataEquipmentArea ) : EquipmentAreaCategory
	{
		var i, j, k : Int32;
		var equipmentAreas : array< EquipmentAreaDisplays >;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			equipmentAreas = m_equipmentAreaCategories[ i ].areaDisplays;
			for( j = 0; j < equipmentAreas.Size(); j += 1 )
			{
				for( k = 0; j < equipmentAreas[ j ].equipmentAreas.Size(); k += 1 )
				{
					if( equipmentAreas[ j ].equipmentAreas[ k ] == equipmentArea )
					{
						return m_equipmentAreaCategories[ i ];
					}
				}
			}
		}
		return NULL;
	}

	private function GetEquipmentAreaDisplaysFromCategory( const equipmentAreas : ref< array< gamedataEquipmentArea > >, categoryArea : EquipmentAreaCategory ) : EquipmentAreaDisplays
	{
		var i, j, k : Int32;
		for( i = 0; i < categoryArea.areaDisplays.Size(); i += 1 )
		{
			for( j = 0; j < categoryArea.areaDisplays[ i ].equipmentAreas.Size(); j += 1 )
			{
				for( k = 0; k < equipmentAreas.Size(); k += 1 )
				{
					if( categoryArea.areaDisplays[ i ].equipmentAreas[ j ] == equipmentAreas[ k ] )
					{
						return categoryArea.areaDisplays[ i ];
					}
				}
			}
		}
		return NULL;
	}

	private function GetSlotType( const areaTypes : ref< array< gamedataEquipmentArea > > ) : CName
	{
		var i : Int32;
		for( i = 0; i < areaTypes.Size(); i += 1 )
		{
			switch( areaTypes[ i ] )
			{
				case gamedataEquipmentArea.Weapon:
					return 'weaponDisplay';
				case gamedataEquipmentArea.SystemReplacementCW:
				case gamedataEquipmentArea.HandsCW:
				case gamedataEquipmentArea.ArmsCW:
					return 'itemDisplay';
				case gamedataEquipmentArea.Outfit:
					return 'outfitDisplay';
			}
		}
		return 'itemDisplay';
	}

	private function IsEquipmentAreaCyberware( const itemData : ref< InventoryItemData > ) : Bool
	{
		var itemRecord : weak< Item_Record >;
		if( m_player )
		{
			itemRecord = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( InventoryItemData.GetID( itemData ) ) );
			if( itemRecord && itemRecord.ItemCategory().Type() == gamedataItemCategory.Cyberware )
			{
				return true;
			}
		}
		return InventoryDataManagerV2.IsEquipmentAreaCyberware( InventoryItemData.GetEquipmentArea( itemData ) );
	}

	protected event OnEquipmentAreaCategoryCreated( e : EquipmentAreaCategoryCreated )
	{
		var i, j, numberOfSlots : Int32;
		var equipmentAreas : array< gamedataEquipmentArea >;
		var equipmentAreaDisplays : EquipmentAreaDisplays;
		var equipmentAreaCategory : EquipmentAreaCategory;
		var equipmentAreaController : InventoryItemDisplayEquipmentArea;
		RefreshEquippedWardrobeItems();
		if( m_InventoryManager )
		{
			equipmentAreaCategory = GetEquipmentCategory( e.categoryController );
			if( equipmentAreaCategory == NULL )
			{
				equipmentAreaCategory = new EquipmentAreaCategory;
				equipmentAreaCategory.parentCategory = e.categoryController;
				m_equipmentAreaCategories.PushBack( equipmentAreaCategory );
			}
			for( i = 0; i < e.equipmentAreasControllers.Size(); i += 1 )
			{
				equipmentAreaController = e.equipmentAreasControllers[ i ];
				equipmentAreaDisplays = GetEquipmentAreaDisplaysFromCategory( equipmentAreaController.GetEquipmentAreas(), equipmentAreaCategory );
				if( equipmentAreaDisplays == NULL )
				{
					equipmentAreaDisplays = new EquipmentAreaDisplays;
					equipmentAreas = equipmentAreaController.GetEquipmentAreas();
					for( j = 0; j < equipmentAreas.Size(); j += 1 )
					{
						equipmentAreaDisplays.equipmentAreas.PushBack( equipmentAreas[ j ] );
					}
					equipmentAreaDisplays.displaysRoot = equipmentAreaController.GetRootWidget();
					equipmentAreaCategory.areaDisplays.PushBack( equipmentAreaDisplays );
					numberOfSlots = equipmentAreaController.GetNumberOfSlots();
					PopulateArea( ( ( inkCompoundWidget )( equipmentAreaDisplays.displaysRoot ) ), equipmentAreaDisplays, numberOfSlots, equipmentAreas );
				}
			}
		}
		else
		{
			m_equipmentAreaCategoryEventQueue.PushBack( e );
		}
	}

	private function CountNewItems( items : ref< array< ItemID > > ) : Int32
	{
		var i, result : Int32;
		for( i = 0; i < items.Size(); i += 1 )
		{
			if( m_uiScriptableSystem.IsInventoryItemNew( items[ i ] ) )
			{
				result += 1;
			}
		}
		return result;
	}

	private function IsAreaLockedByOutfit( equipmentArea : gamedataEquipmentArea ) : Bool
	{
		return ( ( ( ( equipmentArea == gamedataEquipmentArea.Head || equipmentArea == gamedataEquipmentArea.Face ) || equipmentArea == gamedataEquipmentArea.OuterChest ) || equipmentArea == gamedataEquipmentArea.InnerChest ) || equipmentArea == gamedataEquipmentArea.Legs ) || equipmentArea == gamedataEquipmentArea.Feet;
	}

	private function PopulateArea( targetRoot : weak< inkCompoundWidget >, container : EquipmentAreaDisplays, numberOfSlots : Int32, const equipmentAreas : ref< array< gamedataEquipmentArea > > )
	{
		var equipedCyberwares : array< InventoryItemData >;
		var slot : weak< InventoryItemDisplayController >;
		var i, clothingSetIndex : Int32;
		var isOutfitEquipped, isOutfitSlot : Bool;
		var currentEquipmentArea : gamedataEquipmentArea;
		var outfit : ItemID;
		var clothingSet : gameWardrobeClothingSetIndex;
		outfit = m_InventoryManager.GetEquippedItemIdInArea( gamedataEquipmentArea.Outfit );
		isOutfitEquipped = ItemID.IsValid( outfit );
		isOutfitSlot = equipmentAreas.Contains( gamedataEquipmentArea.Outfit );
		if( isOutfitSlot )
		{
			clothingSet = GameInstance.GetWardrobeSystem( m_player.GetGame() ).GetActiveClothingSetIndex();
			clothingSetIndex = WardrobeSystem.WardrobeClothingSetIndexToNumber( clothingSet );
		}
		else
		{
			clothingSetIndex = -1;
		}
		while( container.displayControllers.Size() > numberOfSlots )
		{
			slot = container.displayControllers.PopBack();
			targetRoot.RemoveChild( slot.GetRootWidget() );
		}
		while( container.displayControllers.Size() < numberOfSlots )
		{
			slot = ( ( InventoryItemDisplayController )( ItemDisplayUtils.SpawnCommonSlotController( this, targetRoot, GetSlotType( equipmentAreas ) ) ) );
			container.displayControllers.PushBack( slot );
		}
		for( i = 0; i < numberOfSlots; i += 1 )
		{
			currentEquipmentArea = gamedataEquipmentArea.Invalid;
			if( container.displayControllers[ i ] )
			{
				if( InventoryDataManagerV2.IsEquipmentAreaCyberware( equipmentAreas ) )
				{
					equipedCyberwares = m_InventoryManager.GetInventoryCyberware();
					currentEquipmentArea = InventoryItemData.GetEquipmentArea( equipedCyberwares[ i ] );
					container.displayControllers[ i ].Bind( m_InventoryManager, currentEquipmentArea, , ItemDisplayContext.GearPanel );
				}
				else
				{
					currentEquipmentArea = equipmentAreas[ 0 ];
					container.displayControllers[ i ].Bind( m_InventoryManager, currentEquipmentArea, i, ItemDisplayContext.GearPanel, clothingSetIndex > -1, clothingSetIndex );
				}
				container.displayControllers[ i ].BindComparisonAndScriptableSystem( m_uiScriptableSystem, m_comparisonResolver );
				container.displayControllers[ i ].SetLocked( isOutfitEquipped && IsAreaLockedByOutfit( currentEquipmentArea ), true );
				container.displayControllers[ i ].SetTransmoged( m_wardrobeOutfitAreas.Contains( currentEquipmentArea ) );
				container.displayControllers[ i ].SetItemCounterDisabled( true );
			}
		}
	}

	protected event OnBack( userData : IScriptable )
	{
		var canClose : Bool;
		if( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayerControlledObject(), 'LockInHubMenu' ) )
		{
			return false;
		}
		if( m_openItemMode && m_CyberwareScreenUserData )
		{
			m_menuEventDispatcher.SpawnEvent( 'OnRefreshCurrentTab' );
			super.OnBack( userData );
		}
		else if( m_openItemMode )
		{
			super.OnBack( userData );
		}
		else if( m_mode != InventoryModes.Default || m_openItemMode )
		{
			canClose = m_itemModeLogicController.RequestClose();
			if( canClose )
			{
				OpenDefaultMode();
				UpdateNewItemsIndicators();
				if( ( GameInstance.GetQuestsSystem( m_player.GetGame() ).GetFact( 'close_inventory_mode_tutorial' ) == 0 ) && ( GameInstance.GetQuestsSystem( m_player.GetGame() ).GetFact( 'disable_tutorials' ) == 0 ) )
				{
					GameInstance.GetQuestsSystem( m_player.GetGame() ).SetFact( 'close_inventory_mode_tutorial', 1 );
				}
			}
		}
		else
		{
			m_menuEventDispatcher.SpawnEvent( 'OnCloseHubMenu' );
		}
	}

	private function UpdateNewItemsIndicators()
	{
		var i, j, k : Int32;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			for( j = 0; j < m_equipmentAreaCategories[ i ].areaDisplays.Size(); j += 1 )
			{
				for( k = 0; k < m_equipmentAreaCategories[ i ].areaDisplays[ j ].displayControllers.Size(); k += 1 )
				{
					m_equipmentAreaCategories[ i ].areaDisplays[ j ].displayControllers[ k ].BindComparisonAndScriptableSystem( m_uiScriptableSystem, m_comparisonResolver );
				}
			}
		}
	}

	protected event OnCloseMenu( userData : IScriptable )
	{
		if( ( m_itemModeLogicController.m_itemDropQueue.Size() == 1 ) && ( m_itemModeLogicController.m_itemDropQueue[ 0 ].quantity == 1 ) )
		{
			ItemActionsHelper.DropItem( m_player, m_itemModeLogicController.m_itemDropQueue[ 0 ].itemID );
			m_itemModeLogicController.m_itemDropQueue.Clear();
		}
		else if( m_itemModeLogicController.m_itemDropQueue.Size() > 0 )
		{
			RPGManager.DropManyItems( m_player.GetGame(), m_player, m_itemModeLogicController.m_itemDropQueue );
			m_itemModeLogicController.m_itemDropQueue.Clear();
		}
		if( telemetrySystem )
		{
			telemetrySystem.LogInventoryMenuClosed();
		}
	}

	private function IsUnequipBlocked( itemID : ItemID ) : Bool
	{
		var itemData : weak< gameItemData >;
		itemData = RPGManager.GetItemData( m_player.GetGame(), m_player, itemID );
		return itemData && itemData.HasTag( 'UnequipBlocked' );
	}

	private function WardrobeOutfitUnequipSet()
	{
		var req : UnequipWardrobeSetRequest;
		req = new UnequipWardrobeSetRequest;
		req.owner = m_player;
		m_equipmentSystem.QueueRequest( req );
	}

	protected event OnEquipmentClick( evt : ItemDisplayClickEvent )
	{
		var controller : weak< InventoryItemDisplayController >;
		var itemData : InventoryItemData;
		var hotkey : EHotkey;
		var pressedOpenModsExclusiveHotkey : Bool;
		controller = evt.display;
		if( m_mode == InventoryModes.Item )
		{
			return false;
		}
		if( evt.actionName.IsAction( 'install_quickhack' ) )
		{
			pressedOpenModsExclusiveHotkey = true;
		}
		if( evt.actionName.IsAction( 'unequip_item' ) )
		{
			itemData = controller.GetItemData();
			if( controller.GetEquipmentArea() == gamedataEquipmentArea.Outfit )
			{
				if( GameInstance.GetWardrobeSystem( m_player.GetGame() ).GetActiveClothingSetIndex() != gameWardrobeClothingSetIndex.INVALID )
				{
					if( m_InventoryManager.IsWardrobeEnabled() )
					{
						WardrobeOutfitUnequipSet();
						return false;
					}
				}
			}
			if( !( InventoryItemData.IsEmpty( itemData ) ) )
			{
				m_InventoryManager.GetHotkeyTypeForItemID( InventoryItemData.GetID( itemData ), hotkey );
				if( hotkey != EHotkey.INVALID && hotkey != EHotkey.LBRB )
				{
					m_equipmentSystem.GetPlayerData( m_player ).ClearItemFromHotkey( hotkey );
					NotifyItemUpdate( , , hotkey );
				}
				else
				{
					if( IsEquipmentAreaCyberware( itemData ) )
					{
						return false;
					}
					if( !( InventoryGPRestrictionHelper.CanUse( itemData, m_player ) ) || IsUnequipBlocked( InventoryItemData.GetID( itemData ) ) )
					{
						ShowNotification( m_player.GetGame(), UIMenuNotificationType.InventoryActionBlocked );
						return false;
					}
					if( controller.IsLocked() )
					{
						ShowNotification( m_player.GetGame(), UIMenuNotificationType.InventoryActionBlocked );
						return false;
					}
					UnequipItem( controller, itemData );
				}
				PlaySound( 'ItemAdditional', 'OnUnequip' );
				PlayRumble( RumbleStrength.Light, RumbleType.Pulse, RumblePosition.Right );
			}
		}
		else if( evt.actionName.IsAction( 'select' ) || evt.actionName.IsAction( 'click' ) )
		{
			PlaySound( 'Button', 'OnPress' );
			if( controller.GetEquipmentArea() == gamedataEquipmentArea.Invalid )
			{
				return false;
			}
			if( controller.IsLocked() )
			{
				ShowNotification( m_player.GetGame(), UIMenuNotificationType.InventoryActionBlocked );
				return false;
			}
			itemData = controller.GetItemData();
			if( InventoryDataManagerV2.IsEquipmentAreaCyberware( controller.GetEquipmentArea() ) )
			{
				if( InventoryItemData.IsEmpty( itemData ) )
				{
					return false;
				}
				if( controller.GetAttachmentsSize() > 0 )
				{
					OpenCyberwareModificationScreen( controller.GetItemDisplayData() );
				}
				else if( !( pressedOpenModsExclusiveHotkey ) )
				{
					OpenCyberwareMenu();
				}
				return false;
			}
			else if( !( evt.toggleVisibilityRequest ) )
			{
				OpenItemMode( controller.GetItemDisplayData() );
			}
		}
	}

	private function NotifyItemUpdate( optional equipmentArea : gamedataEquipmentArea, optional slotIndex : Int32, optional hotkey : EHotkey )
	{
		var itemChangedEvent : ItemModeItemChanged;
		itemChangedEvent = new ItemModeItemChanged;
		if( hotkey == EHotkey.DPAD_UP )
		{
			equipmentArea = gamedataEquipmentArea.Consumable;
		}
		else if( hotkey == EHotkey.RB )
		{
			equipmentArea = gamedataEquipmentArea.QuickSlot;
		}
		itemChangedEvent.equipmentArea = equipmentArea;
		itemChangedEvent.slotIndex = slotIndex;
		itemChangedEvent.hotkey = hotkey;
		QueueEvent( itemChangedEvent );
	}

	private function ShowNotification( gameInstance : GameInstance, type : UIMenuNotificationType )
	{
		var inventoryNotification : UIMenuNotificationEvent;
		inventoryNotification = new UIMenuNotificationEvent;
		inventoryNotification.m_notificationType = type;
		GameInstance.GetUISystem( gameInstance ).QueueEvent( inventoryNotification );
	}

	protected event OnInventoryHold( evt : inkPointerEvent )
	{
		var itemData : InventoryItemData;
		var controller : weak< InventoryItemDisplay >;
		var progress : Float;
		controller = GetInventoryItemControllerFromTarget( evt );
		itemData = controller.GetItemData();
		progress = evt.GetHoldProgress();
		if( progress >= 1.0 )
		{
			if( evt.IsAction( 'disassemble_item' ) && !( m_isE3Demo ) )
			{
				if( InventoryItemData.GetQuantity( itemData ) > 1 )
				{
					OpenQuantityPicker( itemData, QuantityPickerActionType.Disassembly );
				}
				else
				{
					PlaySound( 'ItemGeneric', 'OnDisassemble' );
					ItemActionsHelper.DisassembleItem( m_player, InventoryItemData.GetID( itemData ) );
					PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
				}
			}
			else if( evt.IsAction( 'use_item' ) )
			{
				if( InventoryItemData.GetItemType( itemData ) == gamedataItemType.Con_Inhaler || InventoryItemData.GetItemType( itemData ) == gamedataItemType.Con_Injector )
				{
					return false;
				}
				if( !( InventoryGPRestrictionHelper.CanUse( itemData, m_player ) ) )
				{
					ShowNotification( m_player.GetGame(), UIMenuNotificationType.InventoryActionBlocked );
					return false;
				}
				if( InventoryItemData.GetItemType( itemData ) == gamedataItemType.Con_Edible )
				{
					GameInstance.GetAudioSystem( m_player.GetGame() ).Play( 'ui_loot_eat_ui' );
				}
				PlayRumble( RumbleStrength.Light, RumbleType.Pulse, RumblePosition.Right );
				ItemActionsHelper.PerformItemAction( m_player, InventoryItemData.GetID( itemData ) );
				m_InventoryManager.MarkToRebuild();
			}
		}
	}

	protected event OnOpenInventoryQuantityPickerRequest( request : OpenInventoryQuantityPickerRequest )
	{
		OpenQuantityPicker( request.itemData, request.actionType );
	}

	private function OpenQuantityPicker( const itemData : ref< InventoryItemData >, actionType : QuantityPickerActionType, optional local : Bool )
	{
		var data : QuantityPickerPopupData;
		data = new QuantityPickerPopupData;
		data.notificationName = 'base\gameplay\gui\widgets\notifications\item_quantity_picker.inkwidget';
		data.isBlocking = true;
		data.useCursor = true;
		data.queueName = 'modal_popup';
		data.maxValue = InventoryItemData.GetQuantity( itemData );
		data.gameItemData = itemData;
		data.actionType = actionType;
		m_quantityPickerPopupToken = ShowGameNotification( data );
		m_quantityPickerPopupToken.RegisterListener( this, ( ( local ) ? ( 'OnLocalQuantityPickerPopupClosed' ) : ( 'OnQuantityPickerPopupClosed' ) ) );
		m_buttonHintsController.Hide();
	}

	protected event OnLocalQuantityPickerPopupClosed( data : inkGameNotificationData )
	{
		var quantityData : QuantityPickerPopupCloseData;
		m_quantityPickerPopupToken = NULL;
		quantityData = ( ( QuantityPickerPopupCloseData )( data ) );
		if( quantityData.choosenQuantity != -1 )
		{
			switch( quantityData.actionType )
			{
				case QuantityPickerActionType.Disassembly:
					OnQuantityPickerDisassembly( quantityData );
				break;
			}
		}
	}

	public function OnQuantityPickerDisassembly( data : QuantityPickerPopupCloseData )
	{
		PlaySound( 'ItemGeneric', 'OnDisassemble' );
		ItemActionsHelper.DisassembleItem( m_player, InventoryItemData.GetID( data.itemData ), data.choosenQuantity );
		PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
	}

	protected event OnQuantityPickerPopupClosed( data : inkGameNotificationData )
	{
		var quantityData : QuantityPickerPopupCloseData;
		m_quantityPickerPopupToken = NULL;
		quantityData = ( ( QuantityPickerPopupCloseData )( data ) );
		m_itemModeLogicController.OnQuantityPickerPopupClosed( quantityData );
	}

	private override function ReadUICondition( condition : gamedataUICondition ) : Bool
	{
		return condition == gamedataUICondition.IsSetEquippingSubMenu && m_itemModeLogicController.IsOutfitMode();
	}

	public function OpenItemMode( displayData : InventoryItemDisplayData )
	{
		var paperdollTargetPosition : PaperdollPositionAnimation;
		var isItemACyberdeck : Bool;
		SwapMode( InventoryModes.Item );
		m_itemModeLogicController.SetupMode( displayData, m_InventoryManager, this );
		QueueEvent( new DelayedSetItemModeShown );
		paperdollTargetPosition = GetEquipmentAreaPaperdollLocation( displayData.m_equipmentArea );
		if( paperdollTargetPosition == PaperdollPositionAnimation.Right )
		{
			m_itemModeLogicController.SetTranslation( Vector2( 0.0, 0.0 ) );
		}
		else if( paperdollTargetPosition == PaperdollPositionAnimation.Left || paperdollTargetPosition == PaperdollPositionAnimation.LeftFullBody )
		{
			m_itemModeLogicController.SetTranslation( Vector2( 1400.0, 0.0 ) );
		}
		isItemACyberdeck = IsItemACyberdeck( displayData );
		if( isItemACyberdeck )
		{
			m_cyberdeckInventoryStatsController = ( ( CyberdeckInventoryStatsController )( inkCompoundRef.GetController( m_cyberdeckInventoryStatsContainer ) ) );
			if( m_cyberdeckInventoryStatsController )
			{
				m_cyberdeckInventoryStatsController.SetupData( ItemID.GetTDBID( displayData.m_itemID ), m_player, m_TooltipsManager );
				inkCompoundRef.SetVisible( m_cyberdeckInventoryStatsContainer, true );
			}
			else
			{
				inkCompoundRef.SetVisible( m_cyberdeckInventoryStatsContainer, false );
			}
		}
		else
		{
			inkCompoundRef.SetVisible( m_cyberdeckInventoryStatsContainer, false );
		}
		if( ( isItemACyberdeck && ( GameInstance.GetQuestsSystem( m_player.GetGame() ).GetFact( 'cyberdeck_inventory_tutorial' ) == 0 ) ) && ( GameInstance.GetQuestsSystem( m_player.GetGame() ).GetFact( 'disable_tutorials' ) == 0 ) )
		{
			GameInstance.GetQuestsSystem( m_player.GetGame() ).SetFact( 'cyberdeck_inventory_tutorial', 1 );
		}
		StartModeTransitionAnimation( displayData );
	}

	protected event OnDelayedSetItemModeShown( evt : DelayedSetItemModeShown )
	{
		m_itemModeLogicController.m_isShown = true;
	}

	private function IsItemACyberdeck( displayData : InventoryItemDisplayData ) : Bool
	{
		return TweakDBInterface.GetCName( ItemID.GetTDBID( displayData.m_itemID ) + T".cyberwareType", '' ) == 'Cyberdeck';
	}

	private function UnequipItem( controller : InventoryItemDisplayController, const itemData : ref< InventoryItemData > )
	{
		m_InventoryManager.UnequipItem( controller.GetEquipmentArea(), controller.GetSlotIndex() );
		m_InventoryManager.RemoveInventoryItemFromCache( controller.GetItemID() );
	}

	private function EquipItem( const itemData : ref< InventoryItemData > )
	{
		if( !( InventoryItemData.IsEmpty( itemData ) ) && !( InventoryItemData.IsEquipped( itemData ) ) )
		{
			if( InventoryItemData.IsPart( itemData ) || InventoryItemData.GetEquipmentArea( itemData ) == gamedataEquipmentArea.Invalid )
			{
				return;
			}
			if( InventoryItemData.GetEquipmentArea( itemData ) == gamedataEquipmentArea.Weapon )
			{
				m_InventoryManager.EquipItem( InventoryItemData.GetID( itemData ), GetFirstAvailableWeaponSlot() );
			}
			else
			{
				m_InventoryManager.EquipItem( InventoryItemData.GetID( itemData ), 0 );
			}
		}
	}

	private function OnInventoryItemHoverOver( const itemData : ref< InventoryItemData >, target : weak< inkWidget > )
	{
		var equippedItem : InventoryItemData;
		if( !( InventoryItemData.IsEmpty( itemData ) ) )
		{
			if( m_mode == InventoryModes.Default )
			{
				equippedItem = m_InventoryManager.GetEquippedCounterpartForInventroyItem( itemData );
			}
			ShowTooltipsForItemData( equippedItem, itemData, target );
		}
	}

	private function ShowTooltipsForItemData( const equippedItem : ref< InventoryItemData >, const inspectedItemData : ref< InventoryItemData >, target : weak< inkWidget > )
	{
		var tooltipsData : array< ATooltipData >;
		var itemTooltips : CName[ 2 ];
		HideTooltips();
		if( InventoryItemData.IsWeapon( inspectedItemData ) )
		{
			itemTooltips[ 0 ] = 'newItemTooltip';
			itemTooltips[ 1 ] = 'newItemTooltipComparision';
		}
		else
		{
			itemTooltips[ 0 ] = 'itemTooltip';
			itemTooltips[ 1 ] = 'itemTooltipComparision';
		}
		if( !( InventoryItemData.IsEmpty( inspectedItemData ) ) )
		{
			if( !( InventoryItemData.IsEmpty( equippedItem ) ) && equippedItem != inspectedItemData )
			{
				m_InventoryManager.PushIdentifiedComparisonTooltipsData( tooltipsData, itemTooltips[ 0 ], itemTooltips[ 1 ], equippedItem, inspectedItemData );
				m_TooltipsManager.ShowTooltipsAtWidget( tooltipsData, target );
			}
			else
			{
				m_TooltipsManager.ShowTooltipAtWidget( itemTooltips[ 0 ], target, m_InventoryManager.GetTooltipDataForInventoryItem( inspectedItemData, false ), gameuiETooltipPlacement.RightTop, true );
			}
		}
	}

	private function HideTooltips()
	{
		m_TooltipsManager.HideTooltips();
	}

	private function SetInventoryItemButtonHintsHoverOver( const displayingData : ref< InventoryItemData > )
	{
		var cursorData : MenuCursorUserData;
		var playerState : gamePSMVehicle;
		cursorData = new MenuCursorUserData;
		playerState = ( ( gamePSMVehicle )( m_psmBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vehicle ) ) );
		if( !( InventoryItemData.IsEmpty( displayingData ) ) )
		{
			if( !( InventoryItemData.IsPart( displayingData ) ) && InventoryItemData.GetEquipmentArea( displayingData ) != gamedataEquipmentArea.Invalid )
			{
				m_buttonHintsController.AddButtonHint( 'equip_item', GetLocalizedText( "UI-UserActions-Equip" ) );
			}
			if( !( m_isE3Demo ) )
			{
				if( RPGManager.CanItemBeDisassembled( m_player.GetGame(), InventoryItemData.GetID( displayingData ) ) && !( InventoryItemData.IsEquipped( displayingData ) ) )
				{
					m_buttonHintsController.AddButtonHint( 'disassemble_item', ( ( "[" + GetLocalizedText( "Gameplay-Devices-Interactions-Helpers-Hold" ) ) + "] " ) + GetLocalizedText( "UI-ScriptExports-Disassemble0" ) );
					cursorData.AddAction( 'disassemble_item' );
				}
			}
			if( !( InventoryItemData.IsEquipped( displayingData ) ) && RPGManager.CanItemBeDropped( m_player, InventoryItemData.GetGameItemData( displayingData ) ) )
			{
				if( playerState != gamePSMVehicle.Default )
				{
					m_buttonHintsController.AddButtonHint( 'drop_item', GetLocalizedText( "UI-ScriptExports-Drop0" ) );
				}
				else
				{
					m_buttonHintsController.RemoveButtonHint( 'drop_item' );
				}
			}
			if( InventoryItemData.GetEquipmentArea( displayingData ) == gamedataEquipmentArea.Consumable )
			{
				m_buttonHintsController.AddButtonHint( 'UseConsumable', ( ( "[" + GetLocalizedText( "Gameplay-Devices-Interactions-Helpers-Hold" ) ) + "] " ) + GetLocalizedText( "UI-UserActions-Use" ) );
				cursorData.AddAction( 'use_item' );
			}
			if( cursorData.GetActionsListSize() >= 0 )
			{
				SetCursorContext( 'HoldToComplete', cursorData );
			}
			else
			{
				SetCursorContext( 'Hover' );
			}
		}
		else
		{
			SetCursorContext( 'Default' );
		}
	}

	private function SetInventoryItemButtonHintsHoverOut()
	{
		m_buttonHintsController.RemoveButtonHint( 'equip_item' );
		m_buttonHintsController.RemoveButtonHint( 'disassemble_item' );
		m_buttonHintsController.RemoveButtonHint( 'drop_item' );
		m_buttonHintsController.RemoveButtonHint( 'UseConsumable' );
	}

	private function StartModeTransitionAnimation( optional displayData : InventoryItemDisplayData )
	{
		var isCyberware : Bool;
		var hidePaperdoll : Bool;
		isCyberware = InventoryDataManagerV2.IsEquipmentAreaCyberware( displayData.m_equipmentArea );
		hidePaperdoll = isCyberware || displayData.m_equipmentArea == gamedataEquipmentArea.Weapon;
		if( m_itemModeProxy )
		{
			m_itemModeProxy.Stop();
		}
		if( m_itemModeOutroProxy )
		{
			m_itemModeOutroProxy.GotoEndAndStop();
			m_itemModeOutroProxy = NULL;
		}
		switch( m_mode )
		{
			case InventoryModes.Default:
				PlayShowHideItemChooserAnimation( false );
			ZoomCamera( ( ( Int32 )( InventoryPaperdollZoomArea.Default ) ) );
			PlaySlidePaperdollAnimation( PaperdollPositionAnimation.Center );
			m_itemModeProxy = PlayLibraryAnimation( 'default_wrapper_Intro' );
			RefreshPlayerCyberware();
			break;
			case InventoryModes.Item:
				PlayShowHideItemChooserAnimation( true );
			ZoomCamera( ( ( Int32 )( GetZoomArea( displayData.m_equipmentArea ) ) ) );
			PlaySlidePaperdollAnimation( GetEquipmentAreaPaperdollLocation( displayData.m_equipmentArea ), hidePaperdoll );
			m_itemModeOutroProxy = PlayLibraryAnimation( 'default_wrapper_outro' );
			m_itemModeProxy = PlayLibraryAnimation( ( ( isCyberware ) ? ( 'cyberware_grid_intro' ) : ( 'inventory_grid_intro' ) ) );
			break;
		}
	}

	private function ZoomCamera( target : Int32 )
	{
		var setCameraSetupEvent : gameuiPuppetPreview_SetCameraSetupEvent;
		setCameraSetupEvent = new gameuiPuppetPreview_SetCameraSetupEvent;
		setCameraSetupEvent.setupIndex = ( ( Uint32 )( target ) );
		QueueEvent( setCameraSetupEvent );
	}

	private function GetVisibleSlots( optional slotToSkip : InventoryItemDisplayController ) : array< InventoryItemDisplayController >
	{
		var i, j : Int32;
		var result : array< InventoryItemDisplayController >;
		var displays : array< InventoryItemDisplayController >;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			displays = m_equipmentAreaCategories[ i ].GetDisplays();
			for( j = 0; j < displays.Size(); j += 1 )
			{
				if( displays[ j ] != slotToSkip )
				{
					result.PushBack( displays[ j ] );
				}
			}
		}
		return result;
	}

	private function GetVisibleAdditionalWidgets() : array< weak< inkWidget > >
	{
		var i, j : Int32;
		var result : array< weak< inkWidget > >;
		var areasToHide : array< inkWidgetRef >;
		for( i = 0; i < m_equipmentAreaCategories.Size(); i += 1 )
		{
			areasToHide = m_equipmentAreaCategories[ i ].parentCategory.GetAreasToHide();
			for( j = 0; j < areasToHide.Size(); j += 1 )
			{
				if( inkWidgetRef.Get( areasToHide[ j ] ) )
				{
					result.PushBack( inkWidgetRef.Get( areasToHide[ j ] ) );
				}
			}
		}
		return result;
	}

	private function PlayGearToItemModeAnimation( moveAnimation : CName, hideAnimation : CName, target : InventoryItemDisplayController, const itemToHide : ref< array< InventoryItemDisplayController > > ) {}

	private function PlayMoveAnimation( target : InventoryItemDisplayController ) {}

	private function GetZoomArea( equipmentArea : gamedataEquipmentArea ) : InventoryPaperdollZoomArea
	{
		switch( equipmentArea )
		{
			case gamedataEquipmentArea.Weapon:
				return InventoryPaperdollZoomArea.Weapon;
			case gamedataEquipmentArea.Legs:
				return InventoryPaperdollZoomArea.Legs;
			case gamedataEquipmentArea.Feet:
				return InventoryPaperdollZoomArea.Feet;
			case gamedataEquipmentArea.SystemReplacementCW:
			case gamedataEquipmentArea.HandsCW:
			case gamedataEquipmentArea.ArmsCW:
				return InventoryPaperdollZoomArea.Cyberware;
			case gamedataEquipmentArea.QuickSlot:
				return InventoryPaperdollZoomArea.QuickSlot;
			case gamedataEquipmentArea.Consumable:
				return InventoryPaperdollZoomArea.Consumable;
			case gamedataEquipmentArea.Outfit:
				return InventoryPaperdollZoomArea.Outfit;
			case gamedataEquipmentArea.Head:
				return InventoryPaperdollZoomArea.Head;
			case gamedataEquipmentArea.Face:
				return InventoryPaperdollZoomArea.Face;
			case gamedataEquipmentArea.InnerChest:
				return InventoryPaperdollZoomArea.InnerChest;
			case gamedataEquipmentArea.OuterChest:
				return InventoryPaperdollZoomArea.OuterChest;
		}
		return InventoryPaperdollZoomArea.Default;
	}

	private function GetEquipmentAreaPaperdollLocation( equipmentArea : gamedataEquipmentArea ) : PaperdollPositionAnimation
	{
		switch( equipmentArea )
		{
			case gamedataEquipmentArea.SystemReplacementCW:
			case gamedataEquipmentArea.HandsCW:
			case gamedataEquipmentArea.ArmsCW:
			case gamedataEquipmentArea.Weapon:
				return PaperdollPositionAnimation.Right;
			case gamedataEquipmentArea.Head:
			case gamedataEquipmentArea.Face:
			case gamedataEquipmentArea.InnerChest:
			case gamedataEquipmentArea.OuterChest:
				return PaperdollPositionAnimation.Left;
			case gamedataEquipmentArea.QuickSlot:
			case gamedataEquipmentArea.Gadget:
			case gamedataEquipmentArea.Consumable:
			case gamedataEquipmentArea.Legs:
			case gamedataEquipmentArea.Feet:
			case gamedataEquipmentArea.Outfit:
				return PaperdollPositionAnimation.LeftFullBody;
		}
		return PaperdollPositionAnimation.Center;
	}

	private function PlayShowHideItemChooserAnimation( visible : Bool )
	{
		var transparencyAnimationProxy : inkAnimProxy;
		var transparencyAnimation : inkAnimDef;
		var transparencyInterpolator : inkAnimTransparency;
		transparencyAnimation = new inkAnimDef;
		transparencyInterpolator = new inkAnimTransparency;
		transparencyInterpolator.SetDuration( 0.15000001 );
		transparencyInterpolator.SetDirection( inkanimInterpolationDirection.FromTo );
		transparencyInterpolator.SetType( inkanimInterpolationType.Linear );
		transparencyInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		transparencyInterpolator.SetStartTransparency( ( ( visible ) ? ( 0.0 ) : ( 1.0 ) ) );
		transparencyInterpolator.SetEndTransparency( ( ( visible ) ? ( 1.0 ) : ( 0.0 ) ) );
		transparencyAnimation.AddInterpolator( transparencyInterpolator );
		transparencyAnimationProxy = inkWidgetRef.PlayAnimation( m_itemWrapper, transparencyAnimation );
		if( !( visible ) )
		{
			transparencyAnimationProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnItemChooserHideAnimationComplete' );
		}
	}

	private function PlaySlidePaperdollAnimation( position : PaperdollPositionAnimation, optional hide : Bool )
	{
		var translationAnimation : inkAnimDef;
		var translationInterpolator : inkAnimTranslation;
		var transparencyInterpolator : inkAnimTransparency;
		if( m_paperDollProxy )
		{
			m_paperDollProxy.Stop();
		}
		translationAnimation = new inkAnimDef;
		translationInterpolator = new inkAnimTranslation;
		translationInterpolator.SetDuration( 0.2 );
		translationInterpolator.SetDirection( inkanimInterpolationDirection.FromTo );
		translationInterpolator.SetType( inkanimInterpolationType.Linear );
		translationInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
		if( hide || ( !( hide ) && !( m_targetPaperDollVisibility ) ) )
		{
			transparencyInterpolator = new inkAnimTransparency;
			transparencyInterpolator.SetDuration( 0.2 );
			transparencyInterpolator.SetDirection( inkanimInterpolationDirection.FromTo );
			transparencyInterpolator.SetType( inkanimInterpolationType.Linear );
			transparencyInterpolator.SetMode( inkanimInterpolationMode.EasyIn );
			transparencyInterpolator.SetStartTransparency( inkWidgetRef.GetOpacity( m_paperDollWidget ) );
			transparencyInterpolator.SetEndTransparency( ( ( hide ) ? ( 0.0 ) : ( 1.0 ) ) );
			m_targetPaperDollVisibility = !( hide );
		}
		translationInterpolator.SetStartTranslation( inkWidgetRef.GetTranslation( m_paperDollWidget ) );
		switch( position )
		{
			case PaperdollPositionAnimation.Center:
				translationInterpolator.SetEndTranslation( Vector2( 0.0, 0.0 ) );
			break;
			case PaperdollPositionAnimation.Left:
				translationInterpolator.SetEndTranslation( Vector2( -1000.0, 0.0 ) );
			break;
			case PaperdollPositionAnimation.LeftFullBody:
				translationInterpolator.SetEndTranslation( Vector2( -990.0, 0.0 ) );
			break;
			case PaperdollPositionAnimation.Right:
				translationInterpolator.SetEndTranslation( Vector2( 1200.0, 0.0 ) );
			break;
		}
		translationAnimation.AddInterpolator( translationInterpolator );
		translationAnimation.AddInterpolator( transparencyInterpolator );
		m_paperDollProxy = inkWidgetRef.PlayAnimation( m_paperDollWidget, translationAnimation );
	}

	protected event OnItemModeItemChanged( e : ItemModeItemChanged )
	{
		var i : Int32;
		var equipmentAreaDisplays : EquipmentAreaDisplays;
		var equipmentAreaToUpdate : gamedataEquipmentArea;
		equipmentAreaToUpdate = e.equipmentArea;
		if( equipmentAreaToUpdate == gamedataEquipmentArea.Outfit )
		{
			InvlidateAllClothes();
			return false;
		}
		if( e.hotkey == EHotkey.INVALID )
		{
			if( InventoryDataManagerV2.IsEquipmentAreaCyberware( equipmentAreaToUpdate ) )
			{
				equipmentAreaToUpdate = gamedataEquipmentArea.SystemReplacementCW;
			}
		}
		equipmentAreaDisplays = GetEquipementAreaDisplays( equipmentAreaToUpdate );
		for( i = 0; i < equipmentAreaDisplays.equipmentAreas.Size(); i += 1 )
		{
			if( equipmentAreaDisplays.equipmentAreas[ i ] == gamedataEquipmentArea.Invalid )
			{
				return false;
			}
		}
		if( equipmentAreaDisplays.displayControllers.Size() >= e.slotIndex )
		{
			equipmentAreaDisplays.displayControllers[ e.slotIndex ].InvalidateContent();
		}
	}

	private function InvlidateAllClothes()
	{
		var i, j : Int32;
		var equipmentAreaDisplays : EquipmentAreaDisplays;
		var areasToInvalidate : array< gamedataEquipmentArea >;
		var isOutfitEquipped : Bool;
		var outfit : ItemID;
		outfit = m_InventoryManager.GetEquippedItemIdInArea( gamedataEquipmentArea.Outfit );
		isOutfitEquipped = ItemID.IsValid( outfit );
		RefreshEquippedWardrobeItems();
		areasToInvalidate.PushBack( gamedataEquipmentArea.Head );
		areasToInvalidate.PushBack( gamedataEquipmentArea.Face );
		areasToInvalidate.PushBack( gamedataEquipmentArea.OuterChest );
		areasToInvalidate.PushBack( gamedataEquipmentArea.InnerChest );
		areasToInvalidate.PushBack( gamedataEquipmentArea.Legs );
		areasToInvalidate.PushBack( gamedataEquipmentArea.Feet );
		areasToInvalidate.PushBack( gamedataEquipmentArea.Outfit );
		for( i = 0; i < areasToInvalidate.Size(); i += 1 )
		{
			equipmentAreaDisplays = GetEquipementAreaDisplays( areasToInvalidate[ i ] );
			for( j = 0; j < equipmentAreaDisplays.equipmentAreas.Size(); j += 1 )
			{
				if( equipmentAreaDisplays.equipmentAreas[ j ] == gamedataEquipmentArea.Invalid )
				{
					continue;
				}
			}
			for( j = 0; j < equipmentAreaDisplays.displayControllers.Size(); j += 1 )
			{
				equipmentAreaDisplays.displayControllers[ j ].InvalidateContent();
				equipmentAreaDisplays.displayControllers[ j ].SetLocked( isOutfitEquipped && IsAreaLockedByOutfit( areasToInvalidate[ i ] ), true );
				equipmentAreaDisplays.displayControllers[ j ].SetTransmoged( m_wardrobeOutfitAreas.Contains( areasToInvalidate[ i ] ) );
			}
		}
	}

	protected event OnDefaultToItemModeComplete( anim : inkAnimProxy ) {}

	protected event OnItemtoDefaultModeComplete( anim : inkAnimProxy ) {}

	protected event OnItemModeFadeInComplete( anim : inkAnimProxy ) {}

	protected event OnItemModeFadeOutComplete( anim : inkAnimProxy ) {}

	protected event OnDefaultModeFadeInComplete( anim : inkAnimProxy ) {}

	protected event OnDefaultModeFadeOutComplete( anim : inkAnimProxy ) {}

	private function GetAttachmentDataForInventoryItem( const itemData : ref< InventoryItemData >, boxData : ref< array< InventoryComboBoxData > >, allowUnequip : Bool )
	{
		var currItemData, showcaseItemData : InventoryItemData;
		var dataToDisplay : array< InventoryItemData >;
		var i, limit : Int32;
		var message : String;
		var attachmentsSize : Int32;
		var attachments : InventoryItemAttachments;
		attachmentsSize = InventoryItemData.GetAttachmentsSize( itemData );
		for( i = 0, limit = attachmentsSize; i < limit; i += 1 )
		{
			attachments = InventoryItemData.GetAttachment( itemData, i );
			currItemData = attachments.ItemData;
			dataToDisplay.Clear();
			if( InventoryItemData.IsEmpty( currItemData ) )
			{
				message = ( "No " + GetLocalizedText( attachments.SlotName ) ) + " attached";
			}
			else
			{
				message = "Attached " + GetLocalizedText( attachments.SlotName );
				dataToDisplay.PushBack( currItemData );
			}
			boxData.PushBack( InventoryComboBoxData( message, dataToDisplay, allowUnequip, showcaseItemData, false, false ) );
		}
	}

	private function GetAttachmentDataForCustomizeFromInventory( const inspectedItemData : ref< InventoryItemData >, const equipmentData : ref< array< InventoryItemData > >, boxData : ref< array< InventoryComboBoxData > > )
	{
		var i, limit : Int32;
		var j, limitJ : Int32;
		var currentEquipment : InventoryItemData;
		var itemsToDisplay : array< InventoryItemData >;
		var attachmentsSize : Int32;
		var attachments : InventoryItemAttachments;
		for( i = 0, limit = equipmentData.Size(); i < limit; i += 1 )
		{
			currentEquipment = equipmentData[ i ];
			itemsToDisplay.Clear();
			attachmentsSize = InventoryItemData.GetAttachmentsSize( currentEquipment );
			for( j = 0, limitJ = attachmentsSize; j < limitJ; j += 1 )
			{
				attachments = InventoryItemData.GetAttachment( currentEquipment, i );
				if( !( InventoryItemData.IsEmpty( currentEquipment ) ) && InventoryItemData.PlacementSlotsContains( inspectedItemData, attachments.SlotID ) )
				{
					itemsToDisplay.PushBack( attachments.ItemData );
				}
			}
			if( itemsToDisplay.Size() > 0 )
			{
				boxData.PushBack( InventoryComboBoxData( "Attatch to " + GetLocalizedText( InventoryItemData.GetName( currentEquipment ) ), itemsToDisplay, false, currentEquipment, true, false ) );
			}
		}
	}

	protected event OnSetMenuEventDispatcher( menuEventDispatcher : weak< inkMenuEventDispatcher > )
	{
		super.OnSetMenuEventDispatcher( menuEventDispatcher );
		m_menuEventDispatcher = menuEventDispatcher;
		m_menuEventDispatcher.RegisterToEvent( 'OnBack', this, 'OnBack' );
		m_menuEventDispatcher.RegisterToEvent( 'OnCloseMenu', this, 'OnCloseMenu' );
	}

	private function GetSlotNameFromEqArea( area : gamedataEquipmentArea ) : String
	{
		return EnumValueToString( "gamedataEquipmentArea", ( ( Int32 )( area ) ) );
	}

	private function GetInventoryItemControllerFromTarget( evt : inkPointerEvent ) : InventoryItemDisplay
	{
		var widget : inkWidget;
		var controller : weak< InventoryItemDisplay >;
		widget = evt.GetCurrentTarget();
		controller = ( ( InventoryItemDisplay )( widget.GetController() ) );
		return controller;
	}

	private function GetEquipmentSlotControllerFromTarget( evt : inkPointerEvent ) : InventoryItemDisplayController
	{
		var widget : inkWidget;
		var controller : weak< InventoryItemDisplayController >;
		widget = evt.GetCurrentTarget();
		controller = ( ( InventoryItemDisplayController )( widget.GetController() ) );
		return controller;
	}

	private function IsAnEquipmentArea( equipmentArea : gamedataEquipmentArea ) : Bool
	{
		var i : Int32;
		var isEquipmentArea : Bool;
		for( i = 0; i < m_EquipAreas.Size(); i += 1 )
		{
			if( m_EquipAreas[ i ] == equipmentArea )
			{
				return true;
			}
		}
		return isEquipmentArea;
	}

	private function GetFirstAvailableWeaponSlot() : Int32
	{
		var i : Int32;
		var tempWeaponEquipmentSlot : weak< InventoryItemDisplayController >;
		var tempItemData : InventoryItemData;
		for( i = 0; i < m_WeaponsList.Size(); i += 1 )
		{
			tempWeaponEquipmentSlot = m_WeaponsList[ i ];
			tempItemData = tempWeaponEquipmentSlot.GetItemData();
			if( InventoryItemData.IsEmpty( tempItemData ) )
			{
				return i;
			}
		}
		return 0;
	}

	private function GetAssociatedCategory( controller : InventoryItemDisplayController ) : array< weak< InventoryItemDisplayController > >
	{
		var controllerList : array< weak< InventoryItemDisplayController > >;
		switch( controller.GetEquipmentArea() )
		{
			case gamedataEquipmentArea.SystemReplacementCW:
				controllerList = m_CyberwareList;
			break;
			case gamedataEquipmentArea.Weapon:
				controllerList = m_WeaponsList;
			break;
			case gamedataEquipmentArea.QuickSlot:
			case gamedataEquipmentArea.Gadget:
			case gamedataEquipmentArea.Quest:
				controllerList = m_PocketList;
			break;
			case gamedataEquipmentArea.Consumable:
				controllerList = m_ConsumablesList;
			break;
			case gamedataEquipmentArea.Head:
			case gamedataEquipmentArea.Face:
			case gamedataEquipmentArea.InnerChest:
			case gamedataEquipmentArea.OuterChest:
			case gamedataEquipmentArea.Legs:
			case gamedataEquipmentArea.Feet:
				controllerList = m_EquipmentList;
			break;
		}
		return controllerList;
	}

	private function GetSide( controller : InventoryItemDisplayController ) : Bool
	{
		var isLeft : Bool;
		switch( controller.GetEquipmentArea() )
		{
			case gamedataEquipmentArea.SystemReplacementCW:
			case gamedataEquipmentArea.Weapon:
				isLeft = true;
			break;
			case gamedataEquipmentArea.Gadget:
			case gamedataEquipmentArea.Quest:
			case gamedataEquipmentArea.Consumable:
			case gamedataEquipmentArea.Head:
			case gamedataEquipmentArea.Face:
			case gamedataEquipmentArea.InnerChest:
			case gamedataEquipmentArea.OuterChest:
			case gamedataEquipmentArea.Legs:
			case gamedataEquipmentArea.Feet:
			case gamedataEquipmentArea.Outfit:
				isLeft = false;
			break;
		}
		return isLeft;
	}

	private function GetTooltipPlacement( controller : InventoryItemDisplayController ) : gameuiETooltipPlacement
	{
		switch( controller.GetEquipmentArea() )
		{
			case gamedataEquipmentArea.Weapon:
			case gamedataEquipmentArea.SystemReplacementCW:
			case gamedataEquipmentArea.InnerChest:
			case gamedataEquipmentArea.OuterChest:
			case gamedataEquipmentArea.Outfit:
			case gamedataEquipmentArea.Consumable:
				return gameuiETooltipPlacement.RightTop;
			case gamedataEquipmentArea.Gadget:
			case gamedataEquipmentArea.QuickSlot:
			case gamedataEquipmentArea.Head:
			case gamedataEquipmentArea.Face:
			case gamedataEquipmentArea.Legs:
			case gamedataEquipmentArea.Feet:
				return gameuiETooltipPlacement.LeftTop;
			default:
				return gameuiETooltipPlacement.RightTop;
		}
		return gameuiETooltipPlacement.RightTop;
	}

	public function GetCategoryHeader( displayData : InventoryItemDisplayData ) : String
	{
		var controllerLabel : String;
		switch( displayData.m_equipmentArea )
		{
			case gamedataEquipmentArea.SystemReplacementCW:
				controllerLabel = "Gameplay-RPG-Items-Categories-Cyberware";
			break;
			case gamedataEquipmentArea.Weapon:
				controllerLabel = "Gameplay-RPG-Items-Categories-Weapon";
			break;
			case gamedataEquipmentArea.QuickSlot:
			case gamedataEquipmentArea.Gadget:
			case gamedataEquipmentArea.Quest:
				controllerLabel = "Gameplay-RPG-Items-Categories-Gadget";
			break;
			case gamedataEquipmentArea.Consumable:
				controllerLabel = "Gameplay-RPG-Items-Categories-Consumable";
			break;
			case gamedataEquipmentArea.Head:
			case gamedataEquipmentArea.Face:
			case gamedataEquipmentArea.InnerChest:
			case gamedataEquipmentArea.OuterChest:
			case gamedataEquipmentArea.Legs:
			case gamedataEquipmentArea.Feet:
				controllerLabel = "Gameplay-RPG-Items-Categories-Clothing";
			break;
			case gamedataEquipmentArea.Outfit:
				controllerLabel = "UI-Inventory-Labels-Outfit";
			break;
		}
		return controllerLabel;
	}

}

enum InventoryModes
{
	Default = 0,
	Item = 1,
}

enum ItemViewModes
{
	Item = 0,
	Mod = 1,
}

class ItemDisplayInventoryMiniGrid extends inkLogicController
{
	private editable var m_gridList : inkCompoundRef;
	private editable var m_label : inkTextRef;
	private var m_gridWidth : Int32;
	private var m_gridData : array< weak< InventoryItemDisplayController > >;

	protected event OnInitialize()
	{
		m_gridWidth = 4;
		inkTextRef.SetVisible( m_label, false );
	}

	protected event OnUninitialize()
	{
		var gridListItem : weak< InventoryItemDisplayController >;
		while( m_gridData.Size() > 0 )
		{
			gridListItem = m_gridData.PopBack();
			inkCompoundRef.RemoveChild( m_gridList, gridListItem.GetRootWidget() );
		}
	}

	public function SetupData( const label : ref< String >, const playerEquipAreaInventory : ref< array< InventoryItemData > >, optional equipArea : gamedataEquipmentArea, optional displayContext : ItemDisplayContext )
	{
		var displayToUse : CName;
		var i, limit : Int32;
		var gridListItem : weak< InventoryItemDisplayController >;
		var gridSize : Int32;
		var emptyItemData : InventoryItemData;
		var numOfRows : Int32;
		if( equipArea == gamedataEquipmentArea.Weapon || equipArea == gamedataEquipmentArea.SystemReplacementCW )
		{
			InventoryItemData.SetItemShape( emptyItemData, EInventoryItemShape.DoubleSlot );
		}
		if( ( playerEquipAreaInventory.Size() % m_gridWidth ) > 0 )
		{
			numOfRows = CeilF( ( ( ( Float )( playerEquipAreaInventory.Size() ) ) / ( ( Float )( m_gridWidth ) ) ) + 0.5 );
			gridSize = m_gridWidth * numOfRows;
		}
		else if( playerEquipAreaInventory.Size() == 0 )
		{
			gridSize = m_gridWidth;
		}
		else
		{
			gridSize = playerEquipAreaInventory.Size();
		}
		limit = gridSize;
		while( m_gridData.Size() > 0 )
		{
			gridListItem = m_gridData.PopBack();
			inkCompoundRef.RemoveChild( m_gridList, gridListItem.GetRootWidget() );
		}
		for( i = 0; i < limit; i += 1 )
		{
			displayToUse = 'gridItemDisplay';
			if( InventoryItemData.GetEquipmentArea( playerEquipAreaInventory[ i ] ) == gamedataEquipmentArea.Weapon )
			{
				displayToUse = 'gridWeaponDisplay';
			}
			gridListItem = ( ( InventoryItemDisplayController )( ItemDisplayUtils.SpawnCommonSlotController( this, m_gridList, displayToUse ) ) );
			m_gridData.PushBack( gridListItem );
			if( playerEquipAreaInventory.Size() > i )
			{
				gridListItem.Setup( playerEquipAreaInventory[ i ], displayContext );
			}
			else
			{
				gridListItem.Setup( emptyItemData );
			}
		}
		inkTextRef.SetVisible( m_label, true );
		inkTextRef.SetText( m_label, label );
	}

	public function GetInventoryItemDisplays() : array< weak< InventoryItemDisplayController > >
	{
		return m_gridData;
	}

	public function RemoveElement()
	{
		var gridListItem : weak< InventoryItemDisplayController >;
		while( m_gridData.Size() > 0 )
		{
			gridListItem = m_gridData.PopBack();
			inkCompoundRef.RemoveChild( m_gridList, gridListItem.GetRootWidget() );
		}
		inkTextRef.SetVisible( m_label, false );
	}

}

class ItemInventoryMiniGrid extends inkLogicController
{
	private editable var m_gridList : inkCompoundRef;
	private editable var m_label : inkTextRef;
	private var m_gridWidth : Int32;
	private var m_gridData : array< weak< InventoryItemDisplay > >;

	protected event OnInitialize()
	{
		m_gridWidth = 4;
		inkTextRef.SetVisible( m_label, false );
	}

	protected event OnUninitialize()
	{
		var gridListItem : weak< InventoryItemDisplay >;
		while( m_gridData.Size() > 0 )
		{
			gridListItem = m_gridData.PopBack();
			inkCompoundRef.RemoveChild( m_gridList, gridListItem.GetRootWidget() );
		}
	}

	public function SetupData( const label : ref< String >, const playerEquipAreaInventory : ref< array< InventoryItemData > >, optional equipArea : gamedataEquipmentArea )
	{
		var i, limit : Int32;
		var gridListItem : weak< InventoryItemDisplay >;
		var gridSize : Int32;
		var emptyItemData : InventoryItemData;
		var numOfRows : Int32;
		if( equipArea == gamedataEquipmentArea.Weapon || equipArea == gamedataEquipmentArea.SystemReplacementCW )
		{
			InventoryItemData.SetItemShape( emptyItemData, EInventoryItemShape.DoubleSlot );
		}
		if( ( playerEquipAreaInventory.Size() % m_gridWidth ) > 0 )
		{
			numOfRows = CeilF( ( ( ( Float )( playerEquipAreaInventory.Size() ) ) / ( ( Float )( m_gridWidth ) ) ) + 0.5 );
			gridSize = m_gridWidth * numOfRows;
		}
		else if( playerEquipAreaInventory.Size() == 0 )
		{
			gridSize = m_gridWidth;
		}
		else
		{
			gridSize = playerEquipAreaInventory.Size();
		}
		limit = gridSize;
		while( m_gridData.Size() > limit )
		{
			gridListItem = m_gridData.PopBack();
			inkCompoundRef.RemoveChild( m_gridList, gridListItem.GetRootWidget() );
		}
		while( m_gridData.Size() < limit )
		{
			gridListItem = ( ( InventoryItemDisplay )( ItemDisplayUtils.SpawnCommonSlotController( this, m_gridList, 'inventoryHudItem' ) ) );
			m_gridData.PushBack( gridListItem );
		}
		for( i = 0; i < m_gridData.Size(); i += 1 )
		{
			gridListItem = m_gridData[ i ];
			if( playerEquipAreaInventory.Size() > i )
			{
				gridListItem.Setup( playerEquipAreaInventory[ i ] );
			}
			else
			{
				gridListItem.Setup( emptyItemData );
			}
		}
		inkTextRef.SetVisible( m_label, true );
		inkTextRef.SetText( m_label, label );
	}

	public function SetGridWith( gridWidth : Int32 )
	{
		m_gridWidth = gridWidth;
	}

	public function GetInventoryItemDisplays() : array< weak< InventoryItemDisplay > >
	{
		return m_gridData;
	}

	public function RemoveElement()
	{
		var gridListItem : weak< InventoryItemDisplay >;
		while( m_gridData.Size() > 0 )
		{
			gridListItem = m_gridData.PopBack();
			inkCompoundRef.RemoveChild( m_gridList, gridListItem.GetRootWidget() );
		}
		inkTextRef.SetVisible( m_label, false );
	}

}

enum PaperdollPositionAnimation
{
	Center = 0,
	Left = 1,
	Right = 2,
	LeftFullBody = 3,
}

struct EquipmentWidgets
{
	const editable var widgetArray : array< inkWidgetRef >;
}

class EquipmentAreaDisplays
{
	var equipmentAreas : array< gamedataEquipmentArea >;
	var displaysRoot : weak< inkWidget >;
	var displayControllers : array< weak< InventoryItemDisplayController > >;
}

class EquipmentAreaCategory
{
	var parentCategory : weak< InventoryItemDisplayCategoryArea >;
	var areaDisplays : array< EquipmentAreaDisplays >;

	public function GetDisplays() : array< InventoryItemDisplayController >
	{
		var i, j : Int32;
		var result : array< InventoryItemDisplayController >;
		for( i = 0; i < areaDisplays.Size(); i += 1 )
		{
			for( j = 0; j < areaDisplays[ i ].displayControllers.Size(); j += 1 )
			{
				result.PushBack( areaDisplays[ i ].displayControllers[ j ] );
			}
		}
		return result;
	}

}

class InventoryStatsListener extends ScriptStatsListener
{
	var m_owner : weak< GameObject >;
	var m_controller : weak< InventoryStatsController >;

	public override function OnStatChanged( ownerID : StatsObjectID, statType : gamedataStatType, diff : Float, total : Float )
	{
		if( ( ( PlayerPuppet )( m_owner ) ) )
		{
			if( ( statType == gamedataStatType.Armor || statType == gamedataStatType.Health ) || statType == gamedataStatType.Stamina )
			{
				m_controller.NotifyStatUpdate( statType, total );
			}
		}
	}

}

class InventoryStatsController extends inkLogicController
{
	protected editable var m_detailsButton : inkWidgetRef;
	protected editable var m_entryContainer : inkCompoundRef;
	protected var m_healthEntryController : weak< InventoryStatsEntryController >;
	protected var m_armorEntryController : weak< InventoryStatsEntryController >;
	protected var m_staminaEntryController : weak< InventoryStatsEntryController >;

	public function Setup( player : weak< PlayerPuppet > )
	{
		inkCompoundRef.RemoveAllChildren( m_entryContainer );
		m_armorEntryController = SetupEntry( player, gamedataStatType.Armor, 'Gameplay-RPG-Stats-Armor', 'inventory_stat_armor' );
		m_healthEntryController = SetupEntry( player, gamedataStatType.Health, 'Gameplay-RPG-Stats-Health', 'inventory_stat_health' );
		m_staminaEntryController = SetupEntry( player, gamedataStatType.Stamina, 'Gameplay-RPG-Stats-Stamina', 'inventory_stat_stamina' );
		m_armorEntryController.AT_SetATID( "InventoryStats_ArmorStat" );
		m_healthEntryController.AT_SetATID( "InventoryStats_HealthStat" );
		m_staminaEntryController.AT_SetATID( "InventoryStats_StaminaStat" );
	}

	public function NotifyStatUpdate( statType : gamedataStatType, value : Float )
	{
		switch( statType )
		{
			case gamedataStatType.Armor:
				m_armorEntryController.SetValue( value );
			break;
			case gamedataStatType.Health:
				m_armorEntryController.SetValue( value );
			break;
			case gamedataStatType.Stamina:
				m_armorEntryController.SetValue( value );
			break;
		}
	}

	public function SetupEntry( player : weak< PlayerPuppet >, stat : gamedataStatType, localizationKey : CName, icon : CName ) : weak< InventoryStatsEntryController >
	{
		var widget : weak< inkWidget >;
		var statsSystem : StatsSystem;
		var value : Float;
		var controller : weak< InventoryStatsEntryController >;
		statsSystem = GameInstance.GetStatsSystem( player.GetGame() );
		widget = SpawnFromLocal( inkCompoundRef.Get( m_entryContainer ), 'statContainer' );
		if( stat == gamedataStatType.Health )
		{
			value = ( ( Float )( CeilF( statsSystem.GetStatValue( player.GetEntityID(), stat ) ) ) );
		}
		else
		{
			value = statsSystem.GetStatValue( player.GetEntityID(), stat );
		}
		controller = ( ( InventoryStatsEntryController )( widget.GetController() ) );
		controller.Setup( icon, GetLocalizedText( ( ( String )( localizationKey ) ) ), value );
		return controller;
	}

}

class InventoryStatsEntryController extends inkLogicController
{
	protected editable var m_iconWidget : inkImageRef;
	protected editable var m_labelWidget : inkTextRef;
	protected editable var m_valueWidget : inkTextRef;

	public function Setup( icon : CName, const label : ref< String >, value : Float )
	{
		inkTextRef.SetText( m_labelWidget, label );
		InkImageUtils.RequestSetImage( this, m_iconWidget, 'UIIcon.' + icon );
		SetValue( value );
	}

	public function SetValue( value : Float )
	{
		inkTextRef.SetText( m_valueWidget, IntToString( RoundMath( value ) ) );
	}

	public function AT_SetATID( const ATID : ref< String > )
	{
		AT_AddATID( inkTextRef.Get( m_valueWidget ), ATID );
	}

}

class CyberdeckInventoryStatsController extends inkLogicController
{
	[ category = "Buffer" ]
	editable var m_bufferTotal : inkTextRef;
	[ category = "Buffer" ]
	editable var m_bufferBase : inkTextRef;
	[ category = "Buffer" ]
	editable var m_bufferBonus : inkTextRef;
	[ category = "Buffer" ]
	editable var m_bufferHoverArea : inkWidgetRef;
	[ category = "Buffer" ]
	editable var m_bufferTooltipPlacement : gameuiETooltipPlacement;
	default m_bufferTooltipPlacement = gameuiETooltipPlacement.LeftTop;
	[ category = "RAM" ]
	editable var m_ramTotal : inkTextRef;
	[ category = "RAM" ]
	editable var m_ramBase : inkTextRef;
	[ category = "RAM" ]
	editable var m_ramBonus : inkTextRef;
	[ category = "RAM" ]
	editable var m_ramHoverArea : inkWidgetRef;
	[ category = "RAM" ]
	editable var m_ramTooltipPlacement : gameuiETooltipPlacement;
	default m_ramTooltipPlacement = gameuiETooltipPlacement.LeftTop;
	private var m_tooltipsManager : weak< gameuiTooltipsManager >;

	protected event OnInitialize()
	{
		inkWidgetRef.RegisterToCallback( m_bufferHoverArea, 'OnHoverOver', this, 'OnBufferHoverOver' );
		inkWidgetRef.RegisterToCallback( m_bufferHoverArea, 'OnHoverOut', this, 'OnHoverOut' );
		inkWidgetRef.RegisterToCallback( m_ramHoverArea, 'OnHoverOver', this, 'OnRamHoverOver' );
		inkWidgetRef.RegisterToCallback( m_ramHoverArea, 'OnHoverOut', this, 'OnHoverOut' );
	}

	protected event OnUninitialize()
	{
		inkWidgetRef.UnregisterFromCallback( m_bufferHoverArea, 'OnHoverOver', this, 'OnBufferHoverOver' );
		inkWidgetRef.UnregisterFromCallback( m_bufferHoverArea, 'OnHoverOut', this, 'OnHoverOut' );
		inkWidgetRef.UnregisterFromCallback( m_ramHoverArea, 'OnHoverOver', this, 'OnRamHoverOver' );
		inkWidgetRef.UnregisterFromCallback( m_ramHoverArea, 'OnHoverOut', this, 'OnHoverOut' );
	}

	public function SetupData( tweakID : TweakDBID, player : weak< PlayerPuppet >, tooltipsManager : weak< gameuiTooltipsManager > )
	{
		var cyberdeckBufferValue : Int32;
		var cyberdeckMemoryValue : Int32;
		var playerBufferValue : Int32;
		var playerMemoryValue : Int32;
		var tweakRecord : weak< Item_Record >;
		var onEquipList : array< weak< GameplayLogicPackage_Record > >;
		var statsList : array< weak< StatModifier_Record > >;
		var i, j : Int32;
		var statType : weak< Stat_Record >;
		var stat : weak< ConstantStatModifier_Record >;
		m_tooltipsManager = tooltipsManager;
		tweakRecord = TDB.GetItemRecord( tweakID );
		tweakRecord.OnEquip( onEquipList );
		for( i = 0; i < onEquipList.Size(); i += 1 )
		{
			onEquipList[ i ].Stats( statsList );
			for( j = 0; j < statsList.Size(); j += 1 )
			{
				statType = statsList[ j ].StatType();
				stat = ( ( weak< weak< ConstantStatModifier_Record > > )( statsList[ j ] ) );
				if( stat )
				{
					if( statType.StatType() == gamedataStatType.Memory )
					{
						cyberdeckMemoryValue = RoundMath( stat.Value() );
					}
					else if( statType.StatType() == gamedataStatType.BufferSize )
					{
						cyberdeckBufferValue = RoundMath( stat.Value() );
					}
				}
			}
		}
		playerBufferValue = RoundMath( GameInstance.GetStatsSystem( player.GetGame() ).GetStatValue( player.GetEntityID(), gamedataStatType.BufferSize ) );
		playerMemoryValue = RoundMath( GameInstance.GetStatPoolsSystem( player.GetGame() ).GetStatPoolValue( player.GetEntityID(), gamedataStatPoolType.Memory, false ) );
		inkTextRef.SetText( m_bufferTotal, IntToString( playerBufferValue ) );
		inkTextRef.SetText( m_bufferBase, IntToString( playerBufferValue - cyberdeckBufferValue ) );
		inkTextRef.SetText( m_bufferBonus, IntToString( cyberdeckBufferValue ) );
		inkTextRef.SetText( m_ramTotal, IntToString( playerMemoryValue ) );
		inkTextRef.SetText( m_ramBase, IntToString( playerMemoryValue - cyberdeckMemoryValue ) );
		inkTextRef.SetText( m_ramBonus, IntToString( cyberdeckMemoryValue ) );
	}

	protected event OnBufferHoverOver( evt : inkPointerEvent )
	{
		var messageData : MessageTooltipData;
		messageData = new MessageTooltipData;
		messageData.Title = GetLocalizedItemNameByCName( 'UI-Inventory-Cyberdeck-BufferTooltip' );
		m_tooltipsManager.ShowTooltipAtWidget( 0, inkWidgetRef.Get( m_bufferHoverArea ), messageData, m_bufferTooltipPlacement );
	}

	protected event OnRamHoverOver( evt : inkPointerEvent )
	{
		var messageData : MessageTooltipData;
		messageData = new MessageTooltipData;
		messageData.Title = GetLocalizedItemNameByCName( 'UI-Inventory-Cyberdeck-RamTooltip' );
		m_tooltipsManager.ShowTooltipAtWidget( 0, inkWidgetRef.Get( m_ramHoverArea ), messageData, m_ramTooltipPlacement );
	}

	protected event OnHoverOut( evt : inkPointerEvent )
	{
		m_tooltipsManager.HideTooltips();
	}

}

class OpenInventoryQuantityPickerRequest extends Event
{
	var itemData : InventoryItemData;
	var actionType : QuantityPickerActionType;
}

class DelayedRefreshUI extends Event
{
}

class DelayedSetItemModeShown extends Event
{
}

enum InventoryPaperdollZoomArea
{
	Default = 0,
	Weapon = 1,
	Legs = 2,
	Feet = 3,
	Cyberware = 4,
	QuickSlot = 5,
	Consumable = 6,
	Outfit = 7,
	Head = 8,
	Face = 9,
	InnerChest = 10,
	OuterChest = 11,
}

class CyberwareSlotSpawnData
{
	var index : Int32;
}

