]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/entity.cpp
Merge commit '48410b113dd2036e69dbf723a39ec9af02fc9b12'
[xonotic/netradiant.git] / radiant / entity.cpp
index eb4dea509a246154f6de545a8025a7fe759e152a..9478bda27ea00fbc84f39cc281b95a6ab50b751e 100644 (file)
@@ -130,35 +130,124 @@ void Scene_EntitySetClassname_Selected(const char* classname)
 }
 
 
-class EntityUngroupVisitor : public SelectionSystem::Visitor
+void Entity_ungroupSelected()
+{
+  if (GlobalSelectionSystem().countSelected() < 1) return;
+
+  UndoableCommand undo("ungroupSelectedEntities");
+
+  scene::Path world_path(makeReference(GlobalSceneGraph().root()));
+  world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map)));
+
+  scene::Instance &instance = GlobalSelectionSystem().ultimateSelected();
+  scene::Path path = instance.path();
+
+  if (!Node_isEntity(path.top())) path.pop();
+
+  if(Node_getEntity(path.top()) != 0
+    && node_is_group(path.top()))
+  {
+    if(world_path.top().get_pointer() != path.top().get_pointer())
+    {
+      parentBrushes(path.top(), world_path.top());
+      Path_deleteTop(path);
+    }
+  }
+}
+
+
+class EntityFindSelected : public scene::Graph::Walker
 {
-  const scene::Path& m_parent;
 public:
-  EntityUngroupVisitor(const scene::Path& parent) : m_parent(parent)
+  mutable const scene::Path *groupPath;
+  mutable scene::Instance *groupInstance;
+  EntityFindSelected(): groupPath(0), groupInstance(0)
   {
   }
-  void visit(scene::Instance& instance) const
+  bool pre(const scene::Path& path, scene::Instance& instance) const
   {
-    if(Node_getEntity(instance.path().top()) != 0
-      && node_is_group(instance.path().top()))
-    {
-      if(m_parent.top().get_pointer() != instance.path().top().get_pointer())
-      {
-        parentBrushes(instance.path().top(), m_parent.top());
-        Path_deleteTop(instance.path());
-      }
+    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;
     }
   }
 };
 
-void Entity_ungroupSelected()
+class EntityGroupSelected : public scene::Graph::Walker
 {
-  UndoableCommand undo("ungroupSelectedEntities");
+       NodeSmartReference group, worldspawn;
+       //typedef std::pair<NodeSmartReference, NodeSmartReference> DeletionPair;
+       //Stack<DeletionPair> deleteme;
+       public:
+       EntityGroupSelected(const scene::Path &p): group(p.top().get()), worldspawn(Map_FindOrInsertWorldspawn(g_map))
+       {
+       }
+       bool pre(const scene::Path& path, scene::Instance& instance) const
+       {
+               return true;
+       }
+       void post(const scene::Path& path, scene::Instance& instance) const
+       {
+               Selectable *selectable = Instance_getSelectable(instance);
+               if(selectable && selectable->isSelected())
+               { 
+                       Entity* entity = Node_getEntity(path.top());
+                       if(entity == 0 && Node_isPrimitive(path.top()))
+                       {
+                               NodeSmartReference child(path.top().get());
+                               NodeSmartReference parent(path.parent().get());
+
+                               if(path.size() >= 3 && parent != worldspawn)
+                               {
+                                       NodeSmartReference parentparent(path[path.size() - 3].get());
+
+                                       Node_getTraversable(parent)->erase(child);
+                                       Node_getTraversable(group)->insert(child);
+
+                                       if(Node_getTraversable(parent)->empty())
+                                       {
+                                               //deleteme.push(DeletionPair(parentparent, parent));
+                                               Node_getTraversable(parentparent)->erase(parent);
+                                       }
+                               }
+                               else
+                               {
+                                       Node_getTraversable(parent)->erase(child);
+                                       Node_getTraversable(group)->insert(child);
+                               }
+                       }
+               }
+       }
+};
+
+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)));
 
-  GlobalSelectionSystem().foreachSelected(EntityUngroupVisitor(world_path));
+  EntityFindSelected fse;
+  GlobalSceneGraph().traverse(fse);
+  if(fse.groupPath)
+  {
+         GlobalSceneGraph().traverse(EntityGroupSelected(*fse.groupPath));
+  }
+  else
+  {
+         GlobalSceneGraph().traverse(EntityGroupSelected(world_path));
+  }
 }
 
 
@@ -169,7 +258,8 @@ void Entity_connectSelected()
   {
     GlobalEntityCreator().connectEntities(
       GlobalSelectionSystem().penultimateSelected().path(),
-      GlobalSelectionSystem().ultimateSelected().path()
+      GlobalSelectionSystem().ultimateSelected().path(),
+      0
     );
   }
   else
@@ -178,6 +268,22 @@ void Entity_connectSelected()
   }
 }
 
+void Entity_killconnectSelected()
+{
+  if(GlobalSelectionSystem().countSelected() == 2)
+  {
+    GlobalEntityCreator().connectEntities(
+      GlobalSelectionSystem().penultimateSelected().path(),
+      GlobalSelectionSystem().ultimateSelected().path(),
+      1
+    );
+  }
+  else
+  {
+    globalErrorStream() << "entityKillConnectSelected: exactly two instances must be selected\n";
+  }
+}
+
 AABB Doom3Light_getBounds(const AABB& workzone)
 {
   AABB aabb(workzone);
@@ -222,8 +328,7 @@ void Entity_createFromSelection(const char* name, const Vector3& origin)
 
   EntityClass* entityClass = GlobalEntityClassManager().findOrInsert(name, true);
 
-  bool isModel = string_equal_nocase(name, "misc_model")
-    || string_equal_nocase(name, "misc_gamemodel")
+  bool isModel = (string_compare_nocase_n(name, "misc_", 5) == 0 && string_equal_nocase(name + string_length(name) - 5, "model")) // misc_*model (also misc_model)
     || string_equal_nocase(name, "model_static")
     || (GlobalSelectionSystem().countSelected() == 0 && string_equal_nocase(name, "func_static"));
 
@@ -246,7 +351,7 @@ void Entity_createFromSelection(const char* name, const Vector3& origin)
   entitypath.push(makeReference(node.get()));
   scene::Instance& instance = findInstance(entitypath);
 
-  if(entityClass->fixedsize)
+  if(entityClass->fixedsize || (isModel && !brushesSelected))
   {
     Select_Delete();
     
@@ -264,13 +369,13 @@ void Entity_createFromSelection(const char* name, const Vector3& origin)
   }
   else
   {
-    Scene_parentSelectedBrushesToEntity(GlobalSceneGraph(), node);
-    Scene_forEachChildSelectable(SelectableSetSelected(true), instance.path());
-
     if (g_pGameDescription->mGameType == "doom3")
     {
       Node_getEntity(node)->setKeyValue("model", Node_getEntity(node)->getKeyValue("name"));
     }
+
+    Scene_parentSelectedBrushesToEntity(GlobalSceneGraph(), node);
+    Scene_forEachChildSelectable(SelectableSetSelected(true), instance.path());
   }
 
   // tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box
@@ -330,7 +435,7 @@ void Entity_createFromSelection(const char* name, const Vector3& origin)
   }
 }
 
-
+#if 0
 bool DoNormalisedColor(Vector3& color)
 {
   if(!color_dialog(GTK_WIDGET(MainFrame_getWindow()), color))
@@ -365,13 +470,75 @@ bool DoNormalisedColor(Vector3& color)
 
   return true;
 }
+#endif 
+
+void NormalizeColor(Vector3& color)
+{
+  // scale colors so that at least one component is at 1.0F 
+
+  float largest = 0.0F;
+
+  if ( color[0] > largest )
+    largest = color[0];
+  if ( color[1] > largest )
+    largest = color[1];
+  if ( color[2] > largest )
+    largest = color[2];
+
+  if ( largest == 0.0F )
+  {
+    color[0] = 1.0F;
+    color[1] = 1.0F;
+    color[2] = 1.0F;
+  }
+  else
+  {
+    float scaler = 1.0F / largest;
+
+    color[0] *= scaler;
+    color[1] *= scaler;
+    color[2] *= scaler;
+  }
+}
+
+void Entity_normalizeColor()
+{
+       if(GlobalSelectionSystem().countSelected() != 0)
+       {
+               const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path();
+               Entity* entity = Node_getEntity(path.top());
+
+               if(entity != 0)
+               {
+                       const char* strColor = entity->getKeyValue("_color");
+                       if(!string_empty(strColor))
+                       {
+                               Vector3 rgb;
+                               if (string_parse_vector3(strColor, rgb))
+                               {
+                                       g_entity_globals.color_entity = rgb;
+                                       NormalizeColor(g_entity_globals.color_entity);
+
+                                       char buffer[128];
+                                       sprintf(buffer, "%g %g %g", g_entity_globals.color_entity[0],
+                                               g_entity_globals.color_entity[1],
+                                               g_entity_globals.color_entity[2]);
+
+                                       Scene_EntitySetKeyValue_Selected("_color", buffer);
+                               }
+                       }
+               }
+       }
+}
 
 void Entity_setColour()
 {
   if(GlobalSelectionSystem().countSelected() != 0)
   {
+       bool normalize = false;
     const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path();
     Entity* entity = Node_getEntity(path.top());
+
     if(entity != 0)
     {
       const char* strColor = entity->getKeyValue("_color");
@@ -384,17 +551,21 @@ void Entity_setColour()
         }
       }
 
-      if(g_pGameDescription->mGameType == "doom3"
-        ? color_dialog(GTK_WIDGET(MainFrame_getWindow()), g_entity_globals.color_entity)
-        : DoNormalisedColor(g_entity_globals.color_entity))
-      {
-        char buffer[128];
-        sprintf(buffer, "%g %g %g", g_entity_globals.color_entity[0],
-                g_entity_globals.color_entity[1],
-                g_entity_globals.color_entity[2]);
+         if( g_pGameDescription->mGameType == "doom3" )
+                 normalize = false;
 
-        Scene_EntitySetKeyValue_Selected("_color", buffer);
-      }
+         if(color_dialog(GTK_WIDGET(MainFrame_getWindow()), g_entity_globals.color_entity))
+         {
+                 if( normalize )
+                         NormalizeColor(g_entity_globals.color_entity);
+
+                 char buffer[128];
+                 sprintf(buffer, "%g %g %g", g_entity_globals.color_entity[0],
+                         g_entity_globals.color_entity[1],
+                         g_entity_globals.color_entity[2]);
+
+                 Scene_EntitySetKeyValue_Selected("_color", buffer);
+         }
     }
   }
 }
@@ -460,9 +631,12 @@ 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, "_KillConnect", "KillConnectSelection");
   create_menu_item_with_mnemonic(menu, "_Select Color...", "EntityColor");
+  create_menu_item_with_mnemonic(menu, "_Normalize Color...", "NormalizeColor");
 }
 
 
@@ -473,7 +647,10 @@ void Entity_constructMenu(GtkMenu* menu)
 void Entity_Construct()
 {
   GlobalCommands_insert("EntityColor", FreeCaller<Entity_setColour>(), Accelerator('K'));
+  GlobalCommands_insert("NormalizeColor", FreeCaller<Entity_normalizeColor>());
   GlobalCommands_insert("ConnectSelection", FreeCaller<Entity_connectSelected>(), Accelerator('K', (GdkModifierType)GDK_CONTROL_MASK));
+  GlobalCommands_insert("KillConnectSelection", FreeCaller<Entity_killconnectSelected>(), Accelerator('K', (GdkModifierType)(GDK_SHIFT_MASK)));
+  GlobalCommands_insert("GroupSelection", FreeCaller<Entity_groupSelected>());
   GlobalCommands_insert("UngroupSelection", FreeCaller<Entity_ungroupSelected>());
 
   GlobalPreferenceSystem().registerPreference("SI_Colors5", Vector3ImportStringCaller(g_entity_globals.color_entity), Vector3ExportStringCaller(g_entity_globals.color_entity));