1 /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2 /* If you are missing that file, acquire a complete release at teeworlds.com. */
3 #ifndef GAME_EDITOR_EDITOR_H
4 #define GAME_EDITOR_EDITOR_H
9 #include <base/system.h>
11 #include <base/tl/algorithm.h>
12 #include <base/tl/array.h>
13 #include <base/tl/sorted_array.h>
14 #include <base/tl/string.h>
16 #include <game/client/ui.h>
17 #include <game/mapitems.h>
18 #include <game/client/render.h>
20 #include <engine/shared/config.h>
21 #include <engine/shared/datafile.h>
22 #include <engine/editor.h>
23 #include <engine/graphics.h>
27 typedef void (*INDEX_MODIFY_FUNC
)(int *pIndex
);
29 //CRenderTools m_RenderTools;
51 array
<CEnvPoint
> m_lPoints
;
53 float m_Bottom
, m_Top
;
65 sort(m_lPoints
.all());
69 void FindTopBottom(int ChannelMask
)
71 m_Top
= -1000000000.0f
;
72 m_Bottom
= 1000000000.0f
;
73 for(int i
= 0; i
< m_lPoints
.size(); i
++)
75 for(int c
= 0; c
< m_Channels
; c
++)
77 if(ChannelMask
&(1<<c
))
79 float v
= fx2f(m_lPoints
[i
].m_aValues
[c
]);
80 if(v
> m_Top
) m_Top
= v
;
81 if(v
< m_Bottom
) m_Bottom
= v
;
87 int Eval(float Time
, float *pResult
)
89 CRenderTools::RenderEvalEnvelope(m_lPoints
.base_ptr(), m_lPoints
.size(), m_Channels
, Time
, pResult
);
93 void AddPoint(int Time
, int v0
, int v1
=0, int v2
=0, int v3
=0)
101 p
.m_Curvetype
= CURVETYPE_LINEAR
;
109 return m_lPoints
[m_lPoints
.size()-1].m_Time
*(1.0f
/1000.0f
);
122 class CEditor
*m_pEditor
;
123 class IGraphics
*Graphics();
124 class ITextRender
*TextRender();
128 m_Type
= LAYERTYPE_INVALID
;
129 str_copy(m_aName
, "(invalid)", sizeof(m_aName
));
142 virtual void BrushSelecting(CUIRect Rect
) {}
143 virtual int BrushGrab(CLayerGroup
*pBrush
, CUIRect Rect
) { return 0; }
144 virtual void FillSelection(bool Empty
, CLayer
*pBrush
, CUIRect Rect
) {}
145 virtual void BrushDraw(CLayer
*pBrush
, float x
, float y
) {}
146 virtual void BrushPlace(CLayer
*pBrush
, float x
, float y
) {}
147 virtual void BrushFlipX() {}
148 virtual void BrushFlipY() {}
149 virtual void BrushRotate(float Amount
) {}
151 virtual void Render() {}
152 virtual int RenderProperties(CUIRect
*pToolbox
) { return 0; }
154 virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc
) {}
155 virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc
) {}
157 virtual void GetSize(float *w
, float *h
) { *w
= 0; *h
= 0;}
171 class CEditorMap
*m_pMap
;
173 array
<CLayer
*> m_lLayers
;
196 void Convert(CUIRect
*pRect
);
199 void Mapping(float *pPoints
);
201 void GetSize(float *w
, float *h
);
203 void DeleteLayer(int Index
);
204 int SwapLayers(int Index0
, int Index1
);
208 return m_lLayers
.size() == 0;
213 m_lLayers
.delete_all();
216 void AddLayer(CLayer
*l
);
218 void ModifyImageIndex(INDEX_MODIFY_FUNC Func
)
220 for(int i
= 0; i
< m_lLayers
.size(); i
++)
221 m_lLayers
[i
]->ModifyImageIndex(Func
);
224 void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func
)
226 for(int i
= 0; i
< m_lLayers
.size(); i
++)
227 m_lLayers
[i
]->ModifyEnvelopeIndex(Func
);
231 class CEditorImage
: public CImageInfo
236 CEditorImage(CEditor
*pEditor
)
237 : m_AutoMapper(pEditor
)
251 void AnalyseTileFlags();
256 unsigned char m_aTileFlags
[256];
257 class CAutoMapper m_AutoMapper
;
262 void MakeGameGroup(CLayerGroup
*pGroup
);
263 void MakeGameLayer(CLayer
*pLayer
);
273 array
<CLayerGroup
*> m_lGroups
;
274 array
<CEditorImage
*> m_lImages
;
275 array
<CEnvelope
*> m_lEnvelopes
;
277 class CLayerGame
*m_pGameLayer
;
278 CLayerGroup
*m_pGameGroup
;
280 CEnvelope
*NewEnvelope(int Channels
)
283 CEnvelope
*e
= new CEnvelope(Channels
);
288 void DeleteEnvelope(int Index
);
290 CLayerGroup
*NewGroup()
293 CLayerGroup
*g
= new CLayerGroup
;
299 int SwapGroups(int Index0
, int Index1
)
301 if(Index0
< 0 || Index0
>= m_lGroups
.size()) return Index0
;
302 if(Index1
< 0 || Index1
>= m_lGroups
.size()) return Index0
;
303 if(Index0
== Index1
) return Index0
;
305 swap(m_lGroups
[Index0
], m_lGroups
[Index1
]);
309 void DeleteGroup(int Index
)
311 if(Index
< 0 || Index
>= m_lGroups
.size()) return;
313 delete m_lGroups
[Index
];
314 m_lGroups
.remove_index(Index
);
317 void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc
)
320 for(int i
= 0; i
< m_lGroups
.size(); i
++)
321 m_lGroups
[i
]->ModifyImageIndex(pfnFunc
);
324 void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc
)
327 for(int i
= 0; i
< m_lGroups
.size(); i
++)
328 m_lGroups
[i
]->ModifyEnvelopeIndex(pfnFunc
);
332 void CreateDefault(int EntitiesTexture
);
335 int Save(class IStorage
*pStorage
, const char *pFilename
);
336 int Load(class IStorage
*pStorage
, const char *pFilename
, int StorageType
);
367 class CLayerTiles
: public CLayer
370 CLayerTiles(int w
, int h
);
373 void Resize(int NewW
, int NewH
);
374 void Shift(int Direction
);
377 virtual void Render();
379 int ConvertX(float x
) const;
380 int ConvertY(float y
) const;
381 void Convert(CUIRect Rect
, RECTi
*pOut
);
382 void Snap(CUIRect
*pRect
);
383 void Clamp(RECTi
*pRect
);
385 virtual void BrushSelecting(CUIRect Rect
);
386 virtual int BrushGrab(CLayerGroup
*pBrush
, CUIRect Rect
);
387 virtual void FillSelection(bool Empty
, CLayer
*pBrush
, CUIRect Rect
);
388 virtual void BrushDraw(CLayer
*pBrush
, float wx
, float wy
);
389 virtual void BrushFlipX();
390 virtual void BrushFlipY();
391 virtual void BrushRotate(float Amount
);
393 virtual void ShowInfo();
394 virtual int RenderProperties(CUIRect
*pToolbox
);
396 virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc
);
397 virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc
);
399 void PrepareForSave();
401 void GetSize(float *w
, float *h
) { *w
= m_Width
*32.0f
; *h
= m_Height
*32.0f
; }
410 int m_ColorEnvOffset
;
414 class CLayerQuads
: public CLayer
420 virtual void Render();
423 virtual void BrushSelecting(CUIRect Rect
);
424 virtual int BrushGrab(CLayerGroup
*pBrush
, CUIRect Rect
);
425 virtual void BrushPlace(CLayer
*pBrush
, float wx
, float wy
);
426 virtual void BrushFlipX();
427 virtual void BrushFlipY();
428 virtual void BrushRotate(float Amount
);
430 virtual int RenderProperties(CUIRect
*pToolbox
);
432 virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc
);
433 virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc
);
435 void GetSize(float *w
, float *h
);
438 array
<CQuad
> m_lQuads
;
441 class CLayerGame
: public CLayerTiles
444 CLayerGame(int w
, int h
);
447 virtual int RenderProperties(CUIRect
*pToolbox
);
450 class CEditor
: public IEditor
452 class IInput
*m_pInput
;
453 class IClient
*m_pClient
;
454 class IConsole
*m_pConsole
;
455 class IGraphics
*m_pGraphics
;
456 class ITextRender
*m_pTextRender
;
457 class IStorage
*m_pStorage
;
458 CRenderTools m_RenderTools
;
461 class IInput
*Input() { return m_pInput
; };
462 class IClient
*Client() { return m_pClient
; };
463 class IConsole
*Console() { return m_pConsole
; };
464 class IGraphics
*Graphics() { return m_pGraphics
; };
465 class ITextRender
*TextRender() { return m_pTextRender
; };
466 class IStorage
*Storage() { return m_pStorage
; };
467 CUI
*UI() { return &m_UI
; }
468 CRenderTools
*RenderTools() { return &m_RenderTools
; }
470 CEditor() : m_TilesetPicker(16, 16)
477 m_Mode
= MODE_LAYERS
;
481 m_GridActive
= false;
485 m_aFileSaveName
[0] = 0;
486 m_ValidSaveFilename
= false;
488 m_PopupEventActivated
= false;
490 m_FileDialogStorageType
= 0;
491 m_pFileDialogTitle
= 0;
492 m_pFileDialogButtonText
= 0;
493 m_pFileDialogUser
= 0;
494 m_aFileDialogFileName
[0] = 0;
495 m_aFileDialogCurrentFolder
[0] = 0;
496 m_aFileDialogCurrentLink
[0] = 0;
497 m_pFileDialogPath
= m_aFileDialogCurrentFolder
;
498 m_aFileDialogActivate
= false;
499 m_FileDialogScrollValue
= 0.0f
;
500 m_FilesSelectedIndex
= -1;
507 m_EditorOffsetX
= 0.0f
;
508 m_EditorOffsetY
= 0.0f
;
513 m_ShowMousePointer
= true;
520 m_ProofBorders
= false;
522 m_ShowTileInfo
= false;
529 m_ShowEnvelopeEditor
= 0;
531 ms_CheckerTexture
= 0;
532 ms_BackgroundTexture
= 0;
533 ms_CursorTexture
= 0;
534 ms_EntitiesTexture
= 0;
536 ms_pUiGotContext
= 0;
540 virtual void UpdateAndRender();
541 virtual bool HasUnsavedData() { return m_Map
.m_Modified
; }
543 void FilelistPopulate(int StorageType
);
544 void InvokeFileDialog(int StorageType
, int FileType
, const char *pTitle
, const char *pButtonText
,
545 const char *pBasepath
, const char *pDefaultName
,
546 void (*pfnFunc
)(const char *pFilename
, int StorageType
, void *pUser
), void *pUser
);
548 void Reset(bool CreateDefault
=true);
549 int Save(const char *pFilename
);
550 int Load(const char *pFilename
, int StorageType
);
551 int Append(const char *pFilename
, int StorageType
);
554 CQuad
*GetSelectedQuad();
555 CLayer
*GetSelectedLayerType(int Index
, int Type
);
556 CLayer
*GetSelectedLayer(int Index
);
557 CLayerGroup
*GetSelectedGroup();
559 int DoProperties(CUIRect
*pToolbox
, CProperty
*pProps
, int *pIDs
, int *pNewVal
);
563 const char *m_pTooltip
;
568 char m_aFileName
[512];
569 char m_aFileSaveName
[512];
570 bool m_ValidSaveFilename
;
580 int m_PopupEventType
;
581 int m_PopupEventActivated
;
588 MAX_PATH_LENGTH
= 512
591 int m_FileDialogStorageType
;
592 const char *m_pFileDialogTitle
;
593 const char *m_pFileDialogButtonText
;
594 void (*m_pfnFileDialogFunc
)(const char *pFileName
, int StorageType
, void *pUser
);
595 void *m_pFileDialogUser
;
596 char m_aFileDialogFileName
[MAX_PATH_LENGTH
];
597 char m_aFileDialogCurrentFolder
[MAX_PATH_LENGTH
];
598 char m_aFileDialogCurrentLink
[MAX_PATH_LENGTH
];
599 char *m_pFileDialogPath
;
600 bool m_aFileDialogActivate
;
601 int m_FileDialogFileType
;
602 float m_FileDialogScrollValue
;
603 int m_FilesSelectedIndex
;
604 char m_FileDialogNewFolderName
[64];
605 char m_FileDialogErrString
[64];
609 char m_aFilename
[128];
615 bool operator<(const CFilelistItem
&Other
) { return !str_comp(m_aFilename
, "..") ? true : !str_comp(Other
.m_aFilename
, "..") ? false :
616 m_IsDir
&& !Other
.m_IsDir
? true : !m_IsDir
&& Other
.m_IsDir
? false :
617 str_comp_filenames(m_aFilename
, Other
.m_aFilename
) < 0; }
619 sorted_array
<CFilelistItem
> m_FileList
;
624 float m_WorldOffsetX
;
625 float m_WorldOffsetY
;
626 float m_EditorOffsetX
;
627 float m_EditorOffsetY
;
631 bool m_ShowMousePointer
;
636 float m_MouseDeltaWx
;
637 float m_MouseDeltaWy
;
642 int64 m_AnimateStart
;
644 float m_AnimateSpeed
;
646 int m_ShowEnvelopeEditor
;
652 int m_SelectedPoints
;
653 int m_SelectedEnvelope
;
656 static int ms_CheckerTexture
;
657 static int ms_BackgroundTexture
;
658 static int ms_CursorTexture
;
659 static int ms_EntitiesTexture
;
662 CLayerTiles m_TilesetPicker
;
664 static const void *ms_pUiGotContext
;
668 static void EnvelopeEval(float TimeOffset
, int Env
, float *pChannels
, void *pUser
);
671 int DoButton_Editor_Common(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
672 int DoButton_Editor(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
674 int DoButton_Tab(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
675 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
);
676 int DoButton_ButtonDec(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
677 int DoButton_ButtonInc(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
679 int DoButton_File(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
681 int DoButton_Menu(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
);
682 int DoButton_MenuItem(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
=0, const char *pToolTip
=0);
684 int DoEditBox(void *pID
, const CUIRect
*pRect
, char *pStr
, unsigned StrSize
, float FontSize
, float *Offset
, bool Hidden
=false, int Corners
=CUI::CORNER_ALL
);
686 void RenderBackground(CUIRect View
, int Texture
, float Size
, float Brightness
);
688 void RenderGrid(CLayerGroup
*pGroup
);
690 void UiInvokePopupMenu(void *pID
, int Flags
, float X
, float Y
, float W
, float H
, int (*pfnFunc
)(CEditor
*pEditor
, CUIRect Rect
), void *pExtra
=0);
691 void UiDoPopupMenu();
693 int UiDoValueSelector(void *pID
, CUIRect
*pRect
, const char *pLabel
, int Current
, int Min
, int Max
, int Step
, float Scale
, const char *pToolTip
);
695 static int PopupGroup(CEditor
*pEditor
, CUIRect View
);
696 static int PopupLayer(CEditor
*pEditor
, CUIRect View
);
697 static int PopupQuad(CEditor
*pEditor
, CUIRect View
);
698 static int PopupPoint(CEditor
*pEditor
, CUIRect View
);
699 static int PopupNewFolder(CEditor
*pEditor
, CUIRect View
);
700 static int PopupEvent(CEditor
*pEditor
, CUIRect View
);
701 static int PopupSelectImage(CEditor
*pEditor
, CUIRect View
);
702 static int PopupSelectGametileOp(CEditor
*pEditor
, CUIRect View
);
703 static int PopupImage(CEditor
*pEditor
, CUIRect View
);
704 static int PopupMenuFile(CEditor
*pEditor
, CUIRect View
);
705 static int PopupSelectConfigAutoMap(CEditor
*pEditor
, CUIRect View
);
707 static void CallbackOpenMap(const char *pFileName
, int StorageType
, void *pUser
);
708 static void CallbackAppendMap(const char *pFileName
, int StorageType
, void *pUser
);
709 static void CallbackSaveMap(const char *pFileName
, int StorageType
, void *pUser
);
711 void PopupSelectImageInvoke(int Current
, float x
, float y
);
712 int PopupSelectImageResult();
714 void PopupSelectGametileOpInvoke(float x
, float y
);
715 int PopupSelectGameTileOpResult();
717 void PopupSelectConfigAutoMapInvoke(float x
, float y
);
718 int PopupSelectConfigAutoMapResult();
720 vec4
ButtonColorMul(const void *pID
);
722 void DoQuadPoint(CQuad
*pQuad
, int QuadIndex
, int v
);
723 void DoMapEditor(CUIRect View
, CUIRect Toolbar
);
724 void DoToolbar(CUIRect Toolbar
);
725 void DoQuad(CQuad
*pQuad
, int Index
);
726 float UiDoScrollbarV(const void *pID
, const CUIRect
*pRect
, float Current
);
727 vec4
GetButtonColor(const void *pID
, int Checked
);
729 static void ReplaceImage(const char *pFilename
, int StorageType
, void *pUser
);
730 static void AddImage(const char *pFilename
, int StorageType
, void *pUser
);
732 void RenderImages(CUIRect Toolbox
, CUIRect Toolbar
, CUIRect View
);
733 void RenderLayers(CUIRect Toolbox
, CUIRect Toolbar
, CUIRect View
);
734 void RenderModebar(CUIRect View
);
735 void RenderStatusbar(CUIRect View
);
736 void RenderEnvelopeEditor(CUIRect View
);
738 void RenderMenubar(CUIRect Menubar
);
739 void RenderFileDialog();
741 void AddFileDialogEntry(int Index
, CUIRect
*pView
);
743 static void ExtractName(const char *pFileName
, char *pName
, int BufferSize
)
745 const char *pExtractedName
= pFileName
;
746 const char *pEnd
= 0;
747 for(; *pFileName
; ++pFileName
)
749 if(*pFileName
== '/' || *pFileName
== '\\')
750 pExtractedName
= pFileName
+1;
751 else if(*pFileName
== '.')
755 int Length
= pEnd
> pExtractedName
? min(BufferSize
, (int)(pEnd
-pExtractedName
+1)) : BufferSize
;
756 str_copy(pName
, pExtractedName
, Length
);
759 int GetLineDistance();
762 // make sure to inline this function
763 inline class IGraphics
*CLayer::Graphics() { return m_pEditor
->Graphics(); }
764 inline class ITextRender
*CLayer::TextRender() { return m_pEditor
->TextRender(); }