sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Refer to entities from code

    Scheduled Pinned Locked Moved Developers' Forum
    19 Posts 5 Posters 372 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.
    • D Offline
      dacastror
      last edited by

      Hello, I want to make a code that gives a name or a mark to groups (or components) that are selected, so that I can then refer to this object from code without being selected at that time and then apply for example a transformation
      t = Geom::Transformation.scaling 10 entity.transform!

      for now the only thing I've accomplished is to name the group, but I do not believe this will serve for my purpose

      modelo = Sketchup.active_model
      
      if Sketchup.active_model.selection.empty?
         UI.messagebox "seleccione un grupo o un componente"
         return
      end
      
      i=0
      entidades=[]
      modelo.selection.each { |entity| 
       if entity.is_a?(Sketchup;;Group)||
          entity.is_a?(Sketchup;;ComponentInstance)
          i=i+1
          entidades[i-1]=entity 
          entidades[i-1].make_unique
          entidades[i-1].name = "Entidad #{i-1}"
       end
       }
      

      I thought about using entityID but do not quite understand how you could use this, besides not persistent between sessions.

      (google translator)

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        You have already made an array of the groups/instances called ' entidades'
        You have also named theses in turn as 'Entidad 0' 'Entidad 1' etc.
        This is what you see in the 'Entity Info' window.

        You don't need to [re]name them unless you want to.
        You can access them through the array during the current use of the script.
        To find the first one it's entidades[0] etc.
        Later on you can find by name, by iterating the model's definitions' instances...
        name="Entidad 666" hit=nil modelo.definitions.each{|d| next if d.image? d.instances.each{|i| if i.name==name hit=i break end break if hit } }
        This finds the entity with that 'name', or 'nil' if not found...

        If you want to access them by name in another session you could use the 'name' as above, or via an attribute...
        Attributes are attached to the object and endure from session to session, provided that the SKP is saved...
        Instead of renaming the object add an attribute:
        entidades[i-1].set_attribute("dacastor", "id", "Entidad #{i-1}")
        Then later to get an instance's 'id' use.
        entidade.get_attribute("dacastor", "id", nil)
        In an iteration it's be:
        idd="Entidad 666" hit=nil modelo.definitions.each{|d| next if d.image? d.instances.each{|i| if i.get_attribute("dacastor", "id", nil)==idd hit=i break end break if hit } }
        etc etc...

        TIG

        1 Reply Last reply Reply Quote 0
        • D Offline
          dacastror
          last edited by

          wow! thank you very much TIG is exactly what I needed, just some things I do not understand, that is .image?, break and break if hit

          and one more question, is there anything I can use instead of .make_unique? is that the documentation say it is an outdated method

          1 Reply Last reply Reply Quote 0
          • TIGT Offline
            TIG Moderator
            last edited by

            The API docs are sometimes wrong, .make_unique IS needed if you want to change only one instance of a component, AND it's quite possible to have more than one instance of a group too...
            However you only need to do it if there's more than one instance, so I suggest you change the code to:
            if entity.is_a?(Sketchup::Group) && entity.entities.parent.instances[1] entidades[i-1].make_unique elsif entity.definition.instances[1] ### it's a component-instance entidades[i-1].make_unique end
            Note we have to have two ways to access the object's definition and thereby its instances.
            The instance.definition works for a component-instance, but there's no equivalent for a group, for that we get the group's entities-object's parent - which is actually the definition.

            There is a 'collection' called model.definitions which contains all of the definitions in the model.
            A definition can be a Component, or a Group, or an Image.
            Groups and Images just being special kinds of 'components' if you will...
            There are two tests - d.image? and d.group? - which return true if the 'type' matches; because we aren't looking for an image when we iterate through the definitions I added
            next if d.image? which stops processing the current definition and goes on to the next one.
            Similarly when we iterate the instances and get a match on the 'idd' we set 'hit' to refer to that instance and we break - to stop iterating the instances because we have got match. Also after that the line break if hit stops iterating the definitions, when we have found a match.
            We don't actually need to skip an iteration, or stop it - because it'll carry on to the end of the lists; however, when we get a match we will waste time continuing to look because we won't find it, so it's best to learn how to use next and break to exit 'loops' ans streamline the code to do just what it needs, and no more.

            TIG

            1 Reply Last reply Reply Quote 0
            • jolranJ Offline
              jolran
              last edited by

              Hi, just want to jump in and doublecheck a little.

              So group.make_unique in the case for a group is safe to use then?

              Made a clone(instance) of the userselection group and the group was affected by transformations made (not surprisingly) if not made uniq on the original. But that anoying warning freaks me out in the ruby consol.

              1 Reply Last reply Reply Quote 0
              • TIGT Offline
                TIG Moderator
                last edited by

                The deprecated warning IS a mistake in the API.
                You CAN safely make a group unique, indeed sometimes you MUST.

                However, you can side step it, by making an empty new-group in the intended entities context and adding an instance of the copy-group into it and explode that inside it, the new-group is then equivalent to the original BUT not connected...
                new_group = some_entities.add_group() new_copy = new_group.entities.add_instance(original_group.entities.parent, original_group.transformation) new_copy.explode
                The 'new_copy' replicates 'original_group' with no 'connections'...

                TIG

                1 Reply Last reply Reply Quote 0
                • D Offline
                  dacastror
                  last edited by

                  I'm reading carefully the lines of code and I'm learning TIG proposes several things, another question arises me, suppose that I assign a different name to each dictionary of each entity and I want to find the entity using the name of the dictionary. How can I modify the condition
                  " if i.get_attribute("dacastor 666", "id", nil)==idd "?
                  (google translator)

                  1 Reply Last reply Reply Quote 0
                  • TIGT Offline
                    TIG Moderator
                    last edited by

                    If you have say three different dictionaries you can use something like:
                    ` nlist=["dacastor123", "dacastor666", "dacastor999"]###***
                    ###... etc
                    d.instances.each{|i|
                    ###... etc
                    nlist.each{|dict|
                    if i.get_attribute(dict, "id", nil)==idd
                    ###.... etc ### do stuff here
                    end
                    }

                    } ###... etc`

                    ***### 'nlist' is an array of possible dictionary names... set up before you start iterating collections of things...
                    'dict' refers to each "string" name, inside the 'nlist' [array]...

                    Note that the attribute dictionary 'names' AND the 'keys' should not contain 'spaces' or other puncuation - it should start with a-z, then more or 0-9, but you can include an '_'

                    TIG

                    1 Reply Last reply Reply Quote 0
                    • D Offline
                      dacastror
                      last edited by

                      TIG thank you very much, I will try that 😄

                      I was trying something, but is a bit more complicated:

                      
                      idd = "dic1"
                      hit = nil
                      mod.definitions.each{|d|
                         next if d.image?  
                         d.instances.each{|i|
                            next if i.attribute_dictionaries.to_a.size<1
                            dictio = i.attribute_dictionaries.to_a
                            if dictio[0].name==idd
                               hit=i           
                               break
                            end
                         break if hit
                         }
                      }
                      
                      1 Reply Last reply Reply Quote 0
                      • jolranJ Offline
                        jolran
                        last edited by

                        Hah 😄 , yes thats exactly just what I did.

                        I ran into trouble deleting the newly created definition, with something like :
                        gp=Sketchup.active_model.active_entities.add_instance(@su_gp.definition, ORIGIN)

                        Also since @su_gp (in my case) could be either a group or component I had to put in some ifs and nots as well. With entities.parent for groups just like you described.
                        Not a big deal to explode, performance-vise. Feels safer.

                        Thanks for reasuring about the group unique thing. Not gonna use it this time though 😄 .

                        BTW hope this issue was related to the topic.

                        1 Reply Last reply Reply Quote 0
                        • Dan RathbunD Offline
                          Dan Rathbun
                          last edited by

                          @dacastror said:

                          ... suppose that I assign a different name to each dictionary of each entity and I want to find the entity using the name of the dictionary. How can I modify the condition
                          " if i.get_attribute("dacastor 666", "id", nil)==idd "?
                          (google translator)

                          if i.attribute_dictionary(idd)

                          or

                          unless i.attribute_dictionary(idd).nil?

                          I'm not here much anymore.

                          1 Reply Last reply Reply Quote 0
                          • Dan RathbunD Offline
                            Dan Rathbun
                            last edited by

                            @dacastror said:

                            I was trying something, but is a bit more complicated:

                            you can simply do:

                            def find_inst_by_dict_name(dname)
                              found = nil
                              for d in definitions
                                 next if d.image? 
                                 found = d.instances.find{|i|
                                   i.attribute_dictionary(dname)
                                 }
                                 break if found
                              end # for
                              return found
                            end # def
                            

                            I'm not here much anymore.

                            1 Reply Last reply Reply Quote 0
                            • TIGT Offline
                              TIG Moderator
                              last edited by

                              You/we are starting to conflate the searching for an object that has a named attribute-dictionary attached to it [and which is uniquely named for one object, and is irrespective of any key/value pairs], and then the original code snippets which were about assigning, and then checking for, the 'value' of a specific 'key' in a named attribute-dictionary [where the key and dictionary are commonly named across several objects, and only vary by the key's 'value'].

                              I suggest you step back and decide what it is you are trying to do and how you do it best...

                              TIG

                              1 Reply Last reply Reply Quote 0
                              • D Offline
                                dacastror
                                last edited by

                                Thanks Dan, I find it very nice your suggestion, I will give a chance to this

                                Thanks for replying TIG, I really needed to know the two things, I was lost without your help

                                (google translator)

                                1 Reply Last reply Reply Quote 0
                                • D Offline
                                  dacastror
                                  last edited by

                                  I did this and I get "error", I couldn't see what is wrong

                                  mod = Sketchup.active_model
                                  definitions = mod.definitions.to_a
                                  
                                  def find_entity(dname)
                                    found = nil
                                    for d in definitions
                                       next if d.image? 
                                       found = d.instances.find{|i|
                                         i.attribute_dictionary(dname)
                                       }
                                       break if found
                                    end # for
                                    return found
                                  end # def
                                  
                                  entity = find_entity("dic1")
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • sdmitchS Offline
                                    sdmitch
                                    last edited by

                                    you need to move the

                                    mod = Sketchup.active_model
                                    definitions = mod.definitions.to_a

                                    statements inside the def since they are not module variables starting with "@".

                                    Nothing is worthless, it can always be used as a bad example.

                                    http://sdmitch.blogspot.com/

                                    1 Reply Last reply Reply Quote 0
                                    • Dan RathbunD Offline
                                      Dan Rathbun
                                      last edited by

                                      @dacastror said:

                                      I did this and I get "error", I couldn't see what is wrong

                                      I CAN 😳 It is a stupid mistake on my part.

                                      def self.find_entity(dname)
                                        found = nil
                                        for d in Sketchup.active_model.definitions
                                           next if d.image? 
                                           found = d.instances.find{|i|
                                             i.attribute_dictionary(dname)
                                           }
                                           break if found
                                        end # for
                                        return found
                                      end # def
                                      
                                      
                                      entity = find_entity("dic1")
                                      

                                      I'm not here much anymore.

                                      1 Reply Last reply Reply Quote 0
                                      • Dan RathbunD Offline
                                        Dan Rathbun
                                        last edited by

                                        Assume you have a "DiegoCastro" folder:

                                        And in it a "Lib.rb" file for your library methods:

                                        module DiegoCastro
                                        
                                          module Lib
                                        
                                            def find_entity(model,dname)
                                              found = nil
                                              for d in model.definitions
                                                next if d.image? 
                                                found = d.instances.find{|i|
                                                  i.attribute_dictionary(dname)
                                                }
                                                break if found
                                              end # for
                                              return found
                                            end # def
                                        
                                          end # Lib sub-module
                                          
                                        end # Author toplevel namespace module
                                        
                                        

                                        Then in SomePlugin you do this... (name it whatever.. "diegotest.rb" etc.)

                                        
                                        module DiegoCastro
                                        
                                          module SomePlugin # <--<< change plugin sub-module name as needed
                                        
                                            class << self # proxy class
                                        
                                              require('DiegoCastro/Lib')
                                              include(DiegoCastro;;Lib)
                                            
                                              def find_inst_by_dict_name()
                                                if @last_dict.nil?
                                                  @last_dict = "dynamic_attributes" # initial value
                                                end
                                                dname = UI.inputbox(['Dictionary Name........; '], [@last_dict], "Find by Dicto Name")
                                                if dname # user did not cancel the inputbox
                                                  unless dname.empty? || dname[0].length==0
                                                    @last_dict = dname[0]
                                                    entity = find_entity(Sketchup.active_model,dname[0])
                                                    if entity
                                                      UI.messagebox("Found #{entity.inspect}     \nwith dictionary name '#{@last_dict}'     ")
                                                      #
                                                      return entity
                                                      #
                                                    else # nothing was found because find returned nil 
                                                      UI.messagebox("No entity found with     \n dictionary name '#{@last_dict}'     ")
                                                    end
                                                  end
                                                end
                                                return nil
                                              end
                                            
                                            end # proxy class
                                            
                                            unless file_loaded?(File.basename(__FILE__))
                                        
                                              # create menus here;
                                              @@submenu = UI.menu('Plugins').add_submenu('Diego')
                                              @@submenu.add_item('Find entity by Dicto Name') {
                                                find_inst_by_dict_name()
                                              }
                                        
                                              file_loaded(File.basename(__FILE__))
                                        
                                            end
                                        
                                          end # plugin sub-module
                                        
                                        end # Auhtor module
                                        

                                        I'm not here much anymore.

                                        1 Reply Last reply Reply Quote 0
                                        • D Offline
                                          dacastror
                                          last edited by

                                          wow thanks Dan, I will take some time to study this code, worth but me several questions arise, I will try to solve the most I can on my own, thank you very much 😄
                                          (google translator)

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

                                          Advertisement