ToolData - moving object handles



  • On 20/08/2015 at 16:10, xxxxxxxx wrote:

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

    ---------
    Howdy,

    OK, I've got a working ToolData plugin that can detect and move my object's handles, but I'm not calculating the matrix properly that gets passed to the ObjectData::MoveHandle() function.

    At first I didn't convert the mouse X and Y to world coordinates, which resulted in the handles moving too fast with the Y handles moving in the opposite direction and the Z handles not moving at all. Then when I converted from screen to world using BaseView::SW(), the handles didn't seem to move much at all. The printout to the console was showing micro movements in thousandths (0.001).

    How should I properly calculate the matrix to be passed to the ObjectData::MoveHandle() function?

    Adios,
    Cactus Dan



  • On 20/08/2015 at 16:28, xxxxxxxx wrote:

    Howdy,

    Never mind, I figured it out. I needed to calculate the Z according to what view is active. DOH! 😊

    EDIT:
    Well, I'm still doing something wrong because if my object is not at orientation 0º,0º,0º, then the mouse movement moves some of the handles in the opposite direction. 

    Adios,
    Cactus Dan



  • On 20/08/2015 at 20:10, xxxxxxxx wrote:

    Howdy,

    Well, never mind again. I just needed to transform it to my object's space. It's late maybe I ought to turn the computer off and go to bed and take a fresh look at it in the morning. 😂

    Adios,
    Cactus Dan



  • On 21/08/2015 at 04:09, xxxxxxxx wrote:

    Hi Dan,

    we do not mind at all. Actually I'm glad to see, that I'm not the only developer having such "phases". 😉



  • On 23/08/2015 at 14:37, xxxxxxxx wrote:

    Howdy,

    Well, everything I've done is working in R12 but not in R13, R14, R15 or R16. Using ObjectData::DetectHandle() and ObjectData::MoveHandle() are not working properly from R13 and up. Even with the built in tools (Selection, Move, etc.), my object's handles jump out of view once you click on them.

    In R13+, if I change my object to use ObjectData::GetHandleCount(), ObjectData::GetHandle() and ObjectData::SetHandle(), then the handles behave properly with the built in tools. But how do I make my ToolData plugin work properly with the object when it's using those functions instead?

    Adios,
    Cactus Dan



  • On 23/08/2015 at 16:27, xxxxxxxx wrote:

    Howdy,

    AHA! I get it now. Even though I switched the object to use GetHandle() and SetHandle(), my tool can still call DetectHandle() and MoveHandle() if I don't override those virtual functions in my object. That wasn't clear in the documentation until I looked at the HandleInfo page where it showed the code for those functions in the ObjectData class. 😵

    Adios,
    Cactus Dan



  • On 24/08/2015 at 08:07, xxxxxxxx wrote:

    Hi Dan,

    thanks for the hint. I agree, the location of that code example is a bit suboptimal. I'll add it to our list of documentation improvements.



  • On 27/08/2015 at 05:52, xxxxxxxx wrote:

    Howdy,

    OK, now I'm trying to get this working in R12, but I've run into a snag. Since versions R12 and earlier, don't have the HandleInfo class, I'm trying to use the code from R13. But there's a problem with the HandleInfo::CalculateNewPosition() function. Versions R12 and earlier do not have the functions BaseView::ProjectPointOnLine(), BaseView::ProjectPointOnPlane() and BaseView::WP_W().

    Can you provide any information that will help me reconstruct the HandleInfo::CalculateNewPosition() for R12 and earlier?

    EDIT :
    Or, if you can tell me how to calculate the "tm" matrix in my tool to pass to the ObjectData::MoveHandle() function for the R12 version, that would work, too.

    Adios,
    Cactus Dan



  • On 28/08/2015 at 19:06, xxxxxxxx wrote:

    Howdy,

    Anything?

    Adios,
    Cactus Dan



  • On 31/08/2015 at 09:28, xxxxxxxx wrote:

    Hi Dan,

    actually we do support only the latest releases of the SDK. But I think, even in the R12 SDK there was the rounded tube example, demonstrating the use of handles. Please check that one first and let me know, if that helped.



  • On 31/08/2015 at 10:01, xxxxxxxx wrote:

    Howdy,

    Well, actually the handles aren't an issue. I've got them working perfectly with the Cinema 4D native tools in R12 and R13+.

    The problem I'm having is how to calculate the matrix properly in the test tool to manipulate the handles in R12.

    Here's my test code for TestTool::MouseInput() :

    Bool TestTool::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)
    {
    	Real mx = msg.GetReal(BFM_INPUT_X);
    	Real my = msg.GetReal(BFM_INPUT_Y);
    	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;
    	}
    	BaseContainer state;
    	GetInputState(BFM_INPUT_KEYBOARD, BFM_INPUT_CHANNEL, state);
    	QUALIFIER qlfy = (QUALIFIER)state.GetLong(BFM_INPUT_QUALIFIER);
    	
    	BaseObject *op = doc->GetActiveObject();
    	Matrix opM = op->GetMg();
    	
    	BaseObject *cam = bd->GetEditorCamera(); if(!cam) return true;
    	Real mz = 0.0;
    	if(bd->GetProjection() == 0)
    	{
    		mz = Len(op->GetMg().off - cam->GetMg().off);
    	}
    	else
    	{
    		Vector pPos = bd->WS(op->GetMg().off);
    		mz = pPos.z;
    	}
    	
    	ObjectData *oNode = static_cast<ObjectData*>(op->GetNodeData());
    	
    	Real dx,dy;
    	BaseList2D *undo = NULL;
    	
    	doc->AddUndo(UNDOTYPE_CHANGE, op);
    	undo = doc->GetUndoPtr();
    	BaseContainer device;
    	win->MouseDragStart(button,mx,my,MOUSEDRAGFLAGS_DONTHIDEMOUSE|MOUSEDRAGFLAGS_NOMOVE);
    	while (win->MouseDrag(&dx,&dy,&device)==MOUSEDRAGRESULT_CONTINUE)
    	{
    		if(undo->GetType() != op->GetType()) break;
      
    		mx+=dx;
    		my+=dy;
    		
    	#if API_VERSION < 13000
    		Matrix m = Matrix();
    		m.off = Vector(mx,my,mz);
    		oNode->MoveHandle(op, (BaseObject* )undo, m, hID, qlfy)
    	#else
    		oNode->MoveHandle(op, (BaseObject* )undo, Vector(mx,my,mz), hID, qlfy, bd);
    	#ndif
    		
    		DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);
    	}
      
    	EventAdd();
    	return TRUE;
    }
      
    
    

    The above code works somewhat in R12 but not at all angles. It works perfectly in R13. So, I'm assuming the matrix "m" that I'm passing to ObjectData::MoveHandle() for R12 is not correct. The rounded tube example for R12 isn't showing the use of GetHandle(), SetHandle(), but I managed to get that working creating my own HandleInfo class for R12. There is no example anywhere of a tool to manipulate object handles, so even though I've figured out how to get that to work in R13+, it doesn't work quite right for R12 because R12 needs a matrix passed to the ObjectData::MoveHandle() function instead of a vector, as with R13+.

    All I really need to know is how to properly calculate that matrix for R12 and the tool will work properly in R12, too. 😉

    Adios,
    Cactus Dan



  • On 01/09/2015 at 06:06, xxxxxxxx wrote:

    Hi Dan,
    actually we do not support R12 anymore. I don't even have a test environment to check your code.
    From looking into the documentation, it looks like MoveHandle got passed a transform matrix back in R12 (since R13 screen space coordinates are passed). The matrix you pass seems to use screen coordinates. So I'd suppose you need to convert these. BaseView contains a bunch of functions to do such conversions.



  • On 01/09/2015 at 07:19, xxxxxxxx wrote:

    Howdy,

    DOH! Sorry in my haste to post some example code, I forgot a few lines that pertain to R12. 😊

    This test code is actually what I'm doing in the real code for my tool:

    Bool TestTool::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)
    {
    	Real mx = msg.GetReal(BFM_INPUT_X);
    	Real my = msg.GetReal(BFM_INPUT_Y);
    	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;
    	}
    	BaseContainer state;
    	GetInputState(BFM_INPUT_KEYBOARD, BFM_INPUT_CHANNEL, state);
    	QUALIFIER qlfy = (QUALIFIER)state.GetLong(BFM_INPUT_QUALIFIER);
    	
    	BaseObject *op = doc->GetActiveObject();
    	Matrix opM = op->GetMg();
    	
    	BaseObject *cam = bd->GetEditorCamera(); if(!cam) return true;
    	Real mz = 0.0;
    	if(bd->GetProjection() == 0)
    	{
    		mz = Len(cam->GetMg().off);
    		mz = Len(op->GetMg().off - cam->GetMg().off);
    	}
    	else
    	{
    		Vector pPos = bd->WS(op->GetMg().off);
    		mz = pPos.z;
    	}
    #if API_VERSION < 13000
    	Vector start = bd->SW(Vector(mx,my,mz)) ^ opM;
    #endif
    	
    	ObjectData *oNode = static_cast<ObjectData*>(op->GetNodeData());
    	
    	Real dx,dy;
    	BaseList2D *undo = NULL;
    	
    	doc->AddUndo(UNDOTYPE_CHANGE, op);
    	undo = doc->GetUndoPtr();
    	BaseContainer device;
    	win->MouseDragStart(button,mx,my,MOUSEDRAGFLAGS_DONTHIDEMOUSE|MOUSEDRAGFLAGS_NOMOVE);
    	while (win->MouseDrag(&dx,&dy,&device)==MOUSEDRAGRESULT_CONTINUE)
    	{
    		if(undo->GetType() != op->GetType()) break;
      
    		mx+=dx;
    		my+=dy;
      
    	#if API_VERSION < 13000
    		Vector end = bd->SW(Vector(mx,my,mz)) ^ opM;
    		Vector dir = end - start;
    		Matrix m = Matrix();
    		m.off = dir;
    		oNode->MoveHandle(op, (BaseObject* )undo, m, hID, qlfy);
    	#else
    		oNode->MoveHandle(op, (BaseObject* )undo, Vector(mx,my,mz), hID, qlfy, bd);
    	#endif
    		DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);
    	}
      
    	EventAdd();
    	return TRUE;
    }
      
    
    

    The SDK documentation says for the matrix parameter:

    const  [Matrix](file:///Users/danlibisch/Documentation/C4D%20Manuals/R12%20SDK/pages/ge_math/class_Matrix905.html)& tm
    > The amount the handle has been moved by the user.


    ... so I assumed I needed to calculate a "start" and "end" position to get a direction vector for the m.off. But it doesn't seem to be correct because it's not working at all angles. It does seem to work when the object is at world orientation 0,0,0, but once the object is rotated then the movement is not correct. In fact at some object and camera orientations the movement is backwards.

    What am I missing?

    Adios,
    Cactus Dan



  • On 03/09/2015 at 06:58, xxxxxxxx wrote:

    Howdy,

    No hints on the second corrected code I posted?

    Originally posted by xxxxxxxx

    Hi Dan,
    actually we do not support R12 anymore. I don't even have a test environment to check your code.

    Well, that is really a shame, because about 40% of my plugin sales have always been to users of older than current versions of Cinema 4D. That's almost half of my business.

    Adios,
    Cactus Dan



  • On 03/09/2015 at 07:09, xxxxxxxx wrote:

    Hi Dan,

    as I said, I don't even have a R12 environment here. I looked through your code and I don't see the bug. Suspecting the vector math, but without trying, I'm not able to provide useful input. Normally we support only the latest SDK versions.
    Currently we are pretty busy here and I can't say, when exactly I will find the time to set up an R12 test environment. So I need to beg for your patience and understanding.



  • On 03/09/2015 at 07:55, xxxxxxxx wrote:

    Howdy,

    Thanks.

    I'm also going to be busy for a little while updating my plugins for R17 before I get back to this. I was hoping to get this solved before tackling the R17 updates, but it can wait. 😉

    Adios,
    Cactus Dan



  • On 19/09/2015 at 15:13, xxxxxxxx wrote:

    Howdy,

    Well, I may have found a usable solution, but I'd still like to know the correct one.

    For the "start" and "end" vectors, instead of doing this:

    Vector start = bd->SW(Vector(mx,my,mz)) ^ opM;
    Vector end = bd->SW(Vector(mx,my,mz)) ^ opM;
    

    … I'm doing this:

    Vector start = !opM * bd->SW(Vector(mx,my,mz));
    Vector end = !opM * bd->SW(Vector(mx,my,mz));
    

    .. and that seems to make it work somewhat.

    Depending on the angle of the view (perspective camera), the mouse seems to need to be dragged farther than the actual handle movement, but at least it's moving in the correct direction at all angles.

    Maybe I'll have the tool hide the mouse while dragging, like the Cinema 4D tools do in R12.

    Adios,
    Cactus Dan


Log in to reply