Browse Source

A few convenience methods that allow for cleaner code in GSGs

rdb 10 years ago
parent
commit
b4bfe7010c

+ 35 - 37
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -3146,7 +3146,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     // buffers are unbound, or the nVidia drivers may crash.
     unbind_buffers();
 
-    GeomContext *gc = ((Geom *)geom_reader->get_object())->prepare_now(get_prepared_objects(), this);
+    GeomContext *gc = geom_reader->prepare_now(get_prepared_objects(), this);
     nassertr(gc != (GeomContext *)NULL, false);
     CLP(GeomContext) *ggc = DCAST(CLP(GeomContext), gc);
     const CLP(GeomMunger) *gmunger = DCAST(CLP(GeomMunger), _munger);
@@ -4845,7 +4845,7 @@ setup_array_data(const unsigned char *&client_pointer,
   }
 
   // Prepare the buffer object and bind it.
-  VertexBufferContext *vbc = ((GeomVertexArrayData *)array_reader->get_object())->prepare_now(get_prepared_objects(), this);
+  VertexBufferContext *vbc = array_reader->prepare_now(get_prepared_objects(), this);
   nassertr(vbc != (VertexBufferContext *)NULL, false);
   if (!apply_vertex_buffer(vbc, array_reader, force)) {
     return false;
@@ -5039,7 +5039,7 @@ setup_primitive(const unsigned char *&client_pointer,
   }
 
   // Prepare the buffer object and bind it.
-  IndexBufferContext *ibc = ((GeomPrimitive *)reader->get_object())->prepare_now(get_prepared_objects(), this);
+  IndexBufferContext *ibc = reader->prepare_now(get_prepared_objects(), this);
   nassertr(ibc != (IndexBufferContext *)NULL, false);
   if (!apply_index_buffer(ibc, reader, force)) {
     return false;
@@ -5709,8 +5709,8 @@ do_issue_transform() {
 void CLP(GraphicsStateGuardian)::
 do_issue_shade_model() {
 #ifndef OPENGLES_2
-  const ShadeModelAttrib *target_shade_model = (const ShadeModelAttrib *)
-    _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot());
+  const ShadeModelAttrib *target_shade_model;
+  _target_rs->get_attrib_def(target_shade_model);
 
   switch (target_shade_model->get_mode()) {
   case ShadeModelAttrib::M_smooth:
@@ -5794,8 +5794,8 @@ do_issue_shader(bool state_has_changed) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_render_mode() {
-  const RenderModeAttrib *target_render_mode = (const RenderModeAttrib *)
-    _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot());
+  const RenderModeAttrib *target_render_mode;
+  _target_rs->get_attrib_def(target_render_mode);
 
   _render_mode = target_render_mode->get_mode();
   _point_size = target_render_mode->get_thickness();
@@ -5840,8 +5840,8 @@ do_issue_render_mode() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_antialias() {
-  const AntialiasAttrib *target_antialias = (const AntialiasAttrib *)
-    _target_rs->get_attrib_def(AntialiasAttrib::get_class_slot());
+  const AntialiasAttrib *target_antialias;
+  _target_rs->get_attrib_def(target_antialias);
 
   if (target_antialias->get_mode_type() == AntialiasAttrib::M_auto) {
     // In this special mode, we must enable antialiasing on a
@@ -5908,8 +5908,8 @@ do_issue_antialias() {
 void CLP(GraphicsStateGuardian)::
 do_issue_rescale_normal() {
 #ifndef OPENGLES_2 // OpenGL ES 2.0 doesn't support rescaling normals.
-  const RescaleNormalAttrib *target_rescale_normal = (const RescaleNormalAttrib *)
-    _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot());
+  const RescaleNormalAttrib *target_rescale_normal;
+  _target_rs->get_attrib_def(target_rescale_normal);
 
   RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
 
@@ -5962,8 +5962,8 @@ do_issue_rescale_normal() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_depth_test() {
-  const DepthTestAttrib *target_depth_test = (const DepthTestAttrib *)
-    _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot());
+  const DepthTestAttrib *target_depth_test;
+  _target_rs->get_attrib_def(target_depth_test);
 
   DepthTestAttrib::PandaCompareFunc mode = target_depth_test->get_mode();
   if (mode == DepthTestAttrib::M_none) {
@@ -5985,8 +5985,8 @@ do_issue_alpha_test() {
   if (_target_shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) {
     enable_alpha_test(false);
   } else {
-    const AlphaTestAttrib *target_alpha_test = (const AlphaTestAttrib *)
-      _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot());
+    const AlphaTestAttrib *target_alpha_test;
+    _target_rs->get_attrib_def(target_alpha_test);
 
     AlphaTestAttrib::PandaCompareFunc mode = target_alpha_test->get_mode();
     if (mode == AlphaTestAttrib::M_none) {
@@ -6008,8 +6008,8 @@ do_issue_alpha_test() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_depth_write() {
-  const DepthWriteAttrib *target_depth_write = (const DepthWriteAttrib *)
-    _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot());
+  const DepthWriteAttrib *target_depth_write;
+  _target_rs->get_attrib_def(target_depth_write);
 
   DepthWriteAttrib::Mode mode = target_depth_write->get_mode();
   if (mode == DepthWriteAttrib::M_off) {
@@ -6035,8 +6035,8 @@ do_issue_depth_write() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_cull_face() {
-  const CullFaceAttrib *target_cull_face = (const CullFaceAttrib *)
-    _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot());
+  const CullFaceAttrib *target_cull_face;
+  _target_rs->get_attrib_def(target_cull_face);
 
   CullFaceAttrib::Mode mode = target_cull_face->get_effective_mode();
 
@@ -6067,8 +6067,8 @@ do_issue_cull_face() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_fog() {
-  const FogAttrib *target_fog = (const FogAttrib *)
-    _target_rs->get_attrib_def(FogAttrib::get_class_slot());
+  const FogAttrib *target_fog;
+  _target_rs->get_attrib_def(target_fog);
 
   if (!target_fog->is_off()) {
     enable_fog(true);
@@ -6131,8 +6131,8 @@ do_issue_material() {
   static Material empty;
   const Material *material;
 
-  const MaterialAttrib *target_material = (const MaterialAttrib *)
-    _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
+  const MaterialAttrib *target_material;
+  _target_rs->get_attrib_def(target_material);
 
   if (target_material == (MaterialAttrib *)NULL ||
       target_material->is_off()) {
@@ -6239,8 +6239,8 @@ do_issue_blending() {
   // all the other blending-related stuff doesn't matter.  If the
   // device doesn't support color-write, we use blending tricks
   // to effectively disable color write.
-  const ColorWriteAttrib *target_color_write = (const ColorWriteAttrib *)
-    _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot());
+  const ColorWriteAttrib *target_color_write;
+  _target_rs->get_attrib_def(target_color_write);
 
   unsigned int color_channels =
     target_color_write->get_channels() & _color_write_mask;
@@ -6270,13 +6270,13 @@ do_issue_blending() {
   }
 
 
-  const ColorBlendAttrib *target_color_blend = (const ColorBlendAttrib *)
-    _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot());
+  const ColorBlendAttrib *target_color_blend;
+  _target_rs->get_attrib_def(target_color_blend);
   CPT(ColorBlendAttrib) color_blend = target_color_blend;
   ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode();
 
-  const TransparencyAttrib *target_transparency = (const TransparencyAttrib *)
-    _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot());
+  const TransparencyAttrib *target_transparency;
+  _target_rs->get_attrib_def(target_transparency);
   TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode();
 
   _color_blend_involves_color_scale = color_blend->involves_color_scale();
@@ -9636,8 +9636,8 @@ do_issue_tex_matrix() {
 
     glMatrixMode(GL_TEXTURE);
 
-    const TexMatrixAttrib *target_tex_matrix = (const TexMatrixAttrib *)
-      _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot());
+    const TexMatrixAttrib *target_tex_matrix;
+    _target_rs->get_attrib_def(target_tex_matrix);
 
     if (target_tex_matrix->has_stage(stage)) {
       GLPf(LoadMatrix)(target_tex_matrix->get_mat(stage).get_data());
@@ -11959,10 +11959,8 @@ do_issue_stencil() {
     return;
   }
 
-  const StencilAttrib *stencil = (const StencilAttrib *)
-    _target_rs->get_attrib(StencilAttrib::get_class_slot());
-
-  if (stencil != (const StencilAttrib *)NULL) {
+  const StencilAttrib *stencil;
+  if (_target_rs->get_attrib(stencil)) {
     // DEBUG
     if (false) {
       GLCAT.debug() << "STENCIL STATE CHANGE\n";
@@ -12052,8 +12050,8 @@ do_issue_stencil() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 do_issue_scissor() {
-  const ScissorAttrib *target_scissor = (const ScissorAttrib *)
-    _target_rs->get_attrib_def(ScissorAttrib::get_class_slot());
+  const ScissorAttrib *target_scissor;
+  _target_rs->get_attrib_def(target_scissor);
 
   if (!target_scissor->is_off()) {
     // A non-off ScissorAttrib means to override the scissor setting

+ 22 - 0
panda/src/gobj/geom.I

@@ -800,6 +800,28 @@ get_modified() const {
   return _cdata->_modified;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPipelineReader::prepare_now
+//       Access: Public
+//  Description: Creates a context for the geom on the particular
+//               GSG, if it does not already exist.  Returns the new
+//               (or old) GeomContext.  This assumes that the
+//               GraphicsStateGuardian is the currently active
+//               rendering context and that it is ready to accept new
+//               geoms.  If this is not necessarily the case, you
+//               should use prepare() instead.
+//
+//               Normally, this is not called directly except by the
+//               GraphicsStateGuardian; a geom does not need to be
+//               explicitly prepared by the user before it may be
+//               rendered.
+////////////////////////////////////////////////////////////////////
+INLINE GeomContext *GeomPipelineReader::
+prepare_now(PreparedGraphicsObjects *prepared_objects,
+            GraphicsStateGuardianBase *gsg) const {
+  return ((Geom *)_object.p())->prepare_now(prepared_objects, gsg);
+}
+
 INLINE ostream &
 operator << (ostream &out, const Geom &obj) {
   obj.output(out);

+ 3 - 0
panda/src/gobj/geom.h

@@ -424,6 +424,9 @@ public:
 
   bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
 
+  INLINE GeomContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
+                                  GraphicsStateGuardianBase *gsg) const;
+
   bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
             const GeomVertexDataPipelineReader *data_reader,
             bool force) const;

+ 26 - 15
panda/src/gobj/geomPrimitive.I

@@ -512,7 +512,7 @@ CData(const GeomPrimitive::CData &copy) :
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE GeomPrimitivePipelineReader::
-GeomPrimitivePipelineReader(const GeomPrimitive *object, 
+GeomPrimitivePipelineReader(const GeomPrimitive *object,
                             Thread *current_thread) :
   _object(object),
   _current_thread(current_thread),
@@ -594,7 +594,7 @@ get_current_thread() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_shade_model
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE GeomPrimitivePipelineReader::ShadeModel GeomPrimitivePipelineReader::
 get_shade_model() const {
@@ -604,7 +604,7 @@ get_shade_model() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_usage_hint
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE GeomPrimitivePipelineReader::UsageHint GeomPrimitivePipelineReader::
 get_usage_hint() const {
@@ -614,7 +614,7 @@ get_usage_hint() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_index_type
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE GeomPrimitivePipelineReader::NumericType GeomPrimitivePipelineReader::
 get_index_type() const {
@@ -624,7 +624,7 @@ get_index_type() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::is_indexed
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomPrimitivePipelineReader::
 is_indexed() const {
@@ -634,7 +634,7 @@ is_indexed() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_num_vertices
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitivePipelineReader::
 get_num_vertices() const {
@@ -649,7 +649,7 @@ get_num_vertices() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_min_vertex
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitivePipelineReader::
 get_min_vertex() const {
@@ -660,7 +660,7 @@ get_min_vertex() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_max_vertex
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitivePipelineReader::
 get_max_vertex() const {
@@ -682,7 +682,7 @@ get_data_size_bytes() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_modified
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE UpdateSeq GeomPrimitivePipelineReader::
 get_modified() const {
@@ -692,7 +692,7 @@ get_modified() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_index_stride
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitivePipelineReader::
 get_index_stride() const {
@@ -703,7 +703,7 @@ get_index_stride() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_vertices_reader
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE const GeomVertexArrayDataHandle *GeomPrimitivePipelineReader::
 get_vertices_reader() const {
@@ -713,7 +713,7 @@ get_vertices_reader() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_read_pointer
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE const unsigned char *GeomPrimitivePipelineReader::
 get_read_pointer(bool force) const {
@@ -733,7 +733,7 @@ get_strip_cut_index() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_ends
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE CPTA_int GeomPrimitivePipelineReader::
 get_ends() const {
@@ -743,7 +743,7 @@ get_ends() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_mins
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE CPT(GeomVertexArrayData) GeomPrimitivePipelineReader::
 get_mins() const {
@@ -755,7 +755,7 @@ get_mins() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_maxs
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE CPT(GeomVertexArrayData) GeomPrimitivePipelineReader::
 get_maxs() const {
@@ -764,6 +764,17 @@ get_maxs() const {
   return _cdata->_maxs.get_read_pointer();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPrimitivePipelineReader::prepare_now
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE IndexBufferContext *GeomPrimitivePipelineReader::
+prepare_now(PreparedGraphicsObjects *prepared_objects,
+            GraphicsStateGuardianBase *gsg) const {
+  return ((GeomPrimitive *)_object.p())->prepare_now(prepared_objects, gsg);
+}
+
 INLINE ostream &
 operator << (ostream &out, const GeomPrimitive &obj) {
   obj.output(out);

+ 3 - 0
panda/src/gobj/geomPrimitive.h

@@ -374,6 +374,9 @@ public:
   INLINE CPT(GeomVertexArrayData) get_mins() const;
   INLINE CPT(GeomVertexArrayData) get_maxs() const;
 
+  INLINE IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
+                                         GraphicsStateGuardianBase *gsg) const;
+
 private:
   CPT(GeomPrimitive) _object;
   Thread *_current_thread;

+ 31 - 9
panda/src/gobj/geomVertexArrayData.I

@@ -183,7 +183,7 @@ request_resident() const {
 INLINE CPT(GeomVertexArrayDataHandle) GeomVertexArrayData::
 get_handle(Thread *current_thread) const {
   const CData *cdata = _cycler.read_unlocked(current_thread);
-  return new GeomVertexArrayDataHandle(this, current_thread, 
+  return new GeomVertexArrayDataHandle(this, current_thread,
                                        cdata, false);
 }
 
@@ -199,7 +199,7 @@ get_handle(Thread *current_thread) const {
 INLINE PT(GeomVertexArrayDataHandle) GeomVertexArrayData::
 modify_handle(Thread *current_thread) {
   CData *cdata = _cycler.write_upstream(true, current_thread);
-  return new GeomVertexArrayDataHandle(this, current_thread, 
+  return new GeomVertexArrayDataHandle(this, current_thread,
                                        cdata, true);
 }
 
@@ -298,7 +298,7 @@ operator = (const GeomVertexArrayData::CData &copy) {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataHandle::
-GeomVertexArrayDataHandle(const GeomVertexArrayData *object, 
+GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
                           Thread *current_thread,
                           const GeomVertexArrayData::CData *cdata,
                           bool writable) :
@@ -421,7 +421,7 @@ get_object() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_array_format
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE const GeomVertexArrayFormat *GeomVertexArrayDataHandle::
 get_array_format() const {
@@ -431,7 +431,7 @@ get_array_format() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_usage_hint
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataHandle::UsageHint GeomVertexArrayDataHandle::
 get_usage_hint() const {
@@ -441,7 +441,7 @@ get_usage_hint() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_num_rows
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomVertexArrayDataHandle::
 get_num_rows() const {
@@ -452,7 +452,7 @@ get_num_rows() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::clear_rows
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexArrayDataHandle::
 clear_rows() {
@@ -462,7 +462,7 @@ clear_rows() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_data_size_bytes
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomVertexArrayDataHandle::
 get_data_size_bytes() const {
@@ -472,7 +472,7 @@ get_data_size_bytes() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_modified
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE UpdateSeq GeomVertexArrayDataHandle::
 get_modified() const {
@@ -493,6 +493,28 @@ request_resident() const {
   return (get_read_pointer(false) != (const unsigned char *)NULL);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexArrayDataHandle::prepare_now
+//       Access: Public
+//  Description: Creates a context for the data on the particular
+//               GSG, if it does not already exist.  Returns the new
+//               (or old) VertexBufferContext.  This assumes that the
+//               GraphicsStateGuardian is the currently active
+//               rendering context and that it is ready to accept new
+//               datas.  If this is not necessarily the case, you
+//               should use prepare() instead.
+//
+//               Normally, this is not called directly except by the
+//               GraphicsStateGuardian; a data does not need to be
+//               explicitly prepared by the user before it may be
+//               rendered.
+////////////////////////////////////////////////////////////////////
+INLINE VertexBufferContext *GeomVertexArrayDataHandle::
+prepare_now(PreparedGraphicsObjects *prepared_objects,
+            GraphicsStateGuardianBase *gsg) const {
+  return _object->prepare_now(prepared_objects, gsg);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexArrayDataHandle::get_data
 //       Access: Published

+ 11 - 8
panda/src/gobj/geomVertexArrayData.h

@@ -104,7 +104,7 @@ PUBLISHED:
   void prepare(PreparedGraphicsObjects *prepared_objects);
   bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
 
-  VertexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
+  VertexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
                                    GraphicsStateGuardianBase *gsg);
   bool release(PreparedGraphicsObjects *prepared_objects);
   int release_all();
@@ -127,7 +127,7 @@ private:
   INLINE void set_lru_size(size_t lru_size);
 
   void clear_prepared(PreparedGraphicsObjects *prepared_objects);
-  void reverse_data_endianness(unsigned char *dest, 
+  void reverse_data_endianness(unsigned char *dest,
                                const unsigned char *source, size_t size);
 
 
@@ -174,7 +174,7 @@ private:
     // This implements read-write locking.  Anyone who gets the data for
     // reading or writing will hold this mutex during the lock.
     ReMutex _rw_lock;
-    
+
   public:
     static TypeHandle get_class_type() {
       return _type_handle;
@@ -182,7 +182,7 @@ private:
     static void init_type() {
       register_type(_type_handle, "GeomVertexArrayData::CData");
     }
-    
+
   private:
     static TypeHandle _type_handle;
 
@@ -253,13 +253,13 @@ private:
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_GOBJ GeomVertexArrayDataHandle : public ReferenceCount, public GeomEnums {
 private:
-  INLINE GeomVertexArrayDataHandle(const GeomVertexArrayData *object, 
+  INLINE GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
                                    Thread *current_thread,
-                                   const GeomVertexArrayData::CData *_cdata, 
+                                   const GeomVertexArrayData::CData *_cdata,
                                    bool writable);
   INLINE GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle &);
   INLINE void operator = (const GeomVertexArrayDataHandle &);
-  
+
 PUBLISHED:
   INLINE ~GeomVertexArrayDataHandle();
 
@@ -289,6 +289,9 @@ PUBLISHED:
 
   INLINE bool request_resident() const;
 
+  INLINE VertexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
+                                          GraphicsStateGuardianBase *gsg) const;
+
   void copy_data_from(const GeomVertexArrayDataHandle *other);
   void copy_subdata_from(size_t to_start, size_t to_size,
                          const GeomVertexArrayDataHandle *other,
@@ -312,7 +315,7 @@ PUBLISHED:
   void set_subdata(size_t start, size_t size, const string &data);
 
   INLINE void mark_used() const;
-  
+
 private:
   PT(GeomVertexArrayData) _object;
   Thread *_current_thread;

+ 32 - 4
panda/src/pgraph/renderState.I

@@ -513,7 +513,7 @@ consider_update_pstats(int old_referenced_bits) const {
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::Composition::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::Composition::
 Composition() {
@@ -522,7 +522,7 @@ Composition() {
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::Composition::Copy Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::Composition::
 Composition(const RenderState::Composition &copy) :
@@ -545,7 +545,7 @@ Attribute(const RenderAttrib *attrib, int override) :
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::Attribute::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::Attribute::
 Attribute(int override) :
@@ -624,6 +624,34 @@ flush_level() {
   _cache_counter.flush_level();
 }
 
+#ifndef CPPPARSER
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_attrib
+//       Access: Public
+//  Description: Handy templated version of get_attrib that
+//               costs to the right type.  Returns true if the
+//               attribute was present, false otherwise.
+////////////////////////////////////////////////////////////////////
+template<class AttribType>
+INLINE bool RenderState::
+get_attrib(const AttribType *&attrib) const {
+  attrib = (const AttribType *)get_attrib((int)AttribType::get_class_slot());
+  return (attrib != (const AttribType *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: RenderState::get_attrib_def
+//       Access: Public
+//  Description: Handy templated version of get_attrib_def that
+//               costs to the right type.
+////////////////////////////////////////////////////////////////////
+template<class AttribType>
+INLINE void RenderState::
+get_attrib_def(const AttribType *&attrib) const {
+  attrib = (const AttribType *)get_attrib_def((int)AttribType::get_class_slot());
+}
+#endif  // CPPPARSER
+
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::check_hash
 //       Access: Private
@@ -677,7 +705,7 @@ calc_hash() {
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderState::CompositionCycleDescEntry::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE RenderState::CompositionCycleDescEntry::
 CompositionCycleDescEntry(const RenderState *obj,

+ 7 - 0
panda/src/pgraph/renderState.h

@@ -159,6 +159,13 @@ public:
 
   INLINE static void flush_level();
 
+#ifndef CPPPARSER
+  template<class AttribType>
+  INLINE bool get_attrib(const AttribType *&attrib) const;
+  template<class AttribType>
+  INLINE void get_attrib_def(const AttribType *&attrib) const;
+#endif  // CPPPARSER
+
 private:
   INLINE void check_hash() const;
   bool validate_filled_slots() const;