public void CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1, 1, 1))) { throw new UnityException("Can't slice outside of our slice bounds"); } for (int x = 0; x < newSliceSize.x; x++) { for (int y = 0; y < newSliceSize.y; y++) { for (int z = 0; z < newSliceSize.z; z++) { //pre-calculate it before we copy, because afterwards we won't have contextual data. if (tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].shape == TiletypeShape.RAMP) { tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].CalculateRampType(); } target.tiles[x, y, z] = tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z]; target.tiles[x, y, z].container = target; target.tilesPresent[target.PresentIndex(x, y, z)] = tilesPresent[PresentIndex(localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z)]; } } } target.SliceOrigin = newSliceOrigin; }
public MapDataStore CopySlice(DFCoord newSliceOrigin, DFCoord newSliceSize) { MapDataStore target = new MapDataStore(newSliceOrigin, newSliceSize); CopySliceTo(newSliceOrigin, newSliceSize, target); return(target); }
bool DesignationApplies(MapDataStore.Tile tile) { switch (digMode) { case DigMode.None: break; case DigMode.Dig: case DigMode.UpStair: case DigMode.UpDownStair: case DigMode.UpRamp: return tile.Hidden || (tile.isWall && tile.tiletypeMaterial != TiletypeMaterial.TREE_MATERIAL); case DigMode.Channel: case DigMode.DownStair: return tile.Hidden || (tile.tiletypeMaterial != TiletypeMaterial.TREE_MATERIAL); case DigMode.RemoveUpStairRamp: return tile.shape == TiletypeShape.RAMP || tile.shape == TiletypeShape.STAIR_UP || tile.shape == TiletypeShape.STAIR_UPDOWN; case DigMode.ChopTrees: return tile.tiletypeMaterial == TiletypeMaterial.TREE_MATERIAL; case DigMode.GatherPlants: return tile.tiletypeMaterial == TiletypeMaterial.PLANT; case DigMode.SmoothStone: break; case DigMode.EngraveStone: break; case DigMode.CarveFortifications: break; case DigMode.RemoveConstruction: break; case DigMode.RemoveDesignation: return true; default: break; } return false; }
//Handle mouse dragging here. void Update() { if (!DFConnection.Connected || GameMap.Instance == null || !GameMap.Instance.enabled) { return; } //mouseWorldPosition = GetMouseWorldPosition(Input.mousePosition); if (DFConnection.Instance.WorldMode != dfproto.GetWorldInfoOut.Mode.MODE_ADVENTURE) { UpdateCameraPan(); } if (Input.GetMouseButton(0) && !EventSystem.current.IsPointerOverGameObject()) { Ray mouseRay = GetComponent <Camera>().ScreenPointToRay(Input.mousePosition); DFCoord currentTarget; RaycastHit currentTargetCoords; if (DFConnection.Connected && GameMap.Instance.enabled && MapDataStore.Raycast(mouseRay, out currentTarget, out currentTargetCoords)) { GameMap.Instance.cursX = currentTarget.x; GameMap.Instance.cursY = currentTarget.y; GameMap.Instance.cursZ = currentTarget.z; } else { GameMap.Instance.cursX = -30000; GameMap.Instance.cursY = -30000; GameMap.Instance.cursZ = -30000; } } }
//Handle mouse dragging here. void Update() { if (!DFConnection.Connected || GameMap.Instance == null || !GameMap.Instance.enabled) { return; } //mouseWorldPosition = GetMouseWorldPosition(Input.mousePosition); UpdateCameraPan(); if (Input.GetMouseButton(0) && !EventSystem.current.IsPointerOverGameObject()) { Ray mouseRay = GetComponent <Camera>().ScreenPointToRay(Input.mousePosition); DFCoord currentTarget; Vector3 currentTargetCoords; if (DFConnection.Connected && GameMap.Instance.enabled && MapDataStore.FindCurrentTarget(mouseRay, out currentTarget, out currentTargetCoords)) { GameMap.Instance.cursX = currentTarget.x; GameMap.Instance.cursY = currentTarget.y; GameMap.Instance.cursZ = currentTarget.z; } else { GameMap.Instance.cursX = -30000; GameMap.Instance.cursY = -30000; GameMap.Instance.cursZ = -30000; } } }
bool GenerateTiles(MapDataStore data, out CPUMesh tiles, out CPUMesh stencilTiles, out CPUMesh transparentTiles, out CPUMesh topTiles, out CPUMesh topStencilTiles, out CPUMesh topTransparentTiles, out CPUMesh collisionTiles, TempBuffers temp) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; int bufferIndex = 0; int stencilBufferIndex = 0; int transparentBufferIndex = 0; int collisionIndex = 0; for (int xx = (block_x * GameMap.blockSize); xx < (block_x + 1) * GameMap.blockSize; xx++) { for (int yy = (block_y * GameMap.blockSize); yy < (block_y + 1) * GameMap.blockSize; yy++) { if (!data.InSliceBounds(new DFCoord(xx, yy, block_z))) { throw new UnityException("OOB"); } if (data[xx, yy, block_z] == null) { continue; } for (int i = 0; i < (int)MeshLayer.Count; i++) { if (i < (int)MeshLayer.StaticCutout) { FillMeshBuffer(out temp.meshBuffer[bufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); bufferIndex++; } else if (i < (int)MeshLayer.StaticTransparent) { FillMeshBuffer(out temp.stencilMeshBuffer[stencilBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); stencilBufferIndex++; } else if (i < (int)MeshLayer.Collision) { FillMeshBuffer(out temp.transparentMeshBuffer[transparentBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); transparentBufferIndex++; } else { FillMeshBuffer(out temp.collisionMeshBuffer[collisionIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); collisionIndex++; } } } } bool dontCare, success; stencilTiles = MeshCombineUtility.ColorCombine(temp.stencilMeshBuffer, out dontCare, false); topStencilTiles = MeshCombineUtility.ColorCombine(temp.stencilMeshBuffer, out dontCare, true); transparentTiles = MeshCombineUtility.ColorCombine(temp.transparentMeshBuffer, out dontCare, false); topTransparentTiles = MeshCombineUtility.ColorCombine(temp.transparentMeshBuffer, out dontCare, true); topTiles = MeshCombineUtility.ColorCombine(temp.meshBuffer, out dontCare, true); tiles = MeshCombineUtility.ColorCombine(temp.meshBuffer, out success, false); collisionTiles = MeshCombineUtility.ColorCombine(temp.collisionMeshBuffer, out dontCare, false); return(success); }
public void CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1, 1, 1))) { throw new UnityException("Can't slice outside of our slice bounds"); } target.SliceOrigin = newSliceOrigin; for (int x = target.MinCoord.x; x < target.MaxCoord.x; x++) { for (int y = target.MinCoord.y; y < target.MaxCoord.y; y++) { for (int z = target.MinCoord.z; z < target.MaxCoord.z; z++) { if (this[x, y, z] == null) { target[x, y, z] = null; continue; } //pre-calculate it before we copy, because afterwards we won't have contextual data. if (this[x, y, z].shape == TiletypeShape.RAMP) { this[x, y, z].CalculateRampType(); } target[x, y, z] = this[x, y, z]; } } } }
/// <summary> /// Constructs a new DatabaseRenderer that will not draw labels, instead it stores the label /// information in the labelStore for drawing by a LabelLayer. /// </summary> /// <param name="mapDatabase"> /// the MapDatabase from which the map data will be read. </param> public DatabaseRenderer(MapDataStore mapDatabase, IGraphicFactory graphicFactory, TileBasedLabelStore labelStore) { this.mapDatabase = mapDatabase; this.graphicFactory = graphicFactory; this.labelStore = labelStore; this.renderLabels = false; this.tileCache = null; this.tileDependencies = null; }
/// <summary> /// Constructs a new DatabaseRenderer that will draw labels onto the tiles. /// </summary> /// <param name="mapFile"> /// the MapDatabase from which the map data will be read. </param> public DatabaseRenderer(MapDataStore mapFile, IGraphicFactory graphicFactory, TileCache tileCache) { this.mapDatabase = mapFile; this.graphicFactory = graphicFactory; this.labelStore = null; this.renderLabels = true; this.tileCache = tileCache; this.tileDependencies = new TileDependencies(); }
// Enqueue a block for meshing; inclde public bool Enqueue(DFCoord targetLocation, bool tiles, bool liquids) { if (!GameMap.IsBlockCorner(targetLocation)) { throw new UnityException("Can't enqueue non-block-corners"); } if (!tiles && !liquids) { throw new UnityException("Why mesh something without tiles or liquids?"); } UnityEngine.Profiling.Profiler.BeginSample("BlockMesher.Enqueue"); // Using our object pool MapDataStore targetDataStore = AllocateBlockStore(); // Copy data if (!MapDataStore.Main.CopySliceTo(targetLocation, MapDataStore.BLOCK_SIZE, targetDataStore)) { UnityEngine.Profiling.Profiler.EndSample(); return(true); //it's empty, but it isn't a failure condition. } // In case we displace another block update Request redundant; lock (requestQueue) { // Will be { tiles: false, liquids: false, data: null } if we don't have anything queued redundant = requestQueue[targetLocation]; //if there's no existing queue member, don't add more than needed. if (redundant.data == null) { if (requestQueue.Count >= 16) { UnityEngine.Profiling.Profiler.EndSample(); return(false); } } Request meshRequest = new Request(); // If either request wanted liquids, do liquids; // If either request wanted tiles, do tiles. meshRequest.liquids = liquids || redundant.liquids; meshRequest.tiles = tiles || redundant.tiles; meshRequest.data = targetDataStore; requestQueue.EnqueueAndDisplace(targetLocation, meshRequest); } if (redundant.data != null) { lock (recycledBlocks) { // Object pooling! recycledBlocks.Push(redundant.data); } } UnityEngine.Profiling.Profiler.EndSample(); return(true); }
public static bool Handled(MapDataStore.Tile tile) { if (UseBoth(tile)) return true; if (tile == null) return true; //means it's air/empty if (tile.Hidden) return false; return (HandleShape(tile) && IsNatural(tile)); }
// Populate lists when we connect void InitStatics() { MaterialTokenList.matTokenList = _netMaterialList.material_list; TiletypeTokenList.tiletypeTokenList = _netTiletypeList.tiletype_list; ItemTokenList.itemTokenList = _netItemList.material_list; MapDataStore.tiletypeTokenList = _netTiletypeList.tiletype_list; MapDataStore.InitMainMap(_netMapInfo.block_size_x * 16, _netMapInfo.block_size_y * 16, _netMapInfo.block_size_z); Debug.Log("Materials fetched: " + _netMaterialList.material_list.Count); Debug.Log("Tiletypes fetched: " + _netTiletypeList.tiletype_list.Count); Debug.Log("Itemtypes fetched: " + _netItemList.material_list.Count); Debug.Log("Buildingtypes fetched: " + _netBuildingList.building_list.Count); Debug.Log("Fetched " + _netRegionMaps.world_maps.Count + " surrounding regions"); Debug.Log("Creature Raws fetched: " + _netCreatureRawList.creature_raws.Count); }
public Map(int myWidth, int myHeight, string mapString) { mapDataStore = new MapDataStore { width = myWidth, height = myHeight, occupantTicker = 0, maxCost = 100, tiles = new NativeArray <MapTile>(myWidth * myHeight, Allocator.Persistent), occupants = new NativeArray <int>(myWidth * myHeight, Allocator.Persistent), occupantTickers = new NativeArray <int>(myWidth * myHeight, Allocator.Persistent), }; }
public Tile(MapDataStore container, DFCoord position) { this.container = container; this.position = position; tileType = default(int); material = default(MatPairStruct); base_material = default(MatPairStruct); layer_material = default(MatPairStruct); vein_material = default(MatPairStruct); construction_item = default(MatPairStruct); waterLevel = default(int); magmaLevel = default(int); rampType = 0; }
Vector3 GetMouseWorldPosition(Vector3 mousePosition) { DFCoord dfTarget; //dummy coord to hold things for now. RaycastHit WorldPos; Ray mouseRay = GetComponent <Camera>().ScreenPointToRay(mousePosition); if (!MapDataStore.Raycast(mouseRay, out dfTarget, out WorldPos)) { Plane currentPlane = new Plane(Vector3.up, GameMap.DFtoUnityCoord(0, 0, GameMap.Instance.PosZ)); float distance; if (currentPlane.Raycast(mouseRay, out distance)) { WorldPos.point = mouseRay.GetPoint(distance); } else { WorldPos.point = Vector3.zero; } } return(WorldPos.point); }
// Enqueue a block for meshing; inclde public void Enqueue(DFCoord targetLocation, bool tiles, bool liquids) { if (!GameMap.IsBlockCorner(targetLocation)) { throw new UnityException("Can't enqueue non-block-corners"); } if (!tiles && !liquids) { throw new UnityException("Why mesh something without tiles or liquids?"); } // Using our object pool MapDataStore targetDataStore = AllocateBlockStore(); // Copy data MapDataStore.Main.CopySliceTo(targetLocation, MapDataStore.BLOCK_SIZE, targetDataStore); // In case we displace another block update Request redundant; lock (requestQueue) { // Will be { tiles: false, liquids: false, data: null } if we don't have anything queued redundant = requestQueue[targetLocation]; Request meshRequest = new Request(); // If either request wanted liquids, do liquids; // If either request wanted tiles, do tiles. meshRequest.liquids = liquids || redundant.liquids; meshRequest.tiles = tiles || redundant.tiles; meshRequest.data = targetDataStore; requestQueue.EnqueueAndDisplace(targetLocation, meshRequest); } if (redundant.data != null) { lock (recycledBlocks) { // Object pooling! recycledBlocks.Push(redundant.data); } } }
public Tile(MapDataStore container, DFCoord position) { this.container = container; this.position = position; tileType = default(int); material = default(MatPairStruct); base_material = default(MatPairStruct); layer_material = default(MatPairStruct); vein_material = default(MatPairStruct); construction_item = default(MatPairStruct); waterLevel = default(int); magmaLevel = default(int); rampType = 0; buildingMaterial = default(MatPairStruct); buildingType = default(BuildingStruct); buildingLocalPos = default(DFCoord2d); buildingDirection = 0; hidden = false; trunkPercent = 0; positionOnTree = default(DFCoord); digDesignation = TileDigDesignation.NO_DIG; }
bool GenerateTiles(MapDataStore data, out MeshData tiles, out MeshData stencilTiles, TempBuffers temp) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; int bufferIndex = 0; int stencilBufferIndex = 0; for (int xx = (block_x * GameMap.blockSize); xx < (block_x + 1) * GameMap.blockSize; xx++) { for (int yy = (block_y * GameMap.blockSize); yy < (block_y + 1) * GameMap.blockSize; yy++) { if (!data.InSliceBounds(new DFCoord(xx, yy, block_z))) { throw new UnityException("OOB"); } if (data[xx, yy, block_z] == null) { continue; } for (int i = 0; i < (int)MeshLayer.Count; i++) { MeshLayer layer = (MeshLayer)i; switch (layer) { case MeshLayer.StaticMaterial: case MeshLayer.BaseMaterial: case MeshLayer.LayerMaterial: case MeshLayer.VeinMaterial: case MeshLayer.NoMaterial: FillMeshBuffer(out temp.meshBuffer[bufferIndex], layer, data[xx, yy, block_z].Value); bufferIndex++; break; case MeshLayer.StaticCutout: case MeshLayer.BaseCutout: case MeshLayer.LayerCutout: case MeshLayer.VeinCutout: case MeshLayer.Growth0Cutout: case MeshLayer.Growth1Cutout: case MeshLayer.Growth2Cutout: case MeshLayer.Growth3Cutout: case MeshLayer.NoMaterialCutout: FillMeshBuffer(out temp.stencilMeshBuffer[stencilBufferIndex], layer, data[xx, yy, block_z].Value); stencilBufferIndex++; break; default: break; } } } } bool dontCare, success; stencilTiles = MeshCombineUtility.ColorCombine(temp.stencilMeshBuffer, out dontCare); tiles = MeshCombineUtility.ColorCombine(temp.meshBuffer, out success); return(success); }
private bool IsNullOrEmpty(MapDataStore.Tile tile) { if (tile == null) return true; if (tile.shape == TiletypeShape.EMPTY) return true; if (tile.shape == TiletypeShape.ENDLESS_PIT) return true; return false; }
bool GenerateTiles(MapDataStore data, out CPUMesh tiles, out CPUMesh stencilTiles, out CPUMesh transparentTiles, out CPUMesh topTiles, out CPUMesh topStencilTiles, out CPUMesh topTransparentTiles, TempBuffers temp) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; int bufferIndex = 0; int stencilBufferIndex = 0; int transparentBufferIndex = 0; for (int xx = (block_x * GameMap.blockSize); xx < (block_x + 1) * GameMap.blockSize; xx++) for (int yy = (block_y * GameMap.blockSize); yy < (block_y + 1) * GameMap.blockSize; yy++) { if (!data.InSliceBounds(new DFCoord(xx, yy, block_z))) throw new UnityException("OOB"); if (data[xx, yy, block_z] == null) continue; for (int i = 0; i < (int)MeshLayer.Count; i++) { if (i < (int)MeshLayer.StaticCutout) { FillMeshBuffer(out temp.meshBuffer[bufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); bufferIndex++; } else if (i < (int)MeshLayer.StaticTransparent) { FillMeshBuffer(out temp.stencilMeshBuffer[stencilBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); stencilBufferIndex++; } else { FillMeshBuffer(out temp.transparentMeshBuffer[transparentBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); transparentBufferIndex++; } } } bool dontCare, success; stencilTiles = MeshCombineUtility.ColorCombine(temp.stencilMeshBuffer, out dontCare, false); topStencilTiles = MeshCombineUtility.ColorCombine(temp.stencilMeshBuffer, out dontCare, true); transparentTiles = MeshCombineUtility.ColorCombine(temp.transparentMeshBuffer, out dontCare, false); topTransparentTiles = MeshCombineUtility.ColorCombine(temp.transparentMeshBuffer, out dontCare, true); topTiles = MeshCombineUtility.ColorCombine(temp.meshBuffer, out dontCare, true); tiles = MeshCombineUtility.ColorCombine(temp.meshBuffer, out success, false); return success; }
public static bool IsNatural(MapDataStore.Tile tile) { switch (tile.tiletypeMaterial) { case TiletypeMaterial.NO_MATERIAL: case TiletypeMaterial.AIR: case TiletypeMaterial.SOIL: case TiletypeMaterial.STONE: case TiletypeMaterial.FEATURE: case TiletypeMaterial.LAVA_STONE: case TiletypeMaterial.MINERAL: case TiletypeMaterial.GRASS_LIGHT: case TiletypeMaterial.GRASS_DARK: case TiletypeMaterial.GRASS_DRY: case TiletypeMaterial.GRASS_DEAD: case TiletypeMaterial.PLANT: case TiletypeMaterial.POOL: case TiletypeMaterial.BROOK: case TiletypeMaterial.RIVER: case TiletypeMaterial.ROOT: case TiletypeMaterial.HFS: return true; default: return false; } }
public void CopySliceTo(BlockCoord block, MapDataStore target) { CopySliceTo(block.ToDFCoord(), BLOCK_SIZE, target); }
public MapDataStore CopySlice(DFCoord newSliceOrigin, DFCoord newSliceSize) { MapDataStore target = new MapDataStore(newSliceOrigin, newSliceSize); CopySliceTo(newSliceOrigin, newSliceSize, target); return target; }
private MeshCombineUtility.HiddenFaces CalculateHiddenFaces(MapDataStore.Tile tile, RotationType rotation) { MeshCombineUtility.HiddenFaces hiddenFaces = MeshCombineUtility.HiddenFaces.None; if (rotation == RotationType.None) { if (tile.North != null && (tile.North.isWall || tile.North.Hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.North; if (tile.South != null && (tile.South.isWall || tile.South.Hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.South; if (tile.East != null && (tile.East.isWall || tile.East.Hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.East; if (tile.West != null && (tile.West.isWall || tile.West.Hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.West; } if (rotation != RotationType.TreeRound && rotation != RotationType.TreeRoundTall)//these two rotations don't give a flat rotation. { if (tile.Up != null && (tile.Up.isSolidBase || tile.Up.Hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.Up; if (tile.Down != null && (tile.Down.isWall || tile.Down.Hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.Down; } return hiddenFaces; }
/// <summary> /// Performs a single update. /// </summary> /// <exception cref="System.Exception"></exception> void PerformSingleUpdate() { //pause df here, so it doesn't try to resume while we're working. networkClient.SuspendGame(); //everything that controls DF. #region DF Control if (mapResetRequested.Pop()) { mapResetCall.TryExecute(); } if (digCommandCall != null) { while (netDigCommands.Count > 0) { digCommandCall.TryExecute(netDigCommands.Dequeue()); } } if (setSideMenuCall != null) { while (netSidebarSets.Count > 0) { setSideMenuCall.TryExecute(netSidebarSets.Dequeue()); } } if (pauseCommandCall != null) { while (pauseCommands.Count > 0) { pauseCommandCall.TryExecute(pauseCommands.Dequeue()); } } if (keyboardEventCall != null) { KeyboardEvent dfEvent; while (keyPresses.TryDequeue(out dfEvent)) { keyboardEventCall.TryExecute(dfEvent); } } if (moveCommandCall != null) { while (moveCommands.Count > 0) { moveCommandCall.TryExecute(moveCommands.Dequeue()); } } if (jumpCommandCall != null) { while (jumpCommands.Count > 0) { jumpCommandCall.TryExecute(jumpCommands.Dequeue()); } } if (movementSelectCommandCall != null) { while (carefulMoveCommands.Count > 0) { movementSelectCommandCall.TryExecute(carefulMoveCommands.Dequeue()); } } if (miscMoveCall != null) { while (miscMoveCommands.Count > 0) { miscMoveCall.TryExecute(miscMoveCommands.Dequeue()); } } #endregion #region DF Read if (menuQueryCall != null) { AdventureMenuContents = menuQueryCall.Execute(); } if (getSideMenuCall != null) { SidebarState = getSideMenuCall.Execute(); } if (fetchMap) { if (mapInfoCall != null) { var mapInfo = mapInfoCall.Execute(); if (mapInfo == null) { if (netMapInfo != null) { lock (mapInfoLock) { embarkMapPosition = new DFCoord(-1, -1, -1); embarkMapSize = new DFCoord(0, 0, 0); MapDataStore.InitMainMap(embarkMapSize.x * 16, embarkMapSize.y * 16, embarkMapSize.z); } } } else { if ((netMapInfo == null) || mapInfo.block_pos_x != netMapInfo.block_pos_x || mapInfo.block_pos_y != netMapInfo.block_pos_y || mapInfo.block_pos_z != netMapInfo.block_pos_z || mapInfo.block_size_x != netMapInfo.block_size_x || mapInfo.block_size_y != netMapInfo.block_size_y || mapInfo.block_size_z != netMapInfo.block_size_z) { lock (mapInfoLock) { embarkMapPosition = new DFCoord(mapInfo.block_pos_x, mapInfo.block_pos_y, mapInfo.block_pos_z); embarkMapSize = new DFCoord(mapInfo.block_size_x, mapInfo.block_size_y, mapInfo.block_size_z); MapDataStore.InitMainMap(EmbarkMapSize.x * 16, EmbarkMapSize.y * 16, EmbarkMapSize.z); mapResetCall.TryExecute(); } } } netMapInfo = mapInfo; } if (viewInfoCall != null) { ViewInfo viewInfo; viewInfoCall.TryExecute(null, out viewInfo); netViewInfo.Set(viewInfo); } } if (fetchScreen) { if (copyScreenCall != null) { RemoteFortressReader.ScreenCapture screenCapture; copyScreenCall.TryExecute(null, out screenCapture); netScreenCapture.Set(screenCapture); } } BlockCoord.Range?requestRangeUpdate = requestRegion.Pop(); if (requestRangeUpdate != null) { blockRequest.min_x = requestRangeUpdate.Value.Min.x * GameMap.blockSize / 16; blockRequest.min_y = requestRangeUpdate.Value.Min.y * GameMap.blockSize / 16; blockRequest.min_z = requestRangeUpdate.Value.Min.z; blockRequest.max_x = requestRangeUpdate.Value.Max.x * GameMap.blockSize / 16; blockRequest.max_y = requestRangeUpdate.Value.Max.y * GameMap.blockSize / 16; blockRequest.max_z = requestRangeUpdate.Value.Max.z; } if (fetchUnits) { if (unitListCall != null) { UnitList unitList = unitListCall.Execute(blockRequest); netUnitList.Set(unitList); } else if (unitListCallLegacy != null) { UnitList unitList = unitListCallLegacy.Execute(); netUnitList.Set(unitList); } } if (fetchWorldMap) { if (worldMapCenterCall != null) { WorldMap tempWorldMap; worldMapCenterCall.TryExecute(null, out tempWorldMap); if (tempWorldMap != null) { DFTime = new DFTime(tempWorldMap.cur_year, tempWorldMap.cur_year_tick); } if (netWorldMapCenter == null || (tempWorldMap != null && (netWorldMapCenter.center_x != tempWorldMap.center_x || netWorldMapCenter.center_y != tempWorldMap.center_y))) { if (worldMapCall != null) { WorldMap worldMap; worldMapCall.TryExecute(null, out worldMap); netWorldMap.Set(worldMap); } netWorldMapCenter = tempWorldMap; worldMapMoved.Set(); if (regionMapCall != null) { RegionMaps regionMaps; regionMapCall.TryExecute(null, out regionMaps); netRegionMaps.Set(regionMaps); } nextRegionUpdate = DateTime.Now.AddSeconds(0.2); //add another region map update after this one, to get delayed regions.s } } if (nextRegionUpdate < DateTime.Now) { if (regionMapCall != null) { RegionMaps regionMaps; regionMapCall.TryExecute(null, out regionMaps); netRegionMaps.Set(regionMaps); } nextRegionUpdate = DateTime.MaxValue; } } if (pauseCommandCall != null) { SingleBool status; pauseStatusCall.TryExecute(null, out status); if (status != null) { _dfPauseState = status.Value; } } // since enqueueing results can block, we do it after we've unsuspended df BlockList resultList = null; if (fetchMap) { if (EmbarkMapSize.x > 0 && EmbarkMapSize.y > 0 && EmbarkMapSize.z > 0 && _needNewBlocks) { if (blockListCall != null) { //Don't pull more blocks than we have room for in the queue. It blocks things unneccesarily. blockRequest.blocks_needed = Mathf.Min(blockRequest.blocks_needed, pendingBlocks.Capacity - pendingBlocks.Count - 1); if (blockRequest.blocks_needed > 0) { resultList = blockListCall.Execute(blockRequest); } } } } Status stat = null; if (reportsCall != null) { reportsCall.TryExecute(null, out stat); if (stat != null) { netStatus.Set(stat); } } #endregion //All communication with DF should be before this. networkClient.ResumeGame(); if (resultList != null) { try { foreach (MapBlock mapBlock in resultList.map_blocks) { pendingBlocks.Enqueue(mapBlock); } engravings.Enqueue(resultList.engravings); } catch (Exception e) { Debug.LogException(e); } waves = resultList.ocean_waves; UpdatedAnyBlocks = true; } }
public Quaternion GetRotation(MapDataStore.Tile tile) { switch (rotationType) { case RotationType.None: return Quaternion.identity; case RotationType.AwayFromWall: { Directions wallSides = tile.WallBuildingSides; Vector2 average = Vector2.zero; if ((wallSides & Directions.NorthWest) == Directions.NorthWest) average += new Vector2(-1, 1); if ((wallSides & Directions.North) == Directions.North) average += new Vector2(0, 1); if ((wallSides & Directions.NorthEast) == Directions.NorthEast) average += new Vector2(1, 1); if ((wallSides & Directions.West) == Directions.West) average += new Vector2(-1, 0); if ((wallSides & Directions.East) == Directions.East) average += new Vector2(1, -0); if ((wallSides & Directions.SouthWest) == Directions.SouthWest) average += new Vector2(-1, -1); if ((wallSides & Directions.South) == Directions.South) average += new Vector2(0, -1); if ((wallSides & Directions.SouthEast) == Directions.SouthEast) average += new Vector2(1, -1); if (average.magnitude < 0.001) return Quaternion.Euler(0, 0, 0); float angle = Mathf.Atan2(average.x, average.y) * 180 / Mathf.PI; float angle90 = Mathf.Round(angle / 90) * 90; float angle45 = Mathf.Round(angle / 45) * 45; if (Mathf.Abs(angle90 - angle) < 30) return Quaternion.Euler(0, angle90, 0); else return Quaternion.Euler(0, angle45, 0); } case RotationType.Door: { Directions wallSides = tile.WallBuildingSides; if ((wallSides & (Directions.North | Directions.South | Directions.East | Directions.West)) == (Directions.North | Directions.South | Directions.East | Directions.West)) return Quaternion.identity; if ((wallSides & (Directions.North | Directions.South)) == (Directions.North | Directions.South)) return Quaternion.Euler(0, 90, 0); ; return Quaternion.identity; } case RotationType.BuildingDirection: { switch (tile.buildingDirection) { case RemoteFortressReader.BuildingDirection.NORTH: return Quaternion.Euler(0, 0, 0); case RemoteFortressReader.BuildingDirection.EAST: return Quaternion.Euler(0, 90, 0); case RemoteFortressReader.BuildingDirection.SOUTH: return Quaternion.Euler(0, 180, 0); case RemoteFortressReader.BuildingDirection.WEST: return Quaternion.Euler(0, -90, 0); default: return Quaternion.Euler(0, 0, 0); } } case RotationType.Random: { if (noise == null) noise = new OpenSimplexNoise(); float rot = (float)noise.eval(tile.position.x, tile.position.y, tile.position.z); return Quaternion.Euler(0, rot * 360, 0); } case RotationType.Random90: { if (noise == null) noise = new OpenSimplexNoise(); float rot = (float)noise.eval(tile.position.x, tile.position.y, tile.position.z); rot = Mathf.Round(rot * 4) * 90; return Quaternion.Euler(0, rot, 0); } case RotationType.TreeFlat: { Vector2 treeDir = new Vector2(-tile.positionOnTree.x, tile.positionOnTree.y); if (treeDir.sqrMagnitude < 0.001) return Quaternion.identity; float angle = Mathf.Atan2(treeDir.x, treeDir.y) * 180 / Mathf.PI; return Quaternion.Euler(0, angle, 0); } case RotationType.TreeRound: { Vector3 treeDir = new Vector3(-tile.positionOnTree.x, tile.positionOnTree.z, tile.positionOnTree.y); if (treeDir.sqrMagnitude < 0.001) return Quaternion.identity; return Quaternion.LookRotation(treeDir, Vector3.up); } case RotationType.TreeRoundTall: { if (noise == null) noise = new OpenSimplexNoise(); float mainRot = (float)noise.eval(tile.position.x, tile.position.y, tile.position.z); Vector3 smallRot = new Vector3((float)noise.eval(tile.position.x, tile.position.y, tile.position.z * 17), (float)noise.eval(tile.position.x * 17, tile.position.y, tile.position.z), 0); Vector3 treeDir = new Vector3(-tile.positionOnTree.x, tile.positionOnTree.z / 2.0f, tile.positionOnTree.y); if (treeDir.sqrMagnitude < 0.001) return Quaternion.identity; return Quaternion.LookRotation(treeDir, Vector3.up) * Quaternion.Euler(smallRot * 15) * Quaternion.AngleAxis(mainRot * 360.0f, Vector3.back); } default: return Quaternion.identity; } }
public bool CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { bool success = false; if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1,1,1))) { throw new UnityException("Can't slice outside of our slice bounds"); } target.SliceOrigin = newSliceOrigin; for (int x = target.MinCoord.x; x < target.MaxCoord.x; x++) { for (int y = target.MinCoord.y; y < target.MaxCoord.y; y++) { for (int z = target.MinCoord.z; z < target.MaxCoord.z; z++) { if (this[x, y, z] == null) { target[x, y, z] = null; continue; } //pre-calculate it before we copy, because afterwards we won't have contextual data. if (this[x,y,z].shape == TiletypeShape.RAMP) this[x, y, z].CalculateRampType(); target[x, y, z] = this[x,y,z]; success = true; } } } return success; }
public void CopyFrom(Tile orig) { container = orig.container; position = orig.position; tileType = orig.tileType; material = orig.material; base_material = orig.base_material; layer_material = orig.layer_material; vein_material = orig.vein_material; construction_item = orig.construction_item; waterLevel = orig.waterLevel; magmaLevel = orig.magmaLevel; RampType = orig.RampType; buildingType = orig.buildingType; buildingMaterial = orig.buildingMaterial; buildingLocalPos = orig.buildingLocalPos; buildingDirection = orig.buildingDirection; Hidden = orig.Hidden; trunkPercent = orig.trunkPercent; positionOnTree = orig.positionOnTree; digDesignation = orig.digDesignation; spatters = orig.spatters; }
CPUMesh GenerateLiquidSurface(MapDataStore data, int liquid_select) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; Vector3[] finalVertices = new Vector3[(GameMap.blockSize + 1) * (GameMap.blockSize + 1)]; Vector3[] finalNormals = new Vector3[(GameMap.blockSize + 1) * (GameMap.blockSize + 1)]; Vector2[] finalUVs = new Vector2[(GameMap.blockSize + 1) * (GameMap.blockSize + 1)]; List <int> finalFaces = new List <int>(); // Is this necessary? heights[0, 0] = 0; heights[0, 1] = 0; heights[1, 0] = 0; heights[1, 1] = 0; for (int xx = 0; xx <= GameMap.blockSize; xx++) { for (int yy = 0; yy <= GameMap.blockSize; yy++) { //first find the heights of all tiles sharing one corner. for (int xxx = 0; xxx < 2; xxx++) { for (int yyy = 0; yyy < 2; yyy++) { int x = (block_x * GameMap.blockSize) + xx + xxx - 1; int y = (block_y * GameMap.blockSize) + yy + yyy - 1; if (x < 0 || y < 0 || x >= MapDataStore.MapSize.x || y >= MapDataStore.MapSize.y) { heights[xxx, yyy] = -1; continue; } var maybeTile = data[x, y, block_z]; if (maybeTile == null) { heights[xxx, yyy] = -1; continue; } var tile = maybeTile; if (tile.isWall) { heights[xxx, yyy] = -1; continue; } heights[xxx, yyy] = data.GetLiquidLevel(new DFCoord(x, y, block_z), liquid_select); heights[xxx, yyy] /= 7.0f; if (tile.isFloor) { heights[xxx, yyy] *= (GameMap.tileHeight - GameMap.floorHeight); heights[xxx, yyy] += GameMap.floorHeight; } else { heights[xxx, yyy] *= GameMap.tileHeight; } } } //now find their average, discaring invalid ones. float height = 0; float total = 0; foreach (var item in heights) { if (item < 0) { continue; } height += item; total++; } if (total >= 1) { height /= total; } //find the slopes. float sx = (( (heights[0, 0] < 0 ? height : heights[0, 0]) + (heights[0, 1] < 0 ? height : heights[0, 1])) / 2) - (( (heights[1, 0] < 0 ? height : heights[1, 0]) + (heights[1, 1] < 0 ? height : heights[1, 1])) / 2); float sy = (( (heights[0, 0] < 0 ? height : heights[0, 0]) + (heights[1, 0] < 0 ? height : heights[1, 0])) / 2) - (( (heights[0, 1] < 0 ? height : heights[0, 1]) + (heights[1, 1] < 0 ? height : heights[1, 1])) / 2); finalNormals[coord2Index(xx, yy)] = new Vector3(sx, GameMap.tileWidth * 2, -sy); finalNormals[coord2Index(xx, yy)].Normalize(); finalVertices[coord2Index(xx, yy)] = GameMap.DFtoUnityCoord(xx, yy, -GameMap.MapZOffset); finalVertices[coord2Index(xx, yy)].x -= GameMap.tileWidth / 2.0f; finalVertices[coord2Index(xx, yy)].z += GameMap.tileWidth / 2.0f; finalVertices[coord2Index(xx, yy)].y += height; finalUVs[coord2Index(xx, yy)] = new Vector2(xx, yy); } } for (int xx = 0; xx < GameMap.blockSize; xx++) { for (int yy = 0; yy < GameMap.blockSize; yy++) { if (data.GetLiquidLevel( new DFCoord((block_x * GameMap.blockSize) + xx, (block_y * GameMap.blockSize) + yy, block_z), liquid_select) == 0) { continue; } finalFaces.Add(coord2Index(xx, yy)); finalFaces.Add(coord2Index(xx + 1, yy)); finalFaces.Add(coord2Index(xx + 1, yy + 1)); finalFaces.Add(coord2Index(xx, yy)); finalFaces.Add(coord2Index(xx + 1, yy + 1)); finalFaces.Add(coord2Index(xx, yy + 1)); } } if (finalFaces.Count > 0) { return(new CPUMesh(vertices: finalVertices, normals: finalNormals, tangents: null, uv: finalUVs, uv2: null, uv3: null, colors: null, triangles: finalFaces.ToArray())); } else { return(null); } }
// Called from DFConnection.InitStatics public static void InitMainMap(int xSize, int ySize, int zSize) { MapSize = new DFCoord(xSize, ySize, zSize); _main = new MapDataStore(new DFCoord(0, 0, 0), MapSize); Debug.Log("Set main map to " + MapSize); }
// Update is called once per frame void Update() { if (diggingTool.digMode != DiggingTool.DigMode.None) { //start the drag. This is the same for all shapes. if (Input.GetMouseButtonDown(0)) { if (EventSystem.current.IsPointerOverGameObject()) //we just clicked on { coordList.Clear(); //flush out any list we currently have, so the rest doesn't get confused. drawing = false; } else { Ray ray = mainCam.ScreenPointToRay(Input.mousePosition); DFCoord mapTargetPos; Vector3 unityTargetPos; if (MapDataStore.FindCurrentTarget(ray, out mapTargetPos, out unityTargetPos)) { //lastTargetPos = mapTargetPos; unityTargetPos += (ray.direction * 0.001f); lastTargetPosF = GameMap.UnityToFloatingDFCoord(unityTargetPos); drawing = true; } } } else if (Input.GetMouseButton(0) && drawing) //still dragging { Ray ray = mainCam.ScreenPointToRay(Input.mousePosition); DFCoord mapTargetPos; Vector3 unityTargetPos; if (MapDataStore.FindCurrentTarget(ray, out mapTargetPos, out unityTargetPos)) { unityTargetPos += (ray.direction * 0.001f); Vector3 mapFloatTargetPos = GameMap.UnityToFloatingDFCoord(unityTargetPos); switch (brushShape) { case BrushShape.Freehand: //if (dragging) //{ // diggingTool.Apply(coordList); // coordList.Clear(); // RayTrace(coordList, lastTargetPosF, mapFloatTargetPos); //} //lastTargetPosF = mapFloatTargetPos; //dragging = true; //break; case BrushShape.Box: coordList.Clear(); Box(coordList, lastTargetPosF, mapFloatTargetPos); break; default: break; } } foreach (var item in coordList) { DrawCursor(item, true); } } else if (Input.GetMouseButtonUp(0) && drawing) //released the mouse { diggingTool.Apply(coordList); coordList.Clear(); drawing = false; } else if (!EventSystem.current.IsPointerOverGameObject()) // Just hovering over the map. { Ray ray = mainCam.ScreenPointToRay(Input.mousePosition); DFCoord mapTargetPos; Vector3 unityTargetPos; if (MapDataStore.FindCurrentTarget(ray, out mapTargetPos, out unityTargetPos)) { unityTargetPos += ray.direction * 0.001f; Vector3 pos = GameMap.UnityToFloatingDFCoord(unityTargetPos); mapTargetPos = new DFCoord(Mathf.FloorToInt(pos.x), Mathf.FloorToInt(pos.y), Mathf.FloorToInt(pos.z)); DrawCursor(mapTargetPos, false); } } } }
bool GenerateTiles(MapDataStore data, out CPUMesh tiles, out CPUMesh stencilTiles, out CPUMesh transparentTiles, out CPUMesh topTiles, out CPUMesh topStencilTiles, out CPUMesh topTransparentTiles, out CPUMesh collisionTiles, out CPUMesh terrainTiles, out CPUMesh topTerrainTiles) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; int bufferIndex = 0; int stencilBufferIndex = 0; int transparentBufferIndex = 0; int collisionIndex = 0; int terrainIndex = 0; for (int xx = (block_x * GameMap.blockSize); xx < (block_x + 1) * GameMap.blockSize; xx++) for (int yy = (block_y * GameMap.blockSize); yy < (block_y + 1) * GameMap.blockSize; yy++) { if (!data.InSliceBounds(new DFCoord(xx, yy, block_z))) throw new UnityException("OOB"); if (data[xx, yy, block_z] == null) continue; for (int i = 0; i < (int)MeshLayer.Count; i++) { if (i < (int)MeshLayer.StaticCutout) { FillMeshBuffer( out meshBuffer[bufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); bufferIndex++; } else if (i < (int)MeshLayer.StaticTransparent) { FillMeshBuffer( out stencilMeshBuffer[stencilBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); stencilBufferIndex++; } else if (i < (int)MeshLayer.Collision) { FillMeshBuffer( out transparentMeshBuffer[transparentBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); transparentBufferIndex++; } else if (i < (int)MeshLayer.NaturalTerrain) { FillMeshBuffer( out collisionMeshBuffer[collisionIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); collisionIndex++; } else if(i == (int)MeshLayer.NaturalTerrain) { FillMeshBuffer(out terrainMeshBuffer[terrainIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); terrainIndex++; } } } bool dontCare, success; VoxelGenerator voxelGen = new VoxelGenerator(); if (block_z == 0) voxelGen.bottomless = true; terrainTiles = voxelGen.Triangulate(data); terrainTiles = MeshCombineUtility.ColorCombine(terrainMeshBuffer, out dontCare, false, terrainTiles); topTerrainTiles = MeshCombineUtility.ColorCombine(terrainMeshBuffer, out dontCare, true); stencilTiles = MeshCombineUtility.ColorCombine(stencilMeshBuffer, out dontCare, false); topStencilTiles = MeshCombineUtility.ColorCombine(stencilMeshBuffer, out dontCare, true); transparentTiles = MeshCombineUtility.ColorCombine(transparentMeshBuffer, out dontCare, false); topTransparentTiles = MeshCombineUtility.ColorCombine(transparentMeshBuffer, out dontCare, true); topTiles = MeshCombineUtility.ColorCombine(meshBuffer, out dontCare, true); tiles = MeshCombineUtility.ColorCombine(meshBuffer, out success, false); collisionTiles = MeshCombineUtility.ColorCombine(collisionMeshBuffer, out dontCare, false); return success; }
public Quaternion GetRotation(MapDataStore.Tile tile) { switch (rotationType) { case RotationType.None: return Quaternion.identity; case RotationType.AwayFromWall: { Directions wallSides = tile.WallBuildingSides; Vector2 average = Vector2.zero; if ((wallSides & Directions.NorthWest) == Directions.NorthWest) average += new Vector2(-1, 1); if ((wallSides & Directions.North) == Directions.North) average += new Vector2(0, 1); if ((wallSides & Directions.NorthEast) == Directions.NorthEast) average += new Vector2(1, 1); if ((wallSides & Directions.West) == Directions.West) average += new Vector2(-1, 0); if ((wallSides & Directions.East) == Directions.East) average += new Vector2(1, -0); if ((wallSides & Directions.SouthWest) == Directions.SouthWest) average += new Vector2(-1, -1); if ((wallSides & Directions.South) == Directions.South) average += new Vector2(0, -1); if ((wallSides & Directions.SouthEast) == Directions.SouthEast) average += new Vector2(1, -1); if (average.magnitude < 0.001) return Quaternion.Euler(0, 0, 0); float angle = Mathf.Atan2(average.x, average.y) * 180 / Mathf.PI; float angle90 = Mathf.Round(angle / 90) * 90; float angle45 = Mathf.Round(angle / 45) * 45; if (Mathf.Abs(angle90 - angle) < 30) return Quaternion.Euler(0, angle90, 0); else return Quaternion.Euler(0, angle45, 0); } case RotationType.Door: { Directions wallSides = tile.WallBuildingSides; if ((wallSides & (Directions.North | Directions.South | Directions.East | Directions.West)) == (Directions.North | Directions.South | Directions.East | Directions.West)) return Quaternion.identity; if ((wallSides & (Directions.North | Directions.South)) == (Directions.North | Directions.South)) return Quaternion.Euler(0, 90, 0); ; return Quaternion.identity; } case RotationType.BuildingDirection: { switch (tile.buildingDirection) { case RemoteFortressReader.BuildingDirection.NORTH: return Quaternion.Euler(0, 0, 0); case RemoteFortressReader.BuildingDirection.EAST: return Quaternion.Euler(0, 90, 0); case RemoteFortressReader.BuildingDirection.SOUTH: return Quaternion.Euler(0, 180, 0); case RemoteFortressReader.BuildingDirection.WEST: return Quaternion.Euler(0, -90, 0); default: return Quaternion.Euler(0, 0, 0); } } default: break; } return Quaternion.identity; }
/// <summary> /// Performs a single update. /// </summary> /// <exception cref="System.Exception"></exception> void PerformSingleUpdate() { //pause df here, so it doesn't try to resume while we're working. networkClient.suspend_game(); //everything that controls DF. #region DF Control if (mapResetRequested.Pop()) { mapResetCall.execute(); } if (digCommandCall != null) { while (netDigCommands.Count > 0) { digCommandCall.execute(netDigCommands.Dequeue()); } } if (pauseCommandCall != null) { while (pauseCommands.Count > 0) { pauseCommandCall.execute(pauseCommands.Dequeue()); } } if (keyboardEventCall != null) { KeyboardEvent dfEvent; while (keyPresses.TryDequeue(out dfEvent)) { keyboardEventCall.execute(dfEvent); } } #endregion #region DF Read if (fetchMap) { if (mapInfoCall != null) { MapInfo mapInfo; mapInfoCall.execute(null, out mapInfo); if (mapInfo == null) { if (netMapInfo != null) { lock (mapInfoLock) { embarkMapPosition = new DFCoord(-1, -1, -1); embarkMapSize = new DFCoord(0, 0, 0); MapDataStore.InitMainMap(embarkMapSize.x * 16, embarkMapSize.y * 16, embarkMapSize.z); } } } else { if ((netMapInfo == null) || mapInfo.block_pos_x != netMapInfo.block_pos_x || mapInfo.block_pos_y != netMapInfo.block_pos_y || mapInfo.block_pos_z != netMapInfo.block_pos_z || mapInfo.block_size_x != netMapInfo.block_size_x || mapInfo.block_size_y != netMapInfo.block_size_y || mapInfo.block_size_z != netMapInfo.block_size_z) { lock (mapInfoLock) { embarkMapPosition = new DFCoord(mapInfo.block_pos_x, mapInfo.block_pos_y, mapInfo.block_pos_z); embarkMapSize = new DFCoord(mapInfo.block_size_x, mapInfo.block_size_y, mapInfo.block_size_z); MapDataStore.InitMainMap(EmbarkMapSize.x * 16, EmbarkMapSize.y * 16, EmbarkMapSize.z); mapResetCall.execute(); } } } netMapInfo = mapInfo; } if (viewInfoCall != null) { ViewInfo viewInfo; viewInfoCall.execute(null, out viewInfo); netViewInfo.Set(viewInfo); } } if (fetchScreen) { if (copyScreenCall != null) { ScreenCapture screenCapture; copyScreenCall.execute(null, out screenCapture); netScreenCapture.Set(screenCapture); } } if (fetchUnits) { if (unitListCall != null) { UnitList unitList; unitListCall.execute(null, out unitList); netUnitList.Set(unitList); } } if (fetchWorldMap) { if (worldMapCenterCall != null) { WorldMap tempWorldMap; worldMapCenterCall.execute(null, out tempWorldMap); if (tempWorldMap != null) { DFTime = new DFTime(tempWorldMap.cur_year, tempWorldMap.cur_year_tick); } if (netWorldMapCenter == null || (tempWorldMap != null && (netWorldMapCenter.center_x != tempWorldMap.center_x || netWorldMapCenter.center_y != tempWorldMap.center_y))) { if (worldMapCall != null) { WorldMap worldMap; worldMapCall.execute(null, out worldMap); netWorldMap.Set(worldMap); } netWorldMapCenter = tempWorldMap; worldMapMoved.Set(); if (regionMapCall != null) { RegionMaps regionMaps; regionMapCall.execute(null, out regionMaps); netRegionMaps.Set(regionMaps); } nextRegionUpdate = DateTime.Now.AddSeconds(0.2); //add another region map update after this one, to get delayed regions.s } } if (nextRegionUpdate < DateTime.Now) { if (regionMapCall != null) { RegionMaps regionMaps; regionMapCall.execute(null, out regionMaps); netRegionMaps.Set(regionMaps); } nextRegionUpdate = DateTime.MaxValue; } } if (pauseCommandCall != null) { SingleBool status; pauseStatusCall.execute(null, out status); if (status != null) { _dfPauseState = status.Value; } } // since enqueueing results can block, we do it after we've unsuspended df BlockList resultList = null; if (fetchMap) { if (EmbarkMapSize.x > 0 && EmbarkMapSize.y > 0 && EmbarkMapSize.z > 0 && _needNewBlocks) { BlockCoord.Range?requestRangeUpdate = requestRegion.Pop(); if (requestRangeUpdate != null) { blockRequest.min_x = requestRangeUpdate.Value.Min.x; blockRequest.min_y = requestRangeUpdate.Value.Min.y; blockRequest.min_z = requestRangeUpdate.Value.Min.z; blockRequest.max_x = requestRangeUpdate.Value.Max.x; blockRequest.max_y = requestRangeUpdate.Value.Max.y; blockRequest.max_z = requestRangeUpdate.Value.Max.z; } if (blockListCall != null) { blockListCall.execute(blockRequest, out resultList); } } } #endregion //All communication with DF should be before this. networkClient.resume_game(); if (resultList != null) { foreach (MapBlock mapBlock in resultList.map_blocks) { pendingBlocks.Enqueue(mapBlock); } } }
public static bool HandleShape(MapDataStore.Tile tile) { switch (tile.shape) { case TiletypeShape.NO_SHAPE: case TiletypeShape.EMPTY: case TiletypeShape.FLOOR: case TiletypeShape.WALL: case TiletypeShape.BROOK_TOP: case TiletypeShape.ENDLESS_PIT: return true; default: return false; } }
public CPUMesh Triangulate(MapDataStore map) { vertices.Clear(); uvs.Clear(); colors.Clear(); triangles.Clear(); wallPolygons.Clear(); floorPolygons.Clear(); TriangulateCellRows(map); ConvertToMesh(wallPolygons.Polygons, GameMap.tileHeight); ConvertToMesh(floorPolygons.Polygons, GameMap.floorHeight); return new CPUMesh(vertices.ToArray(), null, null, uvs.ToArray(), null, null, null, triangles.ToArray()); }
// A big method, but pretty simple. // Walk through tiles (starting in current one); // in each tile, check if the ray is actively hitting something. // If it's not, find the wall of the tile the ray exits through, // go to that tile, and repeat. bool FindCurrentTarget(Ray ray, out DFCoord tileCoord, out Vector3 unityCoord) { if (!HitsMapCube(ray)) { tileCoord = default(DFCoord); unityCoord = default(Vector3); return(false); } // In each tile, we find its bottom corner, and then add these // values to find the coordinates of the walls. // If the ray increases on this axis, the offset will be the // width of the tile along that axis; if the ray decreases, // the offset will be 0 (since we're already on that wall.) float xWallOffset, yWallOffset, zWallOffset; // When we pass through a tile and hit this wall, how do we increment // our DFCoord? DFCoord xHitIncrement, yHitIncrement, zHitIncrement; if (ray.direction.x > 0) { xWallOffset = GameMap.tileWidth; xHitIncrement = new DFCoord(1, 0, 0); } else { xWallOffset = 0; xHitIncrement = new DFCoord(-1, 0, 0); } if (ray.direction.z > 0) { zWallOffset = GameMap.tileWidth; zHitIncrement = new DFCoord(0, -1, 0); } else { zWallOffset = 0; zHitIncrement = new DFCoord(0, 1, 0); } if (ray.direction.y > 0) { yWallOffset = GameMap.tileHeight; yHitIncrement = new DFCoord(0, 0, 1); } else { yWallOffset = 0; yHitIncrement = new DFCoord(0, 0, -1); } // If this is true and we go onto a tile outside the map, // we stop iterating (since we can't hit anything.) bool haveHitMap = false; // The coordinate we start at. DFCoord currentCoord = GameMap.UnityToDFCoord(ray.origin); // The coordinate of the last tile wall intersection. Vector3 lastHit = ray.origin; // Cheap hack to keep from looping forever if we screw up somehow. for (int _insurance = 0; _insurance < MAXIMUM_CHECKS; _insurance++) { if (debugMode) { DebugHighlightTile(currentCoord, Color.blue); } // Make sure we don't move backwards somehow. if ((lastHit.x - ray.origin.x) / ray.direction.x < 0) { throw new UnityException("Negative distance multiplier?"); } // Get the corner of the current tile. Vector3 cornerCoord = GameMap.DFtoUnityBottomCorner(currentCoord); // Are we in the selectable area of the map? if (!MapDataStore.InMapBounds(currentCoord) || gameMap.PosZ <= currentCoord.z) { // No. if (haveHitMap) { // But we have been before; // we've entered and exited the map without hitting anything. tileCoord = default(DFCoord); unityCoord = default(Vector3); return(false); } } else { // We are in the map. haveHitMap = true; MapDataStore.Tile currentTile = MapDataStore.Main[currentCoord.x, currentCoord.y, currentCoord.z]; // Are we in a real tile? if (currentTile != null) { // Yes. switch (currentTile.shape) { case RemoteFortressReader.TiletypeShape.EMPTY: case RemoteFortressReader.TiletypeShape.NO_SHAPE: // We're not hitting anything, though. break; //case RemoteFortressReader.TiletypeShape.SHRUB: //case RemoteFortressReader.TiletypeShape.SAPLING: case RemoteFortressReader.TiletypeShape.WALL: case RemoteFortressReader.TiletypeShape.FORTIFICATION: //case RemoteFortressReader.TiletypeShape.TRUNK_BRANCH: case RemoteFortressReader.TiletypeShape.TWIG: // We must be hitting things. // (maybe adjust shrub, saplings out of this group?) tileCoord = currentCoord; unityCoord = lastHit; return(true); case RemoteFortressReader.TiletypeShape.RAMP: case RemoteFortressReader.TiletypeShape.FLOOR: case RemoteFortressReader.TiletypeShape.BOULDER: case RemoteFortressReader.TiletypeShape.PEBBLES: case RemoteFortressReader.TiletypeShape.BROOK_TOP: case RemoteFortressReader.TiletypeShape.SAPLING: case RemoteFortressReader.TiletypeShape.SHRUB: case RemoteFortressReader.TiletypeShape.BRANCH: case RemoteFortressReader.TiletypeShape.TRUNK_BRANCH: // Check if we're in the floor. // (that we're in the tile is implied.) if (Between(cornerCoord.y, lastHit.y, cornerCoord.y + GameMap.floorHeight)) { tileCoord = currentCoord; unityCoord = lastHit; return(true); } // Check if we enter the floor; same way we check wall intersections. float floorY = cornerCoord.y + GameMap.floorHeight; float toFloorMult = (floorY - ray.origin.y) / ray.direction.y; Vector3 floorIntercept = ray.origin + ray.direction * toFloorMult; if (Between(cornerCoord.x, floorIntercept.x, cornerCoord.x + GameMap.tileWidth) && Between(cornerCoord.z, floorIntercept.z, cornerCoord.z + GameMap.tileWidth)) { tileCoord = currentCoord; unityCoord = lastHit; return(true); } break; } } } // Didn't hit anything in the tile; figure out which wall we're hitting & walk to that tile. { float xMult = (cornerCoord.x + xWallOffset - ray.origin.x) / ray.direction.x; Vector3 xIntercept = ray.origin + ray.direction * xMult; if (Between(cornerCoord.z, xIntercept.z, cornerCoord.z + GameMap.tileWidth) && Between(cornerCoord.y, xIntercept.y, cornerCoord.y + GameMap.tileHeight)) { lastHit = xIntercept; currentCoord += xHitIncrement; continue; } } { float zMult = (cornerCoord.z + zWallOffset - ray.origin.z) / ray.direction.z; Vector3 zIntercept = ray.origin + ray.direction * zMult; if (Between(cornerCoord.x, zIntercept.x, cornerCoord.x + GameMap.tileWidth) && Between(cornerCoord.y, zIntercept.y, cornerCoord.y + GameMap.tileHeight)) { lastHit = zIntercept; currentCoord += zHitIncrement; continue; } } { float yMult = (cornerCoord.y + yWallOffset - ray.origin.y) / ray.direction.y; Vector3 yIntercept = ray.origin + ray.direction * yMult; if (cornerCoord.x <= yIntercept.x && yIntercept.x <= cornerCoord.x + GameMap.tileWidth && cornerCoord.z <= yIntercept.z && yIntercept.z <= cornerCoord.z + GameMap.tileWidth) { lastHit = yIntercept; currentCoord += yHitIncrement; continue; } } // We haven't found a wall to hit. // This shouldn't happen, but occasionally does. //throw new UnityException("Didn't hit any tile walls?"); } // We went the maximum amount of time without hitting anything tileCoord = default(DFCoord); unityCoord = default(Vector3); return(false); }
/// <summary> /// This is the function that actually decides what mesh and texture each tile gets /// </summary> /// <param name="buffer">Buffer to put the chosen meshes into for combining</param> /// <param name="layer">layer currently being worked on</param> /// <param name="tile">The tile to get all the needed info from.</param> void FillMeshBuffer(out MeshCombineUtility.MeshInstance buffer, MeshLayer layer, MapDataStore.Tile tile, Vector3 pos) { buffer = new MeshCombineUtility.MeshInstance(); Vector2 index1 = Vector2.zero; Vector2 index2 = Vector2.zero; MeshContent meshContent = null; buffer.color = Color.grey; if (layer == MeshLayer.Collision) { if (!ContentLoader.Instance.CollisionMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } if (meshContent.MeshData.ContainsKey(MeshLayer.Collision)) buffer.meshData = meshContent.MeshData[MeshLayer.Collision]; else if (meshContent.MeshData.ContainsKey(MeshLayer.StaticMaterial)) buffer.meshData = meshContent.MeshData[MeshLayer.StaticMaterial]; else { buffer.meshData = null; return; } buffer.transform = Matrix4x4.TRS(pos, meshContent.GetRotation(tile), Vector3.one); buffer.hiddenFaces = CalculateHiddenFaces(tile, meshContent.Rotation); return; } if (layer == MeshLayer.BuildingCollision) { if (tile.buildingType == default(BuildingStruct) || !ContentLoader.Instance.BuildingCollisionMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } if (meshContent.MeshData.ContainsKey(MeshLayer.Collision)) buffer.meshData = meshContent.MeshData[MeshLayer.Collision]; else if (meshContent.MeshData.ContainsKey(MeshLayer.BuildingMaterial)) buffer.meshData = meshContent.MeshData[MeshLayer.BuildingMaterial]; else if (meshContent.MeshData.ContainsKey(MeshLayer.BuildingMaterialCutout)) buffer.meshData = meshContent.MeshData[MeshLayer.BuildingMaterialCutout]; else if (meshContent.MeshData.ContainsKey(MeshLayer.BuildingMaterialTransparent)) buffer.meshData = meshContent.MeshData[MeshLayer.BuildingMaterialTransparent]; else { buffer.meshData = null; return; } buffer.transform = Matrix4x4.TRS(pos, meshContent.GetRotation(tile), Vector3.one); buffer.hiddenFaces = CalculateHiddenFaces(tile, meshContent.Rotation); return; } if (ContentLoader.Instance.DesignationMeshConfiguration.GetValue(tile, layer, out meshContent)) { if (!meshContent.MeshData.ContainsKey(layer)) { buffer.meshData = null; return; } buffer.meshData = meshContent.MeshData[layer]; buffer.transform = Matrix4x4.TRS(pos, meshContent.GetRotation(tile), Vector3.one); if (TextureStorage.UsingArray) { if (meshContent.MaterialTexture != null) index1.x = meshContent.MaterialTexture.ArrayIndex; else index1.x = ContentLoader.Instance.DefaultMatTexArrayIndex; if (meshContent.ShapeTexture != null) index1.y = meshContent.ShapeTexture.ArrayIndex; else index1.y = ContentLoader.Instance.DefaultShapeTexArrayIndex; if (meshContent.SpecialTexture != null) index2.x = meshContent.SpecialTexture.ArrayIndex; else index2.x = ContentLoader.Instance.DefaultSpecialTexArrayIndex; buffer.uv1Transform = Matrix4x4.identity; buffer.uv2Force = index1; buffer.uv3Force = index2; } else { if (meshContent.MaterialTexture != null) buffer.uv1Transform = meshContent.MaterialTexture.UVTransform; else buffer.uv1Transform = ContentLoader.Instance.DefaultMatTexTransform; if (meshContent.ShapeTexture != null) buffer.uv2Transform = meshContent.ShapeTexture.UVTransform; else buffer.uv2Transform = ContentLoader.Instance.DefaultShapeTexTransform; if (meshContent.SpecialTexture != null) buffer.uv3Transform = meshContent.SpecialTexture.UVTransform; else buffer.uv3Transform = ContentLoader.Instance.DefaultSpecialTexTransform; } buffer.hiddenFaces = CalculateHiddenFaces(tile, meshContent.Rotation); return; } switch (layer) { case MeshLayer.GrowthMaterial: case MeshLayer.GrowthMaterial1: case MeshLayer.GrowthMaterial2: case MeshLayer.GrowthMaterial3: case MeshLayer.GrowthCutout: case MeshLayer.GrowthCutout1: case MeshLayer.GrowthCutout2: case MeshLayer.GrowthCutout3: case MeshLayer.GrowthTransparent: case MeshLayer.GrowthTransparent1: case MeshLayer.GrowthTransparent2: case MeshLayer.GrowthTransparent3: { switch (tile.tiletypeMaterial) { case TiletypeMaterial.PLANT: case TiletypeMaterial.ROOT: case TiletypeMaterial.TREE_MATERIAL: case TiletypeMaterial.MUSHROOM: if (!ContentLoader.Instance.GrowthMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } break; default: buffer.meshData = null; return; } } break; case MeshLayer.BuildingMaterial: case MeshLayer.NoMaterialBuilding: case MeshLayer.BuildingMaterialCutout: case MeshLayer.NoMaterialBuildingCutout: case MeshLayer.BuildingMaterialTransparent: case MeshLayer.NoMaterialBuildingTransparent: { if (tile.buildingType == default(BuildingStruct)) { buffer.meshData = null; return; } if (!ContentLoader.Instance.BuildingMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } } break; default: { if (layer == MeshLayer.NaturalTerrain) { if (VoxelGenerator.IsNatural(tile) && !VoxelGenerator.HandleShape(tile) && !VoxelGenerator.UseBoth(tile)) layer = MeshLayer.StaticMaterial; else { buffer.meshData = null; return; } } else if (VoxelGenerator.IsNatural(tile) && !VoxelGenerator.UseBoth(tile)) { buffer.meshData = null; return; } if (!ContentLoader.Instance.TileMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } } break; } if (!meshContent.MeshData.ContainsKey(layer)) { buffer.meshData = null; return; } buffer.meshData = meshContent.MeshData[layer]; buffer.transform = Matrix4x4.TRS(pos, meshContent.GetRotation(tile), Vector3.one); Matrix4x4 matTexTransform = ContentLoader.Instance.DefaultMatTexTransform; Matrix4x4 shapeTextTransform = ContentLoader.Instance.DefaultShapeTexTransform; Matrix4x4 specialTexTransform = Matrix4x4.identity; NormalContent tileTexContent; if (meshContent.ShapeTexture == null) { if (layer == MeshLayer.BuildingMaterial || layer == MeshLayer.BuildingMaterialCutout || layer == MeshLayer.NoMaterialBuilding || layer == MeshLayer.NoMaterialBuildingCutout || layer == MeshLayer.BuildingMaterialTransparent || layer == MeshLayer.NoMaterialBuildingTransparent ) { if (ContentLoader.Instance.BuildingShapeTextureConfiguration.GetValue(tile, layer, out tileTexContent)) { shapeTextTransform = tileTexContent.UVTransform; index1.y = tileTexContent.ArrayIndex; } } else { if (ContentLoader.Instance.ShapeTextureConfiguration.GetValue(tile, layer, out tileTexContent)) { shapeTextTransform = tileTexContent.UVTransform; index1.y = tileTexContent.ArrayIndex; } } } else { shapeTextTransform = meshContent.ShapeTexture.UVTransform; index1.y = meshContent.ShapeTexture.ArrayIndex; } if (meshContent.MaterialTexture != null && (layer == MeshLayer.NoMaterial || layer == MeshLayer.NoMaterialBuilding || layer == MeshLayer.NoMaterialBuildingCutout || layer == MeshLayer.NoMaterialBuildingTransparent || layer == MeshLayer.NoMaterialCutout || layer == MeshLayer.NoMaterialTransparent)) { matTexTransform = meshContent.MaterialTexture.UVTransform; index1.x = meshContent.MaterialTexture.ArrayIndex; } else { TextureContent matTexContent; if (ContentLoader.Instance.MaterialTextureConfiguration.GetValue(tile, layer, out matTexContent)) { matTexTransform = matTexContent.UVTransform; index1.x = matTexContent.ArrayIndex; } } if (meshContent.SpecialTexture != null) { specialTexTransform = meshContent.SpecialTexture.UVTransform; index2.x = meshContent.SpecialTexture.ArrayIndex; } else { specialTexTransform = ContentLoader.Instance.DefaultSpecialTexTransform; index2.x = ContentLoader.Instance.DefaultSpecialTexArrayIndex; } ColorContent newColorContent; Color newColor; if (ContentLoader.Instance.ColorConfiguration.GetValue(tile, layer, out newColorContent)) { newColor = newColorContent.color; } else { MatPairStruct mat = new MatPairStruct(-1, -1); switch (layer) { case MeshLayer.StaticMaterial: case MeshLayer.StaticCutout: case MeshLayer.StaticTransparent: mat = tile.material; break; case MeshLayer.BaseMaterial: case MeshLayer.BaseCutout: case MeshLayer.BaseTransparent: mat = tile.base_material; break; case MeshLayer.LayerMaterial: case MeshLayer.LayerCutout: case MeshLayer.LayerTransparent: mat = tile.layer_material; break; case MeshLayer.VeinMaterial: case MeshLayer.VeinCutout: case MeshLayer.VeinTransparent: mat = tile.vein_material; break; case MeshLayer.NoMaterial: case MeshLayer.NoMaterialCutout: case MeshLayer.NoMaterialBuildingCutout: case MeshLayer.NoMaterialBuilding: case MeshLayer.NoMaterialBuildingTransparent: case MeshLayer.NoMaterialTransparent: break; case MeshLayer.BuildingMaterial: case MeshLayer.BuildingMaterialCutout: case MeshLayer.BuildingMaterialTransparent: mat = tile.buildingMaterial; break; default: break; } MaterialDefinition mattie; if (materials.TryGetValue(mat, out mattie)) { ColorDefinition color = mattie.state_color; if (color == null) newColor = Color.cyan; else newColor = new Color(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, 1); } else { newColor = Color.grey; } } buffer.color = newColor; if (TextureStorage.UsingArray) { buffer.uv1Transform = Matrix4x4.identity; buffer.uv2Force = index1; buffer.uv3Force = index2; } else { buffer.uv1Transform = matTexTransform; buffer.uv2Transform = shapeTextTransform; buffer.uv3Transform = specialTexTransform; } buffer.hiddenFaces = CalculateHiddenFaces(tile, meshContent.Rotation); }
bool GenerateTiles( MapDataStore data, out CPUMesh tiles, out CPUMesh stencilTiles, out CPUMesh transparentTiles, out CPUMesh topTiles, out CPUMesh topStencilTiles, out CPUMesh topTransparentTiles, out CPUMesh collisionTiles, out CPUMesh terrainTiles, out CPUMesh topTerrainTiles) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; int bufferIndex = 0; int stencilBufferIndex = 0; int transparentBufferIndex = 0; int collisionIndex = 0; int terrainIndex = 0; GameMap.BeginSample("Fill Mesh Buffer"); for (int i = 0; i < (int)MeshLayer.Count; i++) { for (int xx = (block_x * GameMap.blockSize); xx < (block_x + 1) * GameMap.blockSize; xx++) { for (int yy = (block_y * GameMap.blockSize); yy < (block_y + 1) * GameMap.blockSize; yy++) { if (!data.InSliceBounds(new DFCoord(xx, yy, block_z))) { throw new UnityException("OOB"); } if (data[xx, yy, block_z] == null) { continue; } if (i < (int)MeshLayer.StaticCutout) { FillMeshBuffer( out meshBuffer[bufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); bufferIndex++; } else if (i < (int)MeshLayer.StaticTransparent) { FillMeshBuffer( out stencilMeshBuffer[stencilBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); stencilBufferIndex++; } else if (i < (int)MeshLayer.Collision) { FillMeshBuffer( out transparentMeshBuffer[transparentBufferIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); transparentBufferIndex++; } else if (i < (int)MeshLayer.NaturalTerrain) { FillMeshBuffer( out collisionMeshBuffer[collisionIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); collisionIndex++; } else if (i == (int)MeshLayer.NaturalTerrain) { FillMeshBuffer(out terrainMeshBuffer[terrainIndex], (MeshLayer)i, data[xx, yy, block_z], GameMap.DFtoUnityCoord(xx - (block_x * GameMap.blockSize), yy - (block_y * GameMap.blockSize), -GameMap.MapZOffset)); terrainIndex++; } } } } GameMap.EndSample(); bool dontCare, success; GameMap.BeginSample("Generate Voxels"); VoxelGenerator voxelGen = new VoxelGenerator(); if (block_z == 0) { voxelGen.bottomless = true; } var naturalTerrain = voxelGen.Triangulate(data); GameMap.EndSample(); GameMap.BeginSample("Combine Meshes"); terrainTiles = MeshCombineUtility.ColorCombine(terrainMeshBuffer, out dontCare, false, naturalTerrain); topTerrainTiles = MeshCombineUtility.ColorCombine(terrainMeshBuffer, out dontCare, true); stencilTiles = MeshCombineUtility.ColorCombine(stencilMeshBuffer, out dontCare, false); topStencilTiles = MeshCombineUtility.ColorCombine(stencilMeshBuffer, out dontCare, true); transparentTiles = MeshCombineUtility.ColorCombine(transparentMeshBuffer, out dontCare, false); topTransparentTiles = MeshCombineUtility.ColorCombine(transparentMeshBuffer, out dontCare, true); topTiles = MeshCombineUtility.ColorCombine(meshBuffer, out dontCare, true); tiles = MeshCombineUtility.ColorCombine(meshBuffer, out success, false); collisionTiles = MeshCombineUtility.ColorCombine(collisionMeshBuffer, out dontCare, false, naturalTerrain); GameMap.EndSample(); return(success); }
bool GenerateTiles(MapDataStore data, out MeshData tiles, out MeshData stencilTiles, TempBuffers temp) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; int bufferIndex = 0; int stencilBufferIndex = 0; for (int xx = (block_x * GameMap.blockSize); xx < (block_x + 1) * GameMap.blockSize; xx++) for (int yy = (block_y * GameMap.blockSize); yy < (block_y + 1) * GameMap.blockSize; yy++) { if (!data.InSliceBounds(new DFCoord(xx, yy, block_z))) throw new UnityException("OOB"); if (data[xx, yy, block_z] == null) continue; for (int i = 0; i < (int)MeshLayer.Count; i++) { MeshLayer layer = (MeshLayer)i; switch (layer) { case MeshLayer.StaticMaterial: case MeshLayer.BaseMaterial: case MeshLayer.LayerMaterial: case MeshLayer.VeinMaterial: case MeshLayer.NoMaterial: FillMeshBuffer(out temp.meshBuffer[bufferIndex], layer, data[xx, yy, block_z].Value); bufferIndex++; break; case MeshLayer.StaticCutout: case MeshLayer.BaseCutout: case MeshLayer.LayerCutout: case MeshLayer.VeinCutout: case MeshLayer.Growth0Cutout: case MeshLayer.Growth1Cutout: case MeshLayer.Growth2Cutout: case MeshLayer.Growth3Cutout: case MeshLayer.NoMaterialCutout: FillMeshBuffer(out temp.stencilMeshBuffer[stencilBufferIndex], layer, data[xx, yy, block_z].Value); stencilBufferIndex++; break; default: break; } } } bool dontCare, success; stencilTiles = MeshCombineUtility.ColorCombine(temp.stencilMeshBuffer, out dontCare); tiles = MeshCombineUtility.ColorCombine(temp.meshBuffer, out success); return success; }
// Called from DFConnection.InitStatics public static void InitMainMap(int xSize, int ySize, int zSize) { MapSize = new DFCoord(xSize, ySize, zSize); _main = new MapDataStore(new DFCoord(0,0,0), MapSize); Debug.Log("Set main map to " + MapSize); }
public Tile(MapDataStore container, DFCoord position) { this.container = container; this.position = position; tileType = default(int); material = default(MatPairStruct); base_material = default(MatPairStruct); layer_material = default(MatPairStruct); vein_material = default(MatPairStruct); construction_item = default(MatPairStruct); waterLevel = default(int); magmaLevel = default(int); rampType = 0; buildingMaterial = default(MatPairStruct); buildingType = default(BuildingStruct); buildingLocalPos = default(DFCoord2d); buildingDirection = 0; hidden = false; }
public Tile(MapDataStore container, DFCoord position) { this.container = container; this.position = position; tileType = default(int); material = default(MatPairStruct); base_material = default(MatPairStruct); layer_material = default(MatPairStruct); vein_material = default(MatPairStruct); construction_item = default(MatPairStruct); waterLevel = default(int); magmaLevel = default(int); rampType = 0; buildingMaterial = default(MatPairStruct); buildingType = default(BuildingStruct); buildingLocalPos = default(DFCoord2d); buildingDirection = 0; Hidden = false; trunkPercent = 0; positionOnTree = default(DFCoord); digDesignation = TileDigDesignation.NO_DIG; spatters = null; }
/// <summary> /// This is the function that actually decides what mesh and texture each tile gets /// </summary> /// <param name="buffer">Buffer to put the chosen meshes into for combining</param> /// <param name="layer">layer currently being worked on</param> /// <param name="tile">The tile to get all the needed info from.</param> void FillMeshBuffer(out MeshCombineUtility.MeshInstance buffer, MeshLayer layer, MapDataStore.Tile tile) { buffer = new MeshCombineUtility.MeshInstance(); MeshContent mesh = null; if (tile.hidden) { buffer.meshData = null; return; } if (layer == MeshLayer.BuildingMaterial || layer == MeshLayer.BuildingMaterialCutout || layer == MeshLayer.NoMaterialBuilding || layer == MeshLayer.NoMaterialBuildingCutout || layer == MeshLayer.BuildingMaterialTransparent || layer == MeshLayer.NoMaterialBuildingTransparent ) { if(tile.buildingType == default(BuildingStruct)) { buffer.meshData = null; return; } if (!contentLoader.BuildingMeshConfiguration.GetValue(tile, layer, out mesh)) { buffer.meshData = null; return; } } else { if (!contentLoader.TileMeshConfiguration.GetValue(tile, layer, out mesh)) { buffer.meshData = null; return; } } buffer.meshData = mesh.MeshData[(int)layer]; buffer.transform = Matrix4x4.TRS(GameMap.DFtoUnityCoord(tile.position), mesh.GetRotation(tile), Vector3.one); Matrix4x4 shapeTextTransform = Matrix4x4.identity; NormalContent tileTexContent; if (mesh.NormalTexture == null) { if (layer == MeshLayer.BuildingMaterial || layer == MeshLayer.BuildingMaterialCutout || layer == MeshLayer.NoMaterialBuilding || layer == MeshLayer.NoMaterialBuildingCutout || layer == MeshLayer.BuildingMaterialTransparent || layer == MeshLayer.NoMaterialBuildingTransparent ) { if (contentLoader.BuildingShapeTextureConfiguration.GetValue(tile, layer, out tileTexContent)) shapeTextTransform = tileTexContent.UVTransform; } else { if (contentLoader.ShapeTextureConfiguration.GetValue(tile, layer, out tileTexContent)) shapeTextTransform = tileTexContent.UVTransform; } } else { shapeTextTransform = mesh.NormalTexture.UVTransform; } Matrix4x4 matTexTransform = Matrix4x4.identity; TextureContent matTexContent; if (contentLoader.MaterialTextureConfiguration.GetValue(tile, layer, out matTexContent)) matTexTransform = matTexContent.UVTransform; ColorContent newColorContent; Color newColor; if (contentLoader.ColorConfiguration.GetValue(tile, layer, out newColorContent)) { newColor = newColorContent.value; } else { MatPairStruct mat = new MatPairStruct(-1, -1); switch (layer) { case MeshLayer.StaticMaterial: case MeshLayer.StaticCutout: case MeshLayer.StaticTransparent: mat = tile.material; break; case MeshLayer.BaseMaterial: case MeshLayer.BaseCutout: case MeshLayer.BaseTransparent: mat = tile.base_material; break; case MeshLayer.LayerMaterial: case MeshLayer.LayerCutout: case MeshLayer.LayerTransparent: mat = tile.layer_material; break; case MeshLayer.VeinMaterial: case MeshLayer.VeinCutout: case MeshLayer.VeinTransparent: mat = tile.vein_material; break; case MeshLayer.NoMaterial: case MeshLayer.NoMaterialCutout: case MeshLayer.NoMaterialBuildingCutout: case MeshLayer.NoMaterialBuilding: case MeshLayer.NoMaterialBuildingTransparent: case MeshLayer.NoMaterialTransparent: break; case MeshLayer.Growth0Cutout: break; case MeshLayer.Growth1Cutout: break; case MeshLayer.Growth2Cutout: break; case MeshLayer.Growth3Cutout: break; case MeshLayer.BuildingMaterial: case MeshLayer.BuildingMaterialCutout: case MeshLayer.BuildingMaterialTransparent: mat = tile.buildingMaterial; break; default: break; } MaterialDefinition mattie; if (materials.TryGetValue(mat, out mattie)) { ColorDefinition color = mattie.state_color; if (color == null) newColor = Color.cyan; else newColor = new Color(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, 1); } else { newColor = Color.grey; } } buffer.color = newColor; buffer.uv1Transform = matTexTransform; buffer.uv2Transform = shapeTextTransform; buffer.hiddenFaces = MeshCombineUtility.HiddenFaces.None; if (tile.North != null && tile.North.isWall) buffer.hiddenFaces |= MeshCombineUtility.HiddenFaces.North; if (tile.South != null && tile.South.isWall) buffer.hiddenFaces |= MeshCombineUtility.HiddenFaces.South; if (tile.East != null && tile.East.isWall) buffer.hiddenFaces |= MeshCombineUtility.HiddenFaces.East; if (tile.West != null && tile.West.isWall) buffer.hiddenFaces |= MeshCombineUtility.HiddenFaces.West; if (tile.Up != null && tile.Up.isSolidBase) buffer.hiddenFaces |= MeshCombineUtility.HiddenFaces.Up; if (tile.Down != null && tile.Down.isWall) buffer.hiddenFaces |= MeshCombineUtility.HiddenFaces.Down; }
public static bool UseBoth(MapDataStore.Tile tile) { if (tile == null) return true; //means it's air/empty switch (tile.shape) { case TiletypeShape.PEBBLES: case TiletypeShape.BOULDER: case TiletypeShape.SAPLING: case TiletypeShape.SHRUB: break; default: return false; } return true; }
/// <summary> /// Performs a single update. /// </summary> /// <exception cref="System.Exception"></exception> void PerformSingleUpdate() { networkClient.suspend_game(); if (mapResetRequested.Pop()) { mapResetCall.execute(); } if (mapInfoCall != null) { RemoteFortressReader.MapInfo mapInfo; mapInfoCall.execute(null, out mapInfo); if (mapInfo == null) { if (netMapInfo != null) { lock (mapInfoLock) { embarkMapPosition = new DFCoord(-1, -1, -1); embarkMapSize = new DFCoord(0, 0, 0); MapDataStore.InitMainMap(embarkMapSize.x * 16, embarkMapSize.y * 16, embarkMapSize.z); } } } else { if ((netMapInfo == null) || mapInfo.block_pos_x != netMapInfo.block_pos_x || mapInfo.block_pos_y != netMapInfo.block_pos_y || mapInfo.block_pos_z != netMapInfo.block_pos_z || mapInfo.block_size_x != netMapInfo.block_size_x || mapInfo.block_size_y != netMapInfo.block_size_y || mapInfo.block_size_z != netMapInfo.block_size_z) { lock (mapInfoLock) { embarkMapPosition = new DFCoord(mapInfo.block_pos_x, mapInfo.block_pos_y, mapInfo.block_pos_z); embarkMapSize = new DFCoord(mapInfo.block_size_x, mapInfo.block_size_y, mapInfo.block_size_z); MapDataStore.InitMainMap(EmbarkMapSize.x * 16, EmbarkMapSize.y * 16, EmbarkMapSize.z); mapResetCall.execute(); } } } netMapInfo = mapInfo; } if (viewInfoCall != null) { RemoteFortressReader.ViewInfo viewInfo; viewInfoCall.execute(null, out viewInfo); netViewInfo.Set(viewInfo); } if (copyScreenCall != null) { RemoteFortressReader.ScreenCapture screenCapture; copyScreenCall.execute(null, out screenCapture); netScreenCapture.Set(screenCapture); } if (unitListCall != null) { RemoteFortressReader.UnitList unitList; unitListCall.execute(null, out unitList); netUnitList.Set(unitList); } if (worldMapCenterCall != null) { RemoteFortressReader.WorldMap tempWorldMap; worldMapCenterCall.execute(null, out tempWorldMap); if (tempWorldMap != null) { DFTime = new DFTime(tempWorldMap.cur_year, tempWorldMap.cur_year_tick); } if (netWorldMapCenter == null || (tempWorldMap != null && (netWorldMapCenter.center_x != tempWorldMap.center_x || netWorldMapCenter.center_y != tempWorldMap.center_y))) { if (worldMapCall != null) { RemoteFortressReader.WorldMap worldMap; worldMapCall.execute(null, out worldMap); netWorldMap.Set(worldMap); } netWorldMapCenter = tempWorldMap; worldMapMoved.Set(); if (regionMapCall != null) { RemoteFortressReader.RegionMaps regionMaps; regionMapCall.execute(null, out regionMaps); netRegionMaps.Set(regionMaps); } nextRegionUpdate = DateTime.Now.AddSeconds(0.2); //add another region map update after this one, to get delayed regions.s } } if (nextRegionUpdate < DateTime.Now) { if (regionMapCall != null) { RemoteFortressReader.RegionMaps regionMaps; regionMapCall.execute(null, out regionMaps); netRegionMaps.Set(regionMaps); } nextRegionUpdate = DateTime.MaxValue; } if (keyboardEventCall != null) { RemoteFortressReader.KeyboardEvent dfEvent; while (keyPresses.TryDequeue(out dfEvent)) { keyboardEventCall.execute(dfEvent); } } // since enqueueing results can block, we do it after we've unsuspended df RemoteFortressReader.BlockList resultList = null; if (EmbarkMapSize.x > 0 && EmbarkMapSize.y > 0 && EmbarkMapSize.z > 0) { BlockCoord.Range?requestRangeUpdate = requestRegion.Pop(); if (requestRangeUpdate != null) { blockRequest.min_x = requestRangeUpdate.Value.Min.x; blockRequest.min_y = requestRangeUpdate.Value.Min.y; blockRequest.min_z = requestRangeUpdate.Value.Min.z; blockRequest.max_x = requestRangeUpdate.Value.Max.x; blockRequest.max_y = requestRangeUpdate.Value.Max.y; blockRequest.max_z = requestRangeUpdate.Value.Max.z; } if (blockListCall != null) { blockListCall.execute(blockRequest, out resultList); } } networkClient.resume_game(); if (resultList != null) { foreach (RemoteFortressReader.MapBlock mapBlock in resultList.map_blocks) { pendingBlocks.Enqueue(mapBlock); } } }
//Dictionary<string, Texture2D> diffuseTextures = new Dictionary<string, Texture2D>(); //Dictionary<string, Texture2D> specularTextures = new Dictionary<string, Texture2D>(); //Dictionary<string, geometry> geometryLibrary = new Dictionary<string, geometry>(); //List<node> nodeList = new List<node>(); //this is very similar to the blockmesher function. void CollectModel(MapDataStore.Tile tile, MeshLayer layer, DFCoord pos) { if (layer == MeshLayer.Collision || layer == MeshLayer.BuildingCollision) return; #region Mesh Selection MeshContent meshContent = null; switch (layer) { case MeshLayer.GrowthMaterial: case MeshLayer.GrowthMaterial1: case MeshLayer.GrowthMaterial2: case MeshLayer.GrowthMaterial3: case MeshLayer.GrowthCutout: case MeshLayer.GrowthCutout1: case MeshLayer.GrowthCutout2: case MeshLayer.GrowthCutout3: case MeshLayer.GrowthTransparent: case MeshLayer.GrowthTransparent1: case MeshLayer.GrowthTransparent2: case MeshLayer.GrowthTransparent3: { switch (tile.tiletypeMaterial) { case TiletypeMaterial.PLANT: case TiletypeMaterial.ROOT: case TiletypeMaterial.TREE_MATERIAL: case TiletypeMaterial.MUSHROOM: if (!ContentLoader.Instance.GrowthMeshConfiguration.GetValue(tile, layer, out meshContent)) return; break; default: return; } } break; case MeshLayer.BuildingMaterial: case MeshLayer.NoMaterialBuilding: case MeshLayer.BuildingMaterialCutout: case MeshLayer.NoMaterialBuildingCutout: case MeshLayer.BuildingMaterialTransparent: case MeshLayer.NoMaterialBuildingTransparent: { if (tile.buildingType == default(BuildingStruct)) return; if (!ContentLoader.Instance.BuildingMeshConfiguration.GetValue(tile, layer, out meshContent)) return; } break; default: { if (!ContentLoader.Instance.TileMeshConfiguration.GetValue(tile, layer, out meshContent)) return; } break; } if (!meshContent.MeshData.ContainsKey(layer)) return; #endregion node tileNode = new node(); tileNode.id = string.Format("Tile[{0},{1},{2}]_{3}", pos.x, pos.y, pos.z, layer); tileNode.Items = new object[] { COLLADA.ConvertMatrix(Matrix4x4.TRS( GameMap.DFtoUnityCoord(pos), meshContent.GetRotation(tile), Vector3.one)) }; tileNode.ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.matrix }; //string geometryName = "Mesh-" + meshContent.UniqueIndex; //if (!geometryLibrary.ContainsKey(geometryName)) //{ // geometryLibrary[geometryName] = COLLADA.MeshToGeometry(meshContent.MeshData[layer], geometryName); //} //instance_geometry geometryInstance = new instance_geometry(); //geometryInstance.url = "#" + geometryLibrary[geometryName].id; //tileNode.instance_geometry = new instance_geometry[] { geometryInstance }; //nodeList.Add(tileNode); //return; //----------------------------------------------------------- //Put normal map stuff here! Remember! //----------------------------------------------------------- //string patternName = "Tex-"; //Texture2D tiletexture = null; //TextureContent textureContent; //if (ContentLoader.Instance.MaterialTextureConfiguration.GetValue(tile, layer, out textureContent)) //{ // tiletexture = textureContent.Texture; // patternName += textureContent.UniqueIndex; //} //else patternName += "#"; //patternName += "-#"; //Color color = Color.grey; //ColorContent colorContent; //if (ContentLoader.Instance.ColorConfiguration.GetValue(tile, layer, out colorContent)) //{ // color = colorContent.color; //} //patternName += string.Format("{0:X2}{1:X2}{2:X2}", ((Color32)color).r, ((Color32)color).g, ((Color32)color).b); //if (diffuseTextures.ContainsKey(patternName)) // return; //Color neutralSpec = new Color(0.04f, 0.04f, 0.04f); //Texture2D outputDiffuse; //Texture2D outputSpec; //if (tiletexture != null) //{ // outputDiffuse = new Texture2D(tiletexture.width, tiletexture.height); // outputSpec = new Texture2D(tiletexture.width, tiletexture.height); // Color[] colors = tiletexture.GetPixels(); // Color[] specs = new Color[colors.Length]; // for (int i = 0; i < colors.Length; i++) // { // var diffuseColor = OverlayBlend(colors[i], color); // diffuseColor.a = 1; // colors[i] = Color.Lerp(Color.black, diffuseColor, color.a); // specs[i] = Color.Lerp(diffuseColor, neutralSpec, color.a); // } // outputDiffuse.SetPixels(colors); // outputSpec.SetPixels(specs); //} //else //{ // outputDiffuse = ContentLoader.CreateFlatTexture(color); // outputSpec = ContentLoader.CreateFlatTexture(neutralSpec); //} //outputDiffuse.name = patternName + "_Diffuse"; //outputSpec.name = patternName + "_Specular"; //diffuseTextures[patternName] = outputDiffuse; //specularTextures[patternName] = outputSpec; }
// Called from DFConnection.InitStatics public static void InitMainMap(int xSize, int ySize, int zSize) { MapSize = new DFCoord(xSize, ySize, zSize); _main = new MapDataStore(new DFCoord(0, 0, 0), MapSize); }
private MeshCombineUtility.HiddenFaces CalculateHiddenFaces(MapDataStore.Tile tile) { MeshCombineUtility.HiddenFaces hiddenFaces = MeshCombineUtility.HiddenFaces.None; if (tile.North != null && (tile.North.isWall || tile.North.hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.North; if (tile.South != null && (tile.South.isWall || tile.South.hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.South; if (tile.East != null && (tile.East.isWall || tile.East.hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.East; if (tile.West != null && (tile.West.isWall || tile.West.hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.West; if (tile.Up != null && (tile.Up.isSolidBase || tile.Up.hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.Up; if (tile.Down != null && (tile.Down.isWall || tile.Down.hidden)) hiddenFaces |= MeshCombineUtility.HiddenFaces.Down; return hiddenFaces; }
// Called from DFConnection.InitStatics public static void InitMainMap(int xSize, int ySize, int zSize) { MapSize = new DFCoord(xSize, ySize, zSize); _main = new MapDataStore(new DFCoord(0,0,0), MapSize); }
/// <summary> /// This is the function that actually decides what mesh and texture each tile gets /// </summary> /// <param name="buffer">Buffer to put the chosen meshes into for combining</param> /// <param name="layer">layer currently being worked on</param> /// <param name="tile">The tile to get all the needed info from.</param> void FillMeshBuffer(out MeshCombineUtility.MeshInstance buffer, MeshLayer layer, MapDataStore.Tile tile, Vector3 pos) { buffer = new MeshCombineUtility.MeshInstance(); MeshContent meshContent = null; if(contentLoader.DesignationMeshConfiguration.GetValue(tile, layer, out meshContent)) { if(!meshContent.MeshData.ContainsKey(layer)) { buffer.meshData = null; return; } buffer.meshData = meshContent.MeshData[layer]; buffer.transform = Matrix4x4.TRS(pos, meshContent.GetRotation(tile), Vector3.one); if (meshContent.MaterialTexture != null) buffer.uv1Transform = meshContent.MaterialTexture.UVTransform; else buffer.uv1Transform = contentLoader.DefaultMatTexTransform; if (meshContent.ShapeTexture != null) buffer.uv2Transform = meshContent.ShapeTexture.UVTransform; else buffer.uv2Transform = contentLoader.DefaultShapeTexTransform; if (meshContent.SpecialTexture != null) buffer.uv3Transform = meshContent.SpecialTexture.UVTransform; else buffer.uv3Transform = contentLoader.DefaultSpecialTexTransform; buffer.hiddenFaces = CalculateHiddenFaces(tile); return; } switch (layer) { case MeshLayer.GrowthMaterial: case MeshLayer.GrowthMaterial1: case MeshLayer.GrowthMaterial2: case MeshLayer.GrowthMaterial3: case MeshLayer.GrowthCutout: case MeshLayer.GrowthCutout1: case MeshLayer.GrowthCutout2: case MeshLayer.GrowthCutout3: case MeshLayer.GrowthTransparent: case MeshLayer.GrowthTransparent1: case MeshLayer.GrowthTransparent2: case MeshLayer.GrowthTransparent3: { switch (tile.tiletypeMaterial) { case TiletypeMaterial.PLANT: case TiletypeMaterial.ROOT: case TiletypeMaterial.TREE_MATERIAL: case TiletypeMaterial.MUSHROOM: if (!contentLoader.GrowthMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } break; default: buffer.meshData = null; return; } } break; case MeshLayer.BuildingMaterial: case MeshLayer.NoMaterialBuilding: case MeshLayer.BuildingMaterialCutout: case MeshLayer.NoMaterialBuildingCutout: case MeshLayer.BuildingMaterialTransparent: case MeshLayer.NoMaterialBuildingTransparent: { if (tile.buildingType == default(BuildingStruct)) { buffer.meshData = null; return; } if (!contentLoader.BuildingMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } } break; default: { if (!contentLoader.TileMeshConfiguration.GetValue(tile, layer, out meshContent)) { buffer.meshData = null; return; } } break; } if (!meshContent.MeshData.ContainsKey(layer)) { buffer.meshData = null; return; } buffer.meshData = meshContent.MeshData[layer]; buffer.transform = Matrix4x4.TRS(pos, meshContent.GetRotation(tile), Vector3.one); Matrix4x4 shapeTextTransform = contentLoader.DefaultShapeTexTransform; NormalContent tileTexContent; if (meshContent.ShapeTexture == null) { if (layer == MeshLayer.BuildingMaterial || layer == MeshLayer.BuildingMaterialCutout || layer == MeshLayer.NoMaterialBuilding || layer == MeshLayer.NoMaterialBuildingCutout || layer == MeshLayer.BuildingMaterialTransparent || layer == MeshLayer.NoMaterialBuildingTransparent ) { if (contentLoader.BuildingShapeTextureConfiguration.GetValue(tile, layer, out tileTexContent)) shapeTextTransform = tileTexContent.UVTransform; } else { if (contentLoader.ShapeTextureConfiguration.GetValue(tile, layer, out tileTexContent)) shapeTextTransform = tileTexContent.UVTransform; } } else { shapeTextTransform = meshContent.ShapeTexture.UVTransform; } Matrix4x4 matTexTransform = contentLoader.DefaultMatTexTransform; if (meshContent.MaterialTexture != null && (layer == MeshLayer.NoMaterial || layer == MeshLayer.NoMaterialBuilding || layer == MeshLayer.NoMaterialBuildingCutout || layer == MeshLayer.NoMaterialBuildingTransparent || layer == MeshLayer.NoMaterialCutout || layer == MeshLayer.NoMaterialTransparent)) { matTexTransform = meshContent.MaterialTexture.UVTransform; } else { TextureContent matTexContent; if (contentLoader.MaterialTextureConfiguration.GetValue(tile, layer, out matTexContent)) matTexTransform = matTexContent.UVTransform; } Matrix4x4 specialTexTransform = Matrix4x4.identity; if(meshContent.SpecialTexture != null) { specialTexTransform = meshContent.SpecialTexture.UVTransform; } else { specialTexTransform = contentLoader.DefaultSpecialTexTransform; } ColorContent newColorContent; Color newColor; if (contentLoader.ColorConfiguration.GetValue(tile, layer, out newColorContent)) { newColor = newColorContent.value; } else { MatPairStruct mat = new MatPairStruct(-1, -1); switch (layer) { case MeshLayer.StaticMaterial: case MeshLayer.StaticCutout: case MeshLayer.StaticTransparent: mat = tile.material; break; case MeshLayer.BaseMaterial: case MeshLayer.BaseCutout: case MeshLayer.BaseTransparent: mat = tile.base_material; break; case MeshLayer.LayerMaterial: case MeshLayer.LayerCutout: case MeshLayer.LayerTransparent: mat = tile.layer_material; break; case MeshLayer.VeinMaterial: case MeshLayer.VeinCutout: case MeshLayer.VeinTransparent: mat = tile.vein_material; break; case MeshLayer.NoMaterial: case MeshLayer.NoMaterialCutout: case MeshLayer.NoMaterialBuildingCutout: case MeshLayer.NoMaterialBuilding: case MeshLayer.NoMaterialBuildingTransparent: case MeshLayer.NoMaterialTransparent: break; case MeshLayer.BuildingMaterial: case MeshLayer.BuildingMaterialCutout: case MeshLayer.BuildingMaterialTransparent: mat = tile.buildingMaterial; break; default: break; } MaterialDefinition mattie; if (materials.TryGetValue(mat, out mattie)) { ColorDefinition color = mattie.state_color; if (color == null) newColor = Color.cyan; else newColor = new Color(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f, 1); } else { newColor = Color.grey; } } buffer.color = newColor; buffer.uv1Transform = matTexTransform; buffer.uv2Transform = shapeTextTransform; buffer.uv3Transform = specialTexTransform; buffer.hiddenFaces = CalculateHiddenFaces(tile); }
public void CopySliceTo(DFCoord newSliceOrigin, DFCoord newSliceSize, MapDataStore target) { if (newSliceSize != target.SliceSize) { throw new UnityException("Mismatched slice sizes"); } var localNewSliceOrigin = WorldToLocalSpace(newSliceOrigin); if (!InSliceBoundsLocal(localNewSliceOrigin) || !InSliceBoundsLocal(localNewSliceOrigin + newSliceSize - new DFCoord(1,1,1))) { throw new UnityException("Can't slice outside of our slice bounds"); } for (int x = 0; x < newSliceSize.x; x++) { for (int y = 0; y < newSliceSize.y; y++) { for (int z = 0; z < newSliceSize.z; z++) { //pre-calculate it before we copy, because afterwards we won't have contextual data. if (tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].shape == TiletypeShape.RAMP) tiles[localNewSliceOrigin.x + x, localNewSliceOrigin.y + y, localNewSliceOrigin.z + z].CalculateRampType(); target.tiles[x, y, z] = tiles[localNewSliceOrigin.x+x, localNewSliceOrigin.y+y, localNewSliceOrigin.z+z]; target.tiles[x, y, z].container = target; target.tilesPresent[target.PresentIndex(x, y, z)] = tilesPresent[PresentIndex(localNewSliceOrigin.x+x, localNewSliceOrigin.y+y, localNewSliceOrigin.z+z)]; } } } target.SliceOrigin = newSliceOrigin; }
CPUMesh GenerateLiquidSurface(MapDataStore data, int liquid_select, TempBuffers temp) { int block_x = data.SliceOrigin.x / GameMap.blockSize; int block_y = data.SliceOrigin.y / GameMap.blockSize; int block_z = data.SliceOrigin.z; Vector3[] finalVertices = new Vector3[(GameMap.blockSize + 1) * (GameMap.blockSize + 1)]; Vector3[] finalNormals = new Vector3[(GameMap.blockSize + 1) * (GameMap.blockSize + 1)]; Vector2[] finalUVs = new Vector2[(GameMap.blockSize + 1) * (GameMap.blockSize + 1)]; List<int> finalFaces = new List<int>(); // Is this necessary? temp.heights[0,0] = 0; temp.heights[0,1] = 0; temp.heights[1,0] = 0; temp.heights[1,1] = 0; for (int xx = 0; xx <= GameMap.blockSize; xx++) for (int yy = 0; yy <= GameMap.blockSize; yy++) { //first find the temp.heights of all tiles sharing one corner. for (int xxx = 0; xxx < 2; xxx++) for (int yyy = 0; yyy < 2; yyy++) { int x = (block_x * GameMap.blockSize) + xx + xxx - 1; int y = (block_y * GameMap.blockSize) + yy + yyy - 1; if (x < 0 || y < 0 || x >= MapDataStore.MapSize.x || y >= MapDataStore.MapSize.y) { temp.heights[xxx, yyy] = -1; continue; } var maybeTile = data[x, y, block_z]; if (maybeTile == null) { temp.heights[xxx, yyy] = -1; continue; } var tile = maybeTile; if (tile.isWall) { temp.heights[xxx, yyy] = -1; continue; } temp.heights[xxx, yyy] = data.GetLiquidLevel(new DFCoord(x,y,block_z), liquid_select); temp.heights[xxx, yyy] /= 7.0f; if (tile.isFloor) { temp.heights[xxx, yyy] *= (GameMap.tileHeight - GameMap.floorHeight); temp.heights[xxx, yyy] += GameMap.floorHeight; } else temp.heights[xxx, yyy] *= GameMap.tileHeight; } //now find their average, discaring invalid ones. float height = 0; float total = 0; foreach (var item in temp.heights) { if (item < 0) continue; height += item; total++; } if (total >= 1) height /= total; //find the slopes. float sx = (( (temp.heights[0, 0] < 0 ? height : temp.heights[0, 0]) + (temp.heights[0, 1] < 0 ? height : temp.heights[0, 1])) / 2) - (( (temp.heights[1, 0] < 0 ? height : temp.heights[1, 0]) + (temp.heights[1, 1] < 0 ? height : temp.heights[1, 1])) / 2); float sy = (( (temp.heights[0, 0] < 0 ? height : temp.heights[0, 0]) + (temp.heights[1, 0] < 0 ? height : temp.heights[1, 0])) / 2) - (( (temp.heights[0, 1] < 0 ? height : temp.heights[0, 1]) + (temp.heights[1, 1] < 0 ? height : temp.heights[1, 1])) / 2); finalNormals[coord2Index(xx, yy)] = new Vector3(sx, GameMap.tileWidth * 2, -sy); finalNormals[coord2Index(xx, yy)].Normalize(); finalVertices[coord2Index(xx, yy)] = GameMap.DFtoUnityCoord(xx, yy, -GameMap.MapZOffset); finalVertices[coord2Index(xx, yy)].x -= GameMap.tileWidth / 2.0f; finalVertices[coord2Index(xx, yy)].z += GameMap.tileWidth / 2.0f; finalVertices[coord2Index(xx, yy)].y += height; finalUVs[coord2Index(xx, yy)] = new Vector2(xx, yy); } for (int xx = 0; xx < GameMap.blockSize; xx++) for (int yy = 0; yy < GameMap.blockSize; yy++) { if (data.GetLiquidLevel( new DFCoord((block_x * GameMap.blockSize) + xx, (block_y * GameMap.blockSize) + yy, block_z), liquid_select) == 0) { continue; } finalFaces.Add(coord2Index(xx, yy)); finalFaces.Add(coord2Index(xx + 1, yy)); finalFaces.Add(coord2Index(xx + 1, yy + 1)); finalFaces.Add(coord2Index(xx, yy)); finalFaces.Add(coord2Index(xx + 1, yy + 1)); finalFaces.Add(coord2Index(xx, yy + 1)); } if (finalFaces.Count > 0) { return new CPUMesh(vertices: finalVertices, normals: finalNormals, tangents: null, uv: finalUVs, uv2: null, uv3: null, colors: null, triangles: finalFaces.ToArray()); } else { return null; } }
private void TriangulateCellRows(MapDataStore map) { for (int y = map.MinCoord.y; y < map.MaxCoord.y - 1; y++) { for (int x = map.MinCoord.x; x < map.MaxCoord.x - 1; x++) { int z = map.SliceOrigin.z; Directions edges = Directions.None; if (x == map.MinCoord.x) edges |= Directions.West; if (x == map.MaxCoord.x - 2) edges |= Directions.East; if (y == map.MinCoord.y) edges |= Directions.North; if (y == map.MaxCoord.y - 2) edges |= Directions.South; TriangulateCell( map[x, y, z], map[x + 1, y, z], map[x, y + 1, z], map[x + 1, y + 1, z], GameMap.DFtoUnityCoord(map.WorldToLocalSpace(new DFCoord(x - 1, y - 1, z))) + new Vector3(GameMap.tileWidth / 2, 0, 0), GameMap.DFtoUnityCoord(map.WorldToLocalSpace(new DFCoord(x, y - 1, z))) + new Vector3(0, 0, -GameMap.tileWidth / 2), GameMap.DFtoUnityCoord(map.WorldToLocalSpace(new DFCoord(x - 1, y, z))) + new Vector3(GameMap.tileWidth / 2, 0, 0), GameMap.DFtoUnityCoord(map.WorldToLocalSpace(new DFCoord(x - 1, y - 1, z))) + new Vector3(0, 0, -GameMap.tileWidth / 2), GameMap.DFtoUnityCoord(map.WorldToLocalSpace(new DFCoord(x - 1, y - 1, z))) + new Vector3(GameMap.tileWidth / 2, 0, -GameMap.tileWidth / 2), edges); } } }