diff options
Diffstat (limited to 'src/game/editor')
| -rw-r--r-- | src/game/editor/auto_map.cpp | 202 | ||||
| -rw-r--r-- | src/game/editor/auto_map.h | 54 | ||||
| -rw-r--r-- | src/game/editor/editor.cpp (renamed from src/game/editor/ed_editor.cpp) | 1030 | ||||
| -rw-r--r-- | src/game/editor/editor.h (renamed from src/game/editor/ed_editor.h) | 94 | ||||
| -rw-r--r-- | src/game/editor/io.cpp (renamed from src/game/editor/ed_io.cpp) | 101 | ||||
| -rw-r--r-- | src/game/editor/layer_game.cpp (renamed from src/game/editor/ed_layer_game.cpp) | 4 | ||||
| -rw-r--r-- | src/game/editor/layer_quads.cpp (renamed from src/game/editor/ed_layer_quads.cpp) | 24 | ||||
| -rw-r--r-- | src/game/editor/layer_tiles.cpp (renamed from src/game/editor/ed_layer_tiles.cpp) | 61 | ||||
| -rw-r--r-- | src/game/editor/popups.cpp (renamed from src/game/editor/ed_popups.cpp) | 200 |
9 files changed, 1502 insertions, 268 deletions
diff --git a/src/game/editor/auto_map.cpp b/src/game/editor/auto_map.cpp new file mode 100644 index 00000000..3abcf0f4 --- /dev/null +++ b/src/game/editor/auto_map.cpp @@ -0,0 +1,202 @@ +#include <stdio.h> // sscanf + +#include <engine/console.h> +#include <engine/storage.h> +#include <engine/shared/linereader.h> + +#include "auto_map.h" +#include "editor.h" + +CAutoMapper::CAutoMapper(CEditor *pEditor) +{ + m_pEditor = pEditor; + m_FileLoaded = false; +} + +void CAutoMapper::Load(const char* pTileName) +{ + char aPath[256]; + str_format(aPath, sizeof(aPath), "editor/%s.rules", pTileName); + IOHANDLE RulesFile = m_pEditor->Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_ALL); + if(!RulesFile) + return; + + CLineReader LineReader; + LineReader.Init(RulesFile); + + CConfiguration *pCurrentConf = 0; + CIndexRule *pCurrentIndex = 0; + + char aBuf[256]; + + // read each line + while(char *pLine = LineReader.Get()) + { + // skip blank/empty lines as well as comments + if(str_length(pLine) > 0 && pLine[0] != '#' && pLine[0] != '\n' && pLine[0] != '\r' + && pLine[0] != '\t' && pLine[0] != '\v' && pLine[0] != ' ') + { + if(pLine[0]== '[') + { + // new configuration, get the name + pLine++; + + CConfiguration NewConf; + int ID = m_lConfigs.add(NewConf); + pCurrentConf = &m_lConfigs[ID]; + + str_copy(pCurrentConf->m_aName, pLine, str_length(pLine)); + } + else + { + if(!str_comp_num(pLine, "Index", 5)) + { + // new index + int ID = 0; + char aFlip[128] = ""; + + sscanf(pLine, "Index %d %127s", &ID, aFlip); + + CIndexRule NewIndexRule; + NewIndexRule.m_ID = ID; + NewIndexRule.m_Flag = 0; + NewIndexRule.m_RandomValue = 0; + NewIndexRule.m_BaseTile = false; + + if(str_length(aFlip) > 0) + { + if(!str_comp(aFlip, "XFLIP")) + NewIndexRule.m_Flag = TILEFLAG_VFLIP; + else if(!str_comp(aFlip, "YFLIP")) + NewIndexRule.m_Flag = TILEFLAG_HFLIP; + } + + // add the index rule object and make it current + int ArrayID = pCurrentConf->m_aIndexRules.add(NewIndexRule); + pCurrentIndex = &pCurrentConf->m_aIndexRules[ArrayID]; + } + else if(!str_comp_num(pLine, "BaseTile", 8) && pCurrentIndex) + { + pCurrentIndex->m_BaseTile = true; + } + else if(!str_comp_num(pLine, "Pos", 3) && pCurrentIndex) + { + int x = 0, y = 0; + char aValue[128]; + int Value = CPosRule::EMPTY; + bool IndexValue = false; + + sscanf(pLine, "Pos %d %d %127s", &x, &y, aValue); + + if(!str_comp(aValue, "FULL")) + Value = CPosRule::FULL; + else if(!str_comp_num(aValue, "INDEX", 5)) + { + sscanf(pLine, "Pos %*d %*d INDEX %d", &Value); + IndexValue = true; + } + + CPosRule NewPosRule = {x, y, Value, IndexValue}; + pCurrentIndex->m_aRules.add(NewPosRule); + } + else if(!str_comp_num(pLine, "Random", 6) && pCurrentIndex) + { + sscanf(pLine, "Random %d", &pCurrentIndex->m_RandomValue); + } + } + } + } + + io_close(RulesFile); + + str_format(aBuf, sizeof(aBuf),"loaded %s", aPath); + m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "editor", aBuf); + + m_FileLoaded = true; +} + +const char* CAutoMapper::GetConfigName(int Index) +{ + if(Index < 0 || Index >= m_lConfigs.size()) + return ""; + + return m_lConfigs[Index].m_aName; +} + +void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID) +{ + if(!m_FileLoaded || pLayer->m_Readonly || ConfigID < 0 || ConfigID >= m_lConfigs.size()) + return; + + CConfiguration *pConf = &m_lConfigs[ConfigID]; + + if(!pConf->m_aIndexRules.size()) + return; + + int BaseTile = 1; + + // find base tile if there is one + for(int i = 0; i < pConf->m_aIndexRules.size(); ++i) + { + if(pConf->m_aIndexRules[i].m_BaseTile) + { + BaseTile = pConf->m_aIndexRules[i].m_ID; + break; + } + } + + // auto map ! + int MaxIndex = pLayer->m_Width*pLayer->m_Height; + for(int y = 0; y < pLayer->m_Height; y++) + for(int x = 0; x < pLayer->m_Width; x++) + { + CTile *pTile = &(pLayer->m_pTiles[y*pLayer->m_Width+x]); + if(pTile->m_Index == 0) + continue; + + pTile->m_Index = BaseTile; + m_pEditor->m_Map.m_Modified = true; + + if(y == 0 || y == pLayer->m_Height-1 || x == 0 || x == pLayer->m_Width-1) + continue; + + for(int i = 0; i < pConf->m_aIndexRules.size(); ++i) + { + if(pConf->m_aIndexRules[i].m_BaseTile) + continue; + + bool RespectRules = true; + for(int j = 0; j < pConf->m_aIndexRules[i].m_aRules.size() && RespectRules; ++j) + { + CPosRule *pRule = &pConf->m_aIndexRules[i].m_aRules[j]; + int CheckIndex = (y+pRule->m_Y)*pLayer->m_Width+(x+pRule->m_X); + + if(CheckIndex < 0 || CheckIndex >= MaxIndex) + RespectRules = false; + else + { + if(pRule->m_IndexValue) + { + if(pLayer->m_pTiles[CheckIndex].m_Index != pRule->m_Value) + RespectRules = false; + } + else + { + if(pLayer->m_pTiles[CheckIndex].m_Index > 0 && pRule->m_Value == CPosRule::EMPTY) + RespectRules = false; + + if(pLayer->m_pTiles[CheckIndex].m_Index == 0 && pRule->m_Value == CPosRule::FULL) + RespectRules = false; + } + } + } + + if(RespectRules && + (pConf->m_aIndexRules[i].m_RandomValue <= 1 || (int)((float)rand() / ((float)RAND_MAX + 1) * pConf->m_aIndexRules[i].m_RandomValue) == 1)) + { + pTile->m_Index = pConf->m_aIndexRules[i].m_ID; + pTile->m_Flags = pConf->m_aIndexRules[i].m_Flag; + } + } + } +} diff --git a/src/game/editor/auto_map.h b/src/game/editor/auto_map.h new file mode 100644 index 00000000..c5537d4f --- /dev/null +++ b/src/game/editor/auto_map.h @@ -0,0 +1,54 @@ +#ifndef GAME_EDITOR_AUTO_MAP_H +#define GAME_EDITOR_AUTO_MAP_H + +#include <base/tl/array.h> + +class CAutoMapper +{ + struct CPosRule + { + int m_X; + int m_Y; + int m_Value; + bool m_IndexValue; + + enum + { + EMPTY=0, + FULL + }; + }; + + struct CIndexRule + { + int m_ID; + array<CPosRule> m_aRules; + int m_Flag; + int m_RandomValue; + bool m_BaseTile; + }; + + struct CConfiguration + { + array<CIndexRule> m_aIndexRules; + char m_aName[128]; + }; + +public: + CAutoMapper(class CEditor *pEditor); + + void Load(const char* pTileName); + void Proceed(class CLayerTiles *pLayer, int ConfigID); + + int ConfigNamesNum() { return m_lConfigs.size(); } + const char* GetConfigName(int Index); + + const bool IsLoaded() { return m_FileLoaded; } +private: + array<CConfiguration> m_lConfigs; + class CEditor *m_pEditor; + bool m_FileLoaded; +}; + + +#endif diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/editor.cpp index 1163dc4a..fa1024e0 100644 --- a/src/game/editor/ed_editor.cpp +++ b/src/game/editor/editor.cpp @@ -8,20 +8,20 @@ #include <engine/client.h> #include <engine/console.h> #include <engine/graphics.h> -#include <engine/textrender.h> #include <engine/input.h> #include <engine/keys.h> #include <engine/storage.h> +#include <engine/textrender.h> -#include <game/client/ui.h> #include <game/gamecore.h> +#include <game/localization.h> +#include <game/client/lineinput.h> #include <game/client/render.h> +#include <game/client/ui.h> #include <game/generated/client_data.h> -#include "ed_editor.h" -#include <game/client/lineinput.h> - -#include <game/localization.h> +#include "auto_map.h" +#include "editor.h" int CEditor::ms_CheckerTexture; int CEditor::ms_BackgroundTexture; @@ -41,9 +41,10 @@ CEditorImage::~CEditorImage() CLayerGroup::CLayerGroup() { - m_pName = ""; + m_aName[0] = 0; m_Visible = true; m_SaveToMap = true; + m_Collapse = false; m_GameGroup = false; m_OffsetX = 0; m_OffsetY = 0; @@ -163,7 +164,7 @@ void CEditorImage::AnalyseTileFlags() int tw = m_Width/16; // tilesizes int th = m_Height/16; if ( tw == th ) - { + { unsigned char *pPixelData = (unsigned char *)m_pData; int TileID = 0; @@ -189,39 +190,84 @@ void CEditorImage::AnalyseTileFlags() } +void CEditor::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) +{ + CEditor *pThis = (CEditor *)pUser; + if(Env < 0 || Env >= pThis->m_Map.m_lEnvelopes.size()) + { + pChannels[0] = 0; + pChannels[1] = 0; + pChannels[2] = 0; + pChannels[3] = 0; + return; + } + + CEnvelope *e = pThis->m_Map.m_lEnvelopes[Env]; + float t = pThis->m_AnimateTime+TimeOffset; + t *= pThis->m_AnimateSpeed; + e->Eval(t, pChannels); +} + /******************************************************** OTHER *********************************************************/ // copied from gc_menu.cpp, should be more generalized //extern int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false); - -int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden) +int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners) { - int Inside = UI()->MouseInside(pRect); + int Inside = UI()->MouseInside(pRect); bool ReturnValue = false; + bool UpdateOffset = false; static int s_AtIndex = 0; + static bool s_DoScroll = false; + static float s_ScrollStart = 0.0f; + + FontSize *= UI()->Scale(); if(UI()->LastActiveItem() == pID) { + m_EditBoxActive = 2; int Len = str_length(pStr); + if(Len == 0) + s_AtIndex = 0; if(Inside && UI()->MouseButton(0)) { + s_DoScroll = true; + s_ScrollStart = UI()->MouseX(); int MxRel = (int)(UI()->MouseX() - pRect->x); - for (int i = 1; i <= Len; i++) + for(int i = 1; i <= Len; i++) { - if (TextRender()->TextWidth(0, FontSize, pStr, i) + 10 > MxRel) + if(TextRender()->TextWidth(0, FontSize, pStr, i) - *Offset > MxRel) { s_AtIndex = i - 1; break; } - if (i == Len) + if(i == Len) s_AtIndex = Len; } } + else if(!UI()->MouseButton(0)) + s_DoScroll = false; + else if(s_DoScroll) + { + // do scrolling + if(UI()->MouseX() < pRect->x && s_ScrollStart-UI()->MouseX() > 10.0f) + { + s_AtIndex = max(0, s_AtIndex-1); + s_ScrollStart = UI()->MouseX(); + UpdateOffset = true; + } + else if(UI()->MouseX() > pRect->x+pRect->w && UI()->MouseX()-s_ScrollStart > 10.0f) + { + s_AtIndex = min(Len, s_AtIndex+1); + s_ScrollStart = UI()->MouseX(); + UpdateOffset = true; + } + } for(int i = 0; i < Input()->NumEvents(); i++) { @@ -235,7 +281,11 @@ int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str if(UI()->ActiveItem() == pID) { if(!UI()->MouseButton(0)) + { + s_AtIndex = min(s_AtIndex, str_length(pStr)); + s_DoScroll = false; UI()->SetActiveItem(0); + } } else if(UI()->HotItem() == pID) { @@ -251,8 +301,8 @@ int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str UI()->SetHotItem(pID); CUIRect Textbox = *pRect; - RenderTools()->DrawUIRect(&Textbox, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 3.0f); - Textbox.VMargin(3.0f, &Textbox); + RenderTools()->DrawUIRect(&Textbox, vec4(1, 1, 1, 0.5f), Corners, 3.0f); + Textbox.VMargin(2.0f, &Textbox); const char *pDisplayStr = pStr; char aStars[128]; @@ -268,19 +318,47 @@ int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str pDisplayStr = aStars; } + // check if the text has to be moved + if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || Input()->NumEvents())) + { + float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); + if(w-*Offset > Textbox.w) + { + // move to the left + float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1); + do + { + *Offset += min(wt-*Offset-Textbox.w, Textbox.w/3); + } + while(w-*Offset > Textbox.w); + } + else if(w-*Offset < 0.0f) + { + // move to the right + do + { + *Offset = max(0.0f, *Offset-Textbox.w/3); + } + while(w-*Offset < 0.0f); + } + } + UI()->ClipEnable(pRect); + Textbox.x -= *Offset; + UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1); - - //TODO: make it blink + + // render the cursor if(UI()->LastActiveItem() == pID && !JustGotActive) { float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); Textbox = *pRect; Textbox.VSplitLeft(2.0f, 0, &Textbox); - Textbox.x += w*UI()->Scale(); - Textbox.y -= FontSize/10.f; - - UI()->DoLabel(&Textbox, "|", FontSize*1.1f, -1); + Textbox.x += (w-*Offset-TextRender()->TextWidth(0, FontSize, "|", -1)/2); + + if((2*time_get()/time_freq()) % 2) // make it blink + UI()->DoLabel(&Textbox, "|", FontSize, -1); } + UI()->ClipDisable(); return ReturnValue; } @@ -303,8 +381,8 @@ float CEditor::UiDoScrollbarV(const void *pID, const CUIRect *pRect, float Curre Handle.y += (pRect->h-Handle.h)*Current; // logic - float Ret = Current; - int Inside = UI()->MouseInside(&Handle); + float Ret = Current; + int Inside = UI()->MouseInside(&Handle); if(UI()->ActiveItem() == pID) { @@ -345,7 +423,7 @@ float CEditor::UiDoScrollbarV(const void *pID, const CUIRect *pRect, float Curre Slider.Margin(5.0f, &Slider); RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f); - return Ret; + return Ret; } vec4 CEditor::GetButtonColor(const void *pID, int Checked) @@ -412,7 +490,7 @@ int CEditor::DoButton_File(const void *pID, const char *pText, int Checked, cons int CEditor::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { CUIRect r = *pRect; - RenderTools()->DrawUIRect(&r, vec4(0.5f, 0.5f, 0.5f, 1.0f), CUI::CORNER_T, 3.0f); + RenderTools()->DrawUIRect(&r, vec4(0.5f, 0.5f, 0.5f, 1.0f), CUI::CORNER_T, 3.0f); r = *pRect; r.VMargin(5.0f, &r); @@ -437,18 +515,18 @@ int CEditor::DoButton_MenuItem(const void *pID, const char *pText, int Checked, int CEditor::DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_T, 5.0f); - CUIRect NewRect = *pRect; - NewRect.y += NewRect.h/2.0f-7.0f; - UI()->DoLabel(&NewRect, pText, 10, 0, -1); + CUIRect NewRect = *pRect; + NewRect.y += NewRect.h/2.0f-7.0f; + UI()->DoLabel(&NewRect, pText, 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } -int CEditor::DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners) +int CEditor::DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners, float FontSize) { RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), Corners, 3.0f); - CUIRect NewRect = *pRect; - NewRect.y += NewRect.h/2.0f-7.0f; - UI()->DoLabel(&NewRect, pText, 10, 0, -1); + CUIRect NewRect = *pRect; + NewRect.HMargin(NewRect.h/2.0f-FontSize/2.0f-1.0f, &NewRect); + UI()->DoLabel(&NewRect, pText, FontSize, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } @@ -466,6 +544,49 @@ int CEditor::DoButton_ButtonDec(const void *pID, const char *pText, int Checked, return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } +void CEditor::RenderGrid(CLayerGroup *pGroup) +{ + if(!m_GridActive) + return; + + float aGroupPoints[4]; + pGroup->Mapping(aGroupPoints); + + float w = UI()->Screen()->w; + float h = UI()->Screen()->h; + + int LineDistance = GetLineDistance(); + + int XOffset = aGroupPoints[0]/LineDistance; + int YOffset = aGroupPoints[1]/LineDistance; + int XGridOffset = XOffset % m_GridFactor; + int YGridOffset = YOffset % m_GridFactor; + + Graphics()->TextureSet(-1); + Graphics()->LinesBegin(); + + for(int i = 0; i < (int)w; i++) + { + if((i+YGridOffset) % m_GridFactor == 0) + Graphics()->SetColor(1.0f, 0.3f, 0.3f, 0.3f); + else + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.15f); + + IGraphics::CLineItem Line = IGraphics::CLineItem(LineDistance*XOffset, LineDistance*i+LineDistance*YOffset, w+aGroupPoints[2], LineDistance*i+LineDistance*YOffset); + Graphics()->LinesDraw(&Line, 1); + + if((i+XGridOffset) % m_GridFactor == 0) + Graphics()->SetColor(1.0f, 0.3f, 0.3f, 0.3f); + else + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.15f); + + Line = IGraphics::CLineItem(LineDistance*i+LineDistance*XOffset, LineDistance*YOffset, LineDistance*i+LineDistance*XOffset, h+aGroupPoints[3]); + Graphics()->LinesDraw(&Line, 1); + } + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + Graphics()->LinesEnd(); +} + void CEditor::RenderBackground(CUIRect View, int Texture, float Size, float Brightness) { Graphics()->TextureSet(Texture); @@ -480,17 +601,14 @@ void CEditor::RenderBackground(CUIRect View, int Texture, float Size, float Brig int CEditor::UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip) { - // logic - static float s_Value; - int Ret = 0; - int Inside = UI()->MouseInside(pRect); + // logic + static float s_Value; + int Inside = UI()->MouseInside(pRect); if(UI()->ActiveItem() == pID) { if(!UI()->MouseButton(0)) { - if(Inside) - Ret = 1; m_LockMouse = false; UI()->SetActiveItem(0); } @@ -534,9 +652,9 @@ int CEditor::UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, in char aBuf[128]; str_format(aBuf, sizeof(aBuf),"%s %d", pLabel, Current); RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, 0), CUI::CORNER_ALL, 5.0f); - pRect->y += pRect->h/2.0f-7.0f; - UI()->DoLabel(pRect, aBuf, 10, 0, -1); - + pRect->y += pRect->h/2.0f-7.0f; + UI()->DoLabel(pRect, aBuf, 10, 0, -1); + return Current; } @@ -595,7 +713,7 @@ void CEditor::CallbackAppendMap(const char *pFileName, int StorageType, void *pU pEditor->m_aFileName[0] = 0; else pEditor->SortImages(); - + pEditor->m_Dialog = DIALOG_NONE; } void CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUser) @@ -616,7 +734,7 @@ void CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUse pEditor->m_ValidSaveFilename = StorageType == IStorage::TYPE_SAVE && pEditor->m_pFileDialogPath == pEditor->m_aFileDialogCurrentFolder; pEditor->m_Map.m_Modified = false; } - + pEditor->m_Dialog = DIALOG_NONE; } @@ -624,32 +742,38 @@ void CEditor::DoToolbar(CUIRect ToolBar) { CUIRect TB_Top, TB_Bottom; CUIRect Button; - + ToolBar.HSplitTop(ToolBar.h/2.0f, &TB_Top, &TB_Bottom); - - TB_Top.HSplitBottom(2.5f, &TB_Top, 0); - TB_Bottom.HSplitTop(2.5f, 0, &TB_Bottom); + + TB_Top.HSplitBottom(2.5f, &TB_Top, 0); + TB_Bottom.HSplitTop(2.5f, 0, &TB_Bottom); // ctrl+o to open - if(Input()->KeyDown('o') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) + if(Input()->KeyDown('o') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)) && m_Dialog == DIALOG_NONE) { if(HasUnsavedData()) { - m_PopupEventType = POPEVENT_LOAD; - m_PopupEventActivated = true; + if(!m_PopupEventWasActivated) + { + m_PopupEventType = POPEVENT_LOAD; + m_PopupEventActivated = true; + } } else InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Load map", "Load", "maps", "", CallbackOpenMap, this); } // ctrl+s to save - if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) + if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)) && m_Dialog == DIALOG_NONE) { - if(m_aFileName[0] && m_ValidSaveFilename) + if(m_aFileName[0] && m_ValidSaveFilename) { - str_copy(m_aFileSaveName, m_aFileName, sizeof(m_aFileSaveName)); - m_PopupEventType = POPEVENT_SAVE; - m_PopupEventActivated = true; + if(!m_PopupEventWasActivated) + { + str_copy(m_aFileSaveName, m_aFileName, sizeof(m_aFileSaveName)); + m_PopupEventType = POPEVENT_SAVE; + m_PopupEventActivated = true; + } } else InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", CallbackSaveMap, this); @@ -696,6 +820,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) (Input()->KeyDown('i') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))) { m_ShowTileInfo = !m_ShowTileInfo; + m_ShowEnvelopePreview = 0; } TB_Top.VSplitLeft(15.0f, 0, &TB_Top); @@ -703,12 +828,12 @@ void CEditor::DoToolbar(CUIRect ToolBar) // zoom group TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); static int s_ZoomOutButton = 0; - if(DoButton_Ex(&s_ZoomOutButton, "ZO", 0, &Button, 0, "[NumPad-] Zoom out", CUI::CORNER_L) || Input()->KeyDown(KEY_KP_MINUS)) + if(DoButton_Ex(&s_ZoomOutButton, "ZO", 0, &Button, 0, "[NumPad-] Zoom out", CUI::CORNER_L)) m_ZoomLevel += 50; TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); static int s_ZoomNormalButton = 0; - if(DoButton_Ex(&s_ZoomNormalButton, "1:1", 0, &Button, 0, "[NumPad*] Zoom to normal and remove editor offset", 0) || Input()->KeyDown(KEY_KP_MULTIPLY)) + if(DoButton_Ex(&s_ZoomNormalButton, "1:1", 0, &Button, 0, "[NumPad*] Zoom to normal and remove editor offset", 0)) { m_EditorOffsetX = 0; m_EditorOffsetY = 0; @@ -717,7 +842,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) TB_Top.VSplitLeft(30.0f, &Button, &TB_Top); static int s_ZoomInButton = 0; - if(DoButton_Ex(&s_ZoomInButton, "ZI", 0, &Button, 0, "[NumPad+] Zoom in", CUI::CORNER_R) || Input()->KeyDown(KEY_KP_PLUS)) + if(DoButton_Ex(&s_ZoomInButton, "ZI", 0, &Button, 0, "[NumPad+] Zoom in", CUI::CORNER_R)) m_ZoomLevel -= 50; TB_Top.VSplitLeft(10.0f, 0, &TB_Top); @@ -741,16 +866,6 @@ void CEditor::DoToolbar(CUIRect ToolBar) m_AnimateSpeed -= 0.5f; } - if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && m_Dialog == DIALOG_NONE) - m_ZoomLevel -= 20; - - if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && m_Dialog == DIALOG_NONE) - m_ZoomLevel += 20; - - if(m_ZoomLevel < 50) - m_ZoomLevel = 50; - m_WorldZoom = m_ZoomLevel/100.0f; - TB_Top.VSplitLeft(10.0f, &Button, &TB_Top); @@ -837,17 +952,17 @@ void CEditor::DoToolbar(CUIRect ToolBar) } } } - + // tile manipulation { TB_Bottom.VSplitLeft(40.0f, &Button, &TB_Bottom); static int s_BorderBut = 0; CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); - + if(DoButton_Editor(&s_BorderBut, "Border", pT?0:-1, &Button, 0, "Adds border tiles")) { if(pT) - DoMapBorder(); + DoMapBorder(); } } @@ -856,11 +971,46 @@ void CEditor::DoToolbar(CUIRect ToolBar) // refocus button TB_Bottom.VSplitLeft(50.0f, &Button, &TB_Bottom); static int s_RefocusButton = 0; - if(DoButton_Editor(&s_RefocusButton, "Refocus", m_WorldOffsetX&&m_WorldOffsetY?0:-1, &Button, 0, "[HOME] Restore map focus") || Input()->KeyDown(KEY_HOME)) + if(DoButton_Editor(&s_RefocusButton, "Refocus", m_WorldOffsetX&&m_WorldOffsetY?0:-1, &Button, 0, "[HOME] Restore map focus") || (m_EditBoxActive == 0 && Input()->KeyDown(KEY_HOME))) { m_WorldOffsetX = 0; m_WorldOffsetY = 0; } + + TB_Bottom.VSplitLeft(5.0f, 0, &TB_Bottom); + + // grid button + TB_Bottom.VSplitLeft(50.0f, &Button, &TB_Bottom); + static int s_GridButton = 0; + if(DoButton_Editor(&s_GridButton, "Grid", m_GridActive, &Button, 0, "Toggle Grid")) + { + m_GridActive = !m_GridActive; + } + + TB_Bottom.VSplitLeft(30.0f, 0, &TB_Bottom); + + // grid zoom + TB_Bottom.VSplitLeft(30.0f, &Button, &TB_Bottom); + static int s_GridIncreaseButton = 0; + if(DoButton_Ex(&s_GridIncreaseButton, "G-", 0, &Button, 0, "Decrease grid", CUI::CORNER_L)) + { + if(m_GridFactor > 1) + m_GridFactor--; + } + + TB_Bottom.VSplitLeft(30.0f, &Button, &TB_Bottom); + static int s_GridNormalButton = 0; + if(DoButton_Ex(&s_GridNormalButton, "1", 0, &Button, 0, "Normal grid", 0)) + m_GridFactor = 1; + + TB_Bottom.VSplitLeft(30.0f, &Button, &TB_Bottom); + + static int s_GridDecreaseButton = 0; + if(DoButton_Ex(&s_GridDecreaseButton, "G+", 0, &Button, 0, "Increase grid", CUI::CORNER_R)) + { + if(m_GridFactor < 15) + m_GridFactor++; + } } static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation) @@ -901,6 +1051,12 @@ void CEditor::DoQuad(CQuad *q, int Index) if(dx*dx+dy*dy < 50) UI()->SetHotItem(pID); + bool IgnoreGrid; + if(Input()->KeyPressed(KEY_LALT) || Input()->KeyPressed(KEY_RALT)) + IgnoreGrid = true; + else + IgnoreGrid = false; + // draw selection background if(m_SelectedQuad == Index) { @@ -911,27 +1067,82 @@ void CEditor::DoQuad(CQuad *q, int Index) if(UI()->ActiveItem() == pID) { - // check if we only should move pivot - if(s_Operation == OP_MOVE_PIVOT) - { - q->m_aPoints[4].x += f2fx(wx-s_LastWx); - q->m_aPoints[4].y += f2fx(wy-s_LastWy); - } - else if(s_Operation == OP_MOVE_ALL) + if(m_MouseDeltaWx*m_MouseDeltaWx+m_MouseDeltaWy*m_MouseDeltaWy > 0.5f) { - // move all points including pivot - for(int v = 0; v < 5; v++) + // check if we only should move pivot + if(s_Operation == OP_MOVE_PIVOT) { - q->m_aPoints[v].x += f2fx(wx-s_LastWx); - q->m_aPoints[v].y += f2fx(wy-s_LastWy); + if(m_GridActive && !IgnoreGrid) + { + int LineDistance = GetLineDistance(); + + float x = 0.0f; + float y = 0.0f; + if(wx >= 0) + x = (int)((wx+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + x = (int)((wx-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + if(wy >= 0) + y = (int)((wy+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + y = (int)((wy-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + + q->m_aPoints[4].x = f2fx(x); + q->m_aPoints[4].y = f2fx(y); + } + else + { + q->m_aPoints[4].x += f2fx(wx-s_LastWx); + q->m_aPoints[4].y += f2fx(wy-s_LastWy); + } } - } - else if(s_Operation == OP_ROTATE) - { - for(int v = 0; v < 4; v++) + else if(s_Operation == OP_MOVE_ALL) + { + // move all points including pivot + if(m_GridActive && !IgnoreGrid) + { + int LineDistance = GetLineDistance(); + + float x = 0.0f; + float y = 0.0f; + if(wx >= 0) + x = (int)((wx+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + x = (int)((wx-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + if(wy >= 0) + y = (int)((wy+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + y = (int)((wy-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + + int OldX = q->m_aPoints[4].x; + int OldY = q->m_aPoints[4].y; + q->m_aPoints[4].x = f2fx(x); + q->m_aPoints[4].y = f2fx(y); + int DiffX = q->m_aPoints[4].x - OldX; + int DiffY = q->m_aPoints[4].y - OldY; + + for(int v = 0; v < 4; v++) + { + q->m_aPoints[v].x += DiffX; + q->m_aPoints[v].y += DiffY; + } + } + else + { + for(int v = 0; v < 5; v++) + { + q->m_aPoints[v].x += f2fx(wx-s_LastWx); + q->m_aPoints[v].y += f2fx(wy-s_LastWy); + } + } + } + else if(s_Operation == OP_ROTATE) { - q->m_aPoints[v] = s_RotatePoints[v]; - Rotate(&q->m_aPoints[4], &q->m_aPoints[v], s_RotateAngle); + for(int v = 0; v < 4; v++) + { + q->m_aPoints[v] = s_RotatePoints[v]; + Rotate(&q->m_aPoints[4], &q->m_aPoints[v], s_RotateAngle); + } } } @@ -967,7 +1178,7 @@ void CEditor::DoQuad(CQuad *q, int Index) ms_pUiGotContext = pID; Graphics()->SetColor(1,1,1,1); - m_pTooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate."; + m_pTooltip = "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate. Hold alt to ignore grid."; if(UI()->MouseButton(0)) { @@ -987,6 +1198,8 @@ void CEditor::DoQuad(CQuad *q, int Index) s_Operation = OP_MOVE_ALL; UI()->SetActiveItem(pID); + if(m_SelectedQuad != Index) + m_SelectedPoints = 0; m_SelectedQuad = Index; s_LastWx = wx; s_LastWy = wy; @@ -994,6 +1207,8 @@ void CEditor::DoQuad(CQuad *q, int Index) if(UI()->MouseButton(1)) { + if(m_SelectedQuad != Index) + m_SelectedPoints = 0; m_SelectedQuad = Index; s_Operation = OP_CONTEXT_MENU; UI()->SetActiveItem(pID); @@ -1040,6 +1255,12 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) static bool s_Moved; static int s_Operation = OP_NONE; + bool IgnoreGrid; + if(Input()->KeyPressed(KEY_LALT) || Input()->KeyPressed(KEY_RALT)) + IgnoreGrid = true; + else + IgnoreGrid = false; + if(UI()->ActiveItem() == pID) { float dx = m_MouseDeltaWx; @@ -1054,24 +1275,49 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) { if(s_Operation == OP_MOVEPOINT) { - for(int m = 0; m < 4; m++) - if(m_SelectedPoints&(1<<m)) - { - pQuad->m_aPoints[m].x += f2fx(dx); - pQuad->m_aPoints[m].y += f2fx(dy); - } + if(m_GridActive && !IgnoreGrid) + { + for(int m = 0; m < 4; m++) + if(m_SelectedPoints&(1<<m)) + { + int LineDistance = GetLineDistance(); + + float x = 0.0f; + float y = 0.0f; + if(wx >= 0) + x = (int)((wx+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + x = (int)((wx-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + if(wy >= 0) + y = (int)((wy+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + y = (int)((wy-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + + pQuad->m_aPoints[m].x = f2fx(x); + pQuad->m_aPoints[m].y = f2fx(y); + } + } + else + { + for(int m = 0; m < 4; m++) + if(m_SelectedPoints&(1<<m)) + { + pQuad->m_aPoints[m].x += f2fx(dx); + pQuad->m_aPoints[m].y += f2fx(dy); + } + } } else if(s_Operation == OP_MOVEUV) { for(int m = 0; m < 4; m++) if(m_SelectedPoints&(1<<m)) { - // 0,2;1,3 - line x + // 0,2;1,3 - line x // 0,1;2,3 - line y pQuad->m_aTexcoords[m].x += f2fx(dx*0.001f); pQuad->m_aTexcoords[(m+2)%4].x += f2fx(dx*0.001f); - + pQuad->m_aTexcoords[m].y += f2fx(dy*0.001f); pQuad->m_aTexcoords[m^1].y += f2fx(dy*0.001f); } @@ -1110,7 +1356,7 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) ms_pUiGotContext = pID; Graphics()->SetColor(1,1,1,1); - m_pTooltip = "Left mouse button to move. Hold shift to move the texture."; + m_pTooltip = "Left mouse button to move. Hold shift to move the texture. Hold alt to ignore grid."; if(UI()->MouseButton(0)) { @@ -1157,14 +1403,222 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) Graphics()->QuadsDraw(&QuadItem, 1); } -void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) +void CEditor::DoQuadEnvelopes(CQuad *pQuad, int Index, int TexID) { - //UI()->ClipEnable(&view); + CEnvelope *pEnvelope = 0x0; + if(pQuad->m_PosEnv >= 0 && pQuad->m_PosEnv < m_Map.m_lEnvelopes.size()) + pEnvelope = m_Map.m_lEnvelopes[pQuad->m_PosEnv]; + if (!pEnvelope) + return; + + //QuadParams + CPoint *pPoints = pQuad->m_aPoints; + + //Draw Lines + Graphics()->TextureSet(-1); + Graphics()->LinesBegin(); + Graphics()->SetColor(80.0f/255, 150.0f/255, 230.f/255, 0.5f); + for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++) + { + float OffsetX = fx2f(pEnvelope->m_lPoints[i].m_aValues[0]); + float OffsetY = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]); + vec2 Pos0 = vec2(fx2f(pPoints[4].x)+OffsetX, fx2f(pPoints[4].y)+OffsetY); - bool ShowPicker = Input()->KeyPressed(KEY_SPACE) != 0 && m_Dialog == DIALOG_NONE; + OffsetX = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[0]); + OffsetY = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[1]); + vec2 Pos1 = vec2(fx2f(pPoints[4].x)+OffsetX, fx2f(pPoints[4].y)+OffsetY); + + IGraphics::CLineItem Line = IGraphics::CLineItem(Pos0.x, Pos0.y, Pos1.x, Pos1.y); + Graphics()->LinesDraw(&Line, 1); + } + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + Graphics()->LinesEnd(); + + //Draw Quads + for(int i = 0; i < pEnvelope->m_lPoints.size(); i++) + { + Graphics()->TextureSet(TexID); + Graphics()->QuadsBegin(); + + //Calc Env Position + float OffsetX = fx2f(pEnvelope->m_lPoints[i].m_aValues[0]); + float OffsetY = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]); + float Rot = fx2f(pEnvelope->m_lPoints[i].m_aValues[2])/360.0f*pi*2; + + //Set Colours + float Alpha = (m_SelectedQuadEnvelope == pQuad->m_PosEnv && m_SelectedEnvelopePoint == i) ? 0.65f : 0.35f; + IGraphics::CColorVertex aArray[4] = { + IGraphics::CColorVertex(0, pQuad->m_aColors[0].r, pQuad->m_aColors[0].g, pQuad->m_aColors[0].b, Alpha), + IGraphics::CColorVertex(1, pQuad->m_aColors[1].r, pQuad->m_aColors[1].g, pQuad->m_aColors[1].b, Alpha), + IGraphics::CColorVertex(2, pQuad->m_aColors[2].r, pQuad->m_aColors[2].g, pQuad->m_aColors[2].b, Alpha), + IGraphics::CColorVertex(3, pQuad->m_aColors[3].r, pQuad->m_aColors[3].g, pQuad->m_aColors[3].b, Alpha)}; + Graphics()->SetColorVertex(aArray, 4); + + //Rotation + if(Rot != 0) + { + static CPoint aRotated[4]; + aRotated[0] = pQuad->m_aPoints[0]; + aRotated[1] = pQuad->m_aPoints[1]; + aRotated[2] = pQuad->m_aPoints[2]; + aRotated[3] = pQuad->m_aPoints[3]; + pPoints = aRotated; + + Rotate(&pQuad->m_aPoints[4], &aRotated[0], Rot); + Rotate(&pQuad->m_aPoints[4], &aRotated[1], Rot); + Rotate(&pQuad->m_aPoints[4], &aRotated[2], Rot); + Rotate(&pQuad->m_aPoints[4], &aRotated[3], Rot); + } + + //Set Texture Coords + Graphics()->QuadsSetSubsetFree( + fx2f(pQuad->m_aTexcoords[0].x), fx2f(pQuad->m_aTexcoords[0].y), + fx2f(pQuad->m_aTexcoords[1].x), fx2f(pQuad->m_aTexcoords[1].y), + fx2f(pQuad->m_aTexcoords[2].x), fx2f(pQuad->m_aTexcoords[2].y), + fx2f(pQuad->m_aTexcoords[3].x), fx2f(pQuad->m_aTexcoords[3].y) + ); + + //Set Quad Coords & Draw + IGraphics::CFreeformItem Freeform( + fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY, + fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY, + fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY, + fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY); + Graphics()->QuadsDrawFreeform(&Freeform, 1); + + Graphics()->QuadsEnd(); + + Graphics()->TextureSet(-1); + Graphics()->QuadsBegin(); + DoQuadEnvPoint(pQuad, Index, i); + Graphics()->QuadsEnd(); + } +} + +void CEditor::DoQuadEnvPoint(CQuad *pQuad, int QIndex, int PIndex) +{ + enum + { + OP_NONE=0, + OP_MOVE, + OP_ROTATE, + }; + // some basic values + static float s_LastWx; + static float s_LastWy; + static int s_Operation = OP_NONE; + float wx = UI()->MouseWorldX(); + float wy = UI()->MouseWorldY(); + CEnvelope *pEnvelope = m_Map.m_lEnvelopes[pQuad->m_PosEnv]; + void *pID = &pEnvelope->m_lPoints[PIndex]; + static int s_ActQIndex = -1; + + // get pivot + float CenterX = fx2f(pQuad->m_aPoints[4].x)+fx2f(pEnvelope->m_lPoints[PIndex].m_aValues[0]); + float CenterY = fx2f(pQuad->m_aPoints[4].y)+fx2f(pEnvelope->m_lPoints[PIndex].m_aValues[1]); + + float dx = (CenterX - wx)/m_WorldZoom; + float dy = (CenterY - wy)/m_WorldZoom; + if(dx*dx+dy*dy < 50.0f && UI()->ActiveItem() == 0) + { + UI()->SetHotItem(pID); + s_ActQIndex = QIndex; + } + + bool IgnoreGrid; + if(Input()->KeyPressed(KEY_LALT) || Input()->KeyPressed(KEY_RALT)) + IgnoreGrid = true; + else + IgnoreGrid = false; + + if(UI()->ActiveItem() == pID && s_ActQIndex == QIndex) + { + if(s_Operation == OP_MOVE) + { + if(m_GridActive && !IgnoreGrid) + { + int LineDistance = GetLineDistance(); + + float x = 0.0f; + float y = 0.0f; + if(wx >= 0) + x = (int)((wx+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + x = (int)((wx-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + if(wy >= 0) + y = (int)((wy+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + else + y = (int)((wy-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); + + pEnvelope->m_lPoints[PIndex].m_aValues[0] = f2fx(x); + pEnvelope->m_lPoints[PIndex].m_aValues[1] = f2fx(y); + } + else + { + pEnvelope->m_lPoints[PIndex].m_aValues[0] += f2fx(wx-s_LastWx); + pEnvelope->m_lPoints[PIndex].m_aValues[1] += f2fx(wy-s_LastWy); + } + } + else if(s_Operation == OP_ROTATE) + pEnvelope->m_lPoints[PIndex].m_aValues[2] += 10*m_MouseDeltaX; + + s_LastWx = wx; + s_LastWy = wy; + + if(!UI()->MouseButton(0)) + { + m_LockMouse = false; + s_Operation = OP_NONE; + UI()->SetActiveItem(0); + } + + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + } + else if(UI()->HotItem() == pID && s_ActQIndex == QIndex) + { + ms_pUiGotContext = pID; + + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + m_pTooltip = "Left mouse button to move. Hold ctrl to rotate. Hold alt to ignore grid."; + + if(UI()->MouseButton(0)) + { + if(Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)) + { + m_LockMouse = true; + s_Operation = OP_ROTATE; + } + else + s_Operation = OP_MOVE; + + m_SelectedEnvelopePoint = PIndex; + m_SelectedQuadEnvelope = pQuad->m_PosEnv; + + UI()->SetActiveItem(pID); + if(m_SelectedQuad != QIndex) + m_SelectedPoints = 0; + m_SelectedQuad = QIndex; + s_LastWx = wx; + s_LastWy = wy; + } + else + { + m_SelectedEnvelopePoint = -1; + m_SelectedQuadEnvelope = -1; + } + } + else + Graphics()->SetColor(0.0f, 1.0f, 0.0f, 1.0f); + + IGraphics::CQuadItem QuadItem(CenterX, CenterY, 5.0f*m_WorldZoom, 5.0f*m_WorldZoom); + Graphics()->QuadsDraw(&QuadItem, 1); +} + +void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) +{ // render all good stuff - if(!ShowPicker) + if(!m_ShowPicker) { for(int g = 0; g < m_Map.m_lGroups.size(); g++) { @@ -1182,7 +1636,16 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) CLayerTiles *pT = static_cast<CLayerTiles *>(GetSelectedLayerType(0, LAYERTYPE_TILES)); if(m_ShowTileInfo && pT && pT->m_Visible && m_ZoomLevel <= 300) + { + GetSelectedGroup()->MapScreen(); pT->ShowInfo(); + } + } + else + { + // fix aspect ratio of the image in the picker + float Max = min(View.w, View.h); + View.w = View.h = Max; } static void *s_pEditorID = (void *)&s_pEditorID; @@ -1196,8 +1659,6 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) static float s_StartWx = 0; static float s_StartWy = 0; - static float s_StartMx = 0; - static float s_StartMy = 0; enum { @@ -1210,7 +1671,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) }; // remap the screen so it can display the whole tileset - if(ShowPicker) + if(m_ShowPicker) { CUIRect Screen = *UI()->Screen(); float Size = 32.0*16.0f; @@ -1239,7 +1700,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) int NumEditLayers = 0; NumEditLayers = 0; - if(ShowPicker) + if(m_ShowPicker) { pEditLayers[0] = &m_TilesetPicker; NumEditLayers++; @@ -1255,6 +1716,8 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { g->MapScreen(); + RenderGrid(g); + for(int i = 0; i < NumEditLayers; i++) { if(pEditLayers[i]->m_Type != LAYERTYPE_TILES) @@ -1285,8 +1748,6 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { s_StartWx = wx; s_StartWy = wy; - s_StartMx = mx; - s_StartMy = my; if(Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL) || UI()->MouseButton(2)) { @@ -1365,8 +1826,8 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { if(!UI()->MouseButton(0)) { - for(int k = 0; k < NumEditLayers; k++) - pEditLayers[k]->FillSelection(m_Brush.IsEmpty(), m_Brush.m_lLayers[0], r); + for(int k = 0; k < NumEditLayers; k++) + pEditLayers[k]->FillSelection(m_Brush.IsEmpty(), m_Brush.m_lLayers[0], r); } else { @@ -1398,10 +1859,10 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) } } - + CLayerTiles *pLayer = (CLayerTiles*)GetSelectedLayerType(0, LAYERTYPE_TILES); if((Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) && pLayer) - s_Operation = OP_BRUSH_PAINT; + s_Operation = OP_BRUSH_PAINT; } if(!m_Brush.IsEmpty()) @@ -1445,7 +1906,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) // quad editing { - if(!ShowPicker && m_Brush.IsEmpty()) + if(!m_ShowPicker && m_Brush.IsEmpty()) { // fetch layers CLayerGroup *g = GetSelectedGroup(); @@ -1458,6 +1919,9 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { CLayerQuads *pLayer = (CLayerQuads *)pEditLayers[k]; + if(!m_ShowEnvelopePreview) + m_ShowEnvelopePreview = 2; + Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); for(int i = 0; i < pLayer->m_lQuads.size(); i++) @@ -1507,11 +1971,11 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) } } - if(GetSelectedGroup() && GetSelectedGroup()->m_UseClipping) + if(!m_ShowPicker && GetSelectedGroup() && GetSelectedGroup()->m_UseClipping) { CLayerGroup *g = m_Map.m_pGameGroup; g->MapScreen(); - + Graphics()->TextureSet(-1); Graphics()->LinesBegin(); @@ -1615,6 +2079,24 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) Graphics()->LinesEnd(); } + if (!m_ShowPicker && m_ShowTileInfo && m_ShowEnvelopePreview != 0 && GetSelectedLayer(0) && GetSelectedLayer(0)->m_Type == LAYERTYPE_QUADS) + { + GetSelectedGroup()->MapScreen(); + + CLayerQuads *pLayer = (CLayerQuads*)GetSelectedLayer(0); + int TexID = -1; + if(pLayer->m_Image >= 0 && pLayer->m_Image < m_Map.m_lImages.size()) + TexID = m_Map.m_lImages[pLayer->m_Image]->m_TexID; + + for(int i = 0; i < pLayer->m_lQuads.size(); i++) + { + if((m_ShowEnvelopePreview == 1 && pLayer->m_lQuads[i].m_PosEnv == m_SelectedEnvelope) || m_ShowEnvelopePreview == 2) + DoQuadEnvelopes(&pLayer->m_lQuads[i], i, TexID); + } + + m_ShowEnvelopePreview = 0; + } + Graphics()->MapScreen(UI()->Screen()->x, UI()->Screen()->y, UI()->Screen()->w, UI()->Screen()->h); //UI()->ClipDisable(); } @@ -1710,7 +2192,7 @@ int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIDs, int * if(pProps[i].m_Value < 0) str_copy(aBuf, "None", sizeof(aBuf)); else - str_format(aBuf, sizeof(aBuf),"%s", m_Map.m_lImages[pProps[i].m_Value]->m_aName); + str_format(aBuf, sizeof(aBuf),"%s", m_Map.m_lImages[pProps[i].m_Value]->m_aName); if(DoButton_Editor(&pIDs[i], aBuf, 0, &Shifter, 0, 0)) PopupSelectImageInvoke(pProps[i].m_Value, UI()->MouseX(), UI()->MouseY()); @@ -1772,22 +2254,18 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) CUIRect Slot, Button; char aBuf[64]; - int ValidGroup = 0; - int ValidLayer = 0; - if(m_SelectedGroup >= 0 && m_SelectedGroup < m_Map.m_lGroups.size()) - ValidGroup = 1; - - if(ValidGroup && m_SelectedLayer >= 0 && m_SelectedLayer < m_Map.m_lGroups[m_SelectedGroup]->m_lLayers.size()) - ValidLayer = 1; - float LayersHeight = 12.0f; // Height of AddGroup button static int s_ScrollBar = 0; static float s_ScrollValue = 0; for(int g = 0; g < m_Map.m_lGroups.size(); g++) + { // Each group is 19.0f // Each layer is 14.0f - LayersHeight += 19.0f + m_Map.m_lGroups[g]->m_lLayers.size() * 14.0f; + LayersHeight += 19.0f; + if(!m_Map.m_lGroups[g]->m_Collapse) + LayersHeight += m_Map.m_lGroups[g]->m_lLayers.size() * 14.0f; + } float ScrollDifference = LayersHeight - LayersBox.h; @@ -1798,6 +2276,20 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) LayersBox.VSplitRight(3.0f, &LayersBox, 0); // extra spacing Scroll.HMargin(5.0f, &Scroll); s_ScrollValue = UiDoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue); + + if(UI()->MouseInside(&Scroll) || UI()->MouseInside(&LayersBox)) + { + int ScrollNum = (int)((LayersHeight-LayersBox.h)/15.0f)+1; + if(ScrollNum > 0) + { + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + s_ScrollValue = clamp(s_ScrollValue - 1.0f/ScrollNum, 0.0f, 1.0f); + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f); + } + else + ScrollNum = 0; + } } float LayerStartAt = ScrollDifference * s_ScrollValue; @@ -1824,7 +2316,7 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) { LayersBox.HSplitTop(12.0f, &Slot, &LayersBox); Slot.VSplitLeft(12, &VisibleToggle, &Slot); - if(DoButton_Ex(&m_Map.m_lGroups[g]->m_Visible, m_Map.m_lGroups[g]->m_Visible?"V":"H", 0, &VisibleToggle, 0, "Toggle group visibility", CUI::CORNER_L)) + if(DoButton_Ex(&m_Map.m_lGroups[g]->m_Visible, m_Map.m_lGroups[g]->m_Visible?"V":"H", m_Map.m_lGroups[g]->m_Collapse ? 1 : 0, &VisibleToggle, 0, "Toggle group visibility", CUI::CORNER_L)) m_Map.m_lGroups[g]->m_Visible = !m_Map.m_lGroups[g]->m_Visible; Slot.VSplitRight(12.0f, &Slot, &SaveCheck); @@ -1832,16 +2324,22 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) if(!m_Map.m_lGroups[g]->m_GameGroup) m_Map.m_lGroups[g]->m_SaveToMap = !m_Map.m_lGroups[g]->m_SaveToMap; - str_format(aBuf, sizeof(aBuf),"#%d %s", g, m_Map.m_lGroups[g]->m_pName); + str_format(aBuf, sizeof(aBuf),"#%d %s", g, m_Map.m_lGroups[g]->m_aName); + float FontSize = 10.0f; + while(TextRender()->TextWidth(0, FontSize, aBuf, -1) > Slot.w) + FontSize--; if(int Result = DoButton_Ex(&m_Map.m_lGroups[g], aBuf, g==m_SelectedGroup, &Slot, - BUTTON_CONTEXT, "Select group. Right click for properties.", 0)) + BUTTON_CONTEXT, m_Map.m_lGroups[g]->m_Collapse ? "Select group. Double click to expand." : "Select group. Double click to collapse.", 0, FontSize)) { m_SelectedGroup = g; m_SelectedLayer = 0; static int s_GroupPopupId = 0; if(Result == 2) - UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, PopupGroup); + UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 145, 220, PopupGroup); + + if(m_Map.m_lGroups[g]->m_lLayers.size() && Input()->MouseDoubleClick()) + m_Map.m_lGroups[g]->m_Collapse ^= 1; } LayersBox.HSplitTop(2.0f, &Slot, &LayersBox); } @@ -1857,6 +2355,9 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) continue; } + if(m_Map.m_lGroups[g]->m_Collapse) + continue; + //visible LayersBox.HSplitTop(12.0f, &Slot, &LayersBox); Slot.VSplitLeft(12.0f, 0, &Button); @@ -1870,15 +2371,24 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) if(m_Map.m_lGroups[g]->m_lLayers[i] != m_Map.m_pGameLayer) m_Map.m_lGroups[g]->m_lLayers[i]->m_SaveToMap = !m_Map.m_lGroups[g]->m_lLayers[i]->m_SaveToMap; - str_format(aBuf, sizeof(aBuf),"#%d %s ", i, m_Map.m_lGroups[g]->m_lLayers[i]->m_pTypeName); + if(m_Map.m_lGroups[g]->m_lLayers[i]->m_aName[0]) + str_format(aBuf, sizeof(aBuf), "%s", m_Map.m_lGroups[g]->m_lLayers[i]->m_aName); + else if(m_Map.m_lGroups[g]->m_lLayers[i]->m_Type == LAYERTYPE_TILES) + str_copy(aBuf, "Tiles", sizeof(aBuf)); + else + str_copy(aBuf, "Quads", sizeof(aBuf)); + + float FontSize = 10.0f; + while(TextRender()->TextWidth(0, FontSize, aBuf, -1) > Button.w) + FontSize--; if(int Result = DoButton_Ex(m_Map.m_lGroups[g]->m_lLayers[i], aBuf, g==m_SelectedGroup&&i==m_SelectedLayer, &Button, - BUTTON_CONTEXT, "Select layer. Right click for properties.", 0)) + BUTTON_CONTEXT, "Select layer.", 0, FontSize)) { m_SelectedLayer = i; m_SelectedGroup = g; static int s_LayerPopupID = 0; if(Result == 2) - UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 220, PopupLayer); + UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 245, PopupLayer); } LayerCur += 14.0f; @@ -1916,12 +2426,13 @@ void CEditor::ReplaceImage(const char *pFileName, int StorageType, void *pUser) *pImg = ImgInfo; pImg->m_External = External; pEditor->ExtractName(pFileName, pImg->m_aName, sizeof(pImg->m_aName)); + pImg->m_AutoMapper.Load(pImg->m_aName); pImg->m_TexID = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0); pEditor->SortImages(); for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i) { - if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, pImg->m_aName)) - pEditor->m_SelectedImage = i; + if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, pImg->m_aName)) + pEditor->m_SelectedImage = i; } pEditor->m_Dialog = DIALOG_NONE; } @@ -1938,8 +2449,8 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser) ExtractName(pFileName, aBuf, sizeof(aBuf)); for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i) { - if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, aBuf)) - return; + if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, aBuf)) + return; } CEditorImage *pImg = new CEditorImage(pEditor); @@ -1947,6 +2458,7 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser) pImg->m_TexID = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0); pImg->m_External = 1; // external by default str_copy(pImg->m_aName, aBuf, sizeof(pImg->m_aName)); + pImg->m_AutoMapper.Load(pImg->m_aName); pEditor->m_Map.m_lImages.add(pImg); pEditor->SortImages(); if(pEditor->m_SelectedImage > -1 && pEditor->m_SelectedImage < pEditor->m_Map.m_lImages.size()) @@ -2064,7 +2576,7 @@ void CEditor::SortImages() gs_pSortedIndex = 0; } } - + void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) { @@ -2080,6 +2592,20 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) ToolBox.VSplitRight(3.0f, &ToolBox, 0); // extra spacing Scroll.HMargin(5.0f, &Scroll); s_ScrollValue = UiDoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue); + + if(UI()->MouseInside(&Scroll) || UI()->MouseInside(&ToolBox)) + { + int ScrollNum = (int)((ImagesHeight-ToolBox.h)/14.0f)+1; + if(ScrollNum > 0) + { + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + s_ScrollValue = clamp(s_ScrollValue - 1.0f/ScrollNum, 0.0f, 1.0f); + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f); + } + else + ScrollNum = 0; + } } float ImageStartAt = ScrollDifference * s_ScrollValue; @@ -2148,15 +2674,28 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) r.w = r.h; else r.h = r.w; + float Max = (float)(max(m_Map.m_lImages[i]->m_Width, m_Map.m_lImages[i]->m_Height)); + r.w *= m_Map.m_lImages[i]->m_Width/Max; + r.h *= m_Map.m_lImages[i]->m_Height/Max; Graphics()->TextureSet(m_Map.m_lImages[i]->m_TexID); Graphics()->BlendNormal(); + Graphics()->WrapClamp(); Graphics()->QuadsBegin(); IGraphics::CQuadItem QuadItem(r.x, r.y, r.w, r.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - + Graphics()->WrapNormal(); } } + + // separator + ToolBox.HSplitTop(5.0f, &Slot, &ToolBox); + ImageCur += 5.0f; + IGraphics::CLineItem LineItem(Slot.x, Slot.y+Slot.h/2, Slot.x+Slot.w, Slot.y+Slot.h/2); + Graphics()->TextureSet(-1); + Graphics()->LinesBegin(); + Graphics()->LinesDraw(&LineItem, 1); + Graphics()->LinesEnd(); } if(ImageCur + 27.0f > ImageStopAt) @@ -2167,7 +2706,6 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) // new image static int s_NewImageButton = 0; - ToolBox.HSplitTop(10.0f, &Slot, &ToolBox); ToolBox.HSplitTop(12.0f, &Slot, &ToolBox); if(DoButton_Editor(&s_NewImageButton, "Add", 0, &Slot, 0, "Load a new image to use in the map")) InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Add Image", "Add", "mapres", "", AddImage, this); @@ -2217,7 +2755,7 @@ void CEditor::AddFileDialogEntry(int Index, CUIRect *pView) Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - if(DoButton_File((void*)(10+(int)Button.y), m_FileList[Index].m_aName, m_FilesSelectedIndex == Index, &Button, 0, 0)) + if(DoButton_File(&m_FileList[Index], m_FileList[Index].m_aName, m_FilesSelectedIndex == Index, &Button, 0, 0)) { if(!m_FileList[Index].m_IsDir) str_copy(m_aFileDialogFileName, m_FileList[Index].m_aFilename, sizeof(m_aFileDialogFileName)); @@ -2243,11 +2781,13 @@ void CEditor::RenderFileDialog() RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.75f), CUI::CORNER_ALL, 5.0f); View.Margin(10.0f, &View); - CUIRect Title, FileBox, FileBoxLabel, ButtonBar, Scroll; + CUIRect Title, FileBox, FileBoxLabel, ButtonBar, Scroll, PathBox; View.HSplitTop(18.0f, &Title, &View); View.HSplitTop(5.0f, 0, &View); // some spacing View.HSplitBottom(14.0f, &View, &ButtonBar); View.HSplitBottom(10.0f, &View, 0); // some spacing + View.HSplitBottom(14.0f, &View, &PathBox); + View.HSplitBottom(5.0f, &View, 0); // some spacing View.HSplitBottom(14.0f, &View, &FileBox); FileBox.VSplitLeft(55.0f, &FileBoxLabel, &FileBox); View.HSplitBottom(10.0f, &View, 0); // some spacing @@ -2258,12 +2798,21 @@ void CEditor::RenderFileDialog() Title.VMargin(10.0f, &Title); UI()->DoLabel(&Title, m_pFileDialogTitle, 12.0f, -1, -1); + // pathbox + char aPath[128], aBuf[128]; + if(m_FilesSelectedIndex != -1) + Storage()->GetCompletePath(m_FileList[m_FilesSelectedIndex].m_StorageType, m_pFileDialogPath, aPath, sizeof(aPath)); + else + aPath[0] = 0; + str_format(aBuf, sizeof(aBuf), "Current path: %s", aPath); + UI()->DoLabel(&PathBox, aBuf, 10.0f, -1, -1); + // filebox if(m_FileDialogStorageType == IStorage::TYPE_SAVE) { - static int s_FileBoxID = 0; + static float s_FileBoxID = 0; UI()->DoLabel(&FileBoxLabel, "Filename:", 10.0f, -1, -1); - if(DoEditBox(&s_FileBoxID, &FileBox, m_aFileDialogFileName, sizeof(m_aFileDialogFileName), 10.0f)) + if(DoEditBox(&s_FileBoxID, &FileBox, m_aFileDialogFileName, sizeof(m_aFileDialogFileName), 10.0f, &s_FileBoxID)) { // remove '/' and '\' for(int i = 0; m_aFileDialogFileName[i]; ++i) @@ -2354,6 +2903,7 @@ void CEditor::RenderFileDialog() static int s_OkButton = 0; static int s_CancelButton = 0; static int s_NewFolderButton = 0; + static int s_MapInfoButton = 0; CUIRect Button; ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button); @@ -2429,6 +2979,22 @@ void CEditor::RenderFileDialog() UI()->SetActiveItem(0); } } + + if(m_FileDialogStorageType == IStorage::TYPE_SAVE) + { + ButtonBar.VSplitLeft(40.0f, 0, &ButtonBar); + ButtonBar.VSplitLeft(70.0f, &Button, &ButtonBar); + if(DoButton_Editor(&s_MapInfoButton, "Map details", 0, &Button, 0, 0)) + { + str_copy(m_Map.m_MapInfo.m_aAuthorTmp, m_Map.m_MapInfo.m_aAuthor, sizeof(m_Map.m_MapInfo.m_aAuthorTmp)); + str_copy(m_Map.m_MapInfo.m_aVersionTmp, m_Map.m_MapInfo.m_aVersion, sizeof(m_Map.m_MapInfo.m_aVersionTmp)); + str_copy(m_Map.m_MapInfo.m_aCreditsTmp, m_Map.m_MapInfo.m_aCredits, sizeof(m_Map.m_MapInfo.m_aCreditsTmp)); + str_copy(m_Map.m_MapInfo.m_aLicenseTmp, m_Map.m_MapInfo.m_aLicense, sizeof(m_Map.m_MapInfo.m_aLicenseTmp)); + static int s_MapInfoPopupID = 0; + UiInvokePopupMenu(&s_MapInfoPopupID, 0, Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, PopupMapInfo); + UI()->SetActiveItem(0); + } + } } void CEditor::FilelistPopulate(int StorageType) @@ -2469,7 +3035,7 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle str_copy(m_aFileDialogFileName, pDefaultName, sizeof(m_aFileDialogFileName)); if(pBasePath) str_copy(m_aFileDialogCurrentFolder, pBasePath, sizeof(m_aFileDialogCurrentFolder)); - + FilelistPopulate(m_FileDialogStorageType); m_Dialog = DIALOG_FILE; @@ -2489,10 +3055,10 @@ void CEditor::RenderModebar(CUIRect View) const char *pButName = m_Mode == MODE_LAYERS ? "Layers" : "Images"; if(DoButton_Tab(&s_Button, pButName, 0, &Button, 0, "Switch between images and layers managment.")) { - if(m_Mode == MODE_LAYERS) - m_Mode = MODE_IMAGES; - else - m_Mode = MODE_LAYERS; + if(m_Mode == MODE_LAYERS) + m_Mode = MODE_IMAGES; + else + m_Mode = MODE_LAYERS; } } @@ -2612,8 +3178,8 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) ToolBar.VSplitLeft(80.0f, &Button, &ToolBar); - static int s_NameBox = 0; - if(DoEditBox(&s_NameBox, &Button, pEnvelope->m_aName, sizeof(pEnvelope->m_aName), 10.0f)) + static float s_NameBox = 0; + if(DoEditBox(&s_NameBox, &Button, pEnvelope->m_aName, sizeof(pEnvelope->m_aName), 10.0f, &s_NameBox)) m_Map.m_Modified = true; } } @@ -2666,6 +3232,17 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) if(DoButton_Editor(&s_aChannelButtons[i], s_paNames[pEnvelope->m_Channels-3][i], s_ActiveChannels&Bit, &Button, 0, paDescriptions[pEnvelope->m_Channels-3][i])) s_ActiveChannels ^= Bit; } + + // sync checkbox + ToolBar.VSplitLeft(15.0f, &Button, &ToolBar); + ToolBar.VSplitLeft(12.0f, &Button, &ToolBar); + static int s_SyncButton; + if(DoButton_Editor(&s_SyncButton, pEnvelope->m_Synchronized?"X":"", 0, &Button, 0, "Enable envelope synchronization between clients")) + pEnvelope->m_Synchronized = !pEnvelope->m_Synchronized; + + ToolBar.VSplitLeft(4.0f, &Button, &ToolBar); + ToolBar.VSplitLeft(80.0f, &Button, &ToolBar); + UI()->DoLabel(&Button, "Synchronized", 10.0f, -1, -1); } float EndTime = pEnvelope->EndTime(); @@ -2705,6 +3282,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) m_Map.m_Modified = true; } + m_ShowEnvelopePreview = 1; m_pTooltip = "Press right mouse button to create a new point"; } } @@ -2811,8 +3389,6 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) // render handles { - static bool s_Move = false; - int CurrentValue = 0, CurrentTime = 0; Graphics()->TextureSet(-1); @@ -2845,11 +3421,13 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) { if(!UI()->MouseButton(0)) { + m_SelectedQuadEnvelope = -1; + m_SelectedEnvelopePoint = -1; + UI()->SetActiveItem(0); - s_Move = false; } else - { + { if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) { if(i != 0) @@ -2871,6 +3449,10 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) else pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*ValueScale); } + + m_SelectedQuadEnvelope = m_SelectedEnvelope; + m_ShowEnvelopePreview = 1; + m_SelectedEnvelopePoint = i; m_Map.m_Modified = true; } @@ -2893,6 +3475,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) m_Map.m_Modified = true; } + m_ShowEnvelopePreview = 1; ColorMod = 100.0f; Graphics()->SetColor(1,0.75f,0.75f,1); m_pTooltip = "Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete."; @@ -2904,7 +3487,10 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) CurrentValue = pEnvelope->m_lPoints[i].m_aValues[c]; } - Graphics()->SetColor(aColors[c].r*ColorMod, aColors[c].g*ColorMod, aColors[c].b*ColorMod, 1.0f); + if (m_SelectedQuadEnvelope == m_SelectedEnvelope && m_SelectedEnvelopePoint == i) + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + else + Graphics()->SetColor(aColors[c].r*ColorMod, aColors[c].g*ColorMod, aColors[c].b*ColorMod, 1.0f); IGraphics::CQuadItem QuadItem(Final.x, Final.y, Final.w, Final.h); Graphics()->QuadsDrawTL(&QuadItem, 1); } @@ -3027,10 +3613,15 @@ void CEditor::RenderMenubar(CUIRect MenuBar) (void)0; */ + CUIRect Info; MenuBar.VSplitLeft(40.0f, 0, &MenuBar); + MenuBar.VSplitLeft(MenuBar.w*0.75f, &MenuBar, &Info); char aBuf[128]; str_format(aBuf, sizeof(aBuf), "File: %s", m_aFileName); UI()->DoLabel(&MenuBar, aBuf, 10.0f, -1, -1); + + str_format(aBuf, sizeof(aBuf), "Z: %i, A: %.1f, G: %i", m_ZoomLevel, m_AnimateSpeed, m_GridFactor); + UI()->DoLabel(&Info, aBuf, 10.0f, 1, -1); } void CEditor::Render() @@ -3046,10 +3637,14 @@ void CEditor::Render() // reset tip m_pTooltip = 0; + if(m_EditBoxActive) + --m_EditBoxActive; + // render checker RenderBackground(View, ms_CheckerTexture, 32.0f, 1.0f); CUIRect MenuBar, CModeBar, ToolBar, StatusBar, EnvelopeEditor, ToolBox; + m_ShowPicker = Input()->KeyPressed(KEY_SPACE) != 0 && m_Dialog == DIALOG_NONE; if(m_GuiActive) { @@ -3059,7 +3654,7 @@ void CEditor::Render() View.VSplitLeft(100.0f, &ToolBox, &View); View.HSplitBottom(16.0f, &View, &StatusBar); - if(m_ShowEnvelopeEditor) + if(m_ShowEnvelopeEditor && !m_ShowPicker) { float size = 125.0f; if(m_ShowEnvelopeEditor == 2) @@ -3074,6 +3669,28 @@ void CEditor::Render() if(m_Mode == MODE_LAYERS) DoMapEditor(View, ToolBar); + // do zooming + if(Input()->KeyDown(KEY_KP_MINUS)) + m_ZoomLevel += 50; + if(Input()->KeyDown(KEY_KP_PLUS)) + m_ZoomLevel -= 50; + if(Input()->KeyDown(KEY_KP_MULTIPLY)) + { + m_EditorOffsetX = 0; + m_EditorOffsetY = 0; + m_ZoomLevel = 100; + } + if(m_Dialog == DIALOG_NONE && UI()->MouseInside(&View)) + { + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP)) + m_ZoomLevel -= 20; + + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) + m_ZoomLevel += 20; + } + m_ZoomLevel = clamp(m_ZoomLevel, 50, 2000); + m_WorldZoom = m_ZoomLevel/100.0f; + if(m_GuiActive) { float Brightness = 0.25f; @@ -3130,6 +3747,7 @@ void CEditor::Render() static int s_PopupID = 0; UiInvokePopupMenu(&s_PopupID, 0, Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, PopupEvent); m_PopupEventActivated = false; + m_PopupEventWasActivated = true; } @@ -3171,7 +3789,6 @@ void CEditor::Render() Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } - } void CEditor::Reset(bool CreateDefault) @@ -3192,12 +3809,12 @@ void CEditor::Reset(bool CreateDefault) m_SelectedPoints = 0; m_SelectedEnvelope = 0; m_SelectedImage = 0; - + m_WorldOffsetX = 0; m_WorldOffsetY = 0; m_EditorOffsetX = 0.0f; m_EditorOffsetY = 0.0f; - + m_WorldZoom = 1.0f; m_ZoomLevel = 200; @@ -3207,6 +3824,26 @@ void CEditor::Reset(bool CreateDefault) m_MouseDeltaWy = 0; m_Map.m_Modified = false; + + m_ShowEnvelopePreview = 0; +} + +int CEditor::GetLineDistance() +{ + int LineDistance = 512; + + if(m_ZoomLevel <= 100) + LineDistance = 16; + else if(m_ZoomLevel <= 250) + LineDistance = 32; + else if(m_ZoomLevel <= 450) + LineDistance = 64; + else if(m_ZoomLevel <= 850) + LineDistance = 128; + else if(m_ZoomLevel <= 1550) + LineDistance = 256; + + return LineDistance; } void CEditorMap::DeleteEnvelope(int Index) @@ -3221,19 +3858,27 @@ void CEditorMap::DeleteEnvelope(int Index) for(int j = 0; j < m_lGroups[i]->m_lLayers.size(); ++j) if(m_lGroups[i]->m_lLayers[j]->m_Type == LAYERTYPE_QUADS) { - CLayerQuads *Layer = static_cast<CLayerQuads *>(m_lGroups[i]->m_lLayers[j]); - for(int k = 0; k < Layer->m_lQuads.size(); ++k) + CLayerQuads *pLayer = static_cast<CLayerQuads *>(m_lGroups[i]->m_lLayers[j]); + for(int k = 0; k < pLayer->m_lQuads.size(); ++k) { - if(Layer->m_lQuads[k].m_PosEnv == Index) - Layer->m_lQuads[k].m_PosEnv = -1; - else if(Layer->m_lQuads[k].m_PosEnv > Index) - Layer->m_lQuads[k].m_PosEnv--; - if(Layer->m_lQuads[k].m_ColorEnv == Index) - Layer->m_lQuads[k].m_ColorEnv = -1; - else if(Layer->m_lQuads[k].m_ColorEnv > Index) - Layer->m_lQuads[k].m_ColorEnv--; + if(pLayer->m_lQuads[k].m_PosEnv == Index) + pLayer->m_lQuads[k].m_PosEnv = -1; + else if(pLayer->m_lQuads[k].m_PosEnv > Index) + pLayer->m_lQuads[k].m_PosEnv--; + if(pLayer->m_lQuads[k].m_ColorEnv == Index) + pLayer->m_lQuads[k].m_ColorEnv = -1; + else if(pLayer->m_lQuads[k].m_ColorEnv > Index) + pLayer->m_lQuads[k].m_ColorEnv--; } } + else if(m_lGroups[i]->m_lLayers[j]->m_Type == LAYERTYPE_TILES) + { + CLayerTiles *pLayer = static_cast<CLayerTiles *>(m_lGroups[i]->m_lLayers[j]); + if(pLayer->m_ColorEnv == Index) + pLayer->m_ColorEnv = -1; + if(pLayer->m_ColorEnv > Index) + pLayer->m_ColorEnv--; + } m_lEnvelopes.remove_index(Index); } @@ -3249,7 +3894,7 @@ void CEditorMap::MakeGameGroup(CLayerGroup *pGroup) { m_pGameGroup = pGroup; m_pGameGroup->m_GameGroup = true; - m_pGameGroup->m_pName = "Game"; + str_copy(m_pGameGroup->m_aName, "Game", sizeof(m_pGameGroup->m_aName)); } @@ -3260,6 +3905,8 @@ void CEditorMap::Clean() m_lEnvelopes.delete_all(); m_lImages.delete_all(); + m_MapInfo.Reset(); + m_pGameLayer = 0x0; m_pGameGroup = 0x0; @@ -3325,19 +3972,19 @@ void CEditor::Init() void CEditor::DoMapBorder() { - CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); - - for(int i = 0; i < pT->m_Width*2; ++i) - pT->m_pTiles[i].m_Index = 1; - - for(int i = 0; i < pT->m_Width*pT->m_Height; ++i) - { - if(i%pT->m_Width < 2 || i%pT->m_Width > pT->m_Width-3) - pT->m_pTiles[i].m_Index = 1; - } - - for(int i = (pT->m_Width*(pT->m_Height-2)); i < pT->m_Width*pT->m_Height; ++i) - pT->m_pTiles[i].m_Index = 1; + CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); + + for(int i = 0; i < pT->m_Width*2; ++i) + pT->m_pTiles[i].m_Index = 1; + + for(int i = 0; i < pT->m_Width*pT->m_Height; ++i) + { + if(i%pT->m_Width < 2 || i%pT->m_Width > pT->m_Width-3) + pT->m_pTiles[i].m_Index = 1; + } + + for(int i = (pT->m_Width*(pT->m_Height-2)); i < pT->m_Width*pT->m_Height; ++i) + pT->m_pTiles[i].m_Index = 1; } void CEditor::UpdateAndRender() @@ -3356,6 +4003,7 @@ void CEditor::UpdateAndRender() float rx, ry; { Input()->MouseRelative(&rx, &ry); + UI()->ConvertMouseMove(&rx, &ry); m_MouseDeltaX = rx; m_MouseDeltaY = ry; @@ -3402,18 +4050,6 @@ void CEditor::UpdateAndRender() if(Input()->KeyDown(KEY_TAB)) m_GuiActive = !m_GuiActive; - if(Input()->KeyDown(KEY_F5)) - Save("maps/debug_test2.map"); - - if(Input()->KeyDown(KEY_F6)) - Load("maps/debug_test2.map", IStorage::TYPE_ALL); - - if(Input()->KeyDown(KEY_F8)) - Load("maps/debug_test.map", IStorage::TYPE_ALL); - - if(Input()->KeyDown(KEY_F7)) - Save("maps/quicksave.map"); - if(Input()->KeyDown(KEY_F10)) m_ShowMousePointer = false; diff --git a/src/game/editor/ed_editor.h b/src/game/editor/editor.h index aab757e1..a81474d9 100644 --- a/src/game/editor/ed_editor.h +++ b/src/game/editor/editor.h @@ -1,25 +1,28 @@ /* (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_ED_EDITOR_H -#define GAME_EDITOR_ED_EDITOR_H +#ifndef GAME_EDITOR_EDITOR_H +#define GAME_EDITOR_EDITOR_H + +#include <math.h> -#include <base/system.h> #include <base/math.h> -#include <base/tl/array.h> +#include <base/system.h> + #include <base/tl/algorithm.h> +#include <base/tl/array.h> #include <base/tl/sorted_array.h> #include <base/tl/string.h> -#include <math.h> +#include <game/client/ui.h> #include <game/mapitems.h> #include <game/client/render.h> -#include <engine/shared/datafile.h> #include <engine/shared/config.h> +#include <engine/shared/datafile.h> #include <engine/editor.h> #include <engine/graphics.h> -#include <game/client/ui.h> +#include "auto_map.h" typedef void (*INDEX_MODIFY_FUNC)(int *pIndex); @@ -48,6 +51,7 @@ public: array<CEnvPoint> m_lPoints; char m_aName[32]; float m_Bottom, m_Top; + bool m_Synchronized; CEnvelope(int Chan) { @@ -55,6 +59,7 @@ public: m_aName[0] = 0; m_Bottom = 0; m_Top = 0; + m_Synchronized = true; } void Resort() @@ -123,7 +128,7 @@ public: CLayer() { m_Type = LAYERTYPE_INVALID; - m_pTypeName = "(invalid)"; + str_copy(m_aName, "(invalid)", sizeof(m_aName)); m_Visible = true; m_Readonly = false; m_SaveToMap = true; @@ -153,7 +158,7 @@ public: virtual void GetSize(float *w, float *h) { *w = 0; *h = 0;} - const char *m_pTypeName; + char m_aName[12]; int m_Type; int m_Flags; @@ -181,10 +186,11 @@ public: int m_ClipW; int m_ClipH; - const char *m_pName; + char m_aName[12]; bool m_GameGroup; bool m_Visible; bool m_SaveToMap; + bool m_Collapse; CLayerGroup(); ~CLayerGroup(); @@ -230,6 +236,7 @@ public: CEditor *m_pEditor; CEditorImage(CEditor *pEditor) + : m_AutoMapper(pEditor) { m_pEditor = pEditor; m_TexID = -1; @@ -249,6 +256,7 @@ public: int m_External; char m_aName[128]; unsigned char m_aTileFlags[256]; + class CAutoMapper m_AutoMapper; }; class CEditorMap @@ -268,6 +276,34 @@ public: array<CEditorImage*> m_lImages; array<CEnvelope*> m_lEnvelopes; + 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; + class CLayerGame *m_pGameLayer; CLayerGroup *m_pGameGroup; @@ -400,6 +436,8 @@ public: int m_Width; int m_Height; CColor m_Color; + int m_ColorEnv; + int m_ColorEnvOffset; CTile *m_pTiles; }; @@ -468,13 +506,18 @@ public: m_Mode = MODE_LAYERS; m_Dialog = 0; + m_EditBoxActive = 0; m_pTooltip = 0; + m_GridActive = false; + m_GridFactor = 1; + m_aFileName[0] = 0; m_aFileSaveName[0] = 0; m_ValidSaveFilename = false; m_PopupEventActivated = false; + m_PopupEventWasActivated = false; m_FileDialogStorageType = 0; m_pFileDialogTitle = 0; @@ -517,6 +560,10 @@ public: m_ShowEnvelopeEditor = 0; + m_ShowEnvelopePreview = 0; + m_SelectedQuadEnvelope = -1; + m_SelectedEnvelopePoint = -1; + ms_CheckerTexture = 0; ms_BackgroundTexture = 0; ms_CursorTexture = 0; @@ -549,8 +596,12 @@ public: int m_Mode; int m_Dialog; + int m_EditBoxActive; const char *m_pTooltip; + bool m_GridActive; + int m_GridFactor; + char m_aFileName[512]; char m_aFileSaveName[512]; bool m_ValidSaveFilename; @@ -565,6 +616,7 @@ public: int m_PopupEventType; int m_PopupEventActivated; + int m_PopupEventWasActivated; enum { @@ -630,12 +682,16 @@ public: float m_AnimateSpeed; int m_ShowEnvelopeEditor; + int m_ShowEnvelopePreview; //Values: 0-Off|1-Selected Envelope|2-All + bool m_ShowPicker; int m_SelectedLayer; int m_SelectedGroup; int m_SelectedQuad; int m_SelectedPoints; int m_SelectedEnvelope; + int m_SelectedEnvelopePoint; + int m_SelectedQuadEnvelope; int m_SelectedImage; static int ms_CheckerTexture; @@ -650,12 +706,14 @@ public: CEditorMap m_Map; + static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser); + void DoMapBorder(); 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_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); + 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_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); @@ -664,10 +722,12 @@ public: 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 DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false); + int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden=false, int Corners=CUI::CORNER_ALL); void RenderBackground(CUIRect View, int 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 *pExtra=0); void UiDoPopupMenu(); @@ -678,11 +738,13 @@ public: static int PopupQuad(CEditor *pEditor, CUIRect View); static int PopupPoint(CEditor *pEditor, CUIRect View); static int PopupNewFolder(CEditor *pEditor, CUIRect View); + static int PopupMapInfo(CEditor *pEditor, CUIRect View); static int PopupEvent(CEditor *pEditor, CUIRect View); static int PopupSelectImage(CEditor *pEditor, CUIRect View); static int PopupSelectGametileOp(CEditor *pEditor, CUIRect View); static int PopupImage(CEditor *pEditor, CUIRect View); static int PopupMenuFile(CEditor *pEditor, CUIRect View); + static int PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View); static void CallbackOpenMap(const char *pFileName, int StorageType, void *pUser); static void CallbackAppendMap(const char *pFileName, int StorageType, void *pUser); @@ -694,9 +756,15 @@ public: void PopupSelectGametileOpInvoke(float x, float y); int PopupSelectGameTileOpResult(); + void PopupSelectConfigAutoMapInvoke(float x, float y); + int PopupSelectConfigAutoMapResult(); + vec4 ButtonColorMul(const void *pID); + void DoQuadEnvelopes(CQuad *pQuad, int Index, int TexID = -1); + void DoQuadEnvPoint(CQuad *pQuad, int QIndex, int pIndex); void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v); + void DoMapEditor(CUIRect View, CUIRect Toolbar); void DoToolbar(CUIRect Toolbar); void DoQuad(CQuad *pQuad, int Index); @@ -732,6 +800,8 @@ public: int Length = pEnd > pExtractedName ? min(BufferSize, (int)(pEnd-pExtractedName+1)) : BufferSize; str_copy(pName, pExtractedName, Length); } + + int GetLineDistance(); }; // make sure to inline this function diff --git a/src/game/editor/ed_io.cpp b/src/game/editor/io.cpp index a5ead97a..463147e1 100644 --- a/src/game/editor/ed_io.cpp +++ b/src/game/editor/io.cpp @@ -6,7 +6,7 @@ #include <engine/serverbrowser.h> #include <engine/storage.h> #include <game/gamecore.h> -#include "ed_editor.h" +#include "editor.h" template<typename T> static int MakeVersion(int i, const T &v) @@ -220,6 +220,31 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) df.AddItem(MAPITEMTYPE_VERSION, 0, sizeof(Item), &Item); } + // save map info + { + CMapItemInfo Item; + Item.m_Version = 1; + + if(m_MapInfo.m_aAuthor[0]) + Item.m_Author = df.AddData(str_length(m_MapInfo.m_aAuthor)+1, m_MapInfo.m_aAuthor); + else + Item.m_Author = -1; + if(m_MapInfo.m_aVersion[0]) + Item.m_MapVersion = df.AddData(str_length(m_MapInfo.m_aVersion)+1, m_MapInfo.m_aVersion); + else + Item.m_MapVersion = -1; + if(m_MapInfo.m_aCredits[0]) + Item.m_Credits = df.AddData(str_length(m_MapInfo.m_aCredits)+1, m_MapInfo.m_aCredits); + else + Item.m_Credits = -1; + if(m_MapInfo.m_aLicense[0]) + Item.m_License = df.AddData(str_length(m_MapInfo.m_aLicense)+1, m_MapInfo.m_aLicense); + else + Item.m_License = -1; + + df.AddItem(MAPITEMTYPE_INFO, 0, sizeof(Item), &Item); + } + // save images for(int i = 0; i < m_lImages.size(); i++) { @@ -266,6 +291,9 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) GItem.m_StartLayer = LayerCount; GItem.m_NumLayers = 0; + // save group name + StrToInts(GItem.m_aName, sizeof(GItem.m_aName)/sizeof(int), pGroup->m_aName); + for(int l = 0; l < pGroup->m_lLayers.size(); l++) { if(!pGroup->m_lLayers[l]->m_SaveToMap) @@ -278,23 +306,24 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) pLayer->PrepareForSave(); CMapItemLayerTilemap Item; - Item.m_Version = 2; + Item.m_Version = 3; Item.m_Layer.m_Flags = pLayer->m_Flags; Item.m_Layer.m_Type = pLayer->m_Type; - Item.m_Color.r = pLayer->m_Color.r; - Item.m_Color.g = pLayer->m_Color.g; - Item.m_Color.b = pLayer->m_Color.b; - Item.m_Color.a = pLayer->m_Color.a; - Item.m_ColorEnv = -1; // not in use right now - Item.m_ColorEnvOffset = 0; + Item.m_Color = pLayer->m_Color; + Item.m_ColorEnv = pLayer->m_ColorEnv; + Item.m_ColorEnvOffset = pLayer->m_ColorEnvOffset; Item.m_Width = pLayer->m_Width; Item.m_Height = pLayer->m_Height; - Item.m_Flags = pLayer->m_Game; + Item.m_Flags = pLayer->m_Game ? TILESLAYERFLAG_GAME : 0; Item.m_Image = pLayer->m_Image; Item.m_Data = df.AddData(pLayer->m_Width*pLayer->m_Height*sizeof(CTile), pLayer->m_pTiles); + + // save layer name + StrToInts(Item.m_aName, sizeof(Item.m_aName)/sizeof(int), pLayer->m_aName); + df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item); GItem.m_NumLayers++; @@ -307,7 +336,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) if(pLayer->m_lQuads.size()) { CMapItemLayerQuads Item; - Item.m_Version = 1; + Item.m_Version = 2; Item.m_Layer.m_Flags = pLayer->m_Flags; Item.m_Layer.m_Type = pLayer->m_Type; Item.m_Image = pLayer->m_Image; @@ -315,6 +344,10 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) // add the data Item.m_NumQuads = pLayer->m_lQuads.size(); Item.m_Data = df.AddDataSwapped(pLayer->m_lQuads.size()*sizeof(CQuad), pLayer->m_lQuads.base_ptr()); + + // save layer name + StrToInts(Item.m_aName, sizeof(Item.m_aName)/sizeof(int), pLayer->m_aName); + df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item); // clean up @@ -334,10 +367,11 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) for(int e = 0; e < m_lEnvelopes.size(); e++) { CMapItemEnvelope Item; - Item.m_Version = 1; + Item.m_Version = CMapItemEnvelope::CURRENT_VERSION; Item.m_Channels = m_lEnvelopes[e]->m_Channels; Item.m_StartPoint = PointCount; Item.m_NumPoints = m_lEnvelopes[e]->m_lPoints.size(); + Item.m_Synchronized = m_lEnvelopes[e]->m_Synchronized; StrToInts(Item.m_aName, sizeof(Item.m_aName)/sizeof(int), m_lEnvelopes[e]->m_aName); df.AddItem(MAPITEMTYPE_ENVELOPE, e, sizeof(Item), &Item); @@ -405,6 +439,22 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag { //editor.reset(false); + // load map info + { + CMapItemInfo *pItem = (CMapItemInfo *)DataFile.FindItem(MAPITEMTYPE_INFO, 0); + if(pItem && pItem->m_Version == 1) + { + if(pItem->m_Author > -1) + str_copy(m_MapInfo.m_aAuthor, (char *)DataFile.GetData(pItem->m_Author), sizeof(m_MapInfo.m_aAuthor)); + if(pItem->m_MapVersion > -1) + str_copy(m_MapInfo.m_aVersion, (char *)DataFile.GetData(pItem->m_MapVersion), sizeof(m_MapInfo.m_aVersion)); + if(pItem->m_Credits > -1) + str_copy(m_MapInfo.m_aCredits, (char *)DataFile.GetData(pItem->m_Credits), sizeof(m_MapInfo.m_aCredits)); + if(pItem->m_License > -1) + str_copy(m_MapInfo.m_aLicense, (char *)DataFile.GetData(pItem->m_License), sizeof(m_MapInfo.m_aLicense)); + } + } + // load images { int Start, Num; @@ -449,6 +499,9 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag if(pName) str_copy(pImg->m_aName, pName, 128); + // load auto mapper file + pImg->m_AutoMapper.Load(pImg->m_aName); + m_lImages.add(pImg); // unload image @@ -486,6 +539,10 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pGroup->m_ClipH = pGItem->m_ClipH; } + // load group name + if(pGItem->m_Version >= 3) + IntsToStr(pGItem->m_aName, sizeof(pGroup->m_aName)/sizeof(int), pGroup->m_aName); + for(int l = 0; l < pGItem->m_NumLayers; l++) { CLayer *pLayer = 0; @@ -498,7 +555,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag CMapItemLayerTilemap *pTilemapItem = (CMapItemLayerTilemap *)pLayerItem; CLayerTiles *pTiles = 0; - if(pTilemapItem->m_Flags&1) + if(pTilemapItem->m_Flags&TILESLAYERFLAG_GAME) { pTiles = new CLayerGame(pTilemapItem->m_Width, pTilemapItem->m_Height); MakeGameLayer(pTiles); @@ -508,10 +565,9 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag { pTiles = new CLayerTiles(pTilemapItem->m_Width, pTilemapItem->m_Height); pTiles->m_pEditor = m_pEditor; - pTiles->m_Color.r = pTilemapItem->m_Color.r; - pTiles->m_Color.g = pTilemapItem->m_Color.g; - pTiles->m_Color.b = pTilemapItem->m_Color.b; - pTiles->m_Color.a = pTilemapItem->m_Color.a; + pTiles->m_Color = pTilemapItem->m_Color; + pTiles->m_ColorEnv = pTilemapItem->m_ColorEnv; + pTiles->m_ColorEnvOffset = pTilemapItem->m_ColorEnvOffset; } pLayer = pTiles; @@ -519,7 +575,11 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pGroup->AddLayer(pTiles); void *pData = DataFile.GetData(pTilemapItem->m_Data); pTiles->m_Image = pTilemapItem->m_Image; - pTiles->m_Game = pTilemapItem->m_Flags&1; + pTiles->m_Game = pTilemapItem->m_Flags&TILESLAYERFLAG_GAME; + + // load layer name + if(pTilemapItem->m_Version >= 3) + IntsToStr(pTilemapItem->m_aName, sizeof(pTiles->m_aName)/sizeof(int), pTiles->m_aName); mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); @@ -543,6 +603,11 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pQuads->m_Image = pQuadsItem->m_Image; if(pQuads->m_Image < -1 || pQuads->m_Image >= m_lImages.size()) pQuads->m_Image = -1; + + // load layer name + if(pQuadsItem->m_Version >= 2) + IntsToStr(pQuadsItem->m_aName, sizeof(pQuads->m_aName)/sizeof(int), pQuads->m_aName); + void *pData = DataFile.GetDataSwapped(pQuadsItem->m_Data); pGroup->AddLayer(pQuads); pQuads->m_lQuads.set_size(pQuadsItem->m_NumQuads); @@ -578,6 +643,8 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag if(pItem->m_aName[0] != -1) // compatibility with old maps IntsToStr(pItem->m_aName, sizeof(pItem->m_aName)/sizeof(int), pEnv->m_aName); m_lEnvelopes.add(pEnv); + if(pItem->m_Version >= 2) + pEnv->m_Synchronized = pItem->m_Synchronized; } } } diff --git a/src/game/editor/ed_layer_game.cpp b/src/game/editor/layer_game.cpp index cf48845e..7e879c3e 100644 --- a/src/game/editor/ed_layer_game.cpp +++ b/src/game/editor/layer_game.cpp @@ -1,12 +1,12 @@ /* (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. */ -#include "ed_editor.h" +#include "editor.h" CLayerGame::CLayerGame(int w, int h) : CLayerTiles(w, h) { - m_pTypeName = "Game"; + str_copy(m_aName, "Game", sizeof(m_aName)); m_Game = 1; } diff --git a/src/game/editor/ed_layer_quads.cpp b/src/game/editor/layer_quads.cpp index 680a54cd..d0b66405 100644 --- a/src/game/editor/ed_layer_quads.cpp +++ b/src/game/editor/layer_quads.cpp @@ -5,7 +5,7 @@ #include <engine/console.h> #include <engine/graphics.h> -#include "ed_editor.h" +#include "editor.h" #include <game/generated/client_data.h> #include <game/client/render.h> #include <game/localization.h> @@ -13,7 +13,7 @@ CLayerQuads::CLayerQuads() { m_Type = LAYERTYPE_QUADS; - m_pTypeName = "Quads"; + str_copy(m_aName, "Quads", sizeof(m_aName)); m_Image = -1; } @@ -21,31 +21,13 @@ CLayerQuads::~CLayerQuads() { } -static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) -{ - CEditor *pEditor = (CEditor *)pUser; - if(Env < 0 || Env > pEditor->m_Map.m_lEnvelopes.size()) - { - pChannels[0] = 0; - pChannels[1] = 0; - pChannels[2] = 0; - pChannels[3] = 0; - return; - } - - CEnvelope *e = pEditor->m_Map.m_lEnvelopes[Env]; - float t = pEditor->m_AnimateTime+TimeOffset; - t *= pEditor->m_AnimateSpeed; - e->Eval(t, pChannels); -} - void CLayerQuads::Render() { Graphics()->TextureSet(-1); if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size()) Graphics()->TextureSet(m_pEditor->m_Map.m_lImages[m_Image]->m_TexID); - m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, m_pEditor); + m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, m_pEditor->EnvelopeEval, m_pEditor); } CQuad *CLayerQuads::NewQuad() diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index d0c9041c..9a21e5ce 100644 --- a/src/game/editor/ed_layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -8,14 +8,14 @@ #include <game/generated/client_data.h> #include <game/client/render.h> -#include "ed_editor.h" +#include "editor.h" #include <game/localization.h> CLayerTiles::CLayerTiles(int w, int h) { m_Type = LAYERTYPE_TILES; - m_pTypeName = "Tiles"; + str_copy(m_aName, "Tiles", sizeof(m_aName)); m_Width = w; m_Height = h; m_Image = -1; @@ -25,6 +25,8 @@ CLayerTiles::CLayerTiles(int w, int h) m_Color.g = 255; m_Color.b = 255; m_Color.a = 255; + m_ColorEnv = -1; + m_ColorEnvOffset = 0; m_pTiles = new CTile[m_Width*m_Height]; mem_zero(m_pTiles, m_Width*m_Height*sizeof(CTile)); @@ -62,7 +64,8 @@ void CLayerTiles::Render() m_TexID = m_pEditor->m_Map.m_lImages[m_Image]->m_TexID; Graphics()->TextureSet(m_TexID); vec4 Color = vec4(m_Color.r/255.0f, m_Color.g/255.0f, m_Color.b/255.0f, m_Color.a/255.0f); - m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT); + m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, + m_pEditor->EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset); } int CLayerTiles::ConvertX(float x) const { return (int)(x/32.0f); } @@ -123,7 +126,7 @@ void CLayerTiles::BrushSelecting(CUIRect Rect) m_pEditor->Graphics()->QuadsEnd(); char aBuf[16]; str_format(aBuf, sizeof(aBuf), "%d,%d", ConvertX(Rect.w), ConvertY(Rect.h)); - TextRender()->Text(0, Rect.x+3.0f, Rect.y+3.0f, 15.0f*m_pEditor->m_WorldZoom, aBuf, -1); + TextRender()->Text(0, Rect.x+3.0f, Rect.y+3.0f, m_pEditor->m_ShowPicker?15.0f:15.0f*m_pEditor->m_WorldZoom, aBuf, -1); } int CLayerTiles::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) @@ -156,6 +159,8 @@ void CLayerTiles::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) if(m_Readonly) return; + Snap(&Rect); + int sx = ConvertX(Rect.x); int sy = ConvertY(Rect.y); int w = ConvertX(Rect.w); @@ -163,9 +168,9 @@ void CLayerTiles::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) CLayerTiles *pLt = static_cast<CLayerTiles*>(pBrush); - for(int y = 0; y <= h; y++) + for(int y = 0; y < h; y++) { - for(int x = 0; x <= w; x++) + for(int x = 0; x < w; x++) { int fx = x+sx; int fy = y+sy; @@ -353,19 +358,39 @@ void CLayerTiles::ShowInfo() } x += m_pTiles[c].m_Skip; } + + Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } int CLayerTiles::RenderProperties(CUIRect *pToolBox) { CUIRect Button; - pToolBox->HSplitBottom(12.0f, pToolBox, &Button); bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty(); - if(m_pEditor->m_Map.m_pGameLayer == this) + if(m_pEditor->m_Map.m_pGameLayer != this) + { + if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size() && m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.IsLoaded()) + { + static int s_AutoMapperButton = 0; + pToolBox->HSplitBottom(12.0f, pToolBox, &Button); + if(m_pEditor->DoButton_Editor(&s_AutoMapperButton, "Auto map", 0, &Button, 0, "")) + m_pEditor->PopupSelectConfigAutoMapInvoke(m_pEditor->UI()->MouseX(), m_pEditor->UI()->MouseY()); + + int Result = m_pEditor->PopupSelectConfigAutoMapResult(); + if(Result > -1) + { + m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.Proceed(this, Result); + return 1; + } + } + } + else InGameGroup = false; if(InGameGroup) { + pToolBox->HSplitBottom(2.0f, pToolBox, 0); + pToolBox->HSplitBottom(12.0f, pToolBox, &Button); static int s_ColclButton = 0; if(m_pEditor->DoButton_Editor(&s_ColclButton, "Game tiles", 0, &Button, 0, "Constructs game tiles from this layer")) m_pEditor->PopupSelectGametileOpInvoke(m_pEditor->UI()->MouseX(), m_pEditor->UI()->MouseY()); @@ -392,6 +417,8 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) PROP_SHIFT, PROP_IMAGE, PROP_COLOR, + PROP_COLOR_ENV, + PROP_COLOR_ENV_OFFSET, NUM_PROPS, }; @@ -407,6 +434,8 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) {"Shift", 0, PROPTYPE_SHIFT, 0, 0}, {"Image", m_Image, PROPTYPE_IMAGE, 0, 0}, {"Color", Color, PROPTYPE_COLOR, 0, 0}, + {"Color Env", m_ColorEnv+1, PROPTYPE_INT_STEP, 0, m_pEditor->m_Map.m_lEnvelopes.size()+1}, + {"Color TO", m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {0}, }; @@ -445,6 +474,22 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) m_Color.b = (NewVal>>8)&0xff; m_Color.a = NewVal&0xff; } + if(Prop == PROP_COLOR_ENV) + { + int Index = clamp(NewVal-1, -1, m_pEditor->m_Map.m_lEnvelopes.size()-1); + int Step = (Index-m_ColorEnv)%2; + if(Step != 0) + { + for(; Index >= -1 && Index < m_pEditor->m_Map.m_lEnvelopes.size(); Index += Step) + if(Index == -1 || m_pEditor->m_Map.m_lEnvelopes[Index]->m_Channels == 4) + { + m_ColorEnv = Index; + break; + } + } + } + if(Prop == PROP_COLOR_ENV_OFFSET) + m_ColorEnvOffset = NewVal; return 0; } diff --git a/src/game/editor/ed_popups.cpp b/src/game/editor/popups.cpp index f572e43c..2382823d 100644 --- a/src/game/editor/ed_popups.cpp +++ b/src/game/editor/popups.cpp @@ -1,11 +1,15 @@ /* (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. */ + +#include <base/tl/array.h> + #include <engine/console.h> #include <engine/graphics.h> #include <engine/input.h> #include <engine/keys.h> #include <engine/storage.h> -#include "ed_editor.h" + +#include "editor.h" // popup menu handling @@ -147,6 +151,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) l->m_pEditor = pEditor; pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l); pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1; + pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_Collapse = false; return 1; } @@ -160,9 +165,22 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) l->m_pEditor = pEditor; pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l); pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1; + pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_Collapse = false; return 1; } + // group name + if(!pEditor->GetSelectedGroup()->m_GameGroup) + { + View.HSplitBottom(5.0f, &View, &Button); + View.HSplitBottom(12.0f, &View, &Button); + static float s_Name = 0; + pEditor->UI()->DoLabel(&Button, "Name:", 10.0f, -1, -1); + Button.VSplitLeft(40.0f, 0, &Button); + if(pEditor->DoEditBox(&s_Name, &Button, pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_aName, sizeof(pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_aName), 10.0f, &s_Name)) + pEditor->m_Map.m_Modified = true; + } + enum { PROP_ORDER=0, @@ -239,6 +257,18 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) return 1; } + // layer name + if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0)) + { + View.HSplitBottom(5.0f, &View, &Button); + View.HSplitBottom(12.0f, &View, &Button); + static float s_Name = 0; + pEditor->UI()->DoLabel(&Button, "Name:", 10.0f, -1, -1); + Button.VSplitLeft(40.0f, 0, &Button); + if(pEditor->DoEditBox(&s_Name, &Button, pEditor->GetSelectedLayer(0)->m_aName, sizeof(pEditor->GetSelectedLayer(0)->m_aName), 10.0f, &s_Name)) + pEditor->m_Map.m_Modified = true; + } + View.HSplitBottom(10.0f, &View, 0); CLayerGroup *pCurrentGroup = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]; @@ -428,9 +458,35 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) for(int k = 0; k < 5; ++k) pQuad->m_aPoints[k].y += Offset; } - if(Prop == PROP_POS_ENV) pQuad->m_PosEnv = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); + if(Prop == PROP_POS_ENV) + { + int Index = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); + int Step = (Index-pQuad->m_PosEnv)%2; + if(Step != 0) + { + for(; Index >= -1 && Index < pEditor->m_Map.m_lEnvelopes.size(); Index += Step) + if(Index == -1 || pEditor->m_Map.m_lEnvelopes[Index]->m_Channels == 3) + { + pQuad->m_PosEnv = Index; + break; + } + } + } if(Prop == PROP_POS_ENV_OFFSET) pQuad->m_PosEnvOffset = NewVal; - if(Prop == PROP_COLOR_ENV) pQuad->m_ColorEnv = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); + if(Prop == PROP_COLOR_ENV) + { + int Index = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); + int Step = (Index-pQuad->m_ColorEnv)%2; + if(Step != 0) + { + for(; Index >= -1 && Index < pEditor->m_Map.m_lEnvelopes.size(); Index += Step) + if(Index == -1 || pEditor->m_Map.m_lEnvelopes[Index]->m_Channels == 4) + { + pQuad->m_ColorEnv = Index; + break; + } + } + } if(Prop == PROP_COLOR_ENV_OFFSET) pQuad->m_ColorEnvOffset = NewVal; return 0; @@ -528,8 +584,8 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) View.HSplitBottom(40.0f, &View, 0); View.VMargin(40.0f, &View); View.HSplitBottom(20.0f, &View, &Label); - static int s_FolderBox = 0; - pEditor->DoEditBox(&s_FolderBox, &Label, pEditor->m_FileDialogNewFolderName, sizeof(pEditor->m_FileDialogNewFolderName), 15.0f); + static float s_FolderBox = 0; + pEditor->DoEditBox(&s_FolderBox, &Label, pEditor->m_FileDialogNewFolderName, sizeof(pEditor->m_FileDialogNewFolderName), 15.0f, &s_FolderBox); View.HSplitBottom(20.0f, &View, &Label); pEditor->UI()->DoLabel(&Label, "Name:", 10.0f, -1); @@ -579,6 +635,74 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) return 0; } +int CEditor::PopupMapInfo(CEditor *pEditor, CUIRect View) +{ + CUIRect Label, ButtonBar, Button; + + // title + View.HSplitTop(10.0f, 0, &View); + View.HSplitTop(30.0f, &Label, &View); + pEditor->UI()->DoLabel(&Label, "Map details", 20.0f, 0); + + View.HSplitBottom(10.0f, &View, 0); + View.HSplitBottom(20.0f, &View, &ButtonBar); + + View.VMargin(40.0f, &View); + + // author box + View.HSplitTop(20.0f, &Label, &View); + pEditor->UI()->DoLabel(&Label, "Author:", 10.0f, -1); + Label.VSplitLeft(40.0f, 0, &Button); + Button.HSplitTop(12.0f, &Button, 0); + static float s_AuthorBox = 0; + pEditor->DoEditBox(&s_AuthorBox, &Button, pEditor->m_Map.m_MapInfo.m_aAuthorTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aAuthorTmp), 10.0f, &s_AuthorBox); + + // version box + View.HSplitTop(20.0f, &Label, &View); + pEditor->UI()->DoLabel(&Label, "Version:", 10.0f, -1); + Label.VSplitLeft(40.0f, 0, &Button); + Button.HSplitTop(12.0f, &Button, 0); + static float s_VersionBox = 0; + pEditor->DoEditBox(&s_VersionBox, &Button, pEditor->m_Map.m_MapInfo.m_aVersionTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aVersionTmp), 10.0f, &s_VersionBox); + + // credits box + View.HSplitTop(20.0f, &Label, &View); + pEditor->UI()->DoLabel(&Label, "Credits:", 10.0f, -1); + Label.VSplitLeft(40.0f, 0, &Button); + Button.HSplitTop(12.0f, &Button, 0); + static float s_CreditsBox = 0; + pEditor->DoEditBox(&s_CreditsBox, &Button, pEditor->m_Map.m_MapInfo.m_aCreditsTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aCreditsTmp), 10.0f, &s_CreditsBox); + + // license box + View.HSplitTop(20.0f, &Label, &View); + pEditor->UI()->DoLabel(&Label, "License:", 10.0f, -1); + Label.VSplitLeft(40.0f, 0, &Button); + Button.HSplitTop(12.0f, &Button, 0); + static float s_LicenseBox = 0; + pEditor->DoEditBox(&s_LicenseBox, &Button, pEditor->m_Map.m_MapInfo.m_aLicenseTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aLicenseTmp), 10.0f, &s_LicenseBox); + + // button bar + ButtonBar.VSplitLeft(30.0f, 0, &ButtonBar); + ButtonBar.VSplitLeft(110.0f, &Label, &ButtonBar); + static int s_CreateButton = 0; + if(pEditor->DoButton_Editor(&s_CreateButton, "Save", 0, &Label, 0, 0)) + { + str_copy(pEditor->m_Map.m_MapInfo.m_aAuthor, pEditor->m_Map.m_MapInfo.m_aAuthorTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aAuthor)); + str_copy(pEditor->m_Map.m_MapInfo.m_aVersion, pEditor->m_Map.m_MapInfo.m_aVersionTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aVersion)); + str_copy(pEditor->m_Map.m_MapInfo.m_aCredits, pEditor->m_Map.m_MapInfo.m_aCreditsTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aCredits)); + str_copy(pEditor->m_Map.m_MapInfo.m_aLicense, pEditor->m_Map.m_MapInfo.m_aLicenseTmp, sizeof(pEditor->m_Map.m_MapInfo.m_aLicense)); + return 1; + } + + ButtonBar.VSplitRight(30.0f, &ButtonBar, 0); + ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label); + static int s_AbortButton = 0; + if(pEditor->DoButton_Editor(&s_AbortButton, "Abort", 0, &Label, 0, 0)) + return 1; + + return 0; +} + int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) { CUIRect Label, ButtonBar; @@ -628,13 +752,17 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) } else if(pEditor->m_PopupEventType == POPEVENT_SAVE) pEditor->CallbackSaveMap(pEditor->m_aFileSaveName, IStorage::TYPE_SAVE, pEditor); + pEditor->m_PopupEventWasActivated = false; return 1; } ButtonBar.VSplitRight(30.0f, &ButtonBar, 0); ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label); static int s_AbortButton = 0; if(pEditor->DoButton_Editor(&s_AbortButton, "Abort", 0, &Label, 0, 0)) + { + pEditor->m_PopupEventWasActivated = false; return 1; + } return 0; } @@ -673,13 +801,23 @@ int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View) } if(ShowImage >= 0 && ShowImage < pEditor->m_Map.m_lImages.size()) + { + if(ImageView.h < ImageView.w) + ImageView.w = ImageView.h; + else + ImageView.h = ImageView.w; + float Max = (float)(max(pEditor->m_Map.m_lImages[ShowImage]->m_Width, pEditor->m_Map.m_lImages[ShowImage]->m_Height)); + ImageView.w *= pEditor->m_Map.m_lImages[ShowImage]->m_Width/Max; + ImageView.h *= pEditor->m_Map.m_lImages[ShowImage]->m_Height/Max; pEditor->Graphics()->TextureSet(pEditor->m_Map.m_lImages[ShowImage]->m_TexID); - else - pEditor->Graphics()->TextureSet(-1); - pEditor->Graphics()->QuadsBegin(); - IGraphics::CQuadItem QuadItem(ImageView.x, ImageView.y, ImageView.w, ImageView.h); - pEditor->Graphics()->QuadsDrawTL(&QuadItem, 1); - pEditor->Graphics()->QuadsEnd(); + pEditor->Graphics()->BlendNormal(); + pEditor->Graphics()->WrapClamp(); + pEditor->Graphics()->QuadsBegin(); + IGraphics::CQuadItem QuadItem(ImageView.x, ImageView.y, ImageView.w, ImageView.h); + pEditor->Graphics()->QuadsDrawTL(&QuadItem, 1); + pEditor->Graphics()->QuadsEnd(); + pEditor->Graphics()->WrapNormal(); + } return 0; } @@ -737,3 +875,43 @@ int CEditor::PopupSelectGameTileOpResult() s_GametileOpSelected = -1; return Result; } + +static int s_AutoMapConfigSelected = -1; + +int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View) +{ + CLayerTiles *pLayer = static_cast<CLayerTiles*>(pEditor->GetSelectedLayer(0)); + CUIRect Button; + static int s_AutoMapperConfigButtons[256]; + CAutoMapper *pAutoMapper = &pEditor->m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper; + + for(int i = 0; i < pAutoMapper->ConfigNamesNum(); ++i) + { + View.HSplitTop(2.0f, 0, &View); + View.HSplitTop(12.0f, &Button, &View); + if(pEditor->DoButton_Editor(&s_AutoMapperConfigButtons[i], pAutoMapper->GetConfigName(i), 0, &Button, 0, 0)) + s_AutoMapConfigSelected = i; + } + + return 0; +} + +void CEditor::PopupSelectConfigAutoMapInvoke(float x, float y) +{ + static int s_AutoMapConfigSelectID = 0; + s_AutoMapConfigSelected = -1; + CLayerTiles *pLayer = static_cast<CLayerTiles*>(GetSelectedLayer(0)); + if(pLayer && pLayer->m_Image >= 0 && pLayer->m_Image < m_Map.m_lImages.size() && + m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum()) + UiInvokePopupMenu(&s_AutoMapConfigSelectID, 0, x, y, 120.0f, 12.0f+14.0f*m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum(), PopupSelectConfigAutoMap); +} + +int CEditor::PopupSelectConfigAutoMapResult() +{ + if(s_AutoMapConfigSelected < 0) + return -1; + + int Result = s_AutoMapConfigSelected; + s_AutoMapConfigSelected = -1; + return Result; +} |