Compare commits

...

4 Commits

Author SHA1 Message Date
Martin Felis a37b028b39 Refactoring now functional 2023-11-15 20:57:25 +01:00
Martin Felis fcc2fdb8d3 Fixed missing ToolAttachment 2023-11-13 20:10:05 +01:00
Martin Felis 71162f9420 Minor cleanup. 2023-11-11 10:58:35 +01:00
Martin Felis d2611c6073 Interactions can now end themselves. 2023-11-10 20:22:55 +01:00
13 changed files with 699 additions and 405 deletions

View File

@ -37,9 +37,9 @@ public class GroundMotionComponent : Component
private void CalcPlaneVelocity(float delta, Entity entity, Vector3 targetPosition)
{
Vector2 planeTargetDirection = new Vector2(DirectionToTarget.x, DirectionToTarget.z);
Vector2 planeTargetDirection = new(DirectionToTarget.x, DirectionToTarget.z);
Vector2 planeVelocity = new Vector2(entity.Velocity.x, entity.Velocity.z);
Vector2 planeVelocity = new(entity.Velocity.x, entity.Velocity.z);
// GD.Print("-- Step: distance: " + targetDistance + " dir: " + planeTargetDirection + " speed: " + planeVelocity.Length() + " vel dir: " + planeVelocity.Normalized());
planeVelocity -= planeVelocity * Damping;
// GD.Print(" damp : speed: " + planeVelocity.Length() + " vel dir: " + planeVelocity.Normalized());
@ -53,7 +53,7 @@ public class GroundMotionComponent : Component
planeVelocity = planeVelocity.Length() * planeTargetDirection + planeTargetDirection * Accel * delta;
// GD.Print(" accel: speed: " + planeVelocity.Length() + " vel dir: " + planeVelocity.Normalized());
var projectedStep = planeTargetDirection.Dot(planeVelocity * delta);
float projectedStep = planeTargetDirection.Dot(planeVelocity * delta);
// GD.Print(" Projected step: " + projectedStep + " Speed: " + planeVelocity.Length() + " delta: " + delta);
if (projectedStep > DistanceToTarget)
{
@ -62,7 +62,7 @@ public class GroundMotionComponent : Component
// GD.Print(" corr speed: " + planeVelocity.Length() + " step: " + projectedStep);
}
var planeSpeed = planeVelocity.Length();
float planeSpeed = planeVelocity.Length();
if (planeSpeed > MaxSpeed) planeVelocity *= MaxSpeed / planeSpeed;
}
else

View File

@ -10,6 +10,12 @@ public class InteractionComponent: Component
[Signal]
delegate void InteractionEnd(Spatial owningEntity, Spatial targetEntity);
public void EndInteraction()
{
hasStopped = true;
}
public bool hasStopped = false;
public Spatial OwningEntity;
public Spatial TargetEntity;
}

View File

@ -27,10 +27,8 @@ public class TaskQueueComponent : Component
do
{
var currentTask = Queue.Peek();
var interactionTask = currentTask as InteractionTask;
if (interactionTask != null) EmitSignal("StartInteraction", entity, interactionTask.TargetEntity);
if (currentTask.PerformTask(entity, delta))
if (currentTask.PerformTask(entity, this, delta))
Queue.Dequeue();
else
break;
@ -43,7 +41,7 @@ public class TaskQueueComponent : Component
/// Executes a Task on the specified entity.
/// </summary>
/// <returns>true when the Task is complete, false otherwise</returns>
public abstract bool PerformTask(Entity entity, float delta);
public abstract bool PerformTask(Entity entity, TaskQueueComponent taskQueueComponent, float delta);
}
/// <summary>
@ -59,7 +57,7 @@ public class TaskQueueComponent : Component
NavigationPoint = navigationPoint;
}
public override bool PerformTask(Entity entity, float delta)
public override bool PerformTask(Entity entity, TaskQueueComponent taskQueueComponent, float delta)
{
return NavigationPoint.IsReached(entity.GlobalTransform);
}
@ -74,8 +72,10 @@ public class TaskQueueComponent : Component
TargetEntity = entity;
}
public override bool PerformTask(Entity entity, float delta)
public override bool PerformTask(Entity entity, TaskQueueComponent taskQueueComponent, float delta)
{
taskQueueComponent.EmitSignal("StartInteraction", entity, TargetEntity);
return true;
}
}

View File

@ -64,7 +64,10 @@ public class Player : Entity, IInteractionInterface
stateMachine.Start("Idle");
_toolAttachement = (BoneAttachment)FindNode("ToolAttachement");
if (_toolAttachement == null) GD.PushWarning("No ToolAttachement found!");
if (_toolAttachement == null)
{
GD.PushWarning("No ToolAttachement found!");
}
_debugGeometry = (DebugGeometry)FindNode("DebugGeometry");
}

View File

@ -1,12 +1,13 @@
[gd_scene load_steps=14 format=2]
[gd_scene load_steps=27 format=2]
[ext_resource path="res://entities/Player.cs" type="Script" id=1]
[ext_resource path="res://components/NavigationComponent.cs" type="Script" id=2]
[ext_resource path="res://materials/debug/PlayerPhysicsGeometry.tres" type="Material" id=3]
[ext_resource path="res://assets/Characters/Pirate.tscn" type="PackedScene" id=4]
[ext_resource path="res://assets/Objects/toolAxe.tscn" type="PackedScene" id=4]
[ext_resource path="res://components/WorldInfoComponent.cs" type="Script" id=5]
[ext_resource path="res://utils/DebugGeometry.cs" type="Script" id=6]
[ext_resource path="res://components/MovableComponent.tscn" type="PackedScene" id=7]
[ext_resource path="res://assets/CreatusPiratePack/Modified/Pirate1_Rigged.glb" type="PackedScene" id=8]
[sub_resource type="CapsuleShape" id=7]
radius = 0.27
@ -23,12 +24,315 @@ radius = 1.5
[sub_resource type="SphereShape" id=23]
radius = 0.1
[sub_resource type="AnimationNodeStateMachinePlayback" id=28]
[sub_resource type="SpatialMaterial" id=25]
flags_unshaded = true
vertex_color_use_as_albedo = true
[sub_resource type="Animation" id=29]
resource_name = "ArmatureAction"
length = 0.791667
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature/Skeleton:HandTip.R")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, -6.33299e-08, 5.96046e-08, -8.72095e-09, 5.15244e-08, -0.167621, -2.38312e-08, 0.985852, 1, 1, 1, 0.791667, 1, -6.33299e-08, 5.96046e-08, -8.72095e-09, 5.15244e-08, -0.167621, -2.38312e-08, 0.985852, 1, 1, 1 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature/Skeleton:LowerArm.R")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = PoolRealArray( 0, 1, 2.98023e-08, 2.98023e-08, 1.02445e-07, 1.49012e-08, -2.98023e-08, -7.45058e-09, 1, 1, 1, 1, 0.0666667, 1, -1.49012e-08, 1.19209e-07, 9.31323e-09, 0.00109829, -8.64304e-05, 0.0102987, 0.999946, 1, 1, 1, 0.133333, 1, -4.47035e-08, -5.96046e-08, 8.56817e-08, 0.00783155, -0.00169418, 0.0734387, 0.997268, 1, 1, 1, 0.2, 1, -1.04308e-07, -1.19209e-07, 5.58794e-09, 0.018495, -0.0080773, 0.173433, 0.984639, 1, 1, 1, 0.266667, 1, -1.49012e-08, 8.9407e-08, -1.67638e-08, 0.0280373, -0.0229293, 0.262915, 0.964139, 1, 1, 1, 0.333333, 1, -1.3411e-07, 1.78814e-07, 1.15484e-07, 0.033043, -0.0493204, 0.309854, 0.948929, 1, 1, 1, 0.4, 1, -8.9407e-08, 5.96046e-08, 7.82311e-08, -0.15378, -0.132786, 0.29174, 0.93467, 1, 1, 1, 0.466667, 1, -1.19209e-07, -2.98023e-08, 3.35276e-08, -0.407158, -0.216318, 0.236834, 0.855184, 1, 1, 1, 0.533333, 1, -1.04308e-07, 5.96046e-08, 8.56817e-08, -0.452066, -0.143661, 0.218081, 0.8529, 1, 1, 1, 0.6, 1, -8.9407e-08, -5.96046e-08, 6.89179e-08, -0.315312, -0.00422263, 0.192105, 0.929331, 1, 1, 1, 0.666667, 1, -5.96046e-08, 5.96046e-08, 1.95578e-07, -0.071726, -0.000218779, 0.0546704, 0.995925, 1, 1, 1, 0.733333, 1, -8.9407e-08, 2.98023e-08, 2.98023e-08, 1.49012e-08, -2.98023e-08, 4.44089e-16, 1, 1, 1, 1, 0.791667, 1, 2.98023e-08, 2.98023e-08, 1.02445e-07, 1.49012e-08, -2.98023e-08, -7.45058e-09, 1, 1, 1, 1 )
tracks/2/type = "transform"
tracks/2/path = NodePath("Armature/Skeleton:UpperArm.R")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = PoolRealArray( 0, 1, -2.98023e-08, -2.98023e-08, -5.96046e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 1.49012e-08, -2.98023e-08, -4.47035e-08, 0.0108857, -6.76363e-05, 0.000112621, 0.999941, 1, 1, 1, 0.133333, 1, 0, -2.98023e-08, -5.96046e-08, 0.0781541, -0.00133826, 0.00222821, 0.996938, 1, 1, 1, 0.2, 1, 1.49012e-08, 2.98023e-08, -1.49012e-08, 0.185823, -0.00642065, 0.0106907, 0.982504, 1, 1, 1, 0.266667, 1, 2.98023e-08, 0, -2.98023e-08, 0.281247, -0.018186, 0.0302806, 0.958985, 1, 1, 1, 0.333333, 1, 1.19209e-07, 5.96046e-08, -5.96046e-08, 0.326813, -0.0385876, 0.0642504, 0.942113, 1, 1, 1, 0.4, 1, 0, 0, 0, 0.27597, -0.130105, 0.14414, 0.941348, 1, 1, 1, 0.466667, 1, 5.96046e-08, -5.96046e-08, 2.98023e-08, 0.155307, -0.238877, 0.223903, 0.932033, 1, 1, 1, 0.533333, 1, 8.9407e-08, 0, 0, 0.00938215, -0.220572, 0.130595, 0.966543, 1, 1, 1, 0.6, 1, 1.49012e-08, 2.98023e-08, -7.45058e-08, -0.0448046, -0.0741939, -0.0355394, 0.995603, 1, 1, 1, 0.666667, 1, -4.47035e-08, -2.98023e-08, 7.45058e-08, -0.0129521, -0.00546457, -0.0102737, 0.999848, 1, 1, 1, 0.733333, 1, -2.98023e-08, -1.19209e-07, 2.98023e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1, 0.791667, 1, -2.98023e-08, -2.98023e-08, -5.96046e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1 )
tracks/3/type = "transform"
tracks/3/path = NodePath("Armature/Skeleton:Shoulder.R")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 4.25331e-10, 2.61906e-11, 0, 0.000588988, -0.00134978, -0.00209551, 0.999997, 1, 1, 1, 0.133333, 1, 3.42889e-09, -1.28054e-10, 0, 0.00420515, -0.00963742, -0.0149611, 0.999833, 1, 1, 1, 0.266667, 1, 1.60017e-08, 3.63217e-09, 1.19209e-07, 0.0152085, -0.0348548, -0.0541085, 0.997811, 1, 1, 1, 0.333333, 1, 1.38597e-08, -2.8136e-09, 0, 0.017721, -0.0406132, -0.0630476, 0.997026, 1, 1, 1, 0.4, 1, 4.95234e-10, -3.39933e-09, 0, -0.0677883, 0.0291052, 0.0488595, 0.996078, 1, 1, 1, 0.466667, 1, 3.0251e-08, 7.71792e-11, 0, -0.186396, 0.126963, 0.20584, 0.952243, 1, 1, 1, 0.533333, 1, 1.833e-08, 4.54755e-09, 1.19209e-07, -0.188148, 0.128888, 0.242103, 0.943066, 1, 1, 1, 0.6, 1, 8.41146e-09, -9.31308e-11, 0, -0.0808999, 0.0423329, 0.227882, 0.969398, 1, 1, 1, 0.666667, 1, 6.40912e-09, 7.10543e-15, 1.19209e-07, -0.00230095, -0.0193147, 0.175059, 0.984366, 1, 1, 1, 0.733333, 1, -4.16577e-10, 0, 0, -0.000324101, -0.00873649, 0.0635702, 0.997939, 1, 1, 1, 0.791667, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 )
tracks/4/type = "transform"
tracks/4/path = NodePath("Armature/Skeleton:HandTip.L")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = PoolRealArray( 0, 1, 0, 0, 3.81116e-09, -1.86265e-09, 7.45058e-09, -1.17579e-08, 1, 1, 1, 1, 0.791667, 1, 0, 0, 3.81116e-09, -1.86265e-09, 7.45058e-09, -1.17579e-08, 1, 1, 1, 1 )
tracks/5/type = "transform"
tracks/5/path = NodePath("Armature/Skeleton:LowerArm.L")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/keys = PoolRealArray( 0, 1, -8.9407e-08, 2.98023e-08, 1.02445e-07, -1.49012e-08, -1.49012e-08, -2.98023e-08, 1, 1, 1, 1, 0.791667, 1, -8.9407e-08, 2.98023e-08, 1.02445e-07, -1.49012e-08, -1.49012e-08, -2.98023e-08, 1, 1, 1, 1 )
tracks/6/type = "transform"
tracks/6/path = NodePath("Armature/Skeleton:UpperArm.L")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/keys = PoolRealArray( 0, 1, -4.47035e-08, -2.98023e-08, 1.49012e-08, -1.49012e-08, -5.21541e-08, 1.49012e-08, 1, 1, 1, 1, 0.791667, 1, -4.47035e-08, -2.98023e-08, 1.49012e-08, -1.49012e-08, -5.21541e-08, 1.49012e-08, 1, 1, 1, 1 )
tracks/7/type = "transform"
tracks/7/path = NodePath("Armature/Skeleton:Shoulder.L")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/keys = PoolRealArray( 0, 1, 2.97255e-31, -2.64698e-23, 0, 0, 0, 0, 1, 1, 1, 1, 0.791667, 1, 2.97255e-31, -2.64698e-23, 0, 0, 0, 0, 1, 1, 1, 1 )
tracks/8/type = "transform"
tracks/8/path = NodePath("Armature/Skeleton:Base")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, -0.00262969, -0.00462533, -7.91099e-05, 0.999986, 1, 1, 1, 0.133333, 1, 0, 0, 0, -0.0187834, -0.0330379, -0.000768041, 0.999277, 1, 1, 1, 0.266667, 1, 0, 0, 0, -0.0678217, -0.119291, -0.00597111, 0.990522, 1, 1, 1, 0.333333, 1, 0, 0, 0, -0.0791032, -0.139134, -0.0111504, 0.987046, 1, 1, 1, 0.4, 1, 0, 0, 0, 0.00167779, -0.0294607, -0.0182862, 0.999397, 1, 1, 1, 0.466667, 1, 0, 0, 0, 0.116381, 0.127423, -0.0233002, 0.984721, 1, 1, 1, 0.533333, 1, 0, 0, 0, 0.120038, 0.144348, -0.0211955, 0.981991, 1, 1, 1, 0.6, 1, 0, 0, 0, 0.0228862, 0.060128, -0.00882898, 0.997889, 1, 1, 1, 0.666667, 1, 0, 0, 0, -0.0459424, -8.28055e-25, 1.02013e-17, 0.998944, 1, 1, 1, 0.733333, 1, 0, 0, 0, -0.00918794, -3.32825e-25, 4.08026e-18, 0.999958, 1, 1, 1, 0.791667, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 )
[sub_resource type="Animation" id=30]
resource_name = "Hit-loop"
length = 0.791667
loop = true
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature/Skeleton:HandTip.R")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, -6.33299e-08, 5.96046e-08, -8.72095e-09, 5.15244e-08, -0.167621, -2.38312e-08, 0.985852, 1, 1, 1, 0.333333, 1, -4.84288e-08, 8.9407e-08, -6.55356e-08, 2.541e-08, -0.167621, -2.04777e-08, 0.985852, 1, 1, 1, 0.4, 1, -4.84288e-08, 5.96046e-08, -1.18914e-08, 0.0547672, -0.0111317, -0.0100956, 0.998386, 1, 1, 1, 0.466667, 1, -3.72529e-08, 5.96046e-08, -7.89466e-08, 0.130055, 0.212042, -0.0239739, 0.968271, 1, 1, 1, 0.533333, 1, -6.70552e-08, 8.9407e-08, -3.72234e-08, 0.146974, 0.263647, -0.0270928, 0.952971, 1, 1, 1, 0.791667, 1, -6.33299e-08, 5.96046e-08, -8.72095e-09, 0.146974, 0.263647, -0.0270928, 0.952971, 1, 1, 1 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature/Skeleton:LowerArm.R")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = PoolRealArray( 0, 1, 2.98023e-08, 2.98023e-08, 1.02445e-07, 1.49012e-08, -2.98023e-08, -7.45058e-09, 1, 1, 1, 1, 0.0666667, 1, -1.49012e-08, 0, 7.63685e-08, -0.00586834, 0.0157643, 0.00645119, 0.999838, 1, 1, 1, 0.133333, 1, -1.49012e-07, 1.19209e-07, 1.21072e-07, -0.0437508, 0.117176, 0.0471372, 0.991027, 1, 1, 1, 0.2, 1, -1.04308e-07, 0, 1.86265e-09, -0.108414, 0.289036, 0.113213, 0.944398, 1, 1, 1, 0.266667, 1, -1.49012e-07, -2.98023e-08, 1.47149e-07, -0.1704, 0.450991, 0.168978, 0.859661, 1, 1, 1, 0.333333, 1, 2.98023e-08, 2.98023e-08, 3.91155e-08, -0.211609, 0.553687, 0.192556, 0.782032, 1, 1, 1, 0.4, 1, -7.45058e-08, 5.96046e-08, 1.49012e-08, -0.230545, 0.604045, 0.0585778, 0.760623, 1, 1, 1, 0.466667, 1, -5.96046e-08, 5.96046e-08, 7.26432e-08, -0.254046, 0.611523, -0.134534, 0.737158, 1, 1, 1, 0.533333, 1, -8.9407e-08, 0, 7.26432e-08, -0.3508, 0.55588, -0.0965608, 0.747404, 1, 1, 1, 0.6, 1, -7.45058e-08, 8.9407e-08, 8.56817e-08, -0.389927, 0.324616, 0.0259209, 0.861342, 1, 1, 1, 0.666667, 1, -1.49012e-08, -8.9407e-08, 8.00937e-08, -0.113728, 0.0644829, 0.00756021, 0.991388, 1, 1, 1, 0.733333, 1, -4.47035e-08, 8.9407e-08, 5.02914e-08, 2.98023e-08, -7.45058e-08, -7.45058e-09, 1, 1, 1, 1, 0.791667, 1, 2.98023e-08, 2.98023e-08, 1.02445e-07, 1.49012e-08, -2.98023e-08, -7.45058e-09, 1, 1, 1, 1 )
tracks/2/type = "transform"
tracks/2/path = NodePath("Armature/Skeleton:UpperArm.R")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = PoolRealArray( 0, 1, -2.98023e-08, -2.98023e-08, -5.96046e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 4.47035e-08, 0, -7.45058e-08, 0.011767, 0.0105079, 0.00820402, 0.999842, 1, 1, 1, 0.133333, 1, -8.9407e-08, -1.49012e-07, 4.47035e-08, 0.0859668, 0.0767673, 0.0602297, 0.991508, 1, 1, 1, 0.2, 1, 2.98023e-08, -1.19209e-07, 5.96046e-08, 0.206183, 0.184119, 0.145576, 0.949945, 1, 1, 1, 0.266667, 1, 7.45058e-08, -5.96046e-08, 7.45058e-08, 0.307592, 0.274676, 0.220059, 0.884033, 1, 1, 1, 0.333333, 1, -1.78814e-07, -1.19209e-07, 0, 0.351106, 0.313534, 0.257053, 0.844006, 1, 1, 1, 0.4, 1, 8.9407e-08, -5.96046e-08, 7.45058e-08, 0.188191, 0.208628, 0.276531, 0.919015, 1, 1, 1, 0.466667, 1, 2.98023e-08, 0, -2.98023e-08, -0.0637092, 0.0115809, 0.273677, 0.959639, 1, 1, 1, 0.533333, 1, 5.96046e-08, 0, -2.98023e-08, -0.101567, -0.0901974, 0.143595, 0.98027, 1, 1, 1, 0.6, 1, 2.98023e-08, -2.98023e-08, -2.98023e-08, -0.0373082, -0.0907643, -0.0355061, 0.99454, 1, 1, 1, 0.666667, 1, -4.47035e-08, -2.98023e-08, 7.45058e-08, -0.00362256, -0.0262561, -0.0102711, 0.999596, 1, 1, 1, 0.733333, 1, 2.98023e-08, -5.96046e-08, 2.98023e-08, -1.49012e-08, -1.49012e-08, 1.49012e-08, 1, 1, 1, 1, 0.791667, 1, -2.98023e-08, -2.98023e-08, -5.96046e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1 )
tracks/3/type = "transform"
tracks/3/path = NodePath("Armature/Skeleton:Shoulder.R")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 4.25331e-10, 2.61906e-11, 0, 0.00658544, 0.00890813, -0.000488712, 0.999939, 1, 1, 1, 0.133333, 1, 3.42889e-09, -1.28054e-10, 0, 0.0472153, 0.0638686, -0.0035038, 0.996835, 1, 1, 1, 0.2, 1, -1.0298e-09, 1.26893e-09, 0, 0.112056, 0.15158, -0.0083152, 0.982038, 1, 1, 1, 0.266667, 1, 1.60017e-08, 3.63217e-09, 1.19209e-07, 0.169552, 0.229355, -0.0125817, 0.958379, 1, 1, 1, 0.333333, 1, 1.38597e-08, -2.8136e-09, 0, 0.197783, 0.267544, -0.0146766, 0.942914, 1, 1, 1, 0.4, 1, 4.95234e-10, -3.39933e-09, 0, 0.0396571, 0.273067, 0.068117, 0.95876, 1, 1, 1, 0.466667, 1, 3.0251e-08, 7.71792e-11, 0, -0.187959, 0.251319, 0.181668, 0.931937, 1, 1, 1, 0.533333, 1, 1.833e-08, 4.54755e-09, 1.19209e-07, -0.213406, 0.19015, 0.209136, 0.935181, 1, 1, 1, 0.6, 1, 8.41146e-09, -9.31308e-11, 0, -0.0919332, 0.0630301, 0.203615, 0.972685, 1, 1, 1, 0.666667, 1, 6.40912e-09, 7.10543e-15, 1.19209e-07, -0.00230095, -0.0193147, 0.175059, 0.984366, 1, 1, 1, 0.733333, 1, -4.16577e-10, 0, 0, -0.000323432, -0.00872148, 0.0715194, 0.997401, 1, 1, 1, 0.791667, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 )
tracks/4/type = "transform"
tracks/4/path = NodePath("Armature/Skeleton:HandTip.L")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = PoolRealArray( 0, 1, 0, 0, 3.81116e-09, -1.86265e-09, 7.45058e-09, -1.17579e-08, 1, 1, 1, 1, 0.791667, 1, 0, 0, 3.81116e-09, -1.86265e-09, 7.45058e-09, -1.17579e-08, 1, 1, 1, 1 )
tracks/5/type = "transform"
tracks/5/path = NodePath("Armature/Skeleton:LowerArm.L")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/keys = PoolRealArray( 0, 1, -8.9407e-08, 2.98023e-08, 1.02445e-07, -1.49012e-08, -1.49012e-08, -2.98023e-08, 1, 1, 1, 1, 0.0666667, 1, -5.96046e-08, 1.19209e-07, 9.12696e-08, -0.00935066, 2.03391e-05, 0.000315729, 0.999956, 1, 1, 1, 0.133333, 1, -1.49012e-08, 2.98023e-08, 8.56817e-08, -0.0671479, 0.000401975, 0.00227173, 0.99774, 1, 1, 1, 0.266667, 1, -5.96046e-08, 5.96046e-08, 1.00583e-07, -0.242279, 0.00547677, 0.0082618, 0.970156, 1, 1, 1, 0.333333, 1, 1.49012e-08, 5.96046e-08, 1.69501e-07, -0.280737, 0.0115882, 0.00965797, 0.959666, 1, 1, 1, 0.4, 1, -2.98023e-08, 5.96046e-08, 6.51926e-08, -0.211918, 0.0208799, 0.00983568, 0.977015, 1, 1, 1, 0.466667, 1, 2.98023e-08, 5.96046e-08, 9.12696e-08, -0.0968075, 0.0283259, 0.00989634, 0.994851, 1, 1, 1, 0.533333, 1, 5.96046e-08, 5.96046e-08, 4.47035e-08, -0.0323694, 0.0271555, 0.0090094, 0.999066, 1, 1, 1, 0.6, 1, -1.04308e-07, 2.98023e-08, 3.53903e-08, -0.00820132, 0.0156167, 0.00518115, 0.999831, 1, 1, 1, 0.666667, 1, 1.49012e-08, 0, -9.49949e-08, -0.000421983, 0.00306127, 0.00101563, 0.999995, 1, 1, 1, 0.733333, 1, -2.98023e-08, 0, 9.31323e-08, -2.98023e-08, 4.47035e-08, -4.47035e-08, 1, 1, 1, 1, 0.791667, 1, -8.9407e-08, 2.98023e-08, 1.02445e-07, -1.49012e-08, -1.49012e-08, -2.98023e-08, 1, 1, 1, 1 )
tracks/6/type = "transform"
tracks/6/path = NodePath("Armature/Skeleton:UpperArm.L")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/keys = PoolRealArray( 0, 1, -4.47035e-08, -2.98023e-08, 1.49012e-08, -1.49012e-08, -5.21541e-08, 1.49012e-08, 1, 1, 1, 1, 0.0666667, 1, -8.9407e-08, -8.9407e-08, -1.49012e-08, -0.00947541, -0.00323637, -0.00573202, 0.999934, 1, 1, 1, 0.133333, 1, -8.9407e-08, -8.9407e-08, -2.98023e-08, -0.0679954, -0.0232241, -0.0411327, 0.996567, 1, 1, 1, 0.2, 1, -7.45058e-08, 5.96046e-08, -5.96046e-08, -0.16145, -0.0551437, -0.0976665, 0.980487, 1, 1, 1, 0.266667, 1, -2.98023e-08, 0, -5.96046e-08, -0.244128, -0.0833825, -0.147681, 0.954798, 1, 1, 1, 0.333333, 1, 2.98023e-08, -8.9407e-08, -2.98023e-08, -0.284491, -0.0971685, -0.172098, 0.938086, 1, 1, 1, 0.4, 1, -5.96046e-08, -8.9407e-08, -2.98023e-08, -0.0658813, 0.00482479, -0.0859779, 0.994105, 1, 1, 1, 0.466667, 1, 7.45058e-08, 0, 4.47035e-08, 0.258148, 0.151193, 0.0735815, 0.95136, 1, 1, 1, 0.533333, 1, -4.47035e-08, 0, -7.45058e-08, 0.266396, 0.172662, 0.156906, 0.935201, 1, 1, 1, 0.6, 1, 2.98023e-08, -2.98023e-08, 2.98023e-08, 0.0838445, 0.112623, 0.14957, 0.978731, 1, 1, 1, 0.666667, 1, 2.98023e-08, 2.98023e-08, -2.98023e-08, 0.00431782, 0.0243932, 0.0432344, 0.998758, 1, 1, 1, 0.733333, 1, -4.47035e-08, -8.9407e-08, 1.49012e-08, -1.49012e-08, -8.19564e-08, 1.49012e-08, 1, 1, 1, 1, 0.791667, 1, -4.47035e-08, -2.98023e-08, 1.49012e-08, -1.49012e-08, -5.21541e-08, 1.49012e-08, 1, 1, 1, 1 )
tracks/7/type = "transform"
tracks/7/path = NodePath("Armature/Skeleton:Shoulder.L")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/keys = PoolRealArray( 0, 1, 2.97255e-31, -2.64698e-23, 0, 0, 0, 0, 1, 1, 1, 1, 0.791667, 1, 2.97255e-31, -2.64698e-23, 0, 0, 0, 0, 1, 1, 1, 1 )
tracks/8/type = "transform"
tracks/8/path = NodePath("Armature/Skeleton:Base")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.0666667, 1, 0, 0, 0, -0.00262969, -0.00462533, -7.91099e-05, 0.999986, 1, 1, 1, 0.133333, 1, 0, 0, 0, -0.0187834, -0.0330379, -0.000768041, 0.999277, 1, 1, 1, 0.266667, 1, 0, 0, 0, -0.0678217, -0.119291, -0.00597111, 0.990522, 1, 1, 1, 0.333333, 1, 0, 0, 0, -0.0791032, -0.139134, -0.0111504, 0.987046, 1, 1, 1, 0.4, 1, 0, 0, 0, 0.00167779, -0.0294607, -0.0182862, 0.999397, 1, 1, 1, 0.466667, 1, 0, 0, 0, 0.116381, 0.127423, -0.0233002, 0.984721, 1, 1, 1, 0.533333, 1, 0, 0, 0, 0.120038, 0.144348, -0.0211955, 0.981991, 1, 1, 1, 0.6, 1, 0, 0, 0, 0.0228862, 0.060128, -0.00882898, 0.997889, 1, 1, 1, 0.666667, 1, 0, 0, 0, -0.0459424, -8.28055e-25, 1.02013e-17, 0.998944, 1, 1, 1, 0.733333, 1, 0, 0, 0, -0.00918794, -3.32825e-25, 4.08026e-18, 0.999958, 1, 1, 1, 0.791667, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 )
[sub_resource type="Animation" id=31]
resource_name = "Idle-loop"
length = 0.333333
loop = true
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature/Skeleton:HandTip.R")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, -6.33299e-08, 5.96046e-08, -8.72095e-09, -4.65661e-10, -3.72529e-09, -1.80444e-09, 1, 1, 1, 1, 0.333333, 1, -6.33299e-08, 5.96046e-08, -8.72095e-09, -4.65661e-10, -3.72529e-09, -1.80444e-09, 1, 1, 1, 1 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature/Skeleton:LowerArm.R")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = PoolRealArray( 0, 1, 2.98023e-08, 2.98023e-08, 1.02445e-07, 1.49012e-08, -2.98023e-08, -7.45058e-09, 1, 1, 1, 1, 0.333333, 1, 2.98023e-08, 2.98023e-08, 1.02445e-07, 1.49012e-08, -2.98023e-08, -7.45058e-09, 1, 1, 1, 1 )
tracks/2/type = "transform"
tracks/2/path = NodePath("Armature/Skeleton:UpperArm.R")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = PoolRealArray( 0, 1, -2.98023e-08, -2.98023e-08, -5.96046e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1, 0.333333, 1, -2.98023e-08, -2.98023e-08, -5.96046e-08, -1.49012e-08, 0, 0, 1, 1, 1, 1 )
tracks/3/type = "transform"
tracks/3/path = NodePath("Armature/Skeleton:Shoulder.R")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.333333, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 )
tracks/4/type = "transform"
tracks/4/path = NodePath("Armature/Skeleton:HandTip.L")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = PoolRealArray( 0, 1, 0, 0, 3.81116e-09, -1.86265e-09, 7.45058e-09, -1.17579e-08, 1, 1, 1, 1, 0.333333, 1, 0, 0, 3.81116e-09, -1.86265e-09, 7.45058e-09, -1.17579e-08, 1, 1, 1, 1 )
tracks/5/type = "transform"
tracks/5/path = NodePath("Armature/Skeleton:LowerArm.L")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/keys = PoolRealArray( 0, 1, -8.9407e-08, 2.98023e-08, 1.02445e-07, -1.49012e-08, -1.49012e-08, -2.98023e-08, 1, 1, 1, 1, 0.333333, 1, -8.9407e-08, 2.98023e-08, 1.02445e-07, -1.49012e-08, -1.49012e-08, -2.98023e-08, 1, 1, 1, 1 )
tracks/6/type = "transform"
tracks/6/path = NodePath("Armature/Skeleton:UpperArm.L")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/keys = PoolRealArray( 0, 1, -4.47035e-08, -2.98023e-08, 1.49012e-08, -1.49012e-08, -5.21541e-08, 1.49012e-08, 1, 1, 1, 1, 0.333333, 1, -4.47035e-08, -2.98023e-08, 1.49012e-08, -1.49012e-08, -5.21541e-08, 1.49012e-08, 1, 1, 1, 1 )
tracks/7/type = "transform"
tracks/7/path = NodePath("Armature/Skeleton:Shoulder.L")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/keys = PoolRealArray( 0, 1, 2.97255e-31, -2.64698e-23, 0, 0, 0, 0, 1, 1, 1, 1, 0.333333, 1, 2.97255e-31, -2.64698e-23, 0, 0, 0, 0, 1, 1, 1, 1 )
tracks/8/type = "transform"
tracks/8/path = NodePath("Armature/Skeleton:Base")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/keys = PoolRealArray( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0.333333, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 )
[sub_resource type="Animation" id=32]
resource_name = "Interaction-loop"
length = 1.04167
loop = true
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature/Skeleton:HandTip.R")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, -3.35276e-08, 0, -1.23743e-07, -0.0397685, -0.000299317, -0.0326481, 0.998675, 1, 1, 1, 0.0666667, 1, -4.09782e-08, 5.96046e-08, -4.10418e-08, -0.0388719, -0.000223445, -0.0301956, 0.998788, 1, 1, 1, 0.2, 1, -7.45058e-08, 8.9407e-08, -7.08441e-08, -0.0304912, 0.000484843, -0.00729624, 0.999508, 1, 1, 1, 0.266667, 1, -2.23517e-08, 5.96046e-08, -4.59312e-08, -0.0351766, 0.000270068, -0.0172153, 0.999233, 1, 1, 1, 0.333333, 1, -5.96046e-08, 5.96046e-08, -2.57215e-08, -0.0444978, -0.000179588, -0.0373135, 0.998312, 1, 1, 1, 0.4, 1, -2.98023e-08, 5.96046e-08, 6.6526e-08, -0.0451622, -0.000199814, -0.0386437, 0.998232, 1, 1, 1, 0.533333, 1, -2.23517e-08, 5.96046e-08, 4.92034e-08, -0.026639, 0.000803509, 0.00223312, 0.999642, 1, 1, 1, 0.6, 1, -4.84288e-08, 5.96046e-08, 4.51055e-08, -0.0276825, 0.000774615, 0.00157664, 0.999615, 1, 1, 1, 0.666667, 1, -8.56817e-08, 8.9407e-08, 6.34526e-08, -0.0308762, 0.000653472, -0.00238591, 0.99952, 1, 1, 1, 0.733333, 1, -3.72529e-08, 5.96046e-08, 2.53151e-08, -0.0314008, 0.000622581, -0.0031118, 0.999502, 1, 1, 1, 0.866667, 1, -5.21541e-08, 5.96046e-08, -4.25319e-08, -0.0278308, 0.00065537, 0.000619829, 0.999612, 1, 1, 1, 0.933333, 1, -4.84288e-08, 0, -2.25217e-09, -0.0312516, 0.000375793, -0.0090599, 0.99947, 1, 1, 1, 1, 1, -6.33299e-08, 0, 6.67123e-08, -0.0378865, -0.000149982, -0.0274314, 0.998905, 1, 1, 1, 1.04167, 1, -3.35276e-08, 0, -1.23743e-07, -0.0397685, -0.000299317, -0.0326481, 0.998675, 1, 1, 1 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature/Skeleton:LowerArm.R")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = PoolRealArray( 0, 1, -8.9407e-08, -5.96046e-08, -5.02914e-08, -0.182251, -0.00221143, -0.121182, 0.975753, 1, 1, 1, 0.0666667, 1, -5.96046e-08, 5.96046e-08, -5.58794e-09, -0.178429, -0.000926142, -0.112629, 0.977485, 1, 1, 1, 0.2, 1, -1.49012e-08, 0, 3.72529e-09, -0.141964, 0.0110719, -0.0323065, 0.989282, 1, 1, 1, 0.266667, 1, -1.04308e-07, 1.49012e-07, 6.51926e-08, -0.162254, 0.00780114, -0.065411, 0.984548, 1, 1, 1, 0.333333, 1, -1.49012e-08, 8.9407e-08, 2.47732e-07, -0.201968, 0.000834197, -0.132512, 0.970386, 1, 1, 1, 0.4, 1, 0, 2.98023e-08, 9.12696e-08, -0.204438, 0.000619536, -0.136288, 0.969345, 1, 1, 1, 0.533333, 1, -5.96046e-08, -2.98023e-08, -2.04891e-08, -0.121433, 0.0170418, 0.00665036, 0.992431, 1, 1, 1, 0.6, 1, -1.49012e-08, 0, 3.35276e-08, -0.127274, 0.0164745, 0.00237392, 0.991728, 1, 1, 1, 0.666667, 1, -4.47035e-08, -2.98023e-08, 4.09782e-08, -0.143827, 0.0142825, -0.015193, 0.989383, 1, 1, 1, 0.733333, 1, -5.96046e-08, 2.98023e-08, 1.11759e-08, -0.146947, 0.0135418, -0.0191313, 0.988867, 1, 1, 1, 0.866667, 1, -7.45058e-08, -5.96046e-08, -2.42144e-08, -0.132294, 0.0134387, -0.00933063, 0.991075, 1, 1, 1, 0.933333, 1, -5.96046e-08, 8.9407e-08, 2.42144e-08, -0.146841, 0.0087808, -0.0420172, 0.988228, 1, 1, 1, 1, 1, -2.98023e-08, 8.9407e-08, 1.13621e-07, -0.174543, 0.000209678, -0.103758, 0.979168, 1, 1, 1, 1.04167, 1, -8.9407e-08, -5.96046e-08, -5.02914e-08, -0.182251, -0.00221143, -0.121182, 0.975753, 1, 1, 1 )
tracks/2/type = "transform"
tracks/2/path = NodePath("Armature/Skeleton:UpperArm.R")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = PoolRealArray( 0, 1, 4.47035e-08, -2.98023e-08, 0, -0.257278, 0.0958797, 0.0591961, 0.959745, 1, 1, 1, 0.0666667, 1, 1.04308e-07, 5.96046e-08, -4.47035e-08, -0.252958, 0.0959003, 0.0594266, 0.960877, 1, 1, 1, 0.2, 1, 5.96046e-08, -2.98023e-08, 0, -0.212377, 0.0968744, 0.0615156, 0.970426, 1, 1, 1, 0.266667, 1, -4.47035e-08, -5.96046e-08, 4.47035e-08, -0.233182, 0.102396, 0.0611982, 0.965089, 1, 1, 1, 0.333333, 1, 7.45058e-08, -2.98023e-08, -4.47035e-08, -0.274556, 0.111221, 0.060385, 0.953206, 1, 1, 1, 0.4, 1, 4.47035e-08, -2.98023e-08, -1.49012e-08, -0.274427, 0.112329, 0.0606839, 0.953095, 1, 1, 1, 0.533333, 1, -1.49012e-08, -5.96046e-08, -7.45058e-08, -0.162406, 0.0994839, 0.0673923, 0.97938, 1, 1, 1, 0.6, 1, 5.96046e-08, 2.98023e-08, -8.9407e-08, -0.177495, 0.10122, 0.0696684, 0.97642, 1, 1, 1, 0.666667, 1, 1.04308e-07, 1.19209e-07, -1.49012e-08, -0.213174, 0.105294, 0.0704232, 0.968768, 1, 1, 1, 0.733333, 1, -2.98023e-08, -8.9407e-08, 0, -0.221933, 0.105306, 0.070184, 0.966815, 1, 1, 1, 0.8, 1, 1.78814e-07, 2.98023e-08, -1.19209e-07, -0.215222, 0.0996311, 0.068472, 0.969054, 1, 1, 1, 0.866667, 1, 4.47035e-08, 0, -4.47035e-08, -0.209579, 0.0948555, 0.065478, 0.970975, 1, 1, 1, 0.933333, 1, 1.49012e-08, 5.96046e-08, 1.49012e-08, -0.223354, 0.0949247, 0.0622329, 0.968106, 1, 1, 1, 1, 1, 4.47035e-08, 2.98023e-08, -4.47035e-08, -0.249803, 0.0956794, 0.0597299, 0.961705, 1, 1, 1, 1.04167, 1, 4.47035e-08, -2.98023e-08, 0, -0.257278, 0.0958797, 0.0591961, 0.959745, 1, 1, 1 )
tracks/3/type = "transform"
tracks/3/path = NodePath("Armature/Skeleton:Shoulder.R")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = PoolRealArray( 0, 1, -1.05356e-08, -1.08299e-08, -1.19209e-07, -0.0304198, 0.217476, 0.165777, 0.961404, 1, 1, 1, 0.0666667, 1, -4.63332e-09, -1.65752e-09, 0, -0.0383344, 0.214758, 0.17136, 0.960752, 1, 1, 1, 0.2, 1, 3.24177e-08, 9.07121e-10, 0, -0.112003, 0.188337, 0.22262, 0.94996, 1, 1, 1, 0.266667, 1, 3.84752e-08, 2.0227e-10, 1.19209e-07, -0.0862053, 0.207715, 0.198912, 0.953864, 1, 1, 1, 0.333333, 1, 1.60653e-08, 5.66796e-09, -1.19209e-07, -0.0324234, 0.244687, 0.149931, 0.957391, 1, 1, 1, 0.4, 1, 3.37837e-08, 3.68154e-10, 0, -0.0242774, 0.246734, 0.139153, 0.958733, 1, 1, 1, 0.466667, 1, 1.92551e-08, -2.56851e-09, 0, -0.0624877, 0.207136, 0.15993, 0.963126, 1, 1, 1, 0.533333, 1, -4.49364e-09, 9.36211e-11, 0, -0.101882, 0.172775, 0.189807, 0.961115, 1, 1, 1, 0.6, 1, 2.33879e-08, -1.31112e-09, 0, -0.114725, 0.179187, 0.214338, 0.953305, 1, 1, 1, 0.666667, 1, 8.36008e-09, -5.16586e-10, 1.19209e-07, -0.118628, 0.197342, 0.233035, 0.944816, 1, 1, 1, 0.733333, 1, 8.60599e-09, -2.88125e-10, 0, -0.120042, 0.200139, 0.246325, 0.940669, 1, 1, 1, 0.8, 1, 2.80561e-09, 3.76021e-09, 0, -0.122382, 0.189051, 0.256239, 0.940013, 1, 1, 1, 0.866667, 1, -1.72062e-08, 6.89179e-09, 0, -0.12399, 0.17982, 0.260764, 0.940369, 1, 1, 1, 0.933333, 1, -6.63562e-10, 1.54396e-09, 0, -0.0967781, 0.190769, 0.233545, 0.948524, 1, 1, 1, 1, 1, 1.62981e-08, -1.06611e-08, 0, -0.0451179, 0.211756, 0.180902, 0.959374, 1, 1, 1, 1.04167, 1, -1.05356e-08, -1.10055e-08, -1.19209e-07, -0.0304198, 0.217476, 0.165777, 0.961404, 1, 1, 1 )
tracks/4/type = "transform"
tracks/4/path = NodePath("Armature/Skeleton:HandTip.L")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = PoolRealArray( 0, 1, -4.47035e-08, 0, 4.84288e-08, -0.0259765, -0.000839302, -0.003693, 0.999655, 1, 1, 1, 0.0666667, 1, -2.23517e-08, -2.98023e-08, 5.06639e-08, -0.027443, -0.000736854, -0.000142364, 0.999623, 1, 1, 1, 0.2, 1, 5.21541e-08, 0, 3.94881e-08, -0.0411107, 0.000219808, 0.0329958, 0.99861, 1, 1, 1, 0.266667, 1, 4.47035e-08, 0, 8.38184e-09, -0.0392144, 0.000149269, 0.0294237, 0.998798, 1, 1, 1, 0.333333, 1, 1.49012e-08, 0, -1.00583e-07, -0.0347486, -4.67662e-05, 0.0205185, 0.999185, 1, 1, 1, 0.4, 1, 7.45058e-09, 5.96046e-08, 3.85568e-08, -0.0338174, -7.52744e-05, 0.0188424, 0.99925, 1, 1, 1, 0.466667, 1, -6.70552e-08, -2.98023e-08, -1.9744e-08, -0.0359106, 7.82064e-05, 0.0239558, 0.999068, 1, 1, 1, 0.6, 1, 2.98023e-08, 5.96046e-08, 1.57392e-08, -0.0426272, 0.000386088, 0.0380744, 0.998365, 1, 1, 1, 0.666667, 1, -6.70552e-08, 5.96046e-08, 7.91624e-09, -0.0449463, 0.000421882, 0.0419609, 0.998108, 1, 1, 1, 0.733333, 1, 3.72529e-08, 0, 2.37488e-08, -0.0453679, 0.000406673, 0.0422226, 0.998078, 1, 1, 1, 0.8, 1, 2.98023e-08, 5.96046e-08, 2.46684e-08, -0.0446239, 0.000279515, 0.0385421, 0.99826, 1, 1, 1, 0.866667, 1, 5.96046e-08, 1.19209e-07, 8.74277e-09, -0.0416562, -2.0318e-06, 0.0290418, 0.99871, 1, 1, 1, 1, 1, 8.9407e-08, 5.96046e-08, 4.47035e-08, -0.0277544, -0.000759324, -0.000433974, 0.999614, 1, 1, 1, 1.04167, 1, -4.47035e-08, 0, -7.45058e-09, -0.0259765, -0.000839302, -0.003693, 0.999655, 1, 1, 1 )
tracks/5/type = "transform"
tracks/5/path = NodePath("Armature/Skeleton:LowerArm.L")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/keys = PoolRealArray( 0, 1, -5.96046e-08, 0, -4.65661e-08, -0.118403, -0.0176198, -0.0117551, 0.99274, 1, 1, 1, 0.0666667, 1, -4.47035e-08, 2.98023e-08, 4.28408e-08, -0.125346, -0.0159979, 0.000566965, 0.991984, 1, 1, 1, 0.2, 1, -4.47035e-08, 5.96046e-08, 8.75443e-08, -0.188895, -0.000707762, 0.115526, 0.975178, 1, 1, 1, 0.266667, 1, 1.49012e-08, 1.49012e-07, 1.24797e-07, -0.180412, -0.00092285, 0.105994, 0.977863, 1, 1, 1, 0.333333, 1, 1.04308e-07, 5.96046e-08, 1.47149e-07, -0.16024, -0.00234829, 0.0804372, 0.983792, 1, 1, 1, 0.4, 1, 0, 2.98023e-08, 7.63685e-08, -0.155967, -0.00228733, 0.076109, 0.984823, 1, 1, 1, 0.466667, 1, -2.98023e-08, 2.98023e-08, 3.91155e-08, -0.165189, 7.06846e-05, 0.0933881, 0.981831, 1, 1, 1, 0.533333, 1, -1.49012e-08, 0, 3.72529e-09, -0.18027, 0.00205633, 0.118129, 0.976496, 1, 1, 1, 0.6, 1, 4.47035e-08, 8.9407e-08, 5.21541e-08, -0.195105, 0.00211556, 0.136242, 0.971271, 1, 1, 1, 0.666667, 1, -1.04308e-07, 5.96046e-08, 1.2666e-07, -0.205658, 0.00164892, 0.145659, 0.967722, 1, 1, 1, 0.733333, 1, -1.49012e-08, 0, 1.06171e-07, -0.207614, 0.000328147, 0.145968, 0.967259, 1, 1, 1, 0.8, 1, 7.45058e-08, 2.98023e-08, 2.98023e-08, -0.204855, -0.00210787, 0.13512, 0.969419, 1, 1, 1, 0.866667, 1, -4.47035e-08, 2.98023e-08, 1.13621e-07, -0.194142, -0.00615519, 0.104122, 0.975413, 1, 1, 1, 0.933333, 1, -1.49012e-08, 8.9407e-08, 4.65661e-08, -0.164634, -0.0117041, 0.0507141, 0.984981, 1, 1, 1, 1, 1, -2.98023e-08, 1.19209e-07, 7.45058e-08, -0.127867, -0.0165417, 8.73655e-06, 0.991653, 1, 1, 1, 1.04167, 1, -5.96046e-08, 0, -4.65661e-08, -0.118403, -0.0176198, -0.0117551, 0.99274, 1, 1, 1 )
tracks/6/type = "transform"
tracks/6/path = NodePath("Armature/Skeleton:UpperArm.L")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/keys = PoolRealArray( 0, 1, -7.45058e-08, -5.96046e-08, -7.45058e-08, -0.158361, -0.0989989, -0.0678321, 0.980061, 1, 1, 1, 0.0666667, 1, -1.49012e-08, -2.98023e-08, -1.49012e-08, -0.167793, -0.0992559, -0.0671212, 0.978513, 1, 1, 1, 0.2, 1, 4.47035e-08, -8.9407e-08, 7.45058e-08, -0.255067, -0.101213, -0.060189, 0.959726, 1, 1, 1, 0.266667, 1, 7.45058e-08, 0, 1.49012e-08, -0.249214, -0.0988195, -0.0599973, 0.961524, 1, 1, 1, 0.333333, 1, 0, -2.98023e-08, 0, -0.232425, -0.0942096, -0.0601037, 0.966173, 1, 1, 1, 0.4, 1, 1.49012e-08, -2.98023e-08, -2.98023e-08, -0.229419, -0.0929231, -0.060043, 0.96702, 1, 1, 1, 0.466667, 1, 5.96046e-08, -1.78814e-07, 2.98023e-08, -0.239933, -0.0934467, -0.0596002, 0.964442, 1, 1, 1, 0.533333, 1, -5.96046e-08, 2.98023e-08, -2.98023e-08, -0.255351, -0.0955354, -0.0592259, 0.960292, 1, 1, 1, 0.6, 1, -1.49012e-08, -5.96046e-08, 2.98023e-08, -0.267343, -0.100811, -0.0595827, 0.95646, 1, 1, 1, 0.666667, 1, 0, 1.19209e-07, -1.19209e-07, -0.274072, -0.107058, -0.0604036, 0.953821, 1, 1, 1, 0.733333, 1, 0, -1.78814e-07, 2.98023e-08, -0.275161, -0.108825, -0.0609397, 0.953273, 1, 1, 1, 0.8, 1, 8.9407e-08, 0, 0, -0.274679, -0.108954, -0.0611182, 0.953386, 1, 1, 1, 0.866667, 1, -4.47035e-08, 2.98023e-08, 1.49012e-08, -0.272769, -0.10898, -0.061592, 0.953901, 1, 1, 1, 0.933333, 1, 5.96046e-08, -5.96046e-08, 1.49012e-08, -0.238162, -0.106197, -0.0639192, 0.963284, 1, 1, 1, 1, 1, -4.47035e-08, 0, -4.47035e-08, -0.175957, -0.100647, -0.0670489, 0.976941, 1, 1, 1, 1.04167, 1, -7.45058e-08, -5.96046e-08, -7.45058e-08, -0.158361, -0.0989989, -0.0678321, 0.980061, 1, 1, 1 )
tracks/7/type = "transform"
tracks/7/path = NodePath("Armature/Skeleton:Shoulder.L")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/keys = PoolRealArray( 0, 1, 2.79397e-08, 1.01133e-08, -1.19209e-07, -0.105738, -0.170004, -0.193499, 0.960456, 1, 1, 1, 0.0666667, 1, 2.18279e-08, 1.09526e-09, 0, -0.0988958, -0.175343, -0.189677, 0.960988, 1, 1, 1, 0.2, 1, -3.05499e-09, -1.92449e-10, 0, -0.0346134, -0.224405, -0.153187, 0.961758, 1, 1, 1, 0.266667, 1, -1.02678e-08, -1.61381e-09, 1.19209e-07, -0.0408083, -0.217599, -0.164468, 0.961216, 1, 1, 1, 0.333333, 1, 1.15833e-08, -1.52068e-09, -1.19209e-07, -0.0566848, -0.201456, -0.18794, 0.959625, 1, 1, 1, 0.4, 1, -6.43776e-09, -4.3874e-10, 0, -0.0594242, -0.197827, -0.193253, 0.959159, 1, 1, 1, 0.466667, 1, 7.97445e-09, 2.0726e-09, 0, -0.0488153, -0.204288, -0.184498, 0.960127, 1, 1, 1, 0.533333, 1, 3.16766e-08, -7.96166e-10, 0, -0.0325078, -0.215894, -0.168064, 0.961295, 1, 1, 1, 0.6, 1, 4.29571e-09, 1.32412e-10, 0, -0.0183872, -0.228989, -0.148323, 0.961887, 1, 1, 1, 0.666667, 1, 5.67524e-09, 9.16771e-10, 1.19209e-07, -0.00943251, -0.239133, -0.132293, 0.961886, 1, 1, 1, 0.733333, 1, 6.72954e-09, 7.77073e-10, 0, -0.0118449, -0.241292, -0.13514, 0.960924, 1, 1, 1, 0.8, 1, 1.55997e-09, -4.59549e-09, 0, -0.0356173, -0.240445, -0.167061, 0.955515, 1, 1, 1, 0.866667, 1, 2.2212e-08, -8.7166e-09, 0, -0.0691231, -0.236236, -0.193717, 0.949678, 1, 1, 1, 0.933333, 1, 1.78698e-08, -1.38971e-09, 0, -0.0926686, -0.21401, -0.195148, 0.952643, 1, 1, 1, 1, 1, 1.10595e-09, 1.00945e-08, 0, -0.104118, -0.179463, -0.193885, 0.958833, 1, 1, 1, 1.04167, 1, 2.79397e-08, 1.02888e-08, -1.19209e-07, -0.105738, -0.170004, -0.193499, 0.960456, 1, 1, 1 )
tracks/8/type = "transform"
tracks/8/path = NodePath("Armature/Skeleton:Base")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/keys = PoolRealArray( 0, 1, 0, 0, -0.3, 0.0998068, -0.00311413, -0.0310306, 0.994518, 1, 1, 1, 0.0666667, 1, 0, 0, -0.3, 0.0978242, -0.00285651, -0.0286044, 0.994788, 1, 1, 1, 0.133333, 1, 0, 0, -0.3, 0.087763, -0.00136632, -0.0144903, 0.996035, 1, 1, 1, 0.2, 1, 0, 0, -0.3, 0.0792657, 0.000687168, 0.00526144, 0.996839, 1, 1, 1, 0.266667, 1, 0, 0, -0.3, 0.0804652, 0.00203443, 0.0188723, 0.996577, 1, 1, 1, 0.333333, 1, 0, 0, -0.3, 0.0853018, 0.00266966, 0.0259549, 0.996013, 1, 1, 1, 0.4, 1, 0, 0, -0.3, 0.091536, 0.00291421, 0.0289664, 0.995376, 1, 1, 1, 0.466667, 1, 0, 0, -0.3, 0.0969729, 0.00305717, 0.030523, 0.994814, 1, 1, 1, 0.533333, 1, 0, 0, -0.3, 0.0996245, 0.0031108, 0.0310037, 0.994537, 1, 1, 1, 0.6, 1, 0, 0, -0.3, 0.0867901, 0.00250436, 0.0249545, 0.995911, 1, 1, 1, 0.666667, 1, 0, 0, -0.3, 0.0623626, 0.00103457, 0.0103089, 0.998, 1, 1, 1, 0.733333, 1, 0, 0, -0.3, 0.0565602, -0.000527597, -0.00525721, 0.998385, 1, 1, 1, 0.8, 1, 0, 0, -0.3, 0.0637818, -0.0016911, -0.0168509, 0.99782, 1, 1, 1, 0.866667, 1, 0, 0, -0.3, 0.0759985, -0.00245039, -0.0244168, 0.996806, 1, 1, 1, 0.933333, 1, 0, 0, -0.3, 0.0886202, -0.00288556, -0.028753, 0.995646, 1, 1, 1, 1, 1, 0, 0, -0.3, 0.0979029, -0.00308691, -0.0307594, 0.994716, 1, 1, 1, 1.04167, 1, 0, 0, -0.3, 0.0998068, -0.00311413, -0.0310306, 0.994518, 1, 1, 1 )
[sub_resource type="AnimationNodeAnimation" id=1]
animation = "Hit-loop"
[sub_resource type="AnimationNodeAnimation" id=2]
animation = "Idle-loop"
[sub_resource type="AnimationNodeAnimation" id=3]
animation = "Interaction-loop"
[sub_resource type="AnimationNodeStateMachineTransition" id=4]
[sub_resource type="AnimationNodeStateMachineTransition" id=5]
switch_mode = 2
xfade_time = 0.2
[sub_resource type="AnimationNodeStateMachineTransition" id=6]
xfade_time = 0.1
[sub_resource type="AnimationNodeStateMachineTransition" id=33]
switch_mode = 2
xfade_time = 0.3
[sub_resource type="AnimationNodeStateMachine" id=8]
states/Hit/node = SubResource( 1 )
states/Hit/position = Vector2( 415, 45 )
states/Idle/node = SubResource( 2 )
states/Idle/position = Vector2( 149, 39 )
states/Interaction/node = SubResource( 3 )
states/Interaction/position = Vector2( 176, 157 )
transitions = [ "Idle", "Hit", SubResource( 4 ), "Hit", "Idle", SubResource( 5 ), "Idle", "Interaction", SubResource( 6 ), "Interaction", "Idle", SubResource( 33 ) ]
start_node = "Idle"
[sub_resource type="AnimationNodeStateMachinePlayback" id=34]
[node name="Player" type="KinematicBody"]
collision_mask = 0
input_ray_pickable = false
@ -53,7 +357,6 @@ material/0 = ExtResource( 3 )
[node name="WorldInfo" type="Node" parent="."]
script = ExtResource( 5 )
World = NodePath("../../TileWorld")
[node name="Navigation" type="Spatial" parent="."]
visible = false
@ -76,16 +379,9 @@ input_ray_pickable = false
monitorable = false
[node name="CollisionShape" type="CollisionShape" parent="ItemPickupArea"]
visible = false
shape = SubResource( 23 )
[node name="Geometry" parent="." groups=["GameGeometry"] instance=ExtResource( 4 )]
[node name="ToolAttachement" parent="Geometry/Armature/Skeleton" index="5"]
transform = Transform( 1, 8.68458e-08, -1.04308e-07, 1.74623e-07, -1, -1.30385e-07, 1.41561e-07, 1.50874e-07, -1, -0.72, 0.45, 3.28113e-08 )
[node name="AnimationTree" parent="Geometry" index="2"]
parameters/playback = SubResource( 28 )
[node name="DebugGeometry" type="Spatial" parent="."]
script = ExtResource( 6 )
@ -94,4 +390,35 @@ material_override = SubResource( 25 )
cast_shadow = 0
generate_lightmap = false
[editable path="Geometry"]
[node name="ImmediateGeometry" type="ImmediateGeometry" parent="."]
[node name="Geometry" type="Spatial" parent="." groups=["GameGeometry"]]
[node name="PirateAsset" parent="Geometry" instance=ExtResource( 8 )]
transform = Transform( 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0 )
[node name="Skeleton" parent="Geometry/PirateAsset/Armature" index="0"]
bones/4/bound_children = [ NodePath("ToolAttachement") ]
[node name="ToolAttachement" type="BoneAttachment" parent="Geometry/PirateAsset/Armature/Skeleton" index="5"]
transform = Transform( 1, 7.13626e-08, -4.47035e-08, 1.64262e-07, -1, -1.00583e-07, 1.19209e-07, 1.18278e-07, -1, -0.72, 0.45, 1.78362e-08 )
visible = false
bone_name = "HandTip.R"
[node name="toolAxe" parent="Geometry/PirateAsset/Armature/Skeleton/ToolAttachement" instance=ExtResource( 4 )]
transform = Transform( -6.98781e-14, 7.86805e-08, -1.2, 1.8, -7.86805e-08, -4.88782e-14, -7.86805e-08, -1.8, -5.24537e-08, 0.0240936, -0.144196, 0.560397 )
[node name="AnimationPlayer" type="AnimationPlayer" parent="Geometry"]
root_node = NodePath("../PirateAsset")
anims/ArmatureAction = SubResource( 29 )
anims/Hit-loop = SubResource( 30 )
anims/Idle-loop = SubResource( 31 )
anims/Interaction-loop = SubResource( 32 )
[node name="AnimationTree" type="AnimationTree" parent="Geometry"]
tree_root = SubResource( 8 )
anim_player = NodePath("../AnimationPlayer")
active = true
parameters/playback = SubResource( 34 )
[editable path="Geometry/PirateAsset"]

View File

@ -88,6 +88,7 @@ script = ExtResource( 3 )
[node name="MountPoint" type="Spatial" parent="."]
transform = Transform( -0.524001, 0, -0.851718, 0, 1, 0, 0.851718, 0, -0.524001, 0.717306, 0, 0.400936 )
visible = false
[node name="Arrow" type="Spatial" parent="MountPoint"]
transform = Transform( -1, 0, -8.74227e-08, 0, 1, 0, 8.74227e-08, 0, -1, 2.38419e-07, 0, 0 )

View File

@ -36,7 +36,6 @@ public class Game : Spatial
// Resources
private PackedScene _tileHighlightScene;
private TileInstanceManager _tileInstanceManager;
private ShaderMaterial _tileMaterial;
private Label _tileOffsetLabel;
private World _world;
@ -46,7 +45,7 @@ public class Game : Spatial
public override void _Ready()
{
// debugStatsContainer
var debugStatsContainer = (Container)FindNode("DebugStatsContainer");
Container debugStatsContainer = (Container)FindNode("DebugStatsContainer");
_framesPerSecondLabel = debugStatsContainer.GetNode<Label>("fps_label");
_centerLabel = debugStatsContainer.GetNode<Label>("center_label");
@ -60,7 +59,7 @@ public class Game : Spatial
_numCoordsRemovedLabel = debugStatsContainer.GetNode<Label>("num_coords_removed_label");
// UI elements
var worldGeneratorContainer = (Container)FindNode("WorldGeneratorContainer");
Container worldGeneratorContainer = (Container)FindNode("WorldGeneratorContainer");
_worldTextureRect = worldGeneratorContainer.GetNode<TextureRect>("WorldTextureRect");
_heightTextureRect = worldGeneratorContainer.GetNode<TextureRect>("HeightTextureRect");
_generateWorldButton = worldGeneratorContainer.GetNode<Button>("WorldGenerateButton");
@ -77,10 +76,9 @@ public class Game : Spatial
_cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation;
_world = (World)FindNode("World");
_tileInstanceManager = (TileInstanceManager)FindNode("TileInstanceManager");
// populate UI values
var generatorWorldSizeSlider = worldGeneratorContainer.GetNode<Slider>("HBoxContainer/WorldSizeSlider");
Slider generatorWorldSizeSlider = worldGeneratorContainer.GetNode<Slider>("HBoxContainer/WorldSizeSlider");
// resources
_tileHighlightScene = GD.Load<PackedScene>("utils/TileHighlight.tscn");
@ -88,7 +86,7 @@ public class Game : Spatial
Debug.Assert(_tileMaterial != null);
_blackWhitePatternTexture = new ImageTexture();
var image = new Image();
Image image = new Image();
image.Load("assets/4x4checker.png");
_blackWhitePatternTexture.CreateFromImage(image, (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
@ -104,8 +102,8 @@ public class Game : Spatial
_player.TaskQueueComponent.Connect("StartInteraction", _interactionSystem,
nameof(_interactionSystem.OnStartInteraction));
_player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged));
_tileInstanceManager.Connect("TileClicked", this, nameof(OnTileClicked));
_tileInstanceManager.Connect("TileHovered", this, nameof(OnTileHovered));
_world.Connect("TileClicked", this, nameof(OnTileClicked));
_world.Connect("TileHovered", this, nameof(OnTileHovered));
_world.Connect("OnWorldViewTileTypeImageChanged", this, nameof(OnWorldViewTileTypeImageChanged));
_world.Connect("OnHeightmapImageChanged", this, nameof(OnHeightmapImageChanged));
@ -118,7 +116,7 @@ public class Game : Spatial
// perform dependency injection
//_streamContainer.SetWorld(_tileWorld);Clicked
var worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
WorldInfoComponent worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
UpdateCurrentTile();
}
@ -134,9 +132,9 @@ public class Game : Spatial
public void UpdateCurrentTile()
{
// cast a ray from the camera to center
var cameraNormal = _camera.ProjectRayNormal(_camera.GetViewport().Size * 0.5f);
var cameraPosition = _camera.ProjectRayOrigin(_camera.GetViewport().Size * 0.5f);
var cameraDir = cameraNormal - cameraPosition;
Vector3 cameraNormal = _camera.ProjectRayNormal(_camera.GetViewport().Size * 0.5f);
Vector3 cameraPosition = _camera.ProjectRayOrigin(_camera.GetViewport().Size * 0.5f);
Vector3 cameraDir = cameraNormal - cameraPosition;
Vector3 centerCoord;
@ -166,13 +164,13 @@ public class Game : Spatial
UpdateCurrentTile();
var tileHighlightTransform = Transform.Identity;
var currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
Transform tileHighlightTransform = Transform.Identity;
Vector2 currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
tileHighlightTransform.origin.x = currentTileCenter.x;
tileHighlightTransform.origin.z = currentTileCenter.y;
_tileHighlight.Transform = tileHighlightTransform;
var cameraTransform = _camera.Transform;
Transform cameraTransform = _camera.Transform;
cameraTransform.origin = _player.GlobalTranslation + _cameraOffset;
_camera.Transform = cameraTransform;
}
@ -181,7 +179,7 @@ public class Game : Spatial
public void OnGenerateButton()
{
GD.Print("Generating");
var worldSizeSlider = (Slider)FindNode("WorldSizeSlider");
Slider worldSizeSlider = (Slider)FindNode("WorldSizeSlider");
if (worldSizeSlider == null) GD.PrintErr("Could not find WorldSizeSlider!");
}
@ -189,8 +187,8 @@ public class Game : Spatial
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
int shapeIndex)
{
var cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
var highlightTransform = Transform.Identity;
HexCell cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
Transform highlightTransform = Transform.Identity;
_mouseWorldLabel.Text = position.ToString("F3");
_mouseTileOffsetLabel.Text = cellAtCursor.OffsetCoords.ToString("N");
@ -213,7 +211,7 @@ public class Game : Spatial
public void OnTileHovered(HexTile3D tile)
{
var highlightTransform = tile.GlobalTransform;
Transform highlightTransform = tile.GlobalTransform;
_mouseTileHighlight.Transform = highlightTransform;
_mouseWorldLabel.Text = highlightTransform.origin.ToString("F3");
_mouseTileOffsetLabel.Text = tile.OffsetCoords.ToString("N");
@ -226,7 +224,7 @@ public class Game : Spatial
{
GD.Print("Clicked on entity at " + entity.GlobalTranslation);
var mountPoint = (Spatial)entity.FindNode("MountPoint");
Spatial mountPoint = (Spatial)entity.FindNode("MountPoint");
if (mountPoint != null)
{
_player.TaskQueueComponent.Reset();
@ -239,7 +237,7 @@ public class Game : Spatial
public void ResetGameState()
{
var playerStartTransform = Transform.Identity;
Transform playerStartTransform = Transform.Identity;
playerStartTransform.origin.y = 0;
_player.Transform = playerStartTransform;
_player.TaskQueueComponent.Reset();
@ -250,9 +248,9 @@ public class Game : Spatial
foreach (Spatial entity in GetNode("Entities").GetChildren())
{
var entityTransform = entity.Transform;
var entityPlanePos = new Vector2(entityTransform.origin.x, entityTransform.origin.z);
var entityOffsetCoordinates = _hexGrid.GetHexAt(entityPlanePos).OffsetCoords;
Transform entityTransform = entity.Transform;
Vector2 entityPlanePos = new Vector2(entityTransform.origin.x, entityTransform.origin.z);
Vector2 entityOffsetCoordinates = _hexGrid.GetHexAt(entityPlanePos).OffsetCoords;
entityTransform.origin.y = 0;
entity.Transform = entityTransform;
}
@ -260,7 +258,7 @@ public class Game : Spatial
private void OnHeightmapImageChanged(Image heightmapImage)
{
var newHeightmapTexture = new ImageTexture();
ImageTexture newHeightmapTexture = new ImageTexture();
newHeightmapTexture.CreateFromImage(heightmapImage,
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
@ -269,7 +267,7 @@ public class Game : Spatial
private void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage)
{
var newWorldTexture = new ImageTexture();
ImageTexture newWorldTexture = new ImageTexture();
newWorldTexture.CreateFromImage(viewTileTypeImage,
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
@ -283,7 +281,7 @@ public class Game : Spatial
public void OnGoldCountChanged(int goldCount)
{
var animationPlayer = _gameUi.GetNode<AnimationPlayer>("AnimationPlayer");
AnimationPlayer animationPlayer = _gameUi.GetNode<AnimationPlayer>("AnimationPlayer");
_goldCountLabel.Text = goldCount.ToString();
animationPlayer.CurrentAnimation = "FlashLabel";
animationPlayer.Seek(0);

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=22 format=2]
[gd_scene load_steps=21 format=2]
[ext_resource path="res://entities/Player.tscn" type="PackedScene" id=2]
[ext_resource path="res://scenes/Camera.tscn" type="PackedScene" id=3]
@ -7,7 +7,6 @@
[ext_resource path="res://ui/DebugStatsContainer.gd" type="Script" id=6]
[ext_resource path="res://scenes/World.cs" type="Script" id=7]
[ext_resource path="res://scenes/Game.cs" type="Script" id=9]
[ext_resource path="res://scenes/TileInstanceManager.cs" type="Script" id=10]
[ext_resource path="res://entities/Chest.tscn" type="PackedScene" id=11]
[ext_resource path="res://ui/WorldGeneratorUI.gd" type="Script" id=12]
[ext_resource path="res://assets/Environment/HexTileMesh.tres" type="CylinderMesh" id=13]
@ -358,6 +357,7 @@ flip_v = true
visible = false
[node name="Camera" parent="." instance=ExtResource( 3 )]
transform = Transform( 1, 0, 0, 0, 0.60042, 0.799685, 0, -0.799685, 0.60042, -4.76837e-07, 5.16505, 3.1696 )
[node name="InteractionSystem" type="Node" parent="."]
script = ExtResource( 15 )
@ -370,33 +370,27 @@ WorldNode = NodePath("../World")
[node name="WorldInfo" parent="Player" index="2"]
WorldPath = NodePath("../../World")
[node name="ToolAttachement" parent="Player/Geometry/Armature/Skeleton" index="5"]
transform = Transform( 1, 8.68458e-08, -1.04308e-07, 1.74623e-07, -1, -1.30385e-07, 1.41561e-07, 1.50874e-07, -1, -0.72, 0.45, 3.28113e-08 )
[node name="ToolAttachement" parent="Player/Geometry/PirateAsset/Armature/Skeleton" index="5"]
transform = Transform( 1, 7.13626e-08, -4.47035e-08, 1.64262e-07, -1, -1.00583e-07, 1.19209e-07, 1.18278e-07, -1, -0.72, 0.45, 1.78362e-08 )
[node name="AnimationTree" parent="Player/Geometry" index="2"]
parameters/playback = SubResource( 26 )
[node name="Entities" type="Spatial" parent="."]
visible = false
[node name="Axe" parent="Entities" instance=ExtResource( 14 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.79762, 0, 0 )
input_ray_pickable = false
[node name="Chest" parent="Entities" instance=ExtResource( 11 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -3.27709, 0, 1.02593 )
transform = Transform( -0.825665, 0, 0.56416, 0, 1, 0, -0.56416, 0, -0.825665, -3.27709, 0, 1.02593 )
[node name="World" type="Spatial" parent="."]
script = ExtResource( 7 )
[node name="Chunks" type="Spatial" parent="World"]
[node name="TileInstanceManager" type="Spatial" parent="World"]
script = ExtResource( 10 )
ShowHexTiles = true
World = NodePath("..")
[node name="TileMultiMeshInstance" type="MultiMeshInstance" parent="World/TileInstanceManager"]
[node name="TileMultiMeshInstance" type="MultiMeshInstance" parent="World"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2.5, 0 )
multimesh = SubResource( 27 )
@ -430,4 +424,4 @@ directional_shadow_mode = 0
[connection signal="toggled" from="Generator Container/WorldGeneratorContainer/ShowTexturesCheckButton" to="Generator Container/WorldGeneratorContainer" method="_on_ShowTexturesCheckButton_toggled"]
[editable path="Player"]
[editable path="Player/Geometry"]
[editable path="Player/Geometry/PirateAsset"]

View File

@ -1,202 +0,0 @@
using System.Diagnostics;
using System.Linq;
using Godot;
using Godot.Collections;
public class TileInstanceManager : Spatial
{
// exports
[Export] public NodePath World;
[Export] public bool ShowHexTiles;
[Export] public Vector2 ViewCenterPlaneCoord;
// scene nodes
public MultiMeshInstance TileMultiMeshInstance;
// other members
private readonly Array<SceneTileChunk> _sceneTileChunks = new();
private int _usedTileInstanceIndices;
private ImageTexture _viewTileTypeTexture;
private World _world;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_world = GetNode<World>(World);
_world.Connect("OnTilesChanged", this, nameof(HandleWorldTileChange));
TileMultiMeshInstance = (MultiMeshInstance)FindNode("TileMultiMeshInstance");
Debug.Assert(TileMultiMeshInstance != null);
}
public override void _Process(float delta)
{
}
private SceneTileChunk CreateSceneTileChunk(Vector2 chunkIndex)
{
var sceneTileChunk =
new SceneTileChunk(chunkIndex, TileMultiMeshInstance, _usedTileInstanceIndices, ShowHexTiles);
_usedTileInstanceIndices += sceneTileChunk.TileNodes.Count;
foreach (var hexTile3D in sceneTileChunk.TileNodes)
{
hexTile3D.Connect("TileClicked", this, nameof(OnTileClicked));
hexTile3D.Connect("TileHovered", this, nameof(OnTileHovered));
}
return sceneTileChunk;
}
private SceneTileChunk FindSceneTileChunkAtIndex(Vector2 chunkIndex)
{
foreach (Spatial child in GetChildren())
{
var sceneTileChunk = child as SceneTileChunk;
if (sceneTileChunk == null) continue;
if (sceneTileChunk.ChunkIndex == chunkIndex) return sceneTileChunk;
}
return null;
}
private void HandleWorldTileChange(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices)
{
Array<SceneTileChunk> removedChunks = new();
foreach (var chunkIndex in removedChunkIndices)
{
var chunk = FindSceneTileChunkAtIndex(chunkIndex);
if (chunk != null) removedChunks.Add(chunk);
}
foreach (var chunkIndex in addedChunkIndices)
{
SceneTileChunk sceneTileChunk = null;
if (removedChunks.Count > 0)
{
sceneTileChunk = removedChunks[^1];
sceneTileChunk.ChunkIndex = chunkIndex;
removedChunks.RemoveAt(removedChunks.Count - 1);
}
else
{
sceneTileChunk = CreateSceneTileChunk(chunkIndex);
AddChild(sceneTileChunk);
}
_sceneTileChunks.Add(sceneTileChunk);
}
GD.Print("Removed Chunks " + removedChunkIndices.Count);
GD.Print("Added Chunks " + addedChunkIndices.Count);
GD.Print("Removed chunk count: " + removedChunks.Count);
}
public void OnTileClicked(HexTile3D tile)
{
EmitSignal("TileClicked", tile);
}
public void OnTileHovered(HexTile3D tile)
{
EmitSignal("TileHovered", tile);
}
// signals
[Signal]
private delegate void TileClicked(HexTile3D tile3d);
[Signal]
private delegate void TileHovered(HexTile3D tile3d);
private class SceneTileChunk : Spatial
{
private readonly PackedScene _hexTile3DScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
private readonly MultiMeshInstance _multiMeshInstance;
private readonly Array<int> _tileInstanceIndices = new();
private readonly HexGrid _hexGrid = new();
private readonly bool _showHexTiles;
public readonly Array<HexTile3D> TileNodes = new();
private Vector2 _chunkIndex = Vector2.Inf;
public SceneTileChunk(Vector2 chunkIndex, MultiMeshInstance multiMeshInstance, int tileInstanceIndexStart,
bool showHexTiles)
{
_showHexTiles = showHexTiles;
var tileInstanceIndexStart1 = tileInstanceIndexStart;
var chunkSize = global::World.ChunkSize;
foreach (var i in Enumerable.Range(0, chunkSize))
foreach (var j in Enumerable.Range(0, chunkSize))
{
var tile3D = (HexTile3D)_hexTile3DScene.Instance();
tile3D.Cell.OffsetCoords = new Vector2(chunkIndex * global::World.ChunkSize + new Vector2(i, j));
var tileTransform = Transform.Identity;
var centerPlaneCoord = _hexGrid.GetHexCenterFromOffset(new Vector2(i, j));
tileTransform.origin = new Vector3(centerPlaneCoord.x, 0, centerPlaneCoord.y);
tile3D.Transform = tileTransform;
TileNodes.Add(tile3D);
AddChild(tile3D);
}
_multiMeshInstance = multiMeshInstance;
var chunkTileCount = global::World.ChunkSize * global::World.ChunkSize;
Debug.Assert(tileInstanceIndexStart1 + chunkTileCount <= _multiMeshInstance.Multimesh.InstanceCount);
foreach (var i in Enumerable.Range(0, chunkTileCount))
_tileInstanceIndices.Add(tileInstanceIndexStart1 + i);
// _multiMeshInstance.Multimesh.InstanceCount += chunkTileCount;
_multiMeshInstance.Multimesh.VisibleInstanceCount = _multiMeshInstance.Multimesh.InstanceCount;
ChunkIndex = chunkIndex;
}
public Vector2 ChunkIndex
{
get => _chunkIndex;
set
{
var chunkTransform = Transform.Identity;
var chunkOriginPlaneCoord = _hexGrid.GetHexCenterFromOffset(value * global::World.ChunkSize);
chunkTransform.origin = new Vector3(chunkOriginPlaneCoord.x, 0, chunkOriginPlaneCoord.y);
Transform = chunkTransform;
_chunkIndex = value;
var tileOrientation = new Basis(Vector3.Up, 90f * Mathf.Pi / 180f);
GD.Print("Updating transforms for instances of chunk " + value + " origin: " + chunkTransform.origin);
foreach (var i in Enumerable.Range(0, _tileInstanceIndices.Count))
{
var column = i % global::World.ChunkSize;
var row = i / global::World.ChunkSize;
var tilePlaneCoord =
_hexGrid.GetHexCenterFromOffset(new Vector2(column, row));
var hexTransform = new Transform(tileOrientation,
chunkTransform.origin + new Vector3(tilePlaneCoord.x, 0, tilePlaneCoord.y));
if (_showHexTiles)
hexTransform = new Transform(tileOrientation.Scaled(Vector3.One * 0.95f),
hexTransform.origin);
_multiMeshInstance.Multimesh.SetInstanceTransform(_tileInstanceIndices[i], hexTransform);
}
}
}
}
}

View File

@ -17,7 +17,7 @@ public class World : Spatial
}
// constants
public const int ChunkSize = 18;
public const int ChunkSize = 12;
public const int NumChunkRows = 3;
public const int NumChunkColumns = NumChunkRows;
private static readonly Color RockColor = new(0.5f, 0.5f, 0.4f);
@ -25,11 +25,13 @@ public class World : Spatial
private static readonly Color DarkGrassColor = new(0.05882353f, 0.5411765f, 0.05882353f);
private static readonly Color LightWaterColor = new(0.05882353f, 0.05882353f, 0.8627451f);
private readonly List<Vector2> _addedChunkIndices = new();
private readonly Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
private readonly List<Vector2> _addedChunkIndices = new();
private readonly List<WorldChunk> _unusedWorldChunks = new();
private readonly Image _heightmapImage = new();
private readonly List<Vector2> _removedChunkIndices = new();
private readonly Image _tileTypeMapImage = new();
private int FrameCounter;
// referenced scenes
private readonly PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
@ -48,7 +50,8 @@ public class World : Spatial
private OpenSimplexNoise _noiseGenerator = new();
private Array<Spatial> _rockAssets;
private TileInstanceManager _tileInstanceManager;
private MultiMeshInstance _tileMultiMeshInstance;
private int _usedTileMeshInstances;
private Array<Spatial> _treeAssets;
private ImageTexture _viewTileTypeTexture;
public Vector2 CenterChunkIndex = Vector2.Zero;
@ -80,6 +83,16 @@ public class World : Spatial
[Signal]
private delegate void OnHeightmapImageChanged(Image heightmapImage);
[Signal]
public delegate void EntityClicked(Entity entity);
// signals
[Signal]
private delegate void TileClicked(HexTile3D tile3d);
[Signal]
private delegate void TileHovered(HexTile3D tile3d);
public World()
{
Debug.Assert(ChunkSize % 2 == 0);
@ -93,10 +106,11 @@ public class World : Spatial
Chunks = (Spatial)FindNode("Chunks");
Debug.Assert(Chunks != null);
_tileInstanceManager = (TileInstanceManager)FindNode("TileInstanceManager");
Debug.Assert(_tileInstanceManager != null);
_tileInstanceManager.TileMultiMeshInstance.Multimesh.InstanceCount =
_tileMultiMeshInstance = (MultiMeshInstance)FindNode("TileMultiMeshInstance");
Debug.Assert(_tileMultiMeshInstance != null);
_tileMultiMeshInstance.Multimesh.InstanceCount =
ChunkSize * ChunkSize * NumChunkColumns * NumChunkRows;
_usedTileMeshInstances = 0;
InitNoiseGenerator();
@ -125,65 +139,72 @@ public class World : Spatial
_noiseGenerator.Lacunarity = 2;
}
public WorldChunk GetOrCreateWorldChunk(int xIndex, int yIndex, Color debugColor)
public WorldChunk GetOrCreateWorldChunk(Vector2 chunkIndex, Color debugColor)
{
if (IsChunkCached(xIndex, yIndex))
WorldChunk chunk;
if (IsChunkCached(chunkIndex))
return _cachedWorldChunks[chunkIndex];
if (_unusedWorldChunks.Count > 0)
{
var cachedChunk = _cachedWorldChunks[new Vector2(xIndex, yIndex)];
return cachedChunk;
chunk = _unusedWorldChunks.First();
_unusedWorldChunks.RemoveAt(0);
GD.Print("Reusing chunk from former index " + chunk.ChunkIndex + " at new index " + chunkIndex);
}
else
{
chunk = CreateWorldChunk(chunkIndex, debugColor);
}
return CreateWorldChunk(xIndex, yIndex, debugColor);
_cachedWorldChunks[chunkIndex] = chunk;
return chunk;
}
private bool IsChunkCached(int xIndex, int yIndex)
private bool IsChunkCached(Vector2 chunkIndex)
{
return _cachedWorldChunks.ContainsKey(new Vector2(xIndex, yIndex));
return _cachedWorldChunks.ContainsKey(chunkIndex);
}
private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor)
private WorldChunk CreateWorldChunk(Vector2 chunkIndex, Color debugColor)
{
var result = (WorldChunk)_worldChunkScene.Instance();
WorldChunk result = (WorldChunk)_worldChunkScene.Instance();
Chunks.AddChild(result);
result.Connect("TileClicked", this, nameof(OnTileClicked));
result.Connect("TileHovered", this, nameof(OnTileHovered));
result.SetSize(ChunkSize);
result.InitializeTileInstances(chunkIndex, _tileMultiMeshInstance, _usedTileMeshInstances);
_usedTileMeshInstances += result.Tiles.GetChildCount();
var offsetCoordSouthWest = new Vector2(xIndex, yIndex) * ChunkSize;
var offsetCoordNorthEast = offsetCoordSouthWest + new Vector2(1, 1) * (ChunkSize - 1);
var planeCoordSouthWest = HexGrid.GetHexCenterFromOffset(offsetCoordSouthWest) +
new Vector2(-HexGrid.HexSize.x, HexGrid.HexSize.y) * 0.5f;
var planeCoordNorthEast = HexGrid.GetHexCenterFromOffset(offsetCoordNorthEast) +
new Vector2(HexGrid.HexSize.x, -HexGrid.HexSize.y) * 0.5f;
result.ChunkIndex = new Vector2(xIndex, yIndex);
result.PlaneRect = new Rect2(
new Vector2(planeCoordSouthWest.x, planeCoordNorthEast.y),
new Vector2(planeCoordNorthEast.x - planeCoordSouthWest.x, planeCoordSouthWest.y - planeCoordNorthEast.y));
result.SetChunkIndex(chunkIndex, HexGrid);
result.UpdateTileTransforms();
result.DebugColor = debugColor;
result.DebugColor.a = 0.6f;
Chunks.AddChild(result);
var chunkIndex = new Vector2(xIndex, yIndex);
_cachedWorldChunks.Add(chunkIndex, result);
return result;
}
private bool IsColorEqualApprox(Color colorA, Color colorB)
{
var colorDifference = new Vector3(colorA.r - colorB.r, colorA.g - colorB.g, colorA.b - colorB.b);
Vector3 colorDifference = new(colorA.r - colorB.r, colorA.g - colorB.g, colorA.b - colorB.b);
return colorDifference.LengthSquared() < 0.1 * 0.1;
}
private Spatial SelectAsset(Vector2 offsetCoord, Array<Spatial> assets, Random randomGenerator, double probability)
private Spatial SelectAsset(Vector2 textureCoord, Array<Spatial> assets, Random randomGenerator, double probability)
{
if (randomGenerator.NextDouble() < 1.0 - probability) return null;
var assetIndex = randomGenerator.Next(assets.Count);
var assetInstance = (Spatial)assets[assetIndex].Duplicate();
var assetTransform = Transform.Identity;
assetTransform.origin = HexGrid.GetHexCenterVec3FromOffset(offsetCoord);
int assetIndex = randomGenerator.Next(assets.Count);
Spatial assetInstance = (Spatial)assets[assetIndex].Duplicate();
Transform assetTransform = Transform.Identity;
assetTransform.origin = HexGrid.GetHexCenterVec3FromOffset(textureCoord);
// TODO: assetTransform.origin.y = GetHeightAtOffset(offsetCoord);
assetTransform.origin.y = 0;
assetTransform.basis =
@ -195,30 +216,30 @@ public class World : Spatial
private void PopulateChunk(WorldChunk chunk)
{
var environmentRandom = new Random(Seed);
Random environmentRandom = new(Seed);
var tileTypeImage = chunk.TileTypeOffscreenViewport.GetTexture().GetData();
Image tileTypeImage = chunk.TileTypeOffscreenViewport.GetTexture().GetData();
tileTypeImage.Lock();
foreach (var textureCoordU in Enumerable.Range(0, chunk.Size))
foreach (var textureCoordV in Enumerable.Range(0, chunk.Size))
foreach (int textureCoordU in Enumerable.Range(0, chunk.Size))
foreach (int textureCoordV in Enumerable.Range(0, chunk.Size))
{
var colorValue = tileTypeImage.GetPixel(textureCoordU, textureCoordV);
var textureCoord = new Vector2(textureCoordU, textureCoordV);
var offsetCoord = chunk.ChunkIndex * ChunkSize + textureCoord;
Color colorValue = tileTypeImage.GetPixel(textureCoordU, textureCoordV);
Vector2 textureCoord = new(textureCoordU, textureCoordV);
Vector2 offsetCoord = chunk.ChunkIndex * ChunkSize + textureCoord;
if (IsColorEqualApprox(colorValue, RockColor))
{
var rockAsset = SelectAsset(offsetCoord, _rockAssets, environmentRandom, 0.15);
Spatial rockAsset = SelectAsset(textureCoord, _rockAssets, environmentRandom, 0.15);
if (rockAsset != null) chunk.Entities.AddChild(rockAsset);
// TODO: MarkCellUnwalkable(cell);
}
else if (IsColorEqualApprox(colorValue, GrassColor) || IsColorEqualApprox(colorValue, DarkGrassColor))
{
var grassAsset = SelectAsset(offsetCoord, _grassAssets, environmentRandom, 0.15);
Spatial grassAsset = SelectAsset(textureCoord, _grassAssets, environmentRandom, 0.15);
if (grassAsset != null) chunk.Entities.AddChild(grassAsset);
Tree treeAsset = SelectAsset(offsetCoord, _treeAssets, environmentRandom, 0.05) as Tree;
Tree treeAsset = SelectAsset(textureCoord, _treeAssets, environmentRandom, 0.05) as Tree;
if (treeAsset != null)
{
chunk.Entities.AddChild(treeAsset);
@ -265,83 +286,89 @@ public class World : Spatial
return;
}
GD.Print("Update Chunks: " + FrameCounter);
// mark all chunks as retired
Godot.Collections.Dictionary<Vector2, WorldChunk> oldCachedChunks = new(_cachedWorldChunks);
// set new center chunk
var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
CenterChunkIndex = new Vector2(chunkIndex.Item1, chunkIndex.Item2);
CenterChunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
var currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
WorldChunk currentChunk = GetOrCreateWorldChunk(CenterChunkIndex,
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
_centerChunkRect = currentChunk.PlaneRect;
_centerChunkRect = new Rect2(
new Vector2(currentChunk.Transform.origin.x, currentChunk.Transform.origin.z)
+ currentChunk.PlaneRect.Position,
currentChunk.PlaneRect.Size);
GD.Print("Center Chunk Rect: " + _centerChunkRect.Position + " size: " + _centerChunkRect.Size);
// load or create adjacent chunks
_activeChunkIndices = new List<Vector2>();
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2 - 1));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 - 1));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 - 1));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(-1, -1));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(0, -1));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(1, -1));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(-1, 0));
_activeChunkIndices.Add(CenterChunkIndex);
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(+1, 0));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2 + 1));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 + 1));
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 + 1));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(-1, +1));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(0, +1));
_activeChunkIndices.Add(CenterChunkIndex + new Vector2(+1, +1));
// clear unused chunks
_unusedWorldChunks.Clear();
_addedChunkIndices.Clear();
foreach (Vector2 oldChunkIndex in oldCachedChunks.Keys)
if (!_activeChunkIndices.Contains(oldChunkIndex))
DeactivateChunk(oldCachedChunks[oldChunkIndex]);
foreach (Vector2 activeChunkIndex in _activeChunkIndices)
{
WorldChunk chunk = GetOrCreateWorldChunk(activeChunkIndex,
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
_cachedWorldChunks[activeChunkIndex] = chunk;
}
Debug.Assert(_activeChunkIndices.Count == NumChunkRows * NumChunkColumns);
foreach (var activeChunkIndex in _activeChunkIndices)
GetOrCreateWorldChunk((int)activeChunkIndex.x, (int)activeChunkIndex.y,
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
// unload retired chunks
_removedChunkIndices.Clear();
_addedChunkIndices.Clear();
foreach (var cachedChunkKey in oldCachedChunks.Keys)
if (!_activeChunkIndices.Contains(cachedChunkKey))
RemoveChunk(cachedChunkKey);
foreach (var chunkKey in _activeChunkIndices)
foreach (Vector2 chunkKey in _activeChunkIndices)
if (!oldCachedChunks.ContainsKey(chunkKey))
{
_addedChunkIndices.Add(chunkKey);
var chunk = _cachedWorldChunks[chunkKey];
GenerateChunkNoiseMap(chunk);
ActivateChunk(_cachedWorldChunks[chunkKey], chunkKey);
State = GenerationState.Heightmap;
}
}
private void ActivateChunk(WorldChunk chunk, Vector2 chunkIndex)
{
chunk.SetChunkIndex(chunkIndex, HexGrid);
chunk.UpdateTileTransforms();
_addedChunkIndices.Add(chunk.ChunkIndex);
GD.Print("Generating noise for chunk " + chunk.ChunkIndex);
GenerateChunkNoiseMap(chunk);
}
private void DeactivateChunk(WorldChunk chunk)
{
GD.Print("Clearing chunk index: " + chunk.ChunkIndex);
_cachedWorldChunks.Remove(chunk.ChunkIndex);
chunk.ClearContent();
_unusedWorldChunks.Add(chunk);
}
private void GenerateChunkNoiseMap(WorldChunk chunk)
{
var chunkIndex = chunk.ChunkIndex;
Vector2 chunkIndex = chunk.ChunkIndex;
var debugChunkColor = new Color(Mathf.Abs(chunkIndex.x) / 5, Mathf.Abs(chunkIndex.y) / 5,
Mathf.RoundToInt(Mathf.Abs(chunkIndex.x + chunkIndex.y)) % 2);
var noiseImageTexture = new ImageTexture();
ImageTexture noiseImageTexture = new();
noiseImageTexture.CreateFromImage(_noiseGenerator.GetImage(ChunkSize, ChunkSize, chunkIndex * ChunkSize),
0);
// Debug Texture
var simpleImage = new Image();
simpleImage.Create(ChunkSize, ChunkSize, false, Image.Format.Rgb8);
simpleImage.Lock();
foreach (var i in Enumerable.Range(0, ChunkSize))
foreach (var j in Enumerable.Range(0, ChunkSize))
if ((i + j) % 2 == 0)
simpleImage.SetPixelv(new Vector2(i, j), Colors.Aqua);
else
simpleImage.SetPixelv(new Vector2(i, j), debugChunkColor);
simpleImage.Unlock();
// noiseImageTexture.CreateFromImage(simpleImage, 0);
chunk.SetNoisemap(noiseImageTexture);
}
@ -356,12 +383,10 @@ public class World : Spatial
}
private Tuple<int, int> GetChunkTupleFromPlaneCoord(Vector2 planeCoord)
private Vector2 GetChunkTupleFromPlaneCoord(Vector2 planeCoord)
{
var centerOffsetCoord = HexGrid.GetHexAt(planeCoord);
var chunkIndexFloat = (centerOffsetCoord.OffsetCoords / ChunkSize).Floor();
var chunkIndex = new Tuple<int, int>((int)chunkIndexFloat.x, (int)chunkIndexFloat.y);
return chunkIndex;
HexCell centerOffsetCoord = HexGrid.GetHexAt(planeCoord);
return (centerOffsetCoord.OffsetCoords / ChunkSize).Floor();
}
public void SetCenterPlaneCoord(Vector2 centerPlaneCoord)
@ -378,18 +403,18 @@ public class World : Spatial
private void UpdateWorldViewTexture()
{
var worldChunkSize = ChunkSize;
var numWorldChunkRows = NumChunkRows;
var numWorldChunkColumns = NumChunkColumns;
int worldChunkSize = ChunkSize;
int numWorldChunkRows = NumChunkRows;
int numWorldChunkColumns = NumChunkColumns;
_heightmapImage.Create(worldChunkSize * numWorldChunkColumns, worldChunkSize * numWorldChunkRows, false,
Image.Format.Rgba8);
_tileTypeMapImage.Create(worldChunkSize * numWorldChunkColumns, worldChunkSize * numWorldChunkRows, false,
Image.Format.Rgba8);
foreach (var chunkIndex in _activeChunkIndices)
foreach (Vector2 chunkIndex in _activeChunkIndices)
{
var worldChunk = GetOrCreateWorldChunk((int)chunkIndex.x, (int)chunkIndex.y, Colors.White);
WorldChunk worldChunk = GetOrCreateWorldChunk(chunkIndex, Colors.White);
_heightmapImage.BlendRect(
worldChunk.HeightmapOffscreenViewport.GetTexture().GetData(),
@ -419,9 +444,9 @@ public class World : Spatial
_chunkIndexSouthWest = Vector2.Inf;
_chunkIndexNorthEast = -Vector2.Inf;
foreach (var chunkIndex in _activeChunkIndices)
foreach (Vector2 chunkIndex in _activeChunkIndices)
{
var worldChunk = GetOrCreateWorldChunk((int)chunkIndex.x, (int)chunkIndex.y, Colors.White);
WorldChunk worldChunk = GetOrCreateWorldChunk(chunkIndex, Colors.White);
if (chunkIndex.x <= _chunkIndexSouthWest.x && chunkIndex.y <= _chunkIndexSouthWest.y)
_chunkIndexSouthWest = chunkIndex;
@ -432,72 +457,95 @@ public class World : Spatial
private void UpdateNavigationBounds()
{
var cellSouthWest = HexGrid.GetHexAtOffset(_chunkIndexSouthWest * ChunkSize);
HexCell cellSouthWest = HexGrid.GetHexAtOffset(_chunkIndexSouthWest * ChunkSize);
// Chunks have their cells ordered from south west (0,0) to north east (ChunkSize, ChunkSize). For the
// north east cell we have to add the chunk size to get to the actual corner cell.
var cellNorthEast = HexGrid.GetHexAtOffset(_chunkIndexNorthEast * ChunkSize + Vector2.One * (ChunkSize - 1));
HexCell cellNorthEast =
HexGrid.GetHexAtOffset(_chunkIndexNorthEast * ChunkSize + Vector2.One * (ChunkSize - 1));
var centerCell =
HexCell centerCell =
HexGrid.GetHexAtOffset(((cellNorthEast.OffsetCoords - cellSouthWest.OffsetCoords) / 2).Round());
var numCells = ChunkSize * Math.Max(NumChunkColumns, NumChunkRows);
int numCells = ChunkSize * Math.Max(NumChunkColumns, NumChunkRows);
HexGrid.SetBoundsOffset(cellSouthWest, ChunkSize * new Vector2(NumChunkColumns, NumChunkRows));
}
public override void _Process(float delta)
{
var oldState = State;
GenerationState oldState = State;
UpdateGenerationState();
if (oldState != GenerationState.Done && State == GenerationState.Done)
{
UpdateWorldViewTexture();
EmitSignal("OnTilesChanged", _removedChunkIndices.ToArray(), _addedChunkIndices.ToArray());
}
}
private void UpdateGenerationState()
{
FrameCounter++;
if (State == GenerationState.Heightmap)
{
var numChunksGeneratingHeightmap = 0;
foreach (var chunkIndex in _addedChunkIndices)
int numChunksGeneratingHeightmap = 0;
foreach (Vector2 chunkIndex in _addedChunkIndices)
{
var chunk = _cachedWorldChunks[chunkIndex];
WorldChunk chunk = _cachedWorldChunks[chunkIndex];
if (chunk.HeightMapFrameCount > 0) numChunksGeneratingHeightmap++;
}
if (numChunksGeneratingHeightmap == 0)
{
// assign height map images
foreach (var chunkIndex in _addedChunkIndices)
foreach (Vector2 chunkIndex in _addedChunkIndices)
{
var chunk = _cachedWorldChunks[chunkIndex];
WorldChunk chunk = _cachedWorldChunks[chunkIndex];
chunk.SetHeightmap(chunk.HeightmapOffscreenViewport.GetTexture());
}
GD.Print("Switching to TileType Generation: " + FrameCounter);
State = GenerationState.TileType;
}
}
else if (State == GenerationState.TileType)
{
var numChunksGeneratingTileType = 0;
foreach (var chunkIndex in _addedChunkIndices)
int numChunksGeneratingTileType = 0;
foreach (Vector2 chunkIndex in _addedChunkIndices)
{
var chunk = _cachedWorldChunks[chunkIndex];
WorldChunk chunk = _cachedWorldChunks[chunkIndex];
if (chunk.TileTypeMapFrameCount > 0) numChunksGeneratingTileType++;
}
if (numChunksGeneratingTileType == 0) State = GenerationState.Objects;
if (numChunksGeneratingTileType == 0)
{
GD.Print("Switching to Object Generation: " + FrameCounter);
State = GenerationState.Objects;
}
}
else if (State == GenerationState.Objects)
{
// generate objects
foreach (var chunkIndex in _addedChunkIndices) PopulateChunk(_cachedWorldChunks[chunkIndex]);
foreach (Vector2 chunkIndex in _addedChunkIndices)
PopulateChunk(_cachedWorldChunks[chunkIndex]);
_addedChunkIndices.Clear();
GD.Print("Generation done: " + FrameCounter);
State = GenerationState.Done;
}
}
private void OnEntityClicked(Entity entity)
{
EmitSignal("EntityClicked", entity);
}
public void OnTileClicked(HexTile3D tile)
{
EmitSignal("TileClicked", tile);
}
public void OnTileHovered(HexTile3D tile)
{
EmitSignal("TileHovered", tile);
}
}

View File

@ -1,9 +1,14 @@
using System.Diagnostics;
using System.Linq;
using Godot;
using Godot.Collections;
public class WorldChunk : Spatial
{
private readonly PackedScene _hexTile3DScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
private MultiMeshInstance _multiMeshInstance;
private readonly Array<int> _tileInstanceIndices = new();
private readonly SpatialMaterial _rectMaterial = new();
private Sprite _heightmapSprite;
private TextureRect _heightmapTextureRect;
@ -11,9 +16,15 @@ public class WorldChunk : Spatial
private Sprite _noiseSprite;
private bool _showTextureOverlay;
[Export] public Vector2 ChunkIndex;
public Color DebugColor = Colors.White;
[Export] public Spatial Entities;
public Spatial Entities;
public Spatial Tiles;
private readonly HexGrid _hexGrid = new();
private readonly bool _showHexTiles;
[Export] public Texture HeightMap;
public int HeightMapFrameCount;
@ -23,10 +34,15 @@ public class WorldChunk : Spatial
public bool NoiseTextureCheckerboardOverlay = true;
// signals
// delegate void OnCoordClicked(Vector2 world_pos);
[Signal]
private delegate void TileClicked(HexTile3D tile3d);
[Signal]
private delegate void TileHovered(HexTile3D tile3d);
// other members
public Rect2 PlaneRect;
// ui elements
// scene nodes
@ -67,7 +83,7 @@ public class WorldChunk : Spatial
Debug.Assert(PlaneRectMesh != null);
if (PlaneRectMesh.Visible) _showTextureOverlay = true;
var planeRectTransform = Transform.Identity;
Transform planeRectTransform = Transform.Identity;
planeRectTransform =
planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x, 0.125f, PlaneRect.Size.y));
planeRectTransform.origin.x = PlaneRect.GetCenter().x;
@ -94,6 +110,9 @@ public class WorldChunk : Spatial
Entities = (Spatial)FindNode("Entities");
Debug.Assert(Entities != null);
Tiles = (Spatial)FindNode("Tiles");
Debug.Assert(Tiles != null);
SetSize(World.ChunkSize);
}
@ -112,10 +131,98 @@ public class WorldChunk : Spatial
}
}
public void SetChunkIndex(Vector2 chunkIndex, HexGrid hexGrid)
{
ChunkIndex = chunkIndex;
float chunkSize = World.ChunkSize;
Vector2 planeCoordSouthWest = hexGrid.GetHexCenterFromOffset(chunkIndex * chunkSize);
Transform = new Transform(Basis.Identity, new Vector3(planeCoordSouthWest.x, 0, planeCoordSouthWest.y));
Vector2 localPlaneCoordSouthWest = new Vector2(-hexGrid.HexSize.x, hexGrid.HexSize.y) * 0.5f;
Vector2 localPlaneCoordNorthEast = hexGrid.GetHexCenterFromOffset(Vector2.One * chunkSize) +
new Vector2(hexGrid.HexSize.x, -hexGrid.HexSize.y) * 0.5f;
PlaneRect = new Rect2(
new Vector2(localPlaneCoordSouthWest.x, localPlaneCoordNorthEast.y),
new Vector2(localPlaneCoordNorthEast.x - localPlaneCoordSouthWest.x,
localPlaneCoordSouthWest.y - localPlaneCoordNorthEast.y)
);
}
public void InitializeTileInstances(Vector2 chunkIndex, MultiMeshInstance multiMeshInstance,
int tileInstanceIndexStart)
{
_multiMeshInstance = multiMeshInstance;
_tileInstanceIndices.Clear();
int chunkSize = World.ChunkSize;
foreach (Spatial node in Tiles.GetChildren())
node.QueueFree();
foreach (int i in Enumerable.Range(0, chunkSize))
foreach (int j in Enumerable.Range(0, chunkSize))
{
HexTile3D tile3D = (HexTile3D)_hexTile3DScene.Instance();
tile3D.Connect("TileClicked", this, nameof(OnTileClicked));
tile3D.Connect("TileHovered", this, nameof(OnTileHovered));
tile3D.Cell.OffsetCoords = new Vector2(chunkIndex * World.ChunkSize + new Vector2(i, j));
_tileInstanceIndices.Add(tileInstanceIndexStart + _tileInstanceIndices.Count);
Transform tileTransform = Transform.Identity;
Vector2 centerPlaneCoord = _hexGrid.GetHexCenterFromOffset(new Vector2(i, j));
tileTransform.origin = new Vector3(centerPlaneCoord.x, 0, centerPlaneCoord.y);
tile3D.Transform = tileTransform;
Tiles.AddChild(tile3D);
}
_multiMeshInstance.Multimesh.VisibleInstanceCount = _multiMeshInstance.Multimesh.InstanceCount;
}
public void ClearContent()
{
foreach (Spatial child in Entities.GetChildren())
child.QueueFree();
}
public void UpdateTileTransforms()
{
Transform chunkTransform = Transform.Identity;
Vector2 chunkOriginPlaneCoord = _hexGrid.GetHexCenterFromOffset(ChunkIndex * World.ChunkSize);
chunkTransform.origin = new Vector3(chunkOriginPlaneCoord.x, 0, chunkOriginPlaneCoord.y);
Transform = chunkTransform;
Basis tileOrientation = new(Vector3.Up, 90f * Mathf.Pi / 180f);
GD.Print("Updating transforms for instances of chunk " + ChunkIndex + " origin: " + chunkTransform.origin);
foreach (int i in Enumerable.Range(0, _tileInstanceIndices.Count))
{
int column = i % World.ChunkSize;
int row = i / World.ChunkSize;
Vector2 tilePlaneCoord =
_hexGrid.GetHexCenterFromOffset(new Vector2(column, row));
Transform hexTransform = new(tileOrientation,
chunkTransform.origin + new Vector3(tilePlaneCoord.x, 0, tilePlaneCoord.y));
if (_showHexTiles)
hexTransform = new Transform(tileOrientation.Scaled(Vector3.One * 0.95f),
hexTransform.origin);
_multiMeshInstance.Multimesh.SetInstanceTransform(_tileInstanceIndices[i], hexTransform);
}
}
// other members
public void SaveToFile(string chunkName)
{
var image = new Image();
Image image = new();
image.CreateFromData(Size, Size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData());
image.SavePng(chunkName + "_tileType.png");
@ -157,14 +264,14 @@ public class WorldChunk : Spatial
if (NoiseTextureCheckerboardOverlay)
{
var tileTypeImage = tileTypeTexture.GetData();
Image tileTypeImage = tileTypeTexture.GetData();
tileTypeImage.Lock();
foreach (var i in Enumerable.Range(0, Size))
foreach (var j in Enumerable.Range(0, Size))
foreach (int i in Enumerable.Range(0, Size))
foreach (int j in Enumerable.Range(0, Size))
{
var textureCoord = new Vector2(i, j);
var baseColor = tileTypeImage.GetPixelv(textureCoord);
Vector2 textureCoord = new(i, j);
Color baseColor = tileTypeImage.GetPixelv(textureCoord);
if ((i + j) % 2 == 0)
tileTypeImage.SetPixelv(textureCoord, baseColor);
@ -173,7 +280,7 @@ public class WorldChunk : Spatial
}
tileTypeImage.Unlock();
var imageTexture = new ImageTexture();
ImageTexture imageTexture = new();
imageTexture.CreateFromImage(tileTypeImage, 0);
tileTypeTexture = imageTexture;
}
@ -198,4 +305,14 @@ public class WorldChunk : Spatial
PlaneRectMesh.MaterialOverride = null;
}
public void OnTileClicked(HexTile3D tile)
{
EmitSignal("TileClicked", tile);
}
public void OnTileHovered(HexTile3D tile)
{
EmitSignal("TileHovered", tile);
}
}

View File

@ -24,6 +24,8 @@ blend_mode = 3
[node name="WorldChunk" type="Spatial"]
script = ExtResource( 1 )
[node name="Tiles" type="Spatial" parent="."]
[node name="Entities" type="Spatial" parent="."]
[node name="PlaneRectMesh" type="MeshInstance" parent="."]