Initial commit
This commit is contained in:
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
GoakeFlax.sln
|
||||
|
||||
Binaries/*
|
||||
Cache/*
|
||||
Logs/*
|
||||
packages/*
|
||||
|
||||
Source/**/*.csproj
|
||||
Source/**/*.Gen.cs
|
||||
*.csproj.user
|
||||
*.suo
|
||||
.vs/*
|
||||
Output/*
|
||||
16
Content/GameSettings.json
Normal file
16
Content/GameSettings.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"ID": "3c7bc3854d42f9b1b0fea9ba0d7fa8e9",
|
||||
"TypeName": "FlaxEditor.Content.Settings.GameSettings",
|
||||
"EngineBuild": 6216,
|
||||
"Data": {
|
||||
"ProductName": "Goake",
|
||||
"CompanyName": "GoaLitiuM",
|
||||
"FirstScene": "0733cc9b40d3d05366be64bbd9b59e21",
|
||||
"NoSplashScreen": true,
|
||||
"Time": "a55dc3c04da4ea3744b7f1994565beac",
|
||||
"Input": "8ec53dba4c238bfbea1d62922e612a4d",
|
||||
"Graphics": "f94d5aae457aeba67033a8a4ca753214",
|
||||
"GameCooking": "af2e52554f7faed7b4937181dd22d166",
|
||||
"WindowsPlatform": "4a5eec97484253fed72934860ae62c40"
|
||||
}
|
||||
}
|
||||
38
Content/Settings/BuildSettings.json
Normal file
38
Content/Settings/BuildSettings.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"ID": "af2e52554f7faed7b4937181dd22d166",
|
||||
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
|
||||
"EngineBuild": 6216,
|
||||
"Data": {
|
||||
"MaxAssetsPerPackage": 4096,
|
||||
"MaxPackageSizeMB": 1024,
|
||||
"ContentKey": 0,
|
||||
"ForDistribution": false,
|
||||
"SkipPackaging": true,
|
||||
"ShadersNoOptimize": false,
|
||||
"ShadersGenerateDebugData": false,
|
||||
"Presets": [
|
||||
{
|
||||
"Name": "Development",
|
||||
"Targets": [
|
||||
{
|
||||
"Name": "Windows 64bit",
|
||||
"Output": "Output\\Win64",
|
||||
"Platform": 2,
|
||||
"Mode": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Release",
|
||||
"Targets": [
|
||||
{
|
||||
"Name": "Windows 64bit",
|
||||
"Output": "Output\\Win64",
|
||||
"Platform": 2,
|
||||
"Mode": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
15
Content/Settings/GraphicsSettings.json
Normal file
15
Content/Settings/GraphicsSettings.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"ID": "f94d5aae457aeba67033a8a4ca753214",
|
||||
"TypeName": "FlaxEditor.Content.Settings.GraphicsSettings",
|
||||
"EngineBuild": 6216,
|
||||
"Data": {
|
||||
"UseVSync": false,
|
||||
"AAQuality": 3,
|
||||
"SSRQuality": 3,
|
||||
"SSAOQuality": 3,
|
||||
"VolumetricFogQuality": 3,
|
||||
"ShadowsQuality": 3,
|
||||
"ShadowMapsQuality": 3,
|
||||
"AllowCSMBlending": true
|
||||
}
|
||||
}
|
||||
179
Content/Settings/InputSettings.json
Normal file
179
Content/Settings/InputSettings.json
Normal file
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"ID": "8ec53dba4c238bfbea1d62922e612a4d",
|
||||
"TypeName": "FlaxEditor.Content.Settings.InputSettings",
|
||||
"EngineBuild": 6216,
|
||||
"Data": {
|
||||
"ActionMappings": [
|
||||
{
|
||||
"Name": "Exit",
|
||||
"Mode": 1,
|
||||
"Key": 27,
|
||||
"MouseButton": 0,
|
||||
"GamepadButton": 0,
|
||||
"Gamepad": 0
|
||||
},
|
||||
{
|
||||
"Name": "DebugTrigger1",
|
||||
"Mode": 2,
|
||||
"Key": 112,
|
||||
"MouseButton": 0,
|
||||
"GamepadButton": 0,
|
||||
"Gamepad": 0
|
||||
},
|
||||
{
|
||||
"Name": "DebugTrigger2",
|
||||
"Mode": 2,
|
||||
"Key": 113,
|
||||
"MouseButton": 0,
|
||||
"GamepadButton": 0,
|
||||
"Gamepad": 0
|
||||
},
|
||||
{
|
||||
"Name": "DebugTrigger3",
|
||||
"Mode": 2,
|
||||
"Key": 114,
|
||||
"MouseButton": 0,
|
||||
"GamepadButton": 0,
|
||||
"Gamepad": 0
|
||||
},
|
||||
{
|
||||
"Name": "Console",
|
||||
"Mode": 1,
|
||||
"Key": 192,
|
||||
"MouseButton": 0,
|
||||
"GamepadButton": 0,
|
||||
"Gamepad": 0
|
||||
},
|
||||
{
|
||||
"Name": "Console",
|
||||
"Mode": 1,
|
||||
"Key": 220,
|
||||
"MouseButton": 0,
|
||||
"GamepadButton": 0,
|
||||
"Gamepad": 0
|
||||
}
|
||||
],
|
||||
"AxisMappings": [
|
||||
{
|
||||
"Name": "Mouse X",
|
||||
"Axis": 0,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 0,
|
||||
"NegativeButton": 0,
|
||||
"DeadZone": 0.0,
|
||||
"Sensitivity": 0.08,
|
||||
"Gravity": 1.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": false
|
||||
},
|
||||
{
|
||||
"Name": "Mouse Y",
|
||||
"Axis": 1,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 0,
|
||||
"NegativeButton": 0,
|
||||
"DeadZone": 0.0,
|
||||
"Sensitivity": 0.08,
|
||||
"Gravity": 1.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": false
|
||||
},
|
||||
{
|
||||
"Name": "Horizontal",
|
||||
"Axis": 9,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 68,
|
||||
"NegativeButton": 65,
|
||||
"DeadZone": 0.01,
|
||||
"Sensitivity": 5.0,
|
||||
"Gravity": 5.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": true
|
||||
},
|
||||
{
|
||||
"Name": "Vertical",
|
||||
"Axis": 9,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 87,
|
||||
"NegativeButton": 83,
|
||||
"DeadZone": 0.01,
|
||||
"Sensitivity": 5.0,
|
||||
"Gravity": 5.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": true
|
||||
},
|
||||
{
|
||||
"Name": "Horizontal",
|
||||
"Axis": 9,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 39,
|
||||
"NegativeButton": 37,
|
||||
"DeadZone": 0.01,
|
||||
"Sensitivity": 5.0,
|
||||
"Gravity": 5.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": true
|
||||
},
|
||||
{
|
||||
"Name": "Vertical",
|
||||
"Axis": 9,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 38,
|
||||
"NegativeButton": 40,
|
||||
"DeadZone": 0.001,
|
||||
"Sensitivity": 5.0,
|
||||
"Gravity": 5.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": true
|
||||
},
|
||||
{
|
||||
"Name": "Horizontal",
|
||||
"Axis": 3,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 0,
|
||||
"NegativeButton": 0,
|
||||
"DeadZone": 0.19,
|
||||
"Sensitivity": 1.0,
|
||||
"Gravity": 1.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": false
|
||||
},
|
||||
{
|
||||
"Name": "Vertical",
|
||||
"Axis": 4,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 0,
|
||||
"NegativeButton": 0,
|
||||
"DeadZone": 0.19,
|
||||
"Sensitivity": 1.0,
|
||||
"Gravity": 1.0,
|
||||
"Scale": 1.0,
|
||||
"Snap": false
|
||||
},
|
||||
{
|
||||
"Name": "Mouse X",
|
||||
"Axis": 5,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 0,
|
||||
"NegativeButton": 0,
|
||||
"DeadZone": 0.19,
|
||||
"Sensitivity": 1.0,
|
||||
"Gravity": 1.0,
|
||||
"Scale": 4.0,
|
||||
"Snap": false
|
||||
},
|
||||
{
|
||||
"Name": "Mouse Y",
|
||||
"Axis": 6,
|
||||
"Gamepad": 0,
|
||||
"PositiveButton": 0,
|
||||
"NegativeButton": 0,
|
||||
"DeadZone": 0.19,
|
||||
"Sensitivity": 1.0,
|
||||
"Gravity": 1.0,
|
||||
"Scale": -4.0,
|
||||
"Snap": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
12
Content/Settings/TimeSettings.json
Normal file
12
Content/Settings/TimeSettings.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ID": "a55dc3c04da4ea3744b7f1994565beac",
|
||||
"TypeName": "FlaxEditor.Content.Settings.TimeSettings",
|
||||
"EngineBuild": 6216,
|
||||
"Data": {
|
||||
"UpdateFPS": 0.0,
|
||||
"PhysicsFPS": 60.0,
|
||||
"DrawFPS": 0.0,
|
||||
"TimeScale": 1.0,
|
||||
"MaxUpdateDeltaTime": 0.1
|
||||
}
|
||||
}
|
||||
17
Content/Settings/WindowsPlatformSettings.json
Normal file
17
Content/Settings/WindowsPlatformSettings.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"ID": "4a5eec97484253fed72934860ae62c40",
|
||||
"TypeName": "FlaxEditor.Content.Settings.WindowsPlatformSettings",
|
||||
"EngineBuild": 6216,
|
||||
"Data": {
|
||||
"WindowMode": 0,
|
||||
"ScreenWidth": 1280,
|
||||
"ScreenHeight": 720,
|
||||
"ResizableWindow": false,
|
||||
"RunInBackground": false,
|
||||
"ForceSingleInstance": false,
|
||||
"SupportDX12": true,
|
||||
"SupportDX11": true,
|
||||
"SupportDX10": true,
|
||||
"SupportVulkan": true
|
||||
}
|
||||
}
|
||||
27
GoakeFlax.flaxproj
Normal file
27
GoakeFlax.flaxproj
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"Name": "GoakeFlax",
|
||||
"Version": "1.0",
|
||||
"Company": "My Company",
|
||||
"Copyright": "",
|
||||
"GameTarget": "GameTarget",
|
||||
"EditorTarget": "GameEditorTarget",
|
||||
"References": [
|
||||
{
|
||||
"Name": "$(EnginePath)/Flax.flaxproj"
|
||||
}
|
||||
],
|
||||
"DefaultScene": "0733cc9b40d3d05366be64bbd9b59e21",
|
||||
"DefaultSceneSpawn": {
|
||||
"Position": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
},
|
||||
"Direction": {
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
},
|
||||
"MinEngineVersion": "0.0.6194"
|
||||
}
|
||||
288
Source/Game/Cabrito/Console/Console.cs
Normal file
288
Source/Game/Cabrito/Console/Console.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Cabrito
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class ConsoleVariableAttribute : Attribute
|
||||
{
|
||||
public string name;
|
||||
|
||||
public ConsoleVariableAttribute(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class ConsoleCommandAttribute : Attribute
|
||||
{
|
||||
public string name;
|
||||
|
||||
public ConsoleCommandAttribute(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ConsoleVariable
|
||||
{
|
||||
private FieldInfo field;
|
||||
|
||||
public ConsoleVariable(FieldInfo field)
|
||||
{
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public string GetValueString()
|
||||
{
|
||||
if (field.FieldType != typeof(string))
|
||||
throw new Exception("cvar is not type of string");
|
||||
|
||||
return (string)field.GetValue(null);
|
||||
}
|
||||
|
||||
public void SetValue(string value)
|
||||
{
|
||||
var type = field.FieldType;
|
||||
if (type == typeof(string))
|
||||
field.SetValue(null, value);
|
||||
else
|
||||
throw new Exception("Unsupported type for SetValue: " + type.Name);
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ConsoleCommand
|
||||
{
|
||||
private MethodInfo method;
|
||||
|
||||
public ConsoleCommand(MethodInfo method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public void Invoke(params object[] parameters)
|
||||
{
|
||||
method.Invoke(null, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Console
|
||||
{
|
||||
private static ConsoleScriptBase scriptInstance = null;
|
||||
|
||||
// Returns if Console window open right now.
|
||||
public static bool IsOpen { get; internal set; }
|
||||
|
||||
// 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 { get { return stopwatch.Elapsed.TotalSeconds > 0.1; } }
|
||||
private static Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
|
||||
// Called when Console is opened.
|
||||
public static Action OnOpen;
|
||||
|
||||
// Called when Console is closed.
|
||||
public static Action OnClose;
|
||||
|
||||
public static bool ShowExecutedLines = true;
|
||||
public static string LinePrefix { get; internal set; } = "]";
|
||||
|
||||
|
||||
private static List<string> consoleLines = new List<string>();
|
||||
private static Dictionary<string, ConsoleCommand> consoleCommands = new Dictionary<string, ConsoleCommand>();
|
||||
private static Dictionary<string, ConsoleVariable> consoleVariables = new Dictionary<string, ConsoleVariable>();
|
||||
|
||||
// Initializes the Console system.
|
||||
public static void Init()
|
||||
{
|
||||
consoleLines.Clear();
|
||||
consoleCommands.Clear();
|
||||
consoleVariables.Clear();
|
||||
|
||||
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."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
foreach (var method in type.GetMethods())
|
||||
{
|
||||
if (!method.IsStatic)
|
||||
continue;
|
||||
|
||||
Attribute[] attributes = Attribute.GetCustomAttributes(method);
|
||||
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
if (attr is ConsoleCommandAttribute cmdAttribute)
|
||||
{
|
||||
//Console.Print("found cmd '" + cmdAttribute.name + "' bound to field '" + method.Name + "'");
|
||||
var cmd = new ConsoleCommand(method);
|
||||
consoleCommands.Add(cmdAttribute.name.ToLower(), cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var field in type.GetFields())
|
||||
{
|
||||
if (!field.IsStatic)
|
||||
continue;
|
||||
|
||||
Attribute[] attributes = Attribute.GetCustomAttributes(field);
|
||||
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
if (attr is ConsoleVariableAttribute cvarAttribute)
|
||||
{
|
||||
//Console.Print("found cvar '" + cvarAttribute.name + "' bound to field '" + field.Name + "'");
|
||||
var cvar = new ConsoleVariable(field);
|
||||
consoleVariables.Add(cvarAttribute.name.ToLower(), cvar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register script for handling the Console frontend.
|
||||
internal static void RegisterConsoleScript(ConsoleScriptBase instance)
|
||||
{
|
||||
if (scriptInstance == instance)
|
||||
return;
|
||||
|
||||
scriptInstance = instance;
|
||||
OnOpen += instance.OnConsoleOpen;
|
||||
OnClose += instance.OnConsoleClose;
|
||||
|
||||
foreach (var line in consoleLines)
|
||||
scriptInstance.AddLine(line);
|
||||
}
|
||||
|
||||
/// Unregister already registered Console script.
|
||||
internal static void UnregisterConsoleScript(ConsoleScriptBase instance)
|
||||
{
|
||||
if (scriptInstance != instance)
|
||||
return;
|
||||
|
||||
Close();
|
||||
|
||||
scriptInstance = null;
|
||||
OnOpen -= instance.OnConsoleOpen;
|
||||
OnClose -= instance.OnConsoleClose;
|
||||
}
|
||||
|
||||
public static IReadOnlyCollection<string> GetLines()
|
||||
{
|
||||
return consoleLines.AsReadOnly();
|
||||
}
|
||||
|
||||
// Echoes text to Console.
|
||||
public static void Print(string text)
|
||||
{
|
||||
consoleLines.Add(text);
|
||||
scriptInstance?.AddLine(text);
|
||||
}
|
||||
|
||||
// Echoes warning text to Console.
|
||||
public static void PrintWarning(string text)
|
||||
{
|
||||
consoleLines.Add(text);
|
||||
scriptInstance?.AddLine(text);
|
||||
}
|
||||
|
||||
// Echoes error text to Console.
|
||||
public static void PrintError(string text)
|
||||
{
|
||||
consoleLines.Add(text);
|
||||
scriptInstance?.AddLine(text);
|
||||
}
|
||||
|
||||
// Echoes developer/debug text to Console.
|
||||
public static void PrintDebug(string text)
|
||||
{
|
||||
consoleLines.Add(text);
|
||||
scriptInstance?.AddLine(text);
|
||||
}
|
||||
|
||||
// Opens the Console.
|
||||
public static void Open()
|
||||
{
|
||||
if (IsOpen)
|
||||
return;
|
||||
|
||||
IsOpen = true;
|
||||
OnOpen?.Invoke();
|
||||
}
|
||||
|
||||
// Closes the Console;
|
||||
public static void Close()
|
||||
{
|
||||
if (!IsOpen)
|
||||
return;
|
||||
|
||||
IsOpen = false;
|
||||
OnClose?.Invoke();
|
||||
|
||||
stopwatch.Restart();
|
||||
}
|
||||
|
||||
public static void ClearInput()
|
||||
{
|
||||
scriptInstance?.SetInput("");
|
||||
}
|
||||
|
||||
public static void Execute(string str)
|
||||
{
|
||||
str = str.Trim();
|
||||
|
||||
if (ShowExecutedLines)
|
||||
Console.Print(LinePrefix + str);
|
||||
|
||||
string[] strs = str.Split(' ');
|
||||
string execute = strs[0];
|
||||
string value = strs.Length > 1 ? str.Substring(execute.Length + 1) : null;
|
||||
|
||||
//Console.PrintDebug("Executed '" + execute + "' with params: '" + value + "'");
|
||||
|
||||
if (consoleCommands.TryGetValue(execute, out ConsoleCommand cmd))
|
||||
{
|
||||
cmd.Invoke();
|
||||
//Console.Print("Command bound to '" + execute + "' is '" + cmd.method.Name + "'");
|
||||
}
|
||||
else if (consoleVariables.TryGetValue(execute, out ConsoleVariable cvar))
|
||||
{
|
||||
if (value != null)
|
||||
cvar.SetValue(value);
|
||||
|
||||
Console.Print("'" + execute + "' is '" + cvar.GetValueString() + "'");
|
||||
}
|
||||
else
|
||||
Console.Print("Unknown command '" + execute + "'");
|
||||
}
|
||||
|
||||
public static string GetVariable(string variableName)
|
||||
{
|
||||
if (consoleVariables.TryGetValue(variableName, out ConsoleVariable cvar))
|
||||
{
|
||||
string value = cvar.GetValueString();
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Source/Game/Cabrito/Console/ConsoleContainerControl.cs
Normal file
37
Source/Game/Cabrito/Console/ConsoleContainerControl.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace Cabrito
|
||||
{
|
||||
// Container that keeps the focus on the input box
|
||||
public class ConsoleContainerControl : ContainerControl
|
||||
{
|
||||
[HideInEditor]
|
||||
public ConsoleInputTextBox inputBox;
|
||||
|
||||
public ConsoleContainerControl() : base()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ConsoleContainerControl(float x, float y, float width, float height) : base(x, y, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGotFocus()
|
||||
{
|
||||
base.OnGotFocus();
|
||||
if (inputBox != null)
|
||||
Focus(inputBox);
|
||||
}
|
||||
|
||||
public override void OnLostFocus()
|
||||
{
|
||||
base.OnLostFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
565
Source/Game/Cabrito/Console/ConsoleContentTextBox.cs
Normal file
565
Source/Game/Cabrito/Console/ConsoleContentTextBox.cs
Normal file
@@ -0,0 +1,565 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FlaxEditor;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace Cabrito
|
||||
{
|
||||
public class ConsoleContentTextBox : Control
|
||||
{
|
||||
[HideInEditor]
|
||||
public ConsoleInputTextBox inputBox;
|
||||
|
||||
protected TextLayoutOptions _layout;
|
||||
|
||||
public FontReference Font;
|
||||
|
||||
public float LineSpacing = 1.0f;
|
||||
|
||||
public TextWrapping Wrapping;
|
||||
|
||||
public Color SelectionColor = new Color(0x00, 0x7A, 0xCC, 0xFF);
|
||||
public Color BackgroundSelectedColor = Color.Transparent;
|
||||
public float BackgroundSelectedFlashSpeed = 0;
|
||||
public Color BorderSelectedColor = Color.Transparent;
|
||||
public float CaretFlashSpeed = 0;
|
||||
public Color BorderColor;
|
||||
public Color TextColor = Color.White;
|
||||
public int DefaultMargin = 1;
|
||||
|
||||
private Vector2 scrollOffset = new Vector2(0);
|
||||
|
||||
private int selectionStartLine = 0;
|
||||
private int selectionStartChar = 0;
|
||||
private int selectionEndLine = 0;
|
||||
private int selectionEndChar = 0;
|
||||
|
||||
private bool selectionActive;
|
||||
public bool HasSelection => !(selectionStartLine == selectionEndLine && selectionStartChar == selectionEndChar);
|
||||
|
||||
public ConsoleContentTextBox() : base()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ConsoleContentTextBox(ConsoleInputTextBox inputBox, float x, float y, float width, float height) : base(x, y, width, height)
|
||||
{
|
||||
this.inputBox = inputBox;
|
||||
Height = height;
|
||||
|
||||
_layout = TextLayoutOptions.Default;
|
||||
_layout.VerticalAlignment = TextAlignment.Near;
|
||||
_layout.TextWrapping = TextWrapping.WrapChars;
|
||||
_layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
|
||||
|
||||
//IsMultiline = true;
|
||||
//IsReadOnly = true;
|
||||
//CaretColor = new Color(0f, 0f, 0f, 0f);
|
||||
AutoFocus = false;
|
||||
}
|
||||
|
||||
public int GetFontHeight()
|
||||
{
|
||||
var font = Font.GetFont();
|
||||
if (font == null)
|
||||
return (int)Height;
|
||||
|
||||
return (int)Mathf.Round(LineSpacing * font.Height * Scale.Y);
|
||||
}
|
||||
|
||||
struct LineInfo
|
||||
{
|
||||
public int lineIndex;
|
||||
public int lineOffset;
|
||||
}
|
||||
|
||||
private void CalculateVisibleLines(IReadOnlyCollection<string> lines, out int firstVisibleLine, out int lastVisibleLine, out LineInfo[] wrappedLines)
|
||||
{
|
||||
wrappedLines = null;
|
||||
firstVisibleLine = 0;
|
||||
lastVisibleLine = 0;
|
||||
|
||||
var font = Font.GetFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
float fontWidth = (int)font.MeasureText("a").X; // hacky, but works for fixed-size fonts...
|
||||
int lineMaxChars = (int)(Width / fontWidth);
|
||||
int lineMaxLines = (int)(Height / font.Height);
|
||||
int numLines = 0;
|
||||
int lineIndex = lines.Count - 1;
|
||||
List<LineInfo> lineInfos = new List<LineInfo>(lineMaxLines);
|
||||
foreach (string line in lines.Reverse())
|
||||
{
|
||||
int numChars = 0;
|
||||
while (numChars < line.Length)
|
||||
{
|
||||
LineInfo li = new LineInfo();
|
||||
li.lineIndex = lineIndex;
|
||||
li.lineOffset = numChars;
|
||||
lineInfos.Add(li);
|
||||
|
||||
numChars += lineMaxChars;
|
||||
}
|
||||
numLines++;
|
||||
lineIndex--;
|
||||
|
||||
if (lineInfos.Count > lineMaxLines)
|
||||
break;
|
||||
}
|
||||
|
||||
lineInfos.Reverse();
|
||||
wrappedLines = lineInfos.ToArray();
|
||||
|
||||
//return lines[lines.Count - numLines .. lines.Count]; // C# 8.0...
|
||||
firstVisibleLine = lines.Count - numLines;
|
||||
lastVisibleLine = lines.Count;
|
||||
}
|
||||
|
||||
public static double accumDrawTime = 0.0;
|
||||
public static long accumDrawTimes = 0;
|
||||
public override void Draw()
|
||||
{
|
||||
// Cache data
|
||||
var rect = new Rectangle(Vector2.Zero, Size);
|
||||
var font = Font.GetFont();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
Profiler.BeginEvent("ConsoleContetTextBoxDraw");
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
// 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);
|
||||
|
||||
var lines = Console.GetLines();
|
||||
|
||||
if (lines.Count > 0)
|
||||
{
|
||||
|
||||
// Apply view offset and clip mask
|
||||
var textClipRectangle = new Rectangle(1, 1, Width - 2, Height - 2);
|
||||
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();
|
||||
float spacing = GetRealLineSpacing();
|
||||
|
||||
// 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);
|
||||
}*/
|
||||
}
|
||||
|
||||
// Make sure lengthy lines are split
|
||||
CalculateVisibleLines(lines, out int startLine, out int lastLine, out LineInfo[] wrappedLines);
|
||||
|
||||
float lineHeight = font.Height;
|
||||
float accumHeight = wrappedLines.Length * lineHeight;
|
||||
|
||||
int selectionLeftLine = selectionStartLine;
|
||||
int selectionLeftChar = selectionStartChar;
|
||||
int selectionRightLine = selectionEndLine;
|
||||
int selectionRightChar = selectionEndChar;
|
||||
|
||||
if (selectionLeftLine > selectionRightLine || (selectionLeftLine == selectionRightLine && selectionLeftChar > selectionRightChar))
|
||||
{
|
||||
selectionLeftLine = selectionEndLine;
|
||||
selectionLeftChar = selectionEndChar;
|
||||
selectionRightLine = selectionStartLine;
|
||||
selectionRightChar = selectionStartChar;
|
||||
}
|
||||
|
||||
// render selection
|
||||
if (selectionActive)
|
||||
{
|
||||
|
||||
//float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
|
||||
//alpha = alpha * alpha;
|
||||
Color selectionColor = SelectionColor;// * alpha;
|
||||
|
||||
TextLayoutOptions layout = _layout;
|
||||
layout.Bounds.Y -= accumHeight - Height;
|
||||
for (int i = startLine; i < lastLine; i++)
|
||||
{
|
||||
string line = lines.ElementAt(i);
|
||||
|
||||
Rectangle selectionRect = new Rectangle(layout.Bounds.X, layout.Bounds.Y, 0f, 0f);
|
||||
|
||||
// apply selection
|
||||
if (i >= selectionLeftLine && i <= selectionRightLine)
|
||||
{
|
||||
if (i > selectionLeftLine && i < selectionRightLine)
|
||||
{
|
||||
// whole line is selected
|
||||
Vector2 lineSize = font.MeasureText(line);
|
||||
selectionRect.Width = lineSize.X;
|
||||
selectionRect.Height = lineSize.Y;
|
||||
}
|
||||
else if (i == selectionLeftLine)
|
||||
{
|
||||
if (i < selectionRightLine)
|
||||
{
|
||||
// right side of the line is selected
|
||||
Vector2 leftSize = font.MeasureText(line.Substring(0, selectionLeftChar));
|
||||
Vector2 rightSize = font.MeasureText(line.Substring(selectionLeftChar));
|
||||
selectionRect.X += leftSize.X;
|
||||
selectionRect.Width = rightSize.X;
|
||||
selectionRect.Height = rightSize.Y;
|
||||
|
||||
//int diff = line.Length - selectionLeftChar;
|
||||
//line = line.Substring(0, selectionLeftChar) + (diff > 0 ? new string('X', diff) : "");
|
||||
}
|
||||
else if (i == selectionRightLine)
|
||||
{
|
||||
// selecting middle of the one line
|
||||
Vector2 lineSize = font.MeasureText(line);
|
||||
Vector2 leftSize = font.MeasureText(line.Substring(0, selectionLeftChar));
|
||||
Vector2 rightSize = font.MeasureText(line.Substring(selectionRightChar));
|
||||
|
||||
selectionRect.X += leftSize.X;
|
||||
selectionRect.Width = lineSize.X - (leftSize.X + rightSize.Y);
|
||||
selectionRect.Height = lineSize.Y;
|
||||
|
||||
//int diff = selectionRightChar - selectionLeftChar;
|
||||
//line = line.Substring(0, selectionLeftChar) + (diff > 0 ? new string('X', diff) : "") + line.Substring(selectionRightChar);
|
||||
}
|
||||
}
|
||||
else if (i == selectionRightLine)
|
||||
{
|
||||
// left side of the line is selected
|
||||
Vector2 leftSize = font.MeasureText(line.Substring(0, selectionRightChar));
|
||||
selectionRect.Width = leftSize.X;
|
||||
selectionRect.Height = leftSize.Y;
|
||||
|
||||
//line = (selectionRightChar > 0 ? new string('X', selectionRightChar) : "") + line.Substring(selectionRightChar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Render2D.FillRectangle(selectionRect, selectionColor);
|
||||
|
||||
layout.Bounds.Y += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// render lines
|
||||
{
|
||||
TextLayoutOptions layout = _layout;
|
||||
layout.Bounds.Y -= accumHeight - Height;
|
||||
for (int i = startLine; i < lastLine; i++)
|
||||
{
|
||||
string line = lines.ElementAt(i);
|
||||
Render2D.DrawText(font, line, TextColor, ref layout);
|
||||
layout.Bounds.Y += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/*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();
|
||||
}
|
||||
sw.Stop();
|
||||
accumDrawTime += sw.Elapsed.TotalSeconds;
|
||||
accumDrawTimes++;
|
||||
Profiler.EndEvent();
|
||||
}
|
||||
|
||||
|
||||
private void OnSelectingBegin()
|
||||
{
|
||||
if (selectionActive)
|
||||
return;
|
||||
|
||||
selectionActive = true;
|
||||
StartMouseCapture();
|
||||
}
|
||||
|
||||
private void OnSelectingEnd()
|
||||
{
|
||||
if (!selectionActive)
|
||||
return;
|
||||
|
||||
selectionActive = false;
|
||||
EndMouseCapture();
|
||||
}
|
||||
|
||||
public bool HitTestText(Vector2 location, out int hitLine, out int hitChar)
|
||||
{
|
||||
hitLine = 0;
|
||||
hitChar = 0;
|
||||
var font = Font.GetFont();
|
||||
if (font == null)
|
||||
return false;
|
||||
|
||||
var lines = Console.GetLines();
|
||||
CalculateVisibleLines(lines, out int startLine, out int lastLine, out LineInfo[] wrappedLines);
|
||||
|
||||
TextLayoutOptions layout = _layout;
|
||||
float lineHeight = font.Height;
|
||||
float visibleHeight = wrappedLines.Length * lineHeight;
|
||||
float top = layout.Bounds.Bottom - visibleHeight;
|
||||
int lineMaxLines = (int)(Height / font.Height);
|
||||
|
||||
int hiddenLines = 0;
|
||||
if (wrappedLines.Length > lineMaxLines)
|
||||
hiddenLines = wrappedLines.Length - lineMaxLines;
|
||||
//if (top < layout.Bounds.Top)
|
||||
// hiddenLines = (int)Math.Ceiling((layout.Bounds.Top - top) / (float)lineHeight);
|
||||
|
||||
int hitWrappedLine = (int)((location.Y - top) / lineHeight) + hiddenLines;
|
||||
if (hitWrappedLine < 0 || hitWrappedLine >= wrappedLines.Length)
|
||||
return false;
|
||||
|
||||
hitLine = wrappedLines[hitWrappedLine].lineIndex;
|
||||
string line = lines.ElementAt(hitLine);
|
||||
|
||||
layout.Bounds.Y = top + ((hitWrappedLine) * lineHeight) + 22.5f;
|
||||
layout.Bounds.Height = top + visibleHeight;
|
||||
/*if (layout.Bounds.Y < 0)
|
||||
{
|
||||
layout.Bounds.Y = 1;
|
||||
}*/
|
||||
|
||||
hitChar = font.HitTestText(line, location, ref layout);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*public int CharIndexAtPoint(ref Vector2 location)
|
||||
{
|
||||
return HitTestText(location + _viewOffset);
|
||||
}*/
|
||||
|
||||
|
||||
public override bool OnMouseDown(Vector2 location, MouseButton button)
|
||||
{
|
||||
bool ret = false;
|
||||
if (button == MouseButton.Left && !IsFocused)
|
||||
{
|
||||
Focus();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
var lines = Console.GetLines();
|
||||
if (button == MouseButton.Left && lines.Count > 0)
|
||||
{
|
||||
bool selectionStarted = !selectionActive;
|
||||
Focus();
|
||||
OnSelectingBegin();
|
||||
|
||||
//FlaxEngine.Debug.Log("mousedown, started: " + selectionStarted.ToString());
|
||||
|
||||
if (HitTestText(location, out int hitLine, out int hitChar))
|
||||
{
|
||||
selectionStartLine = hitLine;
|
||||
selectionStartChar = hitChar;
|
||||
selectionEndLine = hitLine;
|
||||
selectionEndChar = hitChar;
|
||||
}
|
||||
else
|
||||
throw new Exception("no???");
|
||||
|
||||
|
||||
// Select range with shift
|
||||
/*if (_selectionStart != -1 && RootWindow.GetKey(KeyboardKeys.Shift) && SelectionLength == 0)
|
||||
{
|
||||
if (hitPos < _selectionStart)
|
||||
SetSelection(hitPos, _selectionStart);
|
||||
else
|
||||
SetSelection(_selectionStart, hitPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSelection(hitPos);
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override void OnMouseMove(Vector2 location)
|
||||
{
|
||||
if (selectionActive)
|
||||
{
|
||||
if (HitTestText(location, out int hitLine, out int hitChar))
|
||||
{
|
||||
selectionEndLine = hitLine;
|
||||
selectionEndChar = hitChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseUp(Vector2 location, MouseButton button)
|
||||
{
|
||||
if (button == MouseButton.Left)
|
||||
{
|
||||
OnSelectingEnd();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsoleContentTextBox_Old : ConsoleTextBoxBase
|
||||
{
|
||||
[HideInEditor]
|
||||
public ConsoleInputTextBox inputBox;
|
||||
|
||||
private string _textCache;
|
||||
private long _textCacheLines;
|
||||
public override string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
var lines = Console.GetLines();
|
||||
if (_textCache == null || _textCacheLines != lines.Count)
|
||||
{
|
||||
//Deselect();
|
||||
//ResetViewOffset();
|
||||
|
||||
_textCache = string.Join("\n", lines);
|
||||
_textCacheLines = lines.Count;
|
||||
|
||||
OnTextChanged();
|
||||
}
|
||||
return _textCache;
|
||||
}
|
||||
set => _textCache = value;
|
||||
}
|
||||
|
||||
public ConsoleContentTextBox_Old(ConsoleInputTextBox inputBox, float x, float y, float width, float height) : base(x, y, width, height)
|
||||
{
|
||||
this.inputBox = inputBox;
|
||||
Height = height;
|
||||
|
||||
IsMultiline = true;
|
||||
IsReadOnly = true;
|
||||
CaretColor = new Color(0f, 0f, 0f, 0f);
|
||||
AutoFocus = false;
|
||||
}
|
||||
|
||||
public override void OnGotFocus()
|
||||
{
|
||||
base.OnGotFocus();
|
||||
}
|
||||
|
||||
public override void OnLostFocus()
|
||||
{
|
||||
ClearSelection();
|
||||
base.OnLostFocus();
|
||||
}
|
||||
|
||||
protected override void OnTextChanged()
|
||||
{
|
||||
base.OnTextChanged();
|
||||
ScrollToEnd();
|
||||
}
|
||||
|
||||
public override bool OnKeyDown(KeyboardKeys key)
|
||||
{
|
||||
bool ret;
|
||||
switch (key)
|
||||
{
|
||||
case KeyboardKeys.Escape:
|
||||
ret = true; // disable text restoration
|
||||
break;
|
||||
case KeyboardKeys.Home:
|
||||
case KeyboardKeys.End:
|
||||
// TODO: scroll top and scroll bottom
|
||||
ret = true;
|
||||
break;
|
||||
case KeyboardKeys.ArrowUp:
|
||||
case KeyboardKeys.ArrowDown:
|
||||
case KeyboardKeys.ArrowLeft:
|
||||
case KeyboardKeys.ArrowRight:
|
||||
ret = true; // input box has priority
|
||||
break;
|
||||
case KeyboardKeys.PageUp:
|
||||
case KeyboardKeys.PageDown:
|
||||
return true;
|
||||
default:
|
||||
ret = base.OnKeyDown(key);
|
||||
break;
|
||||
}
|
||||
|
||||
if (inputBox == null)
|
||||
return ret;
|
||||
return inputBox.OnKeyDown(key);
|
||||
}
|
||||
|
||||
public override void OnKeyUp(KeyboardKeys key)
|
||||
{
|
||||
base.OnKeyUp(key);
|
||||
if (inputBox != null)
|
||||
inputBox.OnKeyUp(key);
|
||||
}
|
||||
|
||||
public override bool OnCharInput(char c)
|
||||
{
|
||||
if (inputBox == null)
|
||||
return base.OnCharInput(c);
|
||||
|
||||
Focus(inputBox);
|
||||
return inputBox.OnCharInput(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
103
Source/Game/Cabrito/Console/ConsoleInputTextBox.cs
Normal file
103
Source/Game/Cabrito/Console/ConsoleInputTextBox.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
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; }
|
||||
|
||||
private ConsoleContentTextBox contentBox;
|
||||
|
||||
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 override bool OnCharInput(char c)
|
||||
{
|
||||
// Ignore any characters generated by the key which opens the console
|
||||
var consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None);
|
||||
foreach (var mapping in consoleKeyMappings)
|
||||
{
|
||||
if (Input.GetKey(mapping.Key))
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnCharInput(c);
|
||||
}
|
||||
|
||||
public override bool OnKeyDown(KeyboardKeys key)
|
||||
{
|
||||
var consoleKeyMappings = Input.ActionMappings.Where(x => x.Name == "Console" && x.Key != KeyboardKeys.None);
|
||||
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
||||
bool ctrlDown = Root.GetKey(KeyboardKeys.Control);
|
||||
|
||||
if (consoleKeyMappings.Any(x => x.Key == key))
|
||||
{
|
||||
Clear();
|
||||
return true;
|
||||
}
|
||||
else if (key == KeyboardKeys.Escape)
|
||||
{
|
||||
Console.Close();
|
||||
Clear();
|
||||
return true;
|
||||
}
|
||||
else if (key == KeyboardKeys.Return)
|
||||
{
|
||||
Console.Execute(Text);
|
||||
Clear();
|
||||
return true;
|
||||
}
|
||||
else if (key == KeyboardKeys.ArrowUp || key == KeyboardKeys.ArrowDown)
|
||||
{
|
||||
// TODO: implement input history
|
||||
return true;
|
||||
}
|
||||
else if (key == KeyboardKeys.PageUp || key == KeyboardKeys.PageDown)
|
||||
{
|
||||
return contentBox.OnKeyDown(key);
|
||||
}
|
||||
|
||||
return base.OnKeyDown(key);
|
||||
}
|
||||
|
||||
public override void OnLostFocus()
|
||||
{
|
||||
// Avoids reseting the caret location
|
||||
var 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
320
Source/Game/Cabrito/Console/ConsoleScript.cs
Normal file
320
Source/Game/Cabrito/Console/ConsoleScript.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace Cabrito
|
||||
{
|
||||
public abstract class ConsoleScriptBase : Script
|
||||
{
|
||||
public abstract void OnConsoleOpen();
|
||||
public abstract void OnConsoleClose();
|
||||
public abstract void SetInput(string text);
|
||||
public abstract void AddLine(string text);
|
||||
}
|
||||
|
||||
public class ConsoleScript : ConsoleScriptBase
|
||||
{
|
||||
[Limit(5, 720, 1)]
|
||||
public int ConsoleFontSize = 16;
|
||||
|
||||
[Limit(0.05f, 1.0f, 1)]
|
||||
public float ConsoleHeight = 0.65f;
|
||||
|
||||
[Limit(0.5f, 4f, 0.05f)]
|
||||
public float LineSpacing
|
||||
{
|
||||
get => lineSpacing;
|
||||
set
|
||||
{
|
||||
lineSpacing = value;
|
||||
|
||||
if (consoleBox != null)
|
||||
consoleBox.LineSpacing = value;
|
||||
if (consoleInputBox != null)
|
||||
consoleInputBox.LineSpacing = value;
|
||||
|
||||
RefreshLayout();
|
||||
}
|
||||
}
|
||||
private float lineSpacing;
|
||||
|
||||
public FontAsset ConsoleFont;
|
||||
|
||||
public Texture BackgroundTexture;
|
||||
|
||||
public Color BackgroundColor;
|
||||
|
||||
private UIControl rootControl;
|
||||
private ConsoleContentTextBox consoleBox;
|
||||
private ConsoleInputTextBox consoleInputBox;
|
||||
private Image backgroundImage;
|
||||
|
||||
internal InputEvent consoleInputEvent;
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
Console.Init();
|
||||
|
||||
consoleInputEvent = new InputEvent("Console");
|
||||
consoleInputEvent.Triggered += OnConsoleInputEvent;
|
||||
|
||||
Vector2 screenSize = Screen.Size;
|
||||
Vector2 consoleSize = new Vector2(screenSize.X, screenSize.Y * ConsoleHeight);
|
||||
|
||||
FontReference fontReference = new FontReference(ConsoleFont, ConsoleFontSize);
|
||||
Font fontRaw = fontReference.GetFont();
|
||||
int fontHeight = fontRaw.Height;
|
||||
|
||||
// root actor which holds all the elements
|
||||
var rootContainerControl = new ContainerControl(0, 0, screenSize.X, screenSize.Y);
|
||||
rootControl = Actor.AddChild<UIControl>();
|
||||
rootControl.Name = "ConsoleRoot";
|
||||
rootControl.Control = rootContainerControl;
|
||||
|
||||
if (backgroundImage == null)
|
||||
{
|
||||
backgroundImage = new Image(0, 0, consoleSize.X, consoleSize.Y);
|
||||
if (BackgroundTexture != null)
|
||||
{
|
||||
backgroundImage.Brush = new TextureBrush(BackgroundTexture);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundImage.Brush = new SolidColorBrush(BackgroundColor);
|
||||
backgroundImage.KeepAspectRatio = false;
|
||||
}
|
||||
|
||||
var locationFix = backgroundImage.Location;
|
||||
var parentControl = rootControl.AddChild<UIControl>();
|
||||
parentControl.Name = "ConsoleBackground";
|
||||
parentControl.Control = backgroundImage;
|
||||
backgroundImage.Location = locationFix; // workaround to UIControl.Control overriding the old position
|
||||
backgroundImage.Enabled = false;
|
||||
}
|
||||
|
||||
// Create a container that keeps the focus in the input box when clicked outside the console window.
|
||||
// The container must be created before the content box so interacting with the console lines wont get
|
||||
// stolen by this container.
|
||||
var containerControl = new ConsoleContainerControl(0, 0, screenSize.X, screenSize.Y);
|
||||
var focusControl = rootControl.AddChild<UIControl>();
|
||||
focusControl.Name = "ConsoleInputContainer";
|
||||
focusControl.Control = containerControl;
|
||||
|
||||
{
|
||||
if (consoleBox == null)
|
||||
{
|
||||
consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
|
||||
consoleBox.Font = fontReference;
|
||||
|
||||
//consoleBox.HorizontalAlignment = TextAlignment.Near;
|
||||
//consoleBox.VerticalAlignment = TextAlignment.Near;
|
||||
consoleBox.Wrapping = TextWrapping.WrapWords;
|
||||
consoleBox.BackgroundColor = Color.Transparent;
|
||||
consoleBox.BackgroundSelectedColor = Color.Transparent;
|
||||
consoleBox.BackgroundSelectedFlashSpeed = 0;
|
||||
consoleBox.BorderSelectedColor = Color.Transparent;
|
||||
consoleBox.CaretFlashSpeed = 0;
|
||||
consoleBox.LineSpacing = LineSpacing;
|
||||
}
|
||||
|
||||
var locationFix = consoleBox.Location;
|
||||
var parentControl = rootControl.AddChild<UIControl>();
|
||||
parentControl.Name = "ConsoleContent";
|
||||
parentControl.Control = consoleBox;
|
||||
consoleBox.Location = locationFix; // workaround to UIControl.Control overriding the old position
|
||||
}
|
||||
|
||||
{
|
||||
if (consoleInputBox == null)
|
||||
{
|
||||
consoleInputBox = new ConsoleInputTextBox(consoleBox, 0, consoleSize.Y - fontHeight, consoleSize.X, fontHeight);
|
||||
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;
|
||||
}
|
||||
containerControl.inputBox = consoleInputBox;
|
||||
|
||||
var locationFix = consoleInputBox.Location;
|
||||
var parentControl = rootControl.AddChild<UIControl>();
|
||||
parentControl.Name = "ConsoleInput";
|
||||
parentControl.Control = consoleInputBox;
|
||||
consoleInputBox.Location = locationFix; // workaround to UIControl.Control overriding the old position
|
||||
}
|
||||
|
||||
// close instantly
|
||||
var rootlocation = rootControl.Control.Location;
|
||||
rootlocation.Y = -rootControl.Control.Height;
|
||||
rootControl.Control.Location = rootlocation;
|
||||
OnConsoleClose();
|
||||
|
||||
Console.RegisterConsoleScript(this);
|
||||
RefreshLayout();
|
||||
|
||||
//for (int i = 0; i < 10; i++)
|
||||
{
|
||||
string[] teststr = {
|
||||
/*
|
||||
"...loading 'scripts/devilpunch.shader'",
|
||||
"...loading 'scripts/mkoxide.shader'",
|
||||
"...loading 'scripts/cpm22.shader'",
|
||||
"...loading 'scripts/cpm27.shader'",
|
||||
"...loading 'scripts/island.shader'",
|
||||
"...loading 'scripts/noodtex3.shader'",
|
||||
"...loading 'scripts/nood_cosdglass.shader'",
|
||||
"...loading 'scripts/nood_fog_1000.shader'",
|
||||
"...loading 'scripts/nood_lightbeams.shader'",
|
||||
"...loading 'scripts/nood_nightsky_nolight.shader'",
|
||||
"Rescanning shaders",
|
||||
@"Raw input type 0: [0] \\?\HID#VID_046D&PID_C231#2&229a2ea&0&0000#",
|
||||
@"Raw input type 0: [18] \\?\HID#VID_046D&PID_C539&MI_01&Col01#8&24523410&0&0000#",
|
||||
@"Raw input type 0: [19] \\?\HID#VID_28DE&PID_1102&MI_01#8&2fb9bb60&0&0000#",
|
||||
@"Raw input type 0: [20] \\?\HID#VID_04D9&PID_A131&MI_02&Col01#8&197f95af&0&0000#",
|
||||
"Raw input: initialized with 5 mice and 0 keyboards",
|
||||
"WASAPI: overriding channels",
|
||||
"WASAPI: 2 channel 32bit 48000khz non-exclusive",
|
||||
"WASAPI: requested periodicity: 128, default: 480, min: 128, max: 480, step: 16",
|
||||
"WASAPI: Low latency mode enabled",
|
||||
"WASAPI: buffer size: 280",
|
||||
"OpenGL renderer initialized",
|
||||
"video restart took 0.291480 seconds",
|
||||
"main thread video restart took 0.291798 secs",
|
||||
"[------ Goake Initialized ------]",
|
||||
"Initializing menu.dat",
|
||||
"Couldn't load sound/ambience/water1.wav",
|
||||
"Couldn't load sound/ambience/wind2.wav",
|
||||
"Couldn't load sound/misc/menu2.wav",
|
||||
"Couldn't load sound/misc/menu3.wav",
|
||||
"]cl_maxfps 120",
|
||||
"a very very very long long long line in repeat a very very very long long long line in repeat a very very very long long long line in repeat a very very very long long long line in repeat a very very very long long long line in repeat a very very very long long long line in repeat"
|
||||
*/
|
||||
"Warning: Unsupported entity field 'light'",
|
||||
"Warning: Unsupported entity field '_keeplights'",
|
||||
"Warning: Unsupported entity field 'light'",
|
||||
"Warning: Unsupported entity field '_keeplights'",
|
||||
"Warning: Unsupported entity field 'light'",
|
||||
"Warning: Unsupported entity field '_keeplights'",
|
||||
"Warning: Unsupported entity field 'light'",
|
||||
"Warning: Unsupported entity field '_keeplights'",
|
||||
"maps/aerowalk.bsp: Using lightmap format E5BGR9_UF",
|
||||
"maps/devbox.bsp: Using lightmap format E5BGR9_UF",
|
||||
"what",
|
||||
"Game mode changed to: Free For All",
|
||||
"what",
|
||||
"641 additional FS searches",
|
||||
"fixangle frame: 1427",
|
||||
"Couldn't load sound/ambience/wind2.wav",
|
||||
"Couldn't load sound/ambience/water1.wav"
|
||||
};
|
||||
|
||||
foreach (var l in teststr)
|
||||
Console.Print(l);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Console.UnregisterConsoleScript(this);
|
||||
//consoleInputEvent.Triggered -= OnConsoleInputEvent;
|
||||
consoleInputEvent?.Dispose();
|
||||
consoleBox?.Dispose();
|
||||
backgroundImage?.DisposeChildren();
|
||||
backgroundImage?.Dispose();
|
||||
}
|
||||
|
||||
public void RefreshLayout()
|
||||
{
|
||||
if (consoleBox == null || consoleInputBox == null)
|
||||
return;
|
||||
|
||||
float fontHeight = consoleBox.GetFontHeight();
|
||||
Vector2 screenSize = Screen.Size;
|
||||
Vector2 consoleSize = new Vector2(screenSize.X, screenSize.Y * ConsoleHeight);
|
||||
|
||||
consoleBox.Height = consoleSize.Y - fontHeight;
|
||||
|
||||
consoleInputBox.Location = new Vector2(0, consoleBox.Height);
|
||||
consoleInputBox.Height = fontHeight;
|
||||
consoleInputBox.ScrollToCaret();
|
||||
}
|
||||
|
||||
private void OnConsoleInputEvent()
|
||||
{
|
||||
if (!consoleInputBox.IsFocused)
|
||||
Console.Open();
|
||||
else
|
||||
Console.Close();
|
||||
}
|
||||
|
||||
public override void OnConsoleOpen()
|
||||
{
|
||||
consoleInputBox.Focus();
|
||||
Parent.As<UICanvas>().ReceivesEvents = true;
|
||||
}
|
||||
|
||||
public override void OnConsoleClose()
|
||||
{
|
||||
consoleInputBox.Defocus();
|
||||
#if FLAX_EDITOR
|
||||
Editor.Instance.Windows.GameWin.Focus();
|
||||
#endif
|
||||
Parent.As<UICanvas>().ReceivesEvents = false;
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
Profiler.BeginEvent("ConsoleScript_OnUpdate");
|
||||
base.OnUpdate();
|
||||
|
||||
const float consoleSpeed = 3500f;
|
||||
|
||||
float targetY;
|
||||
if (!Console.IsOpen)
|
||||
targetY = -rootControl.Control.Height;
|
||||
else
|
||||
targetY = 0.0f;
|
||||
|
||||
Vector2 location = rootControl.Control.Location;
|
||||
if (location.Y != targetY)
|
||||
{
|
||||
if (location.Y > targetY)
|
||||
{
|
||||
location.Y -= Time.UnscaledDeltaTime * consoleSpeed;
|
||||
if (location.Y < targetY)
|
||||
location.Y = targetY;
|
||||
}
|
||||
else if (location.Y < targetY)
|
||||
{
|
||||
location.Y += Time.UnscaledDeltaTime * consoleSpeed;
|
||||
if (location.Y > targetY)
|
||||
location.Y = targetY;
|
||||
}
|
||||
|
||||
rootControl.Control.Location = location;
|
||||
}
|
||||
Profiler.EndEvent();
|
||||
}
|
||||
|
||||
public override void AddLine(string text)
|
||||
{
|
||||
/*if (string.IsNullOrEmpty(consoleBox.Text))
|
||||
consoleBox.Text += text;
|
||||
else
|
||||
consoleBox.Text += "\n" + text;*/
|
||||
}
|
||||
|
||||
public override void SetInput(string text)
|
||||
{
|
||||
consoleInputBox.Text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
421
Source/Game/Cabrito/Console/ConsoleTextBoxBase.cs
Normal file
421
Source/Game/Cabrito/Console/ConsoleTextBoxBase.cs
Normal file
@@ -0,0 +1,421 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor;
|
||||
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;
|
||||
}
|
||||
|
||||
[EditorDisplay("Style"), EditorOrder(2000), Tooltip("The line spacing of the text.")]
|
||||
public float LineSpacing
|
||||
{
|
||||
get => _layout.BaseLinesGapScale;
|
||||
set
|
||||
{
|
||||
// Round to nearest pixel in order to avoid uneven line heights
|
||||
float newValue = value;
|
||||
var font = Font.GetFont();
|
||||
if (font != null)
|
||||
{
|
||||
float actualHeight = font.Height * Scale.Y;
|
||||
newValue = Mathf.Round(newValue * actualHeight) / actualHeight;
|
||||
}
|
||||
|
||||
_layout.BaseLinesGapScale = newValue;
|
||||
OnTextChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 { get; set; }
|
||||
|
||||
/// <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 { get; set; }
|
||||
|
||||
[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(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
|
||||
|
||||
var style = Style.Current;
|
||||
Font = new FontReference(style.FontMedium);
|
||||
TextColor = style.Foreground;
|
||||
SelectionColor = style.BackgroundSelected;
|
||||
}
|
||||
|
||||
/*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(LineSpacing * font.Height * Scale.Y);
|
||||
}
|
||||
|
||||
private float GetRealLineSpacing()
|
||||
{
|
||||
return GetFontHeight() * (1.0f - LineSpacing);
|
||||
}
|
||||
|
||||
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, GetRealLineSpacing());
|
||||
}
|
||||
|
||||
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;
|
||||
float spacing = GetRealLineSpacing();
|
||||
maxY += spacing;
|
||||
|
||||
Vector2 newLocation = CaretBounds.Location;
|
||||
newLocation.Y += spacing;
|
||||
TargetViewOffset = Vector2.Clamp(newLocation, new Vector2(0, spacing), 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();
|
||||
float spacing = GetRealLineSpacing();
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
Source/Game/CameraMovement.cs
Normal file
118
Source/Game/CameraMovement.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using FlaxEngine;
|
||||
using Cabrito;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class CameraMovement : Script
|
||||
{
|
||||
[Limit(0, 9000), Tooltip("Camera speed")]
|
||||
public float MoveSpeed { get; set; } = 400;
|
||||
|
||||
private float _pitch;
|
||||
private float _yaw;
|
||||
|
||||
private float xAxis;
|
||||
private float yAxis;
|
||||
private float inputH;
|
||||
private float inputV;
|
||||
|
||||
private InputEvent onExit = new InputEvent("Exit");
|
||||
private InputEvent onDebug1 = new InputEvent("DebugTrigger1");
|
||||
private InputEvent onDebug2 = new InputEvent("DebugTrigger2");
|
||||
private InputEvent onDebug3 = new InputEvent("DebugTrigger3");
|
||||
|
||||
public override void OnAwake()
|
||||
{
|
||||
base.OnAwake();
|
||||
|
||||
onExit.Triggered += () =>
|
||||
{
|
||||
if (Console.IsSafeToQuit)
|
||||
Engine.RequestExit();
|
||||
};
|
||||
onDebug1.Triggered += () =>
|
||||
{
|
||||
int quality = (int)Graphics.ShadowsQuality;
|
||||
quality++;
|
||||
if (quality >= (int)Quality.MAX)
|
||||
quality = 0;
|
||||
|
||||
Graphics.ShadowsQuality = (Quality)quality;
|
||||
Debug.Log("ShadowsQuality: " + Graphics.ShadowsQuality.ToString());
|
||||
};
|
||||
onDebug2.Triggered += () =>
|
||||
{
|
||||
int quality = (int)Graphics.ShadowMapsQuality;
|
||||
quality++;
|
||||
if (quality >= (int)Quality.MAX)
|
||||
quality = 0;
|
||||
|
||||
Graphics.ShadowMapsQuality = (Quality)quality;
|
||||
Debug.Log("ShadowMapsQuality: " + Graphics.ShadowMapsQuality.ToString());
|
||||
};
|
||||
onDebug3.Triggered += () =>
|
||||
{
|
||||
var box = Scene.AddChild<BoxBrush>();
|
||||
box.Position = Actor.Position;
|
||||
//Scene.BuildCSG(1000);
|
||||
|
||||
var actor = Actor;
|
||||
|
||||
Console.Print("howdy");
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
|
||||
onExit.Dispose();
|
||||
onDebug1.Dispose();
|
||||
onDebug2.Dispose();
|
||||
onDebug3.Dispose();
|
||||
}
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
var initialEulerAngles = Actor.Orientation.EulerAngles;
|
||||
_pitch = initialEulerAngles.X;
|
||||
_yaw = initialEulerAngles.Y;
|
||||
|
||||
Console.OnOpen += () => { Screen.CursorVisible = true; Screen.CursorLock = CursorLockMode.None; };
|
||||
Console.OnClose += () => { Screen.CursorVisible = false; Screen.CursorLock = CursorLockMode.Locked; };
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnUpdate()
|
||||
{
|
||||
if (Console.IsOpen)
|
||||
return;
|
||||
|
||||
var camTrans = Actor.Transform;
|
||||
|
||||
xAxis = Input.GetAxis("Mouse X");
|
||||
yAxis = Input.GetAxis("Mouse Y");
|
||||
|
||||
if (xAxis != 0.0f || yAxis != 0.0f)
|
||||
{
|
||||
_pitch += yAxis;
|
||||
_yaw += xAxis;
|
||||
|
||||
camTrans.Orientation = Quaternion.Euler(_pitch, _yaw, 0);
|
||||
}
|
||||
|
||||
inputH = Input.GetAxis("Horizontal");
|
||||
inputV = Input.GetAxis("Vertical");
|
||||
var move = new Vector3(inputH, 0.0f, inputV);
|
||||
if (!move.IsZero)
|
||||
{
|
||||
move.Normalize();
|
||||
move = camTrans.TransformDirection(move);
|
||||
camTrans.Translation += move * MoveSpeed * Time.UnscaledDeltaTime;
|
||||
}
|
||||
|
||||
Actor.Transform = camTrans;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Source/Game/Game.Build.cs
Normal file
32
Source/Game/Game.Build.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Flax.Build;
|
||||
using Flax.Build.NativeCpp;
|
||||
using System;
|
||||
|
||||
public class Game : GameModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
|
||||
// C#-only scripting
|
||||
BuildNativeCode = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Setup(BuildOptions options)
|
||||
{
|
||||
//options.PublicDependencies.Add("Cabrito");
|
||||
//options.PrivateDependencies.Add("Cabrito");
|
||||
options.ScriptingAPI.IgnoreMissingDocumentationWarnings = true;
|
||||
//options.CompileEnv.PreprocessorDefinitions.Add("COMPILE_WITH_CSG_BUILDER");
|
||||
//options.PublicDefinitions.Add("COMPILE_WITH_CSG_BUILDER");
|
||||
base.Setup(options);
|
||||
|
||||
// Here you can modify the build options for your game module
|
||||
// To reference another module use: options.PublicDependencies.Add("Audio");
|
||||
// To add C++ define use: options.PublicDefinitions.Add("COMPILE_WITH_FLAX");
|
||||
// To learn more see scripting documentation.
|
||||
BuildNativeCode = false;
|
||||
}
|
||||
}
|
||||
BIN
Source/GameEditorTarget.Build.cs
Normal file
BIN
Source/GameEditorTarget.Build.cs
Normal file
Binary file not shown.
16
Source/GameTarget.Build.cs
Normal file
16
Source/GameTarget.Build.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Flax.Build;
|
||||
|
||||
public class GameTarget : GameProjectTarget
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
|
||||
// Reference the modules for game
|
||||
Modules.Add("Game");
|
||||
//Modules.Add("Cabrito");
|
||||
Architectures = new TargetArchitecture[] { TargetArchitecture.x64 };
|
||||
Platforms = new TargetPlatform[] { TargetPlatform.Windows };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user