From 64d4a06eba30d322134feb43d3de17b500438d00 Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 2 Jan 2009 08:40:46 +0000 Subject: [PATCH] new command: regroup entities. Moves all selected brushes into the selected entity. Usage: - Select brush from entity - Hit Ctrl-Alt-E - Select some other brush - Regroup The other brush will get added to the entity. - Select brush from entity - Regroup The brush will get removed from the entity, and moved to worldspawn. git-svn-id: svn://svn.icculus.org/netradiant/trunk@147 61c419a2-8eb2-4b30-bcec-8cead039b335 --- radiant/commands.cpp | 2 +- radiant/entity.cpp | 84 +++++++++++++++++++++++++++++++++++++++ tools/quake3/q3map2/map.c | 21 ++++++++-- 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/radiant/commands.cpp b/radiant/commands.cpp index cee17117..03daeea5 100644 --- a/radiant/commands.cpp +++ b/radiant/commands.cpp @@ -359,7 +359,7 @@ public: // strBuff has been cleaned of it's modifiers .. switch between a regular key and a virtual one // based on length - if(keyEnd - value == 1 && std::isalpha(value[0])) // most often case.. deal with first + if(keyEnd - value == 1 && std::isalnum(value[0])) // most often case.. deal with first { accelerator.key = std::toupper(value[0]); ++m_count; diff --git a/radiant/entity.cpp b/radiant/entity.cpp index c2a31091..7a08d098 100644 --- a/radiant/entity.cpp +++ b/radiant/entity.cpp @@ -156,6 +156,88 @@ void Entity_ungroupSelected() } +class EntityFindSelected : public scene::Graph::Walker +{ +public: + mutable const scene::Path *groupPath; + mutable scene::Instance *groupInstance; + EntityFindSelected(): groupPath(0), groupInstance(0) + { + } + bool pre(const scene::Path& path, scene::Instance& instance) const + { + return true; + } + void post(const scene::Path& path, scene::Instance& instance) const + { + Entity* entity = Node_getEntity(path.top()); + if(entity != 0 + && Instance_getSelectable(instance)->isSelected() + && node_is_group(path.top()) + && !groupPath) + { + groupPath = &path; + groupInstance = &instance; + } + } +}; + +class EntityGroupSelected : public scene::Graph::Walker +{ + NodeSmartReference group; +public: + EntityGroupSelected(const scene::Path &p): group(p.top().get()) + { + } + bool pre(const scene::Path& path, scene::Instance& instance) const + { + return true; + } + void post(const scene::Path& path, scene::Instance& instance) const + { + if(Instance_getSelectable(instance)->isSelected()) + { + Entity* entity = Node_getEntity(path.top()); + if(entity == 0 && Node_isPrimitive(path.top())) + { + NodeSmartReference child(path.top().get()); + NodeSmartReference parent(path.parent().get()); + + Node_getTraversable(parent)->erase(child); + Node_getTraversable(group)->insert(child); + + if(Node_getTraversable(parent)->empty() && path.size() >= 3 && parent != Map_FindOrInsertWorldspawn(g_map)) + { + NodeSmartReference parentparent(path[path.size() - 3].get()); + Node_getTraversable(parentparent)->erase(parent); + } + } + } + } +}; + +void Entity_groupSelected() +{ + if (GlobalSelectionSystem().countSelected() < 1) return; + + UndoableCommand undo("groupSelectedEntities"); + + scene::Path world_path(makeReference(GlobalSceneGraph().root())); + world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map))); + + EntityFindSelected fse; + GlobalSceneGraph().traverse(fse); + if(fse.groupPath) + { + GlobalSceneGraph().traverse(EntityGroupSelected(*fse.groupPath)); + } + else + { + GlobalSceneGraph().traverse(EntityGroupSelected(world_path)); + } +} + + void Entity_connectSelected() { @@ -454,6 +536,7 @@ void Entity_registerPreferencesPage() void Entity_constructMenu(GtkMenu* menu) { + create_menu_item_with_mnemonic(menu, "_Regroup", "GroupSelection"); create_menu_item_with_mnemonic(menu, "_Ungroup", "UngroupSelection"); create_menu_item_with_mnemonic(menu, "_Connect", "ConnectSelection"); create_menu_item_with_mnemonic(menu, "_Select Color...", "EntityColor"); @@ -468,6 +551,7 @@ void Entity_Construct() { GlobalCommands_insert("EntityColor", FreeCaller(), Accelerator('K')); GlobalCommands_insert("ConnectSelection", FreeCaller(), Accelerator('K', (GdkModifierType)GDK_CONTROL_MASK)); + GlobalCommands_insert("GroupSelection", FreeCaller()); GlobalCommands_insert("UngroupSelection", FreeCaller()); GlobalPreferenceSystem().registerPreference("SI_Colors5", Vector3ImportStringCaller(g_entity_globals.color_entity), Vector3ExportStringCaller(g_entity_globals.color_entity)); diff --git a/tools/quake3/q3map2/map.c b/tools/quake3/q3map2/map.c index 18ab6b21..82d7d2bf 100644 --- a/tools/quake3/q3map2/map.c +++ b/tools/quake3/q3map2/map.c @@ -599,6 +599,9 @@ static void MergeOrigin(entity_t *ent, vec3_t origin) { vec3_t adjustment; + /* we have not parsed the brush completely yet... */ + GetVectorForKey( ent, "origin", ent->origin ); + VectorMA(origin, -1, ent->originbrush_origin, adjustment); VectorAdd(adjustment, ent->origin, ent->origin); VectorCopy(origin, ent->originbrush_origin); @@ -624,6 +627,9 @@ brush_t *FinishBrush( void ) char string[ 32 ]; vec3_t origin; + Sys_Printf( "Entity %i, Brush %i: origin brush detected\n", + mapEnt->mapEntityNum, entitySourceBrushes ); + if( numEntities == 1 ) { Sys_Printf( "Entity %i, Brush %i: origin brushes not allowed in world\n", @@ -1079,11 +1085,17 @@ adds them to the world's brush list (used by func_group) */ +void AdjustBrushesForOrigin( entity_t *ent ); void MoveBrushesToWorld( entity_t *ent ) { brush_t *b, *next; parseMesh_t *pm; + /* we need to undo the common/origin adjustment, and instead shift them by the entity key origin */ + VectorScale(ent->origin, -1, ent->originbrush_origin); + Sys_Printf("func_group: adjusting by %f %f %f\n", ent->originbrush_origin[0], ent->originbrush_origin[1], ent->originbrush_origin[2]); + AdjustBrushesForOrigin(ent); + VectorClear(ent->originbrush_origin); /* move brushes */ for( b = ent->brushes; b != NULL; b = next ) @@ -1146,7 +1158,8 @@ void AdjustBrushesForOrigin( entity_t *ent ) brush_t *b; parseMesh_t *p; - + Sys_Printf("origin: adjusting by %f %f %f\n", ent->originbrush_origin[0], ent->originbrush_origin[1], ent->originbrush_origin[2]); + /* walk brush list */ for( b = ent->brushes; b != NULL; b = b->next ) { @@ -1157,7 +1170,7 @@ void AdjustBrushesForOrigin( entity_t *ent ) s = &b->sides[ i ]; /* offset side plane */ - newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->origin ); + newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->originbrush_origin ); /* find a new plane */ s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal, newdist, 0, NULL ); @@ -1171,7 +1184,7 @@ void AdjustBrushesForOrigin( entity_t *ent ) for( p = ent->patches; p != NULL; p = p->next ) { for( i = 0; i < (p->mesh.width * p->mesh.height); i++ ) - VectorSubtract( p->mesh.verts[ i ].xyz, ent->origin, p->mesh.verts[ i ].xyz ); + VectorSubtract( p->mesh.verts[ i ].xyz, ent->originbrush_origin, p->mesh.verts[ i ].xyz ); } } @@ -1595,7 +1608,7 @@ static qboolean ParseMapEntity( qboolean onlyLights ) /* get entity origin and adjust brushes */ GetVectorForKey( mapEnt, "origin", mapEnt->origin ); - if( mapEnt->origin[ 0 ] || mapEnt->origin[ 1 ] || mapEnt->origin[ 2 ] ) + if( mapEnt->originbrush_origin[ 0 ] || mapEnt->originbrush_origin[ 1 ] || mapEnt->originbrush_origin[ 2 ] ) AdjustBrushesForOrigin( mapEnt ); /* group_info entities are just for editor grouping (fixme: leak!) */ -- 2.39.2