On 08/01/2015 at 08:53, xxxxxxxx wrote:
Thank you Sebastian. But that's not quite enough information.
I still don't understand how to create _nodeGUI and _nodeMaster.
Here is my entire working GeDialog plugin with a User Area attached to it.
I'm trying to figure out how to use the UA as an xpresso window. But I'm having trouble understanding how to set up the basic framework for it.
#include "c4d.h"
#include "c4d_symbols.h"
#include "ge_dynamicarray.h"
#define PLUGIN_ID 1000006 // be sure to use a unique ID obtained from www.plugincafe.com
enum
{
USERAREA = 3001
};
class MyUserArea : public GeUserArea
{
//For the mouse positions within the User Area while LMB dragging
LONG mouseX;
LONG mouseY;
LONG prevX;
LONG prevY;
public:
MyUserArea(void);
virtual Bool Init(void);
virtual Bool GetMinSize(LONG &w,LONG &h);
virtual void DrawMsg(LONG x1,LONG y1,LONG x2,LONG y2, const BaseContainer &msg);
virtual Bool InputEvent(const BaseContainer& msg);
virtual LONG Message(const BaseContainer &msg, BaseContainer &result);
};
MyUserArea::MyUserArea(void)
{}
Bool MyUserArea::Init(void)
{
return TRUE;
}
Bool MyUserArea::GetMinSize(LONG &w,LONG &h)
{
w = 200;
h = 200;
return TRUE;
}
void MyUserArea::DrawMsg(LONG x1,LONG y1,LONG x2,LONG y2, const BaseContainer &msg)
{
//To make the bitmaps more stable. Use OffScreenOn() before drawning them in GUI's
OffScreenOn();
DrawSetPen(COLOR_TEXT); //Set a color for the UA
DrawRectangle(x1, y1, x2, y2); //Draws the rectangle UserArea using the color
}
Bool MyUserArea::InputEvent(const BaseContainer& msg)
{
LONG dev = msg.GetLong(BFM_INPUT_DEVICE); //Get the device being used (mouse, keyboard, etc...)
LONG chn = msg.GetLong(BFM_INPUT_CHANNEL); //Get the device's component (LMB, MWheel, keyboard key, etc...)
if (dev==BFM_INPUT_MOUSE)
{
//Create an action message and also get the UserArea's id. And store them in a container called action
//This will be used later to tell the parent dialog that the UA has been changed in some manner
BaseContainer action(BFM_ACTION);
action.SetLong(BFM_ACTION_ID, GetId());
action.SetLong(BFM_ACTION_VALUE, 0);
//If the left mouse button is down...do some desired action
if(chn==BFM_INPUT_MOUSELEFT)
{
LONG mx = msg.GetLong(BFM_INPUT_X); //Get the mouses's X position
LONG my = msg.GetLong(BFM_INPUT_Y); //Get the mouses's Y position
Bool dc = msg.GetBool(BFM_INPUT_DOUBLECLICK); //Checks if the LMB was double clicked or not
Global2Local(&mx,&my); //Converts the mouse positions to screen values relative to the UA
BaseContainer mState; //Create a container that we will store the mouse actions we do in this next loop
while (GetInputState(BFM_INPUT_MOUSE,BFM_INPUT_MOUSELEFT, mState))
{
if (mState.GetLong(BFM_INPUT_VALUE)==0) break; //If the state value is 0. The LMB is no longer down..so exit the loop
LONG dx = mState.GetLong(BFM_INPUT_X); //Store the mouse positions only while dragging it
LONG dy = mState.GetLong(BFM_INPUT_Y); //Store the mouse positions only while dragging it
Global2Local(&dx,&dy);
//We can't use any Draw functions in the InputEvent() method. We have to do it in the DrawMsg() method
//So we must pass the mouse coords to class level variables so the DrawMsg() method can use them
prevX=dx;
prevY=dy;
mouseX=dx;
mouseY=dy;
GePrint("X Pos: " +LongToString(dx) + " " + "Y Pos: " +LongToString(dy));
Redraw();
//action.SetLong(BFM_ACTION_INDRAG,TRUE);
//SendParentMessage(action);
}
Redraw();
//Notify the parent dialog that the dragging is now finished
action.SetLong(BFM_ACTION_INDRAG, FALSE);
SendParentMessage(action);
}
}
return TRUE;
}
LONG MyUserArea::Message(const BaseContainer &msg, BaseContainer &result)
{
switch (msg.GetId())
{
//This code block returns the mouse's position in the UserArea without the LMB being pressed
case BFM_GETCURSORINFO:
{
LONG mouseX = msg.GetLong(BFM_DRAG_SCREENX);
LONG mouseY = msg.GetLong(BFM_DRAG_SCREENY);
if (Screen2Local(&mouseX, &mouseY)) GePrint(LongToString(mouseX) + ", " + LongToString(mouseY));
}
break;
}
return GeUserArea::Message(msg, result);
}
enum
{
MY_TEXT = 1001
};
class MyDialog : public GeDialog
{
private:
MyDialog *dlg;
MyUserArea ua; //Create an instance of the MyUserArea class to use in this dialog's class
C4DGadget *ua_gui; //Create a gizmo variable here so we can use it in all methods. Not just in CreateLayout()
public:
MyDialog(void);
~MyDialog(void);
virtual Bool CreateLayout(void);
virtual Bool InitValues(void);
virtual Bool Command(LONG id,const BaseContainer &msg);
virtual LONG Message(const BaseContainer &msg,BaseContainer &result);
};
MyDialog::MyDialog(void)
{
}
MyDialog::~MyDialog(void)
{
GeFree(dlg);
GeFree(ua);
}
Bool MyDialog::CreateLayout(void)
{
Bool res = TRUE;
res = LoadDialogResource(IDS_RESDIALOG,NULL,0);
//This text box we'll add here in this .cpp file. And not from the external .res file
AddStaticText(MY_TEXT, BFH_SCALEFIT, 0,0, "my text", 0);
//Trying to create an Xpresso based UserArea...Not working!!!
if(_nodeGUI == nullptr)
{
_shape = GvGetWorld()->AllocShape();
_group = GvGetWorld()->AllocGroupShape();
_nodeGUI = GvGetWorld()->AllocNodeGUI(_shape,_group,1000);
}
if(_nodeMaster && _nodeGUI)
{
_nodeGUI->Attach(this,_nodeMaster);
ua_gui = AddUserArea(USERAREA, BFH_SCALEFIT | BFV_SCALEFIT);
//if(ua_gui) AttachUserArea(ua, ua_gui); <---this works fine
if(ua_gui) AttachUserArea(*_nodeGUI->GetUserArea(), 1000, USERAREA_TABSTOP|USERAREA_HANDLEFOCUS);
}
return res;
}
Bool MyDialog::InitValues(void)
{
//first call the parent instance
if (!GeDialog::InitValues()) return FALSE;
this->SetString(MY_TEXT,"Xpresso Node Example");
return TRUE;
}
Bool MyDialog::Command(LONG id,const BaseContainer &msg) //This is where the code that does something goes
{
BaseDocument *doc = GetActiveDocument(); //Get the active document
//Set up some actions that will tell c4d that a gizmo has been triggered..We'll used those action variables later on in the switch code block
LONG myBtn = msg.GetLong(BFM_ACTION_VALUE); //Assigns an action to a variable
GePrint(LongToString(myBtn));
EventAdd();
return TRUE;
}
LONG MyDialog::Message(const BaseContainer &msg, BaseContainer &result)
{
switch(msg.GetId())
{
case BFM_INPUT: //A dialog/userarea receives this message if any mouse or keyboard input is received
if(msg.GetLong(BFM_INPUT_DEVICE) == BFM_INPUT_KEYBOARD) //If the input is from the keyboard
{
String input = msg.GetString(BFM_INPUT_ASC); //Create a string type variable...
GePrint(input); //and assign it to the pressed key's unicode-text value
}
break;
} //End the key pressed case loop /////////////////////////
return GeDialog::Message(msg,result);
}
class XnodeDialog : public CommandData
{
private:
MyDialog dlg;
public:
virtual Bool Execute(BaseDocument *doc);
virtual Bool RestoreLayout(void *secret);
};
Bool XnodeDialog::Execute(BaseDocument *doc)
{
StopAllThreads();
return dlg.Open(DLG_TYPE_ASYNC,PLUGIN_ID, -1, -1, 300,150);
}
Bool XnodeDialog::RestoreLayout(void *secret)
{
return dlg.RestoreLayout(PLUGIN_ID,0,secret);
}
Bool RegisterXnodeDialog(void)
{
String Help = "Status bar text here...";
//Register the plugin
return RegisterCommandPlugin(PLUGIN_ID, "XNode Dialog Example", 0, AutoBitmap("icon.tif"),Help, gNew XnodeDialog);
}
-ScottA