/* (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 #include #include #include #include #include #include #include #include #include #include #include #include #include "auto_map.h" #include "map_view.h" #include "smooth_value.h" #include #include #include #include #include #include typedef std::function FIndexModifyFunction; // CEditor SPECIFIC enum { MODE_LAYERS = 0, MODE_IMAGES, MODE_SOUNDS, NUM_MODES, DIALOG_NONE = 0, DIALOG_FILE, }; class CEditorImage; class CEditorSound; class CEditorMap { void MakeGameGroup(std::shared_ptr pGroup); void MakeGameLayer(const std::shared_ptr &pLayer); public: CEditor *m_pEditor; CEditorMap() { Clean(); } ~CEditorMap() { Clean(); } bool m_Modified; // unsaved changes in manual save bool m_ModifiedAuto; // unsaved changes in autosave float m_LastModifiedTime; float m_LastSaveTime; float m_LastAutosaveUpdateTime; void OnModify(); std::vector> m_vpGroups; std::vector> m_vpImages; std::vector> m_vpEnvelopes; std::vector> m_vpSounds; class CMapInfo { public: char m_aAuthor[32]; char m_aVersion[16]; char m_aCredits[128]; char m_aLicense[32]; void Reset() { m_aAuthor[0] = '\0'; m_aVersion[0] = '\0'; m_aCredits[0] = '\0'; m_aLicense[0] = '\0'; } void Copy(const CMapInfo &Source) { str_copy(m_aAuthor, Source.m_aAuthor); str_copy(m_aVersion, Source.m_aVersion); str_copy(m_aCredits, Source.m_aCredits); str_copy(m_aLicense, Source.m_aLicense); } }; CMapInfo m_MapInfo; CMapInfo m_MapInfoTmp; struct CSetting { char m_aCommand[256]; CSetting(const char *pCommand) { str_copy(m_aCommand, pCommand); } }; std::vector m_vSettings; std::shared_ptr m_pGameLayer; std::shared_ptr m_pGameGroup; std::shared_ptr NewEnvelope(CEnvelope::EType Type) { OnModify(); std::shared_ptr pEnv = std::make_shared(Type); m_vpEnvelopes.push_back(pEnv); return pEnv; } void DeleteEnvelope(int Index); void SwapEnvelopes(int Index0, int Index1); template void VisitEnvelopeReferences(F &&Visitor); std::shared_ptr NewGroup() { OnModify(); std::shared_ptr pGroup = std::make_shared(); pGroup->m_pMap = this; m_vpGroups.push_back(pGroup); return pGroup; } int SwapGroups(int Index0, int Index1) { if(Index0 < 0 || Index0 >= (int)m_vpGroups.size()) return Index0; if(Index1 < 0 || Index1 >= (int)m_vpGroups.size()) return Index0; if(Index0 == Index1) return Index0; OnModify(); std::swap(m_vpGroups[Index0], m_vpGroups[Index1]); return Index1; } void DeleteGroup(int Index) { if(Index < 0 || Index >= (int)m_vpGroups.size()) return; OnModify(); m_vpGroups.erase(m_vpGroups.begin() + Index); } void ModifyImageIndex(FIndexModifyFunction pfnFunc) { OnModify(); for(auto &pGroup : m_vpGroups) pGroup->ModifyImageIndex(pfnFunc); } void ModifyEnvelopeIndex(FIndexModifyFunction pfnFunc) { OnModify(); for(auto &pGroup : m_vpGroups) pGroup->ModifyEnvelopeIndex(pfnFunc); } void ModifySoundIndex(FIndexModifyFunction pfnFunc) { OnModify(); for(auto &pGroup : m_vpGroups) pGroup->ModifySoundIndex(pfnFunc); } void Clean(); void CreateDefault(IGraphics::CTextureHandle EntitiesTexture); // io bool Save(const char *pFilename); bool Load(const char *pFilename, int StorageType, const std::function &ErrorHandler); void PerformSanityChecks(const std::function &ErrorHandler); // DDRace std::shared_ptr m_pTeleLayer; std::shared_ptr m_pSpeedupLayer; std::shared_ptr m_pFrontLayer; std::shared_ptr m_pSwitchLayer; std::shared_ptr m_pTuneLayer; void MakeTeleLayer(const std::shared_ptr &pLayer); void MakeSpeedupLayer(const std::shared_ptr &pLayer); void MakeFrontLayer(const std::shared_ptr &pLayer); void MakeSwitchLayer(const std::shared_ptr &pLayer); void MakeTuneLayer(const std::shared_ptr &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, }; class CDataFileWriterFinishJob : public IJob { char m_aRealFileName[IO_MAX_PATH_LENGTH]; char m_aTempFileName[IO_MAX_PATH_LENGTH]; CDataFileWriter m_Writer; void Run() override { m_Writer.Finish(); } public: CDataFileWriterFinishJob(const char *pRealFileName, const char *pTempFileName, CDataFileWriter &&Writer) : m_Writer(std::move(Writer)) { str_copy(m_aRealFileName, pRealFileName); str_copy(m_aTempFileName, pTempFileName); } const char *GetRealFileName() const { return m_aRealFileName; } const char *GetTempFileName() const { return m_aTempFileName; } }; class CEditor : public IEditor { class IInput *m_pInput = nullptr; class IClient *m_pClient = nullptr; class CConfig *m_pConfig = nullptr; class IConsole *m_pConsole = nullptr; class IEngine *m_pEngine = nullptr; class IGraphics *m_pGraphics = nullptr; class ITextRender *m_pTextRender = nullptr; class ISound *m_pSound = nullptr; class IStorage *m_pStorage = nullptr; CRenderTools m_RenderTools; CUI m_UI; std::vector> m_vComponents; CMapView m_MapView; 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(); enum EPreviewState { PREVIEW_UNLOADED, PREVIEW_LOADED, PREVIEW_ERROR, }; std::shared_ptr m_apSavedBrushes[10]; 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 IEngine *Engine() { return m_pEngine; } 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; } CRenderTools *RenderTools() { return &m_RenderTools; } CMapView *MapView() { return &m_MapView; } const CMapView *MapView() const { return &m_MapView; } CEditor() : m_ZoomEnvelopeX(1.0f, 0.1f, 600.0f), m_ZoomEnvelopeY(640.0f, 0.1f, 32000.0f) { m_EntitiesTexture.Invalidate(); m_FrontTexture.Invalidate(); m_TeleTexture.Invalidate(); m_SpeedupTexture.Invalidate(); m_SwitchTexture.Invalidate(); m_TuneTexture.Invalidate(); m_Mode = MODE_LAYERS; m_Dialog = 0; m_BrushColorEnabled = true; m_aFileName[0] = '\0'; m_aFileNamePending[0] = '\0'; m_aFileSaveName[0] = '\0'; m_ValidSaveFilename = false; m_PopupEventActivated = false; m_PopupEventWasActivated = false; m_FileDialogStorageType = 0; m_FileDialogLastPopulatedStorageType = 0; m_pFileDialogTitle = nullptr; m_pFileDialogButtonText = nullptr; m_pFileDialogUser = nullptr; m_aFileDialogCurrentFolder[0] = '\0'; m_aFileDialogCurrentLink[0] = '\0'; m_aFilesSelectedName[0] = '\0'; m_pFileDialogPath = m_aFileDialogCurrentFolder; m_FileDialogOpening = false; m_FilesSelectedIndex = -1; m_FilePreviewImage.Invalidate(); m_FilePreviewSound = -1; m_FilePreviewState = PREVIEW_UNLOADED; m_ToolbarPreviewSound = -1; m_SelectEntitiesImage = "DDNet"; m_ResetZoomEnvelope = true; m_OffsetEnvelopeX = 0.1f; m_OffsetEnvelopeY = 0.5f; m_ShowMousePointer = true; m_MouseDeltaX = 0; m_MouseDeltaY = 0; m_MouseDeltaWx = 0; m_MouseDeltaWy = 0; m_GuiActive = true; m_PreviewZoom = false; m_ShowTileInfo = SHOW_TILE_OFF; m_ShowDetail = true; m_Animate = false; m_AnimateStart = 0; m_AnimateTime = 0; m_AnimateSpeed = 1; m_ShowEnvelopePreview = SHOWENV_NONE; m_SelectedQuadEnvelope = -1; m_vSelectedEnvelopePoints = {}; m_UpdateEnvPointInfo = false; m_SelectedTangentInPoint = std::pair(-1, -1); m_SelectedTangentOutPoint = std::pair(-1, -1); m_CurrentQuadIndex = -1; m_QuadKnifeActive = false; m_QuadKnifeCount = 0; mem_zero(m_aQuadKnifePoints, sizeof(m_aQuadKnifePoints)); m_CheckerTexture.Invalidate(); m_BackgroundTexture.Invalidate(); m_CursorTexture.Invalidate(); ms_pUiGotContext = nullptr; // 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; } void Init() override; void OnUpdate() override; void OnRender() override; void OnActivate() override; void OnWindowResize() override; void OnClose() override; void OnDialogClose() override; bool HasUnsavedData() const override { return m_Map.m_Modified; } void UpdateMentions() override { m_Mentions++; } void ResetMentions() override { m_Mentions = 0; } void OnIngameMoved() override { m_IngameMoved = true; } void ResetIngameMoved() override { m_IngameMoved = false; } void HandleCursorMovement(); void DispatchInputEvents(); void HandleAutosave(); bool PerformAutosave(); void HandleWriterFinishJobs(); void RefreshFilteredFileList(); void FilelistPopulate(int StorageType, bool KeepSelection = false); void InvokeFileDialog(int StorageType, int FileType, const char *pTitle, const char *pButtonText, const char *pBasepath, bool FilenameAsDefault, bool (*pfnFunc)(const char *pFilename, int StorageType, void *pUser), void *pUser); struct SStringKeyComparator { bool operator()(const char *pLhs, const char *pRhs) const { return str_comp(pLhs, pRhs) < 0; } }; std::map m_PopupMessageContexts; void ShowFileDialogError(const char *pFormat, ...) GNUC_ATTRIBUTE((format(printf, 2, 3))); void Reset(bool CreateDefault = true); bool Save(const char *pFilename) override; bool Load(const char *pFilename, int StorageType) override; bool HandleMapDrop(const char *pFilename, int StorageType) override; bool Append(const char *pFilename, int StorageType); void LoadCurrentMap(); void Render(); void RenderPressedKeys(CUIRect View); void RenderSavingIndicator(CUIRect View); void FreeDynamicPopupMenus(); void RenderMousePointer(); std::vector GetSelectedQuads(); std::shared_ptr GetSelectedLayerType(int Index, int Type) const; std::shared_ptr GetSelectedLayer(int Index) const; std::shared_ptr GetSelectedGroup() const; CSoundSource *GetSelectedSource(); void SelectLayer(int LayerIndex, int GroupIndex = -1); void AddSelectedLayer(int LayerIndex); void SelectQuad(int Index); void ToggleSelectQuad(int Index); void DeselectQuads(); void DeselectQuadPoints(); void SelectQuadPoint(int QuadIndex, int Index); void ToggleSelectQuadPoint(int QuadIndex, int Index); void DeleteSelectedQuads(); bool IsQuadSelected(int Index) const; bool IsQuadCornerSelected(int Index) const; bool IsQuadPointSelected(int QuadIndex, int Index) const; int FindSelectedQuadIndex(int Index) const; int FindEnvPointIndex(int Index, int Channel) const; void SelectEnvPoint(int Index); void SelectEnvPoint(int Index, int Channel); void ToggleEnvPoint(int Index, int Channel); bool IsEnvPointSelected(int Index, int Channel) const; bool IsEnvPointSelected(int Index) const; void DeselectEnvPoints(); void SelectTangentOutPoint(int Index, int Channel); bool IsTangentOutPointSelected(int Index, int Channel) const; void SelectTangentInPoint(int Index, int Channel); bool IsTangentInPointSelected(int Index, int Channel) const; bool IsTangentInSelected() const; bool IsTangentOutSelected() const; bool IsTangentSelected() const; int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIDs, int *pNewVal, ColorRGBA Color = ColorRGBA(1, 1, 1, 0.5f)); CUI::SColorPickerPopupContext m_ColorPickerPopupContext; const void *m_pColorPickerPopupActiveID = nullptr; void DoColorPickerButton(const void *pID, const CUIRect *pRect, ColorRGBA Color, const std::function &SetColor); int m_Mode; int m_Dialog; char m_aTooltip[256] = ""; bool m_BrushColorEnabled; char m_aFileName[IO_MAX_PATH_LENGTH]; char m_aFileNamePending[IO_MAX_PATH_LENGTH]; char m_aFileSaveName[IO_MAX_PATH_LENGTH]; bool m_ValidSaveFilename; enum { POPEVENT_EXIT = 0, POPEVENT_LOAD, POPEVENT_LOADCURRENT, POPEVENT_LOADDROP, POPEVENT_NEW, POPEVENT_SAVE, POPEVENT_SAVE_COPY, POPEVENT_SAVE_IMG, POPEVENT_SAVE_SOUND, POPEVENT_LARGELAYER, POPEVENT_PREVENTUNUSEDTILES, POPEVENT_IMAGEDIV16, POPEVENT_IMAGE_MAX, POPEVENT_SOUND_MAX, POPEVENT_PLACE_BORDER_TILES, POPEVENT_PIXELART_BIG_IMAGE, POPEVENT_PIXELART_MANY_COLORS, POPEVENT_PIXELART_TOO_MANY_COLORS }; int m_PopupEventType; int m_PopupEventActivated; int m_PopupEventWasActivated; bool m_LargeLayerWasWarned; bool m_PreventUnusedTilesWasWarned; int m_AllowPlaceUnusedTiles; bool m_BrushDrawDestructive; int m_Mentions = 0; bool m_IngameMoved = false; enum { FILETYPE_MAP, FILETYPE_IMG, FILETYPE_SOUND, NUM_FILETYPES }; int m_FileDialogStorageType; int m_FileDialogLastPopulatedStorageType; const char *m_pFileDialogTitle; const char *m_pFileDialogButtonText; bool (*m_pfnFileDialogFunc)(const char *pFileName, int StorageType, void *pUser); void *m_pFileDialogUser; CLineInputBuffered m_FileDialogFileNameInput; char m_aFileDialogCurrentFolder[IO_MAX_PATH_LENGTH]; char m_aFileDialogCurrentLink[IO_MAX_PATH_LENGTH]; char m_aFilesSelectedName[IO_MAX_PATH_LENGTH]; CLineInputBuffered m_FileDialogFilterInput; char *m_pFileDialogPath; int m_FileDialogFileType; bool m_FileDialogMultipleStorages = false; bool m_FileDialogShowingRoot = false; int m_FilesSelectedIndex; CLineInputBuffered m_FileDialogNewFolderNameInput; IGraphics::CTextureHandle m_FilePreviewImage; int m_FilePreviewSound; EPreviewState m_FilePreviewState; CImageInfo m_FilePreviewImageInfo; bool m_FileDialogOpening; int m_ToolbarPreviewSound; struct CFilelistItem { char m_aFilename[IO_MAX_PATH_LENGTH]; char m_aName[IO_MAX_PATH_LENGTH]; bool m_IsDir; bool m_IsLink; int m_StorageType; time_t m_TimeModified; }; std::vector m_vCompleteFileList; std::vector m_vpFilteredFileList; static bool CompareFilenameAscending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) { if(str_comp(pLhs->m_aFilename, "..") == 0) return true; if(str_comp(pRhs->m_aFilename, "..") == 0) return false; if(pLhs->m_IsLink != pRhs->m_IsLink) return pLhs->m_IsLink; if(pLhs->m_IsDir != pRhs->m_IsDir) return pLhs->m_IsDir; return str_comp_filenames(pLhs->m_aName, pRhs->m_aName) < 0; } static bool CompareFilenameDescending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) { if(str_comp(pLhs->m_aFilename, "..") == 0) return true; if(str_comp(pRhs->m_aFilename, "..") == 0) return false; if(pLhs->m_IsLink != pRhs->m_IsLink) return pLhs->m_IsLink; if(pLhs->m_IsDir != pRhs->m_IsDir) return pLhs->m_IsDir; return str_comp_filenames(pLhs->m_aName, pRhs->m_aName) > 0; } static bool CompareTimeModifiedAscending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) { if(str_comp(pLhs->m_aFilename, "..") == 0) return true; if(str_comp(pRhs->m_aFilename, "..") == 0) return false; if(pLhs->m_IsLink || pRhs->m_IsLink) return pLhs->m_IsLink; if(pLhs->m_IsDir != pRhs->m_IsDir) return pLhs->m_IsDir; return pLhs->m_TimeModified < pRhs->m_TimeModified; } static bool CompareTimeModifiedDescending(const CFilelistItem *pLhs, const CFilelistItem *pRhs) { if(str_comp(pLhs->m_aFilename, "..") == 0) return true; if(str_comp(pRhs->m_aFilename, "..") == 0) return false; if(pLhs->m_IsLink || pRhs->m_IsLink) return pLhs->m_IsLink; if(pLhs->m_IsDir != pRhs->m_IsDir) return pLhs->m_IsDir; return pLhs->m_TimeModified > pRhs->m_TimeModified; } void SortFilteredFileList(); int m_SortByFilename = 1; int m_SortByTimeModified = 0; std::vector m_vSelectEntitiesFiles; std::string m_SelectEntitiesImage; // Zooming CSmoothValue m_ZoomEnvelopeX; CSmoothValue m_ZoomEnvelopeY; bool m_ResetZoomEnvelope; float m_OffsetEnvelopeX; float m_OffsetEnvelopeY; bool m_ShowMousePointer; bool m_GuiActive; char m_aMenuBackgroundTooltip[256]; bool m_PreviewZoom; float m_MouseWScale = 1.0f; // Mouse (i.e. UI) scale relative to the World (selected Group) float m_MouseX = 0.0f; float m_MouseY = 0.0f; float m_MouseWorldX = 0.0f; float m_MouseWorldY = 0.0f; float m_MouseWorldNoParaX = 0.0f; float m_MouseWorldNoParaY = 0.0f; float m_MouseDeltaX; float m_MouseDeltaY; float m_MouseDeltaWx; float m_MouseDeltaWy; enum EShowTile { SHOW_TILE_OFF, SHOW_TILE_DECIMAL, SHOW_TILE_HEXADECIMAL }; EShowTile m_ShowTileInfo; bool m_ShowDetail; bool m_Animate; int64_t m_AnimateStart; float m_AnimateTime; float m_AnimateSpeed; enum EExtraEditor { EXTRAEDITOR_NONE = -1, EXTRAEDITOR_ENVELOPES, EXTRAEDITOR_SERVER_SETTINGS, NUM_EXTRAEDITORS, }; EExtraEditor m_ActiveExtraEditor = EXTRAEDITOR_NONE; float m_aExtraEditorSplits[NUM_EXTRAEDITORS] = {250.0f, 250.0f}; enum EShowEnvelope { SHOWENV_NONE = 0, SHOWENV_SELECTED, SHOWENV_ALL }; EShowEnvelope m_ShowEnvelopePreview; bool m_ShowPicker; std::vector m_vSelectedLayers; std::vector m_vSelectedQuads; int m_SelectedQuadPoint; int m_SelectedQuadIndex; int m_SelectedGroup; int m_SelectedQuadPoints; int m_SelectedEnvelope; std::vector> m_vSelectedEnvelopePoints; int m_SelectedQuadEnvelope; int m_CurrentQuadIndex; int m_SelectedImage; int m_SelectedSound; int m_SelectedSource; std::pair m_SelectedTangentInPoint; std::pair m_SelectedTangentOutPoint; bool m_UpdateEnvPointInfo; 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(); std::shared_ptr m_pBrush; std::shared_ptr m_pTilesetPicker; std::shared_ptr m_pQuadsetPicker; static const void *ms_pUiGotContext; CEditorMap m_Map; std::deque> m_WriterFinishJobs; int m_ShiftBy; static void EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser); CLineInputBuffered<256> m_SettingsCommandInput; CImageInfo m_TileartImageInfo; char m_aTileartFilename[IO_MAX_PATH_LENGTH]; void AddTileart(); void TileartCheckColors(); void PlaceBorderTiles(); void UpdateTooltip(const void *pID, const CUIRect *pRect, const char *pToolTip); 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 DoButton_Env(const void *pID, const char *pText, int Checked, const CUIRect *pRect, const char *pToolTip, ColorRGBA Color, int Corners); 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 DoButton_FontIcon(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners, float FontSize = 10.0f); 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 = nullptr); int DoButton_DraggableEx(const void *pID, const char *pText, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted, int Flags, const char *pToolTip = nullptr, int Corners = IGraphics::CORNER_ALL, float FontSize = 10.0f); bool DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const char *pToolTip = nullptr); bool DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize, int Corners = IGraphics::CORNER_ALL, const char *pToolTip = nullptr); void RenderBackground(CUIRect View, IGraphics::CTextureHandle Texture, float Size, float Brightness); 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 = IGraphics::CORNER_ALL, ColorRGBA *pColor = nullptr, bool ShowValue = true); static CUI::EPopupMenuFunctionResult PopupMenuFile(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupMenuTools(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupMenuSettings(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupGroup(void *pContext, CUIRect View, bool Active); struct SLayerPopupContext : public SPopupMenuId { CEditor *m_pEditor; std::vector> m_vpLayers; CLayerTiles::SCommonPropState m_CommonPropState; }; static CUI::EPopupMenuFunctionResult PopupLayer(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupQuad(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSource(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupPoint(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupEnvPoint(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupEnvPointMulti(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupEnvPointCurveType(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupImage(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSound(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupNewFolder(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupMapInfo(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupEvent(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSelectImage(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSelectSound(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSelectGametileOp(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSelectConfigAutoMap(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupTele(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSpeedup(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupSwitch(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupTune(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupGoto(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupEntities(void *pContext, CUIRect View, bool Active); static CUI::EPopupMenuFunctionResult PopupProofMode(void *pContext, CUIRect View, bool Active); static bool CallbackOpenMap(const char *pFileName, int StorageType, void *pUser); static bool CallbackAppendMap(const char *pFileName, int StorageType, void *pUser); static bool CallbackSaveMap(const char *pFileName, int StorageType, void *pUser); static bool CallbackSaveCopyMap(const char *pFileName, int StorageType, void *pUser); static bool CallbackAddTileart(const char *pFilepath, int StorageType, void *pUser); static bool CallbackSaveImage(const char *pFileName, int StorageType, void *pUser); static bool CallbackSaveSound(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 &vQuads, IGraphics::CTextureHandle Texture = IGraphics::CTextureHandle()); void DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int pIndex); void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v); void SetHotQuadPoint(const std::shared_ptr &pLayer); 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 DoToolbarLayers(CUIRect Toolbar); void DoToolbarSounds(CUIRect Toolbar); void DoQuad(CQuad *pQuad, int Index); ColorRGBA GetButtonColor(const void *pID, int Checked); bool ReplaceImage(const char *pFilename, int StorageType, bool CheckDuplicate); static bool ReplaceImageCallback(const char *pFilename, int StorageType, void *pUser); bool ReplaceSound(const char *pFileName, int StorageType, bool CheckDuplicate); static bool ReplaceSoundCallback(const char *pFileName, int StorageType, void *pUser); static bool AddImage(const char *pFilename, int StorageType, void *pUser); static bool AddSound(const char *pFileName, int StorageType, void *pUser); bool IsEnvelopeUsed(int EnvelopeIndex) const; void RemoveUnusedEnvelopes(); static bool IsVanillaImage(const char *pImage); void RenderLayers(CUIRect LayersBox); void RenderImagesList(CUIRect Toolbox); void RenderSelectedImage(CUIRect View); void RenderSounds(CUIRect Toolbox); void RenderModebar(CUIRect View); void RenderStatusbar(CUIRect View, CUIRect *pTooltipRect); void RenderTooltip(CUIRect TooltipRect); void RenderEnvelopeEditor(CUIRect View); void RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEditorLast); void RenderExtraEditorDragBar(CUIRect View, CUIRect DragBar); void SetHotEnvelopePoint(const CUIRect &View, const std::shared_ptr &pEnvelope, int ActiveChannels); void RenderMenubar(CUIRect Menubar); void RenderFileDialog(); void SelectGameLayer(); void SortImages(); bool SelectLayerByTile(); void DoAudioPreview(CUIRect View, const void *pPlayPauseButtonID, const void *pStopButtonID, const void *pSeekBarID, const int SampleID); // 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 class EExplanation { NONE, DDNET, FNG, RACE, VANILLA, BLOCKWORLDS }; static const char *ExplainDDNet(int Tile, int Layer); static const char *ExplainFNG(int Tile, int Layer); static const char *ExplainVanilla(int Tile, int Layer); static const char *Explain(EExplanation Explanation, int Tile, int Layer); // Zooming void ZoomAdaptOffsetX(float ZoomFactor, const CUIRect &View); void UpdateZoomEnvelopeX(const CUIRect &View); void ZoomAdaptOffsetY(float ZoomFactor, const CUIRect &View); void UpdateZoomEnvelopeY(const CUIRect &View); void ResetZoomEnvelope(const std::shared_ptr &pEnvelope, int ActiveChannels); void RemoveTimeOffsetEnvelope(const std::shared_ptr &pEnvelope); float ScreenToEnvelopeX(const CUIRect &View, float x) const; float EnvelopeToScreenX(const CUIRect &View, float x) const; float ScreenToEnvelopeY(const CUIRect &View, float y) const; float EnvelopeToScreenY(const CUIRect &View, float y) const; float ScreenToEnvelopeDX(const CUIRect &View, float dx); float ScreenToEnvelopeDY(const CUIRect &View, float dy); // DDRace IGraphics::CTextureHandle GetFrontTexture(); IGraphics::CTextureHandle GetTeleTexture(); IGraphics::CTextureHandle GetSpeedupTexture(); IGraphics::CTextureHandle GetSwitchTexture(); IGraphics::CTextureHandle GetTuneTexture(); 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(); } #endif