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 3 Watching
    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

      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
      • thomthomT Offline
        thomthom
        last edited by

        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
        • thomthomT Offline
          thomthom
          last edited by

          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

            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
            • thomthomT Offline
              thomthom
              last edited by

              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

                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
                • thomthomT Offline
                  thomthom
                  last edited by

                  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
                  • Dan RathbunD Offline
                    Dan Rathbun
                    last edited by

                    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
                    • Dan RathbunD Offline
                      Dan Rathbun
                      last edited by

                      FYI: [ Code ] wrapping operations

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • J Offline
                        julien.decharentenay
                        last edited by

                        Dan and thomthom, thanks for your time and answer.

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

                        Advertisement