reformat code + level load events

This commit is contained in:
2022-05-05 18:52:53 +03:00
parent 8762138fe3
commit fe443b9f50
38 changed files with 6380 additions and 6408 deletions

View File

@@ -1,7 +1,7 @@
{
"ID": "194e05f445ece24ec5448d886e1334df",
"TypeName": "FlaxEngine.SceneAsset",
"EngineBuild": 6331,
"EngineBuild": 6332,
"Data": [
{
"ID": "194e05f445ece24ec5448d886e1334df",
@@ -76,7 +76,7 @@
},
"Control": "FlaxEngine.GUI.Label",
"Data": {
"Text": "eFPS: 121 uTime: 33.4012628\nuFPS: 117 uTime: 0.00833330024033785\nrFPS: 120 rTime: 0\npFPS: 30 pTime: 0",
"Text": "eFPS: 120 uTime: 0.1533353\nuFPS: -2147483648 uTime: 0.00833330024033785\nrFPS: -2147483648 rTime: 0\npFPS: -2147483648 pTime: 0",
"TextColor": {
"R": 1.0,
"G": 1.0,
@@ -123,7 +123,7 @@
},
"Offsets": {
"Left": 0.0,
"Right": 231.0,
"Right": 284.0,
"Top": -97.0,
"Bottom": 64.0
},

View File

@@ -14,32 +14,16 @@ namespace Game
None = 0,
/// Avoid replacing the existing playing audio source in this channel.
ContinuePlayingExistingSource = 1,
ContinuePlayingExistingSource = 1
}
public static class AudioManager
{
private class AudioInfo
{
public AudioClip[] AudioClips;
public int lastAudioPlayed;
}
private static readonly Random random = new Random();
private class ActorAudioChannels
{
public Dictionary<int, AudioSource> channelSources;
private static readonly Dictionary<string, AudioInfo> cachedAudioInfos = new Dictionary<string, AudioInfo>();
public ActorAudioChannels()
{
channelSources = new Dictionary<int, AudioSource>();
}
}
private static Random random = new Random();
private static Dictionary<string, AudioInfo> cachedAudioInfos = new Dictionary<string, AudioInfo>();
private static Dictionary<Actor, ActorAudioChannels> actorAudioChannels =
private static readonly Dictionary<Actor, ActorAudioChannels> actorAudioChannels =
new Dictionary<Actor, ActorAudioChannels>();
public static void PlaySound(string soundName, Actor actor, Vector3 position, float volume = 1f)
@@ -57,12 +41,14 @@ namespace Game
PlaySound(soundName, actor, channel, AudioFlags.None, position, volume, Vector2.One);
}
public static void PlaySound(string soundName, Actor actor, int channel, AudioFlags flags, Vector3 position, float volume = 1f)
public static void PlaySound(string soundName, Actor actor, int channel, AudioFlags flags, Vector3 position,
float volume = 1f)
{
PlaySound(soundName, actor, channel, flags, position, volume, Vector2.One);
}
public static void PlaySound(string soundName, Actor actor, int channel, AudioFlags flags, Vector3 position, float volume, Vector2 pitchRange)
public static void PlaySound(string soundName, Actor actor, int channel, AudioFlags flags, Vector3 position,
float volume, Vector2 pitchRange)
{
AudioInfo audio = GetSound(soundName);
if (audio.AudioClips.Length == 0)
@@ -109,15 +95,17 @@ namespace Game
audio.lastAudioPlayed = randomIndex;
}
else
{
audioClip = audio.AudioClips[0];
}
float pitch;
if (pitchRange[0] < pitchRange[1]) // Randomized pitch
pitch = (float)(pitchRange[0] + (random.NextDouble() * (pitchRange[1] - pitchRange[0])));
pitch = (float)(pitchRange[0] + random.NextDouble() * (pitchRange[1] - pitchRange[0]));
else
pitch = pitchRange[0];
var audioSource = new AudioSource();
AudioSource audioSource = new AudioSource();
audioSource.Clip = audioClip;
audioSource.Position = position;
audioSource.Parent = actor.Parent;
@@ -126,24 +114,23 @@ namespace Game
audioSource.Volume = volume;
if (volume != 1f)
audioSource.Name += ", vol: " + volume.ToString();
audioSource.Name += ", vol: " + volume;
if (pitch != 1f)
audioSource.Name += ", pitch: " + pitch.ToString();
audioSource.Name += ", pitch: " + pitch;
audioSource.Play();
Object.Destroy(audioSource, audioClip.Length);
if (channel > 0)
{
actorChannels.channelSources[channel] = audioSource;
}
}
public static async void PlaySoundDelayed(Vector2 delayRange, string soundName, Actor actor, int channel, Vector3 position, float volume = 1f)
public static async void PlaySoundDelayed(Vector2 delayRange, string soundName, Actor actor, int channel,
Vector3 position, float volume = 1f)
{
float randomDelay;
if (delayRange[0] < delayRange[1])
randomDelay = (float)(delayRange[0] + (random.NextDouble() * (delayRange[1] - delayRange[0])));
randomDelay = (float)(delayRange[0] + random.NextDouble() * (delayRange[1] - delayRange[0]));
else
randomDelay = delayRange[0];
@@ -155,11 +142,12 @@ namespace Game
PlaySound(soundName, actor, channel, AudioFlags.None, position, volume, Vector2.One);
}
public static async void PlaySoundDelayed(Vector2 delayRange, string soundName, Actor actor, int channel, Vector3 position, float volume, Vector2 pitchRange)
public static async void PlaySoundDelayed(Vector2 delayRange, string soundName, Actor actor, int channel,
Vector3 position, float volume, Vector2 pitchRange)
{
float randomDelay;
if (delayRange[0] < delayRange[1])
randomDelay = (float)(delayRange[0] + (random.NextDouble() * (delayRange[1] - delayRange[0])));
randomDelay = (float)(delayRange[0] + random.NextDouble() * (delayRange[1] - delayRange[0]));
else
randomDelay = delayRange[0];
@@ -171,11 +159,12 @@ namespace Game
PlaySound(soundName, actor, channel, AudioFlags.None, position, volume, pitchRange);
}
public static async void PlaySoundDelayed(Vector2 delayRange, string soundName, Actor actor, int channel, AudioFlags flags, Vector3 position, float volume, Vector2 pitchRange)
public static async void PlaySoundDelayed(Vector2 delayRange, string soundName, Actor actor, int channel,
AudioFlags flags, Vector3 position, float volume, Vector2 pitchRange)
{
float randomDelay;
if (delayRange[0] < delayRange[1])
randomDelay = (float)(delayRange[0] + (random.NextDouble() * (delayRange[1] - delayRange[0])));
randomDelay = (float)(delayRange[0] + random.NextDouble() * (delayRange[1] - delayRange[0]));
else
randomDelay = delayRange[0];
@@ -219,9 +208,7 @@ namespace Game
if (existingAudioSource && existingAudioSource != null &&
existingAudioSource.State == AudioSource.States.Playing)
{
return true;
}
return false;
}
@@ -233,19 +220,22 @@ namespace Game
AudioInfo audio = new AudioInfo();
var workDir = Directory.GetCurrentDirectory();
var audioBasePath = Path.Combine(workDir, "Content", "Audio");
string workDir = Directory.GetCurrentDirectory();
string audioBasePath = Path.Combine(workDir, "Content", "Audio");
AudioClip audioClip = Content.Load<AudioClip>(Path.Combine(audioBasePath, soundName + ".flax"));
if (audioClip != null)
audio.AudioClips = new AudioClip[] { audioClip };
{
audio.AudioClips = new[] { audioClip };
}
else
{
// Check if this audio has multiple variations
List<AudioClip> audioClips = new List<AudioClip>();
for (int i = 1; i<50; i++)
var audioClips = new List<AudioClip>();
for (int i = 1; i < 50; i++)
{
// TODO: make this more efficient, maybe get a list of assets and filter by name?
AudioClip audioClipVariation = Content.Load<AudioClip>(Path.Combine(audioBasePath, soundName + "_var" + i + ".flax"));
AudioClip audioClipVariation =
Content.Load<AudioClip>(Path.Combine(audioBasePath, soundName + "_var" + i + ".flax"));
if (audioClipVariation == null)
break;
@@ -263,5 +253,21 @@ namespace Game
cachedAudioInfos.Add(soundName, audio);
return audio;
}
private class AudioInfo
{
public AudioClip[] AudioClips;
public int lastAudioPlayed;
}
private class ActorAudioChannels
{
public readonly Dictionary<int, AudioSource> channelSources;
public ActorAudioChannels()
{
channelSources = new Dictionary<int, AudioSource>();
}
}
}
}

View File

@@ -1,124 +1,120 @@
using FlaxEngine;
using Cabrito;
using System.Diagnostics;
using System.IO;
using Cabrito;
using FlaxEngine;
namespace Game
{
public class CameraMovement : Script
{
[Limit(0, 9000), Tooltip("Camera speed")]
public float MoveSpeed { get; set; } = 400;
public class CameraMovement : Script
{
private readonly InputEvent onExit = new InputEvent("Exit");
private float viewPitch;
private float viewYaw;
private float viewRoll;
private float viewPitch;
private float viewRoll;
private float viewYaw;
private InputEvent onExit = new InputEvent("Exit");
[Limit(0, 9000)]
[Tooltip("Camera speed")]
public float MoveSpeed { get; set; } = 400;
public override void OnAwake()
{
base.OnAwake();
public override void OnAwake()
{
base.OnAwake();
onExit.Triggered += () =>
{
if (Console.IsSafeToQuit)
Engine.RequestExit();
};
}
onExit.Triggered += () =>
{
if (Console.IsSafeToQuit)
Engine.RequestExit();
};
}
public override void OnDestroy()
{
base.OnDestroy();
public override void OnDestroy()
{
base.OnDestroy();
onExit.Dispose();
}
onExit.Dispose();
}
public override void OnStart()
{
var initialEulerAngles = Actor.Orientation.EulerAngles;
viewPitch = initialEulerAngles.X;
viewYaw = initialEulerAngles.Y;
viewRoll = initialEulerAngles.Z;
}
public override void OnStart()
{
Vector3 initialEulerAngles = Actor.Orientation.EulerAngles;
viewPitch = initialEulerAngles.X;
viewYaw = initialEulerAngles.Y;
viewRoll = initialEulerAngles.Z;
}
public override void OnUpdate()
{
var camTrans = Actor.Transform;
var rootActor = Actor.GetChild(0);
var camera = rootActor.GetChild<Camera>();
public override void OnUpdate()
{
Transform camTrans = Actor.Transform;
Actor rootActor = Actor.GetChild(0);
Camera camera = rootActor.GetChild<Camera>();
float xAxis = InputManager.GetAxisRaw("Mouse X");
float yAxis = InputManager.GetAxisRaw("Mouse Y");
if (xAxis != 0.0f || yAxis != 0.0f)
{
viewPitch += yAxis;
viewYaw += xAxis;
float xAxis = InputManager.GetAxisRaw("Mouse X");
float yAxis = InputManager.GetAxisRaw("Mouse Y");
if (xAxis != 0.0f || yAxis != 0.0f)
{
viewPitch += yAxis;
viewYaw += xAxis;
viewPitch = Mathf.Clamp(viewPitch, -90.0f, 90.0f);
viewPitch = Mathf.Clamp(viewPitch, -90.0f, 90.0f);
// root orientation must be set first
rootActor.Orientation = Quaternion.Euler(0, viewYaw, 0);
camera.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll);
}
// root orientation must be set first
rootActor.Orientation = Quaternion.Euler(0, viewYaw, 0);
camera.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll);
}
float inputH = InputManager.GetAxis("Horizontal");
float inputV = InputManager.GetAxis("Vertical");
var move = new Vector3(inputH, 0.0f, inputV);
float inputH = InputManager.GetAxis("Horizontal");
float inputV = InputManager.GetAxis("Vertical");
Vector3 move = new Vector3(inputH, 0.0f, inputV);
if (!move.IsZero)
{
move.Normalize();
move = camera.Transform.TransformDirection(move) * MoveSpeed;
if (!move.IsZero)
{
move.Normalize();
move = camera.Transform.TransformDirection(move) * MoveSpeed;
{
Vector3 delta = move * Time.UnscaledDeltaTime;
float movementLeft = delta.Length;
{
Vector3 delta = move * Time.UnscaledDeltaTime;
float movementLeft = delta.Length;
// TODO: check multiple times in case we get stuck in walls
// TODO: check multiple times in case we get stuck in walls
float sphereRadius = 10.0f; // TODO: use collider radius
RayCastHit[] hitInfos;
float moveDist = delta.Length;
Physics.SphereCastAll(Actor.Transform.Translation, sphereRadius, move.Normalized, out hitInfos,
moveDist);
float sphereRadius = 10.0f; // TODO: use collider radius
RayCastHit[] hitInfos;
float moveDist = delta.Length;
Physics.SphereCastAll(Actor.Transform.Translation, sphereRadius, move.Normalized, out hitInfos,
moveDist);
//bool nohit = true;
float hitDistance = moveDist;
Vector3 hitNormal = move.Normalized;
foreach (RayCastHit hitInfo in hitInfos)
{
if (hitInfo.Collider.Parent == Parent)
continue;
//bool nohit = true;
float hitDistance = moveDist;
Vector3 hitNormal = move.Normalized;
foreach (RayCastHit hitInfo in hitInfos)
{
if (hitInfo.Collider.Parent == Parent)
continue;
if (hitInfo.Distance < hitDistance)
{
hitDistance = hitInfo.Distance;
hitNormal = hitInfo.Normal;
}
//nohit = false;
//break;
}
if (hitInfo.Distance < hitDistance)
{
hitDistance = hitInfo.Distance;
hitNormal = hitInfo.Normal;
}
//nohit = false;
//break;
}
if (hitDistance != moveDist)
{
//camTrans.Translation = Vector3.Lerp(Actor.Transform.Translation, camTrans.Translation, hitDistance);
if (hitDistance != moveDist)
//camTrans.Translation = Vector3.Lerp(Actor.Transform.Translation, camTrans.Translation, hitDistance);
//projected = normal * dot(direction, normal);
//direction = direction - projected
//projected = normal * dot(direction, normal);
//direction = direction - projected
//camTrans.Translation += hitNormal * (moveDist - hitDistance); // correct?
//camTrans.Translation = hitNormal * (move * hitNormal); // correct?
//camTrans.Translation = Actor.Transform.Translation;
delta += -Vector3.Dot(delta, hitNormal) * hitNormal; // correct?
//camTrans.Translation += hitNormal * (moveDist - hitDistance); // correct?
//camTrans.Translation = hitNormal * (move * hitNormal); // correct?
//camTrans.Translation = Actor.Transform.Translation;
delta += -Vector3.Dot(delta, hitNormal) * hitNormal; // correct?
}
camTrans.Translation += delta;
}
}
camTrans.Translation += delta;
}
}
Actor.Transform = camTrans;
}
}
Actor.Transform = camTrans;
}
}
}

View File

@@ -1,30 +1,34 @@
using System;
using System.Runtime;
using Cabrito;
using FlaxEditor.Content.Settings;
using FlaxEngine;
using Console = Cabrito.Console;
namespace Game
{
/// <summary>
/// CameraRender Script.
/// CameraRender Script.
/// </summary>
[ExecuteInEditMode]
public class CameraRender : PostProcessEffect
{
public Camera camera;
public Material material;
private GPUTexture texture;
private GPUTexture texture2;
private bool lastEnabled;
public Material material;
private MaterialInstance materialInstance;
private SceneRenderTask sceneTask;
private SceneRenderTask sceneTask2;
private GPUTexture texture;
private GPUTexture texture2;
public override PostProcessEffectLocation Location => PostProcessEffectLocation.Default;
public override int Order => 110;
public override bool CanRender => camera.IsActive;
private void CreateTextures(int width, int height)
{
var textureDesc = GPUTextureDescription.New2D(width, height, PixelFormat.R8G8B8A8_UNorm);
GPUTextureDescription textureDesc = GPUTextureDescription.New2D(width, height, PixelFormat.R8G8B8A8_UNorm);
// Prepare texture and SceneRenderTask for viewmodel camera
if (texture == null)
@@ -82,11 +86,8 @@ namespace Game
Destroy(ref texture2);
}
public override PostProcessEffectLocation Location => PostProcessEffectLocation.Default;
public override int Order => 110;
public override bool CanRender => camera.IsActive;
public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input,
GPUTexture output)
{
if (texture == null || texture2 == null)
return;
@@ -94,13 +95,12 @@ namespace Game
Renderer.DrawPostFxMaterial(context, ref renderContext, materialInstance, output, input.View());
}
private bool lastEnabled;
public override void OnUpdate()
{
#if FLAX_EDITOR
if (Input.GetKeyDown(KeyboardKeys.F7))
{
var physicsSettings = GameSettings.Load<PhysicsSettings>();
PhysicsSettings physicsSettings = GameSettings.Load<PhysicsSettings>();
physicsSettings.EnableSubstepping = !physicsSettings.EnableSubstepping;
GameSettings.Save(physicsSettings);
//GameSettings.Apply();
@@ -130,4 +130,4 @@ namespace Game
//OnAwake();
}
}
}
}

View File

@@ -1,25 +1,19 @@
using System;
using System.Runtime;
using FlaxEditor.Content.Settings;
using FlaxEngine;
using Console = Cabrito.Console;
using FlaxEngine;
namespace Game
{
public class CameraSpring : Script
{
private Vector3 targetOffset;
private bool lastGround;
private Vector3 lastPosition;
public float speed = 240f;
public float percY;
private Actor playerActor;
private Actor viewModelHolder;
private PlayerMovement playerMovement;
private bool lastGround;
public float speed = 240f;
private Vector3 targetOffset;
private Actor viewModelHolder;
public override void OnStart()
{
@@ -62,7 +56,9 @@ namespace Game
}
}
else
{
UpdatePosition(position);
}
lastPosition = position;
lastGround = playerMovement.onGround;

View File

@@ -1,16 +1,17 @@
using System;
using System.Collections.Generic;
using FlaxEngine;
using Console = Cabrito.Console;
namespace Game
{
public class WeaponSway : Script
{
public float swaySpeed = 3000f;
private Actor cameraHolder;
private Actor rootActor;
private Actor cameraHolder;
public float swaySpeed = 3000f;
private float timeRemainder;
public override void OnStart()
{
rootActor = Actor.Parent.GetChild("RootActor");
@@ -25,7 +26,6 @@ namespace Game
return yawRoll * pitch;
}
private float timeRemainder = 0f;
public override void OnLateUpdate()
{
Quaternion rotation = GetRotation();
@@ -65,7 +65,7 @@ namespace Game
float percZ = Mathf.Abs(deltaZ) / maxAngle;
float minSpeed = swaySpeedScaled * 0.00001f * 0f;
Func<float, float> fun = (f) => Mathf.Pow(f, 1.3f);
Func<float, float> fun = f => Mathf.Pow(f, 1.3f);
angles.X = Mathf.MoveTowardsAngle(angles.X, targetAngles.X,
Math.Max(swaySpeedScaled * fun(percX), minSpeed));
@@ -74,9 +74,10 @@ namespace Game
angles.Z = Mathf.MoveTowardsAngle(angles.Z, targetAngles.Z,
Math.Max(swaySpeedScaled * fun(percZ), minSpeed));
} while (remaining > minTime);
timeRemainder -= remaining;
Actor.LocalOrientation = Quaternion.Euler(angles);
}
}
}
}

View File

@@ -1,49 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cabrito
{
// Holds common miscellaneous Console variables and commands
public static class CommonCommands
{
[ConsoleCommand("")]
public static void NullCommand()
{
}
// Holds common miscellaneous Console variables and commands
public static class CommonCommands
{
[ConsoleVariable("developer")]
public static string Developer
{
get => Console.DebugVerbosity.ToString();
set
{
if (int.TryParse(value, out int intValue) && intValue >= 0)
Console.DebugVerbosity = intValue;
}
}
[ConsoleCommand("echo")]
public static void EchoCommand()
{
Console.Print("nothing");
}
[ConsoleCommand("")]
public static void NullCommand()
{
}
[ConsoleCommand("echo")]
public static void EchoCommand(string[] text)
{
Console.Print(string.Join(" ", text));
}
[ConsoleCommand("echo")]
public static void EchoCommand()
{
Console.Print("nothing");
}
[ConsoleCommand("debugthrow")]
public static void DebugThrowCommand(string[] text)
{
throw new Exception(string.Join(" ", text));
}
[ConsoleCommand("echo")]
public static void EchoCommand(string[] text)
{
Console.Print(string.Join(" ", text));
}
[ConsoleVariable("developer")]
public static string Developer
{
get
{
return Console.DebugVerbosity.ToString();
}
set
{
if (int.TryParse(value, out int intValue) && intValue >= 0)
Console.DebugVerbosity = intValue;
}
}
}
[ConsoleCommand("debugthrow")]
public static void DebugThrowCommand(string[] text)
{
throw new Exception(string.Join(" ", text));
}
}
}

View File

@@ -3,472 +3,507 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using FlaxEngine;
using Debug = System.Diagnostics.Debug;
using FlaxEditor;
namespace Cabrito
{
public class ConsoleLine
{
public string content;
public class ConsoleLine
{
public string content;
internal ConsoleLine(string line)
{
content = line;
}
internal ConsoleLine(string line)
{
content = line;
}
public static implicit operator string(ConsoleLine line) => line.content;
public static explicit operator ConsoleLine(string line) => new ConsoleLine(line);
public static implicit operator string(ConsoleLine line)
{
return line.content;
}
public override string ToString() => content.ToString();
}
public static explicit operator ConsoleLine(string line)
{
return new ConsoleLine(line);
}
public static class Console
{
private static ConsoleInstance instance;
public override string ToString()
{
return content;
}
}
public static void Init()
{
if (instance != null)
return;
public static class Console
{
private static ConsoleInstance instance;
Destroy();
instance = new ConsoleInstance();
instance.InitConsoleSubsystems();
// Returns if Console window open right now.
public static bool IsOpen => instance.IsOpen;
// For debugging only: Returns true when Console was not closed during the same frame.
// Needed when Escape-key both closes the console and exits the game.
public static bool IsSafeToQuit => instance.IsSafeToQuit;
// Called when Console is opened.
public static Action OnOpen
{
get => instance.OnOpen;
set => instance.OnOpen = value;
}
// Called when Console is closed.
public static Action OnClose
{
get => instance.OnClose;
set => instance.OnClose = value;
}
// Called when a line of text was printed in Console.
public static Action<string> OnPrint
{
get => instance.OnPrint;
set => instance.OnPrint = value;
}
public static bool ShowExecutedLines => instance.ShowExecutedLines;
public static int DebugVerbosity
{
get => instance.DebugVerbosity;
set => instance.DebugVerbosity = value;
}
public static string LinePrefix => instance.LinePrefix;
public static IReadOnlyCollection<ConsoleLine> Lines => instance.Lines;
public static void Init()
{
if (instance != null)
return;
Destroy();
instance = new ConsoleInstance();
instance.InitConsoleSubsystems();
#if FLAX_EDITOR
FlaxEditor.ScriptsBuilder.ScriptsReload += Destroy;
FlaxEditor.Editor.Instance.StateMachine.StateChanged += OnEditorStateChanged;
ScriptsBuilder.ScriptsReload += Destroy;
Editor.Instance.StateMachine.StateChanged += OnEditorStateChanged;
#endif
}
}
public static void Destroy()
{
if (instance != null)
{
instance.Dispose();
instance = null;
public static void Destroy()
{
if (instance != null)
{
instance.Dispose();
instance = null;
#if FLAX_EDITOR
FlaxEditor.ScriptsBuilder.ScriptsReload -= Destroy;
FlaxEditor.Editor.Instance.StateMachine.StateChanged -= OnEditorStateChanged;
ScriptsBuilder.ScriptsReload -= Destroy;
Editor.Instance.StateMachine.StateChanged -= OnEditorStateChanged;
#endif
}
}
}
}
#if FLAX_EDITOR
private static void OnEditorStateChanged()
{
if (!FlaxEditor.Editor.Instance.StateMachine.IsPlayMode)
{
// Clear console buffer when leaving play mode
if (instance != null)
Console.Clear();
}
}
private static void OnEditorStateChanged()
{
if (!Editor.Instance.StateMachine.IsPlayMode)
// Clear console buffer when leaving play mode
if (instance != null)
Clear();
}
#endif
// Returns if Console window open right now.
public static bool IsOpen => instance.IsOpen;
// For debugging only: Returns true when Console was not closed during the same frame.
// Needed when Escape-key both closes the console and exits the game.
public static bool IsSafeToQuit => instance.IsSafeToQuit;
// Called when Console is opened.
public static Action OnOpen
{
get { return instance.OnOpen; }
set { instance.OnOpen = value; }
}
// Called when Console is closed.
public static Action OnClose
{
get { return instance.OnClose; }
set { instance.OnClose = value; }
}
// Called when a line of text was printed in Console.
public static Action<string> OnPrint
{
get { return instance.OnPrint; }
set { instance.OnPrint = value; }
}
public static bool ShowExecutedLines => instance.ShowExecutedLines;
public static int DebugVerbosity
{
get => instance.DebugVerbosity;
set => instance.DebugVerbosity = value;
}
public static string LinePrefix => instance.LinePrefix;
public static IReadOnlyCollection<ConsoleLine> Lines => instance.Lines;
public static string GetBufferHistory(int index) => instance.GetBufferHistory(index);
// Echoes text to Console
public static void Print(string text) => instance.Print(text);
// Echoes warning text to Console
public static void PrintWarning(string text) => instance.PrintWarning(text);
// Echoes error text to Console
public static void PrintError(string text) => instance.PrintError(text);
// Echoes developer/debug text to Console
public static void PrintDebug(string text) => instance.PrintDebug(1, false, text);
// Echoes developer/debug text to Console
public static void PrintDebug(int verbosity, string text) => instance.PrintDebug(verbosity, false, text);
// Echoes developer/debug text to Console
public static void PrintDebug(int verbosity, bool noRepeat, string text) => instance.PrintDebug(verbosity, noRepeat, text);
// Opens the Console
public static void Open() => instance.Open();
// Closes the Console
public static void Close() => instance.Close();
// Clears the content of the Console
public static void Clear() => instance.Clear();
public static void Execute(string str, bool bufferInput = false) => instance.Execute(str, bufferInput);
public static string GetVariable(string variableName) => instance.GetVariable(variableName);
}
public class ConsoleInstance : IDisposable
{
public bool IsOpen { get; internal set; } = true;
public bool IsSafeToQuit
{
get { return stopwatch.Elapsed.TotalSeconds > 0.1; }
}
private Stopwatch stopwatch = Stopwatch.StartNew();
public Action OnOpen;
public Action OnClose;
public Action<string> OnPrint;
public bool ShowExecutedLines = true;
public int DebugVerbosity { get; set; } = 1;
public string LinePrefix { get; internal set; } = "]";
//private static List<string> consoleLines = new List<string>();
private List<ConsoleLine> consoleLines = new List<ConsoleLine>();
private Dictionary<string, ConsoleCommand> consoleCommands = new Dictionary<string, ConsoleCommand>();
private Dictionary<string, ConsoleVariable> consoleVariables = new Dictionary<string, ConsoleVariable>();
private List<string> consoleBufferHistory = new List<string>();
internal ConsoleInstance()
{
}
// Initializes the Console system.
internal void InitConsoleSubsystems()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Assembly[] assemblies = currentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
// Skip common assemblies
var assemblyName = assembly.GetName().Name;
if (assemblyName == "System" ||
assemblyName.StartsWith("System.") ||
assemblyName.StartsWith("Mono.") ||
assemblyName == "mscorlib" ||
assemblyName == "Newtonsoft.Json" ||
assemblyName.StartsWith("FlaxEngine.") ||
assemblyName.StartsWith("JetBrains.") ||
assemblyName.StartsWith("Microsoft.") ||
assemblyName.StartsWith("nunit."))
{
continue;
}
foreach (var type in assembly.GetTypes())
{
Dictionary<string, ConsoleCommand> cmdParsed = new Dictionary<string, ConsoleCommand>();
Dictionary<string, List<MethodInfo>> cmdMethods = new Dictionary<string, List<MethodInfo>>();
MethodInfo cmdInitializer = null;
foreach (MethodInfo method in type.GetMethods())
{
if (!method.IsStatic)
continue;
Attribute[] attributes = Attribute.GetCustomAttributes(method);
foreach (Attribute attr in attributes)
{
if (attr is ConsoleCommandAttribute cmdAttribute)
{
//Console.Print("found cmd '" + cmdAttribute.name + "' bound to field '" + method.Name + "'");
// Defer constructing the command until we have parsed all the methods for it in this assembly.
List<MethodInfo> methods;
if (!cmdMethods.TryGetValue(cmdAttribute.name, out methods))
{
methods = new List<MethodInfo>();
cmdMethods.Add(cmdAttribute.name, methods);
}
methods.Add(method);
ConsoleCommand cmd = new ConsoleCommand(cmdAttribute.name, null);
if (!cmdParsed.ContainsKey(cmdAttribute.name))
cmdParsed.Add(cmdAttribute.name, cmd);
foreach (var alias in cmdAttribute.aliases)
{
if (!cmdParsed.ContainsKey(alias))
cmdParsed.Add(alias, cmd);
List<MethodInfo> aliasMethods;
if (!cmdMethods.TryGetValue(alias, out aliasMethods))
{
aliasMethods = new List<MethodInfo>();
cmdMethods.Add(alias, aliasMethods);
}
aliasMethods.Add(method);
}
}
else if (attr is ConsoleSubsystemInitializer)
{
cmdInitializer = method;
}
}
}
foreach (var kv in cmdParsed)
{
var methods = cmdMethods[kv.Key];
var definition = kv.Value;
ConsoleCommand cmd = new ConsoleCommand(definition.name, methods.ToArray());
consoleCommands.Add(kv.Key, cmd);
}
foreach (FieldInfo field in type.GetFields())
{
if (!field.IsStatic)
continue;
Attribute[] attributes = Attribute.GetCustomAttributes(field);
foreach (Attribute attr in attributes)
{
if (attr is ConsoleVariableAttribute cvarAttribute)
{
//Console.Print("found cvar '" + cvarAttribute.name + "' bound to field '" + field.Name + "'");
consoleVariables.Add(cvarAttribute.name,
new ConsoleVariable(cvarAttribute.name, cvarAttribute.flags, field));
foreach (var alias in cvarAttribute.aliases)
consoleVariables.Add(alias,
new ConsoleVariable(cvarAttribute.name,
cvarAttribute.flags | ConsoleFlags.NoSerialize, field));
}
}
}
foreach (PropertyInfo prop in type.GetProperties())
{
MethodInfo getter = prop.GetGetMethod();
MethodInfo setter = prop.GetSetMethod();
if (getter == null || setter == null || !getter.IsStatic || !setter.IsStatic)
continue;
Attribute[] attributes = Attribute.GetCustomAttributes(prop);
foreach (Attribute attr in attributes)
{
if (attr is ConsoleVariableAttribute cvarAttribute)
{
//Console.Print("found cvar '" + cvarAttribute.name + "' bound to field '" + field.Name + "'");
consoleVariables.Add(cvarAttribute.name,
new ConsoleVariable(cvarAttribute.name, cvarAttribute.flags, getter, setter));
foreach (var alias in cvarAttribute.aliases)
consoleVariables.Add(alias,
new ConsoleVariable(cvarAttribute.name,
cvarAttribute.flags | ConsoleFlags.NoSerialize, getter, setter));
}
}
}
if (cmdInitializer != null)
{
Console.PrintDebug(2, "Initializing " + type.Name);
cmdInitializer.Invoke(null, null);
}
}
}
}
public void Dispose()
{
}
public IReadOnlyCollection<ConsoleLine> Lines
{
get => consoleLines.AsReadOnly();
}
public string GetBufferHistory(int index)
{
if (consoleBufferHistory.Count == 0)
return null;
if (index > consoleBufferHistory.Count - 1 || index < 0)
return null;
return consoleBufferHistory[index];
}
// Echoes text to Console
public void Print(string text)
{
debugLastLine = text;
foreach (var line in text.Split(new[] { '\n' }))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
}
// Echoes warning text to Console
public void PrintWarning(string text)
{
foreach (var line in text.Split(new[] { '\n' }))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
}
// Echoes error text to Console
public void PrintError(string text)
{
foreach (var line in text.Split(new[] { '\n' }))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
if (Debugger.IsAttached)
Debugger.Break();
else
throw new Exception(text);
}
// Echoes developer/debug text to Console
private string debugLastLine = "";
public void PrintDebug(int verbosity, bool noRepeat, string text)
{
if (DebugVerbosity < verbosity)
return;
if (noRepeat)
{
if (debugLastLine.Length == text.Length && debugLastLine == text)
return;
}
debugLastLine = text;
foreach (var line in text.Split(new[] { '\n' }))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
}
// Opens the Console
public void Open()
{
if (IsOpen)
return;
IsOpen = true;
OnOpen?.Invoke();
}
// Closes the Console
public void Close()
{
if (!IsOpen)
return;
IsOpen = false;
OnClose?.Invoke();
stopwatch.Restart();
}
// Clears the content of the Console
public void Clear()
{
consoleLines.Clear();
}
public void Execute(string str, bool bufferInput = false)
{
if (bufferInput)
consoleBufferHistory.Insert(0, str);
str = str.Trim();
if (ShowExecutedLines)
Console.Print(LinePrefix + str);
string[] strs = str.Split(' ');
string execute = strs[0];
string executeLower = execute.ToLowerInvariant();
string value = strs.Length > 1 ? str.Substring(execute.Length + 1) : null;
//Console.PrintDebug("Executed '" + execute + "' with params: '" + value + "'");
if (consoleCommands.TryGetValue(executeLower, out ConsoleCommand cmd))
{
string[] values = strs.Skip(1).ToArray();
if (values.Length > 0)
cmd.Invoke(values);
else
cmd.Invoke();
//Console.Print("Command bound to '" + execute + "' is '" + cmd.method.Name + "'");
}
else if (consoleVariables.TryGetValue(executeLower, out ConsoleVariable cvar))
{
if (value != null)
cvar.SetValue(value);
Console.Print("'" + execute + "' is '" + cvar.GetValueString() + "'");
}
else
Console.Print("Unknown command '" + execute + "'");
}
public string GetVariable(string variableName)
{
if (consoleVariables.TryGetValue(variableName, out ConsoleVariable cvar))
{
string value = cvar.GetValueString();
return value;
}
return null;
}
}
public static string GetBufferHistory(int index)
{
return instance.GetBufferHistory(index);
}
// Echoes text to Console
public static void Print(string text)
{
instance.Print(text);
}
// Echoes warning text to Console
public static void PrintWarning(string text)
{
instance.PrintWarning(text);
}
// Echoes error text to Console
public static void PrintError(string text)
{
instance.PrintError(text);
}
// Echoes developer/debug text to Console
public static void PrintDebug(string text)
{
instance.PrintDebug(1, false, text);
}
// Echoes developer/debug text to Console
public static void PrintDebug(int verbosity, string text)
{
instance.PrintDebug(verbosity, false, text);
}
// Echoes developer/debug text to Console
public static void PrintDebug(int verbosity, bool noRepeat, string text)
{
instance.PrintDebug(verbosity, noRepeat, text);
}
// Opens the Console
public static void Open()
{
instance.Open();
}
// Closes the Console
public static void Close()
{
instance.Close();
}
// Clears the content of the Console
public static void Clear()
{
instance.Clear();
}
public static void Execute(string str, bool bufferInput = false)
{
instance.Execute(str, bufferInput);
}
public static string GetVariable(string variableName)
{
return instance.GetVariable(variableName);
}
}
public class ConsoleInstance : IDisposable
{
private readonly List<string> consoleBufferHistory = new List<string>();
private readonly Dictionary<string, ConsoleCommand> consoleCommands = new Dictionary<string, ConsoleCommand>();
//private static List<string> consoleLines = new List<string>();
private readonly List<ConsoleLine> consoleLines = new List<ConsoleLine>();
private readonly Dictionary<string, ConsoleVariable> consoleVariables =
new Dictionary<string, ConsoleVariable>();
private readonly Stopwatch stopwatch = Stopwatch.StartNew();
// Echoes developer/debug text to Console
private string debugLastLine = "";
public Action OnClose;
public Action OnOpen;
public Action<string> OnPrint;
public bool ShowExecutedLines = true;
internal ConsoleInstance()
{
}
public bool IsOpen { get; internal set; } = true;
public bool IsSafeToQuit => stopwatch.Elapsed.TotalSeconds > 0.1;
public int DebugVerbosity { get; set; } = 1;
public string LinePrefix { get; internal set; } = "]";
public IReadOnlyCollection<ConsoleLine> Lines => consoleLines.AsReadOnly();
public void Dispose()
{
}
// Initializes the Console system.
internal void InitConsoleSubsystems()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
var assemblies = currentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
// Skip common assemblies
string assemblyName = assembly.GetName().Name;
if (assemblyName == "System" ||
assemblyName.StartsWith("System.") ||
assemblyName.StartsWith("Mono.") ||
assemblyName == "mscorlib" ||
assemblyName == "Newtonsoft.Json" ||
assemblyName.StartsWith("FlaxEngine.") ||
assemblyName.StartsWith("JetBrains.") ||
assemblyName.StartsWith("Microsoft.") ||
assemblyName.StartsWith("nunit."))
continue;
foreach (Type type in assembly.GetTypes())
{
var cmdParsed = new Dictionary<string, ConsoleCommand>();
var cmdMethods = new Dictionary<string, List<MethodInfo>>();
MethodInfo cmdInitializer = null;
foreach (MethodInfo method in type.GetMethods())
{
if (!method.IsStatic)
continue;
var attributes = Attribute.GetCustomAttributes(method);
foreach (Attribute attr in attributes)
if (attr is ConsoleCommandAttribute cmdAttribute)
{
//Console.Print("found cmd '" + cmdAttribute.name + "' bound to field '" + method.Name + "'");
// Defer constructing the command until we have parsed all the methods for it in this assembly.
List<MethodInfo> methods;
if (!cmdMethods.TryGetValue(cmdAttribute.name, out methods))
{
methods = new List<MethodInfo>();
cmdMethods.Add(cmdAttribute.name, methods);
}
methods.Add(method);
ConsoleCommand cmd = new ConsoleCommand(cmdAttribute.name, null);
if (!cmdParsed.ContainsKey(cmdAttribute.name))
cmdParsed.Add(cmdAttribute.name, cmd);
foreach (string alias in cmdAttribute.aliases)
{
if (!cmdParsed.ContainsKey(alias))
cmdParsed.Add(alias, cmd);
List<MethodInfo> aliasMethods;
if (!cmdMethods.TryGetValue(alias, out aliasMethods))
{
aliasMethods = new List<MethodInfo>();
cmdMethods.Add(alias, aliasMethods);
}
aliasMethods.Add(method);
}
}
else if (attr is ConsoleSubsystemInitializer)
{
cmdInitializer = method;
}
}
foreach (var kv in cmdParsed)
{
var methods = cmdMethods[kv.Key];
ConsoleCommand definition = kv.Value;
ConsoleCommand cmd = new ConsoleCommand(definition.name, methods.ToArray());
consoleCommands.Add(kv.Key, cmd);
}
foreach (FieldInfo field in type.GetFields())
{
if (!field.IsStatic)
continue;
var attributes = Attribute.GetCustomAttributes(field);
foreach (Attribute attr in attributes)
if (attr is ConsoleVariableAttribute cvarAttribute)
{
//Console.Print("found cvar '" + cvarAttribute.name + "' bound to field '" + field.Name + "'");
consoleVariables.Add(cvarAttribute.name,
new ConsoleVariable(cvarAttribute.name, cvarAttribute.flags, field));
foreach (string alias in cvarAttribute.aliases)
consoleVariables.Add(alias,
new ConsoleVariable(cvarAttribute.name,
cvarAttribute.flags | ConsoleFlags.NoSerialize, field));
}
}
foreach (PropertyInfo prop in type.GetProperties())
{
MethodInfo getter = prop.GetGetMethod();
MethodInfo setter = prop.GetSetMethod();
if (getter == null || setter == null || !getter.IsStatic || !setter.IsStatic)
continue;
var attributes = Attribute.GetCustomAttributes(prop);
foreach (Attribute attr in attributes)
if (attr is ConsoleVariableAttribute cvarAttribute)
{
//Console.Print("found cvar '" + cvarAttribute.name + "' bound to field '" + field.Name + "'");
consoleVariables.Add(cvarAttribute.name,
new ConsoleVariable(cvarAttribute.name, cvarAttribute.flags, getter, setter));
foreach (string alias in cvarAttribute.aliases)
consoleVariables.Add(alias,
new ConsoleVariable(cvarAttribute.name,
cvarAttribute.flags | ConsoleFlags.NoSerialize, getter, setter));
}
}
if (cmdInitializer != null)
{
Console.PrintDebug(2, "Initializing " + type.Name);
cmdInitializer.Invoke(null, null);
}
}
}
}
public string GetBufferHistory(int index)
{
if (consoleBufferHistory.Count == 0)
return null;
if (index > consoleBufferHistory.Count - 1 || index < 0)
return null;
return consoleBufferHistory[index];
}
// Echoes text to Console
public void Print(string text)
{
debugLastLine = text;
foreach (string line in text.Split('\n'))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
}
// Echoes warning text to Console
public void PrintWarning(string text)
{
foreach (string line in text.Split('\n'))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
}
// Echoes error text to Console
public void PrintError(string text)
{
foreach (string line in text.Split('\n'))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
if (Debugger.IsAttached)
Debugger.Break();
else
throw new Exception(text);
}
public void PrintDebug(int verbosity, bool noRepeat, string text)
{
if (DebugVerbosity < verbosity)
return;
if (noRepeat)
if (debugLastLine.Length == text.Length && debugLastLine == text)
return;
debugLastLine = text;
foreach (string line in text.Split('\n'))
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
OnPrint?.Invoke(text);
}
}
// Opens the Console
public void Open()
{
if (IsOpen)
return;
IsOpen = true;
OnOpen?.Invoke();
}
// Closes the Console
public void Close()
{
if (!IsOpen)
return;
IsOpen = false;
OnClose?.Invoke();
stopwatch.Restart();
}
// Clears the content of the Console
public void Clear()
{
consoleLines.Clear();
}
public void Execute(string str, bool bufferInput = false)
{
if (bufferInput)
consoleBufferHistory.Insert(0, str);
str = str.Trim();
if (ShowExecutedLines)
Console.Print(LinePrefix + str);
string[] strs = str.Split(' ');
string execute = strs[0];
string executeLower = execute.ToLowerInvariant();
string value = strs.Length > 1 ? str.Substring(execute.Length + 1) : null;
//Console.PrintDebug("Executed '" + execute + "' with params: '" + value + "'");
if (consoleCommands.TryGetValue(executeLower, out ConsoleCommand cmd))
{
string[] values = strs.Skip(1).ToArray();
if (values.Length > 0)
cmd.Invoke(values);
else
cmd.Invoke();
//Console.Print("Command bound to '" + execute + "' is '" + cmd.method.Name + "'");
}
else if (consoleVariables.TryGetValue(executeLower, out ConsoleVariable cvar))
{
if (value != null)
cvar.SetValue(value);
Console.Print("'" + execute + "' is '" + cvar.GetValueString() + "'");
}
else
{
Console.Print("Unknown command '" + execute + "'");
}
}
public string GetVariable(string variableName)
{
if (consoleVariables.TryGetValue(variableName, out ConsoleVariable cvar))
{
string value = cvar.GetValueString();
return value;
}
return null;
}
}
}

View File

@@ -1,68 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cabrito
{
[AttributeUsage(AttributeTargets.All)]
public abstract class ConsoleBaseAttribute : Attribute
{
internal string name;
[AttributeUsage(AttributeTargets.All)]
public abstract class ConsoleBaseAttribute : Attribute
{
// Additional aliases for this command, these should only be used with user interaction.
// Commands such as 'cvarlist' should not list these in order to avoid clutter.
internal string[] aliases = new string[0];
internal string name;
// Additional aliases for this command, these should only be used with user interaction.
// Commands such as 'cvarlist' should not list these in order to avoid clutter.
internal string[] aliases = new string[0];
public ConsoleBaseAttribute(string name)
{
this.name = name.ToLowerInvariant();
}
public ConsoleFlags flags { get; private set; }
public ConsoleBaseAttribute(params string[] names)
{
name = names[0].ToLowerInvariant();
aliases = new List<string>(names).Skip(1).Select(x => x.ToLowerInvariant()).ToArray();
}
public ConsoleBaseAttribute(string name)
{
this.name = name.ToLowerInvariant();
}
public ConsoleFlags flags { get; private set; }
}
public ConsoleBaseAttribute(params string[] names)
{
this.name = names[0].ToLowerInvariant();
aliases = new List<string>(names).Skip(1).Select(x => x.ToLowerInvariant()).ToArray();
}
}
[AttributeUsage(AttributeTargets.All)]
public class ConsoleVariableAttribute : ConsoleBaseAttribute
{
public ConsoleVariableAttribute(string name) : base(name)
{
}
}
[AttributeUsage(AttributeTargets.All)]
public class ConsoleVariableAttribute : ConsoleBaseAttribute
{
public ConsoleVariableAttribute(string name) : base(name)
{
}
}
[AttributeUsage(AttributeTargets.All)]
public class ConsoleCommandAttribute : ConsoleBaseAttribute
{
/// <summary>
/// Registers a command to Console system.
/// </summary>
/// <param name="name">Name used for calling this command.</param>
public ConsoleCommandAttribute(string name) : base(name)
{
}
[AttributeUsage(AttributeTargets.All)]
public class ConsoleCommandAttribute : ConsoleBaseAttribute
{
/// <summary>
/// Registers a command to Console system.
/// </summary>
/// <param name="name">Name used for calling this command.</param>
public ConsoleCommandAttribute(string name) : base(name)
{
}
/// <summary>
/// Registers a command to Console system.
/// </summary>
/// <param name="names">
/// Names used for calling this command. First name is the main name for this command, rest of the
/// names are aliases.
/// </param>
public ConsoleCommandAttribute(params string[] names) : base(names)
{
}
}
/// <summary>
/// Registers a command to Console system.
/// </summary>
/// <param name="names">Names used for calling this command. First name is the main name for this command, rest of the names are aliases.</param>
public ConsoleCommandAttribute(params string[] names) : base(names)
{
}
}
/// <summary>
/// Constructor for the subsystem, must be called first before registering console commands.
/// </summary>
[AttributeUsage(AttributeTargets.All)]
public class ConsoleSubsystemInitializer : Attribute
{
}
/// <summary>
/// Constructor for the subsystem, must be called first before registering console commands.
/// </summary>
[AttributeUsage(AttributeTargets.All)]
public class ConsoleSubsystemInitializer : Attribute
{
}
}

View File

@@ -1,81 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Cabrito
{
internal struct ConsoleCommand
{
public string name { get; private set; }
internal struct ConsoleCommand
{
public string name { get; }
private MethodInfo[] methods;
private readonly MethodInfo[] methods;
public ConsoleCommand(string name, MethodInfo[] method)
{
this.name = name;
this.methods = method;
}
public ConsoleCommand(string name, MethodInfo[] method)
{
this.name = name;
methods = method;
}
public void Invoke()
{
foreach (var method in methods)
{
var methodParameters = method.GetParameters();
if (methodParameters.Length != 0)
continue;
public void Invoke()
{
foreach (MethodInfo method in methods)
{
var methodParameters = method.GetParameters();
if (methodParameters.Length != 0)
continue;
method.Invoke(null, null);
return;
}
method.Invoke(null, null);
return;
}
throw new Exception("Unexpected number of parameters.");
}
throw new Exception("Unexpected number of parameters.");
}
public void Invoke(string[] parameters)
{
MethodInfo match = null;
foreach (var method in methods)
{
var methodParameters = method.GetParameters();
if (methodParameters.Length == 1 && methodParameters[0].ParameterType == typeof(string[]))
{
match = method;
continue;
}
else if (methodParameters.Length != parameters.Length)
continue;
public void Invoke(string[] parameters)
{
MethodInfo match = null;
foreach (MethodInfo method in methods)
{
var methodParameters = method.GetParameters();
if (methodParameters.Length == 1 && methodParameters[0].ParameterType == typeof(string[]))
{
match = method;
continue;
}
// TODO: try to parse string parameters to needed types first,
// may require finding the exact match first instead of first matching one.
for (int i = 0; i < methodParameters.Length; i++)
//if (methodParameters[i].ParameterType != parameters[i].GetType())
if (methodParameters[i].ParameterType != typeof(string))
continue;
if (methodParameters.Length != parameters.Length)
continue;
if (match != null)
{
// Prefer exact number of parameters over string[] match
if (methodParameters.Length != parameters.Length)
continue;
}
// TODO: try to parse string parameters to needed types first,
// may require finding the exact match first instead of first matching one.
for (int i = 0; i < methodParameters.Length; i++)
//if (methodParameters[i].ParameterType != parameters[i].GetType())
if (methodParameters[i].ParameterType != typeof(string))
continue;
match = method;
}
if (match != null)
// Prefer exact number of parameters over string[] match
if (methodParameters.Length != parameters.Length)
continue;
if (match != null)
{
if (match.GetParameters().Length == 1 && match.GetParameters()[0].ParameterType == typeof(string[]))
match.Invoke(null, new object[] {parameters});
else
match.Invoke(null, parameters);
match = method;
}
return;
}
if (match != null)
{
if (match.GetParameters().Length == 1 && match.GetParameters()[0].ParameterType == typeof(string[]))
match.Invoke(null, new object[] { parameters });
else
match.Invoke(null, parameters);
throw new Exception("Unexpected number of parameters.");
}
}
return;
}
throw new Exception("Unexpected number of parameters.");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,173 +1,167 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor;
using FlaxEngine;
using FlaxEngine.GUI;
namespace Cabrito
{
public class ConsoleInputTextBox : ConsoleTextBoxBase
{
public override string TextPrefix
{
get => Console.LinePrefix;
}
public class ConsoleInputTextBox : ConsoleTextBoxBase
{
private readonly ConsoleContentTextBox contentBox;
private ConsoleContentTextBox contentBox;
private int inputHistoryIndex = -1;
protected override Rectangle TextRectangle => new Rectangle(0, 0, Width, Height);
protected override Rectangle TextClipRectangle => new Rectangle(0, 0, Width, Height);
public ConsoleInputTextBox()
{
}
public ConsoleInputTextBox() : base()
{
}
public ConsoleInputTextBox(ConsoleContentTextBox contentBox, float x, float y, float width, float height) :
base(x, y, width, height)
{
this.contentBox = contentBox;
IsMultiline = true; // Not really but behaves better than single-line box
}
public ConsoleInputTextBox(ConsoleContentTextBox contentBox, float x, float y, float width, float height) :
base(x, y, width, height)
{
this.contentBox = contentBox;
IsMultiline = true; // Not really but behaves better than single-line box
}
public override string TextPrefix => Console.LinePrefix;
private bool IsConsoleKeyPressed(KeyboardKeys key = KeyboardKeys.None)
{
// Ignore any characters generated by the key which opens the console
string inputTextLower = Input.InputText.ToLowerInvariant();
protected override Rectangle TextRectangle => new Rectangle(0, 0, Width, Height);
protected override Rectangle TextClipRectangle => new Rectangle(0, 0, Width, Height);
IEnumerable<ActionConfig> consoleKeyMappings;
if (key == KeyboardKeys.None)
consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None);
else
consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key == key);
foreach (var mapping in consoleKeyMappings)
{
if (inputTextLower.Length > 0)
{
if ((mapping.Key == KeyboardKeys.Backslash || mapping.Key == KeyboardKeys.BackQuote) &&
(inputTextLower.Contains('ö') ||
inputTextLower.Contains('æ') ||
inputTextLower.Contains('ø')))
{
continue; // Scandinavian keyboard layouts
}
else if (mapping.Key == KeyboardKeys.BackQuote && inputTextLower.Contains('\''))
continue;
else if (mapping.Key == KeyboardKeys.Backslash &&
(inputTextLower.Contains('\\') || inputTextLower.Contains('|')))
{
continue;
}
}
private bool IsConsoleKeyPressed(KeyboardKeys key = KeyboardKeys.None)
{
// Ignore any characters generated by the key which opens the console
string inputTextLower = Input.InputText.ToLowerInvariant();
if (Input.GetKey(mapping.Key))
return true;
}
IEnumerable<ActionConfig> consoleKeyMappings;
if (key == KeyboardKeys.None)
consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None);
else
consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key == key);
foreach (ActionConfig mapping in consoleKeyMappings)
{
if (inputTextLower.Length > 0)
{
if ((mapping.Key == KeyboardKeys.Backslash || mapping.Key == KeyboardKeys.BackQuote) &&
(inputTextLower.Contains('ö') ||
inputTextLower.Contains('æ') ||
inputTextLower.Contains('ø')))
continue; // Scandinavian keyboard layouts
if (mapping.Key == KeyboardKeys.BackQuote && inputTextLower.Contains('\''))
continue;
if (mapping.Key == KeyboardKeys.Backslash &&
(inputTextLower.Contains('\\') || inputTextLower.Contains('|')))
continue;
}
return false;
}
if (Input.GetKey(mapping.Key))
return true;
}
public override bool OnCharInput(char c)
{
if (IsConsoleKeyPressed())
return true;
return false;
}
return base.OnCharInput(c);
}
public override bool OnCharInput(char c)
{
if (IsConsoleKeyPressed())
return true;
private int inputHistoryIndex = -1;
public override bool OnKeyDown(KeyboardKeys key)
{
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
bool ctrlDown = Root.GetKey(KeyboardKeys.Control);
return base.OnCharInput(c);
}
if (IsConsoleKeyPressed(key))
{
Clear();
return true;
}
else if (key == KeyboardKeys.Escape)
{
Console.Close();
Clear();
return true;
}
else if (key == KeyboardKeys.Return)
{
try
{
Console.Execute(Text, true);
inputHistoryIndex = -1;
}
finally
{
Clear();
}
public override bool OnKeyDown(KeyboardKeys key)
{
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
bool ctrlDown = Root.GetKey(KeyboardKeys.Control);
contentBox.ScrollOffset = 0;
return true;
}
else if (key == KeyboardKeys.ArrowUp)
{
inputHistoryIndex++;
if (IsConsoleKeyPressed(key))
{
Clear();
return true;
}
string line = Console.GetBufferHistory(inputHistoryIndex);
if (line == null)
{
inputHistoryIndex--;
return true;
}
if (key == KeyboardKeys.Escape)
{
Console.Close();
Clear();
return true;
}
SetText(line);
SetSelection(TextLength);
return true;
}
else if (key == KeyboardKeys.ArrowDown)
{
if (inputHistoryIndex > 0)
inputHistoryIndex--;
if (key == KeyboardKeys.Return)
{
try
{
Console.Execute(Text, true);
inputHistoryIndex = -1;
}
finally
{
Clear();
}
string line = Console.GetBufferHistory(inputHistoryIndex);
if (line == null)
return true;
contentBox.ScrollOffset = 0;
return true;
}
SetText(line);
SetSelection(TextLength);
return true;
}
else if (key == KeyboardKeys.PageUp || key == KeyboardKeys.PageDown)
{
return contentBox.OnKeyDown(key);
}
if (key == KeyboardKeys.ArrowUp)
{
inputHistoryIndex++;
return base.OnKeyDown(key);
}
string line = Console.GetBufferHistory(inputHistoryIndex);
if (line == null)
{
inputHistoryIndex--;
return true;
}
public override void OnLostFocus()
{
// Avoids reseting the caret location
var oldEditing = _isEditing;
_isEditing = false;
base.OnLostFocus();
_isEditing = oldEditing;
}
SetText(line);
SetSelection(TextLength);
return true;
}
public override bool OnMouseDown(Vector2 location, MouseButton button)
{
base.OnMouseDown(location, button);
return true;
}
if (key == KeyboardKeys.ArrowDown)
{
if (inputHistoryIndex > 0)
inputHistoryIndex--;
public override bool OnMouseWheel(Vector2 location, float delta)
{
return contentBox.OnMouseWheel(location, delta);
}
string line = Console.GetBufferHistory(inputHistoryIndex);
if (line == null)
return true;
public override void Draw()
{
Profiler.BeginEvent("ConsoleInputTextBoxDraw");
base.Draw();
Profiler.EndEvent();
}
}
SetText(line);
SetSelection(TextLength);
return true;
}
if (key == KeyboardKeys.PageUp || key == KeyboardKeys.PageDown)
return contentBox.OnKeyDown(key);
return base.OnKeyDown(key);
}
public override void OnLostFocus()
{
// Avoids reseting the caret location
bool oldEditing = _isEditing;
_isEditing = false;
base.OnLostFocus();
_isEditing = oldEditing;
}
public override bool OnMouseDown(Vector2 location, MouseButton button)
{
base.OnMouseDown(location, button);
return true;
}
public override bool OnMouseWheel(Vector2 location, float delta)
{
return contentBox.OnMouseWheel(location, delta);
}
public override void Draw()
{
Profiler.BeginEvent("ConsoleInputTextBoxDraw");
base.Draw();
Profiler.EndEvent();
}
}
}

View File

@@ -1,59 +1,56 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using FlaxEngine;
using Console = Cabrito.Console;
#if FLAX_EDITOR
using FlaxEditor;
#endif
namespace Game
{
public class ConsolePlugin : GamePlugin
{
public override void Initialize()
{
base.Initialize();
Debug.Log("ConsolePlugin Initialize");
public class ConsolePlugin : GamePlugin
{
public static PluginDescription DescriptionInternal = new PluginDescription
{
Author = "Ari Vuollet",
Name = "Console",
Description = "Quake-like console",
Version = Version.Parse("0.1.0"),
IsAlpha = true,
Category = "Game"
};
Console.Init();
}
public override void Initialize()
{
base.Initialize();
Debug.Log("ConsolePlugin Initialize");
public override void Deinitialize()
{
base.Deinitialize();
Debug.Log("ConsolePlugin Deinitialize");
}
Console.Init();
}
public static PluginDescription DescriptionInternal = new PluginDescription()
{
Author = "Ari Vuollet",
Name = "Console",
Description = "Quake-like console",
Version = Version.Parse("0.1.0"),
IsAlpha = true,
Category = "Game",
};
}
public override void Deinitialize()
{
base.Deinitialize();
Debug.Log("ConsolePlugin Deinitialize");
}
}
#if FLAX_EDITOR
public class ConsoleEditorPlugin : EditorPlugin
{
public override void Initialize()
{
Debug.Log("ConsoleEditorPlugin Initialize");
Console.Init();
}
public class ConsoleEditorPlugin : EditorPlugin
{
public override PluginDescription Description => ConsolePlugin.DescriptionInternal;
public override void Deinitialize()
{
Debug.Log("ConsoleEditorPlugin Deinitialize");
}
public override Type GamePluginType => typeof(ConsolePlugin);
public override PluginDescription Description => ConsolePlugin.DescriptionInternal;
public override void Initialize()
{
Debug.Log("ConsoleEditorPlugin Initialize");
Console.Init();
}
public override Type GamePluginType => typeof(ConsolePlugin);
}
public override void Deinitialize()
{
Debug.Log("ConsoleEditorPlugin Deinitialize");
}
}
#endif
}

View File

@@ -1,151 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor;
using FlaxEngine;
using FlaxEngine.Assertions;
using FlaxEngine.GUI;
using Object = FlaxEngine.Object;
namespace Cabrito
{
public class ConsoleScript : Script
{
[Limit(5, 720, 1)] public int ConsoleFontSize = 16;
public class ConsoleScript : Script
{
public Color BackgroundColor;
[Limit(0.05f, 1.0f, 1)] public float ConsoleHeight = 0.65f;
public Texture BackgroundTexture;
private ConsoleContentTextBox consoleBox;
[Limit(0)] public int ConsoleNotifyLines = 3;
public FontAsset ConsoleFont;
[Limit(5, 720)] public int ConsoleFontSize = 16;
[Limit(0f)] public float ConsoleSpeed = 3500f;
[Limit(0.05f, 1.0f)] public float ConsoleHeight = 0.65f;
private ConsoleInputTextBox consoleInputBox;
public FontAsset ConsoleFont;
internal InputEvent consoleInputEvent;
private ConsoleContentTextBox consoleNotifyBox;
public Texture BackgroundTexture;
[Limit(0)] public int ConsoleNotifyLines = 3;
public Color BackgroundColor;
[Limit(0f)] public float ConsoleSpeed = 3500f;
private UIControl rootControl;
private ConsoleContentTextBox consoleBox;
private ConsoleInputTextBox consoleInputBox;
private ConsoleContentTextBox consoleNotifyBox;
private UIControl rootControl;
internal InputEvent consoleInputEvent;
public override void OnStart()
{
consoleInputEvent = new InputEvent("Console");
consoleInputEvent.Triggered += OnConsoleInputEvent;
public override void OnStart()
{
consoleInputEvent = new InputEvent("Console");
consoleInputEvent.Triggered += OnConsoleInputEvent;
FontReference fontReference = new FontReference(ConsoleFont, ConsoleFontSize);
Font fontRaw = fontReference.GetFont();
int fontHeight = (int)(fontRaw.Height / Platform.DpiScale);
FontReference fontReference = new FontReference(ConsoleFont, ConsoleFontSize);
Font fontRaw = fontReference.GetFont();
int fontHeight = (int) (fontRaw.Height / Platform.DpiScale);
// root actor which holds all the elements
//var rootContainerControl = new ContainerControl(new Rectangle(0, 0, screenSize.X, screenSize.Y));
ContainerControl rootContainerControl = new ContainerControl(new Rectangle());
rootContainerControl.SetAnchorPreset(AnchorPresets.StretchAll, false);
// root actor which holds all the elements
//var rootContainerControl = new ContainerControl(new Rectangle(0, 0, screenSize.X, screenSize.Y));
var rootContainerControl = new ContainerControl(new Rectangle());
rootContainerControl.SetAnchorPreset(AnchorPresets.StretchAll, false);
rootControl = Actor.AddChild<UIControl>();
rootControl.Name = "ConsoleRoot";
rootControl.Control = rootContainerControl;
rootControl = Actor.AddChild<UIControl>();
rootControl.Name = "ConsoleRoot";
rootControl.Control = rootContainerControl;
VerticalPanel contentContainer = new VerticalPanel
{
AutoSize = true,
Margin = Margin.Zero,
Spacing = 0,
Bounds = new Rectangle(),
BackgroundColor = BackgroundColor
};
contentContainer.SetAnchorPreset(AnchorPresets.StretchAll, true);
var contentContainer = new VerticalPanel()
{
AutoSize = true,
Margin = Margin.Zero,
Spacing = 0,
Bounds = new Rectangle(),
BackgroundColor = BackgroundColor
};
contentContainer.SetAnchorPreset(AnchorPresets.StretchAll, true);
UIControl contentContainerControl = rootControl.AddChild<UIControl>();
contentContainerControl.Name = "ContentContainer";
contentContainerControl.Control = contentContainer;
var contentContainerControl = rootControl.AddChild<UIControl>();
contentContainerControl.Name = "ContentContainer";
contentContainerControl.Control = contentContainer;
{
if (consoleBox == null)
{
//consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
consoleBox = new ConsoleContentTextBox(fontReference, null, 0, 0, 0, 0);
{
if (consoleBox == null)
{
//consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
consoleBox = new ConsoleContentTextBox(fontReference, null, 0, 0, 0, 0);
consoleBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true);
//consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight);
//consoleBox.Height = consoleSize.Y - fontHeight;
consoleBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true);
//consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight);
//consoleBox.Height = consoleSize.Y - fontHeight;
//consoleBox.HorizontalAlignment = TextAlignment.Near;
//consoleBox.VerticalAlignment = TextAlignment.Near;
consoleBox.HeightMultiplier = ConsoleHeight;
consoleBox.Wrapping = TextWrapping.WrapWords;
consoleBox.BackgroundColor = Color.Transparent;
consoleBox.BackgroundSelectedColor = Color.Transparent;
consoleBox.BackgroundSelectedFlashSpeed = 0;
consoleBox.BorderSelectedColor = Color.Transparent;
consoleBox.CaretFlashSpeed = 0;
}
//consoleBox.HorizontalAlignment = TextAlignment.Near;
//consoleBox.VerticalAlignment = TextAlignment.Near;
consoleBox.HeightMultiplier = ConsoleHeight;
consoleBox.Wrapping = TextWrapping.WrapWords;
consoleBox.BackgroundColor = Color.Transparent;
consoleBox.BackgroundSelectedColor = Color.Transparent;
consoleBox.BackgroundSelectedFlashSpeed = 0;
consoleBox.BorderSelectedColor = Color.Transparent;
consoleBox.CaretFlashSpeed = 0;
}
var locationFix = consoleBox.Location;
var parentControl = contentContainerControl.AddChild<UIControl>();
parentControl.Name = "ConsoleContent";
parentControl.Control = consoleBox;
consoleBox.Location = locationFix; // workaround to UIControl.Control overriding the old position
Vector2 locationFix = consoleBox.Location;
UIControl parentControl = contentContainerControl.AddChild<UIControl>();
parentControl.Name = "ConsoleContent";
parentControl.Control = consoleBox;
consoleBox.Location = locationFix; // workaround to UIControl.Control overriding the old position
if (consoleNotifyBox == null)
{
//consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
consoleNotifyBox = new ConsoleContentTextBox(fontReference, null, 0, 0, 0, 0);
consoleNotifyBox.HeightMultiplier = 0;
consoleNotifyBox.Height = ConsoleNotifyLines * fontHeight;
consoleNotifyBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true);
//consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight);
if (consoleNotifyBox == null)
{
//consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
consoleNotifyBox = new ConsoleContentTextBox(fontReference, null, 0, 0, 0, 0);
consoleNotifyBox.HeightMultiplier = 0;
consoleNotifyBox.Height = ConsoleNotifyLines * fontHeight;
consoleNotifyBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true);
//consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight);
//consoleBox.HorizontalAlignment = TextAlignment.Near;
//consoleBox.VerticalAlignment = TextAlignment.Near;
//consoleNotifyBox.HeightMultiplier = ConsoleHeight;
consoleNotifyBox.Wrapping = TextWrapping.WrapWords;
consoleNotifyBox.BackgroundColor = Color.Transparent;
consoleNotifyBox.BackgroundSelectedColor = Color.Transparent;
consoleNotifyBox.BackgroundSelectedFlashSpeed = 0;
consoleNotifyBox.BorderSelectedColor = Color.Transparent;
consoleNotifyBox.CaretFlashSpeed = 0;
}
//consoleBox.HorizontalAlignment = TextAlignment.Near;
//consoleBox.VerticalAlignment = TextAlignment.Near;
//consoleNotifyBox.HeightMultiplier = ConsoleHeight;
consoleNotifyBox.Wrapping = TextWrapping.WrapWords;
consoleNotifyBox.BackgroundColor = Color.Transparent;
consoleNotifyBox.BackgroundSelectedColor = Color.Transparent;
consoleNotifyBox.BackgroundSelectedFlashSpeed = 0;
consoleNotifyBox.BorderSelectedColor = Color.Transparent;
consoleNotifyBox.CaretFlashSpeed = 0;
}
var locationFix2 = consoleNotifyBox.Location;
var parentControl2 = Actor.AddChild<UIControl>();
parentControl2.Name = "ConsoleNotifyContent";
parentControl2.Control = consoleNotifyBox;
consoleNotifyBox.Location = locationFix2; // workaround to UIControl.Control overriding the old position
}
{
if (consoleInputBox == null)
{
//consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, consoleSize.Y - fontHeight, consoleSize.X, fontHeight);
consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, 0, 0, 0);
consoleInputBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false);
//consoleInputBox.Location = new Vector2(0, consoleSize.Y - fontHeight);
consoleInputBox.Height = fontHeight;
Vector2 locationFix2 = consoleNotifyBox.Location;
UIControl parentControl2 = Actor.AddChild<UIControl>();
parentControl2.Name = "ConsoleNotifyContent";
parentControl2.Control = consoleNotifyBox;
consoleNotifyBox.Location = locationFix2; // workaround to UIControl.Control overriding the old position
}
{
if (consoleInputBox == null)
{
//consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, consoleSize.Y - fontHeight, consoleSize.X, fontHeight);
consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, 0, 0, 0);
consoleInputBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, false);
//consoleInputBox.Location = new Vector2(0, consoleSize.Y - fontHeight);
consoleInputBox.Height = fontHeight;
consoleInputBox.Font = fontReference;
consoleBox.inputBox = consoleInputBox;
consoleInputBox.Font = fontReference;
consoleBox.inputBox = consoleInputBox;
consoleInputBox.Wrapping = TextWrapping.WrapWords;
consoleInputBox.BackgroundColor = Color.Transparent;
consoleInputBox.BackgroundSelectedColor = Color.Transparent;
consoleInputBox.BackgroundSelectedFlashSpeed = 0;
consoleInputBox.BorderSelectedColor = Color.Transparent;
consoleInputBox.CaretFlashSpeed = 0;
}
consoleInputBox.Wrapping = TextWrapping.WrapWords;
consoleInputBox.BackgroundColor = Color.Transparent;
consoleInputBox.BackgroundSelectedColor = Color.Transparent;
consoleInputBox.BackgroundSelectedFlashSpeed = 0;
consoleInputBox.BorderSelectedColor = Color.Transparent;
consoleInputBox.CaretFlashSpeed = 0;
}
Vector2 locationFix = consoleInputBox.Location;
UIControl parentControl = contentContainerControl.AddChild<UIControl>();
parentControl.Name = "ConsoleInput";
parentControl.Control = consoleInputBox;
var locationFix = consoleInputBox.Location;
var parentControl = contentContainerControl.AddChild<UIControl>();
parentControl.Name = "ConsoleInput";
parentControl.Control = consoleInputBox;
consoleInputBox.Location = locationFix; // workaround to UIControl.Control overriding the old position
}
consoleInputBox.Location = locationFix; // workaround to UIControl.Control overriding the old position
}
#if false
//for (int i = 0; i < 10; i++)
@@ -208,191 +206,191 @@ namespace Cabrito
Console.Print(l);
}
#endif
/*FlaxEditor.Editor.Options.OptionsChanged += (FlaxEditor.Options.EditorOptions options) =>
{
/*FlaxEditor.Editor.Options.OptionsChanged += (FlaxEditor.Options.EditorOptions options) =>
{
};*/
};*/
/*Console.Print("normal line");
Console.Print(
"a very very very long long long line in repeat a very very very long long long line in repeat 1 a very very ver"
+ "y long long long line in repeat a very very very 2 long long long line in repeat a very very very 3 long long"
+ " long line in repeat a very very very long long long 4 line in repeat");
Console.Print("another normal line");*/
/*Console.Print("normal line");
Console.Print(
"a very very very long long long line in repeat a very very very long long long line in repeat 1 a very very ver"
+ "y long long long line in repeat a very very very 2 long long long line in repeat a very very very 3 long long"
+ " long line in repeat a very very very long long long 4 line in repeat");
Console.Print("another normal line");*/
Debug.Logger.LogHandler.SendLog += OnSendLog;
Debug.Logger.LogHandler.SendExceptionLog += OnSendExceptionLog;
Debug.Logger.LogHandler.SendLog += OnSendLog;
Debug.Logger.LogHandler.SendExceptionLog += OnSendExceptionLog;
Console.OnOpen += OnConsoleOpen;
Console.OnClose += OnConsoleClose;
Console.OnPrint += OnPrint;
Console.OnOpen += OnConsoleOpen;
Console.OnClose += OnConsoleClose;
Console.OnPrint += OnPrint;
// hide console by default, and close it instantly
Console.Close();
var rootlocation = rootControl.Control.Location;
rootlocation.Y = -rootControl.Control.Height;
rootControl.Control.Location = rootlocation;
// hide console by default, and close it instantly
Console.Close();
Vector2 rootlocation = rootControl.Control.Location;
rootlocation.Y = -rootControl.Control.Height;
rootControl.Control.Location = rootlocation;
Console.Print("Renderer: " + GPUDevice.Instance.RendererType);
}
Console.Print("Renderer: " + GPUDevice.Instance.RendererType);
}
private void OnSendLog(LogType level, string msg, FlaxEngine.Object obj, string stackTrace)
{
Console.Print("[DEBUG] " + msg);
}
private void OnSendLog(LogType level, string msg, Object obj, string stackTrace)
{
Console.Print("[DEBUG] " + msg);
}
private void OnSendExceptionLog(Exception exception, FlaxEngine.Object obj)
{
AssertionException assert = exception as AssertionException;
if (assert != null)
{
var assertLines = assert.Message.Split('\n');
if (assertLines.Length > 2)
Console.Print("Assert Failure: " + assertLines[2]);
else
Console.Print("Assert Failure: " + assert.Message);
}
else
Console.Print("[EXCEP] " + exception.Message);
}
private void OnSendExceptionLog(Exception exception, Object obj)
{
AssertionException assert = exception as AssertionException;
if (assert != null)
{
string[] assertLines = assert.Message.Split('\n');
if (assertLines.Length > 2)
Console.Print("Assert Failure: " + assertLines[2]);
else
Console.Print("Assert Failure: " + assert.Message);
}
else
{
Console.Print("[EXCEP] " + exception.Message);
}
}
public override void OnDestroy()
{
base.OnDestroy();
public override void OnDestroy()
{
base.OnDestroy();
//consoleInputEvent.Triggered -= OnConsoleInputEvent;
consoleInputEvent?.Dispose();
consoleBox?.Dispose();
consoleNotifyBox?.Dispose();
//consoleInputEvent.Triggered -= OnConsoleInputEvent;
consoleInputEvent?.Dispose();
consoleBox?.Dispose();
consoleNotifyBox?.Dispose();
Console.OnOpen -= OnConsoleOpen;
Console.OnClose -= OnConsoleClose;
Console.OnPrint -= OnPrint;
Console.OnOpen -= OnConsoleOpen;
Console.OnClose -= OnConsoleClose;
Console.OnPrint -= OnPrint;
Debug.Logger.LogHandler.SendLog -= OnSendLog;
Debug.Logger.LogHandler.SendExceptionLog -= OnSendExceptionLog;
}
Debug.Logger.LogHandler.SendLog -= OnSendLog;
Debug.Logger.LogHandler.SendExceptionLog -= OnSendExceptionLog;
}
private void OnConsoleInputEvent()
{
string currentInput = Input.InputText;
private void OnConsoleInputEvent()
{
string currentInput = Input.InputText;
if (Input.InputText.Length > 0)
{
// Really need rawinput support with separate ActionConfig.RawKey values, bound to physical keys/scancode instead of virtual ones
var consoleKeys = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None);
bool backslash = consoleKeys.Any(x => x.Key == KeyboardKeys.Backslash);
bool backquote = consoleKeys.Any(x => x.Key == KeyboardKeys.BackQuote);
if (Input.InputText.Length > 0)
{
// Really need rawinput support with separate ActionConfig.RawKey values, bound to physical keys/scancode instead of virtual ones
var consoleKeys = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None);
bool backslash = consoleKeys.Any(x => x.Key == KeyboardKeys.Backslash);
bool backquote = consoleKeys.Any(x => x.Key == KeyboardKeys.BackQuote);
// Workaround to only trigger Console key from key bound to left side of 1 (tilde/backquote/backslash key)
if ((backslash || backquote) &&
(Input.InputText.ToLowerInvariant().Contains('ö') ||
Input.InputText.ToLowerInvariant().Contains('æ') ||
Input.InputText.ToLowerInvariant().Contains('ø'))) // Scandinavian keyboard layouts
{
return;
}
else if (backquote && Input.InputText.ToLowerInvariant().Contains('\'')) // UK keyboard layouts
return;
else if (backslash && (Input.InputText.ToLowerInvariant().Contains('\\') ||
Input.InputText.ToLowerInvariant()
.Contains('|'))) // US/International keyboard layouts
return;
}
// Workaround to only trigger Console key from key bound to left side of 1 (tilde/backquote/backslash key)
if ((backslash || backquote) &&
(Input.InputText.ToLowerInvariant().Contains('ö') ||
Input.InputText.ToLowerInvariant().Contains('æ') ||
Input.InputText.ToLowerInvariant().Contains('ø'))) // Scandinavian keyboard layouts
return;
if (backquote && Input.InputText.ToLowerInvariant().Contains('\'')) // UK keyboard layouts
return;
if (backslash && (Input.InputText.ToLowerInvariant().Contains('\\') ||
Input.InputText.ToLowerInvariant()
.Contains('|'))) // US/International keyboard layouts
return;
}
if (!consoleInputBox.IsFocused)
Console.Open();
else
Console.Close();
}
if (!consoleInputBox.IsFocused)
Console.Open();
else
Console.Close();
}
public void OnConsoleOpen()
{
Screen.CursorVisible = true;
Screen.CursorLock = CursorLockMode.None;
public void OnConsoleOpen()
{
Screen.CursorVisible = true;
Screen.CursorLock = CursorLockMode.None;
consoleInputBox.Focus();
Parent.As<UICanvas>().ReceivesEvents = true;
}
consoleInputBox.Focus();
Parent.As<UICanvas>().ReceivesEvents = true;
}
public void OnConsoleClose()
{
Screen.CursorVisible = false;
Screen.CursorLock = CursorLockMode.Locked;
public void OnConsoleClose()
{
Screen.CursorVisible = false;
Screen.CursorLock = CursorLockMode.Locked;
consoleInputBox.Defocus();
consoleInputBox.Defocus();
#if FLAX_EDITOR
Editor.Instance.Windows.GameWin.Focus();
Editor.Instance.Windows.GameWin.Focus();
#endif
Parent.As<UICanvas>().ReceivesEvents = false;
}
Parent.As<UICanvas>().ReceivesEvents = false;
}
public override void OnUpdate()
{
base.OnUpdate();
public override void OnUpdate()
{
base.OnUpdate();
if (!Console.IsOpen && Input.GetAction("ClearConsole"))
Console.Clear();
if (!Console.IsOpen && Input.GetAction("ClearConsole"))
Console.Clear();
float targetY;
float conHeight = rootControl.Control.Height /*/ Platform.DpiScale*/;
if (!Console.IsOpen)
targetY = -conHeight;
else
targetY = 0.0f;
float targetY;
float conHeight = rootControl.Control.Height /*/ Platform.DpiScale*/;
if (!Console.IsOpen)
targetY = -conHeight;
else
targetY = 0.0f;
Vector2 location = rootControl.Control.Location;
if (location.Y != targetY)
{
if (location.Y > targetY)
{
// closing
location.Y -= Time.UnscaledDeltaTime * ConsoleSpeed;
if (location.Y < targetY)
location.Y = targetY;
Vector2 location = rootControl.Control.Location;
if (location.Y != targetY)
{
if (location.Y > targetY)
{
// closing
location.Y -= Time.UnscaledDeltaTime * ConsoleSpeed;
if (location.Y < targetY)
location.Y = targetY;
if (location.Y < targetY * ConsoleHeight)
location.Y = targetY;
}
else if (location.Y < targetY)
{
// opening
if (location.Y < -conHeight * ConsoleHeight)
location.Y = -conHeight * ConsoleHeight;
if (location.Y < targetY * ConsoleHeight)
location.Y = targetY;
}
else if (location.Y < targetY)
{
// opening
if (location.Y < -conHeight * ConsoleHeight)
location.Y = -conHeight * ConsoleHeight;
location.Y += Time.UnscaledDeltaTime * ConsoleSpeed;
if (location.Y > targetY)
location.Y = targetY;
}
location.Y += Time.UnscaledDeltaTime * ConsoleSpeed;
if (location.Y > targetY)
location.Y = targetY;
}
rootControl.Control.Location = location;
rootControl.Control.Location = location;
if (Console.IsOpen)
{
consoleNotifyBox.Visible = false;
consoleInputBox.Visible = true;
}
else if (!Console.IsOpen)
{
int fontHeight = (int) (consoleNotifyBox.FontHeight / Platform.DpiScale);
if (location.Y < (-conHeight * ConsoleHeight) + fontHeight)
{
consoleNotifyBox.Visible = true;
consoleInputBox.Visible = false;
}
}
}
}
if (Console.IsOpen)
{
consoleNotifyBox.Visible = false;
consoleInputBox.Visible = true;
}
else if (!Console.IsOpen)
{
int fontHeight = (int)(consoleNotifyBox.FontHeight / Platform.DpiScale);
if (location.Y < -conHeight * ConsoleHeight + fontHeight)
{
consoleNotifyBox.Visible = true;
consoleInputBox.Visible = false;
}
}
}
}
public void OnPrint(string text)
{
int fontHeight = (int) (consoleNotifyBox.FontHeight / Platform.DpiScale);
consoleNotifyBox.Height = Math.Min(ConsoleNotifyLines, Console.Lines.Count) * fontHeight;
}
public void OnPrint(string text)
{
int fontHeight = (int)(consoleNotifyBox.FontHeight / Platform.DpiScale);
consoleNotifyBox.Height = Math.Min(ConsoleNotifyLines, Console.Lines.Count) * fontHeight;
}
public void SetInput(string text)
{
consoleInputBox.Text = text;
}
}
public void SetInput(string text)
{
consoleInputBox.Text = text;
}
}
}

View File

@@ -1,390 +1,389 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor;
using System.Diagnostics;
using FlaxEngine;
using FlaxEngine.GUI;
namespace Cabrito
{
// Mostly based on TextBox
public class ConsoleTextBoxBase : TextBoxBase
{
protected TextLayoutOptions _layout;
/// <summary>
/// Gets or sets the text wrapping within the control bounds.
/// </summary>
[EditorDisplay("Style"), EditorOrder(2000), Tooltip("The text wrapping within the control bounds.")]
public TextWrapping Wrapping
{
get => _layout.TextWrapping;
set => _layout.TextWrapping = value;
}
/// <summary>
/// Gets or sets the font.
/// </summary>
[EditorDisplay("Style"), EditorOrder(2000)]
public FontReference Font { get; set; }
/// <summary>
/// Gets or sets the color of the text.
/// </summary>
[EditorDisplay("Style"), EditorOrder(2000), Tooltip("The color of the text.")]
public Color TextColor = Color.White;
/// <summary>
/// Gets or sets the color of the selection (Transparent if not used).
/// </summary>
[EditorDisplay("Style"), EditorOrder(2000), Tooltip("The color of the selection (Transparent if not used).")]
public Color SelectionColor = new Color(0x00, 0x7A, 0xCC, 0xFF);
[HideInEditor] public virtual string TextPrefix { get; set; } = "";
//[HideInEditor]
//public override string Text => _text;
public ConsoleTextBoxBase() : base()
{
}
public ConsoleTextBoxBase(float x, float y, float width, float height) : base(false, x, y, width)
{
Height = height;
IsReadOnly = false;
CaretColor = new Color(1f, 1f, 1f, 1f);
AutoFocus = true;
_layout = TextLayoutOptions.Default;
_layout.VerticalAlignment = IsMultiline ? TextAlignment.Near : TextAlignment.Center;
_layout.TextWrapping = TextWrapping.NoWrap;
_layout.Bounds =
new Rectangle(0, 0, Width,
Height); //new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
}
/*protected override void SetText(string value)
{
// Prevent from null problems
if (value == null)
value = string.Empty;
// Filter text
if (value.IndexOf('\r') != -1)
value = value.Replace("\r", "");
// Clamp length
if (value.Length > MaxLength)
value = value.Substring(0, MaxLength);
// Ensure to use only single line
if (_isMultiline == false && value.Length > 0)
{
// Extract only the first line
value = value.GetLines()[0];
}
if (Text != value)
{
Deselect();
ResetViewOffset();
Text = value;
OnTextChanged();
}
}*/
public int GetFontHeight()
{
var font = Font.GetFont();
if (font == null)
return (int) Height;
return (int) Mathf.Round(font.Height * Scale.Y);
}
public override void Clear()
{
// Can't clear the text while user is editing it...
var oldEditing = _isEditing;
_isEditing = false;
base.Clear();
_isEditing = oldEditing;
}
public override void ResetViewOffset()
{
TargetViewOffset = new Vector2(0, 0);
}
/*public void ScrollToEnd()
{
float maxY = TextSize.Y - Height;
float spacing = GetRealLineSpacing();
maxY += spacing;
TargetViewOffset = new Vector2(0, Math.Max(0, maxY));
}*/
public override void ScrollToCaret()
{
if (Text.Length == 0)
return;
Rectangle caretBounds = CaretBounds;
float maxY = TextSize.Y - Height;
Vector2 newLocation = CaretBounds.Location;
TargetViewOffset = Vector2.Clamp(newLocation, new Vector2(0, 0), new Vector2(_targetViewOffset.X, maxY));
}
/*const bool smoothScrolling = false;
public override bool OnMouseWheel(Vector2 location, float delta)
{
if (!IsMultiline || Text.Length == 0)
return false;
if (!smoothScrolling)
delta = GetFontHeight() * Math.Sign(delta) * 3;
else
delta *= 30;
float maxY = TextSize.Y - Height;
float offset = GetRealLineSpacing();
maxY += offset;
TargetViewOffset = Vector2.Clamp(_targetViewOffset - new Vector2(0, delta), new Vector2(0, offset), new Vector2(_targetViewOffset.X, maxY));
return true;
}*/
public override Vector2 GetTextSize()
{
var font = Font.GetFont();
if (font == null)
return Vector2.Zero;
return font.MeasureText(Text, ref _layout);
}
public override Vector2 GetCharPosition(int index, out float height)
{
var font = Font.GetFont();
if (font == null)
{
height = Height;
return Vector2.Zero;
}
height = GetFontHeight();
return font.GetCharPosition(Text, index, ref _layout);
}
public override int HitTestText(Vector2 location)
{
var font = Font.GetFont();
if (font == null)
return 0;
if (TextPrefix != "")
{
var prefixSize = font.MeasureText(TextPrefix);
location.X -= prefixSize.X;
}
return font.HitTestText(Text, location, ref _layout);
}
protected override void OnIsMultilineChanged()
{
base.OnIsMultilineChanged();
_layout.VerticalAlignment = IsMultiline ? TextAlignment.Near : TextAlignment.Center;
}
public override bool OnKeyDown(KeyboardKeys key)
{
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
bool ctrlDown = Root.GetKey(KeyboardKeys.Control);
if (shiftDown && key == KeyboardKeys.Delete)
Cut();
else if (ctrlDown && key == KeyboardKeys.Insert)
Copy();
else if (shiftDown && key == KeyboardKeys.Insert)
Paste();
if (shiftDown && key == KeyboardKeys.Home)
{
if (!IsReadOnly)
SetSelection(_selectionStart, 0);
return true;
}
else if (shiftDown && key == KeyboardKeys.End)
{
if (!IsReadOnly)
SetSelection(_selectionStart, TextLength);
return true;
}
return base.OnKeyDown(key);
}
bool doubleClicked = false;
System.Diagnostics.Stopwatch lastDoubleClick = new System.Diagnostics.Stopwatch();
Vector2 lastDoubleClickLocation = new Vector2(0, 0);
public override bool OnMouseDown(Vector2 location, MouseButton button)
{
if (doubleClicked && lastDoubleClick.Elapsed.TotalSeconds < 0.5 &&
location == lastDoubleClickLocation) // Windows defaults to 500ms window
{
doubleClicked = false;
if (OnMouseTripleClick(location, button))
return true;
}
return base.OnMouseDown(location, button);
}
public override bool OnMouseDoubleClick(Vector2 location, MouseButton button)
{
doubleClicked = true;
lastDoubleClick.Restart();
lastDoubleClickLocation = location;
return base.OnMouseDoubleClick(location, button);
}
public bool OnMouseTripleClick(Vector2 location, MouseButton button)
{
if (!IsMultiline)
SelectAll();
else
{
// TODO: select the line
SelectAll();
}
return true;
}
protected override void OnSizeChanged()
{
base.OnSizeChanged();
_layout.Bounds = TextRectangle;
}
public override void Draw()
{
// Cache data
var rect = new Rectangle(Vector2.Zero, Size);
var font = Font.GetFont();
if (!font)
return;
// Background
Color backColor = BackgroundColor;
if (IsMouseOver)
backColor = BackgroundSelectedColor;
if (backColor.A > 0.0f)
Render2D.FillRectangle(rect, backColor);
Color borderColor = IsFocused ? BorderSelectedColor : BorderColor;
if (borderColor.A > 0.0f)
Render2D.DrawRectangle(rect, borderColor);
//string text = TextPrefix + Text;
string text = TextPrefix + Text;
if (text.Length == 0)
return;
// Apply view offset and clip mask
Render2D.PushClip(TextClipRectangle);
bool useViewOffset = !_viewOffset.IsZero;
if (useViewOffset)
Render2D.PushTransform(Matrix3x3.Translation2D(-_viewOffset));
// Check if any text is selected to draw selection
if (HasSelection)
{
Vector2 leftEdge = font.GetCharPosition(text, SelectionLeft + TextPrefix.Length, ref _layout);
Vector2 rightEdge = font.GetCharPosition(text, SelectionRight + TextPrefix.Length, ref _layout);
float fontHeight = GetFontHeight();
// Draw selection background
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
alpha = alpha * alpha;
Color selectionColor = SelectionColor * alpha;
int selectedLinesCount = 1 + Mathf.FloorToInt((rightEdge.Y - leftEdge.Y) / fontHeight);
if (selectedLinesCount == 1) // Selected is part of single line
{
Rectangle r1 = new Rectangle(leftEdge.X, leftEdge.Y, rightEdge.X - leftEdge.X, fontHeight);
Render2D.FillRectangle(r1, selectionColor);
}
else // Selected is more than one line
{
float leftMargin = _layout.Bounds.Location.X;
Rectangle r1 = new Rectangle(leftEdge.X, leftEdge.Y, 1000000000, fontHeight);
Render2D.FillRectangle(r1, selectionColor);
for (int i = 3; i <= selectedLinesCount; i++)
{
leftEdge.Y += fontHeight;
Rectangle r = new Rectangle(leftMargin, leftEdge.Y, 1000000000, fontHeight);
Render2D.FillRectangle(r, selectionColor);
}
Rectangle r2 = new Rectangle(leftMargin, rightEdge.Y, rightEdge.X - leftMargin, fontHeight);
Render2D.FillRectangle(r2, selectionColor);
}
}
Render2D.DrawText(font, text, TextColor, ref _layout);
if (CaretPosition > -1)
{
var prefixSize = TextPrefix != "" ? font.MeasureText(TextPrefix) : new Vector2();
var caretBounds = CaretBounds;
caretBounds.X += prefixSize.X;
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.7f);
alpha = alpha * alpha * alpha * alpha * alpha * alpha;
Render2D.FillRectangle(caretBounds, CaretColor * alpha);
}
// Restore rendering state
if (useViewOffset)
Render2D.PopTransform();
Render2D.PopClip();
}
public override void Paste()
{
if (IsReadOnly)
return;
var clipboardText = Clipboard.Text;
// Handle newlines in clipboard text
if (!string.IsNullOrEmpty(clipboardText))
{
// TODO: probably better to just split these lines and parse each line separately
clipboardText = clipboardText.Replace("\r\n", "");
clipboardText = clipboardText.Replace("\n", "");
}
if (!string.IsNullOrEmpty(clipboardText))
{
var right = SelectionRight;
Insert(clipboardText);
SetSelection(Mathf.Max(right, 0) + clipboardText.Length);
}
}
}
// Mostly based on TextBox
public class ConsoleTextBoxBase : TextBoxBase
{
private readonly Stopwatch lastDoubleClick = new Stopwatch();
protected TextLayoutOptions _layout;
private bool doubleClicked;
private Vector2 lastDoubleClickLocation = new Vector2(0, 0);
/// <summary>
/// Gets or sets the color of the selection (Transparent if not used).
/// </summary>
[EditorDisplay("Style")] [EditorOrder(2000)] [Tooltip("The color of the selection (Transparent if not used).")]
public Color SelectionColor = new Color(0x00, 0x7A, 0xCC);
/// <summary>
/// Gets or sets the color of the text.
/// </summary>
[EditorDisplay("Style")] [EditorOrder(2000)] [Tooltip("The color of the text.")]
public Color TextColor = Color.White;
//[HideInEditor]
//public override string Text => _text;
public ConsoleTextBoxBase()
{
}
public ConsoleTextBoxBase(float x, float y, float width, float height) : base(false, x, y, width)
{
Height = height;
IsReadOnly = false;
CaretColor = new Color(1f, 1f, 1f, 1f);
AutoFocus = true;
_layout = TextLayoutOptions.Default;
_layout.VerticalAlignment = IsMultiline ? TextAlignment.Near : TextAlignment.Center;
_layout.TextWrapping = TextWrapping.NoWrap;
_layout.Bounds =
new Rectangle(0, 0, Width,
Height); //new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
}
/// <summary>
/// Gets or sets the text wrapping within the control bounds.
/// </summary>
[EditorDisplay("Style")]
[EditorOrder(2000)]
[Tooltip("The text wrapping within the control bounds.")]
public TextWrapping Wrapping
{
get => _layout.TextWrapping;
set => _layout.TextWrapping = value;
}
/// <summary>
/// Gets or sets the font.
/// </summary>
[EditorDisplay("Style")]
[EditorOrder(2000)]
public FontReference Font { get; set; }
[HideInEditor] public virtual string TextPrefix { get; set; } = "";
/*protected override void SetText(string value)
{
// Prevent from null problems
if (value == null)
value = string.Empty;
// Filter text
if (value.IndexOf('\r') != -1)
value = value.Replace("\r", "");
// Clamp length
if (value.Length > MaxLength)
value = value.Substring(0, MaxLength);
// Ensure to use only single line
if (_isMultiline == false && value.Length > 0)
{
// Extract only the first line
value = value.GetLines()[0];
}
if (Text != value)
{
Deselect();
ResetViewOffset();
Text = value;
OnTextChanged();
}
}*/
public int GetFontHeight()
{
Font font = Font.GetFont();
if (font == null)
return (int)Height;
return (int)Mathf.Round(font.Height * Scale.Y);
}
public override void Clear()
{
// Can't clear the text while user is editing it...
bool oldEditing = _isEditing;
_isEditing = false;
base.Clear();
_isEditing = oldEditing;
}
public override void ResetViewOffset()
{
TargetViewOffset = new Vector2(0, 0);
}
/*public void ScrollToEnd()
{
float maxY = TextSize.Y - Height;
float spacing = GetRealLineSpacing();
maxY += spacing;
TargetViewOffset = new Vector2(0, Math.Max(0, maxY));
}*/
public override void ScrollToCaret()
{
if (Text.Length == 0)
return;
Rectangle caretBounds = CaretBounds;
float maxY = TextSize.Y - Height;
Vector2 newLocation = CaretBounds.Location;
TargetViewOffset = Vector2.Clamp(newLocation, new Vector2(0, 0), new Vector2(_targetViewOffset.X, maxY));
}
/*const bool smoothScrolling = false;
public override bool OnMouseWheel(Vector2 location, float delta)
{
if (!IsMultiline || Text.Length == 0)
return false;
if (!smoothScrolling)
delta = GetFontHeight() * Math.Sign(delta) * 3;
else
delta *= 30;
float maxY = TextSize.Y - Height;
float offset = GetRealLineSpacing();
maxY += offset;
TargetViewOffset = Vector2.Clamp(_targetViewOffset - new Vector2(0, delta), new Vector2(0, offset), new Vector2(_targetViewOffset.X, maxY));
return true;
}*/
public override Vector2 GetTextSize()
{
Font font = Font.GetFont();
if (font == null)
return Vector2.Zero;
return font.MeasureText(Text, ref _layout);
}
public override Vector2 GetCharPosition(int index, out float height)
{
Font font = Font.GetFont();
if (font == null)
{
height = Height;
return Vector2.Zero;
}
height = GetFontHeight();
return font.GetCharPosition(Text, index, ref _layout);
}
public override int HitTestText(Vector2 location)
{
Font font = Font.GetFont();
if (font == null)
return 0;
if (TextPrefix != "")
{
Vector2 prefixSize = font.MeasureText(TextPrefix);
location.X -= prefixSize.X;
}
return font.HitTestText(Text, location, ref _layout);
}
protected override void OnIsMultilineChanged()
{
base.OnIsMultilineChanged();
_layout.VerticalAlignment = IsMultiline ? TextAlignment.Near : TextAlignment.Center;
}
public override bool OnKeyDown(KeyboardKeys key)
{
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
bool ctrlDown = Root.GetKey(KeyboardKeys.Control);
if (shiftDown && key == KeyboardKeys.Delete)
Cut();
else if (ctrlDown && key == KeyboardKeys.Insert)
Copy();
else if (shiftDown && key == KeyboardKeys.Insert)
Paste();
if (shiftDown && key == KeyboardKeys.Home)
{
if (!IsReadOnly)
SetSelection(_selectionStart, 0);
return true;
}
if (shiftDown && key == KeyboardKeys.End)
{
if (!IsReadOnly)
SetSelection(_selectionStart, TextLength);
return true;
}
return base.OnKeyDown(key);
}
public override bool OnMouseDown(Vector2 location, MouseButton button)
{
if (doubleClicked && lastDoubleClick.Elapsed.TotalSeconds < 0.5 &&
location == lastDoubleClickLocation) // Windows defaults to 500ms window
{
doubleClicked = false;
if (OnMouseTripleClick(location, button))
return true;
}
return base.OnMouseDown(location, button);
}
public override bool OnMouseDoubleClick(Vector2 location, MouseButton button)
{
doubleClicked = true;
lastDoubleClick.Restart();
lastDoubleClickLocation = location;
return base.OnMouseDoubleClick(location, button);
}
public bool OnMouseTripleClick(Vector2 location, MouseButton button)
{
if (!IsMultiline)
SelectAll();
else
// TODO: select the line
SelectAll();
return true;
}
protected override void OnSizeChanged()
{
base.OnSizeChanged();
_layout.Bounds = TextRectangle;
}
public override void Draw()
{
// Cache data
Rectangle rect = new Rectangle(Vector2.Zero, Size);
Font font = Font.GetFont();
if (!font)
return;
// Background
Color backColor = BackgroundColor;
if (IsMouseOver)
backColor = BackgroundSelectedColor;
if (backColor.A > 0.0f)
Render2D.FillRectangle(rect, backColor);
Color borderColor = IsFocused ? BorderSelectedColor : BorderColor;
if (borderColor.A > 0.0f)
Render2D.DrawRectangle(rect, borderColor);
//string text = TextPrefix + Text;
string text = TextPrefix + Text;
if (text.Length == 0)
return;
// Apply view offset and clip mask
Render2D.PushClip(TextClipRectangle);
bool useViewOffset = !_viewOffset.IsZero;
if (useViewOffset)
Render2D.PushTransform(Matrix3x3.Translation2D(-_viewOffset));
// Check if any text is selected to draw selection
if (HasSelection)
{
Vector2 leftEdge = font.GetCharPosition(text, SelectionLeft + TextPrefix.Length, ref _layout);
Vector2 rightEdge = font.GetCharPosition(text, SelectionRight + TextPrefix.Length, ref _layout);
float fontHeight = GetFontHeight();
// Draw selection background
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
alpha = alpha * alpha;
Color selectionColor = SelectionColor * alpha;
int selectedLinesCount = 1 + Mathf.FloorToInt((rightEdge.Y - leftEdge.Y) / fontHeight);
if (selectedLinesCount == 1) // Selected is part of single line
{
Rectangle r1 = new Rectangle(leftEdge.X, leftEdge.Y, rightEdge.X - leftEdge.X, fontHeight);
Render2D.FillRectangle(r1, selectionColor);
}
else // Selected is more than one line
{
float leftMargin = _layout.Bounds.Location.X;
Rectangle r1 = new Rectangle(leftEdge.X, leftEdge.Y, 1000000000, fontHeight);
Render2D.FillRectangle(r1, selectionColor);
for (int i = 3; i <= selectedLinesCount; i++)
{
leftEdge.Y += fontHeight;
Rectangle r = new Rectangle(leftMargin, leftEdge.Y, 1000000000, fontHeight);
Render2D.FillRectangle(r, selectionColor);
}
Rectangle r2 = new Rectangle(leftMargin, rightEdge.Y, rightEdge.X - leftMargin, fontHeight);
Render2D.FillRectangle(r2, selectionColor);
}
}
Render2D.DrawText(font, text, TextColor, ref _layout);
if (CaretPosition > -1)
{
Vector2 prefixSize = TextPrefix != "" ? font.MeasureText(TextPrefix) : new Vector2();
Rectangle caretBounds = CaretBounds;
caretBounds.X += prefixSize.X;
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.7f);
alpha = alpha * alpha * alpha * alpha * alpha * alpha;
Render2D.FillRectangle(caretBounds, CaretColor * alpha);
}
// Restore rendering state
if (useViewOffset)
Render2D.PopTransform();
Render2D.PopClip();
}
public override void Paste()
{
if (IsReadOnly)
return;
string clipboardText = Clipboard.Text;
// Handle newlines in clipboard text
if (!string.IsNullOrEmpty(clipboardText))
{
// TODO: probably better to just split these lines and parse each line separately
clipboardText = clipboardText.Replace("\r\n", "");
clipboardText = clipboardText.Replace("\n", "");
}
if (!string.IsNullOrEmpty(clipboardText))
{
int right = SelectionRight;
Insert(clipboardText);
SetSelection(Mathf.Max(right, 0) + clipboardText.Length);
}
}
}
}

View File

@@ -1,75 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Cabrito
{
[Flags]
public enum ConsoleFlags
{
NoSerialize = 1, // Value does not persist
[Flags]
public enum ConsoleFlags
{
NoSerialize = 1, // Value does not persist
Alias = NoSerialize,
}
Alias = NoSerialize
}
internal struct ConsoleVariable
{
public string name { get; private set; }
public ConsoleFlags flags { get; private set; }
internal struct ConsoleVariable
{
public string name { get; }
public ConsoleFlags flags { get; }
private FieldInfo field;
private MethodInfo getter;
private MethodInfo setter;
private readonly FieldInfo field;
private readonly MethodInfo getter;
private readonly MethodInfo setter;
public ConsoleVariable(string name, ConsoleFlags flags, FieldInfo field)
{
this.name = name;
this.flags = flags;
this.field = field;
this.getter = null;
this.setter = null;
}
public ConsoleVariable(string name, ConsoleFlags flags, FieldInfo field)
{
this.name = name;
this.flags = flags;
this.field = field;
getter = null;
setter = null;
}
public ConsoleVariable(string name, ConsoleFlags flags, MethodInfo getter, MethodInfo setter)
{
this.name = name;
this.flags = flags;
this.field = null;
this.getter = getter;
this.setter = setter;
}
public ConsoleVariable(string name, ConsoleFlags flags, MethodInfo getter, MethodInfo setter)
{
this.name = name;
this.flags = flags;
field = null;
this.getter = getter;
this.setter = setter;
}
public string GetValueString()
{
var type = field != null ? field.FieldType : getter.ReturnType;
if (type == typeof(string))
{
if (field != null)
return (string) field.GetValue(null);
else if (setter != null)
return (string) getter.Invoke(null, null);
}
else
throw new Exception("cvar is not type of string");
public string GetValueString()
{
Type type = field != null ? field.FieldType : getter.ReturnType;
if (type == typeof(string))
{
if (field != null)
return (string)field.GetValue(null);
if (setter != null)
return (string)getter.Invoke(null, null);
}
else
{
throw new Exception("cvar is not type of string");
}
throw new Exception("GetValueString no field or getter specified");
}
throw new Exception("GetValueString no field or getter specified");
}
public void SetValue(string value)
{
var type = field != null ? field.FieldType : getter.ReturnType;
if (type == typeof(string))
{
if (field != null)
field.SetValue(null, value);
else if (setter != null)
setter.Invoke(null, new object[] {value});
}
else
throw new Exception("Unsupported type for SetValue: " + type.Name);
}
}
public void SetValue(string value)
{
Type type = field != null ? field.FieldType : getter.ReturnType;
if (type == typeof(string))
{
if (field != null)
field.SetValue(null, value);
else if (setter != null)
setter.Invoke(null, new object[] { value });
}
else
{
throw new Exception("Unsupported type for SetValue: " + type.Name);
}
}
}
}

View File

@@ -1,217 +1,209 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlaxEngine;
using FidelityFX;
using FlaxEngine;
namespace Cabrito
{
// Holds Console variables and commands to control engine behaviour
public static class EngineSubsystem
{
[ConsoleSubsystemInitializer]
public static void Initialize()
{
}
// Holds Console variables and commands to control engine behaviour
public static class EngineSubsystem
{
private static FSR _fsrPlugin;
[ConsoleCommand("quit", "exit")]
public static void ExitCommand()
{
Engine.RequestExit();
}
// TODO: this should manually set all postprocessing values to 0 or disabled
/*[ConsoleVariable("r_postprocessing")]
public static string PostProcessing
{
get
{
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
return postFx.CameraArtifacts.OverrideFlags.ToString();
return "";
}
set
{
bool valueBoolean = false;
if (int.TryParse(value, out int valueInt))
valueBoolean = valueInt != 0;
else
return;
[ConsoleCommand("debuglog")]
public static void DebugLogCommand(string[] text)
{
Debug.Log(string.Join(" ", text));
}
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
{
var cameraArtifacts = postFx.CameraArtifacts;
cameraArtifacts.OverrideFlags = valueBoolean ? CameraArtifactsSettingsOverride.None : CameraArtifactsSettingsOverride.All;
postFx.CameraArtifacts = cameraArtifacts;
}
}
}*/
// TODO: this should manually set all postprocessing values to 0 or disabled
/*[ConsoleVariable("r_postprocessing")]
public static string PostProcessing
{
get
{
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
return postFx.CameraArtifacts.OverrideFlags.ToString();
return "";
}
set
{
bool valueBoolean = false;
if (int.TryParse(value, out int valueInt))
valueBoolean = valueInt != 0;
else
return;
[ConsoleVariable("r_vignette")]
public static string Vignette
{
get
{
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
return postFx.CameraArtifacts.VignetteIntensity.ToString();
return "";
}
set
{
if (float.TryParse(value, out float valueFloat))
{
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
{
valueFloat = Mathf.Clamp(valueFloat, 0.0f, 2.0f);
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
{
var cameraArtifacts = postFx.CameraArtifacts;
cameraArtifacts.OverrideFlags = valueBoolean ? CameraArtifactsSettingsOverride.None : CameraArtifactsSettingsOverride.All;
postFx.CameraArtifacts = cameraArtifacts;
}
}
}*/
CameraArtifactsSettings cameraArtifacts = postFx.CameraArtifacts;
cameraArtifacts.VignetteIntensity = valueFloat;
postFx.CameraArtifacts = cameraArtifacts;
}
}
}
}
[ConsoleVariable("r_vignette")]
public static string Vignette
{
get
{
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
return postFx.CameraArtifacts.VignetteIntensity.ToString();
return "";
}
set
{
if (float.TryParse(value, out float valueFloat))
{
PostFxVolume postFx = Level.FindActor<PostFxVolume>();
if (postFx != null)
{
valueFloat = Mathf.Clamp(valueFloat, 0.0f, 2.0f);
[ConsoleVariable("cl_maxfps")]
public static string MaxFps
{
get => Time.UpdateFPS.ToString();
set
{
if (float.TryParse(value, out float valueFloat))
{
if (valueFloat <= 0.0f)
valueFloat = 0.0f;
else
valueFloat = Mathf.Clamp(valueFloat, 10f, 99999999999.0f);
var cameraArtifacts = postFx.CameraArtifacts;
cameraArtifacts.VignetteIntensity = valueFloat;
postFx.CameraArtifacts = cameraArtifacts;
}
}
}
}
if (Time.UpdateFPS != valueFloat)
Time.UpdateFPS = valueFloat;
if (Time.DrawFPS != valueFloat)
Time.DrawFPS = valueFloat;
}
}
}
[ConsoleVariable("cl_maxfps")]
public static string MaxFps
{
get { return Time.UpdateFPS.ToString(); }
set
{
if (float.TryParse(value, out float valueFloat))
{
if (valueFloat <= 0.0f)
valueFloat = 0.0f;
else
valueFloat = Mathf.Clamp(valueFloat, 10f, 99999999999.0f);
[ConsoleVariable("r_renderscale")]
public static string RenderScale
{
get => MainRenderTask.Instance.RenderingPercentage.ToString();
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.00001f, 4.0f);
MainRenderTask.Instance.RenderingPercentage = valueFloat;
}
}
}
if (Time.UpdateFPS != valueFloat)
Time.UpdateFPS = valueFloat;
if (Time.DrawFPS != valueFloat)
Time.DrawFPS = valueFloat;
}
}
}
public static FSR FsrPlugin
{
get
{
if (_fsrPlugin == null)
_fsrPlugin = PluginManager.GetPlugin<FSR>();
return _fsrPlugin;
}
}
[ConsoleVariable("r_renderscale")]
public static string RenderScale
{
get
{
return MainRenderTask.Instance.RenderingPercentage.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.00001f, 4.0f);
MainRenderTask.Instance.RenderingPercentage = valueFloat;
}
}
}
// TODO: r_upscaling
[ConsoleVariable("r_fsr_enabled")]
public static string FsrEnabled
{
get => FsrPlugin.PostFx.Enabled ? "1" : "0";
set
{
bool boolValue = false;
if (int.TryParse(value, out int intValue))
boolValue = intValue != 0;
else if (float.TryParse(value, out float valueFloat))
boolValue = valueFloat != 0f;
private static FSR _fsrPlugin;
public static FSR FsrPlugin
{
get
{
if (_fsrPlugin == null)
_fsrPlugin = PluginManager.GetPlugin<FSR>();
return _fsrPlugin;
}
}
FsrPlugin.PostFx.Enabled = boolValue;
}
}
// TODO: r_upscaling
[ConsoleVariable("r_fsr_enabled")]
public static string FsrEnabled
{
get
{
return FsrPlugin.PostFx.Enabled ? "1" : "0";
}
set
{
bool boolValue = false;
if (int.TryParse(value, out int intValue))
boolValue = intValue != 0;
else if (float.TryParse(value, out float valueFloat))
boolValue = valueFloat != 0f;
[ConsoleVariable("r_fsr_sharpness")]
public static string FsrSharpness
{
get
{
// In shader, the value of 0 is the max sharpness...
float sharpness = 2.0f - FsrPlugin.PostFx.Sharpness;
return sharpness.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0f, 2.0f);
FsrPlugin.PostFx.Sharpness = 2.0f - valueFloat;
}
}
}
FsrPlugin.PostFx.Enabled = boolValue;
}
}
[ConsoleVariable("cl_showweapon")]
public static string ShowWeapon
{
get => Level.FindActor("ViewModelCamera").IsActive ? "1" : "0";
set
{
bool boolValue = false;
if (int.TryParse(value, out int intValue))
boolValue = intValue != 0;
else if (float.TryParse(value, out float valueFloat))
boolValue = valueFloat != 0f;
[ConsoleVariable("r_fsr_sharpness")]
public static string FsrSharpness
{
get
{
// In shader, the value of 0 is the max sharpness...
float sharpness = 2.0f - FsrPlugin.PostFx.Sharpness;
return sharpness.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0f, 2.0f);
FsrPlugin.PostFx.Sharpness = 2.0f - valueFloat;
}
}
}
[ConsoleVariable("cl_showweapon")]
public static string ShowWeapon
{
get
{
return Level.FindActor("ViewModelCamera").IsActive ? "1" : "0";
}
set
{
bool boolValue = false;
if (int.TryParse(value, out int intValue))
boolValue = intValue != 0;
else if (float.TryParse(value, out float valueFloat))
boolValue = valueFloat != 0f;
Level.FindActor("ViewModelCamera").IsActive = boolValue;
}
}
Level.FindActor("ViewModelCamera").IsActive = boolValue;
}
}
// Horizontal field of view of the Camera
[ConsoleVariable("fov")]
public static string CameraFov
{
get
{
float valueFloat = Level.FindActor("PlayerCamera").As<Camera>().FieldOfView;
float horizontalFov = (float)(180.0f / Math.PI * (2*Math.Atan((4f/3f) * Math.Tan(Math.PI / 180.0f * valueFloat / 2.0f))));
return horizontalFov.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.01f, 360.0f);
// Horizontal field of view of the Camera
[ConsoleVariable("fov")]
public static string CameraFov
{
get
{
float valueFloat = Level.FindActor("PlayerCamera").As<Camera>().FieldOfView;
float horizontalFov = (float)(180.0f / Math.PI *
(2 * Math.Atan(4f / 3f *
Math.Tan(Math.PI / 180.0f * valueFloat / 2.0f))));
return horizontalFov.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.01f, 360.0f);
float verticalFov = (float)(180.0f / Math.PI * (2*Math.Atan((3f/4f) * Math.Tan(Math.PI / 180.0f * valueFloat / 2.0f))));
Level.FindActor("PlayerCamera").As<Camera>().FieldOfView = verticalFov;
}
}
}
}
float verticalFov = (float)(180.0f / Math.PI *
(2 * Math.Atan(3f / 4f *
Math.Tan(Math.PI / 180.0f * valueFloat / 2.0f))));
Level.FindActor("PlayerCamera").As<Camera>().FieldOfView = verticalFov;
}
}
}
[ConsoleSubsystemInitializer]
public static void Initialize()
{
}
[ConsoleCommand("quit", "exit")]
public static void ExitCommand()
{
Engine.RequestExit();
}
[ConsoleCommand("debuglog")]
public static void DebugLogCommand(string[] text)
{
Debug.Log(string.Join(" ", text));
}
}
}

View File

@@ -5,6 +5,11 @@ namespace Game
{
public static class Utilities
{
public static ScopeProfiler ProfileScope(string eventName)
{
return new ScopeProfiler(eventName);
}
public class ScopeProfiler : IDisposable
{
public ScopeProfiler(string eventName)
@@ -17,10 +22,5 @@ namespace Game
Profiler.EndEvent();
}
}
public static ScopeProfiler ProfileScope(string eventName)
{
return new ScopeProfiler(eventName);
}
}
}

View File

@@ -2,6 +2,5 @@
{
public abstract class GameMode
{
}
}

View File

@@ -1,5 +1,7 @@
using Cabrito;
using System;
using FlaxEngine;
using FlaxEngine.Networking;
using Console = Cabrito.Console;
namespace Game
{
@@ -8,6 +10,19 @@ namespace Game
public static void Init()
{
NetworkManager.OnMessage += OnClientConnected;
Level.SceneLoaded += OnLevelLoaded;
Console.Print("level was loaded: " + Level.IsAnySceneLoaded);
}
public static void Cleanup()
{
NetworkManager.OnMessage -= OnClientConnected;
Level.SceneLoaded -= OnLevelLoaded;
}
public static void OnLevelLoaded(Scene scene, Guid assetGuid)
{
Console.Print("level loaded");
}
public static bool OnClientConnected(NetworkMessage message)

View File

@@ -1,108 +1,104 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using FlaxEditor.Content.Settings;
using FlaxEngine;
using FlaxEngine.GUI;
namespace Cabrito
{
[ExecuteInEditMode]
public class FpsScript : Script
{
public UIControl control;
Label label;
[ExecuteInEditMode]
public class FpsScript : Script
{
private const double updateInterval = 0.25;
private const double drawInterval = 0.25;
private const double physicsInterval = 0.25;
Stopwatch sw;
double updateTimeAvg = 0.0;
ulong updateTimeCount;
const double updateInterval = 0.25;
double updateAccumTime = 0.0;
private double conTime;
public UIControl control;
Stopwatch sw2;
double drawTimeAvg = 0.0;
ulong drawTimeCount;
const double drawInterval = 0.25;
double drawAccumTime = 0.0;
private string currentRenderer = "Unknown";
private double drawAccumTime;
private double drawTimeAvg;
private ulong drawTimeCount;
private Label label;
private double physicsAccumTime;
private double physicsTimeAvg;
private ulong physicsTimeCount;
Stopwatch sw3;
double physicsTimeAvg = 0.0;
ulong physicsTimeCount;
const double physicsInterval = 0.25;
double physicsAccumTime = 0.0;
private Stopwatch sw;
Stopwatch sw0;
private Stopwatch sw0;
string currentRenderer = "Unknown";
private Stopwatch sw2;
RenderTask t;
private Stopwatch sw3;
TimeSettings timeSettings;
private RenderTask t;
public override void OnAwake()
{
label = (Label) control.Control;
private TimeSettings timeSettings;
private double updateAccumTime;
private double updateTimeAvg;
private ulong updateTimeCount;
sw = Stopwatch.StartNew();
sw2 = Stopwatch.StartNew();
sw3 = Stopwatch.StartNew();
sw0 = Stopwatch.StartNew();
public override void OnAwake()
{
label = (Label)control.Control;
currentRenderer = GPUDevice.Instance.RendererType.ToString();
sw = Stopwatch.StartNew();
sw2 = Stopwatch.StartNew();
sw3 = Stopwatch.StartNew();
sw0 = Stopwatch.StartNew();
if (t == null)
{
//Destroy(t);
t = new RenderTask();
t.Render += OnDraw;
}
currentRenderer = GPUDevice.Instance.RendererType.ToString();
var settings = FlaxEditor.Content.Settings.GameSettings.Load();
timeSettings = settings.Time.CreateInstance<FlaxEditor.Content.Settings.TimeSettings>();
}
if (t == null)
{
//Destroy(t);
t = new RenderTask();
t.Render += OnDraw;
}
public override void OnDestroy()
{
Destroy(t);
t = null;
}
GameSettings settings = GameSettings.Load();
timeSettings = settings.Time.CreateInstance<TimeSettings>();
}
double conTime = 0.0;
public override void OnDestroy()
{
Destroy(t);
t = null;
}
public override void OnUpdate()
{
updateAccumTime += Time.DeltaTime;
updateTimeCount++;
double elapsed = sw.Elapsed.TotalSeconds;
if (elapsed >= updateInterval)
{
sw.Restart();
updateTimeAvg = elapsed / updateTimeCount;
updateTimeCount = 0;
public override void OnUpdate()
{
updateAccumTime += Time.DeltaTime;
updateTimeCount++;
double elapsed = sw.Elapsed.TotalSeconds;
if (elapsed >= updateInterval)
{
sw.Restart();
updateTimeAvg = elapsed / updateTimeCount;
updateTimeCount = 0;
conTime = ((ConsoleContentTextBox.accumDrawTime / ConsoleContentTextBox.accumDrawTimes) * 1000.0);
ConsoleContentTextBox.accumDrawTime = 0.0;
ConsoleContentTextBox.accumDrawTimes = 0;
}
conTime = ConsoleContentTextBox.accumDrawTime / ConsoleContentTextBox.accumDrawTimes * 1000.0;
ConsoleContentTextBox.accumDrawTime = 0.0;
ConsoleContentTextBox.accumDrawTimes = 0;
}
StringBuilder sb = new StringBuilder();
sb.Append("eFPS: " + Engine.FramesPerSecond);
sb.Append(" uTime: " + sw0.Elapsed.TotalSeconds);
sb.Append("\nuFPS: " + ((int) Math.Round(1.0f / updateTimeAvg)));
sb.Append(" uTime: " + updateAccumTime);
sb.Append("\nrFPS: " + ((int) Math.Round(1.0f / drawTimeAvg)));
sb.Append(" rTime: " + drawAccumTime);
sb.Append("\npFPS: " + ((int) Math.Round(1.0f / physicsTimeAvg)));
sb.Append(" pTime: " + physicsAccumTime);
//sb.Append("\nCon: " + conTime.ToString() + "ms");
//sb.Append("\nGC memory: " + (GC.GetTotalMemory(false) / 1000000.0f).ToString() + "MB");
//sb.Append("\nUpdate profiler: " + updateProfTime.ToString() + "ms");
StringBuilder sb = new StringBuilder();
sb.Append("eFPS: " + Engine.FramesPerSecond);
sb.Append(" uTime: " + sw0.Elapsed.TotalSeconds);
sb.Append("\nuFPS: " + (int)Math.Round(1.0f / updateTimeAvg));
sb.Append(" uTime: " + updateAccumTime);
sb.Append("\nrFPS: " + (int)Math.Round(1.0f / drawTimeAvg));
sb.Append(" rTime: " + drawAccumTime);
sb.Append("\npFPS: " + (int)Math.Round(1.0f / physicsTimeAvg));
sb.Append(" pTime: " + physicsAccumTime);
//sb.Append("\nCon: " + conTime.ToString() + "ms");
//sb.Append("\nGC memory: " + (GC.GetTotalMemory(false) / 1000000.0f).ToString() + "MB");
//sb.Append("\nUpdate profiler: " + updateProfTime.ToString() + "ms");
#if false
#if false
#if BUILD_DEVELOPMENT
var nameOffset = Marshal.OffsetOf(typeof(ProfilerCPU.Event), "Name0");
foreach (var eventsCpu in FlaxEngine.ProfilingTools.EventsCPU)
@@ -132,54 +128,54 @@ namespace Cabrito
#endif
#endif
((Label) control.Control).Text = sb.ToString();
/*if (!Platform.HasFocus)
{
Time.UpdateFPS = 15;
Time.DrawFPS = 15;
Time.PhysicsFPS = 15;
}
((Label)control.Control).Text = sb.ToString();
/*if (!Platform.HasFocus)
{
Time.UpdateFPS = 15;
Time.DrawFPS = 15;
Time.PhysicsFPS = 15;
}
#if FLAX_EDITOR
else if (!FlaxEditor.Editor.IsPlayMode)
{
var editorFPS = FlaxEditor.Editor.Instance.Options.Options.General.EditorFPS;
Time.UpdateFPS = editorFPS;
Time.DrawFPS = editorFPS;
Time.PhysicsFPS = timeSettings.PhysicsFPS;
}
else if (!FlaxEditor.Editor.IsPlayMode)
{
var editorFPS = FlaxEditor.Editor.Instance.Options.Options.General.EditorFPS;
Time.UpdateFPS = editorFPS;
Time.DrawFPS = editorFPS;
Time.PhysicsFPS = timeSettings.PhysicsFPS;
}
#endif
else
{
Time.UpdateFPS = timeSettings.UpdateFPS;
Time.DrawFPS = timeSettings.DrawFPS;
Time.PhysicsFPS = timeSettings.PhysicsFPS;
}*/
}
else
{
Time.UpdateFPS = timeSettings.UpdateFPS;
Time.DrawFPS = timeSettings.DrawFPS;
Time.PhysicsFPS = timeSettings.PhysicsFPS;
}*/
}
public override void OnFixedUpdate()
{
physicsAccumTime += Time.DeltaTime;
physicsTimeCount++;
double elapsed = sw3.Elapsed.TotalSeconds;
if (elapsed >= physicsInterval)
{
sw3.Restart();
physicsTimeAvg = elapsed / physicsTimeCount;
physicsTimeCount = 0;
}
}
public override void OnFixedUpdate()
{
physicsAccumTime += Time.DeltaTime;
physicsTimeCount++;
double elapsed = sw3.Elapsed.TotalSeconds;
if (elapsed >= physicsInterval)
{
sw3.Restart();
physicsTimeAvg = elapsed / physicsTimeCount;
physicsTimeCount = 0;
}
}
void OnDraw(RenderTask tt, GPUContext context)
{
drawAccumTime += Time.DeltaTime;
drawTimeCount++;
double elapsed = sw2.Elapsed.TotalSeconds;
if (elapsed >= drawInterval)
{
sw2.Restart();
drawTimeAvg = elapsed / drawTimeCount;
drawTimeCount = 0;
}
}
}
private void OnDraw(RenderTask tt, GPUContext context)
{
drawAccumTime += Time.DeltaTime;
drawTimeCount++;
double elapsed = sw2.Elapsed.TotalSeconds;
if (elapsed >= drawInterval)
{
sw2.Restart();
drawTimeAvg = elapsed / drawTimeCount;
drawTimeCount = 0;
}
}
}
}

View File

@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using FlaxEngine;
using FlaxEngine;
namespace Game
{
/// <summary>
/// List of supported materials for loaded levels.
/// Maps the given texture/shader name to Flax Material/MaterialInstance.
/// List of supported materials for loaded levels.
/// Maps the given texture/shader name to Flax Material/MaterialInstance.
/// </summary>
public class BrushMaterialList
{
@@ -16,12 +14,10 @@ namespace Game
public struct BrushMaterialListEntry
{
[EditorOrder(1)]
[EditorDisplay(name: "Name")]
[EditorOrder(1)] [EditorDisplay(name: "Name")]
public string name;
[EditorOrder(2)]
[EditorDisplay(name: "Material")]
[EditorOrder(2)] [EditorDisplay(name: "Material")]
public MaterialBase asset;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
#if false
using System;
using System.Collections.Generic;
using System.Linq;
@@ -855,7 +854,8 @@ namespace Game
Vector3 nextVertex = qhe.next.tail;
Vector3 edgeVector = (nextVertex - vertex).Normalized;
Vector3 outVector = Vector3.Cross(-(new Plane(mergedFace.v1, mergedFace.v2, mergedFace.v3).Normal), edgeVector);
Vector3 outVector =
Vector3.Cross(-(new Plane(mergedFace.v1, mergedFace.v2, mergedFace.v3).Normal), edgeVector);
HalfEdge testHe = qhe.next;
do
@@ -1125,7 +1125,7 @@ namespace Game
foreach (var dface in discardedFaces)
{
for (int i=0; i<outsideSet.Count; i++)
for (int i = 0; i<outsideSet.Count; i++)
{
if (outsideSet[i].Item1 == dface)
{

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,15 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using FlaxEditor;
using FlaxEngine;
using FlaxEngine.Networking;
using Console = Cabrito.Console;
using Debug = FlaxEngine.Debug;
namespace Game
{
[AttributeUsage(AttributeTargets.Class)]
public class NetworkPredictedAttribute : Attribute
{
public NetworkPredictedAttribute()
{
}
}
// TODO: insert code to update variables with this attribute?
@@ -24,9 +17,6 @@ namespace Game
[AttributeUsage(AttributeTargets.Class)]
public class NetworkedAttribute : Attribute
{
public NetworkedAttribute()
{
}
}
// NetworkMulticastAttribute: calls methods marked with this in all clients
@@ -34,24 +24,23 @@ namespace Game
public enum NetworkMessageType : byte
{
Handshake = 1,
Message,
Message
}
public static partial class NetworkManager
{
private static bool initialized = false;
public delegate bool OnMessageDecl(NetworkMessage message);
private static bool initialized;
private static NetworkPeer server;
private static NetworkPeer client;
private static ushort ServerPort = 59183;
private static string ServerAddress = null;
private static ushort MTU = 1500;
private static ushort MaximumClients = 32;
public delegate bool OnMessageDecl(NetworkMessage message);
private static readonly ushort ServerPort = 59183;
private static string ServerAddress;
private static readonly ushort MTU = 1500;
private static readonly ushort MaximumClients = 32;
public static OnMessageDecl OnMessage;
public static void Init()
@@ -79,14 +68,18 @@ namespace Game
initialized = true;
GameModeManager.Init(); // FIXME
#if FLAX_EDITOR
Editor.Instance.PlayModeEnd += Cleanup;
#endif
}
public static void Deinitialize()
public static void Cleanup()
{
if (server != null)
{
Scripting.FixedUpdate -= OnServerUpdate;
Scripting.Exit -= Deinitialize;
Scripting.Exit -= Cleanup;
Level.ActorSpawned -= OnServerActorSpawned;
NetworkPeer.ShutdownPeer(server);
server = null;
@@ -95,11 +88,16 @@ namespace Game
if (client != null)
{
Scripting.FixedUpdate -= OnClientUpdate;
Scripting.Exit -= Deinitialize;
Scripting.Exit -= Cleanup;
Level.ActorSpawned -= OnClientActorSpawned;
NetworkPeer.ShutdownPeer(client);
client = null;
}
#if FLAX_EDITOR
Editor.Instance.PlayModeEnd -= Cleanup;
GameModeManager.Cleanup();
#endif
}
private static void OnNetworkMessage(NetworkEvent networkEvent)
@@ -117,14 +115,13 @@ namespace Game
{
case NetworkMessageType.Handshake:
{
var message = networkEvent.Message.ReadString();
string message = networkEvent.Message.ReadString();
Console.Print($"Received handshake from {networkEvent.Sender.ConnectionId}, msg: " + message);
break;
}
case NetworkMessageType.Message:
{
if (OnMessage != null)
{
foreach (OnMessageDecl func in OnMessage.GetInvocationList()
.Cast<OnMessageDecl>().ToArray())
{
@@ -132,7 +129,7 @@ namespace Game
if (ret)
break;
}
}
break;
}
default:

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using FlaxEngine;
using Console = Cabrito.Console;
#if FLAX_EDITOR
using FlaxEditor;
#endif
@@ -11,51 +9,51 @@ namespace Game
{
public class NetworkManagerPlugin : GamePlugin
{
public override void Initialize()
{
base.Initialize();
Debug.Log("NetworkManagerPlugin Initialize");
Console.Init();
NetworkManager.Init();
Level.SceneLoaded += (scene, guid) => Console.Print("scene loaded: " + scene.Name);
}
public override void Deinitialize()
{
base.Deinitialize();
Debug.Log("NetworkManagerPlugin Deinitialize");
}
public static PluginDescription DescriptionInternal = new PluginDescription()
public static PluginDescription DescriptionInternal = new PluginDescription
{
Author = "Ari Vuollet",
Name = "NetworkManager",
Description = "NetworkManager for Goake",
Version = Version.Parse("0.1.0"),
IsAlpha = true,
Category = "Game",
Category = "Game"
};
public override void Initialize()
{
base.Initialize();
Debug.Log("NetworkManagerPlugin Initialize");
Console.Init();
NetworkManager.Init();
}
public override void Deinitialize()
{
base.Deinitialize();
Debug.Log("NetworkManagerPlugin Deinitialize");
}
}
#if FLAX_EDITOR
public class NetworkManagerEditorPlugin : EditorPlugin
{
public override void Initialize()
{
Debug.Log("NetworkManagerEditorPlugin Initialize");
Console.Init();
}
public class NetworkManagerEditorPlugin : EditorPlugin
{
public override PluginDescription Description => NetworkManagerPlugin.DescriptionInternal;
public override void Deinitialize()
{
Debug.Log("NetworkManagerEditorPlugin Deinitialize");
}
public override Type GamePluginType => typeof(NetworkManagerPlugin);
public override PluginDescription Description => NetworkManagerPlugin.DescriptionInternal;
public override void Initialize()
{
Debug.Log("NetworkManagerEditorPlugin Initialize");
Console.Init();
public override Type GamePluginType => typeof(NetworkManagerPlugin);
}
NetworkManager.Init();
}
public override void Deinitialize()
{
Debug.Log("NetworkManagerEditorPlugin Deinitialize");
}
}
#endif
}

View File

@@ -1,29 +1,25 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using FlaxEngine;
using FlaxEngine.Networking;
using Console = Cabrito.Console;
using Debug = FlaxEngine.Debug;
using Object = FlaxEngine.Object;
namespace Game
{
public static partial class NetworkManager
{
public static uint LocalPlayerClientId { get; private set; } = 0;
public static uint LocalPlayerClientId { get; private set; }
public static bool ConnectServer()
{
client = NetworkPeer.CreatePeer(new NetworkConfig
{
NetworkDriver = FlaxEngine.Object.New(typeof(ENetDriver)),
NetworkDriver = Object.New(typeof(ENetDriver)),
ConnectionsLimit = MaximumClients,
MessagePoolSize = 2048,
MessageSize = MTU,
Address = ServerAddress == "localhost" ? "127.0.0.1" : ServerAddress,
Port = ServerPort,
Port = ServerPort
});
if (!client.Connect())
{
@@ -32,17 +28,16 @@ namespace Game
}
Scripting.FixedUpdate += OnClientUpdate;
Scripting.Exit += Deinitialize;
Scripting.Exit += Cleanup;
Level.ActorSpawned += OnClientActorSpawned;
return true;
}
private static void OnClientUpdate()
{
using var _ = Utilities.ProfileScope("NetworkManager_OnClientUpdate");
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnClientUpdate");
while (client.PopEvent(out NetworkEvent networkEvent))
{
switch (networkEvent.EventType)
{
case NetworkEventType.Connected:
@@ -66,18 +61,17 @@ namespace Game
case NetworkEventType.Message:
{
OnNetworkMessage(networkEvent);
client.RecycleMessage(networkEvent.Message);
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
}
private static void OnClientActorSpawned(Actor actor)
{
}
}
}

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using FlaxEngine;
using FlaxEngine.Networking;
using Console = Cabrito.Console;
using Debug = FlaxEngine.Debug;
using Object = FlaxEngine.Object;
namespace Game
{
@@ -23,7 +20,7 @@ namespace Game
ConnectedClients = new List<NetworkConnection>(MaximumClients);
server = NetworkPeer.CreatePeer(new NetworkConfig
{
NetworkDriver = FlaxEngine.Object.New(typeof(ENetDriver)),
NetworkDriver = Object.New(typeof(ENetDriver)),
ConnectionsLimit = MaximumClients,
MessagePoolSize = 2048,
MessageSize = MTU,
@@ -37,18 +34,18 @@ namespace Game
}
Scripting.FixedUpdate += OnServerUpdate;
Scripting.Exit += Deinitialize;
Level.ActorSpawned += OnClientActorSpawned;
Scripting.Exit += Cleanup;
Level.ActorSpawned += OnServerActorSpawned;
NetworkedTypes = new List<Type>();
AppDomain currentDomain = AppDomain.CurrentDomain;
Assembly[] assemblies = currentDomain.GetAssemblies();
var assemblies = currentDomain.GetAssemblies();
foreach (var assembly in assemblies)
foreach (Assembly assembly in assemblies)
{
// Skip common assemblies
var assemblyName = assembly.GetName().Name;
string assemblyName = assembly.GetName().Name;
if (assemblyName == "System" ||
assemblyName.StartsWith("System.") ||
assemblyName.StartsWith("Mono.") ||
@@ -58,31 +55,24 @@ namespace Game
assemblyName.StartsWith("JetBrains.") ||
assemblyName.StartsWith("Microsoft.") ||
assemblyName.StartsWith("nunit."))
{
continue;
}
foreach (var type in assembly.GetTypes())
{
foreach (Type type in assembly.GetTypes())
if (type.GetCustomAttributes().Any(x => x is NetworkedAttribute))
NetworkedTypes.Add(type);
}
}
foreach (Type type in NetworkedTypes)
{
Console.Print("tracking networked type: " + type.Name);
}
return true;
}
private static void OnServerUpdate()
{
using var _ = Utilities.ProfileScope("NetworkManager_OnServerUpdate");
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnServerUpdate");
while (server.PopEvent(out NetworkEvent networkEvent))
{
switch (networkEvent.EventType)
{
case NetworkEventType.Connected:
@@ -119,12 +109,11 @@ namespace Game
default:
throw new ArgumentOutOfRangeException();
}
}
}
private static void OnServerActorSpawned(Actor actor)
{
Console.Print($"actor spawned: {actor.Name} ({actor.TypeName})");
//Console.Print($"actor spawned: {actor.Name} ({actor.TypeName})");
}
}
}

View File

@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using FlaxEngine;
using FlaxEngine;
namespace Game
{
public class CustomCharacterController : CharacterController
{
}
public class CustomCharacterController : CharacterController
{
}
}

View File

@@ -1,30 +1,29 @@
using System.Collections.Generic;
using Cabrito;
using FlaxEngine;
using Cabrito;
namespace Game
{
public static class InputManager
{
public static bool GetAction(string name)
{
if (Console.IsOpen)
return false;
return Input.GetAction(name);
}
public static class InputManager
{
public static bool GetAction(string name)
{
if (Console.IsOpen)
return false;
return Input.GetAction(name);
}
public static float GetAxis(string name)
{
if (Console.IsOpen)
return 0.0f;
return Input.GetAxis(name);
}
public static float GetAxis(string name)
{
if (Console.IsOpen)
return 0.0f;
return Input.GetAxis(name);
}
public static float GetAxisRaw(string name)
{
if (Console.IsOpen)
return 0.0f;
return Input.GetAxisRaw(name);
}
}
public static float GetAxisRaw(string name)
{
if (Console.IsOpen)
return 0.0f;
return Input.GetAxisRaw(name);
}
}
}

View File

@@ -1,12 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using FlaxEngine;
using Cabrito;
#if FLAX_EDITOR
using FlaxEditor.CustomEditors.Dedicated;
using FlaxEditor.Scripting;
#endif
using FlaxEngine.GUI;
namespace Game
{
@@ -16,16 +13,16 @@ namespace Game
{
protected override List<ItemInfo> GetItemsForType(ScriptType type)
{
List<ItemInfo> items = GetItemsForType(type, type.IsClass, true);
var items = GetItemsForType(type, type.IsClass, true);
// Remove all Rigid Body options
items.RemoveAll(x => x.Display.Group == "Rigid Body");
// Inject scripts editor
var scriptsMember = type.GetProperty("Scripts");
ScriptMemberInfo scriptsMember = type.GetProperty("Scripts");
if (scriptsMember != ScriptMemberInfo.Null)
{
var item = new ItemInfo(scriptsMember)
ItemInfo item = new ItemInfo(scriptsMember)
{
CustomEditor = new CustomEditorAttribute(typeof(ScriptsEditor))
};

View File

@@ -1,75 +1,70 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
using FlaxEngine;
namespace Game
{
[StructLayout(LayoutKind.Sequential)]
public struct PlayerInputState
{
public ulong frame;
public float viewDeltaX, viewDeltaY;
public float moveForward;
public float moveRight;
public bool attacking;
public bool jumping;
[StructLayout(LayoutKind.Sequential)]
public struct PlayerInputState
{
public ulong frame;
public float viewDeltaX, viewDeltaY;
public float moveForward;
public float moveRight;
public bool attacking;
public bool jumping;
public Vector3 verificationPosition;
public Vector3 verificationVelocity;
public Vector3 verificationViewAngles;
public Quaternion verificationOrientation;
}
public Vector3 verificationPosition;
public Vector3 verificationVelocity;
public Vector3 verificationViewAngles;
public Quaternion verificationOrientation;
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerActorState
{
public Vector3 position;
public Vector3 velocity;
public Quaternion orientation;
public Vector3 viewAngles; // yaw, pitch, roll
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerActorState
{
public Vector3 position;
public Vector3 velocity;
public Quaternion orientation;
public Vector3 viewAngles; // yaw, pitch, roll
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerState
{
public PlayerInputState input;
public PlayerActorState actor;
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerState
{
public PlayerInputState input;
public PlayerActorState actor;
}
public class PlayerInput
{
public PlayerState currentState;
public ulong frame;
public class PlayerInput
{
public const byte DemoVer = 1;
public PlayerState currentState;
public ulong frame;
public const byte DemoVer = 1;
public virtual void OnUpdate()
{
}
public virtual void OnUpdate()
{
}
public virtual void OnFixedUpdate()
{
}
public virtual void OnFixedUpdate()
{
}
public virtual void OnEndFrame()
{
}
public virtual void OnEndFrame()
{
}
public virtual void RecordCurrentActorState(PlayerActorState actorState)
{
}
public virtual void RecordCurrentActorState(PlayerActorState actorState)
{
}
public PlayerInputState GetCurrentInputState()
{
return currentState.input;
}
public PlayerInputState GetCurrentInputState()
{
return currentState.input;
}
public PlayerActorState GetCurrentActorState()
{
return currentState.actor;
}
}
public PlayerActorState GetCurrentActorState()
{
return currentState.actor;
}
}
}

View File

@@ -2,88 +2,89 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
using Console = Cabrito.Console;
namespace Game
{
public class PlayerInputDemo : PlayerInput
{
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
protected IEnumerator<PlayerInputState> bufferEnumerable;
public class PlayerInputDemo : PlayerInput
{
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
protected IEnumerator<PlayerInputState> bufferEnumerable;
public PlayerInputDemo(string demoPath)
{
if (!File.Exists(demoPath))
return;
public PlayerInputDemo(string demoPath)
{
if (!File.Exists(demoPath))
return;
var expectedPlayerInputStateSize = Marshal.SizeOf(typeof(PlayerInputState));
int expectedPlayerInputStateSize = Marshal.SizeOf(typeof(PlayerInputState));
var stream = File.OpenRead(demoPath);
var ver = (int)stream.ReadByte();
var inputStateSize = (int)stream.ReadByte();
if (ver != DemoVer && inputStateSize != expectedPlayerInputStateSize)
{
Console.Print("demover mismatch: version " + ver + " != " + DemoVer + ", inputStateSize " + inputStateSize + " != " + Marshal.SizeOf(typeof(PlayerInputState)));
stream.Close();
return;
}
FileStream stream = File.OpenRead(demoPath);
int ver = stream.ReadByte();
int inputStateSize = stream.ReadByte();
if (ver != DemoVer && inputStateSize != expectedPlayerInputStateSize)
{
Console.Print("demover mismatch: version " + ver + " != " + DemoVer + ", inputStateSize " +
inputStateSize + " != " + Marshal.SizeOf(typeof(PlayerInputState)));
stream.Close();
return;
}
T RawDeserialize<T>(byte[] rawData, int position)
{
int rawsize = Marshal.SizeOf(typeof(T));
if (rawsize > rawData.Length - position)
throw new ArgumentException("Not enough data to fill struct. Array length from position: " + (rawData.Length-position) + ", Struct length: " + rawsize);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
T retobj = (T)Marshal.PtrToStructure(buffer, typeof(T));
Marshal.FreeHGlobal(buffer);
return retobj;
}
T RawDeserialize<T>(byte[] rawData, int position)
{
int rawsize = Marshal.SizeOf(typeof(T));
if (rawsize > rawData.Length - position)
throw new ArgumentException("Not enough data to fill struct. Array length from position: " +
(rawData.Length - position) + ", Struct length: " + rawsize);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
T retobj = (T)Marshal.PtrToStructure(buffer, typeof(T));
Marshal.FreeHGlobal(buffer);
return retobj;
}
while (true)
{
byte[] b = new byte[expectedPlayerInputStateSize];
var readBytes = stream.Read(b, 0, b.Length);
if (readBytes < expectedPlayerInputStateSize)
break;
while (true)
{
byte[] b = new byte[expectedPlayerInputStateSize];
int readBytes = stream.Read(b, 0, b.Length);
if (readBytes < expectedPlayerInputStateSize)
break;
buffer.Add(RawDeserialize<PlayerInputState>(b, 0));
}
buffer.Add(RawDeserialize<PlayerInputState>(b, 0));
}
bufferEnumerable = buffer.GetEnumerator();
bufferEnumerable = buffer.GetEnumerator();
Console.Print("demo numstates: " + buffer.Count);
Console.Print("demo numstates: " + buffer.Count);
OnEndFrame(); // advances to first frame
}
OnEndFrame(); // advances to first frame
}
public override void OnEndFrame()
{
// TODO: check if the current state frame matches the current frame number before advancing
public override void OnEndFrame()
{
// TODO: check if the current state frame matches the current frame number before advancing
/*asdf++;
if (asdf < 8)
return;*/
/*asdf++;
if (asdf < 8)
return;*/
if (bufferEnumerable == null || !bufferEnumerable.MoveNext())
{
if (buffer.Any())
{
bufferEnumerable.Dispose();
bufferEnumerable = null;
buffer.Clear();
Console.Print("Demo ended");
}
return;
}
if (bufferEnumerable == null || !bufferEnumerable.MoveNext())
{
if (buffer.Any())
{
bufferEnumerable.Dispose();
bufferEnumerable = null;
buffer.Clear();
Console.Print("Demo ended");
}
//var actorState = currentState.actor;
currentState.input = bufferEnumerable.Current;
//frame++;
//currentState.actor = actorState;
}
}
return;
}
//var actorState = currentState.actor;
currentState.input = bufferEnumerable.Current;
//frame++;
//currentState.actor = actorState;
}
}
}

View File

@@ -1,117 +1,116 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
using Console = Cabrito.Console;
namespace Game
{
public class PlayerInputLocal : PlayerInput
{
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
protected FileStream demoFileStream;
public class PlayerInputLocal : PlayerInput
{
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
protected FileStream demoFileStream;
public bool IsRecording { get { return demoFileStream != null; } }
public PlayerInputLocal()
{
}
public PlayerInputLocal()
{
}
public PlayerInputLocal(string demoPath)
{
demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write);
//stream.Position = 0;
//stream.SetLength(0);
demoFileStream.WriteByte(DemoVer);
demoFileStream.WriteByte((byte)Marshal.SizeOf(typeof(PlayerInputState)));
}
public PlayerInputLocal(string demoPath)
{
demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write);
//stream.Position = 0;
//stream.SetLength(0);
demoFileStream.WriteByte(DemoVer);
demoFileStream.WriteByte((byte)Marshal.SizeOf(typeof(PlayerInputState)));
}
public bool IsRecording => demoFileStream != null;
public override void OnUpdate()
{
// Collect all input here
// All axis values here should be accumulated
currentState.input.viewDeltaX += InputManager.GetAxisRaw("Mouse X");
currentState.input.viewDeltaY += InputManager.GetAxisRaw("Mouse Y");
currentState.input.viewDeltaX += InputManager.GetAxisRaw("LookRight") * Time.DeltaTime * 100;
currentState.input.viewDeltaY += -InputManager.GetAxisRaw("LookUp") * Time.DeltaTime * 100;
public override void OnUpdate()
{
// Collect all input here
// All axis values here should be accumulated
currentState.input.viewDeltaX += InputManager.GetAxisRaw("Mouse X");
currentState.input.viewDeltaY += InputManager.GetAxisRaw("Mouse Y");
currentState.input.viewDeltaX += InputManager.GetAxisRaw("LookRight") * Time.DeltaTime * 100;
currentState.input.viewDeltaY += -InputManager.GetAxisRaw("LookUp") * Time.DeltaTime * 100;
currentState.input.moveForward = InputManager.GetAxis("Vertical");
currentState.input.moveRight = InputManager.GetAxis("Horizontal");
currentState.input.attacking = InputManager.GetAction("Attack");
currentState.input.jumping = InputManager.GetAction("Jump");
}
currentState.input.moveForward = InputManager.GetAxis("Vertical");
currentState.input.moveRight = InputManager.GetAxis("Horizontal");
currentState.input.attacking = InputManager.GetAction("Attack");
currentState.input.jumping = InputManager.GetAction("Jump");
}
public override void OnFixedUpdate()
{
}
public override void OnFixedUpdate()
{
}
public override void OnEndFrame()
{
if (IsRecording)
{
currentState.input.verificationPosition = currentState.actor.position;
currentState.input.verificationVelocity = currentState.actor.velocity;
currentState.input.verificationViewAngles = currentState.actor.viewAngles;
currentState.input.verificationOrientation = currentState.actor.orientation;
public override void OnEndFrame()
{
if (IsRecording)
{
currentState.input.verificationPosition = currentState.actor.position;
currentState.input.verificationVelocity = currentState.actor.velocity;
currentState.input.verificationViewAngles = currentState.actor.viewAngles;
currentState.input.verificationOrientation = currentState.actor.orientation;
currentState.input.frame = frame;
buffer.Add(currentState.input);
}
currentState.input.frame = frame;
buffer.Add(currentState.input);
}
// Reset anything accumulatable here
currentState.input.viewDeltaX = 0;
currentState.input.viewDeltaY = 0;
// Reset anything accumulatable here
currentState.input.viewDeltaX = 0;
currentState.input.viewDeltaY = 0;
frame++;
}
frame++;
}
public override void RecordCurrentActorState(PlayerActorState actorState)
{
if (!IsRecording)
return;
public override void RecordCurrentActorState(PlayerActorState actorState)
{
if (!IsRecording)
return;
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
}
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
}
public void FlushDemo()
{
if (!IsRecording)
return;
public void FlushDemo()
{
if (!IsRecording)
return;
byte[] RawSerialize(object anything)
{
int rawSize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawSize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawDatas = new byte[rawSize];
Marshal.Copy(buffer, rawDatas, 0, rawSize);
Marshal.FreeHGlobal(buffer);
return rawDatas;
}
byte[] RawSerialize(object anything)
{
int rawSize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawSize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawDatas = new byte[rawSize];
Marshal.Copy(buffer, rawDatas, 0, rawSize);
Marshal.FreeHGlobal(buffer);
return rawDatas;
}
foreach (var state in buffer)
{
var bytes = RawSerialize(state);
demoFileStream.Write(bytes, 0, bytes.Length * sizeof(byte));
}
foreach (PlayerInputState state in buffer)
{
byte[] bytes = RawSerialize(state);
demoFileStream.Write(bytes, 0, bytes.Length * sizeof(byte));
}
buffer.Clear();
}
buffer.Clear();
}
public void StopRecording()
{
if (!IsRecording)
return;
public void StopRecording()
{
if (!IsRecording)
return;
FlushDemo();
demoFileStream.Close();
demoFileStream = null;
FlushDemo();
demoFileStream.Close();
demoFileStream = null;
Debug.Write(LogType.Info, "demo, wrote states: " + buffer.Count);
}
}
Debug.Write(LogType.Info, "demo, wrote states: " + buffer.Count);
}
}
}

View File

@@ -1,14 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
namespace Game
namespace Game
{
public class PlayerInputNetwork : PlayerInput
{
}
public class PlayerInputNetwork : PlayerInput
{
}
}

File diff suppressed because it is too large Load Diff