Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    User Area Dial?

    SDK Help
    0
    21
    12.6k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 24/12/2015 at 11:03, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R13 
      Platform:   Windows  ;   
      Language(s) :     C++  ;   PYTHON  ;

      ---------
      Hi,

      Does anyone have any code that creates a dial that can be rotated in the User Area?
      I'm currently using DrawBitmap() to draw the dial. But I don't see any way to rotate the rectangle shape that DrawBitmap() generates.

      Do we need to create a custom object from scratch to do this? Or is there a way to use the existing draw functions?

      C++ or Python code is fine. I can use either one.
      T.I.A.

      -ScottA

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 24/12/2015 at 13:52, xxxxxxxx wrote:

        Instead of rotating the bitmap couldn't you rotate what you draw into it using the angle of the dial?  This is how I have done it with such controls (such as a Java version of the Twister spin-dial).

        Otherwise, might need to see your code for drawing the dial into the bitmap (etc.).

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 24/12/2015 at 14:58, xxxxxxxx wrote:

          Hi Robert,

          Yes. I'd prefer to rotate the container object that is is holding the bitmap.
          The only experience I have with this kind of thing is in Qt.
          In Qt I can use a QGraphicsObject that has transforms available to rotate it.

          The code I'm using that draws a UA bitmap in C4D is something like this:
          DrawBitmap(bmp, 100, 50, w, h, 0, 0, w, h, BMP_NORMAL | BMP_ALLOWALPHA)

          But since DrawBitmap() is not an object. And it has no transforms built into it. I'm trying to figure out how to do this kind of thing in the C4D User Area.
          Since DrawBitmap() is not an object. I can't even figure out how to even grab(target) it.

          That's why I'm thinking that maybe I should create my own custom object somehow?
          Or maybe I'm over thinking it?

          -ScottA

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 24/12/2015 at 15:39, xxxxxxxx wrote:

            Is the bitmap a pre-existing image you are loading or something drawn into (with graphics primitives, for instance) and then drawn into the User Area?

            For the former, there doesn't appear to be any built in function to rotate a bitmap in the C4D API.  Here are a couple of links to code to do it (there is BitBlt() for bitmaps in the API!) :

            http://www.leunen.com/cbuilder/rotbmp.html

            http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/Rotate-a-bitmap-image.htm

            You can Google for more references.

            In the latter case, I can dig up my code to show how a clock-like dial is drawn arbitrarily rotated.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              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

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                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.

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  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

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    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!! 😉

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      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).

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        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

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          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.

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            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

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              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).

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                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

                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  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.

                                  1 Reply Last reply Reply Quote 0
                                  • H
                                    Helper
                                    last edited by

                                    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

                                    1 Reply Last reply Reply Quote 0
                                    • H
                                      Helper
                                      last edited by

                                      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

                                      1 Reply Last reply Reply Quote 0
                                      • H
                                        Helper
                                        last edited by

                                        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.

                                        1 Reply Last reply Reply Quote 0
                                        • H
                                          Helper
                                          last edited by

                                          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

                                          1 Reply Last reply Reply Quote 0
                                          • H
                                            Helper
                                            last edited by

                                            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.

                                            -ScottA

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post