Browse Source

Display regions must now be setup into groups by using parenthesis in
window_db. Also, changes in camera nodes results in events being thrown.

khillesl 24 years ago
parent
commit
9d1b7d31d6

+ 20 - 0
panda/src/chancfg/chancfg.I

@@ -15,3 +15,23 @@
 // [email protected] .
 //
 ////////////////////////////////////////////////////////////////////
+
+  INLINE PT_NamedNode ChanConfig::get_group_node(const int node_index) const {
+	 return _group_node[node_index];
+  }
+  INLINE int ChanConfig::get_group_membership(const int dr_index) const {
+    return _group_membership[dr_index];
+  }
+  INLINE int ChanConfig::get_num_groups(void) const {
+    return _group_node.size();
+  }
+  INLINE int ChanConfig::get_num_drs(void) const {
+    return _display_region.size();
+  }
+  INLINE PT(DisplayRegion) ChanConfig::get_dr(const int dr_index) const {
+    return _display_region[dr_index];
+  }
+  INLINE PT(GraphicsWindow) ChanConfig::get_win(void) const {
+    return _graphics_window;
+  }
+

+ 101 - 79
panda/src/chancfg/chancfg.cxx

@@ -30,6 +30,8 @@
 #include <dconfig.h>
 #include <filename.h>
 #include <algorithm>
+#include <pt_NamedNode.h>
+
 
 Configure(chanconfig);
 
@@ -121,7 +123,8 @@ INLINE bool ConfigDefined(std::string sym) {
     (WindowDB->find(sym) != WindowDB->end());
 }
 
-typedef pvector<SetupItem> SVec;
+//KEH:  Moving this up to .h file
+//typedef pvector<SetupItem> SVec;
 
 bool ChanCheckLayouts(SetupSyms& S) {
   if (S.empty())
@@ -207,101 +210,109 @@ SetupFOV ChanResolveFOV(SetupFOV& fov, float sizeX, float sizeY) {
   return ret;
 }
 
-void ChanEval(GraphicsWindow* win, WindowItem& W, LayoutItem& L, SVec& S,
-          ChanViewport& V, int hw_offset, int xsize, int ysize,
-          Node *camera_node, Node *render, bool want_cameras) {
+void ChanConfig::chan_eval(GraphicsWindow* win, WindowItem& W, LayoutItem& L, 
+                           SVec& S,
+                           ChanViewport& V, int hw_offset, int xsize, int ysize,
+                           Node *render, bool want_cameras) {
   int i = min(L.GetNumRegions(), int(S.size()));
   int j;
   SVec::iterator k;
+  std::vector<PT_NamedNode>camera(W.getNumCameraGroups());
+  //first camera is special cased to name "camera" for older code
+  camera[0] = new NamedNode("camera");
+  for(int icam=1;icam<W.getNumCameraGroups();icam++) {
+    char dummy[10];//if more than 10^11 groups, you've got bigger problems
+    sprintf(dummy,"%d",icam);
+    std::string nodeName = "camera";
+    nodeName.append(dummy);
+    camera[icam] = new NamedNode(nodeName.c_str());
+  }
   for (j=0, k=S.begin(); j<i; ++j, ++k) {
     ChanViewport v(ChanScaleViewport(V, L[j]));
     if ((*k).getRecurse()) {
-      SetupSyms l = (*k).getLayouts();
-      SetupSyms s = (*k).getSetups();
-      LayoutItem subL = (*LayoutDB)[l[0]];
-      SVec subS;
-      for (SetupSyms::iterator m=s.begin(); m!=s.end(); ++m)
-    subS.push_back((*SetupDB)[*m]);
-      int xs = int(xsize*(v.right()-v.left()));
-      int ys = int(ysize*(v.top()-v.bottom()));
-      ChanEval(win, W, subL, subS, v, hw_offset, xs, ys, camera_node, render, want_cameras);
+      chancfg_cat->error()<<"Recursive setups no longer supported"<<endl;
+      chancfg_cat->error()<<"Skipping ..."<<endl;
+      ++k;
     } else {
       PT(GraphicsChannel) chan;
       if ((*k).getHWChan() && W.getHWChans()) {
-    if ((*k).getChan() == -1) {
-      chan = win->get_channel(hw_offset);
-    } else
-      chan = win->get_channel((*k).getChan());
-    // HW channels always start with the full area of the channel
-    v = ChanViewport(0., 1., 0., 1.);
+        if ((*k).getChan() == -1) {
+          chan = win->get_channel(hw_offset);
+        } else
+         chan = win->get_channel((*k).getChan());
+  // HW channels always start with the full area of the channel
+        v = ChanViewport(0., 1., 0., 1.);
       } else {
-    chan = win->get_channel(0);
+        chan = win->get_channel(0);
       }
       ChanViewport v2(ChanScaleViewport(v, (*k).getViewport()));
       PT(GraphicsLayer) layer = chan->make_layer();
-      PT(DisplayRegion) dr =
-    layer->make_display_region(v2.left(), v2.right(),
-                   v2.bottom(), v2.top());
-      if (want_cameras && camera_node != (Node *)NULL) {
-    // now make a camera for it
-    PT(Camera) cam = new Camera;
-    dr->set_camera(cam);
-    SetupFOV fov = (*k).getFOV();
-    fov = ChanResolveFOV(fov, xsize*(v2.right()-v2.left()),
-                 ysize*(v2.top()-v2.bottom()));
-    if (chancfg_cat.is_debug()) {
-      chancfg_cat->debug() << "ChanEval:: about to compute frustum."
-                   << endl;
-      chancfg_cat->debug() << "ChanEval:: FOVhoriz = " << fov.getHoriz()
-                   << "  FOVvert = " << fov.getVert() << endl;
-      chancfg_cat->debug() << "ChanEval:: xsize = " << xsize
-                   << "  ysize = " << ysize << endl;
-    }
-    Frustumf frust;
-    frust.make_perspective(fov.getHoriz(), fov.getVert(), 1., 10000.);
-    cam->set_projection(PerspectiveProjection(frust));
-    if (chancfg_cat.is_debug())
-      chancfg_cat->debug() << "ChanEval:: camera hfov = "
-                   << cam->get_hfov() << "  vfov = "
-                   << cam->get_vfov() << endl;
-    cam->set_scene(render);
-
-    // take care of the orientation
-    PT(TransformTransition) orient;
-
-    switch ((*k).getOrientation()) {
-    case SetupItem::Up:
-      break;
-    case SetupItem::Down:
-      orient = new TransformTransition(LMatrix4f::rotate_mat_normaxis(180., LVector3f::forward()));
-      break;
-    case SetupItem::Left:
-      orient = new TransformTransition(LMatrix4f::rotate_mat_normaxis(90., LVector3f::forward()));
-      break;
-    case SetupItem::Right:
-      orient = new TransformTransition(LMatrix4f::rotate_mat_normaxis(-90., LVector3f::forward()));
-      break;
-    }
+      PT(DisplayRegion) dr = 
+        layer->make_display_region(v2.left(), v2.right(),
+                                   v2.bottom(), v2.top());
+      if (want_cameras && camera[0] != (Node *)NULL) {
+        // now make a camera for it
+        PT(Camera) cam = new Camera;
+        dr->set_camera(cam);
+        _display_region.push_back(dr);
+        SetupFOV fov = (*k).getFOV();
+        fov = ChanResolveFOV(fov, xsize*(v2.right()-v2.left()),
+                             ysize*(v2.top()-v2.bottom()));
+        if (chancfg_cat->is_debug()) {
+          chancfg_cat->debug() << "ChanEval:: FOVhoriz = " << fov.getHoriz()
+             << "  FOVvert = " << fov.getVert() << endl;
+          chancfg_cat->debug() << "ChanEval:: xsize = " << xsize
+             << "  ysize = " << ysize << endl;
+        }
+        Frustumf frust;
+        frust.make_perspective(fov.getHoriz(), fov.getVert(), 1., 10000.);
+        cam->set_projection(PerspectiveProjection(frust));
+        if (chancfg_cat->is_debug())
+          chancfg_cat->debug() << "ChanEval:: camera hfov = "
+            << cam->get_hfov() << "  vfov = "
+            << cam->get_vfov() << endl;
+        cam->set_scene(render);
+
+        // take care of the orientation
+        PT(TransformTransition) orient;
+      
+        switch ((*k).getOrientation()) {
+          case SetupItem::Up:
+            break;
+          case SetupItem::Down:
+            orient = new TransformTransition(
+              LMatrix4f::rotate_mat_normaxis(180., LVector3f::forward()));
+            break;
+          case SetupItem::Left:
+            orient = new TransformTransition(
+              LMatrix4f::rotate_mat_normaxis(90., LVector3f::forward()));
+            break;
+          case SetupItem::Right:
+            orient = new TransformTransition(
+              LMatrix4f::rotate_mat_normaxis(-90., LVector3f::forward()));
+            break;
+        }
 
-    RenderRelation *tocam = new RenderRelation(camera_node, cam);
-    if (orient != (TransformTransition *)NULL) {
-      tocam->set_transition(orient);
-    }
+        RenderRelation *tocam = new RenderRelation(camera[W.getCameraGroup(j)], cam);
+        if (orient != (TransformTransition *)NULL) {
+          tocam->set_transition(orient);
+        }
       }
     }
   }
+  _group_node = camera;
   return;
 }
 
-PT(GraphicsWindow) ChanConfig(GraphicsPipe* pipe, std::string cfg,
-                  Node *camera_node, Node *render,
-                  ChanCfgOverrides& overrides) {
+ChanConfig::ChanConfig(GraphicsPipe* pipe, std::string cfg, Node *render,
+                       ChanCfgOverrides& overrides) {
   ReadChanConfigData();
   // check to make sure we know everything we need to
   if (!ConfigDefined(cfg)) {
     chancfg_cat.error()
       << "no window configuration called '" << cfg << "'" << endl;
-    return (GraphicsWindow*)0;
+    _graphics_window = (GraphicsWindow*)0;
+    return;
   }
   WindowItem W = (*WindowDB)[cfg];
 
@@ -309,13 +320,17 @@ PT(GraphicsWindow) ChanConfig(GraphicsPipe* pipe, std::string cfg,
   if (!LayoutDefined(l)) {
     chancfg_cat.error()
       << "No layout called '" << l << "'" << endl;
-    return (GraphicsWindow*)0;
+    _graphics_window = (GraphicsWindow*)0;
+    return;
   }
   LayoutItem L = (*LayoutDB)[l];
 
   SetupSyms s = W.getSetups();
-  if (!ChanCheckSetups(s))
-    return (GraphicsWindow*)0;
+  if (!ChanCheckSetups(s)) {
+    chancfg_cat.error() << "Setup failure" << endl;
+    _graphics_window = (GraphicsWindow*)0;
+    return;
+  }
   SVec S;
   for (SetupSyms::iterator i=s.begin(); i!=s.end(); ++i)
     S.push_back((*SetupDB)[(*i)]);
@@ -385,12 +400,18 @@ PT(GraphicsWindow) ChanConfig(GraphicsPipe* pipe, std::string cfg,
 
   // open that sucker
   PT(GraphicsWindow) win = pipe->make_window(props);
-  nassertr(win != (GraphicsWindow *)NULL, NULL);
+  if(win == (GraphicsWindow *)NULL) {
+    chancfg_cat.error() << "Could not create window" << endl;
+    _graphics_window = (GraphicsWindow *)NULL;
+    return;
+  }
 
   // make channels and display regions
   ChanViewport V(0., 1., 0., 1.);
-  ChanEval(win, W, L, S, V, W.getChanOffset()+1, sizeX, sizeY,
-       camera_node, render, want_cameras);
+  chan_eval(win, W, L, S, V, W.getChanOffset()+1, sizeX, sizeY, 
+            render, want_cameras);
+  for(int dr_index=0; dr_index<_display_region.size(); dr_index++)
+    _group_membership.push_back(W.getCameraGroup(dr_index));
 
   // sanity check
   if (config_sanity_check) {
@@ -443,8 +464,9 @@ PT(GraphicsWindow) ChanConfig(GraphicsPipe* pipe, std::string cfg,
       }
     }
   }
-
-  return win;
+    
+  _graphics_window = win;
+  return;
 }
 
 

+ 23 - 3
panda/src/chancfg/chancfg.h

@@ -28,6 +28,7 @@
 
 #include <graphicsPipe.h>
 #include <graphicsWindow.h>
+#include <pt_NamedNode.h>
 
 #include "pmap.h"
 
@@ -101,9 +102,28 @@ public:
 
 extern ChanCfgOverrides ChanOverrideNone;
 
-PT(GraphicsWindow) EXPCL_PANDA
-ChanConfig(GraphicsPipe*, std::string, Node *camera_node, Node *render,
-           ChanCfgOverrides& = ChanOverrideNone);
+typedef pvector<SetupItem> SVec;
+class NamedNode;
+class EXPCL_PANDA ChanConfig
+{
+private:
+  std::vector<PT_NamedNode> _group_node;
+  std::vector<PT(DisplayRegion)> _display_region;
+  std::vector<int> _group_membership;
+  PT(GraphicsWindow) _graphics_window;
+  void chan_eval(GraphicsWindow* win, WindowItem& W, LayoutItem& L, 
+	 SVec& S, ChanViewport& V, int hw_offset, 
+	 int xsize, int ysize, Node *render, bool want_cameras);
+PUBLISHED:
+  ChanConfig(GraphicsPipe*, std::string, Node *render,
+    ChanCfgOverrides& = ChanOverrideNone);
+  INLINE PT_NamedNode get_group_node(const int node_index) const;
+  INLINE int get_group_membership(const int dr_index) const;
+  INLINE int get_num_groups(void) const;
+  INLINE int get_num_drs(void) const;
+  INLINE PT(DisplayRegion) get_dr(const int dr_index) const;
+  INLINE PT(GraphicsWindow) get_win(void) const;
+};
 
 #include "chancfg.I"
 

+ 29 - 14
panda/src/chancfg/chanwindow.I

@@ -21,21 +21,25 @@ INLINE WindowItem::WindowItem(void) {}
 INLINE WindowItem::WindowItem(const bool h, const bool d, const int o,
                               const std::string& l, const SetupSyms& s,
                               const int x, const int y, const bool b,
-                              const bool c) : _hw_chans(h), _dvr(d),
-                                              _border(b), _cursor(c),
-                                              _chan_offset(o), _sizeX(x),
-                                              _sizeY(y), _layout(l),
-                                              _setups(s) {}
+                              const bool c, PTA(int) n) : 
+  _hw_chans(h), _dvr(d),
+  _border(b), _cursor(c),
+  _chan_offset(o), _sizeX(x),
+  _sizeY(y), _layout(l),
+  _setups(s), 
+  _camera_group(n) {}
 
-INLINE WindowItem::WindowItem(const WindowItem& c) : _hw_chans(c._hw_chans),
-                                                     _dvr(c._dvr),
-                                                     _border(c._border),
-                                                     _cursor(c._cursor),
-                                                     _chan_offset(c._chan_offset),
-                                                     _sizeX(c._sizeX),
-                                                     _sizeY(c._sizeY),
-                                                     _layout(c._layout),
-                                                     _setups(c._setups) {}
+INLINE WindowItem::WindowItem(const WindowItem& c) : 
+  _hw_chans(c._hw_chans),
+  _dvr(c._dvr),
+  _border(c._border),
+  _cursor(c._cursor),
+  _chan_offset(c._chan_offset),
+  _sizeX(c._sizeX),
+  _sizeY(c._sizeY),
+  _layout(c._layout),
+  _setups(c._setups),
+  _camera_group(c._camera_group) {}
 
 INLINE WindowItem::~WindowItem(void) {}
 
@@ -49,6 +53,7 @@ INLINE WindowItem& WindowItem::operator=(const WindowItem& c) {
   _sizeY = c._sizeY;
   _layout = c._layout;
   _setups = c._setups;
+  _camera_group = c._camera_group;
   return *this;
 }
 
@@ -87,3 +92,13 @@ INLINE std::string WindowItem::getLayout(void) const {
 INLINE SetupSyms WindowItem::getSetups(void) const {
   return _setups;
 }
+
+INLINE int WindowItem::getCameraGroup(int display_region) const {
+  return _camera_group[display_region];
+}
+INLINE int WindowItem::getNumCameraGroups(void) const {
+ int largestIndex=0;
+ for(int j=0;j<_camera_group.size();j++)
+  if(_camera_group[j]>largestIndex)largestIndex=_camera_group[j];
+ return largestIndex+1;
+}

+ 45 - 11
panda/src/chancfg/chanwindow.cxx

@@ -21,6 +21,7 @@
 #include "chanshare.h"
 
 #include <notify.h>
+
 WindowType* WindowDB = (WindowType*)0;
 
 class WindowParseFunctor : public ChanParseFunctor {
@@ -48,27 +49,60 @@ void WindowParseFunctor::operator()(std::string S) {
   int hw_chan_offset = ChanReadNextInt(S);
   std::string layout = ChanReadNextWord(S);
   SetupSyms sv;
+  PTA(int) cameraGroup;
+  int group_index=0;
   {
     ChanCheckScoping(S);
-    int i = S.find_first_of(")");
-    std::string stmp = S.substr(1, i-1);
-    S.erase(0, i+1);
-    ChanEatFrontWhite(S);
+    int i=ChanMatchingParen(S);
+    std::string setupSubstring = S.substr(1,i-2);
+    S.erase(0,i);
+    ChanEatFrontWhite(setupSubstring);
 
-    while (!stmp.empty()) {
-      std::string stmp2 = ChanReadNextWord(stmp);
-      sv.push_back(stmp2);
+    while (!setupSubstring.empty()) {
+
+      ChanCheckScoping(setupSubstring);
+      std::string groupSubstring = setupSubstring;
+      //get the group substring
+      int iend = setupSubstring.find_first_of(")");
+      groupSubstring = setupSubstring.substr(1,iend-1);
+      //then erase that portion from the setup string
+      setupSubstring.erase(0,iend+1);
+      ChanEatFrontWhite(setupSubstring);
+
+      while (!groupSubstring.empty()) {
+
+        int region_number = ChanReadNextInt(groupSubstring);
+        if(region_number<0) {
+          nout <<"Trying to read region index, which should be >= 0, ";
+          nout << "but got "<<region_number<<"."<<endl;
+          nout << "Ignoring this entry."<<endl;
+          ChanReadNextWord(groupSubstring); //slurp it up, but ignore it.
+        } else {
+           //0 based.  We don't know yet how much room we actually need
+           //as the information is in the un-analyzed layout.  cameraGroup
+           //and sv are handled the same in this manner.
+           while(sv.size()<region_number+1) {
+             sv.push_back("");
+             cameraGroup.push_back(0);
+           }
+           std::string stmp2 = ChanReadNextWord(groupSubstring);
+           sv[region_number]=stmp2;
+           cameraGroup[region_number]=group_index;
+        }
+      }
+      group_index++;
     }
   }
   int X, Y;
   {
+    ChanEatFrontWhite(S);
     ChanCheckScoping(S);
     int i = S.find_first_of(")");
-    std::string stmp = S.substr(1, i-1);
+    std::string screenSubstring = S.substr(1, i-1);
     S.erase(0, i+1);
     ChanEatFrontWhite(S);
-    X = ChanReadNextInt(stmp);
-    Y = ChanReadNextInt(stmp);
+    X = ChanReadNextInt(screenSubstring);
+    Y = ChanReadNextInt(screenSubstring);
   }
   bool border = ChanReadNextBool(S);
   bool cursor = ChanReadNextBool(S);
@@ -79,7 +113,7 @@ void WindowParseFunctor::operator()(std::string S) {
   }
 
   WindowItem W(hw_chans, dvr, hw_chan_offset, layout, sv, X, Y, border,
-           cursor);
+         cursor, cameraGroup);
 
   if (chancfg_cat.is_debug()) {
     chancfg_cat->debug() << "parsed a window called '" << sym << "':" << endl;

+ 5 - 1
panda/src/chancfg/chanwindow.h

@@ -25,6 +25,7 @@
 #include "pvector.h"
 #include <string>
 #include "chansetup.h"
+#include <pta_int.h>
 
 class WindowItem {
 private:
@@ -32,11 +33,12 @@ private:
   int _chan_offset, _sizeX, _sizeY;
   std::string _layout;
   SetupSyms _setups;
+  PTA(int) _camera_group;
 public:
   INLINE WindowItem(void);
   INLINE WindowItem(const bool, const bool, const int, const std::string&,
                     const SetupSyms&, const int, const int, const bool,
-                    const bool);
+                    const bool, PTA(int) );
   INLINE WindowItem(const WindowItem&);
   INLINE ~WindowItem(void);
 
@@ -51,6 +53,8 @@ public:
   INLINE int getSizeY(void) const;
   INLINE std::string getLayout(void) const;
   INLINE SetupSyms getSetups(void) const;
+  INLINE int getCameraGroup(int display_region) const;
+  INLINE int getNumCameraGroups(void) const;
 };
 
 typedef pmap<std::string, WindowItem> WindowType;

+ 27 - 71
panda/src/chancfg/window_db

@@ -26,9 +26,9 @@
 ;;;    rgn - region
 ;;;
 ;;; The format for a config is:
-;;;     window  use  use  PVC lay-  set-   default  bor- cur-
-;;;      name   PVC  DVR  ofs outs  ups     size    der  sor
-;;;    (string (bool bool int (---) (---) (int int) bool bool))
+;;;     window  lay-  set-            default  bor- cur- PVC 
+;;;      name   out   ups              size    der  sor  offset
+;;;    (string ((---) (({int setup}+)+) (int int) bool bool [int] ))
 ;;;
 ;;;    * In order to have DVR, we must also be using Pipe Video Channels
 ;;;    * If Pipe Video Channels are being used, we do not need the default size
@@ -36,77 +36,33 @@
 ;;;      first chanel number to be used for channels that allow default
 ;;;      assignment (see setup below).
 ;;;    * Setups is an arbitrarilly long list of setup specs.  Any region that
-;;;      does not have a coresponding setup, does not get configured.
+;;;      does not have a coresponding setup, does not get configured.  There is
+;;;      an index associated with each setup from the range of 0 to the number
+;;;      of display regions minus one.  The display regions are divided into 
+;;;      groups by the use of the parenthesis.  Note that he '{' and '}' above
+;;;      are for showing that the int and setup values come in pairs, and are 
+;;;      not literally part of the format.
 ;;;.
 
 ;;;*Public
 
-(single (#f #f 0 layout1x1 (setup-mono-plain) (640 480) #t #t))
-(single-stereo (#f #f 0 layout1x1 (setup-stereo-plain) (640 480) #t #f))
-(single-pronto (#f #f 0 layout1x1 (setup-mono-plain) (720 486) #t #f))
-(single-pronto-widescreen (#f #f 0 layout1x1 (setup-pronto-plain) (720 486) #t
-                           #f))
-(pronto+god (#f #f 0 layout1x2 (setup-mono-plain setup-mono-plain) (720 972)
-             #t #t))
-(pronto-widescreen+god (#f #f 0 layout1x2 (setup-pronto-plain setup-mono-plain)
-                        (720 972) #t #t))
-(fakecave3 (#f #f 0 layout3x1 (setup-mono-plain setup-mono-plain
-                               setup-mono-plain) (720 320) #t #t))
-(fakecave3+god (#f #f 0 layout3x2-1+3x1 (setup-mono-plain setup-mono-plain
-                                         setup-mono-plain setup-mono-wide)
+(single (#f #f 0 layout1x1 ((0 setup-mono-plain)) (640 480) #t #t))
+(single+god (#f #f 0 layout2x1 ((0 setup-mono-plain)(1 setup-mono-plain)) (640 480) #t #t))
+(cave3 (#f #f 0 layout3x1 ((0 setup-mono-plain 1 setup-mono-plain
+                               2 setup-mono-plain)) (720 320) #t #t))
+(cave3+god (#f #f 0 layout3x2-1+3x1 ((0 setup-mono-plain 1 setup-mono-plain
+                                      2 setup-mono-plain) (3 setup-mono-plain))
                 (720 640) #t #t))
-(fakecave5 (#f #f 0 layout5x1 (setup-mono-plain setup-mono-plain
-                               setup-mono-plain setup-mono-plain
-                               setup-mono-plain) (1280 341) #t #t))
-(cave (#t #t 1 layout3x2-0last (setup-mono-left setup-stereo-left
-                                setup-stereo-left setup-stereo-left
-                                setup-mono-left) (1920 960) #t #f))
-(mono-cave (#t #t 1 layout3x2-0last (setup-mono-left setup-mono-left
-                                     setup-mono-left setup-mono-left
-                                     setup-mono-left) (1920 960) #t #f))
-(supercave (#t #t 1 layout3x2-0last (setup-stereo-plain setup-stereo-plain
-                                     setup-stereo-plain setup-stereo-plain
-                                     setup-stereo-plain) (1920 960) #t #f))
-(hmd-ship (#t #t 4 layout2x2 (setup-mono-hmd setup-mono-hmd setup-mono-hmd
-                              setup-mono-hmd) (1280 960) #t #f))
-(square-fakehmd (#f #f 0 layout2x2 (setup-mono-hmd setup-mono-hmd
-                                    setup-mono-hmd setup-mono-hmd) (1280 960)
-                 #t #f))
-(pirates-fakecave (#f #f 0 layout4x1 (setup-mono-plain setup-mono-plain
-                                      setup-mono-plain setup-mono-plain)
-                   (1280 240) #t #t))
-(pirates-small-cave (#t #t 0 layout2x2 (setup-stereo-plain setup-stereo-plain
-                                        setup-stereo-plain setup-stereo-plain)
-                     (1280 960) #t #f))
-(pirates-small-cave+demigod (#t #t 0 layout2x3-1+2x2 (setup-stereo-plain
-                                                      setup-stereo-plain
-                                                      setup-stereo-plain
-                                                      setup-stereo-plain
-                                                      setup-mono-wide-vptrim)
-                             (1280 1440) #t #f))
-(pirates-small-cave+god (#t #t 0 layout2x4-1+2x2 (setup-stereo-plain
-                                                  setup-stereo-plain
-                                                  setup-stereo-plain
-                                                  setup-stereo-plain
-                                                  setup-mono-wide-vptrim2)
-                         (1280 1920) #t #f))
-(pirates-large-cave (#t #t 0 layout2x2 (setup-stereo-plain setup-stereo-plain
-                                        setup-stereo-plain setup-stereo-plain)
-                     (1600 1200) #t #f))
-(multipass-tile (#f #f 0 layout4x4 (setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain
-                                    setup-mono-plain setup-mono-plain)
+(cave3passive (#f #f 0 layout3x2 ((0 setup-mono-plain 1 setup-mono-plain
+                                   2 setup-mono-plain 3 setup-mono-plain
+											  4 setup-mono-plain 5 setup-mono-plain))
+                (720 640) #t #t))
+(multipass-tile (#f #f 0 layout4x4 ((0 setup-mono-plain 1 setup-mono-plain
+                                     2 setup-mono-plain 3 setup-mono-plain
+                                     4 setup-mono-plain 5 setup-mono-plain
+                                     6 setup-mono-plain 7 setup-mono-plain
+                                     8 setup-mono-plain 9 setup-mono-plain
+                                     10 setup-mono-plain 11 setup-mono-plain
+                                     12 setup-mono-plain 13 setup-mono-plain
+                                     14 setup-mono-plain 15 setup-mono-plain))
                                (720 320) #t #t))
-
-;;;*Private
-
-(square-test (#f #f 0 layout2x2 (setup-mono-plain setup-mono-left
-	                         setup-mono-right setup-mono-down) (800 800)
-                 #f #f))
-(two-frame (#f #f 0 layout2x1 (setup-mono-plain setup-mono-plain) (600 300)
-            #f #f))

+ 48 - 0
panda/src/display/displayRegion.I

@@ -31,6 +31,54 @@ get_dimensions(float &l, float &r, float &b, float &t) const {
   t = _t;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_left
+//       Access: Public
+//  Description: Retrieves the x coordinate of the left edge of the
+//               rectangle within its GraphicsLayer.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_left() const {
+  return _l;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_right
+//       Access: Public
+//  Description: Retrieves the x coordinate of the right edge of the
+//               rectangle within its GraphicsLayer.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_right() const {
+  return _r;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_bottom
+//       Access: Public
+//  Description: Retrieves the y coordinate of the bottom edge of 
+//               the rectangle within its GraphicsLayer.  This 
+//               number will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_bottom() const {
+  return _b;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_top
+//       Access: Public
+//  Description: Retrieves the y coordinate of the top edge of the
+//               rectangle within its GraphicsLayer.  This number
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE float DisplayRegion::
+get_top() const {
+  return _t;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::get_layer
 //       Access: Public

+ 4 - 0
panda/src/display/displayRegion.h

@@ -51,6 +51,10 @@ public:
 
 PUBLISHED:
   INLINE void get_dimensions(float &l, float &r, float &b, float &t) const;
+  INLINE float get_left() const;
+  INLINE float get_right() const;
+  INLINE float get_bottom() const;
+  INLINE float get_top() const;
   void set_dimensions(float l, float r, float b, float t);
 
   INLINE GraphicsLayer *get_layer() const;

+ 28 - 15
panda/src/framework/framework.cxx

@@ -986,13 +986,12 @@ static void move_gridded_stuff(GriddedMotionType gridmotiontype,gridded_file_inf
   LMatrix4f tmat1,tmat2,xfm_mat;
 
   for(int i = 0; i < size; i++) {
-        double time_delta = (now-InfoArr[i].starttime);
-
-        #define DO_FP_MODULUS(VAL,MAXVAL)  \
-          {if(VAL > MAXVAL) {int idivresult = VAL / (float)MAXVAL;  VAL=VAL-idivresult*MAXVAL;} else  \
-          if(VAL < -MAXVAL) {int idivresult = VAL / (float)MAXVAL;  VAL=VAL+idivresult*MAXVAL;}}
-
-        // probably should use panda lerps for this stuff, but I dont understand how
+  double time_delta = (now-InfoArr[i].starttime);
+  #define DO_FP_MODULUS(VAL,MAXVAL)  \
+    {if(VAL > MAXVAL) {int idivresult = VAL / (float)MAXVAL;  VAL=VAL-idivresult*MAXVAL;} else  \
+    if(VAL < -MAXVAL) {int idivresult = VAL / (float)MAXVAL;  VAL=VAL+idivresult*MAXVAL;}}
+  
+  // probably should use panda lerps for this stuff, but I dont understand how
 
     if(gridmotiontype==Rotation) {
 
@@ -1181,18 +1180,32 @@ int framework_main(int argc, char *argv[]) {
   // Create the render node
   render = new NamedNode("render");
 
-  // make a node for the cameras to live under
-  cameras = new NamedNode("cameras");
-  RenderRelation* arc1 = new RenderRelation(render, cameras);
-
-  main_win = ChanConfig(main_pipe, conf, cameras, render, override);
+  ChanConfig chanConfig = ChanConfig(main_pipe, conf, render, override);
+  main_win = chanConfig.get_win();
   assert(main_win != (GraphicsWindow*)0L);
+  cameras = chanConfig.get_group_node(0);
+  cameras->set_name("cameras");
+  for(int group_node_index=1;group_node_index<chanConfig.get_num_groups();
+      group_node_index++) {
+    RenderRelation *arc2 = 
+      new RenderRelation(render, chanConfig.get_group_node(group_node_index));
+  }
+  RenderRelation* arc1 = new RenderRelation(render, cameras);
 
   // is ok if this doesn't work or returns NULL
-  if (rib_pipe != (GraphicsPipe*)0L) {
-    Node *rib_cameras = new NamedNode("rib_cameras");
+  if (rib_pipe != (GraphicsPipe*)0L) { 
+    ChanConfig chanConfig = ChanConfig(rib_pipe, "single", render, override);
+    rib_win = chanConfig.get_win();
+    NamedNode *rib_cameras = chanConfig.get_group_node(0);
+    rib_cameras->set_name("rib_cameras");
+    for(int rib_group_node_index=1;
+        rib_group_node_index<chanConfig.get_num_groups();
+        rib_group_node_index++) {
+      RenderRelation *ribarc = 
+        new RenderRelation(render, 
+                           chanConfig.get_group_node(rib_group_node_index));
+    }
     new RenderRelation(render, rib_cameras);
-    rib_win = ChanConfig(rib_pipe, "single", rib_cameras, render, override);
   }
 
   // Make a node for the lights to live under.  We put the lights in

+ 1 - 1
panda/src/sgraph/Sources.pp

@@ -4,7 +4,7 @@
 #begin lib_target
   #define TARGET sgraph
   #define LOCAL_LIBS \
-    gobj putil graph mathutil linmath
+    gobj putil graph mathutil linmath event
     
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx    
 

+ 95 - 0
panda/src/sgraph/camera.cxx

@@ -18,12 +18,14 @@
 #include <pandabase.h>
 #include "camera.h"
 #include <projection.h>
+#include <throw_event.h>
 
 
 ////////////////////////////////////////////////////////////////////
 // Static variables
 ////////////////////////////////////////////////////////////////////
 TypeHandle Camera::_type_handle;
+const std::string Camera::_CHANGE_CAM = "CamChange";
 
 
 ////////////////////////////////////////////////////////////////////
@@ -169,3 +171,96 @@ remove_display_region(DisplayRegion *display_region) {
     _display_regions.erase(dri);
   }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: Camera::set_*
+//       Access: Public
+//  Description: Overrides projection matrix functions.  The intention
+//               is to throw a camera update event for recalculation
+//               of various parameters used by Direct, rather than
+//               recalculating everything every frame "just in case".
+//               When fully implemented, there will be more specific
+//               information for each event, e.g. 
+//               throw_event(_CHANGE_FOV, get_name(), hfov, vfov)
+////////////////////////////////////////////////////////////////////
+void Camera::
+set_projection(const Projection &projection) {
+	ProjectionNode::set_projection(projection);
+	if(has_name()) {
+	  throw_event(_CHANGE_CAM,get_name());
+	}
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_fov(float hfov) {
+	ProjectionNode::set_fov(hfov);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_fov(float hfov, float vfov) {
+	ProjectionNode::set_fov(hfov, vfov);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_hfov(float hfov) {
+	ProjectionNode::set_hfov(hfov);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_vfov(float vfov) {
+	ProjectionNode::set_vfov(vfov);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_aspect(float aspect) {
+	ProjectionNode::set_aspect(aspect);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_near_far(float cnear, float cfar) {
+	ProjectionNode::set_near_far(cnear,cfar);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_near(float cnear) {
+	ProjectionNode::set_near(cnear);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}
+
+void Camera::
+set_far(float cfar) {
+	ProjectionNode::set_far(cfar);
+	if(has_name())
+	  throw_event(_CHANGE_CAM,get_name());
+	else
+	  throw_event(_CHANGE_CAM,std::string(""));
+}

+ 13 - 0
panda/src/sgraph/camera.h

@@ -64,6 +64,17 @@ PUBLISHED:
   int get_num_drs() const;
   DisplayRegion *get_dr(int index) const;
 
+  void set_projection(const Projection &projection);
+
+  void set_fov(float hfov);
+  void set_fov(float hfov, float vfov);
+  void set_hfov(float hfov);
+  void set_vfov(float vfov);
+  void set_aspect(float aspect);
+  void set_near_far(float cnear, float cfar);
+  void set_near(float cnear);
+  void set_far(float cfar);
+
 private:
   void add_display_region(DisplayRegion *display_region);
   void remove_display_region(DisplayRegion *display_region);
@@ -74,6 +85,8 @@ private:
   typedef pvector<DisplayRegion *> DisplayRegions;
   DisplayRegions _display_regions;
 
+  static const std::string _CHANGE_CAM;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;