-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
-*/\r
-\r
-//\r
-// Floating dialog that contains a notebook with at least Entities and Group tabs\r
-// I merged the 2 MS Windows dialogs in a single class\r
-//\r
-// Leonardo Zide (leo@lokigames.com)\r
-//\r
-\r
-#ifndef _WIN32\r
- #include <unistd.h>\r
-#endif\r
-#include <gdk/gdkkeysyms.h>\r
-#include "stdafx.h"\r
-#include "groupdialog.h"\r
-\r
-GtkWidget* EntWidgets[EntLast];\r
-GtkListStore* g_entlist_store;\r
-GtkListStore* g_entprops_store;\r
-int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE\r
-qboolean multiple_entities;\r
-// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=17\r
-qboolean disable_spawn_get = false;\r
-entity_t *edit_entity;\r
-/*\r
-static GdkPixmap *tree_pixmaps[7];\r
-static GdkBitmap *tree_masks[7];\r
-*/\r
-#define IMG_PATCH 0\r
-#define IMG_BRUSH 1\r
-#define IMG_GROUP 2\r
-#define IMG_ENTITY 3\r
-#define IMG_ENTITYGROUP 4\r
-#define IMG_MODEL 5\r
-#define IMG_SCRIPT 6\r
-\r
-// misc group support\r
-#define MAX_GROUPS 4096\r
-#define GROUP_DELIMETER '@'\r
-#define GROUPNAME "QER_Group_%i"\r
-\r
-GroupDlg g_wndGroup;\r
-GroupDlg *g_pGroupDlg = &g_wndGroup;\r
-\r
-// group_t are loaded / saved through "group_info" entities\r
-// they hold epairs for group settings and additionnal access info (tree nodes)\r
-group_t *g_pGroups = NULL;\r
-\r
-// the number of active spawnflags\r
-static int spawnflag_count;\r
-// table: index, match spawnflag item to the spawnflag index (i.e. which bit)\r
-static int spawn_table[MAX_FLAGS];\r
-// we change the layout depending on how many spawn flags we need to display\r
-// the table is a 4x4 in which we need to put the comment box EntWidgets[EntComment] and the spawn flags..\r
-static GtkWidget *LayoutTable;\r
-// 0: none of them are hooked\r
-// 1: only the text, 2: text and four checks, 3: text and 8 checks\r
-static int widget_state = 0;\r
-\r
-static void entity_check (GtkWidget *widget, gpointer data);\r
-\r
-// =============================================================================\r
-// Global functions\r
-\r
-/*\r
-===============================================================\r
-\r
-ENTITY WINDOW\r
-\r
-===============================================================\r
-*/\r
-\r
-void FillClassList ()\r
-{\r
- GtkListStore* store = g_entlist_store;\r
-\r
- gtk_list_store_clear(store);\r
-\r
- for (eclass_t* e = eclass ; e ; e = e->next)\r
- {\r
- GtkTreeIter iter;\r
- gtk_list_store_append(store, &iter);\r
- gtk_list_store_set(store, &iter, 0, e->name, 1, e, -1);\r
- } \r
-}\r
-\r
-// SetKeyValuePairs\r
-//\r
-// Reset the key/value (aka property) listbox and fill it with the \r
-// k/v pairs from the entity being edited.\r
-//\r
-\r
-void SetKeyValuePairs (bool bClearMD3)\r
-{\r
- GtkListStore* store = g_entprops_store;\r
-\r
- gtk_list_store_clear(store);\r
-\r
- if (edit_entity == NULL)\r
- {\r
- // if there's no entity, then display no key/values\r
- return;\r
- }\r
-\r
- // save current key/val pair around filling epair box\r
- // row_select wipes it and sets to first in list\r
- Str strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));\r
- Str strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));\r
-\r
-\r
- // Walk through list and add pairs\r
- for(epair_t* epair = edit_entity->epairs ; epair ; epair = epair->next)\r
- {\r
- GtkTreeIter iter;\r
- gtk_list_store_append(store, &iter);\r
- gtk_list_store_set(store, &iter, 0, epair->key, 1, epair->value, -1);\r
- }\r
-\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), strKey.GetBuffer());\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), strVal.GetBuffer());\r
-\r
- Sys_UpdateWindows(W_CAMERA | W_XY);\r
-}\r
-\r
-// SetSpawnFlags\r
-// \r
-// Update the checkboxes to reflect the flag state of the entity\r
-//\r
-void SetSpawnFlags(void)\r
-{\r
- int f, i, v;\r
-\r
- disable_spawn_get = true;\r
-\r
- f = atoi(ValueForKey (edit_entity, "spawnflags"));\r
- for (i=0 ; i<spawnflag_count ; i++)\r
- {\r
- v = !!(f&(1<<spawn_table[i]));\r
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), v);\r
- }\r
- // take care of the remaining ones\r
- for (i=spawnflag_count ; i<MAX_FLAGS ; i++)\r
- {\r
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), FALSE);\r
- }\r
-\r
- disable_spawn_get = false;\r
-}\r
-\r
-// GetSpawnFlags\r
-// \r
-// Update the entity flags to reflect the state of the checkboxes\r
-//\r
-// NOTE: this function had a tendency to add "spawnflags" "0" on most entities\r
-// if this wants to set spawnflags to zero, remove the key\r
-\r
-void GetSpawnFlags(void)\r
-{\r
- int f, i, v;\r
- char sz[32];\r
-\r
- f = 0;\r
- for (i=0 ; i<spawnflag_count ; i++)\r
- {\r
- v = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]));\r
- f |= v<<spawn_table[i];\r
- }\r
-\r
- if (f==0)\r
- {\r
- // remove all "spawnflags" keys\r
- if (multiple_entities)\r
- {\r
- brush_t *b;\r
- \r
- for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
- DeleteKey (b->owner, "spawnflags");\r
- }\r
- else\r
- DeleteKey (edit_entity, "spawnflags");\r
- }\r
- else\r
- { \r
- sprintf (sz, "%i", f); \r
- if (multiple_entities)\r
- {\r
- brush_t *b;\r
- \r
- for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
- SetKeyValue(b->owner, "spawnflags", sz);\r
- }\r
- else\r
- SetKeyValue (edit_entity, "spawnflags", sz);\r
- }\r
- SetKeyValuePairs ();\r
-}\r
-\r
-//#define DBG_UPDATESEL\r
-\r
-// UpdateSel\r
-//\r
-// Update the listbox, checkboxes and k/v pairs to reflect the new selection\r
-// iIndex is the index in the list box with the class name, -1 if not found\r
-bool UpdateSel(int iIndex, eclass_t *pec)\r
-{\r
- int i, next_state;\r
- brush_t *b;\r
-\r
- // syndrom of crappy code, we may get into stack overflowing crap with this function and Gtk \r
- // if we play with the list of entity classes\r
- // using a static flag to prevent recursion\r
- static bool bBlockUpdate = false;\r
-\r
- if (bBlockUpdate)\r
- return FALSE; // NOTE TTimo wtf is the return value for anyway?\r
-\r
-#ifdef DBG_UPDATESEL\r
- Sys_FPrintf(SYS_WRN, "UpdateSel\n");\r
-#endif\r
-\r
- if (selected_brushes.next == &selected_brushes)\r
- {\r
- edit_entity = world_entity;\r
- multiple_entities = false;\r
- }\r
- else\r
- {\r
- edit_entity = selected_brushes.next->owner;\r
- for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next)\r
- {\r
- if (b->owner != edit_entity)\r
- {\r
- multiple_entities = true;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (iIndex != -1)\r
- {\r
-#ifdef DBG_UPDATESEL\r
- Sys_FPrintf(SYS_WRN,"Setting focus_row to %d\n", iIndex);\r
-#endif\r
- bBlockUpdate = true;\r
-\r
- GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);\r
- GtkTreePath* path = gtk_tree_path_new();\r
- gtk_tree_path_append_index(path, iIndex);\r
- gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);\r
- gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);\r
- gtk_tree_path_free(path);\r
-\r
- bBlockUpdate = false;\r
- }\r
-\r
- if (pec == NULL)\r
- return TRUE;\r
-\r
- // Set up the description\r
- {\r
- GtkTextBuffer* buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(EntWidgets[EntComment]));\r
- gtk_text_buffer_set_text (buffer, pec->comments, -1);\r
- }\r
-\r
- spawnflag_count = 0;\r
-\r
- // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are\r
- for (i=0 ; i<MAX_FLAGS ; i++)\r
- {\r
- if (pec->flagnames[i] && pec->flagnames[i][0] != 0 && strcmp(pec->flagnames[i],"-"))\r
- {\r
- spawn_table[spawnflag_count] = i;\r
- spawnflag_count++;\r
- }\r
- }\r
-\r
- // what's new widget state\r
- if (spawnflag_count==0)\r
- next_state = 1;\r
- else if (spawnflag_count<=4)\r
- next_state = 2;\r
- else if (spawnflag_count<=8)\r
- next_state = 3;\r
- else if (spawnflag_count<=12)\r
- next_state = 4;\r
- else\r
- next_state = 5;\r
- widget_state = next_state;\r
- static int last_count = 0;\r
-\r
- // disable all remaining boxes\r
- // NOTE: these boxes might not even be on display\r
- for (i = 0; i < last_count; i++)\r
- {\r
- GtkWidget* widget = EntWidgets[EntCheck1+i];\r
- gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), " ");\r
- gtk_widget_hide (widget);\r
- gtk_widget_ref (widget);\r
- gtk_container_remove (GTK_CONTAINER (LayoutTable), widget);\r
- }\r
- last_count = spawnflag_count;\r
-\r
- for (i=0 ; i<spawnflag_count ; i++)\r
- {\r
- GtkWidget* widget = EntWidgets[EntCheck1+i];\r
- gtk_widget_show (widget);\r
-\r
- Str str;\r
- str = pec->flagnames[spawn_table[i]];\r
- str.MakeLower ();\r
-\r
-// gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,\r
- gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- gtk_widget_unref (widget);\r
-\r
- gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), str.GetBuffer ());\r
- }\r
-\r
- SetSpawnFlags();\r
-\r
- SetKeyValuePairs();\r
-\r
- return TRUE;\r
-}\r
-\r
-bool UpdateEntitySel(eclass_t *pec)\r
-{\r
-#ifdef DBG_UPDATESEL\r
- Sys_FPrintf(SYS_WRN, "UpdateEntitySel\n");\r
-#endif\r
-\r
- GtkTreeModel* model = GTK_TREE_MODEL(g_entlist_store);\r
- GtkTreeIter iter;\r
- unsigned int i = 0;\r
- for(gboolean good = gtk_tree_model_get_iter_first(model, &iter); good != FALSE; good = gtk_tree_model_iter_next(model, &iter))\r
- {\r
- char* text;\r
- gtk_tree_model_get(model, &iter, 0, &text, -1);\r
- if (strcmp (text, pec->name) == 0)\r
- {\r
-#ifdef DBG_UPDATESEL\r
- Sys_FPrintf(SYS_WRN, "found a match: %d %s\n", i, pec->name);\r
-#endif\r
- return UpdateSel (i, pec);\r
- }\r
- g_free(text);\r
- ++i;\r
- }\r
- return UpdateSel (-1, pec);\r
-}\r
-\r
-// CreateEntity\r
-//\r
-// Creates a new entity based on the currently selected brush and entity type.\r
-//\r
-\r
-void CreateEntity(void)\r
-{\r
- GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);\r
-\r
- // check to make sure we have a brush\r
- if (selected_brushes.next == &selected_brushes)\r
- {\r
- gtk_MessageBox(g_pParentWnd->m_pWidget, "You must have a selected brush to create an entity", "info");\r
- return;\r
- }\r
-\r
- // find out what type of entity we are trying to create\r
- GtkTreeModel* model;\r
- GtkTreeIter iter;\r
- if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE)\r
- {\r
- gtk_MessageBox (g_pParentWnd->m_pWidget, "You must have a selected class to create an entity", "info");\r
- return;\r
- }\r
-\r
- char* text;\r
- gtk_tree_model_get(model, &iter, 0, &text, -1);\r
- CreateEntityFromName(text, vec3_origin);\r
- g_free(text);\r
-\r
- if (selected_brushes.next == &selected_brushes)\r
- edit_entity = world_entity;\r
- else\r
- edit_entity = selected_brushes.next->owner;\r
-\r
- SetKeyValuePairs();\r
- Select_Deselect ();\r
- Select_Brush (edit_entity->brushes.onext);\r
- Sys_UpdateWindows(W_ALL);\r
-}\r
-\r
-/*\r
-===============\r
-AddProp\r
-\r
-===============\r
-*/\r
-void AddProp()\r
-{\r
- if (edit_entity == NULL)\r
- return;\r
-\r
- // Get current selection text\r
- const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));\r
- const char* value = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));\r
-\r
-\r
- // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity\r
- if (!strcmp(key, "classname") && !strcmp(value, "worldspawn"))\r
- {\r
- gtk_MessageBox(g_pParentWnd->m_pWidget, "Cannot change \"classname\" key back to worldspawn.", NULL, MB_OK );\r
- return;\r
- }\r
-\r
-\r
- // RR2DO2: we don't want spaces in entity keys\r
- if (strstr( key, " " ))\r
- {\r
- gtk_MessageBox(g_pParentWnd->m_pWidget, "No spaces are allowed in entity keys.", NULL, MB_OK );\r
- return;\r
- }\r
-\r
- if (multiple_entities)\r
- {\r
- brush_t *b;\r
-\r
- for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
- SetKeyValue(b->owner, key, value);\r
- }\r
- else\r
- SetKeyValue(edit_entity, key, value);\r
-\r
- // refresh the prop listbox\r
- SetKeyValuePairs(); \r
-\r
-\r
-#ifdef USEPLUGINENTITIES\r
- // if it's a plugin entity, perhaps we need to update some drawing parameters\r
- // NOTE: perhaps moving this code to a seperate func would help if we need it in other places\r
- // TODO: we need to call some update func in the IPluginEntity in case model name changes etc.\r
- // ( for the moment only bounding brush is updated ), see UpdateModelBrush in Ritual's Q3Radiant\r
- if (edit_entity->eclass->nShowFlags & ECLASS_PLUGINENTITY)\r
- {\r
- vec3_t mins, maxs;\r
- edit_entity->pPlugEnt->GetBounds( mins, maxs );\r
- // replace old bounding brush by newly computed one\r
- // NOTE: this part is similar to Entity_BuildModelBrush in Ritual's Q3Radiant, it can be\r
- // usefull moved into a seperate func\r
- brush_t *b,*oldbrush;\r
- if (edit_entity->brushes.onext != &edit_entity->brushes)\r
- oldbrush = edit_entity->brushes.onext;\r
- b = Brush_Create (mins, maxs, &edit_entity->eclass->texdef);\r
- Entity_LinkBrush (edit_entity, b);\r
- Brush_Build( b, true );\r
- Select_Deselect();\r
- Brush_AddToList (edit_entity->brushes.onext, &selected_brushes);\r
- if (oldbrush)\r
- Brush_Free( oldbrush );\r
- }\r
-#endif // USEPLUGINENTITIES\r
-}\r
-\r
-/*\r
-===============\r
-DelProp\r
-\r
-===============\r
-*/\r
-void DelProp(void)\r
-{\r
- if (edit_entity == NULL)\r
- return;\r
-\r
- // Get current selection text\r
- const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));\r
-\r
- if (multiple_entities)\r
- {\r
- brush_t *b;\r
-\r
- for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)\r
- DeleteKey(b->owner, key);\r
- }\r
- else\r
- DeleteKey(edit_entity, key);\r
-\r
- // refresh the prop listbox\r
- SetKeyValuePairs();\r
-}\r
-\r
-void ResetEntity ()\r
-{\r
- epair_t *pep;\r
- int i;\r
-\r
- if (edit_entity == NULL)\r
- return;\r
-\r
- if (multiple_entities)\r
- {\r
- brush_t *b;\r
-\r
- for (b=selected_brushes.next; b != &selected_brushes; b=b->next)\r
- for (pep = b->owner->epairs; pep; )\r
- {\r
- if (strcmp (pep->key, "classname") != 0)\r
- {\r
- DeleteKey (b->owner, pep->key);\r
- pep = b->owner->epairs;\r
- }\r
- else\r
- pep = pep->next;\r
- }\r
- }\r
- else\r
- for (pep = edit_entity->epairs; pep; )\r
- {\r
- if (strcmp (pep->key, "classname") != 0)\r
- {\r
- DeleteKey (edit_entity, pep->key);\r
- pep = edit_entity->epairs;\r
- }\r
- else\r
- pep = pep->next;\r
- }\r
-\r
- // refresh the dialog\r
- SetKeyValuePairs ();\r
- for (i = EntCheck1; i <= EntCheck16; i++)\r
- gtk_signal_handler_block_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);\r
- SetSpawnFlags ();\r
- for (i = EntCheck1; i <= EntCheck16; i++)\r
- gtk_signal_handler_unblock_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);\r
-}\r
-\r
-bool GetSelectAllCriteria(CString &strKey, CString &strVal)\r
-{\r
- GtkTreeModel* model;\r
- GtkTreeIter iter;\r
- if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(EntWidgets[EntProps])), &model, &iter)\r
- && (inspector_mode == W_ENTITY)\r
- && GTK_WIDGET_VISIBLE (g_pGroupDlg->m_pWidget))\r
- {\r
- strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));\r
- strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-void AssignSound()\r
-{\r
- char buffer[NAME_MAX];\r
-\r
- strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());\r
- strcat (buffer, "sound/");\r
-\r
- if( access(buffer, R_OK) != 0 )\r
- {\r
- // just go to fsmain\r
- strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());\r
- strcat (buffer, "/");\r
- }\r
-\r
- const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, "Open Wav File", buffer, "sound");\r
- if (filename != NULL)\r
- {\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "noise");\r
- char *aux = vfsExtractRelativePath (filename);\r
- CString str;\r
- if (aux)\r
- str = aux;\r
- else\r
- {\r
- Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");\r
- str = filename;\r
- }\r
-\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer()); \r
- AddProp();\r
- }\r
-}\r
-\r
-void AssignModel()\r
-{\r
- char buffer[NAME_MAX];\r
-\r
- strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());\r
- strcat (buffer, "models/");\r
-\r
- if( access(buffer, R_OK) != 0 )\r
- {\r
- // just go to fsmain\r
- strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());\r
- strcat (buffer, "/");\r
- }\r
-\r
- const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, "Open Model", buffer, MODEL_MAJOR);\r
- if (filename != NULL)\r
- {\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "model");\r
- // use VFS to get the correct relative path\r
- char *aux = vfsExtractRelativePath (filename);\r
- CString str;\r
- if (aux)\r
- str = aux;\r
- else\r
- {\r
- Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");\r
- str = filename;\r
- }\r
-\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer()); \r
- AddProp();\r
- edit_entity->brushes.onext->bModelFailed = false;\r
- }\r
-}\r
-\r
-/*\r
-==============\r
-SetInspectorMode\r
-==============\r
-*/\r
-void SetInspectorMode(int iType)\r
-{\r
- if (iType == W_GROUP)\r
- gtk_MessageBox(g_pParentWnd->m_pWidget, "Brush grouping is not functional yet", NULL, MB_OK | MB_ICONWARNING );\r
-\r
- if (!g_pParentWnd->FloatingGroupDialog() &&\r
- (iType == W_TEXTURE || iType == W_CONSOLE))\r
- return;\r
-\r
- // Is the caller asking us to cycle to the next window?\r
- if (iType == -1)\r
- {\r
- if (inspector_mode == W_ENTITY)\r
- iType = W_TEXTURE;\r
- else if (inspector_mode == W_TEXTURE)\r
- iType = W_CONSOLE;\r
- else if (inspector_mode == W_CONSOLE)\r
- iType = W_GROUP;\r
- else\r
- iType = W_ENTITY;\r
- } \r
-\r
- switch(iType)\r
- {\r
- case W_ENTITY:\r
- // entity is always first in the inspector\r
- gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Entities");\r
- gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 0);\r
- break;\r
-\r
- case W_TEXTURE:\r
- g_pParentWnd->GetTexWnd()->FocusEdit();\r
- gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Textures");\r
- if (g_pParentWnd->FloatingGroupDialog())\r
- gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);\r
- break;\r
-\r
- case W_CONSOLE:\r
- gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Console");\r
- if (g_pParentWnd->FloatingGroupDialog())\r
- gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 2);\r
- break;\r
-\r
- case W_GROUP:\r
- if (g_pParentWnd->FloatingGroupDialog())\r
- gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 3);\r
- else\r
- gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-void Group_Add(entity_t *e)\r
-{\r
- /*\r
- group_t *g = (group_t*)qmalloc(sizeof(group_t));\r
- g->epairs = e->epairs;\r
- g->next = NULL;\r
- e->epairs = NULL;\r
-\r
- // create a new group node\r
- char *text = ValueForKey(g->epairs, "group");\r
- g->itemOwner = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_wndGroup.m_hWorld, NULL, &text, 0,\r
- tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],\r
- tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], TRUE, TRUE);\r
- g->next = g_pGroups;\r
- g_pGroups = g;\r
- */\r
-}\r
-/*\r
-group_t* Group_Alloc(char *name)\r
-{\r
- group_t *g = (group_t*)qmalloc(sizeof(group_t));\r
- SetKeyValue( g->epairs, "group", name );\r
- return g;\r
-}\r
-\r
-group_t* Group_ForName(const char * name)\r
-{\r
- group_t *g = g_pGroups;\r
- while (g != NULL)\r
- {\r
- if (strcmp( ValueForKey(g->epairs,"group"), name ) == 0)\r
- break;\r
- g = g->next;\r
- }\r
- return g;\r
-}\r
-\r
-void Group_AddToItem(brush_t *b, GtkCTreeNode* item)\r
-{\r
- int nImage = IMG_BRUSH;\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
- const char *pName = NULL;\r
- // const char *pNamed = Brush_GetKeyValue(b, "name");\r
- \r
- if (!b->owner || (b->owner == world_entity))\r
- {\r
- if (b->patchBrush) \r
- {\r
- pName = "Generic Patch";\r
- nImage = IMG_PATCH;\r
- } \r
- else \r
- {\r
- pName = "Generic Brush";\r
- nImage = IMG_BRUSH;\r
- }\r
- } \r
- else \r
- {\r
- pName = b->owner->eclass->name;\r
- if (b->owner->eclass->fixedsize) \r
- {\r
- nImage = IMG_ENTITY;\r
- } \r
- else \r
- {\r
- nImage = IMG_ENTITYGROUP;\r
- }\r
- }\r
-\r
- GtkCTreeNode *newItem;\r
- int i = (b->patchBrush) ? IMG_PATCH : IMG_BRUSH;\r
- newItem = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), item, NULL, (gchar**)&pName, 0,\r
- tree_pixmaps[i], tree_masks[i], tree_pixmaps[i],\r
- tree_masks[i], TRUE, TRUE);\r
- gtk_ctree_node_set_row_data (GTK_CTREE (g_wndGroup.m_pTree), newItem, b);\r
- b->itemOwner = newItem;\r
-}\r
-*/\r
-void Group_RemoveBrush(brush_t *b)\r
-{\r
- /*\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
- if (b->itemOwner)\r
- {\r
- gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);\r
- b->itemOwner = NULL;\r
- }\r
- DeleteKey(b->epairs, "group");\r
- */\r
-}\r
-/*\r
-void Group_AddToWorld(brush_t *b)\r
-{\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
- GtkCTreeNode *parent = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);\r
- Group_AddToItem(b, parent);\r
-}\r
-*/\r
-void Group_AddToProperGroup(brush_t *b)\r
-{\r
- /*\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
-\r
- // NOTE: we do a local copy of the "group" key because it gets erased by Group_RemoveBrush\r
- const char *pGroup = Brush_GetKeyValue(b, "group");\r
- // remove the entry in the tree if there's one\r
- if (b->itemOwner)\r
- {\r
- gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);\r
- b->itemOwner = NULL;\r
- }\r
-\r
- if (*pGroup != 0)\r
- {\r
- // find the item\r
- group_t *g = Group_ForName(pGroup);\r
- if (g)\r
- Group_AddToItem(b, g->itemOwner);\r
-#ifdef _DEBUG\r
- else\r
- Sys_Printf("WARNING: unexpected Group_ForName not found in Group_AddToProperGroup\n");\r
-#endif\r
- }\r
- else\r
- {\r
- Group_AddToWorld(b);\r
- }\r
- */\r
-}\r
-/*\r
-void Group_AddToSelected(brush_t *b)\r
-{\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
- GtkCTreeNode *item;\r
- item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), GTK_CLIST (g_pGroupDlg->m_pTree)->focus_row);\r
- if (item == NULL)\r
- {\r
- item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);\r
- }\r
- Group_AddToItem(b, item);\r
-}\r
-*/\r
-/*\r
-void Group_Save(FILE *f)\r
-{\r
- group_t *g = g_pGroups;\r
- while (g)\r
- {\r
- fprintf(f,"{\n\"classname\" \"group_info\"\n\"group\" \"%s\"\n}\n", ValueForKey( g->epairs, "group" ));\r
- g = g->next;\r
- }\r
-}\r
-*/\r
-\r
-void Group_Init()\r
-{\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
- // start by cleaning everything\r
- // clean the groups\r
- //++timo FIXME: we leak, delete the groups on the way (I don't have time to do it now)\r
-#ifdef _DEBUG\r
- Sys_Printf("TODO: fix leak in Group_Init\n");\r
-#endif\r
- group_t *g = g_pGroups;\r
- while (g)\r
- {\r
- epair_t *ep,*enext;\r
- for (ep = g->epairs ; ep ; ep=enext )\r
- {\r
- enext = ep->next;\r
- free (ep->key);\r
- free (ep->value);\r
- free (ep);\r
- }\r
- g = g->next;\r
- }\r
- /*\r
- GtkCTreeNode *world;\r
- char *text = "World";\r
- g_pGroups = NULL;\r
- gtk_clist_clear (GTK_CLIST (g_wndGroup.m_pTree));\r
- world = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), NULL, NULL, &text, 0,\r
- tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], tree_pixmaps[IMG_GROUP],\r
- tree_masks[IMG_GROUP], FALSE, TRUE);\r
- */\r
- // walk through all the brushes, remove the itemOwner key and add them back where they belong\r
- brush_t *b;\r
- for (b = active_brushes.next; b != &active_brushes; b = b->next)\r
- {\r
- b->itemOwner = NULL;\r
- Group_AddToProperGroup(b);\r
- }\r
- for (b = selected_brushes.next ; b != &selected_brushes ; b = b->next)\r
- {\r
- b->itemOwner = NULL;\r
- Group_AddToProperGroup(b);\r
- }\r
-}\r
-/*\r
-// scan through world_entity for groups in this map?\r
-// we use GROUPNAME "QER_group_%i" to look for existing groups and their naming\r
-//++timo FIXME: is this actually needed for anything?\r
-void Group_GetListFromWorld(GSList **pArray)\r
-{\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
-\r
- if (world_entity == NULL)\r
- {\r
- return;\r
- }\r
-\r
- char cBuff[1024];\r
- for (int i =0; i < MAX_GROUPS; i++)\r
- {\r
- sprintf(cBuff, GROUPNAME, i);\r
- char *pGroup = ValueForKey(world_entity, cBuff);\r
- if (pGroup && strlen(pGroup) > 0)\r
- {\r
- *pArray = g_slist_append (*pArray, g_strdup (pGroup));\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
-}\r
-\r
-void Group_RemoveListFromWorld()\r
-{\r
- if (!g_qeglobals.m_bBrushPrimitMode)\r
- {\r
- return;\r
- }\r
- GSList* array = NULL;\r
- Group_GetListFromWorld(&array);\r
-\r
- while (array)\r
- {\r
- DeleteKey(world_entity, (char*)array->data);\r
- g_free (array->data);\r
- array = g_slist_remove (array, array->data);\r
- }\r
-}\r
-\r
-int CountChar(const char *p, char c)\r
-{\r
- int nCount = 0;\r
- int nLen = strlen(p)-1;\r
- while (nLen-- >= 0)\r
- {\r
- if (p[nLen] == c)\r
- {\r
- nCount++;\r
- }\r
- }\r
- return nCount;\r
-}\r
-*/\r
-// =============================================================================\r
-// callbacks\r
-\r
-static void eclasslist_selection_changed(GtkTreeSelection* selection, gpointer data)\r
-{\r
- GtkTreeModel* model;\r
- GtkTreeIter selected;\r
- // no world entity, we are not ready yet\r
- // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=917\r
- if( !world_entity ) {\r
- return; \r
- }\r
- if(gtk_tree_selection_get_selected(selection, &model, &selected))\r
- {\r
- eclass_t* eclass;\r
- gtk_tree_model_get(model, &selected, 1, &eclass, -1);\r
- if(eclass != NULL)\r
- {\r
- GtkTreePath* path = gtk_tree_model_get_path(model, &selected);\r
- UpdateSel(gtk_tree_path_get_indices(path)[0], eclass);\r
- gtk_tree_path_free(path);\r
- }\r
- }\r
-}\r
-\r
-static gint eclasslist_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)\r
-{\r
- if (event->type == GDK_2BUTTON_PRESS)\r
- {\r
- CreateEntity ();\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-static gint eclasslist_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
-{\r
- unsigned int code = gdk_keyval_to_upper (event->keyval);\r
-\r
- if (event->keyval == GDK_Return)\r
- {\r
- CreateEntity ();\r
- return TRUE;\r
- }\r
-\r
- // select the entity that starts with the key pressed\r
- if (code <= 'Z' && code >= 'A')\r
- {\r
- GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);\r
- GtkTreeModel* model;\r
- GtkTreeIter iter;\r
- if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE\r
- || gtk_tree_model_iter_next(model, &iter) == FALSE)\r
- {\r
- gtk_tree_model_get_iter_first(model, &iter);\r
- }\r
-\r
- for(unsigned int count = gtk_tree_model_iter_n_children(model, NULL); count > 0; --count)\r
- {\r
- char* text;\r
- gtk_tree_model_get(model, &iter, 0, &text, -1);\r
-\r
- if (toupper (text[0]) == (int)code)\r
- {\r
- GtkTreePath* path = gtk_tree_model_get_path(model, &iter);\r
- gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);\r
- gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);\r
- gtk_tree_path_free(path);\r
- count = 1;\r
- }\r
-\r
- g_free(text);\r
-\r
- if(gtk_tree_model_iter_next(model, &iter) == FALSE)\r
- gtk_tree_model_get_iter_first(model, &iter);\r
- }\r
-\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-static void proplist_selection_changed(GtkTreeSelection* selection, gpointer data)\r
-{\r
- // find out what type of entity we are trying to create\r
- GtkTreeModel* model;\r
- GtkTreeIter iter;\r
- if(gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)\r
- {\r
- return;\r
- }\r
-\r
- char* key;\r
- char* val;\r
- gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1);\r
-\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), key);\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), val);\r
-\r
- g_free(key);\r
- g_free(val);\r
-}\r
-\r
-static void entity_check (GtkWidget *widget, gpointer data)\r
-{\r
- if( !disable_spawn_get )\r
- GetSpawnFlags();\r
-}\r
-\r
-static void entitylist_angle (GtkWidget *widget, gpointer data)\r
-{\r
- SetKeyValue (edit_entity, "angle", (char*)data);\r
- SetKeyValuePairs ();\r
-}\r
-\r
-static gint entityentry_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
-{\r
- if (event->keyval == GDK_Tab)\r
- {\r
- if (widget == EntWidgets[EntKeyField])\r
- {\r
- //gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");\r
- gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);\r
- }\r
- else\r
- gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntKeyField]);\r
-\r
- return TRUE;\r
- }\r
- else if (event->keyval == GDK_Return)\r
- {\r
- if (widget == EntWidgets[EntKeyField])\r
- {\r
- gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");\r
- gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);\r
- }\r
- else\r
- {\r
- AddProp ();\r
- }\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-/*\r
-// add a new group, put all selected brushes into the group\r
-static void groupdlg_add (GtkWidget *widget, gpointer data)\r
-{\r
- char* name = DoNameDlg ("New Group");\r
-\r
- if (name != NULL)\r
- {\r
- // create a new group node \r
- GtkCTreeNode *item;\r
- item = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_pGroupDlg->m_hWorld, NULL, &name, 0,\r
- tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],\r
- tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], FALSE, TRUE);\r
-\r
- // create a new group\r
- group_t *g = Group_Alloc (name);\r
- g->itemOwner = item;\r
- g->next = g_pGroups;\r
- g_pGroups = g;\r
-\r
- // now add the selected brushes\r
- // NOTE: it would be much faster to give the group_t for adding\r
- // but Select_AddToGroup is the standard way for all other cases\r
- Select_AddToGroup (name);\r
- g_free (name);\r
- }\r
-}\r
-*/\r
-static void switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)\r
-{\r
- char *text;\r
- gtk_label_get(GTK_LABEL(gtk_notebook_get_tab_label(notebook, gtk_notebook_get_nth_page(notebook, page_num))), &text);\r
- gtk_window_set_title (GTK_WINDOW (data), text);\r
-\r
- gpointer item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_misc_selectentitycolor");\r
-\r
- if (g_pParentWnd->FloatingGroupDialog())\r
- {\r
- switch (page_num)\r
- {\r
- case 0: inspector_mode = W_ENTITY; break;\r
- case 1: inspector_mode = W_TEXTURE; break;\r
- case 2: inspector_mode = W_CONSOLE; break;\r
- default: inspector_mode = W_GROUP; break;\r
- }\r
- }\r
- else\r
- {\r
- if (page_num == 0)\r
- inspector_mode = W_ENTITY;\r
- else\r
- inspector_mode = W_GROUP;\r
- }\r
- \r
- if (inspector_mode == W_ENTITY)\r
- gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);\r
- else\r
- gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);\r
-}\r
-\r
-// =============================================================================\r
-// GroupDlg class\r
-\r
-// NOTE: when a key is hit with group window focused, we catch in this handler but it gets propagated to mainframe too\r
-// therefore the message will be intercepted and used as a ID_SELECTION_DESELECT\r
-static gint OnDialogKey (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
-{\r
-#ifdef DBG_PI\r
- Sys_Printf("OnDialogKey\n");\r
-#endif\r
- if ((event->keyval == GDK_Escape) && (g_pParentWnd->CurrentStyle() != MainFrame::eFloating))\r
- {\r
- // toggle off the group view (whatever part of it is currently displayed)\r
- // this used to be done with a g_pParentWnd->OnViewEntity(); but it had bad consequences\r
- // http://fenris.lokigames.com/show_bug.cgi?id=2773\r
- widget_delete_hide (g_qeglobals_gui.d_entity);\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-GroupDlg::GroupDlg ()\r
-{\r
- m_pWidget = NULL;\r
- m_hWorld = NULL;\r
-}\r
-\r
-#ifdef _WIN32\r
-extern void PositionWindowOnPrimaryScreen(window_position_t& position);\r
-#endif\r
-\r
-void GroupDlg::Create ()\r
-{\r
- if (m_pWidget != NULL)\r
- return;\r
-\r
- GtkWidget* dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);\r
-\r
-#ifdef _WIN32\r
- if( g_PrefsDlg.m_bStartOnPrimMon ) {\r
- PositionWindowOnPrimaryScreen( g_PrefsDlg.mWindowInfo.posEntityWnd );\r
- }\r
-#endif\r
- load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posEntityWnd);\r
-\r
- gtk_window_set_title (GTK_WINDOW (dlg), "Entities");\r
- gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (widget_delete_hide), NULL);\r
- // catch 'Esc'\r
- gtk_signal_connect (GTK_OBJECT (dlg), "key_press_event", GTK_SIGNAL_FUNC (OnDialogKey), NULL);\r
- gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pParentWnd->m_pWidget));\r
- g_qeglobals_gui.d_entity = dlg;\r
-\r
- {\r
- GtkWidget* notebook = gtk_notebook_new ();\r
- gtk_widget_show (notebook);\r
- gtk_container_add (GTK_CONTAINER (dlg), notebook);\r
- gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);\r
- m_pNotebook = notebook;\r
-\r
- {\r
- GtkWidget* vbox = gtk_vbox_new (FALSE, 2);\r
- gtk_widget_show (vbox);\r
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);\r
-\r
- {\r
- GtkWidget* label = gtk_label_new ("Entities");\r
- gtk_widget_show (label);\r
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);\r
- }\r
-\r
- {\r
- GtkWidget* split1 = gtk_vpaned_new ();\r
- gtk_box_pack_start (GTK_BOX (vbox), split1, TRUE, TRUE, 0);\r
- gtk_widget_show (split1);\r
- \r
- {\r
- GtkWidget* split2 = gtk_vpaned_new ();\r
- gtk_paned_add1 (GTK_PANED (split1), split2);\r
- gtk_widget_show (split2);\r
-\r
- g_object_set_data (G_OBJECT (dlg), "split1", split1);\r
- g_object_set_data (G_OBJECT (dlg), "split2", split2);\r
-\r
- {\r
- GtkWidget* vbox2 = gtk_vbox_new (FALSE, 2);\r
- gtk_widget_show (vbox2);\r
- gtk_paned_pack2 (GTK_PANED (split1), vbox2, FALSE, FALSE);\r
-\r
- {\r
- GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);\r
- gtk_widget_show (scr);\r
- gtk_paned_add1 (GTK_PANED (split2), scr);\r
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);\r
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);\r
-\r
- {\r
- GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);\r
-\r
- GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));\r
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);\r
- g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(eclasslist_button_press), NULL);\r
- g_signal_connect(G_OBJECT(view), "key_press_event", G_CALLBACK(eclasslist_keypress), this);\r
-\r
- {\r
- GtkCellRenderer* renderer = gtk_cell_renderer_text_new();\r
- GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, NULL);\r
- gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);\r
- }\r
-\r
- {\r
- GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));\r
- g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(eclasslist_selection_changed), dlg);\r
- }\r
-\r
- gtk_widget_show(view);\r
-\r
- gtk_container_add(GTK_CONTAINER (scr), view);\r
- \r
- g_object_unref(G_OBJECT(store));\r
- EntWidgets[EntList] = view;\r
- g_entlist_store = store;\r
- }\r
- }\r
-\r
- {\r
- GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);\r
- gtk_widget_show (scr);\r
- gtk_paned_add2 (GTK_PANED (split2), scr);\r
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);\r
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);\r
-\r
- {\r
- GtkWidget* text = gtk_text_view_new();\r
- gtk_widget_set_size_request(text, 0, -1); // allow shrinking\r
- gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);\r
- gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);\r
- gtk_widget_show (text);\r
- gtk_container_add (GTK_CONTAINER (scr), text);\r
- EntWidgets[EntComment] = text;\r
- }\r
- }\r
-\r
- {\r
- // Spawnflags (4 colums wide max, or window gets too wide.)\r
- GtkWidget* table = LayoutTable = gtk_table_new (4, 4, FALSE);\r
- gtk_box_pack_start (GTK_BOX (vbox2), LayoutTable, FALSE, TRUE, 0);\r
- gtk_widget_show(LayoutTable);\r
-\r
- for (int i = 0; i < MAX_FLAGS; i++)\r
- {\r
- GtkWidget* check = gtk_check_button_new_with_label ("");\r
- gtk_widget_ref (check);\r
- gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);\r
- EntWidgets[EntCheck1+i] = check;\r
- }\r
-\r
- //++timo cleanme: these flags where Q2 stuff\r
- /*\r
- check = gtk_check_button_new_with_label ("!Easy");\r
- gtk_widget_show (check);\r
- gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);\r
- gtk_table_attach (GTK_TABLE (table), check, 2, 3, 0, 1,\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);\r
- EntWidgets[EntCheck17] = check;\r
-\r
- check = gtk_check_button_new_with_label ("!Medium");\r
- gtk_widget_show (check);\r
- gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);\r
- gtk_table_attach (GTK_TABLE (table), check, 2, 3, 1, 2,\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);\r
- EntWidgets[EntCheck18] = check;\r
-\r
- check = gtk_check_button_new_with_label ("!Hard");\r
- gtk_widget_show (check);\r
- gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);\r
- gtk_table_attach (GTK_TABLE (table), check, 2, 3, 2, 3,\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);\r
- EntWidgets[EntCheck19] = check;\r
-\r
- check = gtk_check_button_new_with_label ("!DeathMatch");\r
- gtk_widget_show (check);\r
- gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);\r
- gtk_table_attach (GTK_TABLE (table), check, 2, 3, 3, 4,\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);\r
- EntWidgets[EntCheck20] = check;\r
- */\r
- }\r
-\r
- {\r
- GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);\r
- gtk_widget_show (scr);\r
- gtk_box_pack_start (GTK_BOX (vbox2), scr, TRUE, TRUE, 0);\r
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);\r
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);\r
-\r
- {\r
- GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);\r
-\r
- GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));\r
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);\r
-\r
- {\r
- GtkCellRenderer* renderer = gtk_cell_renderer_text_new();\r
- GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);\r
- gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);\r
- }\r
-\r
- {\r
- GtkCellRenderer* renderer = gtk_cell_renderer_text_new();\r
- GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);\r
- gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);\r
- }\r
-\r
- {\r
- GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));\r
- g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(proplist_selection_changed), dlg);\r
- }\r
-\r
- gtk_widget_show(view);\r
-\r
- gtk_container_add(GTK_CONTAINER (scr), view);\r
- \r
- g_object_unref(G_OBJECT(store));\r
-\r
- EntWidgets[EntProps] = view;\r
- g_entprops_store = store;\r
- }\r
- }\r
- }\r
-\r
- int x = g_PrefsDlg.mWindowInfo.nEntitySplit1;\r
- if (x != -1)\r
- {\r
- gtk_paned_set_position (GTK_PANED (split1), x);\r
-\r
- while (gtk_events_pending ()) gtk_main_iteration ();\r
- x = g_PrefsDlg.mWindowInfo.nEntitySplit2;\r
-\r
- if (x != -1)\r
- gtk_paned_set_position (GTK_PANED (split2), x);\r
- }\r
- }\r
- }\r
-\r
- {\r
- GtkWidget* table = gtk_table_new (2, 2, FALSE);\r
- gtk_widget_show (table);\r
- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);\r
- gtk_table_set_row_spacings (GTK_TABLE (table), 3);\r
- gtk_table_set_col_spacings (GTK_TABLE (table), 5);\r
-\r
- {\r
- GtkWidget* entry = gtk_entry_new ();\r
- gtk_widget_show (entry);\r
- gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
- (GtkAttachOptions) (0), 0, 0);\r
- gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);\r
- gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",\r
- GTK_SIGNAL_FUNC (entityentry_keypress), this);\r
- EntWidgets[EntKeyField] = entry;\r
- }\r
-\r
- {\r
- GtkWidget* entry = gtk_entry_new ();\r
- gtk_widget_show (entry);\r
- gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,\r
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),\r
- (GtkAttachOptions) (0), 0, 0);\r
- gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);\r
- gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",\r
- GTK_SIGNAL_FUNC (entityentry_keypress), this);\r
- EntWidgets[EntValueField] = entry;\r
- }\r
-\r
- {\r
- GtkWidget* label = gtk_label_new ("Value");\r
- gtk_widget_show (label);\r
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (0), 0, 0);\r
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
- }\r
-\r
- {\r
- GtkWidget* label = gtk_label_new ("Key");\r
- gtk_widget_show (label);\r
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (0), 0, 0);\r
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);\r
- }\r
- }\r
-\r
- {\r
- GtkWidget* hbox = gtk_hbox_new (FALSE, 5);\r
- gtk_widget_show (hbox);\r
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);\r
-\r
- {\r
- GtkWidget* table = gtk_table_new (3, 3, TRUE);\r
- gtk_widget_show (table);\r
- gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("360");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"360");\r
- gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("45");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"45");\r
- gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("90");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"90");\r
- gtk_table_attach (GTK_TABLE (table), button, 1, 2, 0, 1,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("135");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"135");\r
- gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("180");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"180");\r
- gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("225");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"225");\r
- gtk_table_attach (GTK_TABLE (table), button, 0, 1, 2, 3,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("270");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"270");\r
- gtk_table_attach (GTK_TABLE (table), button, 1, 2, 2, 3,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("315");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"315");\r
- gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3,\r
- (GtkAttachOptions) (GTK_FILL),\r
- (GtkAttachOptions) (GTK_FILL), 0, 0);\r
- }\r
- }\r
-\r
- {\r
- GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);\r
- gtk_widget_show (vbox2);\r
- gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("Reset");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (ResetEntity), NULL);\r
- gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("Up");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-1");\r
- gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("Dn");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-2");\r
- gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);\r
- }\r
- }\r
-\r
- {\r
- GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);\r
- gtk_widget_show (vbox2);\r
- gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("Del Key/Pair");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (DelProp), NULL);\r
- gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("Sound...");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignSound), NULL);\r
- gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);\r
- }\r
-\r
- {\r
- GtkWidget* button = gtk_button_new_with_label ("Model...");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignModel), NULL);\r
- gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (g_pParentWnd->FloatingGroupDialog())\r
- {\r
- {\r
- GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);\r
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);\r
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);\r
- gtk_widget_show (scr);\r
- gtk_container_set_border_width (GTK_CONTAINER (scr), 3);\r
-\r
- {\r
- GtkWidget* text = gtk_text_view_new ();\r
- gtk_widget_set_size_request(text, 0, -1); // allow shrinking\r
- gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);\r
- gtk_text_view_set_editable (GTK_TEXT_VIEW(text), FALSE);\r
- gtk_container_add (GTK_CONTAINER (scr), text);\r
- gtk_widget_show (text);\r
- g_qeglobals_gui.d_edit = text;\r
- }\r
-\r
- {\r
- GtkWidget* label = gtk_label_new ("Console");\r
- gtk_widget_show (label);\r
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scr, label);\r
- }\r
- }\r
- }\r
-\r
-\r
- //++timo NOTE: this part for grouping code, don't remove! (we'll put it back in sometime soon)\r
-\r
- /*\r
- vbox = gtk_vbox_new (FALSE, 5);\r
- gtk_widget_show (vbox);\r
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);\r
-\r
- scr = gtk_scrolled_window_new (NULL, NULL);\r
- gtk_widget_show (scr);\r
- gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);\r
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);\r
-\r
- ctree = gtk_ctree_new (1, 0);\r
- gtk_widget_show (ctree);\r
- gtk_container_add (GTK_CONTAINER (scr), ctree);\r
- gtk_clist_column_titles_hide (GTK_CLIST (ctree));\r
- m_pTree = ctree;\r
-\r
- hbox = gtk_hbox_new (FALSE, 5);\r
- gtk_widget_show (hbox);\r
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);\r
-\r
- button = gtk_button_new_with_label ("Add...");\r
- gtk_widget_show (button);\r
- gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (groupdlg_add), NULL);\r
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);\r
- gtk_widget_set_usize (button, 60, -2);\r
-\r
- button = gtk_button_new_with_label ("Edit...");\r
- gtk_widget_show (button);\r
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);\r
- gtk_widget_set_usize (button, 60, -2);\r
-\r
- button = gtk_button_new_with_label ("Delete");\r
- gtk_widget_show (button);\r
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);\r
- gtk_widget_set_usize (button, 60, -2);\r
-\r
- label = gtk_label_new ("Groups");\r
- gtk_widget_show (label);\r
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);\r
- */\r
- inspector_mode = W_ENTITY;\r
- // gtk_window_set_title (GTK_WINDOW (dlg), "Entities");\r
- m_pWidget = dlg;\r
- /*\r
- load_pixmap ("grouptree1.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[0], &tree_masks[0]);\r
- load_pixmap ("grouptree2.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[1], &tree_masks[1]);\r
- load_pixmap ("grouptree3.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[2], &tree_masks[2]);\r
- load_pixmap ("grouptree4.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[3], &tree_masks[3]);\r
- load_pixmap ("grouptree5.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[4], &tree_masks[4]);\r
- load_pixmap ("grouptree6.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[5], &tree_masks[5]);\r
- load_pixmap ("grouptree7.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[6], &tree_masks[6]);\r
-\r
- Group_Init();\r
-*/\r
- g_signal_connect (G_OBJECT (notebook), "switch_page", G_CALLBACK (switch_page), dlg);\r
- }\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+//
+// Floating dialog that contains a notebook with at least Entities and Group tabs
+// I merged the 2 MS Windows dialogs in a single class
+//
+// Leonardo Zide (leo@lokigames.com)
+//
+
+#ifndef _WIN32
+ #include <unistd.h>
+#endif
+#include <gdk/gdkkeysyms.h>
+#include "stdafx.h"
+#include "groupdialog.h"
+
+GtkWidget* EntWidgets[EntLast];
+GtkListStore* g_entlist_store;
+GtkListStore* g_entprops_store;
+int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE
+qboolean multiple_entities;
+// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=17
+qboolean disable_spawn_get = false;
+entity_t *edit_entity;
+/*
+static GdkPixmap *tree_pixmaps[7];
+static GdkBitmap *tree_masks[7];
+*/
+#define IMG_PATCH 0
+#define IMG_BRUSH 1
+#define IMG_GROUP 2
+#define IMG_ENTITY 3
+#define IMG_ENTITYGROUP 4
+#define IMG_MODEL 5
+#define IMG_SCRIPT 6
+
+// misc group support
+#define MAX_GROUPS 4096
+#define GROUP_DELIMETER '@'
+#define GROUPNAME "QER_Group_%i"
+
+GroupDlg g_wndGroup;
+GroupDlg *g_pGroupDlg = &g_wndGroup;
+
+// group_t are loaded / saved through "group_info" entities
+// they hold epairs for group settings and additionnal access info (tree nodes)
+group_t *g_pGroups = NULL;
+
+// the number of active spawnflags
+static int spawnflag_count;
+// table: index, match spawnflag item to the spawnflag index (i.e. which bit)
+static int spawn_table[MAX_FLAGS];
+// we change the layout depending on how many spawn flags we need to display
+// the table is a 4x4 in which we need to put the comment box EntWidgets[EntComment] and the spawn flags..
+static GtkWidget *LayoutTable;
+// 0: none of them are hooked
+// 1: only the text, 2: text and four checks, 3: text and 8 checks
+static int widget_state = 0;
+
+static void entity_check (GtkWidget *widget, gpointer data);
+
+// =============================================================================
+// Global functions
+
+/*
+===============================================================
+
+ENTITY WINDOW
+
+===============================================================
+*/
+
+void FillClassList ()
+{
+ GtkListStore* store = g_entlist_store;
+
+ gtk_list_store_clear(store);
+
+ for (eclass_t* e = eclass ; e ; e = e->next)
+ {
+ GtkTreeIter iter;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, e->name, 1, e, -1);
+ }
+}
+
+// SetKeyValuePairs
+//
+// Reset the key/value (aka property) listbox and fill it with the
+// k/v pairs from the entity being edited.
+//
+
+void SetKeyValuePairs (bool bClearMD3)
+{
+ GtkListStore* store = g_entprops_store;
+
+ gtk_list_store_clear(store);
+
+ if (edit_entity == NULL)
+ {
+ // if there's no entity, then display no key/values
+ return;
+ }
+
+ // save current key/val pair around filling epair box
+ // row_select wipes it and sets to first in list
+ Str strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
+ Str strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
+
+
+ // Walk through list and add pairs
+ for(epair_t* epair = edit_entity->epairs ; epair ; epair = epair->next)
+ {
+ GtkTreeIter iter;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, epair->key, 1, epair->value, -1);
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), strKey.GetBuffer());
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), strVal.GetBuffer());
+
+ Sys_UpdateWindows(W_CAMERA | W_XY);
+}
+
+// SetSpawnFlags
+//
+// Update the checkboxes to reflect the flag state of the entity
+//
+void SetSpawnFlags(void)
+{
+ int f, i, v;
+
+ disable_spawn_get = true;
+
+ f = atoi(ValueForKey (edit_entity, "spawnflags"));
+ for (i=0 ; i<spawnflag_count ; i++)
+ {
+ v = !!(f&(1<<spawn_table[i]));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), v);
+ }
+ // take care of the remaining ones
+ for (i=spawnflag_count ; i<MAX_FLAGS ; i++)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]), FALSE);
+ }
+
+ disable_spawn_get = false;
+}
+
+// GetSpawnFlags
+//
+// Update the entity flags to reflect the state of the checkboxes
+//
+// NOTE: this function had a tendency to add "spawnflags" "0" on most entities
+// if this wants to set spawnflags to zero, remove the key
+
+void GetSpawnFlags(void)
+{
+ int f, i, v;
+ char sz[32];
+
+ f = 0;
+ for (i=0 ; i<spawnflag_count ; i++)
+ {
+ v = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (EntWidgets[EntCheck1+i]));
+ f |= v<<spawn_table[i];
+ }
+
+ if (f==0)
+ {
+ // remove all "spawnflags" keys
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ DeleteKey (b->owner, "spawnflags");
+ }
+ else
+ DeleteKey (edit_entity, "spawnflags");
+ }
+ else
+ {
+ sprintf (sz, "%i", f);
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ SetKeyValue(b->owner, "spawnflags", sz);
+ }
+ else
+ SetKeyValue (edit_entity, "spawnflags", sz);
+ }
+ SetKeyValuePairs ();
+}
+
+//#define DBG_UPDATESEL
+
+// UpdateSel
+//
+// Update the listbox, checkboxes and k/v pairs to reflect the new selection
+// iIndex is the index in the list box with the class name, -1 if not found
+bool UpdateSel(int iIndex, eclass_t *pec)
+{
+ int i, next_state;
+ brush_t *b;
+
+ // syndrom of crappy code, we may get into stack overflowing crap with this function and Gtk
+ // if we play with the list of entity classes
+ // using a static flag to prevent recursion
+ static bool bBlockUpdate = false;
+
+ if (bBlockUpdate)
+ return FALSE; // NOTE TTimo wtf is the return value for anyway?
+
+#ifdef DBG_UPDATESEL
+ Sys_FPrintf(SYS_WRN, "UpdateSel\n");
+#endif
+
+ if (selected_brushes.next == &selected_brushes)
+ {
+ edit_entity = world_entity;
+ multiple_entities = false;
+ }
+ else
+ {
+ edit_entity = selected_brushes.next->owner;
+ for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next)
+ {
+ if (b->owner != edit_entity)
+ {
+ multiple_entities = true;
+ break;
+ }
+ }
+ }
+
+ if (iIndex != -1)
+ {
+#ifdef DBG_UPDATESEL
+ Sys_FPrintf(SYS_WRN,"Setting focus_row to %d\n", iIndex);
+#endif
+ bBlockUpdate = true;
+
+ GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
+ GtkTreePath* path = gtk_tree_path_new();
+ gtk_tree_path_append_index(path, iIndex);
+ gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);
+ gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);
+ gtk_tree_path_free(path);
+
+ bBlockUpdate = false;
+ }
+
+ if (pec == NULL)
+ return TRUE;
+
+ // Set up the description
+ {
+ GtkTextBuffer* buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(EntWidgets[EntComment]));
+ gtk_text_buffer_set_text (buffer, pec->comments, -1);
+ }
+
+ spawnflag_count = 0;
+
+ // do a first pass to count the spawn flags, don't touch the widgets, we don't know in what state they are
+ for (i=0 ; i<MAX_FLAGS ; i++)
+ {
+ if (pec->flagnames[i] && pec->flagnames[i][0] != 0 && strcmp(pec->flagnames[i],"-"))
+ {
+ spawn_table[spawnflag_count] = i;
+ spawnflag_count++;
+ }
+ }
+
+ // what's new widget state
+ if (spawnflag_count==0)
+ next_state = 1;
+ else if (spawnflag_count<=4)
+ next_state = 2;
+ else if (spawnflag_count<=8)
+ next_state = 3;
+ else if (spawnflag_count<=12)
+ next_state = 4;
+ else
+ next_state = 5;
+ widget_state = next_state;
+ static int last_count = 0;
+
+ // disable all remaining boxes
+ // NOTE: these boxes might not even be on display
+ for (i = 0; i < last_count; i++)
+ {
+ GtkWidget* widget = EntWidgets[EntCheck1+i];
+ gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), " ");
+ gtk_widget_hide (widget);
+ gtk_widget_ref (widget);
+ gtk_container_remove (GTK_CONTAINER (LayoutTable), widget);
+ }
+ last_count = spawnflag_count;
+
+ for (i=0 ; i<spawnflag_count ; i++)
+ {
+ GtkWidget* widget = EntWidgets[EntCheck1+i];
+ gtk_widget_show (widget);
+
+ Str str;
+ str = pec->flagnames[spawn_table[i]];
+ str.MakeLower ();
+
+// gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,
+ gtk_table_attach (GTK_TABLE (LayoutTable), widget, i%4, i%4+1, i/4, i/4+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_widget_unref (widget);
+
+ gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), str.GetBuffer ());
+ }
+
+ SetSpawnFlags();
+
+ SetKeyValuePairs();
+
+ return TRUE;
+}
+
+bool UpdateEntitySel(eclass_t *pec)
+{
+#ifdef DBG_UPDATESEL
+ Sys_FPrintf(SYS_WRN, "UpdateEntitySel\n");
+#endif
+
+ GtkTreeModel* model = GTK_TREE_MODEL(g_entlist_store);
+ GtkTreeIter iter;
+ unsigned int i = 0;
+ for(gboolean good = gtk_tree_model_get_iter_first(model, &iter); good != FALSE; good = gtk_tree_model_iter_next(model, &iter))
+ {
+ char* text;
+ gtk_tree_model_get(model, &iter, 0, &text, -1);
+ if (strcmp (text, pec->name) == 0)
+ {
+#ifdef DBG_UPDATESEL
+ Sys_FPrintf(SYS_WRN, "found a match: %d %s\n", i, pec->name);
+#endif
+ return UpdateSel (i, pec);
+ }
+ g_free(text);
+ ++i;
+ }
+ return UpdateSel (-1, pec);
+}
+
+// CreateEntity
+//
+// Creates a new entity based on the currently selected brush and entity type.
+//
+
+void CreateEntity(void)
+{
+ GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
+
+ // check to make sure we have a brush
+ if (selected_brushes.next == &selected_brushes)
+ {
+ gtk_MessageBox(g_pParentWnd->m_pWidget, "You must have a selected brush to create an entity", "info");
+ return;
+ }
+
+ // find out what type of entity we are trying to create
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE)
+ {
+ gtk_MessageBox (g_pParentWnd->m_pWidget, "You must have a selected class to create an entity", "info");
+ return;
+ }
+
+ char* text;
+ gtk_tree_model_get(model, &iter, 0, &text, -1);
+ CreateEntityFromName(text, vec3_origin);
+ g_free(text);
+
+ if (selected_brushes.next == &selected_brushes)
+ edit_entity = world_entity;
+ else
+ edit_entity = selected_brushes.next->owner;
+
+ SetKeyValuePairs();
+ Select_Deselect ();
+ Select_Brush (edit_entity->brushes.onext);
+ Sys_UpdateWindows(W_ALL);
+}
+
+/*
+===============
+AddProp
+
+===============
+*/
+void AddProp()
+{
+ if (edit_entity == NULL)
+ return;
+
+ // Get current selection text
+ const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
+ const char* value = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
+
+
+ // TTimo: if you change the classname to worldspawn you won't merge back in the structural brushes but create a parasite entity
+ if (!strcmp(key, "classname") && !strcmp(value, "worldspawn"))
+ {
+ gtk_MessageBox(g_pParentWnd->m_pWidget, "Cannot change \"classname\" key back to worldspawn.", NULL, MB_OK );
+ return;
+ }
+
+
+ // RR2DO2: we don't want spaces in entity keys
+ if (strstr( key, " " ))
+ {
+ gtk_MessageBox(g_pParentWnd->m_pWidget, "No spaces are allowed in entity keys.", NULL, MB_OK );
+ return;
+ }
+
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ SetKeyValue(b->owner, key, value);
+ }
+ else
+ SetKeyValue(edit_entity, key, value);
+
+ // refresh the prop listbox
+ SetKeyValuePairs();
+
+
+#ifdef USEPLUGINENTITIES
+ // if it's a plugin entity, perhaps we need to update some drawing parameters
+ // NOTE: perhaps moving this code to a seperate func would help if we need it in other places
+ // TODO: we need to call some update func in the IPluginEntity in case model name changes etc.
+ // ( for the moment only bounding brush is updated ), see UpdateModelBrush in Ritual's Q3Radiant
+ if (edit_entity->eclass->nShowFlags & ECLASS_PLUGINENTITY)
+ {
+ vec3_t mins, maxs;
+ edit_entity->pPlugEnt->GetBounds( mins, maxs );
+ // replace old bounding brush by newly computed one
+ // NOTE: this part is similar to Entity_BuildModelBrush in Ritual's Q3Radiant, it can be
+ // usefull moved into a seperate func
+ brush_t *b,*oldbrush;
+ if (edit_entity->brushes.onext != &edit_entity->brushes)
+ oldbrush = edit_entity->brushes.onext;
+ b = Brush_Create (mins, maxs, &edit_entity->eclass->texdef);
+ Entity_LinkBrush (edit_entity, b);
+ Brush_Build( b, true );
+ Select_Deselect();
+ Brush_AddToList (edit_entity->brushes.onext, &selected_brushes);
+ if (oldbrush)
+ Brush_Free( oldbrush );
+ }
+#endif // USEPLUGINENTITIES
+}
+
+/*
+===============
+DelProp
+
+===============
+*/
+void DelProp(void)
+{
+ if (edit_entity == NULL)
+ return;
+
+ // Get current selection text
+ const char* key = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
+
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ DeleteKey(b->owner, key);
+ }
+ else
+ DeleteKey(edit_entity, key);
+
+ // refresh the prop listbox
+ SetKeyValuePairs();
+}
+
+void ResetEntity ()
+{
+ epair_t *pep;
+ int i;
+
+ if (edit_entity == NULL)
+ return;
+
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next; b != &selected_brushes; b=b->next)
+ for (pep = b->owner->epairs; pep; )
+ {
+ if (strcmp (pep->key, "classname") != 0)
+ {
+ DeleteKey (b->owner, pep->key);
+ pep = b->owner->epairs;
+ }
+ else
+ pep = pep->next;
+ }
+ }
+ else
+ for (pep = edit_entity->epairs; pep; )
+ {
+ if (strcmp (pep->key, "classname") != 0)
+ {
+ DeleteKey (edit_entity, pep->key);
+ pep = edit_entity->epairs;
+ }
+ else
+ pep = pep->next;
+ }
+
+ // refresh the dialog
+ SetKeyValuePairs ();
+ for (i = EntCheck1; i <= EntCheck16; i++)
+ gtk_signal_handler_block_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);
+ SetSpawnFlags ();
+ for (i = EntCheck1; i <= EntCheck16; i++)
+ gtk_signal_handler_unblock_by_func (GTK_OBJECT (EntWidgets[i]), GTK_SIGNAL_FUNC (entity_check), NULL);
+}
+
+bool GetSelectAllCriteria(CString &strKey, CString &strVal)
+{
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(EntWidgets[EntProps])), &model, &iter)
+ && (inspector_mode == W_ENTITY)
+ && GTK_WIDGET_VISIBLE (g_pGroupDlg->m_pWidget))
+ {
+ strKey = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntKeyField]));
+ strVal = gtk_entry_get_text (GTK_ENTRY (EntWidgets[EntValueField]));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+void AssignSound()
+{
+ char buffer[NAME_MAX];
+
+ strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
+ strcat (buffer, "sound/");
+
+ if( access(buffer, R_OK) != 0 )
+ {
+ // just go to fsmain
+ strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
+ strcat (buffer, "/");
+ }
+
+ const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, "Open Wav File", buffer, "sound");
+ if (filename != NULL)
+ {
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "noise");
+ char *aux = vfsExtractRelativePath (filename);
+ CString str;
+ if (aux)
+ str = aux;
+ else
+ {
+ Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");
+ str = filename;
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer());
+ AddProp();
+ }
+}
+
+void AssignModel()
+{
+ char buffer[NAME_MAX];
+
+ strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
+ strcat (buffer, "models/");
+
+ if( access(buffer, R_OK) != 0 )
+ {
+ // just go to fsmain
+ strcpy (buffer, g_qeglobals.m_strHomeMaps.GetBuffer());
+ strcat (buffer, "/");
+ }
+
+ const char *filename = file_dialog (g_pGroupDlg->m_pWidget, TRUE, "Open Model", buffer, MODEL_MAJOR);
+ if (filename != NULL)
+ {
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), "model");
+ // use VFS to get the correct relative path
+ char *aux = vfsExtractRelativePath (filename);
+ CString str;
+ if (aux)
+ str = aux;
+ else
+ {
+ Sys_FPrintf (SYS_WRN, "WARNING: could not extract the relative path, using full path instead\n");
+ str = filename;
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), str.GetBuffer());
+ AddProp();
+ edit_entity->brushes.onext->bModelFailed = false;
+ }
+}
+
+/*
+==============
+SetInspectorMode
+==============
+*/
+void SetInspectorMode(int iType)
+{
+ if (iType == W_GROUP)
+ gtk_MessageBox(g_pParentWnd->m_pWidget, "Brush grouping is not functional yet", NULL, MB_OK | MB_ICONWARNING );
+
+ if (!g_pParentWnd->FloatingGroupDialog() &&
+ (iType == W_TEXTURE || iType == W_CONSOLE))
+ return;
+
+ // Is the caller asking us to cycle to the next window?
+ if (iType == -1)
+ {
+ if (inspector_mode == W_ENTITY)
+ iType = W_TEXTURE;
+ else if (inspector_mode == W_TEXTURE)
+ iType = W_CONSOLE;
+ else if (inspector_mode == W_CONSOLE)
+ iType = W_GROUP;
+ else
+ iType = W_ENTITY;
+ }
+
+ switch(iType)
+ {
+ case W_ENTITY:
+ // entity is always first in the inspector
+ gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Entities");
+ gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 0);
+ break;
+
+ case W_TEXTURE:
+ g_pParentWnd->GetTexWnd()->FocusEdit();
+ gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Textures");
+ if (g_pParentWnd->FloatingGroupDialog())
+ gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);
+ break;
+
+ case W_CONSOLE:
+ gtk_window_set_title (GTK_WINDOW (g_qeglobals_gui.d_entity), "Console");
+ if (g_pParentWnd->FloatingGroupDialog())
+ gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 2);
+ break;
+
+ case W_GROUP:
+ if (g_pParentWnd->FloatingGroupDialog())
+ gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 3);
+ else
+ gtk_notebook_set_page (GTK_NOTEBOOK (g_pGroupDlg->m_pNotebook), 1);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Group_Add(entity_t *e)
+{
+ /*
+ group_t *g = (group_t*)qmalloc(sizeof(group_t));
+ g->epairs = e->epairs;
+ g->next = NULL;
+ e->epairs = NULL;
+
+ // create a new group node
+ char *text = ValueForKey(g->epairs, "group");
+ g->itemOwner = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_wndGroup.m_hWorld, NULL, &text, 0,
+ tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],
+ tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], TRUE, TRUE);
+ g->next = g_pGroups;
+ g_pGroups = g;
+ */
+}
+/*
+group_t* Group_Alloc(char *name)
+{
+ group_t *g = (group_t*)qmalloc(sizeof(group_t));
+ SetKeyValue( g->epairs, "group", name );
+ return g;
+}
+
+group_t* Group_ForName(const char * name)
+{
+ group_t *g = g_pGroups;
+ while (g != NULL)
+ {
+ if (strcmp( ValueForKey(g->epairs,"group"), name ) == 0)
+ break;
+ g = g->next;
+ }
+ return g;
+}
+
+void Group_AddToItem(brush_t *b, GtkCTreeNode* item)
+{
+ int nImage = IMG_BRUSH;
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ const char *pName = NULL;
+ // const char *pNamed = Brush_GetKeyValue(b, "name");
+
+ if (!b->owner || (b->owner == world_entity))
+ {
+ if (b->patchBrush)
+ {
+ pName = "Generic Patch";
+ nImage = IMG_PATCH;
+ }
+ else
+ {
+ pName = "Generic Brush";
+ nImage = IMG_BRUSH;
+ }
+ }
+ else
+ {
+ pName = b->owner->eclass->name;
+ if (b->owner->eclass->fixedsize)
+ {
+ nImage = IMG_ENTITY;
+ }
+ else
+ {
+ nImage = IMG_ENTITYGROUP;
+ }
+ }
+
+ GtkCTreeNode *newItem;
+ int i = (b->patchBrush) ? IMG_PATCH : IMG_BRUSH;
+ newItem = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), item, NULL, (gchar**)&pName, 0,
+ tree_pixmaps[i], tree_masks[i], tree_pixmaps[i],
+ tree_masks[i], TRUE, TRUE);
+ gtk_ctree_node_set_row_data (GTK_CTREE (g_wndGroup.m_pTree), newItem, b);
+ b->itemOwner = newItem;
+}
+*/
+void Group_RemoveBrush(brush_t *b)
+{
+ /*
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ if (b->itemOwner)
+ {
+ gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);
+ b->itemOwner = NULL;
+ }
+ DeleteKey(b->epairs, "group");
+ */
+}
+/*
+void Group_AddToWorld(brush_t *b)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ GtkCTreeNode *parent = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);
+ Group_AddToItem(b, parent);
+}
+*/
+void Group_AddToProperGroup(brush_t *b)
+{
+ /*
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+
+ // NOTE: we do a local copy of the "group" key because it gets erased by Group_RemoveBrush
+ const char *pGroup = Brush_GetKeyValue(b, "group");
+ // remove the entry in the tree if there's one
+ if (b->itemOwner)
+ {
+ gtk_ctree_remove_node (GTK_CTREE (g_pGroupDlg->m_pTree), b->itemOwner);
+ b->itemOwner = NULL;
+ }
+
+ if (*pGroup != 0)
+ {
+ // find the item
+ group_t *g = Group_ForName(pGroup);
+ if (g)
+ Group_AddToItem(b, g->itemOwner);
+#ifdef _DEBUG
+ else
+ Sys_Printf("WARNING: unexpected Group_ForName not found in Group_AddToProperGroup\n");
+#endif
+ }
+ else
+ {
+ Group_AddToWorld(b);
+ }
+ */
+}
+/*
+void Group_AddToSelected(brush_t *b)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ GtkCTreeNode *item;
+ item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), GTK_CLIST (g_pGroupDlg->m_pTree)->focus_row);
+ if (item == NULL)
+ {
+ item = gtk_ctree_node_nth (GTK_CTREE (g_pGroupDlg->m_pTree), 0);
+ }
+ Group_AddToItem(b, item);
+}
+*/
+/*
+void Group_Save(FILE *f)
+{
+ group_t *g = g_pGroups;
+ while (g)
+ {
+ fprintf(f,"{\n\"classname\" \"group_info\"\n\"group\" \"%s\"\n}\n", ValueForKey( g->epairs, "group" ));
+ g = g->next;
+ }
+}
+*/
+
+void Group_Init()
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ // start by cleaning everything
+ // clean the groups
+ //++timo FIXME: we leak, delete the groups on the way (I don't have time to do it now)
+#ifdef _DEBUG
+ Sys_Printf("TODO: fix leak in Group_Init\n");
+#endif
+ group_t *g = g_pGroups;
+ while (g)
+ {
+ epair_t *ep,*enext;
+ for (ep = g->epairs ; ep ; ep=enext )
+ {
+ enext = ep->next;
+ free (ep->key);
+ free (ep->value);
+ free (ep);
+ }
+ g = g->next;
+ }
+ /*
+ GtkCTreeNode *world;
+ char *text = "World";
+ g_pGroups = NULL;
+ gtk_clist_clear (GTK_CLIST (g_wndGroup.m_pTree));
+ world = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), NULL, NULL, &text, 0,
+ tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], tree_pixmaps[IMG_GROUP],
+ tree_masks[IMG_GROUP], FALSE, TRUE);
+ */
+ // walk through all the brushes, remove the itemOwner key and add them back where they belong
+ brush_t *b;
+ for (b = active_brushes.next; b != &active_brushes; b = b->next)
+ {
+ b->itemOwner = NULL;
+ Group_AddToProperGroup(b);
+ }
+ for (b = selected_brushes.next ; b != &selected_brushes ; b = b->next)
+ {
+ b->itemOwner = NULL;
+ Group_AddToProperGroup(b);
+ }
+}
+/*
+// scan through world_entity for groups in this map?
+// we use GROUPNAME "QER_group_%i" to look for existing groups and their naming
+//++timo FIXME: is this actually needed for anything?
+void Group_GetListFromWorld(GSList **pArray)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+
+ if (world_entity == NULL)
+ {
+ return;
+ }
+
+ char cBuff[1024];
+ for (int i =0; i < MAX_GROUPS; i++)
+ {
+ sprintf(cBuff, GROUPNAME, i);
+ char *pGroup = ValueForKey(world_entity, cBuff);
+ if (pGroup && strlen(pGroup) > 0)
+ {
+ *pArray = g_slist_append (*pArray, g_strdup (pGroup));
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+void Group_RemoveListFromWorld()
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ GSList* array = NULL;
+ Group_GetListFromWorld(&array);
+
+ while (array)
+ {
+ DeleteKey(world_entity, (char*)array->data);
+ g_free (array->data);
+ array = g_slist_remove (array, array->data);
+ }
+}
+
+int CountChar(const char *p, char c)
+{
+ int nCount = 0;
+ int nLen = strlen(p)-1;
+ while (nLen-- >= 0)
+ {
+ if (p[nLen] == c)
+ {
+ nCount++;
+ }
+ }
+ return nCount;
+}
+*/
+// =============================================================================
+// callbacks
+
+static void eclasslist_selection_changed(GtkTreeSelection* selection, gpointer data)
+{
+ GtkTreeModel* model;
+ GtkTreeIter selected;
+ // no world entity, we are not ready yet
+ // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=917
+ if( !world_entity ) {
+ return;
+ }
+ if(gtk_tree_selection_get_selected(selection, &model, &selected))
+ {
+ eclass_t* eclass;
+ gtk_tree_model_get(model, &selected, 1, &eclass, -1);
+ if(eclass != NULL)
+ {
+ GtkTreePath* path = gtk_tree_model_get_path(model, &selected);
+ UpdateSel(gtk_tree_path_get_indices(path)[0], eclass);
+ gtk_tree_path_free(path);
+ }
+ }
+}
+
+static gint eclasslist_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ if (event->type == GDK_2BUTTON_PRESS)
+ {
+ CreateEntity ();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gint eclasslist_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)
+{
+ unsigned int code = gdk_keyval_to_upper (event->keyval);
+
+ if (event->keyval == GDK_Return)
+ {
+ CreateEntity ();
+ return TRUE;
+ }
+
+ // select the entity that starts with the key pressed
+ if (code <= 'Z' && code >= 'A')
+ {
+ GtkTreeView* view = GTK_TREE_VIEW(EntWidgets[EntList]);
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ if(gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &model, &iter) == FALSE
+ || gtk_tree_model_iter_next(model, &iter) == FALSE)
+ {
+ gtk_tree_model_get_iter_first(model, &iter);
+ }
+
+ for(unsigned int count = gtk_tree_model_iter_n_children(model, NULL); count > 0; --count)
+ {
+ char* text;
+ gtk_tree_model_get(model, &iter, 0, &text, -1);
+
+ if (toupper (text[0]) == (int)code)
+ {
+ GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
+ gtk_tree_selection_select_path(gtk_tree_view_get_selection(view), path);
+ gtk_tree_view_scroll_to_cell(view, path, NULL, FALSE, 0, 0);
+ gtk_tree_path_free(path);
+ count = 1;
+ }
+
+ g_free(text);
+
+ if(gtk_tree_model_iter_next(model, &iter) == FALSE)
+ gtk_tree_model_get_iter_first(model, &iter);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static void proplist_selection_changed(GtkTreeSelection* selection, gpointer data)
+{
+ // find out what type of entity we are trying to create
+ GtkTreeModel* model;
+ GtkTreeIter iter;
+ if(gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
+ {
+ return;
+ }
+
+ char* key;
+ char* val;
+ gtk_tree_model_get(model, &iter, 0, &key, 1, &val, -1);
+
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntKeyField]), key);
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), val);
+
+ g_free(key);
+ g_free(val);
+}
+
+static void entity_check (GtkWidget *widget, gpointer data)
+{
+ if( !disable_spawn_get )
+ GetSpawnFlags();
+}
+
+static void entitylist_angle (GtkWidget *widget, gpointer data)
+{
+ SetKeyValue (edit_entity, "angle", (char*)data);
+ SetKeyValuePairs ();
+}
+
+static gint entityentry_keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)
+{
+ if (event->keyval == GDK_Tab)
+ {
+ if (widget == EntWidgets[EntKeyField])
+ {
+ //gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");
+ gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);
+ }
+ else
+ gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntKeyField]);
+
+ return TRUE;
+ }
+ else if (event->keyval == GDK_Return)
+ {
+ if (widget == EntWidgets[EntKeyField])
+ {
+ gtk_entry_set_text (GTK_ENTRY (EntWidgets[EntValueField]), "");
+ gtk_window_set_focus (GTK_WINDOW (g_pGroupDlg->m_pWidget), EntWidgets[EntValueField]);
+ }
+ else
+ {
+ AddProp ();
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+/*
+// add a new group, put all selected brushes into the group
+static void groupdlg_add (GtkWidget *widget, gpointer data)
+{
+ char* name = DoNameDlg ("New Group");
+
+ if (name != NULL)
+ {
+ // create a new group node
+ GtkCTreeNode *item;
+ item = gtk_ctree_insert_node (GTK_CTREE (g_wndGroup.m_pTree), g_pGroupDlg->m_hWorld, NULL, &name, 0,
+ tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP],
+ tree_pixmaps[IMG_GROUP], tree_masks[IMG_GROUP], FALSE, TRUE);
+
+ // create a new group
+ group_t *g = Group_Alloc (name);
+ g->itemOwner = item;
+ g->next = g_pGroups;
+ g_pGroups = g;
+
+ // now add the selected brushes
+ // NOTE: it would be much faster to give the group_t for adding
+ // but Select_AddToGroup is the standard way for all other cases
+ Select_AddToGroup (name);
+ g_free (name);
+ }
+}
+*/
+static void switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)
+{
+ char *text;
+ gtk_label_get(GTK_LABEL(gtk_notebook_get_tab_label(notebook, gtk_notebook_get_nth_page(notebook, page_num))), &text);
+ gtk_window_set_title (GTK_WINDOW (data), text);
+
+ gpointer item = g_object_get_data (G_OBJECT (g_pParentWnd->m_pWidget), "menu_misc_selectentitycolor");
+
+ if (g_pParentWnd->FloatingGroupDialog())
+ {
+ switch (page_num)
+ {
+ case 0: inspector_mode = W_ENTITY; break;
+ case 1: inspector_mode = W_TEXTURE; break;
+ case 2: inspector_mode = W_CONSOLE; break;
+ default: inspector_mode = W_GROUP; break;
+ }
+ }
+ else
+ {
+ if (page_num == 0)
+ inspector_mode = W_ENTITY;
+ else
+ inspector_mode = W_GROUP;
+ }
+
+ if (inspector_mode == W_ENTITY)
+ gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
+ else
+ gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
+}
+
+// =============================================================================
+// GroupDlg class
+
+// NOTE: when a key is hit with group window focused, we catch in this handler but it gets propagated to mainframe too
+// therefore the message will be intercepted and used as a ID_SELECTION_DESELECT
+static gint OnDialogKey (GtkWidget* widget, GdkEventKey* event, gpointer data)
+{
+#ifdef DBG_PI
+ Sys_Printf("OnDialogKey\n");
+#endif
+ if ((event->keyval == GDK_Escape) && (g_pParentWnd->CurrentStyle() != MainFrame::eFloating))
+ {
+ // toggle off the group view (whatever part of it is currently displayed)
+ // this used to be done with a g_pParentWnd->OnViewEntity(); but it had bad consequences
+ // http://fenris.lokigames.com/show_bug.cgi?id=2773
+ widget_delete_hide (g_qeglobals_gui.d_entity);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+GroupDlg::GroupDlg ()
+{
+ m_pWidget = NULL;
+ m_hWorld = NULL;
+}
+
+#ifdef _WIN32
+extern void PositionWindowOnPrimaryScreen(window_position_t& position);
+#endif
+
+void GroupDlg::Create ()
+{
+ if (m_pWidget != NULL)
+ return;
+
+ GtkWidget* dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+#ifdef _WIN32
+ if( g_PrefsDlg.m_bStartOnPrimMon ) {
+ PositionWindowOnPrimaryScreen( g_PrefsDlg.mWindowInfo.posEntityWnd );
+ }
+#endif
+ load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posEntityWnd);
+
+ gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
+ gtk_signal_connect (GTK_OBJECT (dlg), "delete_event", GTK_SIGNAL_FUNC (widget_delete_hide), NULL);
+ // catch 'Esc'
+ gtk_signal_connect (GTK_OBJECT (dlg), "key_press_event", GTK_SIGNAL_FUNC (OnDialogKey), NULL);
+ gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (g_pParentWnd->m_pWidget));
+ g_qeglobals_gui.d_entity = dlg;
+
+ {
+ GtkWidget* notebook = gtk_notebook_new ();
+ gtk_widget_show (notebook);
+ gtk_container_add (GTK_CONTAINER (dlg), notebook);
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_BOTTOM);
+ m_pNotebook = notebook;
+
+ {
+ GtkWidget* vbox = gtk_vbox_new (FALSE, 2);
+ gtk_widget_show (vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
+
+ {
+ GtkWidget* label = gtk_label_new ("Entities");
+ gtk_widget_show (label);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
+ }
+
+ {
+ GtkWidget* split1 = gtk_vpaned_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), split1, TRUE, TRUE, 0);
+ gtk_widget_show (split1);
+
+ {
+ GtkWidget* split2 = gtk_vpaned_new ();
+ gtk_paned_add1 (GTK_PANED (split1), split2);
+ gtk_widget_show (split2);
+
+ g_object_set_data (G_OBJECT (dlg), "split1", split1);
+ g_object_set_data (G_OBJECT (dlg), "split2", split2);
+
+ {
+ GtkWidget* vbox2 = gtk_vbox_new (FALSE, 2);
+ gtk_widget_show (vbox2);
+ gtk_paned_pack2 (GTK_PANED (split1), vbox2, FALSE, FALSE);
+
+ {
+ GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scr);
+ gtk_paned_add1 (GTK_PANED (split2), scr);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
+
+ {
+ GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
+
+ GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
+ g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(eclasslist_button_press), NULL);
+ g_signal_connect(G_OBJECT(view), "key_press_event", G_CALLBACK(eclasslist_keypress), this);
+
+ {
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+ GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
+ }
+
+ {
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+ g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(eclasslist_selection_changed), dlg);
+ }
+
+ gtk_widget_show(view);
+
+ gtk_container_add(GTK_CONTAINER (scr), view);
+
+ g_object_unref(G_OBJECT(store));
+ EntWidgets[EntList] = view;
+ g_entlist_store = store;
+ }
+ }
+
+ {
+ GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scr);
+ gtk_paned_add2 (GTK_PANED (split2), scr);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
+
+ {
+ GtkWidget* text = gtk_text_view_new();
+ gtk_widget_set_size_request(text, 0, -1); // allow shrinking
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
+ gtk_widget_show (text);
+ gtk_container_add (GTK_CONTAINER (scr), text);
+ EntWidgets[EntComment] = text;
+ }
+ }
+
+ {
+ // Spawnflags (4 colums wide max, or window gets too wide.)
+ GtkWidget* table = LayoutTable = gtk_table_new (4, 4, FALSE);
+ gtk_box_pack_start (GTK_BOX (vbox2), LayoutTable, FALSE, TRUE, 0);
+ gtk_widget_show(LayoutTable);
+
+ for (int i = 0; i < MAX_FLAGS; i++)
+ {
+ GtkWidget* check = gtk_check_button_new_with_label ("");
+ gtk_widget_ref (check);
+ gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
+ EntWidgets[EntCheck1+i] = check;
+ }
+
+ //++timo cleanme: these flags where Q2 stuff
+ /*
+ check = gtk_check_button_new_with_label ("!Easy");
+ gtk_widget_show (check);
+ gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
+ gtk_table_attach (GTK_TABLE (table), check, 2, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+ EntWidgets[EntCheck17] = check;
+
+ check = gtk_check_button_new_with_label ("!Medium");
+ gtk_widget_show (check);
+ gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
+ gtk_table_attach (GTK_TABLE (table), check, 2, 3, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+ EntWidgets[EntCheck18] = check;
+
+ check = gtk_check_button_new_with_label ("!Hard");
+ gtk_widget_show (check);
+ gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
+ gtk_table_attach (GTK_TABLE (table), check, 2, 3, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+ EntWidgets[EntCheck19] = check;
+
+ check = gtk_check_button_new_with_label ("!DeathMatch");
+ gtk_widget_show (check);
+ gtk_signal_connect (GTK_OBJECT (check), "toggled", GTK_SIGNAL_FUNC (entity_check), NULL);
+ gtk_table_attach (GTK_TABLE (table), check, 2, 3, 3, 4,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+ EntWidgets[EntCheck20] = check;
+ */
+ }
+
+ {
+ GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scr);
+ gtk_box_pack_start (GTK_BOX (vbox2), scr, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
+
+ {
+ GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+
+ GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
+
+ {
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+ GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
+ }
+
+ {
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+ GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 1, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
+ }
+
+ {
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+ g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(proplist_selection_changed), dlg);
+ }
+
+ gtk_widget_show(view);
+
+ gtk_container_add(GTK_CONTAINER (scr), view);
+
+ g_object_unref(G_OBJECT(store));
+
+ EntWidgets[EntProps] = view;
+ g_entprops_store = store;
+ }
+ }
+ }
+
+ int x = g_PrefsDlg.mWindowInfo.nEntitySplit1;
+ if (x != -1)
+ {
+ gtk_paned_set_position (GTK_PANED (split1), x);
+
+ while (gtk_events_pending ()) gtk_main_iteration ();
+ x = g_PrefsDlg.mWindowInfo.nEntitySplit2;
+
+ if (x != -1)
+ gtk_paned_set_position (GTK_PANED (split2), x);
+ }
+ }
+ }
+
+ {
+ GtkWidget* table = gtk_table_new (2, 2, FALSE);
+ gtk_widget_show (table);
+ gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 3);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+
+ {
+ GtkWidget* entry = gtk_entry_new ();
+ gtk_widget_show (entry);
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
+ gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",
+ GTK_SIGNAL_FUNC (entityentry_keypress), this);
+ EntWidgets[EntKeyField] = entry;
+ }
+
+ {
+ GtkWidget* entry = gtk_entry_new ();
+ gtk_widget_show (entry);
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_widget_set_events (entry, GDK_KEY_PRESS_MASK);
+ gtk_signal_connect (GTK_OBJECT (entry), "key_press_event",
+ GTK_SIGNAL_FUNC (entityentry_keypress), this);
+ EntWidgets[EntValueField] = entry;
+ }
+
+ {
+ GtkWidget* label = gtk_label_new ("Value");
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ }
+
+ {
+ GtkWidget* label = gtk_label_new ("Key");
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ }
+ }
+
+ {
+ GtkWidget* hbox = gtk_hbox_new (FALSE, 5);
+ gtk_widget_show (hbox);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+
+ {
+ GtkWidget* table = gtk_table_new (3, 3, TRUE);
+ gtk_widget_show (table);
+ gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("360");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"360");
+ gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("45");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"45");
+ gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("90");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"90");
+ gtk_table_attach (GTK_TABLE (table), button, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("135");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"135");
+ gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("180");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"180");
+ gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("225");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"225");
+ gtk_table_attach (GTK_TABLE (table), button, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("270");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"270");
+ gtk_table_attach (GTK_TABLE (table), button, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("315");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"315");
+ gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ }
+ }
+
+ {
+ GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox2);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("Reset");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (ResetEntity), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("Up");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-1");
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("Dn");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (entitylist_angle), (void *)"-2");
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+ }
+ }
+
+ {
+ GtkWidget* vbox2 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox2);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("Del Key/Pair");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (DelProp), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("Sound...");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignSound), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+ }
+
+ {
+ GtkWidget* button = gtk_button_new_with_label ("Model...");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (AssignModel), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+ }
+ }
+ }
+ }
+
+ if (g_pParentWnd->FloatingGroupDialog())
+ {
+ {
+ GtkWidget* scr = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
+ gtk_widget_show (scr);
+ gtk_container_set_border_width (GTK_CONTAINER (scr), 3);
+
+ {
+ GtkWidget* text = gtk_text_view_new ();
+ gtk_widget_set_size_request(text, 0, -1); // allow shrinking
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
+ gtk_text_view_set_editable (GTK_TEXT_VIEW(text), FALSE);
+ gtk_container_add (GTK_CONTAINER (scr), text);
+ gtk_widget_show (text);
+ g_qeglobals_gui.d_edit = text;
+ }
+
+ {
+ GtkWidget* label = gtk_label_new ("Console");
+ gtk_widget_show (label);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scr, label);
+ }
+ }
+ }
+
+
+ //++timo NOTE: this part for grouping code, don't remove! (we'll put it back in sometime soon)
+
+ /*
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_widget_show (vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
+
+ scr = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scr);
+ gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ ctree = gtk_ctree_new (1, 0);
+ gtk_widget_show (ctree);
+ gtk_container_add (GTK_CONTAINER (scr), ctree);
+ gtk_clist_column_titles_hide (GTK_CLIST (ctree));
+ m_pTree = ctree;
+
+ hbox = gtk_hbox_new (FALSE, 5);
+ gtk_widget_show (hbox);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+
+ button = gtk_button_new_with_label ("Add...");
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (groupdlg_add), NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_set_usize (button, 60, -2);
+
+ button = gtk_button_new_with_label ("Edit...");
+ gtk_widget_show (button);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_set_usize (button, 60, -2);
+
+ button = gtk_button_new_with_label ("Delete");
+ gtk_widget_show (button);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_set_usize (button, 60, -2);
+
+ label = gtk_label_new ("Groups");
+ gtk_widget_show (label);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
+ */
+ inspector_mode = W_ENTITY;
+ // gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
+ m_pWidget = dlg;
+ /*
+ load_pixmap ("grouptree1.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[0], &tree_masks[0]);
+ load_pixmap ("grouptree2.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[1], &tree_masks[1]);
+ load_pixmap ("grouptree3.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[2], &tree_masks[2]);
+ load_pixmap ("grouptree4.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[3], &tree_masks[3]);
+ load_pixmap ("grouptree5.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[4], &tree_masks[4]);
+ load_pixmap ("grouptree6.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[5], &tree_masks[5]);
+ load_pixmap ("grouptree7.bmp", g_pParentWnd->m_pWidget, &tree_pixmaps[6], &tree_masks[6]);
+
+ Group_Init();
+*/
+ g_signal_connect (G_OBJECT (notebook), "switch_page", G_CALLBACK (switch_page), dlg);
+ }
+}
+