Hi @LingZA ,
Sorry for the delayed answer.
Could you please explain the result that you're trying to achieve?
It looks now that you would like to implement a modeling tool similar to Bevel, when you would like to firstly select points/edges/polys and secondly apply some changes to them. If that's the case, then you need to implement the part of your tool that selects objects. Please have a look at BaseSelect. You can also explore Flatten Polygons example.
You can find a sample code snippet below that simply selects all of the edges of the polygon. You need to be in "Edges" mode for that. Additionally you can emulate the polygon highlighting yourself.
Regarding the flags:
PLUGINFLAG_TOOL_EDITSTATES - designates that the tool supports deformed editing
PLUGINFLAG_TOOL_SWITCHACTION - allows to adjust the active tool. This works in tandem with the MSG_TOOL_SWITCHACTION message type. Namely, when the modifier (aka qualifier) key is pressed, the plugin receives this message such that it can react on this key press.
PLUGINFLAG_TOOL_NO_TOPOLOGY_EDIT - flag that informs cinema that the tool doesn't perform any topology modifications (i.e. doesn't add/remove/reassign of the polygons)
PLUGINFLAG_TOOL_TWEAK - if you click on the element that isn't currently selected, it will select it for you (so your tool can work with this selection), and will deselect it once your tool finishes
PLUGINFLAG_TOOL_TWEAK_NO_HIGHLIGHT - same as above but without highlighting the temporarily selected element
PLUGINFLAG_TOOL_DRAW_MULTIPLANE - some legacy flag that is (or at least should be) deprecated
Cheers,
Ilia
Cinema_4D_EZZRKgKU0Y.gif
import c4d
PLUGIN_ID = 1234321 # Be sure to use a unique ID obtained from www.plugincafe.com
class MyTool(c4d.plugins.ToolData):
def __init__(self):
self.selectionRadius = 10
self.highlightedPolygon: int = -1
def GetState(self, doc):
if doc.GetMode() != c4d.Medges:
return False
return c4d.CMD_ENABLED
def MouseInput(self, doc, data, bd, win, msg):
# Only handle left click
if msg[c4d.BFM_INPUT_CHANNEL] != c4d.BFM_INPUT_MOUSELEFT:
return True
# Get active object
op = doc.GetActiveObject()
if not op: return True
if self.highlightedPolygon < 0:
return True
# Initialize helping Neighbor struct
nbr = c4d.utils.Neighbor()
nbr.Init(op)
polyInfo = nbr.GetPolyInfo(self.highlightedPolygon) # get polygon information
bs = c4d.BaseSelect()
opPolygon: c4d.CPolygon = op.GetPolygon(self.highlightedPolygon)
# Iterate over sides
for side in range(4):
# Skip last edge if polygon is a triangle
if side == 2 and opPolygon.c == opPolygon.d:
continue
# Select edge
edgeIdx = polyInfo['edge'][side]
bs.Select(edgeIdx)
# Apply selection
op.SetSelectedEdges(nbr, bs, c4d.EDGESELECTIONTYPE_SELECTION)
c4d.EventAdd()
return True
def Draw(self, doc, data, bd, bh, bt, flags):
selectionColor = c4d.GetViewColor(c4d.VIEWCOLOR_SELECTION_PREVIEW)
if flags & c4d.TOOLDRAWFLAGS_HIGHLIGHT: # if the DrawPass is the Highlight one
if self.highlightedPolygon >= 0:
# Get active object
op = doc.GetActiveObject()
if not op: return True
bd.SetMatrix_Matrix(op, op.GetMg()) # draw in global coordinates
# Get points and polygon from the object
opPoints: list[c4d.Vector] = op.GetAllPoints()
opPolygon: c4d.CPolygon = op.GetPolygon(self.highlightedPolygon)
points = [opPoints[idx] for idx in (opPolygon.a, opPolygon.b, opPolygon.c, opPolygon.d)]
colors = [selectionColor for _ in points]
if len(points) == 3 or len(points) == 4:
bd.DrawPolygon(points, colors) # draw the polygon highlight
# Draw the outline
bd.SetPen(c4d.Vector(0, 1, 0))
for point1Idx in range(-1, len(points) - 1):
point1, point2 = points[point1Idx], points[point1Idx + 1]
bd.DrawLine(point1, point2, c4d.NOCLIP_D)
return c4d.TOOLDRAW_HIGHLIGHTS
def GetCursorInfo(self, doc, data, bd, x, y, bc):
self.highlightedPolygon = -1
# If the cursor has left a user area, simply return True
if bc.GetId() == c4d.BFM_CURSORINFO_REMOVE or doc.GetMode() != c4d.Medges:
return True
# Get active object
op = doc.GetActiveObject()
if not op: return True
# Calculates the width and height of the screen
bd: c4d.BaseDraw = doc.GetActiveBaseDraw()
frame = bd.GetFrame()
l, r, t, b = frame["cl"], frame["cr"], frame["ct"], frame["cb"]
width, height = r - l + 1, b - t + 1
# Initialize viewport select
vpSelect = c4d.utils.ViewportSelect()
vpSelect.Init(width, height, bd, [op], c4d.Medges, True, c4d.VIEWPORTSELECTFLAGS_IGNORE_HIDDEN_SEL)
c4d.SpecialEventAdd(c4d.EVMSG_UPDATEHIGHLIGHT) # pushing highlighting event to cinema
# Looking for the nearest polygon and saving it's index in self.highlightedPolygon
polyInfo = vpSelect.GetNearestPolygon(op, int(x), int(y), self.selectionRadius)
if not polyInfo or 'i' not in polyInfo:
return True
polygonIdx = polyInfo['i']
if (polygonIdx < 0 or polygonIdx >= op.GetPolygonCount()):
return True
self.highlightedPolygon = polygonIdx
return True
if __name__ == "__main__":
c4d.plugins.RegisterToolPlugin(id=PLUGIN_ID, str="MyTool", info=0, icon=None, help="", dat=MyTool())