broken
This commit is contained in:
@@ -7,45 +7,45 @@ namespace RebootKit.Engine.Services.Console {
|
||||
|
||||
[Serializable]
|
||||
public struct CVarValue {
|
||||
public CVarValueKind Kind;
|
||||
public CVarValueKind kind;
|
||||
|
||||
public double NumberValue;
|
||||
public string StringValue;
|
||||
public double numberValue;
|
||||
public string stringValue;
|
||||
|
||||
public CVarValue(int value) {
|
||||
Kind = CVarValueKind.Number;
|
||||
NumberValue = value;
|
||||
StringValue = null;
|
||||
kind = CVarValueKind.Number;
|
||||
numberValue = value;
|
||||
stringValue = null;
|
||||
}
|
||||
|
||||
public CVarValue(float value) {
|
||||
Kind = CVarValueKind.Number;
|
||||
NumberValue = value;
|
||||
StringValue = null;
|
||||
kind = CVarValueKind.Number;
|
||||
numberValue = value;
|
||||
stringValue = null;
|
||||
}
|
||||
|
||||
public CVarValue(double value) {
|
||||
Kind = CVarValueKind.Number;
|
||||
NumberValue = value;
|
||||
StringValue = null;
|
||||
kind = CVarValueKind.Number;
|
||||
numberValue = value;
|
||||
stringValue = null;
|
||||
}
|
||||
|
||||
public CVarValue(string value) {
|
||||
Kind = CVarValueKind.String;
|
||||
NumberValue = 0;
|
||||
StringValue = value;
|
||||
kind = CVarValueKind.String;
|
||||
numberValue = 0;
|
||||
stringValue = value;
|
||||
}
|
||||
|
||||
public void CopyFrom(CVarValue value) {
|
||||
Kind = value.Kind;
|
||||
NumberValue = value.NumberValue;
|
||||
StringValue = value.StringValue;
|
||||
kind = value.kind;
|
||||
numberValue = value.numberValue;
|
||||
stringValue = value.stringValue;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return Kind switch {
|
||||
CVarValueKind.Number => NumberValue.ToString(),
|
||||
CVarValueKind.String => $"\"{StringValue}\"",
|
||||
return kind switch {
|
||||
CVarValueKind.Number => numberValue.ToString(),
|
||||
CVarValueKind.String => $"\"{stringValue}\"",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
@@ -58,108 +58,98 @@ namespace RebootKit.Engine.Services.Console {
|
||||
|
||||
[Serializable]
|
||||
public class CVar {
|
||||
public CVarFlags Flags;
|
||||
public string Name;
|
||||
public string Description;
|
||||
public CVarValue DefaultValue;
|
||||
public CVarValue Value { get; private set; }
|
||||
|
||||
public int IndexValue => (int) Value.NumberValue;
|
||||
public float FloatValue => (float) Value.NumberValue;
|
||||
public double NumberValue => Value.NumberValue;
|
||||
public string StringValue => Value.StringValue;
|
||||
|
||||
public event Action OnChanged = delegate { };
|
||||
public CVarFlags flags;
|
||||
public string name;
|
||||
public string description;
|
||||
public CVarValue defaultValue;
|
||||
|
||||
public CVar(CVar other) {
|
||||
Flags = other.Flags;
|
||||
Name = other.Name;
|
||||
Description = other.Description;
|
||||
DefaultValue = other.DefaultValue;
|
||||
flags = other.flags;
|
||||
name = other.name;
|
||||
description = other.description;
|
||||
defaultValue = other.defaultValue;
|
||||
Value = other.Value;
|
||||
}
|
||||
|
||||
public CVar(string name, CVarValue value, string description = "") {
|
||||
Name = name;
|
||||
Description = description;
|
||||
DefaultValue = value;
|
||||
Value = DefaultValue;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
defaultValue = value;
|
||||
Value = defaultValue;
|
||||
}
|
||||
|
||||
public CVar(string name, int value, string description = "") {
|
||||
Name = name;
|
||||
Description = description;
|
||||
DefaultValue = new CVarValue(value);
|
||||
Value = DefaultValue;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
defaultValue = new CVarValue(value);
|
||||
Value = defaultValue;
|
||||
}
|
||||
|
||||
public CVar(string name, float value, string description = "") {
|
||||
Name = name;
|
||||
Description = description;
|
||||
DefaultValue = new CVarValue(value);
|
||||
Value = DefaultValue;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
defaultValue = new CVarValue(value);
|
||||
Value = defaultValue;
|
||||
}
|
||||
|
||||
public CVar(string name, double value, string description = "") {
|
||||
Name = name;
|
||||
Description = description;
|
||||
DefaultValue = new CVarValue(value);
|
||||
Value = DefaultValue;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
defaultValue = new CVarValue(value);
|
||||
Value = defaultValue;
|
||||
}
|
||||
|
||||
public CVar(string name, string value, string description = "") {
|
||||
Name = name;
|
||||
Description = description;
|
||||
DefaultValue = new CVarValue(value);
|
||||
Value = DefaultValue;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
defaultValue = new CVarValue(value);
|
||||
Value = defaultValue;
|
||||
}
|
||||
|
||||
public CVarValue Value { get; private set; }
|
||||
|
||||
public int IndexValue => (int) Value.numberValue;
|
||||
public float FloatValue => (float) Value.numberValue;
|
||||
public double NumberValue => Value.numberValue;
|
||||
public string StringValue => Value.stringValue;
|
||||
|
||||
public event Action StateChanged = delegate { };
|
||||
|
||||
public void Set(int value) {
|
||||
if (Flags.HasFlag(CVarFlags.ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
|
||||
|
||||
Value = new CVarValue(value);
|
||||
OnChanged?.Invoke();
|
||||
StateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Set(float value) {
|
||||
if (Flags.HasFlag(CVarFlags.ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
|
||||
|
||||
Value = new CVarValue(value);
|
||||
OnChanged?.Invoke();
|
||||
StateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Set(string value) {
|
||||
if (Flags.HasFlag(CVarFlags.ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
|
||||
|
||||
Value = new CVarValue(value);
|
||||
OnChanged?.Invoke();
|
||||
StateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void ParseFromString(string str) {
|
||||
if (Flags.HasFlag(CVarFlags.ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
|
||||
|
||||
if (float.TryParse(str, out float f)) {
|
||||
if (float.TryParse(str, out float f))
|
||||
Set(f);
|
||||
} else {
|
||||
else
|
||||
Set(str);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset() {
|
||||
if (Flags.HasFlag(CVarFlags.ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
if (flags.HasFlag(CVarFlags.ReadOnly)) return;
|
||||
|
||||
Value = DefaultValue;
|
||||
OnChanged?.Invoke();
|
||||
Value = defaultValue;
|
||||
StateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
[CreateAssetMenu(menuName = RConsts.AssetMenu + "cvar", fileName = "cvar")]
|
||||
[CreateAssetMenu(menuName = RConsts.k_AddComponentMenu + "cvar", fileName = "cvar")]
|
||||
public class CVarAsset : ScriptableObject {
|
||||
[SerializeField]
|
||||
private CVar _cvar;
|
||||
[SerializeField] CVar m_CVar;
|
||||
|
||||
public CVar Create(string cvarName = null) {
|
||||
CVar cvar = new(_cvar);
|
||||
CVar cvar = new(m_CVar);
|
||||
|
||||
if (cvarName != null) {
|
||||
cvar.Name = cvarName;
|
||||
}
|
||||
if (cvarName != null) cvar.name = cvarName;
|
||||
|
||||
return cvar;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@ using RebootKit.Engine.Foundation;
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class CVarAttribute : Attribute {
|
||||
public string Name { get; }
|
||||
public CVarValue Value { get; }
|
||||
|
||||
public CVarAttribute(string name, float defaultValue) {
|
||||
Name = name;
|
||||
Value = new CVarValue(defaultValue);
|
||||
@@ -27,19 +24,20 @@ namespace RebootKit.Engine.Services.Console {
|
||||
Name = name;
|
||||
Value = new CVarValue(defaultValue);
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public CVarValue Value { get; }
|
||||
}
|
||||
|
||||
public class CVarFieldInjector : DIContext.IFieldInjector {
|
||||
private static readonly Logger Logger = new(nameof(CVarFieldInjector));
|
||||
static readonly Logger s_logger = new(nameof(CVarFieldInjector));
|
||||
|
||||
public bool Inject(FieldInfo field, object target, DIContext context) {
|
||||
if (!Attribute.IsDefined(field, typeof(CVarAttribute))) {
|
||||
return false;
|
||||
}
|
||||
if (!Attribute.IsDefined(field, typeof(CVarAttribute))) return false;
|
||||
|
||||
ConsoleService console = context.Resolve<ConsoleService>();
|
||||
if (console == null) {
|
||||
Logger.Error($"Cannot inject field because cannot resolve `{nameof(ConsoleService)}`");
|
||||
s_logger.Error($"Cannot inject field because cannot resolve `{nameof(ConsoleService)}`");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using UnityEngine.InputSystem;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
@@ -21,144 +17,91 @@ namespace RebootKit.Engine.Services.Console {
|
||||
public string Description { get; } = "Prints available commands/cvars and their descriptions.";
|
||||
|
||||
public void Execute(string[] args) {
|
||||
RR.Console().PrintHelp();
|
||||
RR.Console.PrintHelp();
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsoleService : IService {
|
||||
private static readonly Logger _logger = new(nameof(ConsoleService));
|
||||
static readonly Logger _logger = new(nameof(ConsoleService));
|
||||
|
||||
[Serializable]
|
||||
public class Config {
|
||||
public ConsoleUI ConsoleUIPrefab;
|
||||
public ScriptableInputAction ToggleAction;
|
||||
}
|
||||
readonly List<IConsoleCommand> _commands = new();
|
||||
readonly List<CVar> _cvars = new();
|
||||
|
||||
private ConsoleUI _ui;
|
||||
private Config _config;
|
||||
|
||||
private List<IConsoleCommand> _commands = new();
|
||||
private List<CVar> _cvars = new();
|
||||
|
||||
public bool IsVisible => _ui.IsVisible;
|
||||
|
||||
public ConsoleService(Config config) {
|
||||
_config = config;
|
||||
|
||||
public ConsoleService() {
|
||||
_logger.Info("Waking up");
|
||||
|
||||
_ui = UnityEngine.Object.Instantiate(_config.ConsoleUIPrefab);
|
||||
UnityEngine.Object.DontDestroyOnLoad(_ui.gameObject);
|
||||
|
||||
_config.ToggleAction.Action.Enable();
|
||||
_config.ToggleAction.Action.performed += OnToggleAction;
|
||||
|
||||
RegisterCommand(new HelpCommand());
|
||||
|
||||
_ui.SetVisibility(false);
|
||||
_ui.Clear();
|
||||
_ui.Write("Hello shelf\n");
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
if (_ui != null) {
|
||||
UnityEngine.Object.Destroy(_ui);
|
||||
_ui = null;
|
||||
}
|
||||
}
|
||||
|
||||
_config.ToggleAction.Action.performed -= OnToggleAction;
|
||||
public event Action<string> OnOutputMessage = _ => { };
|
||||
|
||||
public void WriteToOutput(string message) {
|
||||
OnOutputMessage?.Invoke(message);
|
||||
}
|
||||
|
||||
public bool CVarExists(string name) {
|
||||
foreach (CVar cvar in _cvars) {
|
||||
if (cvar.Name.Equals(name)) {
|
||||
foreach (CVar cvar in _cvars)
|
||||
if (cvar.name.Equals(name))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public CVar GetCVar(string name) {
|
||||
foreach (CVar cvar in _cvars) {
|
||||
if (cvar.Name.Equals(name)) {
|
||||
foreach (CVar cvar in _cvars)
|
||||
if (cvar.name.Equals(name))
|
||||
return cvar;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public CVar ReplaceOrDefault(CVar cvar) {
|
||||
CVar foundCVar = GetCVar(cvar.Name);
|
||||
if (foundCVar != null) {
|
||||
return foundCVar;
|
||||
}
|
||||
CVar foundCVar = GetCVar(cvar.name);
|
||||
if (foundCVar != null) return foundCVar;
|
||||
|
||||
_cvars.Add(cvar);
|
||||
return cvar;
|
||||
}
|
||||
|
||||
public void Replace(CVar cvar) {
|
||||
CVar foundCVar = GetCVar(cvar.Name);
|
||||
if (foundCVar != null) {
|
||||
_cvars.Remove(foundCVar);
|
||||
}
|
||||
CVar foundCVar = GetCVar(cvar.name);
|
||||
if (foundCVar != null) _cvars.Remove(foundCVar);
|
||||
|
||||
_cvars.Add(cvar);
|
||||
}
|
||||
|
||||
private string[] ParseCommandInputArguments(string text) {
|
||||
if (text.Length == 0) {
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
string[] ParseCommandInputArguments(string text) {
|
||||
if (text.Length == 0) return Array.Empty<string>();
|
||||
|
||||
return new string[] {text};
|
||||
return new[] {text};
|
||||
}
|
||||
|
||||
public void Execute(string input) {
|
||||
if (input.Length == 0) {
|
||||
return;
|
||||
}
|
||||
if (input.Length == 0) return;
|
||||
|
||||
string commandName = input;
|
||||
if (input.IndexOf(' ') != -1) {
|
||||
commandName = input.Substring(0, input.IndexOf(' '));
|
||||
}
|
||||
if (input.IndexOf(' ') != -1) commandName = input.Substring(0, input.IndexOf(' '));
|
||||
|
||||
string[] arguments = ParseCommandInputArguments(input.Substring(commandName.Length));
|
||||
|
||||
foreach (IConsoleCommand command in _commands) {
|
||||
foreach (IConsoleCommand command in _commands)
|
||||
if (command.Name.Equals(commandName)) {
|
||||
command.Execute(arguments);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (CVar cvar in _cvars) {
|
||||
if (cvar.Name.Equals(commandName)) {
|
||||
if (arguments.Length == 1) {
|
||||
cvar.ParseFromString(arguments[0]);
|
||||
}
|
||||
foreach (CVar cvar in _cvars)
|
||||
if (cvar.name.Equals(commandName)) {
|
||||
if (arguments.Length == 1) cvar.ParseFromString(arguments[0]);
|
||||
|
||||
_ui.Write($"<b>{cvar.Name}</b> - {cvar.ToString()}\n");
|
||||
WriteToOutput($"<b>{cvar.name}</b> - {cvar}\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_ui.Write($"ERROR: Command/CVar `{commandName}` not found.");
|
||||
}
|
||||
|
||||
public void ToggleVisibility() {
|
||||
_ui.SetVisibility(!_ui.IsVisible);
|
||||
|
||||
if (_ui.IsVisible) {
|
||||
RR.Input().DisableControls();
|
||||
RR.Input().UnlockCursor();
|
||||
} else {
|
||||
RR.Input().EnableControls();
|
||||
RR.Input().LockCursor();
|
||||
}
|
||||
WriteToOutput($"ERROR: Command/CVar `{commandName}` not found.");
|
||||
}
|
||||
|
||||
public void RegisterCommand(IConsoleCommand command) {
|
||||
@@ -186,17 +129,13 @@ namespace RebootKit.Engine.Services.Console {
|
||||
message.AppendLine("Available cvars:");
|
||||
foreach (CVar cvar in _cvars) {
|
||||
message.Append(" ");
|
||||
message.Append(cvar.Name);
|
||||
message.Append(cvar.name);
|
||||
message.Append(" - ");
|
||||
message.Append(cvar.Description);
|
||||
message.Append(cvar.description);
|
||||
message.AppendLine();
|
||||
}
|
||||
|
||||
_ui.Write(message.ToString());
|
||||
}
|
||||
|
||||
private void OnToggleAction(InputAction.CallbackContext obj) {
|
||||
ToggleVisibility();
|
||||
WriteToOutput(message.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,14 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
[CreateAssetMenu(menuName = RConsts.ServiceAssetMenu + "Console")]
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Console")]
|
||||
public class ConsoleServiceAsset : ServiceAsset<ConsoleService> {
|
||||
[SerializeField]
|
||||
private ConsoleService.Config _config;
|
||||
[SerializeField] CVar[] _initialCVars;
|
||||
|
||||
[SerializeField]
|
||||
private CVar[] _initialCVars;
|
||||
|
||||
[SerializeField]
|
||||
private bool _loadCVarsFromResources = true;
|
||||
[SerializeField] bool _loadCVarsFromResources = true;
|
||||
|
||||
public override ConsoleService Create(DIContext context) {
|
||||
ConsoleService service = new(_config);
|
||||
ConsoleService service = new();
|
||||
context.Inject(service);
|
||||
|
||||
foreach (CVar cvar in _initialCVars) {
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
public class ConsoleUI : MonoBehaviour {
|
||||
private static readonly Logger Logger = new(nameof(ConsoleUI));
|
||||
|
||||
private StringBuilder _content = new();
|
||||
|
||||
[SerializeField]
|
||||
private UIDocument _document;
|
||||
|
||||
private Label _labelMessage;
|
||||
private TextField _textField;
|
||||
private Button _submitButton;
|
||||
|
||||
public bool IsVisible { get; private set; }
|
||||
|
||||
private void OnEnable() {
|
||||
IsVisible = _document.enabled;
|
||||
|
||||
VisualElement root = _document.rootVisualElement;
|
||||
_labelMessage = root.Q<Label>("console-window-message");
|
||||
_labelMessage.text = "SIEMA";
|
||||
|
||||
_textField = root.Q<TextField>("console-text-field");
|
||||
_submitButton = root.Q<Button>("console-btn-submit");
|
||||
_submitButton.clicked += OnSubmitButtonClicked;
|
||||
}
|
||||
|
||||
private void OnSubmit(string input) {
|
||||
RR.Console().Execute(input);
|
||||
_textField.value = input;
|
||||
}
|
||||
|
||||
public void SetVisibility(bool visible) {
|
||||
_document.enabled = visible;
|
||||
IsVisible = visible;
|
||||
}
|
||||
|
||||
public void Write(string message) {
|
||||
_content.Append(message);
|
||||
_labelMessage.text = _content.ToString();
|
||||
_labelMessage.MarkDirtyRepaint();
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
_content.Clear();
|
||||
_labelMessage.text = "";
|
||||
|
||||
if (_textField != null) {
|
||||
_textField.label = "";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSubmitButtonClicked() {
|
||||
Logger.Info("Submit");
|
||||
OnSubmit(_textField.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Services/ConsoleUI.meta
Normal file
3
Runtime/Engine/Code/Services/ConsoleUI.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0500959e68464db2abd534e30f6f5978
|
||||
timeCreated: 1742422569
|
||||
81
Runtime/Engine/Code/Services/ConsoleUI/ConsoleUIService.cs
Normal file
81
Runtime/Engine/Code/Services/ConsoleUI/ConsoleUIService.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System.Text;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.ConsoleUI {
|
||||
public class ConsoleUIService : ServiceMonoBehaviour {
|
||||
static readonly Logger s_logger = new(nameof(ConsoleUIService));
|
||||
|
||||
[SerializeField] ConsoleVC m_ConsoleVC;
|
||||
[SerializeField] ScriptableInputAction m_ToggleAction;
|
||||
|
||||
readonly StringBuilder m_Content = new();
|
||||
|
||||
public bool IsVisible => m_ConsoleVC.gameObject.activeSelf;
|
||||
|
||||
void Awake() {
|
||||
SetVisibility(false);
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
s_logger.Info("OnEnable console");
|
||||
|
||||
m_ToggleAction.Action.Enable();
|
||||
m_ToggleAction.Action.performed += OnToggleAction;
|
||||
|
||||
m_ConsoleVC.InputSubmitted += OnUserInput;
|
||||
m_ConsoleVC.ClearRequested += Clear;
|
||||
RR.Console.OnOutputMessage += Write;
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
m_ToggleAction.Action.performed -= OnToggleAction;
|
||||
|
||||
m_ConsoleVC.InputSubmitted -= OnUserInput;
|
||||
m_ConsoleVC.ClearRequested -= Clear;
|
||||
RR.Console.OnOutputMessage -= Write;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
}
|
||||
|
||||
public void ToggleVisibility() {
|
||||
SetVisibility(!IsVisible);
|
||||
|
||||
if (IsVisible) {
|
||||
RR.Input.DisableControls();
|
||||
RR.Input.UnlockCursor();
|
||||
|
||||
m_ConsoleVC.SetMessageContent(m_Content.ToString());
|
||||
} else {
|
||||
RR.Input.EnableControls();
|
||||
RR.Input.LockCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void OnUserInput(string input) {
|
||||
RR.Console.Execute(input);
|
||||
}
|
||||
|
||||
public void SetVisibility(bool visible) {
|
||||
m_ConsoleVC.gameObject.SetActive(visible);
|
||||
}
|
||||
|
||||
public void Write(string message) {
|
||||
m_Content.AppendLine(message);
|
||||
m_ConsoleVC.SetMessageContent(m_Content.ToString());
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
m_Content.Clear();
|
||||
m_ConsoleVC.SetMessageContent(string.Empty);
|
||||
}
|
||||
|
||||
void OnToggleAction(InputAction.CallbackContext obj) {
|
||||
ToggleVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Runtime/Engine/Code/Services/ConsoleUI/ConsoleVC.cs
Normal file
62
Runtime/Engine/Code/Services/ConsoleUI/ConsoleVC.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.ConsoleUI {
|
||||
public class ConsoleVC : MonoBehaviour {
|
||||
static readonly Logger s_logger = new(nameof(ConsoleVC));
|
||||
|
||||
[SerializeField] UIDocument m_Document;
|
||||
|
||||
Label m_LabelMessage;
|
||||
|
||||
VisualElement m_Root;
|
||||
|
||||
ScrollView m_ScrollView;
|
||||
TextField m_TextField;
|
||||
|
||||
void OnEnable() {
|
||||
m_Root = m_Document.rootVisualElement;
|
||||
m_LabelMessage = m_Root.Q<Label>("console-window-message");
|
||||
|
||||
m_TextField = m_Root.Q<TextField>("console-text-field");
|
||||
m_TextField.value = string.Empty;
|
||||
m_TextField.RegisterCallback<KeyUpEvent>(ev => {
|
||||
if (ev.keyCode == KeyCode.Return) {
|
||||
Submit();
|
||||
ev.StopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
Button submitButton = m_Root.Q<Button>("console-btn-submit");
|
||||
submitButton.RegisterCallback<ClickEvent>(_ => { Submit(); });
|
||||
|
||||
Button clearButton = m_Root.Q<Button>("console-btn-clear");
|
||||
clearButton.RegisterCallback<ClickEvent>(_ => { Clear(); });
|
||||
|
||||
m_ScrollView = m_Root.Q<ScrollView>("console-scrollview");
|
||||
|
||||
m_TextField.schedule.Execute(() => m_TextField.Focus()).StartingIn(1);
|
||||
}
|
||||
|
||||
public event Action<string> InputSubmitted = _ => { };
|
||||
public event Action ClearRequested = () => { };
|
||||
|
||||
public void SetMessageContent(string message) {
|
||||
m_LabelMessage.text = message;
|
||||
m_ScrollView.schedule.Execute(() => { m_ScrollView.scrollOffset = new Vector2(0, m_ScrollView.contentContainer.contentRect.height); }).StartingIn(16);
|
||||
}
|
||||
|
||||
void Submit() {
|
||||
InputSubmitted.Invoke(m_TextField.value);
|
||||
m_TextField.value = string.Empty;
|
||||
m_TextField.Focus();
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
ClearRequested.Invoke();
|
||||
m_TextField.value = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Services/ConsoleUI/ConsoleVC.cs.meta
Normal file
3
Runtime/Engine/Code/Services/ConsoleUI/ConsoleVC.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6131b8af74b4894ba7b95b12286bc66
|
||||
timeCreated: 1742461272
|
||||
3
Runtime/Engine/Code/Services/Development.meta
Normal file
3
Runtime/Engine/Code/Services/Development.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7a30943696f49638fd85fb1f89d5a26
|
||||
timeCreated: 1743250667
|
||||
28
Runtime/Engine/Code/Services/Development/DebugOverlayView.cs
Normal file
28
Runtime/Engine/Code/Services/Development/DebugOverlayView.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace RebootKit.Engine.Services.Development {
|
||||
public class DebugOverlayView : MonoBehaviour, IView {
|
||||
[SerializeField] UIDocument m_Document;
|
||||
|
||||
void Start() {
|
||||
}
|
||||
|
||||
public async UniTask Show(CancellationToken cancellationToken) {
|
||||
gameObject.SetActive(true);
|
||||
await UniTask.Yield(cancellationToken);
|
||||
}
|
||||
|
||||
public async UniTask Hide(CancellationToken cancellationToken) {
|
||||
gameObject.SetActive(false);
|
||||
await UniTask.Yield(cancellationToken);
|
||||
}
|
||||
|
||||
void SetOverlayModeChanged(int mode) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f18f4d0e8d914fdca81f98faf0e1546f
|
||||
timeCreated: 1743249301
|
||||
46
Runtime/Engine/Code/Services/Development/DevToolsService.cs
Normal file
46
Runtime/Engine/Code/Services/Development/DevToolsService.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Development {
|
||||
static class DebugCVars {
|
||||
public const string k_OverlayMode = "debug.mode";
|
||||
}
|
||||
|
||||
public class DevToolsService : ServiceMonoBehaviour {
|
||||
[SerializeField] DebugOverlayView m_DebugOverlayView;
|
||||
|
||||
[CVar(DebugCVars.k_OverlayMode, 1)] CVar m_OverlayMode;
|
||||
|
||||
IDisposable m_CVarChangedListener;
|
||||
|
||||
void OnEnable() {
|
||||
m_CVarChangedListener = RR.CVarChanged.Listen(OnCVarChanged);
|
||||
OnOverlayModeChanged(m_OverlayMode.IndexValue);
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
m_CVarChangedListener.Dispose();
|
||||
}
|
||||
|
||||
void OnOverlayModeChanged(int mode) {
|
||||
if (mode == 1) {
|
||||
m_DebugOverlayView.Show(destroyCancellationToken).Forget();
|
||||
} else {
|
||||
m_DebugOverlayView.Hide(destroyCancellationToken).Forget();
|
||||
}
|
||||
}
|
||||
|
||||
void OnCVarChanged(string cvarName, CVarValue value) {
|
||||
if (cvarName == DebugCVars.k_OverlayMode) {
|
||||
OnOverlayModeChanged((int)value.numberValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ea9757c83234daaae0d4227ac495da2
|
||||
timeCreated: 1743250681
|
||||
@@ -4,14 +4,9 @@ using RebootKit.Engine.Foundation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
[Serializable]
|
||||
public class GameModeConfig {
|
||||
public ControllerAsset[] Controllers;
|
||||
}
|
||||
|
||||
public abstract class GameModeAsset : FactoryAsset<GameMode> {
|
||||
[field: SerializeField]
|
||||
public GameModeConfig GameModeConfig { get; private set; }
|
||||
public GameMode.Config GameModeConfig { get; private set; }
|
||||
|
||||
public override GameMode Create(DIContext context) {
|
||||
GameMode gameMode = new(GameModeConfig);
|
||||
@@ -22,51 +17,62 @@ namespace RebootKit.Engine.Services.Game {
|
||||
|
||||
public abstract void ConfigureGameMode(GameMode gameMode);
|
||||
}
|
||||
|
||||
|
||||
public class GameMode : IDisposable {
|
||||
private readonly GameModeConfig _config;
|
||||
private readonly ControllersManager _controllersManager;
|
||||
[Serializable]
|
||||
public class Config {
|
||||
public ControllerAsset[] controllers;
|
||||
}
|
||||
|
||||
[Inject]
|
||||
private DIContext _diContext;
|
||||
readonly Config m_Config;
|
||||
readonly ControllersManager<IController> m_Controllers;
|
||||
|
||||
private CancellationTokenSource _destroyCancellationTokenSource;
|
||||
|
||||
private bool _isRunning;
|
||||
readonly CancellationTokenSource m_DestroyCancellationTokenSource;
|
||||
|
||||
public GameMode(GameModeConfig config) {
|
||||
_config = config;
|
||||
_isRunning = false;
|
||||
[Inject] DIContext m_DIContext;
|
||||
bool m_IsRunning;
|
||||
|
||||
_destroyCancellationTokenSource = new CancellationTokenSource();
|
||||
_controllersManager = new ControllersManager(_destroyCancellationTokenSource.Token);
|
||||
public GameMode(Config config) {
|
||||
m_Config = config;
|
||||
m_IsRunning = false;
|
||||
|
||||
m_DestroyCancellationTokenSource = new CancellationTokenSource();
|
||||
m_Controllers = new ControllersManager<IController>(m_DestroyCancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
_destroyCancellationTokenSource.Cancel();
|
||||
_controllersManager.Dispose();
|
||||
m_DestroyCancellationTokenSource.Cancel();
|
||||
m_Controllers.Dispose();
|
||||
}
|
||||
|
||||
public async Awaitable<bool> Start(CancellationToken cancellationToken) {
|
||||
_controllersManager.Add(_config.Controllers, _diContext);
|
||||
await _controllersManager.Start(cancellationToken);
|
||||
m_Controllers.Add(m_Config.controllers, m_DIContext);
|
||||
await m_Controllers.Start(cancellationToken);
|
||||
|
||||
_isRunning = true;
|
||||
m_IsRunning = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Stop() {
|
||||
_isRunning = false;
|
||||
m_IsRunning = false;
|
||||
|
||||
_controllersManager.Stop();
|
||||
m_Controllers.Stop();
|
||||
}
|
||||
|
||||
public void Tick() {
|
||||
_controllersManager.Tick();
|
||||
m_Controllers.Tick();
|
||||
}
|
||||
|
||||
public void AddController(IController controller) {
|
||||
_controllersManager.Add(controller);
|
||||
m_Controllers.Add(controller);
|
||||
}
|
||||
|
||||
public T FindController<T>() where T : class, IController {
|
||||
if (m_Controllers.TryFind<T>(out T controller)) {
|
||||
return controller;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,39 +5,42 @@ using UnityEngine.Assertions;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
public class GameService : IService {
|
||||
private static readonly Logger Logger = new(nameof(GameService));
|
||||
static readonly Logger s_logger = new(nameof(GameService));
|
||||
|
||||
[Inject] DIContext m_DIContext;
|
||||
GameMode m_GameMode;
|
||||
|
||||
GameModeAsset m_GameModeAsset;
|
||||
bool m_isRunning;
|
||||
|
||||
[Inject]
|
||||
private DIContext _diContext;
|
||||
|
||||
private GameModeAsset _gameModeAsset;
|
||||
private GameMode _gameMode;
|
||||
private bool _running;
|
||||
|
||||
public void Dispose() {
|
||||
_running = false;
|
||||
_gameMode.Dispose();
|
||||
m_isRunning = false;
|
||||
m_GameMode.Dispose();
|
||||
}
|
||||
|
||||
public async UniTask Start(GameModeAsset asset, CancellationToken cancellationToken) {
|
||||
Assert.IsNotNull(asset);
|
||||
|
||||
_gameMode = asset.Create(_diContext);
|
||||
await _gameMode.Start(cancellationToken);
|
||||
|
||||
m_GameMode = asset.Create(m_DIContext);
|
||||
await m_GameMode.Start(cancellationToken);
|
||||
|
||||
Run(cancellationToken).Forget();
|
||||
}
|
||||
|
||||
private async UniTask Run(CancellationToken cancellationToken) {
|
||||
if (_gameMode == null) {
|
||||
Logger.Error("Trying to run game without game mode");
|
||||
async UniTask Run(CancellationToken cancellationToken) {
|
||||
if (m_GameMode == null) {
|
||||
s_logger.Error("Trying to run game without game mode");
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
while (_running) {
|
||||
|
||||
m_isRunning = true;
|
||||
while (m_isRunning) {
|
||||
await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken);
|
||||
_gameMode.Tick();
|
||||
m_GameMode.Tick();
|
||||
|
||||
if (cancellationToken.IsCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
[CreateAssetMenu(menuName = RConsts.ServiceAssetMenu + "Game")]
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Game")]
|
||||
public class GameServiceAsset : ServiceAsset<GameService> {
|
||||
public override GameService Create(DIContext context) {
|
||||
GameService service = context.Create<GameService>();
|
||||
|
||||
@@ -1,36 +1,29 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace RebootKit.Engine.Services.Input {
|
||||
public class InputService : IService {
|
||||
[Serializable]
|
||||
public class Config {
|
||||
public InputActionAsset InputAsset;
|
||||
}
|
||||
|
||||
private Config _config;
|
||||
readonly Config m_Config;
|
||||
|
||||
public InputService(Config config) {
|
||||
_config = config;
|
||||
m_Config = config;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose() {
|
||||
}
|
||||
|
||||
public void EnableControls() {
|
||||
_config.InputAsset.Enable();
|
||||
m_Config.inputAsset.Enable();
|
||||
}
|
||||
|
||||
public void DisableControls() {
|
||||
_config.InputAsset.Disable();
|
||||
m_Config.inputAsset.Disable();
|
||||
}
|
||||
|
||||
public InputAction FindInputAction(string path) {
|
||||
return _config.InputAsset.FindAction(path);
|
||||
return m_Config.inputAsset.FindAction(path);
|
||||
}
|
||||
|
||||
public void LockCursor() {
|
||||
@@ -42,5 +35,10 @@ namespace RebootKit.Engine.Services.Input {
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
Cursor.visible = true;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Config {
|
||||
public InputActionAsset inputAsset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Input {
|
||||
[CreateAssetMenu(menuName = RConsts.ServiceAssetMenu + "Input")]
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Input")]
|
||||
public class InputServiceAsset : ServiceAsset<InputService> {
|
||||
[SerializeField]
|
||||
private InputService.Config _config;
|
||||
[SerializeField] InputService.Config m_Config;
|
||||
|
||||
public override InputService Create(DIContext context) {
|
||||
InputService instance = new(_config);
|
||||
InputService instance = new(m_Config);
|
||||
context.Inject(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace RebootKit.Engine.Services.Input
|
||||
{
|
||||
[CreateAssetMenu(menuName = RConsts.AssetMenu + "Input Action", fileName = "Input Action")]
|
||||
public class ScriptableInputAction : ScriptableObject
|
||||
{
|
||||
namespace RebootKit.Engine.Services.Input {
|
||||
[CreateAssetMenu(menuName = RConsts.k_AddComponentMenu + "Input Action", fileName = "Input Action")]
|
||||
public class ScriptableInputAction : ScriptableObject {
|
||||
[field: SerializeField]
|
||||
public InputAction Action { get; private set; }
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5fb2de6697247618aa0dc36a659ddcc
|
||||
timeCreated: 1741791621
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace RebootKit.Engine.Services.LoadigScreen
|
||||
{
|
||||
public class LoadingScreenService
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a45f8f7ea6f45198713694a39790614
|
||||
timeCreated: 1740671052
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 663488f6dc6f4f23a2fb88ab0b2a8daa
|
||||
timeCreated: 1741043532
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace RebootKit.Engine.Services.Persistance {
|
||||
|
||||
[Serializable]
|
||||
public class SaveData {
|
||||
public string ProfileName;
|
||||
}
|
||||
|
||||
public class SaveSystemService {
|
||||
public void Save() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fd19386b9584594bac09c3f43489a1a
|
||||
timeCreated: 1741043540
|
||||
@@ -1,74 +1,60 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation.Characters
|
||||
{
|
||||
public class CharacterLocomotion : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private CharacterController _characterController;
|
||||
|
||||
public float MaxMovementSpeed = 4.0f;
|
||||
public float MaxSprintSpeed = 15.0f;
|
||||
public float JumpHeight = 1.0f;
|
||||
public float Gravity = 10f;
|
||||
public float MaxFallSpeed = 20f;
|
||||
public float Damping = 20.0f;
|
||||
namespace RebootKit.Engine.Services.Simulation.Characters {
|
||||
public class CharacterLocomotion : MonoBehaviour {
|
||||
[SerializeField] CharacterController m_CharacterController;
|
||||
|
||||
private Vector3 _pendingInputValue;
|
||||
private Vector3 _currentVelocity;
|
||||
public float maxMovementSpeed = 4.0f;
|
||||
public float maxSprintSpeed = 15.0f;
|
||||
public float jumpHeight = 1.0f;
|
||||
public float gravity = 10f;
|
||||
public float maxFallSpeed = 20f;
|
||||
public float damping = 20.0f;
|
||||
Vector3 m_CurrentVelocity;
|
||||
bool m_IsFalling;
|
||||
|
||||
private bool _isSprinting;
|
||||
private bool _jumpRequested;
|
||||
private bool _isFalling;
|
||||
bool m_IsSprinting;
|
||||
bool m_JumpRequested;
|
||||
|
||||
public bool IsGrounded => _characterController.isGrounded;
|
||||
Vector3 m_PendingInputValue;
|
||||
|
||||
public Vector3 Velocity => _currentVelocity;
|
||||
public bool IsGrounded => m_CharacterController.isGrounded;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
public Vector3 Velocity => m_CurrentVelocity;
|
||||
|
||||
void Update() {
|
||||
ConsumePendingInput();
|
||||
UpdateVerticalVelocity();
|
||||
|
||||
_characterController.Move(_currentVelocity * Time.deltaTime);
|
||||
m_CharacterController.Move(m_CurrentVelocity * Time.deltaTime);
|
||||
|
||||
ApplyFriction();
|
||||
DetectFall();
|
||||
}
|
||||
|
||||
private void DetectFall()
|
||||
{
|
||||
if (_isFalling && _characterController.isGrounded)
|
||||
{
|
||||
_isFalling = false;
|
||||
}
|
||||
else if (!_characterController.isGrounded)
|
||||
{
|
||||
_isFalling = true;
|
||||
}
|
||||
void DetectFall() {
|
||||
if (m_IsFalling && m_CharacterController.isGrounded)
|
||||
m_IsFalling = false;
|
||||
else if (!m_CharacterController.isGrounded) m_IsFalling = true;
|
||||
}
|
||||
|
||||
private void ConsumePendingInput()
|
||||
{
|
||||
if (!IsGrounded)
|
||||
{
|
||||
_pendingInputValue = Vector3.zero;
|
||||
void ConsumePendingInput() {
|
||||
if (!IsGrounded) {
|
||||
m_PendingInputValue = Vector3.zero;
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingInputValue.y = 0.0f;
|
||||
m_PendingInputValue.y = 0.0f;
|
||||
|
||||
float pendingInputMagnitude = _pendingInputValue.magnitude;
|
||||
float pendingInputMagnitude = m_PendingInputValue.magnitude;
|
||||
Vector3 direction = Vector3.zero;
|
||||
|
||||
if (pendingInputMagnitude > 0.0f)
|
||||
{
|
||||
// normalize vector, reusing magnitude to avoid multiple sqrt calls
|
||||
direction = _pendingInputValue / pendingInputMagnitude;
|
||||
}
|
||||
direction = m_PendingInputValue / pendingInputMagnitude;
|
||||
|
||||
float movementSpeed = _isSprinting ? MaxSprintSpeed : MaxMovementSpeed;
|
||||
Vector3 movementVelocity = _currentVelocity;
|
||||
float movementSpeed = m_IsSprinting ? maxSprintSpeed : maxMovementSpeed;
|
||||
Vector3 movementVelocity = m_CurrentVelocity;
|
||||
movementVelocity.y = 0.0f;
|
||||
movementVelocity += direction * (movementSpeed * pendingInputMagnitude);
|
||||
movementVelocity.y = 0.0f;
|
||||
@@ -77,84 +63,62 @@ namespace RebootKit.Engine.Services.Simulation.Characters
|
||||
float movementVelocityMagnitude = movementVelocity.magnitude;
|
||||
Vector3 movementVelocityDirection = movementVelocityMagnitude > 0.0f ? movementVelocity / movementVelocityMagnitude : Vector3.zero;
|
||||
|
||||
if (movementVelocityMagnitude > movementSpeed)
|
||||
{
|
||||
movementVelocityMagnitude = movementSpeed;
|
||||
}
|
||||
if (movementVelocityMagnitude > movementSpeed) movementVelocityMagnitude = movementSpeed;
|
||||
|
||||
movementVelocity = movementVelocityDirection * movementVelocityMagnitude;
|
||||
|
||||
_currentVelocity.x = movementVelocity.x;
|
||||
_currentVelocity.z = movementVelocity.z;
|
||||
m_CurrentVelocity.x = movementVelocity.x;
|
||||
m_CurrentVelocity.z = movementVelocity.z;
|
||||
|
||||
_pendingInputValue = Vector3.zero;
|
||||
m_PendingInputValue = Vector3.zero;
|
||||
}
|
||||
|
||||
private void UpdateVerticalVelocity()
|
||||
{
|
||||
if (_characterController.isGrounded)
|
||||
{
|
||||
if (_jumpRequested)
|
||||
{
|
||||
_currentVelocity.y = Mathf.Sqrt(2.0f * Gravity * JumpHeight);
|
||||
_jumpRequested = false;
|
||||
void UpdateVerticalVelocity() {
|
||||
if (m_CharacterController.isGrounded) {
|
||||
if (m_JumpRequested) {
|
||||
m_CurrentVelocity.y = Mathf.Sqrt(2.0f * gravity * jumpHeight);
|
||||
m_JumpRequested = false;
|
||||
} else {
|
||||
m_CurrentVelocity.y = -1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentVelocity.y = -1f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentVelocity.y -= Gravity * Time.deltaTime;
|
||||
_currentVelocity.y = Mathf.Max(_currentVelocity.y, -MaxFallSpeed);
|
||||
} else {
|
||||
m_CurrentVelocity.y -= gravity * Time.deltaTime;
|
||||
m_CurrentVelocity.y = Mathf.Max(m_CurrentVelocity.y, -maxFallSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFriction()
|
||||
{
|
||||
if (!IsGrounded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void ApplyFriction() {
|
||||
if (!IsGrounded) return;
|
||||
|
||||
Vector3 movementVelocity = _currentVelocity;
|
||||
Vector3 movementVelocity = m_CurrentVelocity;
|
||||
movementVelocity.y = 0.0f;
|
||||
|
||||
movementVelocity = Vector3.MoveTowards(movementVelocity, Vector3.zero, Damping * Time.deltaTime);
|
||||
movementVelocity = Vector3.MoveTowards(movementVelocity, Vector3.zero, damping * Time.deltaTime);
|
||||
|
||||
_currentVelocity.x = movementVelocity.x;
|
||||
_currentVelocity.z = movementVelocity.z;
|
||||
m_CurrentVelocity.x = movementVelocity.x;
|
||||
m_CurrentVelocity.z = movementVelocity.z;
|
||||
}
|
||||
|
||||
public void AddVelocity(Vector3 velocity)
|
||||
{
|
||||
_currentVelocity += velocity;
|
||||
public void AddVelocity(Vector3 velocity) {
|
||||
m_CurrentVelocity += velocity;
|
||||
}
|
||||
|
||||
public void AddMovementInput(Vector3 input, float scale)
|
||||
{
|
||||
_pendingInputValue += input * scale;
|
||||
public void AddMovementInput(Vector3 input, float scale) {
|
||||
m_PendingInputValue += input * scale;
|
||||
}
|
||||
|
||||
public void Jump()
|
||||
{
|
||||
if (!_characterController.isGrounded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
public void Jump() {
|
||||
if (!m_CharacterController.isGrounded) return;
|
||||
|
||||
_jumpRequested = true;
|
||||
m_JumpRequested = true;
|
||||
}
|
||||
|
||||
public void StartSprint()
|
||||
{
|
||||
_isSprinting = true;
|
||||
public void StartSprint() {
|
||||
m_IsSprinting = true;
|
||||
}
|
||||
|
||||
public void StopSprint()
|
||||
{
|
||||
_isSprinting = false;
|
||||
public void StopSprint() {
|
||||
m_IsSprinting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation.Characters {
|
||||
public class GameCharacter : MonoBehaviour {
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4dd42e93f8a469685be596f305ed985
|
||||
timeCreated: 1741791931
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
@@ -9,22 +8,26 @@ namespace RebootKit.Engine.Services.Simulation.Interactors {
|
||||
}
|
||||
|
||||
public interface IInteractor<in TInteractable> {
|
||||
public static Type InteractableType() => typeof(TInteractable);
|
||||
|
||||
void Interact(TInteractable target);
|
||||
}
|
||||
|
||||
public class GroupInteractor<TInteractable> : IInteractor<TInteractable> {
|
||||
private readonly List<IInteractor<TInteractable>> _interactors = new();
|
||||
|
||||
public void Add(IInteractor<TInteractable> interactor) => _interactors.Add(interactor);
|
||||
public void Remove(IInteractor<TInteractable> interactor) => _interactors.Remove(interactor);
|
||||
public void RemoveAll() => _interactors.Clear();
|
||||
readonly List<IInteractor<TInteractable>> m_Interactors = new();
|
||||
|
||||
public void Interact(TInteractable target) {
|
||||
foreach (IInteractor<TInteractable> interactor in _interactors) {
|
||||
interactor.Interact(target);
|
||||
}
|
||||
foreach (IInteractor<TInteractable> interactor in m_Interactors) interactor.Interact(target);
|
||||
}
|
||||
|
||||
public void Add(IInteractor<TInteractable> interactor) {
|
||||
m_Interactors.Add(interactor);
|
||||
}
|
||||
|
||||
public void Remove(IInteractor<TInteractable> interactor) {
|
||||
m_Interactors.Remove(interactor);
|
||||
}
|
||||
|
||||
public void RemoveAll() {
|
||||
m_Interactors.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using RebootKit.Engine.Extensions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation {
|
||||
public class PhysicsObjectDragger : MonoBehaviour {
|
||||
@@ -17,24 +18,8 @@ namespace RebootKit.Engine.Services.Simulation {
|
||||
|
||||
public bool IsDragging => Current != null;
|
||||
|
||||
public void Grab(Rigidbody physicsObject) {
|
||||
Current = physicsObject;
|
||||
Current.linearDamping = 5.0f;
|
||||
}
|
||||
|
||||
public void Drop() {
|
||||
if (Current == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Current.linearDamping = 0.0f;
|
||||
Current = null;
|
||||
}
|
||||
|
||||
public void FixedUpdate() {
|
||||
if (Current == null) {
|
||||
return;
|
||||
}
|
||||
if (Current.OrNull() == null) return;
|
||||
|
||||
Vector3 direction = (TargetWorldPosition - Current.position).normalized;
|
||||
float distance = Vector3.Distance(TargetWorldPosition, Current.position);
|
||||
@@ -46,5 +31,17 @@ namespace RebootKit.Engine.Services.Simulation {
|
||||
|
||||
Current.angularVelocity = Vector3.MoveTowards(Current.angularVelocity, Vector3.zero, Time.fixedDeltaTime * AngularSlowdown);
|
||||
}
|
||||
|
||||
public void Grab(Rigidbody physicsObject) {
|
||||
Current = physicsObject;
|
||||
Current.linearDamping = 5.0f;
|
||||
}
|
||||
|
||||
public void Drop() {
|
||||
if (Current == null) return;
|
||||
|
||||
Current.linearDamping = 0.0f;
|
||||
Current = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,15 @@
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation.Sensors {
|
||||
public class RaycastSensor : ISensor {
|
||||
public Ray Ray;
|
||||
public LayerMask LayerMask;
|
||||
public float MaxDistance;
|
||||
public LayerMask layerMask;
|
||||
public float maxDistance;
|
||||
public Ray ray;
|
||||
|
||||
public bool HasHit { get; private set; }
|
||||
public RaycastHit Hit { get; private set; }
|
||||
|
||||
public void Clear() {
|
||||
HasHit = false;
|
||||
Hit = default;
|
||||
}
|
||||
|
||||
public GameObject Sense() {
|
||||
HasHit = Physics.Raycast(Ray, out RaycastHit hit, MaxDistance, LayerMask);
|
||||
HasHit = Physics.Raycast(ray, out RaycastHit hit, maxDistance, layerMask);
|
||||
|
||||
if (HasHit) {
|
||||
Hit = hit;
|
||||
@@ -25,5 +20,10 @@ namespace RebootKit.Engine.Services.Simulation.Sensors {
|
||||
Hit = default;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
HasHit = false;
|
||||
Hit = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,15 @@ using UnityEngine.AddressableAssets;
|
||||
namespace RebootKit.Engine.Services.Simulation {
|
||||
[Serializable]
|
||||
public struct WorldConfig {
|
||||
public string Name;
|
||||
public string name;
|
||||
|
||||
// @NOTE: stays loaded during world lifetime
|
||||
public AssetReference MainScene;
|
||||
public AssetReference mainScene;
|
||||
}
|
||||
|
||||
[CreateAssetMenu(menuName = RConsts.WorldAssetMenu + "World")]
|
||||
|
||||
[CreateAssetMenu(menuName = RConsts.k_WorldAssetMenu + "World")]
|
||||
public class WorldConfigAsset : ScriptableObject {
|
||||
|
||||
[SerializeField]
|
||||
private WorldConfig _config;
|
||||
|
||||
public WorldConfig Config => _config;
|
||||
[field: SerializeField]
|
||||
public WorldConfig Config { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -10,17 +10,17 @@ using UnityEngine.SceneManagement;
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation {
|
||||
public class WorldService : IService {
|
||||
private WorldConfig _config;
|
||||
private List<Actor> _actors = new();
|
||||
readonly List<Actor> m_Actors = new();
|
||||
WorldConfig m_Config;
|
||||
|
||||
public void Dispose() {
|
||||
KillAllActors();
|
||||
}
|
||||
|
||||
public async UniTask Load(WorldConfig worldConfig) {
|
||||
_config = worldConfig;
|
||||
m_Config = worldConfig;
|
||||
|
||||
AsyncOperationHandle<SceneInstance> handle = worldConfig.MainScene.LoadSceneAsync(LoadSceneMode.Additive);
|
||||
AsyncOperationHandle<SceneInstance> handle = worldConfig.mainScene.LoadSceneAsync(LoadSceneMode.Additive);
|
||||
await handle.ToUniTask();
|
||||
SceneManager.SetActiveScene(handle.Result.Scene);
|
||||
}
|
||||
@@ -32,16 +32,14 @@ namespace RebootKit.Engine.Services.Simulation {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (gameObject.TryGetComponent(out TActor actor)) {
|
||||
return actor;
|
||||
}
|
||||
if (gameObject.TryGetComponent(out TActor actor)) return actor;
|
||||
|
||||
asset.ReleaseInstance(gameObject);
|
||||
return null;
|
||||
}
|
||||
|
||||
public async UniTask RegisterActor(Actor actor) {
|
||||
_actors.Add(actor);
|
||||
m_Actors.Add(actor);
|
||||
await UniTask.Yield();
|
||||
}
|
||||
|
||||
@@ -50,11 +48,9 @@ namespace RebootKit.Engine.Services.Simulation {
|
||||
}
|
||||
|
||||
public void KillAllActors() {
|
||||
foreach (Actor actor in _actors) {
|
||||
Addressables.ReleaseInstance(actor.gameObject);
|
||||
}
|
||||
foreach (Actor actor in m_Actors) Addressables.ReleaseInstance(actor.gameObject);
|
||||
|
||||
_actors.Clear();
|
||||
m_Actors.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Services.Simulation {
|
||||
[CreateAssetMenu(menuName = RConsts.ServiceAssetMenu + "World")]
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "World")]
|
||||
public class WorldServiceAsset : ServiceAsset<WorldService> {
|
||||
public override WorldService Create(DIContext context) {
|
||||
return context.Create<WorldService>();
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
|
||||
namespace RebootKit.Engine.Services {
|
||||
public class UpdateLoopService : IService {
|
||||
public async UniTask OnWakeUp(CancellationToken cancellationToken) {
|
||||
await UniTask.Yield(cancellationToken);
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
}
|
||||
|
||||
public void Add(PlayerLoopTiming playerLoopTiming) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f0892c234a3a3a40a7f2516fa4dd1e0
|
||||
Reference in New Issue
Block a user