Rework interaction menu into a new style. Also, style overloads are easily possible.
Because I did this in the test scenario first, it wasn't really possible to encapsulate different steps, sorry!master
|
@ -0,0 +1,7 @@
|
|||
[DefCore]
|
||||
id=GUI_MenuDeco2
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=1
|
||||
Height=1
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,100 @@
|
|||
/*-- Menu-Deco --*/
|
||||
|
||||
//func FrameDecorationBackClr() { return RGBa(25, 25, 25, 128); }
|
||||
func FrameDecorationBorderTop() { return 0; }
|
||||
func FrameDecorationBorderLeft() { return 0; }
|
||||
func FrameDecorationBorderRight() { return 0; }
|
||||
func FrameDecorationBorderBottom() { return 0; }
|
||||
|
||||
func Definition(def)
|
||||
{
|
||||
var corner_size = 2;
|
||||
var border_size = 2;
|
||||
var border_length = 28;
|
||||
|
||||
var offs = corner_size/2;
|
||||
var offs = corner_size/2;
|
||||
|
||||
SetProperty("ActMap", {
|
||||
FrameDecoTopLeft = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoTopLeft",
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Wdt = corner_size,
|
||||
Hgt = corner_size,
|
||||
OffX = -offs,
|
||||
OffY = -offs,
|
||||
},
|
||||
FrameDecoTopRight = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoTopRight",
|
||||
X = border_length + corner_size,
|
||||
Y = 0,
|
||||
Wdt = corner_size,
|
||||
Hgt = corner_size,
|
||||
OffX = 0,
|
||||
OffY = -offs,
|
||||
},
|
||||
FrameDecoBottomRight = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoBottomRight",
|
||||
X = border_length + corner_size,
|
||||
Y = border_length + corner_size,
|
||||
Wdt = corner_size,
|
||||
Hgt = corner_size,
|
||||
OffX = 0,
|
||||
OffY = 0,
|
||||
},
|
||||
FrameDecoBottomLeft = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoBottomLeft",
|
||||
X = 0,
|
||||
Y = border_length + corner_size,
|
||||
Wdt = corner_size,
|
||||
Hgt = corner_size,
|
||||
OffX = -offs,
|
||||
OffY = 0,
|
||||
},
|
||||
FrameDecoTop = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoTop",
|
||||
X = corner_size,
|
||||
Y = 0,
|
||||
Wdt = border_length,
|
||||
Hgt = border_size,
|
||||
OffX = 0,
|
||||
OffY = -offs,
|
||||
},
|
||||
FrameDecoRight = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoRight",
|
||||
X = corner_size + border_length,
|
||||
Y = corner_size,
|
||||
Wdt = border_size,
|
||||
Hgt = border_length,
|
||||
OffX = 0,
|
||||
OffY = 0,
|
||||
},
|
||||
FrameDecoBottom = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoBottom",
|
||||
X = corner_size,
|
||||
Y = border_length + corner_size,
|
||||
Wdt = border_length,
|
||||
Hgt = border_size,
|
||||
OffX = +offs,
|
||||
OffY = 0,
|
||||
},
|
||||
FrameDecoLeft = {
|
||||
Prototype = Action,
|
||||
Name = "FrameDecoLeft",
|
||||
X = 0,
|
||||
Y = corner_size,
|
||||
Wdt = border_size,
|
||||
Hgt = border_length,
|
||||
OffX = -offs,
|
||||
OffY = 0,
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
[DefCore]
|
||||
id=GUI_OIM_NewStyle
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
HideInCreator=true
|
|
@ -0,0 +1,736 @@
|
|||
/**
|
||||
This defines a menu style for the interaction menu.
|
||||
|
||||
The style definition is given to the interaction menu object upon creation when
|
||||
CreateFor()
|
||||
is called. See Library_ClonkControl, ObjectControl() if you want to provide a
|
||||
different, custom style.
|
||||
|
||||
The object interaction menu will need the following functions in the style definition
|
||||
to work properly:
|
||||
|
||||
Init(object menu)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
Does not expect any return value but can be used to manipulate the menu object in any
|
||||
way desired before the GUI is actually opened. In here, it is used to apply the
|
||||
settings.
|
||||
|
||||
CreateRootMenu(object menu, object center_column_menu, proplist description_box)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
center_column_menu: A dummy object, target for the center column
|
||||
description_box: A proplist, containing initial information for the description box
|
||||
Properties are:
|
||||
.target: A dummy object, target for the surrounding box
|
||||
.symbol_target: A dummy object, target for the symbol box
|
||||
.desc_target: A dummy object, target for the description box
|
||||
The function is called when the menu is first opened, but also during it being open
|
||||
but whenever a total reset of the menu is required.
|
||||
The return value has to be a proplist containing the overarching structure of the
|
||||
interaction menu. As is obvious from the parameters, the menu is expected to have two
|
||||
submenus: one called .center_column and one called .description_box (again with two submenus:
|
||||
.symbol_part and .desc_part). Though the actual placement of the elements is arbitrary (i.e.
|
||||
center_column does not have to be centered). The center column holds the 'move all' buttons.
|
||||
|
||||
CreateMainMenu(object menu, int slot, object target, object obj_for)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
slot: Either 0 or 1. 0: the left-hand menu, 1: the right-hand menu
|
||||
target: A dummy object, target for the main menu
|
||||
obj_for: The object this menu is opened for (which infos are displayed)
|
||||
This is to assemble the menu for a currently selected object. There are always two 'main' menus
|
||||
open, one at the left, one at the right. The displayed object is changed with the sidebar. The
|
||||
menu must not necessarily contain visual elements (but either the main menu, the part menu or the
|
||||
root menu should). The menu will be filled with entries generated from CreateMainMenuItem(). The
|
||||
assembled proplist must be returned.
|
||||
|
||||
CreateMainMenuItem(object menu, int slot, object target, proplist menu_entry, object cursor, int i)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
slot: Either 0 or 1. 0: the left-hand menu, 1: the right-hand menu
|
||||
target: A dummy object, target for the main menu
|
||||
menu_entry: A proplist with various attributes, as defined in the object interaction menu
|
||||
cursor: The player's current cursor (clonk)
|
||||
i: An ascending number
|
||||
The function should assemble and return a unified subelement for the main menu. The content is often
|
||||
up to the specific object whose entries are displayed. Some properties of menu_entry are irrelevant
|
||||
for the visuals, some are not (see Object Interaction Menu for a full list of possible entries).
|
||||
Subentries (like inventory objects) can be included in menu_entry.entries or added later or change
|
||||
dynamically (like inventory!).
|
||||
|
||||
CreateSideBar(object menu, int slot, object target)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
slot: Either 0 or 1. 0: the left-hand menu, 1: the right-hand menu
|
||||
target: A dummy object, target for the menu
|
||||
Assemble a sidebar element which is shown next to the main item and contains a list of all other
|
||||
object that could be displayed in the main menu (because they are available to the clonk). The
|
||||
menu will be filled with entries generated from CreateSideBarItem(). The assembled proplist
|
||||
must be returned.
|
||||
|
||||
CreateSideBarItem(object menu, int slot, object target, bool selected, bool crossed_out, bool cursor)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
slot: Either 0 or 1. 0: the left-hand menu, 1: the right-hand menu
|
||||
target: Object shown in this entry
|
||||
selected: True if the object is currently selected for the main menu
|
||||
crossed_out: True if the object should be unavailable for selection (usually because it is shown
|
||||
in the other main menu)
|
||||
cursor: The player's current cursor (clonk)
|
||||
The function should assemble and return a unified subelement for the sidebar. The visuals can be
|
||||
freely defined. Tabs are a good choice but not the only one.
|
||||
|
||||
CreatePartMenu(object menu, int slot, object target, proplist sidebar, proplist main)
|
||||
menu: The interaction menu object (GUI_ObjectInteractionMenu)
|
||||
slot: Either 0 or 1. 0: the left-hand menu, 1: the right-hand menu
|
||||
target: The object displayed in the 'main' menu
|
||||
sidebar: The complete proplist for the sidebar
|
||||
main: The complete proplist for the main menu
|
||||
The function is mainly expected to assemble to sidebar and the main object into one
|
||||
larger menu that does not need to have any visual elements. The finished proplist must
|
||||
be returned.
|
||||
|
||||
|
||||
The object interaction menu offers this callback in return:
|
||||
|
||||
ReopenWithSetting(string setting, any value)
|
||||
Closes the menu and reopens it wit a specific property (setting) set to a specific
|
||||
value. The property is even available in the Init() function.
|
||||
*/
|
||||
|
||||
// Coordinates in em
|
||||
|
||||
local SideBarSize = 40;
|
||||
local CenterColumnWidth = 50;
|
||||
|
||||
local ExtraData_Settings_Transparency = "InteractionMenu_NewStyle_Transp";
|
||||
local ExtraData_Settings_HideText = "InteractionMenu_NewStyle_THidden";
|
||||
local ExtraData_Settings_Saturation = "InteractionMenu_NewStyle_Saturat";
|
||||
|
||||
/* Callbacks from the menu that should be handled by the style */
|
||||
|
||||
public func ToggleSettings(object menu) // Open/Close additional settings
|
||||
{
|
||||
var value = true;
|
||||
if (menu.SettingsOpen != nil)
|
||||
value = !menu.SettingsOpen;
|
||||
|
||||
menu->ReopenWithSetting("SettingsOpen", value);
|
||||
}
|
||||
|
||||
public func ToggleBackground(object menu) // Change transparency of background
|
||||
{
|
||||
var owner = menu->GetOwner();
|
||||
if (owner == NO_OWNER)
|
||||
return; // NO_OWNER opened a menu?
|
||||
|
||||
// Settings are:
|
||||
// 0 = Semi-transparent background, opaque entries (Default)
|
||||
// 1 = Very transparent background, semi-transparent entries (maximum transparency)
|
||||
// 2 = Non-transparent backgrounds (minimum transparency)
|
||||
var value = 1;
|
||||
if (menu.BackgroundTransparency != nil)
|
||||
{
|
||||
value = menu.BackgroundTransparency + 1;
|
||||
if (value > 2)
|
||||
value = 0;
|
||||
}
|
||||
|
||||
SetPlrExtraData(owner, ExtraData_Settings_Transparency, value);
|
||||
menu->ReopenWithSetting("BackgroundTransparency", value);
|
||||
}
|
||||
|
||||
public func ToggleText(object menu) // Hide text captions
|
||||
{
|
||||
var owner = menu->GetOwner();
|
||||
if (owner == NO_OWNER)
|
||||
return; // NO_OWNER opened a menu?
|
||||
|
||||
// Settings are:
|
||||
// 0 = Captions are there (Default)
|
||||
// 1 = Captions are hidden
|
||||
var value = 1;
|
||||
if (menu.TextHidden != nil)
|
||||
{
|
||||
value = menu.TextHidden + 1;
|
||||
if (value > 1)
|
||||
value = 0;
|
||||
}
|
||||
|
||||
SetPlrExtraData(owner, ExtraData_Settings_HideText, value);
|
||||
menu->ReopenWithSetting("TextHidden", value);
|
||||
}
|
||||
|
||||
public func ToggleSaturation(object menu) // Desaturate the menu
|
||||
{
|
||||
var owner = menu->GetOwner();
|
||||
if (owner == NO_OWNER)
|
||||
return; // NO_OWNER opened a menu?
|
||||
|
||||
// Settings are:
|
||||
// 0 = With color (Default)
|
||||
// 1 = Without color
|
||||
var value = 1;
|
||||
if (menu.Saturation != nil)
|
||||
{
|
||||
value = menu.Saturation + 1;
|
||||
if (value > 1)
|
||||
value = 0;
|
||||
}
|
||||
|
||||
SetPlrExtraData(owner, ExtraData_Settings_Saturation, value);
|
||||
menu->ReopenWithSetting("Saturation", value);
|
||||
}
|
||||
|
||||
/* Everything called by Object Interation Menu */
|
||||
|
||||
// Initialization of the menu
|
||||
public func Init(object menu)
|
||||
{
|
||||
var owner = menu->GetOwner();
|
||||
if (owner == NO_OWNER)
|
||||
return; // NO_OWNER opened a menu?
|
||||
|
||||
// Set background transparency setting
|
||||
if (menu.BackgroundTransparency == nil)
|
||||
{
|
||||
if (GetPlrExtraData(owner, ExtraData_Settings_Transparency) != nil)
|
||||
menu.BackgroundTransparency = GetPlrExtraData(owner, ExtraData_Settings_Transparency);
|
||||
else
|
||||
menu.BackgroundTransparency = 0;
|
||||
}
|
||||
|
||||
// Set caption display setting
|
||||
if (menu.TextHidden == nil)
|
||||
{
|
||||
if (GetPlrExtraData(owner, ExtraData_Settings_HideText) != nil)
|
||||
menu.TextHidden = GetPlrExtraData(owner, ExtraData_Settings_HideText);
|
||||
else
|
||||
menu.TextHidden = 0;
|
||||
}
|
||||
|
||||
// Set saturation setting
|
||||
if (menu.Saturation == nil)
|
||||
{
|
||||
if (GetPlrExtraData(owner, ExtraData_Settings_Saturation) != nil)
|
||||
menu.Saturation = GetPlrExtraData(owner, ExtraData_Settings_Saturation);
|
||||
else
|
||||
menu.Saturation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Root menu is the overall surrounding structure of the menu
|
||||
// Parameters are: Interaction Menu Object, Dummy Object for center column, Dummy Object for description box
|
||||
public func CreateRootMenu(object menu, object center_column_menu, proplist description_box)
|
||||
{
|
||||
var owner = menu->GetOwner();
|
||||
if (owner == NO_OWNER)
|
||||
return; // NO_OWNER opened a menu?
|
||||
|
||||
// Assemble button row (Close, Settings, Background change, Hide text)
|
||||
var buttons_height = 40;
|
||||
if (menu.SettingsOpen)
|
||||
buttons_height = 100;
|
||||
|
||||
var close_button =
|
||||
{
|
||||
Tooltip = "$TooltipClose$",
|
||||
Priority = 0x0fffff,
|
||||
Left = "0%", Top = "0%+0em",
|
||||
Right = "100%", Bottom = "0%+2em",
|
||||
Symbol = Icon_Cancel,
|
||||
BackgroundColor = {Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(menu, "Close")
|
||||
};
|
||||
|
||||
var settings_button =
|
||||
{
|
||||
Tooltip = "$TooltipSettings$",
|
||||
Priority = 0x0ffffe,
|
||||
Left = "0%", Top = "0%+2em",
|
||||
Right = "100%", Bottom = "0%+4em",
|
||||
Symbol = Icon_Settings,
|
||||
BackgroundColor = {Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "ToggleSettings", menu)
|
||||
};
|
||||
if (menu.SettingsOpen)
|
||||
settings_button.Tooltip = "$TooltipSettingsClose$";
|
||||
|
||||
var background_change =
|
||||
{
|
||||
Tooltip = "$TooltipBackground$",
|
||||
Priority = 0x0ffffd,
|
||||
Left = "0%", Top = "0%+4em",
|
||||
Right = "100%", Bottom = "0%+6em",
|
||||
Symbol = Icon_ChangeBackground,
|
||||
BackgroundColor = {Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "ToggleBackground", menu)
|
||||
};
|
||||
|
||||
var hide_text =
|
||||
{
|
||||
Tooltip = "$TooltipHideText$",
|
||||
Priority = 0x0ffffd,
|
||||
Left = "0%", Top = "0%+6em",
|
||||
Right = "100%", Bottom = "0%+8em",
|
||||
Symbol = Icon_HideText,
|
||||
BackgroundColor = {Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "ToggleText", menu)
|
||||
};
|
||||
if (menu.TextHidden == 1)
|
||||
{
|
||||
hide_text.Tooltip = "$TooltipShowText$";
|
||||
hide_text.GraphicsName = "Show";
|
||||
}
|
||||
|
||||
var saturation =
|
||||
{
|
||||
Tooltip = "$TooltipWithoutSaturation$",
|
||||
Priority = 0x0ffffc,
|
||||
Left = "0%", Top = "0%+8em",
|
||||
Right = "100%", Bottom = "0%+10em",
|
||||
Symbol = Icon_ChangeColor,
|
||||
GraphicsName = "Grey",
|
||||
BackgroundColor = {Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "ToggleSaturation", menu)
|
||||
};
|
||||
if (menu.Saturation == 1)
|
||||
{
|
||||
saturation.Tooltip = "$TooltipWithSaturation$";
|
||||
saturation.GraphicsName = nil;
|
||||
}
|
||||
|
||||
// For the description box
|
||||
var background_color = RGBa(25,25,25, 200);
|
||||
if (menu.BackgroundTransparency == 1)
|
||||
background_color = RGBa(25,25,25, 100);
|
||||
if (menu.BackgroundTransparency == 2)
|
||||
background_color = RGBa(25,25,25, 255);
|
||||
|
||||
// Assemble the menu
|
||||
var root_menu =
|
||||
{
|
||||
Target = menu,
|
||||
// Open just below the inventory bar, -20 to counter the standard margin
|
||||
Top = ToEmString(GUI_Controller_InventoryBar_IconMarginScreenTop * 2 + GUI_Controller_InventoryBar_IconSize + GUI_Controller_InventoryBar_IconSize/2 - 20),
|
||||
Style = GUI_NoCrop,
|
||||
// Mostly transparent but shows the 'transfer all' buttons
|
||||
center_column =
|
||||
{
|
||||
// -10 because the button bar takes up 2em on the right side
|
||||
Left = Format("50%% %s", ToEmString(-CenterColumnWidth / 2 - 10)),
|
||||
Right = Format("50%% %s", ToEmString(CenterColumnWidth / 2 - 10)),
|
||||
Top = "1.5em",
|
||||
Bottom = "4.5em",
|
||||
Style = GUI_VerticalLayout,
|
||||
move_all_left =
|
||||
{
|
||||
Target = center_column_menu,
|
||||
ID = 10 + 0,
|
||||
Right = ToEmString(CenterColumnWidth), Bottom = "1.5em",
|
||||
Margin = ["0.1em"],
|
||||
Style = GUI_TextHCenter | GUI_TextVCenter,
|
||||
Symbol = Icon_MoveItems, GraphicsName = "Left",
|
||||
Tooltip = "$TooltipTransferAllLeft$",
|
||||
BackgroundColor ={Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(menu, "OnMoveAllToClicked", 0)
|
||||
},
|
||||
move_all_right =
|
||||
{
|
||||
Target = center_column_menu,
|
||||
ID = 10 + 1,
|
||||
Right = ToEmString(CenterColumnWidth), Bottom = "1.5em",
|
||||
Margin = ["0.1em"],
|
||||
Style = GUI_TextHCenter | GUI_TextVCenter,
|
||||
Symbol = Icon_MoveItems,
|
||||
Tooltip = "$TooltipTransferAllRight$",
|
||||
BackgroundColor ={Std = nil, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(menu, "OnMoveAllToClicked", 1)
|
||||
}
|
||||
},
|
||||
// Show descriptive texts when hovering stuff
|
||||
description_box =
|
||||
{
|
||||
Top = "100%-5em",
|
||||
Right = "100% - 2em",
|
||||
Margin = [ToEmString(SideBarSize), "0em"],
|
||||
Decoration = GUI_MenuDeco2,
|
||||
BackgroundColor = background_color,
|
||||
symbol_part =
|
||||
{
|
||||
Right = "5em",
|
||||
Symbol = nil,
|
||||
Margin = "0.2em",
|
||||
ID = 1,
|
||||
Target = description_box.symbol_target
|
||||
},
|
||||
desc_part =
|
||||
{
|
||||
Left = "5em",
|
||||
Margin = "0.2em",
|
||||
ID = 1,
|
||||
Target = description_box.target,
|
||||
real_contents = // nested one more time so it can dynamically be replaced without messing up the layout
|
||||
{
|
||||
ID = 1,
|
||||
Target = description_box.desc_target
|
||||
}
|
||||
}
|
||||
},
|
||||
// Buttons bar at the top right
|
||||
buttons =
|
||||
{
|
||||
ID = 10 + 2,
|
||||
Left = "100%-2em",
|
||||
Top = "0%+0em",
|
||||
Right = "100%",
|
||||
Bottom = ToEmString(buttons_height),
|
||||
Decoration = GUI_MenuDecoInventoryHeader
|
||||
}
|
||||
};
|
||||
|
||||
GuiAddSubwindow(close_button, root_menu.buttons);
|
||||
GuiAddSubwindow(settings_button, root_menu.buttons);
|
||||
if (menu.SettingsOpen)
|
||||
{
|
||||
GuiAddSubwindow(background_change, root_menu.buttons);
|
||||
GuiAddSubwindow(hide_text, root_menu.buttons);
|
||||
GuiAddSubwindow(saturation, root_menu.buttons);
|
||||
}
|
||||
|
||||
return root_menu;
|
||||
}
|
||||
|
||||
// Assemble the main menu and the sidebar into a surrounding structure
|
||||
// There are always two part menus open
|
||||
// Parameters are: Interaction Menu Object, Slot of the current sidebar (either 0 or 1, left/right), Menu target (probably the same as the first parameter but can change), the sidebar menu, the main menu
|
||||
public func CreatePartMenu(object menu, int slot, object target, proplist sidebar, proplist main)
|
||||
{
|
||||
// Stretch from left border to center column
|
||||
var part_menu =
|
||||
{
|
||||
Left = "0%", Right = Format("50%% %s", ToEmString(-CenterColumnWidth / 2 - 10)),
|
||||
sidebar = sidebar, main = main,
|
||||
Target = target,
|
||||
ID = 1,
|
||||
Style = GUI_NoCrop
|
||||
};
|
||||
|
||||
// Right part menu will stretch from center column to the button bar
|
||||
if (slot == 1)
|
||||
{
|
||||
part_menu.Left = Format("50%% %s", ToEmString(CenterColumnWidth / 2 - 10));
|
||||
part_menu.Right = "100%-2em";
|
||||
}
|
||||
|
||||
return part_menu;
|
||||
}
|
||||
|
||||
// Main menu is the big information menu for a single inspected object
|
||||
// So there are always two 'main' menus open
|
||||
// Parameters are: Interaction Menu Object, Slot of the current main menu (either 0 or 1, left/right), Dummy menu target, Object whose settings are displayed
|
||||
public func CreateMainMenu(object menu, int slot, object target, object obj_for)
|
||||
{
|
||||
var background_color = RGBa(25,25,25, 200);
|
||||
if (menu.BackgroundTransparency == 1)
|
||||
background_color = RGBa(25,25,25, 100);
|
||||
if (menu.BackgroundTransparency == 2)
|
||||
background_color = RGBa(25,25,25, 255);
|
||||
|
||||
var big_menu =
|
||||
{
|
||||
Target = target,
|
||||
Priority = 5,
|
||||
Right = Format("100%% %s", ToEmString(-SideBarSize)),
|
||||
Bottom = "100% - 5.5em",
|
||||
Decoration = GUI_MenuDeco2,
|
||||
BackgroundColor = background_color,
|
||||
container =
|
||||
{
|
||||
Priority = 7,
|
||||
Top = "1em",
|
||||
Style = GUI_VerticalLayout,
|
||||
Margin = ["0.1em"],
|
||||
},
|
||||
headline =
|
||||
{
|
||||
Priority = 7,
|
||||
Bottom = "1em",
|
||||
Text = obj_for->GetName(),
|
||||
Style = GUI_TextHCenter | GUI_TextVCenter,
|
||||
},
|
||||
};
|
||||
|
||||
if (slot == 0)
|
||||
{
|
||||
big_menu.Left = ToEmString(SideBarSize);
|
||||
big_menu.Right = "100%";
|
||||
}
|
||||
|
||||
return big_menu;
|
||||
}
|
||||
|
||||
// Create a single information menu (row) in the main menu
|
||||
// Parameters are: Interaction Menu Object, Slot of the current main menu (either 0 or 1, left/right), Object whose settings are displayed, the menu information, the player's cursor, an ascending integer
|
||||
// This function should create a GUI target (like MenuStyle_Grid)
|
||||
// menu can have the following properties:
|
||||
// flag: Marking special entries (currently only contents), if not set should be set to InteractionMenu_Custom
|
||||
// title: The entry's caption
|
||||
// entries: An array of proplists with subentries ({ symbol, text, unique_index, custom })
|
||||
// entries_callback: A callback the interaction menu will ask for subentries (subentries is most likely empty if given)
|
||||
// callback: A callback if the entry is clicked
|
||||
// callback_hover: A callback if the entry is hovered over
|
||||
// callback_target: Target object for the callback
|
||||
// Anything that goes into scripted GUIs anyway (see documentation)
|
||||
// Most of these entries are of no concern to this function and can be ignored
|
||||
public func CreateMainMenuItem(object menu, int slot, object target, proplist menu_entry, object cursor, int i)
|
||||
{
|
||||
// Create a basic layout object
|
||||
menu_entry.menu_object = CreateObject(MenuStyle_Grid);
|
||||
|
||||
// Special display settings for contents entries
|
||||
if (menu_entry.flag == InteractionMenu_Contents)
|
||||
{
|
||||
menu_entry.menu_object->SetTightGridLayout();
|
||||
}
|
||||
|
||||
// Settings
|
||||
menu_entry.menu_object.Top = "+1em";
|
||||
menu_entry.menu_object.Priority = 7;
|
||||
menu_entry.menu_object->SetPermanent();
|
||||
menu_entry.menu_object->SetFitChildren();
|
||||
menu_entry.menu_object->SetMouseOverCallback(menu, "OnMenuEntryHover");
|
||||
|
||||
// Handle subentries
|
||||
for (var e = 0; e < GetLength(menu_entry.entries); ++e)
|
||||
{
|
||||
var entry = menu_entry.entries[e];
|
||||
entry.unique_index = ++menu_entry.entry_index_count;
|
||||
// This also allows the interaction-menu user to supply a custom entry with custom layout f.e.
|
||||
var added_entry = menu_entry.menu_object->AddItem(entry.symbol, entry.text, entry.unique_index, menu, "OnMenuEntrySelected", { slot = slot, index = i }, entry["custom"]);
|
||||
}
|
||||
|
||||
// Assemble the entry
|
||||
var all =
|
||||
{
|
||||
Priority = menu_entry.Priority ?? i,
|
||||
Style = GUI_FitChildren,
|
||||
// Caption
|
||||
title_bar =
|
||||
{
|
||||
Priority = (menu_entry.Priority ?? i) - 2,
|
||||
Style = GUI_TextVCenter | GUI_TextHCenter,
|
||||
Bottom = "+1em",
|
||||
Text = menu_entry.title,
|
||||
// Visual separation at the top
|
||||
hline = {Bottom = "0.05em", BackgroundColor = RGB(100, 100, 100)},
|
||||
},
|
||||
hline = {Top = "1em", Bottom = "1.05em", BackgroundColor = RGB(100, 100, 100), Priority = (menu_entry.Priority ?? i) - 1},
|
||||
Margin = [nil, nil, nil, "0.25em"],
|
||||
// The content of this entry
|
||||
real_menu = menu_entry.menu_object,
|
||||
spacer = {Left = "0em", Right = "0em", Bottom = "3em"} // guarantees a minimum height
|
||||
};
|
||||
|
||||
// Background color according to transparency setting
|
||||
var background_color = nil;
|
||||
|
||||
// Background color is defined
|
||||
if (menu_entry.BackgroundColor)
|
||||
{
|
||||
if (menu.BackgroundTransparency == 0)
|
||||
background_color = SetRGBaValue(menu_entry.BackgroundColor, Min(200, GetRGBaValue(menu_entry.BackgroundColor, RGBA_ALPHA)), RGBA_ALPHA);
|
||||
if (menu.BackgroundTransparency == 1)
|
||||
background_color = SetRGBaValue(menu_entry.BackgroundColor, Min(100, GetRGBaValue(menu_entry.BackgroundColor, RGBA_ALPHA)), RGBA_ALPHA);
|
||||
if (menu.BackgroundTransparency == 2)
|
||||
background_color = menu_entry.BackgroundColor;
|
||||
}
|
||||
// Menu decoration is defined
|
||||
else if (menu_entry.Decoration)
|
||||
{
|
||||
background_color = menu_entry.Decoration->FrameDecorationBackClr();
|
||||
if (menu.BackgroundTransparency == 0)
|
||||
background_color = SetRGBaValue(menu_entry.Decoration->FrameDecorationBackClr(), Min(200, GetRGBaValue(menu_entry.Decoration->FrameDecorationBackClr(), RGBA_ALPHA)), RGBA_ALPHA);
|
||||
if (menu.BackgroundTransparency == 1)
|
||||
background_color = SetRGBaValue(menu_entry.Decoration->FrameDecorationBackClr(), Min(100, GetRGBaValue(menu_entry.Decoration->FrameDecorationBackClr(), RGBA_ALPHA)), RGBA_ALPHA);
|
||||
//if (menu.BackgroundTransparency == 2)
|
||||
// No change required
|
||||
}
|
||||
|
||||
// Menu color saturation
|
||||
if (background_color)
|
||||
{
|
||||
if (menu.Saturation == 1)
|
||||
{
|
||||
var alpha = GetRGBaValue(background_color, RGBA_ALPHA);
|
||||
var val = RGB2HSL(background_color);
|
||||
// Desaturate
|
||||
if (GetRGBaValue(val, RGBA_GREEN) > 10)
|
||||
val = SetRGBaValue(val, 10, RGBA_GREEN);
|
||||
// Increase light
|
||||
if (GetRGBaValue(val, RGBA_BLUE) < 50)
|
||||
val = SetRGBaValue(val, 50, RGBA_BLUE);
|
||||
val = HSL2RGB(val);
|
||||
// Restore alpha
|
||||
val = SetRGBaValue(val, alpha, RGBA_ALPHA);
|
||||
background_color = val;
|
||||
}
|
||||
}
|
||||
|
||||
//menu_entry.menu_object.BackgroundColor = background_color;
|
||||
all.BackgroundColor = background_color;
|
||||
|
||||
// Hide captions?
|
||||
if (menu.TextHidden)
|
||||
{
|
||||
all.title_bar.Text = nil;
|
||||
all.title_bar.Bottom = "0.05em";
|
||||
all.title_bar.hline.Bottom = nil;
|
||||
all.real_menu.Top = "0.05em";
|
||||
all.spacer.Bottom = "2.05em";
|
||||
all.hline = nil;
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
// The sidebar shows all available objects to display as tabs
|
||||
// There are always two sidebars open (one left, one right)
|
||||
// Parameters are: Interaction Menu Object, Slot of the current sidebar (either 0 or 1, left/right), Menu target (probably the same as the first parameter but can change)
|
||||
public func CreateSideBar(object menu, int slot, object target)
|
||||
{
|
||||
// Entries will be inserted in the next step
|
||||
var sidebar =
|
||||
{
|
||||
Priority = 10,
|
||||
Right = ToEmString(SideBarSize),
|
||||
Style = GUI_VerticalLayout,
|
||||
Target = target,
|
||||
ID = 2
|
||||
};
|
||||
|
||||
if (slot == 1)
|
||||
{
|
||||
sidebar.Left = Format("100%% %s", ToEmString(-SideBarSize));
|
||||
sidebar.Right = "100%";
|
||||
}
|
||||
|
||||
return sidebar;
|
||||
}
|
||||
|
||||
// Create a single sidebar item (/entry)
|
||||
// Parameters are: Interaction Menu Object, Slot of the current sidebar (either 0 or 1, left/right), Object shown in the entry, is the entry selected, is the entry selected on the other side, is the entry the player's cursor
|
||||
public func CreateSideBarItem(object menu, int slot, object target, bool selected, bool crossed_out, bool cursor)
|
||||
{
|
||||
// For sorting: the vertical layout will sort by priority
|
||||
var priority = 10000 - target.Plane;
|
||||
// The cursor should always be at the top
|
||||
if (cursor)
|
||||
priority = 1;
|
||||
|
||||
var background_symbol = "";
|
||||
var highlight_symbol = "Highlight";
|
||||
if (selected)
|
||||
{
|
||||
background_symbol = "Selected";
|
||||
highlight_symbol = "Selected";
|
||||
}
|
||||
|
||||
if (slot == 1)
|
||||
{
|
||||
background_symbol = "Right";
|
||||
highlight_symbol = "RightHighlight";
|
||||
if (selected)
|
||||
{
|
||||
background_symbol = "RightSelected";
|
||||
highlight_symbol = "RightSelected";
|
||||
}
|
||||
}
|
||||
|
||||
var deactivation_symbol = nil;
|
||||
if (crossed_out)
|
||||
deactivation_symbol = Icon_Cancel;
|
||||
|
||||
// Coordinates for the little picture & name
|
||||
var left = "2.25em";
|
||||
var right = "4em";
|
||||
var top = "0%";
|
||||
var bottom = "1.75em";
|
||||
var text_margin = [nil, nil, "0.25em", nil];
|
||||
var text_style = GUI_TextRight | GUI_TextTop | GUI_FitChildren;
|
||||
|
||||
if (slot == 1)
|
||||
{
|
||||
left = "0%";
|
||||
right = "1.5em";
|
||||
var text_margin = ["0.25em", nil, nil, nil];
|
||||
var text_style = GUI_TextLeft | GUI_TextTop | GUI_FitChildren;
|
||||
}
|
||||
|
||||
var entry =
|
||||
{
|
||||
// The object is added as the target of the entry, so it can easily be identified later.
|
||||
// For example, to apply show the grey haze to indicate that it cannot be clicked.
|
||||
Target = target,
|
||||
Right = ToEmString(SideBarSize), Bottom = "2.75em",
|
||||
Priority = priority,
|
||||
Style = GUI_FitChildren,
|
||||
OnMouseIn = GuiAction_SetTag("OnHover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(menu, "OnSidebarEntrySelected", {slot = slot, obj = target}),
|
||||
Priority = 1,
|
||||
obj_background = {
|
||||
Top = top,
|
||||
Left = left,
|
||||
Right = right,
|
||||
Bottom = bottom,
|
||||
Symbol = Icon_Menu_Tab,
|
||||
GraphicsName = { Std = background_symbol, OnHover = highlight_symbol },
|
||||
Priority = 2
|
||||
},
|
||||
obj_symbol = {
|
||||
Top = top,
|
||||
Left = left,
|
||||
Right = right,
|
||||
Bottom = bottom,
|
||||
Symbol = target,
|
||||
Priority = 3
|
||||
},
|
||||
obj_symbol_deactivated = {
|
||||
Target = target,
|
||||
ID = 1 + slot,
|
||||
Top = top,
|
||||
Left = left,
|
||||
Right = right,
|
||||
Bottom = bottom,
|
||||
Symbol = deactivation_symbol,
|
||||
Priority = 4
|
||||
},
|
||||
obj_name = {
|
||||
Style = text_style,
|
||||
Top = "1.75em",
|
||||
Bottom = "2.75em",
|
||||
Margin = text_margin,
|
||||
Text = target->GetName(),
|
||||
Priority = 5
|
||||
}
|
||||
};
|
||||
|
||||
// Hide object's name if the option is selected
|
||||
if (menu.TextHidden)
|
||||
{
|
||||
entry.obj_name = nil;
|
||||
entry.Bottom = "1.75em";
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
TooltipClose=Schließen
|
||||
|
||||
TooltipSettings=Einstellungen öffnen
|
||||
TooltipSettingsClose=Einstellungen schließen
|
||||
|
||||
TooltipBackground=Hintergrundtransparenz umstellen
|
||||
|
||||
TooltipHideText=Überschriften verbergen
|
||||
TooltipShowText=Überschriften anzeigen
|
||||
|
||||
TooltipWithSaturation=Menüfarben anzeigen
|
||||
TooltipWithoutSaturation=Menüfarben ausblenden
|
||||
|
||||
TooltipTransferAllLeft=Gesamtes Inventar nach links schieben.
|
||||
TooltipTransferAllRight=Gesamtes Inventar nach rechts schieben.
|
|
@ -0,0 +1,15 @@
|
|||
TooltipClose=Close
|
||||
|
||||
TooltipSettings=Open settings
|
||||
TooltipSettingsClose=Close settings
|
||||
|
||||
TooltipBackground=Toggle background transparency
|
||||
|
||||
TooltipHideText=Hide captions
|
||||
TooltipShowText=Show captions
|
||||
|
||||
TooltipWithSaturation=Show menu colors
|
||||
TooltipWithoutSaturation=Hide menu colors
|
||||
|
||||
TooltipTransferAllLeft=Transfer inventory to the left.
|
||||
TooltipTransferAllRight=Transfer inventory to the right.
|
|
@ -8,8 +8,6 @@
|
|||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
||||
static const InteractionMenu_SideBarSize = 40; // in tenth-em
|
||||
|
||||
static const InteractionMenu_Contents = 2;
|
||||
static const InteractionMenu_Custom = 4;
|
||||
|
||||
|
@ -111,7 +109,7 @@ func Destruction()
|
|||
}
|
||||
|
||||
// used as a static function
|
||||
func CreateFor(object cursor)
|
||||
func CreateFor(object cursor, id style_def, array settings)
|
||||
{
|
||||
var obj = CreateObject(GUI_ObjectInteractionMenu, AbsX(0), AbsY(0), cursor->GetOwner());
|
||||
obj.Visibility = VIS_Owner;
|
||||
|
@ -129,16 +127,42 @@ func CreateFor(object cursor)
|
|||
{
|
||||
obj.minimized = false;
|
||||
}
|
||||
|
||||
obj->Init(cursor);
|
||||
if (settings != nil)
|
||||
{
|
||||
obj.Settings = settings;
|
||||
for (var setting in settings)
|
||||
obj[setting[0]] = setting[1];
|
||||
}
|
||||
obj->Init(cursor, style_def);
|
||||
cursor->SetMenu(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Reopen the menu with a certain settings value set (arbitrarily defined)
|
||||
// All previous settings will be kept
|
||||
public func ReopenWithSetting(string setting_name, value)
|
||||
{
|
||||
var last_cursor = this.cursor;
|
||||
var settings = [];
|
||||
if (this.Settings != nil)
|
||||
var settings = this.Settings[:];
|
||||
var i;
|
||||
for (i = 0; i < GetLength(settings); i++)
|
||||
if (settings[i][0] == setting_name)
|
||||
break;
|
||||
settings[i] = [setting_name, value];
|
||||
var style_def = this.style_def;
|
||||
RemoveObject();
|
||||
GUI_ObjectInteractionMenu->CreateFor(last_cursor, style_def, settings);
|
||||
}
|
||||
|
||||
func Init(object cursor)
|
||||
|
||||
public func Init(object cursor, id style_def)
|
||||
{
|
||||
this.cursor = cursor;
|
||||
this.style_def = style_def;
|
||||
this.style_def->Init(this);
|
||||
//this.Uncollapsed = uncollapsed;
|
||||
var checking_effect = AddEffect("IntCheckObjects", cursor, 1, 10, this);
|
||||
// Notify the Clonk. This can be used to create custom entries in the objects list via helper objects. For example the "Your Environment" tab.
|
||||
// Note that the cursor is NOT informed when the menu is closed again. Helper objects can be attached to the livetime of this menu by, f.e., effects.
|
||||
|
@ -290,28 +314,13 @@ func OpenMenuForObject(object obj, int slot, bool forced)
|
|||
current_menus[slot].menu_object = main.Target;
|
||||
// Now, the sidebar.
|
||||
var sidebar = CreateSideBar(slot);
|
||||
|
||||
var sidebar_size_em = ToEmString(InteractionMenu_SideBarSize);
|
||||
var part_menu =
|
||||
{
|
||||
Left = "0%", Right = "50%-3em",
|
||||
Bottom = "100%-7em",
|
||||
sidebar = sidebar, main = main,
|
||||
Target = current_menus[slot].menu_object,
|
||||
ID = 1
|
||||
};
|
||||
|
||||
if (slot == 1)
|
||||
{
|
||||
part_menu.Left = "50%-1em";
|
||||
part_menu.Right = "100%-2em";
|
||||
}
|
||||
|
||||
|
||||
var part_menu = this.style_def->CreatePartMenu(this, slot, current_menus[slot].menu_object, sidebar, main);
|
||||
|
||||
if (this.minimized)
|
||||
{
|
||||
part_menu.Bottom = nil; // maximum height
|
||||
}
|
||||
|
||||
|
||||
// need to open a completely new menu?
|
||||
if (!current_main_menu_id)
|
||||
|
@ -325,91 +334,9 @@ func OpenMenuForObject(object obj, int slot, bool forced)
|
|||
if (!current_center_column_target)
|
||||
current_center_column_target = CreateDummy();
|
||||
|
||||
var root_menu =
|
||||
{
|
||||
_one_part = part_menu,
|
||||
Target = this,
|
||||
Decoration = GUI_MenuDeco,
|
||||
BackgroundColor = RGB(0, 0, 0),
|
||||
minimize_button =
|
||||
{
|
||||
Bottom = "100%",
|
||||
Top = "100% - 2em",
|
||||
Left = "100% - 2em",
|
||||
Tooltip = "$Minimize$",
|
||||
Symbol = Icon_Arrow,
|
||||
GraphicsName = "Down",
|
||||
BackgroundColor = {Std = nil, OnHover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("OnHover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "OnToggleMinimizeClicked")
|
||||
},
|
||||
center_column =
|
||||
{
|
||||
Left = "50%-3em",
|
||||
Right = "50%-1em",
|
||||
Top = "1.75em",
|
||||
Bottom = "100%-7em",
|
||||
Style = GUI_VerticalLayout,
|
||||
move_all_left =
|
||||
{
|
||||
Target = current_center_column_target,
|
||||
ID = 10 + 0,
|
||||
Right = "2em", Bottom = "3em",
|
||||
Style = GUI_TextHCenter | GUI_TextVCenter,
|
||||
Symbol = Icon_MoveItems, GraphicsName = "Left",
|
||||
Tooltip = "",
|
||||
BackgroundColor ={Std = 0, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "OnMoveAllToClicked", 0)
|
||||
},
|
||||
move_all_right =
|
||||
{
|
||||
Target = current_center_column_target,
|
||||
ID = 10 + 1,
|
||||
Right = "2em", Bottom = "3em",
|
||||
Style = GUI_TextHCenter | GUI_TextVCenter,
|
||||
Symbol = Icon_MoveItems,
|
||||
Tooltip = "",
|
||||
BackgroundColor ={Std = 0, Hover = 0x50ffff00},
|
||||
OnMouseIn = GuiAction_SetTag("Hover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "OnMoveAllToClicked", 1)
|
||||
}
|
||||
},
|
||||
description_box =
|
||||
{
|
||||
Top = "100%-5em",
|
||||
Right = "100% - 2em",
|
||||
Margin = [sidebar_size_em, "0em"],
|
||||
BackgroundColor = RGB(25, 25, 25),
|
||||
symbol_part =
|
||||
{
|
||||
Right = "5em",
|
||||
Symbol = nil,
|
||||
Margin = "0.5em",
|
||||
ID = 1,
|
||||
Target = current_description_box.symbol_target
|
||||
},
|
||||
desc_part =
|
||||
{
|
||||
Left = "5em",
|
||||
Margin = "0.5em",
|
||||
ID = 1,
|
||||
Target = current_description_box.target,
|
||||
real_contents = // nested one more time so it can dynamically be replaced without messing up the layout
|
||||
{
|
||||
ID = 1,
|
||||
Target = current_description_box.desc_target
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Allow the menu to be closed with a clickable button.
|
||||
GuiAddCloseButton(root_menu, this, "Close");
|
||||
|
||||
var root_menu = this.style_def->CreateRootMenu(this, current_center_column_target, current_description_box);
|
||||
root_menu._one_part = part_menu;
|
||||
|
||||
// Special setup for a minimized menu.
|
||||
if (this.minimized)
|
||||
{
|
||||
|
@ -553,22 +480,9 @@ public func OnMoveAllToClicked(int menu_id)
|
|||
func CreateSideBar(int slot)
|
||||
{
|
||||
var other_menu = current_menus[1 - slot];
|
||||
|
||||
var em_size = ToEmString(InteractionMenu_SideBarSize);
|
||||
var sidebar =
|
||||
{
|
||||
Priority = 10,
|
||||
Right = em_size,
|
||||
Style = GUI_VerticalLayout,
|
||||
Target = current_menus[slot].menu_object,
|
||||
ID = 2
|
||||
};
|
||||
if (slot == 1)
|
||||
{
|
||||
sidebar.Left = Format("100%% %s", ToEmString(-InteractionMenu_SideBarSize));
|
||||
sidebar.Right = "100%";
|
||||
}
|
||||
|
||||
|
||||
var sidebar = this.style_def->CreateSideBar(this, slot, current_menus[slot].menu_object);
|
||||
|
||||
// Now show the current_objects list as entries.
|
||||
// If there is a forced-open menu, also add it to bottom of sidebar..
|
||||
var sidebar_items = nil;
|
||||
|
@ -579,43 +493,11 @@ func CreateSideBar(int slot)
|
|||
}
|
||||
else
|
||||
sidebar_items = current_objects;
|
||||
|
||||
|
||||
for (var obj in sidebar_items)
|
||||
{
|
||||
var background_color = nil;
|
||||
var symbol = {Std = SidebarIconStandard(), OnHover = SidebarIconOnHover()};
|
||||
// figure out whether the object is already selected
|
||||
// if so, highlight the entry
|
||||
if (current_menus[slot].target == obj)
|
||||
{
|
||||
background_color = RGBa(255, 255, 0, 10);
|
||||
symbol = SidebarIconSelected();
|
||||
}
|
||||
var priority = 10000 - obj.Plane;
|
||||
// Cross-out the entry?
|
||||
var deactivation_symbol = nil;
|
||||
if (other_menu && other_menu.target == obj)
|
||||
deactivation_symbol = Icon_Cancel;
|
||||
// Always show Clonk at top.
|
||||
if (obj == cursor) priority = 1;
|
||||
var entry =
|
||||
{
|
||||
// The object is added as the target of the entry, so it can easily be identified later.
|
||||
// For example, to apply show the grey haze to indicate that it cannot be clicked.
|
||||
Target = obj,
|
||||
Right = em_size, Bottom = em_size,
|
||||
Symbol = symbol,
|
||||
Priority = priority,
|
||||
Style = GUI_TextBottom | GUI_TextHCenter,
|
||||
BackgroundColor = background_color,
|
||||
OnMouseIn = GuiAction_SetTag("OnHover"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "OnSidebarEntrySelected", {slot = slot, obj = obj}),
|
||||
Text = obj->GetName(),
|
||||
obj_symbol = {Symbol = obj, Margin = "0.25em", Priority = 1},
|
||||
obj_symbol_deactivated = {Symbol = deactivation_symbol, Margin = "0.5em", Priority = 2, Target = obj, ID = 1 + slot}
|
||||
};
|
||||
|
||||
var entry = this.style_def->CreateSideBarItem(this, slot, obj, current_menus[slot].target == obj, other_menu && other_menu.target == obj, obj == cursor);
|
||||
|
||||
GuiAddSubwindow(entry, sidebar);
|
||||
}
|
||||
return sidebar;
|
||||
|
@ -648,37 +530,13 @@ func OnSidebarEntrySelected(data, int player, int ID, int subwindowID, object ta
|
|||
*/
|
||||
func CreateMainMenu(object obj, int slot)
|
||||
{
|
||||
var big_menu =
|
||||
{
|
||||
Target = CreateDummy(),
|
||||
Priority = 5,
|
||||
Right = Format("100%% %s", ToEmString(-InteractionMenu_SideBarSize)),
|
||||
container =
|
||||
{
|
||||
Top = "1em",
|
||||
Style = GUI_VerticalLayout,
|
||||
BackgroundColor = RGB(25, 25, 25),
|
||||
},
|
||||
headline =
|
||||
{
|
||||
Bottom = "1em",
|
||||
Text = obj->GetName(),
|
||||
Style = GUI_TextHCenter | GUI_TextVCenter,
|
||||
BackgroundColor = 0xff000000
|
||||
}
|
||||
|
||||
};
|
||||
var big_menu = this.style_def->CreateMainMenu(this, slot, CreateDummy(), obj);
|
||||
|
||||
var container = big_menu.container;
|
||||
|
||||
if (slot == 0)
|
||||
{
|
||||
big_menu.Left = ToEmString(InteractionMenu_SideBarSize);
|
||||
big_menu.Right = "100%";
|
||||
}
|
||||
|
||||
|
||||
// Do virtually nothing if the building/object is not ready to be interacted with. This can be caused by several things.
|
||||
var error_message = obj->~RejectInteractionMenu(cursor);
|
||||
|
||||
|
||||
if (error_message)
|
||||
{
|
||||
if (GetType(error_message) != C4V_String)
|
||||
|
@ -688,7 +546,7 @@ func CreateMainMenu(object obj, int slot)
|
|||
current_menus[slot].menus = [];
|
||||
return big_menu;
|
||||
}
|
||||
|
||||
|
||||
var menus = obj->~GetInteractionMenus(cursor) ?? [];
|
||||
// get all interaction info from the object and put it into a menu
|
||||
// contents first
|
||||
|
@ -702,86 +560,44 @@ func CreateMainMenu(object obj, int slot)
|
|||
entries_callback = nil,
|
||||
callback = "OnContentsSelection",
|
||||
callback_target = this,
|
||||
decoration = GUI_MenuDecoInventoryHeader,
|
||||
BackgroundColor = RGB(0, 50, 0),
|
||||
Priority = 10
|
||||
};
|
||||
PushBack(menus, info);
|
||||
}
|
||||
|
||||
|
||||
current_menus[slot].menus = menus;
|
||||
|
||||
|
||||
// now generate the actual menus from the information-list
|
||||
for (var i = 0; i < GetLength(menus); ++i)
|
||||
{
|
||||
var menu = menus[i];
|
||||
|
||||
// Everything not flagged is a custom entry
|
||||
if (!menu.flag)
|
||||
{
|
||||
menu.flag = InteractionMenu_Custom;
|
||||
}
|
||||
// If a callback is given, try to get entries
|
||||
if (menu.entries_callback)
|
||||
{
|
||||
var call_from = menu.entries_callback_target ?? obj;
|
||||
var call_from = menu.entries_callback_target ?? obj;
|
||||
menu.entries = call_from->Call(menu.entries_callback, cursor, menu.entries_callback_parameter);
|
||||
}
|
||||
// Empty entries should not be there
|
||||
if (menu.entries == nil)
|
||||
{
|
||||
FatalError(Format("An interaction menu did not return valid entries. %s -> %v() (object %v)", obj->GetName(), menu.entries_callback, obj));
|
||||
continue;
|
||||
}
|
||||
menu.menu_object = CreateObject(MenuStyle_Grid);
|
||||
if (menu.flag == InteractionMenu_Contents)
|
||||
{
|
||||
menu.menu_object->SetTightGridLayout();
|
||||
}
|
||||
|
||||
menu.menu_object.Top = "+1em";
|
||||
menu.menu_object.Priority = 2;
|
||||
menu.menu_object->SetPermanent();
|
||||
menu.menu_object->SetFitChildren();
|
||||
menu.menu_object->SetMouseOverCallback(this, "OnMenuEntryHover");
|
||||
for (var e = 0; e < GetLength(menu.entries); ++e)
|
||||
{
|
||||
var entry = menu.entries[e];
|
||||
entry.unique_index = ++menu.entry_index_count;
|
||||
// This also allows the interaction-menu user to supply a custom entry with custom layout f.e.
|
||||
var added_entry = menu.menu_object->AddItem(entry.symbol, entry.text, entry.unique_index, this, "OnMenuEntrySelected", { slot = slot, index = i }, entry["custom"]);
|
||||
// Remember the menu entry's ID (e.g. for passing it to an update effect after the menu has been opened).
|
||||
entry.ID = added_entry.ID;
|
||||
}
|
||||
|
||||
var all =
|
||||
{
|
||||
Priority = menu.Priority ?? i,
|
||||
Style = GUI_FitChildren,
|
||||
title_bar =
|
||||
{
|
||||
Priority = 1,
|
||||
Style = GUI_TextVCenter | GUI_TextHCenter,
|
||||
Bottom = "+1em",
|
||||
Text = menu.title,
|
||||
BackgroundColor = 0xa0000000,
|
||||
//Decoration = menu.decoration
|
||||
hline = {Bottom = "0.05em", BackgroundColor = RGB(100, 100, 100)}
|
||||
},
|
||||
Margin = [nil, nil, nil, "0.25em"],
|
||||
real_menu = menu.menu_object,
|
||||
spacer = {Left = "0em", Right = "0em", Bottom = "3em"} // guarantees a minimum height
|
||||
};
|
||||
if (menu.flag == InteractionMenu_Contents)
|
||||
{
|
||||
all.BackgroundColor = RGB(0, 50, 0);
|
||||
}
|
||||
else if (menu.BackgroundColor)
|
||||
{
|
||||
all.BackgroundColor = menu.BackgroundColor;
|
||||
}
|
||||
else if (menu.decoration)
|
||||
{
|
||||
menu.menu_object.BackgroundColor = menu.decoration->FrameDecorationBackClr();
|
||||
}
|
||||
|
||||
var all = this.style_def->CreateMainMenuItem(this, slot, obj, menu, cursor, i);
|
||||
if (!all)
|
||||
continue;
|
||||
|
||||
GuiAddSubwindow(all, container);
|
||||
}
|
||||
|
||||
|
||||
// add refreshing effects for all of the contents menus
|
||||
for (var i = 0; i < GetLength(menus); ++i)
|
||||
{
|
||||
|
@ -789,7 +605,7 @@ func CreateMainMenu(object obj, int slot)
|
|||
continue;
|
||||
AddEffect("IntRefreshContentsMenu", this, 1, 1, this, nil, obj, slot, i);
|
||||
}
|
||||
|
||||
|
||||
return big_menu;
|
||||
}
|
||||
|
||||
|
@ -824,7 +640,7 @@ func OnMenuEntryHover(proplist menu_info, int entry_index, int player)
|
|||
if (!info.menu.callback_target || !info.menu.callback_hover)
|
||||
{
|
||||
var text = Format("%s:|%s", info.entry.symbol->GetName(), info.entry.symbol.Description);
|
||||
|
||||
|
||||
// For contents menus, we can sometimes present additional information about objects.
|
||||
if (info.menu.flag == InteractionMenu_Contents)
|
||||
{
|
||||
|
@ -860,7 +676,7 @@ func OnMenuEntryHover(proplist menu_info, int entry_index, int player)
|
|||
text = Format("%s||%s", text, additional);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GuiUpdateText(text, current_main_menu_id, 1, current_description_box.desc_target);
|
||||
}
|
||||
else
|
||||
|
@ -873,25 +689,25 @@ func OnMenuEntrySelected(proplist menu_info, int entry_index, int player)
|
|||
{
|
||||
var info = GetEntryInformation(menu_info, entry_index);
|
||||
if (!info.entry) return;
|
||||
|
||||
|
||||
var callback_target;
|
||||
if (!(callback_target = info.menu.callback_target)) return;
|
||||
if (!info.menu.callback) return; // The menu can actually decide to handle user interaction itself and not provide a callback.
|
||||
callback_target->Call(info.menu.callback, info.entry.symbol, info.entry.extra_data, cursor);
|
||||
|
||||
// todo: trigger refresh for special value of callback result?
|
||||
var result = callback_target->Call(info.menu.callback, info.entry.symbol, info.entry.extra_data, cursor);
|
||||
|
||||
// todo: trigger refresh for special value of result?
|
||||
}
|
||||
|
||||
private func OnContentsSelection(symbol, extra_data)
|
||||
{
|
||||
if (!current_menus[extra_data.slot]) return;
|
||||
if (!extra_data || !current_menus[extra_data.slot]) return;
|
||||
var target = current_menus[extra_data.slot].target;
|
||||
if (!target) return;
|
||||
// no target to swap to?
|
||||
if (!current_menus[1 - extra_data.slot]) return;
|
||||
var other_target = current_menus[1 - extra_data.slot].target;
|
||||
if (!other_target) return;
|
||||
|
||||
|
||||
// Only if the object wants to be interacted with (hostility etc.)
|
||||
if (other_target->~RejectInteractionMenu(cursor)) return;
|
||||
|
||||
|
@ -901,10 +717,10 @@ private func OnContentsSelection(symbol, extra_data)
|
|||
cursor->~PlaySoundDoubt(true, nil, cursor->GetOwner());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var transfer_only_one = GetPlayerControlState(GetOwner(), CON_ModifierMenu1) == 0; // Transfer ONE object of the stack?
|
||||
var to_transfer = nil;
|
||||
|
||||
|
||||
if (transfer_only_one)
|
||||
{
|
||||
for (var possible in extra_data.objects)
|
||||
|
@ -918,7 +734,7 @@ private func OnContentsSelection(symbol, extra_data)
|
|||
{
|
||||
to_transfer = extra_data.objects;
|
||||
}
|
||||
|
||||
|
||||
var successful_transfers = TransferObjectsFromTo(to_transfer, target, other_target);
|
||||
|
||||
// Did we at least transfer one item?
|
||||
|
@ -1023,7 +839,7 @@ func FxIntRefreshContentsMenuTimer(object target, effect, int time)
|
|||
{
|
||||
var symbol = obj;
|
||||
var extra_data = {slot = effect.slot, menu_index = effect.menu_index, objects = []};
|
||||
|
||||
|
||||
// check if already exists (and then stack!)
|
||||
var found = false;
|
||||
// Never stack containers with (different) contents, though.
|
||||
|
@ -1064,6 +880,8 @@ func FxIntRefreshContentsMenuTimer(object target, effect, int time)
|
|||
// This object has a custom symbol (because it's a container)? Then the normal text would not be displayed.
|
||||
if (inv.custom != nil)
|
||||
{
|
||||
if (inv.custom.top == nil)
|
||||
inv.custom.top = {};
|
||||
inv.custom.top.Text = inv.text;
|
||||
inv.custom.top.Style = inv.custom.top.Style | GUI_TextRight | GUI_TextBottom;
|
||||
}
|
||||
|
@ -1076,27 +894,26 @@ func FxIntRefreshContentsMenuTimer(object target, effect, int time)
|
|||
if (!found)
|
||||
{
|
||||
PushBack(extra_data.objects, obj);
|
||||
|
||||
// Do we need a custom entry when the object has contents?
|
||||
var custom = nil;
|
||||
|
||||
// Use a default grid-menu entry as the base.
|
||||
var custom = MenuStyle_Grid->MakeEntryProplist(symbol, nil);
|
||||
custom.BackgroundColor = {Std = 0, OnHover = RGB(0, 100, 0)};
|
||||
if (is_container)
|
||||
{
|
||||
// Use a default grid-menu entry as the base.
|
||||
custom = MenuStyle_Grid->MakeEntryProplist(symbol, nil);
|
||||
// Pack it into a larger frame to allow for another button below.
|
||||
// Pack the custom entry into a larger frame to allow for another button below.
|
||||
// The priority offset makes sure that double-height items are at the front.
|
||||
custom = {Right = custom.Right, Bottom = "4em", top = custom, Priority = -10000 + obj->GetValue()};
|
||||
// Then add a little container-symbol (that can be clicked).
|
||||
custom.bottom =
|
||||
{
|
||||
Top = "2em",
|
||||
BackgroundColor = {Std = 0, Selected = RGBa(255, 100, 100, 100)},
|
||||
BackgroundColor = {Std = 0, Selected = RGB(0, 100, 0)},
|
||||
OnMouseIn = GuiAction_SetTag("Selected"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
OnClick = GuiAction_Call(this, "OnExtraSlotClicked", {slot = effect.slot, objects = extra_data.objects, ID = obj->GetID()}),
|
||||
container =
|
||||
{
|
||||
Symbol = Chest,
|
||||
Symbol = Icon_ExtraSlot,
|
||||
Priority = 1
|
||||
}
|
||||
};
|
||||
|
@ -1136,15 +953,10 @@ func FxIntRefreshContentsMenuTimer(object target, effect, int time)
|
|||
var overlay = obj->~GetInventoryIconOverlay();
|
||||
if (overlay != nil)
|
||||
{
|
||||
if (!custom)
|
||||
{
|
||||
custom = MenuStyle_Grid->MakeEntryProplist(symbol, nil);
|
||||
custom.Priority = obj->GetValue();
|
||||
custom.top = {};
|
||||
}
|
||||
custom.top._overlay = overlay;
|
||||
custom.Priority = obj->GetValue();
|
||||
custom.top = { _overlay = overlay };
|
||||
}
|
||||
|
||||
|
||||
// Add to menu!
|
||||
var text = nil;
|
||||
if (object_amount > 1)
|
||||
|
@ -1159,36 +971,50 @@ func FxIntRefreshContentsMenuTimer(object target, effect, int time)
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add a contents counter on top.
|
||||
var contents_count_bar =
|
||||
{
|
||||
BackgroundColor = RGBa(0, 0, 0, 100),
|
||||
Priority = -1,
|
||||
// Too low a value (-5000 doesn't work) and the bar will be at the bottom when
|
||||
// an extra slot item is in the container and the HUD breaks
|
||||
Priority = -10000,
|
||||
Bottom = "1em",
|
||||
text =
|
||||
Style = GUI_NoCrop,
|
||||
text =
|
||||
{
|
||||
Priority = 2,
|
||||
Style = GUI_TextRight | GUI_TextVCenter
|
||||
Priority = 3,
|
||||
Style = GUI_TextRight | GUI_TextVCenter,
|
||||
Bottom = "1em"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (effect.obj.MaxContentsCount)
|
||||
{
|
||||
var count = effect.obj->ContentsCount();
|
||||
var max = effect.obj.MaxContentsCount;
|
||||
contents_count_bar.text.Text = Format("<c eeeeee>%3d / %3d</c>", count, max);
|
||||
contents_count_bar.bar =
|
||||
contents_count_bar.Bottom = "0.5em";
|
||||
contents_count_bar.bar =
|
||||
{
|
||||
Priority = 2,
|
||||
BackgroundColor = RGB(0, 100, 0),
|
||||
Right = ToPercentString(1000 * count / max, 10),
|
||||
Bottom = "50%"
|
||||
};
|
||||
contents_count_bar.background =
|
||||
{
|
||||
Priority = 1,
|
||||
BackgroundColor = RGBa(0, 255, 0, 50),
|
||||
Right = ToPercentString(1000 * count / max, 10)
|
||||
};
|
||||
BackgroundColor = RGBa(0, 0, 0, 100),
|
||||
Bottom = "50%"
|
||||
};
|
||||
}
|
||||
else contents_count_bar.text.Text = Format("<c eeeeee>%3d</c>", effect.obj->ContentsCount());
|
||||
|
||||
else
|
||||
{
|
||||
contents_count_bar.text.Text = Format("<c eeeeee>%3d</c>", effect.obj->ContentsCount());
|
||||
}
|
||||
|
||||
PushBack(inventory, {symbol = nil, text = nil, custom = contents_count_bar});
|
||||
|
||||
|
||||
// Check if nothing changed. If so, we don't need to update.
|
||||
if (GetLength(inventory) == GetLength(effect.last_inventory))
|
||||
{
|
||||
|
@ -1203,7 +1029,7 @@ func FxIntRefreshContentsMenuTimer(object target, effect, int time)
|
|||
if (same)
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
|
||||
effect.last_inventory = inventory[:];
|
||||
DoMenuRefresh(effect.slot, effect.menu_index, inventory);
|
||||
return FX_OK;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_ChangeBackground
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=128
|
||||
Height=128
|
||||
Offset=-64,-64
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 5.5 KiB |
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_ChangeColor
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=128
|
||||
Height=128
|
||||
Offset=-64,-64
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_ExtraSlot
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=128
|
||||
Height=128
|
||||
Offset=-64,-64
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_HideText
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=128
|
||||
Height=128
|
||||
Offset=-64,-64
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 8.1 KiB |
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_Settings
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=128
|
||||
Height=128
|
||||
Offset=-64,-64
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 9.6 KiB |
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_Menu_Tab
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=128
|
||||
Height=128
|
||||
Offset=-64,-64
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
|
@ -153,7 +153,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
|||
}
|
||||
// Open contents menu.
|
||||
CancelUse();
|
||||
GUI_ObjectInteractionMenu->CreateFor(this);
|
||||
GUI_ObjectInteractionMenu->CreateFor(this, GUI_OIM_NewStyle);
|
||||
// the interaction menu calls SetMenu(this) in the clonk
|
||||
// so after this call menu = the created menu
|
||||
if(GetMenu())
|
||||
|
|