From 4681c7060ed6d51edfb09e326224d88e73c4653e Mon Sep 17 00:00:00 2001 From: Alessandro Proto Date: Sun, 3 Sep 2023 22:27:54 +0200 Subject: [PATCH] Too many changes. --- Capy64/Capy64.csproj | 2 +- Capy64/Core/Canvas.cs | 122 ++++++++++++ Capy64/Eventing/InputManager.cs | 73 ++++++-- Capy64/{Capy64.cs => Game.cs} | 214 +++++++++++++++++----- Capy64/Integrations/DiscordIntegration.cs | 5 +- Capy64/LegacyEntry.cs | 10 +- Capy64/Program.cs | 2 +- Capy64/Runtime/Libraries/AudioLib.cs | 4 +- Capy64/Runtime/Libraries/EventLib.cs | 4 +- Capy64/Runtime/Libraries/FileSystemLib.cs | 2 +- Capy64/Runtime/Libraries/GPULib.cs | 72 ++++---- Capy64/Runtime/Libraries/HTTPLib.cs | 4 +- Capy64/Runtime/Libraries/MachineLib.cs | 4 +- Capy64/Runtime/Libraries/TermLib.cs | 55 +++--- Capy64/Runtime/Libraries/TimerLib.cs | 4 +- Capy64/Runtime/LuaState.cs | 4 +- Capy64/Runtime/ObjectManager.cs | 4 +- Capy64/Runtime/Objects/FileHandle.cs | 2 +- Capy64/Runtime/Objects/GPUBufferMeta.cs | 4 +- Capy64/Runtime/Objects/Socket.cs | 4 +- Capy64/Runtime/Objects/Task.cs | 4 +- Capy64/Runtime/Objects/WebSocketClient.cs | 2 +- Capy64/Runtime/PanicScreen.cs | 2 +- Capy64/Runtime/RuntimeManager.cs | 8 +- Capy64/{Utils.cs => Utils/Borders.cs} | 39 ++-- Capy64/Utils/Color.cs | 103 +++++++++++ Capy64/Utils/Point.cs | 124 +++++++++++++ Capy64/Utils/Size2.cs | 164 +++++++++++++++++ Capy64/Utils/Vector2.cs | 149 +++++++++++++++ 29 files changed, 1008 insertions(+), 182 deletions(-) create mode 100644 Capy64/Core/Canvas.cs rename Capy64/{Capy64.cs => Game.cs} (58%) rename Capy64/{Utils.cs => Utils/Borders.cs} (51%) create mode 100644 Capy64/Utils/Color.cs create mode 100644 Capy64/Utils/Point.cs create mode 100644 Capy64/Utils/Size2.cs create mode 100644 Capy64/Utils/Vector2.cs diff --git a/Capy64/Capy64.csproj b/Capy64/Capy64.csproj index 2e577d1..d6713b4 100644 --- a/Capy64/Capy64.csproj +++ b/Capy64/Capy64.csproj @@ -1,6 +1,6 @@  - WinExe + Exe net7.0 Major false diff --git a/Capy64/Core/Canvas.cs b/Capy64/Core/Canvas.cs new file mode 100644 index 0000000..bdcba95 --- /dev/null +++ b/Capy64/Core/Canvas.cs @@ -0,0 +1,122 @@ +// This file is part of Capy64 - https://github.com/Ale32bit/Capy64 +// Copyright 2023 Alessandro "AlexDevs" Proto +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Capy64.Utils; +using System; +using System.Collections.Generic; +using System.IO; +using static SDL2.SDL; +using static SDL2.SDL_ttf; + +namespace Capy64.Core; +public class Canvas : IDisposable +{ + public nint Font { get; private set; } + private readonly Game _game; + private nint _surface => _game.VideoSurface; + private nint _renderer => _game.SurfaceRenderer; + public Canvas(Game game) + { + _game = game; + //File.ReadAllBytes(Path.Combine(Game.AssetsPath, "font.ttf")); + Font = TTF_OpenFont(Path.Combine(Game.AssetsPath, "font.ttf"), 13); + } + + public void SetPixel(int x, int y, Color color) { + SDL_SetRenderDrawColor(_renderer, color.R, color.G, color.B, color.A); + SDL_RenderDrawPoint(_renderer, x, y); + } + public void SetPixel(Point point, Color color) + { + SetPixel(point.X, point.Y, color); + } + public Color GetPixel(int x, int y) + { + unsafe { + var pitch = ((SDL_Surface*)_surface)->pitch; + var c = ((uint*)((SDL_Surface*)_surface)->pixels)[x + y * pitch / 4]; + return new Color(c); + } + } + public Color GetPixel(Point point) + { + return GetPixel(point.X, point.Y); + } + public void SetPixels(IEnumerable points, Color color) + { + + } + + public void DrawRectangle(Vector2 pos, Size2 size, Color color, int thickness = 1, float rotation = 0f) + { + var rect = new SDL_FRect + { + x = pos.X, + y = pos.Y, + w = size.Width, + h = size.Height, + }; + + SDL_SetRenderDrawColor(_renderer, color.R, color.G, color.B, color.A); + SDL_RenderDrawRectF(_renderer, ref rect); + //DrawRectangle(new(pos, size), color, thickness, rotation, 0f); + } + + + public void DrawFilledRectangle(Vector2 pos, Size2 size, Color color) + { + var rect = new SDL_FRect + { + x = pos.X, + y = pos.Y, + w = size.Width, + h = size.Height, + }; + + SDL_SetRenderDrawColor(_renderer, color.R, color.G, color.B, color.A); + SDL_RenderFillRectF(_renderer, ref rect); + } + + public void DrawString(Vector2 charpos, string v, Color fg) + { + var surf = TTF_RenderText_Solid(Font, v, fg.ToSDL()); + var message = SDL_CreateTextureFromSurface(_renderer, surf); + var rect = new SDL_Rect + { + x = (int)charpos.X, + y = (int)charpos.Y, + w = 9, + h = 13, + }; + + SDL_SetRenderDrawColor(_surface, 255, 255, 255, 255); + SDL_RenderCopy(_renderer, message, 0, ref rect); + + SDL_DestroyTexture(message); + SDL_FreeSurface(surf); + } + + public void Clear(Color? color = default) + { + var clearColor = color ?? Color.Black; + SDL_SetRenderDrawColor(_renderer, clearColor.R, clearColor.G, clearColor.B, 255); + SDL_RenderClear(_renderer); + } + + public void Dispose() + { + TTF_CloseFont(Font); + } +} diff --git a/Capy64/Eventing/InputManager.cs b/Capy64/Eventing/InputManager.cs index db0b832..ba29074 100644 --- a/Capy64/Eventing/InputManager.cs +++ b/Capy64/Eventing/InputManager.cs @@ -20,20 +20,31 @@ using System; using System.Collections.Generic; using System.Linq; using SDL2; +using Newtonsoft.Json.Linq; namespace Capy64.Eventing; public class InputManager { + // SDL inverts Right and Middle (2 and 3) public enum MouseButton { Left = 1, - Right = 2, - Middle = 3, + Right = 3, + Middle = 2, Button4 = 4, Button5 = 5, } + private Dictionary MouseMap = new() + { + [MouseButton.Left] = 1, + [MouseButton.Right] = 2, + [MouseButton.Middle] = 3, + [MouseButton.Button4] = 4, + [MouseButton.Button5] = 5, + }; + [Flags] public enum Modifiers { @@ -75,7 +86,6 @@ public class InputManager }; public Texture2D Texture { get; set; } - public static float WindowScale => LegacyEntry.Instance.Scale; public const int MouseScrollDelta = 120; private Point mousePosition; @@ -85,9 +95,9 @@ public class InputManager private Modifiers keyboardMods = 0; private readonly HashSet pressedKeys = new(); - private readonly Capy64 _game; + private readonly Game _game; private readonly EventEmitter _eventEmitter; - public InputManager(Capy64 game, EventEmitter eventManager) + public InputManager(Game game, EventEmitter eventManager) { _game = game; @@ -109,18 +119,26 @@ public class InputManager UpdateGamePad(GamePad.GetState(PlayerIndex.One), IsActive); } - public void UpdateMouseSDL(SDL.SDL_Event ev) + private Point GetMouseCoords(int x, int y) { - var position = new Point(ev.button.x, ev.button.y); - var rawPosition = position - new Point(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top); - var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1); + var position = new Point(x, y); + var rawPosition = position - new Point(_game.Borders.Left, _game.Borders.Top); + return new Point((int)(rawPosition.X / _game.Scale), (int)(rawPosition.Y / _game.Scale)) + new Point(1, 1); + } + + public void UpdateMouseMove(SDL.SDL_Event ev) + { + var pos = GetMouseCoords(ev.button.x, ev.button.y); if (pos.X < 1 || pos.Y < 1 || pos.X > (_game.Width) || pos.Y > _game.Height) return; - + if (pos != mousePosition) { mousePosition = pos; + + Console.WriteLine("MOTION {0} {1} {2}", pos.X, pos.Y, ev.button.state); + _eventEmitter.RaiseMouseMove(new() { Position = mousePosition, @@ -130,7 +148,36 @@ public class InputManager .ToArray() }); } - + } + + public void UpdateMouseClick(SDL.SDL_Event ev) + { + var pos = GetMouseCoords(ev.button.x, ev.button.y); + + if (pos.X < 1 || pos.Y < 1 || pos.X > (_game.Width) || pos.Y > _game.Height) + return; + + mouseButtonStates[(MouseButton)ev.button.button] = (ButtonState)ev.button.state; + + Console.WriteLine("MCLICK {0} {1} {2} {3}", pos.X, pos.Y, ev.button.button, ev.button.state); + _eventEmitter.RaiseMouseButton(new() + { + Position = pos, + Button = (MouseButton)ev.button.button, + State = (ButtonState)ev.button.state, + }); + } + + public void UpdateMouseScroll(SDL.SDL_Event ev) + { + + Console.WriteLine("MWHEEL {0} {1} {2} {3}", mousePosition.X, mousePosition.Y, ev.wheel.x, ev.wheel.y); + _eventEmitter.RaiseMouseWheelEvent(new() + { + Position = mousePosition, + VerticalValue = ev.wheel.x, + HorizontalValue = ev.wheel.x, + }); } private void UpdateMouse(MouseState state, bool isActive) @@ -138,8 +185,8 @@ public class InputManager if (!isActive) return; - var rawPosition = state.Position - new Point(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top); - var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1); + var rawPosition = state.Position - new Point(_game.Borders.Left, _game.Borders.Top); + var pos = new Point((int)(rawPosition.X / _game.Scale), (int)(rawPosition.Y / _game.Scale)) + new Point(1, 1); if (pos.X < 1 || pos.Y < 1 || pos.X > Texture.Width || pos.Y > Texture.Height) return; diff --git a/Capy64/Capy64.cs b/Capy64/Game.cs similarity index 58% rename from Capy64/Capy64.cs rename to Capy64/Game.cs index d20daf8..c38917c 100644 --- a/Capy64/Capy64.cs +++ b/Capy64/Game.cs @@ -13,20 +13,27 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Capy64.API; +using Capy64.Core; using Capy64.Eventing; -using Microsoft.Xna.Framework; +using Capy64.PluginManager; +using Capy64.Runtime; +using Capy64.Utils; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Timers; +using static SDL2.SDL; namespace Capy64; -using System; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using static Utils; -using static SDL2.SDL; - -public class Capy64 : IDisposable +public class Game : IDisposable { + public static Game Instance { get; private set; } public const string Version = "1.1.0-beta"; public nint Window { get; private set; } = 0; public nint Renderer { get; private set; } = 0; @@ -42,14 +49,19 @@ public class Capy64 : IDisposable public float Ticktime => 1000f / Tickrate; public float Frametime => 1000f / Framerate; + public IList NativePlugins { get; private set; } + public IList Plugins { get; private set; } - public Color BorderColor { get; set; } = Color.Blue; + public Color BorderColor { get; set; } = Color.Black; - public Borders Borders { + public Borders Borders + { get => _borders; - set { + set + { _borders = value; - _outputRect = new() { + _outputRect = new() + { x = value.Left, y = value.Top, w = (int)(Width * Scale), @@ -63,6 +75,7 @@ public class Capy64 : IDisposable public static readonly string AssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets"); + public IConfiguration Configuration { get; private set; } public static class DefaultParameters { @@ -76,8 +89,10 @@ public class Capy64 : IDisposable public const int FreeTickrate = 60; } - public static string AppDataPath { - get { + public static string AppDataPath + { + get + { string baseDir = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData, @@ -93,24 +108,76 @@ public class Capy64 : IDisposable return Path.Combine(baseDir, "Capy64"); } } - + private bool _running = false; private InputManager _inputManager; - public EventEmitter EventEmitter = new(); + public Eventing.EventEmitter EventEmitter = new(); + public readonly Canvas Canvas; + public Audio Audio { get; private set; } + public LuaState LuaRuntime { get; set; } - public Capy64() + public Game() { + Instance = this; + Canvas = new(this); ResetBorder(); - WindowWidth = (int)(Width * Scale) + Borders.Left + Borders.Right; - WindowHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom; + UpdateSize(); - _inputManager = new(null, EventEmitter); + _inputManager = new(this, EventEmitter); + } + + public void Initialize() + { + var configBuilder = new ConfigurationBuilder(); + + var settingsPath = Path.Combine(AppDataPath, "settings.json"); + if (!Directory.Exists(AppDataPath)) + { + Directory.CreateDirectory(AppDataPath); + } + if (!File.Exists(settingsPath)) + { + File.Copy(Path.Combine(AssetsPath, "default.json"), settingsPath); + } + + configBuilder.AddJsonFile(Path.Combine(AssetsPath, "default.json"), false); + configBuilder.AddJsonFile(settingsPath, false); + + Configuration = configBuilder.Build(); + + Scale = Configuration.GetValue("Window:Scale", DefaultParameters.Scale); + + Audio = new Audio(); + + NativePlugins = LoadNativePlugins(); + var safeMode = Configuration.GetValue("SafeMode", false); + if (!safeMode) + Plugins = PluginLoader.LoadAllPlugins(Path.Combine(AppDataPath, "plugins")); + } + + private List LoadNativePlugins() + { + var iType = typeof(IComponent); + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => iType.IsAssignableFrom(p) && !p.IsInterface); + + var plugins = new List(); + + foreach (var type in types) + { + var instance = (IComponent)Activator.CreateInstance(type, this); + plugins.Add(instance); + } + + return plugins; } private void ResetBorder() { var size = (int)(Scale * DefaultParameters.BorderMultiplier); - Borders = new Borders { + Borders = new Borders + { Top = size, Bottom = size, Left = size, @@ -118,8 +185,22 @@ public class Capy64 : IDisposable }; } + public void UpdateSize(bool resize = true) + { + if (resize) + { + WindowWidth = (int)(Width * Scale) + Borders.Left + Borders.Right; + WindowHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom; + SDL_SetWindowSize(Window, WindowWidth, WindowHeight); + } + + EventEmitter.RaiseScreenSizeChange(); + } + public void Run() { + Initialize(); + #if DEBUG SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1"); #endif @@ -142,7 +223,7 @@ public class Capy64 : IDisposable } var icon = SDL_LoadBMP("./Icon.bmp"); - if(icon != 0) + if (icon != 0) SDL_SetWindowIcon(Window, icon); Renderer = SDL_CreateRenderer(Window, @@ -158,31 +239,23 @@ public class Capy64 : IDisposable VideoSurface = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_ARGB8888); SurfaceRenderer = SDL_CreateSoftwareRenderer(VideoSurface); - SDL_SetRenderDrawColor(SurfaceRenderer, 255, 255, 255, 255); + SDL_SetRenderDrawColor(SurfaceRenderer, 0, 0, 0, 255); SDL_RenderClear(SurfaceRenderer); - _running = true; + EventEmitter.RaiseInit(); + ulong deltaEnd = 0; var perfFreq = SDL_GetPerformanceFrequency(); - while (_running) - { - var deltaStart = SDL_GetPerformanceCounter(); - var delta = deltaStart - deltaEnd; - - while (SDL_PollEvent(out var ev) != 0) - { - ProcessEvent(ev); - } - if ((uint)(perfFreq / delta) >= Framerate) - { - continue; - } - deltaEnd = deltaStart; - + ulong totalTicks = 0; + + var drawTimer = new Timer(TimeSpan.FromMilliseconds(1000d / Framerate)); + drawTimer.Elapsed += (s, e) => + { SDL_SetRenderDrawColor(Renderer, BorderColor.R, BorderColor.G, BorderColor.B, 255); SDL_RenderClear(Renderer); + SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255); var texture = SDL_CreateTextureFromSurface(Renderer, VideoSurface); @@ -190,7 +263,49 @@ public class Capy64 : IDisposable SDL_RenderCopy(Renderer, texture, 0, ref _outputRect); SDL_DestroyTexture(texture); + SDL_RenderPresent(Renderer); + }; + + var updateTimer = new Timer(TimeSpan.FromMilliseconds(1000d / Tickrate)); + updateTimer.Elapsed += (s, e) => { + // Register user input + //_inputManager.Update(true); + + EventEmitter.RaiseTick(new() + { + GameTime = null, + TotalTicks = totalTicks, + IsActiveTick = true, + }); + + totalTicks++; + }; + + drawTimer.Start(); + updateTimer.Start(); + _running = true; + while (_running) + { + var deltaStart = SDL_GetPerformanceCounter(); + var delta = deltaStart - deltaEnd; + + while (SDL_WaitEvent(out var ev) != 0) + { + ProcessEvent(ev); + } + + if ((uint)(perfFreq / delta) < Tickrate) + { + + } + + if ((uint)(perfFreq / delta) < Framerate) + { + deltaEnd = deltaStart; + + + } } } @@ -200,20 +315,24 @@ public class Capy64 : IDisposable { case SDL_EventType.SDL_QUIT: _running = false; + Dispose(); break; + case SDL_EventType.SDL_KEYUP: case SDL_EventType.SDL_KEYDOWN: break; + case SDL_EventType.SDL_MOUSEMOTION: + _inputManager.UpdateMouseMove(ev); + break; + case SDL_EventType.SDL_MOUSEBUTTONUP: case SDL_EventType.SDL_MOUSEBUTTONDOWN: - - unsafe - { - var pitch = ((SDL_Surface*)VideoSurface)->pitch; - ((uint*)((SDL_Surface*)VideoSurface)->pixels)[x + y * pitch / 4] = 0xFFFF00FF; - } + _inputManager.UpdateMouseClick(ev); + break; + case SDL_EventType.SDL_MOUSEWHEEL: + _inputManager.UpdateMouseScroll(ev); break; } } @@ -221,10 +340,9 @@ public class Capy64 : IDisposable public void Dispose() { SDL_DestroyRenderer(SurfaceRenderer); - SDL_FreeSurface(VideoSurface); + //SDL_FreeSurface(VideoSurface); SDL_DestroyRenderer(Renderer); SDL_DestroyWindow(Window); - SDL_Quit(); } } \ No newline at end of file diff --git a/Capy64/Integrations/DiscordIntegration.cs b/Capy64/Integrations/DiscordIntegration.cs index 1597cb4..d64ba65 100644 --- a/Capy64/Integrations/DiscordIntegration.cs +++ b/Capy64/Integrations/DiscordIntegration.cs @@ -24,11 +24,12 @@ namespace Capy64.Integrations; public class DiscordIntegration : IComponent { + public static DiscordIntegration Instance { get; private set; } public DiscordRpcClient Client { get; private set; } public readonly bool Enabled; private readonly IConfiguration _configuration; - public DiscordIntegration(LegacyEntry game) + public DiscordIntegration(Game game) { _configuration = game.Configuration; @@ -42,7 +43,7 @@ public class DiscordIntegration : IComponent Client.OnReady += OnReady; - LegacyEntry.Instance.Discord = this; + Instance = this; if (Enabled) Client.Initialize(); diff --git a/Capy64/LegacyEntry.cs b/Capy64/LegacyEntry.cs index f67d148..fb1ebfb 100644 --- a/Capy64/LegacyEntry.cs +++ b/Capy64/LegacyEntry.cs @@ -20,6 +20,7 @@ using Capy64.Extensions; using Capy64.Integrations; using Capy64.PluginManager; using Capy64.Runtime; +using Capy64.Utils; using Microsoft.Extensions.Configuration; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -31,7 +32,6 @@ using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; -using static Capy64.Utils; namespace Capy64; @@ -41,7 +41,7 @@ public enum EngineMode Free } -public class LegacyEntry : Game +public class LegacyEntry : Microsoft.Xna.Framework.Game { public const string Version = "1.1.0-beta"; @@ -96,7 +96,7 @@ public class LegacyEntry : Game public int TickRate => tickrate; public IConfiguration Configuration { get; private set; } - public Color BorderColor { get; set; } = Color.Black; + public Microsoft.Xna.Framework.Color BorderColor { get; set; } = Microsoft.Xna.Framework.Color.Black; public Borders Borders = new() { @@ -315,7 +315,7 @@ public class LegacyEntry : Game protected override void Draw(GameTime gameTime) { - SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp); + /*SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp); GraphicsDevice.Clear(BorderColor); SpriteBatch.DrawRectangle(renderTarget.Bounds.Location.ToVector2() + new Vector2(Borders.Left, Borders.Top), @@ -333,6 +333,6 @@ public class LegacyEntry : Game SpriteBatch.End(); - base.Draw(gameTime); + base.Draw(gameTime);*/ } } \ No newline at end of file diff --git a/Capy64/Program.cs b/Capy64/Program.cs index 053a151..7783b4b 100644 --- a/Capy64/Program.cs +++ b/Capy64/Program.cs @@ -17,7 +17,7 @@ using Capy64; if (args.Length > 0 && args[0] == "sdl") { - using var game = new Capy64.Capy64(); + using var game = new Capy64.Game(); game.Run(); } diff --git a/Capy64/Runtime/Libraries/AudioLib.cs b/Capy64/Runtime/Libraries/AudioLib.cs index 8b25c1b..8cd001f 100644 --- a/Capy64/Runtime/Libraries/AudioLib.cs +++ b/Capy64/Runtime/Libraries/AudioLib.cs @@ -25,8 +25,8 @@ public class AudioLib : IComponent { private const int queueLimit = 8; - private static LegacyEntry _game; - public AudioLib(LegacyEntry game) + private static Game _game; + public AudioLib(Game game) { _game = game; _game.EventEmitter.OnClose += OnClose; diff --git a/Capy64/Runtime/Libraries/EventLib.cs b/Capy64/Runtime/Libraries/EventLib.cs index 6cad777..02f205f 100644 --- a/Capy64/Runtime/Libraries/EventLib.cs +++ b/Capy64/Runtime/Libraries/EventLib.cs @@ -29,8 +29,8 @@ public class EventLib : IComponent private static bool FrozenTaskAwaiter = false; - private static LegacyEntry _game; - public EventLib(LegacyEntry game) + private static Game _game; + public EventLib(Game game) { _game = game; } diff --git a/Capy64/Runtime/Libraries/FileSystemLib.cs b/Capy64/Runtime/Libraries/FileSystemLib.cs index 6886a07..09c88ce 100644 --- a/Capy64/Runtime/Libraries/FileSystemLib.cs +++ b/Capy64/Runtime/Libraries/FileSystemLib.cs @@ -111,7 +111,7 @@ public class FileSystemLib : IComponent new(), // NULL }; - public FileSystemLib(LegacyEntry _) { } + public FileSystemLib(Game _) { } public void LuaInit(Lua state) { diff --git a/Capy64/Runtime/Libraries/GPULib.cs b/Capy64/Runtime/Libraries/GPULib.cs index dabd363..b46015c 100644 --- a/Capy64/Runtime/Libraries/GPULib.cs +++ b/Capy64/Runtime/Libraries/GPULib.cs @@ -15,9 +15,8 @@ using Capy64.API; using Capy64.Runtime.Objects; +using Capy64.Utils; using KeraLua; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.IO; @@ -28,8 +27,8 @@ namespace Capy64.Runtime.Libraries; public class GPULib : IComponent { - private static LegacyEntry _game; - public GPULib(LegacyEntry game) + private static Game _game; + public GPULib(Game game) { _game = game; } @@ -157,7 +156,9 @@ public class GPULib : IComponent public static void GetColor(uint c, out byte r, out byte g, out byte b) { - Utils.UnpackRGB(c, out r, out g, out b); + var color = new Color(c); + //Utils.UnpackRGB(c, out r, out g, out b); + r = color.R; g = color.G; b = color.B; } private static int L_GetSize(IntPtr state) @@ -174,10 +175,12 @@ public class GPULib : IComponent { var L = Lua.FromIntPtr(state); - if (_game.EngineMode == EngineMode.Classic) + return 0; + + /*if (_game.EngineMode == EngineMode.Classic) { return L.Error("Screen is not resizable"); - } + }*/ var w = L.CheckInteger(1); var h = L.CheckInteger(2); @@ -196,7 +199,8 @@ public class GPULib : IComponent { var L = Lua.FromIntPtr(state); - L.PushBoolean(_game.EngineMode != EngineMode.Classic); + //L.PushBoolean(_game.EngineMode != EngineMode.Classic); + L.PushBoolean(false); return 1; } @@ -208,9 +212,11 @@ public class GPULib : IComponent var x = (int)L.CheckNumber(1) - 1; var y = (int)L.CheckNumber(2) - 1; - var c = _game.Drawing.GetPixel(new(x, y)); + var c = _game.Canvas.GetPixel(new(x, y)); - L.PushInteger(Utils.PackRGB(c)); + //var c = _game.Drawing.GetPixel(new(x, y)); + + L.PushInteger(c.PackedRGB); return 1; } @@ -224,7 +230,7 @@ public class GPULib : IComponent var c = L.CheckInteger(3); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.Plot(new Point(x, y), new Color(r, g, b)); + _game.Canvas.SetPixel(new Point(x, y), new Color(r, g, b)); return 0; } @@ -259,7 +265,7 @@ public class GPULib : IComponent } GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.Plot(pts, new(r, g, b)); + _game.Canvas.SetPixels(pts, new(r, g, b)); return 0; } @@ -274,7 +280,7 @@ public class GPULib : IComponent var s = (int)L.OptNumber(4, 1); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.DrawPoint(new(x, y), new Color(r, g, b), s); + //_game.Drawing.DrawPoint(new(x, y), new Color(r, g, b), s); return 0; } @@ -291,7 +297,7 @@ public class GPULib : IComponent var s = (int)L.OptInteger(6, -1); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.DrawCircle(new(x, y), rad, new Color(r, g, b), t, s); + //_game.Drawing.DrawCircle(new(x, y), rad, new Color(r, g, b), t, s); return 0; } @@ -308,7 +314,7 @@ public class GPULib : IComponent var s = (int)L.OptNumber(6, 1); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.DrawLine(new(x1, y1), new(x2, y2), new Color(r, g, b), s); + //_game.Drawing.DrawLine(new(x1, y1), new(x2, y2), new Color(r, g, b), s); return 0; } @@ -325,7 +331,7 @@ public class GPULib : IComponent var s = (int)L.OptNumber(6, 1); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.DrawRectangle(new(x, y), new(w, h), new Color(r, g, b), s); + //_game.Drawing.DrawRectangle(new(x, y), new(w, h), new Color(r, g, b), s); return 0; } @@ -361,7 +367,7 @@ public class GPULib : IComponent } GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.DrawPolygon(new(x, y), pts.ToArray(), new(r, g, b), s); + //_game.Drawing.DrawPolygon(new(x, y), pts.ToArray(), new(r, g, b), s); return 0; } @@ -378,7 +384,7 @@ public class GPULib : IComponent var s = (int)L.OptNumber(6, 1); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.DrawEllipse(new(x, y), new(rx, ry), new Color(r, g, b), s); + //_game.Drawing.DrawEllipse(new(x, y), new(rx, ry), new Color(r, g, b), s); return 0; } @@ -395,7 +401,7 @@ public class GPULib : IComponent GetColor((uint)c, out var r, out var g, out var b); try { - _game.Drawing.DrawString(new Vector2(x, y), t, new Color(r, g, b)); + //_game.Drawing.DrawString(new Vector2(x, y), t, new Color(r, g, b)); } catch (ArgumentException ex) // UTF-16 fuckery { @@ -411,10 +417,10 @@ public class GPULib : IComponent var t = L.CheckString(1); - var sizes = _game.Drawing.MeasureString(t); + //var sizes = _game.Drawing.MeasureString(t); - L.PushNumber((int)sizes.X); - L.PushNumber((int)sizes.Y); + //L.PushNumber((int)sizes.X); + //L.PushNumber((int)sizes.Y); return 2; } @@ -425,7 +431,7 @@ public class GPULib : IComponent var buffer = new uint[_game.Width * _game.Height]; - _game.Drawing.Canvas.GetData(buffer); + //_game.Drawing.Canvas.GetData(buffer); var gpuBuffer = new GPUBufferMeta.GPUBuffer { @@ -446,7 +452,7 @@ public class GPULib : IComponent var buffer = GPUBufferMeta.CheckBuffer(L, false); - _game.Drawing.Canvas.SetData(buffer.Buffer); + //_game.Drawing.Canvas.SetData(buffer.Buffer); return 0; } @@ -533,7 +539,7 @@ public class GPULib : IComponent var x = (int)L.CheckInteger(2) - 1; var y = (int)L.CheckInteger(3) - 1; - Rectangle? source = null; + /*Rectangle? source = null; Color color = Color.White; float rotation = 0; Vector2 origin = Vector2.Zero; @@ -634,7 +640,7 @@ public class GPULib : IComponent Width = buffer.Width, Height = buffer.Height, }, source, color, rotation, origin, scale, effects); - + */ return 0; } @@ -654,10 +660,10 @@ public class GPULib : IComponent var task = TaskMeta.Push(L, GPUBufferMeta.ObjectType); - Texture2D texture; + //Texture2D texture; try { - texture = Texture2D.FromFile(LegacyEntry.Instance.Drawing.Canvas.GraphicsDevice, path); + //texture = Texture2D.FromFile(LegacyEntry.Instance.Drawing.Canvas.GraphicsDevice, path); } catch (Exception e) { @@ -665,8 +671,8 @@ public class GPULib : IComponent return 1; } - var data = new uint[texture.Width * texture.Height]; - texture.GetData(data); + //var data = new uint[texture.Width * texture.Height]; + //texture.GetData(data); Task.Run(() => { @@ -695,7 +701,7 @@ public class GPULib : IComponent } }*/ - var buffer = new GPUBufferMeta.GPUBuffer + /*var buffer = new GPUBufferMeta.GPUBuffer { Buffer = data, Height = texture.Height, @@ -708,7 +714,7 @@ public class GPULib : IComponent lk.SetMetaTable(GPUBufferMeta.ObjectType); }); - texture.Dispose(); + texture.Dispose();*/ }); return 1; @@ -721,7 +727,7 @@ public class GPULib : IComponent var c = L.OptInteger(1, 0x000000); GetColor((uint)c, out var r, out var g, out var b); - _game.Drawing.Clear(new Color(r, g, b)); + _game.Canvas.Clear(new Color(r, g, b)); return 0; } diff --git a/Capy64/Runtime/Libraries/HTTPLib.cs b/Capy64/Runtime/Libraries/HTTPLib.cs index d78e8bb..e288069 100644 --- a/Capy64/Runtime/Libraries/HTTPLib.cs +++ b/Capy64/Runtime/Libraries/HTTPLib.cs @@ -30,7 +30,7 @@ namespace Capy64.Runtime.Libraries; #nullable enable public class HTTPLib : IComponent { - private static LegacyEntry _game = null!; + private static Game _game = null!; private static HttpClient _httpClient = null!; private static long _requestId; public static readonly HashSet WebSocketConnections = new(); @@ -57,7 +57,7 @@ public class HTTPLib : IComponent }, new(), }; - public HTTPLib(LegacyEntry game) + public HTTPLib(Game game) { _game = game; _requestId = 0; diff --git a/Capy64/Runtime/Libraries/MachineLib.cs b/Capy64/Runtime/Libraries/MachineLib.cs index 1caf92e..8cb3986 100644 --- a/Capy64/Runtime/Libraries/MachineLib.cs +++ b/Capy64/Runtime/Libraries/MachineLib.cs @@ -24,8 +24,8 @@ namespace Capy64.Runtime.Libraries; public class MachineLib : IComponent { - private static LegacyEntry _game; - public MachineLib(LegacyEntry game) + private static Game _game; + public MachineLib(Game game) { _game = game; } diff --git a/Capy64/Runtime/Libraries/TermLib.cs b/Capy64/Runtime/Libraries/TermLib.cs index f4df3de..e67f393 100644 --- a/Capy64/Runtime/Libraries/TermLib.cs +++ b/Capy64/Runtime/Libraries/TermLib.cs @@ -15,11 +15,9 @@ using Capy64.API; using Capy64.Eventing.Events; +using Capy64.Utils; using KeraLua; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; -using static Capy64.Utils; namespace Capy64.Runtime.Libraries; @@ -49,11 +47,11 @@ internal class TermLib : IComponent public static Color BackgroundColor { get; set; } private static Char?[] CharGrid; - private static LegacyEntry _game; + private static Game _game; private static bool cursorState = false; private static bool enableCursor = true; - private static Texture2D cursorTexture; - public TermLib(LegacyEntry game) + //private static Texture2D cursorTexture; + public TermLib(Game game) { _game = game; @@ -61,10 +59,10 @@ internal class TermLib : IComponent ForegroundColor = Color.White; BackgroundColor = Color.Black; - cursorTexture = new(_game.Game.GraphicsDevice, 1, CharHeight - 3); - var textureData = new Color[CharHeight - 3]; - Array.Fill(textureData, Color.White); - cursorTexture.SetData(textureData); + //cursorTexture = new(_game.Game.GraphicsDevice, 1, CharHeight - 3); + //var textureData = new Color[CharHeight - 3]; + //Array.Fill(textureData, Color.White); + //cursorTexture.SetData(textureData); UpdateSize(); @@ -182,7 +180,9 @@ internal class TermLib : IComponent { /*if (_game.EngineMode == EngineMode.Classic) c = ColorPalette.GetColor(c);*/ - UnpackRGB(c, out r, out g, out b); + var color = new Color(c); + //UnpackRGB(c, out r, out g, out b); + r = color.R; g = color.G; b = color.B; } public static void UpdateSize(bool resize = true) @@ -212,22 +212,24 @@ internal class TermLib : IComponent var realpos = ToRealPos(pos); var charpos = realpos + CharOffset; - _game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), bg, Math.Min(CharWidth, CharHeight)); - //_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), Color.Red, 1); + _game.Canvas.DrawFilledRectangle(realpos, new(CharWidth, CharHeight), bg); + //_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), bg, Math.Min(CharWidth, CharHeight)); try { - _game.Drawing.DrawString(charpos, ch.ToString(), fg); + _game.Canvas.DrawString(charpos, ch.ToString(), fg); + //_game.Drawing.DrawString(charpos, ch.ToString(), fg); } catch (ArgumentException) // UTF-16 fuckery { - _game.Drawing.DrawString(charpos, "\xFFFD", fg); + _game.Canvas.DrawString(charpos, "\xFFFD", fg); + //_game.Drawing.DrawString(charpos, "\xFFFD", fg); } if (underline) { - _game.Drawing.DrawLine(charpos + new Vector2(0, CharHeight), charpos + new Vector2(CharWidth, CharHeight), fg); + //_game.Drawing.DrawLine(charpos + new Vector2(0, CharHeight), charpos + new Vector2(CharWidth, CharHeight), fg); } if (!save) @@ -318,14 +320,14 @@ internal class TermLib : IComponent var realpos = ToRealPos(CursorPosition - Vector2.One); var charpos = (realpos * _game.Scale) + ((CharOffset + new Vector2(0, 2)) * _game.Scale); charpos += new Vector2(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top); - _game.Game.SpriteBatch.Draw(cursorTexture, charpos, null, ForegroundColor, 0f, Vector2.Zero, _game.Scale, SpriteEffects.None, 0); + //_game.Game.SpriteBatch.Draw(cursorTexture, charpos, null, ForegroundColor, 0f, Vector2.Zero, _game.Scale, SpriteEffects.None, 0); } } private static void ClearGrid() { CharGrid = new Char?[CharGrid.Length]; - _game.Drawing.Clear(BackgroundColor); + _game.Canvas.Clear(BackgroundColor); } public static void Write(string text) @@ -399,10 +401,12 @@ internal class TermLib : IComponent { var L = Lua.FromIntPtr(state); - if (_game.EngineMode == EngineMode.Classic) - { - return L.Error("Terminal is not resizable"); - } + return 0; + + //if (_game.EngineMode == EngineMode.Classic) + //{ + // return L.Error("Terminal is not resizable"); + //} var w = (int)L.CheckNumber(1); var h = (int)L.CheckNumber(2); @@ -426,7 +430,8 @@ internal class TermLib : IComponent { var L = Lua.FromIntPtr(state); - L.PushBoolean(_game.EngineMode != EngineMode.Classic); + //L.PushBoolean(_game.EngineMode != EngineMode.Classic); + L.PushBoolean(false); return 1; } @@ -435,7 +440,7 @@ internal class TermLib : IComponent { var L = Lua.FromIntPtr(state); - L.PushInteger(PackRGB(ForegroundColor)); + L.PushInteger(ForegroundColor.PackedRGB); return 1; } @@ -477,7 +482,7 @@ internal class TermLib : IComponent { var L = Lua.FromIntPtr(state); - L.PushInteger(PackRGB(BackgroundColor)); + L.PushInteger(ForegroundColor.PackedRGB); return 1; } diff --git a/Capy64/Runtime/Libraries/TimerLib.cs b/Capy64/Runtime/Libraries/TimerLib.cs index eedcd91..dc0f9f8 100644 --- a/Capy64/Runtime/Libraries/TimerLib.cs +++ b/Capy64/Runtime/Libraries/TimerLib.cs @@ -50,11 +50,11 @@ class TimerLib : IComponent new(), }; - private static LegacyEntry _game; + private static Game _game; private static uint _timerId = 0; private static readonly ConcurrentDictionary timers = new(); - public TimerLib(LegacyEntry game) + public TimerLib(Game game) { _game = game; diff --git a/Capy64/Runtime/LuaState.cs b/Capy64/Runtime/LuaState.cs index d221ddb..cc1c443 100644 --- a/Capy64/Runtime/LuaState.cs +++ b/Capy64/Runtime/LuaState.cs @@ -72,8 +72,8 @@ public class LuaState : IDisposable private void InitPlugins() { - var allPlugins = new List(LegacyEntry.Instance.NativePlugins); - allPlugins.AddRange(LegacyEntry.Instance.Plugins); + var allPlugins = new List(Game.Instance.NativePlugins); + allPlugins.AddRange(Game.Instance.Plugins); foreach (var plugin in allPlugins) { plugin.LuaInit(Thread); diff --git a/Capy64/Runtime/ObjectManager.cs b/Capy64/Runtime/ObjectManager.cs index e0c5bcf..31b183a 100644 --- a/Capy64/Runtime/ObjectManager.cs +++ b/Capy64/Runtime/ObjectManager.cs @@ -25,8 +25,8 @@ public class ObjectManager : IComponent { private static readonly ConcurrentDictionary _objects = new(); - private static LegacyEntry _game; - public ObjectManager(LegacyEntry game) + private static Game _game; + public ObjectManager(Game game) { _game = game; _game.EventEmitter.OnClose += OnClose; diff --git a/Capy64/Runtime/Objects/FileHandle.cs b/Capy64/Runtime/Objects/FileHandle.cs index 5a3eddc..33a018b 100644 --- a/Capy64/Runtime/Objects/FileHandle.cs +++ b/Capy64/Runtime/Objects/FileHandle.cs @@ -88,7 +88,7 @@ public class FileHandle : IComponent new(), }; - public FileHandle(LegacyEntry _) { } + public FileHandle(Game _) { } public void LuaInit(Lua L) { diff --git a/Capy64/Runtime/Objects/GPUBufferMeta.cs b/Capy64/Runtime/Objects/GPUBufferMeta.cs index 6d37afb..71c0470 100644 --- a/Capy64/Runtime/Objects/GPUBufferMeta.cs +++ b/Capy64/Runtime/Objects/GPUBufferMeta.cs @@ -66,8 +66,8 @@ public class GPUBufferMeta : IComponent new(), }; - private static LegacyEntry _game; - public GPUBufferMeta(LegacyEntry game) + private static Game _game; + public GPUBufferMeta(Game game) { _game = game; } diff --git a/Capy64/Runtime/Objects/Socket.cs b/Capy64/Runtime/Objects/Socket.cs index 1037ccd..86127ff 100644 --- a/Capy64/Runtime/Objects/Socket.cs +++ b/Capy64/Runtime/Objects/Socket.cs @@ -29,8 +29,8 @@ public class Socket : IDisposable public class SocketLib : IComponent { - private static LegacyEntry _game = null!; - public SocketLib(LegacyEntry game) + private static Game _game = null!; + public SocketLib(Game game) { _game = game; } diff --git a/Capy64/Runtime/Objects/Task.cs b/Capy64/Runtime/Objects/Task.cs index 25f1b06..f739e3b 100644 --- a/Capy64/Runtime/Objects/Task.cs +++ b/Capy64/Runtime/Objects/Task.cs @@ -21,8 +21,8 @@ namespace Capy64.Runtime.Objects; public class TaskMeta : IComponent { - private static LegacyEntry _game; - public TaskMeta(LegacyEntry game) + private static Game _game; + public TaskMeta(Game game) { _game = game; } diff --git a/Capy64/Runtime/Objects/WebSocketClient.cs b/Capy64/Runtime/Objects/WebSocketClient.cs index 74307a4..0def9ee 100644 --- a/Capy64/Runtime/Objects/WebSocketClient.cs +++ b/Capy64/Runtime/Objects/WebSocketClient.cs @@ -73,7 +73,7 @@ public class WebSocketClient : IComponent new(), }; - public WebSocketClient(LegacyEntry _) { } + public WebSocketClient(Game _) { } public void LuaInit(Lua L) { diff --git a/Capy64/Runtime/PanicScreen.cs b/Capy64/Runtime/PanicScreen.cs index 2f1e513..e791635 100644 --- a/Capy64/Runtime/PanicScreen.cs +++ b/Capy64/Runtime/PanicScreen.cs @@ -14,7 +14,7 @@ // limitations under the License. using Capy64.Runtime.Libraries; -using Microsoft.Xna.Framework; +using Capy64.Utils; namespace Capy64.Runtime; diff --git a/Capy64/Runtime/RuntimeManager.cs b/Capy64/Runtime/RuntimeManager.cs index 85147ec..608788d 100644 --- a/Capy64/Runtime/RuntimeManager.cs +++ b/Capy64/Runtime/RuntimeManager.cs @@ -32,8 +32,8 @@ internal class RuntimeManager : IComponent private static bool close = false; private static bool inPanic = false; - private static LegacyEntry _game; - public RuntimeManager(LegacyEntry game) + private static Game _game; + public RuntimeManager(Game game) { _game = game; @@ -95,7 +95,7 @@ internal class RuntimeManager : IComponent private void InitBIOS() { - _game.Discord.SetPresence("Booting up..."); + //_game.Discord.SetPresence("Booting up..."); InstallOS(false); @@ -207,7 +207,7 @@ internal class RuntimeManager : IComponent public static void Shutdown() { close = true; - _game.Exit(); + //_game.Exit(); } public static void InstallOS(bool force = false) diff --git a/Capy64/Utils.cs b/Capy64/Utils/Borders.cs similarity index 51% rename from Capy64/Utils.cs rename to Capy64/Utils/Borders.cs index d011545..8ebcbf2 100644 --- a/Capy64/Utils.cs +++ b/Capy64/Utils/Borders.cs @@ -13,33 +13,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; -namespace Capy64; +namespace Capy64.Utils; -public static class Utils +public struct Borders { - public struct Borders - { - public int Top, Bottom, Left, Right; - } - - /// - /// Return the sane 0xRRGGBB format - /// - /// - public static int PackRGB(Color color) - { - return - (color.R << 16) + - (color.G << 8) + - color.B; - } - - public static void UnpackRGB(uint packed, out byte r, out byte g, out byte b) - { - b = (byte)(packed & 0xff); - g = (byte)((packed >> 8) & 0xff); - r = (byte)((packed >> 16) & 0xff); - } + public int Top { get; set; } + public int Bottom { get; set; } + public int Left { get; set; } + public int Right { get; set; } + public Color Color { get; set; } + public float Size { get; set; } } diff --git a/Capy64/Utils/Color.cs b/Capy64/Utils/Color.cs new file mode 100644 index 0000000..1b89a6c --- /dev/null +++ b/Capy64/Utils/Color.cs @@ -0,0 +1,103 @@ +// This file is part of Capy64 - https://github.com/Ale32bit/Capy64 +// Copyright 2023 Alessandro "AlexDevs" Proto +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static SDL2.SDL; + +namespace Capy64.Utils; + +public struct Color +{ + public byte R + { + get => (byte)(PackedValue >> 16); + set => PackedValue = PackedValue & 0xFF00FFFFu | (uint)value << 16; + } + public byte G + { + get => (byte)(PackedValue >> 8); + set => PackedValue = PackedValue & 0xFFFF00FFu | (uint)value << 8; + } + public byte B + { + get => (byte)PackedValue; + set => PackedValue = PackedValue & 0xFFFFFF00u | value; + } + public byte A + { + get => (byte)(PackedValue >> 24); + set => PackedValue = PackedValue & 0x00FFFFFFu | (uint)value << 24; + } + public uint PackedRGB => PackedValue & 0xFFFFFFu; + public uint PackedValue { get; set; } + + public Color(byte r, byte g, byte b) + { + R = r; + G = g; + B = b; + A = 255; + } + + public Color(byte r, byte g, byte b, byte a) + { + R = r; + G = g; + B = b; + A = a; + } + + public Color(uint packedValue) + { + PackedValue = packedValue; + } + + public SDL_Color ToSDL() => new() + { + r = R, + g = G, + b = B, + a = A, + }; + + public static Color Transparent { get; private set; } + public static Color Black { get; private set; } + public static Color White { get; private set; } + public static Color Gray { get; private set; } + public static Color Red { get; private set; } + public static Color Green { get; private set; } + public static Color Blue { get; private set; } + public static Color Yellow { get; private set; } + public static Color Magenta { get; private set; } + public static Color Cyan { get; private set; } + + static Color() + { + Transparent = new Color(0u); + Black = new Color(0, 0, 0); + White = new Color(255, 255, 255); + Gray = new Color(128, 128, 128); + Red = new Color(255, 0, 0); + Green = new Color(0, 255, 0); + Blue = new Color(0, 0, 255); + Yellow = new Color(255, 255, 0); + Magenta = new Color(255, 0, 255); + Cyan = new Color(0, 255, 255); + } +} diff --git a/Capy64/Utils/Point.cs b/Capy64/Utils/Point.cs new file mode 100644 index 0000000..cf1f50b --- /dev/null +++ b/Capy64/Utils/Point.cs @@ -0,0 +1,124 @@ +// This file is part of Capy64 - https://github.com/Ale32bit/Capy64 +// Copyright 2023 Alessandro "AlexDevs" Proto +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace Capy64.Utils; + +public struct Point : IEquatable +{ + private static readonly Point zeroPoint; + + [DataMember] + public int X; + + [DataMember] + public int Y; + + public static Point Zero => zeroPoint; + + internal string DebugDisplayString => X + " " + Y; + + public Point(int x, int y) + { + X = x; + Y = y; + } + + public Point(int value) + { + X = value; + Y = value; + } + + public static Point operator +(Point value1, Point value2) + { + return new Point(value1.X + value2.X, value1.Y + value2.Y); + } + + public static Point operator -(Point value1, Point value2) + { + return new Point(value1.X - value2.X, value1.Y - value2.Y); + } + + public static Point operator *(Point value1, Point value2) + { + return new Point(value1.X * value2.X, value1.Y * value2.Y); + } + + public static Point operator /(Point source, Point divisor) + { + return new Point(source.X / divisor.X, source.Y / divisor.Y); + } + + public static bool operator ==(Point a, Point b) + { + return a.Equals(b); + } + + public static bool operator !=(Point a, Point b) + { + return !a.Equals(b); + } + + public override bool Equals(object obj) + { + if (obj is Point) + { + return Equals((Point)obj); + } + + return false; + } + + public bool Equals(Point other) + { + if (X == other.X) + { + return Y == other.Y; + } + + return false; + } + + public override int GetHashCode() + { + return (17 * 23 + X.GetHashCode()) * 23 + Y.GetHashCode(); + } + + public override string ToString() + { + return "{X:" + X + " Y:" + Y + "}"; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector2 ToVector2() + { + return new Vector2(X, Y); + } + + public void Deconstruct(out int x, out int y) + { + x = X; + y = Y; + } +} \ No newline at end of file diff --git a/Capy64/Utils/Size2.cs b/Capy64/Utils/Size2.cs new file mode 100644 index 0000000..20c45ff --- /dev/null +++ b/Capy64/Utils/Size2.cs @@ -0,0 +1,164 @@ +// This file is part of Capy64 - https://github.com/Ale32bit/Capy64 +// Copyright 2023 Alessandro "AlexDevs" Proto +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using MonoGame.Extended; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Capy64.Utils; + +public struct Size2 : IEquatable, IEquatableByRef +{ + public static readonly Size2 Empty; + + public float Width; + + public float Height; + + public bool IsEmpty + { + get + { + if (Width == 0f) + { + return Height == 0f; + } + + return false; + } + } + + internal string DebugDisplayString => ToString(); + + public Size2(float width, float height) + { + Width = width; + Height = height; + } + + public static bool operator ==(Size2 first, Size2 second) + { + return first.Equals(ref second); + } + + public bool Equals(Size2 size) + { + return Equals(ref size); + } + + public bool Equals(ref Size2 size) + { + if (Width == size.Width) + { + return Height == size.Height; + } + + return false; + } + + public override bool Equals(object obj) + { + if (obj is Size2) + { + return Equals((Size2)obj); + } + + return false; + } + + public static bool operator !=(Size2 first, Size2 second) + { + return !(first == second); + } + + public static Size2 operator +(Size2 first, Size2 second) + { + return Add(first, second); + } + + public static Size2 Add(Size2 first, Size2 second) + { + Size2 result = default(Size2); + result.Width = first.Width + second.Width; + result.Height = first.Height + second.Height; + return result; + } + + public static Size2 operator -(Size2 first, Size2 second) + { + return Subtract(first, second); + } + + public static Size2 operator /(Size2 size, float value) + { + return new Size2(size.Width / value, size.Height / value); + } + + public static Size2 operator *(Size2 size, float value) + { + return new Size2(size.Width * value, size.Height * value); + } + + public static Size2 Subtract(Size2 first, Size2 second) + { + Size2 result = default(Size2); + result.Width = first.Width - second.Width; + result.Height = first.Height - second.Height; + return result; + } + + public override int GetHashCode() + { + return (Width.GetHashCode() * 397) ^ Height.GetHashCode(); + } + + public static implicit operator Size2(Point2 point) + { + return new Size2(point.X, point.Y); + } + + public static implicit operator Size2(Point point) + { + return new Size2(point.X, point.Y); + } + + public static implicit operator Point2(Size2 size) + { + return new Point2(size.Width, size.Height); + } + + public static implicit operator Vector2(Size2 size) + { + return new Vector2(size.Width, size.Height); + } + + public static implicit operator Size2(Vector2 vector) + { + return new Size2(vector.X, vector.Y); + } + + public static explicit operator Point(Size2 size) + { + return new Point((int)size.Width, (int)size.Height); + } + + public override string ToString() + { + return $"Width: {Width}, Height: {Height}"; + } +} \ No newline at end of file diff --git a/Capy64/Utils/Vector2.cs b/Capy64/Utils/Vector2.cs new file mode 100644 index 0000000..9177bec --- /dev/null +++ b/Capy64/Utils/Vector2.cs @@ -0,0 +1,149 @@ +// This file is part of Capy64 - https://github.com/Ale32bit/Capy64 +// Copyright 2023 Alessandro "AlexDevs" Proto +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace Capy64.Utils; + +public struct Vector2 : IEquatable +{ + private static readonly Vector2 zeroVector = new(0f, 0f); + private static readonly Vector2 unitVector = new(1f, 1f); + private static readonly Vector2 unitXVector = new(1f, 0f); + private static readonly Vector2 unitYVector = new(0f, 1f); + public static Vector2 Zero => zeroVector; + public static Vector2 One => unitVector; + public static Vector2 UnitX => unitXVector; + public static Vector2 UnitY => unitYVector; + + public float X { get; set; } + public float Y { get; set; } + + public Vector2(float x, float y) + { + X = x; + Y = y; + } + + public Vector2(float value) + { + X = value; + Y = value; + } + + public static implicit operator Vector2(System.Numerics.Vector2 value) + { + return new Vector2(value.X, value.Y); + } + + public static Vector2 operator -(Vector2 value) + { + value.X = 0f - value.X; + value.Y = 0f - value.Y; + return value; + } + + public static Vector2 operator +(Vector2 value1, Vector2 value2) + { + value1.X += value2.X; + value1.Y += value2.Y; + return value1; + } + + public static Vector2 operator -(Vector2 value1, Vector2 value2) + { + value1.X -= value2.X; + value1.Y -= value2.Y; + return value1; + } + + public static Vector2 operator *(Vector2 value1, Vector2 value2) + { + value1.X *= value2.X; + value1.Y *= value2.Y; + return value1; + } + + public static Vector2 operator *(Vector2 value, float scaleFactor) + { + value.X *= scaleFactor; + value.Y *= scaleFactor; + return value; + } + + public static Vector2 operator *(float scaleFactor, Vector2 value) + { + value.X *= scaleFactor; + value.Y *= scaleFactor; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator /(Vector2 value1, Vector2 value2) + { + value1.X /= value2.X; + value1.Y /= value2.Y; + return value1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator /(Vector2 value1, float divider) + { + float num = 1f / divider; + value1.X *= num; + value1.Y *= num; + return value1; + } + + public static bool operator ==(Vector2 value1, Vector2 value2) + { + if (value1.X == value2.X) + { + return value1.Y == value2.Y; + } + + return false; + } + + public static bool operator !=(Vector2 value1, Vector2 value2) + { + if (value1.X == value2.X) + { + return value1.Y != value2.Y; + } + + return true; + } + + public override bool Equals(object obj) + { + if (obj is Vector2) + { + return Equals((Vector2)obj); + } + + return false; + } + + public bool Equals(Vector2 other) + { + return X == other.X && Y == other.Y; + } +}