parent
32caf91234
commit
1a7aa03c36
9 changed files with 155 additions and 42 deletions
@ -0,0 +1,110 @@ |
||||
[Tool] |
||||
public partial class Interactable : RigidBody3D |
||||
{ |
||||
PackedScene _modelScene; |
||||
[Export] public PackedScene ModelScene { |
||||
get => _modelScene; |
||||
set => _modelScene = OnModelSceneChanged(value); |
||||
} |
||||
|
||||
Vector3I _gridSize; |
||||
/// <summary> Get the size of this item in grid units. </summary> |
||||
[Export] public Vector3I GridSize { |
||||
get => _gridSize; |
||||
set => _gridSize = OnGridSizeChanged(value); |
||||
} |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
} |
||||
|
||||
public override void _Process(double delta) |
||||
{ |
||||
} |
||||
|
||||
// FIXME: Only change this if ModelScene is actually changed, not when loaded. |
||||
PackedScene OnModelSceneChanged(PackedScene value) |
||||
{ |
||||
if (GetNodeOrNull("_Model") is Node oldModel) { |
||||
RemoveChild(oldModel); |
||||
oldModel.QueueFree(); |
||||
} |
||||
|
||||
// Remove any previously added `CollisionShape3D` nodes. |
||||
foreach (var child in GetChildren(true).OfType<CollisionShape3D>()) { |
||||
RemoveChild(child); |
||||
child.QueueFree(); |
||||
} |
||||
|
||||
if (value is PackedScene scene) { |
||||
var model = scene.Instantiate<Node3D>(); |
||||
model.Name = "_Model"; |
||||
|
||||
var numShapes = 0; |
||||
var min = Vector3.Zero; |
||||
var max = Vector3.Zero; |
||||
|
||||
// Find all the `StaticBody3D` nodes in the model and parent |
||||
// their `CollisionShape3D` children to the this `RigidBody3D`. |
||||
// Required because shapes must be immediate children of the body. |
||||
// See: https://github.com/godotengine/godot-proposals/issues/535 |
||||
// https://github.com/godotengine/godot/pull/77937 |
||||
foreach (var body in model.FindChildren("*", "StaticBody3D").Cast<StaticBody3D>()) { |
||||
body.GetParent().RemoveChild(body); |
||||
body.QueueFree(); |
||||
|
||||
foreach (var shape in body.GetChildren().OfType<CollisionShape3D>()) { |
||||
// Not unsetting the owner results in this warning: |
||||
// "Adding 'CollisionShape3D' as child to 'Interactable' will make owner '...' inconsistent." |
||||
shape.Owner = null; |
||||
|
||||
body.RemoveChild(shape); |
||||
shape.Name = $"_{nameof(CollisionShape3D)}_{numShapes + 1}"; |
||||
AddChild(shape, false, InternalMode.Front); |
||||
// shape.Owner = this; |
||||
numShapes++; |
||||
|
||||
// Finds the axis-aligned boundary of all collision shapes. |
||||
// This assumes that the shape has an identity transformation. |
||||
var vertices = (shape.Shape as ConvexPolygonShape3D)?.Points |
||||
?? (shape.Shape as ConcavePolygonShape3D)?.Data |
||||
?? throw new Exception("Shape must be either convex or concave"); |
||||
foreach (var vert in vertices) { |
||||
min = new(Min(min.X, vert.X), Min(min.Y, vert.Y), Min(min.Z, vert.Z)); |
||||
max = new(Max(max.X, vert.X), Max(max.Y, vert.Y), Max(max.Z, vert.Z)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
AddChild(model, false, InternalMode.Front); |
||||
|
||||
// Set the grid size based on the boundary of all collision shapes. |
||||
GridSize = (Vector3I)((max - min).Snapped(Epsilon) / Grid.StepSize).Ceil(); |
||||
} else { |
||||
GridSize = Vector3I.Zero; |
||||
} |
||||
|
||||
return value; |
||||
} |
||||
|
||||
Vector3I OnGridSizeChanged(Vector3I value) |
||||
{ |
||||
if (GetNodeOrNull("_GridArea") is Node oldGridArea) { |
||||
RemoveChild(oldGridArea); |
||||
oldGridArea.QueueFree(); |
||||
} |
||||
|
||||
if (value.X > 0 && value.Y > 0 && value.Z > 0) { |
||||
var gridArea = new Area3D(); |
||||
gridArea.Name = "_GridArea"; |
||||
|
||||
var shape = new CollisionShape3D(); |
||||
shape.Shape = new BoxShape3D { Size = (Vector3)value * Grid.StepSize }; |
||||
gridArea.AddChild(shape); |
||||
|
||||
AddChild(gridArea, false, InternalMode.Front); |
||||
} |
||||
|
||||
return value; |
||||
} |
||||
} |
@ -0,0 +1,10 @@ |
||||
[gd_scene load_steps=3 format=3 uid="uid://d4l5bguk01qqr"] |
||||
|
||||
[ext_resource type="Script" path="res://objects/Interactable.cs" id="1_vnawe"] |
||||
[ext_resource type="PackedScene" uid="uid://dh18opmr8mjet" path="res://assets/models/plank.blend" id="2_cvuqp"] |
||||
|
||||
[node name="Interactable" type="RigidBody3D"] |
||||
script = ExtResource("1_vnawe") |
||||
ModelScene = ExtResource("2_cvuqp") |
||||
GridSize = Vector3i(16, 1, 3) |
||||
metadata/_edit_group_ = true |
@ -1,20 +1,19 @@ |
||||
[Flags] |
||||
public enum PhysicsLayer : uint |
||||
{ |
||||
/// <summary> Objects that are part of the scene, and never move. </summary> |
||||
Static = 1 << 0, |
||||
/// <summary> Objects players collide with, but may move. </summary> |
||||
Dynamic = 1 << 1, |
||||
/// <summary> Any players, both local and remote. </summary> |
||||
Player = 1 << 2, |
||||
/// <summary> Small objects players don't collide with, but collide with players. </summary> |
||||
Item = 1 << 3, |
||||
/// <summary> Physical objects that are part of the scene and won't move. </summary> |
||||
Static = 0b0000_0000_0000_0001, |
||||
/// <summary> Physical objects that may move. Player collide with these. </summary> |
||||
Dynamic = 0b0000_0000_0000_0010, |
||||
/// <summary> Small physical objects that may move. Players don't collide with these. </summary> |
||||
Small = 0b0000_0000_0000_0100, |
||||
/// <summary> Physical bodies such as those of players. </summary> |
||||
Body = 0b0000_0000_0000_1000, |
||||
|
||||
/// <summary> Objects that may be picked up. </summary> |
||||
Pickup = 1 << 8, |
||||
/// <summary> Objects that other objects may be placed against. </summary> |
||||
Place = 1 << 9, |
||||
|
||||
/// <summary> Various areas, such as workshops. </summary> |
||||
Areas = 1 << 10, |
||||
/// <summary> Areas in the game that can be entered or left by players. </summary> |
||||
Zone = 0b0000_0001_0000_0000, |
||||
/// <summary> Objects that may be ray-traced to interact with them. </summary> |
||||
Interact = 0b0000_0010_0000_0000, |
||||
/// <summary> Objects that others may be placed again, grid-aligned bounding box. </summary> |
||||
Placable = 0b0000_0100_0000_0000, |
||||
} |
||||
|
Loading…
Reference in new issue