/// <inheritdoc/> protected override void ModifyTerrain(Point offset, TerrainBrush brush, byte[,] oldData, byte[,] newData) { #region Sanity checks if (oldData == null) { throw new ArgumentNullException(nameof(oldData)); } if (newData == null) { throw new ArgumentNullException(nameof(newData)); } #endregion var heightMap = Terrain.HeightMap; byte centerHeight = heightMap[offset.X + brush.Size / 2, offset.Y + brush.Size / 2]; // Iterate through intersection of [0,area.Size) and [-offset,heightMap-offset) for (int x = Math.Max(0, -offset.X); x < Math.Min(brush.Size, heightMap.Width - offset.X); x++) { for (int y = Math.Max(0, -offset.Y); y < Math.Min(brush.Size, heightMap.Height - offset.Y); y++) { oldData[x, y] = heightMap[offset.X + x, offset.Y + y]; // Make flat and write back double factor = brush.Factor(x, y); newData[x, y] = heightMap[offset.X + x, offset.Y + y] = (byte)(factor * centerHeight + (1 - factor) * oldData[x, y]); } } }
/// <summary> /// Modifies the <see cref="ITerrain"/> and fills arrays with undo/redo data. /// </summary> /// <param name="offset">The <see cref="ITerrain.TextureMap"/> index that corresponds to the top-left corner of the area to modify.</param> /// <param name="brush">The shape and size of the area to the lower-right of <paramref name="offset"/> to modify.</param> /// <param name="oldData">An array to be filled with data from <see cref="ITerrain.TextureMap"/> before the modification. Both dimensions must be equal to <see cref="TerrainBrush.Size"/>.</param> /// <param name="newData">An array to be filled with data from <see cref="ITerrain.TextureMap"/> after the modification. Both dimensions must be equal to <see cref="TerrainBrush.Size"/>.</param> /// <returns><c>true</c> if anything was changed; <c>false</c> if the <see cref="ITerrain"/> remains unchanged (because no changes were necessary).</returns> private bool ModifyTerrain(Point offset, TerrainBrush brush, byte[,] oldData, byte[,] newData) { bool changed = false; var textureMap = Terrain.TextureMap; // Iterate through intersection of [0,area.Size) and [-offset,textureMap-offset) for (int x = Math.Max(0, -offset.X); x < Math.Min(brush.Size, textureMap.Width - offset.X); x++) { for (int y = Math.Max(0, -offset.Y); y < Math.Min(brush.Size, textureMap.Height - offset.Y); y++) { oldData[x, y] = textureMap[offset.X + x, offset.Y + y]; // Change texture ID and write back if (brush.Contains(x, y)) { newData[x, y] = _textureID; if (newData[x, y] != oldData[x, y]) { textureMap[offset.X + x, offset.Y + y] = newData[x, y]; changed = true; } } else { newData[x, y] = oldData[x, y]; } } } return(changed); }
/// <inheritdoc/> protected override void ModifyTerrain(Point offset, TerrainBrush brush, byte[,] oldData, byte[,] newData) { #region Sanity checks if (oldData == null) { throw new ArgumentNullException(nameof(oldData)); } if (newData == null) { throw new ArgumentNullException(nameof(newData)); } #endregion var noise = new PerlinNoise { InitAmplitude = _amplitude, InitFrequency = _frequency }; var heightMap = Terrain.HeightMap; // Iterate through intersection of [0,area.Size) and [-offset,heightMap-offset) for (int x = Math.Max(0, -offset.X); x < Math.Min(brush.Size, heightMap.Width - offset.X); x++) { for (int y = Math.Max(0, -offset.Y); y < Math.Min(brush.Size, heightMap.Height - offset.Y); y++) { oldData[x, y] = heightMap[offset.X + x, offset.Y + y]; // Add noise and write back newData[x, y] = heightMap[offset.X + x, offset.Y + y] = (byte)(oldData[x, y] + (noise.Function2D(x, y) * brush.Factor(x, y))).Clamp(byte.MinValue, byte.MaxValue); } } }
public static void LoadNewBrushFiles(string[] absNames) { try { foreach (string f in absNames) { TerrainBrush b = FindBrushByFilename(f); if (b == null) { b = TerrainConversionHelpers.CreateBrush(f); } else { TerrainConversionHelpers.CheckBrushModified(b); continue; } if (b == null || !b.Valid) { continue; } _allBrushes.Add(b); } } catch (Exception ex) { EditorManager.DumpException(ex, true); } if (OnBrushCollectionChanged != null) { OnBrushCollectionChanged(null, EventArgs.Empty); } }
private void BrushDown(Vector3 point, TerrainBrush brush, TerrainChunk chunk) { float radius = brush.Radius; float num = brush.Strenght; float blurRange = brush.BlurRadius; float num3 = 1.0f - Mathf.Pow(brush.BlurPower, 4.0f); num3 = 1.0f - Mathf.Pow(1.0f - num3, 1.1f); float target = brush.Targetheight; target -= 1.0f; //Height Vector2 localPoint = new Vector2(point.x - transform.position.x, point.z - transform.position.z); localPoint.x = Mathf.RoundToInt((localPoint.x / chunk.groupInfo.worldSize.x) * (chunk.groupInfo.terrainWidth - 1)); localPoint.y = Mathf.RoundToInt((localPoint.y / chunk.groupInfo.worldSize.y) * (chunk.groupInfo.terrainLength - 1)); float Minx = Mathf.Max(0, localPoint.x - (radius + blurRange)); float Maxx = Mathf.Min(chunk.groupInfo.terrainWidth - 1, localPoint.x + (radius + blurRange)); float MinY = Mathf.Max(0, localPoint.y - (radius + blurRange)); float Maxy = Mathf.Min(chunk.groupInfo.terrainLength - 1, localPoint.y + (radius + blurRange)); Vector2 CenterPoint = new Vector2(Minx, MinY); float localsqrDis = (radius + blurRange) * (radius + blurRange); for (int y = (int)MinY; y <= Maxy; ++y) { for (int x = (int)Minx; x <= Maxx; ++x) { int heightflag = chunk.groupInfo.GetHeightIndex(x, y); int heightMinFlag = chunk.groupInfo.GetMinHeightIndex(x, y); int targetFlag = Mathf.FloorToInt(brush.Targetheight - 0.001f); if (heightMinFlag < targetFlag) { if (heightflag > targetFlag) { chunk.groupInfo.SetCullFace(x, y, targetFlag); } continue; } float curValue = chunk.groupInfo.GetRealHeight(x, y); CenterPoint.x = x; CenterPoint.y = y; float sqr = Vector2.SqrMagnitude(localPoint - CenterPoint); if (sqr < localsqrDis) { float distancePower = GetDistancePower(Mathf.Sqrt(sqr), true, brush); float newvalue = Mathf.Lerp(curValue, target, num * distancePower); newvalue = Mathf.Min(curValue, newvalue); newvalue = Mathf.Max(target + 0.001f, newvalue); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); chunk.groupInfo.SetCullFace(x, y, newvalue); } } } }
protected override Brush CreateBrush() { TerrainBrush terrainBrush = new TerrainBrush(); terrainBrush.Blend = Brush.BlendFunction.Smooth; terrainBrush.AllowNegativeValue = false; return(terrainBrush); }
public bool CastGroup(Ray ray, TerrainBrush brush, List <TerrainChunk> colliedChunks, out Vector3 HitPoint) { RaycastHit info = default(RaycastHit); bool Collided = false; HitPoint = Vector3.zero; List <TerrainChunk> CopyChunks = Chunks; int nChildCount = CopyChunks.Count; int nCopyChunkCount = CopyChunks.Count; for (int idx = 0; idx < nCopyChunkCount; ++idx) { TerrainChunk Curchunk = CopyChunks[idx]; if (Curchunk.GetMeshCollider().Raycast(ray, out info, 1000)) { if (flag != null) { flag.transform.position = info.point; } Brush(info.point, Curchunk, brush); // Brush(info.point + new Vector3(0.0f,0.0f,0.2f), Curchunk, brush); // Brush(info.point + new Vector3(0.0f, 0.0f, -0.2f), Curchunk, brush); // Brush(info.point + new Vector3(-0.2f, 0.0f, 0.0f), Curchunk, brush); // Brush(info.point + new Vector3(0.2f, 0.0f, 0.0f), Curchunk, brush); //return info.point; HitPoint = info.point; Collided = true; break; } } float brushLenght = (brush.Radius + brush.BlurRadius) + 2.0f; Circle brushCircle = new Circle(new Vector2(info.point.x, info.point.z), brushLenght); colliedChunks.Clear(); if (Collided) { for (int idx = 0; idx < nCopyChunkCount; ++idx) { if (Circle.ColliderRect(brushCircle, CopyChunks[idx]._boxRect)) { colliedChunks.Add(CopyChunks[idx]); } } } int nColliderChunks = colliedChunks.Count; for (int idx = 0; idx < nColliderChunks; ++idx) { colliedChunks[idx].BuildChunk(); } return(Collided); }
/// <summary> /// Set the preferred brush name (will be set later if no brushes are yet loaded) /// </summary> /// <param name="name"></param> public static void SetBrushByName(string name) { _preferredBrushName = name; TerrainBrush brush = TerrainEditor.FindBrush(name); if (brush != null) { TerrainEditor.CurrentBrush = brush; } }
private void setBrush(TerrainBrush brush) { brush.Hardness = tbHardness.Value; brush.Intensity = tbIntensity.Value; brush.Radius = tbRadius.Value; brush.Invert = cbInvert.Checked; brush.Rounded = cbRounded.Checked; terrainEditor.Brush = brush; }
private void BrushRaise(Vector3 point, TerrainBrush brush, TerrainChunk chunk) { Vector3 localPoint = point - transform.position; int BrushSize = (int)brush.Radius; float BrushOcaptiy = brush.Targetheight; float powValue = brush.Strenght; int idx = Mathf.RoundToInt((localPoint.x / chunk.groupInfo.worldSize.x) * chunk.groupInfo.terrainWidth); int idy = Mathf.RoundToInt((localPoint.z / chunk.groupInfo.worldSize.y) * chunk.groupInfo.terrainLength); int minX = Mathf.Max(0, idx - BrushSize); int maxX = Mathf.Min(chunk.groupInfo.terrainWidth, idx + BrushSize); int minY = Mathf.Max(0, idy - BrushSize); int maxY = Mathf.Min(chunk.groupInfo.terrainLength, idy + BrushSize); Vector2 center = new Vector2(idx, idy); Vector2 testPoint = new Vector2(maxX, maxY); float maxDistance = Vector2.Distance(center, testPoint); for (int y = minY; y <= maxY; ++y) { for (int x = minX; x <= maxX; ++x) { float curValue = chunk.groupInfo.GetRealHeight(x, y); testPoint.x = x; testPoint.y = y; float distance = Vector2.Distance(center, testPoint); float Distancevalue = (distance / maxDistance); float num1 = Mathf.Pow(Distancevalue, powValue); float num2 = (1.0F - num1); if (num2 > 1.0f) { num2 = 1.0f; } if (num2 < 0.0f) { num2 = 0.0f; } float newvalue = BrushOcaptiy * num2; newvalue = Mathf.Max(newvalue, curValue); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); if (chunk.groupInfo.GetValue(x, y) != chunk.groupInfo.GetSurfaceValue(x, y)) { Debug.LogError("Set Value Error"); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); } } } }
/// <summary> /// Load all default brushes from the directory /// </summary> static void LoadAllBrushes() { if (!EditorManager.EngineManager.IsInitialized()) { return; } try { FreeAllBrushes(); string dir = AbsoluteBrushFilePath; string[] files = Directory.GetFiles(dir, "*.bmp"); foreach (string f in files) { TerrainBrush b = TerrainConversionHelpers.CreateBrush(f); if (b == null || !b.Valid) { continue; } _allBrushes.Add(b); } } catch (Exception ex) { EditorManager.DumpException(ex, true); } if (OnBrushCollectionChanged != null) { OnBrushCollectionChanged(null, EventArgs.Empty); } if (!string.IsNullOrEmpty(_preferredBrushName)) { TerrainBrush b = FindBrush(_preferredBrushName); if (b != null) { CurrentBrush = b; } } if (CurrentBrush == null) { CurrentBrush = FindBrush("Smooth1"); // preferred brush to start with } if (CurrentBrush == null && _allBrushes.Count > 0) { CurrentBrush = (TerrainBrush)_allBrushes[0]; } }
/// <inheritdoc/> public override void Apply(Vector2 terrainCoords, TerrainBrush brush) { // Calculate top-left point of area to modify var offset = new Point( (int)Math.Round(terrainCoords.X / Terrain.Size.StretchH) - brush.Size / 2, (int)Math.Round(terrainCoords.Y / Terrain.Size.StretchH) - brush.Size / 2); var oldData = new byte[brush.Size, brush.Size]; var newData = new byte[brush.Size, brush.Size]; ModifyTerrain(offset, brush, oldData, newData); OldData.AddFirst(offset, oldData); NewData.AddLast(offset, newData); _engineTerrain.ModifyHeight(offset, newData); // Live-update engine terrain }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { TerrainBrush brush = (TerrainBrush)value; switch (int.Parse((string)parameter)) { case 0: return(brush == TerrainBrush.Rectangle); case 1: return(brush == TerrainBrush.Circle); default: return(brush == TerrainBrush.None); } }
public void UpdateSprite() { Vector2 pos = tile.gameObject.transform.position; Tile[,] grid = WorldManager.GetTerrainGrid(new Vector2(pos.x - 1, pos.y - 1), new Vector2Int(3, 3)); int[,] ids = new int[3, 3]; for (int x = 0; x < 3; ++x) { for (int y = 0; y < 3; ++y) { ids[x, y] = grid[x, y].tileData.Id; // if(x != 1 || y != 1){ // grid[x, y].AddDataChangeListener(UpdateSprite); // } } } TerrainBrush.TileType tileType = TerrainBrush.GetTileType(ids, 1, 1); //TerrainBrush.TileType tileType = TerrainBrush.TileType.Center; int other = TerrainBrush.GetOtherType(ids, 1, 1, tileType); if (tileType == TerrainBrush.TileType.Error) { tile.SetTileData(TileData.idToData[other]); return; } if (other != -1) { name = tile.tileData.Name + TileData.idToData[other].Name + (int)tileType; } else { name = tile.tileData.Name + "0"; } Sprite sprite = SpriteManager.GetTileSprite(name + "_" + currFrame.ToString()); if (sprite == null) { name = tile.tileData.Name + "0"; sprite = SpriteManager.GetTileSprite(name + "_" + currFrame.ToString()); } tile.spriteRenderer.sprite = sprite; if (!tile.tileData.IsWalkable) { tile.gameObject.AddComponent <PolygonCollider2D>(); } tile.tileScript.StartCoroutine(Animator()); }
public void generateMineralLikeCoal(TerrainChunk chunk, int value, int replacevalue, int minHeight, int maxHeight) //生成矿物算法-类似煤的生成概率 { int cx = chunk.Coords.X; int cy = chunk.Coords.Y; List <TerrainBrush> terrainBrushes = new List <TerrainBrush>(); Game.Random random = new Game.Random(17); for (int i = 0; i < 16; i++) {//煤块的生成概率 TerrainBrush terrainBrush = new TerrainBrush(); int num = random.UniformInt(4, 12); for (int j = 0; j < num; j++) { Vector3 vector = 0.5f * Vector3.Normalize(new Vector3(random.UniformFloat(-1f, 1f), random.UniformFloat(-1f, 1f), random.UniformFloat(-1f, 1f))); int num2 = random.UniformInt(3, 8); Vector3 zero = Vector3.Zero; for (int k = 0; k < num2; k++) { terrainBrush.AddBox((int)MathUtils.Floor(zero.X), (int)MathUtils.Floor(zero.Y), (int)MathUtils.Floor(zero.Z), 1, 1, 1, value); zero += vector; } } if (i == 0) { terrainBrush.AddCell(0, 0, 0, 150); } terrainBrush.Compile(); terrainBrushes.Add(terrainBrush); } for (int i = cx - 1; i <= cx + 1; i++) { for (int j = cy - 1; j <= cy + 1; j++) { float num2 = CalculateMountainRangeFactor(i * 16, j * 16); int num3 = (int)(5f + 2f * num2 * SimplexNoise.OctavedNoise(i, j, 0.33f, 1, 1f, 1f)); for (int l = 0; l < num3; l++) { int x2 = i * 16 + random.UniformInt(0, 15); int y2 = random.UniformInt(minHeight, maxHeight); int cz = j * 16 + random.UniformInt(0, 15); terrainBrushes[random.UniformInt(0, terrainBrushes.Count - 1)].PaintFastSelective(chunk, x2, y2, cz, replacevalue); } } } }
private void OnSceneGUI() { HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Keyboard)); switch (editorType) { case EditorType.HeightEditor: currentBrush = heightBrush; MeshModifier.instance.m_brush = currentBrush; MeshModifier.instance.DoEvent(); break; case EditorType.WaterEditor: currentBrush = waterBrush; MeshModifier.instance.m_brush = currentBrush; MeshModifier.instance.DoEvent(); break; case EditorType.EdgeEditor: currentBrush = edgeBrush; MeshModifier.instance.m_brush = currentBrush; MeshModifier.instance.DoEvent(); break; case EditorType.MaterialEditor: HexGridChunk preLockedChunk = MaterialModifier.instance.m_lockedChunk; currentBrush = materialBrush; MaterialModifier.instance.m_brush = currentBrush; MaterialModifier.instance.DoEvent(); if (MaterialModifier.instance.m_lockedChunk != preLockedChunk) { Repaint(); } break; case EditorType.SceneObjEditor: currentBrush = sceneObjBrush; SceneObjModifier.instance.m_brush = sceneObjBrush; SceneObjModifier.instance.DoEvent(); break; } SceneView.currentDrawingSceneView.Repaint(); }
void SelectBrushByName(string fullname) { _iIgnoreSelectionChange++; listView.SelectedIndices.Clear(); if (string.IsNullOrEmpty(fullname)) { _iIgnoreSelectionChange--; return; } foreach (ListViewItem item in this.listView.Items) { TerrainBrush b = (TerrainBrush)item.Tag; if (string.Compare(b.Name, fullname, true) == 0) { listView.SelectedIndices.Add(item.Index); break; } } _iIgnoreSelectionChange--; }
/// <inheritdoc/> public override void Apply(Vector2 terrainCoords, TerrainBrush brush) { // Handle texture 3x scale and calculate top-left point of area to modify brush = new TerrainBrush(brush.Size / 3, brush.Circle); var offset = new Point( (int)Math.Round(terrainCoords.X / Terrain.Size.StretchH / 3) - brush.Size / 2, (int)Math.Round(terrainCoords.Y / Terrain.Size.StretchH / 3) - brush.Size / 2); var oldData = new byte[brush.Size, brush.Size]; var newData = new byte[brush.Size, brush.Size]; if (!ModifyTerrain(offset, brush, oldData, newData)) { return; } OldData.AddFirst(offset, oldData); NewData.AddLast(offset, newData); _refreshHandler(); // Live-rebuild engine terrain }
private float GetDistancePower(float distance, bool withBlur, TerrainBrush brush) { float num = 1.0f; if (withBlur && brush.BlurRadius > 0.0f) { num = Mathf.InverseLerp(brush.Radius + brush.BlurRadius, brush.Radius, distance); } float blurPower = brush.BlurPower; if (blurPower > 0.0f) { num = Mathf.Pow(num, blurPower); } else if (blurPower < 0.0f) { num = Mathf.Pow(num, 1.0f / (1.0f - blurPower)); } return(num); }
void EditCell(HexCell cell, TerrainBrush brush) { if (cell == null) { return; } brush.RefreshTarget(cell); List <HexGridChunk> neigborChunk = cell.NeighorChunk(); if (neigborChunk.Count > 0) { for (int i = 0; i < neigborChunk.Count; i++) { if (!m_refreshChunkList.Contains(neigborChunk[i])) { m_refreshChunkList.Add(neigborChunk[i]); } } } }
public void Brush(Vector3 point, TerrainChunk chunk, TerrainBrush brush) { switch (brush.brushType) { case TerrainBrush.BrushType.BT_ADD: { BrushRaiseEx(point, brush, chunk); } break; case TerrainBrush.BrushType.BT_DOWN: { BrushDown(point, brush, chunk); } break; case TerrainBrush.BrushType.LOCK: { BrushRaiseEx(point, brush, chunk); } break; } }
public void BrushBox(TerrainBrush brush, Vector2 point) { Vector2 localPoint = new Vector2(point.x - ChunkOffSet.x, point.y - ChunkOffSet.z); float x = (_v0.x + _v3.x) / 2.0f; float y = (_v0.z + _v2.z) / 2.0f; float maxx = 0.0f; if (localPoint.x > ((_v0.x + _v3.x) / 2.0f)) { maxx = _v0.x; } else { maxx = _v3.x; } float maxy = 0.0f; if (localPoint.y > (_v0.z + _v1.z) / 2.0f) { maxy = _v0.z; } else { maxy = _v1.z; } float distance = Vector2.Distance(new Vector2(maxx, maxy), localPoint); if (distance < brush.Radius) { TestCode = 2; } else { /* * (x - a)^2 + (y-b)^2 = r^2; */ float r2 = brush.Radius * brush.Radius; // 计算 是否跟上边相交 float topysubb2 = (_v2.z - localPoint.y) * (_v2.z - localPoint.y); float topsqrx = Mathf.Sqrt(r2 - topysubb2); float Topleftx = topsqrx + localPoint.x; float Toprightx = -topsqrx + localPoint.x; int topCross = 0; float topCrossValue = -1; if (Toprightx >= _v0.x && Toprightx <= _v2.x) { topCrossValue = Toprightx; topCross++; } if (Topleftx >= _v0.x && Topleftx <= _v2.x) { topCrossValue = Topleftx; topCross++; } if (topCross == 2) { Debug.LogError(2); } float bottomySubb2 = (_v0.z - localPoint.y) * (_v0.z - localPoint.y); float bottomsqr = Mathf.Sqrt(r2 - bottomySubb2); float bottomleftx = bottomsqr + localPoint.x; float bottomrightx = -bottomsqr + localPoint.x; int bottomCross = 0; float bottomCrossValue = -1; if (bottomrightx >= _v0.x && bottomrightx <= _v2.x) { bottomCrossValue = bottomrightx; bottomCross++; } if (bottomleftx >= _v0.x && bottomleftx <= _v2.x) { bottomCrossValue = bottomleftx; bottomCross++; } if (bottomCross == 2) { Debug.LogError(2); } float leftXSub2 = (_v0.x - localPoint.x) * (_v0.x - localPoint.x); float leftsqr = Mathf.Sqrt(r2 - leftXSub2); float lefttop = leftsqr + localPoint.y; float leftbottom = -leftsqr + localPoint.y; int leftCross = 0; if (lefttop >= _v0.z && lefttop <= _v1.z) { leftCross++; } if (leftbottom >= _v0.z && leftbottom <= _v1.z) { leftCross++; } if (leftbottom == 2) { Debug.LogError(2); } float rightXSub2 = (_v3.x - localPoint.x) * (_v3.x - localPoint.x); float rightsqr = Mathf.Sqrt(r2 - rightXSub2); float rightTop = rightsqr + localPoint.y; float rightbottom = -rightsqr + localPoint.y; int rightcross = 0; if (rightTop >= _v0.z && rightTop <= _v1.z) { rightcross++; } if (rightbottom >= _v0.z && rightbottom <= _v1.z) { rightcross++; } if (rightbottom == 2) { Debug.LogError(2); } if ((topCross + bottomCross + leftCross + rightcross) == 2) { if (topCross == 1 && leftCross == 1) { } else if (topCross == 1 && rightcross == 1) { } else if (bottomCross == 1 && leftCross == 1) { } else if (bottomCross == 1 && rightcross == 1) { } else if (topCross == 1 && bottomCross == 1) { } else if (leftCross == 1 && rightcross == 1) { } else { Debug.LogError("Circle Cross Error"); } TestCode = 1; } else { TestCode = 0; } //if( } // }
/// <summary> /// Applies and accumulates a modification to the <see cref="Terrain"/>. /// </summary> /// <param name="terrainCoords">The center coordinates of the area to modify in world space.</param> /// <param name="brush">The shape and size of the area around <paramref name="terrainCoords"/> to modify.</param> public abstract void Apply(Vector2 terrainCoords, TerrainBrush brush);
public static void UndoAdd(HexCell centerCell, TerrainBrush brush) { List <HexCell> cellList = new List <HexCell>(); int centerX = centerCell.coordinates.X; int centerZ = centerCell.coordinates.Z; for (int l = 0, z = centerZ; z >= centerZ - brush.brushRange + 1; l++, z--) { for (int x = centerX - brush.brushRange + 1 + l; x <= centerX + brush.brushRange - 1; x++) { if (HexGrid.instance.GetCell(new HexCoordinates(x, z)) != null) { cellList.Add(HexGrid.instance.GetCell(new HexCoordinates(x, z))); } } } for (int l = 1, z = centerZ + 1; z <= centerZ + brush.brushRange - 1; l++, z++) { for (int x = centerX - brush.brushRange + 1; x <= centerX + brush.brushRange - 1 - l; x++) { if (HexGrid.instance.GetCell(new HexCoordinates(x, z)) != null) { cellList.Add(HexGrid.instance.GetCell(new HexCoordinates(x, z))); } } } List <UndoRedoOperation.UndoRedoInfo> undoRedoInfoList = new List <UndoRedoOperation.UndoRedoInfo>(); for (int i = 0; i < cellList.Count; i++) { UndoRedoOperation.UndoRedoInfo undoRedoInfo = new UndoRedoOperation.UndoRedoInfo(); undoRedoInfo.hexCell = cellList[i]; switch (brush.m_editorType) { case EditorType.HeightEditor: undoRedoInfo.parma = new object[] { cellList[i].Elevation }; break; case EditorType.WaterEditor: undoRedoInfo.parma = new object[] { cellList[i].WaterLevel }; break; case EditorType.EdgeEditor: undoRedoInfo.parma = new object[] { cellList[i].isStepDirection[0], cellList[i].isStepDirection[1], cellList[i].isStepDirection[2], cellList[i].isStepDirection[3], cellList[i].isStepDirection[4], cellList[i].isStepDirection[5] }; break; case EditorType.MaterialEditor: if (HexMetrics.instance.isEditorTexture) { undoRedoInfo.parma = new object[] { cellList[i].TerrainTypeIndex }; } else { undoRedoInfo.parma = new object[] { cellList[i].color }; } break; } undoRedoInfoList.Add(undoRedoInfo); } string name = ""; if (brush.m_editorType == EditorType.HeightEditor || brush.m_editorType == EditorType.WaterEditor || brush.m_editorType == EditorType.EdgeEditor) { MeshOperation.OperationType operationType = MeshOperation.OperationType.HeightEdit; switch (brush.m_editorType) { case EditorType.HeightEditor: name = "高度编辑"; operationType = MeshOperation.OperationType.HeightEdit; break; case EditorType.WaterEditor: name = "水平线编辑"; operationType = MeshOperation.OperationType.WaterLevelEdit; break; case EditorType.EdgeEditor: name = "边界编辑"; operationType = MeshOperation.OperationType.EdgeEdit; break; } MeshOperation meshOperation = new MeshOperation(operationType, name, undoRedoInfoList); undoStack.Push(meshOperation); } else if (brush.m_editorType == EditorType.MaterialEditor) { MaterialOperation.OperationType operationType = MaterialOperation.OperationType.WholeCellEdit; name = "材质编辑"; MaterialOperation materialOperation = new MaterialOperation(operationType, name, undoRedoInfoList); undoStack.Push(materialOperation); } LimitStackCount(); }
public void OnEnable() { mEditor = target as TerrainBrush; // SceneView.onSceneGUIDelegate += OnEditorEvent; // Add a Delegate }
/// <summary> /// Modifies the <see cref="ITerrain"/> and fills arrays with undo/redo data. /// </summary> /// <param name="offset">The <see cref="ITerrain.HeightMap"/> index that corresponds to the top-left corner of the area to modify.</param> /// <param name="brush">The shape and size of the area to the lower-right of <paramref name="offset"/> to modify.</param> /// <param name="oldData">An array to be filled with data from <see cref="ITerrain.HeightMap"/> before the modification. Both dimensions must be equal to <see cref="TerrainBrush.Size"/>.</param> /// <param name="newData">An array to be filled with data from <see cref="ITerrain.HeightMap"/> after the modification. Both dimensions must be equal to <see cref="TerrainBrush.Size"/>.</param> protected abstract void ModifyTerrain(Point offset, TerrainBrush brush, byte[,] oldData, byte[,] newData);
public override void Initialize() { brush = new TerrainBrush(); _selectedTiles = new List <IntVector2>(); base.Initialize(); }
private void Editor_Load(object sender, EventArgs e) { string errorBuild = ""; try { mapModel = new EditorModel.MapModel(); mouseMoving = false; mouseEventArgs = null; tempMouseX = tempMouseY = -1; text = ""; basicEffect = new BasicEffect(graphicsDeviceControl1.GraphicsDevice); contentBuilder = ContentBuilder.Instance; contentManager = new ContentManager(graphicsDeviceControl1.Services, contentBuilder.OutputDirectory); heightmapContent = new ContentManager(graphicsDeviceControl1.Services, contentBuilder.OutputDirectory); spriteBatch = new SpriteBatch(graphicsDeviceControl1.GraphicsDevice); //MessageBox.Show(GraphicsDevice.Adapter.Description); effectFile = AssemblyDirectory + "\\Assets\\effects.fx"; terrainTextureFile = AssemblyDirectory + "\\Assets\\Textures\\grass.dds"; //importer reference: http://msdn.microsoft.com/en-us/library/bb447762%28v=xnagamestudio.20%29.aspx contentBuilder.Add(AssemblyDirectory + "\\Assets\\SegoeUI.spritefont", "SegoeUI.spritefont", null, "FontDescriptionProcessor"); contentBuilder.Add(effectFile, "effects", null, "EffectProcessor"); contentBuilder.Add(AssemblyDirectory + "\\Assets\\brush.bmp", "brush", null, "TextureProcessor"); contentBuilder.Add(terrainTextureFile, "grass", null, "TextureProcessor"); contentBuilder.Add(AssemblyDirectory + "\\Assets\\video_camera.png", "video_camera", null, "TextureProcessor"); contentBuilder.Add(AssemblyDirectory + "\\Assets\\Roads\\jalan_raya.fbx", "jalan_raya", null, "ModelProcessor"); contentBuilder.Add(AssemblyDirectory + "\\Assets\\Roads\\jalan_raya_belok.fbx", "jalan_raya_belok", null, "ModelProcessor"); contentBuilder.Add(AssemblyDirectory + "\\Assets\\heightmap2.png", "heightmap", null, "TextureProcessor"); string error = contentBuilder.Build(); if (!string.IsNullOrEmpty(error)) { throw new Exception(error); } errorBuild = contentBuilder.Build(); spriteFont = contentManager.Load <SpriteFont>("SegoeUI.spritefont"); terrainEffect = contentManager.Load <Effect>("effects"); brushHeightMap = contentManager.Load <Texture2D>("brush"); grassTexture = contentManager.Load <Texture2D>("grass"); camera = new Camera(GraphicsDevice); camera.Position = new Vector3(0, 50, 0); camera.AspectRatio = graphicsDeviceControl1.GraphicsDevice.Viewport.AspectRatio; camera.Rotate(20, 45, 0); camera.Attach(this); CheckIsOrthographic(); string heightMapFile = AssemblyDirectory + "\\test_HeightMap.png"; Terrain = new Terrain(GraphicsDevice, camera, heightMapFile, effectFile, terrainTextureFile, 128, 128); Terrain.Texture = grassTexture; //heightmapContent = new ContentManager(graphicsDeviceControl1.Services, contentBuilder.OutputDirectory); //quadTreeTerrain = new QuadTree(Vector3.Zero, 1025, 1025, camera, GraphicsDevice, 1); //quadTreeTerrain.Effect.Texture = grassTexture; editorMode = new EditorMode_Select(this); Selected = null; selectedBoundingBox = new ModelBoundingBox(graphicsDeviceControl1.GraphicsDevice, camera, false); selectedBoundingBox.SpriteBatch = spriteBatch; selectedBoundingBox.SpriteFont = spriteFont; CheckActiveTransformMode(); terrainBrush = new TerrainBrush(GraphicsDevice, Terrain, brushHeightMap); terrainBrush.BasicEffect = basicEffect; Grid = new Grid(Terrain, 8, camera, GraphicsDevice, basicEffect); Grid.RoadModel = contentManager.Load <Model>("jalan_raya"); Grid.RoadModel_belok = contentManager.Load <Model>("jalan_raya_belok"); Grid.GridMapFile = AssemblyDirectory + "\\Assets\\gridmap.png"; Grid.ExportGridMap(); Grid.RoadAssetFiles.Add(AssemblyDirectory + "\\Assets\\Roads\\jalan_raya.fbx"); Grid.RoadAssetFiles.Add(AssemblyDirectory + "\\Assets\\Roads\\jalan_raya_belok.fbx"); Grid.RoadAssetFiles.Add(AssemblyDirectory + "\\Assets\\Roads\\texture_jalan_raya.png"); Grid.RoadAssetFiles.Add(AssemblyDirectory + "\\Assets\\Roads\\texture_jalan_raya_belok.png"); gridPointer = new GridPointer(Grid); gridPointers = new List <GridPointer>(); mapModel.MainCamera.Texture = contentManager.Load <Texture2D>("video_camera"); mapModel.MainCamera.GraphicsDevice = GraphicsDevice; mapModel.MainCamera.Camera = camera; mapModel.MainCamera.BasicEffect = basicEffect; timer = new System.Threading.Timer((c) => SetGravity(), null, Timeout.Infinite, Timeout.Infinite); camera.Notify(); } catch (Exception ex) { if (!DesignMode) { if (mainUserControl != null && mainUserControl.StatusStrip1 != null) { mainUserControl.StatusStrip1.Text = ex.Message + "\r\n" + ex.StackTrace; } else { MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace); } } } }
public void UpdateSprite() { Vector2 pos = tile.gameObject.transform.position; Tile[,] grid = WorldManager.GetTerrainGrid(new Vector2(pos.x - 1, pos.y - 1), new Vector2Int(3, 3)); int[,] ids = new int[3, 3]; for (int x = 0; x < 3; ++x) { for (int y = 0; y < 3; ++y) { ids[x, y] = grid[x, y].tileData.Id; if (x != 1 || y != 1) { grid[x, y].AddDataChangeListener(UpdateSprite); } } } TerrainBrush.TileType tileType = TerrainBrush.GetTileType(ids, 1, 1); if (type == tileType && tileType != TerrainBrush.TileType.Error) { tile.spriteRenderer.sprite = sprite; if (!tile.tileData.IsWalkable) { tile.gameObject.AddComponent <PolygonCollider2D>(); } return; } type = tileType; int other = TerrainBrush.GetOtherType(ids, 1, 1, tileType); if (tileType == TerrainBrush.TileType.Error) { tile.SetTileData(TileData.idToData[other]); return; //SetTileAsCenter(); } else { string name = ""; if (other != -1) { name = tile.tileData.Name + TileData.idToData[other].Name + (int)tileType; tile.spriteRenderer.sortingLayerName = "Terrain"; sprite = SpriteManager.GetTileSprite(name); if (sprite == null) { SetTileAsCenter(); } } else { SetTileAsCenter(); } } tile.spriteRenderer.sprite = sprite; if (!tile.tileData.IsWalkable) { tile.gameObject.AddComponent <PolygonCollider2D>(); } if (!sprite) { int rand = Random.Range(0, tileAmounts); sprite = SpriteManager.GetTileSprite(tile.tileData.Name + rand.ToString()); } tile.spriteRenderer.sprite = sprite; if (!tile.tileData.IsWalkable) { tile.gameObject.AddComponent <PolygonCollider2D>(); } }
/// <inheritdoc/> protected override void ModifyTerrain(Point offset, TerrainBrush brush, byte[,] oldData, byte[,] newData) { #region Sanity checks if (oldData == null) { throw new ArgumentNullException(nameof(oldData)); } if (newData == null) { throw new ArgumentNullException(nameof(newData)); } #endregion var heightMap = Terrain.HeightMap; // Iterate through intersection of [0,area.Size) and [-offset,heightMap-offset int xMin = Math.Max(0, -offset.X); int xMax = Math.Min(brush.Size, heightMap.Width - offset.X); int yMin = Math.Max(0, -offset.Y); int yMax = Math.Min(brush.Size, heightMap.Height - offset.Y); // Use separated Gaussian filter with additional write-back between steps // Additional write-back is required because data points outside of the modified area may be queried // ReSharper disable AccessToModifiedClosure for (int x = xMin; x < xMax; x++) { for (int y = yMin; y < yMax; y++) { // Filter horizontal double factor = brush.Factor(x, y); double filteredValue = GetFiltered(i => heightMap.ClampedRead(offset.X + x + i, offset.Y + y)); byte previousValue = heightMap[offset.X + x, offset.Y + y]; newData[x, y] = (byte)(factor * filteredValue + (1 - factor) * previousValue); } } for (int x = xMin; x < xMax; x++) { for (int y = yMin; y < yMax; y++) { oldData[x, y] = heightMap[offset.X + x, offset.Y + y]; // Write back heightMap[offset.X + x, offset.Y + y] = newData[x, y]; } } for (int x = xMin; x < xMax; x++) { for (int y = yMin; y < yMax; y++) { // Filter vertical double factor = brush.Factor(x, y); double filteredValue = GetFiltered(i => heightMap.ClampedRead(offset.X + x, offset.Y + y + i)); byte previousValue = heightMap[offset.X + x, offset.Y + y]; newData[x, y] = (byte)(factor * filteredValue + (1 - factor) * previousValue); } } for (int x = xMin; x < xMax; x++) { for (int y = yMin; y < yMax; y++) { // Write back heightMap[offset.X + x, offset.Y + y] = newData[x, y]; } } // ReSharper restore AccessToModifiedClosure }