public void RenderTerrain(MapGenerator gen, TacticsTerrainMesh mesh) { switch (type) { case CellType.Hall: RenderHall(gen, mesh); break; case CellType.Stairway: RenderStairway(gen, mesh); break; case CellType.Switchback: RenderSwitchback(gen, mesh); break; case CellType.Pillar: RenderPillar(gen, mesh); break; case CellType.Room: RenderRoom(gen, mesh); break; } }
private void UpdateTile(TerrainQuad quad, Tile tile) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; quad.UpdateTile(tile, tileset, 0.0f); terrain.SetTile((int)quad.pos.x, (int)quad.pos.z, tile); }
public bool CanSeeLocation(TacticsTerrainMesh mesh, Vector2Int to) { LineOfSightEffect los = battle.GetComponent <LineOfSightEffect>(); if (los.sitemap == null) { los.RegenSitemap(mesh); } if (sight == 0) { sight = unit.Get(StatTag.SIGHT); } //return MathHelper3D.InLos(mesh, this.location, location, sight); Vector2Int at = location; Vector3 at3 = new Vector3(at.x + 0.5f, mesh.HeightAt(at.x, at.y) + 1.5f, at.y + 0.5f); Vector3 to3 = new Vector3(to.x + 0.5f, mesh.HeightAt(to.x, to.y) + 1.5f, to.y + 0.5f); Vector3 delta = (to3 - at3); if (delta.sqrMagnitude > sight * sight) { return(false); } else { return(los.sitemap[ to.y * (mesh.size.x * mesh.size.y * mesh.size.x) + to.x * (mesh.size.x * mesh.size.y) + at.y * (mesh.size.x) + at.x]); } }
private void UpdateTile(TerrainQuad quad, OrthoDir dir, Tile tile) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; quad.UpdateTile(tile, tileset, quad.pos.y); terrain.SetTile((int)quad.pos.x, (int)quad.pos.z, quad.pos.y - 0.5f, dir, tile); }
public static bool InLos(TacticsTerrainMesh mesh, Vector2Int at, Vector2Int to, float range) { if (at == to) { return(true); } Vector3 at3 = new Vector3(at.x + 0.5f, mesh.HeightAt(at.x, at.y) + 1.5f, at.y + 0.5f); Vector3 to3 = new Vector3(to.x + 0.5f, mesh.HeightAt(to.x, to.y) + 1.5f, to.y + 0.5f); Vector3 delta = (to3 - at3); if (delta.sqrMagnitude > range * range) { return(false); } Vector3 planar = Vector3.Cross(delta, new Vector3(0, 1, 0)).normalized; if (ClearRayExists(mesh, at3 + planar * 0.4f, to3 + planar * 0.4f)) { return(true); } else if (ClearRayExists(mesh, at3 - planar * 0.5f, to3 - planar * 0.5f)) { return(true); } else { return(false); } }
private void AddEvent(MapEvent3D mapEvent) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; Map map = terrain.GetComponent <Map>(); GameObjectUtility.SetParentAndAlign(mapEvent.gameObject, map.objectLayer.gameObject); Undo.RegisterCreatedObjectUndo(mapEvent, "Create " + mapEvent.name); mapEvent.SetLocation(new Vector2Int((int)primarySelection.pos.x, (int)primarySelection.pos.z)); Selection.activeObject = mapEvent.gameObject; }
private void RenderPillar(MapGenerator gen, TacticsTerrainMesh mesh) { for (int y = startY; y < startY + sizeY; y += 1) { for (int x = startX; x < startX + sizeX; x += 1) { mesh.SetHeight(x, y, pillarZ); } } }
private void RenderRoom(MapGenerator gen, TacticsTerrainMesh mesh) { RoomInfo room = gen.rooms[x / 2, y / 2]; for (int y = startY; y < startY + sizeY; y += 1) { for (int x = startX; x < startX + sizeX; x += 1) { mesh.SetHeight(x, y, room.z); } } }
private void PaintTileIfNeeded() { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; foreach (TerrainQuad quad in selectedQuads) { if (quad.normal.y > 0.0f) { int originX = (int)primarySelection.pos.x - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.x) / 2.0f); int originY = (int)primarySelection.pos.z - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.y) / 2.0f); Tile tile = TileForSelection((int)(quad.pos.x - originX), (int)(quad.pos.z - originY)); UpdateTile(quad, tile); } else { Tile tile; if (quad.normal.x != 0.0f) { int originX = (int)primarySelection.pos.z - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.x) / 2.0f); int originY = (int)primarySelection.pos.y - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.y) / 2.0f); tile = TileForSelection((int)(quad.pos.z - originX), (int)(quad.pos.y - originY)); } else { int originX = (int)primarySelection.pos.x - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.x) / 2.0f); int originY = (int)primarySelection.pos.y - Mathf.FloorToInt(Mathf.RoundToInt(selectionSize.y) / 2.0f); tile = TileForSelection((int)(quad.pos.x - originX), (int)(quad.pos.y - originY)); } if (wraparoundPaintMode) { foreach (OrthoDir dir in Enum.GetValues(typeof(OrthoDir))) { UpdateTile(quad, dir, tile); } } else { UpdateTile(quad, OrthoDirExtensions.DirectionOf3D(quad.normal), tile); } } } RepaintMesh(); primarySelection = GetSelectedQuad(); CaptureSelection(primarySelection); PrefabStage prefabStage = PrefabStageUtility.GetPrefabStage(terrain.gameObject); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } }
public static bool ClearRayExists(TacticsTerrainMesh mesh, Vector3 start, Vector3 end) { Vector3 slope = (end - start).normalized; float atX = start.x; float atY = start.y; float atZ = start.z; float totalM = 0.0f; float targetM = (end - start).sqrMagnitude; for (int tries = 0; tries < 10000; tries += 1) { float toNextX = slope.x > 0 ? (1.0f - atX % 1) : (atX % 1); float mToX = toNextX < float.Epsilon ? float.MaxValue : Mathf.Abs(toNextX / slope.x); float toNextY = slope.y > 0 ? (1.0f - atY % 1) : (atY % 1); float mToY = toNextY < float.Epsilon ? float.MaxValue : Mathf.Abs(toNextY / slope.y); float toNextZ = slope.z > 0 ? (1.0f - atZ % 1) : (atZ % 1); float mToZ = toNextZ < float.Epsilon ? float.MaxValue : Mathf.Abs(toNextZ / slope.z); float nextM; if (!float.IsInfinity(mToX) && mToX < mToY && mToX < mToZ) { nextM = mToX; } else if (!float.IsInfinity(mToY) && mToY < mToZ && mToY < mToZ) { nextM = mToY; } else { nextM = mToZ; } atX += nextM * slope.x; atY += nextM * slope.y; atZ += nextM * slope.z; totalM += nextM; if (totalM * totalM > targetM) { return(true); } if (mesh.HeightAt(Mathf.FloorToInt(atX), Mathf.FloorToInt(atZ)) > atY) { // translucency would go here but, no if (Math.Abs(Mathf.Floor(atX) - Mathf.Floor(start.x)) > 0.0f || Math.Abs(Mathf.Floor(atZ) - Mathf.Floor(start.z)) > 0.0f) { return(false); } } } Debug.LogError("major fuckup"); return(true); }
private void RenderSwitchback(MapGenerator gen, TacticsTerrainMesh mesh) { RoomInfo lowRoom, highRoom; if (this.x % 2 == 1) { lowRoom = gen.rooms[(this.x - 1) / 2, this.y / 2]; highRoom = gen.rooms[(this.x + 1) / 2, this.y / 2]; } else { lowRoom = gen.rooms[this.x / 2, (this.y - 1) / 2]; highRoom = gen.rooms[this.x / 2, (this.y + 1) / 2]; } if (lowRoom.z > highRoom.z) { RoomInfo temp = lowRoom; lowRoom = highRoom; highRoom = temp; } float deltaZ = highRoom.z - lowRoom.z; float d = (float)deltaZ / (sizeX * sizeY); bool switched = false; int x = 0; int y = 0; for (int i = 0; i < sizeX * sizeY; i += 1) { mesh.SetHeight(startX + x, startY + y, lowRoom.z + Mathf.RoundToInt(d * i * 2.0f) / 2.0f); if (this.x % 2 == 1) { y += switched ? -1 : 1; if (y >= sizeY || y < 0) { switched = !switched; x += 1; y = Math.Min(Math.Max(y, 0), sizeY - 1); } } else { x += switched ? -1 : 1; if (x >= sizeX || x < 0) { switched = !switched; y += 1; x = Math.Min(Math.Max(x, 0), sizeX - 1); } } } }
private void UpdateWithPalette(GridPalette newPalette) { tileSelectRect = new Rect(0, 0, 1, 1); paletteBufferSize = Vector2Int.zero; TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; palette = newPalette; terrain.paletteName = palette.name; string palettePath = "Assets/Tilesets/Palettes/" + palette.name + ".prefab"; GameObject tilesetObject = AssetDatabase.LoadAssetAtPath <GameObject>(palettePath); tileset = tilesetObject.transform.GetChild(0).GetComponent <Tilemap>(); }
// selects a square to be targeted by the acting unit, might be canceled public IEnumerator SelectTargetDirRoutine(Result <EightDir> result, BattleUnit actingUnit, List <EightDir> allowedDirs, bool canCancel = true) { actor = actingUnit.battler; gameObject.SetActive(true); actingUnit.battle.cursor.DisableReticules(); SelectionGrid grid = actingUnit.battle.SpawnSelectionGrid(); TacticsTerrainMesh terrain = actingUnit.battle.map.terrain; grid.ConfigureNewGrid(actingUnit.location, 1, terrain, (Vector2Int loc) => { return((loc.x + loc.y + actingUnit.location.x + actingUnit.location.y) % 2 < 2); }, (Vector2Int loc) => { return(allowedDirs.Contains(actingUnit.battler.GetComponent <MapEvent>().DirectionTo(loc))); }); if (allowedDirs.Count > 0) { AttemptSetDirection(allowedDirs[0]); } else { GetComponent <MapEvent>().SetLocation(actor.location); } while (!result.finished) { Result <EightDir> dirResult = new Result <EightDir>(); yield return(AwaitSelectionRoutine(actor, dirResult)); if (dirResult.canceled) { if (canCancel) { result.Cancel(); break; } } else { result.value = dirResult.value; } } Destroy(grid.gameObject); actingUnit.battle.cursor.EnableReticules(); gameObject.SetActive(false); }
private void RenderHall(MapGenerator gen, TacticsTerrainMesh mesh) { List <RoomInfo> rooms = AdjacentRooms(gen); float z = rooms[0].z < rooms[1].z ? rooms[0].z : rooms[1].z; RoomInfo room = gen.rooms[x / 2, y / 2]; for (int y = startY; y < startY + sizeY; y += 1) { for (int x = startX; x < startX + sizeX; x += 1) { mesh.SetHeight(x, y, z); } } }
private void RepaintMesh() { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; Vector2[] uvArray = new Vector2[terrain.GetComponent <MeshFilter>().sharedMesh.uv.Length]; foreach (Dictionary <Vector3, TerrainQuad> quadDictionary in quads.Values) { foreach (TerrainQuad quad in quadDictionary.Values) { quad.CopyUVs(uvArray); } } terrain.GetComponent <MeshFilter>().sharedMesh.uv = uvArray; uvs = new List <Vector2>(uvArray); }
public void OnSceneGUI() { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; if (quads == null) { Rebuild(false); } int controlId = GUIUtility.GetControlID(FocusType.Passive); EventType typeForControl = Event.current.GetTypeForControl(controlId); switch (Event.current.button) { case 0: HandleLeftclick(typeForControl, controlId); break; case 1: HandleRightclick(typeForControl, controlId); break; } TerrainQuad quad = GetSelectedQuad(); switch (typeForControl) { case EventType.MouseMove: switch (mode) { case EditMode.None: case EditMode.Painting: if (quad != primarySelection) { CaptureSelection(quad); primarySelection = quad; SceneView.RepaintAll(); } break; } break; } MathHelper3D.DrawQuads(selectedQuads, Color.white); }
private Tile TileForSelection(int x, int y) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; if (paletteBufferSize == Vector2.zero) { return(terrain.tileset.GetTile <Tile>(new Vector3Int( (int)tileSelectRect.x + (x % (int)tileSelectRect.width), (int)tileSelectRect.y + (y % (int)tileSelectRect.height), 0))); } else { return(paletteBuffer[ (x % paletteBufferSize.x) + (y % paletteBufferSize.y) * (paletteBufferSize.x)]); } }
public void FillWithVault(TacticsTerrainMesh mesh) { if (RandUtils.Chance(0.4f)) { return; } if (vaults == null) { vaults = Resources.Load <VaultList>(VaultsPath); } bool flipX = RandUtils.Flip(); bool flipY = RandUtils.Flip(); TacticsTerrainMesh vault = vaults.vaults[Random.Range(0, vaults.vaults.Count)]; for (int trueY = 0; trueY < cell.sizeY; trueY += 1) { for (int trueX = 0; trueX < cell.sizeX; trueX += 1) { int x = flipX ? trueX : (cell.sizeX - 1 - trueX); int y = flipY ? trueY : (cell.sizeY - 1 - trueY); mesh.SetHeight(cell.startX + x, cell.startY + y, mesh.HeightAt(cell.startX + x, cell.startY + y) + vault.HeightAt(x, y) - 1.0f); Tile topTile = vault.TileAt(x, y); if (topTile != mesh.defaultTopTile) { mesh.SetTile(cell.startX + x, cell.startY + y, topTile); } for (float h = 0.0f; h < vault.HeightAt(x, y); h += 0.5f) { foreach (OrthoDir dir in System.Enum.GetValues(typeof(OrthoDir))) { Tile t = vault.TileAt(x, y, h, dir); if (t != mesh.defaultFaceTile) { mesh.SetTile(cell.startX + x, cell.startY + y, mesh.HeightAt(x, y) - 1 + h, dir, t); } } } } } }
private void AssignCommonShaderVariables() { Material material = FindMaterial(); if (Application.isPlaying) { if (pc == null || pc.GetComponent <BattleEvent>() == null) { return; } TacticsTerrainMesh mesh = GetComponent <TacticsTerrainMesh>(); material.SetFloat("_CellResolutionX", mesh.size.x); material.SetFloat("_CellResolutionY", mesh.size.y); material.SetTexture("_VisibilityTex", losTexture); material.SetFloat("_VisibilityBlend", visBlend); material.SetVector("_HeroPos", heroPos); material.SetFloat("_SightRange", pc.GetComponent <BattleEvent>().unit.Get(StatTag.SIGHT)); if (oldLosTexture != null) { material.SetTexture("_OldVisibilityTex", oldLosTexture); } else { material.SetTexture("_OldVisibilityTex", losTexture); } if (oldHeroPos == Vector3.zero) { material.SetVector("_OldHeroPos", heroPos); } else { material.SetVector("_OldHeroPos", oldHeroPos); } } else { material.SetFloat("_SightRange", 1000.0f); } }
private void Rebuild(bool regenMesh) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; PrefabStage prefabStage = PrefabStageUtility.GetPrefabStage(terrain.gameObject); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } MeshGenerationResult result = terrain.Rebuild(regenMesh); quads = result.quads; tris = result.tris; uvs = result.uvs; vertices = result.vertices; if (regenMesh) { selectedQuads.Clear(); } }
// SITEMAP GARBAGE ============== public void RegenSitemap(TacticsTerrainMesh mesh) { Vector3 v1 = new Vector3(); Vector3 v2 = new Vector3(); sitemap = new BitArray(mesh.size.x * mesh.size.y * mesh.size.x * mesh.size.y); for (int y1 = 0; y1 < mesh.size.y; y1 += 1) { for (int x1 = 0; x1 < mesh.size.x; x1 += 1) { for (int y2 = 0; y2 < mesh.size.y; y2 += 1) { for (int x2 = 0; x2 < mesh.size.x; x2 += 1) { bool res = false; int dx = x1 - x2; int dy = y1 - y2; if (dx * dx + dy * dy < 10 * 10) { v1.x = x1; v1.y = mesh.heights[y1 * mesh.size.x + x1] + 1.0f; v1.z = y1; v2.x = x2; v2.y = mesh.heights[y2 * mesh.size.x + x2] + 1.0f; v2.z = y2; res = MathHelper3D.ClearRayExists(mesh, v1, v2); } sitemap[ y2 * (mesh.size.x * mesh.size.y * mesh.size.x) + x2 * (mesh.size.x * mesh.size.y) + y1 * (mesh.size.x) + x1] = res; } } } } }
private void Rebuild(bool regenMesh) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; PrefabStage prefabStage = PrefabStageUtility.GetPrefabStage(terrain.gameObject); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } MeshFilter filter = terrain.GetComponent <MeshFilter>(); Mesh mesh = filter.sharedMesh; if (mesh == null) { mesh = new Mesh(); AssetDatabase.CreateAsset(mesh, "Assets/Resources/TacticsMaps/Meshes/" + terrain.gameObject.name + ".asset"); filter.sharedMesh = mesh; } quads = new Dictionary <Vector3, Dictionary <Vector3, TerrainQuad> >(); vertices = new List <Vector3>(); uvs = new List <Vector2>(); tris = new List <int>(); for (int z = 0; z < terrain.size.y; z += 1) { for (int x = 0; x < terrain.size.x; x += 1) { // top vertices float height = terrain.HeightAt(x, z); AddQuad(new Vector3(x, height, z), new Vector3(x + 1, height, z + 1), terrain.TileAt(x, z), new Vector3(x, height, z), new Vector3(0, 1, 0)); // side vertices foreach (OrthoDir dir in Enum.GetValues(typeof(OrthoDir))) { float currentHeight = terrain.HeightAt(x, z); float neighborHeight = terrain.HeightAt(x + dir.Px3DX(), z + dir.Px3DZ()); if (currentHeight > neighborHeight) { Vector2 off1 = Vector2.zero, off2 = Vector2.zero; switch (dir) { case OrthoDir.South: off1 = new Vector2(0, 0); off2 = new Vector2(1, 0); break; case OrthoDir.East: off1 = new Vector2(1, 1); off2 = new Vector2(1, 0); break; case OrthoDir.North: off1 = new Vector2(1, 1); off2 = new Vector2(0, 1); break; case OrthoDir.West: off1 = new Vector2(0, 0); off2 = new Vector2(0, 1); break; } for (float y = neighborHeight; y < currentHeight; y += 0.5f) { AddQuad(new Vector3(x + off1.x, y, z + off1.y), new Vector3(x + off2.x, y + 0.5f, z + off2.y), terrain.TileAt(x, z, y, dir), new Vector3(x, y + 0.5f, z), dir.Px3D()); } } } } } if (regenMesh) { selectedQuads.Clear(); mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.triangles = tris.ToArray(); mesh.uv = uvs.ToArray(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); } }
public void RecalculateVisibilityMap() { Profiler.BeginSample("los"); mesh = GetComponent <TacticsTerrainMesh>(); if (seenMap == null) { seenMap = new bool[mesh.size.x, mesh.size.y]; for (int y = 0; y < mesh.size.y; y += 1) { for (int x = 0; x < mesh.size.x; x += 1) { seenMap[x, y] = false; } } if (Application.isPlaying) { pc = Global.Instance().Maps.pc; } if (pc == null) { pc = FindObjectOfType <PCEvent>(); } } if (oldLosTexture != null) { Destroy(oldLosTexture); } oldLosTexture = losTexture; oldHeroPos = heroPos; losTexture = new Texture2D(mesh.size.x, mesh.size.y, TextureFormat.ARGB32, false); losTexture.filterMode = FilterMode.Point; losTexture.wrapMode = TextureWrapMode.Clamp; heroPos = pc.GetComponent <MapEvent3D>().TileToWorldCoords(pc.GetComponent <MapEvent>().location); heroPos += new Vector3(0.5f, 1.5f, 0.5f); map = new Color[mesh.size.x * mesh.size.y]; BattleEvent battler = pc.GetComponent <BattleEvent>(); Vector2Int v = new Vector2Int(); for (int y = 0; y < mesh.size.y; y += 1) { for (int x = 0; x < mesh.size.x; x += 1) { float r = 1.0f; float b = 1.0f; v.x = x; v.y = y; if (battler.CanSeeLocation(mesh, v)) { seenMap[x, y] = true; } else { r = 0.0f; b = seenMap[x, y] ? 1.0f : 0.0f; } map[y * mesh.size.x + x] = new Color(r, 0.0f, b); } } losTexture.SetPixels(0, 0, mesh.size.x, mesh.size.y, map); losTexture.Apply(); foreach (PCVisibility vis in GetComponent <Map>().GetEvents <PCVisibility>()) { Vector2Int location = vis.GetComponent <MapEvent>().location; vis.SetVisibleByPC(CachedIsVisible(location)); } Profiler.EndSample(); }
public void GenerateMesh(MapGenerator lastMap = null) { TacticsTerrainMesh mesh = GetComponent <TacticsTerrainMesh>(); // copy oldbie values if needed if (lastMap != null) { sizeInRoomsMin = lastMap.sizeInRoomsMin; sizeInRoomsMax = lastMap.sizeInRoomsMax; stairLength = lastMap.stairLength; startEventPrefab = lastMap.startEventPrefab; endEventPrefab = lastMap.endEventPrefab; impassEventPrefab = lastMap.impassEventPrefab; defaultImpassTile = lastMap.defaultImpassTile; chestEventPrefab = lastMap.chestEventPrefab; targetPrefab = lastMap.targetPrefab; finalLevel = lastMap.finalLevel; finalLevelPrefab = lastMap.finalLevelPrefab; table = lastMap.table; level = lastMap.level + 1; } if (level == finalLevel) { Map other = Instantiate(finalLevelPrefab); Global.Instance().Maps.activeMap = other; return; } // wipe what's already there mesh.ClearTiles(); foreach (MapEvent toRemove in GetComponent <Map>().GetEvents <MapEvent>()) { if (toRemove.GetComponent <PCEvent>() == null) { if (toRemove.GetComponent <BattleEvent>() && Application.isPlaying) { GetComponent <BattleController>().RemoveUnit(toRemove.GetComponent <BattleEvent>().unit); } GetComponent <Map>().RemoveEvent(toRemove, true); } } // work out some constants if (Flip()) { sizeInRooms = new Vector2Int(sizeInRoomsMin.x, sizeInRoomsMax.y); } else { sizeInRooms = new Vector2Int(sizeInRoomsMax.x, sizeInRoomsMin.y); } int seed = (int)DateTime.Now.Ticks; Random.InitState(seed); Debug.Log("using seed " + seed); rooms = new RoomInfo[sizeInRooms.x, sizeInRooms.y]; sizeInCells = sizeInRooms * 2 - new Vector2Int(1, 1); cells = new CellInfo[sizeInCells.x, sizeInCells.y]; // are we going to add the starting stairwell on the left or right? if (lastMap != null) { if (lastMap.endStairsNW) { entryRoomCoords = new Vector2Int(Random.Range(0, 2), 0); startStairsSW = false; } else { entryRoomCoords = new Vector2Int(0, Random.Range(0, 2)); startStairsSW = true; } exitRoomCoords = new Vector2Int(sizeInRooms.x - 1, sizeInRooms.y - 1); if (Flip()) { exitRoomCoords.x -= Random.Range(0, 2); } else { exitRoomCoords.y -= Random.Range(0, 2); } } else { if (entryRoomCoords == Vector2Int.zero) { startStairsSW = Flip(); } else if (entryRoomCoords.y > 0) { startStairsSW = true; } else { startStairsSW = false; } } if (exitRoomCoords == new Vector2Int(sizeInRooms.x - 1, sizeInRooms.y - 1)) { endStairsNW = Flip(); } else if (exitRoomCoords.x < sizeInRooms.x - 1) { endStairsNW = true; } else { endStairsNW = false; } // set the size and start of each room and hallway cells = new CellInfo[sizeInCells.x, sizeInCells.y]; widths = new int[sizeInCells.x]; heights = new int[sizeInCells.y]; for (int y = 0; y < sizeInCells.y; y += 1) { if (y % 2 == 1) { heights[y] = RandomHallSize(); } else { heights[y] = RandomRoomSize(); } } for (int x = 0; x < sizeInCells.x; x += 1) { if (x % 2 == 1) { widths[x] = RandomHallSize(); } else { widths[x] = RandomRoomSize(); } } for (int y = 0; y < sizeInCells.y; y += 1) { for (int x = 0; x < sizeInCells.x; x += 1) { cells[x, y] = new CellInfo(x, y, widths[x], heights[y]); if (x % 2 == 1 || y % 2 == 1) { if (x % 2 == 1 && y % 2 == 1) { cells[x, y].type = CellInfo.CellType.Pillar; } else { cells[x, y].type = CellInfo.CellType.Hall; } } else { cells[x, y].type = CellInfo.CellType.Room; } if (x == 0) { cells[x, y].startX = startStairsSW ? stairLength : 0; } else { cells[x, y].startX = cells[x - 1, y].startX + widths[x - 1]; } if (y == 0) { cells[x, y].startY = startStairsSW ? 0 : stairLength; } else { cells[x, y].startY = cells[x, y - 1].startY + heights[y - 1]; } } } // set the elevation of each room for (int diag = 0; diag < sizeInRooms.x + sizeInRooms.y; diag += 1) { int x = diag; int y = 0; while (x >= 0) { if (x < sizeInRooms.x && y < sizeInRooms.y) { float z; if (x == 0 && y == 0) { z = stairLength / 2.0f + 0.5f; } else { float oldZ; if (y == 0) { oldZ = rooms[x - 1, y].z; } else if (x == 0) { oldZ = rooms[x, y - 1].z; } else { oldZ = Math.Max(rooms[x, y - 1].z, rooms[x - 1, y].z); } z = RandomNewZ(oldZ); } rooms[x, y] = new RoomInfo(cells[x * 2, y * 2], z); } x -= 1; y += 1; } } // determine the initial passability map cells[0, 0].connected = true; UpdatePassability(); // knock down walls until all rooms are accessible List <RoomInfo> roomsToGo = new List <RoomInfo>(); for (int x = 0; x < sizeInRooms.x; x += 1) { for (int y = 0; y < sizeInRooms.y; y += 1) { roomsToGo.Add(rooms[x, y]); } } while (roomsToGo.Count > 0) { int index = Random.Range(0, roomsToGo.Count); RoomInfo room = roomsToGo[index]; if (room.cell.connected) { roomsToGo.RemoveAt(index); continue; } List <RoomInfo> adjacents = room.cell.AdjacentRooms(this); RandUtils.Shuffle(adjacents); RoomInfo adj = null; foreach (RoomInfo adj2 in adjacents) { if (!adj2.cell.connected) { continue; } CellInfo connector = cells[(room.cell.x + adj2.cell.x) / 2, (room.cell.y + adj2.cell.y) / 2]; if (Mathf.Abs(adj2.z - room.z) / (widths[connector.x] * heights[connector.y]) > 2) { continue; } adj = adj2; break; } if (adj == null) { continue; } roomsToGo.RemoveAt(index); cells[(room.cell.x + adj.cell.x) / 2, (room.cell.y + adj.cell.y) / 2].connected = true; room.cell.connected = adj.cell.connected; if (adj.cell.connected) { UpdatePassability(); } } // convert halls into stairways as needed for (int y = 0; y < sizeInCells.y; y += 1) { for (int x = 0; x < sizeInCells.x; x += 1) { CellInfo cell = cells[x, y]; if (cell.type == CellInfo.CellType.Hall && cell.connected) { List <RoomInfo> rooms = cell.AdjacentRooms(this); float deltaZ = Math.Abs(rooms[0].z - rooms[1].z); if (deltaZ > 1) { if (deltaZ > cell.sizeX / 2 && deltaZ > cell.sizeY / 2) { cell.type = CellInfo.CellType.Switchback; } else { cell.type = CellInfo.CellType.Stairway; } } } } } // set pillar heights to sane values for (int y = 0; y < sizeInCells.y; y += 1) { for (int x = 0; x < sizeInCells.x; x += 1) { CellInfo cell = cells[x, y]; if (cell.type == CellInfo.CellType.Pillar) { CellInfo n = cells[x, y + 1]; CellInfo e = cells[x + 1, y]; CellInfo s = cells[x, y - 1]; CellInfo w = cells[x - 1, y]; if (n.type == CellInfo.CellType.Stairway && e.type == CellInfo.CellType.Stairway) { cell.pillarZ = rooms[(x + 1) / 2, (y + 1) / 2].z; e.stairAnchoredHigh = true; n.stairAnchoredHigh = true; } else if (s.type == CellInfo.CellType.Switchback && s.sizeX > 1) { cell.pillarZ = (s.AdjacentRooms(this)[0].z + s.AdjacentRooms(this)[1].z) / 2.0f; } else if (w.type == CellInfo.CellType.Switchback && s.sizeY > 1) { cell.pillarZ = (w.AdjacentRooms(this)[0].z + w.AdjacentRooms(this)[1].z) / 2.0f; } else { cell.pillarZ = rooms[(x - 1) / 2, (y - 1) / 2].z; } } } } // decorator fringe RoomInfo cornerRoom = rooms[sizeInRooms.x - 1, sizeInRooms.y - 1]; int wallX = cornerRoom.cell.startX + cornerRoom.cell.sizeX + 1; int wallY = cornerRoom.cell.startY + cornerRoom.cell.sizeY + 1; mesh.Resize(new Vector2Int( wallX + (endStairsNW ? 0 : stairLength), wallY + (endStairsNW ? stairLength : 0)), 0.0f); for (int x = startStairsSW ? stairLength : 0; x < wallX; x += 1) { mesh.SetHeight(x, wallY - 1, cornerRoom.z + MaxHeightDelta + 1); mesh.SetTile(x, wallY - 1, defaultImpassTile); } for (int y = startStairsSW ? 0 : stairLength; y < wallY; y += 1) { mesh.SetHeight(wallX - 1, y, cornerRoom.z + MaxHeightDelta + 1); mesh.SetTile(wallX - 1, y, defaultImpassTile); } // render terrain for (int y = 0; y < sizeInCells.y; y += 1) { for (int x = 0; x < sizeInCells.x; x += 1) { CellInfo cell = cells[x, y]; if (cell.type != CellInfo.CellType.Pillar) { cell.RenderTerrain(this, mesh); } } } for (int y = 0; y < sizeInCells.y; y += 1) { for (int x = 0; x < sizeInCells.x; x += 1) { CellInfo cell = cells[x, y]; if (cell.type == CellInfo.CellType.Pillar) { cell.RenderTerrain(this, mesh); } } } // render rooms for (int x = 0; x < sizeInRooms.x; x += 1) { for (int y = 0; y < sizeInRooms.y; y += 1) { rooms[x, y].FillWithVault(mesh); } } // add the starter stairs RoomInfo startRoom = rooms[entryRoomCoords.x, entryRoomCoords.y]; int stairX, stairZ; if (startStairsSW) { stairX = startRoom.cell.startX - 1; stairZ = startRoom.cell.startY + (startRoom.cell.sizeY / 2); } else { stairX = startRoom.cell.startX + (startRoom.cell.sizeX / 2); stairZ = startRoom.cell.startY - 1; } float stairY = startRoom.z - 0.5f; for (int i = 0; i < stairLength; i += 1) { mesh.SetHeight(stairX, stairZ, stairY); MapEvent3D ev; if (i == 0) { ev = Instantiate(startEventPrefab); } else { ev = Instantiate(impassEventPrefab); } GetComponent <Map>().AddEvent(ev); ev.SetLocation(new Vector2Int(stairX, stairZ)); stairY -= 0.5f; stairX += startStairsSW ? -1 : 0; stairZ += startStairsSW ? 0 : -1; } // add the end stairs RoomInfo endRoom = rooms[exitRoomCoords.x, exitRoomCoords.y]; if (endStairsNW) { stairX = endRoom.cell.startX + (endRoom.cell.sizeX / 2); stairZ = endRoom.cell.startY + endRoom.cell.sizeY; } else { stairX = endRoom.cell.startX + endRoom.cell.sizeX; stairZ = endRoom.cell.startY + (endRoom.cell.sizeY / 2); } stairY = endRoom.z + 0.5f; for (int i = 0; i < stairLength; i += 1) { MapEvent3D ev; if (i == 0) { ev = Instantiate(endEventPrefab); } else { ev = Instantiate(impassEventPrefab); } GetComponent <Map>().AddEvent(ev); ev.SetLocation(new Vector2Int(stairX, stairZ)); mesh.SetHeight(stairX, stairZ, stairY); stairY += 0.5f; stairX += endStairsNW ? 0 : 1; stairZ += endStairsNW ? 1 : 0; } // add the zoom target MapEvent3D zoom = Instantiate(targetPrefab); GetComponent <Map>().AddEvent(zoom); zoom.SetLocation(new Vector2Int(mesh.size.x / 2, mesh.size.y / 2)); // generate the encounters List <RoomInfo> validRooms = new List <RoomInfo>(); for (int x = 0; x < sizeInRooms.x; x += 1) { for (int y = 0; y < sizeInRooms.y; y += 1) { if (x != entryRoomCoords.x || y != entryRoomCoords.y) { validRooms.Add(rooms[x, y]); } } } List <Encounter> encounters = table.GenerateEncounters(level); foreach (Encounter encounter in encounters) { RoomInfo room = validRooms[Random.Range(0, validRooms.Count)]; Vector2Int loc = new Vector2Int( Random.Range(room.cell.startX, room.cell.startX + room.cell.sizeX), Random.Range(room.cell.startY, room.cell.startY + room.cell.sizeY)); encounter.PlaceAt(GetComponent <Map>(), loc); } // generate the chests List <Item> items = table.GenerateItems(level); foreach (Item item in items) { ChestEvent chest = Instantiate(chestEventPrefab); GetComponent <Map>().AddEvent(chest.GetComponent <MapEvent>()); Vector2Int loc; do { RoomInfo room = validRooms[Random.Range(0, validRooms.Count)]; loc = new Vector2Int( Random.Range(room.cell.startX + 1, room.cell.startX + room.cell.sizeX - 1), Random.Range(room.cell.startY + 1, room.cell.startY + room.cell.sizeY - 1)); } while (!chest.GetComponent <MapEvent>().CanPassAt(loc)); chest.PopulateAndPlace(item, loc); } mesh.Rebuild(true); }
private void RenderStairway(MapGenerator gen, TacticsTerrainMesh mesh) { RoomInfo lowRoom, highRoom; if (x % 2 == 1) { lowRoom = gen.rooms[(x - 1) / 2, y / 2]; highRoom = gen.rooms[(x + 1) / 2, y / 2]; } else { lowRoom = gen.rooms[x / 2, (y - 1) / 2]; highRoom = gen.rooms[x / 2, (y + 1) / 2]; } if (lowRoom.z > highRoom.z) { RoomInfo temp = lowRoom; lowRoom = highRoom; highRoom = temp; } float deltaZ = highRoom.z - lowRoom.z; int w = 3; if (!stairAnchoredHigh && !stairAnchoredLow && ((x % 2 == 1 && sizeX >= deltaZ * 2) || (y % 2 == 1 && sizeY >= deltaZ * 2))) { // we're eligible for a straight staircase for (int y = 0; y < sizeY; y += 1) { for (int x = 0; x < sizeX; x += 1) { mesh.SetHeight(startX + x, startY + y, lowRoom.z); } } for (float i = 0.0f; i < deltaZ; i += 0.5f) { for (int j = 0; j < w; j += 1) { if (x % 2 == 1) { mesh.SetHeight( startX + sizeX - (int)(i * 2), startY + j + (sizeY - w) / 2, lowRoom.z + deltaZ - i); } else { mesh.SetHeight( startX + j + (sizeX - w) / 2, startY + sizeY - (int)(i * 2), lowRoom.z + deltaZ - i); } } } } else { // a normal side staircase bool heightSwap = gen.Flip(); for (int y = 0; y < sizeY; y += 1) { for (int x = 0; x < sizeX; x += 1) { if (stairAnchoredLow && stairAnchoredHigh) { // stretch across the entire room heightSwap = false; float t; if (this.x % 2 == 1) { t = (float)x / sizeX; } else { t = (float)y / sizeY; } mesh.SetHeight(startX + x, startY + y, lowRoom.z + Mathf.RoundToInt(t * deltaZ)); } else { float h; if (stairAnchoredLow) { heightSwap = false; if (this.x % 2 == 1) { h = Mathf.Min(highRoom.z, lowRoom.z + (y + 1) * 0.5f); } else { h = Mathf.Min(highRoom.z, lowRoom.z + (x + 1) * 0.5f); } } else if (stairAnchoredHigh) { heightSwap = false; if (this.x % 2 == 1) { h = Mathf.Max(lowRoom.z, highRoom.z - (y + 1) * 0.5f); } else { h = Mathf.Max(lowRoom.z, highRoom.z - (x + 1) * 0.5f); } } else { if (this.x % 2 == 1) { h = Mathf.Max(lowRoom.z, Mathf.Min(highRoom.z, lowRoom.z + (deltaZ * 0.5f) + (y - sizeY / 2) * 0.5f)); } else { h = Mathf.Max(lowRoom.z, Mathf.Min(highRoom.z, lowRoom.z + (deltaZ * 0.5f) + (x - sizeX / 2) * 0.5f)); } } mesh.SetHeight(startX + x, startY + y, heightSwap ? lowRoom.z + (highRoom.z - h) : h); } } } } }
// set up a new grid with the given size in tiles and rule for turning location into whether a // tile is part of the selection grid or not public void ConfigureNewGrid(Vector2Int at, int range, TacticsTerrainMesh terrain, Func <Vector2Int, bool> rangeRule, Func <Vector2Int, bool> selectRule) { ConfigureNewGrid(at - new Vector2Int(range, range), new Vector2Int(range * 2 + 1, range * 2 + 1), terrain, rangeRule, selectRule); }
public void ConfigureNewGrid(Vector2Int at, Vector2Int size, TacticsTerrainMesh terrain, Func <Vector2Int, bool> rangeRule, Func <Vector2Int, bool> selectRule) { transform.position = new Vector3(0.0f, 0.0f, 0.0f); LineOfSightEffect los = terrain.GetComponent <LineOfSightEffect>(); MeshFilter filter = this.mesh; if (filter.mesh != null) { Destroy(filter.mesh); } Mesh mesh = new Mesh(); filter.mesh = mesh; List <Vector3> vertices = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> tris = new List <int>(); for (int y = at.y; y < at.y + size.y; y += 1) { for (int x = at.x; x < at.x + size.x; x += 1) { if (terrain.HeightAt(x, y) == 0.0f || !los.CachedIsVisible(new Vector2Int(x, y))) { continue; } bool selectable = selectRule(new Vector2Int(x, y)); bool rangeable = rangeRule(new Vector2Int(x, y)); if (selectable || rangeable) { int vertIndex = vertices.Count; float height = terrain.HeightAt(x, y); for (int i = 0; i < 4; i += 1) { if (selectable) { uvs.Add(new Vector2( i % 2 == 0 ? .5f : 0, i < 2 ? .5f : 0)); } else if (rangeable) { uvs.Add(new Vector2( i % 2 == 0 ? 1 : .5f, i < 2 ? .5f : 0)); } vertices.Add(new Vector3( x + (i % 2 == 0 ? 1 : 0), height, y + (i < 2 ? 1 : 0))); } tris.Add(vertIndex); tris.Add(vertIndex + 2); tris.Add(vertIndex + 1); tris.Add(vertIndex + 1); tris.Add(vertIndex + 2); tris.Add(vertIndex + 3); } } } mesh.vertices = vertices.ToArray(); mesh.uv = uvs.ToArray(); mesh.triangles = tris.ToArray(); mesh.RecalculateNormals(); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; GUILayout.Space(20.0f); if (GUILayout.Button("Rebuild")) { Rebuild(true); } Vector2Int newSize = EditorGUILayout.Vector2IntField("Size", terrain.size); if (newSize != terrain.size) { terrain.Resize(newSize); Rebuild(true); } GUILayout.Space(20.0f); Vector2Int flooredSelection = new Vector2Int(Mathf.FloorToInt(selectionSize.x), Mathf.FloorToInt(selectionSize.y)); Vector2Int newSelectionSize = EditorGUILayout.Vector2IntField("Brush size", flooredSelection); if (newSelectionSize != flooredSelection) { selectionSize = new Vector2(Mathf.Max(1.0f, newSelectionSize.x), Mathf.Max(1.0f, newSelectionSize.y)); } if (palette == null) { if (terrain.paletteName != null && terrain.paletteName.Length > 0) { string paletteName = "Assets/Tilesets/Palettes/" + terrain.paletteName + ".prefab"; UpdateWithPalette(AssetDatabase.LoadAssetAtPath <GridPalette>(paletteName)); } } GridPalette newPalette = (GridPalette)EditorGUILayout.ObjectField("Tileset", palette, typeof(GridPalette), false); if (newPalette != palette) { UpdateWithPalette(newPalette); } SelectionTool[] ordinals = new SelectionTool[] { SelectionTool.Select, SelectionTool.Paint, SelectionTool.HeightAdjust }; string[] names = new string[] { "Select", "Paint", "HeightAdjust" }; int selectionIndex = GUILayout.SelectionGrid(ArrayUtility.IndexOf(ordinals, tool), names, names.Length); tool = ordinals[selectionIndex]; int controlId = GUIUtility.GetControlID(FocusType.Passive); EventType typeForControl = Event.current.GetTypeForControl(controlId); Vector2 mousePos = Event.current.mousePosition; GUIStyle style = new GUIStyle(); style.padding = new RectOffset(0, 0, 0, 0); if (tileset != null && tool == SelectionTool.Paint) { wraparoundPaintMode = EditorGUILayout.Toggle("Paint all faces", wraparoundPaintMode); Texture2D backer = AssetDatabase.LoadAssetAtPath <Texture2D>("Assets/Resources/Textures/White.png"); for (int y = tileset.size.y - 1; y >= 0; y -= 1) { EditorGUILayout.BeginHorizontal(); for (int x = 0; x < tileset.size.x; x += 1) { Rect selectRect = EditorGUILayout.BeginHorizontal(GUILayout.Width(Map.TileSizePx), GUILayout.Height(Map.TileSizePx)); Tile tile = tileset.GetTile <Tile>(new Vector3Int(x, y, 0)); GUILayout.Box("", style, GUILayout.Width(Map.TileSizePx), GUILayout.Height(Map.TileSizePx)); Rect r = GUILayoutUtility.GetLastRect(); if (r.Contains(Event.current.mousePosition)) { switch (Event.current.type) { case EventType.MouseDown: mode = EditMode.PaletteTileDrag; selectedTileStart = new Vector2(x, y); tileSelectRect = new Rect(x, y, 1, 1); paletteBufferSize = Vector2Int.zero; break; case EventType.MouseDrag: if (mode == EditMode.PaletteTileDrag) { int minX = (int)Mathf.Min(selectedTileStart.x, x); int minY = (int)Mathf.Min(selectedTileStart.y, y); tileSelectRect = new Rect(minX, minY, (int)Mathf.Max(selectedTileStart.x, x) + 1 - minX, (int)Mathf.Max(selectedTileStart.y, y) + 1 - minY); selectionSize = new Vector2(tileSelectRect.width, tileSelectRect.height); } break; case EventType.MouseUp: mode = EditMode.None; break; } } Rect rect = new Rect(tile.sprite.uv[0].x, tile.sprite.uv[3].y, tile.sprite.uv[3].x - tile.sprite.uv[0].x, tile.sprite.uv[0].y - tile.sprite.uv[3].y); GUI.DrawTextureWithTexCoords(r, tile.sprite.texture, rect, true); if (r.Contains(Event.current.mousePosition)) { GUI.DrawTexture(r, backer, ScaleMode.StretchToFill, true, 0.0f, new Color(1, 0, 0, 0.5f), 0.0f, 0.0f); } else if (paletteBufferSize == Vector2Int.zero && tileSelectRect.Contains(new Vector2(x, y))) { GUI.DrawTexture(r, backer, ScaleMode.StretchToFill, true, 0.0f, new Color(1, 1, 1, 0.8f), 0.0f, 0.0f); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndHorizontal(); } } if (tool == SelectionTool.Select) { EditorGUI.BeginDisabledGroup(mode != EditMode.Selected); if (GUILayout.Button("Create MapEvent3D")) { GameObject prefab = AssetDatabase.LoadAssetAtPath <GameObject>(GenericPrefabPath); MapEvent3D mapEvent = Instantiate(prefab).GetComponent <MapEvent3D>(); mapEvent.name = "Event" + Random.Range(1000000, 9999999); AddEvent(mapEvent); } if (GUILayout.Button("Create Tactics Doll")) { GameObject prefab = AssetDatabase.LoadAssetAtPath <GameObject>(TacticsPrefabPath); MapEvent3D mapEvent = ((GameObject)PrefabUtility.InstantiatePrefab(prefab)).GetComponent <MapEvent3D>(); mapEvent.name = "Doll" + Random.Range(1000000, 9999999); AddEvent(mapEvent); } EditorGUI.EndDisabledGroup(); } }
private void HandleLeftclick(EventType typeForControl, int controlId) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; switch (typeForControl) { case EventType.MouseDown: switch (tool) { case SelectionTool.HeightAdjust: if (selectedQuads.Count > 0 && selectedQuads[0].normal.y > 0.0f) { ConsumeEvent(controlId); mode = EditMode.AdjustingHeight; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); selectedHeight = 0.0f; } break; case SelectionTool.Paint: if (selectedQuads.Count > 0) { ConsumeEvent(controlId); PaintTileIfNeeded(); mode = EditMode.Painting; paintingNormal = primarySelection.normal; } break; case SelectionTool.Select: ConsumeEvent(controlId); if (mode == EditMode.Selected) { TerrainQuad newQuad = GetSelectedQuad(); if (newQuad == null || newQuad == primarySelection) { primarySelection = null; } else { primarySelection = newQuad; CaptureSelection(primarySelection); } } mode = primarySelection == null ? EditMode.None : EditMode.Selected; break; } break; case EventType.MouseDrag: switch (mode) { case EditMode.AdjustingHeight: ConsumeEvent(controlId); selectedHeight = MathHelper3D.GetHeightAtMouse(primarySelection); break; case EditMode.Painting: ConsumeEvent(controlId); primarySelection = GetSelectedQuad(); CaptureSelection(primarySelection); PaintTileIfNeeded(); break; } break; case EventType.MouseUp: switch (mode) { case EditMode.AdjustingHeight: mode = EditMode.None; bool dirty = false; float height = MathHelper3D.GetHeightAtMouse(primarySelection); foreach (TerrainQuad quad in selectedQuads) { int x = Mathf.RoundToInt(quad.pos.x); int y = Mathf.RoundToInt(quad.pos.z); if (terrain.HeightAt(x, y) != height) { terrain.SetHeight(x, y, height); dirty = true; } } if (dirty) { Rebuild(true); } break; case EditMode.Painting: mode = EditMode.None; break; } break; case EventType.ScrollWheel: if (mode == EditMode.None && selectedQuads.Count > 0) { GUIUtility.hotControl = 0; Event.current.Use(); float maxSelection = Mathf.Max(selectionSize.x, selectionSize.y); maxSelection += -1.0f * Event.current.delta.y / 5.0f; selectionSize = new Vector2(maxSelection, maxSelection); if (Mathf.RoundToInt(selectionSize.x) < 1) { selectionSize.x = 1; } if (Mathf.RoundToInt(selectionSize.y) < 1) { selectionSize.y = 1; } CaptureSelection(primarySelection); SceneView.RepaintAll(); } break; } if (selectedHeight >= 0.0f && mode == EditMode.AdjustingHeight) { int x = Mathf.RoundToInt(primarySelection.pos.x); int y = Mathf.RoundToInt(primarySelection.pos.z); float h = terrain.HeightAt(x, y); foreach (TerrainQuad quad in selectedQuads) { float z = MathHelper3D.GetHeightAtMouse(primarySelection); for (; Mathf.Abs(z - h) > 0.1f; z += 0.5f * Mathf.Sign(h - z)) { Handles.DrawWireCube(new Vector3(quad.pos.x + 0.5f, z + 0.25f * Mathf.Sign(h - z), quad.pos.z + 0.5f), new Vector3(1.0f, 0.5f, 1.0f)); } } } }
private void HandleRightclick(EventType typeForControl, int controlId) { TacticsTerrainMesh terrain = (TacticsTerrainMesh)target; switch (typeForControl) { case EventType.MouseDown: if (tool != SelectionTool.Select) { TerrainQuad quad = GetSelectedQuad(); if (quad != null) { ConsumeEvent(controlId); primarySelection = quad; selectionSize = new Vector2(1.0f, 1.0f); CaptureSelection(quad); tool = SelectionTool.Paint; mode = EditMode.RlickDrag; } } break; case EventType.MouseDrag: if (mode == EditMode.RlickDrag) { ConsumeEvent(controlId); TerrainQuad quad = GetSelectedQuad(); if (quad != null && quad.normal == primarySelection.normal) { selectedQuads = MathHelper3D.GetQuadsInRect(quads, quad, primarySelection); } } break; case EventType.MouseUp: switch (mode) { case EditMode.Selected: mode = EditMode.None; break; case EditMode.RlickDrag: mode = EditMode.None; TerrainQuad quad = GetSelectedQuad(); if (quad != null && quad.normal == primarySelection.normal) { selectedQuads = MathHelper3D.GetQuadsInRect(quads, quad, primarySelection); Vector3 v1 = quad.pos; Vector3 v2 = primarySelection.pos; float x1 = Mathf.Min(v1.x, v2.x); float x2 = Mathf.Max(v1.x, v2.x); float y1 = Mathf.Min(v1.y, v2.y); float y2 = Mathf.Max(v1.y, v2.y); float z1 = Mathf.Min(v1.z, v2.z); float z2 = Mathf.Max(v1.z, v2.z); if (z1 != z2 && y1 != y2) { paletteBufferSize = new Vector2Int((int)(z2 - z1 + 1), (int)((y2 - y1 + 0.5f) * 2.0f)); paletteBuffer = new Tile[paletteBufferSize.x * paletteBufferSize.y]; for (float z = z1; z <= z2; z += 1.0f) { for (float y = y1; y <= y2; y += 0.5f) { TerrainQuad at = quads[new Vector3(v1.x, y, z)][quad.normal]; paletteBuffer[(int)(paletteBufferSize.x * (2.0f * (y - y1)) + (z - z1))] = at.tile; } } } else if (x1 != x2 && y1 != y2) { paletteBufferSize = new Vector2Int((int)(x2 - x1 + 1), (int)((y2 - y1 + 0.5f) * 2.0f)); paletteBuffer = new Tile[paletteBufferSize.x * paletteBufferSize.y]; for (float x = x1; x <= x2; x += 1.0f) { for (float y = y1; y <= y2; y += 0.5f) { TerrainQuad at = quads[new Vector3(x, y, v1.z)][quad.normal]; paletteBuffer[(int)(paletteBufferSize.x * (2.0f * (y - y1)) + (x - x1))] = at.tile; } } } else { paletteBufferSize = new Vector2Int((int)(x2 - x1 + 1), (int)(z2 - z1 + 1)); paletteBuffer = new Tile[paletteBufferSize.x * paletteBufferSize.y]; for (float x = x1; x <= x2; x += 1.0f) { for (float z = z1; z <= z2; z += 1.0f) { TerrainQuad at = quads[new Vector3(x, v1.y, z)][quad.normal]; paletteBuffer[(int)(paletteBufferSize.x * (z - z1) + (x - x1))] = at.tile; } } } selectionSize = paletteBufferSize; } break; } break; } }