How can I force to close the inputbox before continue the function?

I have an UI.Inputbox to obtain a value. (animation’s duration)
That value received is used at the begining of another function but, while my other function is running the inputbox remains opened in front of my screen and I can’t see the whole proccess.
How can I force to close the inputbox before continue the function?
inputbox

Without example code, we have no idea what you are doing.

The obvious answer will be to not display the inputbox until your code is ready to process it’s return value(s).

1 Like

There is no such function. The goal of the imputbox is the User interaction.
You need to open it in a “right” place in a your code, but without seeing your code, is hard to tell you…

My guessing, is you are using UI.start_timer (s) within a method and the UI.inputbox line placed in your code after the timer block, then you are calling the same method passing the duration parameter from result of inputbox back to the method which is starting a new timer…then the inputbox is “reopening”.

The thing here is: once the timer started the “main” code is still executing the imputbox. The code within a block of the timer will be executed after the time elapsed (unless you stop the timer before ) .
The imputbox is waiting for the user action, during that the “main” code is also “waiting” (while the timer above is still running …)

1 Like

The output of the input box decided how long does it take the animation (in seconds). When the animation just finished then the input box disappear.

This is my code in Spanish (that’s the reason I didn’t put it) but I’ll try to explain/translate variables:
My main purpose is that the animation sleep every loop (seconds of animation/total days of the project)

datos[0] = how long in days does it take the project
datos[1] = [the day that the element should start, the Id of the element]
datos[2] = the amount of seconds received from the input box
periodo = counter
elementoApagar = it helps me when I should remove the selection (I want to take elements selected while they appear)

def comienzaAnimacion(datos)
	duracionTotalDelProyecto = datos[0]
	recopilacionDeTareas = datos[1]
	duracionTotal = datos[2]
	periodo = 1
	fff= Time.now
	for d in 1..duracionTotalDelProyecto.to_i do
		elementoApagar = ""
		recopilacionDeTareas.each {|dd|
			if dd[0].to_i == periodo
				if elementoApagar == ""
					Sketchup.active_model.selection.clear
				end
				elementoApagar = Sketchup.active_model.find_entity_by_id(dd[1])
				Sketchup.active_model.selection.add elementoApagar
				elementoApagar.hidden = false
			end
			}
		view = Sketchup.active_model.active_view
		view.refresh
		timeToSleep = (duracionTotal/duracionTotalDelProyecto.to_f)
		sleep timeToSleep
		periodo +=1
	end
puts Time.now-fff
Sketchup.active_model.selection.clear
end

I’m sorry for the languages mix…

I explained my code before this post. I hope you could understand it

Have you tried to use an abstract Animation class ?

Ruby’s global sleep method does not work well with SketchUp.
This method only works well when Ruby runs in it’s own process.

No I haven’t. My aim is not a real animation as Sketchup does with scenes. My elements should appear in order as they should be built.
First day (element1, 2, etc.) appear
Second day (element n…) appear
Third day

That’s the reason why I’m attaching them data about the starting & finish date.
If I don’t use a delay (sleep) all of them appear very quickly

I don’t see any UI.inputbox call in your code. Still hard to tell why it is appearing or not.

Do you want something like this?
As an example let’s assume you have 5 entities in the model…:
projecttimeline
.
.

def user_input()
  model = Sketchup.active_model
  prompts = ["Duration"]
  defaults = ["5" ]
  list = [ "1|5|10|20" ]
  duration = UI.inputbox(prompts, defaults, list, "Select duration")
  if duration
    datos = []
    ids = model.entities.map(&:entityID).sort
    model.entities.each{|e| e.hidden = true }
    recopilacionDeTareas = [ [ 1, ids[0] ],
                             [ 2, ids[1] ],
                             [ 3, ids[2] ],
                             [ 2, ids[3] ],
                             [ 3, ids[4] ] ]
    datos[0] = 3 #duracionTotalDelProyecto 
    datos[1] = recopilacionDeTareas
    datos[2] = duration.first.to_i
    comienzaAnimacion( datos )
  end
end

def comienzaAnimacion( datos )
  model = Sketchup.active_model
  sel = model.selection
  view = model.active_view
  duracionTotalDelProyecto = datos[0]
  duracionTotal = datos[2]
  timeToSleep = (duracionTotal/duracionTotalDelProyecto.to_f)
  recopilacionDeTareas = datos[1]
  # periodo = 1
  fff = Time.now
  for d in 1..duracionTotalDelProyecto.to_i do
    elementoApagar = nil
    recopilacionDeTareas.each {|dd|
      if dd[0].to_i == d
        sel.clear unless elementoApagar
        elementoApagar = model.find_entity_by_id( dd[1] )
        elementoApagar.hidden = false
        sel.add( elementoApagar )
      end
      }
    view.refresh
    sleep timeToSleep
    # periodo +=1
  end
  puts Time.now - fff
  sel.clear
  user_input( )
end

user_input()

Yes that’s what I really need.
I think my error was that my input function didn’t call directly the animation function. Only returned a value, and that value was used inside de animation function so that it still remained until the function ended.
Thank’s a lot @dezmo I really appreciate the help you all provide here.

I’m afraid @dezmo that it doesn’t works on mac. I changed my code as yours and I have the same problem.
I copied your code in a new script and my input box still remain while animation.
It should be something wrong with mac.

:astonished: That is almost impossible.

If you click on any button ( OK or Cancel) of inputbox the inputbox must be closed!
If you copy-pasted my code above to your Ruby Console - you must have similar 5 (or more) entities in the model - you must see similar actions as in the .gif in my previous post.

You may have a call for user_input() or other UI.inputbox(...) somewhere else in your code…

I would suggest using UI.start_timer rather than Kernel#sleep.

ScreenFlow
I have only copied your code. Nothing more…

I’ll do it. I have to solve before the problem with my inputbox.
I’m sure your option is better than mine
Thanks @DanRathbun

What I’m doing wrong?

for a in 1..5 do
	UI.start_timer(10, false) { puts "hello world"}
end

This script waits 10 seconds and puts “hello world” five times. I suppose to wait 10 seconds between each “hello world”.

You are starting 5 different timers “so to speak” same time. When these timers elapsed each will do its own task: prints out the text.

Here is one snippet what is doing, you supposed to do:

i = 0
@mytimer_id = UI.start_timer(10, true) { 
  i += 1
  puts "hello world"
  UI.stop_timer( @mytimer_id ) if i >= 5
}

UI #start_timer-class_method
UI #stop_timer-class_method

1 Like

Thanks @dezmo

1 Like

I changed my script with UI.start_timer as @DanRathbun said and the inputbox disapear.
The difference between both solutions (I think) is that sleep doesn’t let to finish the proccess and UI.start_timer lets continue the script. (At least on mac).
The only problem I see is that

puts Time.now - fff
sel.clear

are done at the beginning so I had to change and place then after UI.stop_timer
Thanks to both of us. It worked

1 Like