Howto create interactive arrows for parameter changes

I’m searching for an example code to create arrows like from the gumball which can be moved and and where i can react on the changes during or after the movement.

For example like in rhinogold where you can drag and move a circle to change the position and the diameter (e.g. in the video https://www.youtube.com/watch?v=ISX3dRaZpnI starting at 3:20)
I also made a screenshot and marked the arrows and points which i want to create by my own.
Untitled

following.

Hi @dsw,

There is a RhinoCommon sample that demonstrates how to manipulate geometry with a gumball.

https://github.com/mcneel/rhino-developer-samples/blob/6/rhinocommon/cs/SampleCsCommands/SampleCsGumballCylinder.cs

If you need something in C++ or you need a different sample, let me know.

– Dale

Hi @dale
Thank you for the sample. I think it’s exactly what i wanted. Unfortunately i could not translate everything correctly to c++. i got some weird result.
It would be helpful if you got a simple example how to deal with two ore more gumballs in C++.

Thanks

Hi @dsw,

I’ll try to make this more of a priority.

https://mcneel.myjetbrains.com/youtrack/issue/RH-37372

– Dale

Hi @dale

i made now a short c++ sample by converting your C# sample. It’s not yet fully functional, but it shows my problem with the picking of the gumball. I cannot pick the correct axis, in my case it’s always the y-rotation in perspective view and in the other views i cannot pick at all.

I’m pretty sure there is something wrong with the picking context, but referring to the c++ sample from you ( http://developer.rhino3d.com/guides/cpp/picking-objects-without-crhinogetobject/) it should work.

Can you please have a look at this code?

Thanks

ON_Plane gPlane;
double gRadius = 1.0;
double gHeight = 2.0;

class SampleCsGumballCylinderGetPoint : public CRhinoGetPoint
{
	CRhinoGumballDisplayConduit* m_height_dc;
	ON_3dPoint m_base_origin;
	ON_3dPoint m_base_point;

public:
	SampleCsGumballCylinderGetPoint(CRhinoGumballDisplayConduit* heightDc)
	{
		m_height_dc = heightDc;
		m_base_origin = ON_3dPoint::UnsetPoint;
		m_base_point = ON_3dPoint::UnsetPoint;
	}

	virtual void OnMouseDown(CRhinoViewport& vp, UINT nFlags, const ON_3dPoint& point, const CPoint* view_wnd_point)
	{
		if (m_height_dc->m_pick_result.m_gumball_mode != GUMBALL_MODE::gb_mode_nothing)
			return;

		m_base_origin = ON_3dPoint::UnsetPoint;
		m_base_point = ON_3dPoint::UnsetPoint;

		m_height_dc->m_pick_result.SetToDefaultPickResult();

		CRhinoPickContext pick_context;
		pick_context.m_view = vp.ParentView();
		pick_context.m_pick_style = CRhinoPickContext::point_pick;
		switch (vp.DisplayMode())
		{
			case ON::shaded_display:
			case ON::renderpreview_display:
				pick_context.m_pick_mode = CRhinoPickContext::shaded_pick;
				break;
		}

		vp.GetPickXform(view_wnd_point->x, view_wnd_point->y, pick_context.m_model_xform);
		vp.VP().GetFrustumLine(view_wnd_point->x, view_wnd_point->y, pick_context.m_pick_line);
		pick_context.UpdateClippingPlanes();

		// try picking one of the gumballs
		if (m_height_dc->PickGumball(pick_context, this))
		{
			m_base_origin = gPlane.Origin();
			m_base_point = point;
		}
	}

	virtual void OnMouseMove(CRhinoViewport& vp, UINT nFlags, const ON_3dPoint& point, const CPoint* view_wnd_point)
	{
		if (m_base_origin.IsValid() && m_base_point.IsValid())
		{
			ON_Line world_line;
			if (vp.VP().GetFrustumLine(view_wnd_point->x, view_wnd_point->y, world_line))
			{
				ON_3dVector dir = point - m_base_point;
				double len = dir.Length();
				if (m_base_origin.DistanceTo(point) < m_base_origin.DistanceTo(m_base_point))
					len = -len;

				if (m_height_dc->m_pick_result.m_gumball_mode != GUMBALL_MODE::gb_mode_nothing)
				{
					// update hight gumball
					m_height_dc->UpdateGumball(point, world_line);
					// update cylinder
					gHeight = len;
				}
			}
		}

		CRhinoGetPoint::OnMouseMove(vp, nFlags, point, view_wnd_point);
	}

	virtual void DynamicDraw(HDC dc, CRhinoViewport& vp, const ON_3dPoint& point)
	{
		ON_Cylinder cyl;
		cyl.Create(ON_Circle(gPlane, gRadius), gHeight);
		vp.DrawCylinder(cyl);

		// Disable default GetPoint drawing by not calling the base class
		// implementation. All aspects of gumball display are handled by 
		// GumballDisplayConduit
		//base.OnDynamicDraw(e);
	}

	CRhinoGet::result MoveGumball()
	{
		return this->GetPoint(nullptr, true);
	}
};


CRhinoCommand::result SampleCommand::RunCommand( const CRhinoCommandContext& context )
{
	CRhinoGetPoint gp;
	gp.SetCommandPrompt(L"Base of cylinder");
	gp.GetPoint();
	if (gp.CommandResult() != success)
		return gp.CommandResult();

	gRadius = 1.0;
	gHeight = 2.0;

	ON_3dPoint center = gp.Point();
	gPlane = ON_Plane::World_xy;
	CRhinoView* view = gp.View();
	if (nullptr != view)
		gPlane = view->ActiveViewport().ConstructionPlane().m_plane;
	gPlane.SetOrigin(center);

	CRhinoGumball height_go;

	CRhinoGumballDisplayConduit height_dc;

	while (true)
	{
		height_go.SetFromPlane(gPlane);
		height_dc.SetBaseGumball(height_go);
		height_dc.Enable();
		height_dc.EnableGumballDraw(true);

		SampleCsGumballCylinderGetPoint gx(&height_dc);
		gx.SetCommandPrompt(L"Drag gumball. Press Enter when done");
		gx.AcceptNothing(true);
		gx.MoveGumball();

		//radius_dc.Disable();
		height_dc.Disable();

		if (gx.CommandResult() != success)
			break;
		
		CRhinoGet::result res = gx.Result();
		if (res == CRhinoGet::point)
		{
			continue;
		}

		if (res == CRhinoGet::nothing)
		{

		}

		break;
	}

	RhinoApp().ActiveDoc()->Redraw(CRhinoView::regenerate_display_hint);

	return success;
}

Hi @dsw,

Sorry this took so long. Here is (basically) a port of the C# version.

https://github.com/mcneel/rhino-developer-samples/blob/6/cpp/SampleCommands/cmdSampleGumballCylinder.cpp

I sure wish this were easier…

– Dale

Hi @dale

i tried this code in my project, but unfortunately it does not work because in Rhino 5 i do not have SetClippingRegionTransformation.
And if i calculate the clipping region by the pickcontext itself with UpdateClippingPlanes(), the sample does not work. i can see the preview and the arrows, but i cannot pick and drag them.
Is there a workaround in Rhino 5?

I’ve added a V5-equivalent.

https://github.com/mcneel/rhino-developer-samples/blob/5/cpp/SampleCommands/cmdSampleGumballCylinder.cpp

– Daler

Hi @dale

thank you very much for your fast support. Everything works perfect! :ok_hand::ok_hand: