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

    Use Ruby To Apply Materials to Spacific Layers

    Scheduled Pinned Locked Moved Developers' Forum
    24 Posts 8 Posters 10.3k Views 8 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.
    • E Offline
      Eric_Erb
      last edited by

      Alright, I've been messing around with the code... This is it as it is now...
      ` module Eric_Erb
      def self.color_by_layer
      su_materials = Sketchup.active_model.materials
      my_materials = Hash.new
      my_materials["Wall_Surfaces"] = su_materials["Roofing_Metal_Standing_Seam_Red"]
      my_materials["Roof_Surface"] = su_materials["Roofing_Slate_Tan"]
      # .. and so on.

      begin
          Sketchup.active_model.start_operation("Color By Layer", true)
      rescue ArgumentError
          Sketchup.active_model.start_operation("Color By Layer")
      end
      # Loop through entities & apply material based on layer name
      Sketchup.active_model.entities.each do |entity|
          if entity.is_a? Sketchup::Drawingelement
      	entity.material = my_materials[entity.layer.name]
          end
      end
      Sketchup.active_model.commit_operation
      end
      

      end

      UI.menu('Plugins').add_item("Color by Layer") { Eric_Erb.color_by_layer }`

      I didn't add anymore Layers to apply materials to just to see if I could get it running as is. It doesn't apply materials though. The line: su_materials = Sketchup.active_model.materials, I thought that might mean "referance the materials already active in the model", so I created a couple shapes on different layers and applied the materials I wanted to use to those and when I ran the plug-in it actually removed the materials from my new layers, so I guess I interpreted that line wrong. I'm sure my error is completely obvious to people like you that can rap their heads around coding like this (which is absolutely amazing by the way), but can you tell me where I'm messing this up?

      1 Reply Last reply Reply Quote 0
      • RunnerPackR Offline
        RunnerPack
        last edited by

        @eric_erb said:

        The line: su_materials = Sketchup.active_model.materials, I thought that might mean "referance the materials already active in the model", so I created a couple shapes on different layers and applied the materials I wanted to use to those and when I ran the plug-in it actually removed the materials from my new layers, so I guess I interpreted that line wrong.

        No, you interpreted correctly. That is exactly what it means. The only explanation I have for the code removing materials (which I assume means setting them to the default material) is that there is a mismatch between the names of your materials or layers and the contents of your hash.

        My idea would be to skip the hash and just make sure the names of layers and their respective materials are the same. i.e. anything on the "Roof" layer is painted with the material called "Roof", and so on.

        Here's the code for that (which also checks if the material exists before changing it):

        
        module Eric_Erb
        
            def self.paint_by_layer
                mod = Sketchup.active_model
                su_materials = mod.materials
                
                begin
                    mod.start_operation("Paint By Layer", true)
                rescue ArgumentError
                    mod.start_operation("Paint By Layer")
                end
        
                # Loop through entities & apply material based on layer name
                Sketchup.active_model.entities.each do |e|
                    mat = su_materials[e.layer.name]
                    unless mat.nil?
        	            if e.is_a? Sketchup;;Drawingelement then
        	                e.material = mat
        					e.back_material = mat if e.respond_to?('back_material=')
                    	end
                    end
                end
        
                mod.commit_operation
            end
        
        end
        
        unless file_loaded? File;;basename(__FILE__)
            UI.menu('Plugins').add_item('Paint by Layer') { Eric_Erb.paint_by_layer }
            file_loaded File;;basename(__FILE__)
        end
        
        

        (As you can see, I also attached it for downloading.)

        If you do stick with the hash, it may make it easier to edit if you declare it like:

        
        my_materials = {
            "Wall_Surfaces" => su_materials["Roofing_Metal_Standing_Seam_Red"],
            "Roof_Surface" => su_materials["Roofing_Slate_Tan"]
            # .. and so on.
        }
        
        

        Also, when testing, don't paint the objects beforehand. Just make some layers, make a material for each layer with the same name, make a face on each layer, and run the script.

        I hope that helps.


        Paints each entity with a material named after its layer.

        You might have noticed... I'm a bit of a ferpectionist.

        1 Reply Last reply Reply Quote 0
        • E Offline
          Eric_Erb
          last edited by

          Thank you RunnerPack, I'll try that approach right now. Yes, I did mean setting them to the default materials

          1 Reply Last reply Reply Quote 0
          • E Offline
            Eric_Erb
            last edited by

            On Sketchup Load it's returning... undefined method `file_loaded' for main:Object. is there something here I'm supposed to change before I save it to plugins? By the way unless it will crash the script otherwise, there's no need for the script to make sure there's a material that matches the layer name before it runs. Like I said... The Layers are always named the same so when I create materials named after the layer names there will always be a material for each of the layers.

            1 Reply Last reply Reply Quote 0
            • bagateloB Offline
              bagatelo
              last edited by

              I want a plugin that deletes some materials of the scene, even if they are in use, in a similar way that as we deleted several emails in our email account. Maybe if it was possible to substitute several materials for one in one time, this would be also interesting. Another thing that I want would be the possibility of add a word or number in begin of all the materials of the object or scene.

              "I'm organizing my library components from SketchUp, and because I use V-Ray to render my images, I put useful components names of the materials under the name of the component, to edit in V-Ray."

              So, I wonder if it would be possible to create a script that renames the materials of these components according to some criteria. For example, suppose that I am editing a component called "table 045.skp" and it has the following materials: mapple wood, metal, white paint, etc.. After we run the script, the material would have the following names, such as:
              wood mapple >> "wood table 045 01",
              Metal >> "wood table 045 02",
              white paint >> "wood table 045 03"

              The reason for this is that it's confusing to locate in the scene the names of the materials of the componentes for editing in Vray.

              Thanks...

              While the cat's away, the mice will play

              1 Reply Last reply Reply Quote 0
              • honoluludesktopH Offline
                honoluludesktop
                last edited by

                Amos, or anyone, can your code be easily modified to apply textures (by their name) to components (by their name) while ignoring all other entities (surfaces, components with names that do not match textures, groups, etc.)?

                1 Reply Last reply Reply Quote 0
                • RunnerPackR Offline
                  RunnerPack
                  last edited by

                  @eric_erb said:

                  On Sketchup Load it's returning... undefined method `file_loaded' for main:Object. is there something here I'm supposed to change before I save it to plugins?

                  Oops! Put the following line at the top:

                  require 'sketchup'
                  

                  @unknownuser said:

                  By the way unless it will crash the script otherwise, there's no need for the script to make sure there's a material that matches the layer name before it runs. Like I said... The Layers are always named the same so when I create materials named after the layer names there will always be a material for each of the layers.

                  Well, it's always good coding practice to put in as much error handling as one can. Ideally (though not necessary in this simple script) one should use begin...rescue...end blocks to trap and handle errors in a clean manner. Besides, this script could be handy for others who may not want to make sure every layer has a material, and vice versa, just to keep it from wiping out their already-assigned materials. 😄

                  You might have noticed... I'm a bit of a ferpectionist.

                  1 Reply Last reply Reply Quote 0
                  • RunnerPackR Offline
                    RunnerPack
                    last edited by

                    @bagatelo:

                    Ignoring the fact that you hijacked the thread... 😉 I suggest you look at the code posted so far, at the code of some related plugins, and at the SketchUp Ruby API docs, and see if you can come up with something that does what you want. Your idea sounds like a simple extrapolation of the code above. If you start your own thread, I and other Rubyists can answer specific questions as you go.

                    You may find that you really enjoy programming in Ruby. I certainly do! 😄

                    @honoluludesktop:

                    Yes, that would be quite simple. Just change the test for Sketchup::Drawingelement to Sketchup::ComponentInstance and e.layer.name to either e.name or e.definition.name. You might want to put in another test for Groups, too.

                    You might have noticed... I'm a bit of a ferpectionist.

                    1 Reply Last reply Reply Quote 0
                    • E Offline
                      Eric_Erb
                      last edited by

                      @runnerpack said:

                      this script could be handy for others who may not want to make sure every layer has a material, and vice versa, just to keep it from wiping out their already-assigned materials. 😄

                      Sorry, I didn't think about people not wanting to replace all the materials on every layer. Thank you so much RunnerPack. You have been a life saver... Now I just gotta read the little book of ruby a few more times (I just finished the second read) last night), and maybe this will finally click. You know I didn't have near the same difficulty learning AS3 or HTML.

                      1 Reply Last reply Reply Quote 0
                      • honoluludesktopH Offline
                        honoluludesktop
                        last edited by

                        Amos, Thanks, I will give it a spin the next time I have a model that I import by component/texture into my model:-) Btw, I am more of a hacker then a Ruby programmer, any hints on "another test for groups" is welcomed.

                        1 Reply Last reply Reply Quote 0
                        • RunnerPackR Offline
                          RunnerPack
                          last edited by

                          @eric_erb said:

                          ...Thank you so much RunnerPack. You have been a life saver... Now I just gotta read the little book of ruby a few more times (I just finished the second read) last night), and maybe this will finally click. You know I didn't have near the same difficulty learning AS3 or HTML.

                          You're quite welcome. (I didn't even do much, really...)

                          If you can make sense of ActionScript, I'm confident you'll learn Ruby in short order. Not to brag, but I haven't read any books on Ruby; I just keep the reference docs handy. And those are from Ruby 1.4.6. 😛

                          I guess I just learn better by doing, and Ruby makes that process very fast.

                          You might have noticed... I'm a bit of a ferpectionist.

                          1 Reply Last reply Reply Quote 0
                          • RunnerPackR Offline
                            RunnerPack
                            last edited by

                            @honoluludesktop said:

                            Amos, Thanks, I will give it a spin the next time I have a model that I import by component/texture into my model:-) Btw, I am more of a hacker then a Ruby programmer, any hints on "another test for groups" is welcomed.

                            I just meant to add another "if" statement to test for Group entities. It's necessary if you use e.definition.name, since Groups don't have definitions. But it would actually take a bit of code refactoring, like so:

                            
                            module Eric_Erb_and_AJB
                            
                                def self.paint_by_name
                                    mod = Sketchup.active_model
                                    su_materials = mod.materials
                            
                                    begin
                                        mod.start_operation("Paint By Layer", true)
                                    rescue ArgumentError
                                        mod.start_operation("Paint By Layer")
                                    end
                            
                                    # Loop through entities & apply material based on layer name
                                    Sketchup.active_model.entities.each do |e|
                                        begin
                                            mat = su_materials[e.definition.name]
                                        rescue
                                            mat = su_materials[e.name]
                                        end
                            
                                        unless mat.nil?
                                            if e.is_a? Sketchup;;ComponentInstance or e.is_a? Sketchup;;Group then
                                                e.material = mat
                                            end
                                        end
                            
                                    end
                            
                                    mod.commit_operation
                                end
                            
                            end
                            
                            unless file_loaded? File;;basename(__FILE__)
                                UI.menu('Plugins').add_item('Paint by Layer') { Eric_Erb_and_AJB.paint_by_name }
                                file_loaded File;;basename(__FILE__)
                            end
                            
                            

                            You might have noticed... I'm a bit of a ferpectionist.

                            1 Reply Last reply Reply Quote 0
                            • honoluludesktopH Offline
                              honoluludesktop
                              last edited by

                              Amos, Thanks. Am currently at home. Will work on it at the office tomorrow.

                              1 Reply Last reply Reply Quote 0
                              • honoluludesktopH Offline
                                honoluludesktop
                                last edited by

                                Amos, Thanks, this is a big help for me. Any reason why (sometimes) I have to click on the display after the plugin has run in order for the textures to change? Hmm... Sometimes I change the component name from different menus, or change the texture name from diferent menus. Does it matter?

                                1 Reply Last reply Reply Quote 0
                                • bagateloB Offline
                                  bagatelo
                                  last edited by

                                  Inside the Vray Plugin have tool to apply materials to specific layers.

                                  While the cat's away, the mice will play

                                  1 Reply Last reply Reply Quote 0
                                  • Didier BurD Offline
                                    Didier Bur
                                    last edited by

                                    Hi,
                                    This one may help you too: layers_materials.rb to be found at the Ruby Library Depot, "layers Selection"page.

                                    DB

                                    1 Reply Last reply Reply Quote 0
                                    • A Offline
                                      austinryan
                                      last edited by

                                      Man I thought python and Dynamo were hard. I even had a go at lisp but for some reason I cant get my head a round ruby. I like the code above but want to use the clean code but also just add in the layer names and leave the other ones alone. It seams that when I run this it converts all the layers in the model to Default and then the layer color had to be the same as the material name. I like the hash option but cant seem to get it to run on transparent materials and it only paints 1 side. any suggestions

                                      P.S. I am bringing in a dwg (exported from Revit) with 20 or so layers and want to put all the layers to 1 color but windows I want them to be on Translucent Glass Gray

                                      F.E. all layers to color 123_White except 0_EX_Glazing it needs to be on Translucent Glass Gray

                                      Some of the issues

                                      1. the import comes in as 1 group (with layers in the group)
                                      2. some of the groups come in the main group with groups within groups (doors and Door windows)
                                        Objects come in with a material not defined (<auto1>)so a generic material must be placed on all the objects for the script to have a chance.

                                      Thanks in advance

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

                                      Advertisement