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

    Frame Selected Object

    PYTHON Development
    0
    9
    1.4k
    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 09/05/2014 at 15:06, xxxxxxxx wrote:

      I'm trying to render the active object isolated from all other objects of the document.
      To do so, from inside my plugin, I created a new document, created a clone of the intended object and inserted it in the new document. Then I performed a render of that object and finally, get rid of that document.
      It all works fine, except that I can't seem to perform a "Frame Selected Object" on the object that is inside the new document. When I run that command, the current object, still in my current object gets framed.
      I'm using this code:

      doc = documents.GetActiveDocument()
      new_doc=c4d.documents.BaseDocument()
      rd = new_doc.GetActiveRenderData().GetData()
      new_tree=node.GetClone()
      new_doc.InsertObject(new_tree)
      xres = 128
      yres = 128
      bmp = bitmaps.BaseBitmap()
      bmp.Init(x=xres, y=yres, depth=24)
      rd[c4d.RDATA_XRES]=xres
      rd[c4d.RDATA_YRES]=yres
      new_doc.SetSelection(new_tree,c4d.SELECTION_NEW)
      c4d.CallCommand(12151) # Frame Selected Objects
      res = documents.RenderDocument(new_doc, rd, bmp, c4d.RENDERFLAGS_EXTERNAL)
      if res==c4d.RENDERRESULT_OK:
          bitmaps.ShowBitmap(bmp)
      new_doc.Flush()

      How can I frame just the cloned object, inside the new document?

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

        On 10/05/2014 at 00:05, xxxxxxxx wrote:

        How do you think the CallCommand would know that it should use your
        new document? It operates always on the active scene only.

        -Niklas

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

          On 10/05/2014 at 01:11, xxxxxxxx wrote:

          I thought it would operate like how you say, but I tried the "shot in the dark" of selecting the newly inserted object and hopped that it would affect the last selected object 😉
          So, it must be made by hand, adjusting the virtual camera of the new document?
          Does anyone now how to calculate the placement and orientation of the camera to frame an object?

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

            On 10/05/2014 at 03:15, xxxxxxxx wrote:

            You didn't make the new_doc the current document. 😉
            Insert it and make it the active document.

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

              On 10/05/2014 at 03:54, xxxxxxxx wrote:

              Thank you, Niklas. It worked!!!
              However, the object is not being framed correctly.
              My code is this:

              doc = documents.GetActiveDocument()
              new_doc=c4d.documents.BaseDocument()
              rd = new_doc.GetActiveRenderData()
              rdc = rd.GetData()
              new_tree=node.GetClone()
              new_doc.InsertObject(new_tree)
              xres = 256
              yres = 256
              bmp = bitmaps.BaseBitmap()
              bmp.Init(x=xres, y=yres, depth=24)
              rdc[c4d.RDATA_XRES]=xres
              rdc[c4d.RDATA_YRES]=yres
              rd.SetData(rdc)
              c4d.documents.SetActiveDocument(new_doc)
              new_doc.SetActiveRenderData(rd)
              c4d.EventAdd(c4d.EVENT_FORCEREDRAW)
              new_doc.SetSelection(new_tree,c4d.SELECTION_NEW)
              c4d.CallCommand(12151) # Frame Selected Objects
              res = documents.RenderDocument(new_doc, rdc, bmp, c4d.RENDERFLAGS_EXTERNAL)
              c4d.documents.SetActiveDocument(doc)
              if res==c4d.RENDERRESULT_OK:
                  bitmaps.ShowBitmap(bmp)
              new_doc.Flush()

              The render shows a clipped object 😞

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

                On 10/05/2014 at 05:33, xxxxxxxx wrote:

                Already tried with:

                c4d.CallCommand(12148) # Frame Geometry

                and with

                c4d.CallCommand(12288) # Frame All

                To no avail 😞

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

                  On 10/05/2014 at 11:29, xxxxxxxx wrote:

                  Ok, never mind. I created my own framing code. It works for what I need.

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

                    On 11/05/2014 at 04:26, xxxxxxxx wrote:

                    Hi Rui,

                    # Copyright (c) 2014  Niklas Rosenstein
                    #
                    # Permission is hereby granted, free of charge, to any person obtaining a copy
                    # of this software and associated documentation files (the "Software"), to deal
                    # in the Software without restriction, including without limitation the rights
                    # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                    # copies of the Software, and to permit persons to whom the Software is
                    # furnished to do so, subject to the following conditions:
                    #
                    # The above copyright notice and this permission notice shall be included in
                    # all copies or substantial portions of the Software.
                    #
                    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                    # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                    # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                    # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                    # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                    # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                    # THE SOFTWARE.
                    r"""
                    This script shows how to frame the current object and then render
                    it into a 256x256 image without loosing information such as the
                    object's materials. Absolutely non-destructive and memory-optimized.
                    
                    Changelog:
                    v 0.1.0 (May 11, 2014)
                        Initial version
                    """
                    
                    import c4d
                    
                    class Remember(object) :
                        r""" Remembers the hierarchy position of a node and can restore
                        it at a later time. A ``root_routine`` is required when the node
                        was the first and only node in the list. """
                    
                        def \__init\_\_(self, node) :
                            super(Remember, self).\__init\_\_()
                            self.parent = node.GetUp()
                            self.pred = node.GetPred()
                    
                        def restore(self, node, root_routine) :
                            node.Remove()
                            if self.pred:
                                node.InsertAfter(self.pred)
                            elif self.parent:
                                node.InsertUnder(self.parent)
                            else:
                                root_routine(node)
                    
                    class DocumentContext(object) :
                        r""" Context manager for a temporary document that will be inserted
                        when entering the context and \*killed\* when leaving the context. The
                        document can and must not be used after the context was left.
                    
                        Inside the context, the document is inserted and active. """
                    
                        def \__init\_\_(self, doc=None) :
                            if not doc:
                                doc = c4d.documents.BaseDocument()
                            elif not isinstance(doc, c4d.documents.BaseDocument) :
                                raise TypeError('expected BaseDocument')
                    
                            super(DocumentContext, self).\__init\_\_()
                            self.doc = doc
                    
                        def \__enter\_\_(self) :
                            c4d.documents.InsertBaseDocument(self.doc)
                            c4d.documents.SetActiveDocument(self.doc)
                            return self.doc
                    
                        def \__exit\_\_(self, exc_type, exc_value, exc_tb) :
                            c4d.documents.KillDocument(self.doc)
                    
                    def render_object(op, width, height) :
                        r""" Renders the object \*op\* with the specified resolution. Returns
                        the resulting :class:`c4d.bitmaps.BaseBitmap`. It tries to keep the
                        memory overhead at a minimum by stripping down op's document before
                        cloning it. """
                    
                        doc = op.GetDocument()
                        if not doc:
                            raise ValueError('op is not in a document')
                    
                        # Remember the original position of \*op\* in the hierarchy and
                        # remove it from the tree.
                        location = Remember(op)
                        op.Remove()
                    
                        # Put all the objects in the document into a Null-Object that
                        # we will keep separate.
                        root_null = c4d.BaseObject(c4d.Onull)
                        for obj in reversed(doc.GetObjects()) :
                            obj.Remove()
                            obj.InsertUnder(root_null)
                    
                        # Insert it into the document again. Then we clone it to get a 
                        # document with all the materials that the object referenced.
                        doc.InsertObject(op)
                        new_doc = doc.GetClone(c4d.COPYFLAGS_0)
                    
                        # Restore the structure of the original document.
                        for obj in reversed(root_null.GetChildren()) :
                            obj.Remove()
                            doc.InsertObject(obj)
                        root_null.Remove()
                        location.restore(op, root_routine=doc.InsertObject)
                    
                        # Frame the object and render the new document.
                        with DocumentContext(new_doc) :
                            new_doc.SetActiveObject(new_doc.GetFirstObject())
                            force_redraw() # Redraw is required to create the Geometry
                            c4d.CallCommand(12151) # Frame Selected Objects
                            return render_document(new_doc, width, height)
                    
                    def render_document(doc, width, height, depth=24) :
                        r""" Renders \*doc\* with the specified width and height. """
                    
                        bmp = c4d.bitmaps.BaseBitmap()
                        bmp.Init(x=width, y=width, depth=depth)
                        
                        rdc = doc.GetActiveRenderData().GetData()
                        rdc[c4d.RDATA_XRES] = width
                        rdc[c4d.RDATA_YRES] = height
                        
                        c4d.documents.RenderDocument(doc, rdc, bmp, c4d.RENDERFLAGS_EXTERNAL)
                        return bmp
                    
                    def force_redraw() :
                        r""" Force a redraw for the current document. """
                    
                        flags = c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_FORCEFULLREDRAW
                        c4d.DrawViews(flags) 
                    
                    def main() :
                        if not op:
                            c4d.gui.MessageDialog("Please select one object.")
                            return
                    
                        bmp = render_object(op, 256, 256)
                        c4d.bitmaps.ShowBitmap(bmp)
                    
                    main()
                    

                    This should help you.
                    -Niklas

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

                      On 11/05/2014 at 06:49, xxxxxxxx wrote:

                      Thank you Niklas. I learned a lot with this code.

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