Too many changes.

This commit is contained in:
Alessandro Proto 2023-09-03 22:27:54 +02:00
parent 110afd1ca4
commit 4681c7060e
29 changed files with 1008 additions and 182 deletions

View file

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<RollForward>Major</RollForward> <RollForward>Major</RollForward>
<PublishReadyToRun>false</PublishReadyToRun> <PublishReadyToRun>false</PublishReadyToRun>

122
Capy64/Core/Canvas.cs Normal file
View file

@ -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<Point> 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);
}
}

View file

@ -20,20 +20,31 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using SDL2; using SDL2;
using Newtonsoft.Json.Linq;
namespace Capy64.Eventing; namespace Capy64.Eventing;
public class InputManager public class InputManager
{ {
// SDL inverts Right and Middle (2 and 3)
public enum MouseButton public enum MouseButton
{ {
Left = 1, Left = 1,
Right = 2, Right = 3,
Middle = 3, Middle = 2,
Button4 = 4, Button4 = 4,
Button5 = 5, Button5 = 5,
} }
private Dictionary<MouseButton, int> MouseMap = new()
{
[MouseButton.Left] = 1,
[MouseButton.Right] = 2,
[MouseButton.Middle] = 3,
[MouseButton.Button4] = 4,
[MouseButton.Button5] = 5,
};
[Flags] [Flags]
public enum Modifiers public enum Modifiers
{ {
@ -75,7 +86,6 @@ public class InputManager
}; };
public Texture2D Texture { get; set; } public Texture2D Texture { get; set; }
public static float WindowScale => LegacyEntry.Instance.Scale;
public const int MouseScrollDelta = 120; public const int MouseScrollDelta = 120;
private Point mousePosition; private Point mousePosition;
@ -85,9 +95,9 @@ public class InputManager
private Modifiers keyboardMods = 0; private Modifiers keyboardMods = 0;
private readonly HashSet<Keys> pressedKeys = new(); private readonly HashSet<Keys> pressedKeys = new();
private readonly Capy64 _game; private readonly Game _game;
private readonly EventEmitter _eventEmitter; private readonly EventEmitter _eventEmitter;
public InputManager(Capy64 game, EventEmitter eventManager) public InputManager(Game game, EventEmitter eventManager)
{ {
_game = game; _game = game;
@ -109,18 +119,26 @@ public class InputManager
UpdateGamePad(GamePad.GetState(PlayerIndex.One), IsActive); 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 position = new Point(x, y);
var rawPosition = position - new Point(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top); var rawPosition = position - new Point(_game.Borders.Left, _game.Borders.Top);
var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1); 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) if (pos.X < 1 || pos.Y < 1 || pos.X > (_game.Width) || pos.Y > _game.Height)
return; return;
if (pos != mousePosition) if (pos != mousePosition)
{ {
mousePosition = pos; mousePosition = pos;
Console.WriteLine("MOTION {0} {1} {2}", pos.X, pos.Y, ev.button.state);
_eventEmitter.RaiseMouseMove(new() _eventEmitter.RaiseMouseMove(new()
{ {
Position = mousePosition, Position = mousePosition,
@ -130,7 +148,36 @@ public class InputManager
.ToArray() .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) private void UpdateMouse(MouseState state, bool isActive)
@ -138,8 +185,8 @@ public class InputManager
if (!isActive) if (!isActive)
return; return;
var rawPosition = state.Position - new Point(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top); var rawPosition = state.Position - new Point(_game.Borders.Left, _game.Borders.Top);
var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1); 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) if (pos.X < 1 || pos.Y < 1 || pos.X > Texture.Width || pos.Y > Texture.Height)
return; return;

View file

@ -13,20 +13,27 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using Capy64.API;
using Capy64.Core;
using Capy64.Eventing; 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; namespace Capy64;
using System; public class Game : IDisposable
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using static Utils;
using static SDL2.SDL;
public class Capy64 : IDisposable
{ {
public static Game Instance { get; private set; }
public const string Version = "1.1.0-beta"; public const string Version = "1.1.0-beta";
public nint Window { get; private set; } = 0; public nint Window { get; private set; } = 0;
public nint Renderer { 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 Ticktime => 1000f / Tickrate;
public float Frametime => 1000f / Framerate; public float Frametime => 1000f / Framerate;
public IList<IComponent> NativePlugins { get; private set; }
public IList<IComponent> 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; get => _borders;
set { set
{
_borders = value; _borders = value;
_outputRect = new() { _outputRect = new()
{
x = value.Left, x = value.Left,
y = value.Top, y = value.Top,
w = (int)(Width * Scale), 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 AssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets"); public static readonly string AssetsPath = Path.Combine(AssemblyPath, "Assets");
public IConfiguration Configuration { get; private set; }
public static class DefaultParameters public static class DefaultParameters
{ {
@ -76,8 +89,10 @@ public class Capy64 : IDisposable
public const int FreeTickrate = 60; public const int FreeTickrate = 60;
} }
public static string AppDataPath { public static string AppDataPath
get { {
get
{
string baseDir = string baseDir =
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Environment.GetFolderPath( RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData, Environment.SpecialFolder.ApplicationData,
@ -93,24 +108,76 @@ public class Capy64 : IDisposable
return Path.Combine(baseDir, "Capy64"); return Path.Combine(baseDir, "Capy64");
} }
} }
private bool _running = false; private bool _running = false;
private InputManager _inputManager; 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(); ResetBorder();
WindowWidth = (int)(Width * Scale) + Borders.Left + Borders.Right; UpdateSize();
WindowHeight = (int)(Height * Scale) + Borders.Top + Borders.Bottom;
_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<IComponent> 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<IComponent>();
foreach (var type in types)
{
var instance = (IComponent)Activator.CreateInstance(type, this);
plugins.Add(instance);
}
return plugins;
} }
private void ResetBorder() private void ResetBorder()
{ {
var size = (int)(Scale * DefaultParameters.BorderMultiplier); var size = (int)(Scale * DefaultParameters.BorderMultiplier);
Borders = new Borders { Borders = new Borders
{
Top = size, Top = size,
Bottom = size, Bottom = size,
Left = 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() public void Run()
{ {
Initialize();
#if DEBUG #if DEBUG
SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1"); SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
#endif #endif
@ -142,7 +223,7 @@ public class Capy64 : IDisposable
} }
var icon = SDL_LoadBMP("./Icon.bmp"); var icon = SDL_LoadBMP("./Icon.bmp");
if(icon != 0) if (icon != 0)
SDL_SetWindowIcon(Window, icon); SDL_SetWindowIcon(Window, icon);
Renderer = SDL_CreateRenderer(Window, Renderer = SDL_CreateRenderer(Window,
@ -158,31 +239,23 @@ public class Capy64 : IDisposable
VideoSurface = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_ARGB8888); VideoSurface = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_ARGB8888);
SurfaceRenderer = SDL_CreateSoftwareRenderer(VideoSurface); SurfaceRenderer = SDL_CreateSoftwareRenderer(VideoSurface);
SDL_SetRenderDrawColor(SurfaceRenderer, 255, 255, 255, 255); SDL_SetRenderDrawColor(SurfaceRenderer, 0, 0, 0, 255);
SDL_RenderClear(SurfaceRenderer); SDL_RenderClear(SurfaceRenderer);
_running = true; EventEmitter.RaiseInit();
ulong deltaEnd = 0; ulong deltaEnd = 0;
var perfFreq = SDL_GetPerformanceFrequency(); 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) ulong totalTicks = 0;
{
continue; var drawTimer = new Timer(TimeSpan.FromMilliseconds(1000d / Framerate));
} drawTimer.Elapsed += (s, e) =>
deltaEnd = deltaStart; {
SDL_SetRenderDrawColor(Renderer, BorderColor.R, BorderColor.G, BorderColor.B, 255); SDL_SetRenderDrawColor(Renderer, BorderColor.R, BorderColor.G, BorderColor.B, 255);
SDL_RenderClear(Renderer); SDL_RenderClear(Renderer);
SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255); SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255);
var texture = SDL_CreateTextureFromSurface(Renderer, VideoSurface); var texture = SDL_CreateTextureFromSurface(Renderer, VideoSurface);
@ -190,7 +263,49 @@ public class Capy64 : IDisposable
SDL_RenderCopy(Renderer, texture, 0, ref _outputRect); SDL_RenderCopy(Renderer, texture, 0, ref _outputRect);
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
SDL_RenderPresent(Renderer); 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: case SDL_EventType.SDL_QUIT:
_running = false; _running = false;
Dispose();
break; break;
case SDL_EventType.SDL_KEYUP:
case SDL_EventType.SDL_KEYDOWN: case SDL_EventType.SDL_KEYDOWN:
break; break;
case SDL_EventType.SDL_MOUSEMOTION:
_inputManager.UpdateMouseMove(ev);
break;
case SDL_EventType.SDL_MOUSEBUTTONUP: case SDL_EventType.SDL_MOUSEBUTTONUP:
case SDL_EventType.SDL_MOUSEBUTTONDOWN: case SDL_EventType.SDL_MOUSEBUTTONDOWN:
_inputManager.UpdateMouseClick(ev);
unsafe break;
{
var pitch = ((SDL_Surface*)VideoSurface)->pitch;
((uint*)((SDL_Surface*)VideoSurface)->pixels)[x + y * pitch / 4] = 0xFFFF00FF;
}
case SDL_EventType.SDL_MOUSEWHEEL:
_inputManager.UpdateMouseScroll(ev);
break; break;
} }
} }
@ -221,10 +340,9 @@ public class Capy64 : IDisposable
public void Dispose() public void Dispose()
{ {
SDL_DestroyRenderer(SurfaceRenderer); SDL_DestroyRenderer(SurfaceRenderer);
SDL_FreeSurface(VideoSurface); //SDL_FreeSurface(VideoSurface);
SDL_DestroyRenderer(Renderer); SDL_DestroyRenderer(Renderer);
SDL_DestroyWindow(Window); SDL_DestroyWindow(Window);
SDL_Quit(); SDL_Quit();
} }
} }

View file

@ -24,11 +24,12 @@ namespace Capy64.Integrations;
public class DiscordIntegration : IComponent public class DiscordIntegration : IComponent
{ {
public static DiscordIntegration Instance { get; private set; }
public DiscordRpcClient Client { get; private set; } public DiscordRpcClient Client { get; private set; }
public readonly bool Enabled; public readonly bool Enabled;
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
public DiscordIntegration(LegacyEntry game) public DiscordIntegration(Game game)
{ {
_configuration = game.Configuration; _configuration = game.Configuration;
@ -42,7 +43,7 @@ public class DiscordIntegration : IComponent
Client.OnReady += OnReady; Client.OnReady += OnReady;
LegacyEntry.Instance.Discord = this; Instance = this;
if (Enabled) if (Enabled)
Client.Initialize(); Client.Initialize();

View file

@ -20,6 +20,7 @@ using Capy64.Extensions;
using Capy64.Integrations; using Capy64.Integrations;
using Capy64.PluginManager; using Capy64.PluginManager;
using Capy64.Runtime; using Capy64.Runtime;
using Capy64.Utils;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@ -31,7 +32,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static Capy64.Utils;
namespace Capy64; namespace Capy64;
@ -41,7 +41,7 @@ public enum EngineMode
Free Free
} }
public class LegacyEntry : Game public class LegacyEntry : Microsoft.Xna.Framework.Game
{ {
public const string Version = "1.1.0-beta"; public const string Version = "1.1.0-beta";
@ -96,7 +96,7 @@ public class LegacyEntry : Game
public int TickRate => tickrate; public int TickRate => tickrate;
public IConfiguration Configuration { get; private set; } 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() public Borders Borders = new()
{ {
@ -315,7 +315,7 @@ public class LegacyEntry : Game
protected override void Draw(GameTime gameTime) 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); GraphicsDevice.Clear(BorderColor);
SpriteBatch.DrawRectangle(renderTarget.Bounds.Location.ToVector2() + new Vector2(Borders.Left, Borders.Top), SpriteBatch.DrawRectangle(renderTarget.Bounds.Location.ToVector2() + new Vector2(Borders.Left, Borders.Top),
@ -333,6 +333,6 @@ public class LegacyEntry : Game
SpriteBatch.End(); SpriteBatch.End();
base.Draw(gameTime); base.Draw(gameTime);*/
} }
} }

View file

@ -17,7 +17,7 @@ using Capy64;
if (args.Length > 0 && args[0] == "sdl") if (args.Length > 0 && args[0] == "sdl")
{ {
using var game = new Capy64.Capy64(); using var game = new Capy64.Game();
game.Run(); game.Run();
} }

View file

@ -25,8 +25,8 @@ public class AudioLib : IComponent
{ {
private const int queueLimit = 8; private const int queueLimit = 8;
private static LegacyEntry _game; private static Game _game;
public AudioLib(LegacyEntry game) public AudioLib(Game game)
{ {
_game = game; _game = game;
_game.EventEmitter.OnClose += OnClose; _game.EventEmitter.OnClose += OnClose;

View file

@ -29,8 +29,8 @@ public class EventLib : IComponent
private static bool FrozenTaskAwaiter = false; private static bool FrozenTaskAwaiter = false;
private static LegacyEntry _game; private static Game _game;
public EventLib(LegacyEntry game) public EventLib(Game game)
{ {
_game = game; _game = game;
} }

View file

@ -111,7 +111,7 @@ public class FileSystemLib : IComponent
new(), // NULL new(), // NULL
}; };
public FileSystemLib(LegacyEntry _) { } public FileSystemLib(Game _) { }
public void LuaInit(Lua state) public void LuaInit(Lua state)
{ {

View file

@ -15,9 +15,8 @@
using Capy64.API; using Capy64.API;
using Capy64.Runtime.Objects; using Capy64.Runtime.Objects;
using Capy64.Utils;
using KeraLua; using KeraLua;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -28,8 +27,8 @@ namespace Capy64.Runtime.Libraries;
public class GPULib : IComponent public class GPULib : IComponent
{ {
private static LegacyEntry _game; private static Game _game;
public GPULib(LegacyEntry game) public GPULib(Game game)
{ {
_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) 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) private static int L_GetSize(IntPtr state)
@ -174,10 +175,12 @@ public class GPULib : IComponent
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
if (_game.EngineMode == EngineMode.Classic) return 0;
/*if (_game.EngineMode == EngineMode.Classic)
{ {
return L.Error("Screen is not resizable"); return L.Error("Screen is not resizable");
} }*/
var w = L.CheckInteger(1); var w = L.CheckInteger(1);
var h = L.CheckInteger(2); var h = L.CheckInteger(2);
@ -196,7 +199,8 @@ public class GPULib : IComponent
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
L.PushBoolean(_game.EngineMode != EngineMode.Classic); //L.PushBoolean(_game.EngineMode != EngineMode.Classic);
L.PushBoolean(false);
return 1; return 1;
} }
@ -208,9 +212,11 @@ public class GPULib : IComponent
var x = (int)L.CheckNumber(1) - 1; var x = (int)L.CheckNumber(1) - 1;
var y = (int)L.CheckNumber(2) - 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; return 1;
} }
@ -224,7 +230,7 @@ public class GPULib : IComponent
var c = L.CheckInteger(3); var c = L.CheckInteger(3);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -259,7 +265,7 @@ public class GPULib : IComponent
} }
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -274,7 +280,7 @@ public class GPULib : IComponent
var s = (int)L.OptNumber(4, 1); var s = (int)L.OptNumber(4, 1);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -291,7 +297,7 @@ public class GPULib : IComponent
var s = (int)L.OptInteger(6, -1); var s = (int)L.OptInteger(6, -1);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -308,7 +314,7 @@ public class GPULib : IComponent
var s = (int)L.OptNumber(6, 1); var s = (int)L.OptNumber(6, 1);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -325,7 +331,7 @@ public class GPULib : IComponent
var s = (int)L.OptNumber(6, 1); var s = (int)L.OptNumber(6, 1);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -361,7 +367,7 @@ public class GPULib : IComponent
} }
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -378,7 +384,7 @@ public class GPULib : IComponent
var s = (int)L.OptNumber(6, 1); var s = (int)L.OptNumber(6, 1);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }
@ -395,7 +401,7 @@ public class GPULib : IComponent
GetColor((uint)c, out var r, out var g, out var b); GetColor((uint)c, out var r, out var g, out var b);
try 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 catch (ArgumentException ex) // UTF-16 fuckery
{ {
@ -411,10 +417,10 @@ public class GPULib : IComponent
var t = L.CheckString(1); 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.X);
L.PushNumber((int)sizes.Y); //L.PushNumber((int)sizes.Y);
return 2; return 2;
} }
@ -425,7 +431,7 @@ public class GPULib : IComponent
var buffer = new uint[_game.Width * _game.Height]; var buffer = new uint[_game.Width * _game.Height];
_game.Drawing.Canvas.GetData(buffer); //_game.Drawing.Canvas.GetData(buffer);
var gpuBuffer = new GPUBufferMeta.GPUBuffer var gpuBuffer = new GPUBufferMeta.GPUBuffer
{ {
@ -446,7 +452,7 @@ public class GPULib : IComponent
var buffer = GPUBufferMeta.CheckBuffer(L, false); var buffer = GPUBufferMeta.CheckBuffer(L, false);
_game.Drawing.Canvas.SetData(buffer.Buffer); //_game.Drawing.Canvas.SetData(buffer.Buffer);
return 0; return 0;
} }
@ -533,7 +539,7 @@ public class GPULib : IComponent
var x = (int)L.CheckInteger(2) - 1; var x = (int)L.CheckInteger(2) - 1;
var y = (int)L.CheckInteger(3) - 1; var y = (int)L.CheckInteger(3) - 1;
Rectangle? source = null; /*Rectangle? source = null;
Color color = Color.White; Color color = Color.White;
float rotation = 0; float rotation = 0;
Vector2 origin = Vector2.Zero; Vector2 origin = Vector2.Zero;
@ -634,7 +640,7 @@ public class GPULib : IComponent
Width = buffer.Width, Width = buffer.Width,
Height = buffer.Height, Height = buffer.Height,
}, source, color, rotation, origin, scale, effects); }, source, color, rotation, origin, scale, effects);
*/
return 0; return 0;
} }
@ -654,10 +660,10 @@ public class GPULib : IComponent
var task = TaskMeta.Push(L, GPUBufferMeta.ObjectType); var task = TaskMeta.Push(L, GPUBufferMeta.ObjectType);
Texture2D texture; //Texture2D texture;
try try
{ {
texture = Texture2D.FromFile(LegacyEntry.Instance.Drawing.Canvas.GraphicsDevice, path); //texture = Texture2D.FromFile(LegacyEntry.Instance.Drawing.Canvas.GraphicsDevice, path);
} }
catch (Exception e) catch (Exception e)
{ {
@ -665,8 +671,8 @@ public class GPULib : IComponent
return 1; return 1;
} }
var data = new uint[texture.Width * texture.Height]; //var data = new uint[texture.Width * texture.Height];
texture.GetData(data); //texture.GetData(data);
Task.Run(() => Task.Run(() =>
{ {
@ -695,7 +701,7 @@ public class GPULib : IComponent
} }
}*/ }*/
var buffer = new GPUBufferMeta.GPUBuffer /*var buffer = new GPUBufferMeta.GPUBuffer
{ {
Buffer = data, Buffer = data,
Height = texture.Height, Height = texture.Height,
@ -708,7 +714,7 @@ public class GPULib : IComponent
lk.SetMetaTable(GPUBufferMeta.ObjectType); lk.SetMetaTable(GPUBufferMeta.ObjectType);
}); });
texture.Dispose(); texture.Dispose();*/
}); });
return 1; return 1;
@ -721,7 +727,7 @@ public class GPULib : IComponent
var c = L.OptInteger(1, 0x000000); var c = L.OptInteger(1, 0x000000);
GetColor((uint)c, out var r, out var g, out var b); 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; return 0;
} }

View file

@ -30,7 +30,7 @@ namespace Capy64.Runtime.Libraries;
#nullable enable #nullable enable
public class HTTPLib : IComponent public class HTTPLib : IComponent
{ {
private static LegacyEntry _game = null!; private static Game _game = null!;
private static HttpClient _httpClient = null!; private static HttpClient _httpClient = null!;
private static long _requestId; private static long _requestId;
public static readonly HashSet<WebSocketClient.Client> WebSocketConnections = new(); public static readonly HashSet<WebSocketClient.Client> WebSocketConnections = new();
@ -57,7 +57,7 @@ public class HTTPLib : IComponent
}, },
new(), new(),
}; };
public HTTPLib(LegacyEntry game) public HTTPLib(Game game)
{ {
_game = game; _game = game;
_requestId = 0; _requestId = 0;

View file

@ -24,8 +24,8 @@ namespace Capy64.Runtime.Libraries;
public class MachineLib : IComponent public class MachineLib : IComponent
{ {
private static LegacyEntry _game; private static Game _game;
public MachineLib(LegacyEntry game) public MachineLib(Game game)
{ {
_game = game; _game = game;
} }

View file

@ -15,11 +15,9 @@
using Capy64.API; using Capy64.API;
using Capy64.Eventing.Events; using Capy64.Eventing.Events;
using Capy64.Utils;
using KeraLua; using KeraLua;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System; using System;
using static Capy64.Utils;
namespace Capy64.Runtime.Libraries; namespace Capy64.Runtime.Libraries;
@ -49,11 +47,11 @@ internal class TermLib : IComponent
public static Color BackgroundColor { get; set; } public static Color BackgroundColor { get; set; }
private static Char?[] CharGrid; private static Char?[] CharGrid;
private static LegacyEntry _game; private static Game _game;
private static bool cursorState = false; private static bool cursorState = false;
private static bool enableCursor = true; private static bool enableCursor = true;
private static Texture2D cursorTexture; //private static Texture2D cursorTexture;
public TermLib(LegacyEntry game) public TermLib(Game game)
{ {
_game = game; _game = game;
@ -61,10 +59,10 @@ internal class TermLib : IComponent
ForegroundColor = Color.White; ForegroundColor = Color.White;
BackgroundColor = Color.Black; BackgroundColor = Color.Black;
cursorTexture = new(_game.Game.GraphicsDevice, 1, CharHeight - 3); //cursorTexture = new(_game.Game.GraphicsDevice, 1, CharHeight - 3);
var textureData = new Color[CharHeight - 3]; //var textureData = new Color[CharHeight - 3];
Array.Fill(textureData, Color.White); //Array.Fill(textureData, Color.White);
cursorTexture.SetData(textureData); //cursorTexture.SetData(textureData);
UpdateSize(); UpdateSize();
@ -182,7 +180,9 @@ internal class TermLib : IComponent
{ {
/*if (_game.EngineMode == EngineMode.Classic) /*if (_game.EngineMode == EngineMode.Classic)
c = ColorPalette.GetColor(c);*/ 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) public static void UpdateSize(bool resize = true)
@ -212,22 +212,24 @@ internal class TermLib : IComponent
var realpos = ToRealPos(pos); var realpos = ToRealPos(pos);
var charpos = realpos + CharOffset; var charpos = realpos + CharOffset;
_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), bg, Math.Min(CharWidth, CharHeight)); _game.Canvas.DrawFilledRectangle(realpos, new(CharWidth, CharHeight), bg);
//_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), Color.Red, 1); //_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), bg, Math.Min(CharWidth, CharHeight));
try 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 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) 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) if (!save)
@ -318,14 +320,14 @@ internal class TermLib : IComponent
var realpos = ToRealPos(CursorPosition - Vector2.One); var realpos = ToRealPos(CursorPosition - Vector2.One);
var charpos = (realpos * _game.Scale) + ((CharOffset + new Vector2(0, 2)) * _game.Scale); var charpos = (realpos * _game.Scale) + ((CharOffset + new Vector2(0, 2)) * _game.Scale);
charpos += new Vector2(LegacyEntry.Instance.Borders.Left, LegacyEntry.Instance.Borders.Top); 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() private static void ClearGrid()
{ {
CharGrid = new Char?[CharGrid.Length]; CharGrid = new Char?[CharGrid.Length];
_game.Drawing.Clear(BackgroundColor); _game.Canvas.Clear(BackgroundColor);
} }
public static void Write(string text) public static void Write(string text)
@ -399,10 +401,12 @@ internal class TermLib : IComponent
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
if (_game.EngineMode == EngineMode.Classic) return 0;
{
return L.Error("Terminal is not resizable"); //if (_game.EngineMode == EngineMode.Classic)
} //{
// return L.Error("Terminal is not resizable");
//}
var w = (int)L.CheckNumber(1); var w = (int)L.CheckNumber(1);
var h = (int)L.CheckNumber(2); var h = (int)L.CheckNumber(2);
@ -426,7 +430,8 @@ internal class TermLib : IComponent
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
L.PushBoolean(_game.EngineMode != EngineMode.Classic); //L.PushBoolean(_game.EngineMode != EngineMode.Classic);
L.PushBoolean(false);
return 1; return 1;
} }
@ -435,7 +440,7 @@ internal class TermLib : IComponent
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
L.PushInteger(PackRGB(ForegroundColor)); L.PushInteger(ForegroundColor.PackedRGB);
return 1; return 1;
} }
@ -477,7 +482,7 @@ internal class TermLib : IComponent
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
L.PushInteger(PackRGB(BackgroundColor)); L.PushInteger(ForegroundColor.PackedRGB);
return 1; return 1;
} }

View file

@ -50,11 +50,11 @@ class TimerLib : IComponent
new(), new(),
}; };
private static LegacyEntry _game; private static Game _game;
private static uint _timerId = 0; private static uint _timerId = 0;
private static readonly ConcurrentDictionary<uint, Timer> timers = new(); private static readonly ConcurrentDictionary<uint, Timer> timers = new();
public TimerLib(LegacyEntry game) public TimerLib(Game game)
{ {
_game = game; _game = game;

View file

@ -72,8 +72,8 @@ public class LuaState : IDisposable
private void InitPlugins() private void InitPlugins()
{ {
var allPlugins = new List<IComponent>(LegacyEntry.Instance.NativePlugins); var allPlugins = new List<IComponent>(Game.Instance.NativePlugins);
allPlugins.AddRange(LegacyEntry.Instance.Plugins); allPlugins.AddRange(Game.Instance.Plugins);
foreach (var plugin in allPlugins) foreach (var plugin in allPlugins)
{ {
plugin.LuaInit(Thread); plugin.LuaInit(Thread);

View file

@ -25,8 +25,8 @@ public class ObjectManager : IComponent
{ {
private static readonly ConcurrentDictionary<nint, object> _objects = new(); private static readonly ConcurrentDictionary<nint, object> _objects = new();
private static LegacyEntry _game; private static Game _game;
public ObjectManager(LegacyEntry game) public ObjectManager(Game game)
{ {
_game = game; _game = game;
_game.EventEmitter.OnClose += OnClose; _game.EventEmitter.OnClose += OnClose;

View file

@ -88,7 +88,7 @@ public class FileHandle : IComponent
new(), new(),
}; };
public FileHandle(LegacyEntry _) { } public FileHandle(Game _) { }
public void LuaInit(Lua L) public void LuaInit(Lua L)
{ {

View file

@ -66,8 +66,8 @@ public class GPUBufferMeta : IComponent
new(), new(),
}; };
private static LegacyEntry _game; private static Game _game;
public GPUBufferMeta(LegacyEntry game) public GPUBufferMeta(Game game)
{ {
_game = game; _game = game;
} }

View file

@ -29,8 +29,8 @@ public class Socket : IDisposable
public class SocketLib : IComponent public class SocketLib : IComponent
{ {
private static LegacyEntry _game = null!; private static Game _game = null!;
public SocketLib(LegacyEntry game) public SocketLib(Game game)
{ {
_game = game; _game = game;
} }

View file

@ -21,8 +21,8 @@ namespace Capy64.Runtime.Objects;
public class TaskMeta : IComponent public class TaskMeta : IComponent
{ {
private static LegacyEntry _game; private static Game _game;
public TaskMeta(LegacyEntry game) public TaskMeta(Game game)
{ {
_game = game; _game = game;
} }

View file

@ -73,7 +73,7 @@ public class WebSocketClient : IComponent
new(), new(),
}; };
public WebSocketClient(LegacyEntry _) { } public WebSocketClient(Game _) { }
public void LuaInit(Lua L) public void LuaInit(Lua L)
{ {

View file

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
using Capy64.Runtime.Libraries; using Capy64.Runtime.Libraries;
using Microsoft.Xna.Framework; using Capy64.Utils;
namespace Capy64.Runtime; namespace Capy64.Runtime;

View file

@ -32,8 +32,8 @@ internal class RuntimeManager : IComponent
private static bool close = false; private static bool close = false;
private static bool inPanic = false; private static bool inPanic = false;
private static LegacyEntry _game; private static Game _game;
public RuntimeManager(LegacyEntry game) public RuntimeManager(Game game)
{ {
_game = game; _game = game;
@ -95,7 +95,7 @@ internal class RuntimeManager : IComponent
private void InitBIOS() private void InitBIOS()
{ {
_game.Discord.SetPresence("Booting up..."); //_game.Discord.SetPresence("Booting up...");
InstallOS(false); InstallOS(false);
@ -207,7 +207,7 @@ internal class RuntimeManager : IComponent
public static void Shutdown() public static void Shutdown()
{ {
close = true; close = true;
_game.Exit(); //_game.Exit();
} }
public static void InstallOS(bool force = false) public static void InstallOS(bool force = false)

View file

@ -13,33 +13,20 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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 { get; set; }
{ public int Bottom { get; set; }
public int Top, Bottom, Left, Right; public int Left { get; set; }
} public int Right { get; set; }
public Color Color { get; set; }
/// <summary> public float Size { get; set; }
/// Return the sane 0xRRGGBB format
/// </summary>
/// <param name="color"></param>
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);
}
} }

103
Capy64/Utils/Color.cs Normal file
View file

@ -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);
}
}

124
Capy64/Utils/Point.cs Normal file
View file

@ -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<Point>
{
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;
}
}

164
Capy64/Utils/Size2.cs Normal file
View file

@ -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<Size2>, IEquatableByRef<Size2>
{
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}";
}
}

149
Capy64/Utils/Vector2.cs Normal file
View file

@ -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<Vector2>
{
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;
}
}