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
Clonkonaut 2018-10-15 17:38:22 +02:00
parent 952cfef497
commit c6d5c5044f
30 changed files with 1042 additions and 290 deletions

View File

@ -0,0 +1,7 @@
[DefCore]
id=GUI_MenuDeco2
Version=8,0
Category=C4D_StaticBack
Width=1
Height=1
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -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,
}
});
}

View File

@ -0,0 +1,5 @@
[DefCore]
id=GUI_OIM_NewStyle
Version=8,0
Category=C4D_StaticBack
HideInCreator=true

View File

@ -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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -0,0 +1,8 @@
[DefCore]
id=Icon_ChangeBackground
Version=8,0
Category=C4D_StaticBack
Width=128
Height=128
Offset=-64,-64
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,8 @@
[DefCore]
id=Icon_ChangeColor
Version=8,0
Category=C4D_StaticBack
Width=128
Height=128
Offset=-64,-64
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,8 @@
[DefCore]
id=Icon_ExtraSlot
Version=8,0
Category=C4D_StaticBack
Width=128
Height=128
Offset=-64,-64
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,8 @@
[DefCore]
id=Icon_HideText
Version=8,0
Category=C4D_StaticBack
Width=128
Height=128
Offset=-64,-64
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -0,0 +1,8 @@
[DefCore]
id=Icon_Settings
Version=8,0
Category=C4D_StaticBack
Width=128
Height=128
Offset=-64,-64
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -0,0 +1,8 @@
[DefCore]
id=Icon_Menu_Tab
Version=8,0
Category=C4D_StaticBack
Width=128
Height=128
Offset=-64,-64
HideInCreator=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -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())