public WorldEditor(SegmentManager parent)
        {
            ParentSegmentManager = parent;

            _blockMasks = new List <BlockMask>();
            _blockMasks.Add(BlockHelper.BlockMasks.Debug);
            _blockMasks.Add(BlockHelper.BlockMasks.Soil);

            _topRampMasks = new List <BlockMask>();
            _topRampMasks.Add(BlockHelper.RampBlockMasks.Top.Debug);
            _topRampMasks.Add(BlockHelper.RampBlockMasks.Top.Soil);

            _bottomRampMasks = new List <BlockMask>();
            _bottomRampMasks.Add(BlockHelper.RampBlockMasks.Bottom.Debug);
            _bottomRampMasks.Add(BlockHelper.RampBlockMasks.Bottom.Soil);

            _index = 0;

            _selectedType = EditorType.Blocks;

            _keyboardCursor = new SegmentLocation(Vector3.Zero);

            _RampBlockDirection = RampBlockDirection.North;

            _activeBlockMask = BlockHelper.BlockMasks.Soil;

            _previewData = new BlockVertexData();
        }
        public void AddBlock(Vector3Int pos, Vector3Int renderOffset, BlockData block, IWorldRAccessor accessor)
        {
            Quaternion rotation = accessor.GetBlockRotation(pos.x, pos.y, pos.z, Quaternion.identity);
            BlockMesh  mesh     = accessor.World.BlockDataTable.GetMesh(block.Mesh.Value);

            for (int i = 0; i < mesh.Faces.Length; i++)
            {
                BlockMesh.FaceData face    = mesh.Faces[i];
                BlockFace          faceDir = RotateFace(face.Face, rotation);

                if (EnableFaceClipping)
                {
                    // 没有撑满一格的方块所有的面都渲染
                    Vector3 size      = mesh.BoundingBox.Size;
                    bool    neverClip = face.NeverClip | size.x < 1 | size.y < 1 | size.z < 1;

                    if (!neverClip && ClipFace(pos, block, faceDir, accessor))
                    {
                        continue;
                    }
                }

                int?[] texIndices = block.Textures[i];

                // !!! must add indices first
                for (int j = 0; j < face.Indices.Length; j++)
                {
                    AddIndex(face.Indices[j], block.Material.Value);
                }

                for (int j = 0; j < face.Vertices.Length; j++)
                {
                    BlockVertexData vertex = face.Vertices[j];
                    vertex.Position = MathUtility.RotatePoint(vertex.Position, rotation, mesh.Pivot);

                    float   emission = block.GetEmissionValue();
                    Vector2 ambient  = LightingUtility.AmbientOcclusion(pos, faceDir, vertex.CornerInFace, accessor, !EnableAmbientOcclusion);

                    Vector3 posWS = WriteBlockWSPosToVertexData ? (pos + accessor.WorldSpaceOrigin) : Vector3.down;

                    AddVertex(new BlockMeshVertexData
                    {
                        PositionOS      = vertex.Position + pos + renderOffset,
                        UV              = vertex.UV,
                        TexIndices      = new Vector3Int(texIndices[0].Value, texIndices[1].Value, texIndices[2].Value),
                        Lights          = new Vector3(emission, ambient.x, ambient.y),
                        BlockPositionWS = posWS
                    });
                }
            }
        }
        public void Update()
        {
            bool changed = false;

            // SHIFT
            if (InputHelper.IsKeyDown(Keys.LeftShift) || InputHelper.IsKeyDown(Keys.RightShift))
            {
                if (InputHelper.IsNewKeyPress(Keys.Right))
                {
                    if (_RampBlockDirection == RampBlockDirection.North)
                    {
                        _RampBlockDirection = RampBlockDirection.East;
                    }
                    else if (_RampBlockDirection == RampBlockDirection.East)
                    {
                        _RampBlockDirection = RampBlockDirection.South;
                    }
                    else if (_RampBlockDirection == RampBlockDirection.South)
                    {
                        _RampBlockDirection = RampBlockDirection.West;
                    }
                    else if (_RampBlockDirection == RampBlockDirection.West)
                    {
                        _RampBlockDirection = RampBlockDirection.North;
                    }

                    changed = true;
                }

                if (InputHelper.IsNewKeyPress(Keys.Left))
                {
                    if (_RampBlockDirection == RampBlockDirection.North)
                    {
                        _RampBlockDirection = RampBlockDirection.West;
                    }
                    else if (_RampBlockDirection == RampBlockDirection.East)
                    {
                        _RampBlockDirection = RampBlockDirection.North;
                    }
                    else if (_RampBlockDirection == RampBlockDirection.South)
                    {
                        _RampBlockDirection = RampBlockDirection.East;
                    }
                    else if (_RampBlockDirection == RampBlockDirection.West)
                    {
                        _RampBlockDirection = RampBlockDirection.South;
                    }
                    changed = true;
                }
            }
            else
            {
                if (InputHelper.IsNewKeyPress(Keys.Up))
                {
                    switch (_selectedType)
                    {
                    case EditorType.Blocks:
                        _selectedType = EditorType.BottomRamps;
                        break;

                    case EditorType.BottomRamps:
                        _selectedType = EditorType.TopRamps;
                        break;

                    case EditorType.TopRamps:
                        _selectedType = EditorType.Blocks;
                        break;

                    default:
                        _previewData = new BlockVertexData();
                        break;
                    }
                    changed = true;
                }

                if (InputHelper.IsNewKeyPress(Keys.Down))
                {
                    switch (_selectedType)
                    {
                    case EditorType.Blocks:
                        _selectedType = EditorType.TopRamps;
                        break;

                    case EditorType.BottomRamps:
                        _selectedType = EditorType.Blocks;
                        break;

                    case EditorType.TopRamps:
                        _selectedType = EditorType.BottomRamps;
                        break;

                    default:
                        _previewData = new BlockVertexData();
                        break;
                    }
                    changed = true;
                }

                if (InputHelper.IsNewKeyPress(Keys.Right))
                {
                    _index++;

                    if (_index >= CountCurrentList())
                    {
                        _index = 0;
                    }
                    changed = true;
                }

                if (InputHelper.IsNewKeyPress(Keys.Left))
                {
                    _index--;

                    if (_index < 0)
                    {
                        _index = CountCurrentList() - 1;
                    }
                    changed = true;
                }
            }

            if (changed)
            {
                switch (_selectedType)
                {
                case EditorType.Blocks:
                    _activeBlockMask = _blockMasks[_index];
                    _previewData     = BlockVertexData.GetBlockMaskVertexData(_blockMasks[_index]).Copy();
                    break;

                case EditorType.BottomRamps:
                    _activeBlockMask = _bottomRampMasks[_index] | _RampBlockDirection;
                    _previewData     = RampBlockVertexData.GetBlockMaskVertexData(_bottomRampMasks[_index] | _RampBlockDirection).Copy();
                    break;

                case EditorType.TopRamps:
                    _activeBlockMask = _topRampMasks[_index] | _RampBlockDirection;
                    _previewData     = RampBlockVertexData.GetBlockMaskVertexData(_topRampMasks[_index] | _RampBlockDirection).Copy();
                    break;

                default:
                    _previewData = new BlockVertexData();
                    break;
                }
            }

            HandleHighlight();
        }
        public void DrawModels(Camera3D camera)
        {
            BlockMask maskAtCursor = ParentSegmentManager.GetBlockMaskAt(_keyboardCursor);

            switch (_selectedType)
            {
            case EditorType.Blocks:
                if (ParentSegmentManager.IsLocationObstructed(_keyboardCursor))
                {
                    _blockHighlightBlocked.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                }
                else
                {
                    _blockHighlight.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                }
                break;

            case EditorType.BottomRamps:
                if (BlockHelper.HasTopRamp(maskAtCursor) &&
                    BlockHelper.GetRampBlockDirection(maskAtCursor) ==
                    _RampBlockDirection)
                {
                    _blockHighlight.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                }
                else
                {
                    if (ParentSegmentManager.IsLocationObstructed(_keyboardCursor))
                    {
                        _blockHighlightBlocked.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                    }
                    else
                    {
                        _blockHighlight.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                    }
                }
                break;

            case EditorType.TopRamps:
                if (BlockHelper.HasBottomRamp(maskAtCursor) &&
                    BlockHelper.GetRampBlockDirection(maskAtCursor) ==
                    _RampBlockDirection)
                {
                    _blockHighlight.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                }
                else
                {
                    if (ParentSegmentManager.IsLocationObstructed(_keyboardCursor))
                    {
                        _blockHighlightBlocked.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                    }
                    else
                    {
                        _blockHighlight.Draw(ParentSegmentManager.Device, camera, _keyboardCursor.WorldLocation, Vector3.Zero, 0f, new Vector3(1, 1, 1));
                    }
                }
                break;

            default:
                _previewData = new BlockVertexData();
                break;
            }
        }
        public void HandleHighlight()
        {
            Vector3 newPosition = _keyboardCursor.WorldLocation;

            if (InputHelper.IsNewKeyPress(Keys.NumPad3))
            {
                newPosition += WorldDirection.East;
            }
            if (InputHelper.IsNewKeyPress(Keys.NumPad1))
            {
                newPosition += WorldDirection.North;
            }
            if (InputHelper.IsNewKeyPress(Keys.NumPad7))
            {
                newPosition += WorldDirection.West;
            }
            if (InputHelper.IsNewKeyPress(Keys.NumPad9))
            {
                newPosition += WorldDirection.South;
            }
            if (InputHelper.IsNewKeyPress(Keys.Add))
            {
                newPosition += WorldDirection.Up;
            }
            if (InputHelper.IsNewKeyPress(Keys.Subtract))
            {
                newPosition += WorldDirection.Down;
            }

            // Following is for valid block ranges only.
            if (ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(newPosition)) != BlockHelper.BlockMasks.Null)
            {
                if (newPosition != _keyboardCursor.WorldLocation)
                {
                    // check for an object?
                    int segmentX = (int)Math.Floor((double)newPosition.X / WorldGlobal.SegmentSize.X);
                    int segmentZ = (int)Math.Floor((double)newPosition.Z / WorldGlobal.SegmentSize.Z);

                    //_ItemsUnderCursor = ParentSegmentManager.Segments[segmentX, segmentZ].Items.FindItemsAt(newPosition);
                }

                _keyboardCursor = new SegmentLocation(newPosition);
                if (InputHelper.IsNewKeyPress(Keys.Delete))
                {
                    ParentSegmentManager.SetBlockMaskAt(_keyboardCursor, BlockHelper.BlockMasks.Air);
                }

                if (InputHelper.IsNewKeyPress(Keys.Insert))
                {
                    BlockMask maskAtCursor = ParentSegmentManager.GetBlockMaskAt(_keyboardCursor);
                    switch (_selectedType)
                    {
                    case EditorType.Blocks:
                        ParentSegmentManager.SetBlockMaskAt(_keyboardCursor, _activeBlockMask);
                        break;

                    case EditorType.BottomRamps:
                        if (BlockHelper.HasTopRamp(maskAtCursor) &&
                            BlockHelper.GetRampBlockDirection(maskAtCursor) ==
                            _RampBlockDirection)
                        {
                            ParentSegmentManager.SetBlockMaskAt(_keyboardCursor, maskAtCursor | _activeBlockMask);
                        }
                        else
                        {
                            ParentSegmentManager.SetBlockMaskAt(_keyboardCursor, _activeBlockMask);
                        }
                        break;

                    case EditorType.TopRamps:
                        if (BlockHelper.HasBottomRamp(maskAtCursor) &&
                            BlockHelper.GetRampBlockDirection(maskAtCursor) ==
                            _RampBlockDirection)
                        {
                            ParentSegmentManager.SetBlockMaskAt(_keyboardCursor, maskAtCursor | _activeBlockMask);
                        }
                        else
                        {
                            ParentSegmentManager.SetBlockMaskAt(_keyboardCursor, _activeBlockMask);
                        }
                        break;

                    default:
                        _previewData = new BlockVertexData();
                        break;
                    }
                }
            }
            else
            {
                DebugLog.Log("Can't move World Cursor to (" + newPosition.X + ", " + newPosition.Y + ", " + newPosition.Z + ") - Out of bounds", DebugMessageType.Warning);
            }
        }
        public void UpdateDrawModule()
        {
            DebugLog.Log("Updating RenderChunk: (" + ParentRenderSegment.Position.X + ", " + _heightOffset + ", " + ParentRenderSegment.Position.Y + ");");
            for (int x = 0; x < Blocks.GetLength(0); x++)
            {
                for (int y = 0; y < Blocks.GetLength(1); y++)
                {
                    for (int z = 0; z < Blocks.GetLength(2); z++)
                    {
                        if (Blocks[x, y, z] != BlockHelper.BlockMasks.Air && Blocks[x, y, z] != BlockHelper.BlockMasks.AirBlocked)
                        {
                            BlockVertexData currentVertextData = new BlockVertexData();
                            Vector3         blockLocation      = new Vector3(x, y, z) + _locationOffset;
                            if (BlockHelper.IsBlock(Blocks[x, y, z]))
                            {
                                currentVertextData = BlockVertexData.GetCopyOfBlockMasBlockVertexData(Blocks[x, y, z]);
                            }
                            else if (BlockHelper.IsRampBlock(Blocks[x, y, z]))
                            {
                                currentVertextData = RampBlockVertexData.GetBlockMaskVertexData(Blocks[x, y, z]);
                            }

                            currentVertextData.TranslateToWorldLocation(blockLocation);

                            // Following checks all the face blocking cubes around the current location to see if we'll add the vertices to the buffer or not.
                            if (!BlockHelper.DoesBlockMaskAObscureMaskBFace(ParentRenderSegment.ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(blockLocation + WorldDirection.Up)), Blocks[x, y, z], WorldDirection.Up))
                            {
                                _blockDrawModule.AddData(currentVertextData.UpVertices.ToList(),
                                                         currentVertextData.UpIndices.ToList());
                            }
                            if (!BlockHelper.DoesBlockMaskAObscureMaskBFace(ParentRenderSegment.ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(blockLocation + WorldDirection.Down)), Blocks[x, y, z], WorldDirection.Down))
                            {
                                _blockDrawModule.AddData(currentVertextData.DownVertices.ToList(),
                                                         currentVertextData.DownIndices.ToList());
                            }
                            if (!BlockHelper.DoesBlockMaskAObscureMaskBFace(ParentRenderSegment.ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(blockLocation + WorldDirection.North)), Blocks[x, y, z], WorldDirection.North))
                            {
                                _blockDrawModule.AddData(currentVertextData.NorthVertices.ToList(),
                                                         currentVertextData.NorthIndices.ToList());
                            }
                            if (!BlockHelper.DoesBlockMaskAObscureMaskBFace(ParentRenderSegment.ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(blockLocation + WorldDirection.East)), Blocks[x, y, z], WorldDirection.East))
                            {
                                // add east vertices/indices, but don't forget to translate to world location...
                                _blockDrawModule.AddData(currentVertextData.EastVertices.ToList(),
                                                         currentVertextData.EastIndices.ToList());
                            }
                            if (!BlockHelper.DoesBlockMaskAObscureMaskBFace(ParentRenderSegment.ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(blockLocation + WorldDirection.South)), Blocks[x, y, z], WorldDirection.South))
                            {
                                // add east vertices/indices, but don't forget to translate to world location...
                                _blockDrawModule.AddData(currentVertextData.SouthVertices.ToList(),
                                                         currentVertextData.SouthIndices.ToList());
                            }
                            if (!BlockHelper.DoesBlockMaskAObscureMaskBFace(ParentRenderSegment.ParentSegmentManager.GetBlockMaskAt(new SegmentLocation(blockLocation + WorldDirection.West)), Blocks[x, y, z], WorldDirection.West))
                            {
                                // add east vertices/indices, but don't forget to translate to world location...
                                _blockDrawModule.AddData(currentVertextData.WestVertices.ToList(),
                                                         currentVertextData.WestIndices.ToList());
                            }
                        }
                    }
                }
            }
            _blockDrawModule.PrepareToDraw();

            Dirty = false;
        }