- Radiant is now Vista compatible (Aero must be disabled)
[xonotic/netradiant.git] / plugins / entity / light.cpp
index 65aeeea0b8197b8c59ef558ca0ff896ef884d500..667b38b7c19b164f4104b73064e7dc1779fa3719 100644 (file)
@@ -52,6 +52,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include "render.h"
 #include "stringio.h"
 #include "traverselib.h"
+#include "dragplanes.h"
 
 #include "targetable.h"
 #include "origin.h"
@@ -536,25 +537,32 @@ public:
   typedef MemberCaller1<LightRadii, const char*, &LightRadii::flagsChanged> FlagsChangedCaller;
 };
 
-const Vector3 c_defaultDoom3LightRadius = Vector3(300, 300, 300);
 class Doom3LightRadius
 {
 public:
+  Vector3 m_defaultRadius;
   Vector3 m_radius;
+  Vector3 m_radiusTransformed;
   Vector3 m_center;
   Callback m_changed;
   bool m_useCenterKey;
 
-  Doom3LightRadius() : m_radius(c_defaultDoom3LightRadius), m_center(0, 0, 0), m_useCenterKey(false)
+  Doom3LightRadius(const char* defaultRadius) : m_defaultRadius(300, 300, 300), m_center(0, 0, 0), m_useCenterKey(false)
   {
+    if(!string_parse_vector3(defaultRadius, m_defaultRadius))
+    {
+      globalErrorStream() << "Doom3LightRadius: failed to parse default light radius\n";
+    }
+    m_radius = m_defaultRadius;
   }
 
   void lightRadiusChanged(const char* value)
   {
     if(!string_parse_vector3(value, m_radius))
     {
-      m_radius = c_defaultDoom3LightRadius;
+      m_radius = m_defaultRadius;
     }
+    m_radiusTransformed = m_radius;
     m_changed();
     SceneChangeNotify();
   }
@@ -900,6 +908,11 @@ class Light :
       m_traverse.detach(&m_traverseObservers);
     }
   }
+  
+// vc 2k5 compiler fix
+#if _MSC_VER >= 1400
+       public:
+#endif
 
   void updateOrigin()
   {
@@ -992,7 +1005,7 @@ class Light :
   void updateLightRadiiBox() const
   {
     const Matrix4& rotation = rotation_toMatrix(m_rotation);
-    aabb_corners(AABB(Vector3(0, 0, 0), m_doom3Radius.m_radius), m_radii_box.m_points);
+    aabb_corners(AABB(Vector3(0, 0, 0), m_doom3Radius.m_radiusTransformed), m_radii_box.m_points);
     matrix4_transform_point(rotation, m_radii_box.m_points[0]);
     vector3_add(m_radii_box.m_points[0], m_aabb_light.origin);
     matrix4_transform_point(rotation, m_radii_box.m_points[1]);
@@ -1040,6 +1053,7 @@ public:
     m_named(m_entity),
     m_nameKeys(m_entity),
     m_funcStaticOrigin(m_traverse, m_originKey.m_origin),
+    m_doom3Radius(EntityClass_valueForKey(m_entity.getEntityClass(), "light_radius")),
     m_radii_wire(m_radii, m_aabb_light.origin),
     m_radii_fill(m_radii, m_aabb_light.origin),
     m_radii_box(m_aabb_light.origin),
@@ -1063,6 +1077,7 @@ public:
     m_named(m_entity),
     m_nameKeys(m_entity),
     m_funcStaticOrigin(m_traverse, m_originKey.m_origin),
+    m_doom3Radius(EntityClass_valueForKey(m_entity.getEntityClass(), "light_radius")),
     m_radii_wire(m_radii, m_aabb_light.origin),
     m_radii_fill(m_radii, m_aabb_light.origin),
     m_radii_box(m_aabb_light.origin),
@@ -1277,10 +1292,20 @@ public:
       m_originKey.write(&m_entity);
     }
   }
+  void setLightRadius(const AABB& aabb)
+  {
+    m_aabb_light.origin = aabb.origin;
+    m_doom3Radius.m_radiusTransformed = aabb.extents;
+  }
+  void transformLightRadius(const Matrix4& transform)
+  {
+    matrix4_transform_point(transform, m_aabb_light.origin);
+  }
   void revertTransform()
   {
     m_aabb_light.origin = m_useLightOrigin ? m_lightOrigin : m_originKey.m_origin;
     rotation_assign(m_rotation, m_useLightRotation ? m_lightRotation : m_rotationKey.m_rotation);
+    m_doom3Radius.m_radiusTransformed = m_doom3Radius.m_radius;
   }
   void freezeTransform()
   {
@@ -1315,6 +1340,9 @@ public:
 
       rotation_assign(m_rotationKey.m_rotation, m_rotation);
       write_rotation(m_rotationKey.m_rotation, &m_entity);
+
+      m_doom3Radius.m_radius = m_doom3Radius.m_radiusTransformed;
+      write_origin(m_doom3Radius.m_radius, &m_entity, "light_radius");
     }
   }
   void transformChanged()
@@ -1340,7 +1368,7 @@ public:
 
   const AABB& aabb() const
   {
-    m_doom3AABB = AABB(m_aabb_light.origin, m_doom3Radius.m_radius);
+    m_doom3AABB = AABB(m_aabb_light.origin, m_doom3Radius.m_radiusTransformed);
     return m_doom3AABB;
   }
   bool testAABB(const AABB& other) const
@@ -1540,7 +1568,9 @@ class LightInstance :
   public TransformModifier,
   public Renderable,
   public SelectionTestable,
-  public RendererLight
+  public RendererLight,
+  public PlaneSelectable,
+  public ComponentSelectionTestable
 {
   class TypeCasts
   {
@@ -1554,6 +1584,8 @@ class LightInstance :
       InstanceStaticCast<LightInstance, Renderable>::install(m_casts);
       InstanceStaticCast<LightInstance, SelectionTestable>::install(m_casts);
       InstanceStaticCast<LightInstance, Transformable>::install(m_casts);
+      InstanceStaticCast<LightInstance, PlaneSelectable>::install(m_casts);
+      InstanceStaticCast<LightInstance, ComponentSelectionTestable>::install(m_casts);
       InstanceIdentityCast<LightInstance>::install(m_casts);
     }
     InstanceTypeCastTable& get()
@@ -1563,6 +1595,7 @@ class LightInstance :
   };
 
   Light& m_contained;
+  DragPlanes m_dragPlanes;// dragplanes for lightresizing using mousedrag
 public:
   typedef LazyStatic<TypeCasts> StaticTypeCasts;
 
@@ -1576,7 +1609,8 @@ public:
   LightInstance(const scene::Path& path, scene::Instance* parent, Light& contained) :
     TargetableInstance(path, parent, this, StaticTypeCasts::instance().get(), contained.getEntity(), *this),
     TransformModifier(Light::TransformChangedCaller(contained), ApplyTransformCaller(*this)),
-    m_contained(contained)
+    m_contained(contained),
+    m_dragPlanes(SelectedChangedComponentCaller(*this))
   {
     m_contained.instanceAttach(Instance::path());
 
@@ -1613,6 +1647,38 @@ public:
     m_contained.testSelect(selector, test, Instance::localToWorld());
   }
 
+  void selectPlanes(Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback)
+  {
+    test.BeginMesh(localToWorld());
+    m_dragPlanes.selectPlanes(m_contained.aabb(), selector, test, selectedPlaneCallback, rotation());
+  }
+  void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes)
+  {
+    m_dragPlanes.selectReversedPlanes(m_contained.aabb(), selector, selectedPlanes, rotation());
+  }
+  
+  bool isSelectedComponents() const
+  {
+    return m_dragPlanes.isSelected();
+  }
+  void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode)
+  {
+    if(mode == SelectionSystem::eFace)
+    {
+      m_dragPlanes.setSelected(false);
+    }
+  }
+  void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
+  {
+  }
+
+  void selectedChangedComponent(const Selectable& selectable)
+  {
+    GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable);
+    GlobalSelectionSystem().onComponentSelection(*this, selectable);
+  }
+  typedef MemberCaller1<LightInstance, const Selectable&, &LightInstance::selectedChangedComponent> SelectedChangedComponentCaller;
+
   void evaluateTransform()
   {
     if(getType() == TRANSFORM_PRIMITIVE)
@@ -1620,6 +1686,13 @@ public:
       m_contained.translate(getTranslation());
       m_contained.rotate(getRotation());
     }
+    else
+    {
+      //globalOutputStream() << getTranslation() << "\n";
+
+      m_dragPlanes.m_bounds = m_contained.aabb();
+      m_contained.setLightRadius(m_dragPlanes.evaluateResize(getTranslation(), rotation()));
+    }
   }
   void applyTransform()
   {