]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/xonotic/charmap.c
Use a string instead of arrays for the charmap
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / charmap.c
1 #ifdef INTERFACE
2 CLASS(XonoticCharmap) EXTENDS(Item)
3         METHOD(XonoticCharmap, configureXonoticCharmap, void(entity, entity))
4         METHOD(XonoticCharmap, mousePress, float(entity, vector))
5         METHOD(XonoticCharmap, mouseRelease, float(entity, vector))
6         METHOD(XonoticCharmap, mouseMove, float(entity, vector))
7         METHOD(XonoticCharmap, mouseDrag, float(entity, vector))
8         METHOD(XonoticCharmap, keyDown, float(entity, float, float, float))
9         METHOD(XonoticCharmap, focusLeave, void(entity))
10         METHOD(XonoticCharmap, resizeNotify, void(entity, vector, vector, vector, vector))
11         METHOD(XonoticCharmap, draw, void(entity))
12         ATTRIB(XonoticCharmap, focusable, float, 1)
13
14         METHOD(XonoticCharmap, moveFocus, void(entity, vector, vector))
15         METHOD(XonoticCharmap, enterChar, void(entity))
16         ATTRIB(XonoticCharmap, inputBox, entity, NULL)
17         ATTRIB(XonoticCharmap, realFontSize, vector, '0 0 0')
18         ATTRIB(XonoticCharmap, realCellSize, vector, '0 0 0')
19         ATTRIB(XonoticCharmap, focusedCell, vector, '-1 -1 0')
20         ATTRIB(XonoticCharmap, previouslyFocusedCell, vector, '-1 -1 0')
21 ENDCLASS(XonoticCharmap)
22 entity makeXonoticCharmap(entity controlledInputBox);
23 #endif
24
25 #ifdef IMPLEMENTATION
26
27 #define CHARMAP_COLS 14
28 #define CHARMAP_ROWS 10
29
30 string CHARMAP =
31         "๐ŸŒ๐ŸŒŽ๐ŸŒ๐Ÿš€๐ŸŒŒ๐Ÿ‘ฝ๐Ÿ”ซโŒ–โ‡โˆโ†โ†‘โ†’โ†“"
32         "โ˜ โ˜ฃโ˜ขโš›โšกโš™๐Ÿ”ฅโŒโš โ›”โฐโฑโฒโณ"
33         "โ˜…โ—†โ– โ–ฎโ–ฐโ–ฌโ—ฃโ—คโ—ฅโ—ขโ—€โ–ฒโ–ถโ–ผ"
34         "๐Ÿ˜ƒ๐Ÿ˜Š๐Ÿ˜๐Ÿ˜„๐Ÿ˜†๐Ÿ˜Ž๐Ÿ˜ˆ๐Ÿ˜‡๐Ÿ˜‰๐Ÿ˜›๐Ÿ˜๐Ÿ˜˜โค "
35         "๐Ÿ˜๐Ÿ˜’๐Ÿ˜•๐Ÿ˜ฎ๐Ÿ˜ฒ๐Ÿ˜ž๐Ÿ˜Ÿ๐Ÿ˜ ๐Ÿ˜ฃ๐Ÿ˜ญ๐Ÿ˜ต๐Ÿ˜ด  "
36         "๎ƒก๎ƒข๎ƒฃ๎ƒค๎ƒฅ๎ƒฆ๎ƒง๎ƒจ๎ƒฉ๎ƒช๎ƒซ๎ƒฌ๎ƒญ๎ƒฎ"
37         "๎ƒฏ๎ƒฐ๎ƒฑ๎ƒฒ๎ƒณ๎ƒด๎ƒต๎ƒถ๎ƒท๎ƒธ๎ƒน๎ƒบ๎€๎€‘"
38         "๎‚ฐ๎‚ฑ๎‚ฒ๎‚ณ๎‚ด๎‚ต๎‚ถ๎‚ท๎‚ธ๎‚น๎‚ก๎‚ฟ๎‚ฆ๎‚ฅ"
39         "๎ƒ๎ƒ‚๎ƒƒ๎ƒ„๎ƒ…๎ƒ†๎ƒ‡๎ƒˆ๎ƒ‰๎ƒŠ๎ƒ‹๎ƒŒ๎ƒ๎ƒŽ"
40         "๎ƒ๎ƒ๎ƒ‘๎ƒ’๎ƒ“๎ƒ”๎ƒ•๎ƒ–๎ƒ—๎ƒ˜๎ƒ™๎ƒš๎›๎";
41
42 string charmap_cellToChar(vector cell)
43 {
44         string character = substring(CHARMAP, cell_y * CHARMAP_COLS + cell_x, 1);
45
46         if (character != " ")
47                 return character;
48         else
49                 return "";
50 }
51
52 entity makeXonoticCharmap(entity controlledInputBox)
53 {
54         entity me;
55         me = spawnXonoticCharmap();
56         me.configureXonoticCharmap(me, controlledInputBox);
57         return me;
58 }
59
60 void XonoticCharmap_configureXonoticCharmap(entity me, entity controlledInputBox)
61 {
62         me.inputBox = controlledInputBox;
63         me.realCellSize = eX / CHARMAP_COLS + eY / CHARMAP_ROWS;
64 }
65
66 void XonoticCharmap_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
67 {
68         SUPER(XonoticCharmap).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
69
70         float maxFontWidth = SKINFONTSIZE_NORMAL / absSize_x;
71         float maxFontHeight = SKINFONTSIZE_NORMAL / absSize_y;
72
73         if((me.realCellSize_x * absSize_x) > (me.realCellSize_y * absSize_y))
74         {
75                 me.realFontSize_x = me.realCellSize_y * absSize_y / absSize_x;
76                 me.realFontSize_y = me.realCellSize_y;
77         }
78         else
79         {
80                 me.realFontSize_x = me.realCellSize_x;
81                 me.realFontSize_y = me.realCellSize_x * absSize_x / absSize_y;
82         }
83
84         if(me.realFontSize_x > maxFontWidth || me.realFontSize_y > maxFontHeight)
85                 me.realFontSize = eX * maxFontWidth + eY * maxFontHeight;
86 }
87
88 float XonoticCharmap_mouseMove(entity me, vector coords)
89 {
90         me.focusedCell_x = floor(coords_x * CHARMAP_COLS);
91         me.focusedCell_y = floor(coords_y * CHARMAP_ROWS);
92
93         if(me.focusedCell_x < 0 || me.focusedCell_y < 0 ||
94            me.focusedCell_x >= CHARMAP_COLS || me.focusedCell_y >= CHARMAP_ROWS)
95         {
96                 me.focusedCell = '-1 -1 0';
97                 return 0;
98         }
99
100         return 1;
101 }
102
103 float XonoticCharmap_mouseDrag(entity me, vector coords)
104 {
105         return me.mouseMove(me, coords);
106 }
107
108 float XonoticCharmap_mousePress(entity me, vector coords)
109 {
110         me.mouseMove(me, coords);
111
112         if(me.focusedCell_x >= 0)
113         {
114                 me.pressed = 1;
115                 me.previouslyFocusedCell = me.focusedCell;
116         }
117
118         return 1;
119 }
120
121 float XonoticCharmap_mouseRelease(entity me, vector coords)
122 {
123         if(!me.pressed)
124                 return 0;
125
126         me.mouseMove(me, coords);
127
128         if(me.focusedCell == me.previouslyFocusedCell)
129                 me.enterChar(me);
130
131         me.pressed = 0;
132         return 1;
133 }
134
135 float XonoticCharmap_keyDown(entity me, float key, float ascii, float shift)
136 {
137         switch(key)
138         {
139                 case K_LEFTARROW:
140                 case K_KP_LEFTARROW:
141                         me.moveFocus(me, me.focusedCell, '-1 0 0');
142                         return 1;
143                 case K_RIGHTARROW:
144                 case K_KP_RIGHTARROW:
145                         me.moveFocus(me, me.focusedCell, '1 0 0');
146                         return 1;
147                 case K_UPARROW:
148                 case K_KP_UPARROW:
149                         me.moveFocus(me, me.focusedCell, '0 -1 0');
150                         return 1;
151                 case K_DOWNARROW:
152                 case K_KP_DOWNARROW:
153                         me.moveFocus(me, me.focusedCell, '0 1 0');
154                         return 1;
155                 case K_HOME:
156                 case K_KP_HOME:
157                         me.focusedCell = '0 0 0';
158                         return 1;
159                 case K_END:
160                 case K_KP_END:
161                         me.focusedCell_x = CHARMAP_COLS - 1;
162                         me.focusedCell_y = CHARMAP_ROWS - 1;
163                         return 1;
164                 case K_ENTER:
165                 case K_KP_ENTER:
166                 case K_INS:
167                 case K_KP_INS:
168                         me.enterChar(me);
169                         return 1;
170                 default:
171                         return me.inputBox.keyDown(me.inputBox, key, ascii, shift);
172         }
173 }
174
175 void XonoticCharmap_moveFocus(entity me, vector initialCell, vector step)
176 {
177         me.focusedCell_x = mod(me.focusedCell_x + step_x + CHARMAP_COLS, CHARMAP_COLS);
178         me.focusedCell_y = mod(me.focusedCell_y + step_y + CHARMAP_ROWS, CHARMAP_ROWS);
179
180         if(me.focusedCell != initialCell) // Recursion break
181                 if(charmap_cellToChar(me.focusedCell) == "")
182                         me.moveFocus(me, initialCell, step);
183 }
184
185 void XonoticCharmap_enterChar(entity me)
186 {
187         string character = charmap_cellToChar(me.focusedCell);
188         if(character != "")
189                 me.inputBox.enterText(me.inputBox, character);
190 }
191
192 void XonoticCharmap_focusLeave(entity me)
193 {
194         me.inputBox.saveCvars(me.inputBox);
195 }
196
197 void XonoticCharmap_draw(entity me)
198 {
199         string character;
200         vector cell, cellPos, charPos;
201         cell = '0 0 0';
202         cellPos = '0 0 0';
203         charPos = '0 0 0';
204
205         float CHAR_OFFSET_X = me.realCellSize_x / 2;
206         float CHAR_OFFSET_Y = (me.realCellSize_y - me.realFontSize_y) / 2;
207
208         for(cell_y = 0; cell_y < CHARMAP_ROWS; ++cell_y)
209         {
210                 charPos_y = cell_y / CHARMAP_ROWS + CHAR_OFFSET_Y;
211                 for(cell_x = 0; cell_x < CHARMAP_COLS; ++cell_x)
212                 {
213                         character = charmap_cellToChar(cell);
214
215                         if(character == "")
216                                 continue;
217
218                         // Draw focused cell
219                         if(cell == me.focusedCell && me.focused)
220                         {
221                                 if(!me.pressed || me.focusedCell == me.previouslyFocusedCell)
222                                 {
223                                         cellPos_x = mod(me.focusedCell_x, CHARMAP_COLS) / CHARMAP_COLS;
224                                         cellPos_y = mod(me.focusedCell_y, CHARMAP_ROWS) / CHARMAP_ROWS;
225                                         draw_Fill(cellPos, me.realCellSize, SKINCOLOR_CHARMAP_FOCUS, SKINALPHA_CHARMAP_FOCUS);
226                                 }
227                         }
228
229                         // Draw character
230                         charPos_x = cell_x / CHARMAP_COLS + CHAR_OFFSET_X;
231                         draw_CenterText(charPos, character, me.realFontSize, SKINCOLOR_CHARMAP_CHAR, SKINALPHA_CHARMAP_CHAR, 0);
232                 }
233         }
234 }
235 #endif