ViewportSelect

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 19:21, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   11 
Platform:   Windows  ;   
Language(s) :     C++  ;

---------
Could someone tell me how to use the member function within the ViewportSelect Class..   When I try to use SetBrushRadius it tells me :

error C2352: 'ViewportSelect::SetBrushRadius' : illegal call of non-static member function

The code I am using is

> `

  
\>  ViewportSelect::SetBrushRadius(BRUSH_RADIUS);  
\>  

`

Not sure how to call functions from other classes. Any help would be appreciated.

Thanks,

~Shawn

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 19:52, xxxxxxxx wrote:

Looks to me that you have to allocate/free one:

ViewportSelect* vps = ViewportSelect::Alloc();
if (!vps) return FALSE; //etc.
vps->Init(...); // MUST BE DONE!!!!
vps->SetBrushRadius(...);
// When done:
ViewportSelect::Free(vps);

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 20:15, xxxxxxxx wrote:

okay here's what I have in my MouseInput()

> `

  
\>  Bool SculptTool::MouseInput(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg;)  
\>  {  
\>    
\>       PolygonObject *op = ToPoly(doc->GetActiveObject());  
\>    
\>       if (!doc) return FALSE;  
\>       Real rad = data.GetReal(BRUSH_RADIUS);  
\>       Real mx = msg.GetReal(BFM_INPUT_X);  
\>       Real my = msg.GetReal(BFM_INPUT_Y);  
\>       Real mz = msg.GetReal(BFM_INPUT_Z);  
\>       LONG button;  
\>    
\>    
\>       switch (msg.GetLong(BFM_INPUT_CHANNEL))  
\>       {  
\>            case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;  
\>            case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;  
\>            default: return TRUE;  
\>       }  
\>    
\>    
\>       Real dx, dy;  
\>       BaseContainer bc;  
\>       BaseContainer device;  
\>       win->MouseDragStart(button,mx,my,MOUSEDRAG_DONTHIDEMOUSE|MOUSEDRAG_NOMOVE);  
\>       while (win->MouseDrag(&dx;,&dy;,&device;)==MOUSEDRAG_CONTINUE)  
\>       {  
\>    
\>            //DRAW THE CIRCLE AROUND THE MOUSE///////////////////////  
\>       ViewportSelect* vps = ViewportSelect::Alloc();  
\>       if (!vps) return FALSE; //etc.  
\>       vps->Init(...); // MUST BE DONE!!!!  
\>       vps->ShowHotspot(win,mx,my);  
\>       vps->SetBrushRadius(BRUSH_RADIUS);  
\>         
\>            EventAdd(EVENT_FORCEREDRAW);  
\>    
\>       ////////////////////////////////////////////////////  
\>       GePrint("Mouse's X Position is: " + RealToString(mx));  
\>       GePrint("Mouse's Y Position is: " + RealToString(my));  
\>       GePrint("Mouse's Z Position is: " + RealToString(mz));  
\>         
\>       return TRUE;  
\>       }  
\>       return TRUE;  
\>  // When done:  
\>  ViewportSelect::Free(vps);  
\>  

`

I have a few questions,

A. I am not sure what to do with ViewportSelect::init(...)

B. When I attempt to build, ignoring the fact that init() isn't correct, I also get an error that says

error C2065: 'vps' : undeclared identifier

Any thoughts on these.

The SDK says the following about init()

> Quote: __
>
> * * *
>
> Initializes the viewport information for a single object. This has to be done before the pixel information can be retrieved. You have to retrieve the width and height of the viewport manually:
>
>
> LONG left, top, right, bottom, width, height
> bd- >GetFrame(&left;, ⊤, &right;, ⊥);
> width = right - left + 1;
> height = bottom - top + 1;
>
>
>
>
> * * *

But how do I determine the width and height of the viewport?

Thanks,

~Shawn

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 20:22, xxxxxxxx wrote:

okay figured out everything except the

error C2065: 'vps' : undeclared identifier

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 20:32, xxxxxxxx wrote:

You're doing the Free after 'return TRUE'. Again, 'return' instantly exits the function and 'returns' to the caller. You should be doing the ViewportSelect::Free(vps); right before the first return TRUE in MouseInput().

I was hoping you'd figure out where to get the width and height (from the BaseDraw). :)

Also, you really don't want to 'return TRUE' inside the while loop.

> Bool SculptTool::MouseInput(BaseDocument \*doc, BaseContainer &data;, BaseDraw \*bd, EditorWindow \*win, const BaseContainer &msg;) \> { \> \>      PolygonObject \*op = ToPoly(doc->GetActiveObject()); \> \>      if (!doc) return FALSE; \>      Real rad = data.GetReal(BRUSH_RADIUS); \>      Real mx = msg.GetReal(BFM_INPUT_X); \>      Real my = msg.GetReal(BFM_INPUT_Y); \>      Real mz = msg.GetReal(BFM_INPUT_Z); \>      LONG button; \> \> \>      switch (msg.GetLong(BFM_INPUT_CHANNEL)) \>      { \>           case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break; \>           case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break; \>           default: return TRUE; \>      } \> \>      ViewportSelect\* vps = ViewportSelect::Alloc(); \>      if (!vps) return FALSE; //etc. \> \>      Real dx, dy; \>      BaseContainer bc; \>      BaseContainer device; \>      win->MouseDragStart(button,mx,my,MOUSEDRAG_DONTHIDEMOUSE|MOUSEDRAG_NOMOVE); \>      while (win->MouseDrag(&dx;,&dy;,&device;)==MOUSEDRAG_CONTINUE) \>      { \> \>           //DRAW THE CIRCLE AROUND THE MOUSE/////////////////////// \>           vps->Init(...); // MUST BE DONE!!!! \>           vps->ShowHotspot(win,mx,my); \>           vps->SetBrushRadius(BRUSH_RADIUS); \>       \>           EventAdd(EVENT_FORCEREDRAW); \> \>           //////////////////////////////////////////////////// \>           GePrint("Mouse's X Position is: " + RealToString(mx)); \>           GePrint("Mouse's Y Position is: " + RealToString(my)); \>           GePrint("Mouse's Z Position is: " + RealToString(mz)); \>       \>      } \>      // When done: \>      ViewportSelect::Free(vps); \>      return TRUE; \> }

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 20:40, xxxxxxxx wrote:

How do I fix this error?

error C2065: 'vps' : undeclared identifier

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 20:53, xxxxxxxx wrote:

Programming 101: Scope

Variables are declared and remain declared within the scope inwhich they are declared. If you declare 'vps' in the while loop and then try to call ViewportSelect::Free(vps) outside of the while loop, the compiler doesn't know what you're talking about - that call is outside the scope in which 'vps' was declared. In the code that I posted just before, you see that ViewportSelect* vps = ViewportSelect::Alloc() and ViewportSelect::Free(vps) are in the same 'scope' and, for best practices, outside of the while loop*.

* Unless there is a specific reason to allocate/free memory in a loop, it is always best to do it before/after the loop so as to avoid the multiple allocations/frees the loop will incur.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 20:56, xxxxxxxx wrote:

lol..   thanks for the lesson. ~Shawn

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 21:07, xxxxxxxx wrote:

We all confront this. Wait until you are trying to declare variables as class members for persistence so as to save on function arguments and forget what pertinent data they carry from function to function in different situations (is it still valid, does it need to be updated?). It can be torturous to debug. :D

An excellent book for dealing with memory management (in all forms) is "Memory as a Programming Concept in C and C++" by Frantisek Franek (what a name!). It opened my eyes to all sorts of issues that we as programmers in a language that requires direct memory management (heap and stack) must deal with. Also, 'troll' the game developer sites (flipcode, gamedev.net, etc.). They get quite austere about programming practices that create stable, reliable, memory conscious code for the fastest performance. For instance, unrolling small, static loops (between 1 and 8 maybe) is much more efficient than doing for loops. Why? Because the overhead of a for loop in such a situation can be less efficient than simply duplicating the code for the static indices. More typing, better and faster results. Another is pre-increment vs. post-increment. Pre-incrementation (++i) is more efficient since most C/C++ compilers create two calls for post-increment (i++) whereas (++i) is one call. Subleties abound...

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 21:23, xxxxxxxx wrote:

I'll have to check some of those books and sites out.

So I decided to change where I am doing this. Instead of in the MouseInput(), I want to do this in the Draw(),

However, I do not have an EditorWindow in the arguments.

I tried to declare one with:

EditorWindow *win;

but it of course tells me that "win" is an uninitialized local variable.

I assume it should look more like

EditorWindow *win = EditorWindow::Something();

I'm just not sure what Something() is..

Do you know?

~Shawn

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 22:05, xxxxxxxx wrote:

EditorWindow* win = bd->GetEditorWindow();

It isn't something that you can instantiate but must get from a function argument or the BaseDraw.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2009 at 22:22, xxxxxxxx wrote:

when I build the project, it works but when I run c4d and select the tool, the viewport starts to freak out. and then it says it's out of memory. What I want is to draw a circle around the radius of the brush.

ANy thoughts as to why this owuld be happening?

Here's the code for all of Draw() whis includes the symmetry plane.

~Shawn

> `

  
\>  LONG SculptTool::Draw(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,LONG flags)  
\>  {  
\>            EditorWindow *win = bd->GetEditorWindow();  
\>              
\>            PolygonObject *op = ToPoly(doc->GetActiveObject());  
\>          LONG lngMySymPlane =data.GetLong (MIRROR_PLANE);  
\>          LONG trans = 175;  
\>          Vector color = data.GetVector(PLANE_COLOR);  
\>    
\>            LONG bRad = data.GetLong(BRUSH_RADIUS);  
\>            Real mx = data.GetReal(BFM_INPUT_X);  
\>            Real my = data.GetReal(BFM_INPUT_Y);  
\>            Real mz = data.GetReal(BFM_INPUT_Z);  
\>    
\>            //DRAW THE CIRCLE AROUND THE MOUSE///////////////////////  
\>    
\>            ViewportSelect* vps = ViewportSelect::Alloc();  
\>            if (!vps) return FALSE; //etc.  
\>         
\>            LONG left, top, right, bottom, width, height;  
\>            bd->GetFrame(&left;, ⊤, &right;, ⊥);  
\>            width = right - left + 1;  
\>            height = bottom - top + 1;  
\>            Bool ov = true;  
\>    
\>            vps->Init(width,height,bd,op,Mpolyedgepoint,ov,0); // MUST BE DONE!!!!  
\>            vps->ShowHotspot(win,mx,my);  
\>            vps->SetBrushRadius(bRad);  
\>            EventAdd(EVENT_FORCEREDRAW);  
\>         
\>    
\>            ////////////////////////////////////////////////////  
\>              
\>         
\>          //Matrix for determining scale, rotation, and position.   
\>          Matrix m = op->GetMg();  
\>          Vector rad = op->GetRad();  
\>    
\>          m.v1 *= rad.x+100;  
\>          m.v2 *= rad.y+100;  
\>          m.v3 *= rad.z+100;  
\>    
\>    
\>          switch (lngMySymPlane)  
\>          {  
\>    
\>                 case Z_PLANE:  
\>                   
\>                 if (data.GetBool(SHOW_PLANE)) // If SHOW_PLANE is checked, then draw the polygon.  
\>                 {  
\>    
\>                 Vector p[4];  
\>    
\>                 p[0] = Vector(-1,-1,0);  
\>                 p[1] = Vector(-1,1,0);  
\>                 p[2] = Vector(1,1,0);  
\>                 p[3] = Vector(1,-1,0);  
\>    
\>                 p[0] = p[0] * m;  
\>                 p[1] = p[1] * m;  
\>                 p[2] = p[2] * m;  
\>                 p[3] = p[3] * m;  
\>    
\>                 Vector f[3] = { Vector(color),Vector(color),Vector(color)};  
\>    
\>                 bd->SetLightList(BDRAW_SETLIGHTLIST_NOLIGHTS);  
\>                 bd->SetTransparency(trans);  
\>                 bd->Polygon3D(p,f,TRUE);  
\>                      EventAdd(EVENT_FORCEREDRAW);  
\>    
\>    
\>                 return true;  
\>                 }  
\>                 else //If SHOW_PLANE is unchecked, stop drawing the polygon.  
\>                 {  
\>                 Vector p[4] = { Vector(0,0,0),Vector(0,0,0),Vector(0,0,0),Vector(0,0,0)};  
\>                 Vector f[3] = { Vector(0,0,0),Vector(0,0,0),Vector(0,0,0)};  
\>                 bd->Polygon3D(p,f,FALSE);  
\>                      EventAdd(EVENT_FORCEREDRAW);  
\>                 }  
\>    
\>              return DRAW_HANDLES|DRAW_AXIS;  
\>                 break;  
\>    
\>                 case X_PLANE:  
\>                 if (data.GetBool(SHOW_PLANE)) // If SHOW_PLANE is checked, then draw the polygon.  
\>                 {  
\>    
\>                 Vector p[4];      
\>                   
\>                 p[0] = Vector(0,-1,-1);  
\>                 p[1] = Vector(0,-1,1);  
\>                 p[2] = Vector(0,1,1);  
\>                 p[3] = Vector(0,1,-1);  
\>    
\>                 p[0] = p[0] * m;  
\>                 p[1] = p[1] * m;  
\>                 p[2] = p[2] * m;  
\>                 p[3] = p[3] * m;  
\>    
\>                 Vector f[3] = { Vector(color),Vector(color),Vector(color)};  
\>    
\>                 bd->SetLightList(BDRAW_SETLIGHTLIST_NOLIGHTS);  
\>                 bd->SetTransparency(trans);  
\>                 bd->Polygon3D(p,f,TRUE);   
\>                      EventAdd(EVENT_FORCEREDRAW);  
\>                            
\>                 return true;  
\>                 }  
\>                 else //If SHOW_PLANE is unchecked, stop drawing the polygon.  
\>                 {  
\>                 Vector p[4] = { Vector(0,0,0),Vector(0,0,0),Vector(0,0,0),Vector(0,0,0)};  
\>                 Vector f[3] = { Vector(0,0,0),Vector(0,0,0),Vector(0,0,0)};  
\>                 bd->Polygon3D(p,f,FALSE);  
\>                      EventAdd(EVENT_FORCEREDRAW);  
\>                 }  
\>    
\>              return DRAW_HANDLES|DRAW_AXIS;  
\>                 break;  
\>    
\>                 case Y_PLANE:  
\>                 if (data.GetBool(SHOW_PLANE)) // If SHOW_PLANE is checked, then draw the polygon.  
\>                 {  
\>    
\>                 Vector p[4];  
\>                   
\>                 p[0] = Vector(-1,0,-1);  
\>                 p[1] = Vector(-1,0,1);  
\>                 p[2] = Vector(1,0,1);  
\>                 p[3] = Vector(1,0,-1);  
\>    
\>                 p[0] = p[0] * m;  
\>                 p[1] = p[1] * m;  
\>                 p[2] = p[2] * m;  
\>                 p[3] = p[3] * m;  
\>    
\>                 Vector f[3] = { Vector(color),Vector(color),Vector(color)};  
\>    
\>                 bd->SetLightList(BDRAW_SETLIGHTLIST_NOLIGHTS);  
\>                 bd->SetTransparency(trans);  
\>                 bd->Polygon3D(p,f,TRUE);   
\>                      EventAdd(EVENT_FORCEREDRAW);  
\>                            
\>                 return true;  
\>                 }  
\>                 else //If SHOW_PLANE is unchecked, stop drawing the polygon.  
\>                 {  
\>                 Vector p[4] = { Vector(0,0,0),Vector(0,0,0),Vector(0,0,0),Vector(0,0,0)};  
\>                 Vector f[3] = { Vector(0,0,0),Vector(0,0,0),Vector(0,0,0)};  
\>                 bd->Polygon3D(p,f,FALSE);  
\>                      EventAdd(EVENT_FORCEREDRAW);  
\>                 }  
\>    
\>              return DRAW_HANDLES|DRAW_AXIS;  
\>                 break;  
\>          }  
\>                      ViewportSelect::Free(vps);       
\>       return TRUE;  
\>  }  
\>  

`

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 13/09/2009 at 08:31, xxxxxxxx wrote:

Wherever you return in Draw() after you've done ViewportSelect::Alloc(), you will need to free it with ViewportSelect::Free(vps). You can simply repeat this line before each return statement. Again, memory management. Any memory you allocate must be freed by you at some point unless the management is passed to another owner (such as when you insert an object, tag, material, etc. into a document, etc. where C4D takes ownership).

What you could do instead is do the allocation more statically (one time for your plugin) and free one time. In a tool plugin this could be done in InitTool() and FreeTool() for the allocation and the free, respectively, of the ViewportSelect. The variable (vps) would need to be declared a class member of your plugin class and no need to allocate/free in Draw() - you just need to call vps->Init() and so on in Draw().

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 13/09/2009 at 11:03, xxxxxxxx wrote:

awesome.. I'll try it out when I get home.

~Shawn