1 /*************************************************************************/ 2 /* tile_set_editor_plugin.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ 10 /* */ 11 /* Permission is hereby granted, free of charge, to any person obtaining */ 12 /* a copy of this software and associated documentation files (the */ 13 /* "Software"), to deal in the Software without restriction, including */ 14 /* without limitation the rights to use, copy, modify, merge, publish, */ 15 /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 /* permit persons to whom the Software is furnished to do so, subject to */ 17 /* the following conditions: */ 18 /* */ 19 /* The above copyright notice and this permission notice shall be */ 20 /* included in all copies or substantial portions of the Software. */ 21 /* */ 22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 /*************************************************************************/ 30 31 #ifndef TILE_SET_EDITOR_PLUGIN_H 32 #define TILE_SET_EDITOR_PLUGIN_H 33 34 #include "editor/editor_node.h" 35 #include "scene/2d/sprite.h" 36 #include "scene/resources/concave_polygon_shape_2d.h" 37 #include "scene/resources/convex_polygon_shape_2d.h" 38 #include "scene/resources/tile_set.h" 39 40 #define WORKSPACE_MARGIN Vector2(10, 10) 41 class TilesetEditorContext; 42 43 class TileSetEditor : public HSplitContainer { 44 45 friend class TileSetEditorPlugin; 46 friend class TilesetEditorContext; 47 48 GDCLASS(TileSetEditor, HSplitContainer); 49 50 enum TextureToolButtons { 51 TOOL_TILESET_ADD_TEXTURE, 52 TOOL_TILESET_REMOVE_TEXTURE, 53 TOOL_TILESET_CREATE_SCENE, 54 TOOL_TILESET_MERGE_SCENE, 55 TOOL_TILESET_MAX 56 }; 57 58 enum WorkspaceMode { 59 WORKSPACE_EDIT, 60 WORKSPACE_CREATE_SINGLE, 61 WORKSPACE_CREATE_AUTOTILE, 62 WORKSPACE_CREATE_ATLAS, 63 WORKSPACE_MODE_MAX 64 }; 65 66 enum EditMode { 67 EDITMODE_REGION, 68 EDITMODE_COLLISION, 69 EDITMODE_OCCLUSION, 70 EDITMODE_NAVIGATION, 71 EDITMODE_BITMASK, 72 EDITMODE_PRIORITY, 73 EDITMODE_ICON, 74 EDITMODE_Z_INDEX, 75 EDITMODE_MAX 76 }; 77 78 enum TileSetTools { 79 SELECT_PREVIOUS, 80 SELECT_NEXT, 81 TOOL_SELECT, 82 BITMASK_COPY, 83 BITMASK_PASTE, 84 BITMASK_CLEAR, 85 SHAPE_NEW_POLYGON, 86 SHAPE_NEW_RECTANGLE, 87 SHAPE_TOGGLE_TYPE, 88 SHAPE_DELETE, 89 SHAPE_KEEP_INSIDE_TILE, 90 TOOL_GRID_SNAP, 91 ZOOM_OUT, 92 ZOOM_1, 93 ZOOM_IN, 94 VISIBLE_INFO, 95 TOOL_MAX 96 }; 97 98 struct SubtileData { 99 Array collisions; 100 Ref<OccluderPolygon2D> occlusion_shape; 101 Ref<NavigationPolygon> navigation_shape; 102 }; 103 104 Ref<TileSet> tileset; 105 TilesetEditorContext *helper; 106 EditorNode *editor; 107 UndoRedo *undo_redo; 108 109 ConfirmationDialog *cd; 110 AcceptDialog *err_dialog; 111 EditorFileDialog *texture_dialog; 112 113 ItemList *texture_list; 114 int option; 115 ToolButton *tileset_toolbar_buttons[TOOL_TILESET_MAX]; 116 MenuButton *tileset_toolbar_tools; 117 Map<RID, Ref<Texture> > texture_map; 118 119 bool creating_shape; 120 int dragging_point; 121 bool tile_names_visible; 122 Vector2 region_from; 123 Rect2 edited_region; 124 bool draw_edited_region; 125 Vector2 edited_shape_coord; 126 PoolVector2Array current_shape; 127 Map<Vector2i, SubtileData> current_tile_data; 128 Map<Vector2, uint32_t> bitmask_map_copy; 129 130 Vector2 snap_step; 131 Vector2 snap_offset; 132 Vector2 snap_separation; 133 134 Ref<Shape2D> edited_collision_shape; 135 Ref<OccluderPolygon2D> edited_occlusion_shape; 136 Ref<NavigationPolygon> edited_navigation_shape; 137 138 int current_item_index; 139 Sprite *preview; 140 ScrollContainer *scroll; 141 Label *empty_message; 142 Control *workspace_container; 143 bool draw_handles; 144 Control *workspace_overlay; 145 Control *workspace; 146 Button *tool_workspacemode[WORKSPACE_MODE_MAX]; 147 Button *tool_editmode[EDITMODE_MAX]; 148 HSeparator *separator_editmode; 149 HBoxContainer *toolbar; 150 ToolButton *tools[TOOL_MAX]; 151 VSeparator *separator_shape_toggle; 152 VSeparator *separator_bitmask; 153 VSeparator *separator_delete; 154 VSeparator *separator_grid; 155 SpinBox *spin_priority; 156 SpinBox *spin_z_index; 157 WorkspaceMode workspace_mode; 158 EditMode edit_mode; 159 int current_tile; 160 161 float max_scale; 162 float min_scale; 163 float scale_ratio; 164 165 void update_texture_list(); 166 void update_texture_list_icon(); 167 168 void add_texture(Ref<Texture> p_texture); 169 void remove_texture(Ref<Texture> p_texture); 170 171 Ref<Texture> get_current_texture(); 172 173 static void _import_node(Node *p_node, Ref<TileSet> p_library); 174 static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); 175 void _undo_redo_import_scene(Node *p_scene, bool p_merge); 176 177 bool _is_drop_valid(const Dictionary &p_drag_data, const Dictionary &p_item_data) const; 178 Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); 179 bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; 180 void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); 181 void _file_load_request(const PoolVector<String> &p_path, int p_at_pos = -1); 182 183 protected: 184 static void _bind_methods(); 185 void _notification(int p_what); 186 187 public: 188 void edit(const Ref<TileSet> &p_tileset); 189 static Error update_library_file(Node *p_base_scene, Ref<TileSet> ml, bool p_merge = true); 190 191 TileSetEditor(EditorNode *p_editor); 192 ~TileSetEditor(); 193 194 private: 195 void _on_tileset_toolbar_button_pressed(int p_index); 196 void _on_tileset_toolbar_confirm(); 197 void _on_texture_list_selected(int p_index); 198 void _on_textures_added(const PoolStringArray &p_paths); 199 void _on_edit_mode_changed(int p_edit_mode); 200 void _on_workspace_mode_changed(int p_workspace_mode); 201 void _on_workspace_overlay_draw(); 202 void _on_workspace_draw(); 203 void _on_workspace_process(); 204 void _on_scroll_container_input(const Ref<InputEvent> &p_event); 205 void _on_workspace_input(const Ref<InputEvent> &p_ie); 206 void _on_tool_clicked(int p_tool); 207 void _on_priority_changed(float val); 208 void _on_z_index_changed(float val); 209 void _on_grid_snap_toggled(bool p_val); 210 Vector<Vector2> _get_collision_shape_points(const Ref<Shape2D> &p_shape); 211 Vector<Vector2> _get_edited_shape_points(); 212 void _set_edited_shape_points(const Vector<Vector2> &points); 213 void _update_tile_data(); 214 void _update_toggle_shape_button(); 215 void _select_next_tile(); 216 void _select_previous_tile(); 217 Array _get_tiles_in_current_texture(bool sorted = false); 218 bool _sort_tiles(Variant p_a, Variant p_b); 219 void _select_next_subtile(); 220 void _select_previous_subtile(); 221 void _select_next_shape(); 222 void _select_previous_shape(); 223 void _set_edited_collision_shape(const Ref<Shape2D> &p_shape); 224 void _set_snap_step(Vector2 p_val); 225 void _set_snap_off(Vector2 p_val); 226 void _set_snap_sep(Vector2 p_val); 227 228 void _validate_current_tile_id(); 229 void _select_edited_shape_coord(); 230 void _undo_tile_removal(int p_id); 231 232 void _zoom_in(); 233 void _zoom_out(); 234 void _zoom_reset(); 235 236 void draw_highlight_current_tile(); 237 void draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); 238 void draw_tile_subdivision(int p_id, Color p_color) const; 239 void draw_edited_region_subdivision() const; 240 void draw_grid_snap(); 241 void draw_polygon_shapes(); 242 void close_shape(const Vector2 &shape_anchor); 243 void select_coord(const Vector2 &coord); 244 Vector2 snap_point(const Vector2 &point); 245 void update_workspace_tile_mode(); 246 void update_workspace_minsize(); 247 void update_edited_region(const Vector2 &end_point); 248 int get_grabbed_point(const Vector2 &p_mouse_pos, real_t grab_threshold); 249 bool is_within_grabbing_distance_of_first_point(const Vector2 &p_pos, real_t p_grab_threshold); 250 251 int get_current_tile() const; 252 void set_current_tile(int p_id); 253 }; 254 255 class TilesetEditorContext : public Object { 256 257 friend class TileSetEditor; 258 GDCLASS(TilesetEditorContext, Object); 259 260 Ref<TileSet> tileset; 261 TileSetEditor *tileset_editor; 262 bool snap_options_visible; 263 264 public: _hide_script_from_inspector()265 bool _hide_script_from_inspector() { return true; } 266 void set_tileset(const Ref<TileSet> &p_tileset); 267 268 private: 269 void set_snap_options_visible(bool p_visible); 270 271 protected: 272 bool _set(const StringName &p_name, const Variant &p_value); 273 bool _get(const StringName &p_name, Variant &r_ret) const; 274 void _get_property_list(List<PropertyInfo> *p_list) const; 275 static void _bind_methods(); 276 277 public: 278 TilesetEditorContext(TileSetEditor *p_tileset_editor); 279 }; 280 281 class TileSetEditorPlugin : public EditorPlugin { 282 283 GDCLASS(TileSetEditorPlugin, EditorPlugin); 284 285 TileSetEditor *tileset_editor; 286 Button *tileset_editor_button; 287 EditorNode *editor; 288 289 public: get_name()290 virtual String get_name() const { return "TileSet"; } has_main_screen()291 bool has_main_screen() const { return false; } 292 virtual void edit(Object *p_node); 293 virtual bool handles(Object *p_node) const; 294 virtual void make_visible(bool p_visible); 295 void set_state(const Dictionary &p_state); 296 Dictionary get_state() const; 297 298 TileSetEditorPlugin(EditorNode *p_node); 299 }; 300 301 #endif // TILE_SET_EDITOR_PLUGIN_H 302