User Area Dial?



  • On 24/12/2015 at 16:10, xxxxxxxx wrote:

    The image I'm using is a pre-existing image.

    In Qt. A label (A simple widget) is commonly used to display an image. But a Qt label cannot be rotated. So the only way to rotate it is by rotating the image's pixels.
    But if you rotate the image like that. Then it warps as it rotates. Or you get a white background when the image is being rotated.
    So the only way to do it is by drawing the shape by hand using the Qt painter class. Or using the QGraphicsObject that is placed on a scene view.

    The QGraphicsObject and the scene view are basically equivalent to the User Area is in C4D.
    So I think if I try to rotate the image by it's pixels(the links you posted). Then I might run into those same problems.
    So I would prefer to rotate the object itself. Rather than the image's pixels. If possible.
    But since nothing is object based in the C4D UA. I'm having trouble figuring out how to attack this.

    Suppose you wanted to draw two or three dials in the UA?
    How would you know which one's were which?
    How would you target a specific one to for example: Get it's rotation value?

    -ScottA



  • On 24/12/2015 at 20:29, xxxxxxxx wrote:

    One way to minimize the effects of rotating the bitmap would be two fold:

    1. Make the bitmap square and large enough so that the 'important part' never intersects an edge (easy enough).  Also, if you can use transparency, you mitigate the issue of background altogether - though this might be more difficult in the rotation process (??).

    2. If you know the circular region of interest (the 'important part'), then you can restrict the pixels being rotated to a specific 'circular' region.  This should not only minimize 1. but also increase performance.

    When I made a node-based system in a User Area (UA), each node instance maintained a location (UL) and size parameter relative to a virtual plane.  The derived UA class maintained the offset and extents of this virtual plane with respect to the UL of the UA 'view'.  This allowed 'scrolling' of the UA virtually as a window into the virtual space.

    With that in mind, if you are handling mouse clicks over the dials, you can use InputEvent() and check the dial location/size against the cursor location.  In my case, it was a simple bounding-box check.  For something like a rotated dial, for precision, you may need to refine the bounding check, say, using the angle to determine the diagonal of the box (of the two possible) and see how many pixels away from the pixels intercepted by that diagonal the cursor is.

    ETA: Note that you would have four special cases involving the dial at 0/90/180/270 since the bounding-box would be more of a bounding line.

    ETAM: Scratch the bounding-box checks.  If you know the center of the rotation and the radius of the dial, you can easily determine where the cursor is with respect to the dial by calculating the angle and radius of the cursor point relative to the rotation center.  While this requires sin/cos, you could simply use a sin/cos table to avoid the function calculations.



  • On 25/12/2015 at 09:39, xxxxxxxx wrote:

    Merry Christmas Robert.🙂

    I think I have everything I need ( the maths)  to do the actual rotations.
    But the UA itself is where I'm stuck. I don't use it very often so I'm not as familiar with it as other things.
    I guess what I really need is an example of how to make a custom object for hosting images. That also has transforms on it that will let me move and rotate it's matrix.

    The SDK says that we can create our own objects for it. But it doesn't provide any help with how to actually do that.
    Now I have to try to figure out how to write one completely from scratch.
    And that's starting to look fairly complicated without some sort of pre-existing code example to use as a guide.

    -ScottA



  • On 25/12/2015 at 11:11, xxxxxxxx wrote:

    I've built a little Command plugin with a Dialog + UserArea that has a basic dial.  You can rotate the dial by holding the left-mouse button over the 'needle' and dragging.  The download includes a Windows plugin (R16+) and the source code in C++.

    http://www.kuroyumeszone.com/referenced/TestCommand.zip

    Enjoy!  Happy Holidays!! 😉



  • On 25/12/2015 at 11:30, xxxxxxxx wrote:

    With respect to a custom object for hosting images, maybe you can simply create a wrapper class that includes the bitmap as a member.  Use the wrapper class as a means to get to the bitmap but also to do whatever image transforms on it.  You could go further and create a CustomGUIData but that is rather complicated unless you plan on using it a lot (and you feel that it is worth the effort).



  • On 25/12/2015 at 11:40, xxxxxxxx wrote:

    Thanks for the code.
    I kinda wanted to avoid that method though if possible. I really wanted more of an object based gizmo.
    I guess working in Qt has spoiled me.

    The wrapper class you're talking about is what I'm currently trying to do. But I'm having a hard time with it. I've never written an object the for UA. Thus...lots of questions.
    If I have to write my own object from scratch. I'm guessing that I'd also need to write my own matrix code too?

    This might be too advanced for me.

    -ScottA



  • On 25/12/2015 at 12:25, xxxxxxxx wrote:

    C4D's API is wanting in many areas.  If you looked at my code, you see that I had to draw the circle for the dial myself using the Symmetric Midpoint algorithm.  Worse is that since there is no DrawPoint() or DrawPixel() method for the GeUserArea, I had to use DrawLine() and double the coordinates.  Hackish at best.

    Speaking of hackish, maybe a possible solution is in bit-blitting sub-images?  You could make an image containing a block for each dial position (360 little composite does suck).  Then you simply index into the image to get the block that represents the dial angle.  Trade time doing rotation transforms with memory to store the bitmap image.  Just a thought.



  • On 25/12/2015 at 12:51, xxxxxxxx wrote:

    Yeah. I noticed there's not even a circle or ellipse function for it. It's really awful.
    But since this thing was written back in the 90's. I sort of give it a break. It was probably state of the art back in it's day.
    I wish Maxon would just bite the bullet and partner with Qt like Autodesk did. And allow Qt handle all of it's gui stuff. But that's probably never going to happen.

    Perhaps someone from Maxon support could tell me if it's even possible to create an object with transforms for the UA?
    The docs say that we can use the UA to host our own objects. But nothing on how to actually do it.

    -ScottA



  • On 29/12/2015 at 08:13, xxxxxxxx wrote:

    Hi,

    To draw to bitmaps you can use the BaseBitmap class low-level drawing functions (SetPixel(), SetAlphaPixel()).
    Also don't forget GeClipMap class exists to draw even more stuff.
    Then draw the bitmap using GeUserArea::DrawBitmap() with the appropriate mode.

    Originally posted by xxxxxxxx

    Perhaps someone from Maxon support could tell me if it's even possible to create an object with transforms for the UA?
    The docs say that we can use the UA to host our own objects. But nothing on how to actually do it.

    If you want to draw a bitmap with special transform that's something completely up to your implementation.
    The GeUserArea only draws pixels and doesn't know what's really drawn. It doesn't keep any information on the drawn lines, bitmaps, text, etc.
    To draw a bitmap with different transforms implement a struct or class to hold the bitmap and the special setup for its transform (just like Robert already told you).
    Then use this information to draw the transformed bitmap (by your own algorithm, the API doesn't provide this).



  • On 29/12/2015 at 08:34, xxxxxxxx wrote:

    Thanks....but...how?

    If I wanted to create my own UA object with it's own transforms. The first thing I need to know is what base class do I extend?
    And If I create my own object. And then add instances of it to the UA. Can I get at all of those instances by iterating through the UA class somehow?
    Or do I need to create my own container to hosts all of the instances?

    I need more information than "Create a class".

    -ScottA



  • On 29/12/2015 at 09:56, xxxxxxxx wrote:

    I don't know where you got the idea of a UA 'object'.  The UserArea is simply a UI region into which you can draw and respond to user input.  The objects, if we can say that, are simply your own class instances reacting within the UA.  For instance, my one excursion used a UserArea as a realm for nodes (much like Xpresso's system).  Each node was an instance of my node class containing its parameters and information on the location, size, states of the node for display in the UA as well the connections between them.  All of the display code was part of the methods in the node class called from the UA as it iterated through the node list.  When the user clicked over, say, the head of the node, I would find out if the click was over a node, where in the node, and react appropriately.  Over the head, move the node.  Over a input-output connection, either start a connection line or disconnect if one existed already, etc.

    Summarily, all of the 'interface' in the UserArea is just about the same as it would need to be if you were designing your own window system over a basic shell.



  • On 29/12/2015 at 12:02, xxxxxxxx wrote:

    I guess it's not possible to create a UA object the way I'm thinking.

    Sure. We can make our own classes.
    But ultimately these class objects must get drawn onto the UA using one of the SDK draw functions.
    Those draw functions are what create the "object" that I want to make myself. But it doesn't seem possible.

    -ScottA



  • On 30/12/2015 at 08:41, xxxxxxxx wrote:

    Wow. I'm really stunned at how hard this is to do.
    I never would have thought that something as simple as rotating a gizmo would be so difficult.

    It turns out that rotating an image is very difficult to do. And it requires some advanced sampling of the nearest pixels. Which require special libraries.
    So I thought that I'd try to rotate the gizmo by moving it's four corners in an arc like manner instead. Like rotating a polygon.
    But the DrawBitmap() function does not provide the four corners of the gizmo that can be moved. It provides only one corner. And then the width&height.

    From the docs:
    The region ( x , y ) to ( x + w , y +h) from the bitmap will be scaled and transformed into the region ( wx , wy ) to ( wx + ww , wy + wh ) of the destination area.

    This makes it very, very hard to understand what's going on.
    Is there a way to get and change the four corner positions for this thing so I can move them in an arc like fashion to rotate it?

    P.S.
    I have studied your line rotate code Robert. But I'm not seeing how I can use that to rotate an image. If it's there I'm just not seeing it.

    -ScottA



  • On 31/12/2015 at 12:16, xxxxxxxx wrote:

    I think that 'scaled and transformed' means that it will be scaled (width and height) to fit the destination and transformed simply means moved from x,y to wx,wy.  That is it.

    My code was not intended to show how to rotate an image but as a procedural means to draw and handle a rotating object (line) as an interface.  As you noted, arbitrarily rotating a bitmap requires some hefty algorithmic manipulation.  Photoshop (CS4 here) has a very responsive image rotation: Select All, then Move tool, then simply get the cursor to the rotation cursor and interactively drag rotate.

    If I find some reasonable code that would rotate a bitmap image quickly, I will post back here.



  • On 31/12/2015 at 13:04, xxxxxxxx wrote:

    Thanks for trying Robert.
    I don't think I'm going to get anywhere with this. It doesn't seem to be possible.

    -ScottA



  • On 06/01/2016 at 20:18, xxxxxxxx wrote:

    Just an update to let you know that I figured out a way to do it using the OpenCV library.
    It works slicker than gorilla snot.😉
    I would have preferred to do this with the SDK. But it just isn't possible.

    https://www.youtube.com/watch?v=_qXpQRhqvE4

    -ScottA



  • On 06/01/2016 at 20:32, xxxxxxxx wrote:

    Glad to hear that you found a pre-existing solution.  I truly did not find anything past the shear-technique (which is already a bit archaic temporally) as a means of arbitrarily rotating bitmaps. We can land a human on the moon but Bresenham takes decades to surpass.  Thus is technological advance.  Good ventures!


Log in to reply