• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Extending SketchUp entities

Scheduled Pinned Locked Moved Developers' Forum
16 Posts 5 Posters 1.3k Views 5 Watching
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.
  • T Offline
    thomthom
    last edited by 6 Sept 2011, 14:24

    Is there a way to extend a Sketchup::Entity so only the reference you hold is extended?

    Example:
    ` sel = Sketchup.active_model.selection

    face = sel[0]
    face.extend( MyPrettyFaceClass )
    face.is_a?( MyPrettyFaceClass )

    true

    sel[0].is_a?( MyPrettyFaceClass )

    true`

    This is not what I want. What I'd like to do, if possible, is to extend just the reference face, and not the object it points to.

    Did I explain that clearly? πŸ˜•

    Thomas Thomassen β€” SketchUp Monkey & Coding addict
    List of my plugins and link to the CookieWare fund

    1 Reply Last reply Reply Quote 0
    • A Offline
      Anton_S
      last edited by 6 Sept 2011, 19:00

      Why won't you just edit the face class and fill it with your "MyPrettyFaceClass" functions?

      Ex:
      Class Sketchup::Face #"MyPrettyFaceClass" functions end

      Did I got you right?

      1 Reply Last reply Reply Quote 0
      • D Offline
        Dan Rathbun
        last edited by 6 Sept 2011, 19:18

        Because the API Police will haul him off to Ruby Jail !!

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • T Offline
          thomthom
          last edited by 6 Sept 2011, 19:34

          @anton_s said:

          Why won't you just edit the face class and fill it with your "MyPrettyFaceClass" functions?

          Ex:
          Class Sketchup::Face #"MyPrettyFaceClass" functions end

          Did I got you right?

          Because it'd be the same as adding methods to the global namespace. If I add a method "foo" - it could easily be overwritten by another author who also wanted to add his pretty method foo to the Face class.

          Thomas Thomassen β€” SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund

          1 Reply Last reply Reply Quote 0
          • F Offline
            fredo6
            last edited by 6 Sept 2011, 19:42

            @thomthom said:

            Is there a way to extend a Sketchup::Entity so only the reference you hold is extended?

            Example:
            ` sel = Sketchup.active_model.selection

            face = sel[0]
            face.extend( MyPrettyFaceClass )
            face.is_a?( MyPrettyFaceClass )

            true

            sel[0].is_a?( MyPrettyFaceClass )

            true`

            This is not what I want. What I'd like to do, if possible, is to extend just the reference face, and not the object it points to.

            Did I explain that clearly? πŸ˜•

            It seems to me there is no difference between the object and the reference to the object in Ruby (so sel[0] is strictly equivalent to face).

            1 Reply Last reply Reply Quote 0
            • D Offline
              Dan Rathbun
              last edited by 6 Sept 2011, 20:09

              @thomthom said:

              Is there a way to extend a Sketchup::Entity so only the reference you hold is extended?

              Yes.. extend() is supposed to do this when applied to an instance object... any instance methods in the mixin module are supposed to become singleton methods.

              @thomthom said:

              Example:
              sel = Sketchup.active_model.selection face = sel[0] face.extend( MyPrettyFaceClass ) face.is_a?( MyPrettyFaceClass )

              true

              This is weird that you did not get an TypeError exception raised. The docs indicated clearly that the argument to include() and extend() are supposed to be a mixin Module (or a list of them.)

              After you "mixin" a Class... that class becomes the superclass ? And the face is no longer a subclass of Sketchup::Face ??

              That's just not right... perhaps you found a Ruby core bug ? What version and patchlevel (and platform,) did you see this on?

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • D Offline
                Dan Rathbun
                last edited by 6 Sept 2011, 20:16

                Just for kicks...

                On PC, SU 8.0M1, Ruby v1.8.7-p299 :

                face.extend(Dan)
                %(#400000)[Error: #<TypeError: (eval):0:inextend': wrong argument type Class (expected Module)>]`

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • T Offline
                  thomthom
                  last edited by 6 Sept 2011, 21:22

                  I meant module. I just types up a fake example.

                  Regardless, .extend on an entity will affect all scripts trying to access it.

                  Thomas Thomassen β€” SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund

                  1 Reply Last reply Reply Quote 0
                  • Chris FullmerC Offline
                    Chris Fullmer
                    last edited by 6 Sept 2011, 21:46

                    What about keeping your own collection of your own special faces. I guess this is what you're trying to avoid?

                    ` sel = Sketchup.active_model.selection

                    face = sel[0]
                    MyPrettyFaces.add( face )

                    MyPrettyFaces.is_pretty?( face )

                    true`

                    Lately you've been tan, suspicious for the winter.
                    All my Plugins I've written

                    1 Reply Last reply Reply Quote 0
                    • D Offline
                      Dan Rathbun
                      last edited by 6 Sept 2011, 22:19

                      Now if you wish to automate this, similar to a mixin, you need to write your own "Extender" submodule within your namespace:

                      module TT;;Extender
                        def self.add_method_has_dictionary?(obj)
                          unless obj.is_a?(Sketchup;;Entity)
                            raise(TypeError,"wrong argument type #{obj.class.name} (expected Sketchup;;Entity subclass)",caller)
                          end
                          Object.instance_eval %q[
                            def obj.has_dictionary?(dict_name=nil)
                              return false unless ( dicts = self.attribute_dictionaries() )
                              dict_name = '' if dict_name.nil?
                              unless dict_name.is_a?(String)
                                raise(TypeError,"wrong argument type #{dict_name.class.name} (expected String)",caller)
                              end
                              dicts.any?{|dict| dict.name == dict_name }
                            end # def
                          ] 
                        end # def add_method_has_dictionary?(obj)
                      end # module TT;;Extender
                      
                      

                      Then to use:
                      face = sel[0] %(#400000)[>> #<Sketchup::Face:0x62c6090>] TT::Extender.add_method_has_dictionary?(face) %(#400000)[>> nil] face.respond_to?(:has_dictionary?) %(#400000)[>> true]

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • D Offline
                        Dan Rathbun
                        last edited by 6 Sept 2011, 23:12

                        Adding a singleton method to a SINGLE instance object is quite easy:

                        face.is_a?(Sketchup::Face)

                        true

                        def face.has_dictionary?(dict_name=nil)
                          return false unless ( dicts = self.attribute_dictionaries() )
                          dict_name = '' if dict_name.nil?
                          raise(TypeError,"wrong argument type #{dict_name.class.name} (expected String)",caller) unless dict_name.is_a?(String)
                          dicts.any?{|dict| dict.name == dict_name }
                        end
                        

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • T Offline
                          thomthom
                          last edited by 7 Sept 2011, 06:30

                          @dan rathbun said:

                          ` face.respond_to?(:has_dictionary?)

                          true`

                          And if another script was to iterate over the face, would it then get a non-extended version of the face entity?

                          Thomas Thomassen β€” SketchUp Monkey & Coding addict
                          List of my plugins and link to the CookieWare fund

                          1 Reply Last reply Reply Quote 0
                          • D Offline
                            Dan Rathbun
                            last edited by 7 Sept 2011, 13:21

                            @thomthom said:

                            @dan rathbun said:

                            ` face.respond_to?(:has_dictionary?)

                            true`

                            And if another script was to iterate over the face, would it then get a non-extended version of the face entity?

                            No it would get THE instance object, with all it's inherited instance methods, AND any singleton methods (including the newly attached :has_dictionary? method.)

                            UNLESS after using the method, you decided to unattach it somehow... IF Ruby allows doing that.
                            I don't think it does.. because undef_method() and remove_method() are private class methods, and are not inherited by the instances.

                            But what's the big deal? It's better than modifying the base API class, isn't it?

                            Your other option is to create yourself a mixin module, that you mixin to YOUR OWN modules, that creates private methods, such as:
                            ent_has_dictionary?(entity,dict_name)

                            I'm not here much anymore.

                            1 Reply Last reply Reply Quote 0
                            • D Offline
                              Dan Rathbun
                              last edited by 7 Sept 2011, 13:24

                              However .. I'm beginning to form a concept in my mind.. how perhaps scripters could create custom instance methods for any API class, without actually modifying the class... more thought and experimentation will be required.

                              I'm not here much anymore.

                              1 Reply Last reply Reply Quote 0
                              • T Offline
                                thomthom
                                last edited by 7 Sept 2011, 13:46

                                @dan rathbun said:

                                But what's the big deal? It's better than modifying the base API class, isn't it?

                                If my script iterate the entities in a model and extends them with my mixin module - then I wouldn't want to affect other scripts. It'd be the same as modifying the base class.

                                Thomas Thomassen β€” SketchUp Monkey & Coding addict
                                List of my plugins and link to the CookieWare fund

                                1 Reply Last reply Reply Quote 0
                                • D Offline
                                  Dan Rathbun
                                  last edited by 7 Sept 2011, 15:35

                                  @thomthom said:

                                  @dan rathbun said:

                                  But what's the big deal? It's better than modifying the base API class, isn't it?

                                  If my script iterate the entities in a model and extends them with my mixin module - then I wouldn't want to affect other scripts. It'd be the same as modifying the base class.

                                  We'll yes.. if you end up defining a new singleton method for EVERY Sketchup::Entity subclass instance in the model(s), then it would be comparable to extending all the classes themselves.

                                  Also.. a singleton method, is in effect, a single instance override of any inherited method of the same name, so (referring to my previous example,) if Google later ended up adding a :has_dictionary? method to the API Sketchup::Entity superclass, my example would be overriding that method, on an individual instance basis.

                                  I'm not here much anymore.

                                  1 Reply Last reply Reply Quote 0
                                  • 1 / 1
                                  1 / 1
                                  • First post
                                    1/16
                                    Last post
                                  Buy SketchPlus
                                  Buy SUbD
                                  Buy WrapR
                                  Buy eBook
                                  Buy Modelur
                                  Buy Vertex Tools
                                  Buy SketchCuisine
                                  Buy FormFonts

                                  Advertisement