View refresh problem

My plugin operation time is long and maybe boring for users so I wish to show steps of operation as an animation. Following is a sample code for it.

grp = Sketchup.active_model.active_entities.add_group
for i in 0...10
  cp = [0, i, i]
  cir = grp.entities.add_circle cp, [0, 0, 1], (1)
  face1 = grp.entities.add_face(cir)
  face1.reverse! if face1.normal == [0, 0, -1]
  Sketchup.active_model.active_view.refresh
  sleep 0.1
#  Sketchup.active_model.active_view.invalidate
end

As you can check view.invalidate doesn’t work and in this case, I have to use view.refresh.
API has following explanation about refresh.
Note:

This method might impact performance and if used incorrectly cause instability or crashes. Don’t use this unless you have verified that you cannot use #invalidate instead.

When I used refresh in my plugin caused crashes. Following you can see code and crashes.
code:

        p @pt
        Sketchup.active_model.active_view.refresh
        p "----"
        p @pt

result:
[Point3d(47.2441, 0, 5.90551), [48.818897637795274, 11.811023622047244, 43.30708661417323], [50.39370078740158, 23.62204724409449, 49.21259842519685], [51.96850393700788, 35.43307086614173, 55.118110236220474], [53.54330708661418, 47.24409448818898, 61.023622047244096], [53.54330708661418, 47.24409448818898, 5.905511811023622]]
“----”
[Point3d(47.2441, 0, 5.90551), [47.24409448818898, 0.0, 5.905511811023622], [48.818897637795274, 11.811023622047244, 5.905511811023622], [50.39370078740158, 23.62204724409449, 5.905511811023622], [51.96850393700788, 35.43307086614173, 5.905511811023622], [53.54330708661418, 47.24409448818898, 5.905511811023622]]

As you can see my data changed after a refresh.
How can I solve my problem. Your help will be highly appreciated.

(I moved this topic to right category)
Something like this? :

def create_circle( cp )
  cir = @grp.entities.add_circle cp, [0, 0, 1], (1)
  face1 = @grp.entities.add_face(cir)
  face1.reverse! if face1.normal == [0, 0, -1]
end

def add_geometry
  @grp = Sketchup.active_model.active_entities.add_group
  i = -1 
  mytimer = UI.start_timer(0.1, true) {
    i += 1
    cp = [0, i, i]
    create_circle( cp )
    Sketchup.active_model.active_view.invalidate
    UI.stop_timer(mytimer) if i > 10
  }
end
add_geometry

It seems “UI.stop_timer” doesn’t work.

I just copy-pasted my code above to Ruby Console and this is the result:

“i” was 184 and increasing.

Try to paste directly into Ruby Console. NOT to Ruby Code Editor!!

The problem is caused by Ruby Code Editor.

If you paste the code to Ruby Code Editor without the last line, then run it.
then type to Ruby Console. : add_geometry
it will work.

BTW: As far as I remember Dan already warned you about the restriction and worries about Ruby Code Editor…

Sorry, I don’t have access to EWH!!! Let me check Ruby Console later…

I run it in consul and it works!!! I didn’t know we can run code in that consul. What is the ruby code editor problem? For a long time, I tried to used “UI.start_timer” but the same problem.

I changed my plugin to “rb” format and add it to SU extensions but unfortunately, the same problem happens!!!

Try this:
Dezmo_test_ani.rbz (1.6 KB)

Code
#main.rb
module Dezmo_test_ani
  extend self
  @@loaded = false unless defined?(@@loaded)

  def create_circle( cp )
    cir = @grp.entities.add_circle cp, [0, 0, 1], (1)
    face1 = @grp.entities.add_face(cir)
    face1.reverse! if face1.normal == [0, 0, -1]
  end

  def add_geometry
    @grp = Sketchup.active_model.active_entities.add_group
    i = -1
    mytimer = UI.start_timer(0.1, true) {
      i += 1
      cp = [0, i, i]
      create_circle( cp )
      Sketchup.active_model.active_view.invalidate
      UI.stop_timer(mytimer) if i > 9
    }
  end

  def run_plugin
    Sketchup.active_model.start_operation('Dezmo test ani', false)
    add_geometry
    mtimer = UI.start_timer(2, false) {Sketchup.active_model.commit_operation}
  end
  
  unless @@loaded
    cmd1 = UI::Command.new("Dezmo Test Animation"){ run_plugin }
    menu = UI.menu("Plugins").add_item(cmd1)
    @@loaded = true
  end

end # module
#Dezmo_test_ani.rb
module Dezmo_test_ani

  extension_name = 'Dezmo test_ani'
  EXT_SW = SketchupExtension.new(extension_name, 'Dezmo_test_ani/main.rb')

  EXT_SW.description = 'Dezmo test_ani'
  EXT_SW.version = 'Beta1 2021_0212_xxxx'
  EXT_SW.creator = 'Dezmo (dezmo at freemail dot hu)'
  EXT_SW.copyright = '2021, Dezmo'
  # Register the extension with Sketchup.
  Sketchup.register_extension EXT_SW, true
  
end

Dear Dezmo,
In following codes, when I used for loop, it works well in Code Editor and Console and rbz. But When I use the timer loop it cannot work in all. Also it shows endless error loop same as problem that I had in Ruby Code Editor.

        #i = 0
        #mytimer = UI.start_timer(0, true) {
        for i in 0...@rn
          cp = [@pt[i].x, @pt[i].y, @pt[0].z + i * @rr]
          cir = grp1.entities.add_circle cp, [0, 0, 1], (2.5.cm)
          face1 = grp1.entities.add_face(cir)
          face1.reverse! if face1.normal == [0, 0, -1]
          face1.pushpull @rh
          cp = [@pt[i].x, @pt[i].y, @pt[0].z + i * @rr + @rh]
          @pt[i].z = @pt[0].z + i * @rr + @rh if i != 0
          cir = grp1.entities.add_circle cp, [0, 0, 1], (4.cm)
          face1 = grp1.entities.add_face(cir)
          cir = grp1.entities.add_circle cp, [1, 0, 0], (4.cm)
          face1.followme cir
          #i += 1
          #Sketchup.active_model.active_view.invalidate
          #UI.stop_timer(mytimer) if i > @rn
        #}
        end

The answer can be find by in my previous post.
When you call the add geometries method from other methods which is contain start_operation - commit_operation you have wait for the timer loop to end. Therefore you should put the commit_operation into other timer (with repeat = false parameter) which is longer than drawing the rail.

Beside that:

makes no sense here, you shout put non zero value for the timer

… for example something like :

      def onLButtonDown(flags, x, y, view)
        Sketchup.active_model.start_operation "onLButtonDown"
.
.

        draw_rail if @st == @rn
        timer_time = (@rn * 0.1) + 1
        mtimer = UI.start_timer(timer_time, false) {Sketchup.active_model.commit_operation}
      end

So actually the “waiting time” (timer_time ) should be more then the loop time during creating the geometry plus some safety time. (I assume 0.1 sec is the timer loop time in the circles creation loop)

BTW. I think better to change the “onLButtonDown” for the operation to more talkative words like “Drawing rail”.
You know it will be shown in the UI when the user hover the mouse over the undo icon.

Following codes work well.

  @grp = Sketchup.active_model.active_entities.add_group
  i = 0
  mytimer = UI.start_timer(0, true) {
    cp = [0, i, i]
    cir = @grp.entities.add_circle cp, [0, 0, 1], (1)
    face1 = @grp.entities.add_face(cir)
    face1.reverse! if face1.normal == [0, 0, -1]
    Sketchup.active_model.active_view.invalidate
    i += 1
    UI.stop_timer(mytimer) if i > 10
  }

You can make a longer loop and set timer time to zero but it works. Before I used timer and ruby code editor works well but now cannot!!! Before I used to refresh and works well but now cannot!!! Maybe I have another problem with my own system.

Hm. :thinking: Then, I guess there is a default minimum time “build in” to this method…

Probably there is it’s own start_operation - commit_operation inside the Ruby Code editor. Therefore the timer loop will affect it.

It seams if the operation still running when you call commit_operation make this problem. So if you wait till the timer loop ends before put the commit_operation , you should be okay…:wink:

…but not with Ruby code editor :frowning:

This snip of code will demonstrate your problem

  @grp = Sketchup.active_model.active_entities.add_group

  mytimer = UI.start_timer(0, true) {
   puts @grp.deleted?
   UI.stop_timer(mytimer) 
  }
 

Thank you for your attention. Answer is “true” when I use “Ruby Code Editor” and answer is “false” when I use Ruby Console!!! Can you tell me what is my problem?
Following codes work well in Ruby Code Editor…

  i = 0
  mytimer = UI.start_timer(0, true) {
    @grp = Sketchup.active_model.active_entities.add_group if i == 0
    cp = [0, i, i]
    cir = @grp.entities.add_circle cp, [0, 0, 1], (1)
    face1 = @grp.entities.add_face(cir)
    face1.reverse! if face1.normal == [0, 0, -1]
    Sketchup.active_model.active_view.invalidate
    i += 1
    UI.stop_timer(mytimer) if i > 10
  }

SketchUp is probably deleting the group because there is nothing it in (from it’s point of view.)

ALWAYS add a temporary cpoint at the origin of the group immediately after creating a new group. You can delete the cpoint after the geometry has been successfully created.

Unfortunately, my problem is bigger than it. timer and refresh both crash my data. Please see my following data and code.
Code:

        p @pt
        mytimer = UI.start_timer(0, false) {
        p "------"
        p @pt        

Data:
[Point3d(48.1948, 0.254743, 5.90551), [49.53193343476063, 12.002080988018594, 5.905511811023622], [50.86905798537848, 23.74941882140872, 5.905511811023622], [52.206182535996334, 35.49675665479885, 5.905511811023622], [53.54330708661418, 47.24409448818898, 5.905511811023622], [53.54330708661418, 47.24409448818898, 5.905511811023622]]
“------”

As you can see @pt deleted. Also, I check it with SU older version the same problem happens.

It is really difucult to guess what is the problem. Personally I do not understand what "crash my data. " means?

I don’t know too: what should be the @pt originally? In the printout I see it is a Array with a mixed type of objects in it. The first element is Point3D, all the other are Arrays with coordinates. Why do you mix it?

At last but not least, your code contains a syntax error. The 2nd line does not contain end-of-input, expecting ‘}’, and there is nothing to do in the timer method.

As far as I see you does not take care about the syntax in the forum post, that could be one case in your code too.