OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4ObjectMenu.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2008-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 // Menus attached to objects; script created or internal
18 
19 #include "C4Include.h"
20 #include "object/C4ObjectMenu.h"
21 
22 #include "control/C4Control.h"
23 #include "object/C4Def.h"
24 #include "object/C4Object.h"
25 #include "object/C4ObjectCom.h"
26 #include "player/C4Player.h"
27 #include "game/C4Viewport.h"
28 #include "gui/C4MouseControl.h"
30 #include "game/C4Game.h"
31 #include "player/C4PlayerList.h"
32 #include "object/C4GameObjects.h"
33 #include "script/C4AulExec.h"
34 
35 // -----------------------------------------------------------
36 // C4ObjectMenu
37 
39 {
40  Default();
41 }
42 
44 {
47  Object = ParentObject = RefillObject = nullptr;
49  UserMenu = false;
50  CloseQuerying = false;
51 }
52 
54 {
55  // abort if menu is permanented by script; stop endless recursive calls if user opens a new menu by CloseQuerying-flag
56  if (UserMenu && !CloseQuerying)
57  {
58  CloseQuerying = true;
59  bool fResult = false;
61  if (eCallbackType == CB_Object)
62  {
63  if (Object) fResult = !!Object->Call(PSF_MenuQueryCancel, &pars);
64  }
65  else if (eCallbackType == CB_Scenario)
66  fResult = !!::GameScript.Call(PSF_MenuQueryCancel, &pars);
67  CloseQuerying = false;
68  if (fResult) return true;
69  }
70  // close OK
71  return false;
72 }
73 
74 void C4ObjectMenu::LocalInit(C4Object *pObject, bool fUserMenu)
75 {
76  Object=pObject;
77  UserMenu=fUserMenu;
79  if (pObject) eCallbackType = CB_Object; else eCallbackType = CB_Scenario;
80 }
81 
82 bool C4ObjectMenu::Init(C4FacetSurface &fctSymbol, const char *szEmpty, C4Object *pObject, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle, bool fUserMenu)
83 {
84  if (!DoInit(fctSymbol, szEmpty, iExtra, iExtraData, iId, iStyle)) return false;
85  LocalInit(pObject, fUserMenu);
86  return true;
87 }
88 
89 bool C4ObjectMenu::InitRefSym(const C4TargetFacet &fctSymbol, const char *szEmpty, C4Object *pObject, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle, bool fUserMenu)
90 {
91  if (!DoInitRefSym(fctSymbol, szEmpty, iExtra, iExtraData, iId, iStyle)) return false;
92  LocalInit(pObject, fUserMenu);
93  return true;
94 }
95 
96 void C4ObjectMenu::OnSelectionChanged(int32_t iNewSelection)
97 {
98  // do selection callback
99  if (UserMenu)
100  {
101  C4AulParSet pars(iNewSelection, ParentObject);
102  if (eCallbackType == CB_Object && Object)
103  Object->Call(PSF_MenuSelection, &pars);
104  else if (eCallbackType == CB_Scenario)
106  }
107 }
108 
110 {
111  if (Object==pObj) { Object=nullptr; }
112  if (ParentObject==pObj) ParentObject=nullptr; // Reason for menu close anyway.
113  if (RefillObject==pObj) RefillObject=nullptr;
114  C4Menu::ClearPointers(pObj);
115 }
116 
118 {
119  for (C4Object *cObj : Objects)
120  if (cObj->Menu == this)
121  return cObj;
122  return nullptr;
123 }
124 
126 {
127  RefillObject=pObj;
128  NeedRefill=true;
129  Refill();
130 }
131 
132 bool C4ObjectMenu::DoRefillInternal(bool &rfRefilled)
133 {
134  // Variables
135  C4FacetSurface fctSymbol;
136  C4Object *pObj;
137  char szCaption[256+1],szCommand[256+1],szCommand2[256+1];
138  int32_t iCount;
139  C4Def *pDef;
140  C4IDList ListItems;
141  C4Object *pTarget;
142  C4Facet fctTarget;
143 
144  // Refill
145  switch (Identification)
146  {
147  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
148  case C4MN_Activate:
149  // Clear items
150  ClearItems();
151  // Refill target
152  if (!(pTarget=RefillObject)) return false;
153  {
154  // Add target contents items
155  C4ObjectListIterator iter(pTarget->Contents);
156  while ((pObj = iter.GetNext(&iCount)))
157  {
158  pDef = pObj->Def;
159  if (pDef->NoGet) continue;
160  // Prefer fully constructed objects
161  if (~pObj->OCF & OCF_FullCon)
162  {
163  // easy way: only if first concat check matches
164  // this doesn't catch all possibilities, but that will rarely matter
165  C4Object *pObj2=pTarget->Contents.Find(pDef, ANY_OWNER, OCF_FullCon);
166  if (pObj2) if (pObj2->CanConcatPictureWith(pObj)) pObj = pObj2;
167  }
168  // Caption
169  sprintf(szCaption,LoadResStr("IDS_MENU_ACTIVATE"),(const char *) pObj->GetName());
170  // Picture
171  fctSymbol.Set(fctSymbol.Surface, 0,0,C4SymbolSize,C4SymbolSize);
172  pObj->Picture2Facet(fctSymbol);
173  // Commands
174  sprintf(szCommand,"SetCommand(\"Activate\",Object(%d))&&ExecuteCommand()",pObj->Number);
175  sprintf(szCommand2,"SetCommand(\"Activate\",nil,%d,0,Object(%d),%s)&&ExecuteCommand()",pTarget->Contents.ObjectCount(pDef->id),pTarget->Number,pDef->id.ToString());
176  // Add menu item
177  Add(szCaption,fctSymbol,szCommand,iCount,pObj,"",pDef->id,szCommand2,true,pObj->GetValue(pTarget, NO_OWNER));
178  // facet taken over (arrg!)
179  fctSymbol.Default();
180  }
181  }
182  break;
183  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
184  case C4MN_Get:
185  case C4MN_Contents:
186  // Clear items
187  ClearItems();
188  // Refill target
189  if (!(pTarget = RefillObject)) return false;
190  {
191  // Add target contents items
192  C4ObjectListIterator iter(pTarget->Contents);
193  while ((pObj = iter.GetNext(&iCount)))
194  {
195  pDef = pObj->Def;
196  if (pDef->NoGet) continue;
197  // Prefer fully constructed objects
198  if (~pObj->OCF & OCF_FullCon)
199  {
200  // easy way: only if first concat check matches
201  // this doesn't catch all possibilities, but that will rarely matter
202  C4Object *pObj2 = pTarget->Contents.Find(pDef, ANY_OWNER, OCF_FullCon);
203  if (pObj2) if (pObj2->CanConcatPictureWith(pObj)) pObj = pObj2;
204  }
205  // Determine whether to get or activate
206  bool fGet = true;
207  if (!(pObj->OCF & OCF_Carryable)) fGet = false; // not a carryable item
209  {
210  if (Object && !!Object->Call(PSF_RejectCollection, &C4AulParSet(pObj->Def, pObj))) fGet = false; // collection rejected
211  }
212  if (!(pTarget->OCF & OCF_Entrance)) fGet = true; // target object has no entrance: cannot activate - force get
213  // Caption
214  sprintf(szCaption, LoadResStr(fGet ? "IDS_MENU_GET" : "IDS_MENU_ACTIVATE"), (const char *)pObj->GetName());
215  // Picture
216  fctSymbol.Set(fctSymbol.Surface, 0, 0, C4SymbolSize, C4SymbolSize);
217  pObj->Picture2Facet(fctSymbol);
218  // Primary command: get/activate single object
219  sprintf(szCommand, "SetCommand(\"%s\", Object(%d)) && ExecuteCommand()", fGet ? "Get" : "Activate", pObj->Number);
220  // Secondary command: get/activate all objects of the chosen type
221  szCommand2[0] = 0; int32_t iAllCount;
222  if ((iAllCount = pTarget->Contents.ObjectCount(pDef->id)) > 1)
223  sprintf(szCommand2, "SetCommand(\"%s\", nil, %d,0, Object(%d), %s) && ExecuteCommand()", fGet ? "Get" : "Activate", iAllCount, pTarget->Number, pDef->id.ToString());
224  // Add menu item (with object)
225  Add(szCaption, fctSymbol, szCommand, iCount, pObj, "", pDef->id, szCommand2);
226  fctSymbol.Default();
227  }
228  }
229  break;
230  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
231  default:
232  // Not an internal menu
233  return true;
234  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
235  }
236 
237  // Successfull internal refill
238  rfRefilled = true;
239  return true;
240 }
241 
243 {
244  if (!IsActive()) return;
245  // Immediate refill check by RefillObject contents count check
246  if (RefillObject)
249  // inherited
250  C4Menu::Execute();
251 }
252 
253 void C4ObjectMenu::OnUserSelectItem(int32_t Player, int32_t iIndex)
254 {
255  // queue.... 2do
257 }
258 
259 void C4ObjectMenu::OnUserEnter(int32_t Player, int32_t iIndex, bool fRight)
260 {
261  // object menu: Through queue 2do
263 }
264 
266 {
267  // Queue 2do
269 }
270 
272 {
273  // get viewport
274  C4Viewport *pVP = GetViewport();
275  if (!pVP) return false;
276  // is it an observer viewport?
277  if (pVP->fIsNoOwnerViewport)
278  // is this a synced menu?
280  // then don't control it!
281  return true;
282  // if the player is eliminated, do not control either!
283  if (!pVP->fIsNoOwnerViewport)
284  {
286  if (pPlr && pPlr->Eliminated) return true;
287  }
288  return false;
289 }
290 
292 {
293  // menu controlled by object controller
294  return Object ? Object->Controller : NO_OWNER;
295 }
296 
297 bool C4ObjectMenu::MenuCommand(const char *szCommand, bool fIsCloseCommand)
298 {
299  switch (eCallbackType)
300  {
301  case CB_Object:
302  // Object menu
303  if (Object) Object->MenuCommand(szCommand);
304  break;
305 
306  case CB_Scenario:
307  // Object menu with scenario script callback
308  ::AulExec.DirectExec(nullptr, szCommand, "MenuCommand");
309  break;
310 
311  case CB_None:
312  // TODO
313  break;
314  }
315 
316  return true;
317 }
int32_t Selection
Definition: C4Menu.h:137
C4ID id
Definition: C4Def.h:103
C4Object * GetNext(int32_t *piCount)
bool Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand, int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=nullptr, const char *szInfoCaption=nullptr, C4ID idID=C4ID::None, const char *szCommand2=nullptr, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true)
Definition: C4Menu.cpp:351
bool CloseQuerying
Definition: C4ObjectMenu.h:62
const uint32_t OCF_Entrance
Definition: C4Constants.h:90
virtual bool IsCloseDenied()
bool Refill()
Definition: C4Menu.cpp:918
C4Game Game
Definition: C4Globals.cpp:52
C4GameScriptHost GameScript
int32_t GetValue(C4Object *pInBase, int32_t iForPlayer)
Definition: C4Object.cpp:1702
#define sprintf
Definition: Standard.h:171
virtual bool IsReadOnly()
bool MenuCommand(const char *szCommand)
Definition: C4Object.cpp:2466
bool Init(C4FacetSurface &fctSymbol, const char *szEmpty, C4Object *pObject, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal, bool fUserMenu=false)
virtual void OnUserSelectItem(int32_t Player, int32_t iIndex)
struct C4PlayerControlDefs::CInternalCons InternalCons
void Add(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:82
C4Value Call(const char *szFunction, C4AulParSet *pPars=0, bool fPassError=false)
#define PSF_RejectCollection
Definition: C4GameScript.h:133
const int ANY_OWNER
Definition: C4Constants.h:139
Definition: C4Menu.h:122
virtual C4Viewport * GetViewport()
Definition: C4Menu.cpp:996
C4AulExec AulExec
Definition: C4AulExec.cpp:33
C4MouseControl MouseControl
Definition: C4Globals.cpp:47
virtual void Default()
bool InitRefSym(const C4TargetFacet &fctSymbol, const char *szEmpty, C4Object *pObject, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal, bool fUserMenu=false)
void Set(const C4Facet &cpy)
Definition: C4FacetEx.h:46
const uint32_t OCF_FullCon
Definition: C4Constants.h:85
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void Default()
Definition: C4FacetEx.h:43
void ClearPointers(C4Object *pObj)
CallbackType eCallbackType
Definition: C4ObjectMenu.h:60
C4Player * Get(int iPlayer) const
virtual void OnUserEnter(int32_t Player, int32_t iIndex, bool fRight)
C4NotifyingObjectList Contents
Definition: C4Object.h:152
C4Def * Def
Definition: C4Object.h:143
int32_t GetPlayer()
#define PSF_MenuSelection
Definition: C4GameScript.h:139
bool fIsNoOwnerViewport
Definition: C4Viewport.h:43
void ClearItems()
Definition: C4Menu.cpp:898
virtual const char * GetName() const
Definition: C4PropList.cpp:626
C4PlayerList Players
bool DoInit(C4FacetSurface &fctSymbol, const char *szEmpty, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal)
Definition: C4Menu.cpp:301
void ClearPointers(C4Object *pObj)
Definition: C4Menu.cpp:1161
Definition: C4Def.h:100
const int NO_OWNER
Definition: C4Constants.h:138
virtual void OnUserClose()
virtual bool MenuCommand(const char *szCommand, bool fIsCloseCommand)
#define PSF_MenuQueryCancel
Definition: C4GameScript.h:83
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:94
int32_t Eliminated
Definition: C4Player.h:85
virtual void Default()
Definition: C4Menu.cpp:247
bool IsActive()
Definition: C4Menu.cpp:483
C4Control & Input
Definition: C4Game.h:84
bool DoInitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal)
Definition: C4Menu.cpp:308
virtual void OnSelectionChanged(int32_t iNewSelection)
int ObjectCount(C4ID id=C4ID::None) const
C4Object * Find(C4Def *def, int iOwner=ANY_OWNER, DWORD dwOCF=OCF_All)
const int C4SymbolSize
Definition: C4Constants.h:58
const char * ToString() const
Definition: C4Id.h:62
void Execute()
Definition: C4Menu.cpp:906
const uint32_t OCF_Carryable
Definition: C4Constants.h:82
void Picture2Facet(C4FacetSurface &cgo)
Definition: C4Object.cpp:2357
bool CanConcatPictureWith(C4Object *pOtherObject) const
Definition: C4Object.cpp:4766
int32_t NoGet
Definition: C4Def.h:147
C4Object * Object
Definition: C4ObjectMenu.h:56
void SetRefillObject(C4Object *pObj)
bool NeedRefill
Definition: C4Menu.h:135
int32_t RefillObjectContentsCount
Definition: C4ObjectMenu.h:59
C4Surface * Surface
Definition: C4Facet.h:119
C4Object * RefillObject
Definition: C4ObjectMenu.h:58
uint32_t OCF
Definition: C4Object.h:134
C4Value Call(C4PropertyName k, C4AulParSet *pPars=0, bool fPassErrors=false)
Definition: C4PropList.h:112
int32_t Controller
Definition: C4Object.h:111
void LocalInit(C4Object *pObject, bool fUserMenu)
C4Value DirectExec(C4PropList *p, const char *szScript, const char *szContext, bool fPassErrors=false, C4AulScriptContext *context=nullptr, bool parse_function=false)
Definition: C4AulExec.cpp:1020
virtual int32_t GetControllingPlayer()
virtual bool DoRefillInternal(bool &rfRefilled)
virtual C4Object * GetParentObject()
C4Object * ParentObject
Definition: C4ObjectMenu.h:57
int32_t Identification
Definition: C4Menu.h:141
C4GameObjects Objects
Definition: C4Globals.cpp:48