]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/xonotic/charmap.qc
Sort menu classes
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / charmap.qc
1 #ifndef CHARMAP_H
2 #define CHARMAP_H
3 CLASS(XonoticCharmap, Item)
4         METHOD(XonoticCharmap, configureXonoticCharmap, void(entity, entity))
5         METHOD(XonoticCharmap, mousePress, float(entity, vector))
6         METHOD(XonoticCharmap, mouseRelease, float(entity, vector))
7         METHOD(XonoticCharmap, mouseMove, float(entity, vector))
8         METHOD(XonoticCharmap, mouseDrag, float(entity, vector))
9         METHOD(XonoticCharmap, keyDown, float(entity, float, float, float))
10         METHOD(XonoticCharmap, focusLeave, void(entity))
11         METHOD(XonoticCharmap, resizeNotify, void(entity, vector, vector, vector, vector))
12         METHOD(XonoticCharmap, draw, void(entity))
13         ATTRIB(XonoticCharmap, focusable, float, 1)
14
15         METHOD(XonoticCharmap, moveFocus, void(entity, vector, vector))
16         METHOD(XonoticCharmap, enterChar, void(entity))
17         ATTRIB(XonoticCharmap, inputBox, entity, NULL)
18         ATTRIB(XonoticCharmap, realFontSize, vector, '0 0 0')
19         ATTRIB(XonoticCharmap, realCellSize, vector, '0 0 0')
20         ATTRIB(XonoticCharmap, focusedCell, vector, '-1 -1 0')
21         ATTRIB(XonoticCharmap, previouslyFocusedCell, vector, '-1 -1 0')
22 ENDCLASS(XonoticCharmap)
23 entity makeXonoticCharmap(entity controlledInputBox);
24 #endif
25
26 #ifdef IMPLEMENTATION
27
28 const float CHARMAP_COLS = 14;
29 const float CHARMAP_ROWS = 10;
30
31 string CHARMAP =
32         "★◆■▮▰▬◣◤◥◢◀▲▶▼"
33         "🌍🌎🌏🚀🌌👽🔫⌖❇❈←↑→↓"
34         "☠☣☢⚛⚡⚙🔥❌⚠⛔❰❱❲❳"
35         "😃😊😁😄😆😎😈😇😉😛😝😘❤ "
36         "😐😒😕😮😲😞😟😠😣😭😵😴  "
37         "\xEE\x83\xA1\xEE\x83\xA2\xEE\x83\xA3\xEE\x83\xA4\xEE\x83\xA5\xEE\x83\xA6\xEE\x83\xA7"
38         "\xEE\x83\xA8\xEE\x83\xA9\xEE\x83\xAA\xEE\x83\xAB\xEE\x83\xAC\xEE\x83\xAD\xEE\x83\xAE"
39         "\xEE\x83\xAF\xEE\x83\xB0\xEE\x83\xB1\xEE\x83\xB2\xEE\x83\xB3\xEE\x83\xB4\xEE\x83\xB5"
40         "\xEE\x83\xB6\xEE\x83\xB7\xEE\x83\xB8\xEE\x83\xB9\xEE\x83\xBA\xEE\x80\x90\xEE\x80\x91"
41         "\xEE\x82\xB0\xEE\x82\xB1\xEE\x82\xB2\xEE\x82\xB3\xEE\x82\xB4\xEE\x82\xB5\xEE\x82\xB6"
42         "\xEE\x82\xB7\xEE\x82\xB8\xEE\x82\xB9\xEE\x82\xA1\xEE\x82\xBF\xEE\x82\xA6\xEE\x82\xA5"
43         "\xEE\x83\x81\xEE\x83\x82\xEE\x83\x83\xEE\x83\x84\xEE\x83\x85\xEE\x83\x86\xEE\x83\x87"
44         "\xEE\x83\x88\xEE\x83\x89\xEE\x83\x8A\xEE\x83\x8B\xEE\x83\x8C\xEE\x83\x8D\xEE\x83\x8E"
45         "\xEE\x83\x8F\xEE\x83\x90\xEE\x83\x91\xEE\x83\x92\xEE\x83\x93\xEE\x83\x94\xEE\x83\x95"
46         "\xEE\x83\x96\xEE\x83\x97\xEE\x83\x98\xEE\x83\x99\xEE\x83\x9A\xEE\x81\x9B\xEE\x81\x9D";
47
48 string charmap_cellToChar(vector cell)
49 {
50         string character = substring(CHARMAP, cell.y * CHARMAP_COLS + cell.x, 1);
51
52         if (character != " ")
53                 return character;
54         else
55                 return "";
56 }
57
58 entity makeXonoticCharmap(entity controlledInputBox)
59 {
60         entity me;
61         me = NEW(XonoticCharmap);
62         me.configureXonoticCharmap(me, controlledInputBox);
63         return me;
64 }
65
66 void XonoticCharmap_configureXonoticCharmap(entity me, entity controlledInputBox)
67 {
68         me.inputBox = controlledInputBox;
69         me.realCellSize = eX / CHARMAP_COLS + eY / CHARMAP_ROWS;
70 }
71
72 void XonoticCharmap_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
73 {
74         SUPER(XonoticCharmap).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
75
76         float maxFontWidth = SKINFONTSIZE_NORMAL / absSize.x;
77         float maxFontHeight = SKINFONTSIZE_NORMAL / absSize.y;
78
79         if((me.realCellSize.x * absSize.x) > (me.realCellSize.y * absSize.y))
80         {
81                 me.realFontSize_x = me.realCellSize.y * absSize.y / absSize.x;
82                 me.realFontSize_y = me.realCellSize.y;
83         }
84         else
85         {
86                 me.realFontSize_x = me.realCellSize.x;
87                 me.realFontSize_y = me.realCellSize.x * absSize.x / absSize.y;
88         }
89
90         if(me.realFontSize.x > maxFontWidth || me.realFontSize.y > maxFontHeight)
91                 me.realFontSize = eX * maxFontWidth + eY * maxFontHeight;
92 }
93
94 float XonoticCharmap_mouseMove(entity me, vector coords)
95 {
96         me.focusedCell_x = floor(coords.x * CHARMAP_COLS);
97         me.focusedCell_y = floor(coords.y * CHARMAP_ROWS);
98
99         if(me.focusedCell.x < 0 || me.focusedCell.y < 0 ||
100            me.focusedCell.x >= CHARMAP_COLS || me.focusedCell.y >= CHARMAP_ROWS)
101         {
102                 me.focusedCell = '-1 -1 0';
103                 return 0;
104         }
105
106         return 1;
107 }
108
109 float XonoticCharmap_mouseDrag(entity me, vector coords)
110 {
111         return me.mouseMove(me, coords);
112 }
113
114 float XonoticCharmap_mousePress(entity me, vector coords)
115 {
116         me.mouseMove(me, coords);
117
118         if(me.focusedCell.x >= 0)
119         {
120                 me.pressed = 1;
121                 me.previouslyFocusedCell = me.focusedCell;
122         }
123
124         return 1;
125 }
126
127 float XonoticCharmap_mouseRelease(entity me, vector coords)
128 {
129         if(!me.pressed)
130                 return 0;
131
132         me.mouseMove(me, coords);
133
134         if(me.focusedCell == me.previouslyFocusedCell)
135                 me.enterChar(me);
136
137         me.pressed = 0;
138         return 1;
139 }
140
141 float XonoticCharmap_keyDown(entity me, float key, float ascii, float shift)
142 {
143         switch(key)
144         {
145                 case K_LEFTARROW:
146                 case K_KP_LEFTARROW:
147                         me.moveFocus(me, me.focusedCell, '-1 0 0');
148                         return 1;
149                 case K_RIGHTARROW:
150                 case K_KP_RIGHTARROW:
151                         me.moveFocus(me, me.focusedCell, '1 0 0');
152                         return 1;
153                 case K_UPARROW:
154                 case K_KP_UPARROW:
155                         me.moveFocus(me, me.focusedCell, '0 -1 0');
156                         return 1;
157                 case K_DOWNARROW:
158                 case K_KP_DOWNARROW:
159                         me.moveFocus(me, me.focusedCell, '0 1 0');
160                         return 1;
161                 case K_HOME:
162                 case K_KP_HOME:
163                         me.focusedCell = '0 0 0';
164                         return 1;
165                 case K_END:
166                 case K_KP_END:
167                         me.focusedCell_x = CHARMAP_COLS - 1;
168                         me.focusedCell_y = CHARMAP_ROWS - 1;
169                         return 1;
170                 case K_ENTER:
171                 case K_KP_ENTER:
172                 case K_INS:
173                 case K_KP_INS:
174                         me.enterChar(me);
175                         return 1;
176                 default:
177                         return me.inputBox.keyDown(me.inputBox, key, ascii, shift);
178         }
179 }
180
181 void XonoticCharmap_moveFocus(entity me, vector initialCell, vector step)
182 {
183         me.focusedCell_x = mod(me.focusedCell.x + step.x + CHARMAP_COLS, CHARMAP_COLS);
184         me.focusedCell_y = mod(me.focusedCell.y + step.y + CHARMAP_ROWS, CHARMAP_ROWS);
185
186         if(me.focusedCell != initialCell) // Recursion break
187                 if(charmap_cellToChar(me.focusedCell) == "")
188                         me.moveFocus(me, initialCell, step);
189 }
190
191 void XonoticCharmap_enterChar(entity me)
192 {
193         string character = charmap_cellToChar(me.focusedCell);
194         if(character != "")
195                 me.inputBox.enterText(me.inputBox, character);
196 }
197
198 void XonoticCharmap_focusLeave(entity me)
199 {
200         me.inputBox.saveCvars(me.inputBox);
201 }
202
203 void XonoticCharmap_draw(entity me)
204 {
205         string character;
206         vector cell, cellPos, charPos;
207         cell = '0 0 0';
208         cellPos = '0 0 0';
209         charPos = '0 0 0';
210
211         float CHAR_OFFSET_X = me.realCellSize.x / 2;
212         float CHAR_OFFSET_Y = (me.realCellSize.y - me.realFontSize.y) / 2;
213
214         for(cell_y = 0; cell.y < CHARMAP_ROWS; ++cell.y)
215         {
216                 charPos_y = cell.y / CHARMAP_ROWS + CHAR_OFFSET_Y;
217                 for(cell_x = 0; cell.x < CHARMAP_COLS; ++cell.x)
218                 {
219                         character = charmap_cellToChar(cell);
220
221                         if(character == "")
222                                 continue;
223
224                         // Draw focused cell
225                         if(cell == me.focusedCell && me.focused)
226                         {
227                                 if(!me.pressed || me.focusedCell == me.previouslyFocusedCell)
228                                 {
229                                         cellPos_x = mod(me.focusedCell.x, CHARMAP_COLS) / CHARMAP_COLS;
230                                         cellPos_y = mod(me.focusedCell.y, CHARMAP_ROWS) / CHARMAP_ROWS;
231                                         draw_Fill(cellPos, me.realCellSize, SKINCOLOR_CHARMAP_FOCUS, SKINALPHA_CHARMAP_FOCUS);
232                                 }
233                         }
234
235                         // Draw character
236                         charPos_x = cell.x / CHARMAP_COLS + CHAR_OFFSET_X;
237                         draw_CenterText(charPos, character, me.realFontSize, SKINCOLOR_CHARMAP_CHAR, SKINALPHA_CHARMAP_CHAR, 0);
238                 }
239         }
240 }
241 #endif