Displaying/hiding component instances in timed fashion (i.e. most simple animation)


#1

I wonder if someone can help me with a simple “animation”.
In fact I do not want to move anything.
I just would like to show(or hide) my component instances one by one with a small delay.

My model includes several hundreds of my special bricks.
I need to show these bricks one-by-one (as one would build a house by these "LEGO like) bricks).
I mean on this that the first “scene” would be empty.
Second “scene” would display only the first brick,
the third “scene” would show one more brick, and so on.
I do not want to move anything.
Only make them visible one-by-one.

That means I would need the same number of scenes
as the number of bricks (500-1000)
and I think this is way much more than SU Scenes can handle.
That is why I use ruby script instead.

However my code below just does not work.
(I use Sketchup Pro 2018)

It works for the first few bricks than it waits and displays the final state .
I understand that this is something to do with asynch feature of Sketchup.
But can not find solution using Google.

(I’ve a sample model too, but don’t know how to upload.)

I would appreciate any help.

model    = Sketchup.active_model # OK
defns    = model.definitions
view     = model.active_view

defns.each{|defn|
  defn.instances.each{|inst|
model.start_operation('Wall display', true)
    inst.visible = false
    Kernel.sleep(1.0) # a second
    view.invalidate
    # view.refresh
model.commit_operation
  }
}

Component Animation
Testing Grounds for some Wild Format Experiments—Avoid, or be careful!
#2
model    = Sketchup.active_model
defns    = model.definitions
view     = model.active_view

model.start_operation('Wall display', false)

defns.each{|defn|
  defn.instances.each{|inst|
    puts inst
    inst.visible = false
    view.refresh
    Kernel.sleep(0.5)
  }
}
model.commit_operation # for conciseness
'the end'

#3
Attaching files (... click to expand...)

With Windows you can drag and drop the file (from a file explorer window) into the forum post edit box.

You can edit a previous post by using the pencil icon (at the bottom of each of your posts.)

When an empty post / reply edit box first opens, it has some help text displayed telling you which button can be used to open a file browser dialog. As you get to know the forum, pay attention to the prompts. The Discourse forum engine tries to teach “on the fly”.
The initial help text in the edit box says …
Use Markdown, BBCode, or HTML to format. Drag or paste images. Upload your model of file if possible (7th icon to the right.)
As soon as you begin typing this help text disappears.

The “7th icon to the right” is an ol’ 5.25" hard drive bay with an upload arrow above it, pointing upwards.

If you hover your mouse above each edit toolbar button, you’ll see a popup tooltip telling you what the button do.

Markdown is easiest to use for formatting in forums.


#4

Many thanks for these new replies!
With help of Dan, I enclosed the model.
I’ve learned that size limit is under 4Mb - which makes sense of course.
So I enclose a limited model with the ground floor erased.

teszt.skp (1.9 MB)

One can see that this floor alone includes more than 2000 (slightly different)
bricks.

Thanks Williams for the corrected code!
Althout your modification makes the code more coherent,
it does not solve the problem.
Only the very first briks disappear as required then program start to work
in background and then displays the final result suddenly (i.e. hide the remaing part of the model at the same time).


#5

I’ve tested with your model and my code in both sketchup 2015 and sketchup 2017. It worked perfectly even with the Outliner and Model Info windows open.

Is this not working for only SU 2018? Anyone have an idea?


#6

Your code works fine here. I removed the half second sleep and the puts statement to speed it up a bit and it looks quite cool. You’d have to sort the bricks in order to make it look like it was being built or demolished brick-by-brick.


#7

Another version, but building the house

The code is more lengthy, but sorts the bricks.
Note that I found empty groups in the model, which are also discarded

#Top method to animate bricks
def brick_animate
	#Get all the bricks
	model = Sketchup.active_model
	ee = model.entities
	lst_comps = ee.grep(Sketchup::ComponentInstance).find_all {|g| g.definition.entities.grep(Sketchup::Face).length > 0}
	lst_comps += ee.grep(Sketchup::Group).find_all {|g| g.entities.grep(Sketchup::Face).length > 0}
	
	#Sort the bricks by Z, then by X then by Y
	lst_comps.sort! do |a, b| 
		xa, ya, za = a.bounds.center.to_a.collect { |x| x.round }
		xb, yb, zb = b.bounds.center.to_a.collect { |x| x.round }
		(za == zb) ? ((xa == xb) ? ya <=> yb : xa <=> xb) : za <=> zb 
	end	
	
	#Start Operation
	model.start_operation "Brick_animate", true
	
	#Hide all bricks
	lst_comps.each do |comp|
		comp.visible = false
	end
	Sketchup.active_model.active_view.refresh
	
	#Make bricks appear one by one
	brick_appear(lst_comps)
end

#Method to animate one brick
def brick_appear(lst_comps)
	#Get the next brick. If none, we have finished
	comp = lst_comps.shift
	puts "Left bricks = #{lst_comps.length}" if lst_comps.length.modulo(100) == 0
	return Sketchup.active_model.commit_operation unless comp
	
	#Make the brick appear
	comp.visible = true
	Sketchup.active_model.active_view.refresh
	
	#Get to the next brick
	UI.start_timer(0.02) { brick_appear(lst_comps) }
end

Fredo

GregIII%20-%20Bricks%20Animation


#8

Dear Williams and McGordon!

Thank you for your time and looking into this problem.
Indeed, it seems to me that the simple code that works
for Williams and McGordon maybe works only in pre SU 2018 Pro.
I’ve enclosed a video to show how this code works on SU Pro 2018 (ie. for me).

However I am happy to tell that Fredo’s code works fine even on SU 2018 Pro.
I have tested Fredo’s code changing the delay time from 0.02s, 0.5s, 1.0s, and 5.0s.
The code does what is expected: displays the brick on-by-one with the given delay time between brick.
So my special thanks goes to Fredo!

I think this case is solved and I thank to all of you who sent repsonse since I have learned from all responses a lot!

Regards, Viktor


#9

Just a conlcuding remark for future visitors of this topic:
From these expert guys are have learned that the first (and simple)
code is not robust , and does not work under some (not fully explored)
conditions.
Certainly it does not work on my Sketchup Pro 2018 .

To make it robust, one need to give back control to Sketchup
along the lengthy process,
which is done by using a timer.

Fredo presented a very nice and elegant sample code for it:
the first method clears the sceene and calls the
2nd (called “brick_appear”) method that makes the job done.

(As far as I understand this 2nd method calls itself recurzively
by using the UI.start_timer(delaytime) {called_function}. )