2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 // Floating dialog that contains a notebook with at least Entities and Group tabs
24 // I merged the 2 MS Windows dialogs in a single class
26 // Leonardo Zide (leo@lokigames.com)
32 #include <gdk/gdkkeysyms.h>
33 #include <glib/gi18n.h>
35 #include "groupdialog.h"
37 GtkWidget* EntWidgets[EntLast];
38 GtkListStore* g_entlist_store;
39 GtkListStore* g_entprops_store;
40 int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE
41 qboolean multiple_entities;
42 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=17
43 qboolean disable_spawn_get = false;
44 entity_t *edit_entity;
46 static GdkPixmap *tree_pixmaps[7];
47 static GdkBitmap *tree_masks[7];
53 #define IMG_ENTITYGROUP 4
58 #define MAX_GROUPS 4096
59 #define GROUP_DELIMETER '@'
60 #define GROUPNAME "QER_Group_%i"
63 GroupDlg *g_pGroupDlg = &g_wndGroup;
65 // group_t are loaded / saved through "group_info" entities
66 // they hold epairs for group settings and additionnal access info (tree nodes)
67 group_t *g_pGroups = NULL;
69 // the number of active spawnflags
70 static int spawnflag_count;
71 // table: index, match spawnflag item to the spawnflag index (i.e. which bit)
72 static int spawn_table[MAX_FLAGS];
73 // we change the layout depending on how many spawn flags we need to display
74 // the table is a 4x4 in which we need to put the comment box EntWidgets[EntComment] and the spawn flags..
75 static GtkWidget *LayoutTable;
76 // 0: none of them are hooked
77 // 1: only the text, 2: text and four checks, 3: text and 8 checks
78 static int widget_state = 0;
80 static void entity_check (GtkWidget *widget, gpointer data);
82 // =============================================================================
86 ===============================================================
90 ===============================================================
95 GtkListStore* store = g_entlist_store;
97 gtk_list_store_clear(store);
99 for (eclass_t* e = eclass ; e ; e = e->next)
102 gtk_list_store_append(store, &iter);
103 gtk_list_store_set(store, &iter, 0, e->name, 1, e, -1);
109 // Reset the key/value (aka property) listbox and fill it with the
110 // k/v pairs from the entity being edited.
113 void SetKeyValuePairs (bool bClearMD3)
115 GtkListStore* store = g_entprops_store;
117 gtk_list_store_clear(store);
119 if (edit_entity == NULL)
121 // if there's no entity, then display no key/values
125 // save current key/val pair around filling epair box
126 // row_select wipes it and sets to first in list
127 Str strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
128 Str strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
131 // Walk through list and add pairs
132 for(epair_t* epair = edit_entity->epairs ; epair ; epair = epair->next)
135 gtk_list_store_append(store, &iter);
136 gtk_list_store_set(store, &iter, 0, epair->key, 1, epair->value, -1);
139 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), strKey.GetBuffer());
140 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), strVal.GetBuffer());
142 Sys_UpdateWindows(W_CAMERA | W_XY);
147 // Update the checkboxes to reflect the flag state of the entity
149 void SetSpawnFlags(void)
153 disable_spawn_get = true;
155 f = atoi(ValueForKey (edit_entity, "spawnflags"));
156 for (i=0 ; i<spawnflag_count ; i++)
158 v = !!(f&(1<<spawn_table[i]));
159 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), v);
161 // take care of the remaining ones
162 for (i=spawnflag_count ; i<MAX_FLAGS ; i++)
164 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), FALSE);
167 disable_spawn_get = false;
172 // Update the entity flags to reflect the state of the checkboxes
174 // NOTE: this function had a tendency to add "spawnflags" "0" on most entities
175 // if this wants to set spawnflags to zero, remove the key
177 void GetSpawnFlags(void)
183 for (i=0 ; i<spawnflag_count ; i++)
185 v = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]));
186 f |= v<<spawn_table[i];
191 // remove all "spawnflags" keys
192 if (multiple_entities)
196 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
197 DeleteKey (b->owner, "spawnflags");
200 DeleteKey (edit_entity, "spawnflags");
204 sprintf (sz, "%i", f);
205 if (multiple_entities)
209 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
210 SetKeyValue(b->owner, "spawnflags", sz);
213 SetKeyValue (edit_entity, "spawnflags", sz);
218 //#define DBG_UPDATESEL
222 // Update the listbox, checkboxes and k/v pairs to reflect the new selection
223 // iIndex is the index in the list box with the class name, -1 if not found
224 bool UpdateSel(int iIndex, eclass_t *pec)
229 // syndrom of crappy code, we may get into stack overflowing crap with this function and Gtk
230 // if we play with the list of entity classes
231 // using a static flag to prevent recursion
232 static bool bBlockUpdate = false;
235 return FALSE; // NOTE TTimo wtf is the return value for anyway?
238 Sys_FPrintf(SYS_WRN, "UpdateSel\n");
241 if (selected_brushes.next == &selected_brushes)
243 edit_entity = world_entity;
244 multiple_entities = false;
248 edit_entity = selected_brushes.next->owner;
249 for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next)
251 if (b->owner != edit_entity)
253 multiple_entities = true;
262 Sys_FPrintf(SYS_WRN,"Setting focus_row to %d\n", iIndex);
266 GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
267 GtkTreePath* path = gtk_tree_path_new();
268 gtk_tree_path_append_index(path, iIndex);
269 gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);
270 gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);
271 gtk_tree_path_free(path);
273 bBlockUpdate = false;
279 // Set up the description
281 GtkTextBuffer* buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(EntWidgets[EntComment]));
282 gtk_text_buffer_set_text (buffer, pec->comments, -1);
287 // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are
288 for (i=0 ; i<MAX_FLAGS ; i++)
290 if (pec->flagnames[i] && pec->flagnames[i][0] != 0 && strcmp(pec->flagnames[i],"-"))
292 spawn_table[spawnflag_count] = i;
297 // what's new widget state
298 if (spawnflag_count==0)
300 else if (spawnflag_count<=4)
302 else if (spawnflag_count<=8)
304 else if (spawnflag_count<=12)
308 widget_state = next_state;
309 static int last_count = 0;
311 // disable all remaining boxes
312 // NOTE: these boxes might not even be on display
313 for (i = 0; i < last_count; i++)
315 GtkWidget* widget = EntWidgets[EntCheck1+i];
316 gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), " ");
317 gtk_widget_hide (widget);
318 gtk_widget_ref (widget);
319 gtk_container_remove (GTK_CONTAINER (LayoutTable), widget);
321 last_count = spawnflag_count;
323 for (i=0 ; i<spawnflag_count ; i++)
325 GtkWidget* widget = EntWidgets[EntCheck1+i];
326 gtk_widget_show (widget);
329 str = pec->flagnames[spawn_table[i]];
332 // gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,
333 gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,
334 (GtkAttachOptions) (GTK_FILL),
335 (GtkAttachOptions) (GTK_FILL), 0, 0);
336 gtk_widget_unref (widget);
338 gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), str.GetBuffer ());
348 bool UpdateEntitySel(eclass_t *pec)
351 Sys_FPrintf(SYS_WRN, "UpdateEntitySel\n");
354 GtkTreeModel* model = GTK_TREE_MODEL(g_entlist_store);
357 for(gboolean good = gtk_tree_model_get_iter_first(model, &iter); good != FALSE; good = gtk_tree_model_iter_next(model, &iter))
360 gtk_tree_model_get(model, &iter, 0, &text, -1);
361 if (strcmp (text, pec->name) == 0)
364 Sys_FPrintf(SYS_WRN, "found a match: %d %s\n", i, pec->name);
366 return UpdateSel (i, pec);
371 return UpdateSel (-1, pec);
376 // Creates a new entity based on the currently selected brush and entity type.
379 void CreateEntity(void)
381 GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
383 // check to make sure we have a brush
384 if (selected_brushes.next == &selected_brushes)
386 gtk_MessageBox(g_pParentWnd->m_pWidget, "You must have a selected brush to create an entity", "info");
390 // find out what type of entity we are trying to create
393 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE)
395 gtk_MessageBox (g_pParentWnd->m_pWidget, "You must have a selected class to create an entity", "info");
400 gtk_tree_model_get(model, &iter, 0, &text, -1);
401 CreateEntityFromName(text, vec3_origin);
404 if (selected_brushes.next == &selected_brushes)
405 edit_entity = world_entity;
407 edit_entity = selected_brushes.next->owner;
411 Select_Brush (edit_entity->brushes.onext);
412 Sys_UpdateWindows(W_ALL);
423 if (edit_entity == NULL)
426 // Get current selection text
427 const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
428 const char* value = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
431 // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity
432 if (!strcmp(key, "classname") && !strcmp(value, "worldspawn"))
434 gtk_MessageBox(g_pParentWnd->m_pWidget, "Cannot change \"classname\" key back to worldspawn.", NULL, MB_OK );
439 // RR2DO2: we don't want spaces in entity keys
440 if (strstr( key, " " ))
442 gtk_MessageBox(g_pParentWnd->m_pWidget, "No spaces are allowed in entity keys.", NULL, MB_OK );
446 if (multiple_entities)
450 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
451 SetKeyValue(b->owner, key, value);
454 SetKeyValue(edit_entity, key, value);
456 // refresh the prop listbox
460 #ifdef USEPLUGINENTITIES
461 // if it's a plugin entity, perhaps we need to update some drawing parameters
462 // NOTE: perhaps moving this code to a seperate func would help if we need it in other places
463 // TODO: we need to call some update func in the IPluginEntity in case model name changes etc.
464 // ( for the moment only bounding brush is updated ), see UpdateModelBrush in Ritual's Q3Radiant
465 if (edit_entity->eclass->nShowFlags & ECLASS_PLUGINENTITY)
468 edit_entity->pPlugEnt->GetBounds( mins, maxs );
469 // replace old bounding brush by newly computed one
470 // NOTE: this part is similar to Entity_BuildModelBrush in Ritual's Q3Radiant, it can be
471 // usefull moved into a seperate func
472 brush_t *b,*oldbrush;
473 if (edit_entity->brushes.onext != &edit_entity->brushes)
474 oldbrush = edit_entity->brushes.onext;
475 b = Brush_Create (mins, maxs, &edit_entity->eclass->texdef);
476 Entity_LinkBrush (edit_entity, b);
477 Brush_Build( b, true );
479 Brush_AddToList (edit_entity->brushes.onext, &selected_brushes);
481 Brush_Free( oldbrush );
483 #endif // USEPLUGINENTITIES
494 if (edit_entity == NULL)
497 // Get current selection text
498 const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
500 if (multiple_entities)
504 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
505 DeleteKey(b->owner, key);
508 DeleteKey(edit_entity, key);
510 // refresh the prop listbox
519 if (edit_entity == NULL)
522 if (multiple_entities)
526 for (b=selected_brushes.next; b != &selected_brushes; b=b->next)
527 for (pep = b->owner->epairs; pep; )
529 if (strcmp (pep->key, "classname") != 0)
531 DeleteKey (b->owner, pep->key);
532 pep = b->owner->epairs;
539 for (pep = edit_entity->epairs; pep; )
541 if (strcmp (pep->key, "classname") != 0)
543 DeleteKey (edit_entity, pep->key);
544 pep = edit_entity->epairs;
550 // refresh the dialog
552 for (i = EntCheck1; i <= EntCheck16; i++)
553 gtk_signal_handler_block_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);
555 for (i = EntCheck1; i <= EntCheck16; i++)
556 gtk_signal_handler_unblock_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);
559 bool GetSelectAllCriteria(CString &strKey, CString &strVal)
563 if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(EntWidgets[EntProps])), &model, &iter)
564 && (inspector_mode == W_ENTITY)
565 && GTK_WIDGET_VISIBLE (g_pGroupDlg->m_pWidget))
567 strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
568 strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
577 char buffer[NAME_MAX];
579 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
580 strcat (buffer, "sound/");
582 if( access(buffer, R_OK) != 0 )
585 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
586 strcat (buffer, "/");
589 const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, _("Open Wav File"), buffer, "sound");
590 if (filename != NULL)
592 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "noise");
593 char *aux = vfsExtractRelativePath (filename);
599 Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");
603 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer());
610 char buffer[NAME_MAX];
612 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
613 strcat (buffer, "models/");
615 if( access(buffer, R_OK) != 0 )
618 strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
619 strcat (buffer, "/");
622 const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, _("Open Model"), buffer, MODEL_MAJOR);
623 if (filename != NULL)
625 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "model");
626 // use VFS to get the correct relative path
627 char *aux = vfsExtractRelativePath (filename);
633 Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");
637 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer());
639 edit_entity->brushes.onext->bModelFailed = false;
648 void SetInspectorMode(int iType)
650 if (iType == W_GROUP)
651 gtk_MessageBox(g_pParentWnd->m_pWidget, "Brush grouping is not functional yet", NULL, MB_OK | MB_ICONWARNING );
653 if (!g_pParentWnd->FloatingGroupDialog() &&
654 (iType == W_TEXTURE || iType == W_CONSOLE))
657 // Is the caller asking us to cycle to the next window?
660 if (inspector_mode == W_ENTITY)
662 else if (inspector_mode == W_TEXTURE)
664 else if (inspector_mode == W_CONSOLE)
673 // entity is always first in the inspector
674 gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Entities");
675 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 0);
679 g_pParentWnd->GetTexWnd()->FocusEdit();
680 gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Textures");
681 if (g_pParentWnd->FloatingGroupDialog())
682 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);
686 gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Console");
687 if (g_pParentWnd->FloatingGroupDialog())
688 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 2);
692 if (g_pParentWnd->FloatingGroupDialog())
693 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 3);
695 gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);
703 void Group_Add(entity_t *e)
706 group_t *g = (group_t*)qmalloc(sizeof(group_t));
707 g->epairs = e->epairs;
711 // create a new group node
712 char *text = ValueForKey(g->epairs, "group");
713 g->itemOwner = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_wndGroup.m_hWorld, NULL, &text, 0,
714 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],
715 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], TRUE, TRUE);
721 group_t* Group_Alloc(char *name)
723 group_t *g = (group_t*)qmalloc(sizeof(group_t));
724 SetKeyValue( g->epairs, "group", name );
728 group_t* Group_ForName(const char * name)
730 group_t *g = g_pGroups;
733 if (strcmp( ValueForKey(g->epairs,"group"), name ) == 0)
740 void Group_AddToItem(brush_t *b, GtkCTreeNode* item)
742 int nImage = IMG_BRUSH;
743 if (!g_qeglobals.m_bBrushPrimitMode)
747 const char *pName = NULL;
748 // const char *pNamed = Brush_GetKeyValue(b, "name");
750 if (!b->owner || (b->owner == world_entity))
754 pName = "Generic Patch";
759 pName = "Generic Brush";
765 pName = b->owner->eclass->name;
766 if (b->owner->eclass->fixedsize)
772 nImage = IMG_ENTITYGROUP;
776 GtkCTreeNode *newItem;
777 int i = (b->patchBrush) ? IMG_PATCH : IMG_BRUSH;
778 newItem = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), item, NULL, (gchar**)&pName, 0,
779 tree_pixmaps[i], tree_masks[i], tree_pixmaps[i],
780 tree_masks[i], TRUE, TRUE);
781 gtk_ctree_node_set_row_data (GTK_CTREE (g_wndGroup.m_pTree), newItem, b);
782 b->itemOwner = newItem;
785 void Group_RemoveBrush(brush_t *b)
788 if (!g_qeglobals.m_bBrushPrimitMode)
794 gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);
797 DeleteKey(b->epairs, "group");
801 void Group_AddToWorld(brush_t *b)
803 if (!g_qeglobals.m_bBrushPrimitMode)
807 GtkCTreeNode *parent = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);
808 Group_AddToItem(b, parent);
811 void Group_AddToProperGroup(brush_t *b)
814 if (!g_qeglobals.m_bBrushPrimitMode)
819 // NOTE: we do a local copy of the "group" key because it gets erased by Group_RemoveBrush
820 const char *pGroup = Brush_GetKeyValue(b, "group");
821 // remove the entry in the tree if there's one
824 gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);
831 group_t *g = Group_ForName(pGroup);
833 Group_AddToItem(b, g->itemOwner);
836 Sys_Printf("WARNING: unexpected Group_ForName not found in Group_AddToProperGroup\n");
846 void Group_AddToSelected(brush_t *b)
848 if (!g_qeglobals.m_bBrushPrimitMode)
853 item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), GTK_CLIST (g_pGroupDlg->m_pTree)->focus_row);
856 item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);
858 Group_AddToItem(b, item);
862 void Group_Save(FILE *f)
864 group_t *g = g_pGroups;
867 fprintf(f,"{\n\"classname\" \"group_info\"\n\"group\" \"%s\"\n}\n", ValueForKey( g->epairs, "group" ));
875 if (!g_qeglobals.m_bBrushPrimitMode)
879 // start by cleaning everything
881 //++timo FIXME: we leak, delete the groups on the way (I don't have time to do it now)
883 Sys_Printf("TODO: fix leak in Group_Init\n");
885 group_t *g = g_pGroups;
889 for (ep = g->epairs ; ep ; ep=enext )
900 char *text = "World";
902 gtk_clist_clear (GTK_CLIST (g_wndGroup.m_pTree));
903 world = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), NULL, NULL, &text, 0,
904 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], tree_pixmaps[IMG_GROUP],
905 tree_masks[IMG_GROUP], FALSE, TRUE);
907 // walk through all the brushes, remove the itemOwner key and add them back where they belong
909 for (b = active_brushes.next; b != &active_brushes; b = b->next)
912 Group_AddToProperGroup(b);
914 for (b = selected_brushes.next ; b != &selected_brushes ; b = b->next)
917 Group_AddToProperGroup(b);
921 // scan through world_entity for groups in this map?
922 // we use GROUPNAME "QER_group_%i" to look for existing groups and their naming
923 //++timo FIXME: is this actually needed for anything?
924 void Group_GetListFromWorld(GSList **pArray)
926 if (!g_qeglobals.m_bBrushPrimitMode)
931 if (world_entity == NULL)
937 for (int i =0; i < MAX_GROUPS; i++)
939 sprintf(cBuff, GROUPNAME, i);
940 char *pGroup = ValueForKey(world_entity, cBuff);
941 if (pGroup && strlen(pGroup) > 0)
943 *pArray = g_slist_append (*pArray, g_strdup (pGroup));
952 void Group_RemoveListFromWorld()
954 if (!g_qeglobals.m_bBrushPrimitMode)
958 GSList* array = NULL;
959 Group_GetListFromWorld(&array);
963 DeleteKey(world_entity, (char*)array->data);
964 g_free (array->data);
965 array = g_slist_remove (array, array->data);
969 int CountChar(const char *p, char c)
972 int nLen = strlen(p)-1;
983 // =============================================================================
986 static void eclasslist_selection_changed(GtkTreeSelection* selection, gpointer data)
989 GtkTreeIter selected;
990 // no world entity, we are not ready yet
991 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=917
992 if( !world_entity ) {
995 if(gtk_tree_selection_get_selected(selection, &model, &selected))
998 gtk_tree_model_get(model, &selected, 1, &eclass, -1);
1001 GtkTreePath* path = gtk_tree_model_get_path(model, &selected);
1002 UpdateSel(gtk_tree_path_get_indices(path)[0], eclass);
1003 gtk_tree_path_free(path);
1008 static gint eclasslist_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
1010 if (event->type == GDK_2BUTTON_PRESS)
1018 static gint eclasslist_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)
1020 unsigned int code = gdk_keyval_to_upper (event->keyval);
1022 if (event->keyval == GDK_Return)
1028 // select the entity that starts with the key pressed
1029 if (code <= 'Z' && code >= 'A')
1031 GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
1032 GtkTreeModel* model;
1034 if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE
1035 || gtk_tree_model_iter_next(model, &iter) == FALSE)
1037 gtk_tree_model_get_iter_first(model, &iter);
1040 for(unsigned int count = gtk_tree_model_iter_n_children(model, NULL); count > 0; --count)
1043 gtk_tree_model_get(model, &iter, 0, &text, -1);
1045 if (toupper (text[0]) == (int)code)
1047 GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
1048 gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);
1049 gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);
1050 gtk_tree_path_free(path);
1056 if(gtk_tree_model_iter_next(model, &iter) == FALSE)
1057 gtk_tree_model_get_iter_first(model, &iter);
1066 static void proplist_selection_changed(GtkTreeSelection* selection, gpointer data)
1068 // find out what type of entity we are trying to create
1069 GtkTreeModel* model;
1071 if(gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
1078 gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1);
1080 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), key);
1081 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), val);
1087 static void entity_check (GtkWidget *widget, gpointer data)
1089 if( !disable_spawn_get )
1093 static void entitylist_angle (GtkWidget *widget, gpointer data)
1095 SetKeyValue (edit_entity, "angle", (char*)data);
1096 SetKeyValuePairs ();
1099 static gint entityentry_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)
1101 if (event->keyval == GDK_Tab)
1103 if (widget == EntWidgets[EntKeyField])
1105 //gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");
1106 gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);
1109 gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntKeyField]);
1113 else if (event->keyval == GDK_Return)
1115 if (widget == EntWidgets[EntKeyField])
1117 gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");
1118 gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);
1130 // add a new group, put all selected brushes into the group
1131 static void groupdlg_add (GtkWidget *widget, gpointer data)
1133 char* name = DoNameDlg ("New Group");
1137 // create a new group node
1139 item = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_pGroupDlg->m_hWorld, NULL, &name, 0,
1140 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],
1141 tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], FALSE, TRUE);
1143 // create a new group
1144 group_t *g = Group_Alloc (name);
1145 g->itemOwner = item;
1146 g->next = g_pGroups;
1149 // now add the selected brushes
1150 // NOTE: it would be much faster to give the group_t for adding
1151 // but Select_AddToGroup is the standard way for all other cases
1152 Select_AddToGroup (name);
1157 static void switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)
1160 gtk_label_get(GTK_LABEL(gtk_notebook_get_tab_label(notebook, gtk_notebook_get_nth_page(notebook, page_num))), &text);
1161 gtk_window_set_title (GTK_WINDOW (data), text);
1163 gpointer item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_misc_selectentitycolor");
1165 if (g_pParentWnd->FloatingGroupDialog())
1169 case 0: inspector_mode = W_ENTITY; break;
1170 case 1: inspector_mode = W_TEXTURE; break;
1171 case 2: inspector_mode = W_CONSOLE; break;
1172 default: inspector_mode = W_GROUP; break;
1178 inspector_mode = W_ENTITY;
1180 inspector_mode = W_GROUP;
1183 if (inspector_mode == W_ENTITY)
1184 gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
1186 gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
1189 // =============================================================================
1192 // NOTE: when a key is hit with group window focused, we catch in this handler but it gets propagated to mainframe too
1193 // therefore the message will be intercepted and used as a ID_SELECTION_DESELECT
1194 static gint OnDialogKey (GtkWidget* widget, GdkEventKey* event, gpointer data)
1197 Sys_Printf("OnDialogKey\n");
1199 if ((event->keyval == GDK_Escape) && (g_pParentWnd->CurrentStyle() != MainFrame::eFloating))
1201 // toggle off the group view (whatever part of it is currently displayed)
1202 // this used to be done with a g_pParentWnd->OnViewEntity(); but it had bad consequences
1203 // http://fenris.lokigames.com/show_bug.cgi?id=2773
1204 widget_delete_hide (g_qeglobals_gui.d_entity);
1210 GroupDlg::GroupDlg ()
1217 extern void PositionWindowOnPrimaryScreen(window_position_t& position);
1220 void GroupDlg::Create ()
1222 if (m_pWidget != NULL)
1225 GtkWidget* dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1228 if( g_PrefsDlg.m_bStartOnPrimMon ) {
1229 PositionWindowOnPrimaryScreen( g_PrefsDlg.mWindowInfo.posEntityWnd );
1232 load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posEntityWnd);
1234 gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
1235 gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (widget_delete_hide), NULL);
1237 gtk_signal_connect (GTK_OBJECT (dlg), "key_press_event", GTK_SIGNAL_FUNC (OnDialogKey), NULL);
1238 gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pParentWnd->m_pWidget));
1239 g_qeglobals_gui.d_entity = dlg;
1242 GtkWidget* notebook = gtk_notebook_new ();
1243 gtk_widget_show (notebook);
1244 gtk_container_add (GTK_CONTAINER (dlg), notebook);
1245 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);
1246 m_pNotebook = notebook;
1249 GtkWidget* vbox = gtk_vbox_new (FALSE, 2);
1250 gtk_widget_show (vbox);
1251 gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
1254 GtkWidget* label = gtk_label_new ("Entities");
1255 gtk_widget_show (label);
1256 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
1260 GtkWidget* split1 = gtk_vpaned_new ();
1261 gtk_box_pack_start (GTK_BOX (vbox), split1, TRUE, TRUE, 0);
1262 gtk_widget_show (split1);
1265 GtkWidget* split2 = gtk_vpaned_new ();
1266 gtk_paned_add1 (GTK_PANED (split1), split2);
1267 gtk_widget_show (split2);
1269 g_object_set_data (G_OBJECT (dlg), "split1", split1);
1270 g_object_set_data (G_OBJECT (dlg), "split2", split2);
1273 GtkWidget* vbox2 = gtk_vbox_new (FALSE, 2);
1274 gtk_widget_show (vbox2);
1275 gtk_paned_pack2 (GTK_PANED (split1), vbox2, FALSE, FALSE);
1278 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
1279 gtk_widget_show (scr);
1280 gtk_paned_add1 (GTK_PANED (split2), scr);
1281 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
1282 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1285 GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
1287 GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1288 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
1289 g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(eclasslist_button_press), NULL);
1290 g_signal_connect(G_OBJECT(view), "key_press_event", G_CALLBACK(eclasslist_keypress), this);
1293 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1294 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, NULL);
1295 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1299 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1300 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(eclasslist_selection_changed), dlg);
1303 gtk_widget_show(view);
1305 gtk_container_add(GTK_CONTAINER (scr), view);
1307 g_object_unref(G_OBJECT(store));
1308 EntWidgets[EntList] = view;
1309 g_entlist_store = store;
1314 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
1315 gtk_widget_show (scr);
1316 gtk_paned_add2 (GTK_PANED (split2), scr);
1317 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
1318 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1321 GtkWidget* text = gtk_text_view_new();
1322 gtk_widget_set_size_request(text, 0, -1); // allow shrinking
1323 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
1324 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
1325 gtk_widget_show (text);
1326 gtk_container_add (GTK_CONTAINER (scr), text);
1327 EntWidgets[EntComment] = text;
1332 // Spawnflags (4 colums wide max, or window gets too wide.)
1333 GtkWidget* LayoutTable = gtk_table_new (4, 4, FALSE);
1334 gtk_box_pack_start (GTK_BOX (vbox2), LayoutTable, FALSE, TRUE, 0);
1335 gtk_widget_show(LayoutTable);
1337 for (int i = 0; i < MAX_FLAGS; i++)
1339 GtkWidget* check = gtk_check_button_new_with_label ("");
1340 gtk_widget_ref (check);
1341 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
1342 EntWidgets[EntCheck1+i] = check;
1345 //++timo cleanme: these flags where Q2 stuff
1347 check = gtk_check_button_new_with_label ("!Easy");
1348 gtk_widget_show (check);
1349 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
1350 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 0, 1,
1351 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1352 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
1353 EntWidgets[EntCheck17] = check;
1355 check = gtk_check_button_new_with_label ("!Medium");
1356 gtk_widget_show (check);
1357 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
1358 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 1, 2,
1359 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1360 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
1361 EntWidgets[EntCheck18] = check;
1363 check = gtk_check_button_new_with_label ("!Hard");
1364 gtk_widget_show (check);
1365 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
1366 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 2, 3,
1367 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1368 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
1369 EntWidgets[EntCheck19] = check;
1371 check = gtk_check_button_new_with_label ("!DeathMatch");
1372 gtk_widget_show (check);
1373 gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
1374 gtk_table_attach (GTK_TABLE (table), check, 2, 3, 3, 4,
1375 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1376 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
1377 EntWidgets[EntCheck20] = check;
1382 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
1383 gtk_widget_show (scr);
1384 gtk_box_pack_start (GTK_BOX (vbox2), scr, TRUE, TRUE, 0);
1385 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1386 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1389 GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
1391 GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1392 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
1395 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1396 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
1397 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1401 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1402 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);
1403 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1407 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1408 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(proplist_selection_changed), dlg);
1411 gtk_widget_show(view);
1413 gtk_container_add(GTK_CONTAINER (scr), view);
1415 g_object_unref(G_OBJECT(store));
1417 EntWidgets[EntProps] = view;
1418 g_entprops_store = store;
1423 int x = g_PrefsDlg.mWindowInfo.nEntitySplit1;
1426 gtk_paned_set_position (GTK_PANED (split1), x);
1428 while (gtk_events_pending ()) gtk_main_iteration ();
1429 x = g_PrefsDlg.mWindowInfo.nEntitySplit2;
1432 gtk_paned_set_position (GTK_PANED (split2), x);
1438 GtkWidget* table = gtk_table_new (2, 2, FALSE);
1439 gtk_widget_show (table);
1440 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
1441 gtk_table_set_row_spacings (GTK_TABLE (table), 3);
1442 gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1445 GtkWidget* entry = gtk_entry_new ();
1446 gtk_widget_show (entry);
1447 gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
1448 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1449 (GtkAttachOptions) (0), 0, 0);
1450 gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
1451 gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",
1452 GTK_SIGNAL_FUNC (entityentry_keypress), this);
1453 EntWidgets[EntKeyField] = entry;
1457 GtkWidget* entry = gtk_entry_new ();
1458 gtk_widget_show (entry);
1459 gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
1460 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1461 (GtkAttachOptions) (0), 0, 0);
1462 gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
1463 gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",
1464 GTK_SIGNAL_FUNC (entityentry_keypress), this);
1465 EntWidgets[EntValueField] = entry;
1469 GtkWidget* label = gtk_label_new ("Value");
1470 gtk_widget_show (label);
1471 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
1472 (GtkAttachOptions) (GTK_FILL),
1473 (GtkAttachOptions) (0), 0, 0);
1474 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1478 GtkWidget* label = gtk_label_new ("Key");
1479 gtk_widget_show (label);
1480 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
1481 (GtkAttachOptions) (GTK_FILL),
1482 (GtkAttachOptions) (0), 0, 0);
1483 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1488 GtkWidget* hbox = gtk_hbox_new (FALSE, 5);
1489 gtk_widget_show (hbox);
1490 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1493 GtkWidget* table = gtk_table_new (3, 3, TRUE);
1494 gtk_widget_show (table);
1495 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);
1498 GtkWidget* button = gtk_button_new_with_label ("360");
1499 gtk_widget_show (button);
1500 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"360");
1501 gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
1502 (GtkAttachOptions) (GTK_FILL),
1503 (GtkAttachOptions) (GTK_FILL), 0, 0);
1507 GtkWidget* button = gtk_button_new_with_label ("45");
1508 gtk_widget_show (button);
1509 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"45");
1510 gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
1511 (GtkAttachOptions) (GTK_FILL),
1512 (GtkAttachOptions) (GTK_FILL), 0, 0);
1516 GtkWidget* button = gtk_button_new_with_label ("90");
1517 gtk_widget_show (button);
1518 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"90");
1519 gtk_table_attach (GTK_TABLE (table), button, 1, 2, 0, 1,
1520 (GtkAttachOptions) (GTK_FILL),
1521 (GtkAttachOptions) (GTK_FILL), 0, 0);
1526 GtkWidget* button = gtk_button_new_with_label ("135");
1527 gtk_widget_show (button);
1528 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"135");
1529 gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1,
1530 (GtkAttachOptions) (GTK_FILL),
1531 (GtkAttachOptions) (GTK_FILL), 0, 0);
1535 GtkWidget* button = gtk_button_new_with_label ("180");
1536 gtk_widget_show (button);
1537 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"180");
1538 gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2,
1539 (GtkAttachOptions) (GTK_FILL),
1540 (GtkAttachOptions) (GTK_FILL), 0, 0);
1544 GtkWidget* button = gtk_button_new_with_label ("225");
1545 gtk_widget_show (button);
1546 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"225");
1547 gtk_table_attach (GTK_TABLE (table), button, 0, 1, 2, 3,
1548 (GtkAttachOptions) (GTK_FILL),
1549 (GtkAttachOptions) (GTK_FILL), 0, 0);
1553 GtkWidget* button = gtk_button_new_with_label ("270");
1554 gtk_widget_show (button);
1555 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"270");
1556 gtk_table_attach (GTK_TABLE (table), button, 1, 2, 2, 3,
1557 (GtkAttachOptions) (GTK_FILL),
1558 (GtkAttachOptions) (GTK_FILL), 0, 0);
1562 GtkWidget* button = gtk_button_new_with_label ("315");
1563 gtk_widget_show (button);
1564 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"315");
1565 gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3,
1566 (GtkAttachOptions) (GTK_FILL),
1567 (GtkAttachOptions) (GTK_FILL), 0, 0);
1572 GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);
1573 gtk_widget_show (vbox2);
1574 gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
1577 GtkWidget* button = gtk_button_new_with_label ("Reset");
1578 gtk_widget_show (button);
1579 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (ResetEntity), NULL);
1580 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1584 GtkWidget* button = gtk_button_new_with_label ("Up");
1585 gtk_widget_show (button);
1586 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-1");
1587 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1591 GtkWidget* button = gtk_button_new_with_label ("Dn");
1592 gtk_widget_show (button);
1593 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-2");
1594 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1599 GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);
1600 gtk_widget_show (vbox2);
1601 gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
1604 GtkWidget* button = gtk_button_new_with_label ("Del Key/Pair");
1605 gtk_widget_show (button);
1606 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (DelProp), NULL);
1607 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1611 GtkWidget* button = gtk_button_new_with_label ("Sound...");
1612 gtk_widget_show (button);
1613 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignSound), NULL);
1614 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1618 GtkWidget* button = gtk_button_new_with_label ("Model...");
1619 gtk_widget_show (button);
1620 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignModel), NULL);
1621 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1627 if (g_pParentWnd->FloatingGroupDialog())
1630 GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
1631 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1632 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1633 gtk_widget_show (scr);
1634 gtk_container_set_border_width (GTK_CONTAINER (scr), 3);
1637 GtkWidget* text = gtk_text_view_new ();
1638 gtk_widget_set_size_request(text, 0, -1); // allow shrinking
1639 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
1640 gtk_text_view_set_editable (GTK_TEXT_VIEW(text), FALSE);
1641 gtk_container_add (GTK_CONTAINER (scr), text);
1642 gtk_widget_show (text);
1643 g_qeglobals_gui.d_edit = text;
1647 GtkWidget* label = gtk_label_new ("Console");
1648 gtk_widget_show (label);
1649 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scr, label);
1655 //++timo NOTE: this part for grouping code, don't remove! (we'll put it back in sometime soon)
1658 vbox = gtk_vbox_new (FALSE, 5);
1659 gtk_widget_show (vbox);
1660 gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
1662 scr = gtk_scrolled_window_new (NULL, NULL);
1663 gtk_widget_show (scr);
1664 gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
1665 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1667 ctree = gtk_ctree_new (1, 0);
1668 gtk_widget_show (ctree);
1669 gtk_container_add (GTK_CONTAINER (scr), ctree);
1670 gtk_clist_column_titles_hide (GTK_CLIST (ctree));
1673 hbox = gtk_hbox_new (FALSE, 5);
1674 gtk_widget_show (hbox);
1675 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1677 button = gtk_button_new_with_label ("Add...");
1678 gtk_widget_show (button);
1679 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (groupdlg_add), NULL);
1680 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1681 gtk_widget_set_usize (button, 60, -2);
1683 button = gtk_button_new_with_label ("Edit...");
1684 gtk_widget_show (button);
1685 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1686 gtk_widget_set_usize (button, 60, -2);
1688 button = gtk_button_new_with_label ("Delete");
1689 gtk_widget_show (button);
1690 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1691 gtk_widget_set_usize (button, 60, -2);
1693 label = gtk_label_new ("Groups");
1694 gtk_widget_show (label);
1695 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
1697 inspector_mode = W_ENTITY;
1698 // gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
1701 load_pixmap ("grouptree1.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[0], &tree_masks[0]);
1702 load_pixmap ("grouptree2.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[1], &tree_masks[1]);
1703 load_pixmap ("grouptree3.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[2], &tree_masks[2]);
1704 load_pixmap ("grouptree4.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[3], &tree_masks[3]);
1705 load_pixmap ("grouptree5.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[4], &tree_masks[4]);
1706 load_pixmap ("grouptree6.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[5], &tree_masks[5]);
1707 load_pixmap ("grouptree7.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[6], &tree_masks[6]);
1711 g_signal_connect (G_OBJECT (notebook), "switch_page", G_CALLBACK (switch_page), dlg);