Methods for drawing circular handles and selection cues
Hello everyone!
I am looking for the methods that draw little circular handles and selection cues respectively. Does anyone know these?
I am making extensive use of SVG group nodes. I would like to be able to check where the center of an object is, in order to know if I previously changed the group matrix or the content's matrices. I found no way to easily check this in Inkscape.
It is especially difficult to notice if a path object is changed or moved. I found that the default behaviour for dragging a path is that the path data gets altered, instead of applying a translation matrix. I plan to use the graphics as animation assets, so the difference matters to me.
What I would like to do now is to make code modifications to draw a little circle at the center of a selected object, so I can clearly see when the contents or the path are off center.
Can someone maybe help me and point me to the relevant classes and methods? I searched the source code and the mailing list archives, but without luck so far. I need:
1. The method that draws those little white circles, e.g. at the end of Bezier handles.
2. The method that draws a bounding box and the selection cue whenever an object gets selected, so that I can apply the circle.
Many thanks in advance!
Gerrit _________________________________________________________________ Explore the seven wonders of the world http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=...
On 10/16/07, Gerrit . <g99k@...19...> wrote:
Hello everyone!
I am looking for the methods that draw little circular handles and selection cues respectively. Does anyone know these?
Currently no code for this exists, but I was just planning to add a new canvasitem for circles (I will use it for Tweak tool cursor). Once it's in you will also be able to use it. But small fixed-sized circles are already possible and used e.g. for bezier handles in Node tool.
I am making extensive use of SVG group nodes. I would like to be able to check where the center of an object is, in order to know if I previously changed the group matrix or the content's matrices. I found no way to easily check this in Inkscape.
"Center of the object" is ambiguous. If you want just the center of the bbox, click the selection a second time and it will display a handle in the rotation center, which by default is in the center of the bbox.
It is especially difficult to notice if a path object is changed or moved. I found that the default behaviour for dragging a path is that the path data gets altered, instead of applying a translation matrix. I plan to use the graphics as animation assets, so the difference matters to me.
Just switch the preference setting "Store transformation:" to "preserved".
What I would like to do now is to make code modifications to draw a little circle at the center of a selected object, so I can clearly see when the contents or the path are off center.
The rotation center handle is a cross. I don't like that actually because it makes it hard to notice and drag it. Suggestions are welcome.
Thanks a lot for the quick answer!
Just switch the preference setting "Store transformation:" to "preserved".
I missed out on that one, stupid me. Well, half my problem solved already. :-)
Currently no code for this exists, but I was just planning to add a new canvasitem for circles (I will use it for Tweak tool cursor). Once it's in you will also be able to use it. But small fixed-sized circles are already possible and used e.g. for bezier handles in Node tool.
Would these be SPKnot objects with shape set to SP_KNOT_SHAPE_CIRCLE? Just found that one with the keywords you gave me.
"Center of the object" is ambiguous. If you want just the center of the bbox, click the selection a second time and it will display a handle in the rotation center, which by default is in the center of the bbox.
Cool, I didn't notice this one either. Unfortunately, I don't mean the center of the bounding box, but the origin of the object's inner coordinate system, as if you placed a tiny circle at (0,0) inside the selected group node. Maybe I can change the code so that the crosshair is (optionally?) displayed at the object's origin instead of the bbox center?
The rotation center center handle is a cross. I don't like that actually because it makes it hard to notice and drag it. Suggestions are welcome.
I don't mind that shape, really. I think the Flash IDE uses a circle for the rotation handle and a crosshair to denote the selected object's PARENT'S origin, i.e. the origin of the object's outer coordinate system (usually the stage, if it's a top-level node).
_________________________________________________________________ Connect to the next generation of MSN Messenger http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&sour...
On 10/16/07, Gerrit . <g99k@...19...> wrote:
Currently no code for this exists, but I was just planning to add a new canvasitem for circles (I will use it for Tweak tool cursor). Once it's in you will also be able to use it. But small fixed-sized circles are already possible and used e.g. for bezier handles in Node tool.
Would these be SPKnot objects with shape set to SP_KNOT_SHAPE_CIRCLE? Just found that one with the keywords you gave me.
Yes.
"Center of the object" is ambiguous. If you want just the center of the bbox, click the selection a second time and it will display a handle in the rotation center, which by default is in the center of the bbox.
Cool, I didn't notice this one either. Unfortunately, I don't mean the center of the bounding box, but the origin of the object's inner coordinate system, as if you placed a tiny circle at (0,0) inside the selected group node. Maybe I can change the code so that the crosshair is (optionally?) displayed at the object's origin instead of the bbox center?
Yes, you can relatively easily modify seltrans to draw one more handle, indicating the coordinate origin. The code should not be too difficult to figure out. But I'm honestly not sure this feature needs to be in the Inkscape trunk even as an option - I don't see how it's useful. Can you provide a few use cases?
Yes, you can relatively easily modify seltrans to draw one more handle, indicating the coordinate origin. The code should not be too difficult to figure out.
I am sorry to bother you again with this, but I couldn't find the right method to retrieve the item's coordinate origin I was referring to. Maybe someone can point me to the right functions again?
What I want to achieve is that a small dot appears at the translation x and y coordinates of the selected item's global transform. So, if the item is newly created, it would be at (0,0) at the upper left corner. When you drag the item around, the point gets dragged too, but it doesn't change when you scale or rotate.
Here's what I did in seltrans.cpp, but it's probably all wrong, so if you know the solution, don't bother reading it:
_myhandle = sp_knot_new(_desktop, _("Translation point of the selected object")); ... SPItem *item = (SPItem*)sp_object_ref(SP_OBJECT(itemList->data), NULL); NR::Matrix globalTransform = item->getRelativeTransform(_desktop->currentRoot()); NR::Coord coords[6]; globalTransform.copyto( coords ); sp_knot_show(_myhandle); sp_knot_moveto(_myhandle, &NR::Point( coords[4], coords[5]) );
The first problem is that I didn't find a method to get a global transform, so I used SPItem::getRelativeTransform and passed _desktop->currentRoot().
Then, I'm not very good with C++ pointers. I couldn't find a way to access the numbers that make up the NR::Matrix. I tried to use NR::Matrix::copyTo to copy the values to a Coord array, but I still don't even know how to pass the Coord values to the NR::Point constructor or printf functions. When I printed the array out, it never changed, so apparently nothing gets copied at all the way I coded it.
But I'm honestly not sure this feature needs to be in the Inkscape trunk even as an option - I don't see how it's useful. Can you provide a few use cases?
I totally agree that this doesn't belong into the trunk. I am trying to create Flash assets with Inkscape and then arrange and animate them dynamically with ActionScript and statically with a tool I am writing right know. For this, I need to know where the actual origin of a shape is, not the center of the bounding box, because the other APIs apply their transformations that way. But since most people use Inkscape to create static graphics, I doubt anyone besides me needs this feature.
_________________________________________________________________ Invite your mail contacts to join your friends list with Windows Live Spaces. It's easy! http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.a...
On 10/24/07, Gerrit . <g99k@...19...> wrote:
I am sorry to bother you again with this, but I couldn't find the right method to retrieve the item's coordinate origin I was referring to. Maybe someone can point me to the right functions again?
I guess to get the origin, you just need to take NR::Point(0,0) and multiply it by that item's accumulated transform. To get the latter, use sp_item_i2doc_affine and convert it to desktop coords with matrix_to_desktop (that's offhand, not tested).
What I want to achieve is that a small dot appears at the translation x and y coordinates of the selected item's global transform. So, if the item is newly created, it would be at (0,0) at the upper left corner. When you drag the item around, the point gets dragged too, but it doesn't change when you scale or rotate.
That's impossible. When you scale or rotate, you change the matrix and thus the position of the origin too, unless you scale or rotate it around that origin. Looks like you need something else.
Then, I'm not very good with C++ pointers. I couldn't find a way to access the numbers that make up the NR::Matrix.
I think you need matrix.c[number], or look up in the transformation dialog, transform tab, how that code extracts the values.
I tried to use NR::Matrix::copyTo to copy the values to a Coord array, but I still don't even know how to pass the Coord values to the NR::Point constructor or printf functions.
It's just double. Read the .h files in libnr/ for details.
Many thanks for this reply! I actually got it done before I saw this last post, but yor suggestions are still a big improvement.
I think you need matrix.c[number], or look up in the transformation dialog, transform tab, how that code extracts the values.
Thanks for this valuable tip! _c in NR::Matrix is private, but it seems the class overrides the [] operator, so you can simply access the values with matrix[number]. Found that in ui/dialog/transformation.cpp.
That's impossible. When you scale or rotate, you change the matrix and thus the position of the origin too, unless you scale or rotate it around that origin. Looks like you need something else.
Misunderstanding again, sorry: I meant the combined transform. If you express a rotation that's not around the origin with a single matrix, then it becomes a rotation around the origin with a translation. So, yes, in that case the origin has to change position too.
I guess to get the origin, you just need to take NR::Point(0,0) and multiply it by that item's accumulated transform. To get the latter, use sp_item_i2doc_affine and convert it to desktop coords with matrix_to_desktop (that's offhand, not tested).
I am doing a manual conversion right now, but your suggestion would clearly be the cleaner solution.
Thank you very much for your continuous advice. The code works for me right now, so I'll probably close the file for the time being. I'll post the diff here in case anyone else should ever be interested in this. It's mainly copy and paste from the _chandle code.
Have a nice day! :-) Gerrit
diff for seltrans.cpp:
*** inkscape-0.45.1/src/seltrans.cpp 2007-01-16 03:46:08.000000000 +0100 --- myhandle_inkscape-0.45.1/src/seltrans.cpp 2007-10-31 13:58:32.000000000 +0100 *************** Inkscape::SelTrans::SelTrans(SPDesktop * *** 90,95 **** --- 90,96 ---- _show_handles(true), _box(NR::Point(0,0), NR::Point(0,0)), _chandle(NULL), + _myhandle(NULL), _stamp_cache(NULL), _message_context(desktop->messageStack()) { *************** Inkscape::SelTrans::~SelTrans() *** 171,176 **** --- 172,181 ---- g_object_unref(G_OBJECT(_chandle)); _chandle = NULL; } + if (_myhandle) { + g_object_unref(G_OBJECT(_myhandle)); + _myhandle = NULL; + }
if (_norm) { gtk_object_destroy(GTK_OBJECT(_norm)); *************** void Inkscape::SelTrans::_updateHandles( *** 471,476 **** --- 476,482 ---- sp_remove_handles(_shandle, 8); sp_remove_handles(_rhandle, 8); sp_remove_handles(&_chandle, 1); + sp_remove_handles(&_myhandle, 1); return; }
*************** void Inkscape::SelTrans::_updateHandles( *** 499,504 **** --- 505,540 ---- G_CALLBACK(sp_sel_trans_handle_click), (gpointer) &handle_center); }
+ // start _myhandle: display a new handle at the origin of the selected object + if ( _myhandle == NULL ) { + _myhandle = sp_knot_new(_desktop, _("Origin of the selection")); + _myhandle->setShape (SP_CTRL_SHAPE_CIRCLE); + _myhandle->setSize (10); + _myhandle->setAnchor (handle_center.anchor); + _myhandle->setMode (SP_CTRL_MODE_XOR); + _myhandle->setFill(0x00000000, 0x00000000, 0x00000000); + _myhandle->setStroke(0x000000ff, 0xff0000b0, 0xff0000b0); + _myhandle->setPixbuf(handles[handle_center.control]); + // We don't want to use the standard knot handler, + //since we don't want this knot to be draggable. + g_signal_handler_disconnect(G_OBJECT(_myhandle->item), _myhandle->_event_handler_id); + sp_knot_update_ctrl(_myhandle); + } + const GSList *itemList = _desktop->selection->itemList(); + // If only one item is selected, move the _myhandle knot + // to the translation values of its global transform. + if( g_slist_length( (GSList*) itemList ) == 1 ) { + SPItem *item = (SPItem*)sp_object_ref(SP_OBJECT(itemList->data), NULL); + NR::Matrix globalTransform = sp_item_i2root_affine( item ); + // Knot needs desktop coordinates (origin at LOWER left corner) + NR::Point point( globalTransform[4], -globalTransform[5]+sp_document_height(sp_desktop_document(_desktop)) ); + sp_knot_moveto(_myhandle, &point); + sp_knot_show(_myhandle); + } + else sp_knot_hide(_myhandle); + // end _myhandle + + sp_remove_handles(&_chandle, 1); if ( _state == STATE_SCALE ) { sp_remove_handles(_rhandle, 8);
diff for seltrans.h:
*** inkscape-0.45.1/src/seltrans.h 2007-01-16 03:46:08.000000000 +0100 --- myhandle_inkscape-0.45.1/src/seltrans.h 2007-10-25 18:27:38.000000000 +0200 *************** private: *** 128,133 **** --- 128,134 ---- SPKnot *_shandle[8]; SPKnot *_rhandle[8]; SPKnot *_chandle; + SPKnot *_myhandle; SPCanvasItem *_norm; SPCanvasItem *_grip; SPCanvasItem *_l[4];
_________________________________________________________________ Discover the new Windows Vista http://search.msn.com/results.aspx?q=windows+vista&mkt=en-US&form=QB...
participants (2)
-
bulia byak
-
Gerrit .