]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/feedback.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / radiant / feedback.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 //-----------------------------------------------------------------------------\r
23 //\r
24 // DESCRIPTION:\r
25 // classes used for describing geometry information from q3map feedback\r
26 //\r
27 \r
28 #include "stdafx.h"\r
29 \r
30 #include "feedback.h"\r
31 #include "glib.h"\r
32 #include <assert.h>\r
33 \r
34 CDbgDlg g_DbgDlg;\r
35 \r
36 void CSelectMsg::saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)\r
37 {\r
38   if (strcmp ((char *)name, "select")==0)\r
39   {\r
40     // read the message\r
41     ESelectState = SELECT_MESSAGE;\r
42   }\r
43   else\r
44   {\r
45     // read the brush\r
46     assert (strcmp ((char *)name, "brush")==0);\r
47     assert (ESelectState == SELECT_MESSAGE);\r
48     ESelectState = SELECT_BRUSH;\r
49   }\r
50 }\r
51 \r
52 void CSelectMsg::saxEndElement (message_info_t *ctx, const xmlChar *name)\r
53 {\r
54   if (strcmp ((char *)name, "select")==0)\r
55   {\r
56     ctx->bGeometry = false;\r
57   }\r
58 }\r
59 \r
60 void CSelectMsg::saxCharacters (message_info_t *ctx, const xmlChar *ch, int len)\r
61 {\r
62   if (ESelectState == SELECT_MESSAGE)\r
63   {\r
64     message = g_string_sized_new (len+1);\r
65     memcpy (message->str, ch, len);\r
66     message->str[len]='\0';\r
67     Sys_Printf ("%s\n", message->str);\r
68   }\r
69   else\r
70   {\r
71     assert (ESelectState == SELECT_BRUSH);\r
72     sscanf ((char *)ch, "%i %i", &entitynum, &brushnum);\r
73   }\r
74 }\r
75 \r
76 void CSelectMsg::Highlight ()\r
77 {\r
78   Select_Deselect ();\r
79   SelectBrush (entitynum, brushnum);\r
80 }\r
81 \r
82 void CPointMsg::saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)\r
83 {\r
84   if (strcmp ((char *)name, "pointmsg")==0)\r
85   {\r
86     // read the message\r
87     EPointState = POINT_MESSAGE;\r
88   }\r
89   else\r
90   {\r
91     // read the brush\r
92     assert (strcmp ((char *)name, "point")==0);\r
93     assert (EPointState == POINT_MESSAGE);\r
94     EPointState = POINT_POINT;\r
95   }\r
96 }\r
97 \r
98 void CPointMsg::saxEndElement (message_info_t *ctx, const xmlChar *name)\r
99 {\r
100   if (strcmp ((char *)name, "pointmsg")==0)\r
101   {\r
102     ctx->bGeometry = false;\r
103   }\r
104 }\r
105 \r
106 void CPointMsg::saxCharacters (message_info_t *ctx, const xmlChar *ch, int len)\r
107 {\r
108   if (EPointState == POINT_MESSAGE)\r
109   {\r
110     message = g_string_sized_new (len+1);\r
111     memcpy (message->str, ch, len);\r
112     message->str[len]='\0';\r
113     Sys_Printf ("%s\n", message->str);\r
114   }\r
115   else\r
116   {\r
117     assert (EPointState == POINT_POINT);\r
118     sscanf ((char *)ch, "%g %g %g", &(pt[0]), &(pt[1]), &(pt[2]));\r
119   }\r
120 }\r
121 \r
122 void CPointMsg::Highlight ()\r
123 {\r
124   // use the entity API to push a point\r
125   // the API requires a ref count, we do it manually for the current instance\r
126   if (refCount == 0)\r
127   {\r
128     refCount++;\r
129     QERApp_HookGL2DWindow (this);\r
130   }\r
131 }\r
132 \r
133 void CPointMsg::DropHighlight ()\r
134 {\r
135   assert (refCount > 0);\r
136   QERApp_UnHookGL2DWindow (this);\r
137   // do a refCount-- locally (see Highlight)\r
138   refCount--;\r
139 }\r
140 \r
141 void CPointMsg::Draw2D( VIEWTYPE vt )\r
142 {\r
143   int nDim1 = (vt == YZ) ? 1 : 0;\r
144   int nDim2 = (vt == XY) ? 1 : 2;\r
145   qglPointSize(4);\r
146   qglColor3f(1.0f,0.0f,0.0f);\r
147   qglBegin (GL_POINTS);\r
148   qglVertex2f (pt[nDim1], pt[nDim2]);\r
149   qglEnd();\r
150   qglBegin (GL_LINE_LOOP);\r
151   qglVertex2f (pt[nDim1]-8, pt[nDim2]-8);\r
152   qglVertex2f (pt[nDim1]+8, pt[nDim2]-8);\r
153   qglVertex2f (pt[nDim1]+8, pt[nDim2]+8);\r
154   qglVertex2f (pt[nDim1]-8, pt[nDim2]+8);\r
155   qglEnd();\r
156 }\r
157 \r
158 void CWindingMsg::saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs)\r
159 {\r
160   if (strcmp ((char *)name, "windingmsg")==0)\r
161   {\r
162     // read the message\r
163     EPointState = WINDING_MESSAGE;\r
164   }\r
165   else\r
166   {\r
167     // read the brush\r
168     assert (strcmp ((char *)name, "winding")==0);\r
169     assert (EPointState == WINDING_MESSAGE);\r
170     EPointState = WINDING_WINDING;\r
171   }\r
172 }\r
173 \r
174 void CWindingMsg::saxEndElement (message_info_t *ctx, const xmlChar *name)\r
175 {\r
176   if (strcmp ((char *)name, "windingmsg")==0)\r
177   {\r
178     ctx->bGeometry = false;\r
179   }\r
180 }\r
181 \r
182 void CWindingMsg::saxCharacters (message_info_t *ctx, const xmlChar *ch, int len)\r
183 {\r
184   if (EPointState == WINDING_MESSAGE)\r
185   {\r
186     message = g_string_sized_new (len+1);\r
187     memcpy (message->str, ch, len);\r
188     message->str[len]='\0';\r
189     Sys_Printf ("%s\n", message->str);\r
190   }\r
191   else\r
192   {\r
193     char* c;\r
194     int i;\r
195 \r
196     assert (EPointState == WINDING_WINDING);\r
197 \r
198 \r
199     c = (char*)ch;\r
200     sscanf (c, "%i ", &numpoints);\r
201 \r
202     for(i = 0; i < numpoints; i++)\r
203     {\r
204       c = strchr(++c, '(');\r
205       if (c) // even if we are given the number of points when the cycle begins .. don't trust it too much\r
206         sscanf(c, "(%g %g %g)", &wt[i][0], &wt[i][1], &wt[i][2]);\r
207       else\r
208         break;\r
209     }\r
210     numpoints = i;\r
211   }\r
212 }\r
213 \r
214 void CWindingMsg::Highlight ()\r
215 {\r
216   // use the entity API to push a point\r
217   // the API requires a ref count, we do it manually for the current instance\r
218   if (refCount == 0)\r
219   {\r
220     refCount++;\r
221     QERApp_HookGL2DWindow (this);\r
222   }\r
223 }\r
224 \r
225 void CWindingMsg::DropHighlight ()\r
226 {\r
227   assert (refCount > 0);\r
228   QERApp_UnHookGL2DWindow (this);\r
229   // do a refCount-- locally (see Highlight)\r
230   refCount--;\r
231 }\r
232 \r
233 void CWindingMsg::Draw2D( VIEWTYPE vt )\r
234 {\r
235   int i;\r
236 \r
237   int nDim1 = (vt == YZ) ? 1 : 0;\r
238   int nDim2 = (vt == XY) ? 1 : 2;\r
239   qglColor3f(1.0f,0.f,0.0f);\r
240 \r
241   qglPointSize(4);\r
242   qglBegin (GL_POINTS);\r
243   for(i = 0; i < numpoints; i++)\r
244         qglVertex2f (wt[i][nDim1], wt[i][nDim2]);\r
245   qglEnd();\r
246   qglPointSize(1);\r
247 \r
248   qglEnable (GL_BLEND);\r
249   qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\r
250   qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
251   qglColor4f(0.133f,0.4f,1.0f,0.5f);\r
252   qglBegin (GL_POLYGON);\r
253         for(i = 0; i < numpoints; i++)\r
254                 qglVertex2f (wt[i][nDim1], wt[i][nDim2]);\r
255   qglEnd();\r
256   qglDisable (GL_BLEND);\r
257 }\r
258 \r
259 // triggered when the user selects an entry in the feedback box\r
260 static void feedback_selection_changed(GtkTreeSelection* selection, gpointer data)\r
261 {\r
262   g_DbgDlg.DropHighlight();\r
263 \r
264   GtkTreeModel* model;\r
265   GtkTreeIter selected;\r
266   if(gtk_tree_selection_get_selected(selection, &model, &selected))\r
267   {\r
268     GtkTreePath* path = gtk_tree_model_get_path(model, &selected);\r
269       g_DbgDlg.SetHighlight(gtk_tree_path_get_indices(path)[0]);\r
270     gtk_tree_path_free(path);\r
271   }\r
272 }\r
273 \r
274 void CDbgDlg::DropHighlight()\r
275 {\r
276   if (m_pHighlight)\r
277   {\r
278     m_pHighlight->DropHighlight();\r
279     m_pHighlight = NULL;\r
280   }\r
281 }\r
282 \r
283 void CDbgDlg::SetHighlight(gint row)\r
284 {\r
285   ISAXHandler *h = GetElement(row);\r
286   if (h != NULL)\r
287   {\r
288     h->Highlight();\r
289     m_pHighlight = h;\r
290   }\r
291 }\r
292 \r
293 ISAXHandler *CDbgDlg::GetElement (gint row)\r
294 {\r
295   return static_cast<ISAXHandler *>(g_ptr_array_index(m_pFeedbackElements, row));\r
296 }\r
297 \r
298 void CDbgDlg::Init ()\r
299 {\r
300   DropHighlight();\r
301 \r
302   // free all the ISAXHandler*, clean it\r
303   while (m_pFeedbackElements->len)\r
304   {\r
305     delete static_cast<ISAXHandler *>(g_ptr_array_index (m_pFeedbackElements, 0));\r
306     g_ptr_array_remove_index (m_pFeedbackElements, 0);\r
307   }\r
308 \r
309   if (m_clist != NULL)\r
310     gtk_list_store_clear (m_clist);\r
311 }\r
312 \r
313 void CDbgDlg::Push (ISAXHandler *pHandler)\r
314 {\r
315   // push in the list\r
316   g_ptr_array_add (m_pFeedbackElements, (void *)pHandler);\r
317 \r
318   if (m_pWidget == NULL)\r
319     Create();\r
320   // put stuff in the list\r
321   gtk_list_store_clear (m_clist);\r
322   for(unsigned int i = 0; i < m_pFeedbackElements->len; ++i)\r
323   {\r
324     GtkTreeIter iter;\r
325     gtk_list_store_append(m_clist, &iter);\r
326     gtk_list_store_set(m_clist, &iter, 0, GetElement(i)->getName(), -1);\r
327   }\r
328 \r
329   ShowDlg();\r
330 }\r
331 \r
332 void CDbgDlg::BuildDialog ()\r
333 {\r
334   gtk_window_set_title (GTK_WINDOW (m_pWidget), "Q3Map debug window");\r
335 \r
336   GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);\r
337   gtk_widget_show (scr);\r
338   gtk_container_add (GTK_CONTAINER (m_pWidget), GTK_WIDGET (scr));\r
339   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);\r
340   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);\r
341 \r
342   {\r
343     GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);\r
344 \r
345     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));\r
346     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);\r
347 \r
348     {\r
349       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();\r
350       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);\r
351       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);\r
352     }\r
353 \r
354     {\r
355       GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));\r
356       gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);\r
357       g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(feedback_selection_changed), NULL);\r
358     }\r
359 \r
360     gtk_widget_show(view);\r
361 \r
362     gtk_container_add(GTK_CONTAINER (scr), view);\r
363 \r
364     g_object_unref(G_OBJECT(store));\r
365 \r
366     m_clist = store;\r
367   }\r
368 }\r