Compare commits

...

9 Commits

Author SHA1 Message Date
Günther Brammer 6ad42ed24d Restore icons in the player join menu 2016-01-30 16:04:38 +01:00
Günther Brammer 7f75d09740 Increase height of dialog/menu title bars to the standard icon height 2016-01-30 16:04:37 +01:00
Günther Brammer 90860d3422 Use bigger icons for player menu where available 2016-01-30 16:04:37 +01:00
Günther Brammer d60f767f5c Increase all symbol sizes in player menu from 35 to 40 2016-01-30 16:04:22 +01:00
Günther Brammer dd49c5a2fe Increase the symbol size in the player menu items with labels 2016-01-30 16:04:06 +01:00
Günther Brammer 435e5a8eeb Simplify menu construction functions 2016-01-30 16:04:06 +01:00
Günther Brammer 66d78fddab Remove unused support for secondary menu command 2016-01-30 16:04:06 +01:00
Günther Brammer bddbc23354 Remove C4ObjectMenu
It's been superseded by other methods.
2016-01-30 16:04:05 +01:00
Günther Brammer 9741c1e853 Clonk: Don't play idle animations if Menu is open
At least, in theory. I only removed the plain GetMenu() call because the
engine GetMenu is going away.
2016-01-30 16:03:59 +01:00
41 changed files with 146 additions and 2323 deletions

View File

@ -713,8 +713,6 @@ set(OC_CLONK_SOURCES
src/object/C4ObjectInfoList.h
src/object/C4ObjectList.cpp
src/object/C4ObjectList.h
src/object/C4ObjectMenu.cpp
src/object/C4ObjectMenu.h
src/object/C4ObjectPtr.cpp
src/object/C4ObjectPtr.h
src/object/C4ObjectScript.cpp

View File

@ -158,11 +158,6 @@
<col></col>
<col>When an object is loaded from a savegame or network synchronization is performed. Objects with a transfer zone should reset the zone in this call. Also see <emlink href="script/fn/SetTransferZone.html">SetTransferZone</emlink>().</col>
</row>
<row id="MenuQueryCancel">
<literal_col>MenuQueryCancel</literal_col>
<col>int selection, object menu_object</col>
<col>When the player wants to close a user defined object menu. Return value <code>true</code> will keep the menu open.</col>
</row>
<row id="IsFulfilled">
<literal_col>IsFulfilled</literal_col>
<col></col>
@ -213,11 +208,6 @@
<col>object for_collection_of_object</col>
<col>Called to determine the least needed inventory object when a clonk tries to collect a new object and his inventory is full. The function should return the object to be dropped to gain space, or <code>nil</code> if none.</col>
</row>
<row id="OnMenuSelection">
<literal_col>OnMenuSelection</literal_col>
<col>int index, object menu_object</col>
<col>When an object menu entry is selected.</col>
</row>
<row id="CalcValue">
<literal_col>CalcValue</literal_col>
<col>object in_base, int for_player</col>

View File

@ -120,18 +120,6 @@
<literal_col>MenuLeft / MenuUp / MenuRight / MenuDown</literal_col>
<col>Navigation in the player menu (asynchronous command).</col>
</row>
<row>
<literal_col>ObjectMenuOK / ObjectMenuSelect / ObjectMenuOKAll</literal_col>
<col>Confirmation of the selected item in a menu (synchronous command).</col>
</row>
<row>
<literal_col>ObjectMenuCancel</literal_col>
<col>Close a menu (synchronous command).</col>
</row>
<row>
<literal_col>ObjectMenuLeft / ObjectMenuUp / ObjectMenuRight / ObjectMenuDown</literal_col>
<col>Navigation in a menu (synchronous command).</col>
</row>
</table>
</col>
</row>

View File

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>AddMenuItem</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>int</rtype>
<params>
<param>
<type>string</type>
<name>caption</name>
<desc>Text of the new menu entry</desc>
</param>
<param>
<type>string</type>
<name>command</name>
<desc>Command to be executed when the menu item is selected. This can be either a function name or a statement. If a function name is given then the function will be called in the object which was given as command_object to <funclink>CreateMenu</funclink>.</desc>
</param>
<param>
<type>id</type>
<name>symbol</name>
<desc>The ID is used as a picture for the menu item. The name of the definition can be used in caption using %s. Also the ID is passed as the first parameter to the call to command in case it is a function name.</desc>
</param>
<param>
<type>int</type>
<name>count</name>
<desc>Numeric value to be displayed next to the menu entry (such as counts and amounts).</desc>
</param>
<param>
<type>any</type>
<name>parameter</name>
<desc>Second parameter to the function specified in command (see remark).</desc>
</param>
<param>
<type>string</type>
<name>info_caption</name>
<desc>Description text of the new menu entry.</desc>
</param>
<param>
<type>int</type>
<name>extra</name>
<desc>Extra parameter for special behaviour of the menu entry.<br/> Lower 7 bits (0-127): menu symbol.<br/> 0: normal<br/> 1: rank symbol. With symbol specified, the Rank.png component of that definition will be used. count indicates the rank<br/> 2: picture facet, shifted to the right by XPar1 times the facet width. This is used to include multiple menu symbols in a single definition.<br/> 3: XPar1 specifies an object to be drawn with the rank symbol. If the object has no info section (and thus no rank), there will be an empty entry in context menus.<br/> 4: XPar1 specifies an object to be drawn.<br/> 7: XPar1 is a prop list that contains parameters for the menu symbol drawing. See picture parameter of <funclink>CustomMessage</funclink> for possible members. Bit 8 (128): XPar2 is used as object value and overrides the normal object value. Also see extra in <funclink>CreateMenu</funclink></desc>
<optional />
</param>
<param>
<type>any</type>
<name>XPar1</name>
<desc>First additional parameter for extra.</desc>
<optional />
</param>
<param>
<type>any</type>
<name>XPar2</name>
<desc>Second additional parameter for extra.</desc>
<optional />
</param>
</params>
</syntax>
<desc>Adds a menu entry.</desc>
<remark>Custom menu symbols should best have square aspect ratio.</remark>
<remark>If a function name is specified for command, the following parameters are passed: <code>symbol, parameter, bRight[, value]</code> with bRight indicating whether the menu entry was selected with [Special2] or the right mouse button. value is passed only if bit 8 is set in extra and specifies the displayed (overridden) object value of the menu entry.</remark>
<examples>
<example>
<code>
func ControlUse()
{
// Create local menu with local commandos
CreateMenu(GetID());
// Create menu items
AddMenuItem(&quot;Say hello&quot;, &quot;SayHello&quot;);
AddMenuItem(&quot;Do magic&quot;, &quot;DoMagic&quot;);
AddMenuItem(&quot;Create an object: %s&quot;, &quot;CreateItem&quot;, Rock);
AddMenuItem(&quot;Create another object: %s&quot;, &quot;CreateItem&quot;, Firestone);
}
func SayHello()
{
Message(&quot;Hello&quot;,this);
}
func DoMagic()
{
Sound(&quot;Magic*&quot;);
}
func CreateItem(id item)
{
CreateContents(item);
}</code>
<text>Menu for a special item.</text>
</example>
</examples>
<related>
<funclink>CreateMenu</funclink>
<funclink>SelectMenuItem</funclink>
<funclink>CloseMenu</funclink>
</related>
</func>
<author>jwk</author><date>2002-04</date>
</funcs>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>ClearMenuItems</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax><rtype>int</rtype></syntax>
<desc>Removes all entries from a menu.</desc>
<examples>
<example>
<code>var clonk=<funclink>GetCursor</funclink>();
clonk-&gt;<funclink>CreateMenu</funclink>(Clonk, clonk, nil, &quot;&quot;, 0, 2);
clonk-&gt;<funclink>AddMenuItem</funclink>(&quot;&quot;, &quot;&quot;, Gold, nil,nil,&quot;Old Text&quot;);
[...]
clonk-&gt;ClearMenuItems();
clonk-&gt;<funclink>AddMenuItem</funclink>(nil, &quot;&quot;, Gold, nil,0,0,&quot;New Text&quot;);</code>
<text>Opens a text window containing the entry "Old Text" for the selected clonk. Then changes the entry to "New Text".</text>
</example>
</examples>
<related>
<funclink>CreateMenu</funclink>
<funclink>AddMenuItem</funclink>
<funclink>CloseMenu</funclink>
</related>
</func>
<author>Sven2</author><date>2003-06</date>
</funcs>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>CloseMenu</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax><rtype>bool</rtype></syntax>
<desc>Closes the menu of the calling object.</desc>
<examples>
<example>
<code><funclink>Contained</funclink>()-&gt;CloseMenu();</code>
<text>Closes the container's menu.</text>
</example>
</examples>
<related><funclink>CreateMenu</funclink></related>
</func>
<author>Sven2</author><date>2001-11</date>
</funcs>

View File

@ -1,148 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>CreateMenu</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>id</type>
<name>symbol</name>
<desc>The picture of this object definition is used as symbol.</desc>
</param>
<param>
<type>object</type>
<name>command_object</name>
<desc>Object to receive the menu command (see <funclink>AddMenuItem</funclink>). Can be <code>nil</code> in local calls.</desc>
</param>
<param>
<type>int</type>
<name>extra</name>
<desc>
Additional information to be displayed about the currently selected entry. C4MN_ values are now also defined as constants:
<table>
<rowh>
<col>Constant</col>
<col>Value</col>
<col>Effect</col>
</rowh>
<row>
<col>C4MN_Extra_None</col>
<col>0</col>
<col>Nothing</col>
</row>
<row>
<col>C4MN_Extra_Components</col>
<col>1</col>
<col>Components</col>
</row>
<row>
<col>C4MN_Extra_Value</col>
<col>2</col>
<col>Value</col>
</row>
<row>
<col>C4MN_Extra_MagicValue</col>
<col>3</col>
<col>Value as magic value. extra_data is also displayed for comparison, e.g. "50/100".</col>
</row>
<row>
<col>C4MN_Extra_Info</col>
<col>4</col>
<col>Display object description immediately.</col>
</row>
<row>
<col>C4MN_Extra_ComponentsMagic</col>
<col>5</col>
<col>Display components and magic value.</col>
<col></col>
</row>
</table>
</desc>
</param>
<param>
<type>string</type>
<name>caption</name>
<desc>Text to be displayed if the menu is empty.</desc>
</param>
<param>
<type>int</type>
<name>extra_data</name>
<desc>Comparison value for extra 3.</desc>
</param>
<param>
<type>int</type>
<name>style</name>
<desc>
Appearance of the menu. The following constants are defined:
<table>
<rowh>
<col>Constant</col>
<col>Value</col>
<col>Appearance</col>
</rowh>
<row>
<col>C4MN_Style_Normal</col>
<col>0</col>
<col>Normal</col>
</row>
<row>
<col>C4MN_Style_Context</col>
<col>1</col>
<col>Context menu</col>
</row>
<row>
<col>C4MN_Style_Info</col>
<col>2</col>
<col>Info menu</col>
</row>
<row>
<col>C4MN_Style_Dialog</col>
<col>3</col>
<col>Dialog</col>
</row>
<row>
<col>C4MN_Style_EqualItemHeight</col>
<col>128</col>
<col>Can be combined with C4MN_Style_Dialog: all entries with an icon are drawn with the same height.</col>
</row>
</table>
</desc>
</param>
<param>
<type>bool</type>
<name>permanent</name>
<desc>The menu stays open after an entry has been selected.</desc>
</param>
<param>
<type>id</type>
<name>menu_id</name>
<desc>If specified, this id is used as menu id. The current menu id is returned by <funclink>GetMenu</funclink></desc>
<optional />
</param>
</params>
</syntax>
<desc>Creates a user defined menu for the specified object. Menu entries are to be added using <funclink>AddMenuItem</funclink>.</desc>
<examples>
<example>
<text>see <funclink>AddMenuItem</funclink></text>
</example>
</examples>
<related>
<funclink>AddMenuItem</funclink>
<funclink>SelectMenuItem</funclink>
<funclink>GetMenu</funclink>
<funclink>CloseMenu</funclink>
</related>
</func>
<author>springer</author><date>2002-04</date>
<author>Sven2</author><date>2007-03</date>
</funcs>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>GetMenu</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax><rtype>id?</rtype></syntax>
<desc>Returns the id of the menu if the object has an open menu. This is usually the id of the menu symbol (symbol) unless <funclink>CreateMenu</funclink> was used to explicitly use a differing menu id in idMenuID.</desc>
<remark>A return value of <code>nil</code> means that no valid symbol could be determined. This may happen e.g. if no object pointer was passed during a global call to the function. Engine defined menus such as Buy, Sell, etc. never return valid ids.</remark>
<related>
<funclink>CreateMenu</funclink>
<funclink>CloseMenu</funclink>
</related>
</func>
<author>wipfmetz</author><date>2002-08</date>
</funcs>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>GetMenuSelection</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax><rtype>int?</rtype></syntax>
<desc>Determines the currently selected menu entry of the currently open menu of an object, or <code>nil</code> if no menu is open.</desc>
<examples>
<example>
<code><funclink>Log</funclink>(&quot;Current selection: entry %d...&quot;, <funclink>GetCursor</funclink>(0)-&gt;GetMenuSelection();</code>
<text>Writes to the log which menu entry the player has currently selected.</text>
</example>
</examples>
<related><funclink>CreateMenu</funclink></related>
</func>
<author>Sven2</author><date>2001-11</date>
</funcs>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>SelectMenuItem</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>int</type>
<name>number</name>
<desc>Number of the menu item which is to be selected. The first entry is number 0.</desc>
</param>
</params>
</syntax>
<desc>Sets menu selection in an object menu.</desc>
<related>
<funclink>GetMenuSelection</funclink>
<funclink>GetMenu</funclink>
<funclink>CreateMenu</funclink>
<funclink>AddMenuItem</funclink>
</related>
</func>
<author>PeterW</author><date>2002-10</date>
</funcs>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>SetMenuSize</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
<param>
<type>int</type>
<name>coloumns</name>
<desc>0-50: number of entries to be displayed per line</desc>
</param>
<param>
<type>int</type>
<name>rows</name>
<desc>0-50: number of entries to be displayed per column</desc>
</param>
</params>
</syntax>
<desc>Changes the display size of an object menu so the specified number of menu entries will be displayed per line or column.</desc>
<related>
<funclink>GetMenuSelection</funclink>
<funclink>GetMenu</funclink>
<funclink>CreateMenu</funclink>
<funclink>AddMenuItem</funclink>
</related>
</func>
<author>Sven2</author><date>2003-06</date>
</funcs>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs
SYSTEM '../../../clonk.dtd'>
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>ShowInfo</title>
<category>Objects</category>
<subcat>Menu</subcat>
<version>5.1 OC</version>
<syntax>
<rtype>bool</rtype>
</syntax>
<desc>Displays the description text of an object in a popup window (a menu window).</desc>
<remark>The information window's background will be the definition image of the obect.</remark>
<examples>
<example>
<code>func ControlSpecial()
{
if(!<funclink>Contents</funclink>()) return;
<funclink>Contents</funclink>()-&gt;ShowInfo();
}</code>
<text>A feature for a special clonk: pressing a (to be defined) 'special' key will display the description of the first inventory item in a popup window.</text>
</example>
</examples>
<related>
<funclink>SetCommand</funclink>
<funclink>GetDesc</funclink>
<funclink>CreateMenu</funclink>
<funclink>AddMenuItem</funclink>
<funclink>CloseMenu</funclink>
</related>
</func>
<author>Sven2</author><date>2002-08</date>
</funcs>

View File

@ -496,7 +496,7 @@ func FxIntWalkTimer(pTarget, effect)
effect.animation_id = PlayAnimation(anim, CLONK_ANIM_SLOT_Movement, GetWalkAnimationPosition(anim, 0), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
}
// The clonk has to stand, not making a pause animation yet and not doing other actions with the hands (e.g. loading the bow)
else if(anim == Clonk_WalkStand && !GetHandAction() && GetMenu() == nil)
else if(anim == Clonk_WalkStand && !GetHandAction() && !pTarget->~GetMenu())
{
if (effect.footstop_time) effect.footstep_time = 0;
if(!effect.idle_animation_time)

View File

@ -1088,14 +1088,6 @@ If you want to remove the menu, the suggested method is clonk->TryCancelMenu() t
*/
func GetMenu()
{
// No new-style menu set? Return the classic menu ID. This is deprecated and should be removed in some future.
// This function must return a proplist, but clashes with the engine-defined "GetMenu".
// This workaround here at least allows developers to reach the Clonk's menu ID.
if (this.control.menu == nil)
{
var menu_id = inherited(...);
if (menu_id) return {ID = menu_id};
}
return this.control.menu;
}

View File

@ -79,8 +79,6 @@ IDS_COMM_PUSHTO=Schieben
IDS_COMM_PUT=Ablegen
IDS_COMM_RETRY=Erneuter Versuch
IDS_COMM_SELL=Verkaufen
IDS_COMM_TAKE2=Herausnehmen
IDS_COMM_TAKE=Nehmen
IDS_COMM_THROW=Werfen
IDS_COMM_TRANSFER=Bewegung
IDS_COMM_UNGRAB=Loslassen

View File

@ -79,8 +79,6 @@ IDS_COMM_PUSHTO=Push
IDS_COMM_PUT=Put
IDS_COMM_RETRY=Retry
IDS_COMM_SELL=Sell
IDS_COMM_TAKE2=Take out
IDS_COMM_TAKE=Take
IDS_COMM_THROW=Throw
IDS_COMM_TRANSFER=Movement
IDS_COMM_UNGRAB=Let go

View File

@ -56,7 +56,7 @@ const int C4S_MaxPlayer = 4;
const int C4D_MaxVertex = 30;
const int
C4SymbolSize = 35,
C4SymbolSize = 40,
C4SymbolBorder = 5,
C4UpperBoardHeight = 50,
C4PictureSize = 64,
@ -194,27 +194,17 @@ const BYTE
COM_CursorLeft = 30,
COM_CursorRight = 31;
const BYTE
// COM_Help = 35, (obsolete, was: help-mode button)
const BYTE
COM_PlayerMenu = 36,
COM_Chat = 37;
const BYTE
COM_MenuEnter = 38,
COM_MenuEnterAll = 39,
COM_MenuClose = 40,
COM_MenuShowText = 42,
COM_MenuLeft = 52,
COM_MenuRight = 53,
COM_MenuUp = 54,
COM_MenuDown = 55,
COM_MenuSelect = 60,
COM_MenuFirst = COM_MenuEnter,
COM_MenuLast = COM_MenuSelect,
COM_MenuNavigation1 = COM_MenuShowText,
COM_MenuNavigation2 = COM_MenuSelect;
COM_MenuDown = 55;
//=================================== SendCommand ========================================
const int32_t

View File

@ -30,7 +30,6 @@
#include "C4GraphicsSystem.h"
#include "C4Viewport.h"
#include "C4Object.h"
#include "C4ObjectMenu.h"
#include <algorithm>
@ -69,15 +68,6 @@ void C4PlayerControlDef::CompileFunc(StdCompiler *pComp)
{ "MenuUp", CDA_MenuUp },
{ "MenuRight", CDA_MenuRight },
{ "MenuDown", CDA_MenuDown },
{ "ObjectMenuTextComplete", CDA_ObjectMenuTextComplete },
{ "ObjectMenuOK", CDA_ObjectMenuOK },
{ "ObjectMenuOKAll", CDA_ObjectMenuOKAll },
{ "ObjectMenuSelect",CDA_ObjectMenuSelect },
{ "ObjectMenuCancel",CDA_ObjectMenuCancel },
{ "ObjectMenuLeft", CDA_ObjectMenuLeft },
{ "ObjectMenuUp", CDA_ObjectMenuUp },
{ "ObjectMenuRight", CDA_ObjectMenuRight },
{ "ObjectMenuDown", CDA_ObjectMenuDown },
{ "ZoomIn", CDA_ZoomIn },
{ "ZoomOut", CDA_ZoomOut },
{ NULL, CDA_None }
@ -1214,14 +1204,10 @@ bool C4PlayerControl::ExecuteControlAction(int32_t iControl, C4PlayerControlDef:
// get affected player
C4Player *pPlr = NULL;
C4Viewport *pVP;
C4Object *pCursor = NULL;
C4Menu *pCursorMenu = NULL;
if (iPlr > -1)
{
pPlr = ::Players.Get(iPlr);
if (!pPlr) return false;
pCursor = pPlr->Cursor;
if (pCursor && pCursor->Menu && pCursor->Menu->IsActive()) pCursorMenu = pCursor->Menu;
}
// exec action (on player)
switch (eAction)
@ -1238,16 +1224,6 @@ bool C4PlayerControl::ExecuteControlAction(int32_t iControl, C4PlayerControlDef:
case C4PlayerControlDef::CDA_MenuUp: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuUp ,0); return true; // navigate
case C4PlayerControlDef::CDA_MenuRight: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuRight,0); return true; // navigate
case C4PlayerControlDef::CDA_MenuDown: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuDown,0); return true; // navigate
case C4PlayerControlDef::CDA_ObjectMenuTextComplete: if (!pCursorMenu || fUp || !pCursorMenu->IsTextProgressing()) return false; pCursorMenu->Control(COM_MenuShowText,0); return true; // fast-foward text display
case C4PlayerControlDef::CDA_ObjectMenuOK: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuEnter,0); return true; // ok on item
case C4PlayerControlDef::CDA_ObjectMenuOKAll: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuEnterAll,0); return true; // alt ok on item
case C4PlayerControlDef::CDA_ObjectMenuSelect: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuSelect,rKeyExtraData.iStrength); return true; // select an item directly
case C4PlayerControlDef::CDA_ObjectMenuCancel: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuClose,0); return true; // close menu
case C4PlayerControlDef::CDA_ObjectMenuLeft: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuLeft ,0); return true; // navigate
case C4PlayerControlDef::CDA_ObjectMenuUp: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuUp ,0); return true; // navigate
case C4PlayerControlDef::CDA_ObjectMenuRight: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuRight,0); return true; // navigate
case C4PlayerControlDef::CDA_ObjectMenuDown: if (!pCursorMenu || fUp) return false; pCursorMenu->Control(COM_MenuDown ,0); return true; // navigate
case C4PlayerControlDef::CDA_ZoomIn: if (!pPlr || fUp || !(pVP = ::Viewports.GetViewport(iPlr))) return false; pVP->ChangeZoom(C4GFX_ZoomStep); return true; // viewport zoom
case C4PlayerControlDef::CDA_ZoomOut: if (!pPlr || fUp || !(pVP = ::Viewports.GetViewport(iPlr))) return false; pVP->ChangeZoom(1.0f/C4GFX_ZoomStep); return true; // viewport zoom

View File

@ -42,8 +42,6 @@ public:
CDA_Script, // default: Script callback
CDA_Menu, // open player menu (async)
CDA_MenuOK, CDA_MenuCancel, CDA_MenuLeft, CDA_MenuUp, CDA_MenuRight, CDA_MenuDown, // player menu controls (async)
CDA_ObjectMenuTextComplete, // object menu fast-foward through text animation (async)
CDA_ObjectMenuOK, CDA_ObjectMenuOKAll, CDA_ObjectMenuSelect, CDA_ObjectMenuCancel, CDA_ObjectMenuLeft, CDA_ObjectMenuUp, CDA_ObjectMenuRight, CDA_ObjectMenuDown, // object menu controls (sync)
CDA_ZoomIn, CDA_ZoomOut // player viewport control (async)
};
@ -86,9 +84,8 @@ public:
bool operator ==(const C4PlayerControlDef &cmp) const;
bool Execute(bool fUp, const C4KeyEventData &rKeyExtraData); // key was triggered - execute and return if handled
bool IsSyncObjectMenuControl() const { return eAction>=CDA_ObjectMenuOK && eAction<=CDA_ObjectMenuDown; }
bool IsAsync() const { return eAction != CDA_None && eAction != CDA_Script && !IsSyncObjectMenuControl(); } // true if to be executed directly when triggered
bool IsSync() const { return eAction == CDA_Script || IsSyncObjectMenuControl(); } // true if to be executed via control queue
bool IsAsync() const { return eAction != CDA_None && eAction != CDA_Script; } // true if to be executed directly when triggered
bool IsSync() const { return eAction == CDA_Script; } // true if to be executed via control queue
bool IsValid() const { return eAction != CDA_None; }
};

View File

@ -969,8 +969,6 @@ const char * GetRecordChunkTypeName(C4RecordChunkType eType)
case RCT_MatScan: return "MatScan"; // landscape scan execute
case RCT_MatScanDo: return "MatScanDo"; // landscape scan mat change
case RCT_Area: return "Area"; // object area change
case RCT_MenuAdd: return "MenuAdd"; // add menu item
case RCT_MenuAddC: return "MenuAddC"; // add menu item: Following commands
case RCT_OCF: return "OCF"; // OCF setting of updating
case RCT_DirectExec: return "DirectExec"; // a DirectExec-script
case RCT_Definition: return "Definition"; // Definition callback

View File

@ -78,8 +78,6 @@ enum C4RecordChunkType // record file chunk type
RCT_MatScan = 0x9E, // landscape scan execute
RCT_MatScanDo= 0x9F, // landscape scan mat change
RCT_Area = 0xA0, // object area change
RCT_MenuAdd = 0xA1, // add menu item
RCT_MenuAddC = 0xA2, // add menu item: Following commands
RCT_OCF = 0xA3, // OCF setting of updating
RCT_DirectExec = 0xA4, // a DirectExec-script
RCT_Definition = 0xA5, // Definition callback

View File

@ -46,7 +46,6 @@
#include <C4Player.h>
#include <C4GameOverDlg.h>
#include <C4GameParameters.h>
#include <C4ObjectMenu.h>
#include <C4GameLobby.h>
#include <C4ChatDlg.h>
#include <C4PlayerControl.h>

View File

@ -26,7 +26,6 @@
#include <C4FullScreen.h>
#include <C4Stat.h>
#include <C4Player.h>
#include <C4ObjectMenu.h>
#include <C4MouseControl.h>
#include <C4PXS.h>
#include <C4GameMessage.h>
@ -151,22 +150,6 @@ void C4Viewport::DrawMenu(C4TargetFacet &cgo0)
return;
}
// Player cursor object menu
if (pPlr && pPlr->Cursor && pPlr->Cursor->Menu)
{
if (ResetMenuPositions) pPlr->Cursor->Menu->ResetLocation();
// if mouse is dragging, make it transparent to easy construction site drag+drop
bool fDragging=false;
if (::MouseControl.IsDragging() && ::MouseControl.IsViewport(this))
{
fDragging = true;
pDraw->ActivateBlitModulation(0x4fffffff);
}
// draw menu
pPlr->Cursor->Menu->Draw(cgo);
// reset modulation for dragging
if (fDragging) pDraw->DeactivateBlitModulation();
}
// Player menu
if (pPlr && pPlr->Menu.IsActive())
{
@ -798,8 +781,6 @@ bool C4Viewport::IsViewportMenu(class C4Menu *pMenu)
C4Player *pPlr = ::Players.Get(Player);
// Player eliminated: No menu
if (pPlr && pPlr->Eliminated) return false;
// Player cursor object menu
if (pPlr && pPlr->Cursor && pPlr->Cursor->Menu == pMenu) return true;
// Player menu
if (pPlr && pPlr->Menu.IsActive() && &(pPlr->Menu) == pMenu) return true;
// Fullscreen menu (if active, only one viewport can exist)

View File

@ -96,7 +96,6 @@ bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix);
#define PSF_CalcValue "~CalcValue" // C4Object *pInBase, int iForPlayer
#define PSF_CalcDefValue "~CalcDefValue" // C4Object *pInBase, int iForPlayer
#define PSF_InputCallback "InputCallback" // const char *szText
#define PSF_MenuQueryCancel "~MenuQueryCancel" // int iSelection
#define PSF_IsFulfilled "~IsFulfilled" // int for_plr
#define PSF_AttachTargetLost "~AttachTargetLost"
#define PSF_CrewSelection "~CrewSelection" // bool fDeselect
@ -149,7 +148,6 @@ bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix);
// On* Callbacks
#define PSF_OnGameOver "~OnGameOver"
#define PSF_MenuSelection "~OnMenuSelection" // int iItemIndex, C4Object *pMenuObject
#define PSF_OnActionJump "~OnActionJump" // int iXDir100, iYDir100
#define PSF_OnOwnerChanged "~OnOwnerChanged" // iNewOwner, iOldOwner
#define PSF_EnergyChange "~OnEnergyChange" // int iChange, int iCause, int iCausedByPlayer

View File

@ -139,12 +139,12 @@ namespace C4GUI
// draw symbol
if (fctIcon.Surface)
{
C4Facet cgoSymbol(cgo.Surface, cgo.TargetX + rcBounds.x + 1, cgo.TargetY + rcBounds.y + 1, rcBounds.Hgt-2, rcBounds.Hgt-2);
C4Facet cgoSymbol(cgo.Surface, cgo.TargetX + rcBounds.x, cgo.TargetY + rcBounds.y, rcBounds.Hgt, rcBounds.Hgt);
fctIcon.Draw(cgoSymbol);
}
// calculations for automatic scrolling
int32_t iXOff = 0;
if (iAlign == ALeft) iXOff += 5;
int32_t iXOff = 0, iYOff;
if (iAlign == ALeft) iXOff += C4GUI_IconLabelSpacing;
if (iAutoScrollDelay)
{
C4TimeMilliseconds tNow = C4TimeMilliseconds::Now();
@ -168,14 +168,17 @@ namespace C4GUI
// print out text; clipped
pDraw->StorePrimaryClipper();
pDraw->SetPrimaryClipper(rcBounds.x + GetLeftIndent() + cgo.TargetX, rcBounds.y + cgo.TargetY, rcBounds.x+rcBounds.Wdt - GetRightIndent() + cgo.TargetX, rcBounds.y+rcBounds.Hgt + cgo.TargetY);
pDraw->TextOut(sText.getData(), *pFont, 1.0f, cgo.Surface, x0 + cgo.TargetX + iXOff, rcBounds.y + cgo.TargetY + (rcBounds.Hgt-pFont->GetLineHeight())/2-1, dwFgClr, iAlign);
iYOff = (rcBounds.Hgt-pFont->GetLineHeight())/2-1;
// even border all around the text
if (!fctIcon.Surface) iXOff += iYOff;
pDraw->TextOut(sText.getData(), *pFont, 1.0f, cgo.Surface, x0 + cgo.TargetX + iXOff, rcBounds.y + cgo.TargetY + iYOff, dwFgClr, iAlign);
pDraw->RestorePrimaryClipper();
}
int32_t WoodenLabel::GetDefaultHeight(CStdFont *pUseFont)
{
if (!pUseFont) pUseFont = &(::GraphicsResource.TextFont);
return std::max<int32_t>(pUseFont->GetLineHeight(), C4GUI_MinWoodBarHgt);
return std::max<int32_t>(pUseFont->GetLineHeight(), C4SymbolSize);
}
void WoodenLabel::SetIcon(const C4Facet &rfctIcon)

View File

@ -47,16 +47,9 @@ void C4MainMenu::Default()
Player=NO_OWNER;
}
bool C4MainMenu::Init(C4FacetSurface &fctSymbol, const char *szEmpty, int32_t iPlayer, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
bool C4MainMenu::InitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iPlayer, int32_t iId, int32_t iStyle)
{
if (!DoInit(fctSymbol, szEmpty, iExtra, iExtraData, iId, iStyle)) return false;
Player=iPlayer;
return true;
}
bool C4MainMenu::InitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iPlayer, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
{
if (!DoInitRefSym(fctSymbol, szEmpty, iExtra, iExtraData, iId, iStyle)) return false;
if (!DoInitRefSym(fctSymbol, szEmpty, iId, iStyle)) return false;
Player=iPlayer;
return true;
}
@ -71,7 +64,7 @@ bool C4MainMenu::ActivateNewPlayer(int32_t iPlayer)
// Menu symbol/init
if (GfxR->fctPlayerClr.Surface)
GfxR->fctPlayerClr.Surface->SetClr(0xff);
InitRefSym(GfxR->fctPlayerClr, LoadResStr("IDS_MENU_NOPLRFILES"), iPlayer);
InitRefSym(GfxR->fctPlayerClr, LoadResStr("IDS_MENU_CPNEWPLAYER"), iPlayer, 0, C4MN_Style_Context);
for (DirectoryIterator iter(Config.General.UserDataPath); *iter; ++iter)
if (WildcardMatch("*.ocp", *iter))
{
@ -85,13 +78,22 @@ bool C4MainMenu::ActivateNewPlayer(int32_t iPlayer)
// Load player info
C4PlayerInfoCore C4P;
if (!C4P.Load(hGroup)) { hGroup.Close(); continue; }
// Load custom portrait
C4FacetSurface fctSymbol;
if (!fctSymbol.Load(hGroup, C4CFN_BigIcon, C4FCT_Full, C4FCT_Full, false, true))
fctSymbol.Load(hGroup, C4CFN_BigIcon, C4FCT_Full, C4FCT_Full, false, true);
// Close group
hGroup.Close();
// Add player item
sprintf(szCommand, "JoinPlayer:%s", szFilename);
StdStrBuf sItemText;
sItemText.Format(LoadResStr("IDS_MENU_NEWPLAYER"), C4P.PrefName);
C4FacetSurface fctSymbol;
// No custom portrait: use default player image
if (!fctSymbol.Surface)
{
fctSymbol.Create(C4SymbolSize, C4SymbolSize);
GfxR->fctPlayerClr.DrawClr(fctSymbol, true, C4P.PrefColorDw);
}
// Add menu item
Add(sItemText.getData(), fctSymbol, szCommand);
// Reset symbol facet (menu holds on to the surface)
@ -151,7 +153,7 @@ bool C4MainMenu::DoRefillInternal(bool &rfRefilled)
sprintf(szInfoCaption,LoadResStr("IDS_MENU_ATTACKINFO"),pPlr->GetName(),szFriendly,szNot);
if (iIndex==pPlayer->Number) SCopy(LoadResStr("IDS_MENU_ATTACKSELF"),szInfoCaption);
// Add item
Add(sMsg.getData(),fctSymbol,szCommand,C4MN_Item_NoCount,NULL,szInfoCaption);
Add(sMsg.getData(),fctSymbol,szCommand,szInfoCaption);
fctSymbol.Default();
}
break;
@ -209,7 +211,7 @@ bool C4MainMenu::DoRefillInternal(bool &rfRefilled)
sTeamName.Ref(LoadResStr("IDS_PRC_NEWTEAM"));
const char *szOperation = (Identification == C4MN_TeamSwitch) ? "TeamSwitch" : "TeamSel";
Add(sTeamName.getData(), fctSymbol,FormatString("%s:%d", szOperation, pTeam ? pTeam->GetID() : TEAMID_New).getData(),
C4MN_Item_NoCount,NULL,FormatString(LoadResStr("IDS_MSG_JOINTEAM"), sTeamName.getData()).getData(), C4ID(pTeam ? pTeam->GetID() : 0));
FormatString(LoadResStr("IDS_MSG_JOINTEAM"), sTeamName.getData()).getData());
fctSymbol.Default();
}
break;
@ -224,7 +226,7 @@ bool C4MainMenu::DoRefillInternal(bool &rfRefilled)
if (!pVP) return false;
int32_t iInitialSelection = 0;
// Add free view
AddRefSym(LoadResStr("IDS_MSG_FREEVIEW"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Star), "Observe:Free", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MSG_FREELYSCROLLAROUNDTHEMAP"));
AddRefSym(LoadResStr("IDS_MSG_FREEVIEW"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Star), "Observe:Free", LoadResStr("IDS_MSG_FREELYSCROLLAROUNDTHEMAP"));
// Add players
C4Player *pPlr; int32_t iIndex;
for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++)
@ -246,7 +248,7 @@ bool C4MainMenu::DoRefillInternal(bool &rfRefilled)
StdStrBuf sInfo;
sInfo.Format(LoadResStr("IDS_TEXT_FOLLOWVIEWOFPLAYER"), pPlr->GetName());
// Add item
Add(sMsg.getData(),fctSymbol,sCommand.getData(),C4MN_Item_NoCount,NULL,sInfo.getData());
Add(sMsg.getData(),fctSymbol,sCommand.getData(),sInfo.getData());
fctSymbol.Default();
// check if this is the currently selected player
if (pVP->GetPlayer() == pPlr->Number) iInitialSelection = GetItemCount()-1;
@ -288,12 +290,12 @@ void C4MainMenu::OnUserSelectItem(int32_t Player, int32_t iIndex)
SetSelection(iIndex, true, true);
}
void C4MainMenu::OnUserEnter(int32_t Player, int32_t iIndex, bool fRight)
void C4MainMenu::OnUserEnter(int32_t Player, int32_t iIndex)
{
// direct menu control
// but ensure selection is Okay before
SetSelection(iIndex, true, false);
Enter(fRight);
Enter();
}
void C4MainMenu::OnUserClose()
@ -339,7 +341,7 @@ bool C4MainMenu::ActivateGoals(int32_t iPlayer, bool fDoActivate)
::GraphicsResource.fctCaptain.Draw(fctGF);
}
StdStrBuf Command; Command.Format("Player:Goal:%s", idGoal.ToString());
Add(pDef->GetName(),fctSymbol,Command.getData(),C4MN_Item_NoCount,NULL,"");
Add(pDef->GetName(),fctSymbol,Command.getData(),"");
}
// Go back to options menu on close
SetCloseCommand("ActivateMenu:Main");
@ -363,7 +365,7 @@ bool C4MainMenu::ActivateRules(int32_t iPlayer)
{
fctSymbol.Create(C4SymbolSize,C4SymbolSize); pDef->Draw(fctSymbol);
sprintf(Command, "Player:Rule:%s", idGoal.ToString());
Add(pDef->GetName(),fctSymbol,Command,C4MN_Item_NoCount,NULL,"");
Add(pDef->GetName(),fctSymbol,Command,"");
}
// Go back to options menu on close
SetCloseCommand("ActivateMenu:Main");
@ -458,7 +460,7 @@ bool C4MainMenu::ActivateSavegame(int32_t iPlayer)
// Item caption
strCaption = LoadResStr("IDS_MENU_CPSAVEGAME");
// add menu item
AddRefSym(strCaption.getData(), GfxR->fctMenu.GetPhase(i - 1, fFree ? 2 : 1), strCommand.getData(), C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_CPSAVEGAMEINFO"));
AddRefSym(strCaption.getData(), GfxR->fctMenu.GetPhase(i - 1, fFree ? 2 : 1), strCommand.getData(), LoadResStr("IDS_MENU_CPSAVEGAMEINFO"));
}
// Go back to options menu on close
@ -470,7 +472,7 @@ bool C4MainMenu::ActivateSavegame(int32_t iPlayer)
bool C4MainMenu::ActivateHost(int32_t iPlayer)
{
// Menu symbol/init
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), LoadResStr("IDS_MENU_DISCONNECTCLIENT"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), LoadResStr("IDS_MENU_DISCONNECTCLIENT"), iPlayer, 0, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
SetPermanent(true);
// Clients
@ -490,27 +492,20 @@ bool C4MainMenu::ActivateHost(int32_t iPlayer)
bool C4MainMenu::ActivateClient(int32_t iPlayer)
{
// Menu symbol/init
C4FacetSurface fctSymbol;
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), LoadResStr("IDS_MENU_DISCONNECTFROMSERVER"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), LoadResStr("IDS_MENU_DISCONNECTFROMSERVER"), iPlayer, 0, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,3,0);
Add(LoadResStr("IDS_BTN_YES"), fctSymbol, "Part");
fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,1,0);
Add(LoadResStr("IDS_BTN_NO"), fctSymbol, "");
AddRefSym(LoadResStr("IDS_BTN_YES"), GfxR->fctOKCancel.GetPhase(3,0), "Part");
AddRefSym(LoadResStr("IDS_BTN_NO"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Close), "");
SetCloseCommand("ActivateMenu:Main");
return true;
}
bool C4MainMenu::ActivateSurrender(int32_t iPlayer)
{
C4FacetSurface fctSymbol;
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Surrender), LoadResStr("IDS_MENU_SURRENDER"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Surrender), LoadResStr("IDS_MENU_SURRENDER"), iPlayer, 0, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,3,0);
Add(LoadResStr("IDS_BTN_YES"), fctSymbol, "Surrender");
fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,1,0);
Add(LoadResStr("IDS_BTN_NO"), fctSymbol, "");
AddRefSym(LoadResStr("IDS_BTN_YES"), GfxR->fctOKCancel.GetPhase(3), "Surrender");
AddRefSym(LoadResStr("IDS_BTN_NO"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Close), "");
SetCloseCommand("ActivateMenu:Main");
return true;
}
@ -518,15 +513,12 @@ bool C4MainMenu::ActivateSurrender(int32_t iPlayer)
bool C4MainMenu::ActivateOptions(int32_t iPlayer, int32_t selection)
{
// Menu symbol/init
InitRefSym(GfxR->fctOptions.GetPhase(0), LoadResStr("IDS_MNU_OPTIONS"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
InitRefSym(GfxR->fctOptions.GetPhase(0), LoadResStr("IDS_MNU_OPTIONS"), iPlayer, 0, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
SetPermanent(true);
// Sound
AddRefSym(LoadResStr("IDS_DLG_SOUND"), GfxR->fctOptions.GetPhase(17 + Config.Sound.RXSound),"Options:Sound",C4MN_Item_NoCount);
// Music
AddRefSym(LoadResStr("IDS_MNU_MUSIC"), GfxR->fctOptions.GetPhase(1 + Config.Sound.RXMusic),"Options:Music",C4MN_Item_NoCount);
// Music
AddRefSym(LoadResStr("IDS_MENU_DISPLAY"), GfxR->fctMenu.GetPhase(8), "ActivateMenu:Display");
AddRefSym(LoadResStr("IDS_DLG_SOUND"), GfxR->fctOptions.GetPhase(17 + Config.Sound.RXSound),"Options:Sound");
AddRefSym(LoadResStr("IDS_MNU_MUSIC"), GfxR->fctOptions.GetPhase(1 + Config.Sound.RXMusic),"Options:Music");
AddRefSym(LoadResStr("IDS_MENU_DISPLAY"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_View), "ActivateMenu:Display");
// Restore selection
SetSelection(selection, false, true);
// Go back to main menu on close
@ -538,24 +530,24 @@ bool C4MainMenu::ActivateOptions(int32_t iPlayer, int32_t selection)
bool C4MainMenu::ActivateDisplay(int32_t iPlayer, int32_t selection)
{
// Menu symbol/init
InitRefSym(GfxR->fctMenu.GetPhase(8), LoadResStr("IDS_MENU_DISPLAY"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_View), LoadResStr("IDS_MENU_DISPLAY"), iPlayer, 0, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
SetPermanent(true);
// Crew player names
AddRefSym(LoadResStr("IDS_MNU_PLAYERNAMES"), GfxR->fctOptions.GetPhase(7 + Config.Graphics.ShowCrewNames), "Display:PlayerNames", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_PLAYERNAMES_DESC"));
AddRefSym(LoadResStr("IDS_MNU_PLAYERNAMES"), GfxR->fctOptions.GetPhase(7 + Config.Graphics.ShowCrewNames), "Display:PlayerNames", LoadResStr("IDS_MENU_PLAYERNAMES_DESC"));
// Crew clonk names
AddRefSym(LoadResStr("IDS_MNU_CLONKNAMES"), GfxR->fctOptions.GetPhase(9 + Config.Graphics.ShowCrewCNames), "Display:ClonkNames", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_CLONKNAMES_DESC"));
AddRefSym(LoadResStr("IDS_MNU_CLONKNAMES"), GfxR->fctOptions.GetPhase(9 + Config.Graphics.ShowCrewCNames), "Display:ClonkNames", LoadResStr("IDS_MENU_CLONKNAMES_DESC"));
// Upper Board
if (!Application.isEditor)
{
AddRefSym(LoadResStr("IDS_MNU_UPPERBOARD"),GfxR->fctOptions.GetPhase(3 + Config.Graphics.UpperBoard),"Display:UpperBoard",C4MN_Item_NoCount);
AddRefSym(LoadResStr("IDS_MNU_UPPERBOARD"),GfxR->fctOptions.GetPhase(3 + Config.Graphics.UpperBoard),"Display:UpperBoard");
}
// FPS
if (!Application.isEditor)
AddRefSym(LoadResStr("IDS_MNU_FPS"), GfxR->fctOptions.GetPhase(5 + Config.General.FPS), "Display:FPS", C4MN_Item_NoCount);
AddRefSym(LoadResStr("IDS_MNU_FPS"), GfxR->fctOptions.GetPhase(5 + Config.General.FPS), "Display:FPS");
// Clock
if (!Application.isEditor)
AddRefSym(LoadResStr("IDS_MNU_CLOCK"), GfxR->fctOptions.GetPhase(15 + Config.Graphics.ShowClock), "Display:Clock", C4MN_Item_NoCount);
AddRefSym(LoadResStr("IDS_MNU_CLOCK"), GfxR->fctOptions.GetPhase(15 + Config.Graphics.ShowClock), "Display:Clock");
// Restore selection
SetSelection(selection, false, true);
// Go back to options menu on close
@ -569,10 +561,7 @@ bool C4MainMenu::ActivateMain(int32_t iPlayer)
// Determine player
C4Player *pPlr = ::Players.Get(iPlayer);
// Menu symbol/init
C4FacetSurface fctSymbol;
fctSymbol.Create(C4SymbolSize, C4SymbolSize);
GfxR->fctOKCancel.Draw(fctSymbol, true, 1, 1);
Init(fctSymbol, LoadResStr(pPlr ? "IDS_MENU_CPMAIN" : "IDS_MENU_OBSERVER"), iPlayer, C4MN_Extra_None, 0, 0, C4MN_Style_Context);
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Player), LoadResStr(pPlr ? "IDS_MENU_CPMAIN" : "IDS_MENU_OBSERVER"), iPlayer, 0, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
// Goals+Rules (player menu only)
// Goal menu can't be shown because of script callbacks
@ -581,55 +570,55 @@ bool C4MainMenu::ActivateMain(int32_t iPlayer)
if (pPlr)
{
// Goals
AddRefSym(LoadResStr("IDS_MENU_CPGOALS"),GfxR->fctMenu.GetPhase(4),"ActivateMenu:Goals",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPGOALSINFO"));
AddRefSym(LoadResStr("IDS_MENU_CPGOALS"),GfxR->fctMenu.GetPhase(4),"ActivateMenu:Goals",LoadResStr("IDS_MENU_CPGOALSINFO"));
// Rules
AddRefSym(LoadResStr("IDS_MENU_CPRULES"),GfxR->fctMenu.GetPhase(5),"ActivateMenu:Rules",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPRULESINFO"));
AddRefSym(LoadResStr("IDS_MENU_CPRULES"),GfxR->fctMenu.GetPhase(5),"ActivateMenu:Rules",LoadResStr("IDS_MENU_CPRULESINFO"));
}
// Observer menu in free viewport
if (!pPlr)
{
AddRefSym(LoadResStr("IDS_TEXT_VIEW"),C4GUI::Icon::GetIconFacet(C4GUI::Ico_View),"ActivateMenu:Observer",C4MN_Item_NoCount,NULL,LoadResStr("IDS_TEXT_DETERMINEPLAYERVIEWTOFOLL"));
AddRefSym(LoadResStr("IDS_TEXT_VIEW"),C4GUI::Icon::GetIconFacet(C4GUI::Ico_View),"ActivateMenu:Observer",LoadResStr("IDS_TEXT_DETERMINEPLAYERVIEWTOFOLL"));
}
// Hostility (player menu only)
if (pPlr && (::Players.GetCount() > 1))
{
GfxR->fctFlagClr.Surface->SetClr(0xff0000);
AddRefSym(LoadResStr("IDS_MENU_CPATTACK"),GfxR->fctMenu.GetPhase(7),"ActivateMenu:Hostility",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPATTACKINFO"));
AddRefSym(LoadResStr("IDS_MENU_CPATTACK"),C4GUI::Icon::GetIconFacet(C4GUI::Ico_MeleeLeague),"ActivateMenu:Hostility",LoadResStr("IDS_MENU_CPATTACKINFO"));
}
// Team change
if (pPlr && Game.Teams.IsTeamSwitchAllowed())
{
C4Facet fctTeams; fctTeams = C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team);
AddRefSym(LoadResStr("IDS_MSG_SELTEAM"),fctTeams,"ActivateMenu:TeamSel",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MSG_ALLOWSYOUTOJOINADIFFERENT"));
AddRefSym(LoadResStr("IDS_MSG_SELTEAM"),fctTeams,"ActivateMenu:TeamSel",LoadResStr("IDS_MSG_ALLOWSYOUTOJOINADIFFERENT"));
}
// Player join
if ((::Players.GetCount() < Game.Parameters.MaxPlayers) && !Game.Parameters.isLeague())
{
AddRefSym(LoadResStr("IDS_MENU_CPNEWPLAYER"),GfxR->fctPlayerClr.GetPhase(),"ActivateMenu:NewPlayer",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPNEWPLAYERINFO"));
AddRefSym(LoadResStr("IDS_MENU_CPNEWPLAYER"),GfxR->fctPlayerClr.GetPhase(),"ActivateMenu:NewPlayer",LoadResStr("IDS_MENU_CPNEWPLAYERINFO"));
}
// Save game (player menu only - should we allow saving games with no players in it?)
if (pPlr && (!::Network.isEnabled() || ::Network.isHost()))
{
AddRefSym(LoadResStr("IDS_MENU_CPSAVEGAME"),GfxR->fctMenu.GetPhase(0),"ActivateMenu:Save:Game",C4MN_Item_NoCount,NULL,LoadResStr("IDS_MENU_CPSAVEGAMEINFO"));
AddRefSym(LoadResStr("IDS_MENU_CPSAVEGAME"),GfxR->fctMenu.GetPhase(0),"ActivateMenu:Save:Game",LoadResStr("IDS_MENU_CPSAVEGAMEINFO"));
}
// Options
AddRefSym(LoadResStr("IDS_MNU_OPTIONS"), GfxR->fctOptions.GetPhase(0), "ActivateMenu:Options",C4MN_Item_NoCount, NULL, LoadResStr("IDS_MNU_OPTIONSINFO"));
AddRefSym(LoadResStr("IDS_MNU_OPTIONS"), GfxR->fctOptions.GetPhase(0), "ActivateMenu:Options", LoadResStr("IDS_MNU_OPTIONSINFO"));
// Disconnect
if (::Network.isEnabled())
{
// Host
if (::Network.isHost() && Game.Clients.getClient(NULL))
AddRefSym(LoadResStr("IDS_MENU_DISCONNECT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), "ActivateMenu:Host", C4MN_Item_NoCount, NULL, LoadResStr("IDS_TEXT_KICKCERTAINCLIENTSFROMTHE"));
AddRefSym(LoadResStr("IDS_MENU_DISCONNECT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), "ActivateMenu:Host", LoadResStr("IDS_TEXT_KICKCERTAINCLIENTSFROMTHE"));
// Client
if (!::Network.isHost())
AddRefSym(LoadResStr("IDS_MENU_DISCONNECT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), "ActivateMenu:Client", C4MN_Item_NoCount, NULL, LoadResStr("IDS_TEXT_DISCONNECTTHEGAMEFROMTHES"));
AddRefSym(LoadResStr("IDS_MENU_DISCONNECT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Disconnect), "ActivateMenu:Client", LoadResStr("IDS_TEXT_DISCONNECTTHEGAMEFROMTHES"));
}
// Surrender (player menu only)
if (pPlr)
AddRefSym(LoadResStr("IDS_MENU_CPSURRENDER"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Surrender), "ActivateMenu:Surrender", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_CPSURRENDERINFO"));
AddRefSym(LoadResStr("IDS_MENU_CPSURRENDER"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Surrender), "ActivateMenu:Surrender", LoadResStr("IDS_MENU_CPSURRENDERINFO"));
// Abort
if (!Application.isEditor)
AddRefSym(LoadResStr("IDS_MENU_ABORT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Exit), "Abort", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_ABORT_DESC"));
AddRefSym(LoadResStr("IDS_MENU_ABORT"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Exit), "Abort", LoadResStr("IDS_MENU_ABORT_DESC"));
// No empty menus
if (GetItemCount()==0) Close(false);
// Done
@ -639,10 +628,7 @@ bool C4MainMenu::ActivateMain(int32_t iPlayer)
bool C4MainMenu::ActivateHostility(int32_t iPlayer)
{
// Init menu
C4FacetSurface fctSymbol;
fctSymbol.Create(C4SymbolSize, C4SymbolSize);
GfxR->fctMenu.GetPhase(7).Draw(fctSymbol);
Init(fctSymbol, LoadResStr("IDS_MENU_CPATTACK"), iPlayer, C4MN_Extra_None, 0, C4MN_Hostility);
InitRefSym(GfxR->fctMenu.GetPhase(7), LoadResStr("IDS_MENU_CPATTACK"), iPlayer, C4MN_Hostility);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
SetPermanent(true);
Refill();
@ -875,7 +861,7 @@ bool C4MainMenu::ActivateObserver()
// Safety: Viewport lost?
if (!::Viewports.GetViewport(NO_OWNER)) return false;
// Menu symbol/init
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_View), LoadResStr("IDS_TEXT_VIEW"), NO_OWNER, C4MN_Extra_None, 0, C4MN_Observer, C4MN_Style_Context);
InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_View), LoadResStr("IDS_TEXT_VIEW"), NO_OWNER, C4MN_Observer, C4MN_Style_Context);
SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom);
// Players added in Refill
Refill();

View File

@ -41,8 +41,7 @@ protected:
int32_t Player;
public:
bool Init(C4FacetSurface &fctSymbol, const char *szEmpty, int32_t iPlayer, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal);
bool InitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iPlayer, int32_t iExtra=C4MN_Extra_None, int32_t iExtraData=0, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal);
bool InitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iPlayer, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal);
bool ActivateMain(int32_t iPlayer);
bool ActivateNewPlayer(int32_t iPlayer);
@ -64,7 +63,7 @@ protected:
virtual void OnSelectionChanged(int32_t iNewSelection);
virtual void OnUserSelectItem(int32_t Player, int32_t iIndex);
virtual void OnUserEnter(int32_t Player, int32_t iIndex, bool fRight);
virtual void OnUserEnter(int32_t Player, int32_t iIndex);
virtual void OnUserClose();
virtual int32_t GetControllingPlayer() { return Player; }

View File

@ -30,41 +30,23 @@
#include <C4PlayerList.h>
#include <C4GameControl.h>
const int32_t C4MN_DefInfoWdt = 270, // default width of info windows
C4MN_DlgWdt = 270, // default width of dialog windows
C4MN_DlgLines = 5, // default number of text lines visible in a dialog window
C4MN_DlgLineMargin = 5, // px distance between text items
C4MN_DlgOptionLineMargin = 3, // px distance between dialog option items
C4MN_DlgPortraitWdt = 64, // size of portrait
C4MN_DlgPortraitIndent = 5; // space between portrait and text
const int32_t C4MN_InfoCaption_Delay = 90;
// -----------------------------------------------------------
// C4MenuItem
C4MenuItem::C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption,
const char *szCommand, int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, int32_t iStyle, bool fIsSelectable)
: C4GUI::Element(), Count(iCount), id(idID), Object(pObject), pSymbolObj(NULL), pSymbolGraphics(NULL), dwSymbolClr(0u),
fOwnValue(fOwnValue), iValue(iValue), fSelected(false), iStyle(iStyle), pMenu(pMenu),
iIndex(iIndex), IsSelectable(fIsSelectable), TextDisplayProgress(-1)
C4MenuItem::C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption, const char *szCommand, const char *szInfoCaption, int32_t iStyle)
: C4GUI::Element(), pSymbolGraphics(NULL), dwSymbolClr(0u), fSelected(false),
iStyle(iStyle), pMenu(pMenu), iIndex(iIndex)
{
*Caption=*Command=*Command2=*InfoCaption=0;
*Caption=*Command=*InfoCaption=0;
Symbol.Default();
SCopy(szCaption,Caption,C4MaxTitle);
SCopy(szCommand,Command,_MAX_FNAME+30);
SCopy(szCommand2,Command2,_MAX_FNAME+30);
SCopy(szInfoCaption,InfoCaption,C4MaxTitle);
// some info caption corrections
SReplaceChar(InfoCaption, 10, ' '); SReplaceChar(InfoCaption, 13, '|');
SetToolTip(InfoCaption);
// components initialization
if (idID)
{
C4Def *pDef = C4Id2Def(idID);
if (pDef) pDef->GetComponents(&Components, NULL);
}
}
C4MenuItem::~C4MenuItem()
@ -72,53 +54,11 @@ C4MenuItem::~C4MenuItem()
Symbol.Clear();
}
void C4MenuItem::DoTextProgress(int32_t &riByVal)
{
// any progress to be done?
if (TextDisplayProgress<0) return;
// if this is an option or empty text, show it immediately
if (IsSelectable || !*Caption) { TextDisplayProgress=-1; return; }
// normal text: move forward in unbroken message, ignoring markup
StdStrBuf sText(Caption);
C4Markup MarkupChecker(false);
const char *szPos = sText.getPtr(std::min<int>(TextDisplayProgress, sText.getLength()));
while (riByVal && *szPos)
{
MarkupChecker.SkipTags(&szPos);
if (!*szPos) break;
--riByVal;
// Advance one UTF-8 character
uint32_t c = GetNextCharacter(&szPos);
// Treat embedded images {{XXX}} as one entity
if(c == '{' && *szPos == '{')
{
int32_t end = SCharPos('}', szPos);
if(end > 0 && szPos[end+1] == '}')
szPos += end + 2;
}
}
if (!*szPos)
TextDisplayProgress=-1;
else
TextDisplayProgress = szPos - Caption;
}
bool C4MenuItem::IsDragElement()
{
// any constructibles can be dragged
C4Def *pDef = C4Id2Def(id);
return pDef && pDef->Constructable;
}
int32_t C4MenuItem::GetSymbolWidth(int32_t iForHeight)
{
// Context or dialog menus
if (iStyle==C4MN_Style_Context || (iStyle==C4MN_Style_Dialog && Symbol.Surface))
// Context menus
if (iStyle==C4MN_Style_Context)
return std::max(Symbol.Wdt * iForHeight / std::max(Symbol.Hgt, 1.0f), static_cast<float>(iForHeight));
// Info menus
if (iStyle==C4MN_Style_Info && Symbol.Surface && Symbol.Wdt)
return Symbol.Wdt;
// no symbol
return 0;
}
@ -128,9 +68,8 @@ void C4MenuItem::DrawElement(C4TargetFacet &cgo)
// get target pos
C4Facet cgoOut(cgo.Surface, cgo.TargetX + rcBounds.x, cgo.TargetY + rcBounds.y, rcBounds.Wdt, rcBounds.Hgt);
// Select mark
if (iStyle!=C4MN_Style_Info)
if (fSelected && TextDisplayProgress)
pDraw->DrawBoxDw(cgo.Surface, cgoOut.X, cgoOut.Y, cgoOut.X + cgoOut.Wdt - 1, cgoOut.Y + cgoOut.Hgt - 1, C4RGB(0xca, 0, 0));
if (fSelected)
pDraw->DrawBoxDw(cgo.Surface, cgoOut.X, cgoOut.Y, cgoOut.X + cgoOut.Wdt - 1, cgoOut.Y + cgoOut.Hgt - 1, C4RGB(0xca, 0, 0));
// Symbol/text areas
C4Facet cgoItemSymbol,cgoItemText;
cgoItemSymbol=cgoItemText=cgoOut;
@ -146,80 +85,29 @@ void C4MenuItem::DrawElement(C4TargetFacet &cgo)
C4Facet cgoSymbolOut(cgoItemSymbol.Surface, cgoItemSymbol.X, cgoItemSymbol.Y, cgoItemSymbol.Wdt, cgoItemSymbol.Wdt);
// Draw item symbol:
// Draw if there is no text progression at all (TextDisplayProgress==-1, or if it's progressed far enough already (TextDisplayProgress>0)
if(pSymbolObj && TextDisplayProgress)
{
pSymbolObj->DrawPicture(cgoSymbolOut, false, NULL);
}
else if (pSymbolGraphics && TextDisplayProgress)
if (pSymbolGraphics)
{
pSymbolGraphics->Draw(cgoSymbolOut, dwSymbolClr ? dwSymbolClr : 0xffffffff, NULL, 0, 0, NULL);
}
else if (Symbol.Surface && TextDisplayProgress)
else if (Symbol.Surface)
Symbol.DrawClr(cgoItemSymbol, true, dwSymbolClr);
// Draw item text
pDraw->StorePrimaryClipper(); pDraw->SubPrimaryClipper(cgoItemText.X, cgoItemText.Y, cgoItemText.X+cgoItemText.Wdt-1, cgoItemText.Y+cgoItemText.Hgt-1);
switch (iStyle)
{
case C4MN_Style_Context:
pDraw->TextOut(Caption,::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y,C4Draw::DEFAULT_MESSAGE_COLOR,ALeft);
break;
case C4MN_Style_Info:
{
StdStrBuf sText;
::GraphicsResource.FontRegular.BreakMessage(InfoCaption, cgoItemText.Wdt, &sText, true);
pDraw->TextOut(sText.getData(), ::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y);
break;
}
case C4MN_Style_Dialog:
{
// cut buffer at text display pos
char cXChg='\0'; int iStopPos = 0;
if (TextDisplayProgress>-1)
{
iStopPos = std::min<int>(TextDisplayProgress, strlen(Caption));
cXChg = Caption[iStopPos];
Caption[iStopPos] = '\0';
}
// display broken text
StdStrBuf sText;
::GraphicsResource.FontRegular.BreakMessage(Caption, cgoItemText.Wdt, &sText, true);
pDraw->TextOut(sText.getData(),::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y);
// restore complete text
if (cXChg) Caption[iStopPos] = cXChg;
break;
}
}
if (iStyle == C4MN_Style_Context)
pDraw->TextOut(Caption, ::GraphicsResource.FontRegular, 1.0f, cgoItemText.Surface,
cgoItemText.X + C4GUI_IconLabelSpacing,
cgoItemText.Y + round((cgoItemText.Hgt - ::GraphicsResource.FontRegular.GetLineHeight())/2)-1,
C4GUI_ContextFontClr);
pDraw->RestorePrimaryClipper();
// Draw count
if (Count!=C4MN_Item_NoCount)
{
char szCount[10+1];
sprintf(szCount,"%ix",Count);
pDraw->TextOut(szCount, ::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface, cgoItemText.X+cgoItemText.Wdt-1, cgoItemText.Y+cgoItemText.Hgt-1-::GraphicsResource.FontRegular.GetLineHeight(), C4Draw::DEFAULT_MESSAGE_COLOR, ARight);
}
}
void C4MenuItem::MouseInput(C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
{
// clicky clicky!
if (iButton == C4MC_Button_LeftDown)
if (iButton == C4MC_Button_LeftUp || iButton == C4MC_Button_RightUp)
{
// button down: Init drag only; Enter selection only by button up
if (IsDragElement())
StartDragging(rMouse, iX, iY, dwKeyParam);
}
else if (iButton == C4MC_Button_LeftUp)
{
// left-click performed
pMenu->UserEnter(::MouseControl.GetPlayer(), this, false);
return;
}
else if (iButton == C4MC_Button_RightUp)
{
// right-up: Alternative enter command
pMenu->UserEnter(::MouseControl.GetPlayer(), this, true);
pMenu->UserEnter(::MouseControl.GetPlayer(), this);
return;
}
// inherited; this is just setting some vars
@ -257,17 +145,11 @@ void C4Menu::Default()
Symbol.Default();
Caption[0]=0;
Permanent=false;
Extra=C4MN_Extra_None;
ExtraData=0;
TimeOnSelection=0;
Identification=0;
LocationSet=false;
Columns=Lines=0;
Alignment= C4MN_Align_Right | C4MN_Align_Bottom;
VisibleCount=0;
fHasPortrait = false;
fTextProgressing = false;
fEqualIconItemHeight = false;
CloseCommand.Clear();
fActive = false;
}
@ -301,122 +183,62 @@ bool C4Menu::TryClose(bool fOK, bool fControl)
return true;
}
bool C4Menu::DoInit(C4FacetSurface &fctSymbol, const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
{
Clear(); Default();
Symbol.GrabFrom(fctSymbol);
return InitMenu(szEmpty, iExtra, iExtraData, iId, iStyle);
}
bool C4Menu::DoInitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
bool C4Menu::DoInitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iId, int32_t iStyle)
{
Clear(); Default();
Symbol.Set(fctSymbol);
return InitMenu(szEmpty, iExtra, iExtraData, iId, iStyle);
return InitMenu(szEmpty, iId, iStyle);
}
bool C4Menu::InitMenu(const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle)
bool C4Menu::InitMenu(const char *szEmpty, int32_t iId, int32_t iStyle)
{
SCopy(szEmpty,Caption,C4MaxTitle);
Extra=iExtra; ExtraData=iExtraData;
Identification=iId;
if (*Caption || iStyle == C4MN_Style_Dialog) SetTitle(Caption, HasMouse()); else SetTitle(" ", HasMouse());
if (*Caption) SetTitle(Caption, HasMouse()); else SetTitle(" ", HasMouse());
if (pTitle) pTitle->SetIcon(Symbol);
Style=iStyle & C4MN_Style_BaseMask;
Style=iStyle;
// Menus are synchronous to allow COM_MenuUp/Down to be converted to movements at the clients
if (Style == C4MN_Style_Normal)
Columns = 5;
else
// in reality, Dialog menus may have two coloumns (first for the portrait)
// however, they are not uniformly spaced and stuff; so they are better just ignored and handled by the drawing routine
Columns=1;
if (iStyle & C4MN_Style_EqualItemHeight) SetEqualItemHeight(true);
if (Style == C4MN_Style_Dialog) Alignment = C4MN_Align_Top;
::pGUI->ShowDialog(this, false);
fTextProgressing = false;
fActive = true;
return true;
}
bool C4Menu::AddRefSym(const char *szCaption, const C4Facet &fctSymbol, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
bool C4Menu::AddRefSym(const char *szCaption, const C4Facet &fctSymbol, const char *szCommand, const char *szInfoCaption)
{
if (!IsActive()) return false;
// Create new menu item
C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,szInfoCaption,Style);
// Ref Symbol
pNew->RefSymbol(fctSymbol);
// Add
return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
return AddItem(pNew, szCaption, szCommand, szInfoCaption);
}
bool C4Menu::Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
bool C4Menu::Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand, const char *szInfoCaption)
{
if (!IsActive()) return false;
// Create new menu item
C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,szInfoCaption,Style);
// Set Symbol
pNew->GrabSymbol(fctSymbol);
// Add
return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
return AddItem(pNew, szCaption, szCommand, szInfoCaption);
}
bool C4Menu::Add(const char *szCaption, C4Object* pGfxObj, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
bool C4Menu::AddItem(C4MenuItem *pNew, const char *szCaption, const char *szCommand, const char *szInfoCaption)
{
if (!IsActive()) return false;
// Create new menu item
C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
// Set Symbol
pNew->SetGraphics(pGfxObj);
// Add
return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
}
bool C4Menu::Add(const char *szCaption, C4DefGraphics* pGfx, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
{
if (!IsActive()) return false;
// Create new menu item
C4MenuItem *pNew = new C4MenuItem(this, ItemCount, szCaption,szCommand,iCount,pObject,szInfoCaption,idID,szCommand2,fOwnValue,iValue,Style,fIsSelectable);
// Set Symbol
pNew->SetGraphics(pGfx);
// Add
return AddItem(pNew, szCaption, szCommand, iCount, pObject, szInfoCaption, idID, szCommand2, fOwnValue, iValue, fIsSelectable);
}
bool C4Menu::AddItem(C4MenuItem *pNew, const char *szCaption, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable)
{
#ifdef DEBUGREC_MENU
if (Config.General.DebugRec)
if (pObject)
{
C4RCMenuAdd rc = { pObject ? pObject->Number : -1, iCount, idID, fOwnValue, iValue, fIsSelectable };
AddDbgRec(RCT_MenuAdd, &rc, sizeof(C4RCMenuAdd));
if (szCommand) AddDbgRec(RCT_MenuAddC, szCommand, strlen(szCommand)+1);
if (szCommand2) AddDbgRec(RCT_MenuAddC, szCommand2, strlen(szCommand2)+1);
}
#endif
// Add it to the list
pClientWindow->AddElement(pNew);
// first menuitem is portrait, if it does not have text but a facet
if (!ItemCount && (!szCaption || !*szCaption))
fHasPortrait = true;
// Item count
ItemCount++;
// set new item size
if (!pClientWindow->IsFrozen()) UpdateElementPositions();
// Init selection if not frozen
if (Selection==-1 && fIsSelectable && !pClientWindow->IsFrozen()) SetSelection(ItemCount-1, false, false);
// initial progress
if (fTextProgressing) pNew->TextDisplayProgress = 0;
if (Selection==-1 && !pClientWindow->IsFrozen()) SetSelection(ItemCount-1, false, false);
// adjust scrolling, etc.
UpdateScrollBar();
// Success
@ -430,7 +252,6 @@ bool C4Menu::Control(BYTE byCom, int32_t iData)
switch (byCom)
{
case COM_MenuEnter: Enter(); break;
case COM_MenuEnterAll: Enter(true); break;
case COM_MenuClose: TryClose(false, true); break;
// organize with nicer subfunction...
@ -464,13 +285,6 @@ bool C4Menu::Control(BYTE byCom, int32_t iData)
iData-=Columns;
MoveSelection(iData, true, true);
break;
case COM_MenuSelect:
if (ItemCount)
SetSelection(iData & (~C4MN_AdjustPosition), !!(iData & C4MN_AdjustPosition), true);
break;
case COM_MenuShowText:
SetTextProgress(-1, false);
break;
}
return true;
@ -488,23 +302,17 @@ bool C4Menu::IsActive()
return fActive;
}
bool C4Menu::Enter(bool fRight)
bool C4Menu::Enter()
{
// Not active
if (!IsActive()) return false;
if (Style==C4MN_Style_Info) return false;
// Get selected item
C4MenuItem *pItem = GetSelectedItem();
if (!pItem)
{
// okay for dialogs: Just close them
if (Style == C4MN_Style_Dialog) TryClose(false, true);
return true;
}
// Copy command to buffer (menu might be cleared)
char szCommand[_MAX_FNAME+30+1];
SCopy(pItem->Command,szCommand);
if (fRight && pItem->Command2[0]) SCopy(pItem->Command2,szCommand);
// Close if not permanent
if (!Permanent) { Close(true); fActive = false; }
@ -536,12 +344,8 @@ bool C4Menu::MoveSelection(int32_t iBy, bool fAdjustPosition, bool fDoCalls)
iNewSel += iBy;
// selection is out of menu range
if (!Inside<int32_t>(iNewSel, 0, ItemCount-1)) return false;
// determine newly selected item
C4MenuItem *pNewSel = GetItem(iNewSel);
// nothing selectable
if (!pNewSel || !pNewSel->IsSelectable) continue;
// got something: go select it
break;
if (GetItem(iNewSel)) break;
}
// select it
return !!SetSelection(iNewSel, fAdjustPosition, fDoCalls);
@ -553,7 +357,7 @@ bool C4Menu::SetSelection(int32_t iSelection, bool fAdjustPosition, bool fDoCall
if (!IsActive()) return false;
// Outside Limits / Selectable
C4MenuItem *pNewSel = GetItem(iSelection);
if ((iSelection==-1 && !ItemCount) || (pNewSel && pNewSel->IsSelectable))
if ((iSelection==-1 && !ItemCount) || pNewSel)
{
// Selection change
if (iSelection!=Selection)
@ -629,102 +433,36 @@ void C4Menu::SetSize(int32_t iToWdt, int32_t iToHgt)
void C4Menu::InitLocation(C4Facet &cgoArea)
{
// Item size by style
switch (Style)
ItemWidth=ItemHeight=C4SymbolSize;
if (Style == C4MN_Style_Context)
{
case C4MN_Style_Normal:
ItemWidth=ItemHeight=C4SymbolSize;
break;
case C4MN_Style_Context:
{
ItemHeight = std::max<int32_t>(C4MN_SymbolSize, ::GraphicsResource.FontRegular.GetLineHeight());
ItemHeight = std::max<int32_t>(ItemHeight, ::GraphicsResource.FontRegular.GetLineHeight());
int32_t iWdt, iHgt;
::GraphicsResource.FontRegular.GetTextExtent(Caption, ItemWidth, iHgt, true);
::GraphicsResource.FontRegular.GetTextExtent(Caption, iWdt, iHgt, true);
// FIXME: Blah. This stuff should be calculated correctly by pTitle.
ItemWidth += ItemHeight + 16;
ItemWidth += iWdt + 20 + C4GUI_IconLabelSpacing;
C4MenuItem *pItem;
for (int i = 0; (pItem = GetItem(i)); ++i)
{
::GraphicsResource.FontRegular.GetTextExtent(pItem->Caption, iWdt, iHgt, true);
ItemWidth = std::max(ItemWidth, iWdt + pItem->GetSymbolWidth(ItemHeight));
ItemWidth = std::max(ItemWidth, iWdt + pItem->GetSymbolWidth(ItemHeight) + C4GUI_IconLabelSpacing);
}
ItemWidth += 3; // Add some extra space so text doesn't touch right border frame...
break;
}
case C4MN_Style_Info:
{
// calculate size from a default size determined by a window width of C4MN_DefInfoWdt
int32_t iWdt,iHgt,iLargestTextWdt;
::GraphicsResource.FontRegular.GetTextExtent(Caption,iWdt,iHgt, true);
iLargestTextWdt = iWdt + 2 * C4MN_SymbolSize + C4MN_FrameWidth;
ItemWidth=std::min<int>(cgoArea.Wdt - 2*C4MN_FrameWidth, std::max(iLargestTextWdt, C4MN_DefInfoWdt));
ItemHeight=0;
StdStrBuf sText;
C4MenuItem *pItem;
for (int32_t i=0; (pItem=GetItem(i)); ++i)
{
::GraphicsResource.FontRegular.BreakMessage(pItem->InfoCaption, ItemWidth, &sText, true);
::GraphicsResource.FontRegular.GetTextExtent(sText.getData(),iWdt,iHgt, true);
assert(iWdt <= ItemWidth);
ItemWidth=std::max(ItemWidth,iWdt); ItemHeight=std::max(ItemHeight,iHgt);
iLargestTextWdt = std::max(iLargestTextWdt, iWdt);
}
// although width calculation is done from C4MN_DefInfoWdt, this may be too large for some very tiny info windows
// so make sure no space is wasted
ItemWidth = std::min(ItemWidth, iLargestTextWdt);
// Add some extra space so text doesn't touch right border frame...
ItemWidth += 3;
// Now add some space to show the picture on the left
ItemWidth += C4PictureSize;
// And set a minimum item height (again, for the picture)
ItemHeight = std::max<int>(ItemHeight, C4PictureSize);
break;
}
case C4MN_Style_Dialog:
{
// dialog window: Item width is whole dialog, portrait subtracted if any
// Item height varies
int32_t iWdt,iHgt;
::GraphicsResource.FontRegular.GetTextExtent(Caption,iWdt,iHgt, true);
ItemWidth=std::min<int>(cgoArea.Wdt - 2*C4MN_FrameWidth, std::max<int>(iWdt + 2 * C4MN_SymbolSize + C4MN_FrameWidth, C4MN_DlgWdt));
ItemHeight=iHgt; // Items may be multiline and higher
if (HasPortrait())
{
// subtract portrait only if this would not make the dialog too small
if (ItemWidth > C4MN_DlgPortraitWdt*2 && cgoArea.Hgt > cgoArea.Wdt)
ItemWidth = std::max<int>(ItemWidth - C4MN_DlgPortraitWdt - C4MN_DlgPortraitIndent, 40);
}
}
}
int DisplayedItemCount = ItemCount - HasPortrait();
if (Style == C4MN_Style_Dialog)
Lines = C4MN_DlgLines;
else
Lines = DisplayedItemCount/Columns+std::min<int32_t>(DisplayedItemCount%Columns,1);
Lines = ItemCount/Columns+std::min<int32_t>(ItemCount%Columns,1);
// adjust by max. height
Lines=std::max<int32_t>(std::min<int32_t>((cgoArea.Hgt-100)/std::max<int32_t>(ItemHeight,1),Lines),1);
InitSize();
int32_t X,Y;
if (Alignment & C4MN_Align_Free)
{
X = rcBounds.x;
Y = rcBounds.y;
}
else
{
X = (cgoArea.Wdt - rcBounds.Wdt)/2;
Y = (cgoArea.Hgt - rcBounds.Hgt)/2;
}
X = (cgoArea.Wdt - rcBounds.Wdt)/2;
Y = (cgoArea.Hgt - rcBounds.Hgt)/2;
// Alignment
if (Alignment & C4MN_Align_Left) X=C4SymbolSize;
if (Alignment & C4MN_Align_Right) X=cgoArea.Wdt-2*C4SymbolSize-rcBounds.Wdt;
if (Alignment & C4MN_Align_Top) Y=C4SymbolSize;
if (Alignment & C4MN_Align_Bottom) Y=cgoArea.Hgt-C4SymbolSize-rcBounds.Hgt;
if (Alignment & C4MN_Align_Free) { X=Clamp<int32_t>(X,0,cgoArea.Wdt-rcBounds.Wdt); Y=Clamp<int32_t>(Y,0,cgoArea.Hgt-rcBounds.Hgt); }
// Centered (due to small viewport size)
if (rcBounds.Wdt>cgoArea.Wdt-2*C4SymbolSize) X=(cgoArea.Wdt-rcBounds.Wdt)/2;
if (rcBounds.Hgt>cgoArea.Hgt-2*C4SymbolSize) Y=(cgoArea.Hgt-rcBounds.Hgt)/2;
@ -749,17 +487,8 @@ void C4Menu::InitSize()
int Width, Height;
Width=Columns*ItemWidth;
Height=Lines*ItemHeight;
VisibleCount = Columns*Lines;
bool fBarNeeded;
if (HasPortrait()) Width += C4MN_DlgPortraitWdt + C4MN_DlgPortraitIndent;
// dialogs have auto-enlarge vertically
if (pLast && Style == C4MN_Style_Dialog)
{
Height = std::max<int>(Height, pLast->GetBounds().y + pLast->GetBounds().Hgt + C4MN_DlgLineMargin);
fBarNeeded = false;
}
else
fBarNeeded = pLast && pLast->GetBounds().y + pLast->GetBounds().Hgt > pClientWindow->GetBounds().Hgt;
fBarNeeded = pLast && pLast->GetBounds().y + pLast->GetBounds().Hgt > pClientWindow->GetBounds().Hgt;
// add dlg margins
Width += GetMarginLeft() + GetMarginRight() + pClientWindow->GetMarginLeft() + pClientWindow->GetMarginRight();
Height += GetMarginTop() + GetMarginBottom() + pClientWindow->GetMarginTop() + pClientWindow->GetMarginBottom();
@ -794,67 +523,16 @@ void C4Menu::Draw(C4TargetFacet &cgo)
ParentClass::Draw(cgo);
// draw tooltip if selection time has been long enough
if (!fTextProgressing) ++TimeOnSelection;
if (TimeOnSelection >= C4MN_InfoCaption_Delay)
if (Style != C4MN_Style_Info) // No tooltips in info menus - doesn't make any sense...
if (!::Control.isReplay())
if (!::pGUI->Mouse.IsActiveInput())
{
C4MenuItem *pSel = GetSelectedItem();
if (pSel && *pSel->InfoCaption)
{
int32_t iX=0, iY=0;
pSel->ClientPos2ScreenPos(iX, iY);
C4GUI::Screen::DrawToolTip(pSel->InfoCaption, cgo, iX, iY);
}
}
}
void C4Menu::DrawElement(C4TargetFacet &cgo)
{
// inherited (background)
typedef C4GUI::Dialog ParentClass;
ParentClass::DrawElement(cgo);
// Get selected item id
C4ID idSelected; C4MenuItem *pItem;
if ((pItem = GetSelectedItem())) idSelected = pItem->id; else idSelected = C4ID::None;
C4Def *pDef = C4Id2Def(idSelected);
// Get item value
int32_t iValue = 0;
if (pDef)
++TimeOnSelection;
if (TimeOnSelection >= C4MN_InfoCaption_Delay && !::Control.isReplay() && !::pGUI->Mouse.IsActiveInput())
{
if (pItem && pItem->fOwnValue)
iValue = pItem->iValue;
else
iValue = pDef->GetValue(NULL, NO_OWNER);
}
// Store and clear global clipper
// int32_t iX1,iY1,iX2,iY2;
// pDraw->GetPrimaryClipper(iX1,iY1,iX2,iY2);
// pDraw->SubPrimaryClipper(rcBounds.x, rcBounds.y, rcBounds.x+rcBounds.Wdt-1, rcBounds.y+rcBounds.Hgt-1);
C4Facet cgoExtra(cgo.Surface, cgo.TargetX+rcBounds.x+1, cgo.TargetY+rcBounds.y+rcBounds.Hgt-C4MN_SymbolSize-1, rcBounds.Wdt-2, C4MN_SymbolSize);
// Draw bar divider
if (Extra)
{
DrawFrame(cgoExtra.Surface, cgoExtra.X-1, cgoExtra.Y-1, cgoExtra.Wdt+1, cgoExtra.Hgt+1);
}
// Draw specified extra
switch (Extra)
{
case C4MN_Extra_Components:
if (pItem) pItem->Components.Draw(cgoExtra,-1,::Definitions,C4D_All,true,C4FCT_Right | C4FCT_Triple | C4FCT_Half);
break;
case C4MN_Extra_Value:
{
if (pDef) ::GraphicsResource.fctWealth.DrawValue(cgoExtra,iValue,0,0,C4FCT_Right);
}
break;
C4MenuItem *pSel = GetSelectedItem();
if (pSel && *pSel->InfoCaption)
{
int32_t iX=0, iY=0;
pSel->ClientPos2ScreenPos(iX, iY);
C4GUI::Screen::DrawToolTip(pSel->InfoCaption, cgo, iX, iY);
}
}
}
@ -916,9 +594,6 @@ void C4Menu::Execute()
if (!Game.iTick35 || NeedRefill)
if (!RefillInternal())
Close(false);
// text progress
if (fTextProgressing)
SetTextProgress(+1, true);
}
bool C4Menu::Refill()
@ -936,19 +611,17 @@ void C4Menu::AdjustSelection()
// selection valid?
C4MenuItem *pSelection = GetItem(Selection);
int iSel = Selection;
if (!pSelection || !pSelection->IsSelectable)
if (!pSelection)
{
// set to new first valid selection: Downwards first
iSel = Selection;
while (--iSel>=0)
if ((pSelection = GetItem(iSel)))
if (pSelection->IsSelectable)
break;
break;
// no success: upwards then
if (iSel<0)
for (iSel=Selection+1; (pSelection = GetItem(iSel)); ++iSel)
if (pSelection->IsSelectable)
break;
break;
}
// set it then
if (!pSelection)
@ -957,38 +630,6 @@ void C4Menu::AdjustSelection()
SetSelection(iSel, iSel != Selection, true);
}
bool C4Menu::ConvertCom(int32_t &rCom, int32_t &rData, bool fAsyncConversion)
{
// This function converts normal Coms to menu Coms before they are send to the queue
// Menu not active
if (!IsActive()) return false;
// Convert plain com control to menu com
switch (rCom)
{
// Convert recognized menu coms
case COM_Throw: rCom = COM_MenuEnter; break;
case COM_Dig: rCom = COM_MenuClose; break;
case COM_Special2: rCom = COM_MenuEnterAll; break;
case COM_Up: rCom = COM_MenuUp; break;
case COM_Left: rCom = COM_MenuLeft; break;
case COM_Down: rCom = COM_MenuDown; break;
case COM_Right: rCom = COM_MenuRight; break;
// Not a menu com: do nothing
default: return true;
}
// If text is still progressing, any menu com will complete it first
// Note: conversion to COM_MenuShowText is not synchronized because text lengths may vary
// between clients. The above switch is used to determine whether the com was a menu com
if (fTextProgressing && fAsyncConversion)
rCom = COM_MenuShowText;
// Done
return true;
}
bool C4Menu::SetLocation(int32_t iX, int32_t iY)
{
// just set position...
@ -996,41 +637,6 @@ bool C4Menu::SetLocation(int32_t iX, int32_t iY)
return true;
}
bool C4Menu::SetTextProgress(int32_t iToProgress, bool fAdd)
{
// menu active at all?
if (!IsActive()) return false;
// set: enable or disable progress?
if (!fAdd)
fTextProgressing = (iToProgress >= 0);
else
{
// add: Does not enable progressing
if (!fTextProgressing) return false;
}
// update menu items
C4MenuItem *pItem;
bool fAnyItemUnfinished = false;
for (int32_t i=HasPortrait(); (pItem = GetItem(i)); ++i)
{
// disabled progress: set all progresses to shown
if (!fTextProgressing)
{
pItem->TextDisplayProgress = -1;
continue;
}
// do progress on item, if any is left
// this call automatically reduces iToProgress as it's used up
if (!fAdd) pItem->TextDisplayProgress = 0;
if (iToProgress) pItem->DoTextProgress(iToProgress);
if (pItem->TextDisplayProgress > -1) fAnyItemUnfinished = true;
}
// if that progress showed everything already, mark as not progressing
fTextProgressing = fAnyItemUnfinished;
// done, success
return true;
}
C4Viewport *C4Menu::GetViewport()
{
// ask all viewports
@ -1049,22 +655,7 @@ void C4Menu::UpdateElementPositions()
// reposition client scrolling window
pClientWindow->SetBounds(GetContainedClientRect());
// re-stack all list items
int xOff, yOff = 0;
C4MenuItem *pCurr = static_cast<C4MenuItem *>(pClientWindow->GetFirst()), *pPrev = NULL;
if (HasPortrait() && pCurr)
{
// recheck portrait
xOff = C4MN_DlgPortraitWdt + C4MN_DlgPortraitIndent;
C4Facet &fctPortrait = pCurr->Symbol;
C4Rect rcPortraitBounds(0,0, C4MN_DlgPortraitWdt + C4MN_DlgPortraitIndent, fctPortrait.Hgt * C4MN_DlgPortraitWdt / std::max<int>(fctPortrait.Wdt, 1));
if (pCurr->GetBounds() != rcPortraitBounds)
{
pCurr->GetBounds() = rcPortraitBounds;
pCurr->UpdateOwnPos();
}
pCurr = static_cast<C4MenuItem *>(pCurr->GetNext());
}
else xOff = 0;
C4MenuItem *pCurr = static_cast<C4MenuItem *>(pClientWindow->GetFirst());
// recheck list items
int32_t iMaxDlgOptionHeight = -1;
int32_t iIndex = 0; C4Rect rcNewBounds(0,0,ItemWidth,ItemHeight);
@ -1072,67 +663,14 @@ void C4Menu::UpdateElementPositions()
while ((pCurr = pNext))
{
pNext = static_cast<C4MenuItem *>(pCurr->GetNext());
if (Style == C4MN_Style_Dialog)
{
// y-margin always, except between options
if (!pPrev || (!pPrev->IsSelectable || !pCurr->IsSelectable)) yOff += C4MN_DlgLineMargin; else yOff += C4MN_DlgOptionLineMargin;
// determine item height.
StdStrBuf sText;
int32_t iAssumedItemHeight = ::GraphicsResource.FontRegular.GetLineHeight();
int32_t iWdt, iAvailWdt = ItemWidth, iSymWdt;
for (;;)
{
iSymWdt = std::min<int32_t>(pCurr->GetSymbolWidth(iAssumedItemHeight), iAvailWdt/2);
iAvailWdt = ItemWidth - iSymWdt;
::GraphicsResource.FontRegular.BreakMessage(pCurr->Caption, iAvailWdt, &sText, true);
::GraphicsResource.FontRegular.GetTextExtent(sText.getData(),iWdt,rcNewBounds.Hgt, true);
if (!iSymWdt || rcNewBounds.Hgt <= iAssumedItemHeight) break;
// If there is a symbol, the symbol grows as more lines become available
// Thus, less space is available for the text, and it might become larger
iAssumedItemHeight = rcNewBounds.Hgt;
}
if (fEqualIconItemHeight && iSymWdt)
{
// force equal height for all symbol items
if (iMaxDlgOptionHeight < 0)
{
// first selectable item inits field
iMaxDlgOptionHeight = rcNewBounds.Hgt;
}
else if (rcNewBounds.Hgt <= iMaxDlgOptionHeight)
{
// following item height smaller or equal: Force equal
rcNewBounds.Hgt = iMaxDlgOptionHeight;
}
else
{
// following item larger height: Need to re-stack from beginning
iMaxDlgOptionHeight = rcNewBounds.Hgt;
pNext = pFirstStack;
pPrev = NULL;
yOff = 0;
iIndex = 0;
continue;
}
}
assert(iWdt <= iAvailWdt);
rcNewBounds.x = 0;
rcNewBounds.y = yOff;
yOff += rcNewBounds.Hgt;
}
else
{
rcNewBounds.x = (iIndex % std::max<int32_t>(Columns, 1)) * ItemWidth;
rcNewBounds.y = (iIndex / std::max<int32_t>(Columns, 1)) * ItemHeight;
}
rcNewBounds.x += xOff;
rcNewBounds.x = (iIndex % std::max<int32_t>(Columns, 1)) * ItemWidth;
rcNewBounds.y = (iIndex / std::max<int32_t>(Columns, 1)) * ItemHeight;
if (pCurr->GetBounds() != rcNewBounds)
{
pCurr->GetBounds() = rcNewBounds;
pCurr->UpdateOwnPos();
}
++iIndex;
pPrev = pCurr;
}
// update scrolling
pClientWindow->SetClientHeight(rcNewBounds.y + rcNewBounds.Hgt);
@ -1143,7 +681,7 @@ void C4Menu::UpdateElementPositions()
szCapt = pSel->Caption;
else
szCapt = Caption;
SetTitle((*szCapt || Style == C4MN_Style_Dialog) ? szCapt : " ", HasMouse());
SetTitle((*szCapt) ? szCapt : " ", HasMouse());
}
void C4Menu::UpdateOwnPos()
@ -1158,20 +696,18 @@ void C4Menu::UserSelectItem(int32_t Player, C4MenuItem *pItem)
{
// not if user con't control anything
if (IsReadOnly()) return;
// the item must be selectable
if (!pItem || !pItem->IsSelectable) return;
if (!pItem) return;
// queue or direct selection
OnUserSelectItem(Player, pItem->iIndex);
}
void C4Menu::UserEnter(int32_t Player, C4MenuItem *pItem, bool fRight)
void C4Menu::UserEnter(int32_t Player, C4MenuItem *pItem)
{
// not if user con't control anything
if (IsReadOnly()) return;
// the item must be selectable
if (!pItem || !pItem->IsSelectable) return;
if (!pItem) return;
// queue or direct enter
OnUserEnter(Player, pItem->iIndex, fRight);
OnUserEnter(Player, pItem->iIndex);
}
void C4Menu::UserClose(bool fOK)
@ -1196,13 +732,6 @@ bool C4Menu::HasMouse()
return false;
}
void C4Menu::ClearPointers(C4Object *pObj)
{
C4MenuItem *pItem;
for (int32_t i=0; (pItem = GetItem(i)); ++i)
pItem->ClearPointers(pObj);
}
#ifdef _DEBUG
void C4Menu::AssertSurfaceNotUsed(C4Surface *sfc)
{

View File

@ -27,24 +27,12 @@
enum
{
C4MN_SymbolSize = 16,
C4MN_FrameWidth = 2
};
enum
{
C4MN_Style_Normal = 0,
C4MN_Style_Context = 1,
C4MN_Style_Info = 2,
C4MN_Style_Dialog = 3,
C4MN_Style_BaseMask = 127,
C4MN_Style_EqualItemHeight = 128
};
enum
{
C4MN_Extra_None = 0,
C4MN_Extra_Components = 1,
C4MN_Extra_Value = 2,
C4MN_Extra_Info = 4,
};
enum
{
@ -52,15 +40,6 @@ enum
C4MN_Align_Right = 2,
C4MN_Align_Top = 4,
C4MN_Align_Bottom = 8,
C4MN_Align_Free = 16
};
enum
{
C4MN_Item_NoCount = 12345678
};
enum
{
C4MN_AdjustPosition = 1<<31
};
class C4MenuItem : public C4GUI::Element
@ -71,51 +50,31 @@ public:
protected:
char Caption[C4MaxTitle+1];
char Command[_MAX_FNAME+30+1];
char Command2[_MAX_FNAME+30+1];
char InfoCaption[2*C4MaxTitle+1];
int32_t Count;
C4ID id;
C4Object *Object;
C4FacetSurface Symbol;
C4Object* pSymbolObj; // drawn instead of symbol, if non-null
C4DefGraphics* pSymbolGraphics; // drawn instead of symbol, if non-null
uint32_t dwSymbolClr;
bool fOwnValue; // if set, a specific value is to be shown
int32_t iValue; // specific value to be shown
bool fSelected; // item is selected; set by menu
int32_t iStyle;
class C4Menu *pMenu;
int32_t iIndex;
bool IsSelectable;
int32_t TextDisplayProgress; // dialog menus only: Amount of text which is to be displayed already (-1 for everything)
C4IDList Components; // components to be displayed in info line if item is selected
private:
bool IsDragElement();
int32_t GetSymbolWidth(int32_t iForHeight);
protected:
virtual void DrawElement(C4TargetFacet &cgo); // draw menu item
// ctor
C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, int32_t iStyle, bool fIsSelectable);
C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption, const char *szCommand, const char *szInfoCaption, int32_t iStyle);
void GrabSymbol(C4FacetSurface &fctSymbol) { Symbol.GrabFrom(fctSymbol); if (Symbol.Surface) dwSymbolClr=Symbol.Surface->GetClr(); }
void SetGraphics(C4Object* pObj) { pSymbolObj = pObj; }
void SetGraphics(C4DefGraphics* pGfx) { pSymbolGraphics = pGfx; }
void RefSymbol(const C4Facet &fctSymbol) { Symbol.Set(fctSymbol); if (Symbol.Surface) dwSymbolClr=Symbol.Surface->GetClr(); }
void SetSelected(bool fToVal) { fSelected = fToVal; }
void DoTextProgress(int32_t &riByVal); // progress number of shown characters by given amount
public:
C4ID GetC4ID() const { return id; }
int32_t GetValue() const { return iValue; }
C4Object *GetObject() const { return Object; }
const char *GetCommand() const { return Command; }
void ClearPointers(C4Object* pObj) { if(pObj == Object) Object = NULL; if(pObj == pSymbolObj) pSymbolObj = NULL; }
// GUI calls
virtual void MouseInput(class C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam); // input: mouse movement or buttons
virtual void MouseEnter(class C4GUI::CMouse &rMouse); // called when mouse cursor enters element region: Select this item (deselects any other)
@ -139,23 +98,16 @@ protected:
int32_t Selection,TimeOnSelection;
int32_t ItemCount;
int32_t ItemWidth,ItemHeight;
int32_t Extra,ExtraData;
int32_t Identification;
int32_t Columns; // sync
int32_t Lines; // async
int32_t Alignment;
int32_t VisibleCount;
StdStrBuf CloseCommand; // script command that will be executed on menu close
char Caption[C4MaxTitle+1];
C4FacetSurface Symbol;
C4GUI::ScrollWindow *pClientWindow; // window containing the menu items
bool fHasPortrait; // if set, first menu item is used at a portrait at topleft of menu
bool fTextProgressing; // if true, text is being shown progressively (dialog menus)
bool fEqualIconItemHeight; // for dialog menus only: If set, all options with an icon are forced to have the same height
bool fActive; // set if menu is shown - independant of GUI to keep synchronized when there's no GUI
public:
bool ConvertCom(int32_t &rCom, int32_t &rData, bool fAsyncConversion);
void ClearPointers(C4Object *pObj);
bool Refill();
void Execute();
void SetPermanent(bool fPermanent);
@ -165,7 +117,6 @@ public:
int32_t GetPosition();
int32_t GetSelection();
bool IsContextMenu() { return Style == C4MN_Style_Context; }
int GetSymbolSize() { return (Style == C4MN_Style_Dialog) ? 64 : C4SymbolSize; }
int32_t GetItemHeight() { return ItemHeight; }
C4MenuItem* GetSelectedItem();
C4MenuItem* GetItem(int32_t iIndex);
@ -174,47 +125,27 @@ public:
bool SetSelection(int32_t iSelection, bool fAdjustPosition, bool fDoCalls);
bool SetPosition(int32_t iPosition);
void SetSize(int32_t iToWdt, int32_t iToHgt);
bool Enter(bool fRight=false);
bool Enter();
bool IsActive();
bool Control(BYTE byCom, int32_t iData);
bool KeyControl(BYTE byCom); // direct keyboard callback
bool AddRefSym(const char *szCaption, const C4Facet &fctSymbol, const char *szCommand,
int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=NULL,
const char *szInfoCaption=NULL,
C4ID idID=C4ID::None, const char *szCommand2=NULL, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true);
bool Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand,
int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=NULL,
const char *szInfoCaption=NULL,
C4ID idID=C4ID::None, const char *szCommand2=NULL, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true);
bool Add(const char *szCaption, C4Object* pGfxObj, const char *szCommand,
int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=NULL,
const char *szInfoCaption=NULL,
C4ID idID=C4ID::None, const char *szCommand2=NULL, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true);
bool Add(const char *szCaption, C4DefGraphics* pGfx, const char *szCommand,
int32_t iCount=C4MN_Item_NoCount, C4Object *pObject=NULL,
const char *szInfoCaption=NULL,
C4ID idID=C4ID::None, const char *szCommand2=NULL, bool fOwnValue=false, int32_t iValue=0, bool fIsSelectable=true);
bool AddRefSym(const char *szCaption, const C4Facet &fctSymbol, const char *szCommand, const char *szInfoCaption=NULL);
bool Add(const char *szCaption, C4FacetSurface &fctSymbol, const char *szCommand, const char *szInfoCaption=NULL);
void ClearItems();
void ResetLocation() { LocationSet = false; }
bool SetLocation(int32_t iX, int32_t iY); // set location relative to user viewport
bool SetTextProgress(int32_t iToProgress, bool fAdd); // enable/disable progressive text display and set starting pos
void SetEqualItemHeight(bool fToVal) { fEqualIconItemHeight = fToVal; } // enable/disable equal item heights
bool TryClose(bool fOK, bool fControl);
void SetCloseCommand(const char *strCommand);
bool IsTextProgressing() const { return fTextProgressing; }
#ifdef _DEBUG
void AssertSurfaceNotUsed(C4Surface *sfc);
#endif
private:
bool AddItem(C4MenuItem *pNew, const char *szCaption, const char *szCommand,
int32_t iCount, C4Object *pObject, const char *szInfoCaption,
C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable);
bool InitMenu(const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle);
bool AddItem(C4MenuItem *pNew, const char *szCaption, const char *szCommand, const char *szInfoCaption);
bool InitMenu(const char *szEmpty, int32_t iId, int32_t iStyle);
protected:
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);
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);
bool DoInitRefSym(const C4Facet &fctSymbol, const char *szEmpty, int32_t iId=0, int32_t iStyle=C4MN_Style_Normal);
void DrawBuffer(C4Facet &cgo);
void AdjustSelection();
void AdjustPosition();
@ -227,7 +158,7 @@ protected:
void InitSize();
void UpdateScrollBar(); // call InitSize if a scroll bar is needed but not present or vice vera
void UserSelectItem(int32_t Player, C4MenuItem *pItem); // select item (direct) or do control (object menus)
void UserEnter(int32_t Player, C4MenuItem *pItem, bool fRight); // enter on an item
void UserEnter(int32_t Player, C4MenuItem *pItem); // enter on an item
bool HasMouse(); // returns whether the controlling player has mouse control
virtual bool DoRefillInternal(bool &rfRefilled) { return true; };
@ -235,15 +166,13 @@ protected:
virtual void OnSelectionChanged(int32_t iNewSelection) {} // do object callbacks if selection changed in user menus
virtual bool IsCloseDenied() { return false; } // do MenuQueryCancel-callbacks for user menus
virtual void OnUserSelectItem(int32_t Player, int32_t iIndex) {}
virtual void OnUserEnter(int32_t Player, int32_t iIndex, bool fRight) {}
virtual void OnUserEnter(int32_t Player, int32_t iIndex) {}
virtual void OnUserClose() {};
virtual bool IsReadOnly() { return false; } // determine whether the menu is just viewed by an observer, and should not issue any calls
virtual int32_t GetControllingPlayer() { return NO_OWNER; }
virtual const char *GetID() { return 0; } // no ID needed, because it's a viewport dlg
bool HasPortrait() { return fHasPortrait; } // dialog menus only: Whether a portrait is shown in the topleft
protected:
// C4GUI
virtual C4Viewport *GetViewport(); // return associated viewport
@ -253,12 +182,11 @@ protected:
void UpdateElementPositions(); // reposition list items so they are stacked vertically
virtual int32_t GetZOrdering() { return -1; }
virtual void Draw(C4TargetFacet &cgo);
virtual void DrawElement(C4TargetFacet &cgo); // draw menu
virtual bool IsOwnPtrElement() { return true; }
virtual void UserClose(bool fOK);
// bottom area needed for extra info
virtual int32_t GetMarginBottom() { return ((Extra) ? C4MN_SymbolSize : 0) + C4MN_FrameWidth + BaseClass::GetMarginBottom(); }
virtual int32_t GetMarginBottom() { return C4MN_FrameWidth + BaseClass::GetMarginBottom(); }
virtual int32_t GetMarginLeft() { return C4MN_FrameWidth + BaseClass::GetMarginLeft(); }
virtual int32_t GetMarginRight() { return C4MN_FrameWidth + BaseClass::GetMarginRight(); }

View File

@ -26,7 +26,6 @@
#include <C4ObjectInfo.h>
#include <C4Random.h>
#include <C4GameMessage.h>
#include <C4ObjectMenu.h>
#include <C4Player.h>
#include <C4SoundSystem.h>
#include <C4Landscape.h>
@ -72,8 +71,6 @@ const char *CommandName(int32_t iCommand)
case C4CMD_Retry: return "Retry";
case C4CMD_Home: return "Home";
case C4CMD_Call: return "Call";
case C4CMD_Take: return "Take";
case C4CMD_Take2: return "Take2";
default: return "None";
}
}
@ -106,8 +103,6 @@ const char* CommandNameID(int32_t iCommand)
case C4CMD_Retry: return "IDS_COMM_RETRY";
case C4CMD_Home: return "IDS_CON_HOME";
case C4CMD_Call: return "IDS_COMM_CALL";
case C4CMD_Take: return "IDS_COMM_TAKE";
case C4CMD_Take2: return "IDS_COMM_TAKE2";
default: return "IDS_COMM_NONE";
}
}
@ -824,18 +819,6 @@ void C4Command::Throw()
Finish(true);
}
void C4Command::Take()
{
ObjectComTake(cObj);
Finish(true);
}
void C4Command::Take2()
{
ObjectComTake2(cObj);
Finish(true);
}
void C4Command::Drop()
{
@ -948,14 +931,6 @@ bool C4Command::GetTryEnter()
void C4Command::Get()
{
// Data set and target specified: open get menu & done (old style)
if (((Data.getInt()==1) || (Data.getInt()==2)) && Target)
{
cObj->ActivateMenu((Data.getInt()==1) ? C4MN_Get : C4MN_Contents,0,0,0,Target);
Finish(true); return;
}
// Get target specified by container and type
if (!Target && Target2 && Data)
if (!(Target = Target2->Contents.Find(Data.getDef())))
@ -1098,15 +1073,6 @@ void C4Command::Get()
void C4Command::Activate()
{
// Container specified, but no Target & no type: open activate menu for container
if (Target2 && !Target && !Data)
{
cObj->ActivateMenu(C4MN_Activate,0,0,0,Target2);
Finish(true);
return;
}
// Target object specified & outside: success
if (Target)
if (!Target->Contained)
@ -1349,8 +1315,6 @@ void C4Command::Execute()
case C4CMD_Retry: Retry(); break;
case C4CMD_Home: Home(); break;
case C4CMD_Call: Call(); break;
case C4CMD_Take: Take(); break; // carlo
case C4CMD_Take2: Take2(); break; // carlo
default: Finish(); break;
}
@ -1954,8 +1918,6 @@ int32_t C4Command::GetExpGain()
case C4CMD_Dig:
case C4CMD_Buy:
case C4CMD_Sell:
case C4CMD_Take:
case C4CMD_Take2:
return 1;
// not that simple

View File

@ -49,12 +49,10 @@ enum C4CMD
C4CMD_Retry,
C4CMD_Home,
C4CMD_Call,
C4CMD_Take,
C4CMD_Take2,
};
const int32_t C4CMD_First = C4CMD_Follow,
C4CMD_Last = C4CMD_Take2; // carlo
C4CMD_Last = C4CMD_Call;
const int32_t C4CMD_Mode_SilentSub = 0, // subcommand; failure will cause base to fail (no message in case of failure)
C4CMD_Mode_Base = 1, // regular base command
@ -118,8 +116,6 @@ protected:
void Throw();
void Jump();
void Wait();
void Take();
void Take2();
bool GetTryEnter(); // at object pos during get-command: Try entering it
void Get();
void Put();

View File

@ -26,7 +26,6 @@
#include <C4Application.h>
#include <C4Game.h>
#include <C4Menu.h>
#include <C4ObjectMenu.h>
#include <C4Player.h>
#include <C4Log.h>
#include <C4Material.h>
@ -490,12 +489,6 @@ void C4DefGraphicsPtrBackupEntry::AssignUpdate()
// looped through w/o removal?
if (!pGfxOverlay) break;
}
// update menu frame decorations - may do multiple updates to the same deco if multiple menus share it...
C4GUI::FrameDecoration *pDeco;
if (pDef && pObj->Menu && (pDeco = pObj->Menu->GetFrameDecoration()))
if (pDeco->idSourceDef == pDef->id)
if (!pDeco->UpdateGfx())
pObj->Menu->SetFrameDeco(NULL);
}
}
// done; reset field to indicate finished update
@ -545,11 +538,6 @@ void C4DefGraphicsPtrBackupEntry::AssignRemoval()
// looped through w/o removal?
if (!pGfxOverlay) break;
}
// remove menu frame decorations
C4GUI::FrameDecoration *pDeco;
if (pDef && pObj->Menu && (pDeco = pObj->Menu->GetFrameDecoration()))
if (pDeco->idSourceDef == pDef->id)
pObj->Menu->SetFrameDeco(NULL);
}
// done; reset field to indicate finished update
pGraphicsPtr = NULL;

View File

@ -35,7 +35,6 @@
#include <C4Random.h>
#include <C4Log.h>
#include <C4Player.h>
#include <C4ObjectMenu.h>
#include <C4RankSystem.h>
#include <C4GameMessage.h>
#include <C4GraphicsResource.h>
@ -209,7 +208,6 @@ void C4Object::Default()
Command=NULL;
Contained=NULL;
TopFace.Default();
Menu=NULL;
MaterialContents=NULL;
Marker=0;
ColorMod=0xffffffff;
@ -1064,8 +1062,6 @@ void C4Object::Execute()
// Animation. If the mesh is attached, then don't execute animation here but let the parent object do it to make sure it is only executed once a frame.
if (pMeshInstance && !pMeshInstance->GetAttachParent())
pMeshInstance->ExecuteAnimation(1.0f/37.0f /* play smoothly at 37 FPS */);
// Menu
if (Menu) Menu->Execute();
}
bool C4Object::At(int32_t ctx, int32_t cty) const
@ -1366,7 +1362,6 @@ bool C4Object::Exit(int32_t iX, int32_t iY, int32_t iR, C4Real iXDir, C4Real iYD
// Misc updates
Mobile=1;
InLiquid=0;
CloseMenu(true);
UpdateFace(true);
SetOCF();
// Engine calls
@ -1406,12 +1401,6 @@ bool C4Object::Enter(C4Object *pTarget, bool fCalls, bool fCopyMotion, bool *pfR
if (Contained) if (!Exit(GetX(),GetY())) return false;
if (Contained || !Status || !pTarget->Status) return false;
// Failsafe updates
if (Menu)
{
CloseMenu(true);
// CloseMenu might do bad stuff
if (Contained || !Status || !pTarget->Status) return false;
}
SetOCF();
// Set container
Contained=pTarget;
@ -1568,132 +1557,6 @@ bool C4Object::CreateContentsByList(C4IDList &idlist)
return true;
}
static void DrawMenuSymbol(int32_t iMenu, C4Facet &cgo, int32_t iOwner)
{
C4Facet ccgo;
DWORD dwColor=0;
if (ValidPlr(iOwner)) dwColor=::Players.Get(iOwner)->ColorDw;
switch (iMenu)
{
case C4MN_Buy:
::GraphicsResource.fctFlagClr.DrawClr(ccgo = cgo.GetFraction(75, 75), true, dwColor);
::GraphicsResource.fctWealth.Draw(ccgo = cgo.GetFraction(100, 50, C4FCT_Left, C4FCT_Bottom));
::GraphicsResource.fctArrow.Draw(ccgo = cgo.GetFraction(70, 70, C4FCT_Right, C4FCT_Center), false, 0);
break;
case C4MN_Sell:
::GraphicsResource.fctFlagClr.DrawClr(ccgo = cgo.GetFraction(75, 75), true, dwColor);
::GraphicsResource.fctWealth.Draw(ccgo = cgo.GetFraction(100, 50, C4FCT_Left, C4FCT_Bottom));
::GraphicsResource.fctArrow.Draw(ccgo = cgo.GetFraction(70, 70, C4FCT_Right, C4FCT_Center), false, 1);
break;
}
}
bool C4Object::ActivateMenu(int32_t iMenu, int32_t iMenuSelect,
int32_t iMenuData, int32_t iMenuPosition,
C4Object *pTarget)
{
// Variables
C4FacetSurface fctSymbol;
C4IDList ListItems;
// Close any other menu
if (Menu && Menu->IsActive()) if (!Menu->TryClose(true, false)) return false;
// Create menu
if (!Menu) Menu = new C4ObjectMenu; else Menu->ClearItems();
// Open menu
switch (iMenu)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Activate:
// No target specified: use own container as target
if (!pTarget) if (!(pTarget=Contained)) break;
// Opening contents menu blocked by RejectContents
if (!!pTarget->Call(PSF_RejectContents)) return false;
// Create symbol
fctSymbol.Create(C4SymbolSize,C4SymbolSize);
pTarget->Def->Draw(fctSymbol,false,pTarget->Color,pTarget);
// Init
Menu->Init(fctSymbol,FormatString(LoadResStr("IDS_OBJ_EMPTY"),pTarget->GetName()).getData(),this,C4MN_Extra_None,0,iMenu);
Menu->SetPermanent(true);
Menu->SetRefillObject(pTarget);
// Success
return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Buy:
// No target specified: container is base
if (!pTarget) if (!(pTarget=Contained)) break;
// Create symbol
fctSymbol.Create(C4SymbolSize,C4SymbolSize);
DrawMenuSymbol(C4MN_Buy, fctSymbol, pTarget->Owner);
// Init menu
Menu->Init(fctSymbol,LoadResStr("IDS_PLR_NOBUY"),this,C4MN_Extra_Value,0,iMenu);
Menu->SetPermanent(true);
Menu->SetRefillObject(pTarget);
// Success
return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Sell:
// No target specified: container is base
if (!pTarget) if (!(pTarget=Contained)) break;
// Create symbol & init
fctSymbol.Create(C4SymbolSize,C4SymbolSize);
DrawMenuSymbol(C4MN_Sell, fctSymbol, pTarget->Owner);
Menu->Init(fctSymbol,FormatString(LoadResStr("IDS_OBJ_EMPTY"),pTarget->GetName()).getData(),this,C4MN_Extra_Value,0,iMenu);
Menu->SetPermanent(true);
Menu->SetRefillObject(pTarget);
// Success
return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Get:
case C4MN_Contents:
// No target specified
if (!pTarget) break;
// Opening contents menu blocked by RejectContents
if (!!pTarget->Call(PSF_RejectContents)) return false;
// Create symbol & init
fctSymbol.Create(C4SymbolSize,C4SymbolSize);
pTarget->Def->Draw(fctSymbol,false,pTarget->Color,pTarget);
Menu->Init(fctSymbol,FormatString(LoadResStr("IDS_OBJ_EMPTY"),pTarget->GetName()).getData(),this,C4MN_Extra_None,0,iMenu);
Menu->SetPermanent(true);
Menu->SetRefillObject(pTarget);
// Success
return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Info:
// Target by parameter
if (!pTarget) break;
// Create symbol & init menu
fctSymbol.Create(C4SymbolSize, C4SymbolSize); GfxR->fctOKCancel.Draw(fctSymbol,true,0,1);
Menu->Init(fctSymbol, pTarget->GetName(), this, C4MN_Extra_None, 0, iMenu, C4MN_Style_Info);
Menu->SetPermanent(true);
Menu->SetAlignment(C4MN_Align_Free);
C4Viewport *pViewport = ::Viewports.GetViewport(Controller); // Hackhackhack!!!
if (pViewport) Menu->SetLocation((pTarget->GetX() + pTarget->Shape.GetX() + pTarget->Shape.Wdt + 10 - pViewport->GetViewX()) * pViewport->GetZoom(),
(pTarget->GetY() + pTarget->Shape.GetY() - pViewport->GetViewY()) * pViewport->GetZoom());
// Add info item
fctSymbol.Create(C4PictureSize, C4PictureSize); pTarget->Def->Draw(fctSymbol, false, pTarget->Color, pTarget);
Menu->Add(pTarget->GetName(), fctSymbol, "", C4MN_Item_NoCount, NULL, pTarget->GetInfoString().getData());
fctSymbol.Default();
// Success
return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
// Invalid menu identification
CloseMenu(true);
return false;
}
bool C4Object::CloseMenu(bool fForce)
{
if (Menu)
{
if (Menu->IsActive()) if (!Menu->TryClose(fForce, false)) return false;
if (!Menu->IsCloseQuerying()) { delete Menu; Menu=NULL; } // protect menu deletion from recursive menu operation calls
}
return true;
}
BYTE C4Object::GetArea(int32_t &aX, int32_t &aY, int32_t &aWdt, int32_t &aHgt) const
{
if (!Status || !Def) return 0;
@ -1870,8 +1733,6 @@ void C4Object::ClearPointers(C4Object *pObj)
C4Command *cCom;
for (cCom=Command; cCom; cCom=cCom->Next)
cCom->ClearPointers(pObj);
// Menu
if (Menu) Menu->ClearPointers(pObj);
// Layer
if (Layer==pObj) Layer=NULL;
// gfx overlays
@ -2549,7 +2410,6 @@ void C4Object::Clear()
if (pEffects) { delete pEffects; pEffects=NULL; }
if (pSolidMaskData) { delete pSolidMaskData; pSolidMaskData=NULL; }
if (Menu) delete Menu; Menu=NULL;
if (MaterialContents) delete MaterialContents; MaterialContents=NULL;
// clear commands!
C4Command *pCom, *pNext;
@ -2657,8 +2517,6 @@ void C4Object::SyncClearance()
t_contact = 0;
// Update OCF
SetOCF();
// Menu
CloseMenu(true);
// Material contents
if (MaterialContents) delete MaterialContents; MaterialContents=NULL;
// reset speed of staticback-objects
@ -2759,9 +2617,6 @@ void C4Object::SetCommand(int32_t iCommand, C4Object *pTarget, C4Value iTx, int3
{
// Clear stack
ClearCommands();
// Close menu
if (fControl)
if (!CloseMenu(false)) return;
// Script overload
if (fControl)
if (!!Call(PSF_ControlCommand,&C4AulParSet(C4VString(CommandName(iCommand)),
@ -4410,13 +4265,6 @@ void C4Object::DirectComContents(C4Object *pTarget, bool fDoCalls)
if (!(Contents.ShiftContents(pTarget))) return;
// Selection sound
if (fDoCalls) if (!Contents.GetObject()->Call("~Selection", &C4AulParSet(C4VObj(this)))) StartSoundEffect("Clonk::Action::Grab",false,100,this);
// update menu with the new item in "put" entry
if (Menu && Menu->IsActive() && Menu->IsContextMenu())
{
Menu->Refill();
}
// Done
return;
}
void C4Object::GetParallaxity(int32_t *parX, int32_t *parY) const

View File

@ -153,10 +153,6 @@ public:
uint32_t Marker; // state var used by Objects::CrossCheck and C4FindObject - NoSave
C4ObjectPtr Layer;
C4DrawTransform *pDrawTransform; // assigned drawing transformation
// Menu
class C4ObjectMenu *Menu; // SyncClearance-NoSave //
C4Facet TopFace; // NoSave //
C4Def *Def;
C4ObjectPtr Contained;
@ -268,8 +264,6 @@ public:
bool At(int32_t ctx, int32_t cty) const;
bool At(int32_t ctx, int32_t cty, DWORD &ocf) const;
void GetOCFForPos(int32_t ctx, int32_t cty, DWORD &ocf) const;
bool CloseMenu(bool fForce);
bool ActivateMenu(int32_t iMenu, int32_t iMenuSelect=0, int32_t iMenuData=0, int32_t iMenuPosition=0, C4Object *pTarget=NULL);
int32_t ContactCheck(int32_t atx, int32_t aty, uint32_t *border_hack_contacts=0, bool collide_halfvehic=false);
bool Contact(int32_t cnat);
void StopAndContact(C4Real & ctco, C4Real limit, C4Real & speed, int32_t cnat);

View File

@ -26,7 +26,6 @@
#include <C4Command.h>
#include <C4Random.h>
#include <C4GameMessage.h>
#include <C4ObjectMenu.h>
#include <C4Player.h>
#include <C4GraphicsResource.h>
#include <C4Material.h>
@ -225,7 +224,6 @@ bool ObjectComUnGrab(C4Object *cObj)
C4Object *pTarget = cObj->Action.Target;
if (ObjectActionStand(cObj))
{
if (!cObj->CloseMenu(false)) return false;
cObj->Call(PSF_Grab, &C4AulParSet(C4VObj(pTarget), C4VBool(false)));
// clear action target
cObj->Action.Target = NULL;
@ -405,31 +403,10 @@ bool ObjectComPutTake(C4Object *cObj, C4Object *pTarget, C4Object *pThing) // by
// Has thing, put to target
if (pThing)
return ObjectComPut(cObj,pTarget,pThing);
// If target is own container, activate activation menu
if (pTarget==cObj->Contained)
return ObjectComTake(cObj); // carlo
// Assuming target is grabbed, check for grab get
if (pTarget->Def->GrabPutGet & C4D_Grab_Get)
{
// Activate get menu
return cObj->ActivateMenu(C4MN_Get,0,0,0,pTarget);
}
// Failure
return false;
}
// carlo
bool ObjectComTake(C4Object *cObj) // by C4CMD_Take
{
return cObj->ActivateMenu(C4MN_Activate);
}
// carlo
bool ObjectComTake2(C4Object *cObj) // by C4CMD_Take2
{
return cObj->ActivateMenu(C4MN_Get,0,0,0,cObj->Contained);
}
bool ObjectComPunch(C4Object *cObj, C4Object *pTarget, int32_t punch)
{
if (!cObj || !pTarget) return false;

View File

@ -717,13 +717,6 @@ void C4ObjectList::DrawSelectMark(C4TargetFacet &cgo) const
cLnk->Obj->DrawSelectMark(cgo);
}
void C4ObjectList::CloseMenus()
{
C4Object *cobj; C4ObjectLink *clnk;
for (clnk=First; clnk && (cobj=clnk->Obj); clnk=clnk->Next)
cobj->CloseMenu(true);
}
void C4ObjectList::Copy(const C4ObjectList &rList)
{
Clear(); Default();
@ -998,4 +991,4 @@ C4ObjectList::iterator C4ObjectList::ReverseView::begin() const
C4ObjectList::iterator C4ObjectList::ReverseView::end() const
{
return iterator(list, nullptr, true);
}
}

View File

@ -109,7 +109,6 @@ public:
void DrawIfCategory(C4TargetFacet &cgo, int iPlayer, uint32_t dwCat, bool fInvert); // draw all objects that match dwCat (or don't match if fInvert)
void Draw(C4TargetFacet &cgo, int iPlayer, int MinPlane, int MaxPlane); // draw all objects
void DrawSelectMark(C4TargetFacet &cgo) const;
void CloseMenus();
void UpdateGraphics(bool fGraphicsChanged);
void UpdateFaces(bool bUpdateShape);
void ClearInfo(C4ObjectInfo *pInfo);

View File

@ -1,316 +0,0 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, Matthes Bender
* Copyright (c) 2008-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
// Menus attached to objects; script created or internal
#include "C4Include.h"
#include "C4ObjectMenu.h"
#include "C4Control.h"
#include "C4Object.h"
#include "C4ObjectCom.h"
#include "C4Player.h"
#include "C4Viewport.h"
#include "C4MouseControl.h"
#include "C4GraphicsResource.h"
#include "C4Game.h"
#include "C4PlayerList.h"
#include "C4GameObjects.h"
// -----------------------------------------------------------
// C4ObjectMenu
C4ObjectMenu::C4ObjectMenu() : C4Menu()
{
Default();
}
void C4ObjectMenu::Default()
{
C4Menu::Default();
eCallbackType = CB_None;
Object = ParentObject = RefillObject = NULL;
RefillObjectContentsCount=0;
UserMenu = false;
CloseQuerying = false;
}
bool C4ObjectMenu::IsCloseDenied()
{
// abort if menu is permanented by script; stop endless recursive calls if user opens a new menu by CloseQuerying-flag
if (UserMenu && !CloseQuerying)
{
CloseQuerying = true;
bool fResult = false;
C4AulParSet pars(C4VInt(Selection), C4VObj(ParentObject));
if (eCallbackType == CB_Object)
{
if (Object) fResult = !!Object->Call(PSF_MenuQueryCancel, &pars);
}
else if (eCallbackType == CB_Scenario)
fResult = !!::GameScript.Call(PSF_MenuQueryCancel, &pars);
CloseQuerying = false;
if (fResult) return true;
}
// close OK
return false;
}
void C4ObjectMenu::LocalInit(C4Object *pObject, bool fUserMenu)
{
Object=pObject;
UserMenu=fUserMenu;
ParentObject=GetParentObject();
if (pObject) eCallbackType = CB_Object; else eCallbackType = CB_Scenario;
}
bool C4ObjectMenu::Init(C4FacetSurface &fctSymbol, const char *szEmpty, C4Object *pObject, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle, bool fUserMenu)
{
if (!DoInit(fctSymbol, szEmpty, iExtra, iExtraData, iId, iStyle)) return false;
LocalInit(pObject, fUserMenu);
return true;
}
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)
{
if (!DoInitRefSym(fctSymbol, szEmpty, iExtra, iExtraData, iId, iStyle)) return false;
LocalInit(pObject, fUserMenu);
return true;
}
void C4ObjectMenu::OnSelectionChanged(int32_t iNewSelection)
{
// do selection callback
if (UserMenu)
{
C4AulParSet pars(C4VInt(iNewSelection), C4VObj(ParentObject));
if (eCallbackType == CB_Object && Object)
Object->Call(PSF_MenuSelection, &pars);
else if (eCallbackType == CB_Scenario)
::GameScript.Call(PSF_MenuSelection, &pars);
}
}
void C4ObjectMenu::ClearPointers(C4Object *pObj)
{
if (Object==pObj) { Object=NULL; }
if (ParentObject==pObj) ParentObject=NULL; // Reason for menu close anyway.
if (RefillObject==pObj) RefillObject=NULL;
C4Menu::ClearPointers(pObj);
}
C4Object* C4ObjectMenu::GetParentObject()
{
for (C4Object *cObj : Objects)
if (cObj->Menu == this)
return cObj;
return NULL;
}
void C4ObjectMenu::SetRefillObject(C4Object *pObj)
{
RefillObject=pObj;
NeedRefill=true;
Refill();
}
bool C4ObjectMenu::DoRefillInternal(bool &rfRefilled)
{
// Variables
C4FacetSurface fctSymbol;
C4Object *pObj;
char szCaption[256+1],szCommand[256+1],szCommand2[256+1];
int32_t iCount;
C4Def *pDef;
C4IDList ListItems;
C4Object *pTarget;
C4Facet fctTarget;
// Refill
switch (Identification)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Activate:
// Clear items
ClearItems();
// Refill target
if (!(pTarget=RefillObject)) return false;
{
// Add target contents items
C4ObjectListIterator iter(pTarget->Contents);
while ((pObj = iter.GetNext(&iCount)))
{
pDef = pObj->Def;
if (pDef->NoGet) continue;
// Prefer fully constructed objects
if (~pObj->OCF & OCF_FullCon)
{
// easy way: only if first concat check matches
// this doesn't catch all possibilities, but that will rarely matter
C4Object *pObj2=pTarget->Contents.Find(pDef, ANY_OWNER, OCF_FullCon);
if (pObj2) if (pObj2->CanConcatPictureWith(pObj)) pObj = pObj2;
}
// Caption
sprintf(szCaption,LoadResStr("IDS_MENU_ACTIVATE"),(const char *) pObj->GetName());
// Picture
fctSymbol.Set(fctSymbol.Surface, 0,0,C4SymbolSize,C4SymbolSize);
pObj->Picture2Facet(fctSymbol);
// Commands
sprintf(szCommand,"SetCommand(\"Activate\",Object(%d))&&ExecuteCommand()",pObj->Number);
sprintf(szCommand2,"SetCommand(\"Activate\",nil,%d,0,Object(%d),%s)&&ExecuteCommand()",pTarget->Contents.ObjectCount(pDef->id),pTarget->Number,pDef->id.ToString());
// Add menu item
Add(szCaption,fctSymbol,szCommand,iCount,pObj,"",pDef->id,szCommand2,true,pObj->GetValue(pTarget, NO_OWNER));
// facet taken over (arrg!)
fctSymbol.Default();
}
}
break;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case C4MN_Get:
case C4MN_Contents:
// Clear items
ClearItems();
// Refill target
if (!(pTarget = RefillObject)) return false;
{
// Add target contents items
C4ObjectListIterator iter(pTarget->Contents);
while ((pObj = iter.GetNext(&iCount)))
{
pDef = pObj->Def;
if (pDef->NoGet) continue;
// Prefer fully constructed objects
if (~pObj->OCF & OCF_FullCon)
{
// easy way: only if first concat check matches
// this doesn't catch all possibilities, but that will rarely matter
C4Object *pObj2 = pTarget->Contents.Find(pDef, ANY_OWNER, OCF_FullCon);
if (pObj2) if (pObj2->CanConcatPictureWith(pObj)) pObj = pObj2;
}
// Determine whether to get or activate
bool fGet = true;
if (!(pObj->OCF & OCF_Carryable)) fGet = false; // not a carryable item
if (Identification == C4MN_Contents)
{
if (Object && !!Object->Call(PSF_RejectCollection, &C4AulParSet(C4VPropList(pObj->Def), C4VObj(pObj)))) fGet = false; // collection rejected
}
if (!(pTarget->OCF & OCF_Entrance)) fGet = true; // target object has no entrance: cannot activate - force get
// Caption
sprintf(szCaption, LoadResStr(fGet ? "IDS_MENU_GET" : "IDS_MENU_ACTIVATE"), (const char *)pObj->GetName());
// Picture
fctSymbol.Set(fctSymbol.Surface, 0, 0, C4SymbolSize, C4SymbolSize);
pObj->Picture2Facet(fctSymbol);
// Primary command: get/activate single object
sprintf(szCommand, "SetCommand(\"%s\", Object(%d)) && ExecuteCommand()", fGet ? "Get" : "Activate", pObj->Number);
// Secondary command: get/activate all objects of the chosen type
szCommand2[0] = 0; int32_t iAllCount;
if ((iAllCount = pTarget->Contents.ObjectCount(pDef->id)) > 1)
sprintf(szCommand2, "SetCommand(\"%s\", nil, %d,0, Object(%d), %s) && ExecuteCommand()", fGet ? "Get" : "Activate", iAllCount, pTarget->Number, pDef->id.ToString());
// Add menu item (with object)
Add(szCaption, fctSymbol, szCommand, iCount, pObj, "", pDef->id, szCommand2);
fctSymbol.Default();
}
}
break;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
default:
// Not an internal menu
return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
// Successfull internal refill
rfRefilled = true;
return true;
}
void C4ObjectMenu::Execute()
{
if (!IsActive()) return;
// Immediate refill check by RefillObject contents count check
if (RefillObject)
if (RefillObject->Contents.ObjectCount()!=RefillObjectContentsCount)
{ NeedRefill=true; RefillObjectContentsCount=RefillObject->Contents.ObjectCount(); }
// inherited
C4Menu::Execute();
}
void C4ObjectMenu::OnUserSelectItem(int32_t Player, int32_t iIndex)
{
// queue.... 2do
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Player,Game.PlayerControlDefs.InternalCons.CON_ObjectMenuSelect,iIndex | C4MN_AdjustPosition));
}
void C4ObjectMenu::OnUserEnter(int32_t Player, int32_t iIndex, bool fRight)
{
// object menu: Through queue 2do
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Player,fRight ? Game.PlayerControlDefs.InternalCons.CON_ObjectMenuOKAll : Game.PlayerControlDefs.InternalCons.CON_ObjectMenuOK,iIndex));
}
void C4ObjectMenu::OnUserClose()
{
// Queue 2do
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(::MouseControl.GetPlayer(),Game.PlayerControlDefs.InternalCons.CON_ObjectMenuCancel,0));
}
bool C4ObjectMenu::IsReadOnly()
{
// get viewport
C4Viewport *pVP = GetViewport();
if (!pVP) return false;
// is it an observer viewport?
if (pVP->fIsNoOwnerViewport)
// is this a synced menu?
if (eCallbackType == CB_Object || eCallbackType == CB_Scenario)
// then don't control it!
return true;
// if the player is eliminated, do not control either!
if (!pVP->fIsNoOwnerViewport)
{
C4Player *pPlr = ::Players.Get(::MouseControl.GetPlayer());
if (pPlr && pPlr->Eliminated) return true;
}
return false;
}
int32_t C4ObjectMenu::GetControllingPlayer()
{
// menu controlled by object controller
return Object ? Object->Controller : NO_OWNER;
}
bool C4ObjectMenu::MenuCommand(const char *szCommand, bool fIsCloseCommand)
{
switch (eCallbackType)
{
case CB_Object:
// Object menu
if (Object) Object->MenuCommand(szCommand);
break;
case CB_Scenario:
// Object menu with scenario script callback
::GameScript.DirectExec(NULL, szCommand, "MenuCommand");
break;
case CB_None:
// TODO
break;
}
return true;
}

View File

@ -1,89 +0,0 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, Matthes Bender
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
// Menus attached to objects; script created or internal
// These menus are shown to players if the target object is the current cursor
#ifndef INC_C4ObjectMenu
#define INC_C4ObjectMenu
#include "C4Menu.h"
enum
{
C4MN_None = 0,
/*C4MN_Construction = 1, obsolete, now reserved */
/*C4MN_Bridge = 2, obsolete, now reserved */
C4MN_Take = 3,
C4MN_Buy = 4,
C4MN_Sell = 5,
C4MN_Activate = 6,
/*C4MN_Hostility = 7, now defined in C4MainMenu*/
/*C4MN_Surrender = 8, obsolete, now reserved*/
/*C4MN_Put = 9, obsolete, now reserved*/
/*C4MN_Magic = 10, obsolete, now reserved*/
/*C4MN_Main = 12, now defined in C4MainMenu*/
C4MN_Get = 13,
/*C4MN_Context = 14, obsolete, now reserved*/
C4MN_Info = 15,
/*C4MN_TeamSelection= 16, now defined in C4MainMenu */
/*C4MN_TeamSwitch = 17, now defined in C4MainMenu */
C4MN_Contents = 18
};
class C4ObjectMenu : public C4Menu
{
public:
C4ObjectMenu();
virtual void Default();
enum CallbackType { CB_None=0, CB_Object, CB_Scenario };
protected:
C4Object *Object;
C4Object *ParentObject;
C4Object *RefillObject;
int32_t RefillObjectContentsCount;
CallbackType eCallbackType;
bool UserMenu; // set for script created menus; user menus do CloseQuery and MenuSelection callbacks
bool CloseQuerying; // recursion check for close query callback
void LocalInit(C4Object *pObject, bool fUserMenu);
public:
void SetRefillObject(C4Object *pObj);
void ClearPointers(C4Object *pObj);
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);
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 Execute();
virtual C4Object* GetParentObject();
bool IsCloseQuerying() const { return !!CloseQuerying; }
protected:
virtual bool MenuCommand(const char *szCommand, bool fIsCloseCommand);
virtual bool DoRefillInternal(bool &rfRefilled);
virtual void OnSelectionChanged(int32_t iNewSelection); // do object callbacks if selection changed in user menus
virtual bool IsCloseDenied(); // do MenuQueryCancel-callbacks for user menus
virtual bool IsReadOnly(); // determine whether the menu is just viewed by an observer, and should not issue any calls
virtual void OnUserSelectItem(int32_t Player, int32_t iIndex);
virtual void OnUserEnter(int32_t Player, int32_t iIndex, bool fRight);
virtual void OnUserClose();
virtual int32_t GetControllingPlayer();
};
#endif

View File

@ -28,7 +28,6 @@
#include <C4MeshAnimation.h>
#include <C4ObjectCom.h>
#include <C4ObjectInfo.h>
#include <C4ObjectMenu.h>
#include <C4Player.h>
#include <C4PlayerList.h>
#include <C4Random.h>
@ -786,358 +785,6 @@ static C4PropList* FnGetID(C4Object *Obj)
return Obj->GetPrototype();
}
static Nillable<C4ID> FnGetMenu(C4Object *Obj)
{
if (Obj->Menu && Obj->Menu->IsActive())
return C4ID(Obj->Menu->GetIdentification());
return C4Void();
}
static bool FnCreateMenu(C4Object *Obj, C4Def *pDef, C4Object *pCommandObj,
long iExtra, C4String *szCaption, long iExtraData,
long iStyle, bool fPermanent, C4ID idMenuID)
{
if (pCommandObj)
// object menu: Validate object
if (!pCommandObj->Status) return false;
// else scenario script callback: No command object OK
// Create symbol
C4FacetSurface fctSymbol;
fctSymbol.Create(C4SymbolSize,C4SymbolSize);
if (pDef) pDef->Draw(fctSymbol);
// Clear any old menu, init new menu
if (!Obj->CloseMenu(false)) return false;
if (!Obj->Menu) Obj->Menu = new C4ObjectMenu; else Obj->Menu->ClearItems();
Obj->Menu->Init(fctSymbol,FnStringPar(szCaption),pCommandObj,iExtra,iExtraData,(idMenuID ? idMenuID : pDef ? pDef->id : C4ID::None).GetHandle(),iStyle,true);
// Set permanent
Obj->Menu->SetPermanent(fPermanent);
return true;
}
const int C4MN_Add_ImgRank = 1,
C4MN_Add_ImgIndexed = 2,
C4MN_Add_ImgObjRank = 3,
C4MN_Add_ImgObject = 4,
C4MN_Add_ImgTextSpec = 5,
C4MN_Add_ImgColor = 6,
C4MN_Add_ImgPropListSpec = 7,
C4MN_Add_MaxImage = 127, // mask for param which decides what to draw as the menu symbol
C4MN_Add_PassValue = 128,
C4MN_Add_ForceCount = 256,
C4MN_Add_ForceNoDesc = 512;
#ifndef _MSC_VER
#define _snprintf snprintf
#endif
static bool FnAddMenuItem(C4Object *Obj, C4String * szCaption, C4String * szCommand, C4Def * pDef, int iCount, const C4Value & Parameter, C4String * szInfoCaption, int iExtra, const C4Value & XPar, const C4Value & XPar2)
{
if (!Obj->Menu) return false;
char caption[256+1];
char parameter[256+1];
char dummy[256+1];
char command[512+1];
char command2[512+1];
char infocaption[C4MaxTitle+1];
// get needed symbol size
int iSymbolSize = Obj->Menu->GetSymbolSize();
// Compose caption with def name
if (szCaption)
{
const char * s = FnStringPar(szCaption);
const char * sep = strstr(s, "%s");
if (sep && pDef)
{
strncpy(caption, s, std::min<intptr_t>(sep - s,256));
caption[std::min<intptr_t>(sep - s,256)] = 0;
strncat(caption, pDef->GetName(), 256);
strncat(caption, sep + 2, 256);
}
else
{
strncpy(caption, s, 256);
caption[256] = 0;
}
}
else
caption[0] = 0;
// create string to include type-information in command
switch (Parameter.GetType())
{
case C4V_Int:
sprintf(parameter, "%d", Parameter.getInt());
break;
case C4V_Bool:
SCopy(Parameter.getBool() ? "true" : "false", parameter);
break;
case C4V_PropList:
if (Parameter.getPropList()->GetObject())
sprintf(parameter, "Object(%d)", Parameter.getPropList()->GetObject()->Number);
else if (Parameter.getPropList()->GetDef())
sprintf(parameter, "C4Id(\"%s\")", Parameter.getPropList()->GetDef()->id.ToString());
else
throw C4AulExecError("proplist as parameter to AddMenuItem");
break;
case C4V_String:
// note this breaks if there is '"' in the string.
parameter[0] = '"';
SCopy(Parameter.getStr()->GetCStr(), parameter + 1, sizeof(command)-3);
SAppendChar('"', command);
break;
case C4V_Nil:
SCopy("nil", parameter);
break;
case C4V_Array:
// Arrays were never allowed, so tell the scripter
throw C4AulExecError("array as parameter to AddMenuItem");
default:
return false;
}
// own value
bool fOwnValue = false; long iValue=0;
if (iExtra & C4MN_Add_PassValue)
{
fOwnValue = true;
iValue = XPar2.getInt();
}
// New Style: native script command
size_t i = 0;
for (; i < SLen(FnStringPar(szCommand)); i++)
if (!IsIdentifier(FnStringPar(szCommand)[i]))
break;
if (i < SLen(FnStringPar(szCommand)))
{
// Search for "%d" an replace it by "%s" for insertion of formatted parameter
SCopy(FnStringPar(szCommand), dummy, 256);
char* pFound = const_cast<char*>(SSearch(dummy, "%d"));
if (pFound != 0)
*(pFound - 1) = 's';
// Compose left-click command
sprintf(command, dummy, parameter, 0);
// Compose right-click command
sprintf(command2, dummy, parameter, 1);
}
// Old style: function name with id and parameter
else
{
const char *szScriptCom = FnStringPar(szCommand);
if (szScriptCom && *szScriptCom)
{
if (iExtra & C4MN_Add_PassValue)
{
// with value
sprintf(command,"%s(%s,%s,0,%ld)",szScriptCom,pDef ? pDef->id.ToString() : "nil",parameter,iValue);
sprintf(command2,"%s(%s,%s,1,%ld)",szScriptCom,pDef ? pDef->id.ToString() : "nil",parameter,iValue);
}
else
{
// without value
sprintf(command,"%s(%s,%s)",szScriptCom,pDef ? pDef->id.ToString() : "nil",parameter);
sprintf(command2,"%s(%s,%s,1)",szScriptCom,pDef ? pDef->id.ToString() : "nil",parameter);
}
}
else
{
// no command
*command = *command2 = '\0';
}
}
// Info caption
SCopy(FnStringPar(szInfoCaption),infocaption,C4MaxTitle);
// Create symbol
C4FacetSurface fctSymbol;
C4DefGraphics* pGfx = NULL;
C4Object* pGfxObj = NULL;
switch (iExtra & C4MN_Add_MaxImage)
{
case C4MN_Add_ImgRank:
{
// symbol by rank
C4Facet *pfctRankSym = &::GraphicsResource.fctRank;
int32_t iRankSymNum = ::GraphicsResource.iNumRanks;
if (pDef && pDef->pRankSymbols)
{
pfctRankSym = pDef->pRankSymbols;
iRankSymNum = pDef->iNumRankSymbols;
}
C4RankSystem::DrawRankSymbol(&fctSymbol, iCount, pfctRankSym, iRankSymNum, true);
iCount=0;
break;
}
case C4MN_Add_ImgIndexed:
// draw indexed facet
fctSymbol.Create(iSymbolSize,iSymbolSize);
if (pDef)
pDef->Draw(fctSymbol, false, 0, NULL, XPar.getInt());
break;
case C4MN_Add_ImgObjRank:
{
// draw current gfx of XPar_C4V including rank
if (!XPar.CheckConversion(C4V_Object)) return false;
C4Object *pGfxObj = XPar.getObj();
if (pGfxObj && pGfxObj->Status)
{
// create graphics
// get rank gfx
C4Facet *pRankRes=&::GraphicsResource.fctRank;
long iRankCnt=::GraphicsResource.iNumRanks;
C4Def *pDef=pGfxObj->Def;
if (pDef->pRankSymbols)
{
pRankRes=pDef->pRankSymbols;
iRankCnt=pDef->iNumRankSymbols;
}
// context menu
C4Facet fctRank;
if (Obj->Menu->IsContextMenu())
{
// context menu entry: left object gfx
long C4MN_SymbolSize = Obj->Menu->GetItemHeight();
fctSymbol.Create(C4MN_SymbolSize * 2,C4MN_SymbolSize);
fctSymbol.Wdt = C4MN_SymbolSize;
pGfxObj->Def->Draw(fctSymbol, false, pGfxObj->Color, pGfxObj);
// right of it the rank
fctRank = fctSymbol;
fctRank.X = C4MN_SymbolSize;
fctSymbol.Wdt *= 2;
}
else
{
// regular menu: draw object picture
fctSymbol.Create(iSymbolSize,iSymbolSize);
pGfxObj->Def->Draw(fctSymbol, false, pGfxObj->Color, pGfxObj);
// rank at top-right corner
fctRank = fctSymbol;
fctRank.X = fctRank.Wdt - pRankRes->Wdt;
fctRank.Wdt = pRankRes->Wdt;
fctRank.Hgt = pRankRes->Hgt;
}
// draw rank
if (pGfxObj->Info)
{
C4Facet fctBackup = (const C4Facet &) fctSymbol;
fctSymbol.Set(fctRank);
C4RankSystem::DrawRankSymbol(&fctSymbol, pGfxObj->Info->Rank, pRankRes, iRankCnt, true);
fctSymbol.Set(fctBackup);
}
}
}
break;
case C4MN_Add_ImgObject:
{
// draw object picture
if (!XPar.CheckConversion(C4V_Object))
throw C4AulExecError(FormatString("call to \"%s\" parameter %d: got \"%s\", but expected \"%s\"!",
"AddMenuItem", 8, XPar.GetTypeName(), GetC4VName(C4V_Object)
).getData());
pGfxObj = XPar.getObj();
}
break;
case C4MN_Add_ImgTextSpec:
{
C4Def* pDef = C4Id2Def(C4ID(std::string(caption)));
if(pDef)
{
pGfx = &pDef->Graphics;
}
else
{
fctSymbol.Create(iSymbolSize,iSymbolSize);
uint32_t dwClr = XPar.getInt();
if (!szCaption || !Game.DrawTextSpecImage(fctSymbol, caption, NULL, dwClr ? dwClr : 0xff))
return false;
}
*caption = '\0';
}
break;
case C4MN_Add_ImgPropListSpec:
{
C4PropList *gfx_proplist = XPar.getPropList();
fctSymbol.Create(iSymbolSize,iSymbolSize);
if (!Game.DrawPropListSpecImage(fctSymbol, gfx_proplist))
return false;
}
break;
case C4MN_Add_ImgColor:
// draw colored def facet
fctSymbol.Create(iSymbolSize,iSymbolSize);
if (pDef)
pDef->Draw(fctSymbol, false, XPar.getInt());
break;
default:
// default: by def, if it is not specifically NONE
if (pDef)
{
fctSymbol.Create(iSymbolSize,iSymbolSize);
pDef->Draw(fctSymbol);
}
else
{
// otherwise: Clear symbol!
}
break;
}
// Convert default zero count to no count
if (iCount==0 && !(iExtra & C4MN_Add_ForceCount)) iCount=C4MN_Item_NoCount;
// menuitems without commands are never selectable
bool fIsSelectable = !!*command;
// Add menu item
if(pGfxObj)
Obj->Menu->Add(caption,pGfxObj,command,iCount,NULL,infocaption,pDef ? pDef->id : C4ID::None,command2,fOwnValue,iValue,fIsSelectable);
else if(pGfx)
Obj->Menu->Add(caption,pGfx,command,iCount,NULL,infocaption,pDef ? pDef->id : C4ID::None,command2,fOwnValue,iValue,fIsSelectable);
else
Obj->Menu->Add(caption,fctSymbol,command,iCount,NULL,infocaption,pDef ? pDef->id : C4ID::None,command2,fOwnValue,iValue,fIsSelectable);
return true;
}
static bool FnSelectMenuItem(C4Object *Obj, long iItem)
{
if (!Obj->Menu) return false;
return !!Obj->Menu->SetSelection(iItem, false, true);
}
static bool FnSetMenuDecoration(C4Object *Obj, C4ID idNewDeco)
{
if (!Obj->Menu) return false;
C4GUI::FrameDecoration *pNewDeco = new C4GUI::FrameDecoration();
if (!pNewDeco->SetByDef(idNewDeco))
{
delete pNewDeco;
return false;
}
Obj->Menu->SetFrameDeco(pNewDeco);
return true;
}
static bool FnSetMenuTextProgress(C4Object *Obj, long iNewProgress)
{
if (!Obj->Menu) return false;
return Obj->Menu->SetTextProgress(iNewProgress, false);
}
// Check / Status
static C4Object *FnContained(C4Object *Obj)
@ -1299,12 +946,6 @@ static long FnObjectNumber(C4Object *Obj)
// See FnObject
}
static long FnShowInfo(C4Object *Obj, C4Object *pObj)
{
if (!pObj) pObj=Obj; if (!pObj) return false;
return Obj->ActivateMenu(C4MN_Info,0,0,0,pObj);
}
static C4Void FnSetMass(C4Object *Obj, long iValue)
{
Obj->OwnMass=iValue-Obj->Def->Mass;
@ -1421,17 +1062,6 @@ static Nillable<long> FnGetClrModulation(C4Object *Obj, long iOverlayID)
return Obj->ColorMod;
}
static bool FnCloseMenu(C4Object *Obj)
{
return !!Obj->CloseMenu(true);
}
static Nillable<long> FnGetMenuSelection(C4Object *Obj)
{
if (!Obj->Menu || !Obj->Menu->IsActive()) return C4Void();
return Obj->Menu->GetSelection();
}
static bool FnCanConcatPictureWith(C4Object *Obj, C4Object *pObj)
{
// safety
@ -1536,15 +1166,6 @@ static long FnGetDefBottom(C4PropList * _this)
return 0;
}
static bool FnSetMenuSize(C4Object *Obj, long iCols, long iRows)
{
// get menu
C4Menu *pMnu=Obj->Menu;
if (!pMnu || !pMnu->IsActive()) return false;
pMnu->SetSize(Clamp<long>(iCols, 0, 50), Clamp<long>(iRows, 0, 50));
return true;
}
static bool FnGetCrewEnabled(C4Object *Obj)
{
// return status
@ -1593,16 +1214,6 @@ static C4Void FnDoCrewExp(C4Object *Obj, long iChange)
return C4Void();
}
static bool FnClearMenuItems(C4Object *Obj)
{
// check menu
if (!Obj->Menu) return false;
// clear the items
Obj->Menu->ClearItems();
// success
return true;
}
static C4Object *FnGetObjectLayer(C4Object *Obj)
{
// get layer object
@ -2476,28 +2087,6 @@ C4ScriptConstDef C4ScriptObjectConstMap[]=
{ "VIS_LayerToggle" ,C4V_Int, VIS_LayerToggle},
{ "VIS_OverlayOnly" ,C4V_Int, VIS_OverlayOnly},
{ "C4MN_Style_Normal" ,C4V_Int, C4MN_Style_Normal},
{ "C4MN_Style_Context" ,C4V_Int, C4MN_Style_Context},
{ "C4MN_Style_Info" ,C4V_Int, C4MN_Style_Info},
{ "C4MN_Style_Dialog" ,C4V_Int, C4MN_Style_Dialog},
{ "C4MN_Style_EqualItemHeight",C4V_Int, C4MN_Style_EqualItemHeight},
{ "C4MN_Extra_None" ,C4V_Int, C4MN_Extra_None},
{ "C4MN_Extra_Components" ,C4V_Int, C4MN_Extra_Components},
{ "C4MN_Extra_Value" ,C4V_Int, C4MN_Extra_Value},
{ "C4MN_Extra_Info" ,C4V_Int, C4MN_Extra_Info},
{ "C4MN_Add_ImgRank" ,C4V_Int, C4MN_Add_ImgRank},
{ "C4MN_Add_ImgIndexed" ,C4V_Int, C4MN_Add_ImgIndexed},
{ "C4MN_Add_ImgObjRank" ,C4V_Int, C4MN_Add_ImgObjRank},
{ "C4MN_Add_ImgObject" ,C4V_Int, C4MN_Add_ImgObject},
{ "C4MN_Add_ImgTextSpec" ,C4V_Int, C4MN_Add_ImgTextSpec},
{ "C4MN_Add_ImgPropListSpec",C4V_Int, C4MN_Add_ImgPropListSpec},
{ "C4MN_Add_ImgColor" ,C4V_Int, C4MN_Add_ImgColor},
{ "C4MN_Add_PassValue" ,C4V_Int, C4MN_Add_PassValue},
{ "C4MN_Add_ForceCount" ,C4V_Int, C4MN_Add_ForceCount},
{ "C4MN_Add_ForceNoDesc" ,C4V_Int, C4MN_Add_ForceNoDesc},
{ "GFXOV_MODE_None" ,C4V_Int, C4GraphicsOverlay::MODE_None }, // gfx overlay modes
{ "GFXOV_MODE_Base" ,C4V_Int, C4GraphicsOverlay::MODE_Base }, //
{ "GFXOV_MODE_Action" ,C4V_Int, C4GraphicsOverlay::MODE_Action }, //
@ -2612,7 +2201,6 @@ void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "GetOwner", FnGetOwner);
AddFunc(pEngine, "GetMass", FnGetMass);
AddFunc(pEngine, "GetBreath", FnGetBreath);
AddFunc(pEngine, "GetMenu", FnGetMenu);
AddFunc(pEngine, "GetVertexNum", FnGetVertexNum);
AddFunc(pEngine, "GetVertex", FnGetVertex);
AddFunc(pEngine, "SetVertex", FnSetVertex);
@ -2670,11 +2258,6 @@ void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "SetComponent", FnSetComponent);
AddFunc(pEngine, "SetCrewStatus", FnSetCrewStatus, false);
AddFunc(pEngine, "SetPosition", FnSetPosition);
AddFunc(pEngine, "CreateMenu", FnCreateMenu);
AddFunc(pEngine, "AddMenuItem", FnAddMenuItem);
AddFunc(pEngine, "SelectMenuItem", FnSelectMenuItem);
AddFunc(pEngine, "SetMenuDecoration", FnSetMenuDecoration);
AddFunc(pEngine, "SetMenuTextProgress", FnSetMenuTextProgress);
AddFunc(pEngine, "ObjectDistance", FnObjectDistance);
AddFunc(pEngine, "GetValue", FnGetValue);
AddFunc(pEngine, "GetRank", FnGetRank);
@ -2690,18 +2273,13 @@ void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "CanConcatPictureWith", FnCanConcatPictureWith);
AddFunc(pEngine, "SetGraphics", FnSetGraphics);
AddFunc(pEngine, "ObjectNumber", FnObjectNumber);
AddFunc(pEngine, "ShowInfo", FnShowInfo);
AddFunc(pEngine, "CheckVisibility", FnCheckVisibility);
AddFunc(pEngine, "SetClrModulation", FnSetClrModulation);
AddFunc(pEngine, "GetClrModulation", FnGetClrModulation);
AddFunc(pEngine, "CloseMenu", FnCloseMenu);
AddFunc(pEngine, "GetMenuSelection", FnGetMenuSelection);
AddFunc(pEngine, "GetDefBottom", FnGetDefBottom);
AddFunc(pEngine, "SetMenuSize", FnSetMenuSize);
AddFunc(pEngine, "GetCrewEnabled", FnGetCrewEnabled);
AddFunc(pEngine, "SetCrewEnabled", FnSetCrewEnabled);
AddFunc(pEngine, "DoCrewExp", FnDoCrewExp);
AddFunc(pEngine, "ClearMenuItems", FnClearMenuItems);
AddFunc(pEngine, "GetObjectLayer", FnGetObjectLayer);
AddFunc(pEngine, "SetObjectLayer", FnSetObjectLayer);
AddFunc(pEngine, "SetShape", FnSetShape);

View File

@ -33,7 +33,6 @@
#include <C4Log.h>
#include <C4FullScreen.h>
#include <C4GameOverDlg.h>
#include <C4ObjectMenu.h>
#include <C4MouseControl.h>
#include <C4GameMessage.h>
#include <C4GraphicsResource.h>
@ -112,8 +111,6 @@ void C4Player::ClearPointers(C4Object *pObj, bool fDeath)
if (ViewCursor==pObj) ViewCursor = NULL;
// View
if (ViewTarget==pObj) ViewTarget=NULL;
// Menu
Menu.ClearPointers(pObj);
// messageboard-queries
RemoveMessageBoardQuery(pObj);
}
@ -1217,7 +1214,7 @@ bool C4Player::ActivateMenuTeamSelection(bool fFromMain)
{
// Menu symbol/init
bool fSwitch = !(Status==PS_TeamSelection);
Menu.InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team),LoadResStr("IDS_MSG_SELTEAM"),Number, C4MN_Extra_None, 0, fSwitch ? C4MN_TeamSwitch : C4MN_TeamSelection);
Menu.InitRefSym(C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team),LoadResStr("IDS_MSG_SELTEAM"),Number, fSwitch ? C4MN_TeamSwitch : C4MN_TeamSelection);
Menu.SetAlignment(fSwitch ? C4MN_Align_Left | C4MN_Align_Bottom : 0);
Menu.Refill();
// Go back to options menu on close