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); } }
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]); } }
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); } } } } } }
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 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(); } }
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)); } } } }
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(); }