[Gtkradiant] r4797 - in GtkRadiant/trunk: docs/developer libs plugins/entity radiant

svn-noreply at zerowing.idsoftware.com svn-noreply at zerowing.idsoftware.com
Sat Sep 25 13:01:48 CDT 2004


Author: spog
Date: 2004-09-25 13:01:24 -0500 (Sat, 25 Sep 2004)
New Revision: 4797

Modified:
   GtkRadiant/trunk/docs/developer/CHANGES
   GtkRadiant/trunk/docs/developer/TODO
   GtkRadiant/trunk/libs/allocator.h
   GtkRadiant/trunk/libs/auto_array.h
   GtkRadiant/trunk/libs/entitylib.h
   GtkRadiant/trunk/plugins/entity/entity.cpp
   GtkRadiant/trunk/plugins/entity/static.cpp
   GtkRadiant/trunk/plugins/entity/static.h
   GtkRadiant/trunk/radiant/brush.h
   GtkRadiant/trunk/radiant/brush_primit.cpp
   GtkRadiant/trunk/radiant/brush_primit.h
   GtkRadiant/trunk/radiant/patch.h
Log:
curve control-point editing; BP texture-lock fixes

Modified: GtkRadiant/trunk/docs/developer/CHANGES
===================================================================
--- GtkRadiant/trunk/docs/developer/CHANGES	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/docs/developer/CHANGES	2004-09-25 18:01:24 UTC (rev 4797)
@@ -1,7 +1,13 @@
 This is the changelog for developers, != changelog for the end user 
 that we distribute with the binaries. (see changelog)
 
-20/09/2004
+25/09/2004
+SPoG
+- Added component-editing for curves on doom3 entities.
+- Added normalisation of translation for texture-lock on doom3 brushes.
+- Added update of surface inspector for texdef changes caused by texture-lock.
+
+21/09/2004
 Michael Schlueter
 - Changed file-chooser dialogs to use GtkFileChooser.
 

Modified: GtkRadiant/trunk/docs/developer/TODO
===================================================================
--- GtkRadiant/trunk/docs/developer/TODO	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/docs/developer/TODO	2004-09-25 18:01:24 UTC (rev 4797)
@@ -13,10 +13,12 @@
 Texture Browser: selecting a texture doesn't properly scroll the textures window to focus on that texture
 Shaders: pcx.m8 texture loading broken for heretic2
 UI: radiant fails to handle handle the key-up/key-down events when another combination is performed at about the same time (eg CTRL+D).
+texture-lock: faces end up with huge shift values somehow.
 
 
 HIGH priority features
 
+Brush: enable per-face filtering
 Brush: make edge/vertex/face dragging with QE tool select equal points
 Model: add support for doom3 md5anim format
 Model: support doom3 .skin files

Modified: GtkRadiant/trunk/libs/allocator.h
===================================================================
--- GtkRadiant/trunk/libs/allocator.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/libs/allocator.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -169,6 +169,30 @@
 
 #include <algorithm>
 
+template<typename Type, typename T1>
+class Construct
+{
+  const T1& t;
+public:
+  Construct(const T1& t_) : t(t_)
+  {
+  }
+  void operator()(Type& p)
+  {
+    new(&p) Type(t);
+  }
+};
+
+template<typename Type>
+class Destroy
+{
+public:
+  void operator()(Type& t)
+  {
+    t.~Type();
+  }
+};
+
 template<typename Type, typename Allocator = DefaultAllocator<Type> >
 class New : public Allocator
 {
@@ -208,22 +232,18 @@
   {
     return new(Allocator::allocate(size)) Type[size];
   }
+  template<typename T1>
+  Type* vector(std::size_t size, const T1& t1)
+  {
+    Type* p = reinterpret_cast<Type*>(Allocator::allocate(size));
+    std::for_each(p, p + size, Construct<Type, T1>(t1));
+    return p;
+  }
 };
 
 template<typename Type, typename Allocator = DefaultAllocator<Type> >
 class Delete : public Allocator
 {
-  class Destroy : public Allocator
-  {
-  public:
-    Destroy(const Allocator& allocator) : Allocator(allocator)
-    {
-    }
-    void operator()(Type& self)
-    {
-      self.~Type();
-    }
-  };
 public:
   Delete()
   {
@@ -244,7 +264,7 @@
   {
     if(p != 0)
     {
-      std::for_each(p, p + size, Destroy(*this));
+      std::for_each(p, p + size, Destroy<Type>());
       Allocator::deallocate(p, size);
     }
   }

Modified: GtkRadiant/trunk/libs/auto_array.h
===================================================================
--- GtkRadiant/trunk/libs/auto_array.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/libs/auto_array.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -22,6 +22,11 @@
     return new Element[size];
 #endif
   }
+  template<typename T1>
+  Element* construct(std::size_t size, const T1& value)
+  {
+    return New<Element, Allocator>(*this).vector(size, value);
+  }
   void destroy(Element* data, std::size_t size)
   {
 #if 1
@@ -44,6 +49,11 @@
     : m_size(size), m_data(construct(size))
   {
   }
+  template<typename T1>
+  auto_array(std::size_t size, const T1& value)
+    : m_size(size), m_data(construct(size, value))
+  {
+  }
   auto_array(const auto_array& other)
     : m_size(other.size()), m_data(construct(m_size))
   {
@@ -129,6 +139,14 @@
       temp.swap(*this);
     }
   }
+  void allocate(std::size_t count, const value_type& value)
+  {
+    if(count != size())
+    {
+      auto_array temp(count, value);
+      temp.swap(*this);
+    }
+  }
 };
 
 #endif

Modified: GtkRadiant/trunk/libs/entitylib.h
===================================================================
--- GtkRadiant/trunk/libs/entitylib.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/libs/entitylib.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -81,7 +81,7 @@
 
   Vector3 points[8];
   aabb_corners(aabb, points);
-  test.TestQuads(VertexPointer((VertexPointer::pointer)points, sizeof(Vector3)), IndexPointer(indices, 24), best);
+  test.TestQuads(VertexPointer(reinterpret_cast<VertexPointer::pointer>(points), sizeof(Vector3)), IndexPointer(indices, 24), best);
 }
 
 inline void aabb_draw_wire(const AABB& aabb)

Modified: GtkRadiant/trunk/plugins/entity/entity.cpp
===================================================================
--- GtkRadiant/trunk/plugins/entity/entity.cpp	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/plugins/entity/entity.cpp	2004-09-25 18:01:24 UTC (rev 4797)
@@ -366,11 +366,13 @@
 
   Entity_InitFilters(filterTable);
   Light_Construct(g_gameType == eGameTypeRTCW);
+  FuncStatic_construct();
   //RenderableTargetingEntity::m_state = GlobalShaderCache().Capture("$POINT");
 }
 
 void Entity_Destroy()
 {
+  FuncStatic_destroy();
   Light_Destroy();
   //GlobalShaderCache().Release("$POINT");
 }

Modified: GtkRadiant/trunk/plugins/entity/static.cpp
===================================================================
--- GtkRadiant/trunk/plugins/entity/static.cpp	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/plugins/entity/static.cpp	2004-09-25 18:01:24 UTC (rev 4797)
@@ -152,74 +152,322 @@
   globalOutputStream() << "t=1 basis=" << BSpline_basis(knots, point, degree, 1.0) << "\n";  
 }
 
-class NURBSCurve
+bool ControlPoints_parse(ControlPoints& controlPoints, const char* value)
 {
-public:
-  ControlPoints m_controlPoints;
-  NURBSWeights m_weights;
-  Knots m_knots;
-  RenderableCurve m_renderCurve;
+  StringTokeniser tokeniser(value, " ");
 
-  bool parseCurve(const char* value)
+  std::size_t size;
+  if(!string_parse_size(tokeniser.getToken(), size))
   {
-    StringTokeniser tokeniser(value, " ");
+    return false;
+  }
 
-    std::size_t size;
-    if(!string_parse_size(tokeniser.getToken(), size))
+  if(size < 3)
+  {
+    return false;
+  }
+  controlPoints.allocate(size);
+
+  if(!string_equal(tokeniser.getToken(), "("))
+  {
+    return false;
+  }
+  for(ControlPoints::iterator i = controlPoints.begin(); i != controlPoints.end(); ++i)
+  {
+    if(!string_parse_float(tokeniser.getToken(), (*i).x())
+      || !string_parse_float(tokeniser.getToken(), (*i).y())
+      || !string_parse_float(tokeniser.getToken(), (*i).z()))
     {
       return false;
     }
+  }
+  if(!string_equal(tokeniser.getToken(), ")"))
+  {
+    return false;
+  }
+  return true;
+}
 
-    if(size < 3)
+void ControlPoints_write(const ControlPoints& controlPoints, StringOutputStream& value)
+{
+  value << static_cast<unsigned int>(controlPoints.size()) << " (";
+  for(ControlPoints::const_iterator i = controlPoints.begin(); i != controlPoints.end(); ++i)
+  {
+    value << " " << (*i).x() << " " << (*i).y() << " " << (*i).z() << " ";
+  }
+  value << ")";
+}
+
+void ControlPoint_testSelect(const Vector3& point, ObservedSelectableInstance& selectable, Selector& selector, SelectionTest& test)
+{
+  select_point_t best;
+  test.TestPoint(point, best);
+  if(best.valid())
+  {
+    selector.pushSelectable(&selectable); 
+    selector.addIntersection(best);
+    selector.popSelectable();
+  }
+}
+
+class ControlPointTransform
+{
+  const Matrix4& m_matrix;
+public:
+  ControlPointTransform(const Matrix4& matrix) : m_matrix(matrix)
+  {
+  }
+  void operator()(Vector3& point) const
+  {
+    matrix4_transform_point(m_matrix, point);
+  }
+};
+
+class ControlPointSnap
+{
+  float m_snap;
+public:
+  ControlPointSnap(float snap) : m_snap(snap)
+  {
+  }
+  void operator()(Vector3& point) const
+  {
+    vector3_snap(point, m_snap);
+  }
+};
+
+const colour4b_t colour_vertex(0, 255, 0, 255);
+const colour4b_t colour_selected(0, 0, 255, 255);
+
+class ControlPointAdd
+{
+  RenderablePointVector& m_points;
+public:
+  ControlPointAdd(RenderablePointVector& points) : m_points(points)
+  {
+  }
+  void operator()(const Vector3& point)
+  {
+    m_points.push_back(PointVertex(vertex3f_for_vector3(point), colour_vertex));
+  }
+};
+
+class ControlPointAddSelected
+{
+  RenderablePointVector& m_points;
+public:
+  ControlPointAddSelected(RenderablePointVector& points) : m_points(points)
+  {
+  }
+  void operator()(const Vector3& point)
+  {
+    m_points.push_back(PointVertex(vertex3f_for_vector3(point), colour_selected));
+  }
+};
+
+class CurveEdit
+{
+  SelectionChangeClosure m_selectionChanged;
+  ControlPoints& m_controlPoints;
+  typedef auto_array<ObservedSelectableInstance> Selectables;
+  Selectables m_selectables;
+
+  RenderablePointVector m_controlsRender;
+  mutable RenderablePointVector m_selectedRender;
+
+public:
+  static Shader* m_controlsShader;
+  static Shader* m_selectedShader;
+
+  CurveEdit(ControlPoints& controlPoints, const SelectionChangeClosure& selectionChanged) :
+    m_selectionChanged(selectionChanged),
+    m_controlPoints(controlPoints),
+    m_controlsRender(GL_POINTS),
+    m_selectedRender(GL_POINTS)
+  {
+  }
+
+  template<typename Functor>
+  Functor& forEachSelected(Functor& functor)
+  {
+    RADIANT_ASSERT(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
+    ControlPoints::iterator p = m_controlPoints.begin();
+    for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
     {
-      return false;
+      if((*i).selected())
+      {
+        functor(*p);
+      }
     }
-    const int BSpline_degree = 3;
+    return functor;
+  }
+  template<typename Functor>
+  Functor& forEachSelected(Functor& functor) const
+  {
+    RADIANT_ASSERT(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
+    ControlPoints::const_iterator p = m_controlPoints.begin();
+    for(Selectables::const_iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
+    {
+      if((*i).selected())
+      {
+        functor(*p);
+      }
+    }
+    return functor;
+  }
+  template<typename Functor>
+  Functor& forEach(Functor& functor) const
+  {
+    for(ControlPoints::const_iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
+    {
+      functor(*i);
+    }
+    return functor;
+  }
 
-    m_weights.allocate(size);
-    for(NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i)
+  void testSelect(Selector& selector, SelectionTest& test)
+  {
+    RADIANT_ASSERT(m_controlPoints.size() == m_selectables.size(), "curve instance mismatch");
+    ControlPoints::const_iterator p = m_controlPoints.begin();
+    for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i, ++p)
     {
-      (*i) = 1;
+      ControlPoint_testSelect(*p, *i, selector, test);
     }
+  }
 
-    m_controlPoints.allocate(size);
-
-    if(!string_equal(tokeniser.getToken(), "("))
+  void select(bool selected)
+  {
+    for(Selectables::iterator i = m_selectables.begin(); i != m_selectables.end(); ++i)
     {
-      return false;
+      (*i).select(selected);
     }
-    for(ControlPoints::iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
+  }
+
+  void write(const char* key, Entity& entity)
+  {
+    StringOutputStream value(256);
+    if(!m_controlPoints.empty())
     {
-      if(!string_parse_float(tokeniser.getToken(), (*i).x())
-        || !string_parse_float(tokeniser.getToken(), (*i).y())
-        || !string_parse_float(tokeniser.getToken(), (*i).z()))
-      {
-        return false;
-      }
+      ControlPoints_write(m_controlPoints, value);
     }
-    if(!string_equal(tokeniser.getToken(), ")"))
+    entity.setkeyvalue(key, value.c_str());
+  }
+
+  void transform(const Matrix4& matrix)
+  {
+    forEachSelected(ControlPointTransform(matrix));
+  }
+  void snapto(float snap)
+  {
+    forEachSelected(ControlPointSnap(snap));
+  }
+
+  void updateSelected() const
+  {
+    m_selectedRender.clear();
+    forEachSelected(ControlPointAddSelected(m_selectedRender));
+  }
+  
+  void renderComponents(IRenderer* renderer, const VolumeTest& volume, const Matrix4& local2world) const
+  {
+    renderer->SetState(m_controlsShader, IRenderer::eWireframeOnly);
+    renderer->SetState(m_controlsShader, IRenderer::eFullMaterials);
+    renderer->Add(&m_controlsRender, local2world);
+
+    updateSelected();
+    if(!m_selectedRender.empty())
     {
-      return false;
+      renderer->SetState(m_selectedShader, IRenderer::eWireframeOnly);
+      renderer->SetState(m_selectedShader, IRenderer::eFullMaterials);
+      renderer->Add(&m_selectedRender, local2world);
     }
+  }
 
-    KnotVector_openUniform(m_knots, m_controlPoints.size(), BSpline_degree);
+  void curveChanged()
+  {
+    m_selectables.allocate(m_controlPoints.size(), m_selectionChanged);
 
-    const std::size_t numSegments = 64;
+    m_controlsRender.clear();
+    m_controlsRender.reserve(m_controlPoints.size());
+    forEach(ControlPointAdd(m_controlsRender));
+
+    m_selectedRender.reserve(m_controlPoints.size());
+  }
+  typedef MemberCaller<CurveEdit>::Caller<&CurveEdit::curveChanged> CurveChangedCaller;
+};
+
+Shader* CurveEdit::m_controlsShader;
+Shader* CurveEdit::m_selectedShader;
+
+
+
+const int NURBS_degree = 3;
+
+class NURBSCurve
+{
+  typedef std::set<Closure> Closures;
+  Closures m_curveChanged;
+  Closure m_boundsChanged;
+public:
+  ControlPoints m_controlPoints;
+  NURBSWeights m_weights;
+  Knots m_knots;
+  RenderableCurve m_renderCurve;
+  AABB m_bounds;
+
+  NURBSCurve(const Closure& boundsChanged) : m_boundsChanged(boundsChanged)
+  {
+  }
+
+  void attach(const Closure& curveChanged)
+  {
+    m_curveChanged.insert(curveChanged);
+    curveChanged();
+  }
+  void detach(const Closure& curveChanged)
+  {
+    m_curveChanged.erase(curveChanged);
+  }
+  void notify()
+  {
+    std::for_each(m_curveChanged.begin(), m_curveChanged.end(), ClosureInvoke());
+  }
+
+  void tesselate()
+  {
+    const std::size_t numSegments = m_controlPoints.size() * 16;
     m_renderCurve.m_vertices.resize(numSegments + 1);
     m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPoints[0]);
     for(std::size_t i = 1; i < numSegments; ++i)
     {
-      m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(NURBS_evaluate(m_controlPoints, m_weights, m_knots, BSpline_degree, (1.0 / double(numSegments)) * double(i)));
+      m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(NURBS_evaluate(m_controlPoints, m_weights, m_knots, NURBS_degree, (1.0 / double(numSegments)) * double(i)));
     }
     m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3(m_controlPoints[m_controlPoints.size() - 1]);
+  }
 
-    //plotBasisFunction(8, 0, BSpline_degree);
+  bool parseCurve(const char* value)
+  {
+    if(!ControlPoints_parse(m_controlPoints, value))
+    {
+      return false;
+    }
 
+    m_weights.allocate(m_controlPoints.size());
+    for(NURBSWeights::iterator i = m_weights.begin(); i != m_weights.end(); ++i)
+    {
+      (*i) = 1;
+    }
+
+    KnotVector_openUniform(m_knots, m_controlPoints.size(), NURBS_degree);
+
+    //plotBasisFunction(8, 0, NURBS_degree);
+
     return true;
   }
 
   void curveChanged(const char* value)
   {
+    m_bounds = AABB();
     if(string_empty(value) || !parseCurve(value))
     {
       m_controlPoints.allocate(0);
@@ -227,53 +475,52 @@
       m_weights.allocate(0);
       m_renderCurve.m_vertices.clear();
     }
+    else
+    {
+      tesselate();
+
+      for(ControlPoints::iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
+      {
+        aabb_extend_by_point_safe(m_bounds, (*i));
+      }
+      m_boundsChanged();
+    }
+    notify();
   }
   typedef MemberCaller1<NURBSCurve, const char*>::Caller<&NURBSCurve::curveChanged> CurveChangedCaller;
 };
 
 class CatmullRomSpline
 {
+  typedef std::set<Closure> Closures;
+  Closures m_curveChanged;
+  Closure m_boundsChanged;
 public:
   ControlPoints m_controlPoints;
   RenderableCurve m_renderCurve;
+  AABB m_bounds;
 
-  bool parseCurve(const char* value)
+  CatmullRomSpline(const Closure& boundsChanged) : m_boundsChanged(boundsChanged)
   {
-    StringTokeniser tokeniser(value, " ");
+  }
 
-    std::size_t size;
-    if(!string_parse_size(tokeniser.getToken(), size))
-    {
-      return false;
-    }
+  void attach(const Closure& curveChanged)
+  {
+    m_curveChanged.insert(curveChanged);
+    curveChanged();
+  }
+  void detach(const Closure& curveChanged)
+  {
+    m_curveChanged.erase(curveChanged);
+  }
+  void notify()
+  {
+    std::for_each(m_curveChanged.begin(), m_curveChanged.end(), ClosureInvoke());
+  }
 
-    if(size < 3)
-    {
-      return false;
-    }
-    const int spline_degree = 3;
-
-    m_controlPoints.allocate(size);
-
-    if(!string_equal(tokeniser.getToken(), "("))
-    {
-      return false;
-    }
-    for(ControlPoints::iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
-    {
-      if(!string_parse_float(tokeniser.getToken(), (*i).x())
-        || !string_parse_float(tokeniser.getToken(), (*i).y())
-        || !string_parse_float(tokeniser.getToken(), (*i).z()))
-      {
-        return false;
-      }
-    }
-    if(!string_equal(tokeniser.getToken(), ")"))
-    {
-      return false;
-    }
-
-    const std::size_t numSegments = 64;
+  void tesselate()
+  {
+    const std::size_t numSegments = m_controlPoints.size() * 16;
     m_renderCurve.m_vertices.resize(numSegments + 1);
     m_renderCurve.m_vertices[0].vertex = vertex3f_for_vector3(m_controlPoints[0]);
     for(std::size_t i = 1; i < numSegments; ++i)
@@ -281,22 +528,40 @@
       m_renderCurve.m_vertices[i].vertex = vertex3f_for_vector3(CatmullRom_evaluate(m_controlPoints, (1.0 / double(numSegments)) * double(i)));
     }
     m_renderCurve.m_vertices[numSegments].vertex = vertex3f_for_vector3(m_controlPoints[m_controlPoints.size() - 1]);
+  }
 
-    return true;
+  bool parseCurve(const char* value)
+  {
+    return ControlPoints_parse(m_controlPoints, value);
   }
 
   void curveChanged(const char* value)
   {
+    m_bounds = AABB();
     if(string_empty(value) || !parseCurve(value))
     {
       m_controlPoints.allocate(0);
       m_renderCurve.m_vertices.clear();
     }
+    else
+    {
+      tesselate();
+
+      for(ControlPoints::iterator i = m_controlPoints.begin(); i != m_controlPoints.end(); ++i)
+      {
+        aabb_extend_by_point_safe(m_bounds, (*i));
+      }
+      m_boundsChanged();
+    }
+    notify();
   }
   typedef MemberCaller1<CatmullRomSpline, const char*>::Caller<&CatmullRomSpline::curveChanged> CurveChangedCaller;
 };
 
-class FuncStatic : public Editable
+const char* const curve_Nurbs = "curve_Nurbs";
+const char* const curve_CatmullRomSpline = "curve_CatmullRomSpline";
+
+class FuncStatic : public Editable, public Bounded
 {
   EntityKeyValues m_entity;
   KeyObserverMap m_keyObservers;
@@ -313,8 +578,11 @@
   NamedEntity m_named;
   NameKeys m_nameKeys;
 
+public:
   NURBSCurve m_curveNURBS;
   CatmullRomSpline m_curveCatmullRom;
+private:
+  mutable AABB m_curveBounds;
 
   Closure m_transformChanged;
 
@@ -329,6 +597,7 @@
     m_node = node;
 
     node->m_edit = this;
+    node->m_cache = this;
     node->m_transform = &m_transform;
     node->m_traverse = &m_traverse;
     node->m_entity = &m_entity;
@@ -342,8 +611,8 @@
     m_keyObservers.insert("angle", Angle::AngleChangedCaller(m_angle));
     m_keyObservers.insert("rotation", Rotation::RotationChangedCaller(m_rotation));
     m_keyObservers.insert("name", NameChangedCaller(*this));
-    m_keyObservers.insert("curve_Nurbs", NURBSCurve::CurveChangedCaller(m_curveNURBS));
-    m_keyObservers.insert("curve_CatmullRomSpline", CatmullRomSpline::CurveChangedCaller(m_curveCatmullRom));
+    m_keyObservers.insert(curve_Nurbs, NURBSCurve::CurveChangedCaller(m_curveNURBS));
+    m_keyObservers.insert(curve_CatmullRomSpline, CatmullRomSpline::CurveChangedCaller(m_curveCatmullRom));
 
     m_isModel = false;
     m_nameKeys.setKeyIsName(keyIsNameDoom3FuncStatic);
@@ -463,7 +732,7 @@
   typedef MemberCaller<FuncStatic>::Caller<&FuncStatic::originChanged> OriginChangedCaller;
 
 public:
-  FuncStatic(EntityClass* eclass, scene::Node* node, const Closure& transformChanged) :
+  FuncStatic(EntityClass* eclass, scene::Node* node, const Closure& transformChanged, const Closure& boundsChanged) :
     m_entity(eclass),
     m_origin(OriginChangedCaller(*this)),
     m_angle(UpdateTransformCaller(*this)),
@@ -471,12 +740,14 @@
     m_filter(m_entity, node),
     m_named(m_entity),
     m_transformChanged(transformChanged),
+    m_curveNURBS(boundsChanged),
+    m_curveCatmullRom(boundsChanged),
     m_funcStaticOrigin(m_traverse, m_origin),
     m_nameKeys(m_entity)
   {
     construct(node);
   }
-  FuncStatic(const FuncStatic& other, scene::Node* node, const Closure& transformChanged) :
+  FuncStatic(const FuncStatic& other, scene::Node* node, const Closure& transformChanged, const Closure& boundsChanged) :
     m_entity(other.m_entity),
     m_origin(OriginChangedCaller(*this)),
     m_angle(UpdateTransformCaller(*this)),
@@ -484,6 +755,8 @@
     m_filter(m_entity, node),
     m_named(m_entity),
     m_transformChanged(transformChanged),
+    m_curveNURBS(boundsChanged),
+    m_curveCatmullRom(boundsChanged),
     m_funcStaticOrigin(m_traverse, m_origin),
     m_nameKeys(m_entity)
   {
@@ -536,6 +809,13 @@
     m_funcStaticOrigin.detach(observer);
   }
 
+  const AABB& aabb_local() const
+  {
+    m_curveBounds = m_curveNURBS.m_bounds;
+    aabb_extend_by_aabb_safe(m_curveBounds, m_curveCatmullRom.m_bounds);
+    return m_curveBounds;
+  }
+
   void render(IRenderer* renderer, const VolumeTest& volume, const Matrix4& local2world) const
   {
     renderer->SetState(m_entity.eclass().m_state_wire, IRenderer::eWireframeOnly);
@@ -551,6 +831,27 @@
     }
   }
 
+  void testSelect(Selector& selector, SelectionTest& test, select_point_t& best)
+  {
+    test.TestLineStrip(
+      VertexPointer(
+        reinterpret_cast<VertexPointer::pointer>(&m_curveNURBS.m_renderCurve.m_vertices[0].vertex),
+        sizeof(PointVertex)
+      ),
+      IndexPointer::index_type(m_curveNURBS.m_renderCurve.m_vertices.size()),
+      best
+    );
+
+    test.TestLineStrip(
+      VertexPointer(
+        reinterpret_cast<VertexPointer::pointer>(&m_curveCatmullRom.m_renderCurve.m_vertices[0].vertex),
+        sizeof(PointVertex)
+      ),
+      IndexPointer::index_type(m_curveCatmullRom.m_renderCurve.m_vertices.size()),
+      best
+    );
+  }
+
   // edit
   void translate(const Vector3& translation)
   {
@@ -575,17 +876,49 @@
   }
 };
 
-class FuncStaticInstance : public TargetableInstance, public Renderable
+class ControlPointAddBounds
 {
+  AABB& m_bounds;
+public:
+  ControlPointAddBounds(AABB& bounds) : m_bounds(bounds)
+  {
+  }
+  void operator()(const Vector3& point)
+  {
+    aabb_extend_by_point_safe(m_bounds, point);
+  }
+};
+
+class FuncStaticInstance :
+  public TargetableInstance,
+  public Renderable,
+  public Selectable,
+  public ComponentSelectable,
+  public ComponentEditable
+{
   FuncStatic& m_group;
+  CurveEdit m_curveNURBS;
+  CurveEdit m_curveCatmullRom;
+  mutable AABB m_aabb_component;
 public:
-  FuncStaticInstance(const scene::Path& path, scene::Instance* parent, FuncStatic& group) : TargetableInstance(path, parent, group.entity()), m_group(group)
+  FuncStaticInstance(const scene::Path& path, scene::Instance* parent, FuncStatic& group) :
+    TargetableInstance(path, parent, group.entity()),
+    m_group(group),
+    m_curveNURBS(m_group.m_curveNURBS.m_controlPoints, SelectionChangedComponentCaller(*this)),
+    m_curveCatmullRom(m_group.m_curveCatmullRom.m_controlPoints, SelectionChangedComponentCaller(*this))
   {
     scene::Instance::m_render = this;
+    scene::Instance::m_select = this;
+    scene::Instance::m_component_select = this;
+    scene::Instance::m_component_edit = this;
     m_group.instanceAttach(Instance::path());
+    m_group.m_curveNURBS.attach(CurveEdit::CurveChangedCaller(m_curveNURBS));
+    m_group.m_curveCatmullRom.attach(CurveEdit::CurveChangedCaller(m_curveCatmullRom));
   }
   ~FuncStaticInstance()
   {
+    m_group.m_curveCatmullRom.detach(CurveEdit::CurveChangedCaller(m_curveCatmullRom));
+    m_group.m_curveNURBS.detach(CurveEdit::CurveChangedCaller(m_curveNURBS));
     m_group.instanceDetach(Instance::path());
   }
   void renderSolid(IRenderer* renderer, const VolumeTest& volume) const
@@ -597,6 +930,101 @@
   {
     renderSolid(renderer, volume);
   }
+  void renderComponents(IRenderer* renderer, const VolumeTest& volume) const
+  {
+    if(GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex)
+    {
+      m_curveNURBS.renderComponents(renderer, volume, local2world());
+      m_curveCatmullRom.renderComponents(renderer, volume, local2world());
+    }
+  }
+
+  void testSelect(Selector& selector, SelectionTest& test)
+  {
+    test.BeginMesh(local2world());
+    select_point_t best;
+
+    m_group.testSelect(selector, test, best);
+
+    if(best.valid())
+    {
+      selector.pushSelectable(selectable()); 
+      selector.addIntersection(best);
+      selector.popSelectable();
+    }
+  }
+
+  void select_component(bool selected, SelectionSystem::EComponentMode mode)
+  {
+    if(mode == SelectionSystem::eVertex)
+    {
+      m_curveNURBS.select(selected);
+      m_curveCatmullRom.select(selected);
+    }
+  }
+  bool selected_component(SelectionSystem::EComponentMode mode) const
+  {
+    return false;
+  }
+  const AABB& aabb_component(SelectionSystem::EComponentMode mode) const
+  {
+    m_aabb_component = AABB();
+    m_curveNURBS.forEachSelected(ControlPointAddBounds(m_aabb_component));
+    m_curveCatmullRom.forEachSelected(ControlPointAddBounds(m_aabb_component));
+    return m_aabb_component;
+  }
+  void testSelect_component(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
+  {
+    if(mode == SelectionSystem::eVertex)
+    {
+      test.BeginMesh(local2world());
+      m_curveNURBS.testSelect(selector, test);
+      m_curveCatmullRom.testSelect(selector, test);
+    }
+  }
+
+  void transform_component(const Matrix4& matrix, SelectionSystem::EComponentMode mode)
+  {
+    if(mode == SelectionSystem::eVertex)
+    {
+      m_curveNURBS.transform(matrix);
+      m_curveNURBS.write(curve_Nurbs, m_group.entity());
+
+      m_curveCatmullRom.transform(matrix);
+      m_curveCatmullRom.write(curve_CatmullRomSpline, m_group.entity());
+    }
+  }
+
+  void translate_component(const Vector3& translation, SelectionSystem::EComponentMode mode)
+  {
+    transform_component(matrix4_translation_for_vec3(translation), mode);
+  }
+  void rotate_component(const Quaternion& rotation, SelectionSystem::EComponentMode mode)
+  {
+    transform_component(matrix4_rotation_for_quaternion_quantised(rotation), mode);
+  }
+  void scale_component(const Vector3& scaling, SelectionSystem::EComponentMode mode)
+  {
+    transform_component(matrix4_scale_for_vec3(scaling), mode);
+  }
+  void snapto_component(float snap, SelectionSystem::EComponentMode mode)
+  {
+    if(mode == SelectionSystem::eVertex)
+    {
+      m_curveNURBS.snapto(snap);
+      m_curveNURBS.write(curve_Nurbs, m_group.entity());
+
+      m_curveCatmullRom.snapto(snap);
+      m_curveCatmullRom.write(curve_CatmullRomSpline, m_group.entity());
+    }
+  }
+
+  void selectionChangedComponent(const SelectableInstance& selectable)
+  {
+    GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable);
+    GlobalSelectionSystem().onComponentSelection(*this, selectable);
+  }
+  typedef MemberCaller1<FuncStaticInstance, const SelectableInstance&>::Caller<&FuncStaticInstance::selectionChangedComponent> SelectionChangedComponentCaller;
 };
 
 class FuncStaticNode : public scene::Node::Symbiot, public scene::Instantiable, public scene::Cloneable, public scene::Traversable::Observer
@@ -621,13 +1049,13 @@
 public:
   FuncStaticNode(EntityClass* eclass) :
     m_node(this),
-    m_group(eclass, &m_node, Instances::TransformChangedCaller(m_instances))
+    m_group(eclass, &m_node, Instances::TransformChangedCaller(m_instances), Instances::BoundsChangedCaller(m_instances))
   {
     construct();
   }
   FuncStaticNode(const FuncStaticNode& other) :
     m_node(this),
-    m_group(other.m_group, &m_node, Instances::TransformChangedCaller(m_instances))
+    m_group(other.m_group, &m_node, Instances::TransformChangedCaller(m_instances), Instances::BoundsChangedCaller(m_instances))
   {
     construct();
   }
@@ -677,6 +1105,18 @@
   }
 };
 
+void FuncStatic_construct()
+{
+  CurveEdit::m_controlsShader = GlobalShaderCache().Capture("$POINT");
+  CurveEdit::m_selectedShader = GlobalShaderCache().Capture("$SELPOINT");
+}
+
+void FuncStatic_destroy()
+{
+  GlobalShaderCache().Release("$SELPOINT");
+  GlobalShaderCache().Release("$POINT");
+}
+
 scene::Node* New_FuncStatic(EntityClass* eclass)
 {
   return (new FuncStaticNode(eclass))->node();

Modified: GtkRadiant/trunk/plugins/entity/static.h
===================================================================
--- GtkRadiant/trunk/plugins/entity/static.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/plugins/entity/static.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -8,6 +8,8 @@
 }
 class EntityClass;
 
+void FuncStatic_construct();
+void FuncStatic_destroy();
 scene::Node* New_FuncStatic(EntityClass* eclass);
 
 #endif

Modified: GtkRadiant/trunk/radiant/brush.h
===================================================================
--- GtkRadiant/trunk/radiant/brush.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/radiant/brush.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -1042,6 +1042,7 @@
     if(g_brush_texturelock_enabled)
     {
       m_texdef.transform(m_plane.plane3(), matrix);
+      g_brush_texture_changed();
     }
 
     m_plane.transform(matrix, mirror);
@@ -1103,7 +1104,7 @@
 
   void testSelect(SelectionTest& test, select_point_t& best)
   {
-    test.TestPolygon(VertexPointer((VertexPointer::pointer)&m_winding.points.data()->vertex, sizeof(WindingVertex)), m_winding.numpoints, best);
+    test.TestPolygon(VertexPointer(reinterpret_cast<VertexPointer::pointer>(&m_winding.points.data()->vertex), sizeof(WindingVertex)), m_winding.numpoints, best);
   }
 
   void testSelect_centroid(SelectionTest& test, select_point_t& best)

Modified: GtkRadiant/trunk/radiant/brush_primit.cpp
===================================================================
--- GtkRadiant/trunk/radiant/brush_primit.cpp	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/radiant/brush_primit.cpp	2004-09-25 18:01:24 UTC (rev 4797)
@@ -191,14 +191,14 @@
   }
 }
 
-inline void BPTexdef_fromTransform(brushprimit_texdef_t& bp_texdef, const Matrix4& transform)
+inline void BPTexdef_fromTransform(brushprimit_texdef_t& bp_texdef, float width, float height, const Matrix4& transform)
 {
   bp_texdef.coords[0][0] = transform.xx();
   bp_texdef.coords[0][1] = transform.yx();
-  bp_texdef.coords[0][2] = transform.tx();
+  bp_texdef.coords[0][2] = float_mod(transform.tx(), 1.0f);
   bp_texdef.coords[1][0] = transform.xy();
   bp_texdef.coords[1][1] = transform.yy();
-  bp_texdef.coords[1][2] = transform.ty();
+  bp_texdef.coords[1][2] = float_mod(transform.ty(), 1.0f);
 }
 
 inline void Texdef_fromTransform(texdef_t& texdef, brushprimit_texdef_t& bp_texdef, float width, float height, const Matrix4& transform)
@@ -208,7 +208,7 @@
 
   if(g_bp_globals.m_bBrushPrimitMode)
   {
-    BPTexdef_fromTransform(bp_texdef, transform);
+    BPTexdef_fromTransform(bp_texdef, width, height, transform);
   }
   else
   {

Modified: GtkRadiant/trunk/radiant/brush_primit.h
===================================================================
--- GtkRadiant/trunk/radiant/brush_primit.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/radiant/brush_primit.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -2,6 +2,7 @@
 #if !defined(_INCLUDE_BRUSH_PRIMIT_H)
 #define _INCLUDE_BRUSH_PRIMIT_H
 
+#include "math/vector.h"
 // Timo
 // new brush primitive texdef
 struct brushprimit_texdef_t

Modified: GtkRadiant/trunk/radiant/patch.h
===================================================================
--- GtkRadiant/trunk/radiant/patch.h	2004-09-23 19:36:54 UTC (rev 4796)
+++ GtkRadiant/trunk/radiant/patch.h	2004-09-25 18:01:24 UTC (rev 4797)
@@ -1389,8 +1389,12 @@
   {
     m_render_selected.clear();
     for(ctrl_instances_t::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i)
+    {
       if((*i).m_selectable.selected())
+      {
         m_render_selected.push_back(PointVertex(reinterpret_cast<vertex3f_t&>((*i).m_ctrl->m_vertex), colour_selected));
+      }
+    }
   }
 
 #if 0
@@ -1479,8 +1483,12 @@
     m_aabb_component = AABB();
 
     for(ctrl_instances_t::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i)
+    {
       if((*i).m_selectable.selected())
+      {
         aabb_extend_by_point_safe(m_aabb_component, (*i).m_ctrl->m_vertex);
+      }
+    }
 
     return m_aabb_component;
   }




More information about the Gtkradiant mailing list