File: Script.c

package info (click to toggle)
openclonk 8.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 169,500 kB
  • sloc: cpp: 180,478; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 139; sh: 101; javascript: 34
file content (188 lines) | stat: -rw-r--r-- 5,236 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
	List
	Shows a simple list menu.
*/

local Name = "List Menu";

local entries;
local on_mouse_over_callback, on_mouse_out_callback;
local on_close_callback;
local permanent;

local menu_id;

func Construction()
{
	entries = [];
	this.Style = GUI_VerticalLayout;
	this.Target = this;
	this.ID = 0xffffff;
	
	this.OnClose = GuiAction_Call(this, "OnCloseCallback");
	
	SetPosition(0, 0);
}

func OnCloseCallback()
{
	menu_id = 0;
	Close();
}

func Close()
{
	var self = this;
	if (on_close_callback && on_close_callback[0])
		on_close_callback[0]->Call(on_close_callback[1], on_close_callback[2]);
	if (self && menu_id)
		GuiClose(menu_id);
	if (self)
		RemoveObject();
}

func SetPermanent(bool perm) { permanent = perm ?? true; }
func SetFitChildren() { this.Style = this.Style | GUI_FitChildren; this.Bottom = "0em";}

func SetCloseCallback(proplist target, callback, parameter)
{
	on_close_callback = [target, callback, parameter];
}

func SetMouseOverCallback(proplist target, callback)
{
	on_mouse_over_callback = [target, callback];
}

func SetMouseOutCallback(proplist target, callback)
{
	on_mouse_out_callback = [target, callback];
}

// can be overloaded for custom menu styles
func MakeEntryProplist(symbol, text)
{
	var custom_entry = {Bottom = "+2em", sym = {Right = "+2em", Bottom = "+2em"}, desc = {Left = "+2em"}};
	custom_entry.sym.Symbol = symbol;
	custom_entry.desc.Text = text;
	custom_entry.desc.Style = GUI_TextVCenter;
	custom_entry.Style = GUI_FitChildren;
	custom_entry.BackgroundColor = {Std = 0, OnHover = 0x50ff0000};
	return custom_entry;
}

// custom_menu_id should be passed if the menu was manually opened and not via Open()
func AddItem(symbol, string text, user_ID, proplist target, command, parameter, custom_entry, custom_menu_id, bool onlyUpdate)
{
	onlyUpdate = onlyUpdate ?? false;
	custom_menu_id = custom_menu_id ?? menu_id;
	
	var on_hover = GuiAction_SetTag("OnHover", 0, nil);
	if (on_mouse_over_callback)
		on_hover = [on_hover, GuiAction_Call(this, "DoCallback", on_mouse_over_callback)];
	var on_hover_stop = GuiAction_SetTag("Std", 0, nil);
	if (on_mouse_out_callback)
		on_hover_stop = [on_hover_stop, GuiAction_Call(this, "DoCallback", on_mouse_out_callback)];
	
	// in case of a new entry, append to array
	var ID = GetLength(entries) + 1;
	// otherwise, replace the old entry
	if (onlyUpdate)
	{
		for (var i = 0; i < GetLength(entries); ++i)
		{
			if (!entries[i]) continue;
			if (entries[i][3] != user_ID) continue;
			ID = i + 1;
			break;
		}
	}
	
	if (!custom_entry)
		custom_entry = MakeEntryProplist(symbol, text);
	
	// Always add some properties later. This is done so that real custom entries do not need to care about target etc.
	custom_entry.ID = ID; // A fixed ID is obligatory for now. Might be possible to omit that, but would need to check if updating etc works.
	custom_entry.Target = this; // Same as above.
	
	// These properties can in theory be set/customized by the user without breaking functionality. But they are (probably) required anway.
	custom_entry.Priority = custom_entry.Priority ?? ID;
	custom_entry.OnClick = custom_entry.OnClick ?? GuiAction_Call(this, "OnClick");
	custom_entry.OnMouseIn = custom_entry.OnMouseIn ?? on_hover;
	custom_entry.OnMouseOut = custom_entry.OnMouseOut ?? on_hover_stop;
	
	// Save entry to list and prepare call information.
	entries[ID - 1] = [target, command, parameter, user_ID];
	this[Format("_menuChild%d", ID)] = custom_entry;
	
	// need to add to existing menu?
	if (custom_menu_id)
	{
		if (onlyUpdate)
		{
			// need to close the old entry first
			// this is done so a full refresh is guaranteed
			GuiClose(custom_menu_id, ID, this);
		}
		
		var temp = {_child = custom_entry};
		GuiUpdate(temp, custom_menu_id, this.ID, this);
	}
	
	return custom_entry;
}

// updates an existing entry with the given user_ID
func UpdateItem(symbol, string text, user_ID, proplist target, command, parameter, custom_entry, custom_menu_id)
{
	return AddItem(symbol, text, user_ID, target, command, parameter, custom_entry, custom_menu_id, true);
}

// can be used when the menu has already been opened
// needs to be passed the menu ID if the menu was not opened using Open()
func RemoveItem(user_ID, int custom_menu_id)
{
	custom_menu_id = custom_menu_id ?? menu_id;
	for (var i = 0; i < GetLength(entries); ++i)
	{
		var ID = i+1;
		if (!entries[i]) continue;
		if (entries[i][3] != user_ID) continue;
		GuiClose(custom_menu_id, ID, this);
		entries[i] = nil;
		return true;
	}
	return false;
}

func DoCall(int ID, command, proplist target, bool noclose, int player)
{
	var self = this; // safety
	var entry = entries[ID - 1];
	target = target ?? entry[0];
	// target removed? safety first!
	if (target)
	{
		if (target->Call(command ?? entry[1], entry[2], entry[3], player) == -1) return;
	}
	if (self)
	if (!noclose && !permanent)
		Close();
}

func OnClick(data, int player, int ID, int subwindowID, object target)
{
	DoCall(subwindowID, nil, nil, nil, player);	
}

func DoCallback(data, int player, int ID, int subwindowID, object target)
{
	DoCall(subwindowID, data[1], data[0], true, player);
}

func Open()
{
	this.ID = nil; // no subwindow ID when opened as real menu
	menu_id = GuiOpen(this);
	return menu_id;
}