Compare commits
No commits in common. 'wip/interactable-rework' and 'main' have entirely different histories.
wip/intera
...
main
9 changed files with 42 additions and 155 deletions
@ -1,110 +0,0 @@ |
|||||||
[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; |
|
||||||
} |
|
||||||
} |
|
@ -1,10 +0,0 @@ |
|||||||
[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,19 +1,20 @@ |
|||||||
[Flags] |
[Flags] |
||||||
public enum PhysicsLayer : uint |
public enum PhysicsLayer : uint |
||||||
{ |
{ |
||||||
/// <summary> Physical objects that are part of the scene and won't move. </summary> |
/// <summary> Objects that are part of the scene, and never move. </summary> |
||||||
Static = 0b0000_0000_0000_0001, |
Static = 1 << 0, |
||||||
/// <summary> Physical objects that may move. Player collide with these. </summary> |
/// <summary> Objects players collide with, but may move. </summary> |
||||||
Dynamic = 0b0000_0000_0000_0010, |
Dynamic = 1 << 1, |
||||||
/// <summary> Small physical objects that may move. Players don't collide with these. </summary> |
/// <summary> Any players, both local and remote. </summary> |
||||||
Small = 0b0000_0000_0000_0100, |
Player = 1 << 2, |
||||||
/// <summary> Physical bodies such as those of players. </summary> |
/// <summary> Small objects players don't collide with, but collide with players. </summary> |
||||||
Body = 0b0000_0000_0000_1000, |
Item = 1 << 3, |
||||||
|
|
||||||
/// <summary> Areas in the game that can be entered or left by players. </summary> |
/// <summary> Objects that may be picked up. </summary> |
||||||
Zone = 0b0000_0001_0000_0000, |
Pickup = 1 << 8, |
||||||
/// <summary> Objects that may be ray-traced to interact with them. </summary> |
/// <summary> Objects that other objects may be placed against. </summary> |
||||||
Interact = 0b0000_0010_0000_0000, |
Place = 1 << 9, |
||||||
/// <summary> Objects that others may be placed again, grid-aligned bounding box. </summary> |
|
||||||
Placable = 0b0000_0100_0000_0000, |
/// <summary> Various areas, such as workshops. </summary> |
||||||
|
Areas = 1 << 10, |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue