On 17/06/2014 at 12:27, xxxxxxxx wrote:
At the risk of posting too much code.
Here's an entire Tool plugin I wrote a while ago using ViewportSelect() and GetPixelInfoPoint() to select the points of an object. With a range value option.
//This is an example of using a radius to select points of an object
//Once the points are found. The ViewportSelect class is used to select them in the scene
#include "c4d.h"
#include "radSelect.h"
#include "c4d_symbols.h"
#define ID_SCULPTING_TOOL 000000002 //Testing ID ONLY!!!!
class RadiusSelect : public DescriptionToolData
{
public:
RadiusSelect();
virtual ~RadiusSelect();
private:
virtual LONG GetToolPluginId() { return ID_SCULPTING_TOOL; }
virtual const String GetResourceSymbol() { return String("radSelect"); }
virtual Bool InitTool(BaseDocument *doc, BaseContainer &data, BaseThread *bt);
virtual void FreeTool(BaseDocument *doc, BaseContainer &data);
virtual void InitDefaultSettings(BaseDocument *doc, BaseContainer &data);
virtual Bool GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);
virtual Bool MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);
ViewportSelect *vps; //USed later on for selecting the points of the object
LONG eWinWidth, eWinHeight; //The editor window's scale values
//Custom methods to select an object's points if they're within the radius range
Bool createVPS(BaseDocument *doc, BaseDraw *bd);
void selectRadius(Vector* points, BaseContainer &data, Real mouseX, Real mouseY, Real radius);
};
RadiusSelect::RadiusSelect()
{
vps = NULL;
}
RadiusSelect::~RadiusSelect()
{
ViewportSelect::Free(vps);
}
Bool RadiusSelect::InitTool(BaseDocument *pDoc, BaseContainer &data, BaseThread *bt)
{
if(!DescriptionToolData::InitTool(pDoc, data, bt)) return FALSE; //Loads the .res file gizmo stuff
//Since we could launch this tool many times
//We will free the ViewportSelect memory used every time it launches as a precaution
ViewportSelect::Free(vps);
return TRUE;
}
void RadiusSelect::FreeTool(BaseDocument *pDoc, BaseContainer &data)
{
//Free the memory used when the plugin closes
ViewportSelect::Free(vps);
DescriptionToolData::FreeTool(pDoc,data);
}
void RadiusSelect::InitDefaultSettings(BaseDocument *doc, BaseContainer &data)
{
data.SetReal(SELECTION_RADIUS, 40.0);
DescriptionToolData::InitDefaultSettings(doc, data);
}
Bool RadiusSelect::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc)
{
if (bc.GetId()!=BFM_CURSORINFO_REMOVE)
{
bc.SetString(RESULT_BUBBLEHELP, "My Sculpt Tool"); //Text shown in the bottom left corner of the C4D UI
bc.SetLong(RESULT_CURSOR, MOUSE_PAINTMOVE);
}
return TRUE;
}
Bool RadiusSelect::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg)
{
//This is how to get the pixel values for the editor window (the main scene view window) if needed
//LONG left, top, right, bottom; //The pixel dimensions of the editor view window
//bd->GetFrame(&left, &top, &right, &bottom); //Gets the dimensions in pixels of the editor view window an stores them in the above variables
//This calls to and executes the custom function that allocates an instance of the ViewportSelect class so we can select object points
if (!createVPS(doc, bd)) return FALSE;
Real mouseX = msg.GetReal(BFM_INPUT_X); //Get the mouse's X position in the editor view
Real mouseY = msg.GetReal(BFM_INPUT_Y); //Get the mouse's Y position in the editor view
Real draggingX; //We will use these variables to store the mouse's position values while RMB dragging in the editor view
Real draggingY;
PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject(); //The object we're sculpting on
Vector *points = obj->GetPointW(); //Gets all of the point positions in the object
Real radius = data.GetReal(SELECTION_RADIUS); //Gets the radius value from the GUI options (how many points we will select)
//This code block checks if the mouse is being dragged with them RMB held down
//If it is being dragged...Then it runs the code to move the points in the object
win->MouseDragStart(KEY_MLEFT, mouseX, mouseY, MOUSEDRAGFLAGS_DONTHIDEMOUSE); //Initialise a mouse dragging loop
doc->StartUndo();
doc->AddUndo(UNDOTYPE_CHANGE, obj);
BaseContainer draggingBC; //Stores the dragging data into this container
//While we're RMB dragging. Send the position values to the draggingX & draggingY variables
while (win->MouseDrag(&draggingX, &draggingY, &draggingBC) == MOUSEDRAGRESULT_CONTINUE)
{
mouseX += draggingX; //Constantly update and change the X position values
mouseY += draggingY; //Constantly update and change the Y position values
//Run the custom function that changes the points of the object
selectRadius(points, data, mouseX, mouseY, radius);
//If we don't redraw the editor we won't see the changes until we let go of the RMB
DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);
}
win->MouseDragEnd();
obj->Message(MSG_UPDATE);
doc->EndUndo();
DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);
SpecialEventAdd(EVMSG_UPDATEHIGHLIGHT);
return TRUE;
}
//A custom method that allocates a ViewportSelect instance so you can select a point on the active object
Bool RadiusSelect::createVPS(BaseDocument* doc, BaseDraw* bd)
{
//If we don't have the vps (ViewportSelect) instance created..then create it
if (!vps)
{
//Only get the active object's points
PolygonObject *obj = (PolygonObject* ) doc->GetActiveObject();
if(obj)
{
vps = ViewportSelect::Alloc();
LONG left, top, right, bottom;
bd->GetFrame(&left, &top, &right, &bottom);
eWinWidth = right - left + 1;
eWinHeight = bottom - top + 1;
if (!vps->Init(eWinWidth, eWinHeight, bd, obj, Mpoints, TRUE, VIEWPORTSELECTFLAGS_0)) return FALSE;
}
}
return TRUE;
}
//A custom method that moves the points based on the mouse position, radius, and vector values
void RadiusSelect::selectRadius(Vector *points, BaseContainer &data, Real mouseX, Real mouseY, Real radius)
{
//The object we are targeting to grab it's points with the mouse
PolygonObject *obj = (PolygonObject* ) GetActiveDocument()->GetActiveObject();
Real radSqr = radius * radius;
if (radSqr < 1.0) return;
//This code block sets up the radius around the mouse's current position
//x1 is amount of screen pixels to check towards the left of the mouse
//x2 is amount of screen pixels to check towards the right of the mouse
//y1 is amount of screen pixels to check towards the top of the mouse
//y2 is amount of screen pixels to check towards the bottom of the mouse
LONG x1 = LMax(0, (LONG)(mouseX - radius)); //Gets the mouseX position - the radius value (but returns 0 if value is less than zero)
LONG x2 = LMin(eWinWidth - 1, (LONG)(mouseX + radius)); //Gets the mouseX position + the radius value (but returns the screen width if value is more than the screen width)
LONG y1 = LMax(0, (LONG)(mouseY - radius)); //Gets the mouseY position - the radius value (but returns 0 if value is less than zero)
LONG y2 = LMin(eWinHeight - 1, (LONG)(mouseY + radius)); //Gets the mouseY position + the radius value (but returns the screen height if value is more than the screen height)
//Loop through the pixels in the screen in a matrix like fashion
//By getting the pixels using Rows & Columns using 2 for loops
for (LONG i = x1; i <= x2; i++)
{
for (LONG j = y1; j <= y2; j++)
{
Real rSqrDist = (i - mouseX)*(i - mouseX) + (j - mouseY)*(j - mouseY);
if (rSqrDist > radSqr) continue;
//Get the point of an object in the scene at this screen pixel location
ViewportPixel *pPixel = vps->GetPixelInfoPoint(i, j);
while (pPixel)
{
//If the point found belongs to our desired target object
if (pPixel->op == obj)
{
//This code will select the points on the object if they're within the radius range
BaseSelect *bs = obj->GetPointS();
bs->Select(pPixel->i);
}
pPixel = pPixel->next;
}
}
}
obj->Message(MSG_UPDATE);
}
Bool RegisterRadiusSelect()
{
return RegisterToolPlugin(ID_SCULPTING_TOOL, GeLoadString(IDS_RADSELECT_TOOL), 0, AutoBitmap("myicon.png"), GeLoadString(IDS_RADSELECT_TOOL), gNew RadiusSelect);
}
I hope that's not too much code to sift through.
-ScottA