Awperative Completely Reworked!

This commit is contained in:
2026-02-12 16:47:42 -05:00
parent 8bfc8437dc
commit fd4c07844b
25 changed files with 106 additions and 576 deletions

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
@@ -11,16 +12,19 @@ namespace Awperative;
/// Anything that inherits Component is built to work in any DockerEntity, which leads to generic /// Anything that inherits Component is built to work in any DockerEntity, which leads to generic
/// Assumptions. If you want to make a body specific or scene specific component both classes are available. /// Assumptions. If you want to make a body specific or scene specific component both classes are available.
/// </summary> /// </summary>
public abstract partial class Component : DockerEntity public abstract partial class Behavior : Docker
{ {
internal DockerEntity Docker; internal Docker Docker;
public Scene Scene;
public List<Behavior> Parents { get; private set; }
//todo tags order and singleton
internal virtual void Initiate(Docker docker) {
Docker = docker;
internal virtual void Initiate(DockerEntity __docker) {
Docker = __docker;
Create(); Create();
} }

View File

@@ -0,0 +1,23 @@
using System;
namespace Awperative;
public abstract partial class Docker
{
public Behavior Add<Generic>() where Generic : Behavior => Add<Generic>([]);
public Behavior Add<Generic>(object[] __args) where Generic : Behavior {
if(typeof(Generic).GetConstructor((Type[]) __args) == null) { Debug.LogError("Component does not contain a valid constructor"); return null; };
try {
Behavior behavior = (Generic)Activator.CreateInstance(typeof(Generic), __args);
if(behavior == null) { Debug.LogError("Failed to create component"); return null; }
_components.Add(behavior);
behavior.Initiate(this);
return behavior;
}catch { Debug.LogError("Failed to create component"); return null; }
}
}

View File

@@ -8,9 +8,7 @@ namespace Awperative;
/// <summary> /// <summary>
/// Base class for all Awperative entities, manages components as a requirement because that is the job of all entities. /// Base class for all Awperative entities, manages components as a requirement because that is the job of all entities.
/// </summary> /// </summary>
public abstract partial class DockerEntity public abstract partial class Docker
{ {
public Scene Scene; internal HashSet<Behavior> _components;
internal HashSet<Component> _components;
} }

View File

@@ -3,13 +3,13 @@ using System.Collections.Generic;
namespace Awperative; namespace Awperative;
public abstract partial class DockerEntity public abstract partial class Docker
{ {
public Component GetComponent<Generic>() where Generic : Component => GetComponents<Generic>()[0]; public Behavior Get<Generic>() where Generic : Behavior => GetAll<Generic>()[0];
public Component[] GetComponents<Generic>() where Generic : Component { public Behavior[] GetAll<Generic>() where Generic : Behavior {
List<Component> returnValue = []; List<Behavior> returnValue = [];
foreach (Component component in _components) foreach (Behavior component in _components)
if (component is Generic) returnValue.Add(component); if (component is Generic) returnValue.Add(component);
if(returnValue.Count == 0) { Debug.LogWarning("Scene has no components of this type"); return null; } if(returnValue.Count == 0) { Debug.LogWarning("Scene has no components of this type"); return null; }

View File

@@ -0,0 +1,31 @@
namespace Awperative;
public abstract partial class Docker
{
public void Remove(Behavior behavior) {
if(!_components.Contains(behavior)) { Debug.LogError("Body does not have a component of this type"); return; }
behavior.End();
_components.Remove(behavior);
}
public void Remove<Generic>() where Generic : Behavior {
try
{
Behavior foundBehavior = Get<Generic>();
foundBehavior.End();
_components.Remove(foundBehavior);
}catch { Debug.LogError("Removal failed"); }
}
public void RemoveAll<Generic>() where Generic : Behavior {
try {
foreach (Behavior component in GetAll<Generic>()) {
component.End();
_components.Remove(component);
}
}catch { Debug.LogError("Removal failed"); }
}
}

View File

@@ -0,0 +1,19 @@
using Microsoft.Xna.Framework;
namespace Awperative;
public abstract partial class Docker
{
internal virtual void ChainUnload() { foreach (Behavior component in _components) component.Unload(); }
internal virtual void ChainLoad() { foreach (Behavior component in _components) { component.Load(); } }
internal virtual void ChainUpdate(GameTime __gameTime) { foreach (Behavior component in _components) { component.Update(__gameTime); } }
internal virtual void ChainDraw(GameTime __gameTime) { foreach (Behavior component in _components) { component.Draw(__gameTime); } }
internal virtual void ChainDestroy() { foreach(Behavior component in _components) component.Destroy(); }
internal virtual void ChainCreate() { foreach (Behavior component in _components) component.Create(); }
}

View File

@@ -1,96 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
namespace Awperative;
public sealed partial class Body : DockerEntity
{
/// <summary>
/// Current scene the body exists in
/// </summary>
public Scene Scene { get; internal set; }
/// <summary>
/// All components attached to the body
/// </summary>
public List<Component> Components => _components.ToList();
internal HashSet<Component> _components { get; private set; } = [];
/// <summary>
/// All tags attached to the body
/// </summary>
public List<string> Tags => _tags.ToList();
internal HashSet<string> _tags { get; private set; }= [];
/// <summary>
/// Position of the body
/// </summary>
public Transform transform { get; internal set; } = new();
//Prevents outside construction
internal Body() {}
/// <summary>
/// Creates a body in the given scene
/// </summary>
/// <param name="__scene"></param>
internal Body(Scene __scene) {
Scene = __scene;
}
/// <summary>
/// Creates a body with a scene and transform
/// </summary>
/// <param name="__scene"></param>
/// <param name="__transform"></param>
internal Body(Scene __scene, Transform __transform) {
Scene = __scene;
transform = __transform;
}
internal void Unload() { foreach (Component component in _components) component.Unload(); }
internal void Load() { foreach (Component component in _components) { component.Load(); } }
internal void Update(GameTime __gameTime) { foreach (Component component in _components) { component.Update(__gameTime); } }
internal void Draw(GameTime __gameTime) { foreach (Component component in _components) { component.Draw(__gameTime); } }
internal void Destroy() { foreach(Component component in _components) component.Destroy(); }
internal void Create() { foreach (Component component in _components) component.Create(); }
}

View File

@@ -1,23 +0,0 @@
using System;
namespace Awperative;
public abstract partial class DockerEntity
{
public Component AddComponent<Generic>() where Generic : Component => AddComponent<Generic>([]);
public Component AddComponent<Generic>(object[] __args) where Generic : Component {
if(typeof(Generic).GetConstructor((Type[]) __args) == null) { Debug.LogError("Component does not contain a valid constructor"); return null; };
try {
Component component = (Generic)Activator.CreateInstance(typeof(Generic), __args);
if(component == null) { Debug.LogError("Failed to create component"); return null; }
_components.Add(component);
component.Initiate(this);
return component;
}catch { Debug.LogError("Failed to create component"); return null; }
}
}

View File

@@ -1,31 +0,0 @@
namespace Awperative;
public abstract partial class DockerEntity
{
public void RemoveComponent(Component __component) {
if(!_components.Contains(__component)) { Debug.LogError("Body does not have a component of this type"); return; }
__component.End();
_components.Remove(__component);
}
public void RemoveComponent<Generic>() where Generic : Component {
try
{
Component foundComponent = GetComponent<Generic>();
foundComponent.End();
_components.Remove(foundComponent);
}catch { Debug.LogError("Removal failed"); }
}
public void RemoveComponents<Generic>() where Generic : Component {
try {
foreach (Component component in GetComponents<Generic>()) {
component.End();
_components.Remove(component);
}
}catch { Debug.LogError("Removal failed"); }
}
}

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
namespace Awperative;
public sealed partial class Scene : DockerEntity
{
public Body AddBody(Transform __transform) {
Body body = new Body(this, __transform);
bodies.Add(body);
body.Create();
BodyCreatedEvent?.Invoke(this, new BodyCreateEvent(body, this));
return body;
}
public Body AddBody() {
Body body = new Body(this, new Transform());
bodies.Add(body);
body.Create();
BodyCreatedEvent?.Invoke(this, new BodyCreateEvent(body, this));
return body;
}
public Body[] GetBodies(string tag) {
List<Body> _bodies = new List<Body>();
foreach (Body body in bodies)
if (body._tags.Contains(tag))
_bodies.Add(body);
if(_bodies.Count == 0)
throw new Exception("No Bodies found with the tag " + tag);
return _bodies.ToArray();
}
public Body GetBody(string tag) {
foreach (Body body in bodies)
if (body._tags.Contains(tag))
return body;
throw new Exception("No Body found with the tag " + tag);
}
public void DestroyBody(Body __body) {
__body.Destroy();
BodyDestroyedEvent?.Invoke(this, new BodyDestroyEvent(__body, this));
if (!bodies.Remove(__body))
throw new Exception("Removal Failed! Does the Body Exist?");
}
//todo: add destroying and creating bodies with tags
//TAG SYSTEM IN V4
}

View File

@@ -1,35 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
namespace Awperative;
public sealed partial class Scene : DockerEntity
{
public List<Body> bodies { get; private set; } = [];
public void Unload() {
foreach (Component component in _components) component.Unload();
foreach (Body body in bodies.ToList()) body.Unload();
}
public void Load() {
foreach (Component component in _components) component.Load();
foreach (Body body in bodies.ToList()) { body.Load(); }
}
public void Update(GameTime __gameTime) {
foreach (Component component in _components) component.Update(__gameTime);
foreach (Body body in bodies.ToList()) { body.Update(__gameTime); }
}
public void Draw(GameTime __gameTime) {
foreach (Component component in _components) component.Draw(__gameTime);
foreach (Body body in bodies.ToList()) { body.Draw(__gameTime); }
}
//todo: add scene.destroy in v5
}

View File

@@ -1,12 +0,0 @@
using System;
namespace Awperative;
public sealed partial class Scene : DockerEntity
{
public event EventHandler<BodyCreateEvent> BodyCreatedEvent;
public event EventHandler<BodyDestroyEvent> BodyDestroyedEvent;
}

View File

@@ -1,15 +0,0 @@
namespace Awperative;
public sealed record BodyCreateEvent
{
public readonly Body body;
public readonly Scene scene;
internal BodyCreateEvent() {}
internal BodyCreateEvent(Body __body, Scene __scene)
{
body = __body;
scene = __scene;
}
}

View File

@@ -1,15 +0,0 @@
namespace Awperative;
public sealed record BodyDestroyEvent
{
public readonly Body body;
public readonly Scene scene;
internal BodyDestroyEvent() {}
internal BodyDestroyEvent(Body __body, Scene __scene)
{
body = __body;
scene = __scene;
}
}

View File

@@ -1,17 +0,0 @@
namespace Awperative;
public sealed record ComponentCreateEvent
{
public readonly Component component;
public readonly Body body;
public readonly Scene scene;
internal ComponentCreateEvent() {}
internal ComponentCreateEvent(Component __component, Body __body, Scene __scene)
{
component = __component;
body = __body;
scene = __scene;
}
}

View File

@@ -1,17 +0,0 @@
namespace Awperative;
public sealed record ComponentDestroyEvent
{
public readonly Component component;
public readonly Body body;
public readonly Scene scene;
internal ComponentDestroyEvent() {}
internal ComponentDestroyEvent(Component __component, Body __body, Scene __scene)
{
component = __component;
body = __body;
scene = __scene;
}
}

View File

@@ -1,14 +0,0 @@
namespace Awperative;
public sealed record SceneCreateEvent
{
public Scene scene;
internal SceneCreateEvent() {}
internal SceneCreateEvent(Scene __scene)
{
scene = __scene;
}
}

View File

@@ -1,14 +0,0 @@
namespace Awperative;
public sealed record SceneDestroyEvent
{
public Scene scene;
internal SceneDestroyEvent() {}
internal SceneDestroyEvent(Scene __scene)
{
scene = __scene;
}
}

View File

@@ -1,60 +0,0 @@
using Microsoft.Xna.Framework;
namespace Awperative;
public sealed record TransformModifyEvent
{
public readonly Transform before;
public readonly Transform after;
internal TransformModifyEvent() {}
internal TransformModifyEvent(Transform __before, Transform __after)
{
before = __before;
after = __after;
}
internal static TransformModifyEvent FromTransforms(Transform __previous, Transform __after)
{
Transform before = __previous;
Transform after = new Transform(__after.Origin, __after.Position, __after.Depth, __after.Rotation, __after.Scale);
return new TransformModifyEvent(before, after);
}
internal static TransformModifyEvent FromOrigin(Transform __previous, Vector2 __origin)
{
Transform before = __previous;
Transform after = new Transform(__origin, __previous.Position, __previous.Depth, __previous.Rotation, __previous.Scale);
return new TransformModifyEvent(before, after);
}
internal static TransformModifyEvent FromPosition(Transform __previous, Vector2 __position)
{
Transform before = __previous;
Transform after = new Transform(__previous.Origin, __position, __previous.Depth, __previous.Rotation, __previous.Scale);
return new TransformModifyEvent(before, after);
}
internal static TransformModifyEvent FromDepth(Transform __previous, float __depth)
{
Transform before = __previous;
Transform after = new Transform(__previous.Origin, __previous.Position, __depth, __previous.Rotation, __previous.Scale);
return new TransformModifyEvent(before, after);
}
internal static TransformModifyEvent FromRotation(Transform __previous, float __rotation)
{
Transform before = __previous;
Transform after = new Transform(__previous.Origin, __previous.Position, __previous.Depth, __rotation, __previous.Scale);
return new TransformModifyEvent(before, after);
}
internal static TransformModifyEvent FromScale(Transform __previous, Vector2 __scale)
{
Transform before = __previous;
Transform after = new Transform(__previous.Origin, __previous.Position, __previous.Depth, __previous.Rotation, __scale);
return new TransformModifyEvent(before, after);
}
}

View File

@@ -46,7 +46,7 @@ public sealed class Base : Game
/// <remarks> It is recommended to load content during LoadContent()</remarks> /// <remarks> It is recommended to load content during LoadContent()</remarks>
protected override void LoadContent() { protected override void LoadContent() {
foreach (AwperativeHook hook in Awperative.EventHooks.ToList()) hook.Load(); foreach (AwperativeHook hook in Awperative.EventHooks.ToList()) hook.Load();
foreach(Scene scene in Awperative.LoadedScenes.ToList()) scene.Load(); foreach(Scene scene in Awperative.LoadedScenes.ToList()) scene.ChainLoad();
} }
@@ -58,7 +58,7 @@ public sealed class Base : Game
/// </summary> /// </summary>
/// <remarks> Hooks are unable to receive both Update() and Draw()</remarks> /// <remarks> Hooks are unable to receive both Update() and Draw()</remarks>
protected override void Update(GameTime __gameTime) { protected override void Update(GameTime __gameTime) {
foreach(Scene scene in Awperative.LoadedScenes.ToList()) scene.Update(__gameTime); foreach(Scene scene in Awperative.LoadedScenes.ToList()) scene.ChainUpdate(__gameTime);
base.Update(__gameTime); base.Update(__gameTime);
} }
@@ -71,7 +71,7 @@ public sealed class Base : Game
/// </summary> /// </summary>
/// <remarks> Hooks are unable to receive both Update() and Draw()</remarks> /// <remarks> Hooks are unable to receive both Update() and Draw()</remarks>
protected override void Draw(GameTime __gameTime) { protected override void Draw(GameTime __gameTime) {
foreach(Scene scene in Awperative.LoadedScenes.ToList()) scene.Draw(__gameTime); foreach(Scene scene in Awperative.LoadedScenes.ToList()) scene.ChainDraw(__gameTime);
base.Draw(__gameTime); base.Draw(__gameTime);
} }
@@ -85,7 +85,7 @@ public sealed class Base : Game
/// <remarks> This event may not trigger if the program is force closed.</remarks> /// <remarks> This event may not trigger if the program is force closed.</remarks>
protected override void EndRun() { protected override void EndRun() {
foreach (AwperativeHook hook in Awperative.EventHooks.ToList()) hook.Unload(); foreach (AwperativeHook hook in Awperative.EventHooks.ToList()) hook.Unload();
foreach (Scene scene in Awperative.LoadedScenes.ToList()) scene.Unload(); foreach (Scene scene in Awperative.LoadedScenes.ToList()) scene.ChainUnload();
} }

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
namespace Awperative;
public sealed partial class Scene : Docker
{
//todo: make useful lolol
}

View File

@@ -1,19 +0,0 @@
namespace Awperative;
public class BodyComponent : Component
{
public Body Body;
internal override void Initiate(DockerEntity __docker) {
Docker = __docker;
Body = (Body)__docker;
Create();
}
public Transform Transform => Body.transform;
}

View File

@@ -1,26 +0,0 @@
namespace Awperative;
public abstract partial class Component
{
protected Body AddBody() => Scene.AddBody();
protected Body AddBody(Transform __transform) => Scene.AddBody(__transform);
protected Body GetBody(string __tag) => Scene.GetBody(__tag);
protected Body[] GetBodies(string __tag) => Scene.GetBodies(__tag);
protected void DestroyBody(Body __body) => Scene.DestroyBody(__body);
public Component AddComponent<Generic>() where Generic : Component => Docker.AddComponent<Generic>();
public Component AddComponent<Generic>(object[] __args) where Generic : Component => Docker.AddComponent<Generic>(__args);
public Component GetComponent<Generic>() where Generic : Component => Docker.GetComponent<Generic>();
public Component[] GetComponents<Generic>() where Generic : Component => Docker.GetComponents<Generic>();
public void RemoveComponent<Generic>() where Generic : Component => Docker.RemoveComponent<Generic>();
}

View File

@@ -1,7 +0,0 @@
namespace Awperative;
public class SceneComponent : Component
{
}

View File

@@ -1,92 +0,0 @@
using System;
using Microsoft.Xna.Framework;
namespace Awperative;
public sealed class Transform
{
public event EventHandler<TransformModifyEvent> OnTransformChangedEvent;
public Vector2 Origin {
get => _origin; set {
if(!value.Equals(_origin))
OnTransformChangedEvent?.Invoke(this, TransformModifyEvent.FromPosition(this, value)); _origin = value;
}
}
private Vector2 _origin = Vector2.Zero;
public Vector2 Position {
get => _position; set {
if(!value.Equals(_position))
OnTransformChangedEvent?.Invoke(this, TransformModifyEvent.FromPosition(this, value)); _position = value;
}
}
private Vector2 _position = Vector2.Zero;
public float Depth {
get => _depth; set {
if(!value.Equals(_depth))
OnTransformChangedEvent?.Invoke(this, TransformModifyEvent.FromDepth(this, value)); _depth = value;
}
}
private float _depth = 0f;
public float Rotation {
get => _rotation; set {
if(!value.Equals(_rotation))
OnTransformChangedEvent?.Invoke(this, TransformModifyEvent.FromRotation(this, value)); _rotation = value;
}
}
private float _rotation = 0f;
public Vector2 Scale {
get => _scale; set {
if(!value.Equals(_scale))
OnTransformChangedEvent?.Invoke(this, TransformModifyEvent.FromScale(this, value)); _scale = value;
}
}
private Vector2 _scale = Vector2.One;
public void Set(Vector2 __origin, Vector2 __position, float __depth, float __rotation, Vector2 __scale)
{
//todo: rename to previous and check names`
var previous = Clone();
bool changed = false;
if (!_origin.Equals(_origin)) { _origin = __origin; changed = true; }
if (!_position.Equals(_position)) { _position = __position; changed = true; }
if (!_depth.Equals(_depth)) { _depth = __depth; changed = true; }
if (!_rotation.Equals(_rotation)) { _rotation = __rotation; changed = true; }
if (!_scale.Equals(_scale)) { _scale = __scale; changed = true; }
if (changed)
OnTransformChangedEvent?.Invoke(this, TransformModifyEvent.FromTransforms(this, previous));
}
public Transform() {}
public Transform(Vector2 __origin, Vector2 __position, float __depth, float __rotation, Vector2 __scale) {
Origin = __origin; Position = __position; Depth = __depth; Rotation = __rotation; Scale = __scale;
}
//todo: operators?
public Transform Clone()
{
return new Transform(Origin, Position, Depth, Rotation, Scale);
}
public Matrix ToMatrix()
{
return
Matrix.CreateTranslation(new Vector3(-Position, 0f)) *
Matrix.CreateTranslation(new Vector3(-Origin, 0f)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(new Vector3(Scale, 1f)) *
Matrix.CreateTranslation(new Vector3(Origin, 0f));
}
}