File: | client/ui/node/ui_node_image.cpp |
Location: | line 181, column 26 |
Description: | The left operand of '+' is a garbage value |
1 | /** | ||
2 | * @file | ||
3 | * @brief The <code>pic</code> behaviour allow to draw an image or a part of an image | ||
4 | * into the GUI. It provide some layout properties. We can use it like an active node | ||
5 | * (mouse in/out/click...) but in this case, it is better to use nodes with a semantics (like button, | ||
6 | * or checkbox). | ||
7 | * @code | ||
8 | * image aircraft_return | ||
9 | * { | ||
10 | * src ui/buttons_small | ||
11 | * pos "550 410" | ||
12 | * texl "0 32" | ||
13 | * texh "16 48" | ||
14 | * [..] | ||
15 | * } | ||
16 | * @endcode | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | Copyright (C) 2002-2011 UFO: Alien Invasion. | ||
21 | |||
22 | This program is free software; you can redistribute it and/or | ||
23 | modify it under the terms of the GNU General Public License | ||
24 | as published by the Free Software Foundation; either version 2 | ||
25 | of the License, or (at your option) any later version. | ||
26 | |||
27 | This program is distributed in the hope that it will be useful, | ||
28 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
30 | |||
31 | See the GNU General Public License for more details. | ||
32 | |||
33 | You should have received a copy of the GNU General Public License | ||
34 | along with this program; if not, write to the Free Software | ||
35 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
36 | |||
37 | */ | ||
38 | |||
39 | #include "../ui_nodes.h" | ||
40 | #include "../ui_parse.h" | ||
41 | #include "../ui_behaviour.h" | ||
42 | #include "../ui_render.h" | ||
43 | #include "ui_node_image.h" | ||
44 | #include "ui_node_abstractnode.h" | ||
45 | |||
46 | #include "../../client.h" | ||
47 | |||
48 | #define EXTRADATA_TYPEimageExtraData_t imageExtraData_t | ||
49 | #define EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))) UI_EXTRADATA(node, EXTRADATA_TYPE)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))) | ||
50 | #define EXTRADATACONST(node)(*((const imageExtraData_t*)((const char*)node + sizeof(uiNode_t )))) UI_EXTRADATACONST(node, EXTRADATA_TYPE)(*((const imageExtraData_t*)((const char*)node + sizeof(uiNode_t )))) | ||
51 | |||
52 | /** | ||
53 | * @brief Handled after the end of the load of the node from the script (all data and/or child are set) | ||
54 | */ | ||
55 | void uiImageNode::onLoaded (uiNode_t *node) | ||
56 | { | ||
57 | /* update the size when its possible */ | ||
58 | if (Vector2Empty(node->box.size)(((fabs((((node->box.size))[0])-((vec2_origin)[0]))<0.0000000001 )?(fabs((((node->box.size))[1])-((vec2_origin)[1]))<0.0000000001 )?1:0:0))) { | ||
59 | if (EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texl[0] != 0 || EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texh[0]) { | ||
60 | node->box.size[0] = EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texh[0] - EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texl[0]; | ||
61 | node->box.size[1] = EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texh[1] - EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texl[1]; | ||
62 | } else if (EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).source) { | ||
63 | const image_t *image = UI_LoadImage(EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).source); | ||
64 | if (image) { | ||
65 | node->box.size[0] = image->width; | ||
66 | node->box.size[1] = image->height; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | #ifdef DEBUG1 | ||
71 | if (Vector2Empty(node->box.size)(((fabs((((node->box.size))[0])-((vec2_origin)[0]))<0.0000000001 )?(fabs((((node->box.size))[1])-((vec2_origin)[1]))<0.0000000001 )?1:0:0))) { | ||
72 | if (node->onClick || node->onRightClick || node->onMouseEnter || node->onMouseLeave || node->onWheelUp || node->onWheelDown || node->onWheel || node->onMiddleClick) { | ||
73 | Com_DPrintf(DEBUG_CLIENT0x20, "Node '%s' is an active image without size\n", UI_GetPath(node)); | ||
74 | } | ||
75 | } | ||
76 | #endif | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * @brief Get position of a inner box inside an outer box according to align param. | ||
81 | * @todo Generic function, move it outside. | ||
82 | * @param[in] outerBoxPos Position of the top-left corner of the outer box. | ||
83 | * @param[in] outerBoxSize Size of the outer box. | ||
84 | * @param[in] innerBoxSize Size of the inner box. | ||
85 | * @param align Alignment of the inner box inside the outer box. | ||
86 | * @param[out] innerBoxPos Position of the top-left corner of the inner box. | ||
87 | */ | ||
88 | static void UI_ImageAlignBoxInBox (vec2_t outerBoxPos, vec2_t outerBoxSize, vec2_t innerBoxSize, align_t align, vec2_t innerBoxPos) | ||
89 | { | ||
90 | switch (align % 3) { | ||
91 | case 0: /* left */ | ||
92 | innerBoxPos[0] = outerBoxPos[0]; | ||
93 | break; | ||
94 | case 1: /* middle */ | ||
95 | innerBoxPos[0] = outerBoxPos[0] + (outerBoxSize[0] * 0.5) - (innerBoxSize[0] * 0.5); | ||
96 | break; | ||
97 | case 2: /* right */ | ||
98 | innerBoxPos[0] = outerBoxPos[0] + outerBoxSize[0] - innerBoxSize[0]; | ||
99 | break; | ||
100 | } | ||
101 | switch (align / 3) { | ||
102 | case 0: /* top */ | ||
103 | innerBoxPos[1] = outerBoxPos[1]; | ||
104 | break; | ||
105 | case 1: /* middle */ | ||
106 | innerBoxPos[1] = outerBoxPos[1] + (outerBoxSize[1] * 0.5) - (innerBoxSize[1] * 0.5); | ||
107 | break; | ||
108 | case 2: /* bottom */ | ||
109 | innerBoxPos[1] = outerBoxPos[1] + outerBoxSize[1] - innerBoxSize[1]; | ||
110 | break; | ||
111 | default: | ||
112 | innerBoxPos[1] = outerBoxPos[1]; | ||
113 | Com_Error(ERR_FATAL0, "UI_ImageAlignBoxInBox: Align %d not supported\n", align); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * @brief Draws the image node | ||
119 | * @param[in] node The UI node to draw | ||
120 | */ | ||
121 | void uiImageNode::draw (uiNode_t *node) | ||
122 | { | ||
123 | vec2_t size; | ||
124 | vec2_t nodepos; | ||
125 | const image_t *image; | ||
126 | vec2_t imagepos; | ||
127 | vec2_t nodesize; | ||
128 | |||
129 | const char* imageName = UI_GetReferenceString(node, EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).source); | ||
130 | if (Q_strnull(imageName)((imageName) == __null || (imageName)[0] == '\0')) | ||
| |||
131 | return; | ||
132 | |||
133 | image = UI_LoadImage(imageName); | ||
134 | if (!image) | ||
| |||
135 | return; | ||
136 | |||
137 | /* mouse darken effect */ | ||
138 | /** @todo convert all pic using mousefx into button. | ||
139 | * @todo delete mousefx | ||
140 | */ | ||
141 | #if 0 | ||
142 | if (node->mousefx && node->state) { | ||
143 | vec4_t color; | ||
144 | VectorScale(node->color, 0.8, color)((color)[0] = (node->color)[0] * (0.8),(color)[1] = (node-> color)[1] * (0.8),(color)[2] = (node->color)[2] * (0.8)); | ||
145 | color[3] = node->color[3]; | ||
146 | R_Color(color); | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | UI_GetNodeAbsPos(node, nodepos); | ||
151 | Vector2Copy(node->box.size, nodesize)((nodesize)[0]=(node->box.size)[0],(nodesize)[1]=(node-> box.size)[1]); | ||
152 | nodesize[0] -= node->padding + node->padding; | ||
153 | if (nodesize[0] < 0) | ||
| |||
154 | nodesize[0] = 0; | ||
155 | nodesize[1] -= node->padding + node->padding; | ||
156 | if (nodesize[1] < 0) | ||
| |||
157 | nodesize[1] = 0; | ||
158 | |||
159 | /** @todo code is duplicated in the ekg node code */ | ||
160 | if (node->box.size[0] && !node->box.size[1]) { | ||
| |||
161 | const float scale = image->width / node->box.size[0]; | ||
162 | Vector2Set(size, node->box.size[0], image->height / scale)((size)[0]=(node->box.size[0]), (size)[1]=(image->height / scale)); | ||
163 | } else if (node->box.size[1] && !node->box.size[0]) { | ||
| |||
164 | const float scale = image->height / node->box.size[1]; | ||
165 | Vector2Set(size, image->width / scale, node->box.size[1])((size)[0]=(image->width / scale), (size)[1]=(node->box .size[1])); | ||
166 | } else { | ||
167 | Vector2Copy(nodesize, size)((size)[0]=(nodesize)[0],(size)[1]=(nodesize)[1]); | ||
168 | |||
169 | if (EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).preventRatio) { | ||
| |||
170 | /* maximize the image into the bounding box */ | ||
171 | const float ratio = (float) image->width / (float) image->height; | ||
172 | if (size[1] * ratio > size[0]) { | ||
173 | Vector2Set(size, size[0], size[0] / ratio)((size)[0]=(size[0]), (size)[1]=(size[0] / ratio)); | ||
174 | } else { | ||
175 | Vector2Set(size, size[1] * ratio, size[1])((size)[0]=(size[1] * ratio), (size)[1]=(size[1])); | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
180 | UI_ImageAlignBoxInBox(nodepos, nodesize, size, (align_t) node->contentAlign, imagepos); | ||
181 | UI_DrawNormImage(false, imagepos[0] + node->padding, imagepos[1] + node->padding, size[0], size[1], | ||
| |||
182 | EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texh[0], EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texh[1], | ||
183 | EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texl[0], EXTRADATA(node)(*((imageExtraData_t*)((char*)node + sizeof(uiNode_t)))).texl[1], image); | ||
184 | |||
185 | /** @todo convert all pic using mousefx into button. | ||
186 | * @todo delete mousefx | ||
187 | */ | ||
188 | #if 0 | ||
189 | if (node->mousefx && node->state) { | ||
190 | R_Color(NULL__null); | ||
191 | } | ||
192 | #endif | ||
193 | } | ||
194 | |||
195 | void UI_RegisterImageNode (uiBehaviour_t* behaviour) | ||
196 | { | ||
197 | /** @todo rename it according to the function name when its possible */ | ||
198 | behaviour->name = "image"; | ||
199 | behaviour->manager = new uiImageNode(); | ||
200 | behaviour->extraDataSize = sizeof(EXTRADATA_TYPEimageExtraData_t); | ||
201 | |||
202 | /* Do not change the image ratio. The image will be proportionally stretched. */ | ||
203 | UI_RegisterExtradataNodeProperty(behaviour, "preventratio", V_BOOL, EXTRADATA_TYPE, preventRatio)UI_RegisterNodePropertyPosSize_(behaviour, "preventratio", V_BOOL , ((size_t) &((imageExtraData_t *)(((imageExtraData_t*)(( char*)0 + sizeof(uiNode_t)))))->preventRatio), sizeof(((imageExtraData_t *)0)->preventRatio)); | ||
204 | /* Now this property do nothing. But we use it like a tag, to remember nodes we should convert into button... | ||
205 | * @todo delete it when its possible (use more button instead of image) | ||
206 | */ | ||
207 | UI_RegisterExtradataNodeProperty(behaviour, "mousefx", V_BOOL, EXTRADATA_TYPE, mousefx)UI_RegisterNodePropertyPosSize_(behaviour, "mousefx", V_BOOL, ((size_t) &((imageExtraData_t *)(((imageExtraData_t*)((char *)0 + sizeof(uiNode_t)))))->mousefx), sizeof(((imageExtraData_t *)0)->mousefx)); | ||
208 | |||
209 | /* Texture high. Optional. Define the higher corner of the texture we want to display. Used with texl to crop the image. */ | ||
210 | UI_RegisterExtradataNodeProperty(behaviour, "texh", V_POS, EXTRADATA_TYPE, texh)UI_RegisterNodePropertyPosSize_(behaviour, "texh", V_POS, ((size_t ) &((imageExtraData_t *)(((imageExtraData_t*)((char*)0 + sizeof (uiNode_t)))))->texh), sizeof(((imageExtraData_t *)0)-> texh)); | ||
211 | /* Texture low. Optional. Define the lower corner of the texture we want to display. Used with texh to crop the image. */ | ||
212 | UI_RegisterExtradataNodeProperty(behaviour, "texl", V_POS, EXTRADATA_TYPE, texl)UI_RegisterNodePropertyPosSize_(behaviour, "texl", V_POS, ((size_t ) &((imageExtraData_t *)(((imageExtraData_t*)((char*)0 + sizeof (uiNode_t)))))->texl), sizeof(((imageExtraData_t *)0)-> texl)); | ||
213 | |||
214 | /* Source of the image */ | ||
215 | UI_RegisterExtradataNodeProperty(behaviour, "src", V_CVAR_OR_STRING, EXTRADATA_TYPE, source)UI_RegisterNodePropertyPosSize_(behaviour, "src", ((0x8000 + 0x0100 ) + V_STRING), ((size_t) &((imageExtraData_t *)(((imageExtraData_t *)((char*)0 + sizeof(uiNode_t)))))->source), sizeof(((imageExtraData_t *)0)->source)); | ||
216 | } |