1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2010 by The Allacrost Project
3 //                         All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 /*!****************************************************************************
11  * \file    editor.h
12  * \author  Philip Vorsilak, gorzuate@allacrost.org
13  * \brief   Header file for editor's main window and user interface.
14  *****************************************************************************/
15 
16 #ifndef __EDITOR_HEADER__
17 #define __EDITOR_HEADER__
18 
19 #include <map>
20 
21 #include <QApplication>
22 #include <QCheckBox>
23 #include <QCloseEvent>
24 #include <QComboBox>
25 #include <QContextMenuEvent>
26 #include <QErrorMessage>
27 #include <QFileDialog>
28 #include <QLayout>
29 #include <QLineEdit>
30 #include <QMainWindow>
31 #include <QMenuBar>
32 #include <QMessageBox>
33 #include <QMouseEvent>
34 #include <QProgressDialog>
35 #include <Q3ScrollView>
36 #include <QSplitter>
37 #include <QSpinBox>
38 #include <QStatusBar>
39 #include <QTabWidget>
40 #include <QToolBar>
41 #include <QUndoCommand>
42 
43 #include "dialog_boxes.h"
44 #include "grid.h"
45 #include "sprites.h"
46 #include "skill_editor.h"
47 #include "tileset_editor.h"
48 
49 //! All calls to the editor are wrapped in this namespace.
50 namespace hoa_editor
51 {
52 
53 //! Different tile editing modes follow.
54 enum TILE_MODE_TYPE
55 {
56 	INVALID_TILE = -1,
57 	PAINT_TILE   = 0,
58 	MOVE_TILE    = 1,
59 	DELETE_TILE  = 2,
60 	TOTAL_TILE   = 3
61 };
62 
63 //! Different types of transition patterns for autotileable tiles follow.
64 enum TRANSITION_PATTERN_TYPE
65 {
66 	INVALID_PATTERN   = -1,
67 	NW_BORDER_PATTERN = 0,
68 	N_BORDER_PATTERN  = 1,
69 	NE_BORDER_PATTERN = 2,
70 	E_BORDER_PATTERN  = 3,
71 	SE_BORDER_PATTERN = 4,
72 	S_BORDER_PATTERN  = 5,
73 	SW_BORDER_PATTERN = 6,
74 	W_BORDER_PATTERN  = 7,
75 	NW_CORNER_PATTERN = 8,
76 	NE_CORNER_PATTERN = 9,
77 	SE_CORNER_PATTERN = 10,
78 	SW_CORNER_PATTERN = 11,
79 	TOTAL_PATTERN     = 12
80 };
81 
82 //! Maximum number of allowable map contexts.
83 const int MAX_CONTEXTS = 32;
84 
85 
86 class EditorScrollView;
87 
88 
89 class Editor: public QMainWindow
90 {
91 	//! Macro needed to use Qt's slots and signals.
92 	Q_OBJECT
93 
94 	public:
95 		Editor();                       // constructor
96 		~Editor();                      // destructor
97 
98 		//! Needed for tile editing and accessing the map properties.
99 		friend class EditorScrollView;
100 		friend class MapPropertiesDialog;
101 		friend class MusicDialog;
102 		friend class ContextPropertiesDialog;
103 		friend class LayerCommand;
104 
105 
106 	protected:
107 		//! Handles close and/or quit events.
108 		//! \note Reimplemented from QMainWindow.
109 		//! \param QCloseEvent* A pointer to a Qt close event.
110 		void closeEvent(QCloseEvent*);
111 
112 	private slots:
113 		//! \name Menu-Toolbar Setup Slots
114 		//! \brief These slots are used to gray out items in the menus and toolbars.
115 		//{@
116 		void _FileMenuSetup();
117 		void _ViewMenuSetup();
118 		void _TilesEnableActions();
119 		void _TilesetMenuSetup();
120 		void _MapMenuSetup();
121 		void _ScriptMenuSetup();
122 		//@}
123 
124 		//! \name File Menu Item Slots
125 		//! \brief These slots process selection for their item in the File menu.
126 		//{@
127 		void _FileNew();
128 		void _FileOpen();
129 		void _FileSaveAs();
130 		void _FileSave();
131 		void _FileClose();
132 		void _FileQuit();
133 		//@}
134 
135 		//! \name View Menu Item Slots
136 		//! \brief These slots process selection for their item in the View menu.
137 		//{@
138 		void _ViewToggleGrid();
139 		void _ViewToggleLL();
140 		void _ViewToggleML();
141 		void _ViewToggleUL();
142 		void _ViewToggleOL();
143 		void _ViewCoordTile();
144 		void _ViewCoordCollision();
145 		void _ViewTextures();
146 		//@}
147 
148 		//! \name Tiles Menu Item Slots
149 		//! \brief These slots process selection for their item in the Tiles menu.
150 		//{@LayerCommand
151 		void _TileLayerFill();
152 		void _TileLayerClear();
153 		void _TileToggleSelect();
154 		void _TileModePaint();
155 		void _TileModeMove();
156 		void _TileModeDelete();
157 		void _TileEditLL();
158 		void _TileEditML();
159 		void _TileEditUL();
160 		void _TileEditOL();
161 		//@}
162 
163 		//! \name Tileset Menu Item Slots
164 		//! \brief These slots process selection for their item in the Tileset menu.
165 		//{@
166 		void _TilesetEdit();
167 		//@}
168 
169 		//! \name Map Menu Item Slots
170 		//! \brief These slots process selection for their item in the Map menu.
171 		//{@
172 		void _MapSelectMusic();
173 		void _MapProperties();
174 		void _MapAddContext();
175 		//@}
176 
177 		//! \name Script Menu Item Slots
178 		//! \brief These slots handle the events for the Script menu
179 		//{@
180 		void _ScriptEditSkills();
181 		//@}
182 
183 		//! \name Help Menu Item Slots
184 		//! \brief These slots process selection for their item in the Help menu.
185 		//{@
186 		void _HelpHelp();
187 		void _HelpAbout();
188 		void _HelpAboutQt();
189 		//@}
190 
191 		//! This slot switches the map context to the designated one for editing.
192 		void _SwitchMapContext(int context);
193 	private:
194 		//! Helper function to the constructor, creates actions for use by menus
195 		//! and toolbars.
196 		void _CreateActions();
197 		//! Helper function to the constructor, creates the actual menus.
198 		void _CreateMenus();
199 		//! Helper function to the constructor, creates the actual toolbars.
200 		void _CreateToolbars();
201 
202 		//! \brief Used to determine if it is safe to erase the current map.
203 		//!        Will prompt the user for action: to save or not to save.
204 		//! \return True if user decided to save the map or intentionally erase it;
205 		//!         False if user canceled the operation.
206 		bool _EraseOK();
207 
208 		//! \name Application Menus
209 		//! \brief These are used to represent various menus found in the menu bar.
210 		//{@
211 		QMenu* _file_menu;
212 		QMenu* _view_menu;
213 		QMenu* _tiles_menu;
214 		QMenu* _map_menu;
215 		QMenu* _help_menu;
216 		QMenu* _tileset_menu;
217 		QMenu* _script_menu;
218 		//@}
219 
220 		//! \name Application Toolbars
221 		//! \brief These are used to represent various toolbars found in the main window.
222 		//{@
223 		QToolBar* _tiles_toolbar;
224 		//@}
225 
226 		//! \name Application Menu Actions
227 		//! \brief These are Qt's way of associating the same back-end functionality to occur whether a user
228 		//!        invokes a menu through the menu bar, a keyboard shortcut, a toolbar button, or other means.
229 		//{@
230 		QAction* _new_action;
231 		QAction* _open_action;
232 		QAction* _save_as_action;
233 		QAction* _save_action;
234 		QAction* _close_action;
235 		QAction* _quit_action;
236 
237 		QAction* _toggle_grid_action;
238 		QAction* _toggle_ll_action;
239 		QAction* _toggle_ml_action;
240 		QAction* _toggle_ul_action;
241 		QAction* _toggle_ol_action;
242 		QAction* _coord_tile_action;
243 		QAction* _coord_collision_action;
244 		QAction* _view_textures_action;
245 
246 		QAction* _undo_action;
247 		QAction* _redo_action;
248 		QAction* _layer_fill_action;
249 		QAction* _layer_clear_action;
250 		QAction* _toggle_select_action;
251 		QAction* _mode_paint_action;
252 		QAction* _mode_move_action;
253 		QAction* _mode_delete_action;
254 		QAction* _edit_ll_action;
255 		QAction* _edit_ml_action;
256 		QAction* _edit_ul_action;
257 		QAction* _edit_ol_action;
258 		QActionGroup* _mode_group;
259 		QActionGroup* _edit_group;
260 
261 		QAction* _edit_tileset_action;
262 
263 		QAction* _context_properties_action;
264 		QAction* _map_properties_action;
265 		QAction* _select_music_action;
266 
267 		QAction* _edit_skill_action;
268 
269 		QAction* _help_action;
270 		QAction* _about_action;
271 		QAction* _about_qt_action;
272 		//@}
273 
274 		//! Tabbed widget of tilesets.
275 		QTabWidget* _ed_tabs;
276 		//! Used to add scrollbars to the QGLWidget of the map.
277 		EditorScrollView* _ed_scrollview;
278 		//! The skills editor window
279 		SkillEditor *_skill_editor;
280 		//! Used as the main widget in the editor since it enables user-sizable sub-widgets.
281 		QSplitter* _ed_splitter;
282 
283 		//! Grid toggle view switch.
284 		bool _grid_on;
285 		//! Selection rectangle toggle view switch.
286 		bool _select_on;
287 		//! Textures toggle view switch.
288 		bool _textures_on;
289 		//! Lower layer toggle view switch.
290 		bool _ll_on;
291 		//! Middle layer toggle view switch.
292 		bool _ml_on;
293 		//! Upper layer toggle view switch.
294 		bool _ul_on;
295 		//! Object layer toggle view switch.
296 		bool _ol_on;
297 		//! Coordinate display type (0 = tile, 1 = collision, 2 = classic)
298 		int32 _coord_type;
299 
300 		//! The stack that contains the undo and redo operations.
301 		QUndoStack* _undo_stack;
302 
303 		//! The combobox that allows the user to change the current map context
304 		//! for editing. Contains a list of all existing contexts.
305 		QComboBox* _context_cbox;
306 
307 		//! An error dialog for exceeding the maximum allowable number of contexts.
308 		QErrorMessage* _error_max_contexts;
309 }; // class Editor
310 
311 class EditorScrollView: public Q3ScrollView
312 {
313 	//! Macro needed to use Qt's slots and signals.
314 	Q_OBJECT
315 
316 	public:
317 		EditorScrollView(QWidget* parent, const QString& name, int width, int height);
318 		~EditorScrollView();
319 
320 		//! Resizes the map.
321 		//! \param width Width of the map.
322 		//! \param height Height of the map.
323 		void Resize(int width, int height);
324 
325 		//! Gets currently edited layer
326 		std::vector<int32>& GetCurrentLayer();
327 
328 		//! Needed for changing the editing mode and painting, and accessing the map's properties.
329 		friend class Editor;
330 		friend class MapPropertiesDialog;
331 		friend class MusicDialog;
332 		friend class ContextPropertiesDialog;
333 		friend class LayerCommand;
334 
335 	protected:
336 		//! \name Mouse Processing Functions
337 		//! \brief Functions to process mouse events on the map.
338 		//! \note Reimplemented from QScrollView.
339 		//! \param evt A pointer to the QMouseEvent generated by the mouse.
340 		//{@
341 		void contentsMousePressEvent(QMouseEvent *evt);
342 		void contentsMouseMoveEvent(QMouseEvent *evt);
343 		void contentsMouseReleaseEvent(QMouseEvent *evt);
344 		void contentsContextMenuEvent(QContextMenuEvent *evt);
345 		void keyPressEvent(QKeyEvent *evt);
346 		//@}
347 
348 	private slots:
349 		//! \name Context Menu Slots
350 		//! \brief These slots process selection for their item in the Context menu,
351 		//!        which pops up on right-clicks of the mouse on the map.
352 		//{@
353 		void _ContextInsertRow();
354 		void _ContextInsertColumn();
355 		void _ContextDeleteRow();
356 		void _ContextDeleteColumn();
357 		//@}
358 
359 	private:
360 		//! \name Tile Editing Functions
361 		//! \brief These functions perform the gritty details of tile modification
362 		//!        such as painting, deleting, and moving.
363 		//! \param index The index on the map/grid of the tile to modify.
364 		//{@
365 		void _PaintTile(int32 index);
366 		//void _MoveTile(int32 index);
367 		void _DeleteTile(int32 index);
368 		//@}
369 
370 		//! \name Autotiling Functions
371 		//! \brief These functions perform all the nitty gritty details associated
372 		//!        with autotiling. _AutotileRandomize randomizes tiles being painted
373 		//!        on the map, and _AutotileTransitions calculates which tiles need
374 		//!        border transitions from one tile group to the next.
375 		//!        _CheckForTransitionPattern checks tiles surrounding the current tile
376 		//!        for patterns necessary to put in a transition tile. It's a helper to
377 		//!        _AutotileTransitions.
378 		//! \param tileset_num The index of the specified tileset as loaded in the
379 		//!                    QTabWidget.
380 		//! \param tile_index The index of the selected tile in its tileset.
381 		//! \param tile_group The autotileable group that the current tile belongs to.
382 		//{@
383 		void _AutotileRandomize(int32& tileset_num, int32& tile_index);
384 		void _AutotileTransitions(int32& tileset_num, int32& tile_index, const std::string tile_group);
385 		TRANSITION_PATTERN_TYPE _CheckForTransitionPattern(const std::string current_group,
386 			const std::vector<std::string>& surrounding_groups, std::string& border_group);
387 		//@}
388 
389 		//! \name Context Menu Actions
390 		//! \brief These are Qt's way of associating the same back-end functionality to occur whether a user
391 		//!        invokes a menu through the menu bar, a keyboard shortcut, a toolbar button, or other means.
392 		//{@
393 		QAction* _insert_row_action;
394 		QAction* _insert_column_action;
395 		QAction* _delete_row_action;
396 		QAction* _delete_column_action;
397 		//@}
398 
399 		//! Current working map.
400 		Grid* _map;
401 		//! Current tile edit mode being used.
402 		TILE_MODE_TYPE _tile_mode;
403 		//! Current layer being edited.
404 		LAYER_TYPE _layer_edit;
405 		//! Mouse is at this tile index on the map.
406 		int32 _tile_index;
407 		//! Menu used on right-clicks of the mouse on the map.
408 		QMenu* _context_menu;
409 
410 		//! Stores first index, i.e. beginning, of the selection rectangle.
411 		int32 _first_corner_index;
412 		//! Stores source index of the moved tile.
413 		int32 _move_source_index;
414 		//! Moving tiles has 2 phases to it when using the selection rectangle
415 		//! and hence moving more than one tile at a time. This determines which phase
416 		//! is in effect: false is the first phase, when the user creates the
417 		//! selection rectangle; true is the second phase, when the user clicks on
418 		//! the rectangle and moves it to another location.
419 		bool _moving;
420 
421 		//! \name Tile Vectors
422 		//! \brief The following three vectors are used to know how to perform undo and redo operations
423 		//!        for this command. They should be the same size and one-to-one. So, the j-th element
424 		//!        of each vector should correspond to the j-th element of the other vectors.
425 		//{@
426 		std::vector<int32> _tile_indeces;  //! A vector of tile indeces in the map that were modified by a command.
427 		std::vector<int32> _previous_tiles;//! A vector of indeces into tilesets of the modified tiles before they were modified.
428 		std::vector<int32> _modified_tiles;//! A vector of indeces into tilesets of the modified tiles after they were modified.
429 		//@}
430 }; // class EditorScrollView
431 
432 class LayerCommand: public QUndoCommand
433 {
434 	public:
435 		LayerCommand(std::vector<int32> indeces, std::vector<int32> previous,
436 			std::vector<int32> modified, LAYER_TYPE layer, int context, Editor* editor,
437 			const QString& text = "Layer Operation", QUndoCommand* parent = 0);
438 
439 		//! \name Undo Functions
440 		//! \brief Reimplemented from the QUndoCommand class to provide specific undo/redo capability towards the map.
441 		//{@
442 		void undo();
443 		void redo();
444 		//@}
445 
446 		//! Needed for accessing the current map's layers.
447 		friend class Editor;
448 		friend class EditorScrollView;
449 
450 	private:
451 		//! \name Tile Vectors
452 		//! \brief The following three vectors are used to know how to perform undo and redo operations
453 		//!        for this command. They should be the same size and one-to-one. So, the j-th element
454 		//!        of each vector should correspond to the j-th element of the other vectors.
455 		//{@
456 		std::vector<int32> _tile_indeces;  //! A vector of tile indeces in the map that were modified by this command.
457 		std::vector<int32> _previous_tiles;//! A vector of indeces into tilesets of the modified tiles before they were modified.
458 		std::vector<int32> _modified_tiles;//! A vector of indeces into tilesets of the modified tiles after they were modified.
459 		//@}
460 
461 		//! Indicates which map layer this command was performed upon.
462 		LAYER_TYPE _edited_layer;
463 		//! A record of the active context when this command was performed.
464 		int _context;
465 		//! A reference to the main window so we can get the current map.
466 		Editor* _editor;
467 }; // class LayerCommand
468 
469 } // namespace hoa_editor
470 
471 #endif
472 // __EDITOR_HEADER__
473