Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development #27

Merged
merged 20 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d33c620
feat: Add base particle system component.
thiagomvas Jun 15, 2024
3615e2a
feat: Add RaylibParticleSystem component
thiagomvas Jun 15, 2024
4298aa7
Add Particle.Scale and Particle.Color prroperties
thiagomvas Jun 15, 2024
3ffb29a
Modify particle reset to use custom default
thiagomvas Jun 15, 2024
3032088
Modify system to use models instead of sphere
thiagomvas Jun 15, 2024
7acdade
feat: Add System.Drawing.Color.ToRaylibColor() extension method
thiagomvas Jun 15, 2024
0c06bca
docs: Add documentation for changes so far
thiagomvas Jun 15, 2024
0099ea8
feat: Add CameraControllerBase<T> generic class
thiagomvas Jun 15, 2024
2568b60
feat: Add base Raylib camera controller class
thiagomvas Jun 15, 2024
57c6f74
feat: Add First Person camera controller class
thiagomvas Jun 15, 2024
7ec5323
feat: RaylibGraphicsEngine updated to support new camera system.
thiagomvas Jun 15, 2024
0cd2cab
feat: CameraController can now be changed for RaylibGraphicsEngine
thiagomvas Jun 15, 2024
5e5db23
docs: Add XML doc comments
thiagomvas Jun 15, 2024
6b1d15a
feat: Add Entity.Clone() and Entity.Create()
thiagomvas Jun 15, 2024
0aa34fb
fix: OnCollision no longer called when entity is destroyed.
thiagomvas Jun 17, 2024
b2cd357
remove misspelling
thiagomvas Jun 17, 2024
32de895
fix: InvalidResourceKeyException now contains the param name and valu…
thiagomvas Jun 18, 2024
00bc197
feat: Particle Systems can be looping or have limited emission duration.
thiagomvas Jun 18, 2024
7c4d854
chore: Clean up
thiagomvas Jun 18, 2024
8189013
chore(release): 1.9.0
thiagomvas Jun 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Basalt.Core/Basalt.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.8.1</Version>
<Version>1.9.0</Version>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageIcon>BasaltLogoBg.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand Down
2 changes: 1 addition & 1 deletion Basalt.Raylib/Basalt.Raylib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.8.1</Version>
<Version>1.9.0</Version>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageIcon>BasaltLogoBg.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand Down
45 changes: 45 additions & 0 deletions Basalt.Raylib/Components/FirstPersonCameraController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Basalt.Common.Entities;
using Basalt.Math;
using System.Numerics;
using static Raylib_cs.Raylib;

namespace Basalt.Raylib.Components
{
/// <summary>
/// Represents a first-person camera controller for Raylib.
/// </summary>
public class FirstPersonCameraController : RayCameraController
{
/// <summary>
/// The sensitivity of the camera controller.
/// </summary>
public float Sensitivity = 0.1f;

/// <summary>
/// Initializes a new instance of the <see cref="FirstPersonCameraController"/> class.
/// </summary>
/// <param name="entity">The entity associated with the camera controller.</param>
public FirstPersonCameraController(Entity entity) : base(entity)
{
}

public override void OnUpdate()
{
if (!Enabled)
return;

Vector3 rotation = new(GetMouseDelta().X * Sensitivity, // Rotation: yaw
GetMouseDelta().Y * Sensitivity, // Rotation: pitch
0.0f); // Rotation: roll

// Update the camera in raylib

camera.Position = Entity.Transform.Position;
camera.Target = camera.Position + Entity.Transform.Forward;

UpdateCameraPro(ref camera, Vector3.Zero, rotation, 0);

Entity.Transform.Rotation = BasaltMath.LookAtRotation(camera.Position, camera.Target, camera.Up);
}
}
}
2 changes: 1 addition & 1 deletion Basalt.Raylib/Components/Image.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using Basalt.Common.Utils;
using Basalt.Raylib.Graphics;
using Raylib_cs;
using static Raylib_cs.Raylib;
using System.Numerics;
using static Raylib_cs.Raylib;

namespace Basalt.Raylib.Components
{
Expand Down
2 changes: 1 addition & 1 deletion Basalt.Raylib/Components/ModelRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public override unsafe void OnRender()
cube = ResourceCache.Instance.GetModel(ModelCacheKey)!.Value;
else
{
throw new InvalidResourceKeyException(nameof(ModelCacheKey));
throw new InvalidResourceKeyException(nameof(ModelCacheKey), ModelCacheKey);
}
init = true;
}
Expand Down
39 changes: 39 additions & 0 deletions Basalt.Raylib/Components/RayCameraController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Basalt.Common.Components;
using Basalt.Common.Entities;
using Raylib_cs;
using System.Numerics;

namespace Basalt.Raylib.Components
{
/// <summary>
/// Represents a camera controller for Raylib using Camera3D.
/// </summary>
public class RayCameraController : CameraControllerBase<Camera3D>
{
/// <summary>
/// Initializes a new instance of the <see cref="RayCameraController"/> class.
/// </summary>
/// <param name="entity">The entity associated with the camera controller.</param>
public RayCameraController(Entity entity) : base(entity)
{
Camera = new Camera3D
{
Position = Entity.Transform.Position,
Target = Entity.Transform.Position + Entity.Transform.Forward,
Up = new Vector3(0f, 1f, 0f),
FovY = 60f,
Projection = CameraProjection.Perspective
};

// Set the camera as the active camera in raylib
Raylib_cs.Raylib.UpdateCamera(ref camera, CameraMode.FirstPerson);
}

protected Camera3D camera;

/// <summary>
/// Gets or sets the camera.
/// </summary>
public override Camera3D Camera { get => camera; set => camera = value; }
}
}
55 changes: 55 additions & 0 deletions Basalt.Raylib/Components/RaylibParticleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Basalt.Common.Components;
using Basalt.Common.Entities;
using Basalt.Common.Exceptions;
using Basalt.Common.Utils;
using Basalt.Raylib.Graphics;
using Raylib_cs;
using System.Numerics;

namespace Basalt.Raylib.Components
{
/// <summary>
/// A particle system that renders particles using Raylib.
/// </summary>
public class RaylibParticleSystem : BaseParticleSystem
{
private string _modelCacheKey = "sphere";
/// <summary>
/// The <see cref="ResourceCache"/> cache key for the model to use for rendering particles.
/// </summary>
public string ModelCacheKey
{
get => _modelCacheKey;
set
{
_modelCacheKey = value;
init = false;
}
}
bool init = false;
Model model;
public RaylibParticleSystem(Entity entity) : base(entity)
{
}

protected override void RenderParticles()
{
if (!init)
{
init = true;
var m = ResourceCache.Instance.GetModel(ModelCacheKey);
if (m == null)
{
throw new InvalidResourceKeyException(nameof(ModelCacheKey), ModelCacheKey);
}
model = m.Value;

}
foreach (var particle in _particles)
{
model.Transform = Raymath.MatrixRotateXYZ(Raymath.QuaternionToEuler(particle.Rotation));
Raylib_cs.Raylib.DrawModelEx(model, particle.Position, Vector3.UnitY, 0, particle.Scale, particle.Color.ToRaylibColor());
}
}
}
}
8 changes: 8 additions & 0 deletions Basalt.Raylib/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,13 @@ public static EngineBuilder UseRaylibPreset(this EngineBuilder builder, WindowIn
builder.AddComponent<ISoundSystem, RaylibSoundSystem>();
return builder;
}


/// <summary>
/// Converts a <see cref="System.Drawing.Color"/> to a <see cref="Raylib_cs.Color"/>.
/// </summary>
/// <param name="color">The color to be converted to a raylib color type</param>
/// <returns>The original color as a <see cref="Raylib_cs.Color"/></returns>
public static Raylib_cs.Color ToRaylibColor(this System.Drawing.Color color) => new(color.R, color.G, color.B, color.A);
}
}
28 changes: 18 additions & 10 deletions Basalt.Raylib/Graphics/RaylibGraphicsEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class RaylibGraphicsEngine : IGraphicsEngine
private EntityManager entityManager;
private ISoundSystem? soundSystem;
private IEventBus eventBus;
private RayCameraController? cameraController;

Shader PostProcessShader, LightShader;
bool ShouldRun = true;
Expand Down Expand Up @@ -107,14 +108,19 @@ public unsafe void Initialize()
public unsafe void Render()
{
Camera3D camera = new();
var control = entityManager.GetEntities().FirstOrDefault(e => e.GetComponent<CameraController>() != null)?.GetComponent<CameraController>() ?? null;
var control = Engine.Instance.EntityManager.GetEntities().FirstOrDefault(e => e.GetComponents().FirstOrDefault(c => c.GetType().IsSubclassOf(typeof(RayCameraController))) is not null);
if (control == null)
{
throw new NullReferenceException("No camera controller found in the scene.");
Engine.Instance.Logger?.LogError("No camera controller found. Using default controller instead.");
var entity = new Entity();
entity.AddComponent(new FirstPersonCameraController(entity));
Engine.CreateEntity(entity);
cameraController = entity.GetComponent<FirstPersonCameraController>()!;
control = entity;
}

camera = control!.camera;
control.OnStart();
else
cameraController = control!.GetComponents().FirstOrDefault(c => c.GetType().IsSubclassOf(typeof(RayCameraController))) as RayCameraController;
camera = cameraController!.Camera;

RenderTexture2D target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());

Expand All @@ -140,7 +146,6 @@ public unsafe void Render()
// Main game loop
while (ShouldRun)
{
control.OnUpdate();
Time.DeltaTime = GetFrameTime();


Expand Down Expand Up @@ -173,7 +178,7 @@ public unsafe void Render()
foreach (var source in sources)
Rlights.UpdateLightValues(LightShader, source.Source);

SetShaderValue(LightShader, LightShader.Locs[(int)ShaderLocationIndex.VectorView], control.Entity.Transform.Position, ShaderUniformDataType.Vec3);
SetShaderValue(LightShader, LightShader.Locs[(int)ShaderLocationIndex.VectorView], cameraController.Entity.Transform.Position, ShaderUniformDataType.Vec3);
}

//----------------------------------------------------------------------------------
Expand All @@ -184,7 +189,7 @@ public unsafe void Render()
BeginTextureMode(target);
ClearBackground(Color.Black);

BeginMode3D(control.camera);
BeginMode3D(cameraController.Camera);

eventBus?.TriggerEvent(BasaltConstants.RenderEventKey);

Expand Down Expand Up @@ -259,13 +264,16 @@ public static T InvokeOnThread<T>(Func<T> delegateFunc)

private T invoke<T>(Func<T> delegateFunc) => delegateFunc();



public void Shutdown()
{
ShouldRun = false;
ResourceCache.Instance.UnloadRaylib();
logger?.LogWarning("Shutting down graphics engine...");
}

public void SetCameraController(RayCameraController newController)
{
cameraController = newController;
}
}
}
4 changes: 2 additions & 2 deletions Basalt.Raylib/Sound/RaylibSoundSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void Initialize()

private void UpdateStream(object? sender, EventArgs args)
{
if(MusicPlaying is not null)
if (MusicPlaying is not null)
{
UpdateMusicStream(MusicPlaying.Value);
}
Expand All @@ -49,7 +49,7 @@ public void Shutdown()
/// </summary>
/// <param name="logger">The logger to use for logging.</param>
public RaylibSoundSystem()
{
{
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions Basalt.TestField/Basalt.TestField.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 0 additions & 2 deletions Basalt.TestField/Components/DebugInfo.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Basalt.Common;
using Basalt.Common.Components;
using Basalt.Common.Entities;
using Raylib_cs;
using System.Diagnostics;
using static Raylib_cs.Raylib;

namespace Basalt.TestField.Components
Expand Down
2 changes: 1 addition & 1 deletion Basalt.TestField/Components/TestTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public TestTrigger(Entity entity) : base(entity)

public override void OnCollision(Collider other)
{
if(other.Entity.Id == "entity.player")
if (other.Entity.Id == "entity.player")
{
Console.WriteLine($"Trigger collided with {other.Entity.Id}");
Entity.GetComponent<ModelRenderer>().ModelCacheKey = "sphere";
Expand Down
24 changes: 14 additions & 10 deletions Basalt.TestField/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using Basalt.Raylib.Sound;
using Basalt.Raylib.Utils;
using Basalt.TestField;
using Basalt.TestField.Components;
using Basalt.Types;
using Raylib_cs;
using System.Numerics;
Expand Down Expand Up @@ -54,7 +53,7 @@


var player = new Entity();
player.AddComponent(new CameraController(player));
player.AddComponent(new FirstPersonCameraController(player));
player.Id = "entity.player";
Vector3 offset = Vector3.UnitY * -1;
player.Transform.Position = new Vector3(0, 5, 0);
Expand All @@ -66,15 +65,20 @@

Engine.CreateEntity(player);

var trigger = new Entity();
trigger.Id = "entity.trigger";
trigger.Transform.Position = new Vector3(10, 2.5f, 0);
trigger.AddComponent(new BoxCollider(trigger) { Size = new Vector3(5), IsTrigger = true });
trigger.AddComponent(new ModelRenderer(trigger) { ModelCacheKey = "cube", Size = new Vector3(5), ColorTint = Color.Blue });
trigger.AddComponent(new Rigidbody(trigger) { IsKinematic = true });
trigger.AddComponent(new TestTrigger(trigger));
Engine.CreateEntity(trigger);
var emitter = new Entity();
emitter.Transform.Position = new Vector3(0, 10, 0);
emitter.AddComponent(new RaylibParticleSystem(emitter) { ModelCacheKey = "cube" });
Engine.CreateEntity(emitter);

var ps = emitter.GetComponent<RaylibParticleSystem>()!;

ps.SubscribeOnParticleReset((ref Particle p) =>
{
p.Velocity = new(Random.Shared.NextSingle() * 10 - 5, Random.Shared.NextSingle() * 10 - 5, Random.Shared.NextSingle() * 10 - 5);
// Apply random rotation
p.Rotation = Quaternion.CreateFromYawPitchRoll(Random.Shared.NextSingle() * MathF.PI * 2, Random.Shared.NextSingle() * MathF.PI * 2, Random.Shared.NextSingle() * MathF.PI * 2);

});

TestingUtils.SetupTestingScene(250);
TestingUtils.SetupDebugInfo();
2 changes: 0 additions & 2 deletions Basalt.Tests/CircularBufferTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Basalt.Utility;
using NUnit.Framework;
using System;

namespace Basalt.Tests
{
Expand Down
11 changes: 9 additions & 2 deletions Basalt.Tests/Common/TestComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ public Entity? Target
}
}
}
public bool HasStarted;
public int OnStartCount = 0, OnUpdateCount = 0, OnRenderCount = 0, OnPhysicsUpdateCount = 0;
public bool HasStarted {get; set;}
public int OnStartCount { get; set; } = 0;
public int OnUpdateCount { get; set; } = 0;
public int OnRenderCount {get; set;} = 0;
public int OnPhysicsUpdateCount { get; set;} = 0;
public int Foo { get; private set; } = 0;
public override void OnStart()
{
HasStarted = true;
Expand All @@ -57,5 +61,8 @@ public override void OnPhysicsUpdate()
OnPhysicsUpdateCount++;
}

public int Get() => Foo;
public void Set(int value) => Foo = value;

}
}
Loading
Loading