void Update() { if (!m_isInitialized) { Init(); return; } #region Draw Collisions // Generate texture again in case window has been resized Vector2 screenSize = new Vector2(Screen.width, Screen.height); if (m_prevScreenSize != screenSize) { _GenerateCollisionTexture(); } m_prevScreenSize = screenSize; m_spriteCollLayer.SetActive(m_showCollisions); if (m_showCollisions && (int)(Time.timeSinceLevelLoad * 4) % 2 == 0) { SpriteRenderer sprRender = m_spriteCollLayer.GetComponent <SpriteRenderer>(); Vector3 vPos = m_camera2D.transform.position; vPos.x -= (vPos.x % (m_autoTileMap.Tileset.TileWorldWidth / 4)); vPos.y -= (vPos.y % (m_autoTileMap.Tileset.TileWorldHeight / 4)); vPos.z += 1f; // Collision texture position snap to a quarter of tile part sprRender.transform.position = vPos; // Collision texture pixel scaled to a quarter of tile part sprRender.transform.localScale = new Vector3((m_autoTileMap.Tileset.TilePartWidth / 2), (m_autoTileMap.Tileset.TilePartHeight / 2), 1f); vPos = m_camera2D.Camera.WorldToScreenPoint(sprRender.transform.position); // vPos = center of collision texture in screen coords Vector3 vTopLeftOff = new Vector3(sprRender.sprite.texture.width * (m_autoTileMap.Tileset.TilePartWidth / 2) / 2, -sprRender.sprite.texture.height * (m_autoTileMap.Tileset.TilePartHeight / 2) / 2) * m_camera2D.Zoom; vPos -= vTopLeftOff; vPos = m_camera2D.Camera.ScreenToWorldPoint(vPos); // vPos is now the top left corner of the collison texture in world coordinates Color32[] colors = sprRender.sprite.texture.GetPixels32(); float factorX = m_autoTileMap.Tileset.TileWorldWidth / 4; //smallest collision part has a size of a quarter of tile part float factorY = m_autoTileMap.Tileset.TileWorldHeight / 4; for (int y = 0; y < sprRender.sprite.texture.height; ++y) { for (int x = 0; x < sprRender.sprite.texture.width; ++x) { Vector3 vCheckPos = vPos; vCheckPos.x += (x + 0.5f) * factorX; vCheckPos.y -= (y + 0.5f) * factorY; AutoTileMap.eTileCollisionType collType = m_autoTileMap.GetAutotileCollisionAtPosition(vCheckPos); //Color32 color = (x+y)%2 == 0? new Color32(0, 0, 64, 128) : new Color32(64, 0, 0, 128) ; Color32 color = new Color32(0, 0, 0, 0); colors[(sprRender.sprite.texture.height - 1 - y) * sprRender.sprite.texture.width + x] = (collType != AutoTileMap.eTileCollisionType.PASSABLE)? new Color32(255, 0, 0, 128) : color; } } sprRender.sprite.texture.SetPixels32(colors); sprRender.sprite.texture.Apply(); } #endregion if (Input.GetKeyDown(KeyCode.Delete)) //TODO: only delete the tiles in ground layer, fix this { // select delete tile m_selectedTileIdx = -1; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; } #region Undo / Redo if (m_isCtrlKeyHold) { if (Input.GetKeyDown(KeyCode.Z)) { m_autoTileMap.BrushGizmo.UndoAction(); } else if (Input.GetKeyDown(KeyCode.Y)) { m_autoTileMap.BrushGizmo.RedoAction(); } //+++ Key Repetition Implementation if (Input.GetKey(KeyCode.Z)) { m_keyPressTimer += Time.deltaTime; if (m_keyPressTimer >= k_timeBeforeKeyRepeat) { m_keyPressTimer -= k_timeBetweenKeyRepeat; m_autoTileMap.BrushGizmo.UndoAction(); } } else if (Input.GetKey(KeyCode.Y)) { m_keyPressTimer += Time.deltaTime; if (m_keyPressTimer >= k_timeBeforeKeyRepeat) { m_keyPressTimer -= k_timeBetweenKeyRepeat; m_autoTileMap.BrushGizmo.RedoAction(); } } else { m_keyPressTimer = 0f; } //--- } #endregion if (Input.GetKeyDown(KeyCode.M)) { m_showMinimap = !m_showMinimap; } if (Input.GetKeyDown(KeyCode.C)) { m_showCollisions = !m_showCollisions; } bool isMouseLeft = Input.GetMouseButton(0); bool isMouseRight = Input.GetMouseButton(1); bool isMouseMiddle = Input.GetMouseButton(2); bool isMouseLeftDown = Input.GetMouseButtonDown(0); bool isMouseRightDown = Input.GetMouseButtonDown(1); m_drawSelectionRect = false; Vector3 vGuiMouse = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y); Vector3 vGuiMouseDelta = vGuiMouse - m_mousePrevPos; m_mousePrevPos = vGuiMouse; //+++ Set window with focus if (!isMouseLeft) { if (m_rEditorRect.Contains(vGuiMouse)) { m_focusWindow = eEditorWindow.TOOLS; } else if (m_rMinimapRect.Contains(vGuiMouse) && m_showMinimap) { m_focusWindow = eEditorWindow.MINIMAP; } // Added an extra padding to avoid drawing tiles when resizing window else if (new Rect(m_rEditorRect.x + m_rEditorRect.width + 10f, 10f, Screen.width - 20f - (m_rEditorRect.x + m_rEditorRect.width), Screen.height - 20f).Contains(vGuiMouse)) { m_focusWindow = eEditorWindow.MAPVIEW; } else { m_focusWindow = eEditorWindow.NONE; } } //--- // drag and move over the map if (isMouseMiddle) { if (m_camera2DFollowBehaviour) { m_camera2DFollowBehaviour.Target = null; } Vector3 vTemp = vGuiMouseDelta; vTemp.y = -vTemp.y; m_camera2D.transform.position -= (vTemp / 100) / m_camera2D.Zoom; } // // Inputs inside Editor Rect // if (m_rEditorRect.Contains(vGuiMouse)) { if (m_rTilesetRect.Contains(vGuiMouse)) { vGuiMouse += new Vector3(m_scrollPos.x, m_scrollPos.y); Vector3 vOff = new Vector2(vGuiMouse.x, vGuiMouse.y) - m_rTilesetRect.position; int tileX = (int)(vOff.x / k_visualTileWidth); int tileY = (int)(vOff.y / k_visualTileHeight); int autotileIdx = tileY * m_autoTileMap.Tileset.AutoTilesPerRow + tileX + (m_subTilesetIdx * 256); if (isMouseLeftDown || isMouseRightDown && m_isCtrlKeyHold) { if (m_isCtrlKeyHold) { // cycle pressed tile collision type int collType = (int)m_autoTileMap.Tileset.AutotileCollType[autotileIdx]; collType += isMouseLeftDown? 1 : (int)AutoTileMap.eTileCollisionType._SIZE - 1; collType %= (int)AutoTileMap.eTileCollisionType._SIZE; m_autoTileMap.Tileset.AutotileCollType[autotileIdx] = (AutoTileMap.eTileCollisionType)(collType); } else { // select pressed tile m_selectedTileIdx = autotileIdx; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; } } else if (isMouseRightDown) { m_tilesetSelStart = m_tilesetSelEnd = autotileIdx; } else if (isMouseRight) { m_tilesetSelEnd = autotileIdx; } else if (m_tilesetSelStart >= 0 && m_tilesetSelEnd >= 0) { m_autoTileMap.BrushGizmo.RefreshBrushGizmoFromTileset(m_tilesetSelStart, m_tilesetSelEnd); m_tilesetSelStart = m_tilesetSelEnd = -1; } } } // // Inputs inside Minimap Rect // else if (m_showMinimap && m_rMinimapRect.Contains(vGuiMouse) && m_focusWindow == eEditorWindow.MINIMAP) { if (isMouseLeft) { float minimapScale = m_rMinimapRect.width / m_autoTileMap.MinimapTexture.width; Vector3 vPos = vGuiMouse - new Vector3(m_rMinimapRect.position.x, m_rMinimapRect.position.y); vPos.y = -vPos.y; vPos.x *= m_autoTileMap.Tileset.TileWidth / (AutoTileset.PixelToUnits * minimapScale); vPos.y *= m_autoTileMap.Tileset.TileHeight / (AutoTileset.PixelToUnits * minimapScale); vPos.z = m_camera2D.transform.position.z; m_camera2D.transform.position = vPos; if (m_camera2DFollowBehaviour) { m_camera2DFollowBehaviour.Target = null; } } } // // Insputs inside map view // else if (m_focusWindow == eEditorWindow.MAPVIEW) { Vector3 vWorldMousePos = m_autoTileMap.ViewCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y)); m_autoTileMap.BrushGizmo.UpdateBrushGizmo(vWorldMousePos); if (isMouseRight || isMouseLeft) { m_drawSelectionRect = isMouseRight; //+++ Move camera automatically when near bounds if (isMouseLeft) { float fAutoDragDistX = m_rMapViewRect.width / 15; float fAutoDragDistY = m_rMapViewRect.height / 15; float fHDist = m_rMapViewRect.center.x - vGuiMouse.x; float fVDist = m_rMapViewRect.center.y - vGuiMouse.y; float fHSpeed = Mathf.Lerp(0f, -Mathf.Sign(fHDist), Mathf.Abs(fHDist) < (m_rMapViewRect.width / 2 - fAutoDragDistX)? 0 : 1f - (m_rMapViewRect.width / 2 - Mathf.Abs(fHDist)) / fAutoDragDistX); float fVSpeed = Mathf.Lerp(0f, Mathf.Sign(fVDist), Mathf.Abs(fVDist) < (m_rMapViewRect.height / 2 - fAutoDragDistY)? 0 : 1f - (m_rMapViewRect.height / 2 - Mathf.Abs(fVDist)) / fAutoDragDistY); if (fVSpeed != 0f || fHSpeed != 0f) { if (m_camera2DFollowBehaviour) { m_camera2DFollowBehaviour.Target = null; } m_camera2D.transform.position += (new Vector3(fHSpeed, fVSpeed, 0f) / 30) / m_camera2D.Zoom; } } //--- Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Plane hPlane = new Plane(Vector3.forward, Vector3.zero); float distance = 0; if (hPlane.Raycast(ray, out distance)) { // get the hit point: Vector3 vPos = ray.GetPoint(distance); int tile_x = (int)(vPos.x / m_autoTileMap.Tileset.TileWorldWidth); int tile_y = (int)(-vPos.y / m_autoTileMap.Tileset.TileWorldHeight); // for optimization, is true when mouse is over a diffent tile during the first update bool isMouseTileChanged = (tile_x != m_prevMouseTileX) || (tile_y != m_prevMouseTileY); //if ( m_autoTileMap.IsValidAutoTilePos(tile_x, tile_y)) // commented to allow drawing outside map, useful when brush has a lot of copied tiles { int gndTileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, m_autoTileMap.BrushGizmo.SelectedLayer).Id; int gndOverlayTileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, m_autoTileMap.BrushGizmo.SelectedLayer + 1).Id; // mouse right for tile selection if (isMouseRightDown || isMouseRight && isMouseTileChanged) { if (isMouseRightDown) { m_startDragTileX = tile_x; m_startDragTileY = tile_y; // copy tile if (m_isCtrlKeyHold) { m_selectedTileIdx = -2; //NOTE: -2 means, ignore this tile when painting } else { m_selectedTileIdx = gndTileType >= 0? gndTileType : gndOverlayTileType; } } m_dragTileX = tile_x; m_dragTileY = tile_y; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; } // isMouseLeft else if (isMouseLeftDown || isMouseTileChanged) // avoid Push the same action twice during mouse drag { AutoTileBrush.TileAction action = new AutoTileBrush.TileAction(); if (m_autoTileMap.BrushGizmo.BrushAction != null) { //+++ case of multiple tiles painting action.CopyRelative(m_autoTileMap, m_autoTileMap.BrushGizmo.BrushAction, tile_x, tile_y); if (m_isCtrlKeyHold && (m_autoTileMap.BrushGizmo.SelectedLayer + 1) < m_autoTileMap.GetLayerCount()) { // old functionality: ground tiles become ground overlay, ground overlay are removed, overlay tiles remains // Tiles in SelectedLayer are moved to next layer action.BecomeOverlay(m_autoTileMap.BrushGizmo.SelectedLayer); } } else { //+++ case of single tile painting // If smart brush is enabled, the tiles with collision type Overlay will be placed directly in the first overlay layer found over current SelectedLayer int overlayLayer = m_autoTileMap.FindFirstLayerIdx(AutoTileMap.eLayerType.Overlay, m_autoTileMap.BrushGizmo.SelectedLayer); if (m_autoTileMap.BrushGizmo.SmartBrushEnabled && overlayLayer >= 0 && m_selectedTileIdx >= 0 && m_autoTileMap.Tileset.AutotileCollType[m_selectedTileIdx] == AutoTileMap.eTileCollisionType.OVERLAY) { action.Push(m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, overlayLayer); } else { if (m_isCtrlKeyHold || m_autoTileMap.IsAutoTileHasAlpha(m_selectedTileIdx) && m_autoTileMap.BrushGizmo.SmartBrushEnabled) { // Put tiles with alpha in the layer over Selected Layer action.Push(m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, m_autoTileMap.BrushGizmo.SelectedLayer + 1); } else if (m_selectedTileIdx >= 0) { // Paint the selected tile action.Push(m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, m_autoTileMap.BrushGizmo.SelectedLayer); } else //if (m_selectedTileIdx < 0) { // Delete all tiles of all layers for (int i = 0; i < m_autoTileMap.GetLayerCount(); ++i) { if ( m_autoTileMap.MapLayers[i].LayerType == AutoTileMap.eLayerType.Ground || m_autoTileMap.MapLayers[i].LayerType == AutoTileMap.eLayerType.Overlay || m_autoTileMap.MapLayers[i].LayerType == AutoTileMap.eLayerType.FogOfWar ) { action.Push(m_autoTileMap, tile_x, tile_y, -1, i); } } } } } m_autoTileMap.BrushGizmo.PerformAction(action); } } m_prevMouseTileX = tile_x; m_prevMouseTileY = tile_y; } } else { // Copy selected tiles if (m_dragTileX != -1 && m_dragTileY != -1) { m_autoTileMap.BrushGizmo.BrushAction = new AutoTileBrush.TileAction(); int startTileX = Mathf.Min(m_startDragTileX, m_dragTileX); int startTileY = Mathf.Min(m_startDragTileY, m_dragTileY); int endTileX = Mathf.Max(m_startDragTileX, m_dragTileX); int endTileY = Mathf.Max(m_startDragTileY, m_dragTileY); for (int tile_x = startTileX; tile_x <= endTileX; ++tile_x) { for (int tile_y = startTileY; tile_y <= endTileY; ++tile_y) { // Tile position is relative to last released position ( m_dragTile ) if (m_isCtrlKeyHold) { // Copy overlay only for (int i = m_autoTileMap.BrushGizmo.SelectedLayer + 1; i < m_autoTileMap.GetLayerCount(); ++i) { int tileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, i).Id; if ( (m_autoTileMap.MapLayers[i].LayerType != AutoTileMap.eLayerType.Ground) || (tileType >= 0) // this allow paste overlay tiles without removing ground or ground overlay ) { m_autoTileMap.BrushGizmo.BrushAction.Push(m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, tileType, i); } } } else { for (int i = 0; i < m_autoTileMap.GetLayerCount(); ++i) { int tileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, i).Id; m_autoTileMap.BrushGizmo.BrushAction.Push(m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, tileType, i); } } } } m_autoTileMap.BrushGizmo.RefreshBrushGizmo(startTileX, startTileY, endTileX, endTileY, m_dragTileX, m_dragTileY, m_isCtrlKeyHold); m_dragTileX = m_dragTileY = -1; } if (Input.GetAxis("Mouse ScrollWheel") < 0) // back { if (m_camera2D.Zoom > 1f) { m_camera2D.Zoom = Mathf.Max(m_camera2D.Zoom - 1, 1); } else { m_camera2D.Zoom = Mathf.Max(m_camera2D.Zoom / 2f, 0.05f); } } else if (Input.GetAxis("Mouse ScrollWheel") > 0) // forward { if (m_camera2D.Zoom >= 1f) { m_camera2D.Zoom = Mathf.Min(m_camera2D.Zoom + 1, 10); } else { m_camera2D.Zoom *= 2f; } } } } }
public void OnSceneGUI() { #region Undo / Redo if (Event.current.isKey && Event.current.shift && Event.current.type == EventType.KeyUp) { if (Event.current.keyCode == KeyCode.Z) { m_autoTileMap.BrushGizmo.UndoAction(); } if (Event.current.keyCode == KeyCode.Y) { m_autoTileMap.BrushGizmo.RedoAction(); } } #endregion Rect rSceneView = new Rect(0, 0, Screen.width, Screen.height); if (rSceneView.Contains(Event.current.mousePosition)) { UpdateMouseInputs(); Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); Plane hPlane = new Plane(Vector3.forward, Vector3.zero); float distance = 0; if (hPlane.Raycast(ray, out distance)) { // get the hit point: Vector3 vPos = ray.GetPoint(distance); m_autoTileMap.BrushGizmo.UpdateBrushGizmo(vPos); if (m_isMouseRight || m_isMouseLeft) { int tile_x = (int)(vPos.x / m_autoTileMap.Tileset.TileWorldWidth); int tile_y = (int)(-vPos.y / m_autoTileMap.Tileset.TileWorldHeight); // for optimization, is true when mouse is over a diffent tile during the first update bool isMouseTileChanged = (tile_x != m_prevMouseTileX) || (tile_y != m_prevMouseTileY); //if ( m_autoTileMap.IsValidAutoTilePos(tile_x, tile_y)) // commented to allow drawing outside map, useful when brush has a lot of copied tiles { int gndTileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, m_autoTileMap.BrushGizmo.SelectedLayer).Id; int gndOverlayTileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, m_autoTileMap.BrushGizmo.SelectedLayer + 1).Id; // mouse right for tile selection if (m_isMouseRightDown || m_isMouseRight && isMouseTileChanged) { if (m_isMouseRightDown) { m_startDragTileX = tile_x; m_startDragTileY = tile_y; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; // copy tile if (Event.current.shift) { m_selectedTileId = -2; //NOTE: -2 means, ignore this tile when painting } else { m_selectedTileId = gndTileType >= 0? gndTileType : gndOverlayTileType; } } m_dragTileX = tile_x; m_dragTileY = tile_y; } // isMouseLeft else if (m_isMouseLeftDown || isMouseTileChanged) // avoid Push the same action twice during mouse drag { AutoTileBrush.TileAction action = new AutoTileBrush.TileAction(); if (m_autoTileMap.BrushGizmo.BrushAction != null) { //+++ case of multiple tiles painting action.CopyRelative(m_autoTileMap, m_autoTileMap.BrushGizmo.BrushAction, tile_x, tile_y); if (Event.current.shift && (m_autoTileMap.BrushGizmo.SelectedLayer + 1) < m_autoTileMap.GetLayerCount()) { // old functionality: ground tiles become ground overlay, ground overlay are removed, overlay tiles remains // Tiles in SelectedLayer are moved to next layer action.BecomeOverlay(m_autoTileMap.BrushGizmo.SelectedLayer); } } else { //+++ case of single tile painting // If smart brush is enabled, the tiles with collision type Overlay will be placed directly in the first overlay layer found over current SelectedLayer int overlayLayer = m_autoTileMap.FindFirstLayerIdx(eLayerType.Overlay, m_autoTileMap.BrushGizmo.SelectedLayer); if (m_autoTileMap.BrushGizmo.SmartBrushEnabled && overlayLayer >= 0 && m_selectedTileId >= 0 && m_autoTileMap.Tileset.AutotileCollType[m_selectedTileId] == eTileCollisionType.OVERLAY) { action.Push(m_autoTileMap, tile_x, tile_y, m_selectedTileId, overlayLayer); } else { if (Event.current.shift || m_autoTileMap.IsAutoTileHasAlpha(m_selectedTileId) && m_autoTileMap.BrushGizmo.SmartBrushEnabled) { // Put tiles with alpha in the layer over Selected Layer action.Push(m_autoTileMap, tile_x, tile_y, m_selectedTileId, m_autoTileMap.BrushGizmo.SelectedLayer + 1); } else { action.Push(m_autoTileMap, tile_x, tile_y, m_selectedTileId, m_autoTileMap.BrushGizmo.SelectedLayer); } } } m_autoTileMap.BrushGizmo.PerformAction(action); EditorUtility.SetDirty(m_autoTileMap); } } m_prevMouseTileX = tile_x; m_prevMouseTileY = tile_y; } else { // Copy selected tiles if (m_dragTileX != -1 && m_dragTileY != -1) { m_autoTileMap.BrushGizmo.BrushAction = new AutoTileBrush.TileAction(); int startTileX = Mathf.Min(m_startDragTileX, m_dragTileX); int startTileY = Mathf.Min(m_startDragTileY, m_dragTileY); int endTileX = Mathf.Max(m_startDragTileX, m_dragTileX); int endTileY = Mathf.Max(m_startDragTileY, m_dragTileY); for (int tile_x = startTileX; tile_x <= endTileX; ++tile_x) { for (int tile_y = startTileY; tile_y <= endTileY; ++tile_y) { // Tile position is relative to last released position ( m_dragTile ) if (Event.current.shift) { // Copy overlay only for (int i = m_autoTileMap.BrushGizmo.SelectedLayer + 1; i < m_autoTileMap.GetLayerCount(); ++i) { int tileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, i).Id; if ( (m_autoTileMap.MapLayers[i].LayerType != eLayerType.Ground) || (tileType >= 0) // this allow paste overlay tiles without removing ground or ground overlay ) { m_autoTileMap.BrushGizmo.BrushAction.Push(m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, tileType, i); } } } else { for (int i = 0; i < m_autoTileMap.GetLayerCount(); ++i) { int tileType = m_autoTileMap.GetAutoTile(tile_x, tile_y, i).Id; m_autoTileMap.BrushGizmo.BrushAction.Push(m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, tileType, i); } } } } m_autoTileMap.BrushGizmo.RefreshBrushGizmo(startTileX, startTileY, endTileX, endTileY, m_dragTileX, m_dragTileY, Event.current.shift); m_dragTileX = m_dragTileY = -1; } } } // Draw selection rect if (m_isMouseRight) { float rX = m_autoTileMap.transform.position.x + Mathf.Min(m_startDragTileX, m_dragTileX) * m_autoTileMap.Tileset.TileWorldWidth; float rY = m_autoTileMap.transform.position.y + Mathf.Min(m_startDragTileY, m_dragTileY) * m_autoTileMap.Tileset.TileWorldHeight; float rWidth = (Mathf.Abs(m_dragTileX - m_startDragTileX) + 1) * m_autoTileMap.Tileset.TileWorldWidth; float rHeight = (Mathf.Abs(m_dragTileY - m_startDragTileY) + 1) * m_autoTileMap.Tileset.TileWorldHeight; Rect rSelection = new Rect(rX, -rY, rWidth, -rHeight); UtilsGuiDrawing.DrawRectWithOutline(rSelection, new Color(0f, 1f, 0f, 0.2f), new Color(0f, 1f, 0f, 1f)); } } }
public void OnSceneGUI() { #region Undo / Redo if( Event.current.isKey && Event.current.shift && Event.current.type == EventType.KeyUp ) { if( Event.current.keyCode == KeyCode.Z ) { m_autoTileMap.BrushGizmo.UndoAction(); } if( Event.current.keyCode == KeyCode.Y ) { m_autoTileMap.BrushGizmo.RedoAction(); } } #endregion Rect rSceneView = new Rect( 0, 0, Screen.width, Screen.height ); if( rSceneView.Contains( Event.current.mousePosition ) ) { UpdateMouseInputs(); Ray ray = HandleUtility.GUIPointToWorldRay( Event.current.mousePosition ); Plane hPlane = new Plane(Vector3.forward, Vector3.zero); float distance = 0; if ( hPlane.Raycast(ray, out distance) ) { // get the hit point: Vector3 vPos = ray.GetPoint(distance); m_autoTileMap.BrushGizmo.UpdateBrushGizmo( vPos ); if( m_isMouseRight || m_isMouseLeft ) { int tile_x = (int)(vPos.x / m_autoTileMap.Tileset.TileWorldWidth); int tile_y = (int)(-vPos.y / m_autoTileMap.Tileset.TileWorldHeight); // for optimization, is true when mouse is over a diffent tile during the first update bool isMouseTileChanged = (tile_x != m_prevMouseTileX) || (tile_y != m_prevMouseTileY); //if ( m_autoTileMap.IsValidAutoTilePos(tile_x, tile_y)) // commented to allow drawing outside map, useful when brush has a lot of copied tiles { int gndTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND ).Idx; int gndOverlayTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY ).Idx; // mouse right for tile selection if( m_isMouseRightDown || m_isMouseRight && isMouseTileChanged ) { if( m_isMouseRightDown ) { m_startDragTileX = tile_x; m_startDragTileY = tile_y; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; // copy tile if( Event.current.shift ) { m_selectedTileIdx = -2; //NOTE: -2 means, ignore this tile when painting } else { m_selectedTileIdx = gndTileType >= 0? gndTileType : gndOverlayTileType; } } m_dragTileX = tile_x; m_dragTileY = tile_y; } // isMouseLeft else if( m_isMouseLeftDown || isMouseTileChanged ) // avoid Push the same action twice during mouse drag { AutoTileBrush.TileAction action = new AutoTileBrush.TileAction(); if( m_autoTileMap.BrushGizmo.BrushAction != null ) { //+++ case of multiple tiles painting action.CopyRelative( m_autoTileMap, m_autoTileMap.BrushGizmo.BrushAction, tile_x, tile_y ); if(Event.current.shift) { // ground tiles become ground overlay, ground overlay are removed, overlay tiles remains action.BecomeOverlay(); } } else { //+++ case of single tile painting if( Event.current.shift || m_autoTileMap.IsAutoTileHasAlpha( m_selectedTileIdx ) ) { // Put tiles with alpha in the overlay layer action.Push( m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY ); } else { action.Push( m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, (int)AutoTileMap.eTileLayer.GROUND ); } } m_autoTileMap.BrushGizmo.PerformAction( action ); EditorUtility.SetDirty( m_autoTileMap ); } } m_prevMouseTileX = tile_x; m_prevMouseTileY = tile_y; } else { // Copy selected tiles if( m_dragTileX != -1 && m_dragTileY != -1 ) { m_autoTileMap.BrushGizmo.BrushAction = new AutoTileBrush.TileAction(); int startTileX = Mathf.Min( m_startDragTileX, m_dragTileX ); int startTileY = Mathf.Min( m_startDragTileY, m_dragTileY ); int endTileX = Mathf.Max( m_startDragTileX, m_dragTileX ); int endTileY = Mathf.Max( m_startDragTileY, m_dragTileY ); for( int tile_x = startTileX; tile_x <= endTileX; ++tile_x ) { for( int tile_y = startTileY; tile_y <= endTileY; ++tile_y ) { int gndTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND ).Idx; int gndOverlayTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY ).Idx; int overlayTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.OVERLAY ).Idx; // Tile position is relative to last released position ( m_dragTile ) if( Event.current.shift ) { // Copy overlay only if( gndOverlayTileType >= 0 ) // this allow paste overlay tiles without removing ground or ground overlay m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, gndOverlayTileType, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY); m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, overlayTileType, (int)AutoTileMap.eTileLayer.OVERLAY); } else { m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, gndTileType, (int)AutoTileMap.eTileLayer.GROUND); m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, gndOverlayTileType, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY); m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, overlayTileType, (int)AutoTileMap.eTileLayer.OVERLAY); } } } m_autoTileMap.BrushGizmo.RefreshBrushGizmo( startTileX, startTileY, endTileX, endTileY, m_dragTileX, m_dragTileY, Event.current.shift ); m_dragTileX = m_dragTileY = -1; } } } // Draw selection rect if( m_isMouseRight ) { float rX = m_autoTileMap.transform.position.x + Mathf.Min(m_startDragTileX, m_dragTileX) * m_autoTileMap.Tileset.TileWorldWidth; float rY = m_autoTileMap.transform.position.y + Mathf.Min(m_startDragTileY, m_dragTileY) * m_autoTileMap.Tileset.TileWorldHeight; float rWidth = (Mathf.Abs(m_dragTileX - m_startDragTileX) + 1) * m_autoTileMap.Tileset.TileWorldWidth; float rHeight = (Mathf.Abs(m_dragTileY - m_startDragTileY) + 1) * m_autoTileMap.Tileset.TileWorldHeight; Rect rSelection = new Rect( rX, -rY, rWidth, -rHeight ); UtilsGuiDrawing.DrawRectWithOutline( rSelection, new Color(0f, 1f, 0f, 0.2f), new Color(0f, 1f, 0f, 1f)); } } }
void Update () { if( !m_isInitialized ) { Init(); return; } #region Draw Collisions // Generate texture again in case window has been resized Vector2 screenSize = new Vector2(Screen.width, Screen.height); if( m_prevScreenSize != screenSize ) { _GenerateCollisionTexture(); } m_prevScreenSize = screenSize; m_spriteCollLayer.SetActive( m_showCollisions ); if( m_showCollisions && (int)(Time.timeSinceLevelLoad*4)%2 == 0 ) { SpriteRenderer sprRender = m_spriteCollLayer.GetComponent<SpriteRenderer>(); Vector3 vPos = m_camera2D.transform.position; vPos.x -= (vPos.x % ( m_autoTileMap.Tileset.TileWorldWidth / 4)); vPos.y -= (vPos.y % ( m_autoTileMap.Tileset.TileWorldHeight / 4)); vPos.z += 1f; // Collision texture position snap to a quarter of tile part sprRender.transform.position = vPos; // Collision texture pixel scaled to a quarter of tile part sprRender.transform.localScale = new Vector3((m_autoTileMap.Tileset.TilePartWidth / 2), (m_autoTileMap.Tileset.TilePartHeight / 2), 1f); vPos = m_camera2D.Camera.WorldToScreenPoint( sprRender.transform.position ); // vPos = center of collision texture in screen coords Vector3 vTopLeftOff = new Vector3(sprRender.sprite.texture.width * (m_autoTileMap.Tileset.TilePartWidth / 2) / 2, -sprRender.sprite.texture.height * (m_autoTileMap.Tileset.TilePartHeight / 2) / 2) * m_camera2D.Zoom; vPos -= vTopLeftOff; vPos = m_camera2D.Camera.ScreenToWorldPoint(vPos); // vPos is now the top left corner of the collison texture in world coordinates Color32[] colors = sprRender.sprite.texture.GetPixels32(); float factorX = m_autoTileMap.Tileset.TileWorldWidth / 4; //smallest collision part has a size of a quarter of tile part float factorY = m_autoTileMap.Tileset.TileWorldHeight / 4; for( int y = 0; y < sprRender.sprite.texture.height; ++y ) { for( int x = 0; x < sprRender.sprite.texture.width; ++x ) { Vector3 vCheckPos = vPos; vCheckPos.x += (x+0.5f)*factorX; vCheckPos.y -= (y+0.5f)*factorY; AutoTileMap.eTileCollisionType collType = m_autoTileMap.GetAutotileCollisionAtPosition( vCheckPos ); //Color32 color = (x+y)%2 == 0? new Color32(0, 0, 64, 128) : new Color32(64, 0, 0, 128) ; Color32 color = new Color32(0, 0, 0, 0); colors[ (sprRender.sprite.texture.height-1-y) * sprRender.sprite.texture.width + x ] = (collType != AutoTileMap.eTileCollisionType.PASSABLE)? new Color32(255, 0, 0, 128) : color; } } sprRender.sprite.texture.SetPixels32( colors ); sprRender.sprite.texture.Apply(); } #endregion #region Undo / Redo if( m_isCtrlKeyHold ) { if( Input.GetKeyDown(KeyCode.Z ) ) { m_autoTileMap.BrushGizmo.UndoAction(); } else if( Input.GetKeyDown(KeyCode.Y ) ) { m_autoTileMap.BrushGizmo.RedoAction(); } //+++ Key Repetition Implementation if( Input.GetKey(KeyCode.Z ) ) { m_keyPressTimer += Time.deltaTime; if( m_keyPressTimer >= k_timeBeforeKeyRepeat ) { m_keyPressTimer -= k_timeBetweenKeyRepeat; m_autoTileMap.BrushGizmo.UndoAction(); } } else if( Input.GetKey(KeyCode.Y ) ) { m_keyPressTimer += Time.deltaTime; if( m_keyPressTimer >= k_timeBeforeKeyRepeat ) { m_keyPressTimer -= k_timeBetweenKeyRepeat; m_autoTileMap.BrushGizmo.RedoAction(); } } else { m_keyPressTimer = 0f; } //--- } #endregion if( Input.GetKeyDown(KeyCode.M) ) m_showMinimap = !m_showMinimap; if( Input.GetKeyDown(KeyCode.C) ) m_showCollisions = !m_showCollisions; bool isMouseLeft = Input.GetMouseButton(0); bool isMouseRight = Input.GetMouseButton(1); bool isMouseMiddle = Input.GetMouseButton(2); bool isMouseLeftDown = Input.GetMouseButtonDown(0); bool isMouseRightDown = Input.GetMouseButtonDown(1); m_drawSelectionRect = false; Vector3 vGuiMouse = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y); Vector3 vGuiMouseDelta = vGuiMouse - m_mousePrevPos; m_mousePrevPos = vGuiMouse; //+++ Set window with focus if( !isMouseLeft ) { if( m_rEditorRect.Contains( vGuiMouse ) ) { m_focusWindow = eEditorWindow.TOOLS; } else if( m_rMinimapRect.Contains( vGuiMouse ) && m_showMinimap ) { m_focusWindow = eEditorWindow.MINIMAP; } // Added an extra padding to avoid drawing tiles when resizing window else if( new Rect(m_rEditorRect.x + m_rEditorRect.width + 10f, 10f, Screen.width-20f-(m_rEditorRect.x + m_rEditorRect.width), Screen.height-20f).Contains( vGuiMouse ) ) { m_focusWindow = eEditorWindow.MAPVIEW; } else { m_focusWindow = eEditorWindow.NONE; } } //--- // drag and move over the map if( isMouseMiddle ) { if( m_camera2DFollowBehaviour ) { m_camera2DFollowBehaviour.Target = null; } Vector3 vTemp = vGuiMouseDelta; vTemp.y = -vTemp.y; m_camera2D.transform.position -= (vTemp/100)/m_camera2D.Zoom; } // // Inputs inside Editor Rect // if( m_rEditorRect.Contains( vGuiMouse ) ) { if( m_rTilesetRect.Contains( vGuiMouse ) ) { vGuiMouse += new Vector3(m_scrollPos.x, m_scrollPos.y); Vector3 vOff = new Vector2(vGuiMouse.x, vGuiMouse.y) - m_rTilesetRect.position; int tileX = (int)(vOff.x / k_visualTileWidth); int tileY = (int)(vOff.y / k_visualTileHeight); int autotileIdx = tileY * m_autoTileMap.Tileset.AutoTilesPerRow + tileX + (m_subTilesetIdx * 256); if( isMouseLeftDown || isMouseRightDown && m_isCtrlKeyHold ) { if( m_isCtrlKeyHold ) { // cycle pressed tile collision type int collType = (int)m_autoTileMap.Tileset.AutotileCollType[ autotileIdx ]; collType += isMouseLeftDown? 1 : (int)AutoTileMap.eTileCollisionType._SIZE - 1; collType%=(int)AutoTileMap.eTileCollisionType._SIZE; m_autoTileMap.Tileset.AutotileCollType[ autotileIdx ] = (AutoTileMap.eTileCollisionType)(collType); } else { // select pressed tile m_selectedTileIdx = autotileIdx; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; } } else if( isMouseRightDown ) { m_tilesetSelStart = m_tilesetSelEnd = autotileIdx; } else if( isMouseRight ) { m_tilesetSelEnd = autotileIdx; } else if( m_tilesetSelStart >= 0 && m_tilesetSelEnd >= 0 ) { m_autoTileMap.BrushGizmo.RefreshBrushGizmoFromTileset( m_tilesetSelStart, m_tilesetSelEnd ); m_tilesetSelStart = m_tilesetSelEnd = -1; } } } // // Inputs inside Minimap Rect // else if( m_showMinimap && m_rMinimapRect.Contains( vGuiMouse ) && m_focusWindow == eEditorWindow.MINIMAP ) { if( isMouseLeft ) { float minimapScale = m_rMinimapRect.width / m_autoTileMap.MinimapTexture.width; Vector3 vPos = vGuiMouse - new Vector3( m_rMinimapRect.position.x, m_rMinimapRect.position.y); vPos.y = -vPos.y; vPos.x *= m_autoTileMap.Tileset.TileWidth / (AutoTileset.PixelToUnits * minimapScale); vPos.y *= m_autoTileMap.Tileset.TileHeight / (AutoTileset.PixelToUnits * minimapScale); vPos.z = m_camera2D.transform.position.z; m_camera2D.transform.position = vPos; if( m_camera2DFollowBehaviour ) { m_camera2DFollowBehaviour.Target = null; } } } // // Insputs inside map view // else if( m_focusWindow == eEditorWindow.MAPVIEW ) { Vector3 vWorldMousePos = m_autoTileMap.ViewCamera.ScreenToWorldPoint( new Vector3(Input.mousePosition.x, Input.mousePosition.y) ); m_autoTileMap.BrushGizmo.UpdateBrushGizmo( vWorldMousePos ); if( isMouseRight || isMouseLeft ) { m_drawSelectionRect = isMouseRight; //+++ Move camera automatically when near bounds if( isMouseLeft ) { float fAutoDragDistX = m_rMapViewRect.width/15; float fAutoDragDistY = m_rMapViewRect.height/15; float fHDist = m_rMapViewRect.center.x - vGuiMouse.x; float fVDist = m_rMapViewRect.center.y - vGuiMouse.y; float fHSpeed = Mathf.Lerp(0f, -Mathf.Sign(fHDist), Mathf.Abs(fHDist) < (m_rMapViewRect.width/2 - fAutoDragDistX)? 0 : 1f - (m_rMapViewRect.width/2 - Mathf.Abs(fHDist)) / fAutoDragDistX ); float fVSpeed = Mathf.Lerp(0f, Mathf.Sign(fVDist), Mathf.Abs(fVDist) < (m_rMapViewRect.height/2 - fAutoDragDistY)? 0 : 1f - (m_rMapViewRect.height/2 - Mathf.Abs(fVDist)) / fAutoDragDistY ); if( fVSpeed != 0f || fHSpeed != 0f ) { if( m_camera2DFollowBehaviour ) { m_camera2DFollowBehaviour.Target = null; } m_camera2D.transform.position += (new Vector3(fHSpeed, fVSpeed, 0f)/30)/m_camera2D.Zoom; } } //--- Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Plane hPlane = new Plane(Vector3.forward, Vector3.zero); float distance = 0; if (hPlane.Raycast(ray, out distance)) { // get the hit point: Vector3 vPos = ray.GetPoint(distance); int tile_x = (int)(vPos.x / m_autoTileMap.Tileset.TileWorldWidth); int tile_y = (int)(-vPos.y / m_autoTileMap.Tileset.TileWorldHeight); // for optimization, is true when mouse is over a diffent tile during the first update bool isMouseTileChanged = (tile_x != m_prevMouseTileX) || (tile_y != m_prevMouseTileY); //if ( m_autoTileMap.IsValidAutoTilePos(tile_x, tile_y)) // commented to allow drawing outside map, useful when brush has a lot of copied tiles { int gndTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND ).Idx; int gndOverlayTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY ).Idx; // mouse right for tile selection if( isMouseRightDown || isMouseRight && isMouseTileChanged ) { if( isMouseRightDown ) { m_startDragTileX = tile_x; m_startDragTileY = tile_y; // copy tile if( m_isCtrlKeyHold ) { m_selectedTileIdx = -2; //NOTE: -2 means, ignore this tile when painting } else { m_selectedTileIdx = gndTileType >= 0? gndTileType : gndOverlayTileType; } } m_dragTileX = tile_x; m_dragTileY = tile_y; // Remove Brush m_autoTileMap.BrushGizmo.Clear(); m_tilesetSelStart = m_tilesetSelEnd = -1; } // isMouseLeft else if( isMouseLeftDown || isMouseTileChanged ) // avoid Push the same action twice during mouse drag { AutoTileBrush.TileAction action = new AutoTileBrush.TileAction(); if( m_autoTileMap.BrushGizmo.BrushAction != null ) { //+++ case of multiple tiles painting action.CopyRelative( m_autoTileMap, m_autoTileMap.BrushGizmo.BrushAction, tile_x, tile_y ); if(m_isCtrlKeyHold) { // ground tiles become ground overlay, ground overlay are removed, overlay tiles remains action.BecomeOverlay(); } } else { //+++ case of single tile painting if( m_isCtrlKeyHold || m_autoTileMap.IsAutoTileHasAlpha( m_selectedTileIdx ) ) { // Put tiles with alpha in the overlay layer action.Push( m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY ); } else { action.Push( m_autoTileMap, tile_x, tile_y, m_selectedTileIdx, (int)AutoTileMap.eTileLayer.GROUND ); } } m_autoTileMap.BrushGizmo.PerformAction( action ); } } m_prevMouseTileX = tile_x; m_prevMouseTileY = tile_y; } } else { // Copy selected tiles if( m_dragTileX != -1 && m_dragTileY != -1 ) { m_autoTileMap.BrushGizmo.BrushAction = new AutoTileBrush.TileAction(); int startTileX = Mathf.Min( m_startDragTileX, m_dragTileX ); int startTileY = Mathf.Min( m_startDragTileY, m_dragTileY ); int endTileX = Mathf.Max( m_startDragTileX, m_dragTileX ); int endTileY = Mathf.Max( m_startDragTileY, m_dragTileY ); for( int tile_x = startTileX; tile_x <= endTileX; ++tile_x ) { for( int tile_y = startTileY; tile_y <= endTileY; ++tile_y ) { int gndTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND ).Idx; int gndOverlayTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY ).Idx; int overlayTileType = m_autoTileMap.GetAutoTile( tile_x, tile_y, (int)AutoTileMap.eTileLayer.OVERLAY ).Idx; // Tile position is relative to last released position ( m_dragTile ) if( m_isCtrlKeyHold ) { // Copy overlay only if( gndOverlayTileType >= 0 ) // this allow paste overlay tiles without removing ground or ground overlay m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, gndOverlayTileType, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY); m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, overlayTileType, (int)AutoTileMap.eTileLayer.OVERLAY); } else { m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, gndTileType, (int)AutoTileMap.eTileLayer.GROUND); m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, gndOverlayTileType, (int)AutoTileMap.eTileLayer.GROUND_OVERLAY); m_autoTileMap.BrushGizmo.BrushAction.Push( m_autoTileMap, tile_x - m_dragTileX, tile_y - m_dragTileY, overlayTileType, (int)AutoTileMap.eTileLayer.OVERLAY); } } } m_autoTileMap.BrushGizmo.RefreshBrushGizmo( startTileX, startTileY, endTileX, endTileY, m_dragTileX, m_dragTileY, m_isCtrlKeyHold ); m_dragTileX = m_dragTileY = -1; } if (Input.GetAxis("Mouse ScrollWheel") < 0) // back { if( m_camera2D.Zoom > 1f ) m_camera2D.Zoom = Mathf.Max(m_camera2D.Zoom-1, 1); else m_camera2D.Zoom = Mathf.Max(m_camera2D.Zoom/2f, 0.05f); } else if (Input.GetAxis("Mouse ScrollWheel") > 0) // forward { if( m_camera2D.Zoom >= 1f ) m_camera2D.Zoom = Mathf.Min(m_camera2D.Zoom+1, 10); else m_camera2D.Zoom*=2f; } } } }