~popey/+junk/openspades-stable

« back to all changes in this revision

Viewing changes to Resources/Scripts/Gui/Preferences.as

  • Committer: Alan Pope
  • Date: 2017-04-30 20:42:53 UTC
  • Revision ID: alan@popey.com-20170430204253-1vpvxb47ygller2c
openspades stable 0.1.1c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (c) 2013 yvt
 
3
 
 
4
 This file is part of OpenSpades.
 
5
 
 
6
 OpenSpades is free software: you can redistribute it and/or modify
 
7
 it under the terms of the GNU General Public License as published by
 
8
 the Free Software Foundation, either version 3 of the License, or
 
9
 (at your option) any later version.
 
10
 
 
11
 OpenSpades is distributed in the hope that it will be useful,
 
12
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 GNU General Public License for more details.
 
15
 
 
16
 You should have received a copy of the GNU General Public License
 
17
 along with OpenSpades.  If not, see <http://www.gnu.org/licenses/>.
 
18
 
 
19
 */
 
20
 
 
21
namespace spades {
 
22
 
 
23
        class PreferenceViewOptions {
 
24
                bool GameActive = false;
 
25
        }
 
26
 
 
27
        class PreferenceView: spades::ui::UIElement {
 
28
                private spades::ui::UIElement@ owner;
 
29
 
 
30
                private PreferenceTab@[] tabs;
 
31
                float ContentsLeft, ContentsWidth;
 
32
                float ContentsTop, ContentsHeight;
 
33
 
 
34
                int SelectedTabIndex = 0;
 
35
 
 
36
                spades::ui::EventHandler@ Closed;
 
37
 
 
38
                PreferenceView(spades::ui::UIElement@ owner, PreferenceViewOptions@ options, FontManager@ fontManager) {
 
39
                        super(owner.Manager);
 
40
                        @this.owner = owner;
 
41
                        this.Bounds = owner.Bounds;
 
42
                        ContentsWidth = 800.f;
 
43
                        ContentsLeft = (Manager.Renderer.ScreenWidth - ContentsWidth) * 0.5f;
 
44
                        ContentsHeight = 550.f;
 
45
                        ContentsTop = (Manager.Renderer.ScreenHeight - ContentsHeight) * 0.5f;
 
46
 
 
47
                        {
 
48
                                spades::ui::Label label(Manager);
 
49
                                label.BackgroundColor = Vector4(0, 0, 0, 0.4f);
 
50
                                label.Bounds = Bounds;
 
51
                                AddChild(label);
 
52
                        }
 
53
                        {
 
54
                                spades::ui::Label label(Manager);
 
55
                                label.BackgroundColor = Vector4(0, 0, 0, 0.8f);
 
56
                                label.Bounds = AABB2(0.f, ContentsTop - 13.f, Size.x, ContentsHeight + 27.f);
 
57
                                AddChild(label);
 
58
                        }
 
59
 
 
60
                        AddTab(GameOptionsPanel(Manager, options, fontManager), _Tr("Preferences", "Game Options"));
 
61
                        AddTab(ControlOptionsPanel(Manager, options, fontManager), _Tr("Preferences", "Controls"));
 
62
                        AddTab(MiscOptionsPanel(Manager, options, fontManager), _Tr("Preferences", "Misc"));
 
63
 
 
64
                        {
 
65
                                PreferenceTabButton button(Manager);
 
66
                                button.Caption = _Tr("Preferences", "Back");
 
67
                                button.Bounds = AABB2(
 
68
                                        ContentsLeft + 10.f,
 
69
                                        ContentsTop + 10.f + float(tabs.length) * 32.f + 5.f
 
70
                                        , 150.f, 30.f);
 
71
                                button.Alignment = Vector2(0.f, 0.5f);
 
72
                                @button.Activated = spades::ui::EventHandler(this.OnClosePressed);
 
73
                                AddChild(button);
 
74
                        }
 
75
 
 
76
                        UpdateTabs();
 
77
                }
 
78
 
 
79
                private void AddTab(spades::ui::UIElement@ view, string caption) {
 
80
                        PreferenceTab tab(this, view);
 
81
                        int order = int(tabs.length);
 
82
                        tab.TabButton.Bounds = AABB2(ContentsLeft + 10.f, ContentsTop + 10.f + float(order) * 32.f, 150.f, 30.f);
 
83
                        tab.TabButton.Caption = caption;
 
84
                        tab.View.Bounds = AABB2(ContentsLeft + 170.f, ContentsTop + 10.f, ContentsWidth - 180.f, ContentsHeight - 20.f);
 
85
                        tab.View.Visible = false;
 
86
                        @tab.TabButton.Activated = spades::ui::EventHandler(this.OnTabButtonActivated);
 
87
                        AddChild(tab.View);
 
88
                        AddChild(tab.TabButton);
 
89
                        tabs.insertLast(tab);
 
90
                }
 
91
 
 
92
                private void OnTabButtonActivated(spades::ui::UIElement@ sender) {
 
93
                        for(uint i = 0; i < tabs.length; i++) {
 
94
                                if(cast<spades::ui::UIElement>(tabs[i].TabButton) is sender) {
 
95
                                        SelectedTabIndex = i;
 
96
                                        UpdateTabs();
 
97
                                }
 
98
                        }
 
99
                }
 
100
 
 
101
                private void UpdateTabs() {
 
102
                        for(uint i = 0; i < tabs.length; i++) {
 
103
                                PreferenceTab@ tab = tabs[i];
 
104
                                bool selected = SelectedTabIndex == int(i);
 
105
                                tab.TabButton.Toggled = selected;
 
106
                                tab.View.Visible = selected;
 
107
                        }
 
108
                }
 
109
 
 
110
                private void OnClosePressed(spades::ui::UIElement@ sender) {
 
111
                        Close();
 
112
                }
 
113
 
 
114
                private void OnClosed() {
 
115
                        if(Closed !is null) Closed(this);
 
116
                }
 
117
 
 
118
                void HotKey(string key) {
 
119
                        if(key == "Escape") {
 
120
                                Close();
 
121
                        } else {
 
122
                                UIElement::HotKey(key);
 
123
                        }
 
124
                }
 
125
 
 
126
                void Render() {
 
127
                        Vector2 pos = ScreenPosition;
 
128
                        Vector2 size = Size;
 
129
                        Renderer@ r = Manager.Renderer;
 
130
                        Image@ img = r.RegisterImage("Gfx/White.tga");
 
131
 
 
132
                        r.ColorNP = Vector4(1, 1, 1, 0.08f);
 
133
                        r.DrawImage(img,
 
134
                                AABB2(pos.x, pos.y + ContentsTop - 15.f, size.x, 1.f));
 
135
                        r.DrawImage(img,
 
136
                                AABB2(pos.x, pos.y + ContentsTop + ContentsHeight + 15.f, size.x, 1.f));
 
137
                        r.ColorNP = Vector4(1, 1, 1, 0.2f);
 
138
                        r.DrawImage(img,
 
139
                                AABB2(pos.x, pos.y + ContentsTop - 14.f, size.x, 1.f));
 
140
                        r.DrawImage(img,
 
141
                                AABB2(pos.x, pos.y + ContentsTop + ContentsHeight + 14.f, size.x, 1.f));
 
142
 
 
143
                        UIElement::Render();
 
144
                }
 
145
 
 
146
 
 
147
                void Close() {
 
148
                        owner.Enable = true;
 
149
                        @this.Parent = null;
 
150
                        OnClosed();
 
151
                }
 
152
 
 
153
                void Run() {
 
154
                        owner.Enable = false;
 
155
                        owner.Parent.AddChild(this);
 
156
                }
 
157
 
 
158
 
 
159
        }
 
160
 
 
161
        class PreferenceTabButton: spades::ui::Button {
 
162
                PreferenceTabButton(spades::ui::UIManager@ manager) {
 
163
                        super(manager);
 
164
                        Alignment = Vector2(0.f, 0.5f);
 
165
                }
 
166
                /*
 
167
                void Render() {
 
168
                        Renderer@ renderer = Manager.Renderer;
 
169
                        Vector2 pos = ScreenPosition;
 
170
                        Vector2 size = Size;
 
171
 
 
172
                        Vector4 color = Vector4(0.2f, 0.2f, 0.2f, 0.5f);
 
173
                        if(Toggled or (Pressed and Hover)) {
 
174
                                color = Vector4(0.7f, 0.7f, 0.7f, 0.9f);
 
175
                        }else if(Hover) {
 
176
                                color = Vector4(0.4f, 0.4f, 0.4f, 0.7f);
 
177
                        }
 
178
 
 
179
                        Font@ font = this.Font;
 
180
                        string text = this.Caption;
 
181
                        Vector2 txtSize = font.Measure(text);
 
182
                        Vector2 txtPos;
 
183
                        txtPos.y = pos.y + (size.y - txtSize.y) * 0.5f;
 
184
 
 
185
                        font.DrawShadow(text, txtPos, 1.f,
 
186
                                color, Vector4(0.f, 0.f, 0.f, 0.4f));
 
187
                }*/
 
188
 
 
189
        }
 
190
 
 
191
        class PreferenceTab {
 
192
                spades::ui::UIElement@ View;
 
193
                PreferenceTabButton@ TabButton;
 
194
 
 
195
                PreferenceTab(PreferenceView@ parent, spades::ui::UIElement@ view) {
 
196
                        @View = view;
 
197
                        @TabButton = PreferenceTabButton(parent.Manager);
 
198
                        TabButton.Toggle = true;
 
199
                }
 
200
        }
 
201
 
 
202
        class ConfigField: spades::ui::Field {
 
203
                ConfigItem@ config;
 
204
                ConfigField(spades::ui::UIManager manager, string configName) {
 
205
                        super(manager);
 
206
                        @config = ConfigItem(configName);
 
207
                        this.Text = config.StringValue;
 
208
                }
 
209
 
 
210
                void OnChanged() {
 
211
                        Field::OnChanged();
 
212
                        config = this.Text;
 
213
                }
 
214
        }
 
215
 
 
216
        class ConfigNumberFormatter {
 
217
                int digits;
 
218
                string suffix;
 
219
                string prefix;
 
220
                ConfigNumberFormatter(int digits, string suffix) {
 
221
                        this.digits = digits;
 
222
                        this.suffix = suffix;
 
223
                        this.prefix = "";
 
224
                }
 
225
                ConfigNumberFormatter(int digits, string suffix, string prefix) {
 
226
                        this.digits = digits;
 
227
                        this.suffix = suffix;
 
228
                        this.prefix = prefix;
 
229
                }
 
230
                private string FormatInternal(float value) {
 
231
                        if(value < 0.f) {
 
232
                                return "-" + Format(-value);
 
233
                        }
 
234
 
 
235
                        // do rounding
 
236
                        float rounding = 0.5f;
 
237
                        for(int i = digits; i > 0; i--)
 
238
                                rounding *= 0.1f;
 
239
                        value += rounding;
 
240
 
 
241
                        int intPart = int(value);
 
242
                        string s = ToString(intPart);
 
243
                        if(digits > 0){
 
244
                                s += ".";
 
245
                                for(int i = digits; i > 0; i--) {
 
246
                                        value -= float(intPart);
 
247
                                        value *= 10.f;
 
248
                                        intPart = int(value);
 
249
                                        if(intPart > 9) intPart = 9;
 
250
                                        s += ToString(intPart);
 
251
                                }
 
252
                        }
 
253
                        s += suffix;
 
254
                        return s;
 
255
                }
 
256
                string Format(float value) {
 
257
                        return prefix + FormatInternal(value);
 
258
                }
 
259
        }
 
260
 
 
261
        class ConfigSlider: spades::ui::Slider {
 
262
                ConfigItem@ config;
 
263
                float stepSize;
 
264
                spades::ui::Label@ label;
 
265
                ConfigNumberFormatter@ formatter;
 
266
 
 
267
                ConfigSlider(spades::ui::UIManager manager, string configName,
 
268
                        float minValue, float maxValue, float stepValue,
 
269
                        ConfigNumberFormatter@ formatter) {
 
270
                        super(manager);
 
271
                        @config = ConfigItem(configName);
 
272
                        this.MinValue = minValue;
 
273
                        this.MaxValue = maxValue;
 
274
                        this.Value = Clamp(config.FloatValue, minValue, maxValue);
 
275
                        this.stepSize = stepValue;
 
276
                        @this.formatter = formatter;
 
277
 
 
278
                        // compute large change
 
279
                        int steps = int((maxValue - minValue) / stepValue);
 
280
                        steps = (steps + 9) / 10;
 
281
                        this.LargeChange = float(steps) * stepValue;
 
282
 
 
283
                        @label = spades::ui::Label(Manager);
 
284
                        label.Alignment = Vector2(1.f, 0.5f);
 
285
                        AddChild(label);
 
286
                        UpdateLabel();
 
287
                }
 
288
 
 
289
                void OnResized() {
 
290
                        Slider::OnResized();
 
291
                        label.Bounds = AABB2(Size.x, 0.f, 80.f, Size.y);
 
292
                }
 
293
 
 
294
                void UpdateLabel() {
 
295
                        label.Text = formatter.Format(config.FloatValue);
 
296
                }
 
297
 
 
298
                void DoRounding() {
 
299
                        float v = float(this.Value - this.MinValue);
 
300
                        v = floor((v / stepSize) + 0.5) * stepSize;
 
301
                        v += float(this.MinValue);
 
302
                        this.Value = v;
 
303
                }
 
304
 
 
305
                void OnChanged() {
 
306
                        Slider::OnChanged();
 
307
                        DoRounding();
 
308
                        config = this.Value;
 
309
                        UpdateLabel();
 
310
                }
 
311
        }
 
312
 
 
313
        uint8 ToUpper(uint8 c) {
 
314
                if(c >= uint8(0x61) and c <= uint8(0x7a)) {
 
315
                        return uint8(c - 0x61 + 0x41);
 
316
                } else {
 
317
                        return c;
 
318
                }
 
319
        }
 
320
        class ConfigHotKeyField: spades::ui::UIElement {
 
321
                ConfigItem@ config;
 
322
                private bool hover;
 
323
                spades::ui::EventHandler@ KeyBound;
 
324
 
 
325
                ConfigHotKeyField(spades::ui::UIManager manager, string configName) {
 
326
                        super(manager);
 
327
                        @config = ConfigItem(configName);
 
328
                        IsMouseInteractive = true;
 
329
                }
 
330
 
 
331
                string BoundKey {
 
332
                        get { return config.StringValue; }
 
333
                        set { config = value; }
 
334
                }
 
335
 
 
336
                void KeyDown(string key) {
 
337
                        if(IsFocused) {
 
338
                                if(key != "Escape") {
 
339
                                        if(key == " ") {
 
340
                                                key = "Space";
 
341
                                        } else if(key == "BackSpace" or key == "Delete") {
 
342
                                                key = ""; // unbind
 
343
                                        }
 
344
                                        config = key;
 
345
                                        KeyBound(this);
 
346
                                }
 
347
                                @Manager.ActiveElement = null;
 
348
                                AcceptsFocus = false;
 
349
                        } else {
 
350
                                UIElement::KeyDown(key);
 
351
                        }
 
352
                }
 
353
 
 
354
                void MouseDown(spades::ui::MouseButton button, Vector2 clientPosition) {
 
355
                        if(not AcceptsFocus) {
 
356
                                AcceptsFocus = true;
 
357
                                @Manager.ActiveElement = this;
 
358
                                return;
 
359
                        }
 
360
                        if(IsFocused) {
 
361
                                if(button == spades::ui::MouseButton::LeftMouseButton) {
 
362
                                        config = "LeftMouseButton";
 
363
                                }else if(button == spades::ui::MouseButton::RightMouseButton) {
 
364
                                        config = "RightMouseButton";
 
365
                                }else if(button == spades::ui::MouseButton::MiddleMouseButton) {
 
366
                                        config = "MiddleMouseButton";
 
367
                                }else if(button == spades::ui::MouseButton::MouseButton4) {
 
368
                                        config = "MouseButton4";
 
369
                                }else if(button == spades::ui::MouseButton::MouseButton5) {
 
370
                                        config = "MouseButton5";
 
371
                                }
 
372
                                KeyBound(this);
 
373
                                @Manager.ActiveElement = null;
 
374
                                AcceptsFocus = false;
 
375
                        }
 
376
                }
 
377
 
 
378
                void MouseEnter() {
 
379
                        hover = true;
 
380
                }
 
381
                void MouseLeave() {
 
382
                        hover = false;
 
383
                }
 
384
 
 
385
                void Render() {
 
386
                        // render background
 
387
                        Renderer@ renderer = Manager.Renderer;
 
388
                        Vector2 pos = ScreenPosition;
 
389
                        Vector2 size = Size;
 
390
                        Image@ img = renderer.RegisterImage("Gfx/White.tga");
 
391
                        renderer.ColorNP = Vector4(0.f, 0.f, 0.f, IsFocused ? 0.3f : 0.1f);
 
392
                        renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
 
393
 
 
394
                        if(IsFocused) {
 
395
                                renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.2f);
 
396
                        }else if(hover) {
 
397
                                renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.1f);
 
398
                        } else {
 
399
                                renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.06f);
 
400
                        }
 
401
                        renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, 1.f));
 
402
                        renderer.DrawImage(img, AABB2(pos.x, pos.y + size.y - 1.f, size.x, 1.f));
 
403
                        renderer.DrawImage(img, AABB2(pos.x, pos.y + 1.f, 1.f, size.y - 2.f));
 
404
                        renderer.DrawImage(img, AABB2(pos.x + size.x - 1.f, pos.y + 1.f, 1.f, size.y - 2.f));
 
405
 
 
406
                        Font@ font = this.Font;
 
407
                        string text = IsFocused ? _Tr("Preferences", "Press Key to Bind or [Escape] to Cancel...") : config.StringValue;
 
408
 
 
409
                        Vector4 color(1,1,1,1);
 
410
 
 
411
                        if(IsFocused) {
 
412
                                color.w = abs(sin(Manager.Time * 2.f));
 
413
                        }else{
 
414
                                AcceptsFocus = false;
 
415
                        }
 
416
 
 
417
                        if(text == " " or text == "Space") {
 
418
                                text = _Tr("Preferences", "Space");
 
419
                        }else if(text.length == 0) {
 
420
                                text = _Tr("Preferences", "Unbound");
 
421
                                color.w *= 0.3f;
 
422
                        }else if(text == "Shift") {
 
423
                                text = _Tr("Preferences", "Shift");
 
424
                        }else if(text == "Control") {
 
425
                                text = _Tr("Preferences", "Control");
 
426
                        }else if(text == "Meta") {
 
427
                                text = _Tr("Preferences", "Meta");
 
428
                        }else if(text == "Alt") {
 
429
                                text = _Tr("Preferences", "Alt");
 
430
                        }else if(text == "LeftMouseButton") {
 
431
                                text = _Tr("Preferences", "Left Mouse Button");
 
432
                        }else if(text == "RightMouseButton") {
 
433
                                text = _Tr("Preferences", "Right Mouse Button");
 
434
                        }else if(text == "MiddleMouseButton") {
 
435
                                text = _Tr("Preferences", "Middle Mouse Button");
 
436
                        }else if(text == "MouseButton4") {
 
437
                                text = _Tr("Preferences", "Mouse Button 4");
 
438
                        }else if(text == "MouseButton5") {
 
439
                                text = _Tr("Preferences", "Mouse Button 5");
 
440
                        }else{
 
441
                                for(uint i = 0, len = text.length; i < len; i++)
 
442
                                        text[i] = ToUpper(text[i]);
 
443
                        }
 
444
 
 
445
                        Vector2 txtSize = font.Measure(text);
 
446
                        Vector2 txtPos;
 
447
                        txtPos = pos + (size - txtSize) * 0.5f;
 
448
 
 
449
 
 
450
 
 
451
                        font.Draw(text, txtPos, 1.f, color);
 
452
                }
 
453
        }
 
454
 
 
455
        class ConfigSimpleToggleButton: spades::ui::RadioButton {
 
456
                ConfigItem@ config;
 
457
                int value;
 
458
                ConfigSimpleToggleButton(spades::ui::UIManager manager, string caption, string configName, int value) {
 
459
                        super(manager);
 
460
                        @config = ConfigItem(configName);
 
461
                        this.Caption = caption;
 
462
                        this.value = value;
 
463
                        this.Toggle = true;
 
464
                        this.Toggled = config.IntValue == value;
 
465
                }
 
466
 
 
467
                void OnActivated() {
 
468
                        RadioButton::OnActivated();
 
469
                        this.Toggled = true;
 
470
                        config = value;
 
471
                }
 
472
 
 
473
                void Render() {
 
474
                        this.Toggled = config.IntValue == value;
 
475
                        RadioButton::Render();
 
476
                }
 
477
        }
 
478
 
 
479
        class StandardPreferenceLayouterModel: spades::ui::ListViewModel {
 
480
                private spades::ui::UIElement@[]@ items;
 
481
                StandardPreferenceLayouterModel(spades::ui::UIElement@[]@ items) {
 
482
                        @this.items = items;
 
483
                }
 
484
                int NumRows {
 
485
                        get { return int(items.length); }
 
486
                }
 
487
                spades::ui::UIElement@ CreateElement(int row) {
 
488
                        return items[row];
 
489
                }
 
490
                void RecycleElement(spades::ui::UIElement@ elem) {
 
491
                }
 
492
        }
 
493
        class StandardPreferenceLayouter {
 
494
                spades::ui::UIElement@ Parent;
 
495
                private float FieldX = 250.f;
 
496
                private float FieldWidth = 310.f;
 
497
                private spades::ui::UIElement@[] items;
 
498
                private ConfigHotKeyField@[] hotkeyItems;
 
499
                private FontManager@ fontManager;
 
500
 
 
501
                StandardPreferenceLayouter(spades::ui::UIElement@ parent, FontManager@ fontManager) {
 
502
                        @Parent = parent;
 
503
                        @this.fontManager = fontManager;
 
504
                }
 
505
 
 
506
                private spades::ui::UIElement@ CreateItem() {
 
507
                        spades::ui::UIElement elem(Parent.Manager);
 
508
                        elem.Size = Vector2(300.f, 32.f);
 
509
                        items.insertLast(elem);
 
510
                        return elem;
 
511
                }
 
512
 
 
513
                private void OnKeyBound(spades::ui::UIElement@ sender) {
 
514
                        // unbind already bound key
 
515
                        ConfigHotKeyField@ bindField = cast<ConfigHotKeyField>(sender);
 
516
                        string key = bindField.BoundKey;
 
517
                        for(uint i = 0; i < hotkeyItems.length; i++) {
 
518
                                ConfigHotKeyField@ f = hotkeyItems[i];
 
519
                                if(f !is bindField) {
 
520
                                        if(f.BoundKey == key) {
 
521
                                                f.BoundKey = "";
 
522
                                        }
 
523
                                }
 
524
                        }
 
525
                }
 
526
 
 
527
                void AddHeading(string text) {
 
528
                        spades::ui::UIElement@ container = CreateItem();
 
529
 
 
530
                        spades::ui::Label label(Parent.Manager);
 
531
                        label.Text = text;
 
532
                        label.Alignment = Vector2(0.f, 1.f);
 
533
                        @label.Font = fontManager.HeadingFont;
 
534
                        label.Bounds = AABB2(10.f, 0.f, 300.f, 32.f);
 
535
                        container.AddChild(label);
 
536
                }
 
537
 
 
538
                ConfigField@ AddInputField(string caption, string configName, bool enabled = true) {
 
539
                        spades::ui::UIElement@ container = CreateItem();
 
540
 
 
541
                        spades::ui::Label label(Parent.Manager);
 
542
                        label.Text = caption;
 
543
                        label.Alignment = Vector2(0.f, 0.5f);
 
544
                        label.Bounds = AABB2(10.f, 0.f, 300.f, 32.f);
 
545
                        container.AddChild(label);
 
546
 
 
547
                        ConfigField field(Parent.Manager, configName);
 
548
                        field.Bounds = AABB2(FieldX, 1.f, FieldWidth, 30.f);
 
549
                        field.Enable = enabled;
 
550
                        container.AddChild(field);
 
551
 
 
552
                        return field;
 
553
                }
 
554
 
 
555
                ConfigSlider@ AddSliderField(string caption, string configName,
 
556
                         float minRange, float maxRange, float step,
 
557
                         ConfigNumberFormatter@ formatter, bool enabled = true) {
 
558
                        spades::ui::UIElement@ container = CreateItem();
 
559
 
 
560
                        spades::ui::Label label(Parent.Manager);
 
561
                        label.Text = caption;
 
562
                        label.Alignment = Vector2(0.f, 0.5f);
 
563
                        label.Bounds = AABB2(10.f, 0.f, 300.f, 32.f);
 
564
                        container.AddChild(label);
 
565
 
 
566
                        ConfigSlider slider(Parent.Manager, configName, minRange, maxRange, step,
 
567
                                formatter);
 
568
                        slider.Bounds = AABB2(FieldX, 8.f, FieldWidth - 80.f, 16.f);
 
569
                        slider.Enable = enabled;
 
570
                        container.AddChild(slider);
 
571
 
 
572
                        return slider;
 
573
                }
 
574
 
 
575
                void AddControl(string caption, string configName, bool enabled = true) {
 
576
                        spades::ui::UIElement@ container = CreateItem();
 
577
 
 
578
                        spades::ui::Label label(Parent.Manager);
 
579
                        label.Text = caption;
 
580
                        label.Alignment = Vector2(0.f, 0.5f);
 
581
                        label.Bounds = AABB2(10.f, 0.f, 300.f, 32.f);
 
582
                        container.AddChild(label);
 
583
 
 
584
                        ConfigHotKeyField field(Parent.Manager, configName);
 
585
                        field.Bounds = AABB2(FieldX, 1.f, FieldWidth, 30.f);
 
586
                        field.Enable = enabled;
 
587
                        container.AddChild(field);
 
588
 
 
589
                        @field.KeyBound = spades::ui::EventHandler(OnKeyBound);
 
590
                        hotkeyItems.insertLast(field);
 
591
                }
 
592
 
 
593
                void AddChoiceField(string caption, string configName, array<string> labels, array<int> values, bool enabled = true) {
 
594
                        spades::ui::UIElement@ container = CreateItem();
 
595
 
 
596
                        spades::ui::Label label(Parent.Manager);
 
597
                        label.Text = caption;
 
598
                        label.Alignment = Vector2(0.f, 0.5f);
 
599
                        label.Bounds = AABB2(10.f, 0.f, 300.f, 32.f);
 
600
                        container.AddChild(label);
 
601
 
 
602
                        for (uint i = 0; i < labels.length; ++i) {
 
603
                                ConfigSimpleToggleButton field(Parent.Manager, labels[i], configName, values[i]);
 
604
                                field.Bounds = AABB2(FieldX + FieldWidth / labels.length * i,
 
605
                                        1.f, FieldWidth / labels.length, 30.f);
 
606
                                field.Enable = enabled;
 
607
                                container.AddChild(field);
 
608
                        }
 
609
                }
 
610
 
 
611
                void AddToggleField(string caption, string configName, bool enabled = true) {
 
612
                        AddChoiceField(caption, configName,
 
613
                                array<string> = {_Tr("Preferences", "ON"), _Tr("Preferences", "OFF")},
 
614
                                array<int> = {1, 0}, enabled);
 
615
                }
 
616
 
 
617
                void AddPlusMinusField(string caption, string configName, bool enabled = true) {
 
618
                        AddChoiceField(caption, configName,
 
619
                                array<string> = {_Tr("Preferences", "ON"), _Tr("Preferences", "REVERSED"), _Tr("Preferences", "OFF")},
 
620
                                array<int> = {1, -1, 0}, enabled);
 
621
                }
 
622
 
 
623
                void FinishLayout() {
 
624
                        spades::ui::ListView list(Parent.Manager);
 
625
                        @list.Model = StandardPreferenceLayouterModel(items);
 
626
                        list.RowHeight = 32.f;
 
627
                        list.Bounds = AABB2(0.f, 0.f, 580.f, 530.f);
 
628
                        Parent.AddChild(list);
 
629
                }
 
630
        }
 
631
 
 
632
        class GameOptionsPanel: spades::ui::UIElement {
 
633
                GameOptionsPanel(spades::ui::UIManager@ manager, PreferenceViewOptions@ options, FontManager@ fontManager) {
 
634
                        super(manager);
 
635
 
 
636
                        StandardPreferenceLayouter layouter(this, fontManager);
 
637
                        layouter.AddHeading(_Tr("Preferences", "Player Information"));
 
638
                        ConfigField@ nameField = layouter.AddInputField(_Tr("Preferences", "Player Name"), "cg_playerName", not options.GameActive);
 
639
                        nameField.MaxLength = 15;
 
640
                        nameField.DenyNonAscii = true;
 
641
 
 
642
                        layouter.AddHeading(_Tr("Preferences", "Effects"));
 
643
                        layouter.AddToggleField(_Tr("Preferences", "Blood"), "cg_blood");
 
644
                        layouter.AddToggleField(_Tr("Preferences", "Ejecting Brass"), "cg_ejectBrass");
 
645
                        layouter.AddToggleField(_Tr("Preferences", "Ragdoll"), "cg_ragdoll");
 
646
                        layouter.AddToggleField(_Tr("Preferences", "Animations"), "cg_animations");
 
647
                        layouter.AddChoiceField(_Tr("Preferences", "Camera Shake"), "cg_shake",
 
648
                                array<string> = {_Tr("Preferences", "MORE"), _Tr("Preferences", "NORMAL"), _Tr("Preferences", "OFF")},
 
649
                                array<int> = {2, 1, 0});
 
650
                        layouter.AddChoiceField(_Tr("Preferences", "Particles"), "cg_particles",
 
651
                                array<string> = {_Tr("Preferences", "NORMAL"), _Tr("Preferences", "LESS"), _Tr("Preferences", "OFF")},
 
652
                                array<int> = {2, 1, 0});
 
653
 
 
654
                        layouter.AddHeading(_Tr("Preferences", "Feedbacks"));
 
655
                        layouter.AddToggleField(_Tr("Preferences", "Chat Notify Sounds"), "cg_chatBeep");
 
656
                        layouter.AddToggleField(_Tr("Preferences", "Hit Indicator"), "cg_hitIndicator");
 
657
                        layouter.AddToggleField(_Tr("Preferences", "Show Alerts"), "cg_alerts");
 
658
 
 
659
                        layouter.AddHeading(_Tr("Preferences", "AoS 0.75/0.76 Compatibility"));
 
660
                        layouter.AddToggleField(_Tr("Preferences", "Allow Unicode"), "cg_unicode");
 
661
                        layouter.AddToggleField(_Tr("Preferences", "Server Alert"), "cg_serverAlert");
 
662
 
 
663
                        layouter.AddHeading(_Tr("Preferences", "Misc"));
 
664
                        layouter.AddSliderField(_Tr("Preferences", "Field of View"), "cg_fov", 45, 90, 1,
 
665
                                ConfigNumberFormatter(0, " deg"));
 
666
                        layouter.AddSliderField(_Tr("Preferences", "Minimap size"), "cg_minimapSize", 128, 256, 8,
 
667
                                ConfigNumberFormatter(0, " px"));
 
668
                        layouter.AddToggleField(_Tr("Preferences", "Show Statistics"), "cg_stats");
 
669
                        layouter.FinishLayout();
 
670
                }
 
671
        }
 
672
 
 
673
        class ControlOptionsPanel: spades::ui::UIElement {
 
674
                ControlOptionsPanel(spades::ui::UIManager@ manager, PreferenceViewOptions@ options, FontManager@ fontManager) {
 
675
                        super(manager);
 
676
 
 
677
                        StandardPreferenceLayouter layouter(this, fontManager);
 
678
                        layouter.AddHeading(_Tr("Preferences", "Weapons/Tools"));
 
679
                        layouter.AddControl(_Tr("Preferences", "Attack"), "cg_keyAttack");
 
680
                        layouter.AddControl(_Tr("Preferences", "Alt. Attack"), "cg_keyAltAttack");
 
681
                        layouter.AddToggleField(_Tr("Preferences", "Hold Aim Down Sight"), "cg_holdAimDownSight");
 
682
                        layouter.AddSliderField(_Tr("Preferences", "Mouse Sensitivity"), "cg_mouseSensitivity", 0.1, 10, 0.1,
 
683
                                ConfigNumberFormatter(1, "x"));
 
684
                        layouter.AddSliderField(_Tr("Preferences", "ADS Mouse Sens. Scale"), "cg_zoomedMouseSensScale", 0.05, 3, 0.05,
 
685
                                ConfigNumberFormatter(2, "x"));
 
686
                        layouter.AddSliderField(_Tr("Preferences", "Exponential Power"), "cg_mouseExpPower", 0.5, 1.5, 0.02,
 
687
                                ConfigNumberFormatter(2, "", "^"));
 
688
                        layouter.AddToggleField(_Tr("Preferences", "Invert Y-axis Mouse Input"), "cg_invertMouseY");
 
689
                        layouter.AddControl(_Tr("Preferences", "Reload"), "cg_keyReloadWeapon");
 
690
                        layouter.AddControl(_Tr("Preferences", "Capture Color"), "cg_keyCaptureColor");
 
691
                        layouter.AddControl(_Tr("Preferences", "Equip Spade"), "cg_keyToolSpade");
 
692
                        layouter.AddControl(_Tr("Preferences", "Equip Block"), "cg_keyToolBlock");
 
693
                        layouter.AddControl(_Tr("Preferences", "Equip Weapon"), "cg_keyToolWeapon");
 
694
                        layouter.AddControl(_Tr("Preferences", "Equip Grenade"), "cg_keyToolGrenade");
 
695
                        layouter.AddControl(_Tr("Preferences", "Last Used Tool"), "cg_keyLastTool");
 
696
                        layouter.AddPlusMinusField(_Tr("Preferences", "Switch Tools by Wheel"), "cg_switchToolByWheel");
 
697
 
 
698
                        layouter.AddHeading(_Tr("Preferences", "Movement"));
 
699
                        layouter.AddControl(_Tr("Preferences", "Walk Forward"), "cg_keyMoveForward");
 
700
                        layouter.AddControl(_Tr("Preferences", "Backpedal"), "cg_keyMoveBackward");
 
701
                        layouter.AddControl(_Tr("Preferences", "Move Left"), "cg_keyMoveLeft");
 
702
                        layouter.AddControl(_Tr("Preferences", "Move Right"), "cg_keyMoveRight");
 
703
                        layouter.AddControl(_Tr("Preferences", "Crouch"), "cg_keyCrouch");
 
704
                        layouter.AddControl(_Tr("Preferences", "Sneak"), "cg_keySneak");
 
705
                        layouter.AddControl(_Tr("Preferences", "Jump"), "cg_keyJump");
 
706
                        layouter.AddControl(_Tr("Preferences", "Sprint"), "cg_keySprint");
 
707
 
 
708
                        layouter.AddHeading(_Tr("Preferences", "Misc"));
 
709
                        layouter.AddControl(_Tr("Preferences", "Minimap Scale"), "cg_keyChangeMapScale");
 
710
                        layouter.AddControl(_Tr("Preferences", "Toggle Map"), "cg_keyToggleMapZoom");
 
711
                        layouter.AddControl(_Tr("Preferences", "Flashlight"), "cg_keyFlashlight");
 
712
                        layouter.AddControl(_Tr("Preferences", "Global Chat"), "cg_keyGlobalChat");
 
713
                        layouter.AddControl(_Tr("Preferences", "Team Chat"), "cg_keyTeamChat");
 
714
                        layouter.AddControl(_Tr("Preferences", "Limbo Menu"), "cg_keyLimbo");
 
715
                        layouter.AddControl(_Tr("Preferences", "Save Map"), "cg_keySaveMap");
 
716
                        layouter.AddControl(_Tr("Preferences", "Save Sceneshot"), "cg_keySceneshot");
 
717
                        layouter.AddControl(_Tr("Preferences", "Save Screenshot"), "cg_keyScreenshot");
 
718
 
 
719
                        layouter.FinishLayout();
 
720
                }
 
721
        }
 
722
 
 
723
 
 
724
        class MiscOptionsPanel: spades::ui::UIElement {
 
725
                spades::ui::Label@ msgLabel;
 
726
                spades::ui::Button@ enableButton;
 
727
 
 
728
                private ConfigItem cl_showStartupWindow("cl_showStartupWindow");
 
729
 
 
730
                MiscOptionsPanel(spades::ui::UIManager@ manager, PreferenceViewOptions@ options, FontManager@ fontManager) {
 
731
                        super(manager);
 
732
 
 
733
                        {
 
734
                                spades::ui::Button e(Manager);
 
735
                                e.Bounds = AABB2(10.f, 10.f, 400.f, 30.f);
 
736
                                e.Caption = _Tr("Preferences", "Enable Startup Window");
 
737
                                @e.Activated = spades::ui::EventHandler(this.OnEnableClicked);
 
738
                                AddChild(e);
 
739
                                @enableButton = e;
 
740
                        }
 
741
 
 
742
                        {
 
743
                                spades::ui::Label label(Manager);
 
744
                                label.Bounds = AABB2(10.f, 50.f, 0.f, 0.f);
 
745
                                label.Text = "Hoge";
 
746
                                AddChild(label);
 
747
                                @msgLabel = label;
 
748
                        }
 
749
 
 
750
                        UpdateState();
 
751
                }
 
752
 
 
753
                void UpdateState() {
 
754
                        bool enabled = cl_showStartupWindow.IntValue != 0;
 
755
 
 
756
                        msgLabel.Text = enabled ?
 
757
                                _Tr("Preferences", "Quit and restart OpenSpades to access the startup window."):
 
758
                                _Tr("Preferences", "Some settings only can be changed in the startup window.");
 
759
                        enableButton.Enable = not enabled;
 
760
                }
 
761
 
 
762
                private void OnEnableClicked(spades::ui::UIElement@) {
 
763
                        cl_showStartupWindow.IntValue = 1;
 
764
                        UpdateState();
 
765
                }
 
766
 
 
767
        }
 
768
}