ModelViewer/ClothingCamera.cs
using Sandbox;
using Sandbox.Citizen;
using Sandbox.Internal;
using System;
using System.IO;
using System.Numerics;
using static Sandbox.ColorGrading;
using static Sandbox.PhysicsContact;
[Title( "Model Viewer Camera Set Up" )]
[Category( "Model Viewer" )]
[Icon( "camera", "red", "white" )]
[Tint(EditorTint.Yellow)]
public sealed class ClothingCamera : Component
{
public enum CameraMode
{
Orbit,
Maya,
FreeCam,
FPS,
ThirdPerson
}
public enum Poses
{
TPose,
RaisedHands,
None
}
//CameraMode
[Property][Title( "Camera Mode" )][Group( "Camera Mode" )] public CameraMode Mode { get; set; } = CameraMode.Orbit;
[Property][Title( "Lock Camera" )][Group( "Camera Mode" )] public bool LockCamera { get; set; } = false;
[Property][Title( "Camera Focus Object" )][Group( "Camera Mode" )] public GameObject FocusObject { get; set; }
[Property]
[Title( "Field of View" )]
[Range( 0, 180 )]
[Group( "Camera" )]
public float Fov { get; set; } = 80.0f;
[Property]
[Title( "Near Clip" )]
[Range( 0, 10 )]
[Group( "Camera" )]
public float Near { get; set; } = 0.1f;
[Property]
[Title( "Far Clip" )]
[Range( 0, 10000 )]
[Group( "Camera" )]
public float Far { get; set; } = 10000.0f;
[Property]
[Title( "Orthographic" )]
[Group( "Camera" )]
public bool Ortho { get; set; } = false;
[Property]
[Title( "Orthographic Size" )]
[Range( 0, 1000 )]
[Group( "Camera" )]
public float OrthoSize { get; set; } = 1000.0f;
//Orbit Controls
[Property][Group( "Orbit Controls" ), ShowIf( "Mode", CameraMode.Orbit )] public float CameraDistance { get; set; } = 200.0f;
//
public Vector3 orbitObject { get; set; }
private float orbitDistance = 200.0f;
//Maya Controls
[Property][Title( "Maya Orbit Speed" )][Range( 0, 1 )][Group( "Maya Controls" ),ShowIf( "Mode", CameraMode.Maya )] private float orbitSpeed { get; set; } = 1.0f;
[Property][Title( "Maya Zoom Speed" )][Range( 0, 1 )][Group( "Maya Controls" ), ShowIf( "Mode", CameraMode.Maya )] private float zoomSpeed { get; set; } = 10.0f;
[Property][Title( "Maya Pan Speed" )][Range( 0, 10 )][Group( "Maya Controls" ), ShowIf( "Mode", CameraMode.Maya )] private float panSpeed { get; set; } = 10.0f;
[Property][Title( "Maya Fly Speed" )][Range( 0, 200 )][Group( "Maya Controls" ), ShowIf( "Mode", CameraMode.Maya )] private float MayaFlySpeed { get; set; } = 100.0f;
//
//Lazy Susan
[Property][FeatureEnabled( "LazySusan", Icon = "👩" )] private bool LazySusan { get; set; } = false;
[Property][Title( "Lazy Susan Speed" )][Range( 0, 2 )][Feature( "LazySusan" )] public float LazySuzzy { get; set; } = 0.50f;
//
//World Color
[Property][Title( "Hide World" )][Group( "World" )] public bool HideWorld { get; set; } = false;
[Property][Title( "World Color" )][Group( "World" )] public Color WorldColor { get; set; } = Color.White;
[Property][Title( "Fog Color" )][Group( "World" )] public Color FogColor { get; set; } = Color.White;
[Property][Title( "Skybox Material" )][Group( "World" )] public Material SkyboxMaterial { get; set; } = Material.Load( "materials/skybox/skybox_day_01.vmat");
[Property][Title( "Skybox" )][Group( "World" )] SkyBox2D skybox { get; set; }
[Property][Title( "Fog Start Distance" )][Group( "World" )] public float FogStartDistance { get; set; } = 300.0f;
[Property][Title( "Fog End Distance" )][Group( "World" )] public float FogEndDistance { get; set; } = 1024.0f;
[Property][Title( "Fog Falloff Exponent" )][Group( "World" )] public float FogFalloffExponent { get; set; } = 1.0f;
[Property][Title( "Fog Height" )][Group( "World" )] public float FogHeight { get; set; } = 500.0f;
[Property][Title( "Fog Verticle Falloff Exponent" )][Group( "World" )] public float FogVerticleFalloffExponent { get; set; } = 2.0f;
//
//Post Processing
[Property, FeatureEnabled( "ColorMapping", Icon = "🎨" )] public bool ColorMapping { get; set; } = true;
[Property, Feature( "ColorMapping" )] public GradingType ColorGrading { get; set; } = GradingType.None;
[Property, Feature( "ColorMapping" ), ShowIf( "ColorGrading", GradingType.TemperatureControl )]
[Range( 1000f, 40000f, 0.01f, true, true )]
[DefaultValue( 6500f )]
[Group( "ColorMapping" )] public float Temperature { get; set; } = 0.0f;
[Property, Feature( "ColorMapping" ), ShowIf( "ColorGrading", GradingType.TemperatureControl )]
[Range( 0f, 1f, 0.01f, true, true )]
[DefaultValue( 0f )]
[Group( "ColorMapping" )] public float Blend { get; set; } = 0.0f;
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[ShowIf( "ColorGrading", GradingType.LUT )]
[Property]
public Texture LookupTexture { get; set; } = Texture.White;
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[DefaultValue( ColorSpaceEnum.None )]
public ColorSpaceEnum ColorSpace { get; set; } = ColorSpaceEnum.None;
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[ShowIf( "ColorSpace", ColorSpaceEnum.RGB )]
public Curve Rcurve { get; set; } = new Curve( new Curve.Frame( 0f, 0.5f ), new Curve.Frame( 1f, 1f ) );
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[ShowIf( "ColorSpace", ColorSpaceEnum.RGB )]
public Curve Gcurve { get; set; } = new Curve( new Curve.Frame( 0f, 0.5f ), new Curve.Frame( 1f, 1f ) );
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[ShowIf( "ColorSpace", ColorSpaceEnum.RGB )]
public Curve Bcurve { get; set; } = new Curve( new Curve.Frame( 0f, 0.5f ), new Curve.Frame( 1f, 1f ) );
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[ShowIf( "ColorSpace", ColorSpaceEnum.HSV )]
public Curve Hcurve { get; set; } = new Curve( new Curve.Frame( 0f, 0.5f ), new Curve.Frame( 1f, 1f ) );
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[ShowIf( "ColorSpace", ColorSpaceEnum.HSV )]
public Curve Scurve { get; set; } = new Curve( new Curve.Frame( 0f, 0.5f ), new Curve.Frame( 1f, 1f ) );
[Group( "ColorMapping" ), Feature( "ColorMapping" )]
[Property]
[ShowIf( "ColorSpace", ColorSpaceEnum.HSV )]
public Curve Vcurve { get; set; } = new Curve( new Curve.Frame( 0f, 0.5f ), new Curve.Frame( 1f, 1f ) );
[Property, FeatureEnabled( "Bloom", Icon = "💣" )] public bool Bloom { get; set; } = true;
[Property, Feature( "Bloom" )][Title( "Mode" )] public SceneCamera.BloomAccessor.BloomMode BloomMode { get; set; } = SceneCamera.BloomAccessor.BloomMode.Screen;
[Property, Feature( "Bloom" ),Range(0,10)] public float BloomStrength { get; set; } = 0.1f;
[Property, Feature( "Bloom" ), Range( 0, 2 )] public float BloomThreshold { get; set; } = 0.3f;
[Property, Feature( "Bloom" ), Range( 0, 5 )] public float BloomThresholdWidth { get; set; } = 0.0f;
[Property, Feature( "Bloom" )] public Curve BloomCurve { get; set; } = new Curve( new Curve.Frame( 0.0f, 0.5f ), new Curve.Frame( 1.0f, 1.0f ) );
[Property, Feature( "Bloom" )] public Gradient BloomColor { get; set; } = new Gradient( new Gradient.ColorFrame( 0.0f, Color.White ), new Gradient.ColorFrame( 1.0f, Color.White ) );
//
[Property, FeatureEnabled( "FilmGrain", Icon = "🌌" )] public bool FilmGrain { get; set; } = true;
[Property, Feature( "FilmGrain" )] public float FilmGrainIntensity { get; set; } = 0.025f;
[Property, Feature( "FilmGrain" )] public float FilmGrainResponse { get; set; } = 0.5f;
//
[Property, FeatureEnabled( "Vignette", Icon = "🔘" )] public bool Vignette { get; set; } = true;
[Property, Feature( "Vignette" ), Range( 0, 1 )] public float VignetteIntensity { get; set; } = 0.5f;
[Property, Feature( "Vignette" ), Range( 0, 1 )] public float VignetteSmoothness { get; set; } = 0.5f;
[Property, Feature( "Vignette" ), Range( 0, 2 )] public float VignetteRoundness { get; set; } = 1.0f;
[Property, Feature( "Vignette" )] public Color VignetteColor { get; set; } = Color.Black;
[Property, Feature( "Vignette" )] public Vector2 VignetteCenter { get; set; } = new Vector2( 0.5f, 0.5f );
//
[Property, FeatureEnabled( "Sharpen", Icon = "🔪" )] public bool Sharpen { get; set; } = true;
[Property, Feature( "Sharpen" ), Range( 0, 5 )] public float SharpenIntensity { get; set; } = 0.25f;
//
[Property, FeatureEnabled( "DepthOfField", Icon = "🔭" )] public bool DepthOfField { get; set; } = false;
[Property, Feature( "DepthOfField" )][Range( 0, 1000 )] public float DepthOfFieldFocusDistance { get; set; } = 200.0f;
[Property, Feature( "DepthOfField" )][Range( 0, 100 )] public float DepthOfFieldBlurSize { get; set; } = 0.0f;
[Property, Feature( "DepthOfField" )] public bool DepthOfFieldFrontBlur { get; set; } = false;
[Property, Feature( "DepthOfField" )] public bool DepthOfFieldBackBlur { get; set; } = false;
//
[Property, FeatureEnabled( "ChromaticAberration", Icon = "🏳️🌈" )] public bool ChromaticAberration { get; set; } = false;
[Property, Feature( "ChromaticAberration" )] public float ChromaticAberrationIntensity { get; set; } = 0.1f;
[Property, Feature( "ChromaticAberration" )] public Vector3 ChromaticAberrationOffset { get; set; } = new Vector3( 4.0f, 6.0f, 0.0f );
//
//
[Property, FeatureEnabled( "Animation", Icon = "🏃" )] public bool Animation { get; set; } = true;
[Property, Feature( "Animation" )][Range( 0, 20 )] public int FacePose { get; set; } = 0;
[Property, Feature( "Animation" )][Range( 0, 20 )] public bool MenuIdle { get; set; } = false;
[Property, Feature( "Animation" )][Range( -250, 250 )] public Vector3 Move { get; set; } = 0;
//
//
[Property, FeatureEnabled( "IK", Icon = "🕺" )] public bool IK { get; set; } = true;
[Property, Feature( "IK" )] public Poses IKPose { get; set; } = Poses.None;
[Property, Feature( "IK" )] public Vector3 LeftHandPosition { get; set; } = new Vector3( 0.0f, 0.0f, 0.0f );
[Property, Feature( "IK" )] public Rotation LeftHandRotation { get; set; } = Rotation.Identity;
[Property, Feature( "IK" )] public Vector3 RightHandPosition { get; set; } = new Vector3( 0.0f, 0.0f, 0.0f );
[Property, Feature( "IK" )] public Rotation RightHandRotation { get; set; } = Rotation.Identity;
[Property, Feature( "IK" )] public Vector3 LeftFootPosition { get; set; } = new Vector3( 0.0f, 0.0f, 0.0f );
[Property, Feature( "IK" )] public Rotation LeftFootRotation { get; set; } = Rotation.Identity;
[Property, Feature( "IK" )] public Vector3 RightFootPosition { get; set; } = new Vector3( 0.0f, 0.0f, 0.0f );
[Property, Feature( "IK" )] public Rotation RightFootRotation { get; set; } = Rotation.Identity;
[Property, Feature( "IK" )] public Rotation HeadLook { get; set; } = Rotation.Identity;
[Property, Feature( "IK" )] public Rotation EyeLook { get; set; } = Rotation.Identity;
[Property, Feature( "IK" )] public Rotation BodyLook { get; set; } = Rotation.Identity;
//
[Property, FeatureEnabled( "AnimatedViewModel", Icon = "🫸" )] public bool AnimatedViewModel { get; set; } = false;
[Property, Feature( "AnimatedViewModel" )] public Vector3 AnimatedViewModelOffset { get; set; } = new Vector3( 15.0f, -5.0f, -8.0f );
[Property, Feature( "AnimatedViewModel" )] public Rotation AnimatedViewModelRotation { get; set; } = new Rotation( 1.0f, 0.0f, 0.0f, 0.0f );
//
//
[Property, FeatureEnabled( "StaticViewModel", Icon = "🤳🏼" )] public bool StaticViewModel { get; set; } = false;
[Property, Feature( "StaticViewModel" )] public Vector3 StaticiewModelOffset { get; set; } = new Vector3( 15.0f, -5.0f, -8.0f );
[Property, Feature( "StaticViewModel" )] public Rotation StaticViewModelRotation { get; set; } = new Rotation( 1.0f, 0.0f, 0.0f, 0.0f );
//
/*
[Property, ToggleGroup( "PlayerController", Label = "Player Controller" )] public bool PlayerController { get; set; } = false;
[Property, ToggleGroup( "PlayerController", Label = "Maya Camera Follow" )] public bool MayaFollowPlayer { get; set; } = true;
[Property, ToggleGroup( "PlayerController", Label = "Z Offset" )][Range( 0, 72 )] public float Zoffset { get; set; } = 48;
*/
//
public bool PlayerController { get; set; } = false;
public bool MayaFollowPlayer { get; set; } = false;
public float Zoffset { get; set; } = 48;
//
//
[Property, FeatureEnabled( "Don't worry about these", Icon = "🚫" )] public bool DontWorry { get; set; } = false;
[Feature( "Don't worry about these" )]
[Property] GameObject CameraObject { get; set; }
[Feature( "Don't worry about these" )]
[Property] GameObject CameraOrbit { get; set; }
[Feature( "Don't worry about these" )]
[Property] GameObject CharacterObject { get; set; }
[Feature( "Don't worry about these" )]
[Property] GameObject LightingRig { get; set; }
[Feature( "Don't worry about these" )]
[Property] public GameObject ViewModelObject { get; set; }
[Feature( "Don't worry about these" )]
[Property] GameObject StaticViewModelObject { get; set; }
[Feature( "Don't worry about these" )]
[Property] GameObject PlayerControllerObject { get; set; }
[Feature( "Don't worry about these" )]
[Property] IkMover LeftHand { get; set; }
[Feature( "Don't worry about these" )]
[Property] IkMover RightHand { get; set; }
[Feature( "Don't worry about these" )]
[Property] IkMover LeftFoot { get; set; }
[Feature( "Don't worry about these" )]
[Property] IkMover RightFoot { get; set; }
[Feature( "Don't worry about these" )]
[Property]
public MVCitizenAnimation Animator { get; set; }
[Feature( "Don't worry about these" )]
[Property]
public ModelRenderer WorldFloor { get; set; }
[Feature( "Don't worry about these" )]
[Property]
public ModelRenderer WorldCeiling { get; set; }
[Feature( "Don't worry about these" )]
[Property]
public GradientFog WorldFog { get; set; }
[Feature( "Don't worry about these" )]
[Property]
public ColorGrading Grading { get; set; }
[Feature( "Don't worry about these" )]
[Property]
public GameObject WorldObject { get; set; }
//
private float MayaSpeed { get; set; } = 100.0f;
private Vector2 cameraAngles;
Vector3 wishDir = default;
public Angles EyeAngles;
public float ZOffset;
public float FovScale = 50.0f;
public float CharacterRotation = 180.0f;
private bool isInFlyMode = false;
public float flySpeed = 50.0f;
private float targetCameraDistance;
private float targetZOffset;
private float targetFovScale;
private float targetCharacterRotation;
private Bloom bloomCompo;
private FilmGrain flimgrainCompo;
private Vignette vigneCompo;
private Sharpen sharpenComp;
private DepthOfField dofCompo;
private ChromaticAberration chromCompo;
public float EyeHeight { get; set; } = 64.0f;
public Vector3 WishVelocity { get; private set; }
public float JumpForce = 1200f; // The force of the jump
public bool isGrounded = false;
private Vector3 gravity { get; set; } = new Vector3( 0, 0, 800 );
public ClothingCamera()
{
targetCameraDistance = CameraDistance;
targetZOffset = ZOffset;
targetFovScale = FovScale;
targetCharacterRotation = CharacterRotation;
}
protected override void OnStart()
{
base.OnStart();
orbitObject = CharacterObject.WorldPosition;
ViewModelObject.Parent = CameraObject;
StaticViewModelObject.Parent = CameraObject;
CameraObject.WorldPosition = CharacterObject.WorldPosition + CameraObject.WorldRotation.Backward * orbitDistance;
skybox = Scene.Components.Get<SkyBox2D>(FindMode.EverythingInSelfAndDescendants);
}
public void FakePlayerMovement()
{
// Clamp pitch to prevent over-rotation (optional but useful to prevent full flips)
EyeAngles.pitch = Math.Clamp( EyeAngles.pitch, -89.9f, 89.9f );
CameraObject.WorldRotation = EyeAngles.ToRotation();
var rot = EyeAngles.ToRotation();
WishVelocity = 0;
if ( Input.Down( "Forward" ) ) WishVelocity += rot.Forward;
if ( Input.Down( "Backward" ) ) WishVelocity += rot.Backward;
if ( Input.Down( "Left" ) ) WishVelocity += rot.Left;
if ( Input.Down( "Right" ) ) WishVelocity += rot.Right;
WishVelocity = WishVelocity.WithZ( 0 );
if ( !WishVelocity.IsNearZeroLength ) WishVelocity = WishVelocity.Normal;
if ( Input.Down( "Run" ) ) WishVelocity *= 320.0f;
else WishVelocity *= 70.0f;
// Jump logic
if ( Input.Down( "Jump" ) && isGrounded )
{
//Log.Info( "Jump" );
float flGroundFactor = 1.0f;
float flMul = 268.3281572999747f * 10.2f;
Punch( Vector3.Up * flMul * flGroundFactor );
var anim = ViewModelObject.Children[0].Components.Get<SkinnedModelRenderer>();
}
}
public void Punch( in Vector3 amount )
{
WishVelocity += amount;
}
public void FakeFPSPhys()
{
// Apply gravity if the player is in the air
if ( !isGrounded )
{
// Apply gravity to vertical velocity
WishVelocity -= gravity * Time.Delta * 5.5f;
// Check if the player has reached the ground
if ( CameraObject.WorldPosition.z <= EyeHeight )
{
// Snap back to ground level and reset jump state
CameraObject.WorldPosition = CameraObject.WorldPosition.WithZ( 0 + EyeHeight );
//WishVelocity = WishVelocity.WithZ(0); // Reset vertical velocity
}
}
// Apply the calculated WishVelocity to move the camera
CameraObject.WorldPosition = CameraObject.WorldPosition + WishVelocity * RealTime.Delta;
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
if ( Mode == CameraMode.FPS )
{
FakeFPSPhys();
FakePlayerMovement();
return;
}
}
public void SetIK()
{
if ( IKPose == Poses.None )
{
LeftHand.Offset = LeftHandPosition;
RightHand.Offset = RightHandPosition;
LeftFoot.Offset = LeftFootPosition;
RightFoot.Offset = RightFootPosition;
LeftHand.RotationOffset = LeftHandRotation;
RightHand.RotationOffset = RightHandRotation;
LeftFoot.RotationOffset = LeftFootRotation;
RightFoot.RotationOffset = RightFootRotation;
}
else if ( IKPose == Poses.TPose )
{
LeftHand.Offset = new Vector3( 0, -32, 50 );
RightHand.Offset = new Vector3( 0, 32, 50 );
LeftFoot.Offset = new Vector3( 0, -4, 4 );
RightFoot.Offset = new Vector3( 0, 4, 4 );
LeftHand.RotationOffset = new Rotation( 0.70f, -0.70f, 0.0f, -0.0f );
RightHand.RotationOffset = new Rotation( 0, 0, 0.70f, 0.70f );
LeftFoot.RotationOffset = new Rotation( -0.2705985f, 0.6532815f, 0.6532814f, 0.2705978f );
RightFoot.RotationOffset = new Rotation( -0.2705985f, 0.6532815f, 0.6532814f, 0.2705978f );
}
else if ( IKPose == Poses.RaisedHands )
{
LeftHand.Offset = new Vector3( 0, -32, 150 );
RightHand.Offset = new Vector3( 0, 23, 150 );
LeftFoot.Offset = new Vector3( 0, -4, 4 );
RightFoot.Offset = new Vector3( 0, 4, 4 );
LeftHand.RotationOffset = new Rotation( 0.6418805f, -0.3497548f, 0.6190226f, 0.2871793f );
RightHand.RotationOffset = new Rotation( -0.3726256f, 0.6093453f, -0.301973f, -0.6313959f );
LeftFoot.RotationOffset = new Rotation( -0.2705985f, 0.653281f, 0.653281f, 0.2705978f );
RightFoot.RotationOffset = new Rotation( -0.2705985f, 0.6532815f, 0.653281f, 0.2705978f );
}
var animmod = CharacterObject.Components.Get<SkinnedModelRenderer>();
animmod.Set( "aim_head", HeadLook.Forward * 10 );
animmod.Set( "aim_eyes", EyeLook.Forward * 50 );
animmod.Set( "aim_body", BodyLook.Forward * 10 );
}
public void WorldStuff()
{
WorldCeiling.Tint = WorldColor;
WorldFloor.Tint = WorldColor;
if ( skybox.IsValid() )
{
skybox.SkyMaterial = SkyboxMaterial;
}
WorldFog.Color = FogColor;
WorldFog.StartDistance = FogStartDistance;
WorldFog.EndDistance = FogEndDistance;
WorldFog.FalloffExponent = FogFalloffExponent;
WorldFog.Height = FogHeight;
WorldFog.VerticalFalloffExponent = FogVerticleFalloffExponent;
}
protected override void OnUpdate()
{
//Update camera
UpdateCamera();
RotateLightingRig();
WorldStuff();
// Eye input
EyeAngles.pitch += Input.MouseDelta.y * 0.1f;
EyeAngles.yaw -= Input.MouseDelta.x * 0.1f;
EyeAngles.roll = 0;
if(WorldObject != null)
{
WorldObject.Enabled = !HideWorld;
}
if ( Animator.IsValid() )
{
if ( IK )
{
SetIK();
Animator.IkLeftFoot = LeftFoot.GameObject.Children[0];
Animator.IkRightFoot = RightFoot.GameObject.Children[0];
Animator.IkLeftHand = LeftHand.GameObject.Children[0];
Animator.IkRightHand = RightHand.GameObject.Children[0];
}
else
{
Animator.IkLeftFoot = null;
Animator.IkRightFoot = null;
Animator.IkLeftHand = null;
Animator.IkRightHand = null;
}
if ( Animation )
{
Animator.FacesOverride = FacePose;
Animator.WithVelocity( Move );
Animator.SpecialMenu( MenuIdle );
}
}
if ( PlayerController )
{
PlayerControllerObject.Enabled = true;
}
else
{
PlayerControllerObject.Enabled = false;
}
if ( StaticViewModel )
{
AnimatedViewModel = false;
StaticViewModelObject.Enabled = true;
StaticViewModelObject.Transform.LocalPosition = StaticiewModelOffset;
StaticViewModelObject.Transform.LocalRotation = StaticViewModelRotation;
}
else
{
StaticViewModelObject.Enabled = false;
}
if ( AnimatedViewModel )
{
StaticViewModel = false;
ViewModelObject.Enabled = true;
ViewModelObject.Children[0].Enabled = true;
ViewModelObject.Transform.LocalPosition = AnimatedViewModelOffset;
ViewModelObject.Transform.LocalRotation = AnimatedViewModelRotation;
}
else
{
ViewModelObject.Enabled = false;
ViewModelObject.Children[0].Enabled = false;
}
if ( Input.Pressed( "View" ) )
{
LazySusan = !LazySusan;
}
if ( LazySusan )
{
CharacterRotation += LazySuzzy;
}
var tr = Scene.PhysicsWorld.Trace.Ray( CameraObject.WorldPosition, CameraObject.WorldPosition + Vector3.Down * 100 )
.Run();
if ( tr.Distance <= EyeHeight )
{
isGrounded = true;
}
else
{
isGrounded = false;
}
CharacterObject.WorldRotation = Rotation.From( 0, CharacterRotation, 0 );
if ( Input.Pressed( "slot1" ) )
{
Mode = CameraMode.Orbit;
}
if ( Input.Pressed( "slot2" ) )
{
Mode = CameraMode.Maya;
}
if ( Input.Pressed( "slot3" ) )
{
Mode = CameraMode.FreeCam;
}
if ( PlayerController )
{
if ( Mode == CameraMode.ThirdPerson )
{
CameraObject.Enabled = false;
var tps = PlayerControllerObject.Components.Get<CameraComponent>(FindMode.EverythingInSelf );
tps.GameObject.Enabled = true;
}
else
{
var tps = PlayerControllerObject.Components.Get<CameraComponent>( FindMode.EverythingInSelf );
tps.GameObject.Enabled = false;
CameraObject.Enabled = true;
}
}
if ( Mode == CameraMode.FPS )
{
return;
}
if ( Mode == CameraMode.Orbit )
{
OrbitCamera();
return;
}
if ( Mode == CameraMode.Maya )
{
MayaCamera();
return;
}
if ( Mode == CameraMode.FreeCam )
{
HandleFlyCameraMovement();
return;
}
}
private float zoffet = 0;
private void MayaCamera()
{
if ( !LockCamera )
{
// Simulate how the Maya camera works
var camera = CameraObject.Components.Get<CameraComponent>( FindMode.EverythingInSelf );
if ( camera is not null )
{
float x = Input.MouseDelta.x;
float y = Input.MouseDelta.y;
// Check if both "attack2" and "walk" are held
if ( Input.Down( "attack1" ) && Input.Down( "walk" ) )
{
// Rotate the camera around the orbitObject
cameraAngles += new Vector2( y * orbitSpeed, x * orbitSpeed );
// Limit pitch angle to prevent camera flipping
cameraAngles.x = Math.Clamp( cameraAngles.x, -89.9f, 89.9f );
// Convert cameraAngles to a rotation
CameraObject.WorldRotation = Rotation.From( cameraAngles.x, -cameraAngles.y, 0 );
// Calculate the new camera position based on the orbit distance
var newCameraPosition = orbitObject + CameraObject.WorldRotation.Backward * orbitDistance;
// Set the camera position
CameraObject.WorldPosition = newCameraPosition;
}
else if ( Input.Down( "attack2" ) && Input.Down( "walk" ) )
{
// Calculate zoom speed for zooming in/out
var currentZoomSpeed = Math.Clamp( zoomSpeed * (orbitDistance / 50), 0.1f, 2.0f );
// Zoom the camera in/out
CameraObject.WorldPosition += CameraObject.WorldRotation.Backward * (y * -1f * currentZoomSpeed);
orbitDistance = CameraObject.WorldPosition.Distance( orbitObject );
}
else if ( Input.Down( "attack3" ) && Input.Down( "walk" ) )
{
var translateX = CameraObject.WorldRotation.Right * (-x * panSpeed * RealTime.Delta);
var translateY = CameraObject.WorldRotation.Up * (y * panSpeed * RealTime.Delta);
// Move the camera in the local coordinates
CameraObject.WorldPosition += translateX;
CameraObject.WorldPosition += translateY;
// Move the orbitObject with the same values, along the camera's axes.
orbitObject += translateX;
orbitObject += translateY;
}
else
{
var currentZoomSpeed = Math.Clamp( zoomSpeed * (orbitDistance / 50), 0.1f, 2.0f );
// Zoom the camera in/out
CameraObject.WorldPosition += CameraObject.WorldRotation.Backward * (Input.MouseWheel.y * -1f * currentZoomSpeed);
// Handle regular camera movement if "attack2" or "walk" are not both held
wishDir = Vector3.Zero;
if ( !MayaFollowPlayer )
{
if ( Input.Down( "Forward" ) ) wishDir.x = 1;
else if ( Input.Down( "Backward" ) ) wishDir.x = -1;
if ( Input.Down( "Left" ) ) wishDir.y = 1;
else if ( Input.Down( "Right" ) ) wishDir.y = -1;
wishDir = wishDir.Normal;
MayaSpeed = Input.Down( "run" ) ? MayaFlySpeed : MayaFlySpeed / 2;
if ( wishDir.Length > 0 )
{
CameraObject.WorldPosition += (CameraObject.WorldRotation * wishDir).Normal * MayaSpeed * Time.Delta;
}
}
if ( Input.Pressed( "flashlight" ) )
{
if ( FocusObject is not null )
{
CameraObject.WorldPosition = FocusObject.WorldPosition + FocusObject.WorldRotation.Forward * orbitDistance;
CameraObject.WorldRotation = Rotation.LookAt( FocusObject.WorldPosition - CameraObject.WorldPosition );
}
else
{
CameraObject.WorldPosition = Vector3.Zero + CameraObject.WorldRotation.Forward * orbitDistance;
CameraObject.WorldRotation = Rotation.LookAt( Vector3.Zero - CameraObject.WorldPosition );
}
}
if ( MayaFollowPlayer )
{
orbitObject = PlayerControllerObject.WorldPosition + new Vector3( 0, 0, Zoffset );
// Calculate the new camera position based on the orbit distance
var newCameraPosition = orbitObject + CameraObject.WorldRotation.Backward * orbitDistance;
// Set the camera position
CameraObject.WorldPosition = newCameraPosition;
}
else
{
orbitObject = CameraObject.WorldPosition + CameraObject.WorldRotation.Forward * orbitDistance;
}
}
}
}
if ( Input.Down( "walk" ) )
{
//Gizmo.Draw.Sprite( orbitObject, 1, "materials/gizmo/envmap.png" );
}
}
private void OrbitCamera()
{
if ( !LockCamera )
{
if ( !Input.Down( "Walk" ) && !Input.Down( "Run" ) && !Input.Down( "Duck" ) )
{
targetCameraDistance = Math.Clamp( targetCameraDistance + Input.MouseWheel.y * -5, 50, 500 );
CameraDistance = Lerp( CameraDistance, targetCameraDistance, 0.1f );
}
if ( Input.Down( "Walk" ) )
{
targetZOffset = Math.Clamp( targetZOffset + Input.MouseWheel.y * -2, -100, 100 );
ZOffset = Lerp( ZOffset, targetZOffset, 0.1f );
}
/*
if ( Input.Down( "Run" ) )
{
targetFovScale = Math.Clamp( targetFovScale + Input.MouseWheel * -5, 10, 100 );
FovScale = Lerp( FovScale, targetFovScale, 0.1f );
}
*/
if ( Input.Down( "Duck" ) )
{
targetCharacterRotation = targetCharacterRotation + Input.MouseWheel.y * -5;
CharacterRotation = Lerp( CharacterRotation, targetCharacterRotation, 0.1f );
}
// Update camera position
var camera = CameraObject.Components.Get<CameraComponent>( FindMode.EverythingInSelf );
if ( camera is not null )
{
var camPos = CameraOrbit.WorldPosition - EyeAngles.ToRotation().Forward * CameraDistance;
camPos.z += ZOffset;
camera.WorldPosition = camPos;
camera.WorldRotation = EyeAngles.ToRotation();
}
}
}
private void HandleFlyCameraMovement()
{
var direction = Vector3.Zero;
if ( Input.Down( "Forward" ) )
direction += CameraObject.WorldRotation.Forward;
if ( Input.Down( "Backward" ) )
direction -= CameraObject.WorldRotation.Forward;
if ( Input.Down( "Left" ) )
direction -= CameraObject.WorldRotation.Right;
if ( Input.Down( "Right" ) )
direction += CameraObject.WorldRotation.Right;
if ( Input.Down( "Jump" ) && Mode == CameraMode.FreeCam ) // Assuming "Space" is for moving upwards
direction += Vector3.Up;
if ( Input.Down( "Duck" ) ) // Assuming "LeftShift" is for moving downwards
direction -= Vector3.Up;
flySpeed = Input.Down( "Run" ) ? 150.0f : 50.0f;
// Normalize the direction to ensure consistent speed in diagonal movement
float magnitude = direction.Length;
if ( magnitude > 0 )
{
direction.x /= magnitude;
direction.y /= magnitude;
direction.z /= magnitude;
}
// Update the position based on the direction
CameraObject.WorldPosition += direction * flySpeed * Time.Delta; // Assuming Time.Delta is the time since the last frame
// Adjusting view direction based on mouse movement
EyeAngles.pitch += Input.MouseDelta.y * 0.03f;
EyeAngles.yaw -= Input.MouseDelta.x * 0.03f;
// Clamp pitch to prevent over-rotation (optional but useful to prevent full flips)
EyeAngles.pitch = Math.Clamp( EyeAngles.pitch, -89.9f, 89.9f );
// Convert EyeAngles to a rotation and set to the camera
CameraObject.WorldRotation = EyeAngles.ToRotation();
}
public static float Lerp( float a, float b, float t )
{
return a + t * (b - a);
}
private float lightRigRotation { get; set; }
public void RotateLightingRig()
{
float x = Input.MouseDelta.x;
if ( Input.Down( "run" ) && Input.Down( "attack2" ) )
{
lightRigRotation += x;
LightingRig.WorldRotation = Rotation.From( 0, lightRigRotation, 0 );
}
}
public void UpdateCamera()
{
var cam = CameraObject.Components.Get<CameraComponent>( FindMode.EverythingInSelf );
if ( cam is not null )
{
cam.FieldOfView = Fov;
cam.ZNear = Near;
cam.ZFar = Far;
cam.Orthographic = Ortho;
cam.OrthographicHeight = OrthoSize;
bloomCompo = CameraObject.Components.Get<Bloom>( FindMode.EverythingInSelf );
bloomCompo.Enabled = Bloom;
bloomCompo.Mode = BloomMode;
bloomCompo.Strength = BloomStrength;
bloomCompo.Threshold = BloomThreshold;
flimgrainCompo = CameraObject.Components.Get<FilmGrain>( FindMode.EverythingInSelf );
flimgrainCompo.Enabled = FilmGrain;
flimgrainCompo.Intensity = FilmGrainIntensity;
flimgrainCompo.Response = FilmGrainResponse;
vigneCompo = CameraObject.Components.Get<Vignette>( FindMode.EverythingInSelf );
vigneCompo.Enabled = Vignette;
vigneCompo.Intensity = VignetteIntensity;
vigneCompo.Smoothness = VignetteSmoothness;
vigneCompo.Roundness = VignetteRoundness;
vigneCompo.Color = VignetteColor;
vigneCompo.Center = VignetteCenter;
sharpenComp = CameraObject.Components.Get<Sharpen>( FindMode.EverythingInSelf );
sharpenComp.Enabled = Sharpen;
sharpenComp.Scale = SharpenIntensity;
dofCompo = CameraObject.Components.Get<DepthOfField>( FindMode.EverythingInSelf );
dofCompo.Enabled = DepthOfField;
dofCompo.FocalDistance = DepthOfFieldFocusDistance;
dofCompo.BlurSize = DepthOfFieldBlurSize;
dofCompo.FrontBlur = DepthOfFieldFrontBlur;
dofCompo.BackBlur = DepthOfFieldBackBlur;
chromCompo = CameraObject.Components.Get<ChromaticAberration>( FindMode.EverythingInSelf );
chromCompo.Enabled = ChromaticAberration;
chromCompo.Scale = ChromaticAberrationIntensity;
chromCompo.Offset = ChromaticAberrationOffset;
Grading = CameraObject.Components.Get<ColorGrading>( FindMode.EverythingInSelf );
Grading.Enabled = ColorMapping;
Grading.GradingMethod = ColorGrading;
Grading.ColorTempK = Temperature;
Grading.BlendFactor = Blend;
Grading.LookupTexture = LookupTexture;
Grading.ColorSpace = ColorSpace;
}
}
}