Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    Change Icon based on State in CommandData

    PYTHON Development
    0
    16
    1.8k
    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 26/09/2013 at 08:29, xxxxxxxx wrote:

      Technically yes, practically no / you shouldn't. Invoking BaseList2D.GetIcon() will return a reference 
      to the BaseBitmap used by c4d to draw the interface. Any modifications made here will also show 
      up in the gui, but we are actually meant to treat that bitmap as readonly, so handle with care 😉

      import c4d, random
      from c4d import bitmaps
        
      def main() :
          if isinstance(op, c4d.BaseList2D) :
              data = op.GetIcon()
              bmp = data['bmp']
              sx, sy = data['x'], data['y']
              w, h = data['w'], data['h']
              for px in xrange(sx, sx + w) :
                  for py in xrange(sy, sy + h) :
                      r = random.randint(0,255)
                      g = random.randint(0,255)
                      b = random.randint(0,255)
                      bmp.SetPixel(px,py,r,g,b)
              bitmaps.ShowBitmap(bmp)
          c4d.EventAdd()
          
      if __name__=='__main__':
          main()
      

      That code chunk will change the color information of the selected objects icon to some random 
      color noise. For anything useful you would have to write some alpha informations too.

      FYI: For a command plugin you would have to grab the BasePlugin instance of your plugin.

      happy rendering,
      ferdinand

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

        On 26/09/2013 at 23:56, xxxxxxxx wrote:

        thanks alot for that, but how do I get an instance of my plugin, searching the forums I found

        myPlugin = c4d.BaseList2D(c4d.plugins.BasePlugin(PLUGIN_ID))

        but this gives "this cannot be instantiated" error

        which is also mentioned in python documentation, so is this a dead end?

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

          On 27/09/2013 at 00:32, xxxxxxxx wrote:

          The BasePlugin can be found via c4d.plugins.FindPlugin(PLUGIN_ID)

          You can use c4d.gui.GetIcon() instead, too.

          -Niklas

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

            On 27/09/2013 at 01:39, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            myPlugin = c4d.BaseList2D(c4d.plugins.BasePlugin(PLUGIN_ID))

            I can not really believe that you have found that code fragment somewhere in the c4d python
            documentation, as it does not make any sense on a very basic level. There is only one constructor
            for BaseList2D and that does require you to pass an integer as an argument. You are trying to 
            pass a BasePlugin instance, which does not work because the BasePlugin class cannot be 
            instantiated, as the interpreter already did tell you and also is not the correct argument type for 
            the BaseList2D constructor.

            Also trying to instantiate your plugin does not really make sense in that case, as it is one of the
            plugin types (CommandData, MessageData etc.)  which cannot be instantiated, or more precisely 
            are only instantiated once after the start up by c4d. It is also quite important to understand the 
            difference of your plugin class derived from BaseData, a BasePlugin and an actual node  repre-
            senting a plugin object.

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

              On 27/09/2013 at 01:41, xxxxxxxx wrote:

              awesome, thanks for all the help!

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

                On 27/09/2013 at 01:55, xxxxxxxx wrote:

                Yeah thats not a direct copy, most of the code I simply copy from here and there.

                I don't have any deep understanding of the sdk, but I get along with trial and error, examples and forums 😃

                Thanks for that explanation.

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

                  On 27/09/2013 at 08:27, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  I am wondering if it's possible to change the icon of CommandData plugin based on a its state.

                  It's not possible to dynamically change the icon images for CommandData plugins in the menu.
                  That image is set during the registration process when C4D starts up. And cannot be changed dynamically.

                  The CommandData plugin does have a checkbox option for it which might look like an icon image. But it's not. It's done with a flag. And doesn't use the bitmap image where the icons are stored.
                  It's an internal thing hard coded by Maxon.

                  It would be very nice to be able swap our own icon images for the on/off state of these plugins. Instead of being stuck with that checkmark option. Lots of people want to do that.
                  But it's not possible until Maxon adds that ability to the API.

                  -ScottA

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

                    On 27/09/2013 at 10:17, xxxxxxxx wrote:

                    It is possible. You can easily change the icon of the Cube plugin with this script.
                    >
                    >
                    >
                    >
                    > import c4d
                    >
                    > def set_icon(pluginid, bmp, overwrite_alpha=True) :
                    > icon = c4d.gui.GetIcon(pluginid)
                    > if not icon:
                    > return c4d.gui.RegisterIcon(pluginid, bmp)
                    >
                    > ref = icon['bmp']
                    > w, h = icon['w'], icon['h']
                    >
                    > temp = c4d.bitmaps.BaseBitmap()
                    > if temp.Init(w, h, bmp.GetBt()) != c4d.IMAGERESULT_OK:
                    > return False
                    >
                    > bmp.ScaleIt(temp, 256, True, True)
                    >
                    > a1 = a2 = None
                    > if overwrite_alpha:
                    > a1 = ref.GetInternalChannel()
                    > a2 = temp.GetInternalChannel()
                    > for x in xrange(w) :
                    > rx = x + icon['x']
                    > for y in xrange(h) :
                    > ry = y + icon['y']
                    > ref[rx, ry] = temp[x, y]
                    > if a1:
                    > if a2:
                    > alpha = temp.GetAlphaPixel(a2, x, y)
                    > else:
                    > alpha = 255
                    > ref.SetAlphaPixel(a1, rx, ry, alpha)
                    >
                    > return True
                    >
                    > def main() :
                    > fn = c4d.storage.LoadDialog()
                    > if not fn: return
                    >
                    > bmp = c4d.bitmaps.BaseBitmap()
                    > res = bmp.InitWith(fn)[0]
                    > if res != c4d.IMAGERESULT_OK:
                    > print "Invalid image:", res
                    > return
                    >
                    > set_icon(c4d.Ocube, bmp)
                    > c4d.gui.GeUpdateUI()
                    > c4d.EventAdd()
                    >
                    > main()

                    It is not possible to change the icon of an individual node, but that is also not a necessity when
                    working with a CommandData plugin.

                    Best,
                    -Niklas

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

                      On 27/09/2013 at 10:21, xxxxxxxx wrote:

                      Well actually it is Scott, my example above shows how to ;). But it is kind of black magic, as we
                      are meant to treat the BaseBitmap as readonly.

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

                        On 27/09/2013 at 10:46, xxxxxxxx wrote:

                        I think we're talking about different things.
                        Your code shows how to edit the read only bitmap file found in: resource\icons\interface_icons.tif
                        But a CommandData plugin does not use this file.

                        The CommandData plugin uses a flag in the GetState() method to toggle a check mark on/off

                            if(menustate) return CMD_ENABLED|CMD_VALUE;  //Enable the menu checkmark  
                          else return CMD_ENABLED;                     //Turn off the menu checkmark
                        

                        AFAIK. It's not possible toggle between two images instead of this checkmark.
                        There's nothing in the SDK that allows us to do this.
                        Many people have tried. No one has succeeded.

                        -ScottA

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

                          On 27/09/2013 at 11:48, xxxxxxxx wrote:

                          Not sure what you mean, for me it is just working fine. It actually does not matter if the
                          bitmap is located in the main icon file or somewhere else. Took a command data plugin
                          of mine and did a quick test.

                          import c4d, random
                          from c4d import bitmaps, gui
                            
                          CMD_DATA_ID = 1030901
                            
                          def main() :
                              data = gui.GetIcon(CMD_DATA_ID)
                              bmp = data['bmp']
                              sx, sy = data['x'], data['y']
                              w, h = data['w'], data['h']
                              for px in xrange(sx, sx + w) :
                                  for py in xrange(sy, sy + h) :
                                      bmp.SetPixel(px,py,255,0,0)
                              gui.GeUpdateUI()
                              c4d.EventAdd()
                              
                          if __name__=='__main__':
                              main()
                          

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

                            On 27/09/2013 at 12:11, xxxxxxxx wrote:

                            Scott, the GetState() method has nothing to do with the icon of the command. As littledevil
                            already pointed out, it doesn't matter whether you modify an icon which originates from
                            Cinema's own icon-table bitmap. You are only modifying the copy in the RAM, not the one
                            on the HD.

                            Download the full plugin
                             
                            >
                            > _<_t_>_
                            >
                            >
                            > 1
                            > 2
                            > 3
                            > 4
                            > 5
                            > 6
                            > 7
                            > 8
                            > 9
                            > 10
                            > 11
                            > 12
                            > 13
                            > 14
                            > 15
                            > 16
                            > 17
                            > 18
                            > 19
                            > 20
                            > 21
                            > 22
                            > 23
                            > 24
                            > 25
                            > 26
                            > 27
                            > 28
                            > 29
                            > 30
                            > 31
                            > 32
                            > 33
                            > 34
                            > 35
                            > 36
                            > 37
                            > 38
                            > 39
                            > 40
                            > 41
                            > 42
                            > 43
                            > 44
                            > 45
                            > 46
                            > 47
                            > 48
                            > 49
                            > 50
                            > 51
                            > 52
                            > 53
                            > 54
                            > 55
                            > 56
                            > 57
                            > 58
                            > 59
                            > 60
                            > 61
                            > 62
                            > 63
                            > 64
                            > 65
                            > 66
                            > 67
                            > 68
                            > 69
                            > 70
                            > 71
                            > 72
                            > 73
                            >
                            > |
                            >
                            >
                            > import os
                            > import c4d
                            >
                            > def get_res_bitmap(filename) :
                            > bmp = c4d.bitmaps.BaseBitmap()
                            > result = bmp.InitWith(os.path.join(os.path.dirname(__file__), 'res', filename))
                            > if not result or result[0] != c4d.IMAGERESULT_OK:
                            > return None
                            >
                            > return bmp
                            >
                            > def set_icon(pluginid, bmp, overwrite_alpha=True) :
                            > icon = c4d.gui.GetIcon(pluginid)
                            > if not icon and bmp:
                            > return c4d.gui.RegisterIcon(pluginid, bmp)
                            > elif icon and not bmp:
                            > return c4d.gui.UnregisterIcon(pluginid, bmp)
                            > elif not icon:
                            > return
                            >
                            > ref = icon['bmp']
                            > w, h = icon['w'], icon['h']
                            >
                            > temp = c4d.bitmaps.BaseBitmap()
                            > if temp.Init(w, h, bmp.GetBt()) != c4d.IMAGERESULT_OK:
                            > return False
                            >
                            > bmp.ScaleIt(temp, 256, True, True)
                            >
                            > a1 = a2 = None
                            > if overwrite_alpha:
                            > a1 = ref.GetInternalChannel()
                            > a2 = temp.GetInternalChannel()
                            > for x in xrange(w) :
                            > rx = x + icon['x']
                            > for y in xrange(h) :
                            > ry = y + icon['y']
                            > ref[rx, ry] = temp[x, y]
                            > if a1:
                            > if a2:
                            > alpha = temp.GetAlphaPixel(a2, x, y)
                            > else:
                            > alpha = 255
                            > ref.SetAlphaPixel(a1, rx, ry, alpha)
                            >
                            > return True
                            >
                            > class MyCommand(c4d.plugins.CommandData) :
                            >
                            > pluginid = 1000010 # TEST ID ONLY
                            > state = False
                            > bmp_a = get_res_bitmap('state-a.png')
                            > bmp_b = get_res_bitmap('state-b.png')
                            >
                            > def Register(self) :
                            > c4d.plugins.RegisterCommandPlugin(self.pluginid, "Icon Toggler", 0,
                            > None, "Execute to switch the icon of the command.", self)
                            > self.UpdateIcon()
                            >
                            > def UpdateIcon(self) :
                            > if not self.state:
                            > bmp = self.bmp_a
                            > else:
                            > bmp = self.bmp_b
                            > set_icon(self.pluginid, bmp)
                            >
                            > def Execute(self, doc) :
                            > self.state = not self.state
                            > self.UpdateIcon()
                            > return True
                            >
                            > if __name__ == "__main__":
                            > MyCommand().Register()
                            >
                            > <_<_t_>_

                            Best,
                            -Niklas

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

                              On 27/09/2013 at 13:01, xxxxxxxx wrote:

                              Thanks for the code Nik.

                              It doesn't solve the problem I was talking about.
                              But storing the icon in RAM is an interesting way to get around the problem.

                              -ScottA

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

                                On 27/09/2013 at 13:08, xxxxxxxx wrote:

                                Originally posted by xxxxxxxx

                                Thanks for the code Nik.

                                It doesn't solve the problem I was talking about.
                                But storing the icon in RAM is an interesting way to get around the problem.

                                -ScottA

                                I am not sure what problem you are talking about, could you pinpoint it for me please?

                                Best,
                                -Niklas

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

                                  On 27/09/2013 at 14:44, xxxxxxxx wrote:

                                  Well. It was a long time ago. And now I'm wondering if I'm remembering something else we were trying to do and having problems.
                                  I can't remember if we couldn't update the CommandData icons in the menu. Or if it was the icons for a plugin that were docked in the UI. Or something like that.
                                  The original poster commented about reading this problem on CGTalk. I'm guessing he was probably reading our old posts.

                                  We were trying to swap images that were stored on the HD using COFFEE. But could not figure it out.
                                  It was a long time ago.

                                  -ScottA

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