/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #ifndef GAME_EDITOR_EDITOR_H #define GAME_EDITOR_EDITOR_H #include #include #include #include #include #include #include #include #include #include "auto_map.h" #include using namespace std::chrono_literals; typedef void (*INDEX_MODIFY_FUNC)(int *pIndex); //CRenderTools m_RenderTools; // CEditor SPECIFIC enum { MODE_LAYERS = 0, MODE_IMAGES, MODE_SOUNDS, DIALOG_NONE = 0, DIALOG_FILE, }; class CEnvelope { public: int m_Channels; std::vector m_lPoints; char m_aName[32]; float m_Bottom, m_Top; bool m_Synchronized; CEnvelope(int Chan) { m_Channels = Chan; m_aName[0] = 0; m_Bottom = 0; m_Top = 0; m_Synchronized = false; } void Resort() { std::sort(m_lPoints.begin(), m_lPoints.end()); FindTopBottom(0xf); } void FindTopBottom(int ChannelMask) { m_Top = -1000000000.0f; m_Bottom = 1000000000.0f; for(auto &Point : m_lPoints) { for(int c = 0; c < m_Channels; c++) { if(ChannelMask & (1 << c)) { float v = fx2f(Point.m_aValues[c]); if(v > m_Top) m_Top = v; if(v < m_Bottom) m_Bottom = v; } } } } int Eval(float Time, float *pResult) { CRenderTools::RenderEvalEnvelope(&m_lPoints[0], m_lPoints.size(), m_Channels, std::chrono::nanoseconds((int64_t)((double)Time * (double)std::chrono::nanoseconds(1s).count())), pResult); return m_Channels; } void AddPoint(int Time, int v0, int v1 = 0, int v2 = 0, int v3 = 0) { CEnvPoint p; p.m_Time = Time; p.m_aValues[0] = v0; p.m_aValues[1] = v1; p.m_aValues[2] = v2; p.m_aValues[3] = v3; p.m_Curvetype = CURVETYPE_LINEAR; m_lPoints.push_back(p); Resort(); } float EndTime() const { if(!m_lPoints.empty()) return m_lPoints[m_lPoints.size() - 1].m_Time * (1.0f / 1000.0f); return 0; } }; class CLayer; class CLayerGroup; class CEditorMap; class CLayer { public: class CEditor *m_pEditor; class IGraphics *Graphics(); class ITextRender *TextRender(); CLayer() { m_Type = LAYERTYPE_INVALID; str_copy(m_aName, "(invalid)", sizeof(m_aName)); m_Visible = true; m_Readonly = false; m_Flags = 0; m_pEditor = 0; m_BrushRefCount = 0; } virtual ~CLayer() { } virtual void BrushSelecting(CUIRect Rect) {} virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { return 0; } virtual void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) {} virtual void BrushDraw(CLayer *pBrush, float x, float y) {} virtual void BrushPlace(CLayer *pBrush, float x, float y) {} virtual void BrushFlipX() {} virtual void BrushFlipY() {} virtual void BrushRotate(float Amount) {} virtual void Render(bool Tileset = false) {} virtual int RenderProperties(CUIRect *pToolbox) { return 0; } virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) {} virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) {} virtual void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc) {} virtual void GetSize(float *w, float *h) { *w = 0; *h = 0; } char m_aName[12]; int m_Type; int m_Flags; bool m_Readonly; bool m_Visible; int m_BrushRefCount; }; class CLayerGroup { public: class CEditorMap *m_pMap; std::vector m_lLayers; int m_OffsetX; int m_OffsetY; int m_ParallaxX; int m_ParallaxY; int m_UseClipping; int m_ClipX; int m_ClipY; int m_ClipW; int m_ClipH; char m_aName[12]; bool m_GameGroup; bool m_Visible; bool m_Collapse; CLayerGroup(); ~CLayerGroup(); void Convert(CUIRect *pRect); void Render(); void MapScreen(); void Mapping(float *pPoints); void GetSize(float *w, float *h) const; void DeleteLayer(int Index); int SwapLayers(int Index0, int Index1); bool IsEmpty() const { return m_lLayers.size() == 0; // stupid function, since its bad for Fillselection: TODO add a function for Fillselection that returns whether a specific tile is used in the given layer } /*bool IsUsedInThisLayer(int Layer, int Index) // <--------- this is what i meant but cause i don't know which Indexes belongs to which layers i can't finish yet { switch Layer { case LAYERTYPE_GAME: // security return true; case LAYERTYPE_FRONT: return true; case LAYERTYPE_TELE: { if (Index ==) // you could add an 2D array into mapitems.h which defines which Indexes belong to which layer(s) } case LAYERTYPE_SPEEDUP: { if (Index == TILE_BOOST) return true; else return false; } case LAYERTYPE_SWITCH: { } case LAYERTYPE_TUNE: { if (Index == TILE_TUNE) return true; else return false; } default: return false; } }*/ void Clear() { m_lLayers.clear(); } void AddLayer(CLayer *l); void ModifyImageIndex(INDEX_MODIFY_FUNC Func) { for(auto &pLayer : m_lLayers) pLayer->ModifyImageIndex(Func); } void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) { for(auto &pLayer : m_lLayers) pLayer->ModifyEnvelopeIndex(Func); } void ModifySoundIndex(INDEX_MODIFY_FUNC Func) { for(auto &pLayer : m_lLayers) pLayer->ModifySoundIndex(Func); } }; class CEditorImage : public CImageInfo { public: CEditor *m_pEditor; CEditorImage(CEditor *pEditor) : m_AutoMapper(pEditor) { m_pEditor = pEditor; m_aName[0] = 0; m_External = 0; m_Width = 0; m_Height = 0; m_pData = 0; m_Format = 0; } ~CEditorImage(); void AnalyseTileFlags(); IGraphics::CTextureHandle m_Texture; int m_External; char m_aName[128]; unsigned char m_aTileFlags[256]; class CAutoMapper m_AutoMapper; }; class CEditorSound { public: CEditor *m_pEditor; CEditorSound(CEditor *pEditor) { m_pEditor = pEditor; m_aName[0] = 0; m_SoundID = 0; m_pData = 0x0; m_DataSize = 0; } ~CEditorSound(); int m_SoundID; char m_aName[128]; void *m_pData; unsigned m_DataSize; }; class CEditorMap { void MakeGameGroup(CLayerGroup *pGroup); void MakeGameLayer(CLayer *pLayer); public: CEditor *m_pEditor; bool m_Modified; CEditorMap() { Clean(); } ~CEditorMap() { Clean(); } std::vector m_lGroups; std::vector m_lImages; std::vector m_lEnvelopes; std::vector m_lSounds; class CMapInfo { public: char m_aAuthorTmp[32]; char m_aVersionTmp[16]; char m_aCreditsTmp[128]; char m_aLicenseTmp[32]; char m_aAuthor[32]; char m_aVersion[16]; char m_aCredits[128]; char m_aLicense[32]; void Reset() { m_aAuthorTmp[0] = 0; m_aVersionTmp[0] = 0; m_aCreditsTmp[0] = 0; m_aLicenseTmp[0] = 0; m_aAuthor[0] = 0; m_aVersion[0] = 0; m_aCredits[0] = 0; m_aLicense[0] = 0; } }; CMapInfo m_MapInfo; struct CSetting { char m_aCommand[256]; }; std::vector m_lSettings; class CLayerGame *m_pGameLayer; CLayerGroup *m_pGameGroup; CEnvelope *NewEnvelope(int Channels) { m_Modified = true; CEnvelope *e = new CEnvelope(Channels); m_lEnvelopes.push_back(e); return e; } void DeleteEnvelope(int Index); CLayerGroup *NewGroup() { m_Modified = true; CLayerGroup *g = new CLayerGroup; g->m_pMap = this; m_lGroups.push_back(g); return g; } int SwapGroups(int Index0, int Index1) { if(Index0 < 0 || Index0 >= (int)m_lGroups.size()) return Index0; if(Index1 < 0 || Index1 >= (int)m_lGroups.size()) return Index0; if(Index0 == Index1) return Index0; m_Modified = true; std::swap(m_lGroups[Index0], m_lGroups[Index1]); return Index1; } void DeleteGroup(int Index) { if(Index < 0 || Index >= (int)m_lGroups.size()) return; m_Modified = true; delete m_lGroups[Index]; m_lGroups.erase(m_lGroups.begin() + Index); } void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) { m_Modified = true; for(auto &pGroup : m_lGroups) pGroup->ModifyImageIndex(pfnFunc); } void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) { m_Modified = true; for(auto &pGroup : m_lGroups) pGroup->ModifyEnvelopeIndex(pfnFunc); } void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc) { m_Modified = true; for(auto &pGroup : m_lGroups) pGroup->ModifySoundIndex(pfnFunc); } void Clean(); void CreateDefault(IGraphics::CTextureHandle EntitiesTexture); // io int Save(class IStorage *pStorage, const char *pFilename); int Load(class IStorage *pStorage, const char *pFilename, int StorageType); // DDRace class CLayerTele *m_pTeleLayer; class CLayerSpeedup *m_pSpeedupLayer; class CLayerFront *m_pFrontLayer; class CLayerSwitch *m_pSwitchLayer; class CLayerTune *m_pTuneLayer; void MakeTeleLayer(CLayer *pLayer); void MakeSpeedupLayer(CLayer *pLayer); void MakeFrontLayer(CLayer *pLayer); void MakeSwitchLayer(CLayer *pLayer); void MakeTuneLayer(CLayer *pLayer); }; struct CProperty { const char *m_pName; int m_Value; int m_Type; int m_Min; int m_Max; }; enum { PROPTYPE_NULL = 0, PROPTYPE_BOOL, PROPTYPE_INT_STEP, PROPTYPE_INT_SCROLL, PROPTYPE_ANGLE_SCROLL, PROPTYPE_COLOR, PROPTYPE_IMAGE, PROPTYPE_ENVELOPE, PROPTYPE_SHIFT, PROPTYPE_SOUND, PROPTYPE_AUTOMAPPER, }; enum { DIRECTION_LEFT = 1, DIRECTION_RIGHT = 2, DIRECTION_UP = 4, DIRECTION_DOWN = 8, }; typedef struct { int x, y; int w, h; } RECTi; class CLayerTiles : public CLayer { protected: template void ShiftImpl(T *pTiles, int Direction, int ShiftBy) { switch(Direction) { case DIRECTION_LEFT: for(int y = 0; y < m_Height; ++y) { mem_move(&pTiles[y * m_Width], &pTiles[y * m_Width + ShiftBy], (m_Width - ShiftBy) * sizeof(T)); mem_zero(&pTiles[y * m_Width + (m_Width - ShiftBy)], ShiftBy * sizeof(T)); } break; case DIRECTION_RIGHT: for(int y = 0; y < m_Height; ++y) { mem_move(&pTiles[y * m_Width + ShiftBy], &pTiles[y * m_Width], (m_Width - ShiftBy) * sizeof(T)); mem_zero(&pTiles[y * m_Width], ShiftBy * sizeof(T)); } break; case DIRECTION_UP: for(int y = 0; y < m_Height - ShiftBy; ++y) { mem_copy(&pTiles[y * m_Width], &pTiles[(y + ShiftBy) * m_Width], m_Width * sizeof(T)); mem_zero(&pTiles[(y + ShiftBy) * m_Width], m_Width * sizeof(T)); } break; case DIRECTION_DOWN: for(int y = m_Height - 1; y >= ShiftBy; --y) { mem_copy(&pTiles[y * m_Width], &pTiles[(y - ShiftBy) * m_Width], m_Width * sizeof(T)); mem_zero(&pTiles[(y - ShiftBy) * m_Width], m_Width * sizeof(T)); } } } public: CLayerTiles(int w, int h); ~CLayerTiles(); virtual CTile GetTile(int x, int y); virtual void SetTile(int x, int y, CTile tile); virtual void Resize(int NewW, int NewH); virtual void Shift(int Direction); void MakePalette(); void Render(bool Tileset = false) override; int ConvertX(float x) const; int ConvertY(float y) const; void Convert(CUIRect Rect, RECTi *pOut); void Snap(CUIRect *pRect); void Clamp(RECTi *pRect); virtual bool IsEmpty(CLayerTiles *pLayer); void BrushSelecting(CUIRect Rect) override; int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) override; void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) override; void BrushDraw(CLayer *pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; void BrushRotate(float Amount) override; virtual void ShowInfo(); int RenderProperties(CUIRect *pToolbox) override; struct SCommonPropState { bool Modified = false; int Width = -1; int Height = -1; int Color = 0; }; static int RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, std::vector &pLayers); void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) override; void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override; void PrepareForSave(); void GetSize(float *w, float *h) override { *w = m_Width * 32.0f; *h = m_Height * 32.0f; } void FlagModified(int x, int y, int w, int h); IGraphics::CTextureHandle m_Texture; int m_Game; int m_Image; int m_Width; int m_Height; CColor m_Color; int m_ColorEnv; int m_ColorEnvOffset; CTile *m_pTiles; // DDRace int m_AutoMapperConfig; int m_Seed; bool m_AutoAutoMap; int m_Tele; int m_Speedup; int m_Front; int m_Switch; int m_Tune; char m_aFileName[IO_MAX_PATH_LENGTH]; }; class CLayerQuads : public CLayer { public: CLayerQuads(); ~CLayerQuads(); void Render(bool QuadPicker = false) override; CQuad *NewQuad(int x, int y, int Width, int Height); void BrushSelecting(CUIRect Rect) override; int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) override; void BrushPlace(CLayer *pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; void BrushRotate(float Amount) override; int RenderProperties(CUIRect *pToolbox) override; void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) override; void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override; void GetSize(float *w, float *h) override; int m_Image; std::vector m_lQuads; }; class CLayerGame : public CLayerTiles { public: CLayerGame(int w, int h); ~CLayerGame(); CTile GetTile(int x, int y) override; void SetTile(int x, int y, CTile tile) override; int RenderProperties(CUIRect *pToolbox) override; }; class CEditor : public IEditor { class IInput *m_pInput; class IClient *m_pClient; class CConfig *m_pConfig; class IConsole *m_pConsole; class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; class ISound *m_pSound; class IStorage *m_pStorage; CRenderTools m_RenderTools; CUI m_UI; CUIEx m_UIEx; bool m_EditorWasUsedBefore = false; IGraphics::CTextureHandle m_EntitiesTexture; IGraphics::CTextureHandle m_FrontTexture; IGraphics::CTextureHandle m_TeleTexture; IGraphics::CTextureHandle m_SpeedupTexture; IGraphics::CTextureHandle m_SwitchTexture; IGraphics::CTextureHandle m_TuneTexture; int GetTextureUsageFlag(); public: class IInput *Input() { return m_pInput; } class IClient *Client() { return m_pClient; } class CConfig *Config() { return m_pConfig; } class IConsole *Console() { return m_pConsole; } class IGraphics *Graphics() { return m_pGraphics; } class ISound *Sound() { return m_pSound; } class ITextRender *TextRender() { return m_pTextRender; } class IStorage *Storage() { return m_pStorage; } CUI *UI() { return &m_UI; } CUIEx *UIEx() { return &m_UIEx; } CRenderTools *RenderTools() { return &m_RenderTools; } CEditor() : m_TilesetPicker(16, 16) { m_pInput = 0; m_pClient = 0; m_pGraphics = 0; m_pTextRender = 0; m_pSound = 0; m_Mode = MODE_LAYERS; m_Dialog = 0; m_EditBoxActive = 0; m_pTooltip = 0; m_GridActive = false; m_GridFactor = 1; m_BrushColorEnabled = true; m_aFileName[0] = 0; m_aFileSaveName[0] = 0; m_ValidSaveFilename = false; m_PopupEventActivated = false; m_PopupEventWasActivated = false; m_MouseInsidePopup = false; m_FileDialogStorageType = 0; m_pFileDialogTitle = 0; m_pFileDialogButtonText = 0; m_pFileDialogUser = 0; m_aFileDialogFileName[0] = 0; m_aFileDialogCurrentFolder[0] = 0; m_aFileDialogCurrentLink[0] = 0; m_pFileDialogPath = m_aFileDialogCurrentFolder; m_FileDialogActivate = false; m_FileDialogOpening = false; m_FileDialogScrollValue = 0.0f; m_FilesSelectedIndex = -1; m_FilesStartAt = 0; m_FilesCur = 0; m_FilesStopAt = 999; m_SelectEntitiesImage = "DDNet"; m_WorldOffsetX = 0; m_WorldOffsetY = 0; m_EditorOffsetX = 0.0f; m_EditorOffsetY = 0.0f; m_WorldZoom = 1.0f; m_ZoomLevel = 200; m_LockMouse = false; m_ShowMousePointer = true; m_MouseDeltaX = 0; m_MouseDeltaY = 0; m_MouseDeltaWx = 0; m_MouseDeltaWy = 0; m_GuiActive = true; m_ProofBorders = false; m_ShowTileInfo = false; m_ShowDetail = true; m_Animate = false; m_AnimateStart = 0; m_AnimateTime = 0; m_AnimateSpeed = 1; m_ShowEnvelopeEditor = 0; m_ShowServerSettingsEditor = false; m_ShowEnvelopePreview = 0; m_SelectedQuadEnvelope = -1; m_SelectedEnvelopePoint = -1; m_QuadKnifeActive = false; m_QuadKnifeCount = 0; m_CommandBox = 0.0f; m_aSettingsCommand[0] = 0; ms_pUiGotContext = 0; // DDRace m_TeleNumber = 1; m_SwitchNum = 1; m_TuningNum = 1; m_SwitchDelay = 0; m_SpeedupForce = 50; m_SpeedupMaxSpeed = 0; m_SpeedupAngle = 0; m_LargeLayerWasWarned = false; m_PreventUnusedTilesWasWarned = false; m_AllowPlaceUnusedTiles = 0; m_BrushDrawDestructive = true; m_Mentions = 0; } void Init() override; void UpdateAndRender() override; bool HasUnsavedData() const override { return m_Map.m_Modified; } void UpdateMentions() override { m_Mentions++; } void ResetMentions() override { m_Mentions = 0; } CLayerGroup *m_apSavedBrushes[10]; void FilelistPopulate(int StorageType); void InvokeFileDialog(int StorageType, int FileType, const char *pTitle, const char *pButtonText, const char *pBasepath, const char *pDefaultName, void (*pfnFunc)(const char *pFilename, int StorageType, void *pUser), void *pUser); void Reset(bool CreateDefault = true); int Save(const char *pFilename) override; int Load(const char *pFilename, int StorageType) override; int Append(const char *pFilename, int StorageType); void LoadCurrentMap(); void Render(); std::vector GetSelectedQuads(); CLayer *GetSelectedLayerType(int Index, int Type) const; CLayer *GetSelectedLayer(int Index) const; CLayerGroup *GetSelectedGroup() const; CSoundSource *GetSelectedSource(); void SelectLayer(int LayerIndex, int GroupIndex = -1); void AddSelectedLayer(int LayerIndex); void SelectQuad(int Index); void DeleteSelectedQuads(); bool IsQuadSelected(int Index) const; int FindSelectedQuadIndex(int Index) const; float ScaleFontSize(char *pText, int TextSize, float FontSize, int Width); int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIDs, int *pNewVal, ColorRGBA Color = ColorRGBA(1, 1, 1, 0.5f)); int m_Mode; int m_Dialog; int m_EditBoxActive; const char *m_pTooltip; bool m_GridActive; int m_GridFactor; bool m_BrushColorEnabled; char m_aFileName[IO_MAX_PATH_LENGTH]; char m_aFileSaveName[IO_MAX_PATH_LENGTH]; bool m_ValidSaveFilename; enum { POPEVENT_EXIT = 0, POPEVENT_LOAD, POPEVENT_LOADCURRENT, POPEVENT_NEW, POPEVENT_SAVE, POPEVENT_LARGELAYER, POPEVENT_PREVENTUNUSEDTILES, POPEVENT_IMAGEDIV16, POPEVENT_IMAGE_MAX, POPEVENT_PLACE_BORDER_TILES }; int m_PopupEventType; int m_PopupEventActivated; int m_PopupEventWasActivated; bool m_MouseInsidePopup; bool m_LargeLayerWasWarned; bool m_PreventUnusedTilesWasWarned; int m_AllowPlaceUnusedTiles; bool m_BrushDrawDestructive; int m_Mentions; enum { FILETYPE_MAP, FILETYPE_IMG, FILETYPE_SOUND, }; int m_FileDialogStorageType; const char *m_pFileDialogTitle; const char *m_pFileDialogButtonText; void (*m_pfnFileDialogFunc)(const char *pFileName, int StorageType, void *pUser); void *m_pFileDialogUser; char m_aFileDialogFileName[IO_MAX_PATH_LENGTH]; char m_aFileDialogCurrentFolder[IO_MAX_PATH_LENGTH]; char m_aFileDialogCurrentLink[IO_MAX_PATH_LENGTH]; char m_aFileDialogSearchText[64]; char m_aFileDialogPrevSearchText[64]; char *m_pFileDialogPath; bool m_FileDialogActivate; int m_FileDialogFileType; float m_FileDialogScrollValue; int m_FilesSelectedIndex; char m_aFileDialogNewFolderName[64]; char m_FileDialogErrString[64]; IGraphics::CTextureHandle m_FilePreviewImage; bool m_PreviewImageIsLoaded; CImageInfo m_FilePreviewImageInfo; bool m_FileDialogOpening; struct CFilelistItem { char m_aFilename[IO_MAX_PATH_LENGTH]; char m_aName[128]; bool m_IsDir; bool m_IsLink; int m_StorageType; bool m_IsVisible; bool operator<(const CFilelistItem &Other) const { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : str_comp_nocase(m_aFilename, Other.m_aFilename) < 0; } }; std::vector m_FileList; int m_FilesStartAt; int m_FilesCur; int m_FilesStopAt; std::vector m_SelectEntitiesFiles; std::string m_SelectEntitiesImage; float m_WorldOffsetX; float m_WorldOffsetY; float m_EditorOffsetX; float m_EditorOffsetY; float m_WorldZoom; int m_ZoomLevel; bool m_LockMouse; bool m_ShowMousePointer; bool m_GuiActive; bool m_ProofBorders; float m_MouseDeltaX; float m_MouseDeltaY; float m_MouseDeltaWx; float m_MouseDeltaWy; bool m_ShowTileInfo; bool m_ShowDetail; bool m_Animate; int64_t m_AnimateStart; float m_AnimateTime; float m_AnimateSpeed; int m_ShowEnvelopeEditor; int m_ShowEnvelopePreview; //Values: 0-Off|1-Selected Envelope|2-All bool m_ShowServerSettingsEditor; bool m_ShowPicker; std::vector m_lSelectedLayers; std::vector m_lSelectedQuads; int m_SelectedQuadPoint; int m_SelectedQuadIndex; int m_SelectedGroup; int m_SelectedPoints; int m_SelectedEnvelope; int m_SelectedEnvelopePoint; int m_SelectedQuadEnvelope; int m_SelectedImage; int m_SelectedSound; int m_SelectedSource; bool m_QuadKnifeActive; int m_QuadKnifeCount; vec2 m_aQuadKnifePoints[4]; IGraphics::CTextureHandle m_CheckerTexture; IGraphics::CTextureHandle m_BackgroundTexture; IGraphics::CTextureHandle m_CursorTexture; IGraphics::CTextureHandle GetEntitiesTexture(); CLayerGroup m_Brush; CLayerTiles m_TilesetPicker; CLayerQuads m_QuadsetPicker; static const void *ms_pUiGotContext; CEditorMap m_Map; int m_ShiftBy; static void EnvelopeEval(int TimeOffsetMillis, int Env, float *pChannels, void *pUser); float m_CommandBox; char m_aSettingsCommand[256]; void PlaceBorderTiles(); int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int AlignVert = 1); int DoButton_Env(const void *pID, const char *pText, int Checked, const CUIRect *pRect, const char *pToolTip, ColorRGBA Color); int DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners, float FontSize = 10.0f, int AlignVert = 1); int DoButton_ButtonDec(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags = 0, const char *pToolTip = 0); int DoButton_ColorPicker(const void *pID, const CUIRect *pRect, ColorRGBA *pColor, const char *pToolTip = 0); bool DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = CUI::CORNER_ALL); bool DoClearableEditBox(void *pID, void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners); void RenderBackground(CUIRect View, IGraphics::CTextureHandle Texture, float Size, float Brightness); void RenderGrid(CLayerGroup *pGroup); void UiInvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect, void *pContext), void *pContext = 0); void UiDoPopupMenu(); bool UiPopupExists(void *pID); bool UiPopupOpen(); int UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip, bool IsDegree = false, bool IsHex = false, int corners = CUI::CORNER_ALL, ColorRGBA *Color = 0); static int PopupGroup(CEditor *pEditor, CUIRect View, void *pContext); struct CLayerPopupContext { std::vector m_aLayers; CLayerTiles::SCommonPropState m_CommonPropState; }; static int PopupLayer(CEditor *pEditor, CUIRect View, void *pContext); static int PopupQuad(CEditor *pEditor, CUIRect View, void *pContext); static int PopupPoint(CEditor *pEditor, CUIRect View, void *pContext); static int PopupNewFolder(CEditor *pEditor, CUIRect View, void *pContext); static int PopupMapInfo(CEditor *pEditor, CUIRect View, void *pContext); static int PopupEvent(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSelectImage(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSelectSound(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSelectGametileOp(CEditor *pEditor, CUIRect View, void *pContext); static int PopupImage(CEditor *pEditor, CUIRect View, void *pContext); static int PopupMenuFile(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSound(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSource(CEditor *pEditor, CUIRect View, void *pContext); static int PopupColorPicker(CEditor *pEditor, CUIRect View, void *pContext); static int PopupEntities(CEditor *pEditor, CUIRect View, void *pContext); static void CallbackOpenMap(const char *pFileName, int StorageType, void *pUser); static void CallbackAppendMap(const char *pFileName, int StorageType, void *pUser); static void CallbackSaveMap(const char *pFileName, int StorageType, void *pUser); static void CallbackSaveCopyMap(const char *pFileName, int StorageType, void *pUser); void PopupSelectImageInvoke(int Current, float x, float y); int PopupSelectImageResult(); void PopupSelectGametileOpInvoke(float x, float y); int PopupSelectGameTileOpResult(); void PopupSelectConfigAutoMapInvoke(int Current, float x, float y); int PopupSelectConfigAutoMapResult(); void PopupSelectSoundInvoke(int Current, float x, float y); int PopupSelectSoundResult(); void DoQuadEnvelopes(const std::vector &m_lQuads, IGraphics::CTextureHandle Texture = IGraphics::CTextureHandle()); void DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int pIndex); void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v); float TriangleArea(vec2 A, vec2 B, vec2 C); bool IsInTriangle(vec2 Point, vec2 A, vec2 B, vec2 C); void DoQuadKnife(int QuadIndex); void DoSoundSource(CSoundSource *pSource, int Index); void DoMapEditor(CUIRect View); void DoToolbar(CUIRect Toolbar); void DoQuad(CQuad *pQuad, int Index); ColorRGBA GetButtonColor(const void *pID, int Checked); static void ReplaceImage(const char *pFilename, int StorageType, void *pUser); static void ReplaceSound(const char *pFileName, int StorageType, void *pUser); static void AddImage(const char *pFilename, int StorageType, void *pUser); static void AddSound(const char *pFileName, int StorageType, void *pUser); bool IsEnvelopeUsed(int EnvelopeIndex) const; void RenderImages(CUIRect Toolbox, CUIRect View); void RenderLayers(CUIRect Toolbox, CUIRect View); void RenderSounds(CUIRect Toolbox, CUIRect View); void RenderModebar(CUIRect View); void RenderStatusbar(CUIRect View); void RenderEnvelopeEditor(CUIRect View); void RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEditorLast); void RenderMenubar(CUIRect Menubar); void RenderFileDialog(); void AddFileDialogEntry(int Index, CUIRect *pView); void SelectGameLayer(); void SortImages(); void SelectLayerByTile(float &Scroll); //Tile Numbers For Explanations - TODO: Add/Improve tiles and explanations enum { TILE_PUB_AIR, TILE_PUB_HOOKABLE, TILE_PUB_DEATH, TILE_PUB_UNHOOKABLE, TILE_PUB_CREDITS1 = 140, TILE_PUB_CREDITS2, TILE_PUB_CREDITS3, TILE_PUB_CREDITS4, TILE_PUB_CREDITS5 = 156, TILE_PUB_CREDITS6, TILE_PUB_CREDITS7, TILE_PUB_CREDITS8, TILE_PUB_ENTITIES_OFF1 = 190, TILE_PUB_ENTITIES_OFF2, }; enum { TILE_FNG_SPIKE_GOLD = 7, TILE_FNG_SPIKE_NORMAL, TILE_FNG_SPIKE_RED, TILE_FNG_SPIKE_BLUE, TILE_FNG_SCORE_RED, TILE_FNG_SCORE_BLUE, TILE_FNG_SPIKE_GREEN = 14, TILE_FNG_SPIKE_PURPLE, TILE_FNG_SPAWN = 192, TILE_FNG_SPAWN_RED, TILE_FNG_SPAWN_BLUE, TILE_FNG_FLAG_RED, TILE_FNG_FLAG_BLUE, TILE_FNG_SHIELD, TILE_FNG_HEART, TILE_FNG_SHOTGUN, TILE_FNG_GRENADE, TILE_FNG_NINJA, TILE_FNG_LASER, TILE_FNG_SPIKE_OLD1 = 208, TILE_FNG_SPIKE_OLD2, TILE_FNG_SPIKE_OLD3 }; enum { TILE_VANILLA_SPAWN = 192, TILE_VANILLA_SPAWN_RED, TILE_VANILLA_SPAWN_BLUE, TILE_VANILLA_FLAG_RED, TILE_VANILLA_FLAG_BLUE, TILE_VANILLA_SHIELD, TILE_VANILLA_HEART, TILE_VANILLA_SHOTGUN, TILE_VANILLA_GRENADE, TILE_VANILLA_NINJA, TILE_VANILLA_LASER, }; //Explanations enum { EXPLANATION_DDNET, EXPLANATION_FNG, EXPLANATION_RACE, EXPLANATION_VANILLA, EXPLANATION_BLOCKWORLDS }; static const char *Explain(int ExplanationID, int Tile, int Layer); int GetLineDistance() const; void ZoomMouseTarget(float ZoomFactor); static ColorHSVA ms_PickerColor; static int ms_SVPicker; static int ms_HuePicker; // DDRace IGraphics::CTextureHandle GetFrontTexture(); IGraphics::CTextureHandle GetTeleTexture(); IGraphics::CTextureHandle GetSpeedupTexture(); IGraphics::CTextureHandle GetSwitchTexture(); IGraphics::CTextureHandle GetTuneTexture(); static int PopupTele(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSpeedup(CEditor *pEditor, CUIRect View, void *pContext); static int PopupSwitch(CEditor *pEditor, CUIRect View, void *pContext); static int PopupTune(CEditor *pEditor, CUIRect View, void *pContext); unsigned char m_TeleNumber; unsigned char m_TuningNum; unsigned char m_SpeedupForce; unsigned char m_SpeedupMaxSpeed; short m_SpeedupAngle; unsigned char m_SwitchNum; unsigned char m_SwitchDelay; }; // make sure to inline this function inline class IGraphics *CLayer::Graphics() { return m_pEditor->Graphics(); } inline class ITextRender *CLayer::TextRender() { return m_pEditor->TextRender(); } // DDRace class CLayerTele : public CLayerTiles { public: CLayerTele(int w, int h); ~CLayerTele(); CTeleTile *m_pTeleTile; unsigned char m_TeleNum; void Resize(int NewW, int NewH) override; void Shift(int Direction) override; bool IsEmpty(CLayerTiles *pLayer) override; void BrushDraw(CLayer *pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; void BrushRotate(float Amount) override; void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) override; virtual bool ContainsElementWithId(int Id); }; class CLayerSpeedup : public CLayerTiles { public: CLayerSpeedup(int w, int h); ~CLayerSpeedup(); CSpeedupTile *m_pSpeedupTile; int m_SpeedupForce; int m_SpeedupMaxSpeed; int m_SpeedupAngle; void Resize(int NewW, int NewH) override; void Shift(int Direction) override; bool IsEmpty(CLayerTiles *pLayer) override; void BrushDraw(CLayer *pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; void BrushRotate(float Amount) override; void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) override; }; class CLayerFront : public CLayerTiles { public: CLayerFront(int w, int h); void Resize(int NewW, int NewH) override; void SetTile(int x, int y, CTile tile) override; }; class CLayerSwitch : public CLayerTiles { public: CLayerSwitch(int w, int h); ~CLayerSwitch(); CSwitchTile *m_pSwitchTile; unsigned char m_SwitchNumber; unsigned char m_SwitchDelay; void Resize(int NewW, int NewH) override; void Shift(int Direction) override; bool IsEmpty(CLayerTiles *pLayer) override; void BrushDraw(CLayer *pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; void BrushRotate(float Amount) override; void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) override; virtual bool ContainsElementWithId(int Id); }; class CLayerTune : public CLayerTiles { public: CLayerTune(int w, int h); ~CLayerTune(); CTuneTile *m_pTuneTile; unsigned char m_TuningNumber; void Resize(int NewW, int NewH) override; void Shift(int Direction) override; bool IsEmpty(CLayerTiles *pLayer) override; void BrushDraw(CLayer *pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; void BrushRotate(float Amount) override; void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) override; }; class CLayerSounds : public CLayer { public: CLayerSounds(); ~CLayerSounds(); void Render(bool Tileset = false) override; CSoundSource *NewSource(int x, int y); void BrushSelecting(CUIRect Rect) override; int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) override; void BrushPlace(CLayer *pBrush, float wx, float wy) override; int RenderProperties(CUIRect *pToolbox) override; void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override; void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc) override; int m_Sound; std::vector m_lSources; }; #endif