Init.
This commit is contained in:
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
*.swp
|
||||||
|
*.*~
|
||||||
|
project.lock.json
|
||||||
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
|
nupkg/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# Rider
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
build/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
msbuild.log
|
||||||
|
msbuild.err
|
||||||
|
msbuild.wrn
|
||||||
|
|
||||||
|
# Visual Studio 2015
|
||||||
|
.vs/
|
||||||
12
DaggerFramework.csproj
Normal file
12
DaggerFramework.csproj
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ImGui.NET" Version="1.89.4" />
|
||||||
|
<PackageReference Include="Raylib-cs" Version="4.2.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
29
Source/Audio/AudioBackend.cs
Normal file
29
Source/Audio/AudioBackend.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace DaggerFramework.Audio
|
||||||
|
{
|
||||||
|
public abstract class AudioBackend
|
||||||
|
{
|
||||||
|
public abstract void Initialize();
|
||||||
|
public abstract void Update();
|
||||||
|
// BUS
|
||||||
|
public abstract void CreateBus(string busName);
|
||||||
|
public abstract void SetBusVolume(string busName, float volume);
|
||||||
|
public abstract float GetBusVolume(string busName);
|
||||||
|
|
||||||
|
// SOUND
|
||||||
|
protected abstract void PlaySound(Sound sound, string bus = "Master", float pitch = 1.0f, float volume = 1.0f);
|
||||||
|
public void PlaySound(Sound sound, string bus = "Master") => PlaySound(sound, bus, sound.PitchScale, sound.Volume);
|
||||||
|
public void PlaySoundVariation(Sound sound, string bus = "Master", float pitchVariation = 0.1f)
|
||||||
|
{
|
||||||
|
var maxPitch = sound.PitchScale + pitchVariation;
|
||||||
|
var minPitch = sound.PitchScale - pitchVariation;
|
||||||
|
|
||||||
|
var pitch = (float)_random.NextDouble() * (maxPitch - minPitch) + minPitch;
|
||||||
|
PlaySound(sound, bus, pitch, sound.Volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EFFECTS
|
||||||
|
public abstract void AddBusEffect<T>(T effect, string bus = "Master") where T : AudioEffect;
|
||||||
|
|
||||||
|
private LehmerRandom _random = new LehmerRandom();
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Source/Audio/AudioBus.cs
Normal file
7
Source/Audio/AudioBus.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class AudioBus
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Source/Audio/AudioEffect.cs
Normal file
9
Source/Audio/AudioEffect.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class AudioEffect { }
|
||||||
|
|
||||||
|
public class AudioEffectReverb : AudioEffect
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Source/Audio/DummyAudioBackend.cs
Normal file
40
Source/Audio/DummyAudioBackend.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
namespace DaggerFramework.Audio
|
||||||
|
{
|
||||||
|
public class DummyAudioBackend : AudioBackend
|
||||||
|
{
|
||||||
|
public override void AddBusEffect<T>(T effect, string bus = "Master")
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CreateBus(string busName)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float GetBusVolume(string busName)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetBusVolume(string busName, float volume)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PlaySound(Sound sound, string bus = "Master", float pitch = 1, float volume = 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
103
Source/Audio/FmodAudioBackend.cs
Normal file
103
Source/Audio/FmodAudioBackend.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// using FMOD;
|
||||||
|
|
||||||
|
// namespace RogueMine.Audio
|
||||||
|
// {
|
||||||
|
// public class FmodAudioBackend : AudioBackend
|
||||||
|
// {
|
||||||
|
// public override void Initialize()
|
||||||
|
// {
|
||||||
|
// CreateSystem();
|
||||||
|
// _loadedSounds = new Dictionary<string, FMOD.Sound>();
|
||||||
|
// _channelGroups = new Dictionary<string, ChannelGroup>();
|
||||||
|
|
||||||
|
// CreateBus("Master");
|
||||||
|
// }
|
||||||
|
// public override void Update() => _system.update();
|
||||||
|
|
||||||
|
// protected override void PlaySound(Sound sound, string bus = "Master", float pitch = 1, float volume = 1)
|
||||||
|
// {
|
||||||
|
// var channel = PlaySoundFromPath(sound.Path, GetChannelGroup(bus));
|
||||||
|
// channel.setVolume(volume);
|
||||||
|
// channel.setPitch(pitch);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void CreateBus(string busName)
|
||||||
|
// {
|
||||||
|
// ChannelGroup channelGroup;
|
||||||
|
// _system.createChannelGroup(busName, out channelGroup);
|
||||||
|
// _channelGroups.Add(busName, channelGroup);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetBusVolume(string busName, float volume)
|
||||||
|
// {
|
||||||
|
// var channel = GetChannelGroup(busName);
|
||||||
|
// channel.setVolume(volume);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override float GetBusVolume(string busName)
|
||||||
|
// {
|
||||||
|
// float volume;
|
||||||
|
// GetChannelGroup(busName).getVolume(out volume);
|
||||||
|
// return volume;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void AddBusEffect<T>(T effect, string bus = "Master")
|
||||||
|
// {
|
||||||
|
// var channelGroup = GetChannelGroup(bus);
|
||||||
|
// DSP dsp;
|
||||||
|
|
||||||
|
// switch (effect)
|
||||||
|
// {
|
||||||
|
// case AudioEffectReverb:
|
||||||
|
// dsp = CreateReverbDsp(effect as AudioEffectReverb);
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// _system.createDSPByType(DSP_TYPE.UNKNOWN, out dsp);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// channelGroup.addDSP(0, dsp);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private DSP CreateReverbDsp(AudioEffectReverb effectReverb)
|
||||||
|
// {
|
||||||
|
// DSP dsp;
|
||||||
|
// _system.createDSPByType(DSP_TYPE.SFXREVERB, out dsp);
|
||||||
|
// return dsp;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void CreateSystem()
|
||||||
|
// {
|
||||||
|
// var result = FMOD.Factory.System_Create(out _system);
|
||||||
|
// _system.init(128, INITFLAGS.NORMAL, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private Channel PlaySoundFromPath(string path, ChannelGroup channelGroup)
|
||||||
|
// {
|
||||||
|
// FMOD.Channel fmodChannel;
|
||||||
|
// FMOD.Sound fmodSound = IsLoaded(path) ? GetSoundFromLoaded(path) : CreateSound(path);
|
||||||
|
// _system.playSound(fmodSound, channelGroup, false, out fmodChannel);
|
||||||
|
|
||||||
|
// return fmodChannel;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private FMOD.Sound GetSoundFromLoaded(string path) => _loadedSounds[path];
|
||||||
|
// private bool IsLoaded(string path) => _loadedSounds.ContainsKey(path);
|
||||||
|
|
||||||
|
// private FMOD.Sound CreateSound(string path)
|
||||||
|
// {
|
||||||
|
// FMOD.Sound sound;
|
||||||
|
// _system.createSound(path, FMOD.MODE.DEFAULT, out sound);
|
||||||
|
// AddToLoaded(path, sound);
|
||||||
|
// return sound;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void AddToLoaded(string path, FMOD.Sound sound) => _loadedSounds.Add(path, sound);
|
||||||
|
|
||||||
|
// private ChannelGroup GetChannelGroup(string busName) => _channelGroups[busName];
|
||||||
|
|
||||||
|
// private FMOD.System _system;
|
||||||
|
// private Dictionary<string, FMOD.Sound> _loadedSounds;
|
||||||
|
// private Dictionary<string, ChannelGroup> _channelGroups;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
20
Source/Entities/CircleShape2d.cs
Executable file
20
Source/Entities/CircleShape2d.cs
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class CircleShape2d : Drawable2d
|
||||||
|
{
|
||||||
|
public float Radius { get => _radius; set => _radius = value; }
|
||||||
|
public Color Color { get => _color; set => _color = value; }
|
||||||
|
|
||||||
|
public override void OnDraw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
renderer.DrawCircle(_radius, _color);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _radius;
|
||||||
|
private System.Drawing.Color _color;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Source/Entities/Drawable2d.cs
Executable file
15
Source/Entities/Drawable2d.cs
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public abstract class Drawable2d : Entity2d, IDrawable
|
||||||
|
{
|
||||||
|
public void Draw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
renderer.SetTransform(position);
|
||||||
|
OnDraw(ref renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void OnDraw(ref Renderer renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Source/Entities/Entity.cs
Executable file
27
Source/Entities/Entity.cs
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
using DaggerFramework.Audio;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Entity
|
||||||
|
{
|
||||||
|
public EntityLayer Layer { get; set; }
|
||||||
|
public InputHandler Input => Layer.Scene.Input;
|
||||||
|
public AudioBackend Audio => Layer.Scene.Audio;
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public void Start() => OnStart();
|
||||||
|
public void Update(double dt) => OnUpdate(dt);
|
||||||
|
public void ReceiveInput(InputHandler input) => OnInput(input);
|
||||||
|
|
||||||
|
protected virtual void OnStart() { }
|
||||||
|
protected virtual void OnDestroy() { }
|
||||||
|
protected virtual void OnUpdate(double dt) { }
|
||||||
|
protected virtual void OnInput(InputHandler input) { }
|
||||||
|
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
OnDestroy();
|
||||||
|
Layer?.DestroyEntity(Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Source/Entities/Entity2d.cs
Executable file
10
Source/Entities/Entity2d.cs
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Entity2d : Entity
|
||||||
|
{
|
||||||
|
public Vector2 Position { get => position; set => position = value; }
|
||||||
|
protected Vector2 position;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Source/Entities/IDrawable.cs
Executable file
9
Source/Entities/IDrawable.cs
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public interface IDrawable
|
||||||
|
{
|
||||||
|
public void Draw(ref Renderer renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
158
Source/Entities/Particles2d.cs
Normal file
158
Source/Entities/Particles2d.cs
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
// TODO: add oneshot parameter.
|
||||||
|
public class Particles2d : Drawable2d
|
||||||
|
{
|
||||||
|
public int MaxParticles => _maxParticles;
|
||||||
|
|
||||||
|
public void BeginEmit(ParticleSettings settings)
|
||||||
|
{
|
||||||
|
_settings = settings;
|
||||||
|
_maxParticles = _settings.MaxParticles;
|
||||||
|
_particleIndex = _maxParticles - 1;
|
||||||
|
InitializeParticles();
|
||||||
|
}
|
||||||
|
public void Restart()
|
||||||
|
{
|
||||||
|
CleanupParticles();
|
||||||
|
InitializeParticles();
|
||||||
|
}
|
||||||
|
public override void OnDraw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
foreach (var particle in _particles)
|
||||||
|
{
|
||||||
|
if (!particle.Alive) continue;
|
||||||
|
|
||||||
|
var t = particle.LifeTimeRemaining / particle.LifeTime;
|
||||||
|
var scale = MathUtils.Lerp(_settings.ScaleEnd, _settings.ScaleBegin, t);
|
||||||
|
var color = MathUtils.LerpColor(_settings.ColorEnd, _settings.ColorBegin, t);
|
||||||
|
|
||||||
|
renderer.SetTransform(particle.Position, particle.Rotation);
|
||||||
|
renderer.DrawRectangle(Vector2.One * scale, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected override void OnStart()
|
||||||
|
{
|
||||||
|
base.OnStart();
|
||||||
|
// Emit();
|
||||||
|
}
|
||||||
|
protected override void OnUpdate(double dt)
|
||||||
|
{
|
||||||
|
base.OnUpdate(dt);
|
||||||
|
|
||||||
|
var rate = (int)MathUtils.Lerp(1, _maxParticles, _settings.Explosiveness);
|
||||||
|
for (int i = 0; i < rate; i++)
|
||||||
|
{
|
||||||
|
Emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _maxParticles; i++)
|
||||||
|
{
|
||||||
|
var particle = _particles[i];
|
||||||
|
if (!particle.Alive) continue;
|
||||||
|
|
||||||
|
if (particle.LifeTimeRemaining <= 0.0f)
|
||||||
|
{
|
||||||
|
particle.Alive = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
particle.LifeTimeRemaining -= (float)dt;
|
||||||
|
particle.Velocity += _settings.Gravity * (float)dt;
|
||||||
|
particle.Position += particle.Velocity * (float)dt;
|
||||||
|
particle.Rotation += particle.AngularVelocity * (float)dt;
|
||||||
|
|
||||||
|
particle.Velocity -= particle.Velocity * _settings.Damping * (float)dt;
|
||||||
|
|
||||||
|
_particles[i] = particle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeParticles()
|
||||||
|
{
|
||||||
|
_particles = new Particle[_maxParticles];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Emit()
|
||||||
|
{
|
||||||
|
Particle particle = _particles[_particleIndex];
|
||||||
|
if (!(particle.LifeTimeRemaining <= 0)) return;
|
||||||
|
particle.Alive = true;
|
||||||
|
particle.Position = GetEmitPosition();
|
||||||
|
particle.Velocity = _settings.Direction * _settings.LinearVelocity;
|
||||||
|
|
||||||
|
particle.Velocity += Vector2.One * _settings.LinearVelocityRandom * ((float)_random.NextDouble() - 0.5f);
|
||||||
|
|
||||||
|
particle.AngularVelocity = _settings.AngularVelocity;
|
||||||
|
particle.AngularVelocity += 1f * _settings.AngularVelocityRandom * ((float)_random.NextDouble() - 0.5f);
|
||||||
|
|
||||||
|
particle.LifeTime = _settings.LifeTime;
|
||||||
|
particle.LifeTimeRemaining = particle.LifeTime;
|
||||||
|
|
||||||
|
_particles[_particleIndex] = particle;
|
||||||
|
_particleIndex = --_particleIndex <= 0 ? _maxParticles - 1 : --_particleIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanupParticles() => Array.Clear(_particles);
|
||||||
|
private Vector2 GetEmitPosition()
|
||||||
|
{
|
||||||
|
// https://gamedev.stackexchange.com/questions/26713/calculate-random-points-pixel-within-a-circle-image
|
||||||
|
var angle = _random.NextDouble() * Math.PI * 2;
|
||||||
|
float radius = (float)Math.Sqrt(_random.NextDouble()) * _settings.EmitRadius;
|
||||||
|
|
||||||
|
float x = Position.X + radius * (float)Math.Cos(angle);
|
||||||
|
float y = Position.Y + radius * (float)Math.Sin(angle);
|
||||||
|
|
||||||
|
return new Vector2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParticleSettings _settings;
|
||||||
|
private int _maxParticles;
|
||||||
|
private Particle[] _particles;
|
||||||
|
private int _particleIndex;
|
||||||
|
|
||||||
|
// TODO: replace a random function for better distribution and performance.
|
||||||
|
private LehmerRandom _random = new LehmerRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ParticleSettings
|
||||||
|
{
|
||||||
|
public ParticleSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public float EmitRadius;
|
||||||
|
public float LifeTime;
|
||||||
|
public float Explosiveness;
|
||||||
|
public int MaxParticles;
|
||||||
|
public Vector2 Direction;
|
||||||
|
public float LinearVelocity;
|
||||||
|
public float AngularVelocity = 0.0f;
|
||||||
|
public float AngularVelocityRandom;
|
||||||
|
public float LinearVelocityRandom;
|
||||||
|
public Vector2 Gravity;
|
||||||
|
public float ScaleBegin = 16f;
|
||||||
|
public float ScaleEnd = 0.0f;
|
||||||
|
public Color ColorBegin = Color.White;
|
||||||
|
public Color ColorEnd = Color.Black;
|
||||||
|
public float Damping = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Particle
|
||||||
|
{
|
||||||
|
public Particle()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public Vector2 Position;
|
||||||
|
public Vector2 Velocity;
|
||||||
|
public float AngularVelocity;
|
||||||
|
public float LifeTime;
|
||||||
|
public float LifeTimeRemaining;
|
||||||
|
public float Scale;
|
||||||
|
public float Rotation;
|
||||||
|
public bool Alive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Source/Entities/Sprite2d.cs
Executable file
25
Source/Entities/Sprite2d.cs
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Sprite2d : Drawable2d
|
||||||
|
{
|
||||||
|
public Texture2d Texture { get => _texture; set => _texture = value; }
|
||||||
|
|
||||||
|
protected override void OnStart()
|
||||||
|
{
|
||||||
|
var renderer = Layer.Scene.Renderer;
|
||||||
|
_texId = renderer.LoadTexture(Texture.Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDraw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
renderer.DrawTexture(_texId, Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Texture2d _texture;
|
||||||
|
private int _texId;
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Source/EntityLayer.cs
Executable file
58
Source/EntityLayer.cs
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class EntityLayer : Layer
|
||||||
|
{
|
||||||
|
public List<Entity> Entities { get => _entities; }
|
||||||
|
public EntityLayer(List<Entity> entities)
|
||||||
|
{
|
||||||
|
_entities = entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityLayer()
|
||||||
|
{
|
||||||
|
_entities = new List<Entity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddEntity(Entity entity)
|
||||||
|
{
|
||||||
|
entity.Id = Entities.Count;
|
||||||
|
entity.Layer = this;
|
||||||
|
Entities.Add(entity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DestroyEntity(int at)
|
||||||
|
{
|
||||||
|
_entities.RemoveAt(at);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart()
|
||||||
|
{
|
||||||
|
foreach (var entity in _entities)
|
||||||
|
{
|
||||||
|
entity.Layer = this;
|
||||||
|
entity.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdate(double dt)
|
||||||
|
{
|
||||||
|
foreach (var entity in _entities)
|
||||||
|
{
|
||||||
|
entity.Update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDraw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
foreach (IDrawable drawable in _entities)
|
||||||
|
{
|
||||||
|
drawable.Draw(ref renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Entity> _entities;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Source/Extensions/Mat4Extensions.cs
Executable file
14
Source/Extensions/Mat4Extensions.cs
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace DaggerFramework.Extensions
|
||||||
|
{
|
||||||
|
public static class Mat4Extensions
|
||||||
|
{
|
||||||
|
public static Matrix4x4 Scale(this Matrix4x4 mat, Vector2 scale)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2506
Source/External/FastNoiseLite.cs
vendored
Executable file
2506
Source/External/FastNoiseLite.cs
vendored
Executable file
File diff suppressed because it is too large
Load Diff
201
Source/External/LehmerRandom.cs
vendored
Normal file
201
Source/External/LehmerRandom.cs
vendored
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/// <summary>
|
||||||
|
/// https://github.com/YourRobotOverlord/LehmerRandom/blob/master/Lehmer/Random.cs
|
||||||
|
/// Alternative to System.Random based on the Lehmer algorithm.
|
||||||
|
/// </summary>
|
||||||
|
public class LehmerRandom
|
||||||
|
{
|
||||||
|
// Stores the seed for the Next methods.
|
||||||
|
private uint _seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Random class, using a time-dependent default seed value.
|
||||||
|
/// </summary>
|
||||||
|
public LehmerRandom()
|
||||||
|
{
|
||||||
|
_seed = (uint)System.Environment.TickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Random class, using the specified seed value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seed"></param>
|
||||||
|
public LehmerRandom(int seed)
|
||||||
|
{
|
||||||
|
_seed = (uint)seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Random class, using the specified seed value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seed"></param>
|
||||||
|
public LehmerRandom(uint seed)
|
||||||
|
{
|
||||||
|
_seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a non-negative random integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Int32</returns>
|
||||||
|
public int Next()
|
||||||
|
{
|
||||||
|
return GetNextInt(0, int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a non-negative random integer that is less than the specified maximum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="maxValue">Int32</param>
|
||||||
|
/// <returns>Int32</returns>
|
||||||
|
public int Next(int maxValue)
|
||||||
|
{
|
||||||
|
return GetNextInt(0, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random integer that is within a specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minValue">Int32</param>
|
||||||
|
/// <param name="maxValue">Int32</param>
|
||||||
|
/// <returns>Int32</returns>
|
||||||
|
public int Next(int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
return GetNextInt(minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public double NextDouble()
|
||||||
|
{
|
||||||
|
return GetNextDouble(0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a non-negative random floating-point number that is less than the specified maximum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="maxValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public double NextDouble(double maxValue)
|
||||||
|
{
|
||||||
|
return GetNextDouble(0.0, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random floating-point number that is within a specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minValue"></param>
|
||||||
|
/// <param name="maxValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public double NextDouble(double minValue, double maxValue)
|
||||||
|
{
|
||||||
|
return GetNextDouble(minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fills the elements of a specified array of bytes with random numbers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The array to be filled with random numbers.</param>
|
||||||
|
public void NextBytes(byte[] buffer)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < buffer.Length; i++)
|
||||||
|
{
|
||||||
|
buffer[i] = (byte)Next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a random int and sets the seed for the next pass.
|
||||||
|
internal int GetNextInt(int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
_seed = Rnd(_seed);
|
||||||
|
return ConvertToIntRange(_seed, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a random double and sets the seed for the next pass.
|
||||||
|
internal double GetNextDouble(double minValue, double maxValue)
|
||||||
|
{
|
||||||
|
_seed = Rnd(_seed);
|
||||||
|
return ConvertToDoubleRange(_seed, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random integer that is within a specified range, using the specified seed value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seed"></param>
|
||||||
|
/// <param name="minValue"></param>
|
||||||
|
/// <param name="maxValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int RndInt(uint seed, int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
return GetInt(seed, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random integer that is within a specified range, using a time-dependent default seed value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minValue"></param>
|
||||||
|
/// <param name="maxValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int RndInt(int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
return GetInt((uint)System.Environment.TickCount, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random double that is within a specified range, using the specified seed value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seed"></param>
|
||||||
|
/// <param name="minValue"></param>
|
||||||
|
/// <param name="maxValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double RndDouble(uint seed, double minValue, double maxValue)
|
||||||
|
{
|
||||||
|
return GetDouble(seed, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random double that is within a specified range, using a time-dependent default seed value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="minValue"></param>
|
||||||
|
/// <param name="maxValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double RndDouble(double minValue, double maxValue)
|
||||||
|
{
|
||||||
|
return GetDouble((uint)System.Environment.TickCount, minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int GetInt(uint seed, int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
return ConvertToIntRange(Rnd(seed), minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static double GetDouble(uint seed, double minValue, double maxValue)
|
||||||
|
{
|
||||||
|
return ConvertToDoubleRange(Rnd(seed), minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts uint to integer within the given range.
|
||||||
|
internal static int ConvertToIntRange(uint val, int minValue, int maxValue)
|
||||||
|
{
|
||||||
|
return (int)(val % (maxValue - minValue) + minValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts uint to double within the given range.
|
||||||
|
internal static double ConvertToDoubleRange(uint val, double minValue, double maxValue)
|
||||||
|
{
|
||||||
|
return (double)val / uint.MaxValue * (maxValue - minValue) + minValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pseudo-random number generator based on the Lehmer Algorithm
|
||||||
|
// and javidx9's implementation:
|
||||||
|
// https://github.com/OneLoneCoder/olcPixelGameEngine/blob/master/Videos/OneLoneCoder_PGE_ProcGen_Universe.cpp
|
||||||
|
internal static uint Rnd(uint seed)
|
||||||
|
{
|
||||||
|
seed += 0xe120fc15;
|
||||||
|
ulong tmp = (ulong)seed * 0x4a39b70d;
|
||||||
|
uint m1 = (uint)((tmp >> 32) ^ tmp);
|
||||||
|
tmp = (ulong)m1 * 0x12fad5c9;
|
||||||
|
return (uint)((tmp >> 32) ^ tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Source/Game.cs
Executable file
17
Source/Game.cs
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public abstract class Game
|
||||||
|
{
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
LoadResources();
|
||||||
|
OnStart();
|
||||||
|
}
|
||||||
|
protected abstract void OnStart();
|
||||||
|
protected abstract void LoadResources();
|
||||||
|
protected abstract void MainLoop();
|
||||||
|
public abstract void Shutdown();
|
||||||
|
|
||||||
|
protected Scene scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Source/IMainLoop.cs
Normal file
11
Source/IMainLoop.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public interface IMainLoop
|
||||||
|
{
|
||||||
|
public void Init();
|
||||||
|
public void Start();
|
||||||
|
public bool ShouldStop();
|
||||||
|
public void Update();
|
||||||
|
public double DeltaTime { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
320
Source/ImGuiRenderLayer.cs
Executable file
320
Source/ImGuiRenderLayer.cs
Executable file
@@ -0,0 +1,320 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Raylib_cs;
|
||||||
|
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class ImGuiRenderLayer : Layer
|
||||||
|
{
|
||||||
|
protected override void OnDraw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
Layout();
|
||||||
|
_controller.Draw(ref renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Layout() { }
|
||||||
|
|
||||||
|
protected override void OnStart()
|
||||||
|
{
|
||||||
|
_controller = new ImGuiController();
|
||||||
|
_controller.Load(Scene.Renderer.WindowSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdate(double dt)
|
||||||
|
{
|
||||||
|
_controller.Update(dt, Input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImGuiController _controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImGuiController : IDisposable, IDrawable
|
||||||
|
{
|
||||||
|
public ImGuiController()
|
||||||
|
{
|
||||||
|
_context = ImGui.CreateContext();
|
||||||
|
ImGui.SetCurrentContext(_context);
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ImGui.DestroyContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(Vector2 size)
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
io.Fonts.AddFontDefault();
|
||||||
|
|
||||||
|
Resize(size);
|
||||||
|
LoadFontTexture();
|
||||||
|
SetupInput();
|
||||||
|
ImGui.NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe void LoadFontTexture()
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
io.Fonts.GetTexDataAsRGBA32(out byte* pixels, out int width, out int height);
|
||||||
|
|
||||||
|
// TODO: use engine API instead of Raylib.
|
||||||
|
Image image = new Image
|
||||||
|
{
|
||||||
|
data = pixels,
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
mipmaps = 1,
|
||||||
|
format = PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
|
||||||
|
};
|
||||||
|
_fontTexture = Raylib.LoadTextureFromImage(image);
|
||||||
|
|
||||||
|
io.Fonts.SetTexID(new IntPtr(_fontTexture.id));
|
||||||
|
io.Fonts.ClearTexData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupInput()
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
|
||||||
|
// Setup config flags
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard;
|
||||||
|
|
||||||
|
// Setup back-end capabilities flags
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors;
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags.HasSetMousePos;
|
||||||
|
|
||||||
|
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||||
|
io.KeyMap[(int)ImGuiKey.Tab] = (int)KeyboardKey.Tab;
|
||||||
|
io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)KeyboardKey.Left;
|
||||||
|
io.KeyMap[(int)ImGuiKey.RightArrow] = (int)KeyboardKey.Right;
|
||||||
|
io.KeyMap[(int)ImGuiKey.UpArrow] = (int)KeyboardKey.Up;
|
||||||
|
io.KeyMap[(int)ImGuiKey.DownArrow] = (int)KeyboardKey.Down;
|
||||||
|
io.KeyMap[(int)ImGuiKey.PageUp] = (int)KeyboardKey.PageUp;
|
||||||
|
io.KeyMap[(int)ImGuiKey.PageDown] = (int)KeyboardKey.PageDown;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Home] = (int)KeyboardKey.Home;
|
||||||
|
io.KeyMap[(int)ImGuiKey.End] = (int)KeyboardKey.End;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Insert] = (int)KeyboardKey.Insert;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Delete] = (int)KeyboardKey.Delete;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Backspace] = (int)KeyboardKey.Backspace;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Space] = (int)KeyboardKey.Spacebar;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Enter] = (int)KeyboardKey.Enter;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Escape] = (int)KeyboardKey.Escape;
|
||||||
|
io.KeyMap[(int)ImGuiKey.A] = (int)KeyboardKey.A;
|
||||||
|
io.KeyMap[(int)ImGuiKey.C] = (int)KeyboardKey.C;
|
||||||
|
io.KeyMap[(int)ImGuiKey.V] = (int)KeyboardKey.V;
|
||||||
|
io.KeyMap[(int)ImGuiKey.X] = (int)KeyboardKey.X;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Y] = (int)KeyboardKey.Y;
|
||||||
|
io.KeyMap[(int)ImGuiKey.Z] = (int)KeyboardKey.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resize(Vector2 size)
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
io.DisplaySize = size / _scaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(double dt, InputHandler input)
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
|
||||||
|
io.DisplayFramebufferScale = Vector2.One;
|
||||||
|
io.DeltaTime = (float)dt;
|
||||||
|
|
||||||
|
UpdateKeyboard(input);
|
||||||
|
UpdateMouse(input);
|
||||||
|
|
||||||
|
ImGui.NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateKeyboard(InputHandler input)
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
|
||||||
|
// Modifiers are not reliable across systems
|
||||||
|
io.KeyCtrl = io.KeysDown[(int)KeyboardKey.LeftControl] || io.KeysDown[(int)KeyboardKey.RightControl];
|
||||||
|
io.KeyShift = io.KeysDown[(int)KeyboardKey.LeftShift] || io.KeysDown[(int)KeyboardKey.RightShift];
|
||||||
|
io.KeyAlt = io.KeysDown[(int)KeyboardKey.LeftAlt] || io.KeysDown[(int)KeyboardKey.RightAlt];
|
||||||
|
io.KeySuper = io.KeysDown[(int)KeyboardKey.LeftSuper] || io.KeysDown[(int)KeyboardKey.RightSuper];
|
||||||
|
|
||||||
|
// Key states
|
||||||
|
for (int i = (int)KeyboardKey.Spacebar; i < (int)KeyboardKey.KBMenu + 1; i++)
|
||||||
|
{
|
||||||
|
io.KeysDown[i] = input.IsKeyboardKeyDown((KeyboardKey)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key input
|
||||||
|
int keyPressed = input.GetCharPressed();
|
||||||
|
if (keyPressed != 0)
|
||||||
|
{
|
||||||
|
io.AddInputCharacter((uint)keyPressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateMouse(InputHandler input)
|
||||||
|
{
|
||||||
|
ImGuiIOPtr io = ImGui.GetIO();
|
||||||
|
|
||||||
|
// Store button states
|
||||||
|
for (int i = 0; i < io.MouseDown.Count; i++)
|
||||||
|
{
|
||||||
|
io.MouseDown[i] = input.IsMouseButtonDown((MouseButton)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse scroll
|
||||||
|
io.MouseWheel += input.GetMouseWheelMovement();
|
||||||
|
|
||||||
|
// Mouse position
|
||||||
|
Vector2 mousePosition = io.MousePos;
|
||||||
|
// TODO:
|
||||||
|
// bool focused = Raylib.IsWindowFocused();
|
||||||
|
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
input.SetMousePosition(mousePosition);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
io.MousePos = input.GetMousePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse cursor state
|
||||||
|
if ((io.ConfigFlags & ImGuiConfigFlags.NoMouseCursorChange) == 0 || input.IsCursorHidden())
|
||||||
|
{
|
||||||
|
ImGuiMouseCursor cursor = ImGui.GetMouseCursor();
|
||||||
|
if (cursor == ImGuiMouseCursor.None || io.MouseDrawCursor)
|
||||||
|
{
|
||||||
|
input.HideCursor();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input.ShowCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Render()
|
||||||
|
{
|
||||||
|
ImGui.Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderCommandLists(ImDrawDataPtr data)
|
||||||
|
{
|
||||||
|
// Scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
int fbWidth = (int)(data.DisplaySize.X * data.FramebufferScale.X);
|
||||||
|
int fbHeight = (int)(data.DisplaySize.Y * data.FramebufferScale.Y);
|
||||||
|
|
||||||
|
// Avoid rendering if display is minimized or if the command list is empty
|
||||||
|
if (fbWidth <= 0 || fbHeight <= 0 || data.CmdListsCount == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rlgl.rlDrawRenderBatchActive();
|
||||||
|
Rlgl.rlDisableBackfaceCulling();
|
||||||
|
Rlgl.rlEnableScissorTest();
|
||||||
|
|
||||||
|
data.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale);
|
||||||
|
|
||||||
|
for (int n = 0; n < data.CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
int idxOffset = 0;
|
||||||
|
ImDrawListPtr cmdList = data.CmdListsRange[n];
|
||||||
|
|
||||||
|
// Vertex buffer and index buffer generated by DearImGui
|
||||||
|
ImPtrVector<ImDrawVertPtr> vtxBuffer = cmdList.VtxBuffer;
|
||||||
|
ImVector<ushort> idxBuffer = cmdList.IdxBuffer;
|
||||||
|
|
||||||
|
for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++)
|
||||||
|
{
|
||||||
|
ImDrawCmdPtr pcmd = cmdList.CmdBuffer[cmdi];
|
||||||
|
|
||||||
|
// Scissor rect
|
||||||
|
Vector2 pos = data.DisplayPos;
|
||||||
|
int rectX = (int)((pcmd.ClipRect.X - pos.X) * data.FramebufferScale.X);
|
||||||
|
int rectY = (int)((pcmd.ClipRect.Y - pos.Y) * data.FramebufferScale.Y);
|
||||||
|
int rectW = (int)((pcmd.ClipRect.Z - rectX) * data.FramebufferScale.Y);
|
||||||
|
int rectH = (int)((pcmd.ClipRect.W - rectY) * data.FramebufferScale.Y);
|
||||||
|
Rlgl.rlScissor(rectX, Raylib.GetScreenHeight() - (rectY + rectH), rectW, rectH);
|
||||||
|
|
||||||
|
if (pcmd.UserCallback != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// pcmd.UserCallback(cmdList, pcmd);
|
||||||
|
idxOffset += (int)pcmd.ElemCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawTriangles(pcmd.ElemCount, idxOffset, (int)pcmd.VtxOffset, idxBuffer, vtxBuffer, pcmd.TextureId);
|
||||||
|
idxOffset += (int)pcmd.ElemCount;
|
||||||
|
Rlgl.rlDrawRenderBatchActive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rlgl.rlSetTexture(0);
|
||||||
|
Rlgl.rlDisableScissorTest();
|
||||||
|
Rlgl.rlEnableBackfaceCulling();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetColor(uint hexValue)
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
color.r = (byte)(hexValue & 0xFF);
|
||||||
|
color.g = (byte)((hexValue >> 8) & 0xFF);
|
||||||
|
color.b = (byte)((hexValue >> 16) & 0xFF);
|
||||||
|
color.a = (byte)((hexValue >> 24) & 0xFF);
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTriangleVertex(ImDrawVertPtr idxVert)
|
||||||
|
{
|
||||||
|
Color c = GetColor(idxVert.col);
|
||||||
|
Rlgl.rlColor4ub(c.r, c.g, c.b, c.a);
|
||||||
|
Rlgl.rlTexCoord2f(idxVert.uv.X, idxVert.uv.Y);
|
||||||
|
Rlgl.rlVertex2f(idxVert.pos.X, idxVert.pos.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the imgui triangle data
|
||||||
|
private void DrawTriangles(uint count, int idxOffset, int vtxOffset, ImVector<ushort> idxBuffer, ImPtrVector<ImDrawVertPtr> idxVert, IntPtr textureId)
|
||||||
|
{
|
||||||
|
ushort index = 0;
|
||||||
|
ImDrawVertPtr vertex;
|
||||||
|
|
||||||
|
if (Rlgl.rlCheckRenderBatchLimit((int)count * 3))
|
||||||
|
{
|
||||||
|
Rlgl.rlDrawRenderBatchActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rlgl.rlBegin(DrawMode.TRIANGLES);
|
||||||
|
Rlgl.rlSetTexture((uint)textureId);
|
||||||
|
|
||||||
|
for (int i = 0; i <= (count - 3); i += 3)
|
||||||
|
{
|
||||||
|
index = idxBuffer[idxOffset + i];
|
||||||
|
vertex = idxVert[vtxOffset + index];
|
||||||
|
DrawTriangleVertex(vertex);
|
||||||
|
|
||||||
|
index = idxBuffer[idxOffset + i + 1];
|
||||||
|
vertex = idxVert[vtxOffset + index];
|
||||||
|
DrawTriangleVertex(vertex);
|
||||||
|
|
||||||
|
index = idxBuffer[idxOffset + i + 2];
|
||||||
|
vertex = idxVert[vtxOffset + index];
|
||||||
|
DrawTriangleVertex(vertex);
|
||||||
|
}
|
||||||
|
Rlgl.rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
ImGui.Render();
|
||||||
|
RenderCommandLists(ImGui.GetDrawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr _context;
|
||||||
|
private Texture2D _fontTexture;
|
||||||
|
private Vector2 _scaleFactor = Vector2.One;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Source/InputAction.cs
Normal file
29
Source/InputAction.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public abstract class InputAction
|
||||||
|
{
|
||||||
|
public abstract bool IsDown(InputHandler inputHandler);
|
||||||
|
public abstract bool IsPressed(InputHandler inputHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class KeyInputAction : InputAction
|
||||||
|
{
|
||||||
|
public KeyboardKey Key => _keyboardKey;
|
||||||
|
|
||||||
|
public KeyInputAction(KeyboardKey keyboardKey)
|
||||||
|
{
|
||||||
|
_keyboardKey = keyboardKey;
|
||||||
|
}
|
||||||
|
public override bool IsDown(InputHandler inputHandler)
|
||||||
|
{
|
||||||
|
return inputHandler.IsKeyboardKeyDown(_keyboardKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsPressed(InputHandler inputHandler)
|
||||||
|
{
|
||||||
|
return inputHandler.KeyboardKeyJustPressed(_keyboardKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeyboardKey _keyboardKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
159
Source/InputHandler.cs
Executable file
159
Source/InputHandler.cs
Executable file
@@ -0,0 +1,159 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public abstract class InputHandler
|
||||||
|
{
|
||||||
|
public InputHandler()
|
||||||
|
{
|
||||||
|
inputMappings = new Dictionary<string, IEnumerable<InputAction>>();
|
||||||
|
}
|
||||||
|
public Action OnInput;
|
||||||
|
public bool Handled { get => _handled; set => _handled = value; }
|
||||||
|
public abstract bool IsKeyboardKeyDown(KeyboardKey key);
|
||||||
|
public abstract bool KeyboardKeyJustPressed(KeyboardKey key);
|
||||||
|
public abstract Vector2 GetInputDirection(KeyboardKey leftKey, KeyboardKey rightKey, KeyboardKey upKey, KeyboardKey downKey);
|
||||||
|
public abstract int GetCharPressed();
|
||||||
|
|
||||||
|
public abstract bool IsActionDown(string action);
|
||||||
|
public abstract bool IsActionJustPressed(string action);
|
||||||
|
|
||||||
|
public abstract bool IsMouseButtonDown(MouseButton button);
|
||||||
|
public abstract float GetMouseWheelMovement();
|
||||||
|
public abstract void SetMousePosition(Vector2 position);
|
||||||
|
public abstract Vector2 GetMousePosition();
|
||||||
|
public abstract void HideCursor();
|
||||||
|
public abstract void ShowCursor();
|
||||||
|
public abstract bool IsCursorHidden();
|
||||||
|
|
||||||
|
public void SetAsHandled() => _handled = true;
|
||||||
|
|
||||||
|
public void AddInputMapping(string actionName, IEnumerable<InputAction> inputActions)
|
||||||
|
{
|
||||||
|
inputMappings.Add(actionName, inputActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _handled;
|
||||||
|
protected Dictionary<string, IEnumerable<InputAction>> inputMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum KeyboardKey
|
||||||
|
{
|
||||||
|
Null = 0,
|
||||||
|
Back = 4,
|
||||||
|
VolumeUp = 24,
|
||||||
|
VolumeDown = 25,
|
||||||
|
Spacebar = 32,
|
||||||
|
Apostrophe = 39,
|
||||||
|
Comma = 44,
|
||||||
|
Minus = 45,
|
||||||
|
Period = 46,
|
||||||
|
Slash = 47,
|
||||||
|
Zero = 48,
|
||||||
|
One = 49,
|
||||||
|
Two = 50,
|
||||||
|
Three = 51,
|
||||||
|
Four = 52,
|
||||||
|
Five = 53,
|
||||||
|
Six = 54,
|
||||||
|
Seven = 55,
|
||||||
|
Eight = 56,
|
||||||
|
Nine = 57,
|
||||||
|
Semicolon = 59,
|
||||||
|
Equal = 61,
|
||||||
|
A = 65,
|
||||||
|
B = 66,
|
||||||
|
C = 67,
|
||||||
|
D = 68,
|
||||||
|
E = 69,
|
||||||
|
F = 70,
|
||||||
|
G = 71,
|
||||||
|
H = 72,
|
||||||
|
I = 73,
|
||||||
|
J = 74,
|
||||||
|
K = 75,
|
||||||
|
L = 76,
|
||||||
|
M = 77,
|
||||||
|
N = 78,
|
||||||
|
O = 79,
|
||||||
|
P = 80,
|
||||||
|
Q = 81,
|
||||||
|
R = 82,
|
||||||
|
Menu = 82,
|
||||||
|
S = 83,
|
||||||
|
T = 84,
|
||||||
|
U = 85,
|
||||||
|
V = 86,
|
||||||
|
W = 87,
|
||||||
|
X = 88,
|
||||||
|
Y = 89,
|
||||||
|
Z = 90,
|
||||||
|
LeftBracket = 91,
|
||||||
|
Backslash = 92,
|
||||||
|
RightBracket = 93,
|
||||||
|
Grave = 96,
|
||||||
|
Escape = 256,
|
||||||
|
Enter = 257,
|
||||||
|
Tab = 258,
|
||||||
|
Backspace = 259,
|
||||||
|
Insert = 260,
|
||||||
|
Delete = 261,
|
||||||
|
Right = 262,
|
||||||
|
Left = 263,
|
||||||
|
Down = 264,
|
||||||
|
Up = 265,
|
||||||
|
PageUp = 266,
|
||||||
|
PageDown = 267,
|
||||||
|
Home = 268,
|
||||||
|
End = 269,
|
||||||
|
CapsLock = 280,
|
||||||
|
ScrollLock = 281,
|
||||||
|
NumLock = 282,
|
||||||
|
PrintScreen = 283,
|
||||||
|
Pause = 284,
|
||||||
|
F1 = 290,
|
||||||
|
F2 = 291,
|
||||||
|
F3 = 292,
|
||||||
|
F4 = 293,
|
||||||
|
F5 = 294,
|
||||||
|
F6 = 295,
|
||||||
|
F7 = 296,
|
||||||
|
F8 = 297,
|
||||||
|
F9 = 298,
|
||||||
|
F10 = 299,
|
||||||
|
F11 = 300,
|
||||||
|
F12 = 301,
|
||||||
|
KP0 = 320,
|
||||||
|
KP1 = 321,
|
||||||
|
KP2 = 322,
|
||||||
|
KP3 = 323,
|
||||||
|
KP4 = 324,
|
||||||
|
KP5 = 325,
|
||||||
|
KP6 = 326,
|
||||||
|
KP7 = 327,
|
||||||
|
KP8 = 328,
|
||||||
|
KP9 = 329,
|
||||||
|
KPDecimal = 330,
|
||||||
|
KPDivide = 331,
|
||||||
|
KPMultiply = 332,
|
||||||
|
KPSubstract = 333,
|
||||||
|
KPAdd = 334,
|
||||||
|
KPEnter = 335,
|
||||||
|
KPEqual = 336,
|
||||||
|
LeftShift = 340,
|
||||||
|
LeftControl = 341,
|
||||||
|
LeftAlt = 342,
|
||||||
|
LeftSuper = 343,
|
||||||
|
RightShift = 344,
|
||||||
|
RightControl = 345,
|
||||||
|
RightAlt = 346,
|
||||||
|
RightSuper = 347,
|
||||||
|
KBMenu = 348
|
||||||
|
}
|
||||||
|
public enum MouseButton
|
||||||
|
{
|
||||||
|
Left = 0,
|
||||||
|
Right = 1,
|
||||||
|
Middle = 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Source/Layer.cs
Executable file
22
Source/Layer.cs
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
using DaggerFramework.Audio;
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public abstract class Layer
|
||||||
|
{
|
||||||
|
public Scene Scene { get; set; }
|
||||||
|
public InputHandler Input { get; set; }
|
||||||
|
|
||||||
|
public void Draw(ref Renderer renderer) => OnDraw(ref renderer);
|
||||||
|
|
||||||
|
public void Start() => OnStart();
|
||||||
|
public void Update(double dt) => OnUpdate(dt);
|
||||||
|
public void ReceiveInput(InputHandler input) => OnInput(input);
|
||||||
|
|
||||||
|
protected virtual void OnStart() { }
|
||||||
|
protected virtual void OnUpdate(double dt) { }
|
||||||
|
protected virtual void OnInput(InputHandler input) { }
|
||||||
|
protected abstract void OnDraw(ref Renderer renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Source/MathUtils.cs
Executable file
45
Source/MathUtils.cs
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public static class MathUtils
|
||||||
|
{
|
||||||
|
public static float Lerp(float a, float b, double t) => a + (b - a) * (float)t;
|
||||||
|
|
||||||
|
public static Color LerpColor(Color colorA, Color colorB, double t)
|
||||||
|
{
|
||||||
|
var r = (byte)Lerp(colorA.R, colorB.R, t);
|
||||||
|
var g = (byte)Lerp(colorA.G, colorB.G, t);
|
||||||
|
var b = (byte)Lerp(colorA.B, colorB.B, t);
|
||||||
|
return Color.FromArgb(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 LerpVector2(Vector2 v1, Vector2 v2, double t)
|
||||||
|
{
|
||||||
|
var x = Lerp(v1.X, v2.X, t);
|
||||||
|
var y = Lerp(v1.X, v2.Y, t);
|
||||||
|
|
||||||
|
return new Vector2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float EaseOutBack(float x)
|
||||||
|
{
|
||||||
|
var c1 = 1.70158f;
|
||||||
|
var c3 = c1 + 1f;
|
||||||
|
|
||||||
|
return 1f + c3 * (float)Math.Pow(x - 1f, 3f) + c1 * (float)Math.Pow(x - 1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float EaseOutElastic(float x)
|
||||||
|
{
|
||||||
|
var c4 = (2f * (float)Math.PI) / 3f;
|
||||||
|
|
||||||
|
return x == 0
|
||||||
|
? 0
|
||||||
|
: x == 1
|
||||||
|
? 1
|
||||||
|
: (float)Math.Pow(2, -10 * x) * (float)Math.Sin((x * 10 - 0.75f) * c4) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
Source/RaylibInputHandler.cs
Executable file
87
Source/RaylibInputHandler.cs
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Raylib_cs;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class RaylibInputHandler : InputHandler
|
||||||
|
{
|
||||||
|
public override int GetCharPressed()
|
||||||
|
{
|
||||||
|
return Raylib.GetCharPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector2 GetInputDirection(KeyboardKey leftKey, KeyboardKey rightKey, KeyboardKey upKey, KeyboardKey downKey)
|
||||||
|
{
|
||||||
|
Vector2 dir = Vector2.Zero;
|
||||||
|
|
||||||
|
if (IsKeyboardKeyDown(leftKey))
|
||||||
|
dir += new Vector2(-1, 0);
|
||||||
|
if (IsKeyboardKeyDown(rightKey))
|
||||||
|
dir += new Vector2(1, 0);
|
||||||
|
if (IsKeyboardKeyDown(upKey))
|
||||||
|
dir += new Vector2(0, -1);
|
||||||
|
if (IsKeyboardKeyDown(downKey))
|
||||||
|
dir += new Vector2(0, 1);
|
||||||
|
|
||||||
|
return dir == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector2 GetMousePosition()
|
||||||
|
{
|
||||||
|
return Raylib.GetMousePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float GetMouseWheelMovement()
|
||||||
|
{
|
||||||
|
return Raylib.GetMouseWheelMove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HideCursor()
|
||||||
|
{
|
||||||
|
Raylib.HideCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsActionDown(string action)
|
||||||
|
{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// return inputMappings[action].IsPressed();
|
||||||
|
foreach (InputAction inputAction in inputMappings[action])
|
||||||
|
if (inputAction.IsDown(this)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsActionJustPressed(string action)
|
||||||
|
{
|
||||||
|
foreach (InputAction inputAction in inputMappings[action])
|
||||||
|
if (inputAction.IsPressed(this)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsKeyboardKeyDown(DaggerFramework.KeyboardKey key)
|
||||||
|
{
|
||||||
|
Raylib_cs.KeyboardKey rayKey = (Raylib_cs.KeyboardKey)key;
|
||||||
|
OnInput?.Invoke();
|
||||||
|
return Raylib.IsKeyDown(rayKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsMouseButtonDown(MouseButton button)
|
||||||
|
{
|
||||||
|
return Raylib.IsMouseButtonDown((Raylib_cs.MouseButton)button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool KeyboardKeyJustPressed(KeyboardKey key)
|
||||||
|
{
|
||||||
|
Raylib_cs.KeyboardKey rayKey = (Raylib_cs.KeyboardKey)key;
|
||||||
|
return Raylib.IsKeyPressed(rayKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetMousePosition(Vector2 position)
|
||||||
|
{
|
||||||
|
Raylib.SetMousePosition((int)position.X, (int)position.Y);
|
||||||
|
}
|
||||||
|
public override void ShowCursor() => Raylib.ShowCursor();
|
||||||
|
public override bool IsCursorHidden() => Raylib.IsCursorHidden();
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Source/Rendering/ColorRectShader.cs
Executable file
49
Source/Rendering/ColorRectShader.cs
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
namespace DaggerFramework.Rendering
|
||||||
|
{
|
||||||
|
public class ColorRectShader : Shader
|
||||||
|
{
|
||||||
|
public override string FragmentSource => @"
|
||||||
|
#version 450
|
||||||
|
layout(location = 0) out vec4 fsout_Color;
|
||||||
|
layout (set = 0, binding = 0) uniform Uniforms
|
||||||
|
{
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
fsout_Color = color;
|
||||||
|
}
|
||||||
|
";
|
||||||
|
|
||||||
|
public override string VertexSource => @"
|
||||||
|
#version 450
|
||||||
|
layout(location = 0) in vec2 Position;
|
||||||
|
|
||||||
|
// uniform MatrixBlock
|
||||||
|
// {
|
||||||
|
// // mat4 model = mat4();
|
||||||
|
// // mat4 view;
|
||||||
|
// // mat4 proj;
|
||||||
|
// mat4 transform = mat4(1.0, 1.0, 1.0, 1.0,
|
||||||
|
// 1.0, 1.0, 1.0, 1.0,
|
||||||
|
// 1.0, 1.0, 1.0, 1.0,
|
||||||
|
// 1.0, 1.0, 1.0, 1.0);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// mat4 transform = mat4(1.0, 1.0, 0.0, 1.0,
|
||||||
|
// 0.0, 1.0, 1.0, 1.0,
|
||||||
|
// 0.0, 0.0, 1.0, 1.0,
|
||||||
|
// 0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
mat4 transform = mat4(1.0);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// gl_Position = proj * view * model * vec4(Position, 0, 1);
|
||||||
|
// gl_Position = vec4(Position, 0, 1);
|
||||||
|
gl_Position = transform * vec4(Position, 0, 1);
|
||||||
|
}";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
160
Source/Rendering/RaylibRenderer.cs
Executable file
160
Source/Rendering/RaylibRenderer.cs
Executable file
@@ -0,0 +1,160 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
using Raylib_cs;
|
||||||
|
|
||||||
|
namespace DaggerFramework.Rendering
|
||||||
|
{
|
||||||
|
public class RaylibRenderer : Renderer
|
||||||
|
{
|
||||||
|
public override Vector2 WindowSize => _windowSize;
|
||||||
|
public override void DrawCircle(float radius, System.Drawing.Color color)
|
||||||
|
{
|
||||||
|
Raylib.DrawCircle((int)_position.X, (int)_position.Y, radius, SystemColorToRaylibColor(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetTransform(Vector2 position, float rotation)
|
||||||
|
{
|
||||||
|
_position = position;
|
||||||
|
_rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CreateWindow(string title, Vector2 size)
|
||||||
|
{
|
||||||
|
Raylib.SetTraceLogLevel(TraceLogLevel.LOG_NONE);
|
||||||
|
_windowSize = size;
|
||||||
|
Raylib.InitWindow((int)_windowSize.X, (int)_windowSize.Y, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetWindowTitle(string title)
|
||||||
|
{
|
||||||
|
Raylib.SetWindowTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetWindowVSync(bool value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetTargetFps(int fps)
|
||||||
|
{
|
||||||
|
Raylib.SetTargetFPS(fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool WindowShouldClose()
|
||||||
|
{
|
||||||
|
return Raylib.WindowShouldClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CloseWindow()
|
||||||
|
{
|
||||||
|
Raylib.CloseWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BeginFrame()
|
||||||
|
{
|
||||||
|
Raylib.BeginDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void EndFrame()
|
||||||
|
{
|
||||||
|
Raylib.EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClearBackground(System.Drawing.Color color)
|
||||||
|
{
|
||||||
|
Raylib.ClearBackground(SystemColorToRaylibColor(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double GetFrameTime()
|
||||||
|
{
|
||||||
|
return (double)Raylib.GetFrameTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Raylib_cs.Color SystemColorToRaylibColor(System.Drawing.Color color)
|
||||||
|
{
|
||||||
|
return new Color { r = color.R, g = color.G, b = color.B, a = color.A };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int LoadTexture(Texture2d texture)
|
||||||
|
{
|
||||||
|
Image image;
|
||||||
|
Texture2D rayTexture;
|
||||||
|
string ext = "png";
|
||||||
|
byte[] extBytes = Encoding.ASCII.GetBytes(ext);
|
||||||
|
|
||||||
|
// TODO: This can cause memory leaks.
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* textureData = texture.Data)
|
||||||
|
{
|
||||||
|
fixed (byte* bExt = extBytes)
|
||||||
|
{
|
||||||
|
sbyte* sbExt = (sbyte*)*bExt;
|
||||||
|
image = Raylib.LoadImageFromMemory(sbExt, textureData, texture.Data.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rayTexture = Raylib.LoadTextureFromImage(image);
|
||||||
|
Raylib.UnloadImage(image);
|
||||||
|
|
||||||
|
_texturePool.Add(rayTexture);
|
||||||
|
|
||||||
|
return _texturePool.Count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int LoadTexture(string path)
|
||||||
|
{
|
||||||
|
Image image = Raylib.LoadImage(path);
|
||||||
|
var rayTexture = Raylib.LoadTextureFromImage(image);
|
||||||
|
Raylib.UnloadImage(image);
|
||||||
|
|
||||||
|
_texturePool.Add(rayTexture);
|
||||||
|
return _texturePool.Count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawTexture(int id, System.Drawing.Color tint)
|
||||||
|
{
|
||||||
|
Raylib.DrawTextureV(_texturePool[id], _position, SystemColorToRaylibColor(tint));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawRectangle(Vector2 size, System.Drawing.Color color)
|
||||||
|
{
|
||||||
|
// Raylib.DrawRectangleV(_position, size, SystemColorToRaylibColor(color));
|
||||||
|
Raylib.DrawRectanglePro(new Rectangle()
|
||||||
|
{
|
||||||
|
x = _position.X,
|
||||||
|
y = _position.Y,
|
||||||
|
width = size.X,
|
||||||
|
height = size.Y
|
||||||
|
}, Vector2.Zero, _rotation, SystemColorToRaylibColor(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawDebugText(Vector2 position, string text, int fontSize, System.Drawing.Color color)
|
||||||
|
{
|
||||||
|
Raylib.DrawText(text, (int)position.X, (int)position.Y, fontSize, SystemColorToRaylibColor(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize(RendererSettings settings)
|
||||||
|
{
|
||||||
|
ConfigFlags flags = 0;
|
||||||
|
|
||||||
|
// MSAA
|
||||||
|
flags |= settings.Msaa == Msaa.Msaa4x ? ConfigFlags.FLAG_MSAA_4X_HINT : 0;
|
||||||
|
|
||||||
|
// VSync
|
||||||
|
flags |= settings.UseVSync ? ConfigFlags.FLAG_VSYNC_HINT : 0;
|
||||||
|
|
||||||
|
// Fullscreen
|
||||||
|
flags |= settings.Fullscreen ? ConfigFlags.FLAG_FULLSCREEN_MODE : 0;
|
||||||
|
Raylib.SetConfigFlags(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
public override void SetTransform(Matrix4x4 transform) { }
|
||||||
|
|
||||||
|
private List<Texture2D> _texturePool = new List<Texture2D>();
|
||||||
|
private Vector2 _position;
|
||||||
|
private float _rotation;
|
||||||
|
private Vector2 _windowSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Source/Rendering/Renderer.cs
Executable file
52
Source/Rendering/Renderer.cs
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace DaggerFramework.Rendering
|
||||||
|
{
|
||||||
|
public abstract class Renderer
|
||||||
|
{
|
||||||
|
// INIT
|
||||||
|
public abstract void Initialize(RendererSettings settings);
|
||||||
|
// WINDOW
|
||||||
|
public abstract Vector2 WindowSize { get; }
|
||||||
|
public abstract void CreateWindow(string title, Vector2 size);
|
||||||
|
public abstract void SetWindowTitle(string title);
|
||||||
|
public abstract void SetWindowVSync(bool value);
|
||||||
|
public abstract void SetTargetFps(int fps);
|
||||||
|
public abstract bool WindowShouldClose();
|
||||||
|
public abstract void CloseWindow();
|
||||||
|
|
||||||
|
// DRAWING
|
||||||
|
public abstract void BeginFrame();
|
||||||
|
public abstract void EndFrame();
|
||||||
|
public abstract void ClearBackground(Color color);
|
||||||
|
public abstract double GetFrameTime();
|
||||||
|
public abstract int LoadTexture(Texture2d texture);
|
||||||
|
/// <summary>
|
||||||
|
/// Temporary workaround for Raylib's LoadImageFromMemory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract int LoadTexture(string path);
|
||||||
|
public abstract void SetTransform(Vector2 position, float rotation = 0.0f);
|
||||||
|
public abstract void SetTransform(Matrix4x4 transform);
|
||||||
|
public abstract void DrawCircle(float radius, Color color);
|
||||||
|
public abstract void DrawRectangle(Vector2 size, Color color);
|
||||||
|
public abstract void DrawDebugText(Vector2 position, string text, int fontSize, Color color);
|
||||||
|
public abstract void DrawTexture(int id, Color tint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Msaa
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Msaa2x,
|
||||||
|
Msaa4x,
|
||||||
|
Msaa8x
|
||||||
|
}
|
||||||
|
public struct RendererSettings
|
||||||
|
{
|
||||||
|
public Msaa Msaa;
|
||||||
|
public bool UseVSync;
|
||||||
|
public bool Fullscreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Source/Rendering/Shader.cs
Executable file
8
Source/Rendering/Shader.cs
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace DaggerFramework.Rendering
|
||||||
|
{
|
||||||
|
public abstract class Shader
|
||||||
|
{
|
||||||
|
public abstract string FragmentSource { get; }
|
||||||
|
public abstract string VertexSource { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
227
Source/Rendering/StandardRenderer.cs
Normal file
227
Source/Rendering/StandardRenderer.cs
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
// using Veldrid;
|
||||||
|
// using Veldrid.Sdl2;
|
||||||
|
// using Veldrid.SPIRV;
|
||||||
|
// using Veldrid.StartupUtilities;
|
||||||
|
|
||||||
|
namespace DaggerFramework.Rendering
|
||||||
|
{
|
||||||
|
// public class StandardRenderer : Renderer
|
||||||
|
// {
|
||||||
|
// public override void BeginFrame()
|
||||||
|
// {
|
||||||
|
// _commandList.Begin();
|
||||||
|
// _commandList.SetFramebuffer(_graphicsDevice.SwapchainFramebuffer);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void ClearBackground(Color color)
|
||||||
|
// {
|
||||||
|
// _commandList.ClearColorTarget(0, SystemColorToRgbaFloat(color));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void CloseWindow()
|
||||||
|
// {
|
||||||
|
// _window.Close();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void CreateWindow(string title, Vector2 size)
|
||||||
|
// {
|
||||||
|
// var windowCreateInfo = new WindowCreateInfo()
|
||||||
|
// {
|
||||||
|
// // TODO: add position property to CreateWindow.
|
||||||
|
// X = (int)size.X / 2,
|
||||||
|
// Y = (int)size.Y / 2,
|
||||||
|
// WindowWidth = (int)size.X,
|
||||||
|
// WindowHeight = (int)size.Y,
|
||||||
|
// WindowTitle = title,
|
||||||
|
|
||||||
|
// };
|
||||||
|
|
||||||
|
// _window = VeldridStartup.CreateWindow(ref windowCreateInfo);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void DrawCircle(float radius, Color color)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void DrawDebugText(Vector2 position, string text, int fontSize, Color color)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void DrawRectangle(Vector2 size, Color color)
|
||||||
|
// {
|
||||||
|
// _commandList.SetVertexBuffer(0, _vertexBuffer);
|
||||||
|
// _commandList.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
|
||||||
|
// _commandList.SetPipeline(_graphicsPipeline);
|
||||||
|
// _commandList.SetGraphicsResourceSet(0, _resourceSet);
|
||||||
|
// _graphicsDevice.UpdateBuffer(_uniformBuffer, 0, SystemColorToRgbaFloat(color));
|
||||||
|
// _commandList.DrawIndexed(indexCount: 4, instanceCount: 1, 0, 0, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void DrawTexture(int id, Color tint)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void EndFrame()
|
||||||
|
// {
|
||||||
|
// _commandList.End();
|
||||||
|
// _graphicsDevice.SubmitCommands(_commandList);
|
||||||
|
// _graphicsDevice.SwapBuffers();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override double GetFrameTime()
|
||||||
|
// {
|
||||||
|
// return 0.16f;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void CreateResources()
|
||||||
|
// {
|
||||||
|
// _resourceFactory = _graphicsDevice.ResourceFactory;
|
||||||
|
// _commandList = _resourceFactory.CreateCommandList();
|
||||||
|
|
||||||
|
// _vertexBuffer = _resourceFactory.CreateBuffer(new BufferDescription(4 * 8, BufferUsage.VertexBuffer));
|
||||||
|
// _indexBuffer = _resourceFactory.CreateBuffer(new BufferDescription(4 * sizeof(ushort), BufferUsage.IndexBuffer));
|
||||||
|
// _uniformBuffer = _resourceFactory.CreateBuffer(new BufferDescription(4 * sizeof(float), BufferUsage.UniformBuffer));
|
||||||
|
|
||||||
|
|
||||||
|
// FillBuffers();
|
||||||
|
// var vertexDesc = new ShaderDescription(ShaderStages.Vertex, Encoding.UTF8.GetBytes(_colorRectShader.VertexSource), "main");
|
||||||
|
// var fragmentDesc = new ShaderDescription(ShaderStages.Fragment, Encoding.UTF8.GetBytes(_colorRectShader.FragmentSource), "main");
|
||||||
|
// _shaders = _resourceFactory.CreateFromSpirv(vertexDesc, fragmentDesc);
|
||||||
|
// CreatePipeline();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void CreatePipeline()
|
||||||
|
// {
|
||||||
|
// VertexLayoutDescription vertexLayout = new VertexLayoutDescription(
|
||||||
|
// new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2));
|
||||||
|
|
||||||
|
// var pipelineDesc = new GraphicsPipelineDescription();
|
||||||
|
// pipelineDesc.BlendState = BlendStateDescription.SingleOverrideBlend;
|
||||||
|
|
||||||
|
// pipelineDesc.RasterizerState = new RasterizerStateDescription(
|
||||||
|
// cullMode: FaceCullMode.Back,
|
||||||
|
// fillMode: PolygonFillMode.Solid,
|
||||||
|
// frontFace: FrontFace.Clockwise,
|
||||||
|
// depthClipEnabled: true,
|
||||||
|
// scissorTestEnabled: false);
|
||||||
|
|
||||||
|
// pipelineDesc.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
|
||||||
|
|
||||||
|
// var layout = _resourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
|
||||||
|
// new ResourceLayoutElementDescription("color", ResourceKind.UniformBuffer, ShaderStages.Fragment)
|
||||||
|
// ));
|
||||||
|
|
||||||
|
// _resourceSet = _resourceFactory.CreateResourceSet(new ResourceSetDescription(layout, _uniformBuffer));
|
||||||
|
|
||||||
|
// pipelineDesc.ResourceLayouts = new ResourceLayout[] { layout };
|
||||||
|
|
||||||
|
// pipelineDesc.ShaderSet = new ShaderSetDescription(vertexLayouts: new VertexLayoutDescription[] { vertexLayout }, _shaders);
|
||||||
|
|
||||||
|
// pipelineDesc.Outputs = _graphicsDevice.SwapchainFramebuffer.OutputDescription;
|
||||||
|
|
||||||
|
// _graphicsPipeline = _resourceFactory.CreateGraphicsPipeline(pipelineDesc);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void FillBuffers()
|
||||||
|
// {
|
||||||
|
// _graphicsDevice.UpdateBuffer(_vertexBuffer, 0, _quadVertices);
|
||||||
|
// _graphicsDevice.UpdateBuffer(_indexBuffer, 0, _quadIndices);
|
||||||
|
// }
|
||||||
|
// public override void Initialize(RendererSettings settings)
|
||||||
|
// {
|
||||||
|
// _settings = settings;
|
||||||
|
// _graphicsDevice = VeldridStartup.CreateGraphicsDevice(_window, new GraphicsDeviceOptions
|
||||||
|
// {
|
||||||
|
// PreferStandardClipSpaceYDirection = true,
|
||||||
|
// PreferDepthRangeZeroToOne = true
|
||||||
|
// });
|
||||||
|
|
||||||
|
// CreateResources();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override int LoadTexture(Texture2d texture)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override int LoadTexture(string path)
|
||||||
|
// {
|
||||||
|
// // throw new NotImplementedException();
|
||||||
|
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetTargetFps(int fps)
|
||||||
|
// {
|
||||||
|
// _window.PollIntervalInMs = 1 / fps;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetTransform(Vector2 position)
|
||||||
|
// {
|
||||||
|
// // throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetWindowTitle(string title)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetWindowVSync(bool value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override bool WindowShouldClose()
|
||||||
|
// {
|
||||||
|
// _window.PumpEvents();
|
||||||
|
// return !_window.Exists;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private RgbaFloat SystemColorToRgbaFloat(System.Drawing.Color color)
|
||||||
|
// {
|
||||||
|
// return new RgbaFloat(color.R, color.G, color.B, color.A);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetTransform(Matrix4x4 transform)
|
||||||
|
// {
|
||||||
|
// _transform = transform;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Transform
|
||||||
|
// private Matrix4x4 _transform;
|
||||||
|
|
||||||
|
// // TEMP: quad stuff.
|
||||||
|
// private readonly Vector2[] _quadVertices =
|
||||||
|
// {
|
||||||
|
// new Vector2(-0.5f, 0.5f),
|
||||||
|
// new Vector2(0.5f, 0.5f),
|
||||||
|
// new Vector2(-0.5f, -0.5f),
|
||||||
|
// new Vector2(0.5f, -0.5f)
|
||||||
|
// };
|
||||||
|
|
||||||
|
// private readonly ushort[] _quadIndices = { 0, 1, 2, 3 };
|
||||||
|
// private ColorRectShader _colorRectShader = new ColorRectShader();
|
||||||
|
|
||||||
|
// private Sdl2Window _window;
|
||||||
|
// private RendererSettings _settings;
|
||||||
|
// private GraphicsDevice _graphicsDevice;
|
||||||
|
|
||||||
|
// // Resources
|
||||||
|
// private ResourceFactory _resourceFactory;
|
||||||
|
// private CommandList _commandList;
|
||||||
|
// private Pipeline _graphicsPipeline;
|
||||||
|
// private Veldrid.Shader[] _shaders;
|
||||||
|
|
||||||
|
// // Quad resources
|
||||||
|
// private DeviceBuffer _vertexBuffer;
|
||||||
|
// private DeviceBuffer _indexBuffer;
|
||||||
|
// private DeviceBuffer _uniformBuffer;
|
||||||
|
// private ResourceSet _resourceSet;
|
||||||
|
// }
|
||||||
|
}
|
||||||
10
Source/Resources/Resource.cs
Executable file
10
Source/Resources/Resource.cs
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public abstract class Resource : IDisposable
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Source/Resources/ResourceLoader.cs
Executable file
7
Source/Resources/ResourceLoader.cs
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class ResourceLoader
|
||||||
|
{
|
||||||
|
public virtual Resource Load(string path) { return default; }
|
||||||
|
}
|
||||||
|
}
|
||||||
87
Source/Resources/ResourceManager.cs
Executable file
87
Source/Resources/ResourceManager.cs
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public static class ResourceManager
|
||||||
|
{
|
||||||
|
public static string ResourceRoot { get; set; } = "Resources/";
|
||||||
|
public static T Load<T>(string relativePath) where T : Resource
|
||||||
|
{
|
||||||
|
var path = GlobalizePath(relativePath);
|
||||||
|
var loader = GetAssociatedResourceLoader<T>();
|
||||||
|
var res = loader.Load(path);
|
||||||
|
res.Path = path;
|
||||||
|
return res as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Load<T>(string name, string relativePath) where T : Resource
|
||||||
|
{
|
||||||
|
T res = null;
|
||||||
|
if (TryGetResourceFromCache<T>(name, out res)) return res as T;
|
||||||
|
|
||||||
|
res = Load<T>(relativePath);
|
||||||
|
AddResourceToCache(name, res);
|
||||||
|
return res as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a list of resources from a folder. Their names will be derived from the actual file name, excluding the extension.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Resource type for all of the resources.</typeparam>
|
||||||
|
/// <param name="localPath">Path to the folder, relative to the ResourceRoot.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static void LoadFolder<T>(string relativePath) where T : Resource
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(GlobalizePath(relativePath));
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
var resName = Path.GetFileNameWithoutExtension(file);
|
||||||
|
var resRelativePath = Path.GetRelativePath(ResourceRoot, file);
|
||||||
|
|
||||||
|
Load<T>(resName, resRelativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Get<T>(string name) where T : Resource
|
||||||
|
{
|
||||||
|
T res = null;
|
||||||
|
if (TryGetResourceFromCache<T>(name, out res)) return res as T;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GlobalizePath(string relativePath)
|
||||||
|
{
|
||||||
|
return Path.Join(ResourceRoot, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddResourceToCache(string name, Resource resource)
|
||||||
|
{
|
||||||
|
_resourceCache.Add(name, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryGetResourceFromCache<T>(string name, out T resource) where T : Resource
|
||||||
|
{
|
||||||
|
resource = null;
|
||||||
|
if (!_resourceCache.ContainsKey(name)) return false;
|
||||||
|
resource = _resourceCache[name] as T;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResourceLoader GetAssociatedResourceLoader<T>() where T : Resource
|
||||||
|
{
|
||||||
|
return _resourceLoaderAssociations[typeof(T)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KeyValuePair<Type, ResourceLoader> CreateResourceAssociation(Type type, ResourceLoader loader)
|
||||||
|
{
|
||||||
|
return new KeyValuePair<Type, ResourceLoader>(type, loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, Resource> _resourceCache = new Dictionary<string, Resource>();
|
||||||
|
private static readonly Dictionary<Type, ResourceLoader> _resourceLoaderAssociations = new Dictionary<Type, ResourceLoader>()
|
||||||
|
{
|
||||||
|
{typeof(Texture2d), new Texture2dLoader()},
|
||||||
|
{typeof(Sound), new SoundLoader()}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Source/Resources/Sound.cs
Normal file
13
Source/Resources/Sound.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Sound : Resource
|
||||||
|
{
|
||||||
|
public float PitchScale { get; set; } = 1.0f;
|
||||||
|
public float Volume { get; set; } = 1.0f;
|
||||||
|
public Sound(byte[] data)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
public byte[] Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Source/Resources/SoundLoader.cs
Normal file
15
Source/Resources/SoundLoader.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class SoundLoader : ResourceLoader
|
||||||
|
{
|
||||||
|
public override Resource Load(string path)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// var data = File.ReadAllBytes(path);
|
||||||
|
var sound = new Sound(null);
|
||||||
|
sound.Path = path;
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Source/Resources/Texture2d.cs
Executable file
11
Source/Resources/Texture2d.cs
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Texture2d : Resource
|
||||||
|
{
|
||||||
|
public Texture2d(byte[] data)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
public byte[] Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Source/Resources/Texture2dLoader.cs
Executable file
14
Source/Resources/Texture2dLoader.cs
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Texture2dLoader : ResourceLoader
|
||||||
|
{
|
||||||
|
public override Resource Load(string path)
|
||||||
|
{
|
||||||
|
var data = File.ReadAllBytes(path);
|
||||||
|
var texture = new Texture2d(data);
|
||||||
|
texture.Path = path;
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
82
Source/Scene.cs
Executable file
82
Source/Scene.cs
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
using DaggerFramework.Audio;
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class Scene : IMainLoop
|
||||||
|
{
|
||||||
|
public Renderer Renderer { get => _renderer; set => _renderer = value; }
|
||||||
|
public InputHandler Input { get => _input; set => _input = value; }
|
||||||
|
public AudioBackend Audio => _audioBackend;
|
||||||
|
|
||||||
|
public double DeltaTime => Renderer.GetFrameTime();
|
||||||
|
|
||||||
|
public Scene(Renderer renderer, InputHandler input, AudioBackend audioBackend)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
_input = input;
|
||||||
|
_audioBackend = audioBackend;
|
||||||
|
_layers = new Dictionary<string, Layer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scene(Renderer renderer)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init() => SetupRenderer();
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
foreach (var layer in _layers.Values)
|
||||||
|
{
|
||||||
|
layer.Input = _input;
|
||||||
|
layer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
foreach (var layer in _layers)
|
||||||
|
{
|
||||||
|
layer.Value.Update(DeltaTime);
|
||||||
|
}
|
||||||
|
Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddLayer(string name, Layer layer)
|
||||||
|
{
|
||||||
|
layer.Scene = this;
|
||||||
|
_layers.Add(name, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShouldStop() => Renderer.WindowShouldClose();
|
||||||
|
|
||||||
|
private void Draw()
|
||||||
|
{
|
||||||
|
Renderer.BeginFrame();
|
||||||
|
Renderer.ClearBackground(Color.Black);
|
||||||
|
foreach (var layer in _layers.Values)
|
||||||
|
{
|
||||||
|
layer.Draw(ref _renderer);
|
||||||
|
}
|
||||||
|
Renderer.EndFrame();
|
||||||
|
|
||||||
|
Audio.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupRenderer()
|
||||||
|
{
|
||||||
|
Renderer.CreateWindow("RogueMine", new Vector2(1280, 720));
|
||||||
|
Renderer.Initialize(new RendererSettings { Msaa = Msaa.Msaa4x, UseVSync = true });
|
||||||
|
Renderer.SetTargetFps(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, Layer> _layers;
|
||||||
|
private Renderer _renderer;
|
||||||
|
private AudioBackend _audioBackend;
|
||||||
|
private InputHandler _input;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Source/UiLayer.cs
Executable file
24
Source/UiLayer.cs
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
using DaggerFramework.Rendering;
|
||||||
|
|
||||||
|
namespace DaggerFramework
|
||||||
|
{
|
||||||
|
public class UiLayer : Layer
|
||||||
|
{
|
||||||
|
protected override void OnUpdate(double dt)
|
||||||
|
{
|
||||||
|
base.OnUpdate(dt);
|
||||||
|
_time += dt;
|
||||||
|
}
|
||||||
|
protected override void OnDraw(ref Renderer renderer)
|
||||||
|
{
|
||||||
|
renderer.SetTransform(Vector2.Zero);
|
||||||
|
renderer.DrawRectangle(new Vector2(720 / 2, 1280), Color.Green);
|
||||||
|
renderer.DrawDebugText(new Vector2(720 / 4 - 24, 64), "UI :)", 24, Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _time;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
TODO.md
Executable file
28
TODO.md
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
# RogueMine
|
||||||
|
## Engine
|
||||||
|
### Rendering
|
||||||
|
- ~~API for drawing textured quads~~
|
||||||
|
- Switch to custom rendering (Veldrid?)
|
||||||
|
|
||||||
|
### Audio
|
||||||
|
- 2D audio abstraction
|
||||||
|
- Integrate FMOD
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- ~~Asset manager~~
|
||||||
|
- Separate engine and game into separate projects
|
||||||
|
- Switch to GlmSharp
|
||||||
|
- Particle system
|
||||||
|
|
||||||
|
### Entity system
|
||||||
|
- ~~Layers (sorting mechanism)~~
|
||||||
|
|
||||||
|
## Input
|
||||||
|
- ~~Action system~~
|
||||||
|
|
||||||
|
### UI
|
||||||
|
- Basic containers
|
||||||
|
- MarginContainer
|
||||||
|
- XML layout file
|
||||||
|
- Interaction
|
||||||
|
- Callbacks
|
||||||
Reference in New Issue
Block a user