A simple .NET Framework to make 2D games quick and easy.
at main 7.2 kB view raw
1using System.Diagnostics; 2using System.Numerics; 3using System.Reflection; 4using Fjord.Graphics; 5using Fjord.Input; 6using Fjord.Scenes; 7using Fjord.Ui; 8using static Fjord.Helpers; 9using static SDL2.SDL; 10 11namespace Fjord.Scenes; 12 13public class Export : Attribute 14{ 15 public float sliderMin = 0; 16 public float sliderMax = 200; 17 18 public Export(float min, float max) { 19 this.sliderMin = min; 20 this.sliderMax = max; 21 } 22 23 public Export() { 24 25 } 26} 27 28public struct DebugLog 29{ 30 public string time; 31 public string sender; 32 public string message; 33 public LogLevel level; 34 public int repeat; 35 public bool hideInfo; 36 37 public override bool Equals(object? obj) 38 { 39 return obj is DebugLog log && 40 sender == log.sender && 41 message == log.message && 42 level == log.level && 43 hideInfo == log.hideInfo; 44 } 45 46 public override int GetHashCode() 47 { 48 return HashCode.Combine(time, sender, message, level, repeat, hideInfo); 49 } 50} 51 52public enum LogLevel 53{ 54 User, 55 Message, 56 Warning, 57 Error, 58} 59 60public static class Debug { 61 62 public static List<DebugLog> Logs = new List<DebugLog>(); 63 64 65 public static Dictionary<string, Action<object[]>> commands = new Dictionary<string, Action<object[]>>(); 66 67 public static void RegisterCommand(string id, Action<object[]> callback) { 68 if (commands.ContainsKey(id)) 69 { 70 commands.Remove(id); 71 } 72 commands.Add(id, callback); 73 } 74 public static void RegisterCommand(string[] ids, Action<object[]> callback) 75 { 76 foreach (string id in ids) 77 RegisterCommand(id, callback); 78 } 79 80 public static void Initialize() 81 { 82 SceneHandler.Register(new InspectorScene((int)(Game.Window.Width * 0.201), 1080) 83 .SetAllowWindowResize(false) 84 .SetAlwaysRebuildTexture(true) 85 .SetRelativeWindowSize(0.8f, 0f, 1.0001f, 1f)); 86 87 SceneHandler.Register(new ConsoleScene((int)(Game.Window.Width * 0.2), (int)(Game.Window.Height * 0.4)) 88 .SetAllowWindowResize(true) 89 .SetRelativeWindowSize(0.1f, 0.1f, 0.4f, 0.6f) 90 .SetAlwaysRebuildTexture(true)); 91 92 SceneHandler.Register(new PerformanceScene((int)(Game.Window.Width * 0.2), (int)(Game.Window.Height * 0.4)) 93 .SetRelativeWindowSize(0f, 0.89f, 0.10f, 1.001f) 94 .SetAlwaysRebuildTexture(true)); 95 96 SceneHandler.Register(new NotificationScene(0, 0) 97 .SetRelativeWindowSize(0f, 0f, 0.5f, 1.001f) 98 .SetAlwaysRebuildTexture(true)); 99 SceneHandler.Load<NotificationScene>(); 100 101 //SceneHandler.Load("Performance"); 102 // SceneHandler.Load("Console"); 103 // SceneHandler.Load("Inspector"); 104 105 RegisterCommand("clear", (args) => 106 { 107 Logs = new(); 108 }); 109 110 RegisterCommand("showfps", (args) => 111 { 112 if (args.Length < 1) 113 { 114 Debug.Log(SceneHandler.IsLoaded<PerformanceScene>()); 115 return; 116 } 117 118 if (args[0].GetType() != typeof(bool)) 119 { 120 Debug.Log("Argument 1 is not of type bool"); 121 return; 122 } 123 124 if ((bool)args[0]) 125 { 126 SceneHandler.Load<PerformanceScene>(); 127 } 128 else 129 { 130 SceneHandler.Unload<PerformanceScene>(); 131 } 132 }); 133 134 RegisterCommand("maxfps", (args) => { 135 if(args.Length > 0) { 136 if(args[0].GetType() == typeof(float)) { 137 Debug.Log(args[0].GetType()); 138 Game.FPSMax = (double)((float)args[0]); 139 } else { 140 Debug.Log(LogLevel.Warning, $"Argument must be number"); 141 } 142 } else { 143 Debug.Log(LogLevel.Error, $"No argument provided"); 144 } 145 }); 146 147 148 RegisterCommand("commands", (args) => { 149 foreach(string command in commands.Keys.ToList()) 150 { 151 Debug.Log(command); 152 } 153 }); 154 155 RegisterCommand(new string[3] { "q", "quit", "exit" }, (args) => 156 { 157 Game.Stop(); 158 }); 159 160 RegisterCommand("debug_selectscene", (args) => { 161 if(args.Length > 0) { 162 if(SceneHandler.Scenes.ContainsKey((string)args[0])) { 163 SceneHandler.Get<InspectorScene>().SelectedScene = (string)args[0]; 164 Debug.Log(LogLevel.Message, $"{(string)args[0]} is now selected"); 165 } else { 166 Debug.Log(LogLevel.Warning, $"No scene named {(string)args[0]}"); 167 } 168 } else { 169 Debug.Log(LogLevel.Error, $"No argument provided"); 170 } 171 }); 172 } 173 174 public static void SendNotification(string message) 175 { 176 SceneHandler.Get<NotificationScene>().Notifications.Add(new(message, 100)); 177 } 178 179 public static SDL_FRect DebugWindowOffset = new() 180 { 181 x = 0f, 182 y = 0f, 183 w = 0.2f, 184 h = 0f 185 }; 186 187 public static void Log(object message) 188 { 189 Log(LogLevel.Message, message); 190 } 191 192 public static void Log(LogLevel level, object message) 193 { 194 var words = message.ToString()?.Split(); 195 // List<string> messageSplit = message.ToString().SplitInParts(60).ToList(); 196 197 if(level == LogLevel.Error) 198 { 199 SendNotification(message.ToString()!); 200 } 201 202 var lines = new List<string> { words![0] }; 203 var lineNum = 0; 204 for(int i = 1; i < words.Length; i++) 205 { 206 if(lines[lineNum].Length + words[i].Length + 1 <= 120) 207 lines[lineNum] += " " + words[i]; 208 else 209 { 210 lines.Add(words[i]); 211 lineNum++; 212 } 213 } 214 215 StackTrace stackTrace = new StackTrace(); 216 StackFrame? stackFrame = stackTrace.GetFrame(1); 217 218 int idx = -1; 219 foreach(string i in lines) { 220 idx++; 221 if(stackFrame is not null) { 222 System.Reflection.MethodBase? methodBase = stackFrame.GetMethod(); 223 if(methodBase is not null) { 224 var names = methodBase.DeclaringType; 225 if (names is not null) { 226 var logtmp = new DebugLog() { 227 level = level, 228 time = DateTime.Now.ToString("hh:mm:ss"), 229 sender = names.Name, 230 message = i, 231 hideInfo = idx != 0 232 }; 233 234 Logs.Add(logtmp); 235 } 236 } 237 } 238 } 239 } 240 241 public static void PerformCommand(string command, object[] args) { 242 if(commands.TryGetValue(command, out var command1)) { 243 try { 244 command1(args); 245 } catch(Exception e) { 246 Debug.Log(LogLevel.Error, e.ToString()); 247 } 248 } else { 249 Debug.Log(LogLevel.Error, $"Unknown Command: {command}"); 250 } 251 } 252}