2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
8 #include "AllComponents.hpp"
9 #include "CompBase.hpp"
11 #include "WindowCreateParams.hpp"
12 #include "ConsoleCommands/Console.hpp"
13 #include "ConsoleCommands/Console_Lua.hpp"
14 #include "ConsoleCommands/ConsoleInterpreter.hpp"
15 #include "MaterialSystem/Material.hpp"
16 #include "MaterialSystem/Mesh.hpp"
17 #include "MaterialSystem/Renderer.hpp"
18 #include "Network/State.hpp"
19 #include "OpenGL/OpenGLWindow.hpp" // Just for the Ca*EventT classes...
21 #include "TypeSys.hpp"
22 #include "UniScriptState.hpp"
35 using namespace cf::GuiSys
;
38 // Note that we cannot simply replace this method with a global TypeInfoManT instance,
39 // because it is called during global static initialization time. The TIM instance being
40 // embedded in the function guarantees that it is properly initialized before first use.
41 cf::TypeSys::TypeInfoManT
& cf::GuiSys::GetGuiTIM()
43 static cf::TypeSys::TypeInfoManT TIM
;
49 const char* GuiImplT::DocClass
=
50 "This class holds the hierarchy of windows that together form a GUI.";
53 GuiImplT::InitErrorT::InitErrorT(const std::string
& Message
)
54 : std::runtime_error(Message
)
59 /*static*/ void GuiImplT::InitScriptState(cf::UniScriptStateT
& ScriptState
)
61 lua_State
* LuaState
= ScriptState
.GetLuaState();
63 // Load the console library. (Adds a global table with name "Console" to the LuaState with the functions of the ConsoleI interface.)
64 cf::Console_RegisterLua(LuaState
);
66 // Load the "ci" (console interpreter) library. (Adds a global table with name "ci" to the LuaState with (some of) the functions of the ConsoleInterpreterI interface.)
67 ConsoleInterpreterI::RegisterLua(LuaState
);
69 // For each class that the TypeInfoManTs know about, add a (meta-)table to the registry of the LuaState.
70 // The (meta-)table holds the Lua methods that the respective class implements in C++,
71 // and is to be used as metatable for instances of this class.
72 ScriptBinderT
Binder(LuaState
);
74 Binder
.Init(GetGuiTIM());
75 Binder
.Init(GetWindowTIM());
76 Binder
.Init(GetComponentTIM());
80 GuiImplT::GuiImplT(cf::UniScriptStateT
& ScriptState
, GuiResourcesT
& GuiRes
)
82 m_ScriptState(&ScriptState
),
83 m_IsOwnScriptSt(false),
88 m_GuiResources(GuiRes
),
91 MouseOverWindow(NULL
),
96 MousePosX(VIRTUAL_SCREEN_SIZE_X
/2.0f
), // 320.0f
97 MousePosY(VIRTUAL_SCREEN_SIZE_Y
/2.0f
), // 240.0f
98 m_MouseCursorSize(20.0f
),
104 GuiImplT::GuiImplT(GuiResourcesT
& GuiRes
)
106 m_ScriptState(new UniScriptStateT()),
107 m_IsOwnScriptSt(true),
109 m_GuiDefaultRM(NULL
),
110 m_GuiPointerRM(NULL
),
111 m_GuiFinishZRM(NULL
),
112 m_GuiResources(GuiRes
),
115 MouseOverWindow(NULL
),
120 MousePosX(VIRTUAL_SCREEN_SIZE_X
/2.0f
), // 320.0f
121 MousePosY(VIRTUAL_SCREEN_SIZE_Y
/2.0f
), // 240.0f
122 m_MouseCursorSize(20.0f
),
125 InitScriptState(*m_ScriptState
);
129 void GuiImplT::LoadScript(const std::string
& GuiScriptName
, int Flags
)
131 ScriptName
= (Flags
& InitFlag_InlineCode
) ? "" : GuiScriptName
;
133 if ((Flags
& InitFlag_InlineCode
) == 0)
135 std::string s
=cf::String::StripExt(GuiScriptName
);
137 if (cf::String::EndsWith(s
, "_main") || cf::String::EndsWith(s
, "_init"))
138 s
=std::string(s
, 0, s
.length()-5);
140 /*ArrayT<MaterialT*> AllMats=*/m_MaterialMan
.RegisterMaterialScript(s
+".cmat", cf::String::GetPath(GuiScriptName
)+"/");
143 if (!m_MaterialMan
.HasMaterial("Gui/Default"))
145 // This material has either not been defined in the .cmat file, or we're dealing with inline code.
148 Mat
.Name
="Gui/Default";
149 Mat
.UseMeshColors
=true;
150 Mat
.BlendFactorSrc
=MaterialT::SrcAlpha
;
151 Mat
.BlendFactorDst
=MaterialT::OneMinusSrcAlpha
;
152 Mat
.AmbientMask
[4]=false;
154 m_MaterialMan
.RegisterMaterial(Mat
);
157 if (!m_MaterialMan
.HasMaterial("Gui/Cursors/Pointer"))
159 // This material has either not been defined in the .cmat file, or we're dealing with inline code.
162 Mat
.Name
="Gui/Cursors/Pointer";
163 // Mat.DiffMapComp =...;
164 Mat
.UseMeshColors
=true;
165 Mat
.BlendFactorSrc
=MaterialT::SrcAlpha
;
166 Mat
.BlendFactorDst
=MaterialT::OneMinusSrcAlpha
;
168 m_MaterialMan
.RegisterMaterial(Mat
);
171 if (!m_MaterialMan
.HasMaterial("Gui/FinishZ"))
173 // This material has either not been defined in the .cmat file, or we're dealing with inline code.
176 Mat
.Name
="Gui/FinishZ";
177 // Mat.DiffMapComp =...;
178 Mat
.UseMeshColors
=true;
179 Mat
.AmbientMask
[0]=false;
180 Mat
.AmbientMask
[1]=false;
181 Mat
.AmbientMask
[2]=false;
182 Mat
.AmbientMask
[3]=false;
184 m_MaterialMan
.RegisterMaterial(Mat
);
187 MatSys::Renderer
->FreeMaterial(m_GuiDefaultRM
); // It shouldn't happen, but LoadScript() might still be called multiple times.
188 MatSys::Renderer
->FreeMaterial(m_GuiPointerRM
);
189 MatSys::Renderer
->FreeMaterial(m_GuiFinishZRM
);
191 m_GuiDefaultRM
= MatSys::Renderer
->RegisterMaterial(m_MaterialMan
.GetMaterial("Gui/Default"));
192 m_GuiPointerRM
= MatSys::Renderer
->RegisterMaterial(m_MaterialMan
.GetMaterial("Gui/Cursors/Pointer"));
193 m_GuiFinishZRM
= MatSys::Renderer
->RegisterMaterial(m_MaterialMan
.GetMaterial("Gui/FinishZ"));
196 const std::string
PrintScriptName((Flags
& InitFlag_InlineCode
) ? "<inline code>" : GuiScriptName
);
197 lua_State
* LuaState
= GetScriptState().GetLuaState();
198 ScriptBinderT
Binder(LuaState
);
200 // Load the user script!
201 const int LoadResult
= (Flags
& InitFlag_InlineCode
) ? luaL_loadstring(LuaState
, GuiScriptName
.c_str())
202 : luaL_loadfile (LuaState
, GuiScriptName
.c_str());
206 const std::string Msg
= "Could not load \"" + PrintScriptName
+ "\":\n" + lua_tostring(LuaState
, -1);
208 lua_pop(LuaState
, 1);
209 Console
->Warning(Msg
+ "\n");
211 // The LuaState will be closed by the m_ScriptState.
212 throw InitErrorT(Msg
);
215 // This is the parameter for the lua_pcall().
216 // Script code will fetch it via the "..." ellipsis operator like this:
218 Binder
.Push(IntrusivePtrT
<GuiImplT
>(this));
220 if (lua_pcall(LuaState
, 1, 0, 0) != 0)
222 const std::string Msg
= "Could not load \"" + PrintScriptName
+ "\":\n" + lua_tostring(LuaState
, -1);
224 lua_pop(LuaState
, 1);
225 Console
->Warning(Msg
+ "\n");
227 // The LuaState will be closed by the m_ScriptState.
228 throw InitErrorT(Msg
);
231 if (RootWindow
== NULL
)
233 const std::string Msg
= "No root window set for GUI \"" + PrintScriptName
+ "\".";
235 Console
->Warning(Msg
+ "\n");
237 // The LuaState will be closed by the m_ScriptState.
238 throw InitErrorT(Msg
);
241 // Make sure that everyone dealt properly with the Lua stack so far.
242 assert(lua_gettop(LuaState
)==0);
245 // Finally call the Lua OnInit() and OnInit2() methods of each window.
246 ArrayT
< IntrusivePtrT
<WindowT
> > AllChildren
;
248 AllChildren
.PushBack(RootWindow
);
249 RootWindow
->GetChildren(AllChildren
, true);
251 Init(); // The script has the option to call this itself (via gui:Init()) at an earlier time.
253 for (unsigned long ChildNr
=0; ChildNr
<AllChildren
.Size(); ChildNr
++)
255 // The OnInit2() methods contain custom, hand-written code by the user (*_main.cgui files).
256 AllChildren
[ChildNr
]->CallLuaMethod("OnInit2");
258 // Let each component know that the "static" part of initialization is now complete.
259 const ArrayT
< IntrusivePtrT
<ComponentBaseT
> >& Components
= AllChildren
[ChildNr
]->GetComponents();
261 for (unsigned int CompNr
= 0; CompNr
< Components
.Size(); CompNr
++)
262 Components
[CompNr
]->OnPostLoad((Flags
& InitFlag_InGuiEditor
) != 0);
266 // Make sure that everyone dealt properly with the Lua stack so far.
267 assert(lua_gettop(LuaState
)==0);
271 GuiImplT::~GuiImplT()
273 // Manually "destruct" these references before the Lua state (m_ScriptState).
274 // This is redundant: the normal member destruction sequence achieves the same.
277 MouseOverWindow
=NULL
;
279 // Free the render materials.
280 MatSys::Renderer
->FreeMaterial(m_GuiDefaultRM
);
281 MatSys::Renderer
->FreeMaterial(m_GuiPointerRM
);
282 MatSys::Renderer
->FreeMaterial(m_GuiFinishZRM
);
286 delete m_ScriptState
;
287 m_ScriptState
= NULL
;
292 void GuiImplT::ObsoleteForceKill()
294 assert(m_IsOwnScriptSt
);
298 delete m_ScriptState
;
299 m_ScriptState
= NULL
;
304 void GuiImplT::Init()
306 if (m_IsInited
) return;
308 ArrayT
< IntrusivePtrT
<WindowT
> > AllChildren
;
310 AllChildren
.PushBack(RootWindow
);
311 RootWindow
->GetChildren(AllChildren
, true);
313 for (unsigned long ChildNr
= 0; ChildNr
< AllChildren
.Size(); ChildNr
++)
315 // The OnInit() methods are automatically written by the Cafu GUI editor (*_init.cgui files).
316 AllChildren
[ChildNr
]->CallLuaMethod("OnInit");
323 MatSys::RenderMaterialT
* GuiImplT::GetDefaultRM() const
325 return m_GuiDefaultRM
;
329 MatSys::RenderMaterialT
* GuiImplT::GetPointerRM() const
331 return m_GuiPointerRM
;
335 const std::string
& GuiImplT::GetScriptName() const
341 IntrusivePtrT
<WindowT
> GuiImplT::GetRootWindow() const
347 IntrusivePtrT
<WindowT
> GuiImplT::GetFocusWindow() const
353 void GuiImplT::Activate(bool doActivate
)
357 // Call the OnActivate() or OnDeactivate() methods of all windows.
358 ArrayT
< IntrusivePtrT
<WindowT
> > AllChildren
;
360 AllChildren
.PushBack(RootWindow
);
361 RootWindow
->GetChildren(AllChildren
, true);
363 for (unsigned long ChildNr
=0; ChildNr
<AllChildren
.Size(); ChildNr
++)
364 AllChildren
[ChildNr
]->CallLuaMethod(IsActive
? "OnActivate" : "OnDeactivate");
368 void GuiImplT::SetInteractive(bool IsInteractive_
)
370 IsInteractive
=IsInteractive_
;
374 void GuiImplT::GetMousePos(float& MousePosX_
, float& MousePosY_
) const
376 MousePosX_
=MousePosX
;
377 MousePosY_
=MousePosY
;
381 void GuiImplT::SetMousePos(float MousePosX_
, float MousePosY_
)
383 MousePosX
=MousePosX_
;
384 MousePosY
=MousePosY_
;
387 // Clip the mouse position to valid coordinates.
388 if (MousePosX
<0.0f
) MousePosX
=0.0;
389 if (MousePosX
>VIRTUAL_SCREEN_SIZE_X
) MousePosX
=VIRTUAL_SCREEN_SIZE_X
;
391 if (MousePosY
<0.0f
) MousePosY
=0.0;
392 if (MousePosY
>VIRTUAL_SCREEN_SIZE_Y
) MousePosY
=VIRTUAL_SCREEN_SIZE_Y
;
395 // Determine if the mouse cursor has been moved into (or "over") another window,
396 // that is, see if we have to run any OnMouseLeave() and OnMouseEnter() scripts.
397 IntrusivePtrT
<WindowT
> Win
=RootWindow
->Find(Vector2fT(MousePosX
, MousePosY
));
399 if (Win
!= MouseOverWindow
)
401 if (MouseOverWindow
!= NULL
) MouseOverWindow
->CallLuaMethod("OnMouseLeave");
402 MouseOverWindow
= Win
;
403 if (MouseOverWindow
!= NULL
) MouseOverWindow
->CallLuaMethod("OnMouseEnter");
408 void GuiImplT::SetShowMouse(bool ShowMouse_
)
410 MouseIsShown
=ShowMouse_
;
414 // Note that this method is the twin of Deserialize(), whose implementation it must match.
415 void GuiImplT::Serialize(cf::Network::OutStreamT
& Stream
) const
421 Stream
<< m_MouseCursorSize
;
423 RootWindow
->Serialize(Stream
, true /*WithChildren*/);
427 // Note that this method is the twin of Serialize(), whose implementation it must match.
428 void GuiImplT::Deserialize(cf::Network::InStreamT
& Stream
, bool IsIniting
)
434 Stream
>> m_MouseCursorSize
;
436 RootWindow
->Deserialize(Stream
, IsIniting
);
440 void GuiImplT::Render(bool zLayerCoating
) const
442 RootWindow
->Render();
444 static MatSys::MeshT
Mesh(MatSys::MeshT::TriangleFan
);
446 if (Mesh
.Vertices
.Size()<4)
448 Mesh
.Vertices
.PushBackEmpty(4);
450 for (unsigned long VNr
=0; VNr
<Mesh
.Vertices
.Size(); VNr
++)
452 Mesh
.Vertices
[VNr
].SetColor(1.0f
, 1.0f
, 1.0f
, 1.0f
);
453 Mesh
.Vertices
[VNr
].SetTextureCoord(VNr
==0 || VNr
==3 ? 0.0f
: 1.0f
, VNr
<2 ? 0.0f
: 1.0f
);
459 Mesh
.Vertices
[0].SetOrigin(MousePosX
, MousePosY
);
460 Mesh
.Vertices
[1].SetOrigin(MousePosX
+m_MouseCursorSize
, MousePosY
);
461 Mesh
.Vertices
[2].SetOrigin(MousePosX
+m_MouseCursorSize
, MousePosY
+m_MouseCursorSize
);
462 Mesh
.Vertices
[3].SetOrigin(MousePosX
, MousePosY
+m_MouseCursorSize
);
464 MatSys::Renderer
->SetCurrentMaterial(m_GuiPointerRM
);
465 MatSys::Renderer
->RenderMesh(Mesh
);
470 // Finish by applying a z-layer coating to the GUI screen.
471 // This is important whenever the z-ordering of scene elements can be imperfect, e.g. in the Map Editor.
472 Mesh
.Vertices
[0].SetOrigin( 0.0f
, 0.0f
);
473 Mesh
.Vertices
[1].SetOrigin(640.0f
, 0.0f
);
474 Mesh
.Vertices
[2].SetOrigin(640.0f
, 480.0f
);
475 Mesh
.Vertices
[3].SetOrigin( 0.0f
, 480.0f
);
477 MatSys::Renderer
->SetCurrentMaterial(m_GuiFinishZRM
);
478 MatSys::Renderer
->RenderMesh(Mesh
);
483 bool GuiImplT::ProcessDeviceEvent(const CaKeyboardEventT
& KE
)
485 for (IntrusivePtrT
<WindowT
> Win
=FocusWindow
; Win
!=NULL
; Win
=Win
->GetParent())
487 bool KeyWasProcessed
=false;
488 bool ResultOK
=false;
492 case CaKeyboardEventT::CKE_KEYDOWN
: ResultOK
=Win
->CallLuaMethod("OnKeyPress", "i>b", KE
.Key
, &KeyWasProcessed
); break;
493 case CaKeyboardEventT::CKE_CHAR
: ResultOK
=Win
->CallLuaMethod("OnChar", "i>b", KE
.Key
, &KeyWasProcessed
); break;
494 case CaKeyboardEventT::CKE_KEYUP
: ResultOK
=Win
->CallLuaMethod("OnKeyRelease", "i>b", KE
.Key
, &KeyWasProcessed
); break;
497 if (ResultOK
&& KeyWasProcessed
) return true;
498 if (Win
->OnInputEvent(KE
)) return true;
505 bool GuiImplT::ProcessDeviceEvent(const CaMouseEventT
& ME
)
507 // Note that the processing of the mouse event is orthogonal to (independent of) MouseIsShown.
508 // That is, we may be active and interactive even if the mouse cursor is *not* shown,
509 // as for example with the 3D window of the Cafu engine client, which must receive the
510 // mouse events even if no mouse cursor is shown!
512 bool MEWasProcessed
=false; // If the Lua script handler consumed the event.
513 bool ResultOK
=false; // If the Lua script handler returned without script error.
517 case CaMouseEventT::CM_BUTTON0
:
518 case CaMouseEventT::CM_BUTTON1
:
519 case CaMouseEventT::CM_BUTTON2
:
520 case CaMouseEventT::CM_BUTTON3
:
522 const bool ButtonDown
=(ME
.Amount
>0); // Was it a "button up" or "button down" event?
524 if (MouseOverWindow
!=NULL
)
526 ResultOK
=MouseOverWindow
->CallLuaMethod(ButtonDown
? "OnMouseButtonDown" : "OnMouseButtonUp", "i>b", ME
.Type
, &MEWasProcessed
);
529 // Change the keyboard input focus, but only if the mouse button event was not handled by the script
530 // (by handling the event the script signals that the default behaviour (focus change) should not take place).
531 if (!MEWasProcessed
&& ME
.Type
==CaMouseEventT::CM_BUTTON0
&& ButtonDown
&& MouseOverWindow
!=FocusWindow
)
533 // Only "unhandled left mouse button down" events change the keyboard input focus.
534 if (FocusWindow
!=NULL
) FocusWindow
->CallLuaMethod("OnFocusLose");
535 FocusWindow
=MouseOverWindow
;
536 if (FocusWindow
!=NULL
) FocusWindow
->CallLuaMethod("OnFocusGain");
542 case CaMouseEventT::CM_MOVE_X
:
544 // Update the mouse cursor position according to the ME.
545 SetMousePos(MousePosX
+ME
.Amount
, MousePosY
);
547 // if (MouseOverWindow!=NULL)
549 // ResultOK=MouseOverWindow->CallLuaMethod("OnMouseMove", "ii>b", RelMousePosX, RelMousePosY, &MEWasProcessed);
554 case CaMouseEventT::CM_MOVE_Y
:
556 // Update the mouse cursor position according to the ME.
557 SetMousePos(MousePosX
, MousePosY
+ME
.Amount
);
559 // if (MouseOverWindow!=NULL)
561 // ResultOK=MouseOverWindow->CallLuaMethod("OnMouseMove", "ii>b", RelMousePosX, RelMousePosY, &MEWasProcessed);
567 // Just ignore the other possible ME types.
571 if (ResultOK
&& MEWasProcessed
) return true;
572 if (MouseOverWindow
==NULL
) return false;
574 const Vector2fT AbsWinPos
= MouseOverWindow
->GetAbsolutePos();
576 return MouseOverWindow
->OnInputEvent(ME
, MousePosX
-AbsWinPos
.x
, MousePosY
-AbsWinPos
.y
);
580 void GuiImplT::DistributeClockTickEvents(float t
)
582 if (GetIsActive()) // Inconsistent and inconsequent, but saves performance: Only distribute clock tick events when this GUI is active.
584 ArrayT
< IntrusivePtrT
<WindowT
> > AllChildren
;
586 AllChildren
.PushBack(RootWindow
);
587 RootWindow
->GetChildren(AllChildren
, true);
589 for (unsigned long ChildNr
=0; ChildNr
<AllChildren
.Size(); ChildNr
++)
591 AllChildren
[ChildNr
]->OnClockTickEvent(t
);
592 AllChildren
[ChildNr
]->CallLuaMethod("OnFrame");
598 // Run the pending coroutines always, even if this GUI is currently not active.
599 m_ScriptState
->RunPendingCoroutines(t
);
604 /***********************************************/
605 /*** Implementation of Lua binding functions ***/
606 /***********************************************/
608 static const cf::TypeSys::MethsDocT META_Activate
=
611 "Sets the IsActive flag of this GUI.",
612 "", "(bool IsActive)"
615 int GuiImplT::Activate(lua_State
* LuaState
)
617 ScriptBinderT
Binder(LuaState
);
618 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
620 // I also want to treat the number 0 as false, not just "false" and "nil".
621 if (lua_isnumber(LuaState
, 2)) Gui
->IsActive
=lua_tointeger(LuaState
, 2)!=0;
622 else Gui
->IsActive
=lua_toboolean(LuaState
, 2)!=0;
628 static const cf::TypeSys::MethsDocT META_Close
=
631 "Same as calling `gui:activate(false);`",
635 int GuiImplT::Close(lua_State
* LuaState
)
637 ScriptBinderT
Binder(LuaState
);
638 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
645 static const cf::TypeSys::MethsDocT META_SetInteractive
=
648 "Sets the IsInteractive flag of this GUI.",
649 "", "(bool IsInteractive)"
652 int GuiImplT::SetInteractive(lua_State
* LuaState
)
654 ScriptBinderT
Binder(LuaState
);
655 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
657 // I also want to treat the number 0 as false, not just "false" and "nil".
658 if (lua_isnumber(LuaState
, 2)) Gui
->IsInteractive
=lua_tointeger(LuaState
, 2)!=0;
659 else Gui
->IsInteractive
=lua_toboolean(LuaState
, 2)!=0;
665 static const cf::TypeSys::MethsDocT META_SetFullCover
=
668 "Sets the IsFullCover flag of this GUI.",
669 "", "(bool IsFullCover)"
672 int GuiImplT::SetFullCover(lua_State
* LuaState
)
674 ScriptBinderT
Binder(LuaState
);
675 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
677 // I also want to treat the number 0 as false, not just "false" and "nil".
678 if (lua_isnumber(LuaState
, 2)) Gui
->IsFullCover
=lua_tointeger(LuaState
, 2)!=0;
679 else Gui
->IsFullCover
=lua_toboolean(LuaState
, 2)!=0;
685 static const cf::TypeSys::MethsDocT META_SetMousePos
=
688 "Sets the position of the mouse cursor.",
689 "", "(number x, number y)"
692 int GuiImplT::SetMousePos(lua_State
* LuaState
)
694 ScriptBinderT
Binder(LuaState
);
695 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
697 Gui
->SetMousePos(float(lua_tonumber(LuaState
, 2)),
698 float(lua_tonumber(LuaState
, 3)));
704 static const cf::TypeSys::MethsDocT META_SetMouseCursorSize
=
706 "setMouseCursorSize",
707 "Sets the size of the mouse cursor.",
711 int GuiImplT::SetMouseCursorSize(lua_State
* LuaState
)
713 ScriptBinderT
Binder(LuaState
);
714 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
716 Gui
->SetMouseCursorSize(float(lua_tonumber(LuaState
, 2)));
722 static const cf::TypeSys::MethsDocT META_SetMouseMat
=
725 "Sets the material that is used to render the mouse cursor.\n"
726 "(This method is not yet implemented.)",
727 "", "(string MatName)"
730 int GuiImplT::SetMouseMat(lua_State
* LuaState
)
736 static const cf::TypeSys::MethsDocT META_SetMouseIsShown
=
739 "Determines whether the mouse cursor is shown at all.",
743 int GuiImplT::SetMouseIsShown(lua_State
* LuaState
)
745 ScriptBinderT
Binder(LuaState
);
746 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
748 // I also want to treat the number 0 as false, not just "false" and "nil".
749 if (lua_isnumber(LuaState
, 2)) Gui
->MouseIsShown
=lua_tointeger(LuaState
, 2)!=0;
750 else Gui
->MouseIsShown
=lua_toboolean(LuaState
, 2)!=0;
756 static const cf::TypeSys::MethsDocT META_CreateNew
=
759 "This method creates new GUI windows or new GUI components.",
760 "object", "(string ClassName, string InstanceName=\"\")"
763 int GuiImplT::CreateNew(lua_State
* LuaState
)
765 ScriptBinderT
Binder(LuaState
);
766 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
768 const std::string TypeName
= std::string("GuiSys::") + luaL_checkstring(LuaState
, 2);
769 const char* ObjName
= lua_tostring(LuaState
, 3); // Passing an object name is optional.
771 const cf::TypeSys::TypeInfoT
* TI
= GetWindowTIM().FindTypeInfoByName(TypeName
.c_str());
775 IntrusivePtrT
<WindowT
> Win(static_cast<WindowT
*>(TI
->CreateInstance(WindowCreateParamsT(*Gui
))));
777 // Console->DevPrint(cf::va("Creating window %p.\n", Win));
778 assert(Win
->GetType() == TI
);
779 assert(strcmp(TI
->ClassName
, TypeName
.c_str()) == 0);
781 if (ObjName
) Win
->GetBasics()->SetWindowName(ObjName
);
787 TI
= GetComponentTIM().FindTypeInfoByName(TypeName
.c_str());
791 IntrusivePtrT
<ComponentBaseT
> Comp(static_cast<ComponentBaseT
*>(TI
->CreateInstance(cf::TypeSys::CreateParamsT())));
797 return luaL_argerror(LuaState
, 2, (std::string("unknown class name \"") + TypeName
+ "\"").c_str());
801 static const cf::TypeSys::MethsDocT META_SetFocus
=
804 "Sets the keyboard input focus to the given window. Does *not* call the OnFocusLose() or OnFocusGain() callbacks!\n"
805 "Instead of a window instance, it is also possible to pass the name of the window (a string).",
806 "", "(WindowT Window)"
809 int GuiImplT::SetFocus(lua_State
* LuaState
)
811 ScriptBinderT
Binder(LuaState
);
812 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
814 if (lua_isstring(LuaState
, 2))
816 Gui
->FocusWindow
=Gui
->RootWindow
->Find(lua_tostring(LuaState
, 2));
818 else if (lua_istable(LuaState
, 2))
820 Gui
->FocusWindow
=Binder
.GetCheckedObjectParam
< IntrusivePtrT
<WindowT
> >(2);
823 // Note that we intentionally did *not* call the Lua OnFocusLose() or OnFocusGain() scripts,
824 // as is done when the focus changes due to a mouse click:
825 // the Lua code that calls this method should instead call the desired OnFocus*() script functions itself.
826 // This behaviour must be explicitly stated in the user documentation!
831 static const cf::TypeSys::MethsDocT META_GetRootWindow
=
834 "Returns the root window of this GUI as previously set by SetRootWindow().",
838 int GuiImplT::GetRootWindow(lua_State
* LuaState
)
840 ScriptBinderT
Binder(LuaState
);
841 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
843 if (Gui
->RootWindow
.IsNull())
845 lua_pushnil(LuaState
);
849 Binder
.Push(Gui
->RootWindow
);
856 static const cf::TypeSys::MethsDocT META_SetRootWindow
=
859 "Sets the root window for this GUI.",
860 "", "(WindowT Window)"
863 int GuiImplT::SetRootWindow(lua_State
* LuaState
)
865 ScriptBinderT
Binder(LuaState
);
866 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
868 Gui
->RootWindow
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<WindowT
> >(2);
873 static const cf::TypeSys::MethsDocT META_Init
=
876 "Calls the OnInit() script methods of all windows.",
880 int GuiImplT::Init(lua_State
* LuaState
)
882 ScriptBinderT
Binder(LuaState
);
883 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
890 static const cf::TypeSys::MethsDocT META_toString
=
893 "Returns a short string representation of this GUI.",
897 int GuiImplT::toString(lua_State
* LuaState
)
899 ScriptBinderT
Binder(LuaState
);
900 IntrusivePtrT
<GuiImplT
> Gui
= Binder
.GetCheckedObjectParam
< IntrusivePtrT
<GuiImplT
> >(1);
902 if (Gui
->ScriptName
=="") lua_pushfstring(LuaState
, "A programmatically generated GUI.");
903 else lua_pushfstring(LuaState
, "A gui generated from the script \"%s\".", Gui
->ScriptName
.c_str());
909 /***********************************/
910 /*** TypeSys-related definitions ***/
911 /***********************************/
913 void* GuiImplT::CreateInstance(const cf::TypeSys::CreateParamsT
& Params
)
915 // At this time, GuiImplT instances cannot be created "anonymously" via the TypeSys' CreateInstance() method,
916 // as it would require us to derive from cf::TypeSys::CreateParamsT and deal with that.
917 // That's not a problem though, because there is no class hierarchy deriving from GuiImplT, so any code that
918 // instantiates GuiImplTs can do so by using the normal constructor -- no "virtual constructor" is needed.
920 // return new GuiImplT(*static_cast<const cf::GameSys::GuiCreateParamsT*>(&Params));
924 const luaL_Reg
GuiImplT::MethodsList
[] =
926 { "activate", Activate
},
928 { "setInteractive", SetInteractive
},
929 { "setFullCover", SetFullCover
},
930 { "setMousePos", SetMousePos
},
931 { "setMouseCursorSize", SetMouseCursorSize
},
932 { "setMouseMat", SetMouseMat
},
933 { "showMouse", SetMouseIsShown
},
934 { "new", CreateNew
},
935 { "setFocus", SetFocus
},
936 { "GetRootWindow", GetRootWindow
},
937 { "SetRootWindow", SetRootWindow
},
939 { "__tostring", toString
},
943 const cf::TypeSys::MethsDocT
GuiImplT::DocMethods
[] =
950 META_SetMouseCursorSize
,
952 META_SetMouseIsShown
,
959 { NULL
, NULL
, NULL
, NULL
}
962 const cf::TypeSys::TypeInfoT
GuiImplT::TypeInfo(GetGuiTIM(), "GuiSys::GuiImplT", NULL
/*No base class.*/, CreateInstance
, MethodsList
, DocClass
, DocMethods
);