mirror of
https://github.com/antopilo/Nuake.git
synced 2026-01-01 05:48:14 +03:00
331 lines
9.8 KiB
C#
331 lines
9.8 KiB
C#
using Coral.Managed.Interop;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Reflection.Metadata;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Nuake.Net
|
|
{
|
|
public struct CollisionData
|
|
{
|
|
Entity Entity1;
|
|
Entity Entity2;
|
|
Vector3 Normal;
|
|
Vector3 Position;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public class Entity
|
|
{
|
|
internal static unsafe delegate*<int, int, bool> EntityHasComponentIcall;
|
|
internal static unsafe delegate*<int, int, void> EntityAddComponentIcall;
|
|
internal static unsafe delegate*<int, bool> EntityHasManagedInstanceIcall;
|
|
internal static unsafe delegate*<int, NativeString, int> EntityGetEntityIcall;
|
|
internal static unsafe delegate*<int, NativeString> EntityGetNameIcall;
|
|
internal static unsafe delegate*<int, NativeString, void> EntitySetNameIcall;
|
|
internal static unsafe delegate*<int, bool> EntityIsValidIcall;
|
|
internal static unsafe delegate*<NativeString, NativeArray<int>> EntityGetTargetsIcall;
|
|
internal static unsafe delegate*<int, NativeString> EntityGetTargetIcall;
|
|
|
|
public enum ComponentTypes
|
|
{
|
|
Unknown = -1,
|
|
PARENT = 0,
|
|
NAME,
|
|
PREFAB,
|
|
TRANSFORM,
|
|
LIGHT,
|
|
CAMERA,
|
|
AUDIO_EMITTER,
|
|
MODEL,
|
|
SKINNED_MODEL,
|
|
BONE,
|
|
RIGIDBODY,
|
|
BOX_COLLIDER,
|
|
SPHERE_COLLIDER,
|
|
CAPSULE_COLLIDER,
|
|
CYLINDER_COLLIDER,
|
|
MESH_COLLIDER,
|
|
CHARACTER_CONTROLLER,
|
|
PARTICLE_EMITTER,
|
|
QUAKE_MAP,
|
|
BSP_BRUSH,
|
|
SPRITE,
|
|
NAVMESH
|
|
}
|
|
|
|
public List<Entity> Targets
|
|
{
|
|
get
|
|
{
|
|
unsafe
|
|
{
|
|
var targetIds = EntityGetTargetsIcall(Target);
|
|
|
|
List<Entity> targets = new List<Entity>();
|
|
foreach(var target in targetIds)
|
|
{
|
|
bool hasInstance = EntityHasManagedInstanceIcall(target);
|
|
Entity entityInstance;
|
|
if (hasInstance)
|
|
{
|
|
entityInstance = Scene.GetEntity<Entity>(target);
|
|
}
|
|
else
|
|
{
|
|
entityInstance = new Entity(ECSHandle);
|
|
}
|
|
|
|
targets.Add(entityInstance);
|
|
}
|
|
|
|
return targets;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected TransformComponent internalTransform;
|
|
public TransformComponent Transform
|
|
{
|
|
get
|
|
{
|
|
if(internalTransform == null)
|
|
{
|
|
internalTransform = GetComponent<TransformComponent>()!;
|
|
}
|
|
|
|
return internalTransform;
|
|
}
|
|
}
|
|
|
|
public string Target { get { unsafe { return EntityGetTargetIcall(ECSHandle); } }}
|
|
public int ID { get; set; }
|
|
public int ECSHandle { get; set; } = -1;
|
|
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
unsafe
|
|
{
|
|
NativeString name = EntityGetNameIcall(ECSHandle);
|
|
return name;
|
|
}
|
|
}
|
|
set
|
|
{
|
|
if(String.IsNullOrEmpty(value))
|
|
{
|
|
Engine.Log("Invalid entity name: cannot be empty.");
|
|
return;
|
|
}
|
|
|
|
unsafe
|
|
{
|
|
EntitySetNameIcall(ECSHandle, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Entity() { }
|
|
public Entity(int handle)
|
|
{
|
|
ECSHandle = handle;
|
|
}
|
|
|
|
public virtual void OnInit() { }
|
|
public virtual void OnUpdate(float dt) { }
|
|
public virtual void OnFixedUpdate(float dt) { }
|
|
public virtual void OnDestroy() { }
|
|
|
|
public virtual void OnCollision(Entity entity)
|
|
{
|
|
}
|
|
|
|
public virtual void Activate(Entity triggeredFrom)
|
|
{
|
|
|
|
}
|
|
|
|
// Physics
|
|
public void OnCollisionInternal(int entity)
|
|
{
|
|
Entity entityInstance;
|
|
unsafe
|
|
{
|
|
bool hasInstance = EntityHasManagedInstanceIcall(entity);
|
|
|
|
if (hasInstance)
|
|
{
|
|
entityInstance = Scene.GetEntity<Entity>(entity);
|
|
}
|
|
else
|
|
{
|
|
entityInstance = new Entity(ECSHandle);
|
|
}
|
|
}
|
|
|
|
OnCollision(entityInstance);
|
|
}
|
|
|
|
protected static Dictionary<Type, ComponentTypes> MappingTypeEnum = new Dictionary<Type, ComponentTypes>()
|
|
{
|
|
{ typeof(ParentComponent), ComponentTypes.PARENT },
|
|
{ typeof(NameComponent), ComponentTypes.NAME },
|
|
{ typeof(PrefabComponent), ComponentTypes.PREFAB },
|
|
{ typeof(TransformComponent), ComponentTypes.TRANSFORM},
|
|
{ typeof(LightComponent), ComponentTypes.LIGHT },
|
|
{ typeof(CameraComponent), ComponentTypes.CAMERA },
|
|
{ typeof(AudioEmitterComponent), ComponentTypes.AUDIO_EMITTER },
|
|
{ typeof(ModelComponent), ComponentTypes.MODEL },
|
|
{ typeof(SkinnedModelComponent), ComponentTypes.SKINNED_MODEL },
|
|
{ typeof(BoneComponent), ComponentTypes.BONE },
|
|
{ typeof(BoxCollider), ComponentTypes.BOX_COLLIDER },
|
|
{ typeof(SphereCollider), ComponentTypes.SPHERE_COLLIDER },
|
|
{ typeof(CapsuleColliderComponent), ComponentTypes.CAPSULE_COLLIDER },
|
|
{ typeof(CylinderColliderComponent), ComponentTypes.CYLINDER_COLLIDER },
|
|
{ typeof(MeshColliderComponent), ComponentTypes.MESH_COLLIDER },
|
|
{ typeof(CharacterControllerComponent), ComponentTypes.CHARACTER_CONTROLLER },
|
|
{ typeof(ParticleEmitterComponent), ComponentTypes.PARTICLE_EMITTER },
|
|
{ typeof(QuakeMapComponent), ComponentTypes.QUAKE_MAP },
|
|
{ typeof(BSPBrushComponent), ComponentTypes.BSP_BRUSH },
|
|
{ typeof(SpriteComponent), ComponentTypes.SPRITE },
|
|
{ typeof(NavMeshVolumeComponent), ComponentTypes.NAVMESH }
|
|
};
|
|
|
|
public bool HasComponent<T>()
|
|
{
|
|
if (MappingTypeEnum.ContainsKey(typeof(T)))
|
|
{
|
|
unsafe { return EntityHasComponentIcall(ECSHandle, (int)MappingTypeEnum[typeof(T)]); };
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public T? AddComponent<T>() where T : IComponent
|
|
{
|
|
if(HasComponent<T>())
|
|
{
|
|
return (T?)Activator.CreateInstance(typeof(T), ECSHandle);
|
|
}
|
|
|
|
unsafe
|
|
{
|
|
EntityAddComponentIcall(ECSHandle, (int)MappingTypeEnum[typeof(T)]);
|
|
return (T?)Activator.CreateInstance(typeof(T), ECSHandle);
|
|
};
|
|
}
|
|
|
|
public T? GetComponent<T>() where T : IComponent
|
|
{
|
|
if (HasComponent<T>())
|
|
{
|
|
return (T?)Activator.CreateInstance(typeof(T), ECSHandle);
|
|
}
|
|
|
|
throw new Exception("Component not found: " + typeof(T).GetType().Name);
|
|
}
|
|
|
|
public T? GetEntity<T>(string path) where T : Entity
|
|
{
|
|
Entity entityInstance;
|
|
unsafe
|
|
{
|
|
int entityHandle = EntityGetEntityIcall(ECSHandle, path );
|
|
|
|
bool hasInstance = EntityHasManagedInstanceIcall(entityHandle);
|
|
if (hasInstance)
|
|
{
|
|
entityInstance = Scene.GetEntity<Entity>(entityHandle);
|
|
}
|
|
else
|
|
{
|
|
entityInstance = new Entity(entityHandle);
|
|
}
|
|
}
|
|
|
|
return entityInstance as T;
|
|
}
|
|
|
|
public static implicit operator bool(Entity entity)
|
|
{
|
|
if (object.ReferenceEquals(entity, null))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool isValid;
|
|
unsafe
|
|
{
|
|
isValid = EntityIsValidIcall(entity.ECSHandle);
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
}
|
|
|
|
public class Prefab
|
|
{
|
|
internal static unsafe delegate*<NativeString, Vector3, float, float, float, float, int> PrefabInstanceIcall;
|
|
|
|
string Path { get; set; }
|
|
|
|
public Prefab()
|
|
{
|
|
|
|
}
|
|
|
|
public Prefab(string path)
|
|
{
|
|
Path = path;
|
|
Engine.Log("Prefab instance created with path: " + path);
|
|
}
|
|
|
|
public Entity? Instance(Vector3 position = default, Quaternion quat = default)
|
|
{
|
|
int handle;
|
|
unsafe { handle = PrefabInstanceIcall(Path, position, quat.X, quat.Y, quat.Z, quat.W); }
|
|
|
|
if (handle == -1)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Entity entity = new Entity(handle);
|
|
return entity;
|
|
}
|
|
|
|
public T? Instance<T>(Vector3 position = default, Quaternion quat = default) where T : Entity
|
|
{
|
|
int handle;
|
|
unsafe { handle = PrefabInstanceIcall(Path, position, quat.X, quat.Y, quat.Z, quat.W); }
|
|
|
|
if (handle == -1)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
T? instance = Scene.GetEntity<T>(handle);
|
|
instance.OnInit();
|
|
|
|
return instance;
|
|
}
|
|
|
|
public static implicit operator bool(Prefab prefab)
|
|
{
|
|
if (object.ReferenceEquals(prefab, null))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return prefab.Path != string.Empty;
|
|
}
|
|
}
|
|
}
|