Browse Source

Add support for glLogicOp via LogicOpAttrib / NodePath::set_logic_op

rdb 9 years ago
parent
commit
82ab126ea7

+ 40 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -56,6 +56,7 @@
 #include "depthWriteAttrib.h"
 #include "depthWriteAttrib.h"
 #include "fogAttrib.h"
 #include "fogAttrib.h"
 #include "lightAttrib.h"
 #include "lightAttrib.h"
+#include "logicOpAttrib.h"
 #include "materialAttrib.h"
 #include "materialAttrib.h"
 #include "rescaleNormalAttrib.h"
 #include "rescaleNormalAttrib.h"
 #include "scissorAttrib.h"
 #include "scissorAttrib.h"
@@ -475,6 +476,7 @@ reset() {
   _inv_state_mask.clear_bit(TransparencyAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TransparencyAttrib::get_class_slot());
   _inv_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
   _inv_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
   _inv_state_mask.clear_bit(ColorBlendAttrib::get_class_slot());
   _inv_state_mask.clear_bit(ColorBlendAttrib::get_class_slot());
+  _inv_state_mask.clear_bit(LogicOpAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TexGenAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TexGenAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
   _inv_state_mask.clear_bit(TexMatrixAttrib::get_class_slot());
@@ -6631,6 +6633,34 @@ do_issue_material() {
 }
 }
 #endif  // SUPPORT_FIXED_FUNCTION
 #endif  // SUPPORT_FIXED_FUNCTION
 
 
+/**
+ * Issues the logic operation attribute to the GL.
+ */
+#if !defined(OPENGLES) || defined(OPENGLES_1)
+void CLP(GraphicsStateGuardian)::
+do_issue_logic_op() {
+  const LogicOpAttrib *target_logic_op;
+  _target_rs->get_attrib_def(target_logic_op);
+
+  if (target_logic_op->get_operation() != LogicOpAttrib::O_none) {
+    glEnable(GL_COLOR_LOGIC_OP);
+    glLogicOp(GL_CLEAR - 1 + (int)target_logic_op->get_operation());
+
+    if (GLCAT.is_spam()) {
+      GLCAT.spam() << "glEnable(GL_COLOR_LOGIC_OP)\n";
+      GLCAT.spam() << "glLogicOp(" << target_logic_op->get_operation() << ")\n";
+    }
+  } else {
+    glDisable(GL_COLOR_LOGIC_OP);
+    glLogicOp(GL_COPY);
+
+    if (GLCAT.is_spam()) {
+      GLCAT.spam() << "glDisable(GL_COLOR_LOGIC_OP)\n";
+    }
+  }
+}
+#endif
+
 /**
 /**
  *
  *
  */
  */
@@ -9660,6 +9690,16 @@ set_state_and_transform(const RenderState *target,
   }
   }
 #endif
 #endif
 
 
+#if !defined(OPENGLES) || defined(OPENGLES_1)
+  int logic_op_slot = LogicOpAttrib::get_class_slot();
+  if (_target_rs->get_attrib(logic_op_slot) != _state_rs->get_attrib(logic_op_slot) ||
+      !_state_mask.get_bit(logic_op_slot)) {
+    // PStatGPUTimer timer(this, _draw_set_state_logic_op_pcollector);
+    do_issue_logic_op();
+    _state_mask.set_bit(logic_op_slot);
+  }
+#endif
+
   int transparency_slot = TransparencyAttrib::get_class_slot();
   int transparency_slot = TransparencyAttrib::get_class_slot();
   int color_write_slot = ColorWriteAttrib::get_class_slot();
   int color_write_slot = ColorWriteAttrib::get_class_slot();
   int color_blend_slot = ColorBlendAttrib::get_class_slot();
   int color_blend_slot = ColorBlendAttrib::get_class_slot();

+ 3 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -405,6 +405,9 @@ protected:
   void do_issue_material();
   void do_issue_material();
 #endif
 #endif
   void do_issue_texture();
   void do_issue_texture();
+#if !defined(OPENGLES) || defined(OPENGLES_1)
+  void do_issue_logic_op();
+#endif
   void do_issue_blending();
   void do_issue_blending();
 #ifdef SUPPORT_FIXED_FUNCTION
 #ifdef SUPPORT_FIXED_FUNCTION
   void do_issue_tex_gen();
   void do_issue_tex_gen();

+ 3 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -50,6 +50,7 @@
 #include "loaderFileType.h"
 #include "loaderFileType.h"
 #include "loaderFileTypeBam.h"
 #include "loaderFileTypeBam.h"
 #include "loaderFileTypeRegistry.h"
 #include "loaderFileTypeRegistry.h"
+#include "logicOpAttrib.h"
 #include "materialAttrib.h"
 #include "materialAttrib.h"
 #include "modelFlattenRequest.h"
 #include "modelFlattenRequest.h"
 #include "modelLoadRequest.h"
 #include "modelLoadRequest.h"
@@ -419,6 +420,7 @@ init_libpgraph() {
   Loader::init_type();
   Loader::init_type();
   LoaderFileType::init_type();
   LoaderFileType::init_type();
   LoaderFileTypeBam::init_type();
   LoaderFileTypeBam::init_type();
+  LogicOpAttrib::init_type();
   MaterialAttrib::init_type();
   MaterialAttrib::init_type();
   ModelFlattenRequest::init_type();
   ModelFlattenRequest::init_type();
   ModelLoadRequest::init_type();
   ModelLoadRequest::init_type();
@@ -483,6 +485,7 @@ init_libpgraph() {
   LensNode::register_with_read_factory();
   LensNode::register_with_read_factory();
   LightAttrib::register_with_read_factory();
   LightAttrib::register_with_read_factory();
   LightRampAttrib::register_with_read_factory();
   LightRampAttrib::register_with_read_factory();
+  LogicOpAttrib::register_with_read_factory();
   MaterialAttrib::register_with_read_factory();
   MaterialAttrib::register_with_read_factory();
   ModelNode::register_with_read_factory();
   ModelNode::register_with_read_factory();
   ModelRoot::register_with_read_factory();
   ModelRoot::register_with_read_factory();

+ 29 - 0
panda/src/pgraph/logicOpAttrib.I

@@ -0,0 +1,29 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file logicOpAttrib.I
+ * @author rdb
+ * @date 2016-03-24
+ */
+
+/**
+ * Use LogicOpAttrib::make() to construct a new LogicOpAttrib object.
+ */
+INLINE LogicOpAttrib::
+LogicOpAttrib(LogicOpAttrib::Operation op) :
+  _op(op)
+{
+}
+
+/**
+ * Returns the logic operation specified by this attribute.
+ */
+INLINE LogicOpAttrib::Operation LogicOpAttrib::
+get_operation() const {
+  return _op;
+}

+ 205 - 0
panda/src/pgraph/logicOpAttrib.cxx

@@ -0,0 +1,205 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file logicOpAttrib.I
+ * @author rdb
+ * @date 2016-03-24
+ */
+
+#include "logicOpAttrib.h"
+#include "graphicsStateGuardianBase.h"
+#include "dcast.h"
+#include "bamReader.h"
+#include "bamWriter.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+
+TypeHandle LogicOpAttrib::_type_handle;
+int LogicOpAttrib::_attrib_slot;
+
+/**
+ * Constructs a new LogicOpAttrib object that disables special-effect
+ * blending, allowing normal transparency to be used instead.
+ */
+CPT(RenderAttrib) LogicOpAttrib::
+make_off() {
+  return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
+}
+
+/**
+ * Constructs a new LogicOpAttrib object with the given logic operation.
+ */
+CPT(RenderAttrib) LogicOpAttrib::
+make(LogicOpAttrib::Operation op) {
+  LogicOpAttrib *attrib = new LogicOpAttrib(op);
+  return return_new(attrib);
+}
+
+/**
+ * Returns a RenderAttrib that corresponds to whatever the standard default
+ * properties for render attributes of this type ought to be.
+ */
+CPT(RenderAttrib) LogicOpAttrib::
+make_default() {
+  return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
+}
+
+/**
+ *
+ */
+void LogicOpAttrib::
+output(ostream &out) const {
+  out << get_type() << ":" << get_operation();
+}
+
+/**
+ * Intended to be overridden by derived LogicOpAttrib types to return a
+ * unique number indicating whether this LogicOpAttrib is equivalent to the
+ * other one.
+ *
+ * This should return 0 if the two LogicOpAttrib objects are equivalent, a
+ * number less than zero if this one should be sorted before the other one,
+ * and a number greater than zero otherwise.
+ *
+ * This will only be called with two LogicOpAttrib objects whose get_type()
+ * functions return the same.
+ */
+int LogicOpAttrib::
+compare_to_impl(const RenderAttrib *other) const {
+  const LogicOpAttrib *la = (const LogicOpAttrib *)other;
+  return (int)_op - (int)la->_op;
+}
+
+/**
+ * Intended to be overridden by derived RenderAttrib types to return a unique
+ * hash for these particular properties.  RenderAttribs that compare the same
+ * with compare_to_impl(), above, should return the same hash; RenderAttribs
+ * that compare differently should return a different hash.
+ */
+size_t LogicOpAttrib::
+get_hash_impl() const {
+  size_t hash = 0;
+  hash = int_hash::add_hash(hash, (int)_op);
+  return hash;
+}
+
+/**
+ *
+ */
+CPT(RenderAttrib) LogicOpAttrib::
+get_auto_shader_attrib_impl(const RenderState *state) const {
+  return RenderAttribRegistry::quick_get_global_ptr()->get_slot_default(_attrib_slot);
+}
+
+/**
+ * Tells the BamReader how to create objects of type LogicOpAttrib.
+ */
+void LogicOpAttrib::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+/**
+ * Writes the contents of this object to the datagram for shipping out to a
+ * Bam file.
+ */
+void LogicOpAttrib::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  RenderAttrib::write_datagram(manager, dg);
+
+  dg.add_uint8(_op);
+}
+
+/**
+ * This function is called by the BamReader's factory when a new object of
+ * type LogicOpAttrib is encountered in the Bam file.  It should create the
+ * LogicOpAttrib and extract its information from the file.
+ */
+TypedWritable *LogicOpAttrib::
+make_from_bam(const FactoryParams &params) {
+  LogicOpAttrib *attrib = new LogicOpAttrib(O_none);
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  attrib->fillin(scan, manager);
+
+  return attrib;
+}
+
+/**
+ * This internal function is called by make_from_bam to read in all of the
+ * relevant data from the BamFile for the new LogicOpAttrib.
+ */
+void LogicOpAttrib::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  RenderAttrib::fillin(scan, manager);
+
+  _op = (Operation)scan.get_uint8();
+}
+
+/**
+ *
+ */
+ostream &
+operator << (ostream &out, LogicOpAttrib::Operation op) {
+  switch (op) {
+  case LogicOpAttrib::O_none:
+    return out << "none";
+
+  case LogicOpAttrib::O_clear:
+    return out << "clear";
+
+  case LogicOpAttrib::O_and:
+    return out << "and";
+
+  case LogicOpAttrib::O_and_reverse:
+    return out << "and_reverse";
+
+  case LogicOpAttrib::O_copy:
+    return out << "copy";
+
+  case LogicOpAttrib::O_and_inverted:
+    return out << "and_inverted";
+
+  case LogicOpAttrib::O_noop:
+    return out << "noop";
+
+  case LogicOpAttrib::O_xor:
+    return out << "xor";
+
+  case LogicOpAttrib::O_or:
+    return out << "or";
+
+  case LogicOpAttrib::O_nor:
+    return out << "nor";
+
+  case LogicOpAttrib::O_equivalent:
+    return out << "equivalent";
+
+  case LogicOpAttrib::O_invert:
+    return out << "invert";
+
+  case LogicOpAttrib::O_or_reverse:
+    return out << "or_reverse";
+
+  case LogicOpAttrib::O_copy_inverted:
+    return out << "copy_inverted";
+
+  case LogicOpAttrib::O_or_inverted:
+    return out << "or_inverted";
+
+  case LogicOpAttrib::O_nand:
+    return out << "nand";
+
+  case LogicOpAttrib::O_set:
+    return out << "set";
+  }
+
+  return out << "**invalid LogicOpAttrib::Operation(" << (int)op << ")**";
+}

+ 112 - 0
panda/src/pgraph/logicOpAttrib.h

@@ -0,0 +1,112 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file logicOpAttrib.I
+ * @author rdb
+ * @date 2016-03-24
+ */
+
+#ifndef LOGICOPATTRIB_H
+#define LOGICOPATTRIB_H
+
+#include "pandabase.h"
+#include "luse.h"
+#include "renderAttrib.h"
+
+class FactoryParams;
+
+/**
+ * If enabled, specifies that a custom logical operation be performed instead
+ * of any color blending.  Setting it to a value other than M_none will cause
+ * color blending to be disabled and the given logic operation to be performed.
+ */
+class EXPCL_PANDA_PGRAPH LogicOpAttrib : public RenderAttrib {
+PUBLISHED:
+  enum Operation {
+    O_none,  // LogicOp disabled, regular blending occurs.
+    O_clear, // Clears framebuffer value.
+    O_and,
+    O_and_reverse,
+    O_copy,  // Writes the incoming color to the framebuffer.
+    O_and_inverted,
+    O_noop,  // Leaves the framebuffer value unaltered.
+    O_xor,
+    O_or,
+    O_nor,
+    O_equivalent,
+    O_invert,
+    O_or_reverse,
+    O_copy_inverted,
+    O_or_inverted,
+    O_nand,
+    O_set,   // Sets all the bits in the framebuffer to 1.
+  };
+
+private:
+  INLINE LogicOpAttrib(Operation op);
+
+PUBLISHED:
+  static CPT(RenderAttrib) make_off();
+  static CPT(RenderAttrib) make(Operation op);
+  static CPT(RenderAttrib) make_default();
+
+  INLINE Operation get_operation() const;
+  MAKE_PROPERTY(operation, get_operation);
+
+public:
+  virtual void output(ostream &out) const;
+
+protected:
+  virtual int compare_to_impl(const RenderAttrib *other) const;
+  virtual size_t get_hash_impl() const;
+  virtual CPT(RenderAttrib) get_auto_shader_attrib_impl(const RenderState *state) const;
+
+private:
+  Operation _op;
+
+PUBLISHED:
+  static int get_class_slot() {
+    return _attrib_slot;
+  }
+  virtual int get_slot() const {
+    return get_class_slot();
+  }
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    RenderAttrib::init_type();
+    register_type(_type_handle, "LogicOpAttrib",
+                  RenderAttrib::get_class_type());
+    _attrib_slot = register_slot(_type_handle, 100, new LogicOpAttrib(O_none));
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+  static int _attrib_slot;
+};
+
+EXPCL_PANDA_PGRAPH ostream &operator << (ostream &out, LogicOpAttrib::Operation op);
+
+#include "logicOpAttrib.I"
+
+#endif

+ 56 - 0
panda/src/pgraph/nodePath.cxx

@@ -4832,6 +4832,62 @@ get_transparency() const {
   return TransparencyAttrib::M_none;
   return TransparencyAttrib::M_none;
 }
 }
 
 
+/**
+ * Specifically sets or disables a logical operation on this particular node.
+ * If no other nodes override, this will cause geometry to be rendered without
+ * color blending but instead using the given logical operator.
+ */
+void NodePath::
+set_logic_op(LogicOpAttrib::Operation op, int priority) {
+  nassertv_always(!is_empty());
+
+  node()->set_attrib(LogicOpAttrib::make(op), priority);
+}
+
+/**
+ * Completely removes any logical operation that may have been set on this
+ * node via set_logic_op(). The geometry at this level and below will
+ * subsequently be rendered using standard color blending.
+ */
+void NodePath::
+clear_logic_op() {
+  nassertv_always(!is_empty());
+  node()->clear_attrib(LogicOpAttrib::get_class_slot());
+}
+
+/**
+ * Returns true if a logical operation has been explicitly set on this
+ * particular node via set_logic_op().  If this returns true, then
+ * get_logic_op() may be called to determine whether a logical operation has
+ * been explicitly disabled for this node or set to particular operation.
+ */
+bool NodePath::
+has_logic_op() const {
+  nassertr_always(!is_empty(), false);
+  return node()->has_attrib(LogicOpAttrib::get_class_slot());
+}
+
+/**
+ * Returns the logical operation that has been specifically set on this node
+ * via set_logic_op(), or O_none if standard color blending has been
+ * specifically set, or if nothing has been specifically set.  See also
+ * has_logic_op().  This does not necessarily imply that the geometry will
+ * or will not be rendered with the given logical operation, as there may be
+ * other nodes that override.
+ */
+LogicOpAttrib::Operation NodePath::
+get_logic_op() const {
+  nassertr_always(!is_empty(), LogicOpAttrib::O_none);
+  const RenderAttrib *attrib =
+    node()->get_attrib(LogicOpAttrib::get_class_slot());
+  if (attrib != (const RenderAttrib *)NULL) {
+    const LogicOpAttrib *ta = DCAST(LogicOpAttrib, attrib);
+    return ta->get_operation();
+  }
+
+  return LogicOpAttrib::O_none;
+}
+
 /**
 /**
  * Specifies the antialiasing type that should be applied at this node and
  * Specifies the antialiasing type that should be applied at this node and
  * below.  See AntialiasAttrib.
  * below.  See AntialiasAttrib.

+ 83 - 51
panda/src/pgraph/nodePath.h

@@ -26,6 +26,7 @@
 #include "transformState.h"
 #include "transformState.h"
 #include "renderModeAttrib.h"
 #include "renderModeAttrib.h"
 #include "transparencyAttrib.h"
 #include "transparencyAttrib.h"
+#include "logicOpAttrib.h"
 #include "nodePathComponent.h"
 #include "nodePathComponent.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "referenceCount.h"
 #include "referenceCount.h"
@@ -62,57 +63,83 @@ class SamplerState;
 class Shader;
 class Shader;
 class ShaderInput;
 class ShaderInput;
 
 
-/*
- * A NodePath is the fundamental unit of high-level interaction with the scene
- * graph.  It encapsulates the complete path down to a node from some other
- * node, usually the root of the scene graph.  This is used to resolve
- * ambiguities associated with instancing.  NodePath also contains a number of
- * handy high-level methods for common scene-graph manipulations, such as
- * reparenting, and common state changes, such as repositioning.  There are
- * also a number of NodePath methods for finding nodes deep within the tree by
- * name or by type.  These take a path string, which at its simplest consists
- * of a series of node names separated by slashes, like a directory pathname.
- * Each component of the path string may optionally consist of one of the
- * following special names, instead of a node name: *          -- matches
- * exactly one node, with any name.  **         -- matches any sequence of
- * zero or more nodes.  +typename  -- matches any node that is or derives from
- * the given type.  -typename  -- matches any node that is the given type
- * exactly.  =tag       -- matches any node that has the indicated tag.
- * =tag=value -- matches any node whose tag matches the indicated value.
- * Furthermore, a node name may itself contain standard filename globbing
- * characters, like *, ?, and [a-z], that will be accepted as a partial match.
- * (In fact, the '*' special name may be seen as just a special case of this.)
- * The globbing characters may not be used with the typename matches or with
- * tag matches, but they may be used to match a tag's value in the =tag=value
- * syntax.  The special characters "@@", appearing at the beginning of a node
- * name, indicate a stashed node.  Normally, stashed nodes are not returned by
- * a find (but see the special flags, below), but a stashed node may be found
- * if it is explicitly named with its leading @@ characters.  By extension,
- * "@@*" may be used to identify any stashed node.  Examples: "roomgraph" will
- * look for a node named "graph", which is a child of an unnamed node, which
- * is a child of a node named "room", which is a child of the starting path.
- * "**red*" will look for any node anywhere in the tree (below the starting
- * path) with a name that begins with "red". "**+PartBundleNode**head" will
- * look for a node named "head", somewhere below a PartBundleNode anywhere in
- * the tree.  The search is always potentially ambiguous, even if the special
- * wildcard operators are not used, because there may be multiple nodes in the
- * tree with the same name.  In general, in the case of an ambiguity, the
- * shortest path is preferred; when a method (such as extend_by) must choose
- * only only one of several possible paths, it will choose the shortest
- * available; on the other hand, when a method (such as find_all_matches) is
- * to return all of the matching paths, it will sort them so that the shortest
- * paths appear first in the output.  Special flags.  The entire string may
- * optionally be followed by the ";" character, followed by one or more of the
- * following special control flags, with no intervening spaces or punctuation:
- * -h    Do not return hidden nodes.  +h    Do return hidden nodes.  -s    Do
- * not return stashed nodes unless explicitly referenced with @@. +s    Return
- * stashed nodes even without any explicit @@ characters.  -i    Node name
- * comparisons are not case insensitive: case must match exactly.  +i    Node
- * name comparisons are case insensitive: case is not important.  This affects
- * matches against the node name only; node type and tag strings are always
- * case sensitive.  The default flags are +h-s-i.
- */
-
+//
+// A NodePath is the fundamental unit of high-level interaction with the scene
+// graph.  It encapsulates the complete path down to a node from some other
+// node, usually the root of the scene graph.  This is used to resolve
+// ambiguities associated with instancing.
+//
+// NodePath also contains a number of handy high-level methods for common
+// scene-graph manipulations, such as reparenting, and common state changes,
+// such as repositioning.
+//
+// There are also a number of NodePath methods for finding nodes deep within
+// the tree by name or by type.  These take a path string, which at its
+// simplest consists of a series of node names separated by slashes, like a
+// directory pathname.
+//
+// Each component of the path string may optionally consist of one of the
+// following special names, instead of a node name:
+//
+//   *          -- matches exactly one node, with any name.
+//   **         -- matches any sequence of zero or more nodes.
+//   +typename  -- matches any node that is or derives from the given type.
+//   -typename  -- matches any node that is the given type exactly.
+//   =tag       -- matches any node that has the indicated tag.
+//   =tag=value -- matches any node whose tag matches the indicated value.
+//
+// Furthermore, a node name may itself contain standard filename globbing
+// characters, like *, ?, and [a-z], that will be accepted as a partial match.
+// (In fact, the '*' special name may be seen as just a special case of this.)
+// The globbing characters may not be used with the typename matches or with
+// tag matches, but they may be used to match a tag's value in the =tag=value
+// syntax.
+//
+// The special characters "@@", appearing at the beginning of a node name,
+// indicate a stashed node.  Normally, stashed nodes are not returned by a
+// find (but see the special flags, below), but a stashed node may be found if
+// it is explicitly named with its leading @@ characters.  By extension, "@@*"
+// may be used to identify any stashed node.
+//
+// Examples:
+//
+// "room//graph" will look for a node named "graph", which is a child of an
+// unnamed node, which is a child of a node named "room", which is a child of
+// the starting path.
+//
+// "**/red*" will look for any node anywhere in the tree (below the starting
+// path) with a name that begins with "red".
+//
+// "**/+PartBundleNode/**/head" will look for a node named "head", somewhere
+// below a PartBundleNode anywhere in the tree.
+//
+//
+// The search is always potentially ambiguous, even if the special wildcard
+// operators are not used, because there may be multiple nodes in the tree
+// with the same name.  In general, in the case of an ambiguity, the shortest
+// path is preferred; when a method (such as extend_by) must choose only only
+// one of several possible paths, it will choose the shortest available; on
+// the other hand, when a method (such as find_all_matches) is to return all
+// of the matching paths, it will sort them so that the shortest paths appear
+// first in the output.
+//
+//
+// Special flags.  The entire string may optionally be followed by the ";"
+// character, followed by one or more of the following special control flags,
+// with no intervening spaces or punctuation:
+//
+//    -h    Do not return hidden nodes.
+//    +h    Do return hidden nodes.
+//    -s    Do not return stashed nodes unless explicitly referenced with @@.
+//    +s    Return stashed nodes even without any explicit @@ characters.
+//    -i    Node name comparisons are not case insensitive: case must match
+//          exactly.
+//    +i    Node name comparisons are case insensitive: case is not important.
+//          This affects matches against the node name only; node type and tag
+//          strings are always case sensitive.
+//
+// The default flags are +h-s-i.
+//
 
 
 /**
 /**
  * NodePath is the fundamental system for disambiguating instances, and also
  * NodePath is the fundamental system for disambiguating instances, and also
@@ -786,6 +813,11 @@ PUBLISHED:
   bool has_transparency() const;
   bool has_transparency() const;
   TransparencyAttrib::Mode get_transparency() const;
   TransparencyAttrib::Mode get_transparency() const;
 
 
+  void set_logic_op(LogicOpAttrib::Operation op, int priority = 0);
+  void clear_logic_op();
+  bool has_logic_op() const;
+  LogicOpAttrib::Operation get_logic_op() const;
+
   void set_antialias(unsigned short mode, int priority = 0);
   void set_antialias(unsigned short mode, int priority = 0);
   void clear_antialias();
   void clear_antialias();
   bool has_antialias() const;
   bool has_antialias() const;

+ 1 - 0
panda/src/pgraph/p3pgraph_composite3.cxx

@@ -7,6 +7,7 @@
 #include "loaderFileType.cxx"
 #include "loaderFileType.cxx"
 #include "loaderFileTypeBam.cxx"
 #include "loaderFileTypeBam.cxx"
 #include "loaderFileTypeRegistry.cxx"
 #include "loaderFileTypeRegistry.cxx"
+#include "logicOpAttrib.cxx"
 #include "materialAttrib.cxx"
 #include "materialAttrib.cxx"
 #include "materialCollection.cxx"
 #include "materialCollection.cxx"
 #include "modelFlattenRequest.cxx"
 #include "modelFlattenRequest.cxx"

+ 1 - 1
panda/src/pgraph/renderAttribRegistry.h

@@ -47,7 +47,7 @@ public:
 
 
   // Raise this number whenever we add a new attrib.  This used to be
   // Raise this number whenever we add a new attrib.  This used to be
   // determined at runtime, but it's better to have it as a constexpr.
   // determined at runtime, but it's better to have it as a constexpr.
-  static const int _max_slots = 29;
+  static const int _max_slots = 32;
 
 
   int register_slot(TypeHandle type_handle, int sort,
   int register_slot(TypeHandle type_handle, int sort,
                     RenderAttrib *default_attrib);
                     RenderAttrib *default_attrib);