using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.Xna.Framework;
namespace Awperative;
public abstract partial class Component : ComponentDocker
{
///
/// Current parent of the Component. Can be either Scene or another Component.
///
public ComponentDocker ComponentDocker { get; internal set; }
///
/// If the component receives time events or not.
///
public bool Enabled = true;
///
/// Order for when Components are called on. Only applies between Components on the same Docker.
///
public int Priority {
get => _priority; set => ComponentDocker.UpdatePriority(this, value);
} internal int _priority;
///
/// To be called when the Component is created.
///
/// Docker that this spawned in this Component
internal void Initiate(ComponentDocker __parent) {
ComponentDocker = __parent;
Create();
}
///
/// Called when the Game is Closing; does not always happen depending on if it is Force Closed.
///
protected internal virtual void Unload() {}
///
/// Called when the Game is Loading.
///
protected internal virtual void Load() {}
///
/// Called every frame before Draw, it is recommended to do any Non-Drawing update logic here.
///
protected internal virtual void Update() {}
///
/// Called after Update when the screen is being drawn. Please only put Drawing related logic here.
///
protected internal virtual void Draw() {}
///
/// Called when the Component is created.
///
protected internal virtual void Create() {}
///
/// Called when the Component is destroyed. Not called when the Game is closed.
///
protected internal virtual void Destroy() {}
///
/// Scene the Component resides in.
///
public Scene Scene => __QueryScene();
protected Scene __QueryScene() {
if (ComponentDocker is Scene scene) return scene;
if (ComponentDocker is Component Component) return Component.__QueryScene();
return null;
}
///
/// Identifiers for Components.
///
public ImmutableArray Tags => [.._tags];
internal HashSet _tags = [];
///
/// Adds a new tag to the Component
///
/// The tag to add
public void AddTag(string __tag) => ComponentDocker.HashTaggedComponent(this, __tag);
///
/// Removes a tag from the Component
///
/// The tag to remove
public void RemoveTag(string __tag) => ComponentDocker.UnhashTaggedComponent(this, __tag);
///
/// All parent Dockers and the parents of the parents up until the Scene. Will only list parents of parents, not uncle dockers.
///
/// Dockers[0] is the parent of this object, and Dockers[^1] is the Scene.
public ImmutableArray Dockers => __QueryDockers();
protected ImmutableArray __QueryDockers() {
List returnValue = [];
ComponentDocker currentComponentDocker = ComponentDocker;
while (!(currentComponentDocker is Scene)) {
if (currentComponentDocker is Component Component) {
returnValue.Add(currentComponentDocker);
currentComponentDocker = Component.ComponentDocker;
} else {
Debug.LogError("Component has a Parent that is not a Scene or Component, Please do not use the Docker class unless you know what you are doing!", ["Component", "Type", "Docker"],
[GetHashCode().ToString(), GetType().ToString(), ComponentDocker.GetHashCode().ToString()]);
}
}
returnValue.Add(currentComponentDocker);
return [..returnValue];
}
///
/// Returns the Parent Component. Will be null if the Component is under a scene.
///
public Component Parent => __QueryParent();
protected Component __QueryParent() {
if (ComponentDocker is Component Component)
return Component;
return null;
}
///
/// All parent Components and the parents of the parents up until the Scene. Will only list parents of parents, not uncle Components.
///
public ImmutableArray Parents => __QueryComponents();
protected ImmutableArray __QueryComponents() {
List returnValue = [];
ComponentDocker currentComponentDocker = ComponentDocker;
while (!(currentComponentDocker is Scene))
if (currentComponentDocker is Component Component) {
returnValue.Add(Component);
currentComponentDocker = Component.ComponentDocker;
}
return [..returnValue];
}
}