Select all sub-components in a selection

You are absolutely right and finding the solution is for the moment beyond my abilities!

I will definitely drop the idea of purging components by selection.

I will propose a global cleanup for all dynamic components in SketchUp.

It remains for me to define if I do it only for the models proposed by Click-Cuisine 2.

Sorry not to present the methods in the respect of styles, but I do not have much experience in Ruby.

You understand the 3 methods, they do exactly what I wanted.

It would be interesting to be able to select the parent components after the 3rd method.

Do you know how to return to the previous selection?

Thank you

I solved the problem to make all unique. :wink:

Are you sure this is what the user would expect? I’ve seen extensions make objects unique in order to make the programming easier - at the expence of breaking the component definition/instance contract that users expect.

2 Likes

Did create a unique definition for each individual instance or did re-use definitions for instances that previously used the same definition? If you did the former the file size while increase quite a bit.

You mean like the DC extension? An extension making an instance unique when interacting with it, instead of having a true DC system built-in the core of SketchUp.

:wink:

4 Likes

Add or remove dynamic attributes affects all instances.

If the user chooses to modify only the selected instances, he must expect it to be made unique.

You’re still right, making all instances of a piece of furniture unique will increase the volume of the file.

And the loading time can be very long, if there are many instances!

For this reason, making unique will only be applied in the cleaning method of the selection.

The method of cleaning all the project or all the furniture proposed by Click-Cuisine does not need to make unique! ( So no increase in the file size, no execution time. )

I understand that cleaning dynamic components in a selection may seem odd or unnecessary!

This method is under study to determine if it is more beneficial than harmful.

Cordially

David

eneroth3, I just noticed that your method selects sub-components for a single parent component.

Maybe this comes from the use of the “first” method?

How can you select the sub-components of several parent components?

Thank you

David

David, I think it’s difficult for those who do not know the history and workings of your extensions


as the files are huge, I’ll show some image


the skp file is 46.9MB:

after a clean up it’s 1.3MB:

cc_test_file_1.skp (1.3 MB)

but it still has ‘dynamic attributes’ as well as some that should be purged before including in the extension


and here’s a gif of removed geometry [ anything with #BADA55 background ]

john

1 Like

John, which weighs 46.9MB is not the models but the 700 IKEA materials, which are imported with the control panel.

Without these materials, Click-Cuisine could not offer the 5000 IKEA kitchen furniture.

Without taking into account the materials that will be purged:

The dynamic furniture with all these sub-components and attributes makes a weight of 1MB.

After cleaning the attributes as well as the hidden components the furniture makes a weight of 360KO.

I need help in the programming so if a person of experience can help me for my previous question, he would be very nice.

Thank you

David

as I said the other day


then cleanup is a lot easier


I modified one of my ‘commercial’ plugins to clean the model and generate that report


did you inspect the ‘cleaned’ model?

you do not need to ‘select’ them, you need to ‘collect’ them


john

2 Likes

Touché!

1 Like

This is the case for Click-Cuisine 2, which will soon be available. :wink:

Yes, and the job seems well done!

Ok I will collect!

Can you show me an example that collects all the entities of a selection and then removes the hidden entities?

Thank you

are you wanting to change the handles?

after ‘collecting’ them in an array you can pass them to the ‘model.selection’ and use ‘replace selected’ manually


but you would need to fix the insertion points and axis for all handle placements to match


I just tacked this onto to my cleaner code to explain what I mean


in code you can do the same thing without ever adding to the ‘model.selection’


is handle replacement your end goal?

john

No it has been done for a long time on Click-Kitchen 2, with automatic positioning of the handles : :grinning:

I am in the final straight or I want to propose a solution of cleanings of furniture proposed by Click-Kitchen 2.

To purge the components of the first level of nesting, I found hundreds of methods!

Here is a simple method that works:

mod = Sketchup.active_model
sel = mod.selection
sel.each{|s| s.definition.entities.grep(Sketchup::ComponentInstance).each{|e| e.erase! if e.hidden? }}

Cleaning the subcomponents of the child component is much more complicated!

It is on this subject that I need your help.

I do not lose hope!

David

Ps: If I find the only solution, I will come to post it to help all those who will find a day in my situation.

please read and try to understand what happens in this code


ask questions when you don’t follow the code


I left in ‘collecting’ the handles, but commented out the highlighting


# ClickCuisine::Cleaner (C) Copyright 2017 john@drivenupthewall.co.uk
#
#
require 'sketchup.rb'
# your namespace
module ClickCuisine
  # your cleaner
  module Cleaner

    extend self

    def target(ents)
      ents.grep(Sketchup::Group).concat(ents.grep(Sketchup::ComponentInstance))
    end

    def kids?(entity)
      entity.definition.entities rescue entity.entities
    end

    def hidden(e)
      e.hidden?
    end

    def layer(e, ln)
      e.layer.name =~ ln
    end

    def to_clean(entity)
      #
      kids  = kids?(entity)
      tents = target(kids)
      lngth = tents.length
      return unless lngth > 0
      tents.each do |child|
        # add any child we do not want, we can use known names to help...
        if hidden(child) || layer(child, /VIGNETTES/) || child.definition.name == '00'
          @to_go << child
        # now we can remove dynamic attributes from the ones we want to keep
        elsif child.definition.attribute_dictionaries
          child.definition.attribute_dictionaries.delete('dynamic_attributes')
          child.attribute_dictionaries.delete('dynamic_attributes') if child.attribute_dictionaries
        end
        # we can also 'collect' the handles here or you could have a separate ruby without  @to_go[] code...
        if child.parent != Sketchup.active_model
           # again, we can use known names to help...
          @handles << child if child.definition.name =~ /F.*POIGNEE/
        end
        # send it back to start like in 'Snakes and Ladders'
        to_clean(child)
      end # do
    end # def

    # we start and end here
    def main
      model = Sketchup.active_model
      defs  = model.definitions
      ents  = model.entities
      lays  = model.layers
      mats  = model.materials
      sel = model.selection
      # we create an array we can fill from outside this method
      @to_go = []
      # we can also 'collect' the handles
      @handles = []
      # we send the whole model to the cleaners
      to_clean(model)
      # create an operation before touching geometry
      model.start_operation('cc_clean')
      # to_clean(model) returns the array which we can erase
      ents.erase_entities(@to_go)
      # then we cleanup properly
      [defs, lays, mats].each{|a| a.purge_unused}
      # always close the operation
      ensure model.commit_operation
      # we can then do stuff with the handles in @ handles
      # sel.add(@handles)
    end
  end
end

file = File.basename(__FILE__)

unless file_loaded?(file)
  UI.menu('Plugins').add_item('Click Cuisine Cleaner') { ClickCuisine::Cleaner.main }
  file_loaded(file)
end

# ClickCuisine::Cleaner.main

john

Wow, I was not asking as much!

Your code works wonderfully and purges all dynamic attributes and hidden components and much more.

I will take the time to analyze it and come back to ask my questions.

Thank you

Does your code purge all hidden sub-components and dynamic attributes in SketchUp or am I mistaken?

My goal is to purge the selected components:

Method 1 - Activate all Click-Kitchen 2 Dynamic Parent Components using the definitions names:

def method1	
    ["IKEA","PLAN BAR SUR PIEDS","TABLE SUR PIED"].each{|name|
    match = /#{name}/i	
    m=Sketchup.active_model;
    s=m.selection;
    m.definitions.each{|d|s.add d.instances if d.name =~ match }}
    end

Method 2 - Purge all dynamic attributes and hidden components in the selection.

### It's code that I want to write. :-(

Thus, users of Click-Cuisine 2, will not affect other components that have nothing to do with the Plugin.

To purge all the hidden components and dynamic attributes of the SketchUp file, I know this solution:

def erase_hidden_components
    Sketchup.active_model.definitions.each{|d|d.entities.grep(Sketchup::ComponentInstance).each{|e|e.erase! if e.hidden?}}
	end
	
def purge_dynamic_attributes	
    m=Sketchup.active_model;m.definitions.each{|d|d.attribute_dictionaries.delete("dynamic_attributes") 
	d.instances.each{|i|i.attribute_dictionaries.delete("dynamic_attributes")}}
	end
	
	erase_hidden_components
	purge_dynamic_attributes

But I do not want to do that!

Tomorrow I will study your code better, because it is certain that I have things to learn.

Thank you for your help John.

David

will cause the code to look 3 times over the same things


you can do them all at once if you recall the code from earlier posts at SCF


names = Regexp.union("IKEA","PLAN BAR SUR PIEDS","TABLE SUR PIED") 
tents.each do |child|
next unless child.definition.name =~ names

EDIT: in the version of C_C I have, you would be better with a single filter method


here’s a cut and paste test snippet


    model = Sketchup.active_model
    sel = model.selection
    def davids(child)
      dicts = child.definition.attribute_dictionaries
      'david B.' == dicts['GSU_ContributorsInfo']['NicknamesKey'].first
      rescue
        false
      end
    end
    # to test select other items then run
    davids(sel[0])

when combined into the cleaner, correctly, you will then only destroy ‘your’ named DC’s


john

in slightly the wrong place it misses some of your hidden entities


john

Good morning, John

I took an hour to analyze your code and I find it very surprising!

For example this excerpt:

if hidden(child)||layer(child,/VIGNETTES/)||child.definition.name=~/#{"00"}/

  • It allows you to delete all Hidden entities.

  • The models with the layer “VIGNETTES”.

  • The definitions with “00” in their name.

I am surprised not to find the method that triggers the deletion, like “erase!” for example.

And yet the elements are removed!

I also enjoyed this excerpt:

[defs, lays, mats] .each {| a | a.purge_unused}

That allows to purge the definitions, layers and materials with a single purge_unused. :slight_smile:
_

What is the purpose of opening and closing an operation like “model.start_operation (‘cc_clean’)”?

Can cancel the operation immediately in SketchUp?

If yes, can the cleaning operation be memorized so that it can be canceled at any time with a method?

Here are my first questions and comments on your code.

Thank you

David