If you have comments or questions concerning this source file, discuss them in the forum.
/*
Copyright (c) 2002 Nicolai Haehnle

See the license.txt for details. If that file was not included in the
source distributions, please email <prefect@rtts.org>
*/
// editor.h - included by all editor modules

#include "game.h"

#include "gui_panel.h"
#include "gui_checkbox.h"

/*
==============================================================================

TILESETS

==============================================================================
*/

// tile type border; bit 0: positive axis; bit 1: vertical
#define ttb_left    0
#define ttb_right   1
#define ttb_bottom  2
#define ttb_top     3

struct ed_tiletype_t {
    int     border[4];  // -1 = any
    bool    noauto;     // don't autoplace this tile type (border adj)
};

class EdTilePool {
public:
    char            *m_pszName;
    LPool<unsigned> m_ids;

public:
    EdTilePool(const char *pszName);
    ~EdTilePool();
};

class EdTilesets {
public:
    ETileTypes      m_tiletypes;
    unsigned        m_iNumTypesEx;
    ed_tiletype_t   *m_pTypesEx;

    int             m_iNumBorderNames;
    char            **m_pBorderNames;

    int             m_iNumTilesets;
    EdTilePool      **m_ppTilesets;

    EdTilePool      *m_pCurrent;
    int             m_iCurIdx;
    unsigned        m_iCurTile;

public:
    EdTilesets();
    ~EdTilesets();

    void Load();
    void LoadTileset(const char *name);

    int GetBorderByName(const char *name);
    ed_tiletype_t *GetTileTypeEx(unsigned id);

    bool isCurTileValid();

    void SetTileset(int id);
    void SetCurTile(unsigned id);
    void SetCurIdx(int idx);
    void NextTile();
    void PrevTile();
};

/*
==============================================================================

Editor CLASS

==============================================================================
*/

/*
The editor can be in tile editing mode or unit editing mode.
*/
enum {
    tlm_tile = 1,
    tlm_unit,
};

class Editor : public GPanel {
public:
    bool            m_bDirty;
    EdTilesets      m_tilesets;
    ELevel          m_level;

    int             m_numunittypes;
    airunit_type_t  **m_unittypes;

    float           m_flScrollSpeed;
    int             m_iScrollTime;

    int             m_iMode;        // current state

    GButton         *m_pModeButton;

public:
    Editor();
    ~Editor();

    void LoadUnitTypes();

    void SetTLM(int mode);
    void LeaveTLM();

    void EditorQuit(int id);
    void Options(int id);
    void Mode_Pick(int id);
    void ToggleMode(int id);

    void TestRun();

    void SnapToGrid(float *px, float *py);

private: // logic and refresh
    void Scroll(float speed);

    virtual void Logic();
    void DrawAirJobs();
    virtual void Draw();

    virtual bool Key(int code, char c, bool down);
    virtual bool MouseButton(int btn, int x, int y, bool down);
    virtual void MouseMove(int x, int y);

public: // TLM: Tile editing
    bool        m_bInPaint;     // currently painting

    void Tile_Enter(); // enter tile mode
    void Tile_Leave();

    int Tile_FixTile(int tx, int ty, int changable);
    void Tile_DoPlace(int tx, int ty, int tile);

    void Tile_Logic(byte *keystate, int btns, int mx, int my);
    bool Tile_MouseButton(int btn, int x, int y, bool down);
    bool Tile_Key(int code, char c, bool down);
    void Tile_Draw();

    void Tile_Pick();

public: // TLM: Unit editing
    std::vector<airjob_t>   unit_Formation; // the formation we are currently placing

    bool    unit_bSelecting; // true while selecting
    float   unit_flSelectStartX; // selection box
    float   unit_flSelectStartY;

    bool    unit_bDragStart; // initiate drag (set by Unit_DragStart, unset by Unit_DragEnd)
    bool    unit_bDragSelectIfFail;
    bool    unit_bDrag; // reached a critical distance where we actually change the map
    float   unit_flDragX;
    float   unit_flDragY;
    airjob_t    *unit_pDragNodeJob; // non-zero if we're dragging a node instead of units
    int         unit_iDragNodeIdx;

    airjob_t    *unit_pEditNodeJob; // information for Unit_Node_* handlers
    int         unit_iEditNodeIdx;

    // list of selected units; note: you _must_ unselect all units when
    // a unit is created or removed
    std::vector<airjob_t*>  unit_Selected;

    void SetCurUnit(int id);
    void SetCurUnitByType(airunit_type_t *type);

    void Unit_Enter();
    void Unit_Leave();

    bool Unit_IsSelected(airjob_t *aj);
    void Unit_AddToSelection(const std::vector<airjob_t*> &list);
    void Unit_RemoveFromSelection(const std::vector<airjob_t*> &list);

    void Unit_DragStart(float lx, float ly, bool selectiffail);
    void Unit_DragStart(float lx, float ly, airjob_t *aj, int idx);
    void Unit_DragUpdate(float lx, float ly);
    void Unit_DragEnd();

    void Unit_Action_Level();
    void Unit_Action_Mirror();
    void Unit_Action_Copy();
    void Unit_Action_Delete();

    void Unit_Node_Add();
    void Unit_Node_AddRel();
    void Unit_Node_Delete();
    void Unit_Node_DeleteRel();

    void Unit_NodeRightClick(airjob_t *aj, int idx);
    void Unit_RightClick();

    bool Unit_MouseButton(int btn, int x, int y, bool down);
    void Unit_MouseMove(int x, int y);

    bool Unit_Key(int code, char c, bool down);

    void Unit_Draw();
    void Unit_DrawAirjob(airjob_t *aj, float relx = 0, float rely = 0, int a = 255);
    void Unit_DrawAirjobNodes(airjob_t *aj, float relx = 0, float rely = 0, int a = 255);

    void Unit_Pick();
/*
public: // em_sel_unit
    int         m_iNumSelected;
    airjob_t    **m_pSelected;

    bool        m_bSelectDragStart;
    bool        m_bSelectDrag;
    float       m_flSelectDragX;
    float       m_flSelectDragY;

    void ClearSelect();
    void ToggleSelect(airjob_t *aj);
    bool IsSelected(airjob_t *aj);

    void Select_Enter();
    void Select_Leave();

    bool Select_MouseButton(int btn, int x, int y, bool down);
    void Select_MouseMove(int x, int y);
    bool Select_Key(int code, char c, bool down);
    void Select_DrawAirjob(airjob_t *aj);

public: // node manipulation (not a distinct editor state)
    airjob_t    *m_pNodeDragJob;
    int         m_iNodeDragIdx;
    float       m_flNodeDragX;
    float       m_flNodeDragY;
    bool        m_bNodeDrag;

    void Node_Action(airjob_t *aj, int idx, int x, int y);
    bool Node_MouseButton(int btn, int x, int y, bool down);
    void Node_MouseMove(int x, int y);
*/
};