using Godot; using Godot.Collections; namespace Gmtk24 { public partial class BuildingBlock : Interactible { [Signal] public delegate void PickUpEventHandler(BuildingBlock block); public BaseBlock Base; public ShaderMaterial Material; public ShaderMaterial HoverMaterial; public float RelativeScale; public uint PhysicalModeLayer; public BlockMode Mode { private set; get; } = BlockMode.Physical; private MeshInstance3D MeshInstance; private ShaderMaterial[] NormalMaterialArr; private ShaderMaterial[] HoverMaterialArr; public BuildingBlock() { Name = "BuildingBlock"; FreezeMode = FreezeModeEnum.Kinematic; CanSleep = false; } public override void _Ready() { base._Ready(); UpdatePhysics(); HoverMaterial ??= Material; Hovered += OnHover; Interacted += OnInteract; MeshInstance = new MeshInstance3D() { Mesh = Base.Mesh, Scale = Vector3.One * RelativeScale, }; AddChild(MeshInstance); int count = MeshInstance.GetSurfaceOverrideMaterialCount(); NormalMaterialArr = new ShaderMaterial[count]; HoverMaterialArr = new ShaderMaterial[count]; for (int i = 0; i < MeshInstance.GetSurfaceOverrideMaterialCount(); i++) { var replacedMaterial = MeshInstance.Mesh.SurfaceGetMaterial(i); var transparency = replacedMaterial.Get("transparency"); if (((int)transparency) != 0) { ShaderMaterial newMat = (ShaderMaterial)Material.Duplicate(); newMat.SetShaderParameter("texture_albedo_for_alpha", replacedMaterial.Get("albedo_texture")); ShaderMaterial newHoverMat = (ShaderMaterial)HoverMaterial.Duplicate(); newHoverMat.SetShaderParameter("texture_albedo_for_alpha", replacedMaterial.Get("albedo_texture")); NormalMaterialArr[i] = newMat; HoverMaterialArr[i] = newHoverMat; } else { NormalMaterialArr[i] = Material; HoverMaterialArr[i] = HoverMaterial; } MeshInstance.SetSurfaceOverrideMaterial(i, NormalMaterialArr[i]); } foreach (var shape in Base.Colliders) { var bigPoints = ((ConvexPolygonShape3D)shape.Shape).Points; var points = new Vector3[bigPoints.Length]; for (int i = 0; i < bigPoints.Length; i++) { points[i] = bigPoints[i] * RelativeScale; } AddChild(new CollisionShape3D { Shape = new ConvexPolygonShape3D { Points = points, }, }); } } public void SetMode(BlockMode mode) { GD.Print(mode); Mode = mode; SetMaterial(false); UpdatePhysics(); } private void UpdatePhysics() { if (Mode != BlockMode.NonPhysical) { CollisionLayer = PhysicalModeLayer; CollisionMask = PhysicalModeLayer; if (Mode == BlockMode.Dragged) { FreezeMode = FreezeModeEnum.Kinematic; Freeze = true; } else { Freeze = false; } } else { CollisionLayer = 0; CollisionMask = 0; FreezeMode = FreezeModeEnum.Static; Freeze = true; } } public void OnHover(bool hovered) { if (Mode != BlockMode.NonPhysical) { SetMaterial(hovered); } } private void SetMaterial(bool hoverMaterial) { for (int i = 0; i < MeshInstance.GetSurfaceOverrideMaterialCount(); i++) { if (hoverMaterial) MeshInstance.SetSurfaceOverrideMaterial(i, HoverMaterialArr[i]); else MeshInstance.SetSurfaceOverrideMaterial(i, NormalMaterialArr[i]); } } public void OnInteract(InputEvent _) { EmitSignal(SignalName.PickUp, this); } public struct BaseBlock { public Mesh Mesh; public Array Colliders; public BaseBlock(StaticBody3D reference) { Mesh = ((MeshInstance3D)reference.FindChild("*_mesh_instance")).Mesh; Colliders = new Array(); foreach (var shape in reference.FindChildren("*_collision_shape")) { Colliders.Add((CollisionShape3D)shape); } } } public enum BlockMode { Physical, Dragged, NonPhysical, } } }