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. */
4 #include <base/system.h>
6 #include <engine/shared/datafile.h>
7 #include <engine/shared/config.h>
8 #include <engine/client.h>
9 #include <engine/console.h>
10 #include <engine/graphics.h>
11 #include <engine/input.h>
12 #include <engine/keys.h>
13 #include <engine/storage.h>
14 #include <engine/textrender.h>
16 #include <game/gamecore.h>
17 #include <game/localization.h>
18 #include <game/client/lineinput.h>
19 #include <game/client/render.h>
20 #include <game/client/ui.h>
21 #include <game/generated/client_data.h>
26 int CEditor::ms_CheckerTexture
;
27 int CEditor::ms_BackgroundTexture
;
28 int CEditor::ms_CursorTexture
;
29 int CEditor::ms_EntitiesTexture
;
30 const void* CEditor::ms_pUiGotContext
;
37 CEditorImage::~CEditorImage()
39 m_pEditor
->Graphics()->UnloadTexture(m_TexID
);
42 CLayerGroup::CLayerGroup()
61 CLayerGroup::~CLayerGroup()
66 void CLayerGroup::Convert(CUIRect
*pRect
)
68 pRect
->x
+= m_OffsetX
;
69 pRect
->y
+= m_OffsetY
;
72 void CLayerGroup::Mapping(float *pPoints
)
74 m_pMap
->m_pEditor
->RenderTools()->MapscreenToWorld(
75 m_pMap
->m_pEditor
->m_WorldOffsetX
, m_pMap
->m_pEditor
->m_WorldOffsetY
,
76 m_ParallaxX
/100.0f
, m_ParallaxY
/100.0f
,
78 m_pMap
->m_pEditor
->Graphics()->ScreenAspect(), m_pMap
->m_pEditor
->m_WorldZoom
, pPoints
);
80 pPoints
[0] += m_pMap
->m_pEditor
->m_EditorOffsetX
;
81 pPoints
[1] += m_pMap
->m_pEditor
->m_EditorOffsetY
;
82 pPoints
[2] += m_pMap
->m_pEditor
->m_EditorOffsetX
;
83 pPoints
[3] += m_pMap
->m_pEditor
->m_EditorOffsetY
;
86 void CLayerGroup::MapScreen()
90 m_pMap
->m_pEditor
->Graphics()->MapScreen(aPoints
[0], aPoints
[1], aPoints
[2], aPoints
[3]);
93 void CLayerGroup::Render()
96 IGraphics
*pGraphics
= m_pMap
->m_pEditor
->Graphics();
101 m_pMap
->m_pGameGroup
->Mapping(aPoints
);
102 float x0
= (m_ClipX
- aPoints
[0]) / (aPoints
[2]-aPoints
[0]);
103 float y0
= (m_ClipY
- aPoints
[1]) / (aPoints
[3]-aPoints
[1]);
104 float x1
= ((m_ClipX
+m_ClipW
) - aPoints
[0]) / (aPoints
[2]-aPoints
[0]);
105 float y1
= ((m_ClipY
+m_ClipH
) - aPoints
[1]) / (aPoints
[3]-aPoints
[1]);
107 pGraphics
->ClipEnable((int)(x0
*pGraphics
->ScreenWidth()), (int)(y0
*pGraphics
->ScreenHeight()),
108 (int)((x1
-x0
)*pGraphics
->ScreenWidth()), (int)((y1
-y0
)*pGraphics
->ScreenHeight()));
111 for(int i
= 0; i
< m_lLayers
.size(); i
++)
113 if(m_lLayers
[i
]->m_Visible
&& m_lLayers
[i
] != m_pMap
->m_pGameLayer
)
115 if(m_pMap
->m_pEditor
->m_ShowDetail
|| !(m_lLayers
[i
]->m_Flags
&LAYERFLAG_DETAIL
))
116 m_lLayers
[i
]->Render();
120 pGraphics
->ClipDisable();
123 void CLayerGroup::AddLayer(CLayer
*l
)
125 m_pMap
->m_Modified
= true;
129 void CLayerGroup::DeleteLayer(int Index
)
131 if(Index
< 0 || Index
>= m_lLayers
.size()) return;
132 delete m_lLayers
[Index
];
133 m_lLayers
.remove_index(Index
);
134 m_pMap
->m_Modified
= true;
137 void CLayerGroup::GetSize(float *w
, float *h
)
140 for(int i
= 0; i
< m_lLayers
.size(); i
++)
143 m_lLayers
[i
]->GetSize(&lw
, &lh
);
150 int CLayerGroup::SwapLayers(int Index0
, int Index1
)
152 if(Index0
< 0 || Index0
>= m_lLayers
.size()) return Index0
;
153 if(Index1
< 0 || Index1
>= m_lLayers
.size()) return Index0
;
154 if(Index0
== Index1
) return Index0
;
155 m_pMap
->m_Modified
= true;
156 swap(m_lLayers
[Index0
], m_lLayers
[Index1
]);
160 void CEditorImage::AnalyseTileFlags()
162 mem_zero(m_aTileFlags
, sizeof(m_aTileFlags
));
164 int tw
= m_Width
/16; // tilesizes
165 int th
= m_Height
/16;
168 unsigned char *pPixelData
= (unsigned char *)m_pData
;
171 for(int ty
= 0; ty
< 16; ty
++)
172 for(int tx
= 0; tx
< 16; tx
++, TileID
++)
175 for(int x
= 0; x
< tw
; x
++)
176 for(int y
= 0; y
< th
; y
++)
178 int p
= (ty
*tw
+y
)*m_Width
+ tx
*tw
+x
;
179 if(pPixelData
[p
*4+3] < 250)
187 m_aTileFlags
[TileID
] |= TILEFLAG_OPAQUE
;
193 void CEditor::EnvelopeEval(float TimeOffset
, int Env
, float *pChannels
, void *pUser
)
195 CEditor
*pThis
= (CEditor
*)pUser
;
196 if(Env
< 0 || Env
>= pThis
->m_Map
.m_lEnvelopes
.size())
205 CEnvelope
*e
= pThis
->m_Map
.m_lEnvelopes
[Env
];
206 float t
= pThis
->m_AnimateTime
+TimeOffset
;
207 t
*= pThis
->m_AnimateSpeed
;
208 e
->Eval(t
, pChannels
);
211 /********************************************************
213 *********************************************************/
215 // copied from gc_menu.cpp, should be more generalized
216 //extern int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false);
218 int CEditor::DoEditBox(void *pID
, const CUIRect
*pRect
, char *pStr
, unsigned StrSize
, float FontSize
, float *Offset
, bool Hidden
, int Corners
)
220 int Inside
= UI()->MouseInside(pRect
);
221 bool ReturnValue
= false;
222 bool UpdateOffset
= false;
223 static int s_AtIndex
= 0;
224 static bool s_DoScroll
= false;
225 static float s_ScrollStart
= 0.0f
;
227 FontSize
*= UI()->Scale();
229 if(UI()->LastActiveItem() == pID
)
231 int Len
= str_length(pStr
);
235 if(Inside
&& UI()->MouseButton(0))
238 s_ScrollStart
= UI()->MouseX();
239 int MxRel
= (int)(UI()->MouseX() - pRect
->x
);
241 for(int i
= 1; i
<= Len
; i
++)
243 if(TextRender()->TextWidth(0, FontSize
, pStr
, i
) - *Offset
> MxRel
)
253 else if(!UI()->MouseButton(0))
258 if(UI()->MouseX() < pRect
->x
&& s_ScrollStart
-UI()->MouseX() > 10.0f
)
260 s_AtIndex
= max(0, s_AtIndex
-1);
261 s_ScrollStart
= UI()->MouseX();
264 else if(UI()->MouseX() > pRect
->x
+pRect
->w
&& UI()->MouseX()-s_ScrollStart
> 10.0f
)
266 s_AtIndex
= min(Len
, s_AtIndex
+1);
267 s_ScrollStart
= UI()->MouseX();
272 for(int i
= 0; i
< Input()->NumEvents(); i
++)
274 Len
= str_length(pStr
);
275 ReturnValue
|= CLineInput::Manipulate(Input()->GetEvent(i
), pStr
, StrSize
, &Len
, &s_AtIndex
);
279 bool JustGotActive
= false;
281 if(UI()->ActiveItem() == pID
)
283 if(!UI()->MouseButton(0))
285 s_AtIndex
= min(s_AtIndex
, str_length(pStr
));
287 UI()->SetActiveItem(0);
290 else if(UI()->HotItem() == pID
)
292 if(UI()->MouseButton(0))
294 if (UI()->LastActiveItem() != pID
)
295 JustGotActive
= true;
296 UI()->SetActiveItem(pID
);
301 UI()->SetHotItem(pID
);
303 CUIRect Textbox
= *pRect
;
304 RenderTools()->DrawUIRect(&Textbox
, vec4(1, 1, 1, 0.5f
), Corners
, 3.0f
);
305 Textbox
.VMargin(2.0f
, &Textbox
);
307 const char *pDisplayStr
= pStr
;
312 unsigned s
= str_length(pStr
);
313 if(s
>= sizeof(aStars
))
314 s
= sizeof(aStars
)-1;
315 for(unsigned int i
= 0; i
< s
; ++i
)
318 pDisplayStr
= aStars
;
321 // check if the text has to be moved
322 if(UI()->LastActiveItem() == pID
&& !JustGotActive
&& (UpdateOffset
|| Input()->NumEvents()))
324 float w
= TextRender()->TextWidth(0, FontSize
, pDisplayStr
, s_AtIndex
);
325 if(w
-*Offset
> Textbox
.w
)
328 float wt
= TextRender()->TextWidth(0, FontSize
, pDisplayStr
, -1);
331 *Offset
+= min(wt
-*Offset
-Textbox
.w
, Textbox
.w
/3);
333 while(w
-*Offset
> Textbox
.w
);
335 else if(w
-*Offset
< 0.0f
)
340 *Offset
= max(0.0f
, *Offset
-Textbox
.w
/3);
342 while(w
-*Offset
< 0.0f
);
345 UI()->ClipEnable(pRect
);
346 Textbox
.x
-= *Offset
;
348 UI()->DoLabel(&Textbox
, pDisplayStr
, FontSize
, -1);
351 if(UI()->LastActiveItem() == pID
&& !JustGotActive
)
353 float w
= TextRender()->TextWidth(0, FontSize
, pDisplayStr
, s_AtIndex
);
355 Textbox
.VSplitLeft(2.0f
, 0, &Textbox
);
356 Textbox
.x
+= (w
-*Offset
-TextRender()->TextWidth(0, FontSize
, "|", -1)/2);
358 if((2*time_get()/time_freq()) % 2) // make it blink
359 UI()->DoLabel(&Textbox
, "|", FontSize
, -1);
366 vec4
CEditor::ButtonColorMul(const void *pID
)
368 if(UI()->ActiveItem() == pID
)
369 return vec4(1,1,1,0.5f
);
370 else if(UI()->HotItem() == pID
)
371 return vec4(1,1,1,1.5f
);
372 return vec4(1,1,1,1);
375 float CEditor::UiDoScrollbarV(const void *pID
, const CUIRect
*pRect
, float Current
)
378 static float s_OffsetY
;
379 pRect
->HSplitTop(33, &Handle
, 0);
381 Handle
.y
+= (pRect
->h
-Handle
.h
)*Current
;
385 int Inside
= UI()->MouseInside(&Handle
);
387 if(UI()->ActiveItem() == pID
)
389 if(!UI()->MouseButton(0))
390 UI()->SetActiveItem(0);
392 float Min
= pRect
->y
;
393 float Max
= pRect
->h
-Handle
.h
;
394 float Cur
= UI()->MouseY()-s_OffsetY
;
396 if(Ret
< 0.0f
) Ret
= 0.0f
;
397 if(Ret
> 1.0f
) Ret
= 1.0f
;
399 else if(UI()->HotItem() == pID
)
401 if(UI()->MouseButton(0))
403 UI()->SetActiveItem(pID
);
404 s_OffsetY
= UI()->MouseY()-Handle
.y
;
409 UI()->SetHotItem(pID
);
413 pRect
->VMargin(5.0f
, &Rail
);
414 RenderTools()->DrawUIRect(&Rail
, vec4(1,1,1,0.25f
), 0, 0.0f
);
416 CUIRect Slider
= Handle
;
417 Slider
.w
= Rail
.x
-Slider
.x
;
418 RenderTools()->DrawUIRect(&Slider
, vec4(1,1,1,0.25f
), CUI::CORNER_L
, 2.5f
);
419 Slider
.x
= Rail
.x
+Rail
.w
;
420 RenderTools()->DrawUIRect(&Slider
, vec4(1,1,1,0.25f
), CUI::CORNER_R
, 2.5f
);
423 Slider
.Margin(5.0f
, &Slider
);
424 RenderTools()->DrawUIRect(&Slider
, vec4(1,1,1,0.25f
)*ButtonColorMul(pID
), CUI::CORNER_ALL
, 2.5f
);
429 vec4
CEditor::GetButtonColor(const void *pID
, int Checked
)
432 return vec4(0,0,0,0.5f
);
436 if(UI()->HotItem() == pID
)
437 return vec4(1,0,0,0.75f
);
438 return vec4(1,0,0,0.5f
);
441 if(UI()->HotItem() == pID
)
442 return vec4(1,1,1,0.75f
);
443 return vec4(1,1,1,0.5f
);
446 int CEditor::DoButton_Editor_Common(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
448 if(UI()->MouseInside(pRect
))
450 if(Flags
&BUTTON_CONTEXT
)
451 ms_pUiGotContext
= pID
;
453 m_pTooltip
= pToolTip
;
456 if(UI()->HotItem() == pID
&& pToolTip
)
457 m_pTooltip
= (const char *)pToolTip
;
459 return UI()->DoButtonLogic(pID
, pText
, Checked
, pRect
);
462 //return UI()->DoButton(id, text, checked, r, draw_func, 0);
466 int CEditor::DoButton_Editor(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
468 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), CUI::CORNER_ALL
, 3.0f
);
469 CUIRect NewRect
= *pRect
;
470 NewRect
.y
+= NewRect
.h
/2.0f
-7.0f
;
471 float tw
= min(TextRender()->TextWidth(0, 10.0f
, pText
, -1), NewRect
.w
);
473 TextRender()->SetCursor(&Cursor
, NewRect
.x
+ NewRect
.w
/2-tw
/2, NewRect
.y
- 1.0f
, 10.0f
, TEXTFLAG_RENDER
|TEXTFLAG_STOP_AT_END
);
474 Cursor
.m_LineWidth
= NewRect
.w
;
475 TextRender()->TextEx(&Cursor
, pText
, -1);
476 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
479 int CEditor::DoButton_File(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
482 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), CUI::CORNER_ALL
, 3.0f
);
486 UI()->DoLabel(&t
, pText
, 10, -1, -1);
487 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
490 int CEditor::DoButton_Menu(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
493 RenderTools()->DrawUIRect(&r
, vec4(0.5f
, 0.5f
, 0.5f
, 1.0f
), CUI::CORNER_T
, 3.0f
);
497 UI()->DoLabel(&r
, pText
, 10, -1, -1);
498 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
501 int CEditor::DoButton_MenuItem(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
503 if(UI()->HotItem() == pID
|| Checked
)
504 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), CUI::CORNER_ALL
, 3.0f
);
509 TextRender()->SetCursor(&Cursor
, t
.x
, t
.y
- 1.0f
, 10.0f
, TEXTFLAG_RENDER
|TEXTFLAG_STOP_AT_END
);
510 Cursor
.m_LineWidth
= t
.w
;
511 TextRender()->TextEx(&Cursor
, pText
, -1);
512 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
515 int CEditor::DoButton_Tab(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
517 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), CUI::CORNER_T
, 5.0f
);
518 CUIRect NewRect
= *pRect
;
519 NewRect
.y
+= NewRect
.h
/2.0f
-7.0f
;
520 UI()->DoLabel(&NewRect
, pText
, 10, 0, -1);
521 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
524 int CEditor::DoButton_Ex(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
, int Corners
, float FontSize
)
526 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), Corners
, 3.0f
);
527 CUIRect NewRect
= *pRect
;
528 NewRect
.HMargin(NewRect
.h
/2.0f
-FontSize
/2.0f
-1.0f
, &NewRect
);
529 UI()->DoLabel(&NewRect
, pText
, FontSize
, 0, -1);
530 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
533 int CEditor::DoButton_ButtonInc(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
535 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), CUI::CORNER_R
, 3.0f
);
536 UI()->DoLabel(pRect
, pText
?pText
:"+", 10, 0, -1);
537 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
540 int CEditor::DoButton_ButtonDec(const void *pID
, const char *pText
, int Checked
, const CUIRect
*pRect
, int Flags
, const char *pToolTip
)
542 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, Checked
), CUI::CORNER_L
, 3.0f
);
543 UI()->DoLabel(pRect
, pText
?pText
:"-", 10, 0, -1);
544 return DoButton_Editor_Common(pID
, pText
, Checked
, pRect
, Flags
, pToolTip
);
547 void CEditor::RenderGrid(CLayerGroup
*pGroup
)
552 float aGroupPoints
[4];
553 pGroup
->Mapping(aGroupPoints
);
555 float w
= UI()->Screen()->w
;
556 float h
= UI()->Screen()->h
;
558 int LineDistance
= GetLineDistance();
560 int XOffset
= aGroupPoints
[0]/LineDistance
;
561 int YOffset
= aGroupPoints
[1]/LineDistance
;
562 int XGridOffset
= XOffset
% m_GridFactor
;
563 int YGridOffset
= YOffset
% m_GridFactor
;
565 Graphics()->TextureSet(-1);
566 Graphics()->LinesBegin();
568 for(int i
= 0; i
< (int)w
; i
++)
570 if((i
+YGridOffset
) % m_GridFactor
== 0)
571 Graphics()->SetColor(1.0f
, 0.3f
, 0.3f
, 0.3f
);
573 Graphics()->SetColor(1.0f
, 1.0f
, 1.0f
, 0.15f
);
575 IGraphics::CLineItem Line
= IGraphics::CLineItem(LineDistance
*XOffset
, LineDistance
*i
+LineDistance
*YOffset
, w
+aGroupPoints
[2], LineDistance
*i
+LineDistance
*YOffset
);
576 Graphics()->LinesDraw(&Line
, 1);
578 if((i
+XGridOffset
) % m_GridFactor
== 0)
579 Graphics()->SetColor(1.0f
, 0.3f
, 0.3f
, 0.3f
);
581 Graphics()->SetColor(1.0f
, 1.0f
, 1.0f
, 0.15f
);
583 Line
= IGraphics::CLineItem(LineDistance
*i
+LineDistance
*XOffset
, LineDistance
*YOffset
, LineDistance
*i
+LineDistance
*XOffset
, h
+aGroupPoints
[3]);
584 Graphics()->LinesDraw(&Line
, 1);
586 Graphics()->SetColor(1.0f
, 1.0f
, 1.0f
, 1.0f
);
587 Graphics()->LinesEnd();
590 void CEditor::RenderBackground(CUIRect View
, int Texture
, float Size
, float Brightness
)
592 Graphics()->TextureSet(Texture
);
593 Graphics()->BlendNormal();
594 Graphics()->QuadsBegin();
595 Graphics()->SetColor(Brightness
, Brightness
, Brightness
, 1.0f
);
596 Graphics()->QuadsSetSubset(0,0, View
.w
/Size
, View
.h
/Size
);
597 IGraphics::CQuadItem
QuadItem(View
.x
, View
.y
, View
.w
, View
.h
);
598 Graphics()->QuadsDrawTL(&QuadItem
, 1);
599 Graphics()->QuadsEnd();
602 int CEditor::UiDoValueSelector(void *pID
, CUIRect
*pRect
, const char *pLabel
, int Current
, int Min
, int Max
, int Step
, float Scale
, const char *pToolTip
)
605 static float s_Value
;
606 int Inside
= UI()->MouseInside(pRect
);
608 if(UI()->ActiveItem() == pID
)
610 if(!UI()->MouseButton(0))
613 UI()->SetActiveItem(0);
617 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
618 s_Value
+= m_MouseDeltaX
*0.05f
;
620 s_Value
+= m_MouseDeltaX
;
622 if(absolute(s_Value
) > Scale
)
624 int Count
= (int)(s_Value
/Scale
);
625 s_Value
= fmod(s_Value
, Scale
);
626 Current
+= Step
*Count
;
634 m_pTooltip
= pToolTip
;
636 else if(UI()->HotItem() == pID
)
638 if(UI()->MouseButton(0))
642 UI()->SetActiveItem(pID
);
645 m_pTooltip
= pToolTip
;
649 UI()->SetHotItem(pID
);
653 str_format(aBuf
, sizeof(aBuf
),"%s %d", pLabel
, Current
);
654 RenderTools()->DrawUIRect(pRect
, GetButtonColor(pID
, 0), CUI::CORNER_ALL
, 5.0f
);
655 pRect
->y
+= pRect
->h
/2.0f
-7.0f
;
656 UI()->DoLabel(pRect
, aBuf
, 10, 0, -1);
661 CLayerGroup
*CEditor::GetSelectedGroup()
663 if(m_SelectedGroup
>= 0 && m_SelectedGroup
< m_Map
.m_lGroups
.size())
664 return m_Map
.m_lGroups
[m_SelectedGroup
];
668 CLayer
*CEditor::GetSelectedLayer(int Index
)
670 CLayerGroup
*pGroup
= GetSelectedGroup();
674 if(m_SelectedLayer
>= 0 && m_SelectedLayer
< m_Map
.m_lGroups
[m_SelectedGroup
]->m_lLayers
.size())
675 return pGroup
->m_lLayers
[m_SelectedLayer
];
679 CLayer
*CEditor::GetSelectedLayerType(int Index
, int Type
)
681 CLayer
*p
= GetSelectedLayer(Index
);
682 if(p
&& p
->m_Type
== Type
)
687 CQuad
*CEditor::GetSelectedQuad()
689 CLayerQuads
*ql
= (CLayerQuads
*)GetSelectedLayerType(0, LAYERTYPE_QUADS
);
692 if(m_SelectedQuad
>= 0 && m_SelectedQuad
< ql
->m_lQuads
.size())
693 return &ql
->m_lQuads
[m_SelectedQuad
];
697 void CEditor::CallbackOpenMap(const char *pFileName
, int StorageType
, void *pUser
)
699 CEditor
*pEditor
= (CEditor
*)pUser
;
700 if(pEditor
->Load(pFileName
, StorageType
))
702 str_copy(pEditor
->m_aFileName
, pFileName
, 512);
703 pEditor
->m_ValidSaveFilename
= StorageType
== IStorage::TYPE_SAVE
&& pEditor
->m_pFileDialogPath
== pEditor
->m_aFileDialogCurrentFolder
;
704 pEditor
->SortImages();
705 pEditor
->m_Dialog
= DIALOG_NONE
;
706 pEditor
->m_Map
.m_Modified
= false;
709 void CEditor::CallbackAppendMap(const char *pFileName
, int StorageType
, void *pUser
)
711 CEditor
*pEditor
= (CEditor
*)pUser
;
712 if(pEditor
->Append(pFileName
, StorageType
))
713 pEditor
->m_aFileName
[0] = 0;
715 pEditor
->SortImages();
717 pEditor
->m_Dialog
= DIALOG_NONE
;
719 void CEditor::CallbackSaveMap(const char *pFileName
, int StorageType
, void *pUser
)
721 CEditor
*pEditor
= static_cast<CEditor
*>(pUser
);
723 const int Length
= str_length(pFileName
);
725 if(Length
<= 4 || pFileName
[Length
-4] != '.' || str_comp_nocase(pFileName
+Length
-3, "map"))
727 str_format(aBuf
, sizeof(aBuf
), "%s.map", pFileName
);
731 if(pEditor
->Save(pFileName
))
733 str_copy(pEditor
->m_aFileName
, pFileName
, sizeof(pEditor
->m_aFileName
));
734 pEditor
->m_ValidSaveFilename
= StorageType
== IStorage::TYPE_SAVE
&& pEditor
->m_pFileDialogPath
== pEditor
->m_aFileDialogCurrentFolder
;
735 pEditor
->m_Map
.m_Modified
= false;
738 pEditor
->m_Dialog
= DIALOG_NONE
;
741 void CEditor::DoToolbar(CUIRect ToolBar
)
743 CUIRect TB_Top
, TB_Bottom
;
746 ToolBar
.HSplitTop(ToolBar
.h
/2.0f
, &TB_Top
, &TB_Bottom
);
748 TB_Top
.HSplitBottom(2.5f
, &TB_Top
, 0);
749 TB_Bottom
.HSplitTop(2.5f
, 0, &TB_Bottom
);
752 if(Input()->KeyDown('o') && (Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
)) && m_Dialog
== DIALOG_NONE
)
756 if(!m_PopupEventWasActivated
)
758 m_PopupEventType
= POPEVENT_LOAD
;
759 m_PopupEventActivated
= true;
763 InvokeFileDialog(IStorage::TYPE_ALL
, FILETYPE_MAP
, "Load map", "Load", "maps", "", CallbackOpenMap
, this);
767 if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
)) && m_Dialog
== DIALOG_NONE
)
769 if(m_aFileName
[0] && m_ValidSaveFilename
)
771 if(!m_PopupEventWasActivated
)
773 str_copy(m_aFileSaveName
, m_aFileName
, sizeof(m_aFileSaveName
));
774 m_PopupEventType
= POPEVENT_SAVE
;
775 m_PopupEventActivated
= true;
779 InvokeFileDialog(IStorage::TYPE_SAVE
, FILETYPE_MAP
, "Save map", "Save", "maps", "", CallbackSaveMap
, this);
783 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
784 static int s_HqButton
= 0;
785 if(DoButton_Editor(&s_HqButton
, "HD", m_ShowDetail
, &Button
, 0, "[ctrl+h] Toggle High Detail") ||
786 (Input()->KeyDown('h') && (Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
))))
788 m_ShowDetail
= !m_ShowDetail
;
791 TB_Top
.VSplitLeft(5.0f
, 0, &TB_Top
);
794 TB_Top
.VSplitLeft(40.0f
, &Button
, &TB_Top
);
795 static int s_AnimateButton
= 0;
796 if(DoButton_Editor(&s_AnimateButton
, "Anim", m_Animate
, &Button
, 0, "[ctrl+m] Toggle animation") ||
797 (Input()->KeyDown('m') && (Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
))))
799 m_AnimateStart
= time_get();
800 m_Animate
= !m_Animate
;
803 TB_Top
.VSplitLeft(5.0f
, 0, &TB_Top
);
806 TB_Top
.VSplitLeft(40.0f
, &Button
, &TB_Top
);
807 static int s_ProofButton
= 0;
808 if(DoButton_Editor(&s_ProofButton
, "Proof", m_ProofBorders
, &Button
, 0, "[ctrl+p] Toggles proof borders. These borders represent what a player maximum can see.") ||
809 (Input()->KeyDown('p') && (Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
))))
811 m_ProofBorders
= !m_ProofBorders
;
814 TB_Top
.VSplitLeft(5.0f
, 0, &TB_Top
);
817 TB_Top
.VSplitLeft(40.0f
, &Button
, &TB_Top
);
818 static int s_TileInfoButton
= 0;
819 if(DoButton_Editor(&s_TileInfoButton
, "Info", m_ShowTileInfo
, &Button
, 0, "[ctrl+i] Show tile informations") ||
820 (Input()->KeyDown('i') && (Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
))))
822 m_ShowTileInfo
= !m_ShowTileInfo
;
825 TB_Top
.VSplitLeft(15.0f
, 0, &TB_Top
);
828 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
829 static int s_ZoomOutButton
= 0;
830 if(DoButton_Ex(&s_ZoomOutButton
, "ZO", 0, &Button
, 0, "[NumPad-] Zoom out", CUI::CORNER_L
) || Input()->KeyDown(KEY_KP_MINUS
))
833 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
834 static int s_ZoomNormalButton
= 0;
835 if(DoButton_Ex(&s_ZoomNormalButton
, "1:1", 0, &Button
, 0, "[NumPad*] Zoom to normal and remove editor offset", 0) || Input()->KeyDown(KEY_KP_MULTIPLY
))
842 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
843 static int s_ZoomInButton
= 0;
844 if(DoButton_Ex(&s_ZoomInButton
, "ZI", 0, &Button
, 0, "[NumPad+] Zoom in", CUI::CORNER_R
) || Input()->KeyDown(KEY_KP_PLUS
))
847 TB_Top
.VSplitLeft(10.0f
, 0, &TB_Top
);
850 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
851 static int s_AnimFasterButton
= 0;
852 if(DoButton_Ex(&s_AnimFasterButton
, "A+", 0, &Button
, 0, "Increase animation speed", CUI::CORNER_L
))
853 m_AnimateSpeed
+= 0.5f
;
855 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
856 static int s_AnimNormalButton
= 0;
857 if(DoButton_Ex(&s_AnimNormalButton
, "1", 0, &Button
, 0, "Normal animation speed", 0))
858 m_AnimateSpeed
= 1.0f
;
860 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
861 static int s_AnimSlowerButton
= 0;
862 if(DoButton_Ex(&s_AnimSlowerButton
, "A-", 0, &Button
, 0, "Decrease animation speed", CUI::CORNER_R
))
864 if(m_AnimateSpeed
> 0.5f
)
865 m_AnimateSpeed
-= 0.5f
;
868 m_WorldZoom
= m_ZoomLevel
/100.0f
;
870 TB_Top
.VSplitLeft(10.0f
, &Button
, &TB_Top
);
873 // brush manipulation
875 int Enabled
= m_Brush
.IsEmpty()?-1:0;
878 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
879 static int s_FlipXButton
= 0;
880 if(DoButton_Ex(&s_FlipXButton
, "X/X", Enabled
, &Button
, 0, "[N] Flip brush horizontal", CUI::CORNER_L
) || Input()->KeyDown('n'))
882 for(int i
= 0; i
< m_Brush
.m_lLayers
.size(); i
++)
883 m_Brush
.m_lLayers
[i
]->BrushFlipX();
886 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
887 static int s_FlipyButton
= 0;
888 if(DoButton_Ex(&s_FlipyButton
, "Y/Y", Enabled
, &Button
, 0, "[M] Flip brush vertical", CUI::CORNER_R
) || Input()->KeyDown('m'))
890 for(int i
= 0; i
< m_Brush
.m_lLayers
.size(); i
++)
891 m_Brush
.m_lLayers
[i
]->BrushFlipY();
895 TB_Top
.VSplitLeft(15.0f
, &Button
, &TB_Top
);
897 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
898 static int s_RotationAmount
= 90;
899 bool TileLayer
= false;
900 // check for tile layers in brush selection
901 for(int i
= 0; i
< m_Brush
.m_lLayers
.size(); i
++)
902 if(m_Brush
.m_lLayers
[i
]->m_Type
== LAYERTYPE_TILES
)
905 s_RotationAmount
= max(90, (s_RotationAmount
/90)*90);
908 s_RotationAmount
= UiDoValueSelector(&s_RotationAmount
, &Button
, "", s_RotationAmount
, TileLayer
?90:1, 359, TileLayer
?90:1, TileLayer
?10.0f
:2.0f
, "Rotation of the brush in degrees. Use left mouse button to drag and change the value. Hold shift to be more precise.");
910 TB_Top
.VSplitLeft(5.0f
, &Button
, &TB_Top
);
911 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
912 static int s_CcwButton
= 0;
913 if(DoButton_Ex(&s_CcwButton
, "CCW", Enabled
, &Button
, 0, "[R] Rotates the brush counter clockwise", CUI::CORNER_L
) || Input()->KeyDown('r'))
915 for(int i
= 0; i
< m_Brush
.m_lLayers
.size(); i
++)
916 m_Brush
.m_lLayers
[i
]->BrushRotate(-s_RotationAmount
/360.0f
*pi
*2);
919 TB_Top
.VSplitLeft(30.0f
, &Button
, &TB_Top
);
920 static int s_CwButton
= 0;
921 if(DoButton_Ex(&s_CwButton
, "CW", Enabled
, &Button
, 0, "[T] Rotates the brush clockwise", CUI::CORNER_R
) || Input()->KeyDown('t'))
923 for(int i
= 0; i
< m_Brush
.m_lLayers
.size(); i
++)
924 m_Brush
.m_lLayers
[i
]->BrushRotate(s_RotationAmount
/360.0f
*pi
*2);
931 TB_Top
.VSplitLeft(10.0f
, &Button
, &TB_Top
);
932 TB_Top
.VSplitLeft(60.0f
, &Button
, &TB_Top
);
933 static int s_NewButton
= 0;
935 CLayerQuads
*pQLayer
= (CLayerQuads
*)GetSelectedLayerType(0, LAYERTYPE_QUADS
);
936 //CLayerTiles *tlayer = (CLayerTiles *)get_selected_layer_type(0, LAYERTYPE_TILES);
937 if(DoButton_Editor(&s_NewButton
, "Add Quad", pQLayer
?0:-1, &Button
, 0, "Adds a new quad"))
942 CLayerGroup
*g
= GetSelectedGroup();
944 int AddX
= f2fx(Mapping
[0] + (Mapping
[2]-Mapping
[0])/2);
945 int AddY
= f2fx(Mapping
[1] + (Mapping
[3]-Mapping
[1])/2);
947 CQuad
*q
= pQLayer
->NewQuad();
948 for(int i
= 0; i
< 5; i
++)
950 q
->m_aPoints
[i
].x
+= AddX
;
951 q
->m_aPoints
[i
].y
+= AddY
;
959 TB_Bottom
.VSplitLeft(40.0f
, &Button
, &TB_Bottom
);
960 static int s_BorderBut
= 0;
961 CLayerTiles
*pT
= (CLayerTiles
*)GetSelectedLayerType(0, LAYERTYPE_TILES
);
963 if(DoButton_Editor(&s_BorderBut
, "Border", pT
?0:-1, &Button
, 0, "Adds border tiles"))
970 TB_Bottom
.VSplitLeft(5.0f
, 0, &TB_Bottom
);
973 TB_Bottom
.VSplitLeft(50.0f
, &Button
, &TB_Bottom
);
974 static int s_RefocusButton
= 0;
975 if(DoButton_Editor(&s_RefocusButton
, "Refocus", m_WorldOffsetX
&&m_WorldOffsetY
?0:-1, &Button
, 0, "[HOME] Restore map focus") || Input()->KeyDown(KEY_HOME
))
981 TB_Bottom
.VSplitLeft(5.0f
, 0, &TB_Bottom
);
984 TB_Bottom
.VSplitLeft(50.0f
, &Button
, &TB_Bottom
);
985 static int s_GridButton
= 0;
986 if(DoButton_Editor(&s_GridButton
, "Grid", m_GridActive
, &Button
, 0, "Toggle Grid"))
988 m_GridActive
= !m_GridActive
;
991 TB_Bottom
.VSplitLeft(30.0f
, 0, &TB_Bottom
);
994 TB_Bottom
.VSplitLeft(30.0f
, &Button
, &TB_Bottom
);
995 static int s_GridIncreaseButton
= 0;
996 if(DoButton_Ex(&s_GridIncreaseButton
, "G-", 0, &Button
, 0, "Decrease grid", CUI::CORNER_L
))
1002 TB_Bottom
.VSplitLeft(30.0f
, &Button
, &TB_Bottom
);
1003 static int s_GridNormalButton
= 0;
1004 if(DoButton_Ex(&s_GridNormalButton
, "1", 0, &Button
, 0, "Normal grid", 0))
1007 TB_Bottom
.VSplitLeft(30.0f
, &Button
, &TB_Bottom
);
1009 static int s_GridDecreaseButton
= 0;
1010 if(DoButton_Ex(&s_GridDecreaseButton
, "G+", 0, &Button
, 0, "Increase grid", CUI::CORNER_R
))
1012 if(m_GridFactor
< 15)
1017 static void Rotate(CPoint
*pCenter
, CPoint
*pPoint
, float Rotation
)
1019 int x
= pPoint
->x
- pCenter
->x
;
1020 int y
= pPoint
->y
- pCenter
->y
;
1021 pPoint
->x
= (int)(x
* cosf(Rotation
) - y
* sinf(Rotation
) + pCenter
->x
);
1022 pPoint
->y
= (int)(x
* sinf(Rotation
) + y
* cosf(Rotation
) + pCenter
->y
);
1025 void CEditor::DoQuad(CQuad
*q
, int Index
)
1036 // some basic values
1037 void *pID
= &q
->m_aPoints
[4]; // use pivot addr as id
1038 static CPoint s_RotatePoints
[4];
1039 static float s_LastWx
;
1040 static float s_LastWy
;
1041 static int s_Operation
= OP_NONE
;
1042 static float s_RotateAngle
= 0;
1043 float wx
= UI()->MouseWorldX();
1044 float wy
= UI()->MouseWorldY();
1047 float CenterX
= fx2f(q
->m_aPoints
[4].x
);
1048 float CenterY
= fx2f(q
->m_aPoints
[4].y
);
1050 float dx
= (CenterX
- wx
)/m_WorldZoom
;
1051 float dy
= (CenterY
- wy
)/m_WorldZoom
;
1052 if(dx
*dx
+dy
*dy
< 50)
1053 UI()->SetHotItem(pID
);
1055 // draw selection background
1056 if(m_SelectedQuad
== Index
)
1058 Graphics()->SetColor(0,0,0,1);
1059 IGraphics::CQuadItem
QuadItem(CenterX
, CenterY
, 7.0f
, 7.0f
);
1060 Graphics()->QuadsDraw(&QuadItem
, 1);
1063 if(UI()->ActiveItem() == pID
)
1065 if(m_MouseDeltaWx
*m_MouseDeltaWx
+m_MouseDeltaWy
*m_MouseDeltaWy
> 0.5f
)
1067 // check if we only should move pivot
1068 if(s_Operation
== OP_MOVE_PIVOT
)
1072 int LineDistance
= GetLineDistance();
1077 x
= (int)((wx
+(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1079 x
= (int)((wx
-(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1081 y
= (int)((wy
+(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1083 y
= (int)((wy
-(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1085 q
->m_aPoints
[4].x
= f2fx(x
);
1086 q
->m_aPoints
[4].y
= f2fx(y
);
1090 q
->m_aPoints
[4].x
+= f2fx(wx
-s_LastWx
);
1091 q
->m_aPoints
[4].y
+= f2fx(wy
-s_LastWy
);
1094 else if(s_Operation
== OP_MOVE_ALL
)
1096 // move all points including pivot
1099 int LineDistance
= GetLineDistance();
1104 x
= (int)((wx
+(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1106 x
= (int)((wx
-(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1108 y
= (int)((wy
+(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1110 y
= (int)((wy
-(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1112 int OldX
= q
->m_aPoints
[4].x
;
1113 int OldY
= q
->m_aPoints
[4].y
;
1114 q
->m_aPoints
[4].x
= f2fx(x
);
1115 q
->m_aPoints
[4].y
= f2fx(y
);
1116 int DiffX
= q
->m_aPoints
[4].x
- OldX
;
1117 int DiffY
= q
->m_aPoints
[4].y
- OldY
;
1119 for(int v
= 0; v
< 4; v
++)
1121 q
->m_aPoints
[v
].x
+= DiffX
;
1122 q
->m_aPoints
[v
].y
+= DiffY
;
1127 for(int v
= 0; v
< 5; v
++)
1129 q
->m_aPoints
[v
].x
+= f2fx(wx
-s_LastWx
);
1130 q
->m_aPoints
[v
].y
+= f2fx(wy
-s_LastWy
);
1134 else if(s_Operation
== OP_ROTATE
)
1136 for(int v
= 0; v
< 4; v
++)
1138 q
->m_aPoints
[v
] = s_RotatePoints
[v
];
1139 Rotate(&q
->m_aPoints
[4], &q
->m_aPoints
[v
], s_RotateAngle
);
1144 s_RotateAngle
+= (m_MouseDeltaX
) * 0.002f
;
1148 if(s_Operation
== OP_CONTEXT_MENU
)
1150 if(!UI()->MouseButton(1))
1152 static int s_QuadPopupID
= 0;
1153 UiInvokePopupMenu(&s_QuadPopupID
, 0, UI()->MouseX(), UI()->MouseY(), 120, 180, PopupQuad
);
1154 m_LockMouse
= false;
1155 s_Operation
= OP_NONE
;
1156 UI()->SetActiveItem(0);
1161 if(!UI()->MouseButton(0))
1163 m_LockMouse
= false;
1164 s_Operation
= OP_NONE
;
1165 UI()->SetActiveItem(0);
1169 Graphics()->SetColor(1,1,1,1);
1171 else if(UI()->HotItem() == pID
)
1173 ms_pUiGotContext
= pID
;
1175 Graphics()->SetColor(1,1,1,1);
1176 m_pTooltip
= "Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate.";
1178 if(UI()->MouseButton(0))
1180 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
1181 s_Operation
= OP_MOVE_PIVOT
;
1182 else if(Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
))
1185 s_Operation
= OP_ROTATE
;
1187 s_RotatePoints
[0] = q
->m_aPoints
[0];
1188 s_RotatePoints
[1] = q
->m_aPoints
[1];
1189 s_RotatePoints
[2] = q
->m_aPoints
[2];
1190 s_RotatePoints
[3] = q
->m_aPoints
[3];
1193 s_Operation
= OP_MOVE_ALL
;
1195 UI()->SetActiveItem(pID
);
1196 if(m_SelectedQuad
!= Index
)
1197 m_SelectedPoints
= 0;
1198 m_SelectedQuad
= Index
;
1203 if(UI()->MouseButton(1))
1205 if(m_SelectedQuad
!= Index
)
1206 m_SelectedPoints
= 0;
1207 m_SelectedQuad
= Index
;
1208 s_Operation
= OP_CONTEXT_MENU
;
1209 UI()->SetActiveItem(pID
);
1213 Graphics()->SetColor(0,1,0,1);
1215 IGraphics::CQuadItem
QuadItem(CenterX
, CenterY
, 5.0f
*m_WorldZoom
, 5.0f
*m_WorldZoom
);
1216 Graphics()->QuadsDraw(&QuadItem
, 1);
1219 void CEditor::DoQuadPoint(CQuad
*pQuad
, int QuadIndex
, int V
)
1221 void *pID
= &pQuad
->m_aPoints
[V
];
1223 float wx
= UI()->MouseWorldX();
1224 float wy
= UI()->MouseWorldY();
1226 float px
= fx2f(pQuad
->m_aPoints
[V
].x
);
1227 float py
= fx2f(pQuad
->m_aPoints
[V
].y
);
1229 float dx
= (px
- wx
)/m_WorldZoom
;
1230 float dy
= (py
- wy
)/m_WorldZoom
;
1231 if(dx
*dx
+dy
*dy
< 50)
1232 UI()->SetHotItem(pID
);
1234 // draw selection background
1235 if(m_SelectedQuad
== QuadIndex
&& m_SelectedPoints
&(1<<V
))
1237 Graphics()->SetColor(0,0,0,1);
1238 IGraphics::CQuadItem
QuadItem(px
, py
, 7.0f
, 7.0f
);
1239 Graphics()->QuadsDraw(&QuadItem
, 1);
1250 static bool s_Moved
;
1251 static int s_Operation
= OP_NONE
;
1253 if(UI()->ActiveItem() == pID
)
1255 float dx
= m_MouseDeltaWx
;
1256 float dy
= m_MouseDeltaWy
;
1259 if(dx
*dx
+dy
*dy
> 0.5f
)
1265 if(s_Operation
== OP_MOVEPOINT
)
1269 for(int m
= 0; m
< 4; m
++)
1270 if(m_SelectedPoints
&(1<<m
))
1272 int LineDistance
= GetLineDistance();
1277 x
= (int)((wx
+(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1279 x
= (int)((wx
-(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1281 y
= (int)((wy
+(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1283 y
= (int)((wy
-(LineDistance
/2)*m_GridFactor
)/(LineDistance
*m_GridFactor
)) * (LineDistance
*m_GridFactor
);
1285 pQuad
->m_aPoints
[m
].x
= f2fx(x
);
1286 pQuad
->m_aPoints
[m
].y
= f2fx(y
);
1291 for(int m
= 0; m
< 4; m
++)
1292 if(m_SelectedPoints
&(1<<m
))
1294 pQuad
->m_aPoints
[m
].x
+= f2fx(dx
);
1295 pQuad
->m_aPoints
[m
].y
+= f2fx(dy
);
1299 else if(s_Operation
== OP_MOVEUV
)
1301 for(int m
= 0; m
< 4; m
++)
1302 if(m_SelectedPoints
&(1<<m
))
1307 pQuad
->m_aTexcoords
[m
].x
+= f2fx(dx
*0.001f
);
1308 pQuad
->m_aTexcoords
[(m
+2)%4].x
+= f2fx(dx
*0.001f
);
1310 pQuad
->m_aTexcoords
[m
].y
+= f2fx(dy
*0.001f
);
1311 pQuad
->m_aTexcoords
[m
^1].y
+= f2fx(dy
*0.001f
);
1316 if(s_Operation
== OP_CONTEXT_MENU
)
1318 if(!UI()->MouseButton(1))
1320 static int s_PointPopupID
= 0;
1321 UiInvokePopupMenu(&s_PointPopupID
, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupPoint
);
1322 UI()->SetActiveItem(0);
1327 if(!UI()->MouseButton(0))
1331 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
1332 m_SelectedPoints
^= 1<<V
;
1334 m_SelectedPoints
= 1<<V
;
1336 m_LockMouse
= false;
1337 UI()->SetActiveItem(0);
1341 Graphics()->SetColor(1,1,1,1);
1343 else if(UI()->HotItem() == pID
)
1345 ms_pUiGotContext
= pID
;
1347 Graphics()->SetColor(1,1,1,1);
1348 m_pTooltip
= "Left mouse button to move. Hold shift to move the texture.";
1350 if(UI()->MouseButton(0))
1352 UI()->SetActiveItem(pID
);
1354 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
1356 s_Operation
= OP_MOVEUV
;
1360 s_Operation
= OP_MOVEPOINT
;
1362 if(!(m_SelectedPoints
&(1<<V
)))
1364 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
1365 m_SelectedPoints
|= 1<<V
;
1367 m_SelectedPoints
= 1<<V
;
1370 m_SelectedQuad
= QuadIndex
;
1372 else if(UI()->MouseButton(1))
1374 s_Operation
= OP_CONTEXT_MENU
;
1375 m_SelectedQuad
= QuadIndex
;
1376 UI()->SetActiveItem(pID
);
1377 if(!(m_SelectedPoints
&(1<<V
)))
1379 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
1380 m_SelectedPoints
|= 1<<V
;
1382 m_SelectedPoints
= 1<<V
;
1388 Graphics()->SetColor(1,0,0,1);
1390 IGraphics::CQuadItem
QuadItem(px
, py
, 5.0f
*m_WorldZoom
, 5.0f
*m_WorldZoom
);
1391 Graphics()->QuadsDraw(&QuadItem
, 1);
1394 void CEditor::DoMapEditor(CUIRect View
, CUIRect ToolBar
)
1396 // render all good stuff
1399 for(int g
= 0; g
< m_Map
.m_lGroups
.size(); g
++)
1401 if(m_Map
.m_lGroups
[g
]->m_Visible
)
1402 m_Map
.m_lGroups
[g
]->Render();
1403 //UI()->ClipEnable(&view);
1406 // render the game above everything else
1407 if(m_Map
.m_pGameGroup
->m_Visible
&& m_Map
.m_pGameLayer
->m_Visible
)
1409 m_Map
.m_pGameGroup
->MapScreen();
1410 m_Map
.m_pGameLayer
->Render();
1413 CLayerTiles
*pT
= static_cast<CLayerTiles
*>(GetSelectedLayerType(0, LAYERTYPE_TILES
));
1414 if(m_ShowTileInfo
&& pT
&& pT
->m_Visible
&& m_ZoomLevel
<= 300)
1416 GetSelectedGroup()->MapScreen();
1421 static void *s_pEditorID
= (void *)&s_pEditorID
;
1422 int Inside
= UI()->MouseInside(&View
);
1424 // fetch mouse position
1425 float wx
= UI()->MouseWorldX();
1426 float wy
= UI()->MouseWorldY();
1427 float mx
= UI()->MouseX();
1428 float my
= UI()->MouseY();
1430 static float s_StartWx
= 0;
1431 static float s_StartWy
= 0;
1443 // remap the screen so it can display the whole tileset
1446 CUIRect Screen
= *UI()->Screen();
1447 float Size
= 32.0*16.0f
;
1448 float w
= Size
*(Screen
.w
/View
.w
);
1449 float h
= Size
*(Screen
.h
/View
.h
);
1450 float x
= -(View
.x
/Screen
.w
)*w
;
1451 float y
= -(View
.y
/Screen
.h
)*h
;
1452 wx
= x
+w
*mx
/Screen
.w
;
1453 wy
= y
+h
*my
/Screen
.h
;
1454 Graphics()->MapScreen(x
, y
, x
+w
, y
+h
);
1455 CLayerTiles
*t
= (CLayerTiles
*)GetSelectedLayerType(0, LAYERTYPE_TILES
);
1458 m_TilesetPicker
.m_Image
= t
->m_Image
;
1459 m_TilesetPicker
.m_TexID
= t
->m_TexID
;
1460 m_TilesetPicker
.Render();
1462 m_TilesetPicker
.ShowInfo();
1466 static int s_Operation
= OP_NONE
;
1468 // draw layer borders
1469 CLayer
*pEditLayers
[16];
1470 int NumEditLayers
= 0;
1475 pEditLayers
[0] = &m_TilesetPicker
;
1480 pEditLayers
[0] = GetSelectedLayer(0);
1484 CLayerGroup
*g
= GetSelectedGroup();
1491 for(int i
= 0; i
< NumEditLayers
; i
++)
1493 if(pEditLayers
[i
]->m_Type
!= LAYERTYPE_TILES
)
1497 pEditLayers
[i
]->GetSize(&w
, &h
);
1499 IGraphics::CLineItem Array
[4] = {
1500 IGraphics::CLineItem(0, 0, w
, 0),
1501 IGraphics::CLineItem(w
, 0, w
, h
),
1502 IGraphics::CLineItem(w
, h
, 0, h
),
1503 IGraphics::CLineItem(0, h
, 0, 0)};
1504 Graphics()->TextureSet(-1);
1505 Graphics()->LinesBegin();
1506 Graphics()->LinesDraw(Array
, 4);
1507 Graphics()->LinesEnd();
1514 UI()->SetHotItem(s_pEditorID
);
1516 // do global operations like pan and zoom
1517 if(UI()->ActiveItem() == 0 && (UI()->MouseButton(0) || UI()->MouseButton(2)))
1522 if(Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
) || UI()->MouseButton(2))
1524 if(Input()->KeyPressed(KEY_LSHIFT
))
1525 s_Operation
= OP_PAN_EDITOR
;
1527 s_Operation
= OP_PAN_WORLD
;
1528 UI()->SetActiveItem(s_pEditorID
);
1533 if(UI()->HotItem() == s_pEditorID
)
1535 if(m_Brush
.IsEmpty())
1536 m_pTooltip
= "Use left mouse button to drag and create a brush.";
1538 m_pTooltip
= "Use left mouse button to paint with the brush. Right button clears the brush.";
1540 if(UI()->ActiveItem() == s_pEditorID
)
1559 if(s_Operation
== OP_BRUSH_DRAW
)
1561 if(!m_Brush
.IsEmpty())
1564 for(int k
= 0; k
< NumEditLayers
; k
++)
1566 if(pEditLayers
[k
]->m_Type
== m_Brush
.m_lLayers
[0]->m_Type
)
1567 pEditLayers
[k
]->BrushDraw(m_Brush
.m_lLayers
[0], wx
, wy
);
1571 else if(s_Operation
== OP_BRUSH_GRAB
)
1573 if(!UI()->MouseButton(0))
1577 str_format(aBuf
, sizeof(aBuf
),"grabbing %f %f %f %f", r
.x
, r
.y
, r
.w
, r
.h
);
1578 Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG
, "editor", aBuf
);
1580 // TODO: do all layers
1582 for(int k
= 0; k
< NumEditLayers
; k
++)
1583 Grabs
+= pEditLayers
[k
]->BrushGrab(&m_Brush
, r
);
1589 //editor.map.groups[selected_group]->mapscreen();
1590 for(int k
= 0; k
< NumEditLayers
; k
++)
1591 pEditLayers
[k
]->BrushSelecting(r
);
1592 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
1595 else if(s_Operation
== OP_BRUSH_PAINT
)
1597 if(!UI()->MouseButton(0))
1599 for(int k
= 0; k
< NumEditLayers
; k
++)
1600 pEditLayers
[k
]->FillSelection(m_Brush
.IsEmpty(), m_Brush
.m_lLayers
[0], r
);
1604 //editor.map.groups[selected_group]->mapscreen();
1605 for(int k
= 0; k
< NumEditLayers
; k
++)
1606 pEditLayers
[k
]->BrushSelecting(r
);
1607 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
1613 if(UI()->MouseButton(1))
1616 if(UI()->MouseButton(0) && s_Operation
== OP_NONE
)
1618 UI()->SetActiveItem(s_pEditorID
);
1620 if(m_Brush
.IsEmpty())
1621 s_Operation
= OP_BRUSH_GRAB
;
1624 s_Operation
= OP_BRUSH_DRAW
;
1625 for(int k
= 0; k
< NumEditLayers
; k
++)
1627 if(pEditLayers
[k
]->m_Type
== m_Brush
.m_lLayers
[0]->m_Type
)
1628 pEditLayers
[k
]->BrushPlace(m_Brush
.m_lLayers
[0], wx
, wy
);
1633 CLayerTiles
*pLayer
= (CLayerTiles
*)GetSelectedLayerType(0, LAYERTYPE_TILES
);
1634 if((Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
)) && pLayer
)
1635 s_Operation
= OP_BRUSH_PAINT
;
1638 if(!m_Brush
.IsEmpty())
1640 m_Brush
.m_OffsetX
= -(int)wx
;
1641 m_Brush
.m_OffsetY
= -(int)wy
;
1642 for(int i
= 0; i
< m_Brush
.m_lLayers
.size(); i
++)
1644 if(m_Brush
.m_lLayers
[i
]->m_Type
== LAYERTYPE_TILES
)
1646 m_Brush
.m_OffsetX
= -(int)(wx
/32.0f
)*32;
1647 m_Brush
.m_OffsetY
= -(int)(wy
/32.0f
)*32;
1652 CLayerGroup
*g
= GetSelectedGroup();
1655 m_Brush
.m_OffsetX
+= g
->m_OffsetX
;
1656 m_Brush
.m_OffsetY
+= g
->m_OffsetY
;
1657 m_Brush
.m_ParallaxX
= g
->m_ParallaxX
;
1658 m_Brush
.m_ParallaxY
= g
->m_ParallaxY
;
1661 m_Brush
.GetSize(&w
, &h
);
1663 IGraphics::CLineItem Array
[4] = {
1664 IGraphics::CLineItem(0, 0, w
, 0),
1665 IGraphics::CLineItem(w
, 0, w
, h
),
1666 IGraphics::CLineItem(w
, h
, 0, h
),
1667 IGraphics::CLineItem(0, h
, 0, 0)};
1668 Graphics()->TextureSet(-1);
1669 Graphics()->LinesBegin();
1670 Graphics()->LinesDraw(Array
, 4);
1671 Graphics()->LinesEnd();
1679 if(!m_ShowPicker
&& m_Brush
.IsEmpty())
1682 CLayerGroup
*g
= GetSelectedGroup();
1686 for(int k
= 0; k
< NumEditLayers
; k
++)
1688 if(pEditLayers
[k
]->m_Type
== LAYERTYPE_QUADS
)
1690 CLayerQuads
*pLayer
= (CLayerQuads
*)pEditLayers
[k
];
1692 Graphics()->TextureSet(-1);
1693 Graphics()->QuadsBegin();
1694 for(int i
= 0; i
< pLayer
->m_lQuads
.size(); i
++)
1696 for(int v
= 0; v
< 4; v
++)
1697 DoQuadPoint(&pLayer
->m_lQuads
[i
], i
, v
);
1699 DoQuad(&pLayer
->m_lQuads
[i
], i
);
1701 Graphics()->QuadsEnd();
1705 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
1709 if(UI()->ActiveItem() == s_pEditorID
)
1711 if(s_Operation
== OP_PAN_WORLD
)
1713 m_WorldOffsetX
-= m_MouseDeltaX
*m_WorldZoom
;
1714 m_WorldOffsetY
-= m_MouseDeltaY
*m_WorldZoom
;
1716 else if(s_Operation
== OP_PAN_EDITOR
)
1718 m_EditorOffsetX
-= m_MouseDeltaX
*m_WorldZoom
;
1719 m_EditorOffsetY
-= m_MouseDeltaY
*m_WorldZoom
;
1723 if(!UI()->MouseButton(0))
1725 s_Operation
= OP_NONE
;
1726 UI()->SetActiveItem(0);
1731 else if(UI()->ActiveItem() == s_pEditorID
)
1734 if(!UI()->MouseButton(0))
1736 s_Operation
= OP_NONE
;
1737 UI()->SetActiveItem(0);
1741 if(GetSelectedGroup() && GetSelectedGroup()->m_UseClipping
)
1743 CLayerGroup
*g
= m_Map
.m_pGameGroup
;
1746 Graphics()->TextureSet(-1);
1747 Graphics()->LinesBegin();
1750 r
.x
= GetSelectedGroup()->m_ClipX
;
1751 r
.y
= GetSelectedGroup()->m_ClipY
;
1752 r
.w
= GetSelectedGroup()->m_ClipW
;
1753 r
.h
= GetSelectedGroup()->m_ClipH
;
1755 IGraphics::CLineItem Array
[4] = {
1756 IGraphics::CLineItem(r
.x
, r
.y
, r
.x
+r
.w
, r
.y
),
1757 IGraphics::CLineItem(r
.x
+r
.w
, r
.y
, r
.x
+r
.w
, r
.y
+r
.h
),
1758 IGraphics::CLineItem(r
.x
+r
.w
, r
.y
+r
.h
, r
.x
, r
.y
+r
.h
),
1759 IGraphics::CLineItem(r
.x
, r
.y
+r
.h
, r
.x
, r
.y
)};
1760 Graphics()->SetColor(1,0,0,1);
1761 Graphics()->LinesDraw(Array
, 4);
1763 Graphics()->LinesEnd();
1766 // render screen sizes
1769 CLayerGroup
*g
= m_Map
.m_pGameGroup
;
1772 Graphics()->TextureSet(-1);
1773 Graphics()->LinesBegin();
1775 float aLastPoints
[4];
1776 float Start
= 1.0f
; //9.0f/16.0f;
1777 float End
= 16.0f
/9.0f
;
1778 const int NumSteps
= 20;
1779 for(int i
= 0; i
<= NumSteps
; i
++)
1782 float Aspect
= Start
+ (End
-Start
)*(i
/(float)NumSteps
);
1784 RenderTools()->MapscreenToWorld(
1785 m_WorldOffsetX
, m_WorldOffsetY
,
1786 1.0f
, 1.0f
, 0.0f
, 0.0f
, Aspect
, 1.0f
, aPoints
);
1790 IGraphics::CLineItem Array
[2] = {
1791 IGraphics::CLineItem(aPoints
[0], aPoints
[1], aPoints
[2], aPoints
[1]),
1792 IGraphics::CLineItem(aPoints
[0], aPoints
[3], aPoints
[2], aPoints
[3])};
1793 Graphics()->LinesDraw(Array
, 2);
1798 IGraphics::CLineItem Array
[4] = {
1799 IGraphics::CLineItem(aPoints
[0], aPoints
[1], aLastPoints
[0], aLastPoints
[1]),
1800 IGraphics::CLineItem(aPoints
[2], aPoints
[1], aLastPoints
[2], aLastPoints
[1]),
1801 IGraphics::CLineItem(aPoints
[0], aPoints
[3], aLastPoints
[0], aLastPoints
[3]),
1802 IGraphics::CLineItem(aPoints
[2], aPoints
[3], aLastPoints
[2], aLastPoints
[3])};
1803 Graphics()->LinesDraw(Array
, 4);
1808 IGraphics::CLineItem Array
[2] = {
1809 IGraphics::CLineItem(aPoints
[0], aPoints
[1], aPoints
[0], aPoints
[3]),
1810 IGraphics::CLineItem(aPoints
[2], aPoints
[1], aPoints
[2], aPoints
[3])};
1811 Graphics()->LinesDraw(Array
, 2);
1814 mem_copy(aLastPoints
, aPoints
, sizeof(aPoints
));
1819 Graphics()->SetColor(1,0,0,1);
1820 for(int i
= 0; i
< 2; i
++)
1823 float aAspects
[] = {4.0f
/3.0f
, 16.0f
/10.0f
, 5.0f
/4.0f
, 16.0f
/9.0f
};
1824 float Aspect
= aAspects
[i
];
1826 RenderTools()->MapscreenToWorld(
1827 m_WorldOffsetX
, m_WorldOffsetY
,
1828 1.0f
, 1.0f
, 0.0f
, 0.0f
, Aspect
, 1.0f
, aPoints
);
1833 r
.w
= aPoints
[2]-aPoints
[0];
1834 r
.h
= aPoints
[3]-aPoints
[1];
1836 IGraphics::CLineItem Array
[4] = {
1837 IGraphics::CLineItem(r
.x
, r
.y
, r
.x
+r
.w
, r
.y
),
1838 IGraphics::CLineItem(r
.x
+r
.w
, r
.y
, r
.x
+r
.w
, r
.y
+r
.h
),
1839 IGraphics::CLineItem(r
.x
+r
.w
, r
.y
+r
.h
, r
.x
, r
.y
+r
.h
),
1840 IGraphics::CLineItem(r
.x
, r
.y
+r
.h
, r
.x
, r
.y
)};
1841 Graphics()->LinesDraw(Array
, 4);
1842 Graphics()->SetColor(0,1,0,1);
1846 Graphics()->LinesEnd();
1849 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
1850 //UI()->ClipDisable();
1854 int CEditor::DoProperties(CUIRect
*pToolBox
, CProperty
*pProps
, int *pIDs
, int *pNewVal
)
1858 for(int i
= 0; pProps
[i
].m_pName
; i
++)
1861 pToolBox
->HSplitTop(13.0f
, &Slot
, pToolBox
);
1862 CUIRect Label
, Shifter
;
1863 Slot
.VSplitMid(&Label
, &Shifter
);
1864 Shifter
.HMargin(1.0f
, &Shifter
);
1865 UI()->DoLabel(&Label
, pProps
[i
].m_pName
, 10.0f
, -1, -1);
1867 if(pProps
[i
].m_Type
== PROPTYPE_INT_STEP
)
1872 Shifter
.VSplitRight(10.0f
, &Shifter
, &Inc
);
1873 Shifter
.VSplitLeft(10.0f
, &Dec
, &Shifter
);
1874 str_format(aBuf
, sizeof(aBuf
),"%d", pProps
[i
].m_Value
);
1875 RenderTools()->DrawUIRect(&Shifter
, vec4(1,1,1,0.5f
), 0, 0.0f
);
1876 UI()->DoLabel(&Shifter
, aBuf
, 10.0f
, 0, -1);
1878 if(DoButton_ButtonDec(&pIDs
[i
], 0, 0, &Dec
, 0, "Decrease"))
1880 *pNewVal
= pProps
[i
].m_Value
-1;
1883 if(DoButton_ButtonInc(((char *)&pIDs
[i
])+1, 0, 0, &Inc
, 0, "Increase"))
1885 *pNewVal
= pProps
[i
].m_Value
+1;
1889 else if(pProps
[i
].m_Type
== PROPTYPE_BOOL
)
1892 Shifter
.VSplitMid(&No
, &Yes
);
1893 if(DoButton_ButtonDec(&pIDs
[i
], "No", !pProps
[i
].m_Value
, &No
, 0, ""))
1898 if(DoButton_ButtonInc(((char *)&pIDs
[i
])+1, "Yes", pProps
[i
].m_Value
, &Yes
, 0, ""))
1904 else if(pProps
[i
].m_Type
== PROPTYPE_INT_SCROLL
)
1906 int NewValue
= UiDoValueSelector(&pIDs
[i
], &Shifter
, "", pProps
[i
].m_Value
, pProps
[i
].m_Min
, pProps
[i
].m_Max
, 1, 1.0f
, "Use left mouse button to drag and change the value. Hold shift to be more precise.");
1907 if(NewValue
!= pProps
[i
].m_Value
)
1909 *pNewVal
= NewValue
;
1913 else if(pProps
[i
].m_Type
== PROPTYPE_COLOR
)
1915 static const char *s_paTexts
[4] = {"R", "G", "B", "A"};
1916 static int s_aShift
[] = {24, 16, 8, 0};
1919 for(int c
= 0; c
< 4; c
++)
1921 int v
= (pProps
[i
].m_Value
>> s_aShift
[c
])&0xff;
1922 NewColor
|= UiDoValueSelector(((char *)&pIDs
[i
])+c
, &Shifter
, s_paTexts
[c
], v
, 0, 255, 1, 1.0f
, "Use left mouse button to drag and change the color value. Hold shift to be more precise.")<<s_aShift
[c
];
1926 pToolBox
->HSplitTop(13.0f
, &Slot
, pToolBox
);
1927 Slot
.VSplitMid(0, &Shifter
);
1928 Shifter
.HMargin(1.0f
, &Shifter
);
1932 if(NewColor
!= pProps
[i
].m_Value
)
1934 *pNewVal
= NewColor
;
1938 else if(pProps
[i
].m_Type
== PROPTYPE_IMAGE
)
1941 if(pProps
[i
].m_Value
< 0)
1942 str_copy(aBuf
, "None", sizeof(aBuf
));
1944 str_format(aBuf
, sizeof(aBuf
),"%s", m_Map
.m_lImages
[pProps
[i
].m_Value
]->m_aName
);
1946 if(DoButton_Editor(&pIDs
[i
], aBuf
, 0, &Shifter
, 0, 0))
1947 PopupSelectImageInvoke(pProps
[i
].m_Value
, UI()->MouseX(), UI()->MouseY());
1949 int r
= PopupSelectImageResult();
1956 else if(pProps
[i
].m_Type
== PROPTYPE_SHIFT
)
1958 CUIRect Left
, Right
, Up
, Down
;
1959 Shifter
.VSplitMid(&Left
, &Up
);
1960 Left
.VSplitRight(1.0f
, &Left
, 0);
1961 Up
.VSplitLeft(1.0f
, 0, &Up
);
1962 Left
.VSplitLeft(10.0f
, &Left
, &Shifter
);
1963 Shifter
.VSplitRight(10.0f
, &Shifter
, &Right
);
1964 RenderTools()->DrawUIRect(&Shifter
, vec4(1,1,1,0.5f
), 0, 0.0f
);
1965 UI()->DoLabel(&Shifter
, "X", 10.0f
, 0, -1);
1966 Up
.VSplitLeft(10.0f
, &Up
, &Shifter
);
1967 Shifter
.VSplitRight(10.0f
, &Shifter
, &Down
);
1968 RenderTools()->DrawUIRect(&Shifter
, vec4(1,1,1,0.5f
), 0, 0.0f
);
1969 UI()->DoLabel(&Shifter
, "Y", 10.0f
, 0, -1);
1970 if(DoButton_ButtonDec(&pIDs
[i
], "-", 0, &Left
, 0, "Left"))
1975 if(DoButton_ButtonInc(((char *)&pIDs
[i
])+3, "+", 0, &Right
, 0, "Right"))
1980 if(DoButton_ButtonDec(((char *)&pIDs
[i
])+1, "-", 0, &Up
, 0, "Up"))
1985 if(DoButton_ButtonInc(((char *)&pIDs
[i
])+2, "+", 0, &Down
, 0, "Down"))
1996 void CEditor::RenderLayers(CUIRect ToolBox
, CUIRect ToolBar
, CUIRect View
)
1998 CUIRect LayersBox
= ToolBox
;
2003 CUIRect Slot
, Button
;
2006 float LayersHeight
= 12.0f
; // Height of AddGroup button
2007 static int s_ScrollBar
= 0;
2008 static float s_ScrollValue
= 0;
2010 for(int g
= 0; g
< m_Map
.m_lGroups
.size(); g
++)
2012 // Each group is 19.0f
2013 // Each layer is 14.0f
2014 LayersHeight
+= 19.0f
;
2015 if(!m_Map
.m_lGroups
[g
]->m_Collapse
)
2016 LayersHeight
+= m_Map
.m_lGroups
[g
]->m_lLayers
.size() * 14.0f
;
2019 float ScrollDifference
= LayersHeight
- LayersBox
.h
;
2021 if(LayersHeight
> LayersBox
.h
) // Do we even need a scrollbar?
2024 LayersBox
.VSplitRight(15.0f
, &LayersBox
, &Scroll
);
2025 LayersBox
.VSplitRight(3.0f
, &LayersBox
, 0); // extra spacing
2026 Scroll
.HMargin(5.0f
, &Scroll
);
2027 s_ScrollValue
= UiDoScrollbarV(&s_ScrollBar
, &Scroll
, s_ScrollValue
);
2029 if(UI()->MouseInside(&Scroll
) || UI()->MouseInside(&LayersBox
))
2031 int ScrollNum
= (int)((LayersHeight
-LayersBox
.h
)/15.0f
)+1;
2034 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP
))
2035 s_ScrollValue
= clamp(s_ScrollValue
- 1.0f
/ScrollNum
, 0.0f
, 1.0f
);
2036 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN
))
2037 s_ScrollValue
= clamp(s_ScrollValue
+ 1.0f
/ScrollNum
, 0.0f
, 1.0f
);
2044 float LayerStartAt
= ScrollDifference
* s_ScrollValue
;
2045 if(LayerStartAt
< 0.0f
)
2046 LayerStartAt
= 0.0f
;
2048 float LayerStopAt
= LayersHeight
- ScrollDifference
* (1 - s_ScrollValue
);
2053 for(int g
= 0; g
< m_Map
.m_lGroups
.size(); g
++)
2055 if(LayerCur
> LayerStopAt
)
2057 else if(LayerCur
+ m_Map
.m_lGroups
[g
]->m_lLayers
.size() * 14.0f
+ 19.0f
< LayerStartAt
)
2059 LayerCur
+= m_Map
.m_lGroups
[g
]->m_lLayers
.size() * 14.0f
+ 19.0f
;
2063 CUIRect VisibleToggle
, SaveCheck
;
2064 if(LayerCur
>= LayerStartAt
)
2066 LayersBox
.HSplitTop(12.0f
, &Slot
, &LayersBox
);
2067 Slot
.VSplitLeft(12, &VisibleToggle
, &Slot
);
2068 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
))
2069 m_Map
.m_lGroups
[g
]->m_Visible
= !m_Map
.m_lGroups
[g
]->m_Visible
;
2071 Slot
.VSplitRight(12.0f
, &Slot
, &SaveCheck
);
2072 if(DoButton_Ex(&m_Map
.m_lGroups
[g
]->m_SaveToMap
, "S", m_Map
.m_lGroups
[g
]->m_SaveToMap
, &SaveCheck
, 0, "Enable/disable group for saving", CUI::CORNER_R
))
2073 if(!m_Map
.m_lGroups
[g
]->m_GameGroup
)
2074 m_Map
.m_lGroups
[g
]->m_SaveToMap
= !m_Map
.m_lGroups
[g
]->m_SaveToMap
;
2076 str_format(aBuf
, sizeof(aBuf
),"#%d %s", g
, m_Map
.m_lGroups
[g
]->m_aName
);
2077 float FontSize
= 10.0f
;
2078 while(TextRender()->TextWidth(0, FontSize
, aBuf
, -1) > Slot
.w
)
2080 if(int Result
= DoButton_Ex(&m_Map
.m_lGroups
[g
], aBuf
, g
==m_SelectedGroup
, &Slot
,
2081 BUTTON_CONTEXT
, m_Map
.m_lGroups
[g
]->m_Collapse
? "Select group. Double click to expand." : "Select group. Double click to collapse.", 0, FontSize
))
2083 m_SelectedGroup
= g
;
2084 m_SelectedLayer
= 0;
2086 static int s_GroupPopupId
= 0;
2088 UiInvokePopupMenu(&s_GroupPopupId
, 0, UI()->MouseX(), UI()->MouseY(), 145, 220, PopupGroup
);
2090 if(m_Map
.m_lGroups
[g
]->m_lLayers
.size() && Input()->MouseDoubleClick())
2091 m_Map
.m_lGroups
[g
]->m_Collapse
^= 1;
2093 LayersBox
.HSplitTop(2.0f
, &Slot
, &LayersBox
);
2097 for(int i
= 0; i
< m_Map
.m_lGroups
[g
]->m_lLayers
.size(); i
++)
2099 if(LayerCur
> LayerStopAt
)
2101 else if(LayerCur
< LayerStartAt
)
2107 if(m_Map
.m_lGroups
[g
]->m_Collapse
)
2111 LayersBox
.HSplitTop(12.0f
, &Slot
, &LayersBox
);
2112 Slot
.VSplitLeft(12.0f
, 0, &Button
);
2113 Button
.VSplitLeft(15, &VisibleToggle
, &Button
);
2115 if(DoButton_Ex(&m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_Visible
, m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_Visible
?"V":"H", 0, &VisibleToggle
, 0, "Toggle layer visibility", CUI::CORNER_L
))
2116 m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_Visible
= !m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_Visible
;
2118 Button
.VSplitRight(12.0f
, &Button
, &SaveCheck
);
2119 if(DoButton_Ex(&m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_SaveToMap
, "S", m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_SaveToMap
, &SaveCheck
, 0, "Enable/disable layer for saving", CUI::CORNER_R
))
2120 if(m_Map
.m_lGroups
[g
]->m_lLayers
[i
] != m_Map
.m_pGameLayer
)
2121 m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_SaveToMap
= !m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_SaveToMap
;
2123 if(m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_aName
[0])
2124 str_format(aBuf
, sizeof(aBuf
), "%s", m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_aName
);
2125 else if(m_Map
.m_lGroups
[g
]->m_lLayers
[i
]->m_Type
== LAYERTYPE_TILES
)
2126 str_copy(aBuf
, "Tiles", sizeof(aBuf
));
2128 str_copy(aBuf
, "Quads", sizeof(aBuf
));
2130 float FontSize
= 10.0f
;
2131 while(TextRender()->TextWidth(0, FontSize
, aBuf
, -1) > Button
.w
)
2133 if(int Result
= DoButton_Ex(m_Map
.m_lGroups
[g
]->m_lLayers
[i
], aBuf
, g
==m_SelectedGroup
&&i
==m_SelectedLayer
, &Button
,
2134 BUTTON_CONTEXT
, "Select layer.", 0, FontSize
))
2136 m_SelectedLayer
= i
;
2137 m_SelectedGroup
= g
;
2138 static int s_LayerPopupID
= 0;
2140 UiInvokePopupMenu(&s_LayerPopupID
, 0, UI()->MouseX(), UI()->MouseY(), 120, 245, PopupLayer
);
2144 LayersBox
.HSplitTop(2.0f
, &Slot
, &LayersBox
);
2146 if(LayerCur
> LayerStartAt
&& LayerCur
< LayerStopAt
)
2147 LayersBox
.HSplitTop(5.0f
, &Slot
, &LayersBox
);
2152 if(LayerCur
<= LayerStopAt
)
2154 LayersBox
.HSplitTop(12.0f
, &Slot
, &LayersBox
);
2156 static int s_NewGroupButton
= 0;
2157 if(DoButton_Editor(&s_NewGroupButton
, "Add group", 0, &Slot
, 0, "Adds a new group"))
2160 m_SelectedGroup
= m_Map
.m_lGroups
.size()-1;
2165 void CEditor::ReplaceImage(const char *pFileName
, int StorageType
, void *pUser
)
2167 CEditor
*pEditor
= (CEditor
*)pUser
;
2168 CEditorImage
ImgInfo(pEditor
);
2169 if(!pEditor
->Graphics()->LoadPNG(&ImgInfo
, pFileName
, StorageType
))
2172 CEditorImage
*pImg
= pEditor
->m_Map
.m_lImages
[pEditor
->m_SelectedImage
];
2173 int External
= pImg
->m_External
;
2174 pEditor
->Graphics()->UnloadTexture(pImg
->m_TexID
);
2176 pImg
->m_External
= External
;
2177 pEditor
->ExtractName(pFileName
, pImg
->m_aName
, sizeof(pImg
->m_aName
));
2178 pImg
->m_AutoMapper
.Load(pImg
->m_aName
);
2179 pImg
->m_TexID
= pEditor
->Graphics()->LoadTextureRaw(ImgInfo
.m_Width
, ImgInfo
.m_Height
, ImgInfo
.m_Format
, ImgInfo
.m_pData
, CImageInfo::FORMAT_AUTO
, 0);
2180 pEditor
->SortImages();
2181 for(int i
= 0; i
< pEditor
->m_Map
.m_lImages
.size(); ++i
)
2183 if(!str_comp(pEditor
->m_Map
.m_lImages
[i
]->m_aName
, pImg
->m_aName
))
2184 pEditor
->m_SelectedImage
= i
;
2186 pEditor
->m_Dialog
= DIALOG_NONE
;
2189 void CEditor::AddImage(const char *pFileName
, int StorageType
, void *pUser
)
2191 CEditor
*pEditor
= (CEditor
*)pUser
;
2192 CEditorImage
ImgInfo(pEditor
);
2193 if(!pEditor
->Graphics()->LoadPNG(&ImgInfo
, pFileName
, StorageType
))
2196 // check if we have that image already
2198 ExtractName(pFileName
, aBuf
, sizeof(aBuf
));
2199 for(int i
= 0; i
< pEditor
->m_Map
.m_lImages
.size(); ++i
)
2201 if(!str_comp(pEditor
->m_Map
.m_lImages
[i
]->m_aName
, aBuf
))
2205 CEditorImage
*pImg
= new CEditorImage(pEditor
);
2207 pImg
->m_TexID
= pEditor
->Graphics()->LoadTextureRaw(ImgInfo
.m_Width
, ImgInfo
.m_Height
, ImgInfo
.m_Format
, ImgInfo
.m_pData
, CImageInfo::FORMAT_AUTO
, 0);
2208 pImg
->m_External
= 1; // external by default
2209 str_copy(pImg
->m_aName
, aBuf
, sizeof(pImg
->m_aName
));
2210 pImg
->m_AutoMapper
.Load(pImg
->m_aName
);
2211 pEditor
->m_Map
.m_lImages
.add(pImg
);
2212 pEditor
->SortImages();
2213 if(pEditor
->m_SelectedImage
> -1 && pEditor
->m_SelectedImage
< pEditor
->m_Map
.m_lImages
.size())
2215 for(int i
= 0; i
<= pEditor
->m_SelectedImage
; ++i
)
2216 if(!str_comp(pEditor
->m_Map
.m_lImages
[i
]->m_aName
, aBuf
))
2218 pEditor
->m_SelectedImage
++;
2222 pEditor
->m_Dialog
= DIALOG_NONE
;
2226 static int gs_ModifyIndexDeletedIndex
;
2227 static void ModifyIndexDeleted(int *pIndex
)
2229 if(*pIndex
== gs_ModifyIndexDeletedIndex
)
2231 else if(*pIndex
> gs_ModifyIndexDeletedIndex
)
2232 *pIndex
= *pIndex
- 1;
2235 int CEditor::PopupImage(CEditor
*pEditor
, CUIRect View
)
2237 static int s_ReplaceButton
= 0;
2238 static int s_RemoveButton
= 0;
2241 View
.HSplitTop(2.0f
, &Slot
, &View
);
2242 View
.HSplitTop(12.0f
, &Slot
, &View
);
2243 CEditorImage
*pImg
= pEditor
->m_Map
.m_lImages
[pEditor
->m_SelectedImage
];
2245 static int s_ExternalButton
= 0;
2246 if(pImg
->m_External
)
2248 if(pEditor
->DoButton_MenuItem(&s_ExternalButton
, "Embed", 0, &Slot
, 0, "Embeds the image into the map file."))
2250 pImg
->m_External
= 0;
2256 if(pEditor
->DoButton_MenuItem(&s_ExternalButton
, "Make external", 0, &Slot
, 0, "Removes the image from the map file."))
2258 pImg
->m_External
= 1;
2263 View
.HSplitTop(10.0f
, &Slot
, &View
);
2264 View
.HSplitTop(12.0f
, &Slot
, &View
);
2265 if(pEditor
->DoButton_MenuItem(&s_ReplaceButton
, "Replace", 0, &Slot
, 0, "Replaces the image with a new one"))
2267 pEditor
->InvokeFileDialog(IStorage::TYPE_ALL
, FILETYPE_IMG
, "Replace Image", "Replace", "mapres", "", ReplaceImage
, pEditor
);
2271 View
.HSplitTop(10.0f
, &Slot
, &View
);
2272 View
.HSplitTop(12.0f
, &Slot
, &View
);
2273 if(pEditor
->DoButton_MenuItem(&s_RemoveButton
, "Remove", 0, &Slot
, 0, "Removes the image from the map"))
2276 pEditor
->m_Map
.m_lImages
.remove_index(pEditor
->m_SelectedImage
);
2277 gs_ModifyIndexDeletedIndex
= pEditor
->m_SelectedImage
;
2278 pEditor
->m_Map
.ModifyImageIndex(ModifyIndexDeleted
);
2285 static int CompareImageName(const void *pObject1
, const void *pObject2
)
2287 CEditorImage
*pImage1
= *(CEditorImage
**)pObject1
;
2288 CEditorImage
*pImage2
= *(CEditorImage
**)pObject2
;
2290 return str_comp(pImage1
->m_aName
, pImage2
->m_aName
);
2293 static int *gs_pSortedIndex
= 0;
2294 static void ModifySortedIndex(int *pIndex
)
2297 *pIndex
= gs_pSortedIndex
[*pIndex
];
2300 void CEditor::SortImages()
2303 for(int i
= 1; i
< m_Map
.m_lImages
.size(); i
++)
2304 if( str_comp(m_Map
.m_lImages
[i
]->m_aName
, m_Map
.m_lImages
[i
-1]->m_aName
) < 0 )
2312 array
<CEditorImage
*> lTemp
= array
<CEditorImage
*>(m_Map
.m_lImages
);
2313 gs_pSortedIndex
= new int[lTemp
.size()];
2315 qsort(m_Map
.m_lImages
.base_ptr(), m_Map
.m_lImages
.size(), sizeof(CEditorImage
*), CompareImageName
);
2317 for(int OldIndex
= 0; OldIndex
< lTemp
.size(); OldIndex
++)
2318 for(int NewIndex
= 0; NewIndex
< m_Map
.m_lImages
.size(); NewIndex
++)
2319 if(lTemp
[OldIndex
] == m_Map
.m_lImages
[NewIndex
])
2320 gs_pSortedIndex
[OldIndex
] = NewIndex
;
2322 m_Map
.ModifyImageIndex(ModifySortedIndex
);
2324 delete [] gs_pSortedIndex
;
2325 gs_pSortedIndex
= 0;
2330 void CEditor::RenderImages(CUIRect ToolBox
, CUIRect ToolBar
, CUIRect View
)
2332 static int s_ScrollBar
= 0;
2333 static float s_ScrollValue
= 0;
2334 float ImagesHeight
= 30.0f
+ 14.0f
* m_Map
.m_lImages
.size() + 27.0f
;
2335 float ScrollDifference
= ImagesHeight
- ToolBox
.h
;
2337 if(ImagesHeight
> ToolBox
.h
) // Do we even need a scrollbar?
2340 ToolBox
.VSplitRight(15.0f
, &ToolBox
, &Scroll
);
2341 ToolBox
.VSplitRight(3.0f
, &ToolBox
, 0); // extra spacing
2342 Scroll
.HMargin(5.0f
, &Scroll
);
2343 s_ScrollValue
= UiDoScrollbarV(&s_ScrollBar
, &Scroll
, s_ScrollValue
);
2345 if(UI()->MouseInside(&Scroll
) || UI()->MouseInside(&ToolBox
))
2347 int ScrollNum
= (int)((ImagesHeight
-ToolBox
.h
)/14.0f
)+1;
2350 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP
))
2351 s_ScrollValue
= clamp(s_ScrollValue
- 1.0f
/ScrollNum
, 0.0f
, 1.0f
);
2352 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN
))
2353 s_ScrollValue
= clamp(s_ScrollValue
+ 1.0f
/ScrollNum
, 0.0f
, 1.0f
);
2360 float ImageStartAt
= ScrollDifference
* s_ScrollValue
;
2361 if(ImageStartAt
< 0.0f
)
2362 ImageStartAt
= 0.0f
;
2364 float ImageStopAt
= ImagesHeight
- ScrollDifference
* (1 - s_ScrollValue
);
2365 float ImageCur
= 0.0f
;
2367 for(int e
= 0; e
< 2; e
++) // two passes, first embedded, then external
2371 if(ImageCur
> ImageStopAt
)
2373 else if(ImageCur
>= ImageStartAt
)
2376 ToolBox
.HSplitTop(15.0f
, &Slot
, &ToolBox
);
2378 UI()->DoLabel(&Slot
, "Embedded", 12.0f
, 0);
2380 UI()->DoLabel(&Slot
, "External", 12.0f
, 0);
2384 for(int i
= 0; i
< m_Map
.m_lImages
.size(); i
++)
2386 if((e
&& !m_Map
.m_lImages
[i
]->m_External
) ||
2387 (!e
&& m_Map
.m_lImages
[i
]->m_External
))
2392 if(ImageCur
> ImageStopAt
)
2394 else if(ImageCur
< ImageStartAt
)
2402 str_copy(aBuf
, m_Map
.m_lImages
[i
]->m_aName
, sizeof(aBuf
));
2403 ToolBox
.HSplitTop(12.0f
, &Slot
, &ToolBox
);
2405 if(int Result
= DoButton_Editor(&m_Map
.m_lImages
[i
], aBuf
, m_SelectedImage
== i
, &Slot
,
2406 BUTTON_CONTEXT
, "Select image"))
2408 m_SelectedImage
= i
;
2410 static int s_PopupImageID
= 0;
2412 UiInvokePopupMenu(&s_PopupImageID
, 0, UI()->MouseX(), UI()->MouseY(), 120, 80, PopupImage
);
2415 ToolBox
.HSplitTop(2.0f
, 0, &ToolBox
);
2418 if(m_SelectedImage
== i
)
2421 View
.Margin(10.0f
, &r
);
2426 float Max
= (float)(max(m_Map
.m_lImages
[i
]->m_Width
, m_Map
.m_lImages
[i
]->m_Height
));
2427 r
.w
*= m_Map
.m_lImages
[i
]->m_Width
/Max
;
2428 r
.h
*= m_Map
.m_lImages
[i
]->m_Height
/Max
;
2429 Graphics()->TextureSet(m_Map
.m_lImages
[i
]->m_TexID
);
2430 Graphics()->BlendNormal();
2431 Graphics()->QuadsBegin();
2432 IGraphics::CQuadItem
QuadItem(r
.x
, r
.y
, r
.w
, r
.h
);
2433 Graphics()->QuadsDrawTL(&QuadItem
, 1);
2434 Graphics()->QuadsEnd();
2440 ToolBox
.HSplitTop(5.0f
, &Slot
, &ToolBox
);
2442 IGraphics::CLineItem
LineItem(Slot
.x
, Slot
.y
+Slot
.h
/2, Slot
.x
+Slot
.w
, Slot
.y
+Slot
.h
/2);
2443 Graphics()->TextureSet(-1);
2444 Graphics()->LinesBegin();
2445 Graphics()->LinesDraw(&LineItem
, 1);
2446 Graphics()->LinesEnd();
2449 if(ImageCur
+ 27.0f
> ImageStopAt
)
2453 ToolBox
.HSplitTop(5.0f
, &Slot
, &ToolBox
);
2456 static int s_NewImageButton
= 0;
2457 ToolBox
.HSplitTop(12.0f
, &Slot
, &ToolBox
);
2458 if(DoButton_Editor(&s_NewImageButton
, "Add", 0, &Slot
, 0, "Load a new image to use in the map"))
2459 InvokeFileDialog(IStorage::TYPE_ALL
, FILETYPE_IMG
, "Add Image", "Add", "mapres", "", AddImage
, this);
2463 static int EditorListdirCallback(const char *pName
, int IsDir
, int StorageType
, void *pUser
)
2465 CEditor
*pEditor
= (CEditor
*)pUser
;
2466 int Length
= str_length(pName
);
2467 if((pName
[0] == '.' && (pName
[1] == 0 ||
2468 (pName
[1] == '.' && pName
[2] == 0 && (!str_comp(pEditor
->m_pFileDialogPath
, "maps") || !str_comp(pEditor
->m_pFileDialogPath
, "mapres"))))) ||
2469 (!IsDir
&& ((pEditor
->m_FileDialogFileType
== CEditor::FILETYPE_MAP
&& (Length
< 4 || str_comp(pName
+Length
-4, ".map"))) ||
2470 (pEditor
->m_FileDialogFileType
== CEditor::FILETYPE_IMG
&& (Length
< 4 || str_comp(pName
+Length
-4, ".png"))))))
2473 CEditor::CFilelistItem Item
;
2474 str_copy(Item
.m_aFilename
, pName
, sizeof(Item
.m_aFilename
));
2476 str_format(Item
.m_aName
, sizeof(Item
.m_aName
), "%s/", pName
);
2478 str_copy(Item
.m_aName
, pName
, min(static_cast<int>(sizeof(Item
.m_aName
)), Length
-3));
2479 Item
.m_IsDir
= IsDir
!= 0;
2480 Item
.m_IsLink
= false;
2481 Item
.m_StorageType
= StorageType
;
2482 pEditor
->m_FileList
.add(Item
);
2487 void CEditor::AddFileDialogEntry(int Index
, CUIRect
*pView
)
2490 if(m_FilesCur
-1 < m_FilesStartAt
|| m_FilesCur
>= m_FilesStopAt
)
2493 CUIRect Button
, FileIcon
;
2494 pView
->HSplitTop(15.0f
, &Button
, pView
);
2495 pView
->HSplitTop(2.0f
, 0, pView
);
2496 Button
.VSplitLeft(Button
.h
, &FileIcon
, &Button
);
2497 Button
.VSplitLeft(5.0f
, 0, &Button
);
2499 Graphics()->TextureSet(g_pData
->m_aImages
[IMAGE_FILEICONS
].m_Id
);
2500 Graphics()->QuadsBegin();
2501 RenderTools()->SelectSprite(m_FileList
[Index
].m_IsDir
?SPRITE_FILE_FOLDER
:SPRITE_FILE_MAP2
);
2502 IGraphics::CQuadItem
QuadItem(FileIcon
.x
, FileIcon
.y
, FileIcon
.w
, FileIcon
.h
);
2503 Graphics()->QuadsDrawTL(&QuadItem
, 1);
2504 Graphics()->QuadsEnd();
2506 if(DoButton_File(&m_FileList
[Index
], m_FileList
[Index
].m_aName
, m_FilesSelectedIndex
== Index
, &Button
, 0, 0))
2508 if(!m_FileList
[Index
].m_IsDir
)
2509 str_copy(m_aFileDialogFileName
, m_FileList
[Index
].m_aFilename
, sizeof(m_aFileDialogFileName
));
2511 m_aFileDialogFileName
[0] = 0;
2512 m_FilesSelectedIndex
= Index
;
2514 if(Input()->MouseDoubleClick())
2515 m_aFileDialogActivate
= true;
2519 void CEditor::RenderFileDialog()
2522 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
2523 CUIRect View
= *UI()->Screen();
2524 float Width
= View
.w
, Height
= View
.h
;
2526 RenderTools()->DrawUIRect(&View
, vec4(0,0,0,0.25f
), 0, 0);
2527 View
.VMargin(150.0f
, &View
);
2528 View
.HMargin(50.0f
, &View
);
2529 RenderTools()->DrawUIRect(&View
, vec4(0,0,0,0.75f
), CUI::CORNER_ALL
, 5.0f
);
2530 View
.Margin(10.0f
, &View
);
2532 CUIRect Title
, FileBox
, FileBoxLabel
, ButtonBar
, Scroll
;
2533 View
.HSplitTop(18.0f
, &Title
, &View
);
2534 View
.HSplitTop(5.0f
, 0, &View
); // some spacing
2535 View
.HSplitBottom(14.0f
, &View
, &ButtonBar
);
2536 View
.HSplitBottom(10.0f
, &View
, 0); // some spacing
2537 View
.HSplitBottom(14.0f
, &View
, &FileBox
);
2538 FileBox
.VSplitLeft(55.0f
, &FileBoxLabel
, &FileBox
);
2539 View
.HSplitBottom(10.0f
, &View
, 0); // some spacing
2540 View
.VSplitRight(15.0f
, &View
, &Scroll
);
2543 RenderTools()->DrawUIRect(&Title
, vec4(1, 1, 1, 0.25f
), CUI::CORNER_ALL
, 4.0f
);
2544 Title
.VMargin(10.0f
, &Title
);
2545 UI()->DoLabel(&Title
, m_pFileDialogTitle
, 12.0f
, -1, -1);
2548 if(m_FileDialogStorageType
== IStorage::TYPE_SAVE
)
2550 static float s_FileBoxID
= 0;
2551 UI()->DoLabel(&FileBoxLabel
, "Filename:", 10.0f
, -1, -1);
2552 if(DoEditBox(&s_FileBoxID
, &FileBox
, m_aFileDialogFileName
, sizeof(m_aFileDialogFileName
), 10.0f
, &s_FileBoxID
))
2554 // remove '/' and '\'
2555 for(int i
= 0; m_aFileDialogFileName
[i
]; ++i
)
2556 if(m_aFileDialogFileName
[i
] == '/' || m_aFileDialogFileName
[i
] == '\\')
2557 str_copy(&m_aFileDialogFileName
[i
], &m_aFileDialogFileName
[i
+1], (int)(sizeof(m_aFileDialogFileName
))-i
);
2558 m_FilesSelectedIndex
= -1;
2562 int Num
= (int)(View
.h
/17.0f
)+1;
2563 static int ScrollBar
= 0;
2564 Scroll
.HMargin(5.0f
, &Scroll
);
2565 m_FileDialogScrollValue
= UiDoScrollbarV(&ScrollBar
, &Scroll
, m_FileDialogScrollValue
);
2567 int ScrollNum
= m_FileList
.size()-Num
+1;
2570 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP
))
2571 m_FileDialogScrollValue
-= 3.0f
/ScrollNum
;
2572 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN
))
2573 m_FileDialogScrollValue
+= 3.0f
/ScrollNum
;
2578 if(m_FilesSelectedIndex
> -1)
2580 for(int i
= 0; i
< Input()->NumEvents(); i
++)
2583 if(Input()->GetEvent(i
).m_Flags
&IInput::FLAG_PRESS
)
2585 if(Input()->GetEvent(i
).m_Key
== KEY_DOWN
) NewIndex
= m_FilesSelectedIndex
+ 1;
2586 if(Input()->GetEvent(i
).m_Key
== KEY_UP
) NewIndex
= m_FilesSelectedIndex
- 1;
2588 if(NewIndex
> -1 && NewIndex
< m_FileList
.size())
2591 float IndexY
= View
.y
- m_FileDialogScrollValue
*ScrollNum
*17.0f
+ NewIndex
*17.0f
;
2592 int Scroll
= View
.y
> IndexY
? -1 : View
.y
+View
.h
< IndexY
+17.0f
? 1 : 0;
2596 m_FileDialogScrollValue
= ((float)(NewIndex
)+0.5f
)/ScrollNum
;
2598 m_FileDialogScrollValue
= ((float)(NewIndex
-Num
)+2.5f
)/ScrollNum
;
2601 if(!m_FileList
[NewIndex
].m_IsDir
)
2602 str_copy(m_aFileDialogFileName
, m_FileList
[NewIndex
].m_aFilename
, sizeof(m_aFileDialogFileName
));
2604 m_aFileDialogFileName
[0] = 0;
2605 m_FilesSelectedIndex
= NewIndex
;
2610 for(int i
= 0; i
< Input()->NumEvents(); i
++)
2612 if(Input()->GetEvent(i
).m_Flags
&IInput::FLAG_PRESS
)
2614 if(Input()->GetEvent(i
).m_Key
== KEY_RETURN
|| Input()->GetEvent(i
).m_Key
== KEY_KP_ENTER
)
2615 m_aFileDialogActivate
= true;
2619 if(m_FileDialogScrollValue
< 0) m_FileDialogScrollValue
= 0;
2620 if(m_FileDialogScrollValue
> 1) m_FileDialogScrollValue
= 1;
2622 m_FilesStartAt
= (int)(ScrollNum
*m_FileDialogScrollValue
);
2623 if(m_FilesStartAt
< 0)
2626 m_FilesStopAt
= m_FilesStartAt
+Num
;
2631 UI()->ClipEnable(&View
);
2633 for(int i
= 0; i
< m_FileList
.size(); i
++)
2634 AddFileDialogEntry(i
, &View
);
2636 // disable clipping again
2637 UI()->ClipDisable();
2640 static int s_OkButton
= 0;
2641 static int s_CancelButton
= 0;
2642 static int s_NewFolderButton
= 0;
2645 ButtonBar
.VSplitRight(50.0f
, &ButtonBar
, &Button
);
2646 bool IsDir
= m_FilesSelectedIndex
>= 0 && m_FileList
[m_FilesSelectedIndex
].m_IsDir
;
2647 if(DoButton_Editor(&s_OkButton
, IsDir
? "Open" : m_pFileDialogButtonText
, 0, &Button
, 0, 0) || m_aFileDialogActivate
)
2649 m_aFileDialogActivate
= false;
2652 if(str_comp(m_FileList
[m_FilesSelectedIndex
].m_aFilename
, "..") == 0) // parent folder
2654 if(fs_parent_dir(m_pFileDialogPath
))
2655 m_pFileDialogPath
= m_aFileDialogCurrentFolder
; // leave the link
2659 if(m_FileList
[m_FilesSelectedIndex
].m_IsLink
)
2661 m_pFileDialogPath
= m_aFileDialogCurrentLink
; // follow the link
2662 str_copy(m_aFileDialogCurrentLink
, m_FileList
[m_FilesSelectedIndex
].m_aFilename
, sizeof(m_aFileDialogCurrentLink
));
2666 char aTemp
[MAX_PATH_LENGTH
];
2667 str_copy(aTemp
, m_pFileDialogPath
, sizeof(aTemp
));
2668 str_format(m_pFileDialogPath
, MAX_PATH_LENGTH
, "%s/%s", aTemp
, m_FileList
[m_FilesSelectedIndex
].m_aFilename
);
2671 FilelistPopulate(!str_comp(m_pFileDialogPath
, "maps") || !str_comp(m_pFileDialogPath
, "mapres") ? m_FileDialogStorageType
:
2672 m_FileList
[m_FilesSelectedIndex
].m_StorageType
);
2673 if(m_FilesSelectedIndex
>= 0 && !m_FileList
[m_FilesSelectedIndex
].m_IsDir
)
2674 str_copy(m_aFileDialogFileName
, m_FileList
[m_FilesSelectedIndex
].m_aFilename
, sizeof(m_aFileDialogFileName
));
2676 m_aFileDialogFileName
[0] = 0;
2680 str_format(m_aFileSaveName
, sizeof(m_aFileSaveName
), "%s/%s", m_pFileDialogPath
, m_aFileDialogFileName
);
2681 if(!str_comp(m_pFileDialogButtonText
, "Save"))
2683 IOHANDLE File
= Storage()->OpenFile(m_aFileSaveName
, IOFLAG_READ
, IStorage::TYPE_SAVE
);
2687 m_PopupEventType
= POPEVENT_SAVE
;
2688 m_PopupEventActivated
= true;
2691 if(m_pfnFileDialogFunc
)
2692 m_pfnFileDialogFunc(m_aFileSaveName
, m_FilesSelectedIndex
>= 0 ? m_FileList
[m_FilesSelectedIndex
].m_StorageType
: m_FileDialogStorageType
, m_pFileDialogUser
);
2695 if(m_pfnFileDialogFunc
)
2696 m_pfnFileDialogFunc(m_aFileSaveName
, m_FilesSelectedIndex
>= 0 ? m_FileList
[m_FilesSelectedIndex
].m_StorageType
: m_FileDialogStorageType
, m_pFileDialogUser
);
2700 ButtonBar
.VSplitRight(40.0f
, &ButtonBar
, &Button
);
2701 ButtonBar
.VSplitRight(50.0f
, &ButtonBar
, &Button
);
2702 if(DoButton_Editor(&s_CancelButton
, "Cancel", 0, &Button
, 0, 0) || Input()->KeyPressed(KEY_ESCAPE
))
2703 m_Dialog
= DIALOG_NONE
;
2705 if(m_FileDialogStorageType
== IStorage::TYPE_SAVE
)
2707 ButtonBar
.VSplitLeft(40.0f
, 0, &ButtonBar
);
2708 ButtonBar
.VSplitLeft(70.0f
, &Button
, &ButtonBar
);
2709 if(DoButton_Editor(&s_NewFolderButton
, "New folder", 0, &Button
, 0, 0))
2711 m_FileDialogNewFolderName
[0] = 0;
2712 m_FileDialogErrString
[0] = 0;
2713 static int s_NewFolderPopupID
= 0;
2714 UiInvokePopupMenu(&s_NewFolderPopupID
, 0, Width
/2.0f
-200.0f
, Height
/2.0f
-100.0f
, 400.0f
, 200.0f
, PopupNewFolder
);
2715 UI()->SetActiveItem(0);
2720 void CEditor::FilelistPopulate(int StorageType
)
2723 if(m_FileDialogStorageType
!= IStorage::TYPE_SAVE
&& !str_comp(m_pFileDialogPath
, "maps"))
2726 str_copy(Item
.m_aFilename
, "downloadedmaps", sizeof(Item
.m_aFilename
));
2727 str_copy(Item
.m_aName
, "downloadedmaps/", sizeof(Item
.m_aName
));
2728 Item
.m_IsDir
= true;
2729 Item
.m_IsLink
= true;
2730 Item
.m_StorageType
= IStorage::TYPE_SAVE
;
2731 m_FileList
.add(Item
);
2733 Storage()->ListDirectory(StorageType
, m_pFileDialogPath
, EditorListdirCallback
, this);
2734 m_FilesSelectedIndex
= m_FileList
.size() ? 0 : -1;
2735 m_aFileDialogActivate
= false;
2738 void CEditor::InvokeFileDialog(int StorageType
, int FileType
, const char *pTitle
, const char *pButtonText
,
2739 const char *pBasePath
, const char *pDefaultName
,
2740 void (*pfnFunc
)(const char *pFileName
, int StorageType
, void *pUser
), void *pUser
)
2742 m_FileDialogStorageType
= StorageType
;
2743 m_pFileDialogTitle
= pTitle
;
2744 m_pFileDialogButtonText
= pButtonText
;
2745 m_pfnFileDialogFunc
= pfnFunc
;
2746 m_pFileDialogUser
= pUser
;
2747 m_aFileDialogFileName
[0] = 0;
2748 m_aFileDialogCurrentFolder
[0] = 0;
2749 m_aFileDialogCurrentLink
[0] = 0;
2750 m_pFileDialogPath
= m_aFileDialogCurrentFolder
;
2751 m_FileDialogFileType
= FileType
;
2752 m_FileDialogScrollValue
= 0.0f
;
2755 str_copy(m_aFileDialogFileName
, pDefaultName
, sizeof(m_aFileDialogFileName
));
2757 str_copy(m_aFileDialogCurrentFolder
, pBasePath
, sizeof(m_aFileDialogCurrentFolder
));
2759 FilelistPopulate(m_FileDialogStorageType
);
2761 m_Dialog
= DIALOG_FILE
;
2766 void CEditor::RenderModebar(CUIRect View
)
2772 View
.VSplitLeft(65.0f
, &Button
, &View
);
2773 Button
.HSplitTop(30.0f
, 0, &Button
);
2774 static int s_Button
= 0;
2775 const char *pButName
= m_Mode
== MODE_LAYERS
? "Layers" : "Images";
2776 if(DoButton_Tab(&s_Button
, pButName
, 0, &Button
, 0, "Switch between images and layers managment."))
2778 if(m_Mode
== MODE_LAYERS
)
2779 m_Mode
= MODE_IMAGES
;
2781 m_Mode
= MODE_LAYERS
;
2785 View
.VSplitLeft(5.0f
, 0, &View
);
2788 void CEditor::RenderStatusbar(CUIRect View
)
2791 View
.VSplitRight(60.0f
, &View
, &Button
);
2792 static int s_EnvelopeButton
= 0;
2793 if(DoButton_Editor(&s_EnvelopeButton
, "Envelopes", m_ShowEnvelopeEditor
, &Button
, 0, "Toggles the envelope editor."))
2794 m_ShowEnvelopeEditor
= (m_ShowEnvelopeEditor
+1)%4;
2798 if(ms_pUiGotContext
&& ms_pUiGotContext
== UI()->HotItem())
2801 str_format(aBuf
, sizeof(aBuf
), "%s Right click for context menu.", m_pTooltip
);
2802 UI()->DoLabel(&View
, aBuf
, 10.0f
, -1, -1);
2805 UI()->DoLabel(&View
, m_pTooltip
, 10.0f
, -1, -1);
2809 void CEditor::RenderEnvelopeEditor(CUIRect View
)
2811 if(m_SelectedEnvelope
< 0) m_SelectedEnvelope
= 0;
2812 if(m_SelectedEnvelope
>= m_Map
.m_lEnvelopes
.size()) m_SelectedEnvelope
= m_Map
.m_lEnvelopes
.size()-1;
2814 CEnvelope
*pEnvelope
= 0;
2815 if(m_SelectedEnvelope
>= 0 && m_SelectedEnvelope
< m_Map
.m_lEnvelopes
.size())
2816 pEnvelope
= m_Map
.m_lEnvelopes
[m_SelectedEnvelope
];
2818 CUIRect ToolBar
, CurveBar
, ColorBar
;
2819 View
.HSplitTop(15.0f
, &ToolBar
, &View
);
2820 View
.HSplitTop(15.0f
, &CurveBar
, &View
);
2821 ToolBar
.Margin(2.0f
, &ToolBar
);
2822 CurveBar
.Margin(2.0f
, &CurveBar
);
2827 CEnvelope
*pNewEnv
= 0;
2829 ToolBar
.VSplitRight(50.0f
, &ToolBar
, &Button
);
2830 static int s_New4dButton
= 0;
2831 if(DoButton_Editor(&s_New4dButton
, "Color+", 0, &Button
, 0, "Creates a new color envelope"))
2833 m_Map
.m_Modified
= true;
2834 pNewEnv
= m_Map
.NewEnvelope(4);
2837 ToolBar
.VSplitRight(5.0f
, &ToolBar
, &Button
);
2838 ToolBar
.VSplitRight(50.0f
, &ToolBar
, &Button
);
2839 static int s_New2dButton
= 0;
2840 if(DoButton_Editor(&s_New2dButton
, "Pos.+", 0, &Button
, 0, "Creates a new pos envelope"))
2842 m_Map
.m_Modified
= true;
2843 pNewEnv
= m_Map
.NewEnvelope(3);
2847 if(m_SelectedEnvelope
>= 0)
2849 ToolBar
.VSplitRight(10.0f
, &ToolBar
, &Button
);
2850 ToolBar
.VSplitRight(50.0f
, &ToolBar
, &Button
);
2851 static int s_DelButton
= 0;
2852 if(DoButton_Editor(&s_DelButton
, "Delete", 0, &Button
, 0, "Delete this envelope"))
2854 m_Map
.m_Modified
= true;
2855 m_Map
.DeleteEnvelope(m_SelectedEnvelope
);
2856 if(m_SelectedEnvelope
>= m_Map
.m_lEnvelopes
.size())
2857 m_SelectedEnvelope
= m_Map
.m_lEnvelopes
.size()-1;
2858 pEnvelope
= m_SelectedEnvelope
>= 0 ? m_Map
.m_lEnvelopes
[m_SelectedEnvelope
] : 0;
2862 if(pNewEnv
) // add the default points
2864 if(pNewEnv
->m_Channels
== 4)
2866 pNewEnv
->AddPoint(0, 1,1,1,1);
2867 pNewEnv
->AddPoint(1000, 1,1,1,1);
2871 pNewEnv
->AddPoint(0, 0);
2872 pNewEnv
->AddPoint(1000, 0);
2876 CUIRect Shifter
, Inc
, Dec
;
2877 ToolBar
.VSplitLeft(60.0f
, &Shifter
, &ToolBar
);
2878 Shifter
.VSplitRight(15.0f
, &Shifter
, &Inc
);
2879 Shifter
.VSplitLeft(15.0f
, &Dec
, &Shifter
);
2881 str_format(aBuf
, sizeof(aBuf
),"%d/%d", m_SelectedEnvelope
+1, m_Map
.m_lEnvelopes
.size());
2882 RenderTools()->DrawUIRect(&Shifter
, vec4(1,1,1,0.5f
), 0, 0.0f
);
2883 UI()->DoLabel(&Shifter
, aBuf
, 10.0f
, 0, -1);
2885 static int s_PrevButton
= 0;
2886 if(DoButton_ButtonDec(&s_PrevButton
, 0, 0, &Dec
, 0, "Previous Envelope"))
2887 m_SelectedEnvelope
--;
2889 static int s_NextButton
= 0;
2890 if(DoButton_ButtonInc(&s_NextButton
, 0, 0, &Inc
, 0, "Next Envelope"))
2891 m_SelectedEnvelope
++;
2895 ToolBar
.VSplitLeft(15.0f
, &Button
, &ToolBar
);
2896 ToolBar
.VSplitLeft(35.0f
, &Button
, &ToolBar
);
2897 UI()->DoLabel(&Button
, "Name:", 10.0f
, -1, -1);
2899 ToolBar
.VSplitLeft(80.0f
, &Button
, &ToolBar
);
2901 static float s_NameBox
= 0;
2902 if(DoEditBox(&s_NameBox
, &Button
, pEnvelope
->m_aName
, sizeof(pEnvelope
->m_aName
), 10.0f
, &s_NameBox
))
2903 m_Map
.m_Modified
= true;
2907 bool ShowColorBar
= false;
2908 if(pEnvelope
&& pEnvelope
->m_Channels
== 4)
2910 ShowColorBar
= true;
2911 View
.HSplitTop(20.0f
, &ColorBar
, &View
);
2912 ColorBar
.Margin(2.0f
, &ColorBar
);
2913 RenderBackground(ColorBar
, ms_CheckerTexture
, 16.0f
, 1.0f
);
2916 RenderBackground(View
, ms_CheckerTexture
, 32.0f
, 0.1f
);
2920 static array
<int> Selection
;
2921 static int sEnvelopeEditorID
= 0;
2922 static int s_ActiveChannels
= 0xf;
2928 ToolBar
.VSplitLeft(15.0f
, &Button
, &ToolBar
);
2930 static const char *s_paNames
[2][4] = {
2931 {"X", "Y", "R", ""},
2932 {"R", "G", "B", "A"},
2935 const char *paDescriptions
[2][4] = {
2936 {"X-axis of the envelope", "Y-axis of the envelope", "Rotation of the envelope", ""},
2937 {"Red value of the envelope", "Green value of the envelope", "Blue value of the envelope", "Alpha value of the envelope"},
2940 static int s_aChannelButtons
[4] = {0};
2942 //ui_draw_button_func draw_func;
2944 for(int i
= 0; i
< pEnvelope
->m_Channels
; i
++, Bit
<<=1)
2946 ToolBar
.VSplitLeft(15.0f
, &Button
, &ToolBar
);
2948 /*if(i == 0) draw_func = draw_editor_button_l;
2949 else if(i == envelope->channels-1) draw_func = draw_editor_button_r;
2950 else draw_func = draw_editor_button_m;*/
2952 if(DoButton_Editor(&s_aChannelButtons
[i
], s_paNames
[pEnvelope
->m_Channels
-3][i
], s_ActiveChannels
&Bit
, &Button
, 0, paDescriptions
[pEnvelope
->m_Channels
-3][i
]))
2953 s_ActiveChannels
^= Bit
;
2957 float EndTime
= pEnvelope
->EndTime();
2961 pEnvelope
->FindTopBottom(s_ActiveChannels
);
2962 float Top
= pEnvelope
->m_Top
;
2963 float Bottom
= pEnvelope
->m_Bottom
;
2970 float TimeScale
= EndTime
/View
.w
;
2971 float ValueScale
= (Top
-Bottom
)/View
.h
;
2973 if(UI()->MouseInside(&View
))
2974 UI()->SetHotItem(&sEnvelopeEditorID
);
2976 if(UI()->HotItem() == &sEnvelopeEditorID
)
2981 if(UI()->MouseButtonClicked(1))
2984 int Time
= (int)(((UI()->MouseX()-View
.x
)*TimeScale
)*1000.0f
);
2985 //float env_y = (UI()->MouseY()-view.y)/TimeScale;
2987 pEnvelope
->Eval(Time
, aChannels
);
2988 pEnvelope
->AddPoint(Time
,
2989 f2fx(aChannels
[0]), f2fx(aChannels
[1]),
2990 f2fx(aChannels
[2]), f2fx(aChannels
[3]));
2991 m_Map
.m_Modified
= true;
2994 m_pTooltip
= "Press right mouse button to create a new point";
2998 vec3 aColors
[] = {vec3(1,0.2f
,0.2f
), vec3(0.2f
,1,0.2f
), vec3(0.2f
,0.2f
,1), vec3(1,1,0.2f
)};
3002 UI()->ClipEnable(&View
);
3003 Graphics()->TextureSet(-1);
3004 Graphics()->LinesBegin();
3005 for(int c
= 0; c
< pEnvelope
->m_Channels
; c
++)
3007 if(s_ActiveChannels
&(1<<c
))
3008 Graphics()->SetColor(aColors
[c
].r
,aColors
[c
].g
,aColors
[c
].b
,1);
3010 Graphics()->SetColor(aColors
[c
].r
*0.5f
,aColors
[c
].g
*0.5f
,aColors
[c
].b
*0.5f
,1);
3014 pEnvelope
->Eval(0.000001f
, aResults
);
3015 float PrevValue
= aResults
[c
];
3017 int Steps
= (int)((View
.w
/UI()->Screen()->w
) * Graphics()->ScreenWidth());
3018 for(int i
= 1; i
<= Steps
; i
++)
3020 float a
= i
/(float)Steps
;
3021 pEnvelope
->Eval(a
*EndTime
, aResults
);
3022 float v
= aResults
[c
];
3023 v
= (v
-Bottom
)/(Top
-Bottom
);
3025 IGraphics::CLineItem
LineItem(View
.x
+ PrevX
*View
.w
, View
.y
+View
.h
- PrevValue
*View
.h
, View
.x
+ a
*View
.w
, View
.y
+View
.h
- v
*View
.h
);
3026 Graphics()->LinesDraw(&LineItem
, 1);
3031 Graphics()->LinesEnd();
3032 UI()->ClipDisable();
3035 // render curve options
3037 for(int i
= 0; i
< pEnvelope
->m_lPoints
.size()-1; i
++)
3039 float t0
= pEnvelope
->m_lPoints
[i
].m_Time
/1000.0f
/EndTime
;
3040 float t1
= pEnvelope
->m_lPoints
[i
+1].m_Time
/1000.0f
/EndTime
;
3042 //dbg_msg("", "%f", end_time);
3045 v
.x
= CurveBar
.x
+ (t0
+(t1
-t0
)*0.5f
) * CurveBar
.w
;
3050 void *pID
= &pEnvelope
->m_lPoints
[i
].m_Curvetype
;
3051 const char *paTypeName
[] = {
3052 "N", "L", "S", "F", "M"
3055 if(DoButton_Editor(pID
, paTypeName
[pEnvelope
->m_lPoints
[i
].m_Curvetype
], 0, &v
, 0, "Switch curve type"))
3056 pEnvelope
->m_lPoints
[i
].m_Curvetype
= (pEnvelope
->m_lPoints
[i
].m_Curvetype
+1)%NUM_CURVETYPES
;
3063 Graphics()->TextureSet(-1);
3064 Graphics()->QuadsBegin();
3065 for(int i
= 0; i
< pEnvelope
->m_lPoints
.size()-1; i
++)
3067 float r0
= fx2f(pEnvelope
->m_lPoints
[i
].m_aValues
[0]);
3068 float g0
= fx2f(pEnvelope
->m_lPoints
[i
].m_aValues
[1]);
3069 float b0
= fx2f(pEnvelope
->m_lPoints
[i
].m_aValues
[2]);
3070 float a0
= fx2f(pEnvelope
->m_lPoints
[i
].m_aValues
[3]);
3071 float r1
= fx2f(pEnvelope
->m_lPoints
[i
+1].m_aValues
[0]);
3072 float g1
= fx2f(pEnvelope
->m_lPoints
[i
+1].m_aValues
[1]);
3073 float b1
= fx2f(pEnvelope
->m_lPoints
[i
+1].m_aValues
[2]);
3074 float a1
= fx2f(pEnvelope
->m_lPoints
[i
+1].m_aValues
[3]);
3076 IGraphics::CColorVertex Array
[4] = {IGraphics::CColorVertex(0, r0
, g0
, b0
, a0
),
3077 IGraphics::CColorVertex(1, r1
, g1
, b1
, a1
),
3078 IGraphics::CColorVertex(2, r1
, g1
, b1
, a1
),
3079 IGraphics::CColorVertex(3, r0
, g0
, b0
, a0
)};
3080 Graphics()->SetColorVertex(Array
, 4);
3082 float x0
= pEnvelope
->m_lPoints
[i
].m_Time
/1000.0f
/EndTime
;
3083 // float y0 = (fx2f(envelope->points[i].values[c])-bottom)/(top-bottom);
3084 float x1
= pEnvelope
->m_lPoints
[i
+1].m_Time
/1000.0f
/EndTime
;
3085 //float y1 = (fx2f(envelope->points[i+1].values[c])-bottom)/(top-bottom);
3087 v
.x
= ColorBar
.x
+ x0
*ColorBar
.w
;
3089 v
.w
= (x1
-x0
)*ColorBar
.w
;
3092 IGraphics::CQuadItem
QuadItem(v
.x
, v
.y
, v
.w
, v
.h
);
3093 Graphics()->QuadsDrawTL(&QuadItem
, 1);
3095 Graphics()->QuadsEnd();
3100 int CurrentValue
= 0, CurrentTime
= 0;
3102 Graphics()->TextureSet(-1);
3103 Graphics()->QuadsBegin();
3104 for(int c
= 0; c
< pEnvelope
->m_Channels
; c
++)
3106 if(!(s_ActiveChannels
&(1<<c
)))
3109 for(int i
= 0; i
< pEnvelope
->m_lPoints
.size(); i
++)
3111 float x0
= pEnvelope
->m_lPoints
[i
].m_Time
/1000.0f
/EndTime
;
3112 float y0
= (fx2f(pEnvelope
->m_lPoints
[i
].m_aValues
[c
])-Bottom
)/(Top
-Bottom
);
3114 Final
.x
= View
.x
+ x0
*View
.w
;
3115 Final
.y
= View
.y
+View
.h
- y0
*View
.h
;
3121 void *pID
= &pEnvelope
->m_lPoints
[i
].m_aValues
[c
];
3123 if(UI()->MouseInside(&Final
))
3124 UI()->SetHotItem(pID
);
3126 float ColorMod
= 1.0f
;
3128 if(UI()->ActiveItem() == pID
)
3130 if(!UI()->MouseButton(0))
3132 UI()->SetActiveItem(0);
3136 if(Input()->KeyPressed(KEY_LSHIFT
) || Input()->KeyPressed(KEY_RSHIFT
))
3140 if((Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
)))
3141 pEnvelope
->m_lPoints
[i
].m_Time
+= (int)((m_MouseDeltaX
));
3143 pEnvelope
->m_lPoints
[i
].m_Time
+= (int)((m_MouseDeltaX
*TimeScale
)*1000.0f
);
3144 if(pEnvelope
->m_lPoints
[i
].m_Time
< pEnvelope
->m_lPoints
[i
-1].m_Time
)
3145 pEnvelope
->m_lPoints
[i
].m_Time
= pEnvelope
->m_lPoints
[i
-1].m_Time
+ 1;
3146 if(i
+1 != pEnvelope
->m_lPoints
.size() && pEnvelope
->m_lPoints
[i
].m_Time
> pEnvelope
->m_lPoints
[i
+1].m_Time
)
3147 pEnvelope
->m_lPoints
[i
].m_Time
= pEnvelope
->m_lPoints
[i
+1].m_Time
- 1;
3152 if((Input()->KeyPressed(KEY_LCTRL
) || Input()->KeyPressed(KEY_RCTRL
)))
3153 pEnvelope
->m_lPoints
[i
].m_aValues
[c
] -= f2fx(m_MouseDeltaY
*0.001f
);
3155 pEnvelope
->m_lPoints
[i
].m_aValues
[c
] -= f2fx(m_MouseDeltaY
*ValueScale
);
3157 m_Map
.m_Modified
= true;
3161 Graphics()->SetColor(1,1,1,1);
3163 else if(UI()->HotItem() == pID
)
3165 if(UI()->MouseButton(0))
3169 UI()->SetActiveItem(pID
);
3173 if(UI()->MouseButtonClicked(1))
3175 pEnvelope
->m_lPoints
.remove_index(i
);
3176 m_Map
.m_Modified
= true;
3180 Graphics()->SetColor(1,0.75f
,0.75f
,1);
3181 m_pTooltip
= "Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete.";
3184 if(UI()->ActiveItem() == pID
|| UI()->HotItem() == pID
)
3186 CurrentTime
= pEnvelope
->m_lPoints
[i
].m_Time
;
3187 CurrentValue
= pEnvelope
->m_lPoints
[i
].m_aValues
[c
];
3190 Graphics()->SetColor(aColors
[c
].r
*ColorMod
, aColors
[c
].g
*ColorMod
, aColors
[c
].b
*ColorMod
, 1.0f
);
3191 IGraphics::CQuadItem
QuadItem(Final
.x
, Final
.y
, Final
.w
, Final
.h
);
3192 Graphics()->QuadsDrawTL(&QuadItem
, 1);
3195 Graphics()->QuadsEnd();
3198 str_format(aBuf
, sizeof(aBuf
),"%.3f %.3f", CurrentTime
/1000.0f
, fx2f(CurrentValue
));
3199 UI()->DoLabel(&ToolBar
, aBuf
, 10.0f
, 0, -1);
3204 int CEditor::PopupMenuFile(CEditor
*pEditor
, CUIRect View
)
3206 static int s_NewMapButton
= 0;
3207 static int s_SaveButton
= 0;
3208 static int s_SaveAsButton
= 0;
3209 static int s_OpenButton
= 0;
3210 static int s_AppendButton
= 0;
3211 static int s_ExitButton
= 0;
3214 View
.HSplitTop(2.0f
, &Slot
, &View
);
3215 View
.HSplitTop(12.0f
, &Slot
, &View
);
3216 if(pEditor
->DoButton_MenuItem(&s_NewMapButton
, "New", 0, &Slot
, 0, "Creates a new map"))
3218 if(pEditor
->HasUnsavedData())
3220 pEditor
->m_PopupEventType
= POPEVENT_NEW
;
3221 pEditor
->m_PopupEventActivated
= true;
3226 pEditor
->m_aFileName
[0] = 0;
3231 View
.HSplitTop(10.0f
, &Slot
, &View
);
3232 View
.HSplitTop(12.0f
, &Slot
, &View
);
3233 if(pEditor
->DoButton_MenuItem(&s_OpenButton
, "Load", 0, &Slot
, 0, "Opens a map for editing"))
3235 if(pEditor
->HasUnsavedData())
3237 pEditor
->m_PopupEventType
= POPEVENT_LOAD
;
3238 pEditor
->m_PopupEventActivated
= true;
3241 pEditor
->InvokeFileDialog(IStorage::TYPE_ALL
, FILETYPE_MAP
, "Load map", "Load", "maps", "", pEditor
->CallbackOpenMap
, pEditor
);
3245 View
.HSplitTop(10.0f
, &Slot
, &View
);
3246 View
.HSplitTop(12.0f
, &Slot
, &View
);
3247 if(pEditor
->DoButton_MenuItem(&s_AppendButton
, "Append", 0, &Slot
, 0, "Opens a map and adds everything from that map to the current one"))
3249 pEditor
->InvokeFileDialog(IStorage::TYPE_ALL
, FILETYPE_MAP
, "Append map", "Append", "maps", "", pEditor
->CallbackAppendMap
, pEditor
);
3253 View
.HSplitTop(10.0f
, &Slot
, &View
);
3254 View
.HSplitTop(12.0f
, &Slot
, &View
);
3255 if(pEditor
->DoButton_MenuItem(&s_SaveButton
, "Save", 0, &Slot
, 0, "Saves the current map"))
3257 if(pEditor
->m_aFileName
[0] && pEditor
->m_ValidSaveFilename
)
3259 str_copy(pEditor
->m_aFileSaveName
, pEditor
->m_aFileName
, sizeof(pEditor
->m_aFileSaveName
));
3260 pEditor
->m_PopupEventType
= POPEVENT_SAVE
;
3261 pEditor
->m_PopupEventActivated
= true;
3264 pEditor
->InvokeFileDialog(IStorage::TYPE_SAVE
, FILETYPE_MAP
, "Save map", "Save", "maps", "", pEditor
->CallbackSaveMap
, pEditor
);
3268 View
.HSplitTop(2.0f
, &Slot
, &View
);
3269 View
.HSplitTop(12.0f
, &Slot
, &View
);
3270 if(pEditor
->DoButton_MenuItem(&s_SaveAsButton
, "Save As", 0, &Slot
, 0, "Saves the current map under a new name"))
3272 pEditor
->InvokeFileDialog(IStorage::TYPE_SAVE
, FILETYPE_MAP
, "Save map", "Save", "maps", "", pEditor
->CallbackSaveMap
, pEditor
);
3276 View
.HSplitTop(10.0f
, &Slot
, &View
);
3277 View
.HSplitTop(12.0f
, &Slot
, &View
);
3278 if(pEditor
->DoButton_MenuItem(&s_ExitButton
, "Exit", 0, &Slot
, 0, "Exits from the editor"))
3280 if(pEditor
->HasUnsavedData())
3282 pEditor
->m_PopupEventType
= POPEVENT_EXIT
;
3283 pEditor
->m_PopupEventActivated
= true;
3286 g_Config
.m_ClEditor
= 0;
3293 void CEditor::RenderMenubar(CUIRect MenuBar
)
3295 static CUIRect s_File
/*, view, help*/;
3297 MenuBar
.VSplitLeft(60.0f
, &s_File
, &MenuBar
);
3298 if(DoButton_Menu(&s_File
, "File", 0, &s_File
, 0, 0))
3299 UiInvokePopupMenu(&s_File
, 1, s_File
.x
, s_File
.y
+s_File
.h
-1.0f
, 120, 150, PopupMenuFile
, this);
3302 menubar.VSplitLeft(5.0f, 0, &menubar);
3303 menubar.VSplitLeft(60.0f, &view, &menubar);
3304 if(do_editor_button(&view, "View", 0, &view, draw_editor_button_menu, 0, 0))
3307 menubar.VSplitLeft(5.0f, 0, &menubar);
3308 menubar.VSplitLeft(60.0f, &help, &menubar);
3309 if(do_editor_button(&help, "Help", 0, &help, draw_editor_button_menu, 0, 0))
3313 MenuBar
.VSplitLeft(40.0f
, 0, &MenuBar
);
3315 str_format(aBuf
, sizeof(aBuf
), "File: %s", m_aFileName
);
3316 UI()->DoLabel(&MenuBar
, aBuf
, 10.0f
, -1, -1);
3319 void CEditor::Render()
3322 Graphics()->Clear(1.0f
, 0.0f
, 1.0f
);
3323 CUIRect View
= *UI()->Screen();
3324 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
3326 float Width
= View
.w
;
3327 float Height
= View
.h
;
3333 RenderBackground(View
, ms_CheckerTexture
, 32.0f
, 1.0f
);
3335 CUIRect MenuBar
, CModeBar
, ToolBar
, StatusBar
, EnvelopeEditor
, ToolBox
;
3336 m_ShowPicker
= Input()->KeyPressed(KEY_SPACE
) != 0 && m_Dialog
== DIALOG_NONE
;
3341 View
.HSplitTop(16.0f
, &MenuBar
, &View
);
3342 View
.HSplitTop(53.0f
, &ToolBar
, &View
);
3343 View
.VSplitLeft(100.0f
, &ToolBox
, &View
);
3344 View
.HSplitBottom(16.0f
, &View
, &StatusBar
);
3346 if(m_ShowEnvelopeEditor
&& !m_ShowPicker
)
3348 float size
= 125.0f
;
3349 if(m_ShowEnvelopeEditor
== 2)
3351 else if(m_ShowEnvelopeEditor
== 3)
3353 View
.HSplitBottom(size
, &View
, &EnvelopeEditor
);
3357 // a little hack for now
3358 if(m_Mode
== MODE_LAYERS
)
3359 DoMapEditor(View
, ToolBar
);
3362 if(m_Dialog
== DIALOG_NONE
&& UI()->MouseInside(&View
))
3364 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP
))
3367 if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN
))
3370 m_ZoomLevel
= clamp(m_ZoomLevel
, 50, 2000);
3375 float Brightness
= 0.25f
;
3376 RenderBackground(MenuBar
, ms_BackgroundTexture
, 128.0f
, Brightness
*0);
3377 MenuBar
.Margin(2.0f
, &MenuBar
);
3379 RenderBackground(ToolBox
, ms_BackgroundTexture
, 128.0f
, Brightness
);
3380 ToolBox
.Margin(2.0f
, &ToolBox
);
3382 RenderBackground(ToolBar
, ms_BackgroundTexture
, 128.0f
, Brightness
);
3383 ToolBar
.Margin(2.0f
, &ToolBar
);
3384 ToolBar
.VSplitLeft(100.0f
, &CModeBar
, &ToolBar
);
3386 RenderBackground(StatusBar
, ms_BackgroundTexture
, 128.0f
, Brightness
);
3387 StatusBar
.Margin(2.0f
, &StatusBar
);
3390 if(m_Mode
== MODE_LAYERS
)
3393 if(m_ShowEnvelopeEditor
)
3395 RenderBackground(EnvelopeEditor
, ms_BackgroundTexture
, 128.0f
, Brightness
);
3396 EnvelopeEditor
.Margin(2.0f
, &EnvelopeEditor
);
3401 if(m_Mode
== MODE_LAYERS
)
3402 RenderLayers(ToolBox
, ToolBar
, View
);
3403 else if(m_Mode
== MODE_IMAGES
)
3404 RenderImages(ToolBox
, ToolBar
, View
);
3406 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
3410 RenderMenubar(MenuBar
);
3412 RenderModebar(CModeBar
);
3413 if(m_ShowEnvelopeEditor
)
3414 RenderEnvelopeEditor(EnvelopeEditor
);
3417 if(m_Dialog
== DIALOG_FILE
)
3419 static int s_NullUiTarget
= 0;
3420 UI()->SetHotItem(&s_NullUiTarget
);
3424 if(m_PopupEventActivated
)
3426 static int s_PopupID
= 0;
3427 UiInvokePopupMenu(&s_PopupID
, 0, Width
/2.0f
-200.0f
, Height
/2.0f
-100.0f
, 400.0f
, 200.0f
, PopupEvent
);
3428 m_PopupEventActivated
= false;
3429 m_PopupEventWasActivated
= true;
3436 RenderStatusbar(StatusBar
);
3439 if(g_Config
.m_EdShowkeys
)
3441 Graphics()->MapScreen(UI()->Screen()->x
, UI()->Screen()->y
, UI()->Screen()->w
, UI()->Screen()->h
);
3443 TextRender()->SetCursor(&Cursor
, View
.x
+10, View
.y
+View
.h
-24-10, 24.0f
, TEXTFLAG_RENDER
);
3446 for(int i
= 0; i
< KEY_LAST
; i
++)
3448 if(Input()->KeyPressed(i
))
3451 TextRender()->TextEx(&Cursor
, " + ", -1);
3452 TextRender()->TextEx(&Cursor
, Input()->KeyName(i
), -1);
3458 if(m_ShowMousePointer
)
3460 // render butt ugly mouse cursor
3461 float mx
= UI()->MouseX();
3462 float my
= UI()->MouseY();
3463 Graphics()->TextureSet(ms_CursorTexture
);
3464 Graphics()->QuadsBegin();
3465 if(ms_pUiGotContext
== UI()->HotItem())
3466 Graphics()->SetColor(1,0,0,1);
3467 IGraphics::CQuadItem
QuadItem(mx
,my
, 16.0f
, 16.0f
);
3468 Graphics()->QuadsDrawTL(&QuadItem
, 1);
3469 Graphics()->QuadsEnd();
3473 void CEditor::Reset(bool CreateDefault
)
3477 // create default layers
3479 m_Map
.CreateDefault(ms_EntitiesTexture
);
3485 m_SelectedLayer
= 0;
3486 m_SelectedGroup
= 0;
3487 m_SelectedQuad
= -1;
3488 m_SelectedPoints
= 0;
3489 m_SelectedEnvelope
= 0;
3490 m_SelectedImage
= 0;
3494 m_EditorOffsetX
= 0.0f
;
3495 m_EditorOffsetY
= 0.0f
;
3505 m_Map
.m_Modified
= false;
3508 int CEditor::GetLineDistance()
3510 int LineDistance
= 512;
3512 if(m_ZoomLevel
<= 100)
3514 else if(m_ZoomLevel
<= 250)
3516 else if(m_ZoomLevel
<= 450)
3518 else if(m_ZoomLevel
<= 850)
3520 else if(m_ZoomLevel
<= 1550)
3523 return LineDistance
;
3526 void CEditorMap::DeleteEnvelope(int Index
)
3528 if(Index
< 0 || Index
>= m_lEnvelopes
.size())
3533 // fix links between envelopes and quads
3534 for(int i
= 0; i
< m_lGroups
.size(); ++i
)
3535 for(int j
= 0; j
< m_lGroups
[i
]->m_lLayers
.size(); ++j
)
3536 if(m_lGroups
[i
]->m_lLayers
[j
]->m_Type
== LAYERTYPE_QUADS
)
3538 CLayerQuads
*Layer
= static_cast<CLayerQuads
*>(m_lGroups
[i
]->m_lLayers
[j
]);
3539 for(int k
= 0; k
< Layer
->m_lQuads
.size(); ++k
)
3541 if(Layer
->m_lQuads
[k
].m_PosEnv
== Index
)
3542 Layer
->m_lQuads
[k
].m_PosEnv
= -1;
3543 else if(Layer
->m_lQuads
[k
].m_PosEnv
> Index
)
3544 Layer
->m_lQuads
[k
].m_PosEnv
--;
3545 if(Layer
->m_lQuads
[k
].m_ColorEnv
== Index
)
3546 Layer
->m_lQuads
[k
].m_ColorEnv
= -1;
3547 else if(Layer
->m_lQuads
[k
].m_ColorEnv
> Index
)
3548 Layer
->m_lQuads
[k
].m_ColorEnv
--;
3552 m_lEnvelopes
.remove_index(Index
);
3555 void CEditorMap::MakeGameLayer(CLayer
*pLayer
)
3557 m_pGameLayer
= (CLayerGame
*)pLayer
;
3558 m_pGameLayer
->m_pEditor
= m_pEditor
;
3559 m_pGameLayer
->m_TexID
= m_pEditor
->ms_EntitiesTexture
;
3562 void CEditorMap::MakeGameGroup(CLayerGroup
*pGroup
)
3564 m_pGameGroup
= pGroup
;
3565 m_pGameGroup
->m_GameGroup
= true;
3566 str_copy(m_pGameGroup
->m_aName
, "Game", sizeof(m_pGameGroup
->m_aName
));
3571 void CEditorMap::Clean()
3573 m_lGroups
.delete_all();
3574 m_lEnvelopes
.delete_all();
3575 m_lImages
.delete_all();
3583 void CEditorMap::CreateDefault(int EntitiesTexture
)
3586 CLayerGroup
*pGroup
= NewGroup();
3587 pGroup
->m_ParallaxX
= 0;
3588 pGroup
->m_ParallaxY
= 0;
3589 CLayerQuads
*pLayer
= new CLayerQuads
;
3590 pLayer
->m_pEditor
= m_pEditor
;
3591 CQuad
*pQuad
= pLayer
->NewQuad();
3592 const int Width
= 800000;
3593 const int Height
= 600000;
3594 pQuad
->m_aPoints
[0].x
= pQuad
->m_aPoints
[2].x
= -Width
;
3595 pQuad
->m_aPoints
[1].x
= pQuad
->m_aPoints
[3].x
= Width
;
3596 pQuad
->m_aPoints
[0].y
= pQuad
->m_aPoints
[1].y
= -Height
;
3597 pQuad
->m_aPoints
[2].y
= pQuad
->m_aPoints
[3].y
= Height
;
3598 pQuad
->m_aColors
[0].r
= pQuad
->m_aColors
[1].r
= 94;
3599 pQuad
->m_aColors
[0].g
= pQuad
->m_aColors
[1].g
= 132;
3600 pQuad
->m_aColors
[0].b
= pQuad
->m_aColors
[1].b
= 174;
3601 pQuad
->m_aColors
[2].r
= pQuad
->m_aColors
[3].r
= 204;
3602 pQuad
->m_aColors
[2].g
= pQuad
->m_aColors
[3].g
= 232;
3603 pQuad
->m_aColors
[2].b
= pQuad
->m_aColors
[3].b
= 255;
3604 pGroup
->AddLayer(pLayer
);
3607 MakeGameGroup(NewGroup());
3608 MakeGameLayer(new CLayerGame(50, 50));
3609 m_pGameGroup
->AddLayer(m_pGameLayer
);
3612 void CEditor::Init()
3614 m_pInput
= Kernel()->RequestInterface
<IInput
>();
3615 m_pClient
= Kernel()->RequestInterface
<IClient
>();
3616 m_pConsole
= Kernel()->RequestInterface
<IConsole
>();
3617 m_pGraphics
= Kernel()->RequestInterface
<IGraphics
>();
3618 m_pTextRender
= Kernel()->RequestInterface
<ITextRender
>();
3619 m_pStorage
= Kernel()->RequestInterface
<IStorage
>();
3620 m_RenderTools
.m_pGraphics
= m_pGraphics
;
3621 m_RenderTools
.m_pUI
= &m_UI
;
3622 m_UI
.SetGraphics(m_pGraphics
, m_pTextRender
);
3623 m_Map
.m_pEditor
= this;
3625 ms_CheckerTexture
= Graphics()->LoadTexture("editor/checker.png", IStorage::TYPE_ALL
, CImageInfo::FORMAT_AUTO
, 0);
3626 ms_BackgroundTexture
= Graphics()->LoadTexture("editor/background.png", IStorage::TYPE_ALL
, CImageInfo::FORMAT_AUTO
, 0);
3627 ms_CursorTexture
= Graphics()->LoadTexture("editor/cursor.png", IStorage::TYPE_ALL
, CImageInfo::FORMAT_AUTO
, 0);
3628 ms_EntitiesTexture
= Graphics()->LoadTexture("editor/entities.png", IStorage::TYPE_ALL
, CImageInfo::FORMAT_AUTO
, 0);
3630 m_TilesetPicker
.m_pEditor
= this;
3631 m_TilesetPicker
.MakePalette();
3632 m_TilesetPicker
.m_Readonly
= true;
3634 m_Brush
.m_pMap
= &m_Map
;
3637 m_Map
.m_Modified
= false;
3640 void CEditor::DoMapBorder()
3642 CLayerTiles
*pT
= (CLayerTiles
*)GetSelectedLayerType(0, LAYERTYPE_TILES
);
3644 for(int i
= 0; i
< pT
->m_Width
*2; ++i
)
3645 pT
->m_pTiles
[i
].m_Index
= 1;
3647 for(int i
= 0; i
< pT
->m_Width
*pT
->m_Height
; ++i
)
3649 if(i
%pT
->m_Width
< 2 || i
%pT
->m_Width
> pT
->m_Width
-3)
3650 pT
->m_pTiles
[i
].m_Index
= 1;
3653 for(int i
= (pT
->m_Width
*(pT
->m_Height
-2)); i
< pT
->m_Width
*pT
->m_Height
; ++i
)
3654 pT
->m_pTiles
[i
].m_Index
= 1;
3657 void CEditor::UpdateAndRender()
3659 static float s_MouseX
= 0.0f
;
3660 static float s_MouseY
= 0.0f
;
3663 m_AnimateTime
= (time_get()-m_AnimateStart
)/(float)time_freq();
3666 ms_pUiGotContext
= 0;
3668 // handle mouse movement
3669 float mx
, my
, Mwx
, Mwy
;
3672 Input()->MouseRelative(&rx
, &ry
);
3673 UI()->ConvertMouseMove(&rx
, &ry
);
3683 s_MouseX
= clamp(s_MouseX
, 0.0f
, UI()->Screen()->w
);
3684 s_MouseY
= clamp(s_MouseY
, 0.0f
, UI()->Screen()->h
);
3692 // fix correct world x and y
3693 CLayerGroup
*g
= GetSelectedGroup();
3697 g
->Mapping(aPoints
);
3699 float WorldWidth
= aPoints
[2]-aPoints
[0];
3700 float WorldHeight
= aPoints
[3]-aPoints
[1];
3702 Mwx
= aPoints
[0] + WorldWidth
* (s_MouseX
/UI()->Screen()->w
);
3703 Mwy
= aPoints
[1] + WorldHeight
* (s_MouseY
/UI()->Screen()->h
);
3704 m_MouseDeltaWx
= m_MouseDeltaX
*(WorldWidth
/ UI()->Screen()->w
);
3705 m_MouseDeltaWy
= m_MouseDeltaY
*(WorldHeight
/ UI()->Screen()->h
);
3709 if(Input()->KeyPressed(KEY_MOUSE_1
)) Buttons
|= 1;
3710 if(Input()->KeyPressed(KEY_MOUSE_2
)) Buttons
|= 2;
3711 if(Input()->KeyPressed(KEY_MOUSE_3
)) Buttons
|= 4;
3713 UI()->Update(mx
,my
,Mwx
,Mwy
,Buttons
);
3717 if(Input()->KeyDown(KEY_TAB
))
3718 m_GuiActive
= !m_GuiActive
;
3720 if(Input()->KeyDown(KEY_F10
))
3721 m_ShowMousePointer
= false;
3725 if(Input()->KeyDown(KEY_F10
))
3727 Graphics()->TakeScreenshot(0);
3728 m_ShowMousePointer
= true;
3731 Input()->ClearEvents();
3734 IEditor
*CreateEditor() { return new CEditor
; }