GodotComponentTest/scenes/WorldChunk.cs

201 lines
6.7 KiB
C#

using System.Diagnostics;
using System.Linq;
using Godot;
public class WorldChunk : Spatial
{
private readonly SpatialMaterial _rectMaterial = new();
private Sprite _heightmapSprite;
private TextureRect _heightmapTextureRect;
private Sprite _noiseMask;
private Sprite _noiseSprite;
private bool _showTextureOverlay;
[Export] public Vector2 ChunkIndex;
public Color DebugColor = Colors.White;
[Export] public Spatial Entities;
[Export] public Texture HeightMap;
public int HeightMapFrameCount;
public Viewport HeightmapOffscreenViewport;
[Export] public Texture NavigationMap;
public bool NoiseTextureCheckerboardOverlay = true;
// signals
// delegate void OnCoordClicked(Vector2 world_pos);
// other members
public Rect2 PlaneRect;
// ui elements
// scene nodes
private MeshInstance PlaneRectMesh;
[Export] public int Size = 32;
// resources
// exports
[Export] public Texture TileTypeMap;
public int TileTypeMapFrameCount;
public Viewport TileTypeOffscreenViewport;
public WorldChunk()
{
}
public WorldChunk(int size)
{
SetSize(size);
}
[Export]
public bool ShowTextureOverlay
{
get => _showTextureOverlay;
set
{
if (PlaneRectMesh != null) PlaneRectMesh.Visible = value;
}
}
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
PlaneRectMesh = (MeshInstance)FindNode("PlaneRectMesh");
Debug.Assert(PlaneRectMesh != null);
if (PlaneRectMesh.Visible) _showTextureOverlay = true;
var planeRectTransform = Transform.Identity;
planeRectTransform =
planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x, 0.125f, PlaneRect.Size.y));
planeRectTransform.origin.x = PlaneRect.GetCenter().x;
planeRectTransform.origin.z = PlaneRect.GetCenter().y;
PlaneRectMesh.Transform = planeRectTransform;
// PlaneRectMesh.MaterialOverride = new SpatialMaterial();
// ((SpatialMaterial)PlaneRectMesh.MaterialOverride).AlbedoColor = DebugColor;
// ((SpatialMaterial)PlaneRectMesh.MaterialOverride).FlagsTransparent = true;
HeightmapOffscreenViewport = (Viewport)FindNode("HeightmapOffscreenViewport");
HeightmapOffscreenViewport.Size = Vector2.One * Size;
Debug.Assert(HeightmapOffscreenViewport != null);
_noiseSprite = (Sprite)FindNode("NoiseSprite");
_noiseMask = (Sprite)FindNode("NoiseMask");
_heightmapSprite = (Sprite)FindNode("HeightmapSprite");
TileTypeOffscreenViewport = (Viewport)FindNode("TileTypeOffscreenViewport");
TileTypeOffscreenViewport.Size = Vector2.One * Size;
Debug.Assert(TileTypeOffscreenViewport != null);
Entities = (Spatial)FindNode("Entities");
Debug.Assert(Entities != null);
SetSize(World.ChunkSize);
}
public void SetSize(int size)
{
Size = size;
if (TileTypeOffscreenViewport != null)
{
TileTypeOffscreenViewport.Size = Vector2.One * size;
HeightmapOffscreenViewport.Size = Vector2.One * size;
_noiseMask.Transform = Transform2D.Identity.Scaled(Vector2.One * size / _noiseMask.Texture.GetSize().x);
_noiseSprite.Transform = Transform2D.Identity.Scaled(Vector2.One * size / _noiseSprite.Texture.GetSize().x);
_heightmapSprite.Transform =
Transform2D.Identity.Scaled(Vector2.One * size / _heightmapSprite.Texture.GetSize().x);
}
}
// other members
public void SaveToFile(string chunkName)
{
var image = new Image();
image.CreateFromData(Size, Size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData());
image.SavePng(chunkName + "_tileType.png");
image.CreateFromData(Size, Size, false, Image.Format.Rgba8, NavigationMap.GetData().GetData());
image.SavePng(chunkName + "_navigationMap.png");
image.CreateFromData(Size, Size, false, Image.Format.Rgba8, HeightMap.GetData().GetData());
image.SavePng(chunkName + "_heightMap.png");
}
public void LoadFromFile(string chunkName)
{
}
public void SetNoisemap(Texture texture)
{
_noiseSprite.Texture = texture;
_noiseSprite.Transform =
Transform2D.Identity.Scaled(HeightmapOffscreenViewport.Size / _noiseSprite.Texture.GetSize().x);
HeightmapOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once;
HeightMapFrameCount = 1;
}
public void SetHeightmap(Texture texture)
{
_heightmapSprite.Texture = texture;
_heightmapSprite.Transform =
Transform2D.Identity.Scaled(TileTypeOffscreenViewport.Size / _heightmapSprite.Texture.GetSize());
TileTypeOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once;
TileTypeMapFrameCount = 1;
}
public override void _Process(float delta)
{
Texture tileTypeTexture = TileTypeOffscreenViewport.GetTexture();
if (NoiseTextureCheckerboardOverlay)
{
var tileTypeImage = tileTypeTexture.GetData();
tileTypeImage.Lock();
foreach (var i in Enumerable.Range(0, Size))
foreach (var j in Enumerable.Range(0, Size))
{
var textureCoord = new Vector2(i, j);
var baseColor = tileTypeImage.GetPixelv(textureCoord);
if ((i + j) % 2 == 0)
tileTypeImage.SetPixelv(textureCoord, baseColor);
else
tileTypeImage.SetPixelv(textureCoord, baseColor * 0.6f);
}
tileTypeImage.Unlock();
var imageTexture = new ImageTexture();
imageTexture.CreateFromImage(tileTypeImage, 0);
tileTypeTexture = imageTexture;
}
_rectMaterial.AlbedoTexture = tileTypeTexture;
_rectMaterial.FlagsTransparent = true;
// _rectMaterial.AlbedoTexture = _heightmapRect.Texture;
_rectMaterial.Uv1Scale = new Vector3(-3, -2, 1);
_rectMaterial.Uv1Offset = Vector3.One * 2;
//RectMaterial.Uv1Triplanar = true;
PlaneRectMesh.SetSurfaceMaterial(0, _rectMaterial);
if (HeightMapFrameCount == 0) HeightmapOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Disabled;
HeightMapFrameCount = HeightMapFrameCount > 0 ? HeightMapFrameCount - 1 : 0;
if (TileTypeMapFrameCount == 0) TileTypeOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Disabled;
TileTypeMapFrameCount = TileTypeMapFrameCount > 0 ? TileTypeMapFrameCount - 1 : 0;
PlaneRectMesh.MaterialOverride = null;
}
}