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?
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).
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 …)
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…:
.
.
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.
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
.
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
}
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