mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Generic shape/collider configs
This commit is contained in:
parent
2c7b5a63f6
commit
5aace8408a
140
NewHorizons/Builder/Props/ShapeBuilder.cs
Normal file
140
NewHorizons/Builder/Props/ShapeBuilder.cs
Normal file
@ -0,0 +1,140 @@
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.External.Modules.Props;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Builder.Props
|
||||
{
|
||||
public static class ShapeBuilder
|
||||
{
|
||||
public static Component AddShapeOrCollider(GameObject go, ShapeInfo info)
|
||||
{
|
||||
if (info.useShape.HasValue)
|
||||
{
|
||||
// Explicitly add either a shape or collider if specified
|
||||
if (info.useShape.Value)
|
||||
return AddShape(go, info);
|
||||
else
|
||||
return AddCollider(go, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prefer colliders over shapes if no preference is specified
|
||||
if (info.type is ShapeType.Sphere or ShapeType.Box or ShapeType.Capsule)
|
||||
return AddCollider(go, info);
|
||||
else
|
||||
return AddShape(go, info);
|
||||
}
|
||||
}
|
||||
|
||||
public static Shape AddShape(GameObject go, ShapeInfo info)
|
||||
{
|
||||
if (info.hasCollision)
|
||||
{
|
||||
throw new NotSupportedException($"Shapes do not support collision; set {info.hasCollision} to false and use a supported collider type (sphere, box, or capsule).");
|
||||
}
|
||||
if (info.useShape.HasValue && !info.useShape.Value)
|
||||
{
|
||||
throw new NotSupportedException($"{info.useShape} was explicitly set to false but a shape is required here.");
|
||||
}
|
||||
switch (info.type)
|
||||
{
|
||||
case ShapeType.Sphere:
|
||||
var sphereShape = go.AddComponent<SphereShape>();
|
||||
sphereShape._radius = info.radius;
|
||||
sphereShape._center = info.offset ?? Vector3.zero;
|
||||
return sphereShape;
|
||||
case ShapeType.Box:
|
||||
var boxShape = go.AddComponent<BoxShape>();
|
||||
boxShape._size = info.size ?? Vector3.one;
|
||||
boxShape._center = info.offset ?? Vector3.zero;
|
||||
return boxShape;
|
||||
case ShapeType.Capsule:
|
||||
var capsuleShape = go.AddComponent<CapsuleShape>();
|
||||
capsuleShape._radius = info.radius;
|
||||
capsuleShape._direction = (int)info.direction;
|
||||
capsuleShape._height = info.height;
|
||||
capsuleShape._center = info.offset ?? Vector3.zero;
|
||||
return capsuleShape;
|
||||
case ShapeType.Cylinder:
|
||||
var cylinderShape = go.AddComponent<CylinderShape>();
|
||||
cylinderShape._radius = info.radius;
|
||||
cylinderShape._height = info.height;
|
||||
cylinderShape._center = info.offset ?? Vector3.zero;
|
||||
return cylinderShape;
|
||||
case ShapeType.Cone:
|
||||
var coneShape = go.AddComponent<ConeShape>();
|
||||
coneShape._topRadius = info.innerRadius;
|
||||
coneShape._bottomRadius = info.outerRadius;
|
||||
coneShape._direction = (int)info.direction;
|
||||
coneShape._height = info.height;
|
||||
coneShape._center = info.offset ?? Vector3.zero;
|
||||
return coneShape;
|
||||
case ShapeType.Hemisphere:
|
||||
var hemisphereShape = go.AddComponent<HemisphereShape>();
|
||||
hemisphereShape._radius = info.radius;
|
||||
hemisphereShape._direction = (int)info.direction;
|
||||
hemisphereShape._cap = info.cap;
|
||||
hemisphereShape._center = info.offset ?? Vector3.zero;
|
||||
return hemisphereShape;
|
||||
case ShapeType.Hemicapsule:
|
||||
var hemicapsuleShape = go.AddComponent<HemicapsuleShape>();
|
||||
hemicapsuleShape._radius = info.radius;
|
||||
hemicapsuleShape._direction = (int)info.direction;
|
||||
hemicapsuleShape._height = info.height;
|
||||
hemicapsuleShape._cap = info.cap;
|
||||
hemicapsuleShape._center = info.offset ?? Vector3.zero;
|
||||
return hemicapsuleShape;
|
||||
case ShapeType.Ring:
|
||||
var ringShape = go.AddComponent<RingShape>();
|
||||
ringShape.innerRadius = info.innerRadius;
|
||||
ringShape.outerRadius = info.outerRadius;
|
||||
ringShape.height = info.height;
|
||||
ringShape.center = info.offset ?? Vector3.zero;
|
||||
return ringShape;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(info.type), info.type, $"Unsupported shape type");
|
||||
}
|
||||
}
|
||||
|
||||
public static Collider AddCollider(GameObject go, ShapeInfo info)
|
||||
{
|
||||
if (info.useShape.HasValue && info.useShape.Value)
|
||||
{
|
||||
throw new NotSupportedException($"{info.useShape} was explicitly set to true but a non-shape collider is required here.");
|
||||
}
|
||||
switch (info.type)
|
||||
{
|
||||
case ShapeType.Sphere:
|
||||
var sphereCollider = go.AddComponent<SphereCollider>();
|
||||
sphereCollider.radius = info.radius;
|
||||
sphereCollider.center = info.offset ?? Vector3.zero;
|
||||
sphereCollider.isTrigger = !info.hasCollision;
|
||||
go.GetAddComponent<OWCollider>();
|
||||
return sphereCollider;
|
||||
case ShapeType.Box:
|
||||
var boxCollider = go.AddComponent<BoxCollider>();
|
||||
boxCollider.size = info.size ?? Vector3.one;
|
||||
boxCollider.center = info.offset ?? Vector3.zero;
|
||||
boxCollider.isTrigger = !info.hasCollision;
|
||||
go.GetAddComponent<OWCollider>();
|
||||
return boxCollider;
|
||||
case ShapeType.Capsule:
|
||||
var capsuleCollider = go.AddComponent<CapsuleCollider>();
|
||||
capsuleCollider.radius = info.radius;
|
||||
capsuleCollider.direction = (int)info.direction;
|
||||
capsuleCollider.height = info.height;
|
||||
capsuleCollider.center = info.offset ?? Vector3.zero;
|
||||
capsuleCollider.isTrigger = !info.hasCollision;
|
||||
go.GetAddComponent<OWCollider>();
|
||||
return capsuleCollider;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(info.type), info.type, $"Unsupported collider type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
NewHorizons/External/Modules/Props/ShapeInfo.cs
vendored
Normal file
92
NewHorizons/External/Modules/Props/ShapeInfo.cs
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
using NewHorizons.External.SerializableData;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NewHorizons.External.Modules.Props
|
||||
{
|
||||
[JsonObject]
|
||||
public class ShapeInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of shape or collider to add. Sphere, box, and capsule colliders are more performant and support collision. Defaults to sphere.
|
||||
/// </summary>
|
||||
public ShapeType type = ShapeType.Sphere;
|
||||
|
||||
/// <summary>
|
||||
/// The radius of the shape or collider. Defaults to 0.5 meters. Only used by spheres, capsules, cylinders, hemispheres, hemicapsules, and rings.
|
||||
/// </summary>
|
||||
public float radius = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the shape or collider. Defaults to 1 meter. Only used by capsules, cylinders, cones, hemicapsules, and rings.
|
||||
/// </summary>
|
||||
public float height = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// The axis that the shape or collider is aligned with. Defaults to the Y axis (up). The flat bottom of the shape will be pointing towards the negative axis. Only used by capsules, cones, hemispheres, and hemicapsules.
|
||||
/// </summary>
|
||||
public ColliderAxis direction = ColliderAxis.Y;
|
||||
|
||||
/// <summary>
|
||||
/// The inner radius of the shape. Defaults to 0 meters. Only used by cones and rings.
|
||||
/// </summary>
|
||||
public float innerRadius = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The outer radius of the shape. Defaults to 0.5 meters. Only used by cones and rings.
|
||||
/// </summary>
|
||||
public float outerRadius = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the shape has an end cap. Defaults to true. Only used by hemispheres and hemicapsules.
|
||||
/// </summary>
|
||||
public bool cap = true;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the shape or collider. Defaults to (1,1,1). Only used by boxes.
|
||||
/// </summary>
|
||||
public MVector3 size;
|
||||
|
||||
/// <summary>
|
||||
/// The offset of the shape or collider from the object's origin. Defaults to (0,0,0). Supported by all collider and shape types.
|
||||
/// </summary>
|
||||
public MVector3 offset;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the collider should have collision enabled. If false, the collider will be a trigger. Defaults to false. Only supported for spheres, boxes, and capsules.
|
||||
/// </summary>
|
||||
public bool hasCollision = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to explicitly use a shape instead of a collider. Shapes do not support collision and are less performant, but support a wider set of shapes and are required by some components. Omit this unless you explicitly want to use a sphere, box, or capsule shape instead of a collider.
|
||||
/// </summary>
|
||||
public bool? useShape;
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum ShapeType
|
||||
{
|
||||
[EnumMember(Value = @"sphere")] Sphere,
|
||||
[EnumMember(Value = @"box")] Box,
|
||||
[EnumMember(Value = @"capsule")] Capsule,
|
||||
[EnumMember(Value = @"cylinder")] Cylinder,
|
||||
[EnumMember(Value = @"cone")] Cone,
|
||||
[EnumMember(Value = @"hemisphere")] Hemisphere,
|
||||
[EnumMember(Value = @"hemicapsule")] Hemicapsule,
|
||||
[EnumMember(Value = @"ring")] Ring,
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum ColliderAxis
|
||||
{
|
||||
[EnumMember(Value = @"x")] X = 0,
|
||||
[EnumMember(Value = @"y")] Y = 1,
|
||||
[EnumMember(Value = @"z")] Z = 2,
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user