2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\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
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
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
23 // Floating dialog that contains a notebook with at least Entities and Group tabs
\r
24 // I merged the 2 MS Windows dialogs in a single class
\r
26 // Leonardo Zide (leo@lokigames.com)
\r
32 #include <gdk/gdkkeysyms.h>
\r
34 #include "groupdialog.h"
\r
36 GtkWidget* EntWidgets[EntLast];
\r
37 GtkListStore* g_entlist_store;
\r
38 GtkListStore* g_entprops_store;
\r
39 int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE
\r
40 qboolean multiple_entities;
\r
41 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=17
\r
42 qboolean disable_spawn_get = false;
\r
43 entity_t *edit_entity;
\r
45 static GdkPixmap *tree_pixmaps[7];
\r
46 static GdkBitmap *tree_masks[7];
\r
51 #define IMG_ENTITY 3
\r
52 #define IMG_ENTITYGROUP 4
\r
54 #define IMG_SCRIPT 6
\r
56 // misc group support
\r
57 #define MAX_GROUPS 4096
\r
58 #define GROUP_DELIMETER '@'
\r
59 #define GROUPNAME "QER_Group_%i"
\r
61 GroupDlg g_wndGroup;
\r
62 GroupDlg *g_pGroupDlg = &g_wndGroup;
\r
64 // group_t are loaded / saved through "group_info" entities
\r
65 // they hold epairs for group settings and additionnal access info (tree nodes)
\r
66 group_t *g_pGroups = NULL;
\r
68 // the number of active spawnflags
\r
69 static int spawnflag_count;
\r
70 // table: index, match spawnflag item to the spawnflag index (i.e. which bit)
\r
71 static int spawn_table[MAX_FLAGS];
\r
72 // we change the layout depending on how many spawn flags we need to display
\r
73 // the table is a 4x4 in which we need to put the comment box EntWidgets[EntComment] and the spawn flags..
\r
74 static GtkWidget *LayoutTable;
\r
75 // 0: none of them are hooked
\r
76 // 1: only the text, 2: text and four checks, 3: text and 8 checks
\r
77 static int widget_state = 0;
\r
79 static void entity_check (GtkWidget *widget, gpointer data);
\r
81 // =============================================================================
\r
85 ===============================================================
\r
89 ===============================================================
\r
92 void FillClassList ()
\r
94 GtkListStore* store = g_entlist_store;
\r
96 gtk_list_store_clear(store);
\r
98 for (eclass_t* e = eclass ; e ; e = e->next)
\r
101 gtk_list_store_append(store, &iter);
\r
102 gtk_list_store_set(store, &iter, 0, e->name, 1, e, -1);
\r
106 // SetKeyValuePairs
\r
108 // Reset the key/value (aka property) listbox and fill it with the
\r
109 // k/v pairs from the entity being edited.
\r
112 void SetKeyValuePairs (bool bClearMD3)
\r
114 GtkListStore* store = g_entprops_store;
\r
116 gtk_list_store_clear(store);
\r
118 if (edit_entity == NULL)
\r
120 // if there's no entity, then display no key/values
\r
124 // save current key/val pair around filling epair box
\r
125 // row_select wipes it and sets to first in list
\r
126 Str strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
\r
127 Str strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
\r
130 // Walk through list and add pairs
\r
131 for(epair_t* epair = edit_entity->epairs ; epair ; epair = epair->next)
\r
134 gtk_list_store_append(store, &iter);
\r
135 gtk_list_store_set(store, &iter, 0, epair->key, 1, epair->value, -1);
\r
138 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), strKey.GetBuffer());
\r
139 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), strVal.GetBuffer());
\r
141 Sys_UpdateWindows(W_CAMERA | W_XY);
\r
146 // Update the checkboxes to reflect the flag state of the entity
\r
148 void SetSpawnFlags(void)
\r
152 disable_spawn_get = true;
\r
154 f = atoi(ValueForKey (edit_entity, "spawnflags"));
\r
155 for (i=0 ; i<spawnflag_count ; i++)
\r
157 v = !!(f&(1<<spawn_table[i]));
\r
158 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), v);
\r
160 // take care of the remaining ones
\r
161 for (i=spawnflag_count ; i<MAX_FLAGS ; i++)
\r
163 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), FALSE);
\r
166 disable_spawn_get = false;
\r
171 // Update the entity flags to reflect the state of the checkboxes
\r
173 // NOTE: this function had a tendency to add "spawnflags" "0" on most entities
\r
174 // if this wants to set spawnflags to zero, remove the key
\r
176 void GetSpawnFlags(void)
\r
182 for (i=0 ; i<spawnflag_count ; i++)
\r
184 v = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]));
\r
185 f |= v<<spawn_table[i];
\r
190 // remove all "spawnflags" keys
\r
191 if (multiple_entities)
\r
195 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
\r
196 DeleteKey (b->owner, "spawnflags");
\r
199 DeleteKey (edit_entity, "spawnflags");
\r
203 sprintf (sz, "%i", f);
\r
204 if (multiple_entities)
\r
208 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
\r
209 SetKeyValue(b->owner, "spawnflags", sz);
\r
212 SetKeyValue (edit_entity, "spawnflags", sz);
\r
214 SetKeyValuePairs ();
\r
217 //#define DBG_UPDATESEL
\r
221 // Update the listbox, checkboxes and k/v pairs to reflect the new selection
\r
222 // iIndex is the index in the list box with the class name, -1 if not found
\r
223 bool UpdateSel(int iIndex, eclass_t *pec)
\r
228 // syndrom of crappy code, we may get into stack overflowing crap with this function and Gtk
\r
229 // if we play with the list of entity classes
\r
230 // using a static flag to prevent recursion
\r
231 static bool bBlockUpdate = false;
\r
234 return FALSE; // NOTE TTimo wtf is the return value for anyway?
\r
236 #ifdef DBG_UPDATESEL
\r
237 Sys_FPrintf(SYS_WRN, "UpdateSel\n");
\r
240 if (selected_brushes.next == &selected_brushes)
\r
242 edit_entity = world_entity;
\r
243 multiple_entities = false;
\r
247 edit_entity = selected_brushes.next->owner;
\r
248 for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next)
\r
250 if (b->owner != edit_entity)
\r
252 multiple_entities = true;
\r
260 #ifdef DBG_UPDATESEL
\r
261 Sys_FPrintf(SYS_WRN,"Setting focus_row to %d\n", iIndex);
\r
263 bBlockUpdate = true;
\r
265 GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
\r
266 GtkTreePath* path = gtk_tree_path_new();
\r
267 gtk_tree_path_append_index(path, iIndex);
\r
268 gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);
\r
269 gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);
\r
270 gtk_tree_path_free(path);
\r
272 bBlockUpdate = false;
\r
278 // Set up the description
\r
280 GtkTextBuffer* buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(EntWidgets[EntComment]));
\r
281 gtk_text_buffer_set_text (buffer, pec->comments, -1);
\r
284 spawnflag_count = 0;
\r
286 // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are
\r
287 for (i=0 ; i<MAX_FLAGS ; i++)
\r
289 if (pec->flagnames[i] && pec->flagnames[i][0] != 0 && strcmp(pec->flagnames[i],"-"))
\r
291 spawn_table[spawnflag_count] = i;
\r
296 // what's new widget state
\r
297 if (spawnflag_count==0)
\r
299 else if (spawnflag_count<=4)
\r
301 else if (spawnflag_count<=8)
\r
303 else if (spawnflag_count<=12)
\r
307 widget_state = next_state;
\r
308 static int last_count = 0;
\r
310 // disable all remaining boxes
\r
311 // NOTE: these boxes might not even be on display
\r
312 for (i = 0; i < last_count; i++)
\r
314 GtkWidget* widget = EntWidgets[EntCheck1+i];
\r
315 gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), " ");
\r
316 gtk_widget_hide (widget);
\r
317 gtk_widget_ref (widget);
\r
318 gtk_container_remove (GTK_CONTAINER (LayoutTable), widget);
\r
320 last_count = spawnflag_count;
\r
322 for (i=0 ; i<spawnflag_count ; i++)
\r
324 GtkWidget* widget = EntWidgets[EntCheck1+i];
\r
325 gtk_widget_show (widget);
\r
328 str = pec->flagnames[spawn_table[i]];
\r
331 // gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,
\r
332 gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,
\r
333 (GtkAttachOptions) (GTK_FILL),
\r
334 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
335 gtk_widget_unref (widget);
\r
337 gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), str.GetBuffer ());
\r
342 SetKeyValuePairs();
\r
347 bool UpdateEntitySel(eclass_t *pec)
\r
349 #ifdef DBG_UPDATESEL
\r
350 Sys_FPrintf(SYS_WRN, "UpdateEntitySel\n");
\r
353 GtkTreeModel* model = GTK_TREE_MODEL(g_entlist_store);
\r
355 unsigned int i = 0;
\r
356 for(gboolean good = gtk_tree_model_get_iter_first(model, &iter); good != FALSE; good = gtk_tree_model_iter_next(model, &iter))
\r
359 gtk_tree_model_get(model, &iter, 0, &text, -1);
\r
360 if (strcmp (text, pec->name) == 0)
\r
362 #ifdef DBG_UPDATESEL
\r
363 Sys_FPrintf(SYS_WRN, "found a match: %d %s\n", i, pec->name);
\r
365 return UpdateSel (i, pec);
\r
370 return UpdateSel (-1, pec);
\r
375 // Creates a new entity based on the currently selected brush and entity type.
\r
378 void CreateEntity(void)
\r
380 GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
\r
382 // check to make sure we have a brush
\r
383 if (selected_brushes.next == &selected_brushes)
\r
385 gtk_MessageBox(g_pParentWnd->m_pWidget, "You must have a selected brush to create an entity", "info");
\r
389 // find out what type of entity we are trying to create
\r
390 GtkTreeModel* model;
\r
392 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE)
\r
394 gtk_MessageBox (g_pParentWnd->m_pWidget, "You must have a selected class to create an entity", "info");
\r
399 gtk_tree_model_get(model, &iter, 0, &text, -1);
\r
400 CreateEntityFromName(text, vec3_origin);
\r
403 if (selected_brushes.next == &selected_brushes)
\r
404 edit_entity = world_entity;
\r
406 edit_entity = selected_brushes.next->owner;
\r
408 SetKeyValuePairs();
\r
409 Select_Deselect ();
\r
410 Select_Brush (edit_entity->brushes.onext);
\r
411 Sys_UpdateWindows(W_ALL);
\r
422 if (edit_entity == NULL)
\r
425 // Get current selection text
\r
426 const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
\r
427 const char* value = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
\r
430 // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity
\r
431 if (!strcmp(key, "classname") && !strcmp(value, "worldspawn"))
\r
433 gtk_MessageBox(g_pParentWnd->m_pWidget, "Cannot change \"classname\" key back to worldspawn.", NULL, MB_OK );
\r
438 // RR2DO2: we don't want spaces in entity keys
\r
439 if (strstr( key, " " ))
\r
441 gtk_MessageBox(g_pParentWnd->m_pWidget, "No spaces are allowed in entity keys.", NULL, MB_OK );
\r
445 if (multiple_entities)
\r
449 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
\r
450 SetKeyValue(b->owner, key, value);
\r
453 SetKeyValue(edit_entity, key, value);
\r
455 // refresh the prop listbox
\r
456 SetKeyValuePairs();
\r
459 #ifdef USEPLUGINENTITIES
\r
460 // if it's a plugin entity, perhaps we need to update some drawing parameters
\r
461 // NOTE: perhaps moving this code to a seperate func would help if we need it in other places
\r
462 // TODO: we need to call some update func in the IPluginEntity in case model name changes etc.
\r
463 // ( for the moment only bounding brush is updated ), see UpdateModelBrush in Ritual's Q3Radiant
\r
464 if (edit_entity->eclass->nShowFlags & ECLASS_PLUGINENTITY)
\r
467 edit_entity->pPlugEnt->GetBounds( mins, maxs );
\r
468 // replace old bounding brush by newly computed one
\r
469 // NOTE: this part is similar to Entity_BuildModelBrush in Ritual's Q3Radiant, it can be
\r
470 // usefull moved into a seperate func
\r
471 brush_t *b,*oldbrush;
\r
472 if (edit_entity->brushes.onext != &edit_entity->brushes)
\r
473 oldbrush = edit_entity->brushes.onext;
\r
474 b = Brush_Create (mins, maxs, &edit_entity->eclass->texdef);
\r
475 Entity_LinkBrush (edit_entity, b);
\r
476 Brush_Build( b, true );
\r
478 Brush_AddToList (edit_entity->brushes.onext, &selected_brushes);
\r
480 Brush_Free( oldbrush );
\r
482 #endif // USEPLUGINENTITIES
\r
493 if (edit_entity == NULL)
\r
496 // Get current selection text
\r
497 const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
\r
499 if (multiple_entities)
\r
503 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
\r
504 DeleteKey(b->owner, key);
\r
507 DeleteKey(edit_entity, key);
\r
509 // refresh the prop listbox
\r
510 SetKeyValuePairs();
\r
513 void ResetEntity ()
\r
518 if (edit_entity == NULL)
\r
521 if (multiple_entities)
\r
525 for (b=selected_brushes.next; b != &selected_brushes; b=b->next)
\r
526 for (pep = b->owner->epairs; pep; )
\r
528 if (strcmp (pep->key, "classname") != 0)
\r
530 DeleteKey (b->owner, pep->key);
\r
531 pep = b->owner->epairs;
\r
538 for (pep = edit_entity->epairs; pep; )
\r
540 if (strcmp (pep->key, "classname") != 0)
\r
542 DeleteKey (edit_entity, pep->key);
\r
543 pep = edit_entity->epairs;
\r
549 // refresh the dialog
\r
550 SetKeyValuePairs ();
\r
551 for (i = EntCheck1; i <= EntCheck16; i++)
\r
552 gtk_signal_handler_block_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);
\r
554 for (i = EntCheck1; i <= EntCheck16; i++)
\r
555 gtk_signal_handler_unblock_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);
\r
558 bool GetSelectAllCriteria(CString &strKey, CString &strVal)
\r
560 GtkTreeModel* model;
\r
562 if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(EntWidgets[EntProps])), &model, &iter)
\r
563 && (inspector_mode == W_ENTITY)
\r
564 && GTK_WIDGET_VISIBLE (g_pGroupDlg->m_pWidget))
\r
566 strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
\r
567 strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
\r
576 char buffer[NAME_MAX];
\r
578 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
\r
579 strcat (buffer, "sound/");
\r
581 if( access(buffer, R_OK) != 0 )
\r
583 // just go to fsmain
\r
584 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
\r
585 strcat (buffer, "/");
\r
588 const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, "Open Wav File", buffer, "sound");
\r
589 if (filename != NULL)
\r
591 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "noise");
\r
592 char *aux = vfsExtractRelativePath (filename);
\r
598 Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");
\r
602 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer());
\r
609 char buffer[NAME_MAX];
\r
611 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
\r
612 strcat (buffer, "models/");
\r
614 if( access(buffer, R_OK) != 0 )
\r
616 // just go to fsmain
\r
617 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
\r
618 strcat (buffer, "/");
\r
621 const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, "Open Model", buffer, MODEL_MAJOR);
\r
622 if (filename != NULL)
\r
624 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "model");
\r
625 // use VFS to get the correct relative path
\r
626 char *aux = vfsExtractRelativePath (filename);
\r
632 Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");
\r
636 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer());
\r
638 edit_entity->brushes.onext->bModelFailed = false;
\r
647 void SetInspectorMode(int iType)
\r
649 if (iType == W_GROUP)
\r
650 gtk_MessageBox(g_pParentWnd->m_pWidget, "Brush grouping is not functional yet", NULL, MB_OK | MB_ICONWARNING );
\r
652 if (!g_pParentWnd->FloatingGroupDialog() &&
\r
653 (iType == W_TEXTURE || iType == W_CONSOLE))
\r
656 // Is the caller asking us to cycle to the next window?
\r
659 if (inspector_mode == W_ENTITY)
\r
661 else if (inspector_mode == W_TEXTURE)
\r
663 else if (inspector_mode == W_CONSOLE)
\r
672 // entity is always first in the inspector
\r
673 gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Entities");
\r
674 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 0);
\r
678 g_pParentWnd->GetTexWnd()->FocusEdit();
\r
679 gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Textures");
\r
680 if (g_pParentWnd->FloatingGroupDialog())
\r
681 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);
\r
685 gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Console");
\r
686 if (g_pParentWnd->FloatingGroupDialog())
\r
687 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 2);
\r
691 if (g_pParentWnd->FloatingGroupDialog())
\r
692 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 3);
\r
694 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);
\r
702 void Group_Add(entity_t *e)
\r
705 group_t *g = (group_t*)qmalloc(sizeof(group_t));
\r
706 g->epairs = e->epairs;
\r
710 // create a new group node
\r
711 char *text = ValueForKey(g->epairs, "group");
\r
712 g->itemOwner = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_wndGroup.m_hWorld, NULL, &text, 0,
\r
713 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],
\r
714 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], TRUE, TRUE);
\r
715 g->next = g_pGroups;
\r
720 group_t* Group_Alloc(char *name)
\r
722 group_t *g = (group_t*)qmalloc(sizeof(group_t));
\r
723 SetKeyValue( g->epairs, "group", name );
\r
727 group_t* Group_ForName(const char * name)
\r
729 group_t *g = g_pGroups;
\r
732 if (strcmp( ValueForKey(g->epairs,"group"), name ) == 0)
\r
739 void Group_AddToItem(brush_t *b, GtkCTreeNode* item)
\r
741 int nImage = IMG_BRUSH;
\r
742 if (!g_qeglobals.m_bBrushPrimitMode)
\r
746 const char *pName = NULL;
\r
747 // const char *pNamed = Brush_GetKeyValue(b, "name");
\r
749 if (!b->owner || (b->owner == world_entity))
\r
751 if (b->patchBrush)
\r
753 pName = "Generic Patch";
\r
754 nImage = IMG_PATCH;
\r
758 pName = "Generic Brush";
\r
759 nImage = IMG_BRUSH;
\r
764 pName = b->owner->eclass->name;
\r
765 if (b->owner->eclass->fixedsize)
\r
767 nImage = IMG_ENTITY;
\r
771 nImage = IMG_ENTITYGROUP;
\r
775 GtkCTreeNode *newItem;
\r
776 int i = (b->patchBrush) ? IMG_PATCH : IMG_BRUSH;
\r
777 newItem = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), item, NULL, (gchar**)&pName, 0,
\r
778 tree_pixmaps[i], tree_masks[i], tree_pixmaps[i],
\r
779 tree_masks[i], TRUE, TRUE);
\r
780 gtk_ctree_node_set_row_data (GTK_CTREE (g_wndGroup.m_pTree), newItem, b);
\r
781 b->itemOwner = newItem;
\r
784 void Group_RemoveBrush(brush_t *b)
\r
787 if (!g_qeglobals.m_bBrushPrimitMode)
\r
793 gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);
\r
794 b->itemOwner = NULL;
\r
796 DeleteKey(b->epairs, "group");
\r
800 void Group_AddToWorld(brush_t *b)
\r
802 if (!g_qeglobals.m_bBrushPrimitMode)
\r
806 GtkCTreeNode *parent = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);
\r
807 Group_AddToItem(b, parent);
\r
810 void Group_AddToProperGroup(brush_t *b)
\r
813 if (!g_qeglobals.m_bBrushPrimitMode)
\r
818 // NOTE: we do a local copy of the "group" key because it gets erased by Group_RemoveBrush
\r
819 const char *pGroup = Brush_GetKeyValue(b, "group");
\r
820 // remove the entry in the tree if there's one
\r
823 gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);
\r
824 b->itemOwner = NULL;
\r
830 group_t *g = Group_ForName(pGroup);
\r
832 Group_AddToItem(b, g->itemOwner);
\r
835 Sys_Printf("WARNING: unexpected Group_ForName not found in Group_AddToProperGroup\n");
\r
840 Group_AddToWorld(b);
\r
845 void Group_AddToSelected(brush_t *b)
\r
847 if (!g_qeglobals.m_bBrushPrimitMode)
\r
851 GtkCTreeNode *item;
\r
852 item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), GTK_CLIST (g_pGroupDlg->m_pTree)->focus_row);
\r
855 item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);
\r
857 Group_AddToItem(b, item);
\r
861 void Group_Save(FILE *f)
\r
863 group_t *g = g_pGroups;
\r
866 fprintf(f,"{\n\"classname\" \"group_info\"\n\"group\" \"%s\"\n}\n", ValueForKey( g->epairs, "group" ));
\r
874 if (!g_qeglobals.m_bBrushPrimitMode)
\r
878 // start by cleaning everything
\r
879 // clean the groups
\r
880 //++timo FIXME: we leak, delete the groups on the way (I don't have time to do it now)
\r
882 Sys_Printf("TODO: fix leak in Group_Init\n");
\r
884 group_t *g = g_pGroups;
\r
887 epair_t *ep,*enext;
\r
888 for (ep = g->epairs ; ep ; ep=enext )
\r
898 GtkCTreeNode *world;
\r
899 char *text = "World";
\r
901 gtk_clist_clear (GTK_CLIST (g_wndGroup.m_pTree));
\r
902 world = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), NULL, NULL, &text, 0,
\r
903 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], tree_pixmaps[IMG_GROUP],
\r
904 tree_masks[IMG_GROUP], FALSE, TRUE);
\r
906 // walk through all the brushes, remove the itemOwner key and add them back where they belong
\r
908 for (b = active_brushes.next; b != &active_brushes; b = b->next)
\r
910 b->itemOwner = NULL;
\r
911 Group_AddToProperGroup(b);
\r
913 for (b = selected_brushes.next ; b != &selected_brushes ; b = b->next)
\r
915 b->itemOwner = NULL;
\r
916 Group_AddToProperGroup(b);
\r
920 // scan through world_entity for groups in this map?
\r
921 // we use GROUPNAME "QER_group_%i" to look for existing groups and their naming
\r
922 //++timo FIXME: is this actually needed for anything?
\r
923 void Group_GetListFromWorld(GSList **pArray)
\r
925 if (!g_qeglobals.m_bBrushPrimitMode)
\r
930 if (world_entity == NULL)
\r
936 for (int i =0; i < MAX_GROUPS; i++)
\r
938 sprintf(cBuff, GROUPNAME, i);
\r
939 char *pGroup = ValueForKey(world_entity, cBuff);
\r
940 if (pGroup && strlen(pGroup) > 0)
\r
942 *pArray = g_slist_append (*pArray, g_strdup (pGroup));
\r
951 void Group_RemoveListFromWorld()
\r
953 if (!g_qeglobals.m_bBrushPrimitMode)
\r
957 GSList* array = NULL;
\r
958 Group_GetListFromWorld(&array);
\r
962 DeleteKey(world_entity, (char*)array->data);
\r
963 g_free (array->data);
\r
964 array = g_slist_remove (array, array->data);
\r
968 int CountChar(const char *p, char c)
\r
971 int nLen = strlen(p)-1;
\r
972 while (nLen-- >= 0)
\r
982 // =============================================================================
\r
985 static void eclasslist_selection_changed(GtkTreeSelection* selection, gpointer data)
\r
987 GtkTreeModel* model;
\r
988 GtkTreeIter selected;
\r
989 // no world entity, we are not ready yet
\r
990 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=917
\r
991 if( !world_entity ) {
\r
994 if(gtk_tree_selection_get_selected(selection, &model, &selected))
\r
997 gtk_tree_model_get(model, &selected, 1, &eclass, -1);
\r
1000 GtkTreePath* path = gtk_tree_model_get_path(model, &selected);
\r
1001 UpdateSel(gtk_tree_path_get_indices(path)[0], eclass);
\r
1002 gtk_tree_path_free(path);
\r
1007 static gint eclasslist_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
\r
1009 if (event->type == GDK_2BUTTON_PRESS)
\r
1017 static gint eclasslist_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)
\r
1019 unsigned int code = gdk_keyval_to_upper (event->keyval);
\r
1021 if (event->keyval == GDK_Return)
\r
1027 // select the entity that starts with the key pressed
\r
1028 if (code <= 'Z' && code >= 'A')
\r
1030 GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
\r
1031 GtkTreeModel* model;
\r
1033 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE
\r
1034 || gtk_tree_model_iter_next(model, &iter) == FALSE)
\r
1036 gtk_tree_model_get_iter_first(model, &iter);
\r
1039 for(unsigned int count = gtk_tree_model_iter_n_children(model, NULL); count > 0; --count)
\r
1042 gtk_tree_model_get(model, &iter, 0, &text, -1);
\r
1044 if (toupper (text[0]) == (int)code)
\r
1046 GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
\r
1047 gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);
\r
1048 gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);
\r
1049 gtk_tree_path_free(path);
\r
1055 if(gtk_tree_model_iter_next(model, &iter) == FALSE)
\r
1056 gtk_tree_model_get_iter_first(model, &iter);
\r
1065 static void proplist_selection_changed(GtkTreeSelection* selection, gpointer data)
\r
1067 // find out what type of entity we are trying to create
\r
1068 GtkTreeModel* model;
\r
1070 if(gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
\r
1077 gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1);
\r
1079 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), key);
\r
1080 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), val);
\r
1086 static void entity_check (GtkWidget *widget, gpointer data)
\r
1088 if( !disable_spawn_get )
\r
1092 static void entitylist_angle (GtkWidget *widget, gpointer data)
\r
1094 SetKeyValue (edit_entity, "angle", (char*)data);
\r
1095 SetKeyValuePairs ();
\r
1098 static gint entityentry_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)
\r
1100 if (event->keyval == GDK_Tab)
\r
1102 if (widget == EntWidgets[EntKeyField])
\r
1104 //gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");
\r
1105 gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);
\r
1108 gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntKeyField]);
\r
1112 else if (event->keyval == GDK_Return)
\r
1114 if (widget == EntWidgets[EntKeyField])
\r
1116 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");
\r
1117 gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);
\r
1129 // add a new group, put all selected brushes into the group
\r
1130 static void groupdlg_add (GtkWidget *widget, gpointer data)
\r
1132 char* name = DoNameDlg ("New Group");
\r
1136 // create a new group node
\r
1137 GtkCTreeNode *item;
\r
1138 item = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_pGroupDlg->m_hWorld, NULL, &name, 0,
\r
1139 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],
\r
1140 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], FALSE, TRUE);
\r
1142 // create a new group
\r
1143 group_t *g = Group_Alloc (name);
\r
1144 g->itemOwner = item;
\r
1145 g->next = g_pGroups;
\r
1148 // now add the selected brushes
\r
1149 // NOTE: it would be much faster to give the group_t for adding
\r
1150 // but Select_AddToGroup is the standard way for all other cases
\r
1151 Select_AddToGroup (name);
\r
1156 static void switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)
\r
1159 gtk_label_get(GTK_LABEL(gtk_notebook_get_tab_label(notebook, gtk_notebook_get_nth_page(notebook, page_num))), &text);
\r
1160 gtk_window_set_title (GTK_WINDOW (data), text);
\r
1162 gpointer item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_misc_selectentitycolor");
\r
1164 if (g_pParentWnd->FloatingGroupDialog())
\r
1168 case 0: inspector_mode = W_ENTITY; break;
\r
1169 case 1: inspector_mode = W_TEXTURE; break;
\r
1170 case 2: inspector_mode = W_CONSOLE; break;
\r
1171 default: inspector_mode = W_GROUP; break;
\r
1176 if (page_num == 0)
\r
1177 inspector_mode = W_ENTITY;
\r
1179 inspector_mode = W_GROUP;
\r
1182 if (inspector_mode == W_ENTITY)
\r
1183 gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
\r
1185 gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
\r
1188 // =============================================================================
\r
1191 // NOTE: when a key is hit with group window focused, we catch in this handler but it gets propagated to mainframe too
\r
1192 // therefore the message will be intercepted and used as a ID_SELECTION_DESELECT
\r
1193 static gint OnDialogKey (GtkWidget* widget, GdkEventKey* event, gpointer data)
\r
1196 Sys_Printf("OnDialogKey\n");
\r
1198 if ((event->keyval == GDK_Escape) && (g_pParentWnd->CurrentStyle() != MainFrame::eFloating))
\r
1200 // toggle off the group view (whatever part of it is currently displayed)
\r
1201 // this used to be done with a g_pParentWnd->OnViewEntity(); but it had bad consequences
\r
1202 // http://fenris.lokigames.com/show_bug.cgi?id=2773
\r
1203 widget_delete_hide (g_qeglobals_gui.d_entity);
\r
1209 GroupDlg::GroupDlg ()
\r
1216 extern void PositionWindowOnPrimaryScreen(window_position_t& position);
\r
1219 void GroupDlg::Create ()
\r
1221 if (m_pWidget != NULL)
\r
1224 GtkWidget* dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
\r
1227 if( g_PrefsDlg.m_bStartOnPrimMon ) {
\r
1228 PositionWindowOnPrimaryScreen( g_PrefsDlg.mWindowInfo.posEntityWnd );
\r
1231 load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posEntityWnd);
\r
1233 gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
\r
1234 gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (widget_delete_hide), NULL);
\r
1236 gtk_signal_connect (GTK_OBJECT (dlg), "key_press_event", GTK_SIGNAL_FUNC (OnDialogKey), NULL);
\r
1237 gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pParentWnd->m_pWidget));
\r
1238 g_qeglobals_gui.d_entity = dlg;
\r
1241 GtkWidget* notebook = gtk_notebook_new ();
\r
1242 gtk_widget_show (notebook);
\r
1243 gtk_container_add (GTK_CONTAINER (dlg), notebook);
\r
1244 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);
\r
1245 m_pNotebook = notebook;
\r
1248 GtkWidget* vbox = gtk_vbox_new (FALSE, 2);
\r
1249 gtk_widget_show (vbox);
\r
1250 gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
\r
1253 GtkWidget* label = gtk_label_new ("Entities");
\r
1254 gtk_widget_show (label);
\r
1255 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
\r
1259 GtkWidget* split1 = gtk_vpaned_new ();
\r
1260 gtk_box_pack_start (GTK_BOX (vbox), split1, TRUE, TRUE, 0);
\r
1261 gtk_widget_show (split1);
\r
1264 GtkWidget* split2 = gtk_vpaned_new ();
\r
1265 gtk_paned_add1 (GTK_PANED (split1), split2);
\r
1266 gtk_widget_show (split2);
\r
1268 g_object_set_data (G_OBJECT (dlg), "split1", split1);
\r
1269 g_object_set_data (G_OBJECT (dlg), "split2", split2);
\r
1272 GtkWidget* vbox2 = gtk_vbox_new (FALSE, 2);
\r
1273 gtk_widget_show (vbox2);
\r
1274 gtk_paned_pack2 (GTK_PANED (split1), vbox2, FALSE, FALSE);
\r
1277 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
\r
1278 gtk_widget_show (scr);
\r
1279 gtk_paned_add1 (GTK_PANED (split2), scr);
\r
1280 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
\r
1281 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
\r
1284 GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
\r
1286 GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
\r
1287 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
\r
1288 g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(eclasslist_button_press), NULL);
\r
1289 g_signal_connect(G_OBJECT(view), "key_press_event", G_CALLBACK(eclasslist_keypress), this);
\r
1292 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
\r
1293 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, NULL);
\r
1294 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
\r
1298 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
\r
1299 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(eclasslist_selection_changed), dlg);
\r
1302 gtk_widget_show(view);
\r
1304 gtk_container_add(GTK_CONTAINER (scr), view);
\r
1306 g_object_unref(G_OBJECT(store));
\r
1307 EntWidgets[EntList] = view;
\r
1308 g_entlist_store = store;
\r
1313 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
\r
1314 gtk_widget_show (scr);
\r
1315 gtk_paned_add2 (GTK_PANED (split2), scr);
\r
1316 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
\r
1317 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
\r
1320 GtkWidget* text = gtk_text_view_new();
\r
1321 gtk_widget_set_size_request(text, 0, -1); // allow shrinking
\r
1322 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
\r
1323 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
\r
1324 gtk_widget_show (text);
\r
1325 gtk_container_add (GTK_CONTAINER (scr), text);
\r
1326 EntWidgets[EntComment] = text;
\r
1331 // Spawnflags (4 colums wide max, or window gets too wide.)
\r
1332 GtkWidget* table = LayoutTable = gtk_table_new (4, 4, FALSE);
\r
1333 gtk_box_pack_start (GTK_BOX (vbox2), LayoutTable, FALSE, TRUE, 0);
\r
1334 gtk_widget_show(LayoutTable);
\r
1336 for (int i = 0; i < MAX_FLAGS; i++)
\r
1338 GtkWidget* check = gtk_check_button_new_with_label ("");
\r
1339 gtk_widget_ref (check);
\r
1340 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
\r
1341 EntWidgets[EntCheck1+i] = check;
\r
1344 //++timo cleanme: these flags where Q2 stuff
\r
1346 check = gtk_check_button_new_with_label ("!Easy");
\r
1347 gtk_widget_show (check);
\r
1348 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
\r
1349 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 0, 1,
\r
1350 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
\r
1351 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
\r
1352 EntWidgets[EntCheck17] = check;
\r
1354 check = gtk_check_button_new_with_label ("!Medium");
\r
1355 gtk_widget_show (check);
\r
1356 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
\r
1357 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 1, 2,
\r
1358 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
\r
1359 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
\r
1360 EntWidgets[EntCheck18] = check;
\r
1362 check = gtk_check_button_new_with_label ("!Hard");
\r
1363 gtk_widget_show (check);
\r
1364 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
\r
1365 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 2, 3,
\r
1366 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
\r
1367 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
\r
1368 EntWidgets[EntCheck19] = check;
\r
1370 check = gtk_check_button_new_with_label ("!DeathMatch");
\r
1371 gtk_widget_show (check);
\r
1372 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
\r
1373 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 3, 4,
\r
1374 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
\r
1375 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
\r
1376 EntWidgets[EntCheck20] = check;
\r
1381 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
\r
1382 gtk_widget_show (scr);
\r
1383 gtk_box_pack_start (GTK_BOX (vbox2), scr, TRUE, TRUE, 0);
\r
1384 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
\r
1385 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
\r
1388 GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
\r
1390 GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
\r
1391 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
\r
1394 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
\r
1395 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
\r
1396 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
\r
1400 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
\r
1401 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);
\r
1402 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
\r
1406 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
\r
1407 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(proplist_selection_changed), dlg);
\r
1410 gtk_widget_show(view);
\r
1412 gtk_container_add(GTK_CONTAINER (scr), view);
\r
1414 g_object_unref(G_OBJECT(store));
\r
1416 EntWidgets[EntProps] = view;
\r
1417 g_entprops_store = store;
\r
1422 int x = g_PrefsDlg.mWindowInfo.nEntitySplit1;
\r
1425 gtk_paned_set_position (GTK_PANED (split1), x);
\r
1427 while (gtk_events_pending ()) gtk_main_iteration ();
\r
1428 x = g_PrefsDlg.mWindowInfo.nEntitySplit2;
\r
1431 gtk_paned_set_position (GTK_PANED (split2), x);
\r
1437 GtkWidget* table = gtk_table_new (2, 2, FALSE);
\r
1438 gtk_widget_show (table);
\r
1439 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
\r
1440 gtk_table_set_row_spacings (GTK_TABLE (table), 3);
\r
1441 gtk_table_set_col_spacings (GTK_TABLE (table), 5);
\r
1444 GtkWidget* entry = gtk_entry_new ();
\r
1445 gtk_widget_show (entry);
\r
1446 gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
\r
1447 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
\r
1448 (GtkAttachOptions) (0), 0, 0);
\r
1449 gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
\r
1450 gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",
\r
1451 GTK_SIGNAL_FUNC (entityentry_keypress), this);
\r
1452 EntWidgets[EntKeyField] = entry;
\r
1456 GtkWidget* entry = gtk_entry_new ();
\r
1457 gtk_widget_show (entry);
\r
1458 gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
\r
1459 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
\r
1460 (GtkAttachOptions) (0), 0, 0);
\r
1461 gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
\r
1462 gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",
\r
1463 GTK_SIGNAL_FUNC (entityentry_keypress), this);
\r
1464 EntWidgets[EntValueField] = entry;
\r
1468 GtkWidget* label = gtk_label_new ("Value");
\r
1469 gtk_widget_show (label);
\r
1470 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
\r
1471 (GtkAttachOptions) (GTK_FILL),
\r
1472 (GtkAttachOptions) (0), 0, 0);
\r
1473 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
\r
1477 GtkWidget* label = gtk_label_new ("Key");
\r
1478 gtk_widget_show (label);
\r
1479 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
\r
1480 (GtkAttachOptions) (GTK_FILL),
\r
1481 (GtkAttachOptions) (0), 0, 0);
\r
1482 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
\r
1487 GtkWidget* hbox = gtk_hbox_new (FALSE, 5);
\r
1488 gtk_widget_show (hbox);
\r
1489 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
\r
1492 GtkWidget* table = gtk_table_new (3, 3, TRUE);
\r
1493 gtk_widget_show (table);
\r
1494 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);
\r
1497 GtkWidget* button = gtk_button_new_with_label ("360");
\r
1498 gtk_widget_show (button);
\r
1499 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"360");
\r
1500 gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
\r
1501 (GtkAttachOptions) (GTK_FILL),
\r
1502 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1506 GtkWidget* button = gtk_button_new_with_label ("45");
\r
1507 gtk_widget_show (button);
\r
1508 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"45");
\r
1509 gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
\r
1510 (GtkAttachOptions) (GTK_FILL),
\r
1511 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1515 GtkWidget* button = gtk_button_new_with_label ("90");
\r
1516 gtk_widget_show (button);
\r
1517 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"90");
\r
1518 gtk_table_attach (GTK_TABLE (table), button, 1, 2, 0, 1,
\r
1519 (GtkAttachOptions) (GTK_FILL),
\r
1520 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1525 GtkWidget* button = gtk_button_new_with_label ("135");
\r
1526 gtk_widget_show (button);
\r
1527 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"135");
\r
1528 gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1,
\r
1529 (GtkAttachOptions) (GTK_FILL),
\r
1530 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1534 GtkWidget* button = gtk_button_new_with_label ("180");
\r
1535 gtk_widget_show (button);
\r
1536 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"180");
\r
1537 gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2,
\r
1538 (GtkAttachOptions) (GTK_FILL),
\r
1539 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1543 GtkWidget* button = gtk_button_new_with_label ("225");
\r
1544 gtk_widget_show (button);
\r
1545 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"225");
\r
1546 gtk_table_attach (GTK_TABLE (table), button, 0, 1, 2, 3,
\r
1547 (GtkAttachOptions) (GTK_FILL),
\r
1548 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1552 GtkWidget* button = gtk_button_new_with_label ("270");
\r
1553 gtk_widget_show (button);
\r
1554 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"270");
\r
1555 gtk_table_attach (GTK_TABLE (table), button, 1, 2, 2, 3,
\r
1556 (GtkAttachOptions) (GTK_FILL),
\r
1557 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1561 GtkWidget* button = gtk_button_new_with_label ("315");
\r
1562 gtk_widget_show (button);
\r
1563 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"315");
\r
1564 gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3,
\r
1565 (GtkAttachOptions) (GTK_FILL),
\r
1566 (GtkAttachOptions) (GTK_FILL), 0, 0);
\r
1571 GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);
\r
1572 gtk_widget_show (vbox2);
\r
1573 gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
\r
1576 GtkWidget* button = gtk_button_new_with_label ("Reset");
\r
1577 gtk_widget_show (button);
\r
1578 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (ResetEntity), NULL);
\r
1579 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
\r
1583 GtkWidget* button = gtk_button_new_with_label ("Up");
\r
1584 gtk_widget_show (button);
\r
1585 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-1");
\r
1586 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
\r
1590 GtkWidget* button = gtk_button_new_with_label ("Dn");
\r
1591 gtk_widget_show (button);
\r
1592 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-2");
\r
1593 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
\r
1598 GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);
\r
1599 gtk_widget_show (vbox2);
\r
1600 gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
\r
1603 GtkWidget* button = gtk_button_new_with_label ("Del Key/Pair");
\r
1604 gtk_widget_show (button);
\r
1605 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (DelProp), NULL);
\r
1606 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
\r
1610 GtkWidget* button = gtk_button_new_with_label ("Sound...");
\r
1611 gtk_widget_show (button);
\r
1612 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignSound), NULL);
\r
1613 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
\r
1617 GtkWidget* button = gtk_button_new_with_label ("Model...");
\r
1618 gtk_widget_show (button);
\r
1619 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignModel), NULL);
\r
1620 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
\r
1626 if (g_pParentWnd->FloatingGroupDialog())
\r
1629 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
\r
1630 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
\r
1631 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
\r
1632 gtk_widget_show (scr);
\r
1633 gtk_container_set_border_width (GTK_CONTAINER (scr), 3);
\r
1636 GtkWidget* text = gtk_text_view_new ();
\r
1637 gtk_widget_set_size_request(text, 0, -1); // allow shrinking
\r
1638 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
\r
1639 gtk_text_view_set_editable (GTK_TEXT_VIEW(text), FALSE);
\r
1640 gtk_container_add (GTK_CONTAINER (scr), text);
\r
1641 gtk_widget_show (text);
\r
1642 g_qeglobals_gui.d_edit = text;
\r
1646 GtkWidget* label = gtk_label_new ("Console");
\r
1647 gtk_widget_show (label);
\r
1648 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scr, label);
\r
1654 //++timo NOTE: this part for grouping code, don't remove! (we'll put it back in sometime soon)
\r
1657 vbox = gtk_vbox_new (FALSE, 5);
\r
1658 gtk_widget_show (vbox);
\r
1659 gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
\r
1661 scr = gtk_scrolled_window_new (NULL, NULL);
\r
1662 gtk_widget_show (scr);
\r
1663 gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
\r
1664 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
\r
1666 ctree = gtk_ctree_new (1, 0);
\r
1667 gtk_widget_show (ctree);
\r
1668 gtk_container_add (GTK_CONTAINER (scr), ctree);
\r
1669 gtk_clist_column_titles_hide (GTK_CLIST (ctree));
\r
1672 hbox = gtk_hbox_new (FALSE, 5);
\r
1673 gtk_widget_show (hbox);
\r
1674 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
\r
1676 button = gtk_button_new_with_label ("Add...");
\r
1677 gtk_widget_show (button);
\r
1678 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (groupdlg_add), NULL);
\r
1679 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
\r
1680 gtk_widget_set_usize (button, 60, -2);
\r
1682 button = gtk_button_new_with_label ("Edit...");
\r
1683 gtk_widget_show (button);
\r
1684 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
\r
1685 gtk_widget_set_usize (button, 60, -2);
\r
1687 button = gtk_button_new_with_label ("Delete");
\r
1688 gtk_widget_show (button);
\r
1689 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
\r
1690 gtk_widget_set_usize (button, 60, -2);
\r
1692 label = gtk_label_new ("Groups");
\r
1693 gtk_widget_show (label);
\r
1694 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
\r
1696 inspector_mode = W_ENTITY;
\r
1697 // gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
\r
1700 load_pixmap ("grouptree1.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[0], &tree_masks[0]);
\r
1701 load_pixmap ("grouptree2.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[1], &tree_masks[1]);
\r
1702 load_pixmap ("grouptree3.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[2], &tree_masks[2]);
\r
1703 load_pixmap ("grouptree4.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[3], &tree_masks[3]);
\r
1704 load_pixmap ("grouptree5.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[4], &tree_masks[4]);
\r
1705 load_pixmap ("grouptree6.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[5], &tree_masks[5]);
\r
1706 load_pixmap ("grouptree7.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[6], &tree_masks[6]);
\r
1710 g_signal_connect (G_OBJECT (notebook), "switch_page", G_CALLBACK (switch_page), dlg);
\r