• Login
sketchucation logo sketchucation
  • Login
🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

Use of start/commit_operation

Scheduled Pinned Locked Moved Developers' Forum
10 Posts 3 Posters 271 Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    julien.decharentenay
    last edited by 13 Mar 2013, 03:22

    Hi,

    I am trying to use start_operation/commit_operation to implement undo/redo for a plugin. I am unsure if I am going about it the right way. Attached is a sample of the code that I am trying to write. The purpose is to allow the user to specify coordinates that are used in other parts of the plugin - in this example the coordinates are defined when the left button is released. For visual feedback, the selected coordinates are shown as construction point - which are deleted when the tool is unselected.

    From the redo/undo point of the issue: the tool creates the correct undo/redo statement, but SketchUp also creates "Erase" and "Guide" undo/redo when the tool is deactivated/activated.

    Is there any way to let SketchUp know not to create the "Erase" and "Guide" undo/redo? Or should I use another visual feedback mechanism in place of construction point (such as through the draw function or other)?

    Thanks a lot for your help.
    Julien

    Note: the code also has issues if the undo button is press while the tool is active or the construction point is erased. A test e.deleted? in the deactivate would avoid the error message, but it might be best handled with an entity observer.

    module Hibou
    	class TestingOperationCommitTool
    		def initialize()
    			@cPoints = []
    		end # def initialize
    
    		def activate()
    			begin
    				dictionary = getDictionary()
    				if ((nCoordinate = dictionary["nCoordinate"]) != nil)
    					for i in 0...nCoordinate
    						x, y, z = dictionary["Coordinate_#{i.to_s}"].split(",")
    						@cPoints.push(Sketchup.active_model.entities.add_cpoint(Geom;;Point3d.new(x.to_f.m, y.to_f.m, z.to_f.m)))
    					end
    				end
    			rescue Exception => e
    				UI.messagebox("Error; #{e.to_s}.\nBacktrace; #{e.backtrace}")
    			end
    		end # def activate
    
    		def deactivate(view)
    			begin
    				@cPoints.each() { |e|
    					Sketchup.active_model.entities.erase_entities(e)
    				}
    			rescue Exception => e
    				UI.messagebox("Error; #{e.to_s}.\nBacktrace; #{e.backtrace}")
    			end
    		end # def deactivate
    
    		def onLButtonUp(flags, x, y, view)
    			begin
    				model = Sketchup.active_model
    				inputPoint = Sketchup;;InputPoint.new()
    				inputPoint.pick(view, x, y)
    				if (inputPoint.valid?())
    					model.start_operation("Define coordinate")
    					@cPoints.push(Sketchup;;active_model.entities.add_cpoint(p3d = inputPoint.position))
    					dictionary = getDictionary()
    					dictionary["nCoordinate"] = @cPoints.length
    					dictionary["Coordinate_#{(@cPoints.length-1).to_s}"] = [p3d.x.to_m, p3d.y.to_m, p3d.z.to_m].join(",")
    					model.commit_operation
    				end
    
    			rescue Exception => e
    				model.abort_operation
    				UI.messagebox("Error; #{e.to_s}.\nBacktrace; #{e.backtrace}")
    			end
    		end # def onLButtonUp
    
    		private
    		def getDictionary()
    			return Sketchup.active_model.attribute_dictionary("HibouTestingOperation", true)
    		end # def getDictionary
    	end # class TestingOperationCommitTool
    end # module Hibou
    
    if (not file_loaded?(__FILE__))
    	UI.menu("Plugins").add_item("Hibou-Testing") { Sketchup.active_model.tools.push_tool(Hibou;;TestingOperationCommitTool.new()) }
    	file_loaded(__FILE__)
    end
    
    
    1 Reply Last reply Reply Quote 0
    • T Offline
      thomthom
      last edited by 13 Mar 2013, 08:44

      If these guide points are only used for visual illustrations while using the tool then use the View.draw method to draw them to the viewport instead of adding entities. Drawing to the viewport will be faster and cleaner (no extra undo points).

      Thomas Thomassen — SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund

      1 Reply Last reply Reply Quote 0
      • T Offline
        thomthom
        last edited by 13 Mar 2013, 08:48

        On a sidenote - you can make operations transparent, using the third and fourth argument of [ruby]start_operation[ruby]. Avoid the third because it's hard to predict what will happen. The second one let you make the operation you commit transparent. However, since it was added in SU7 and until some of the first releases of SU8 the Undo name overwrote the previous one - not something you want, making the "Edit > Undo xxxx" menu item confusing. However, in one of the recent updates of SU8 they fixed this.

        But again,in the scenario you describe you are better off not doing this - just draw directly to the viewport.

        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • J Offline
          julien.decharentenay
          last edited by 13 Mar 2013, 11:19

          Thanks for the feedback. I think that drawing from the draw method using View.draw is the way forward in my case - and avoid adding entities to the model.

          Beyond the code extract shown, the user is also able to select the input point to change their location (or delete). I used PickHelper.picked_element (or a loop through PickHelper.all_picked) to retrieve the construction point. If I am drawing the point using View.draw, PickHelper.picked_element/all_picked will not pick the point drawn with View.draw and I will have to test using PickHelper.test_point. Is it correct?

          Thanks in advance. Julien

          1 Reply Last reply Reply Quote 0
          • T Offline
            thomthom
            last edited by 13 Mar 2013, 11:23

            Correct.

            Btw, I've tried to make an overview over the various methods of the PickHelper: http://www.thomthom.net/thoughts/2013/01/pickhelper-a-visual-guide/

            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • J Offline
              julien.decharentenay
              last edited by 13 Mar 2013, 11:40

              Thanks a lot for the link and taking the time to writing it. It is very clear and detailed.

              Just a quick question: on the last page (section Segments and Points), the example for testing multiple points faster reads:

              <span class="syntaxdefault">pickhelper</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">init</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">x</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">y&nbsp;</span><span class="syntaxkeyword">)<br />for&nbsp;</span><span class="syntaxdefault">point&nbsp;in&nbsp;points<br />&nbsp;&nbsp;p&nbsp;pickhelper</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">test_point</span><span class="syntaxkeyword">(&nbsp;</span><span class="syntaxdefault">point</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">x</span><span class="syntaxkeyword">,&nbsp;</span><span class="syntaxdefault">y&nbsp;</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">end</span>
              

              Shouldn't the second call reads "test_point( point )" or does it not matter?

              1 Reply Last reply Reply Quote 0
              • T Offline
                thomthom
                last edited by 13 Mar 2013, 11:44

                That's true! I've made a typo there. Thanks for catching that. I'll correct it.

                Thomas Thomassen — SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

                1 Reply Last reply Reply Quote 0
                • D Offline
                  Dan Rathbun
                  last edited by 14 Mar 2013, 01:29

                  Another thing:

                  DONT:
                  Sketchup.active_model.entities.erase_entities(e)

                  DO:
                  Sketchup.active_model.**active_entities**.erase_entities(e)

                  WHY?
                  If the user changes the editing context, and is within a group or component, the first call will cause SketchUp to BugSplat!

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • D Offline
                    Dan Rathbun
                    last edited by 14 Mar 2013, 02:01

                    FYI: [ Code ] wrapping operations

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • J Offline
                      julien.decharentenay
                      last edited by 15 Mar 2013, 11:21

                      Dan and thomthom, thanks for your time and answer.

                      1 Reply Last reply Reply Quote 0
                      • 1 / 1
                      1 / 1
                      • First post
                        5/10
                        Last post
                      Buy SketchPlus
                      Buy SUbD
                      Buy WrapR
                      Buy eBook
                      Buy Modelur
                      Buy Vertex Tools
                      Buy SketchCuisine
                      Buy FormFonts

                      Advertisement