import struct inkEntityPreviewCameraSettings
{
	import var panSpeed : Float;
	import var rotationSpeed : EulerAngles;
	import var rotationMin : EulerAngles;
	import var rotationMax : EulerAngles;
	import var rotationDefault : EulerAngles;
	import var zoomSpeed : Float;
	import var zoomMin : Float;
	import var zoomMax : Float;
	import var zoomDefault : Float;
}

import class inkEntityPreviewGameController extends gameuiMenuGameController
{
	public import function GetCameraSettings() : inkEntityPreviewCameraSettings;
	public import function EnableCamera();
	public import function DisableCamera();
	public import function ResetCamera();
	public import function ResetTargetPosition();
	public import function ZoomIn( strength : Float );
	public import function ZoomOut( strength : Float );
	public import function RotateYaw( strength : Float );
	public import function RotatePitch( strength : Float );
	public import function Move( direction : Vector4, strength : Float );
}

import class gameuiPuppetPreview_ReadyToBeDisplayed extends Event
{
	import var isMale : Bool;
}

import class gameuiPuppetPreview_SetCameraSetupEvent extends Event
{
	import var setupIndex : Uint32;
	import var slotName : CName;
}

import abstract class inkPreviewGameController extends gameuiMenuGameController
{
	protected editable var m_isRotatable : Bool;
	protected editable var m_rotationSpeed : Float;
	default m_rotationSpeed = 30.0f;
	protected var m_inputDisabled : Bool;

	public import function Rotate( yaw : Float );
	public import function RotateVector( value : Vector3 );

	protected event OnInitialize()
	{
		m_inputDisabled = false;
		if( m_isRotatable )
		{
			RegisterToGlobalInputCallback( 'OnPostOnAxis', this, 'OnAxisInput' );
		}
	}

	protected event OnUninitialize()
	{
		if( m_isRotatable )
		{
			UnregisterFromGlobalInputCallback( 'OnPostOnAxis', this, 'OnAxisInput' );
		}
	}

	protected virtual function HandleAxisInput( e : inkPointerEvent )
	{
		var amount : Float;
		amount = e.GetAxisData();
		if( e.IsAction( 'left_trigger' ) || e.IsAction( 'character_preview_rotate' ) )
		{
			Rotate( amount * -( m_rotationSpeed ) );
		}
		else if( e.IsAction( 'right_trigger' ) || e.IsAction( 'character_preview_rotate' ) )
		{
			Rotate( amount * m_rotationSpeed );
		}
	}

	protected event OnAxisInput( e : inkPointerEvent )
	{
		if( !( m_inputDisabled ) )
		{
			HandleAxisInput( e );
		}
	}

	public function SetInputDisabled( disabled : Bool )
	{
		m_inputDisabled = disabled;
	}

}

import class inkPuppetPreviewGameController extends inkPreviewGameController
{
	public import function GetGamePuppet() : weak< gamePuppet >;

	protected event OnPreviewInitialized()
	{
		SendAnimData();
	}

	private virtual function SendAnimData()
	{
		var animFeature : AnimFeature_Paperdoll;
		GetAnimFeature( animFeature );
		AnimationControllerComponent.ApplyFeature( GetGamePuppet(), 'Paperdoll', animFeature );
	}

	private virtual function GetAnimFeature( out animFeature : AnimFeature_Paperdoll )
	{
		animFeature = new AnimFeature_Paperdoll;
	}

}

import class inkGenderSelectionPuppetPreviewGameController extends inkPuppetPreviewGameController
{

	protected event OnInitialize()
	{
		super.OnInitialize();
	}

	private override function GetAnimFeature( out animFeature : AnimFeature_Paperdoll )
	{
		animFeature = new AnimFeature_Paperdoll;
		animFeature.genderSelection = true;
	}

}

import class inkCharacterCreationPuppetPreviewGameController extends inkPuppetPreviewGameController
{
	private var m_characterCustomizationSystem : weak< gameuiICharacterCustomizationSystem >;

	protected event OnInitialize()
	{
		super.OnInitialize();
		PlayLibraryAnimation( 'intro' );
	}

	protected event OnUninitialize()
	{
		super.OnUninitialize();
		if( m_characterCustomizationSystem )
		{
			m_characterCustomizationSystem.UnregisterPuppetPreviewGameController();
		}
	}

	private override function GetAnimFeature( out animFeature : AnimFeature_Paperdoll )
	{
		animFeature = new AnimFeature_Paperdoll;
		animFeature.characterCreation = true;
	}

	protected event OnSetCameraSetupEvent( index : Uint32, slotName : CName )
	{
		var animFeature : AnimFeature_Paperdoll;
		m_characterCustomizationSystem = GameInstance.GetCharacterCustomizationSystem( GetGamePuppet().GetGame() );
		if( m_characterCustomizationSystem )
		{
			m_characterCustomizationSystem.RegisterPuppetPreviewGameController( this );
		}
		animFeature = new AnimFeature_Paperdoll;
		if( slotName == 'UI_HeadPreview' )
		{
			animFeature.characterCreation_Head = true;
		}
		else if( slotName == 'UI_Skin' )
		{
			animFeature.characterCreation_Head = true;
		}
		else if( slotName == 'UI_Hairs' )
		{
			animFeature.characterCreation_Head = true;
			animFeature.characterCreation_Hair = true;
		}
		else if( slotName == 'UI_Teeth' )
		{
			animFeature.characterCreation_Head = true;
			animFeature.characterCreation_Teeth = true;
		}
		else if( slotName == 'UI_FingerNails' )
		{
			animFeature.characterCreation_Nails = true;
		}
		else if( slotName == 'UI_Eyes' )
		{
			animFeature.characterCreation_Head = true;
			animFeature.characterCreation_Eyes = true;
		}
		else if( slotName == 'UI_Nose' )
		{
			animFeature.characterCreation_Head = true;
			animFeature.characterCreation_Nose = true;
		}
		else if( slotName == 'UI_Lips' )
		{
			animFeature.characterCreation_Head = true;
			animFeature.characterCreation_Lips = true;
		}
		else if( slotName == 'UI_Jaw' )
		{
			animFeature.characterCreation_Head = true;
			animFeature.characterCreation_Jaw = true;
		}
		else if( slotName == 'Summary_Preview' )
		{
			animFeature.characterCreation_Summary = true;
		}
		else if( slotName == 'Gender_Preview' )
		{
			animFeature.genderSelection = true;
		}
		else
		{
			animFeature.characterCreation = true;
		}
		AnimationControllerComponent.ApplyFeature( GetGamePuppet(), 'Paperdoll', animFeature );
	}

}

import class inkInventoryPuppetPreviewGameController extends inkPuppetPreviewGameController
{
	default m_rotationSpeed = 60.0f;
	private editable var m_collider : inkWidgetRef;
	private var m_rotationIsMouseDown : Bool;
	protected var m_maxMousePointerOffset : Float;
	default m_maxMousePointerOffset = 40.0f;
	protected var m_mouseRotationSpeed : Float;
	default m_mouseRotationSpeed = 250.0f;

	protected event OnInitialize()
	{
		super.OnInitialize();
		inkWidgetRef.RegisterToCallback( m_collider, 'OnPress', this, 'OnMouseDown' );
		RegisterToGlobalInputCallback( 'OnPreOnRelease', this, 'OnGlobalRelease' );
		RegisterToGlobalInputCallback( 'OnPostOnRelative', this, 'OnRelativeInput' );
	}

	protected event OnUninitialize()
	{
		var evt : inkMenuLayer_SetCursorVisibility;
		super.OnUninitialize();
		if( m_rotationIsMouseDown )
		{
			m_rotationIsMouseDown = false;
			evt = new inkMenuLayer_SetCursorVisibility;
			evt.Init( true, Vector2( 0.5, 0.5 ) );
			QueueEvent( evt );
		}
		inkWidgetRef.UnregisterFromCallback( m_collider, 'OnPress', this, 'OnMouseDown' );
		UnregisterFromGlobalInputCallback( 'OnPreOnRelease', this, 'OnGlobalRelease' );
		UnregisterFromGlobalInputCallback( 'OnPostOnRelative', this, 'OnRelativeInput' );
	}

	protected event OnMouseDown( e : inkPointerEvent )
	{
		var evt : inkMenuLayer_SetCursorVisibility;
		if( e.IsAction( 'mouse_left' ) )
		{
			m_rotationIsMouseDown = true;
			evt = new inkMenuLayer_SetCursorVisibility;
			evt.Init( false );
			QueueEvent( evt );
		}
	}

	protected event OnGlobalRelease( e : inkPointerEvent )
	{
		var evt : inkMenuLayer_SetCursorVisibility;
		if( m_rotationIsMouseDown && e.IsAction( 'mouse_left' ) )
		{
			e.Consume();
			m_rotationIsMouseDown = false;
			evt = new inkMenuLayer_SetCursorVisibility;
			evt.Init( true, Vector2( 0.5, 0.5 ) );
			QueueEvent( evt );
		}
	}

	protected event OnRelativeInput( e : inkPointerEvent )
	{
		var offset, ratio, velocity : Float;
		offset = e.GetAxisData();
		if( offset > 0.0 )
		{
			ratio = ClampF( offset / m_maxMousePointerOffset, 0.5, 1.0 );
		}
		else
		{
			ratio = ClampF( offset / m_maxMousePointerOffset, -1.0, -0.5 );
		}
		velocity = ratio * m_mouseRotationSpeed;
		if( m_rotationIsMouseDown )
		{
			if( e.IsAction( 'mouse_x' ) )
			{
				Rotate( velocity );
			}
		}
	}

	private override function GetAnimFeature( out animFeature : AnimFeature_Paperdoll )
	{
		animFeature = new AnimFeature_Paperdoll;
		animFeature.inventoryScreen = true;
	}

	protected event OnSetCameraSetupEvent( index : Uint32, slotName : CName )
	{
		var zoomArea : InventoryPaperdollZoomArea;
		var animFeature : AnimFeature_Paperdoll;
		animFeature = new AnimFeature_Paperdoll;
		zoomArea = ( ( InventoryPaperdollZoomArea )( index ) );
		animFeature.inventoryScreen = zoomArea == InventoryPaperdollZoomArea.Default;
		animFeature.inventoryScreen_Weapon = zoomArea == InventoryPaperdollZoomArea.Weapon;
		animFeature.inventoryScreen_Legs = zoomArea == InventoryPaperdollZoomArea.Legs;
		animFeature.inventoryScreen_Feet = zoomArea == InventoryPaperdollZoomArea.Feet;
		animFeature.inventoryScreen_Cyberware = zoomArea == InventoryPaperdollZoomArea.Cyberware;
		animFeature.inventoryScreen_QuickSlot = zoomArea == InventoryPaperdollZoomArea.QuickSlot;
		animFeature.inventoryScreen_Consumable = zoomArea == InventoryPaperdollZoomArea.Consumable;
		animFeature.inventoryScreen_Outfit = zoomArea == InventoryPaperdollZoomArea.Outfit;
		animFeature.inventoryScreen_Head = zoomArea == InventoryPaperdollZoomArea.Head;
		animFeature.inventoryScreen_Face = zoomArea == InventoryPaperdollZoomArea.Face;
		animFeature.inventoryScreen_InnerChest = zoomArea == InventoryPaperdollZoomArea.InnerChest;
		animFeature.inventoryScreen_OuterChest = zoomArea == InventoryPaperdollZoomArea.OuterChest;
		AnimationControllerComponent.ApplyFeature( GetGamePuppet(), 'Paperdoll', animFeature );
	}

}

