136 lines
5.0 KiB
C#
Raw Normal View History

2025-09-06 17:17:39 +04:00
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
public class ManualTerrainRegionCopier : EditorWindow
{
private Terrain sourceTerrain;
private Terrain targetTerrain;
private int gridX = 0, gridZ = 0;
private int splitCount = 4;
private bool copyHeights = true;
private bool copyDetails = true;
private bool copyTrees = true;
private bool copyLayers = true;
[MenuItem("Tools/Terrain Region Copier")]
public static void ShowWindow()
{
GetWindow<ManualTerrainRegionCopier>("Copy Terrain Region");
}
void OnGUI()
{
GUILayout.Label("Копіювати сектор з Map.asset", EditorStyles.boldLabel);
sourceTerrain = (Terrain)EditorGUILayout.ObjectField("Звідки (Map)", sourceTerrain, typeof(Terrain), true);
targetTerrain = (Terrain)EditorGUILayout.ObjectField("Куди (частина)", targetTerrain, typeof(Terrain), true);
gridX = EditorGUILayout.IntSlider("Grid X (0-3)", gridX, 0, splitCount - 1);
gridZ = EditorGUILayout.IntSlider("Grid Z (0-3)", gridZ, 0, splitCount - 1);
splitCount = EditorGUILayout.IntField("Розмір сітки", splitCount);
GUILayout.Space(10);
GUILayout.Label("Що копіювати:");
copyHeights = EditorGUILayout.Toggle("Висоти", copyHeights);
copyDetails = EditorGUILayout.Toggle("Трава / деталі", copyDetails);
copyTrees = EditorGUILayout.Toggle("Дерева", copyTrees);
copyLayers = EditorGUILayout.Toggle("Текстури / шари", copyLayers);
if (GUILayout.Button("🔁 Копіювати"))
{
if (sourceTerrain == null || targetTerrain == null)
{
Debug.LogError("❌ Обери обидва Terrain'и.");
return;
}
CopyRegion(sourceTerrain, targetTerrain, gridX, gridZ, splitCount);
}
}
void CopyRegion(Terrain source, Terrain target, int gx, int gz, int grid)
{
TerrainData src = source.terrainData;
TerrainData dst = target.terrainData;
// --- HEIGHTS ---
if (copyHeights)
{
int heightRes = src.heightmapResolution - 1;
int chunkSize = heightRes / grid;
float[,] heights = src.GetHeights(gx * chunkSize, gz * chunkSize, dst.heightmapResolution, dst.heightmapResolution);
dst.SetHeights(0, 0, heights);
}
// --- DETAILS ---
if (copyDetails)
{
dst.detailPrototypes = src.detailPrototypes;
int detailRes = src.detailResolution;
int detailChunk = detailRes / grid;
dst.SetDetailResolution(detailChunk, src.detailResolutionPerPatch);
for (int i = 0; i < src.detailPrototypes.Length; i++)
{
int[,] layer = src.GetDetailLayer(gx * detailChunk, gz * detailChunk, detailChunk, detailChunk, i);
dst.SetDetailLayer(0, 0, i, layer);
}
}
// --- TREES ---
if (copyTrees)
{
dst.treePrototypes = src.treePrototypes;
List<TreeInstance> trees = new List<TreeInstance>();
Vector2 min = new Vector2(gx / (float)grid, gz / (float)grid);
Vector2 max = min + new Vector2(1f / grid, 1f / grid);
foreach (TreeInstance tree in src.treeInstances)
{
if (tree.position.x >= min.x && tree.position.x < max.x &&
tree.position.z >= min.y && tree.position.z < max.y)
{
TreeInstance t = tree;
t.position.x = (t.position.x - min.x) * grid;
t.position.z = (t.position.z - min.y) * grid;
trees.Add(t);
}
}
dst.treeInstances = trees.ToArray();
}
// --- TEXTURES (Layers + Alphamaps) ---
if (copyLayers)
{
dst.terrainLayers = src.terrainLayers;
dst.wavingGrassAmount = src.wavingGrassAmount;
dst.wavingGrassSpeed = src.wavingGrassSpeed;
dst.wavingGrassStrength = src.wavingGrassStrength;
dst.wavingGrassTint = src.wavingGrassTint;
int alphaRes = src.alphamapResolution;
int alphaChunk = alphaRes / grid;
dst.alphamapResolution = alphaChunk;
float[,,] alphaMaps = src.GetAlphamaps(gx * alphaChunk, gz * alphaChunk, alphaChunk, alphaChunk);
if (alphaMaps != null && alphaMaps.GetLength(2) == dst.terrainLayers.Length)
{
dst.SetAlphamaps(0, 0, alphaMaps);
}
else
{
Debug.LogWarning($"⚠️ Alphamap mismatch. Skipping for ({gx},{gz})");
}
}
EditorUtility.SetDirty(dst);
AssetDatabase.SaveAssets();
Debug.Log($"✅ Скопійовано сектор ({gx}, {gz}) до → {target.name}");
}
}
#endif