sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Save coordinates in an array

    Scheduled Pinned Locked Moved Developers' Forum
    17 Posts 3 Posters 647 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.
    • M Offline
      michaelazer
      last edited by

      Hi TIG, I really can't thank you enough, but probably I have major issues in understanding how the program is performing.
      I got the syntax onLButtonDown(flag,x,y,view) from the API, which I don't get, by the way.

      Why am I entering an X and a Y, if the idea behind the function is get the X and Y?

      Also, I don't understand what the flag is?

      And lastly, why do I need the view? do I get relative coordinates? so if I move the view I may get a duplicate point?
      Sorry TIG for the hassle.

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        All of the extra 'Tool' methods are automatically added by Sketchup to your code IF you add the special tool methods to your class and launch it as a 'tool'...
        Read the Tool API https://developers.google.com/sketchup/docs/ourdoc/tool
        These methods expect to receive various arguments like (flag,x,y,view) [this varies with the method].
        These are passed automatically by Sketchup - YOU do not do anything.
        The method:
        ` def onLButtonDown(flag,x,y,view)

        do some stuff here!

        endis called if the user presses the left mouse-button - you don't need to worry about how it gets the arguments passed to it - BUT you can use them in your code... Code like... ip1 = view.inputpoint(x,y)
        @pt = ip1.position which make use of the view's points clicked on screen [x/y] - with the view's ' .inputpoint' - there are several view methods you can call - see the API [https://developers.google.com/sketchup/docs/ourdoc/view](https://developers.google.com/sketchup/docs/ourdoc/view) So from that you can get the Point3d etc using an inputpoint method like ' .position`' ...

        TIG

        1 Reply Last reply Reply Quote 0
        • M Offline
          michaelazer
          last edited by

          I think I got it πŸ˜„ thank you so much TIG.
          I really appreciate your help.

          1 Reply Last reply Reply Quote 0
          • Dan RathbunD Offline
            Dan Rathbun
            last edited by

            @michaelazer said:

            I got the syntax onLButtonDown(flag,x,y,view) from the API, which I don't get, by the way.
            ... Why am I entering an X and a Y, ...

            Let me explain it specifically (and technically.)

            All the methods listed in the API dictionary, for the Tool class, are a special kind of method, termed a "callback".

            A Tool class object is an event-driven object, in this case, driven by what the user does.
            When the user starts the tool, (by clicking a menu item or a toolbar button,) the SketchUp application "calls back" into the tool instance, specifically calling the activate() callback.

            YOU are expected to overrride (ie, redefine,) this callback in YOUR custom Tool class. (Pretending here that the API Tool class actually does or hopefully will have in the future, a true superclass; .. because it really should have one. Anyway... it helps to understand basic Ruby subclassing. Most times in Ruby your custom classes will have a superclass that they inherit methods from.)

            So whatever you define in the activate() callback runs. You are free to define normal instance methods, within your class, (often coders write a reset() method that gets called from the onCancel callback, but you can also call it from within activate() and initialize(), and/or whichever other method or callback you need to.)

            As TIG said, arguments for callbacks, are passed by the SketchUp application engine.

            In event-driven code like Tool class instances, you never know which callback will get called in what order. It all depends on what the user clicks on, or what key they press. So the code does not run sequentially.
            This is why you must store references in instance variables, that ALL of the instance methods and callbacks can access. It is common to reset (or init,) these variables in a reset() method.

            Now Ruby itself, also has callback methods that are called automatically. The most important is the private instance method initialize(), which is automatically called by the public class constructor method new(), after it has created the new instance object. The new() method passes all of the arguments IT got, into the initialize() callback, of the newly created instance.
            !! Since this is Ruby Core stuff, you will not see it listed in the API dictionary. Please read the "guide" I wrote, click link in my signature tagline; follow the steps, and get the standard Ruby reference CHM and other resources, cheatsheets etc.

            But most of all.. watch out! Your about to become addicted to Ruby. πŸ˜›

            P.S.: Have you read the "Plugins/Examples/linetool.rb" ??

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • Dan RathbunD Offline
              Dan Rathbun
              last edited by

              @tig said:

              Incidentally don't define the mod etc outside of the class, if you need them, define them inside the activate() and use @mod so it's accessible in all def methods...

              This is important, not only for access from all instance methods,...

              .. but because SketchUp can (via user control,) close, open, and on the Mac, switch to another model. Each model maintains it's OWN toolstack. When your tool instance gets activated, and the activate() callback gets called, within it, you need to set these model specific references to the model ( @mod), it's selection or any of this model's collection objects THIS tool instance will access.

              SO.. this is also why TIG suggested creating a new tool instance, each time the user selects your tool from the menu or a toolbar. (Even though this is considered bad form in Ruby, ... usually best practice is to create a var to hold a reference to the instance, while it's in use, and then release it, by @var = nil, so Garbage Collection can dispose of the now unneeded object. BUT... it is easier, and simplier [makes more readable code, etc.] and most of all less error-prone in SketchUp embedded Ruby, if you just let each model's toolstack hold the reference to it's own instance of your tool. When the tool is no longer in use, the toolstack will no longer reference it, and Garbage Collection will clean it up automatically.)

              To understand why this is important... think about a user on the Mac, with 2 models open.

              He is in "model one", activates your tool (which creates "instance 1" of your tool, referenced by "model one's" Tools collection (aka toolstack,)
              He clicks a point and begins drawing a line...

              But then he remembers a line he forgot to draw in "model two", and decides to do that first, before he forgets again...
              So he switches to the document window for "model two" (which causes a change in the active model,) and he then activates your line tool, for "model two"...

              At this point AN instance of your tool is the active tool in both model's toolstack, but "model two's" toolstack should reference "instance two" of your tool.

              It is important that each model's toolstack, have it's own instance of your tool. Because the tool state (tool step, whatever you call it,) may differ between each model. At this point in time model two's tools state would be 0, as no starting point has yet been picked, but the tool instance in "model one" is at tool state 1 as the user has already picked the start point.

              Your Tool class should allow the user to draw the line he forgot in "model two", then switch back to "model one" where it's OWN instance of your tool is still the active tool, and I believe the SketchUp engine will automatically call the resume() callback, which gives you the opportunity to redraw the view. Anyway the user should be able to continue where he was, with the first point already chosen.

              All this will be automatic, if you use TIG's suggestion in your menu item (or toolbar,) command blocks:
              Sketchup.active_model.select_tool(Mazer::LineTool.new)
              and have the references to the model, and it's collections, as instance vars created in the initialize() method.

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • M Offline
                michaelazer
                last edited by

                Thanks Dan, I think I actually got addicted to Ruby πŸ˜„
                If I'm not asking for too much, I have a request and a question.
                Request: I theoretically understood both your comments, but can you write me a small piece of code or point me to a link to give me a practical example of how to use the resume(), activate(),new(), and initialize()? I got confused on where to put the code that I want to run when I click the Left Mouse button.
                Question: I don't understand what the @mod is. Is this a variable that Sketchup understands alone or do I need to declare it?
                Sorry, but after I thought I understood, I couldn't apply what I understood.
                Thanks a lot

                1 Reply Last reply Reply Quote 0
                • Dan RathbunD Offline
                  Dan Rathbun
                  last edited by

                  @michaelazer said:

                  I don't understand what the @mod is.

                  It is an instance variable that YOU use within your custom class definition.

                  Ruby does not make you define @name instance variables, before use.
                  Usually they are initialized to some value, within a class' initialize() method.
                  But a SU Tool class does not (usually,) do anything when it is initialized, only after it becomes active, and the activate() callback gets called. So, it's kind of take your pick.

                  But it DOES make you define @@name module/class variables and NAME constants before they are accessed.

                  Using the word 'declare' is un-ruby, because Ruby does not really have variables, they are actually object references. (But somebody decided they would scare off old BASIC programmers if it got out that Ruby had no variables.) Anyway, do not worry about this for now, except to know that Ruby variables/references can point at any class of object when initialized, and at anytime later, can be re-assigned to point at an object of a completely different, unrelated class.
                  Realize that = is the reference assignment operator, not equals (which is == in Ruby.)

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • Dan RathbunD Offline
                    Dan Rathbun
                    last edited by

                    Links... Others and I have written and sampled our fingers raw.

                    Check the [ Code Snippets ] indexes. It is one of the "Sticky" topics that is always at the top of the first forum page.

                    Then use the forum search to search on "Tool" or "Tool +activate +resume" etc.

                    About new(), don't worry about, because at this stage your not ready to override a class constructor. And you do not need to. Only know that after it does it's creation work, it calls initialize() in the newly created instance, passing along any arguments it itself was passed.

                    So if you wish to pass something into your instance, via new(), then define initialize() with arguments in it's parameter list.

                    class Bear
                      def initialize(myname,father)
                        @myname = myname
                        @father = father
                      end
                    end
                    
                    booboo = Bear.new('BooBoo','YogiBear')
                    

                    And in case you are wondering, method arguments ARE local variables, whose scope is local to the method.
                    But these 'locals' will "go out of scope" when the method ends, and the objects they point at, will become unreferenced.
                    So.. we create instance variable references (whose scope is the entire instance,) that are assigned to point at those same objects; .. and after the method ends, these objects are still referenced, and will not be Garbage Collected.(ie, GC'd, as we say.)

                    So, this:
                    @myname = myname
                    means:
                    The reference @myname (shall be created if not,) and assigned to point at the object, that myname is pointing at.

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • M Offline
                      michaelazer
                      last edited by

                      Really, Dan, I can't thank you enough. I think I now have my feet on the right path.
                      I believe I will be a regular here on this forum. Again, many thanks to you and TIG.

                      1 Reply Last reply Reply Quote 0
                      • M Offline
                        michaelazer
                        last edited by

                        After I got your comments I worked on my program, I wrote the following code:

                        class MyTool
                        	
                        		# Initialization
                        	def activate
                        		@input = Sketchup;;InputPoint.new
                        		@pts[]
                        	end
                        
                        	# Respond to left click
                        	def onLButtonDown flags, x, y, view
                        		@input.pick view, x, y
                        		sketchup;;set_status_text "Left click ", SB_VCB_LABEL
                        		pos = @input.position
                        		@pts << pos
                        		str = "%.2f, %.2f,%.2f" % [pos.x, pos.y, pos.z]
                        		Sketchup;;set_status_text str, SB_VCB_VALUE
                        	end
                        	
                        end
                        
                        # Create Command object
                        simple_cmd = UI;;Command.new("Click") {
                        	Sketchup.active_model.select_tool MyTool.new
                        }
                        	
                        #Add command to tools menu
                        tool_menu = UI.menu "Tools"
                        tool_menu.add_separator
                        tool_menu.add_item simple_cmd	
                        

                        But still something is not right! I'm getting the following error:

                        @unknownuser said:

                        Error: #<NoMethodError: undefined method <<' for nil:NilClass> C:/Program Files/Google/Google SketchUp 8/Plugins/click.rb:14:in onLButtonDown'
                        C:/Program Files/Google/Google SketchUp 8/Plugins/click.rb:14

                        Can you please help me out? Thanks!

                        1 Reply Last reply Reply Quote 0
                        • Dan RathbunD Offline
                          Dan Rathbun
                          last edited by

                          It's just a couple of typos.

                          Line 6 should be:
                          @pts = []
                          so it is defined as an empty Array.

                          Line 12 needs to spec the Sketchup module with a captial first letter. (All module and class Identifiers in Ruby are constants. Constants begin with a capital letter.)

                          P.S.: Constants values are traditionally ALLCAPS. πŸ€“

                          And... please learn to wrap ALL your code with a toplevel module with your unique name, before you release anything.

                          I'm not here much anymore.

                          1 Reply Last reply Reply Quote 0
                          • M Offline
                            michaelazer
                            last edited by

                            Thank you so much, Dan. Your tips solved the problem.
                            Now, I have the program running, but I don't get the correct coordinates.
                            I was expecting to get some positive and some negative, according to where I am from the axes.
                            I clicked the 4 corners of the screen and I got the following, which doesn't look right:

                            @unknownuser said:

                            x: 46 y: 48 z: 48
                            x: 53 y: 52 z: 46
                            x: 54 y: 57 z: 46
                            x: 52 y: 46 z: 56

                            1 Reply Last reply Reply Quote 0
                            • M Offline
                              michaelazer
                              last edited by

                              Thank you so much, Dan. Your tips solved the problem.
                              Now, I have the program running, but I don't get the correct coordinates.
                              I was expecting to get some positive and some negative, according to where I am from the axes.
                              I clicked the 4 corners of the screen and I got the following, which doesn't look right:

                              @unknownuser said:

                              x: 46 y: 48 z: 48
                              x: 53 y: 52 z: 46
                              x: 54 y: 57 z: 46
                              x: 52 y: 46 z: 56
                              
                              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