public void RefreshTileObjects() { // 销毁tile为null或者prefab为null的object for (int i = 0; i < tileObjData_list.Count; ++i) { TileObjData tileObjData = tileObjData_list[i]; uint tileData = tileData_list[tileObjData.index]; int tileId = TileSetUtil.GetTileIdFromTileData(tileData); Tile tile = tileSet.GetTile(tileId); if (tile == null || tile.tilePrefabData.prefab == null) { DestroyTileObject(tileObjData.index); } } //重建 for (int tile_index = 0; tile_index < tileData_list.Count; ++tile_index) { uint tileData = tileData_list[tile_index]; int tileId = TileSetUtil.GetTileIdFromTileData(tileData); Tile tile = tileSet.GetTile(tileId); if (tile != null && tile.tilePrefabData.prefab != null) { CreateTileObject(tile_index, tile.tilePrefabData); } } }
public void RemoveFlippingFlags(uint tileData) { if (TileSetUtil.IsTileFlagFlipH(tileData)) { FlipH(); } if (TileSetUtil.IsTileFlagFlipV(tileData)) { FlipV(); } if (TileSetUtil.IsTileFlagRot90(tileData)) { Rot90Back(); } }
public void ApplyFlippingFlags(uint tileData) { if (TileSetUtil.IsTileFlagFlipH(tileData)) { FlipH(); } if (TileSetUtil.IsTileFlagFlipV(tileData)) { FlipV(); } if (TileSetUtil.IsTileFlagRot90(tileData)) { Rot90(); } }
private void SetTileObjTransform(GameObject tile_gameObject, int grid_x, int grid_y, TilePrefabData tilePrefabData, uint tileData) { // 比如格子[0,0],中点坐标应该是[0.5 * cell_size.x,0.5 * cell_size.y] Vector3 chunk_localPosition = new Vector3((grid_x + .5f) * cell_size.x, (grid_y + .5f) * cell_size.y, tilePrefabData.prefab.transform.position.z); if (tilePrefabData.offsetMode == TilePrefabDataOffsetMode.Pixels) { float ppu = tileSet.tile_pixel_size.x / cell_size.x; chunk_localPosition += tilePrefabData.offset / ppu; } else //if (tilePrefabData.offsetMode == TileOffsetMode.Unit) { chunk_localPosition += tilePrefabData.offset; } Vector3 worldPosition = transform.TransformPoint(chunk_localPosition); tile_gameObject.transform.position = worldPosition; tile_gameObject.transform.rotation = transform.rotation; tile_gameObject.transform.parent = transform.parent; tile_gameObject.transform.localRotation = tilePrefabData.prefab.transform.localRotation; tile_gameObject.transform.localScale = tilePrefabData.prefab.transform.localScale; //+++ Apply tile flags Vector3 localScale = tile_gameObject.transform.localScale; if (TileSetUtil.IsTileFlagRot90(tileData)) { tile_gameObject.transform.localRotation *= Quaternion.Euler(0, 0, -90); } //For Rot180 and Rot270 avoid changing the scale if (TileSetUtil.IsTileFlagFlipH(tileData) && TileSetUtil.IsTileFlagFlipV(tileData)) { tile_gameObject.transform.localRotation *= Quaternion.Euler(0, 0, -180); } else { if (TileSetUtil.IsTileFlagFlipH(tileData)) { localScale.x = -tile_gameObject.transform.localScale.x; } if (TileSetUtil.IsTileFlagFlipV(tileData)) { localScale.y = -tile_gameObject.transform.localScale.y; } } tile_gameObject.transform.localScale = localScale; }
//在指定的dst_rect区域画tile public static void DoGUIDrawTileFromTileData(Rect dst_rect, uint tileData, TileSet tileSet, Rect custom_uv = default(Rect)) { int tileId = (int)(tileData & TileSetConst.TileDataMask_TileId); Tile tile = tileSet.GetTile(tileId); if (tileId != TileSetConst.TileId_Empty && tileSet.atlas_texture) { if (TileSetUtil.IsTileFlagFlipV(tileData)) { GUIUtility.ScaleAroundPivot(new Vector2(1f, -1f), dst_rect.center); } if (TileSetUtil.IsTileFlagFlipH(tileData)) { GUIUtility.ScaleAroundPivot(new Vector2(-1f, 1f), dst_rect.center); } if (TileSetUtil.IsTileFlagRot90(tileData)) { GUIUtility.RotateAroundPivot(90f, dst_rect.center); } if (tile != null && tile.tilePrefabData.prefab && tile.tilePrefabData.is_show_prefab_preview_in_tile_palette) { Texture2D asset_preview = AssetPreview.GetAssetPreview(tile.tilePrefabData.prefab); if (asset_preview) { GUI.DrawTexture(dst_rect, asset_preview, ScaleMode.ScaleToFit); } else { GUI.DrawTextureWithTexCoords(dst_rect, tileSet.atlas_texture, custom_uv == default(Rect) && tile != null ? tile.uv : custom_uv, true); } } else { GUI.DrawTextureWithTexCoords(dst_rect, tileSet.atlas_texture, custom_uv == default(Rect) && tile != null ? tile.uv : custom_uv, true); } GUI.matrix = Matrix4x4.identity; } }
public virtual Rect GetAnimUV() { int tileId = TileSetUtil.GetTileIdFromTileData(PreviewTileData()); return(tileSet && tileId != TileSetConst.TileId_Empty ? tileSet.tile_list[tileId].uv : default(Rect)); }
public void OnSceneGUI_DoPaint() { Event e = Event.current; DrawToolbar(); if (DragAndDrop.objectReferences.Length > 0 || // hide brush when user is dragging a prefab into the scene EditorWindow.mouseOverWindow != SceneView.currentDrawingSceneView || // hide brush when it's not over the scene view (Tools.current != Tool.Rect && Tools.current != Tool.None)) { is_tileSetBrush_visible = false; SceneView.RepaintAll(); return; } int control_id = GUIUtility.GetControlID(FocusType.Passive); HandleUtility.AddDefaultControl(control_id); EventType current_event_type = Event.current.GetTypeForControl(control_id); bool is_skip = false; int save_control = GUIUtility.hotControl; try { if (current_event_type == EventType.Layout) { is_skip = true; } else if (current_event_type == EventType.ScrollWheel) { is_skip = true; } if (tileMap.tileSet == null) { return; } if (!is_skip) { if (e.type == EventType.KeyDown) { switch (e.keyCode) { case TileToolbarConst.Key_FlipH: TileSetBrushBehaviour.instance.GetOrCreateTileSetBrushBehaviour(tileMap).FlipH(!e.shift); e.Use(); // Use key event break; case TileToolbarConst.Key_FlipV: TileSetBrushBehaviour.instance.GetOrCreateTileSetBrushBehaviour(tileMap).FlipV(!e.shift); e.Use(); // Use key event break; case TileToolbarConst.Key_Rot90: TileSetBrushBehaviour.instance.GetOrCreateTileSetBrushBehaviour(tileMap).Rot90(!e.shift); e.Use(); // Use key event break; case TileToolbarConst.Key_Rot90Back: TileSetBrushBehaviour.instance.GetOrCreateTileSetBrushBehaviour(tileMap).Rot90Back(!e.shift); e.Use(); // Use key event break; case TileToolbarConst.Key_PencilTool: case TileToolbarConst.Key_LineTool: case TileToolbarConst.Key_RectTool: case TileToolbarConst.Key_EllipseTool: switch (e.keyCode) { case TileToolbarConst.Key_PencilTool: TileSetBrushBehaviour.instance.paint_mode = TileSetBrushPaintMode.Pencil; break; case TileToolbarConst.Key_LineTool: TileSetBrushBehaviour.instance.paint_mode = TileSetBrushPaintMode.Line; break; case TileToolbarConst.Key_RectTool: TileSetBrushBehaviour.instance.paint_mode = TileSetBrushBehaviour.instance.paint_mode == TileSetBrushPaintMode.Rect ? TileSetBrushPaintMode.FilledRect : TileSetBrushPaintMode.Rect;//在filledRect和Rect之间切换 break; case TileToolbarConst.Key_EllipseTool: TileSetBrushBehaviour.instance.paint_mode = TileSetBrushBehaviour.instance.paint_mode == TileSetBrushPaintMode.Ellipse ? TileSetBrushPaintMode.FilledEllipse : TileSetBrushPaintMode.Ellipse;//在FilledEllipse和Ellipse之间切换 break; } tileSetBrush_mode = TileMapEditorBrushMode.Paint; TileToolbar.instance.tileSetBrushToolbar.TriggerButton((int)tileSetBrush_mode); TileToolbar.instance.tileSetBrushPaintToolbar.TriggerButton((int)TileSetBrushBehaviour.instance .paint_mode); e.Use(); break; } } EditorGUIUtility.AddCursorRect(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), MouseCursor.Arrow); GUIUtility.hotControl = control_id; { Plane tileMapChunk_plane = new Plane(tileMap.transform.forward, tileMap.transform.position); Vector2 mouse_pos = Event.current.mousePosition; mouse_pos.y = Screen.height - mouse_pos.y; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); float distance; if (tileMapChunk_plane.Raycast(ray, out distance)) { Rect tile_rect = new Rect(0, 0, tileMap.cell_size.x, tileMap.cell_size.y); tile_rect.position = tileMap.transform.InverseTransformPoint(ray.GetPoint(distance)); Vector2 tile_pos = tile_rect.position; if (tile_pos.x < 0) { tile_pos.x -= tileMap.cell_size.x;//因为负数是从-1开始的,正数是从0开始的 } if (tile_pos.y < 0) { tile_pos.y -= tileMap.cell_size.y; //因为负数是从-1开始的,正数是从0开始的 } tile_pos.x -= tile_pos.x % tileMap.cell_size.x; //取整 tile_pos.y -= tile_pos.y % tileMap.cell_size.y; //取整 tile_rect.position = tile_pos; Vector2 start_pos = new Vector2(Mathf.Min(start_dragging_pos.x, end_dragging_pos.x), Mathf.Min(start_dragging_pos.y, end_dragging_pos.y)); Vector2 end_pos = new Vector2(Mathf.Max(start_dragging_pos.x, end_dragging_pos.x), Mathf.Max(start_dragging_pos.y, end_dragging_pos.y)); Vector2 selection_snapped_pos = TileSetBrushUtil.GetSnappedPosition(start_pos, tileMap.cell_size); Vector2 selection_size = TileSetBrushUtil.GetSnappedPosition(end_pos, tileMap.cell_size) - selection_snapped_pos + tileMap.cell_size; TileSetBrushBehaviour tileSetBrushBehaviour = TileSetBrushBehaviour.instance.GetOrCreateTileSetBrushBehaviour(tileMap); // Update brush transform local_tileSetBrushBehaviour_pos = (Vector2)tileMap.transform.InverseTransformPoint(ray.GetPoint(distance));//设置tileSetBrushBehaviour的position Vector2 tileSetBrushBehaviour_snapped_pos = TileSetBrushUtil.GetSnappedPosition((tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos), tileMap.cell_size); tileSetBrushBehaviour.transform.rotation = tileMap.transform.rotation; tileSetBrushBehaviour.transform.localScale = tileMap.transform.lossyScale; if (!TileSetBrushBehaviour.instance.is_dragging)//不是拖动的时候 { tileSetBrushBehaviour.transform.position = tileMap.transform.TransformPoint(new Vector3(tileSetBrushBehaviour_snapped_pos.x, tileSetBrushBehaviour_snapped_pos.y, -0.01f)); } int pre_mouse_grid_x = mouse_grid_x; int pre_mouse_grid_y = mouse_grid_y; if (e.isMouse) { mouse_grid_x = TileSetBrushUtil.GetGridX(local_tileSetBrushBehaviour_pos, tileMap.cell_size); mouse_grid_y = TileSetBrushUtil.GetGridY(local_tileSetBrushBehaviour_pos, tileMap.cell_size); } bool is_mouse_grid_changed = pre_mouse_grid_x != mouse_grid_x || pre_mouse_grid_y != mouse_grid_y; //Update Fill Preview if (GetTileSetBrushMode() == TileMapEditorBrushMode.Fill && is_mouse_grid_changed) { fill_preview_tile_pos_list.Clear(); TileMapDrawingUtil.FloodFillPreview(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos, tileSetBrushBehaviour.tileMap.GetTileData(0, 0), fill_preview_tile_pos_list); } bool is_modifiers_changed = false; if (e.isKey) { EventModifiers filtered_modifiers = e.modifiers & (EventModifiers.Control | EventModifiers.Alt); is_modifiers_changed = filtered_modifiers != m_prevEventModifiers; m_prevEventModifiers = filtered_modifiers; } if ( (EditorWindow.focusedWindow == EditorWindow.mouseOverWindow ) && // fix painting tiles when closing another window popup over the SceneView like GameObject Selection window (e.type == EventType.MouseDown || e.type == EventType.MouseDrag && is_mouse_grid_changed || e.type == EventType.MouseUp || is_modifiers_changed) ) { if (e.button == 0) { if (mouseDoubleClick.IsDoubleClick && tileSetBrushBehaviour.tileMap.GridWidth == 1 && tileSetBrushBehaviour.tileMap.GridHeight == 1) { // Restore previous tiledata modified by Paint, because before the double click, a single click is done before tileMap.SetTileData(tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos, flood_fill_restored_tileData); tileSetBrushBehaviour.FloodFill(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos); } // Do a brush paint action else { switch (GetTileSetBrushMode()) { case TileMapEditorBrushMode.Paint: if (e.type == EventType.MouseDown) { flood_fill_restored_tileData = tileMap.GetTileData(mouse_grid_x, mouse_grid_y); } if (e.type == EventType.MouseDown) { tileSetBrushBehaviour.DoPaintPressed(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos, e.modifiers); } else if (e.type == EventType.MouseDrag || is_modifiers_changed && TileSetBrushBehaviour.instance.paint_mode != TileSetBrushPaintMode.Pencil) { tileSetBrushBehaviour.DoPaintDragged(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos, e.modifiers); } else if (e.type == EventType.MouseUp) { tileSetBrushBehaviour.DoPaintReleased(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos, e.modifiers); } break; case TileMapEditorBrushMode.Erase: tileSetBrushBehaviour.Erase(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos); break; case TileMapEditorBrushMode.Fill: tileSetBrushBehaviour.FloodFill(tileMap, tileSetBrushBehaviour.offset + local_tileSetBrushBehaviour_pos); break; } } } else if (e.button == 1) { if (e.type == EventType.MouseDown) { is_dragging = true; tileSetBrushBehaviour.tileMap.ClearMap(); start_dragging_pos = end_dragging_pos = local_tileSetBrushBehaviour_pos; } else { end_dragging_pos = local_tileSetBrushBehaviour_pos; } } } if (e.type == EventType.MouseUp) { if (e.button == 1) // right mouse button { is_dragging = false; ResetTileSetBrushMode(); // Copy one tile if (selection_size.x <= tileMap.cell_size.x && selection_size.y <= tileMap.cell_size.y) { uint tileData = tileMap.GetTileData(local_tileSetBrushBehaviour_pos); //Select the first tile not null if any and select the tilemap if (e.control && tileMap.parent_tileMapGroup) { for (int i = tileMap.parent_tileMapGroup.tileMap_list.Count - 1; i >= 0; --i) { var tileMap = this.tileMap.parent_tileMapGroup.tileMap_list[i]; tileData = tileMap.GetTileData(local_tileSetBrushBehaviour_pos); if (tileData != TileSetConst.TileData_Empty) { tileMap.parent_tileMapGroup.selected_tileMap = tileMap; if (Selection.activeGameObject == this.tileMap.gameObject) { Selection.activeGameObject = tileMap.gameObject; } break; } } } if (tileData == TileSetConst.TileData_Empty) { tileMap.tileSet.selected_tileId = TileSetConst.TileId_Empty; tileSetBrushBehaviour.tileMap.SetTileData(0, 0, TileSetConst.TileData_Empty); } else { int brushId = TileSetUtil.GetTileSetBrushIdFromTileData(tileData); int tileId = TileSetUtil.GetTileIdFromTileData(tileData); // Select the copied tile in the tileset if (brushId > 0 && !e.alt) //NOTE: if Alt is held, the tile is selected instead { tileMap.tileSet.selected_tileSetBrushId = brushId; } else { tileMap.tileSet.selected_tileId = tileId; tileSetBrushBehaviour.tileMap.SetTileData(0, 0, tileData & ~TileSetConst.TileDataMask_TileSetBrushId); // keep tile flags } } // Cut tile if key shift is pressed if (e.shift) { int startGridX = TileSetBrushUtil.GetGridX(start_pos, tileMap.cell_size); int startGridY = TileSetBrushUtil.GetGridY(start_pos, tileMap.cell_size); tileSetBrushBehaviour.CutRect(tileMap, startGridX, startGridY, startGridX, startGridY); } tileSetBrushBehaviour.tileMap.UpdateMesh(); tileSetBrushBehaviour.offset = Vector2.zero; } // copy a rect of tiles else { int startGridX = TileSetBrushUtil.GetGridX(start_pos, tileMap.cell_size); int startGridY = TileSetBrushUtil.GetGridY(start_pos, tileMap.cell_size); int endGridX = TileSetBrushUtil.GetGridX(end_pos, tileMap.cell_size); int endGridY = TileSetBrushUtil.GetGridY(end_pos, tileMap.cell_size); // Cut tile if key shift is pressed if (e.shift) { tileSetBrushBehaviour.CutRect(tileMap, startGridX, startGridY, endGridX, endGridY); } else { tileSetBrushBehaviour.CopyRect(tileMap, startGridX, startGridY, endGridX, endGridY); } tileSetBrushBehaviour.offset.x = end_dragging_pos.x > start_dragging_pos.x ? -(endGridX - startGridX) * tileMap.cell_size.x : 0f; tileSetBrushBehaviour.offset.y = end_dragging_pos.y > start_dragging_pos.y ? -(endGridY - startGridY) * tileMap.cell_size.y : 0f; } } } if (is_dragging) { Rect rGizmo = new Rect(selection_snapped_pos, selection_size); DrawUtil.HandlesDrawSolidRectangleWithOutline(rGizmo, new Color(), Color.white, tileMap.transform); } else // Draw brush border { Rect rBound = new Rect(tileSetBrushBehaviour.tileMap.tileMapBounds.min, tileSetBrushBehaviour.tileMap.tileMapBounds.size); Color fillColor; switch (GetTileSetBrushMode()) { case TileMapEditorBrushMode.Paint: fillColor = new Color(0, 0, 0, 0); break; case TileMapEditorBrushMode.Erase: fillColor = new Color(1f, 0f, 0f, 0.1f); break; case TileMapEditorBrushMode.Fill: fillColor = new Color(1f, 1f, 0f, 0.2f); break; default: fillColor = new Color(0, 0, 0, 0); break; } DrawUtil.HandlesDrawSolidRectangleWithOutline(rBound, fillColor, new Color(1, 1, 1, 0.2f), tileSetBrushBehaviour.transform); } } } if (current_event_type == EventType.MouseDrag && Event.current.button < 2) // 2 is for central mouse button { // avoid dragging the map Event.current.Use(); } } } catch (Exception exception) { Debug.LogException(exception); } SceneView.RepaintAll(); GUIUtility.hotControl = save_control; }
private void DisplayCollider() { Event e = Event.current; if (tileSet.selected_tileSetBrushId != TileSetConst.TileSetBrushId_Default) { EditorGUILayout.LabelField("tileSetBrush不能被编辑", EditorStyles.boldLabel); return; } bool is_multi_selection = tileSet.tileSelection != null; bool is_save_changes = false; Tile selected_tile = is_multi_selection ? tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[0])] : tileSet.selected_tile; if (e.type == EventType.MouseDown) { is_dragging = true; if (selected_tile.tileColliderData.vertices != null) { saved_vertexs = new Vector2[selected_tile.tileColliderData.vertices.Length]; selected_tile.tileColliderData.vertices.CopyTo(saved_vertexs, 0); } } else if (e.type == EventType.MouseUp) { is_dragging = false; } //background_color tileSet.background_color = EditorGUILayout.ColorField(tileSet.background_color); if (pre_background_color != tileSet.background_color || GUIStyleConst.Scroll_Style.normal.background == null) { pre_background_color = tileSet.background_color; if (GUIStyleConst.Scroll_Style.normal.background == null) { GUIStyleConst.Scroll_Style.normal.background = new Texture2D(1, 1) { hideFlags = HideFlags.DontSave } } ; GUIStyleConst.Scroll_Style.normal.background.SetPixel(0, 0, tileSet.background_color); GUIStyleConst.Scroll_Style.normal.background.Apply(); } float aspect_ratio = tileSet.tile_pixel_size.x / tileSet.tile_pixel_size.y; //比例 float padding = 2; // pixel size of the border around the tile //画tile图 //包围tile_rect的rect Rect tile_parent_rect = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); using (new GUIBeginGroupScope(tile_parent_rect, GUIStyleConst.Scroll_Style)) { if (e.type == EventType.Repaint) { float tile_pixel_size = tile_parent_rect.width / (tileSet.tile_pixel_size.x + 2 * padding);//2*padding是因为padding有左边和右边 mouse_pos = e.mousePosition; tile_rect = new Rect(padding * tile_pixel_size, padding * tile_pixel_size, tile_parent_rect.width - 2 * padding * tile_pixel_size, (tile_parent_rect.width / aspect_ratio) - 2 * padding * tile_pixel_size); tile_rect.height = Mathf.Min(tile_rect.height, tile_parent_rect.height - 2 * padding * tile_pixel_size); tile_rect.width = (tile_rect.height * aspect_ratio); } using (new GUIColorScope(new Color(1f, 1f, 1f, 0.1f))) { GUI.DrawTexture(tile_rect, EditorGUIUtility.whiteTexture); } if (is_multi_selection) { foreach (uint tileData in tileSet.tileSelection.selection_tileData_list) { int tileId = TileSetUtil.GetTileIdFromTileData(tileData); Tile tile = tileSet.GetTile(tileId); if (tile != null) { GUI.color = new Color(1f, 1f, 1f, 1f / tileSet.tileSelection.selection_tileData_list.Count); GUI.DrawTextureWithTexCoords(tile_rect, tileSet.atlas_texture, tile.uv); } } GUI.color = Color.white; } else { GUI.DrawTextureWithTexCoords(tile_rect, tileSet.atlas_texture, selected_tile.uv); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// Color saved_handle_color = Handles.color; if (selected_tile.tileColliderData.type != TileColliderType.None) { Vector2[] collider_vertices = selected_tile.tileColliderData.type == TileColliderType.Full ? TileConst.Full_Collider_Tile_Vertices : selected_tile.tileColliderData.vertices; if (collider_vertices == null || collider_vertices.Length == 0) { collider_vertices = selected_tile.tileColliderData.vertices = new Vector2[TileConst.Full_Collider_Tile_Vertices.Length]; Array.Copy(TileConst.Full_Collider_Tile_Vertices, collider_vertices, TileConst.Full_Collider_Tile_Vertices.Length); EditorUtility.SetDirty(tileSet); } // 将vertice的xy限制在[0,1]之间 for (int i = 0; i < collider_vertices.Length; ++i) { Vector2 collider_vertice = collider_vertices[i]; collider_vertice = collider_vertice.Snap2(tileSet.tile_pixel_size).ConvertElement(v => Mathf.Clamp01(v)); collider_vertices[i] = collider_vertice; } // 画边 draw edges Vector3[] poly_edges = new Vector3[collider_vertices.Length + 1]; for (int i = 0; i < collider_vertices.Length; ++i) { Vector2 collider_vertice = collider_vertices[i]; collider_vertice.x = tile_rect.x + tile_rect.width * collider_vertice.x; collider_vertice.y = tile_rect.yMax - tile_rect.height * collider_vertice.y; Vector2 collider_vertice_next = collider_vertices[(i + 1) % collider_vertices.Length]; collider_vertice_next.x = tile_rect.x + tile_rect.width * collider_vertice_next.x; collider_vertice_next.y = tile_rect.yMax - tile_rect.height * collider_vertice_next.y; poly_edges[i] = collider_vertice; poly_edges[i + 1] = collider_vertice_next; //画边 Handles.color = Color.green; Handles.DrawLine(collider_vertice, collider_vertice_next); //画边上的法线 Draw normals Handles.color = Color.white; Vector3 normal_pos = (collider_vertice + collider_vertice_next) / 2f; Handles.DrawLine(normal_pos, normal_pos + Vector3.Cross(collider_vertice_next - collider_vertice, Vector3.forward).normalized *tile_rect.yMin); Handles.color = saved_handle_color; } float pixel_size = tile_rect.width / tileSet.tile_pixel_size.x; if (selected_tile.tileColliderData.type == TileColliderType.Polygon) { bool is_adding_vertex_on = !is_dragging && e.shift && active_vertex_index == -1; bool is_removing_vertex_on = !is_dragging && ((Application.platform == RuntimePlatform.OSXEditor) ? e.command : e.control) && collider_vertices.Length > 3; //删除顶点 if (is_removing_vertex_on && active_vertex_index != -1 && e.type == EventType.MouseUp) { selected_tile.tileColliderData.vertices = new Vector2[collider_vertices.Length - 1]; for (int i = 0, j = 0; i < collider_vertices.Length; ++i) { if (i == active_vertex_index) { continue; } selected_tile.tileColliderData.vertices[j] = collider_vertices[i]; ++j; } collider_vertices = selected_tile.tileColliderData.vertices; active_vertex_index = -1; } float min_distance = float.MaxValue; if (!is_dragging) { active_vertex_index = -1; } for (int i = 0; i < collider_vertices.Length; ++i) { Vector2 collider_vertice = collider_vertices[i]; collider_vertice.x = tile_rect.x + tile_rect.width * collider_vertice.x; collider_vertice.y = tile_rect.yMax - tile_rect.height * collider_vertice.y; if (is_dragging) { if (i == active_vertex_index) { collider_vertice = mouse_pos; collider_vertice -= tile_rect.position; collider_vertice.x = Mathf.Clamp(Mathf.Round(collider_vertice.x / pixel_size) * pixel_size, 0, tile_rect.width); collider_vertice.y = Mathf.Clamp(Mathf.Round(collider_vertice.y / pixel_size) * pixel_size, 0, tile_rect.height); collider_vertice += tile_rect.position; collider_vertices[i].x = Mathf.Clamp01((collider_vertice.x - tile_rect.x) / tile_rect.width); collider_vertices[i].y = Mathf.Clamp01((collider_vertice.y - tile_rect.yMax) / -tile_rect.height); } } else { float distance = Vector2.Distance(mouse_pos, collider_vertice); //distance < GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width是为了限定少于多少距离(该顶点与mouse_pos的距离)的时候才选中该顶点 if (distance <= min_distance && distance < GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width) { min_distance = distance; active_vertex_index = i; } } //画顶点 if (e.type == EventType.Repaint) { //画左上角的坐标 if (i == active_vertex_index) { GUIStyleConst.VertexCoord_Style.fontSize = (int)(Mathf.Min(12f, tile_rect.yMin / 2f)); GUI.Label(new Rect(0, 0, tile_rect.width, tile_rect.yMin), Vector2.Scale(collider_vertices[i], tileSet.tile_pixel_size).ToString(), GUIStyleConst.VertexCoord_Style); } GUI.color = active_vertex_index == i ? (is_removing_vertex_on ? Color.red : Color.cyan) : new Color(0.7f, 0.7f, 0.7f, 0.8f); GUIStyleConst.Collider_Vertex_Handle_Style.Draw(new Rect(collider_vertice.x - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width / 2, collider_vertice.y - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.height / 2, 1, 1), i.ToString(), false, false, false, false); GUI.color = Color.white; } } //添加顶点 if (is_adding_vertex_on) { //线段index int segment_index; Vector2 new_vertex_pos = ClosestPointToPolyLine(poly_edges, out segment_index); if (e.type == EventType.MouseUp) { selected_tile.tileColliderData.vertices = new Vector2[collider_vertices.Length + 1]; segment_index = (segment_index + 1) % selected_tile.tileColliderData.vertices.Length; for (int i = 0, j = 0; i < selected_tile.tileColliderData.vertices.Length; ++i) { if (segment_index == i) { new_vertex_pos.x = Mathf.Clamp(Mathf.Round(new_vertex_pos.x / pixel_size) * pixel_size, tile_rect.x, tile_rect.xMax); new_vertex_pos.y = Mathf.Clamp(Mathf.Round(new_vertex_pos.y / pixel_size) * pixel_size, tile_rect.y, tile_rect.yMax); selected_tile.tileColliderData.vertices[i].x = Mathf.Clamp01((new_vertex_pos.x - tile_rect.x) / tile_rect.width); selected_tile.tileColliderData.vertices[i].y = Mathf.Clamp01((new_vertex_pos.y - tile_rect.yMax) / -tile_rect.height); } else { selected_tile.tileColliderData.vertices[i] = collider_vertices[j]; ++j; } } collider_vertices = selected_tile.tileColliderData.vertices; active_vertex_index = -1; } else if (e.type == EventType.Repaint) { //添加顶点中移动鼠标,透明动态显示当前将要新增顶点的位置 GUI.color = new Color(0.7f, 0.7f, 0.7f, 0.8f); GUIStyleConst.Collider_Vertex_Handle_Style.Draw(new Rect(new_vertex_pos.x - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width / 2, new_vertex_pos.y - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.height / 2, 1, 1), segment_index.ToString(), false, false, false, false); GUI.color = Color.white; } } } if (e.type == EventType.MouseUp) { is_save_changes = true; //remove duplicated vertex selected_tile.tileColliderData.vertices = selected_tile.tileColliderData.vertices.Distinct().ToArray(); if (selected_tile.tileColliderData.vertices.Length <= 2) { selected_tile.tileColliderData.vertices = saved_vertexs; } //snap vertex positions selected_tile.tileColliderData.SnapVertices(tileSet); } } } if (GUILayout.Button("反转法线")) { selected_tile.tileColliderData.vertices.Reverse(); } EditorGUILayout.Space(); string helpInfo = " - 移动:点击图中的顶点并移动它的位置" + "\n" + " - 添加:按住Shift并点击鼠标进行添加顶点" + "\n" + " - 删除:按住Ctrl并且点击顶点进行删除顶点 (should be more than 3)"; EditorGUILayout.HelpBox(helpInfo, MessageType.Info); // Collider Settings float saved_label_width = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 40; if (is_multi_selection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } using (new EditorGUILayoutBeginHorizontalScope(GUILayout.MinWidth(140))) { EditorGUILayout.LabelField("Collider Data", EditorStyles.boldLabel); if (GUILayout.Button("Copy", GUILayout.Width(50))) { copied_colliderData = selected_tile.tileColliderData.Clone(); } if (GUILayout.Button("Paste", GUILayout.Width(50))) { selected_tile.tileColliderData = copied_colliderData.Clone(); is_save_changes = true; } } EditorGUILayout.Space(); using (var check = new EditorGUIBeginChangeCheckScope()) { EditorGUIUtility.labelWidth = 100; EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel); using (new EditorGUIIndentLevelScope(2)) { string[] tile_collider_names = Enum.GetNames(typeof(TileColliderType)); selected_tile.tileColliderData.type = (TileColliderType)GUILayout.Toolbar((int)selected_tile.tileColliderData.type, tile_collider_names); } EditorGUIUtility.labelWidth = saved_label_width; is_save_changes |= check.IsChanged; } //Save changes if (is_save_changes) { if (is_multi_selection) { for (int i = 0; i < tileSet.tileSelection.selection_tileData_list.Count; ++i) { tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[i])].tileColliderData = selected_tile.tileColliderData.Clone(); } } EditorUtility.SetDirty(tileSet); //Refresh selected tileMap TileMap selected_tileMap = Selection.activeGameObject ? Selection.activeGameObject.GetComponent <TileMap>() : null; if (selected_tileMap) { selected_tileMap.Refresh(false, true); } } } //获取polyline(vertices组成的线段)线段上的离当前mouse poistion最近的点 //Get the point on a polyline (in 3D space) which is closest to the current mouse position Vector3 ClosestPointToPolyLine(Vector3[] vertices, out int closest_segment_index) { float min_distance = float.MaxValue; closest_segment_index = 0; for (int i = 0; i < vertices.Length - 1; ++i) { float distance = HandleUtility.DistanceToLine(vertices[i], vertices[i + 1]); if (distance < min_distance) { min_distance = distance; closest_segment_index = i; } } return(HandleUtility.ClosestPointToPolyLine(vertices)); } }
public void SetTileData(int local_grid_x, int local_grid_y, uint tileData) { if (local_grid_x >= 0 && local_grid_x < width && local_grid_y >= 0 && local_grid_y < height) { int tile_index = local_grid_y * width + local_grid_x; int tileId = (int)(tileData & TileSetConst.TileDataMask_TileId); Tile tile = tileSet.GetTile(tileId); int prev_tileId = (int)(tileData_list[tile_index] & TileSetConst.TileDataMask_TileId); Tile prev_tile = tileSet.GetTile(prev_tileId); int brushId = TileSetUtil.GetTileSetBrushIdFromTileData(tileData); int prev_brushId = TileSetUtil.GetTileSetBrushIdFromTileData(tileData_list[tile_index]); if (brushId != prev_brushId) { if (!current_updated_tileMapChunk) // avoid this is chunks is being Updated from FillMeshData { // Refresh Neighbors ( and itself if needed ) for (int y_offset = -1; y_offset <= 1; ++y_offset) { for (int x_offset = -1; x_offset <= 1; ++x_offset) { if ((x_offset | y_offset) == 0) { if (brushId > 0) { // Refresh itself tileData = (tileData & ~TileSetConst.TileFlag_Updated); } } else { int grid_x = (local_grid_x + x_offset); int grid_y = (local_grid_y + y_offset); int index = grid_y * width + grid_x; bool is_inside_chunk = (grid_x >= 0 && grid_x < width && grid_y >= 0 && grid_y < height); uint neighbor_tileData = is_inside_chunk ? tileData_list[index] : parent_tileMap.GetTileData(offset_grid_x + local_grid_x + x_offset, offset_grid_y + local_grid_y + y_offset); int neighbor_brushId = (int)((neighbor_tileData & TileSetConst.TileDataMask_TileSetBrushId) >> 16); TileSetBrush neighbor_tileSetBrush = parent_tileMap.tileSet.FindTileSetBrush(neighbor_brushId); //if (brush != null && brush.AutotileWith(brushId, neighborBrushId) || prevBrush != null && prevBrush.AutotileWith(prevBrushId, neighborBrushId)) if (neighbor_tileSetBrush != null && (neighbor_tileSetBrush.AutoTileWith(neighbor_brushId, brushId) || neighbor_tileSetBrush.AutoTileWith(neighbor_brushId, prev_brushId))) { neighbor_tileData = (neighbor_tileData & ~TileSetConst.TileFlag_Updated); // force a refresh if (is_inside_chunk) { tileData_list[index] = neighbor_tileData; } else { parent_tileMap.SetTileData(offset_grid_x + grid_x, offset_grid_y + grid_y, neighbor_tileData); } } } } } } } else if (brushId > 0) { // Refresh itself tileData = (tileData & ~TileSetConst.TileFlag_Updated); } is_need_rebuild_mesh |= (tileData_list[tile_index] != tileData) || (tileData & TileSetConst.TileDataMask_TileId) == TileSetConst.TileId_Empty; is_need_rebuild_colliders |= is_need_rebuild_mesh && ( (prev_brushId > 0) || (brushId > 0) || // there is a brush (a brush could change the collider data later) (tile != null && tile.tileColliderData.type != TileColliderType.None) || (prev_tile != null && prev_tile.tileColliderData.type != TileColliderType.None) // prev. or new tile has colliders ); if (parent_tileMap.tileMapColliderType != TileMapColliderType.None && is_need_rebuild_colliders) { // Refresh Neighbors tilechunk colliders, to make the collider autotiling // Only if neighbor is outside this tilechunk for (int y_offset = -1; y_offset <= 1; ++y_offset) { for (int x_offset = -1; x_offset <= 1; ++x_offset) { if ((x_offset | y_offset) != 0) // skip this tile position xf = yf = 0 { int grid_x = (local_grid_x + x_offset); int grid_y = (local_grid_y + y_offset); bool is_inside_chunk = (grid_x >= 0 && grid_x < width && grid_y >= 0 && grid_y < height); if (!is_inside_chunk) { parent_tileMap.InvalidateChunkAt(offset_grid_x + grid_x, offset_grid_y + grid_y, false, true); } } } } } // Update tile data tileData_list[tile_index] = tileData; if (!TileMap.Is_Disable_Tile_Prefab_Creation) { // Create tile Objects if (tile != null && tile.tilePrefabData.prefab != null) { CreateTileObject(tile_index, tile.tilePrefabData); } else { DestroyTileObject(tile_index); } } TileSetBrush brush = parent_tileMap.tileSet.FindTileSetBrush(brushId); if (brushId != prev_brushId) { TileSetBrush prevBrush = parent_tileMap.tileSet.FindTileSetBrush(prev_brushId); if (prevBrush != null) { prevBrush.OnErase(this, local_grid_x, local_grid_y, tileData, prev_brushId); } } if (brush != null) { tileData = brush.OnPaint(this, local_grid_x, local_grid_y, tileData); } } }
//https://social.msdn.microsoft.com/Forums/en-US/9d926a16-0051-4ca3-b77c-8095fb489ae2/flood-fill-c?forum=csharplanguage public static void FloodFill(TileMap tilemap, int gridX, int gridY, uint[,] tileData, bool randomize = false) { float timeStamp; timeStamp = Time.realtimeSinceStartup; //float callTimeStamp = timeStamp; int patternW = tileData.GetLength(0); int patternH = tileData.GetLength(1); LinkedList <Point> check = new LinkedList <Point>(); uint floodFrom = tilemap.GetTileData(gridX, gridY); int dataIdx0 = randomize ? Random.Range(0, patternW) : (gridX % patternW + patternW) % patternW; int dataIdx1 = randomize ? Random.Range(0, patternH) : (gridY % patternH + patternH) % patternH; tilemap.SetTileData(gridX, gridY, tileData[dataIdx0, dataIdx1]); bool isBrush = TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != 0; //Debug.Log(" Flood Fill Starts +++++++++++++++ "); if ( (patternW > 0 && patternH > 0) && isBrush ? TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != TileSetUtil.GetTileSetBrushIdFromTileData(tileData[0, 0]) : floodFrom != tileData[0, 0] ) { check.AddLast(new Point(gridX, gridY)); while (check.Count > 0) { Point cur = check.First.Value; check.RemoveFirst(); foreach (Point off in new Point[] { new Point(0, -1), new Point(0, 1), new Point(-1, 0), new Point(1, 0) }) { Point next = new Point(cur.X + off.X, cur.Y + off.Y); uint nextTileData = tilemap.GetTileData(next.X, next.Y); if ( next.X >= tilemap.min_grid_x && next.X <= tilemap.max_grid_x && next.Y >= tilemap.min_grid_y && next.Y <= tilemap.max_grid_y ) { if ( isBrush ? TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) == TileSetUtil.GetTileSetBrushIdFromTileData(nextTileData) : floodFrom == nextTileData ) { check.AddLast(next); dataIdx0 = randomize ? Random.Range(0, patternW) : (next.X % patternW + patternW) % patternW; dataIdx1 = randomize ? Random.Range(0, patternH) : (next.Y % patternH + patternH) % patternH; tilemap.SetTileData(next.X, next.Y, tileData[dataIdx0, dataIdx1]); } } } float timePast = Time.realtimeSinceStartup - timeStamp; if (timePast > k_timeToAbortFloodFill) { #if UNITY_EDITOR int result = UnityEditor.EditorUtility.DisplayDialogComplex("FloodFill is taking too much time", "Do you want to continue for another " + k_timeToAbortFloodFill + " seconds?", "Wait", "Cancel", "Wait and Don't ask again"); if (result == 0) { timeStamp = Time.realtimeSinceStartup; } else if (result == 1) { break; } else if (result == 2) { timeStamp = float.MaxValue; } #else check.Clear(); #endif } } } //Debug.Log("FloodFill Time " + (int)((Time.realtimeSinceStartup - callTimeStamp) * 1000) + "ms"); }
//Note: this is doing the same as FloodFill but not saving data in the tilemap, only saving the filled points and returning a list public static void FloodFillPreview(TileMap tilemap, int gridX, int gridY, uint tileData, List <Vector2> outFilledPoints, uint maxPoints = uint.MaxValue) { if ( gridX >= tilemap.min_grid_x && gridX <= tilemap.max_grid_x && gridY >= tilemap.min_grid_y && gridY <= tilemap.max_grid_y ) { bool[] filledPoints = new bool[tilemap.GridWidth * tilemap.GridHeight]; LinkedList <Point> check = new LinkedList <Point>(); uint floodFrom = tilemap.GetTileData(gridX, gridY); outFilledPoints.Add(Vector2.Scale(new Vector2(gridX, gridY), tilemap.cell_size)); filledPoints[(gridY - tilemap.min_grid_y) * tilemap.GridWidth + gridX - tilemap.min_grid_x] = true; bool isBrush = TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != 0; if ( isBrush ? TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) != TileSetUtil.GetTileSetBrushIdFromTileData(tileData) : floodFrom != tileData ) { check.AddLast(new Point(gridX, gridY)); while (check.Count > 0) { Point cur = check.First.Value; check.RemoveFirst(); foreach (Point off in new Point[] { new Point(0, -1), new Point(0, 1), new Point(-1, 0), new Point(1, 0) }) { Point next = new Point(cur.X + off.X, cur.Y + off.Y); if ( next.X >= tilemap.min_grid_x && next.X <= tilemap.max_grid_x && next.Y >= tilemap.min_grid_y && next.Y <= tilemap.max_grid_y ) { if (filledPoints[(next.Y - tilemap.min_grid_y) * tilemap.GridWidth + next.X - tilemap.min_grid_x]) { continue; // skip already filled points } uint nextTileData = tilemap.GetTileData(next.X, next.Y); if ( isBrush ? TileSetUtil.GetTileSetBrushIdFromTileData(floodFrom) == TileSetUtil.GetTileSetBrushIdFromTileData(nextTileData) : floodFrom == nextTileData ) { check.AddLast(next); filledPoints[(next.Y - tilemap.min_grid_y) * tilemap.GridWidth + next.X - tilemap.min_grid_x] = true; outFilledPoints.Add(Vector2.Scale(new Vector2(next.X, next.Y), tilemap.cell_size)); if (outFilledPoints.Count >= maxPoints) { return; } } } } } } } }
private Vector2 last_tile_palette_scroll_mouse_pos;//上次在tile_palette中scroll_mouse_pos public void DrawTilePalette() { Event e = Event.current; is_left_mouse_released = e.type == EventType.MouseUp && e.button == 0; //鼠标左键放开 is_right_mouse_released = e.type == EventType.MouseUp && e.button == 1; //鼠标右键放开 is_mouse_inside_tile_palette_scroll_area = e.isMouse && tile_palette_scroll_area_rect.Contains(e.mousePosition); //鼠标是否在tile_palette中 //header string tileId_label = tileSet.selected_tileId != TileSetConst.TileId_Empty ? string.Format("(id:{0})", tileSet.selected_tileId) : ""; EditorGUILayout.LabelField(string.Format("Tile Palette {0}", tileId_label), EditorStyles.boldLabel); sharedTileSetData.tileView_column_count_in_tile_palette = Mathf.Max(1, sharedTileSetData.tileView_column_count_in_tile_palette); float tile_area_width = sharedTileSetData.tileView_column_count_in_tile_palette * (tileSet.visual_tile_size.x + visual_tile_padding) + 4f; float tile_area_height = (tileSet.visual_tile_size.y + visual_tile_padding) * (1 + (visible_tile_count - 1) / sharedTileSetData.tileView_column_count_in_tile_palette) + 4f; sharedTileSetData.tileView_column_count_in_tile_palette = tileView != null ? tileView.tileSelection.column_count : tileSet.column_tile_count_in_palette; Vector2 tile_palette_scroll_pos = sharedTileSetData.tile_palette_scroll_pos; using (new EditorGUILayoutBeginScrollViewScope(ref tile_palette_scroll_pos, GUIStyleConst.Scroll_Style)) { //更新新tile_palette中的scroll_pos if (is_update_scroll_pos) { sharedTileSetData.tile_palette_scroll_pos = tile_palette_scroll_pos; } if (e.type == EventType.MouseDrag && (e.button == 1 || e.button == 2))//鼠标中键或者右键拖动中 { sharedTileSetData.tile_palette_scroll_pos = sharedTileSetData.tile_palette_scroll_pos - e.delta; } else { DoAutoScroll(); } //记录上次在tile_palette中scroll_mouse_pos if (e.isMouse) { last_tile_palette_scroll_mouse_pos = e.mousePosition; } if (tileSet.tile_list != null) { GUILayoutUtility.GetRect(tile_area_width, tile_area_height); visible_tile_count = 0; List <uint> visible_tile_list = new List <uint>(); int tileView_column_count = tileView != null ? tileView.tileSelection.column_count : tileSet.column_tile_count; int tileView_row_count = tileView != null ? ((tileView.tileSelection.selection_tileData_list.Count - 1) / tileView.tileSelection.column_count) + 1 : tileSet.row_tile_count; //在tile_palette中全部的tile个数(可能比实际的tile_count多,因为可能出现空的tile来填满行或者列的tile) int total_tile_count_in_tile_palette = ((((tileView_column_count - 1) / sharedTileSetData.tileView_column_count_in_tile_palette) + 1) * sharedTileSetData.tileView_column_count_in_tile_palette) * tileView_row_count; int tileId_offset = 0; for (int i = 0; i < total_tile_count_in_tile_palette; ++i) { //i是在tile_palette中的index(在column_tile_count_in_palette下) int tileId = GetTileIdFromIndex(i, sharedTileSetData.tileView_column_count_in_tile_palette, tileView_column_count, tileView_row_count) + tileId_offset; uint tileData = (uint)tileId; if (tileView != null && tileId != TileSetConst.TileId_Empty) { //如果是tileVeiw则,上面的tileId是在tileView中的index tileData = tileView.tileSelection.selection_tileData_list[tileId - tileId_offset]; tileId = TileSetUtil.GetTileIdFromTileData(tileData); } Tile tile = tileSet.GetTile(tileId); while (tile != null && tile.uv == default(Rect)) // 忽略无效的tiles(tile.uv == default(Rect),普通的tile是有uv的) { tile = tileSet.GetTile(++tileId); tileData = (uint)tileId; tileId_offset = tileId; } visible_tile_list.Add(tileData); int tile_x = visible_tile_count % sharedTileSetData.tileView_column_count_in_tile_palette; //在tile_palette中的x int tile_y = visible_tile_count / sharedTileSetData.tileView_column_count_in_tile_palette; //在tile_palette中的y //当前tile的rect Rect visual_tile_rect = new Rect(2 + tile_x * (tileSet.visual_tile_size.x + visual_tile_padding), 2 + tile_y * (tileSet.visual_tile_size.y + visual_tile_padding), tileSet.visual_tile_size.x, tileSet.visual_tile_size.y); Rect local_visual_tile_rect = visual_tile_rect; local_visual_tile_rect.position -= sharedTileSetData.tile_palette_scroll_pos;//相对于当前的scroll_rect区域矩形位置 if (local_visual_tile_rect.Overlaps(tile_scroll_size_rect)) { // 画tile (Draw Tile) if (tile == null) { DrawUtil.HandlesDrawSolidRectangleWithOutline(visual_tile_rect, new Color(0f, 0f, 0f, 0.2f), new Color(0f, 0f, 0f, 0.2f)); } else { DrawUtil.HandlesDrawSolidRectangleWithOutline(visual_tile_rect, new Color(0f, 0f, 0f, 0.1f), new Color(0f, 0f, 0f, 0.1f)); TileSetEditor.DoGUIDrawTileFromTileData(visual_tile_rect, tileData, tileSet); } Rect tile_rect = new Rect(2 + tile_x * (tileSet.visual_tile_size.x + visual_tile_padding), 2 + tile_y * (tileSet.visual_tile_size.y + visual_tile_padding), (tileSet.visual_tile_size.x + visual_tile_padding), (tileSet.visual_tile_size.y + visual_tile_padding)); if (visual_tile_rect.Contains(e.mousePosition)) //当前tile的矩形包含鼠标 { if (e.type == EventType.MouseDrag && e.button == 0) //鼠标左键点击并且拖动,设置sharedTileSetData.pointed_tile_index_rect { sharedTileSetData.pointed_tile_index_rect = new KeyValuePair <int, Rect>(visible_tile_count, tile_rect); } else if (e.type == EventType.MouseDown && e.button == 0)//鼠标左键按下,设置sharedTileSetData.start_drag_tile_index_rect,sharedTileSetData.pointed_tile_index_rect, sharedTileSetData.end_drag_tile_index_rect { sharedTileSetData.start_drag_tile_index_rect = sharedTileSetData.pointed_tile_index_rect = sharedTileSetData.end_drag_tile_index_rect = new KeyValuePair <int, Rect>(visible_tile_count, tile_rect); } else if (e.type == EventType.MouseUp && e.button == 0)//放开鼠标左键,设置sharedTileSetData.end_drag_tile_index_rect { sharedTileSetData.end_drag_tile_index_rect = new KeyValuePair <int, Rect>(visible_tile_count, tile_rect); DoSetTileSelection(); } } if ((is_left_mouse_released || is_right_mouse_released) && //放开鼠标左键或者右键 is_mouse_inside_tile_palette_scroll_area && visual_tile_rect.Contains(e.mousePosition) && //鼠标位置处在该tile中 (sharedTileSetData.start_drag_tile_index_rect.Key == sharedTileSetData.end_drag_tile_index_rect.Key) && // 没有拖动 tile_scroll_size_rect.Contains(e.mousePosition - sharedTileSetData.tile_palette_scroll_pos))// and it's inside the scroll area { tileSet.selected_tileId = tileId; //Give focus to SceneView to get key events FocusSceneView(); //放开鼠标右键,打开显示tile的属性面板 if (is_right_mouse_released) { TilePropertiesEditor.Show(tileSet); } } else if (tile != null && tileSet.selected_tileId == tileId)//用黄色外边框选中的tile { DrawUtil.HandlesDrawSolidRectangleWithOutline(tile_rect, new Color(0f, 0f, 0f, 0.1f), new Color(1f, 1f, 0f, 1f)); } } ++visible_tile_count; } this.visible_tile_list = visible_tile_list; // 画选中的矩形 用于TileSelection if (sharedTileSetData.start_drag_tile_index_rect.Key != sharedTileSetData.pointed_tile_index_rect.Key) { Rect selection_rect = new Rect(sharedTileSetData.start_drag_tile_index_rect.Value.center, sharedTileSetData.pointed_tile_index_rect.Value.center - sharedTileSetData.start_drag_tile_index_rect.Value.center); selection_rect.Set(Mathf.Min(selection_rect.xMin, selection_rect.xMax), Mathf.Min(selection_rect.yMin, selection_rect.yMax), Mathf.Abs(selection_rect.width), Mathf.Abs(selection_rect.height)); selection_rect.xMin -= sharedTileSetData.start_drag_tile_index_rect.Value.width / 2; selection_rect.xMax += sharedTileSetData.start_drag_tile_index_rect.Value.width / 2; selection_rect.yMin -= sharedTileSetData.start_drag_tile_index_rect.Value.height / 2; selection_rect.yMax += sharedTileSetData.start_drag_tile_index_rect.Value.height / 2; DrawUtil.HandlesDrawSolidRectangleWithOutline(selection_rect, new Color(0f, 0f, 0f, 0.1f), new Color(1f, 1f, 1f, 1f)); } } } if (e.type == EventType.Repaint) { tile_palette_scroll_area_rect = GUILayoutUtility.GetLastRect(); tile_scroll_size_rect = tile_palette_scroll_area_rect; tile_scroll_size_rect.position = Vector2.zero; // reset position to the Contains and Overlaps inside the tile scroll view without repositioning the position of local positions if (tile_area_width > tile_scroll_size_rect.width) { tile_scroll_size_rect.height -= GUI.skin.verticalScrollbar.fixedWidth; } if (tile_area_height > tile_scroll_size_rect.height) { tile_scroll_size_rect.width -= GUI.skin.verticalScrollbar.fixedWidth; } } }
private void DisplayPrefab() { if (tileSet.selected_tileSetBrushId != TileSetConst.TileSetBrushId_Default) { EditorGUILayout.LabelField("TileSetBrush tile不能被编辑", EditorStyles.boldLabel); } else { bool is_multi_selection = tileSet.tileSelection != null; Tile selected_tile = is_multi_selection ? tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[0])] : tileSet.selected_tile; GUILayoutUtility.GetRect(1, 1, GUILayout.Width(tileSet.visual_tile_size.x), GUILayout.Height(tileSet.visual_tile_size.y));//Pos1 Rect tile_uv = selected_tile.uv; GUI.color = tileSet.background_color; GUI.DrawTextureWithTexCoords(GUILayoutUtility.GetLastRect(), EditorGUIUtility.whiteTexture, tile_uv, true); //即在Pos1处画图片 GUI.color = Color.white; GUI.DrawTextureWithTexCoords(GUILayoutUtility.GetLastRect(), tileSet.atlas_texture, tile_uv, true); //即在Pos1处画图片 if (is_multi_selection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } using (var check1 = new EditorGUIBeginChangeCheckScope()) { TilePrefabData tilePrefabData = selected_tile.tilePrefabData; float saved_label_width = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 80; //offset tilePrefabData.offset = EditorGUILayout.Vector3Field("offset", tilePrefabData.offset); tilePrefabData.offsetMode = (TilePrefabDataOffsetMode)EditorGUILayout.EnumPopup("offset mode", tilePrefabData.offsetMode); //prefab bool is_prefab_changed = false; using (var check2 = new EditorGUIBeginChangeCheckScope()) { tilePrefabData.prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", tilePrefabData.prefab, typeof(GameObject), false); if (check2.IsChanged) { is_prefab_changed = true; } } //prefab preview Texture2D prefab_preview; using (new GUILayoutBeginHorizontalScope()) { prefab_preview = AssetPreview.GetAssetPreview(selected_tile.tilePrefabData.prefab); GUILayout.Box(prefab_preview, prefab_preview != null ? (GUIStyle)"Box" : GUIStyle.none); } if (tilePrefabData.prefab) { EditorGUIUtility.labelWidth = 260; if (prefab_preview) { tilePrefabData.is_show_prefab_preview_in_tile_palette = EditorGUILayout.Toggle("在tile palette中显示预设", tilePrefabData.is_show_prefab_preview_in_tile_palette); } EditorGUIUtility.labelWidth = saved_label_width; tilePrefabData.is_show_tile_with_prefab = EditorGUILayout.Toggle("Show Tile With Prefab", tilePrefabData.is_show_tile_with_prefab); } if (check1.IsChanged) { Undo.RecordObject(tileSet, "Tile Prefab Data Changed"); if (is_multi_selection) { for (int i = 0; i < tileSet.tileSelection.selection_tileData_list.Count; ++i) { Tile tile = tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[i])]; GameObject saved_prefab = tile.tilePrefabData.prefab; tile.tilePrefabData = tilePrefabData; if (!is_prefab_changed) { tile.tilePrefabData.prefab = saved_prefab; } } } else { selected_tile.tilePrefabData = tilePrefabData; } EditorUtility.SetDirty(tileSet); } } } }