Listbox: highlight item under the cursor
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / skinlist.qc
1 #ifdef INTERFACE
2 CLASS(XonoticSkinList) EXTENDS(XonoticListBox)
3         METHOD(XonoticSkinList, configureXonoticSkinList, void(entity))
4         ATTRIB(XonoticSkinList, rowsPerItem, float, 4)
5         METHOD(XonoticSkinList, resizeNotify, void(entity, vector, vector, vector, vector))
6         METHOD(XonoticSkinList, drawListBoxItem, void(entity, int, vector, bool, float))
7         METHOD(XonoticSkinList, getSkins, void(entity))
8         METHOD(XonoticSkinList, setSkin, void(entity))
9         METHOD(XonoticSkinList, loadCvars, void(entity))
10         METHOD(XonoticSkinList, saveCvars, void(entity))
11         METHOD(XonoticSkinList, skinParameter, string(entity, float, float))
12         METHOD(XonoticSkinList, doubleClickListBoxItem, void(entity, float, vector))
13         METHOD(XonoticSkinList, keyDown, float(entity, float, float, float))
14         METHOD(XonoticSkinList, destroy, void(entity))
15
16         ATTRIB(XonoticSkinList, skinlist, float, -1)
17         ATTRIB(XonoticSkinList, realFontSize, vector, '0 0 0')
18         ATTRIB(XonoticSkinList, columnPreviewOrigin, float, 0)
19         ATTRIB(XonoticSkinList, columnPreviewSize, float, 0)
20         ATTRIB(XonoticSkinList, columnNameOrigin, float, 0)
21         ATTRIB(XonoticSkinList, columnNameSize, float, 0)
22         ATTRIB(XonoticSkinList, realUpperMargin1, float, 0)
23         ATTRIB(XonoticSkinList, realUpperMargin2, float, 0)
24         ATTRIB(XonoticSkinList, origin, vector, '0 0 0')
25         ATTRIB(XonoticSkinList, itemAbsSize, vector, '0 0 0')
26
27         ATTRIB(XonoticSkinList, name, string, "skinselector")
28 ENDCLASS(XonoticSkinList)
29
30 entity makeXonoticSkinList();
31 void SetSkin_Click(entity btn, entity me);
32 #endif
33
34 #ifdef IMPLEMENTATION
35
36 const float SKINPARM_NAME = 0;
37 const float SKINPARM_TITLE = 1;
38 const float SKINPARM_AUTHOR = 2;
39 const float SKINPARM_PREVIEW = 3;
40 const float SKINPARM_COUNT = 4;
41
42 entity makeXonoticSkinList()
43 {
44         entity me;
45         me = spawnXonoticSkinList();
46         me.configureXonoticSkinList(me);
47         return me;
48 }
49
50 void XonoticSkinList_configureXonoticSkinList(entity me)
51 {
52         me.configureXonoticListBox(me);
53         me.getSkins(me);
54         me.loadCvars(me);
55 }
56
57 void XonoticSkinList_loadCvars(entity me)
58 {
59         string s;
60         float i, n;
61         s = cvar_string("menu_skin");
62         n = me.nItems;
63         for(i = 0; i < n; ++i)
64         {
65                 if(me.skinParameter(me, i, SKINPARM_NAME) == s)
66                 {
67                         me.selectedItem = i;
68                         break;
69                 }
70         }
71 }
72
73 void XonoticSkinList_saveCvars(entity me)
74 {
75         cvar_set("menu_skin", me.skinParameter(me, me.selectedItem, SKINPARM_NAME));
76 }
77
78 string XonoticSkinList_skinParameter(entity me, float i, float key)
79 {
80         return bufstr_get(me.skinlist, i * SKINPARM_COUNT + key);
81 }
82
83 void XonoticSkinList_getSkins(entity me)
84 {
85         float glob, buf, i, n, fh;
86         string s;
87
88         buf = buf_create();
89         glob = search_begin("gfx/menu/*/skinvalues.txt", true, true);
90         if(glob < 0)
91         {
92                 me.skinlist = buf;
93                 me.nItems = 0;
94                 return;
95         }
96
97         n = search_getsize(glob);
98         for(i = 0; i < n; ++i)
99         {
100                 s = search_getfilename(glob, i);
101                 bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_NAME, substring(s, 9, strlen(s) - 24)); // the * part
102                 bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, _("<TITLE>"));
103                 bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, _("<AUTHOR>"));
104                 if(draw_PictureSize(strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview")) == '0 0 0')
105                         bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, "nopreview_menuskin");
106                 else
107                         bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview"));
108                 fh = fopen(language_filename(s), FILE_READ);
109                 if(fh < 0)
110                 {
111                         print("Warning: can't open skinvalues.txt file\n");
112                         continue;
113                 }
114                 while((s = fgets(fh)))
115                 {
116                         // these two are handled by skinlist.qc
117                         if(substring(s, 0, 6) == "title ")
118                                 bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, substring(s, 6, strlen(s) - 6));
119                         else if(substring(s, 0, 7) == "author ")
120                                 bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, substring(s, 7, strlen(s) - 7));
121                 }
122                 fclose(fh);
123         }
124
125         search_end(glob);
126
127         me.skinlist = buf;
128         me.nItems = n;
129 }
130
131 void XonoticSkinList_destroy(entity me)
132 {
133         buf_del(me.skinlist);
134 }
135
136 void XonoticSkinList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
137 {
138         me.itemAbsSize = '0 0 0';
139         SUPER(XonoticSkinList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
140
141         me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
142         me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
143         me.realUpperMargin1 = 0.5 * (1 - 2.5 * me.realFontSize.y);
144         me.realUpperMargin2 = me.realUpperMargin1 + 1.5 * me.realFontSize.y;
145
146         me.columnPreviewOrigin = 0;
147         me.columnPreviewSize = me.itemAbsSize.y / me.itemAbsSize.x * 4 / 3;
148         me.columnNameOrigin = me.columnPreviewOrigin + me.columnPreviewSize + me.realFontSize.x;
149         me.columnNameSize = 1 - me.columnPreviewSize - 2 * me.realFontSize.x;
150 }
151
152 void XonoticSkinList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, float highlightedTime)
153 {
154         string s;
155
156         if(isSelected)
157                 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
158         else if(highlightedTime)
159                 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, getHighlightAlpha(SKINALPHA_LISTBOX_SELECTED * 0.1, highlightedTime));
160
161         s = me.skinParameter(me, i, SKINPARM_PREVIEW);
162         draw_Picture(me.columnPreviewOrigin * eX, s, me.columnPreviewSize * eX + eY, '1 1 1', 1);
163
164         s = me.skinParameter(me, i, SKINPARM_TITLE);
165         s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
166         draw_Text(me.realUpperMargin1 * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_SKINLIST_TITLE, SKINALPHA_TEXT, 0);
167
168         s = me.skinParameter(me, i, SKINPARM_AUTHOR);
169         s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
170         draw_Text(me.realUpperMargin2 * eY + (me.columnNameOrigin + 1.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, SKINCOLOR_SKINLIST_AUTHOR, SKINALPHA_TEXT, 0);
171 }
172
173 void XonoticSkinList_setSkin(entity me)
174 {
175         me.saveCvars(me);
176         localcmd("\nmenu_restart\nmenu_cmd skinselect\n");
177 }
178
179 void SetSkin_Click(entity btn, entity me)
180 {
181         me.setSkin(me);
182 }
183
184 void XonoticSkinList_doubleClickListBoxItem(entity me, float i, vector where)
185 {
186         m_play_click_sound(MENU_SOUND_EXECUTE);
187         me.setSkin(me);
188 }
189
190 float XonoticSkinList_keyDown(entity me, float scan, float ascii, float shift)
191 {
192         if(scan == K_ENTER || scan == K_KP_ENTER)
193         {
194                 m_play_click_sound(MENU_SOUND_EXECUTE);
195                 me.setSkin(me);
196                 return 1;
197         }
198         else
199                 return SUPER(XonoticSkinList).keyDown(me, scan, ascii, shift);
200 }
201 #endif