File indexing completed on 2024-12-08 06:45:59

0001 /*
0002     SPDX-FileCopyrightText: 2009 Ian Wadham <iandw.au@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef KGREDITOR_H
0008 #define KGREDITOR_H
0009 
0010 #include "kgrglobals.h"
0011 
0012 #include <QObject>
0013 
0014 class KGrView;
0015 class KGrScene;
0016 class KGrGameIO;
0017 class QTimer;
0018 
0019 /**
0020  * This class is the game-editor for KGoldrunner.  It loads KGrGameData and
0021  * KGrLevelData objects from files, operates directly on the data in those
0022  * objects and saves them back to files.  In particular, the layout of a level
0023  * is edited by selecting objects such as bricks, ladders, etc. from a toolbar
0024  * and using mouse-clicks and drags to show where those objects are required.
0025  * As this happens, the corresponding character-codes are stored directly in
0026  * the QByteArray of layout-data and the corresponding visual objects (tiles)
0027  * are displayed on the screen by the KGrScene and KGrView objects.
0028  *
0029  * @short Game-editor class
0030  */
0031 class KGrEditor : public QObject
0032 {
0033     Q_OBJECT
0034 public:
0035     /**
0036      * The constructor of KGrEditor.
0037      *
0038      * @param theView      The canvas on which the editor paints the layout.
0039      *                     Also the object that owns the editor and will destroy
0040      *                     it if the KGoldrunner application is terminated.
0041      * @param theSystemDir The directory-path where the games and levels
0042      *                     released with KGoldrunner are stored.  This data is
0043      *                     read-only, but can be copied, edited and saved in
0044      *                     the user's area.
0045      * @param theUserDir   The directory-path where the user's composed or
0046      *                     edited games and levels are stored.
0047      * @param pGameList    The current list of system and user game-data.  The
0048      *                     user can add a game to the list and add levels to
0049      *                     that game or any other game in the user's area.
0050      */
0051     KGrEditor (KGrView * theView, const QString &theSystemDir,
0052                                   const QString &theUserDir,
0053                                   QList<KGrGameData *> & pGameList);
0054     ~KGrEditor() override;
0055 
0056     /**
0057      * Check if there are any unsaved edits and, if so, ask the user what to
0058      * do.  It will call saveLevelFile() if the user wants to save.
0059      *
0060      * @return             If true, the level was successfully saved or there
0061      *                     was nothing to save or the user decided not to save,
0062      *                     so it is OK to do something new or close KGoldrunner.
0063      *                     If false, the user decided to continue editing or the
0064      *                     file I/O failed.
0065      */
0066     bool saveOK();
0067 
0068     /**
0069      * Set up a blank level-layout, ready for editing.
0070      *
0071      * @param pGameIndex   The list-index of the game which will contain the new
0072      *                     level: assumed for now, but can change at save time.
0073      *
0074      * @return             If false, the action failed or was cancelled.
0075      */
0076     bool createLevel (int pGameIndex);
0077 
0078     /**
0079      * Load and display an existing level, ready for editing.  This can be a
0080      * released level, but the changes must be saved in the user's area.
0081      *
0082      * @param pGameIndex   The list-index of the game that contains the level
0083      *                     to be edited: verified by a dialog and may change.
0084      * @param pLevel       The number of the level to be edited: verified by a
0085      *                     dialog and may change.
0086      *
0087      * @return             If false, the action failed or was cancelled.
0088      */
0089     bool updateLevel (int pGameIndex, int pLevel);
0090 
0091     /**
0092      * Save an edited level in a text file (*.grl) in the user's area.  The
0093      * required game and level number are obtained from a dialog.  These are the
0094      * same as the original game and level number by default, but can be altered
0095      * so as to get a Save As effect.  For example, a system level can be loaded
0096      * and edited, then saved in one of the user's own games.
0097      *
0098      * @return             If true, the level was successfully saved.  If false,
0099      *                     the user cancelled the save or the file I/O failed.
0100      */
0101     bool saveLevelFile();   // Save the edited level in a text file (.grl).
0102 
0103     /**
0104      * Move a level to another game or level number.  Can be used to arrange
0105      * levels in order of difficulty within a game.
0106      *
0107      * @param pGameIndex   The list-index of the game that contains the level
0108      *                     to be moved: a dialog selects the game to move to.
0109      * @param pLevel       The number of the level to be moved: a dialog selects
0110      *                     the number to move to.  Other numbers may be changed,
0111      *                     to preserve the sequential numbering of levels.
0112      *
0113      * @return             If false, the action failed or was cancelled.
0114      */
0115     bool moveLevelFile (int pGameIndex, int pLevel);
0116 
0117     /**
0118      * Delete a level from a game.
0119      *
0120      * @param pGameIndex   The list-index of the game that contains the level
0121      *                     to be deleted: verified by a dialog and may change.
0122      * @param pLevel       The number of the level to be deleted: verified by a
0123      *                     dialog and may change.
0124      *
0125      * @return             If false, the action failed or was cancelled.
0126      */
0127     bool deleteLevelFile (int pGameIndex, int pLevel);
0128 
0129     /**
0130      * Create a new game (a collection point for levels) or load the details
0131      * of an existing game, ready for editing.
0132      *
0133      * @param pGameIndex   The list-index of the game to be created or edited:
0134      *                     0 = create, >0 = edit (verified by a dialog and may
0135      *                     change).
0136      *
0137      * @return             If false, the action failed or was cancelled.
0138      */
0139     bool editGame (int pGameIndex);
0140 
0141 public Q_SLOTS:
0142     /**
0143      * Run a dialog in which the name and hint of a level can be edited.
0144      */
0145     void editNameAndHint();
0146 
0147 public:
0148     /**
0149      * Set the next object for the editor to paint, e.g. brick, enemy, ladder.
0150      *
0151      * @param newEditObj   A character-code for the type of object.
0152      */
0153     void setEditObj (char newEditObj);
0154 
0155     inline void getGameAndLevel (int & game, int & lev) {
0156                                  game = gameIndex; lev = editLevel; }
0157 
0158 Q_SIGNALS:
0159     /**
0160      * Get the next grid-position at which to paint an object in the layout.
0161      *
0162      * @param i            The row-number of the cell (return by reference).
0163      * @param j            The column-number of the cell (return by reference).
0164      */
0165     void getMousePos    (int & i, int & j);
0166 
0167 private:
0168     KGrView   * view;       // The canvas on which the editor paints.
0169     KGrScene  * scene;
0170     KGrGameIO * io;     // I/O object for reading level-data.
0171     QString     systemDataDir;
0172     QString     userDataDir;
0173 
0174     // Will REFERENCE the main list in KGrGame, allowing KGrEditor to add games.
0175     QList<KGrGameData *> & gameList;
0176 
0177     bool mouseMode;     // Flag to set up keyboard OR mouse control.
0178     bool editMode;      // Flag to change keyboard and mouse functions.
0179     char editObj;       // Type of object to be painted by the mouse.
0180     bool paintEditObj;      // Sets painting on/off (toggled by clicking).
0181     bool paintAltObj;       // Sets painting for the alternate object on/off
0182     int  oldI, oldJ;        // Last mouse position painted.
0183     int  editLevel;     // Level to be edited (= 0 for new level).
0184     int  heroCount;     // Can enter at most one hero.
0185     bool shouldSave;        // True if name or hint was edited.
0186 
0187     // The list-index of the game (collection of levels) being composed/edited.
0188     int  gameIndex;
0189 
0190     // The data, including the layout, for the level being composed or edited.
0191     KGrLevelData levelData;
0192     KGrLevelData savedLevelData;
0193     QString      levelName; // Level name during editing (optional).
0194     QString      levelHint; // Level hint during editing (optional).
0195 
0196     /**
0197      * Run a dialog to select a game and level to be edited or saved.
0198      *
0199      * @param action         A code for the type of editing: affects validation
0200      *                       and labeling in the dialog.
0201      * @param requestedLevel The current level, used as a default, but can be
0202      *                       changed by the user.
0203      * @param requestedGame  The current game, used as a default, but can be
0204      *                       changed by the user (return by reference).
0205      *
0206      * @return               The level the user chose, or zero if the user
0207      *                       cancelled the dialog.  The level chosen could be
0208      *                       different from the requestedLevel parameter.
0209      */
0210     int  selectLevel (int action, int requestedLevel, int & requestedGame);
0211 
0212     void loadEditLevel (int);   // Load and display an existing level for edit.
0213     void initEdit();
0214     void insertEditObj (int, int, char object);
0215     char editableCell (int i, int j);
0216     void setEditableCell (int, int, char);
0217     bool reNumberLevels (int, int, int, int);
0218     bool ownerOK (Owner o);
0219     bool saveGameData (Owner o);
0220 
0221     QString getTitle();
0222     QString getLevelFilePath (KGrGameData * gameData, int lev);
0223 
0224     QTimer *     timer;     // The time-signal for the game-editor.
0225 
0226     bool mouseDisabled;
0227 
0228 private Q_SLOTS:
0229     /**
0230      * Start painting or erasing cells on the layout.  Triggered by pressing
0231      * a mouse-button.
0232      *
0233      * @param button The button being pressed: left for paint, right for erase.
0234      */
0235     void doEdit  (int button);
0236 
0237     /**
0238      * If the mouse has moved to a new cell and a button is down, continue
0239      * painting or erasing cells on the layout.  Triggered by a timer signal.
0240      */
0241     void tick    ();
0242 
0243     /**
0244      * Stop painting or erasing cells on the layout.  Triggered by releasing
0245      * a mouse-button.
0246      *
0247      * @param button The button being released: left for paint, right for erase.
0248      */
0249     void endEdit (int button);
0250 };
0251 
0252 #endif // KGREDITOR_H