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

    Making a SketchUp tool - incorporating the mouse & keyboard

    Scheduled Pinned Locked Moved Developers' Forum
    55 Posts 6 Posters 1.8k Views 6 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.
    • Chris FullmerC Offline
      Chris Fullmer
      last edited by

      This is the very bare bones beginnings of a script that makes a Tool class. The importance of this is that you have to make a tool class to implement the mouse, keyboard, cursor icons, and more. See the Tool class in the API for different methods that you can dd to your tool class. What took me a while to realize is that everything listed on that Tools page is actually a method that you have to add to your tool. Hopefully the example will make it more clear.

      I've ended up making two examples. One is very simple. The other is slightly more robust. Copy and paste it into the Web Console and execute it there to see it in action. Here's the simple version. Run it and it will start a new tool, which changes the cursor to a default white cursor in SU. This tool only has an onMouseMove method enabled. Open the webconsole to see the output when you move the mouse after the tool is instantiated.

      class SUC_Test_tool
      
       def onMouseMove(flags, x, y, view)
         puts "x = " + x.to_s + ", y = " + y.to_s + ", Flags = " + flags.to_s
       end
      
      end
      
      Sketchup.active_model.select_tool SUC_Test_tool.new
      

      And this is a slightly more complex version. It has an onMouseMove, onReturn (when you hit enter), onMouseLeave whent he mouse goes off the screen, and some more. Check it out, modify it, remove what you don't want, add methods that you want to play with.

      class SUC_Test_tool
      
      #This method gets run by default when the tool is instantiated (started)
       def activate
        puts "The tool is activated"
        start_method
       end
       
       def start_method
        puts "This is my start method.  It is my own method,"
        puts "not a pre-defined one from the API."
       end
      
       def onMouseMove(flags, x, y, view)
         puts "x = " + x.to_s + ", y = " + y.to_s + ", Flags = " + flags.to_s
       end
      
       def onLButtonUp(flags, x, y, view)
         puts "onRButtonDown; flags = " + flags.to_s
         puts "                 x = " + x.to_s
         puts "                 y = " + y.to_s
         puts "              view = " + view.to_s
       end
      
       def onMouseLeave(view)
         puts "Your mouse left the screen"
       end
      
       def onReturn(view)
         puts "You hit enter"
       end
      
      end
      
      Sketchup.active_model.select_tool SUC_Test_tool.new
      

      I hope this is enough to get you started. Questions?

      Lately you've been tan, suspicious for the winter.
      All my Plugins I've written

      1 Reply Last reply Reply Quote 0
      • B Offline
        BTM
        last edited by

        Ah, thanks; now all I ned to know is what to do with:
        def draw(view)

        1 Reply Last reply Reply Quote 0
        • Chris FullmerC Offline
          Chris Fullmer
          last edited by

          what are you trying to do? Make a "rubber band" from where you first click, to the mouse cursor?

          Lately you've been tan, suspicious for the winter.
          All my Plugins I've written

          1 Reply Last reply Reply Quote 0
          • B Offline
            BTM
            last edited by

            ...Let's just say I was going to try and make a move tool, or a tool to draw a line. Is def draw(view) necessary? What exactly does it do? If it's necessary/ not, where should I put what?

            1 Reply Last reply Reply Quote 0
            • AdamBA Offline
              AdamB
              last edited by

              A good little learning exercise for the Tool protocol, is to see what messages SU tries to fire at it.

              Add this to your class to log whenever SU queries your Tool instance to check its capabilities. You'll be surprised how much querying goes on!

              
              	def respond_to?(msg)
              		result = super
              		puts "unhandled respond_to(#{msg})" unless result
              		result
              	end
              
              

              Developer of LightUp Click for website

              1 Reply Last reply Reply Quote 0
              • Chris FullmerC Offline
                Chris Fullmer
                last edited by

                Oooh!, that looks great! I'll try that when I get back on my working computer.

                How do you guys find this stuff? I guess you just pick these tricks up over time. Thanks Adam!

                Chris

                Lately you've been tan, suspicious for the winter.
                All my Plugins I've written

                1 Reply Last reply Reply Quote 0
                • B Offline
                  BTM
                  last edited by

                  ... I still can't figure out how to really implement mouse control yet, and haven't been doing much in terms of learning any SketchUp API for a while.

                  The first 'scrip' I'm trying to write would be presumably simple; but that's just a guess. I've decided I would try to make a "pinch move" as a first ruby script extension, because I think it could end up as something useful for others (possibly).

                  How I think I could make it work:
                  select a point, and move it ( x, y, z). This distance is called 'V'. The script would get all endpoint entities, and put them into an array. It would then check to see if the distance between them and the selected point is greater than __. If not, then it would put the point into another array. It would take the points in this array and find the distance between the point and the selected point. This distance is called 'D'. It will then move them in ( V with an exponent of -D) xV . This creates a "pinch move".
                  Bottom values are distance away from first point, and y axis represents the movement of the point of that distance. This graph is by no means accurate, but gives a general Idea.
                  ... Before I even think of starting: How hard do you think a script like this would be to make; and if it's not that hard, how hard do you think it would be to implement mouse interaction (probably optional)?

                  1 Reply Last reply Reply Quote 0
                  • Chris FullmerC Offline
                    Chris Fullmer
                    last edited by

                    Thats a good sounding script. I think it will be hard to write, but its do-able. I think you might have to simplify some things at first until you get it working. Then make it more complex over time. Here is how I could see it working easiest.

                    I'm envisioning this on a terrain (for now). So a large flat field full of nice triangles.
                    Place a construction point somewhere. Then move it to the extreme "pinch" position. Then select it. So far none of this is actually your script yet. But you might need to provide a way to make and place construction points.
                    Now select the construction point and activate your tool. A box pops up asking for the pinch radius (I know pop up boxes are lame, but they are the easiest to implement). Enter 50' or something. Hit enter and your mouse tool is active and you have to click on the vertex that will act as the "center" of the pinch. That vertex will move to the position of the construction point. all other points within the 50' radius will move in that same direction, varying distances, based on their proximity to the selected vertex.

                    Does that workflow make sense?

                    Then in time you could implement a better looking UI, and get the VCB included (I think thats a pain). Perhaps have visualization geometry drawn in, and use the mouse to move the vertex using all inferencing, instead of having to use the re-set construction point.

                    Those are my thoughts. I'm sure there's plenty of other ways to do it, but that makes sense to me, trying to imagine what parts of the process will give you trouble.

                    Chris

                    Lately you've been tan, suspicious for the winter.
                    All my Plugins I've written

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      @adamb said:

                      A good little learning exercise for the Tool protocol, is to see what messages SU tries to fire at it.

                      Add this to your class to log whenever SU queries your Tool instance to check its capabilities. You'll be surprised how much querying goes on!

                      
                      > 	def respond_to?(msg)
                      > 		result = super
                      > 		puts "unhandled respond_to(#{msg})" unless result
                      > 		result
                      > 	end
                      > 
                      

                      Undocumented feature?

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

                      1 Reply Last reply Reply Quote 0
                      • B Offline
                        BTM
                        last edited by

                        Other than finding out that my math is completely flawed (the larger the number, the smaller the pinch. I have to fix that...), I have also mannaged to make a script that will draw a line starting at [0, 0, 0,], and going to wherever you input into the control box. Now, how would I change it so what's input into the box is in meters?

                        ` model = Sketchup.active_model
                        entities = model.entities
                        selection = model.selection

                        prompts = ["X", "Y", "Z"]
                        defaults = ["0", "0", "0"]
                        list = ["", "", ""]
                        results = UI.inputbox prompts, defaults, list, "Input X, Y, Z."
                        pt1= Geom::Point3d.new results.to_i
                        pt2= [0, 0, 0]
                        edges = entities.add_edges pt1, pt2`

                        1 Reply Last reply Reply Quote 0
                        • Chris FullmerC Offline
                          Chris Fullmer
                          last edited by

                          SU will work in the default unit that the user has set. So you might be best not trying to force it into meters.

                          And your defaults:

                          defaults = ["0", "0", "0"]

                          Since you have the zeros in quotes, it will treat the user input as a string. So you would need to convert each answer to a float. OR if you remove the quotes and use 0.0, 0,0, 0,0 then it will treat whatever the user inputs as a float, which is what you want to use (or an integer) to make a point3d object.

                          Then what you posted works like a charm.

                          Lately you've been tan, suspicious for the winter.
                          All my Plugins I've written

                          1 Reply Last reply Reply Quote 0
                          • B Offline
                            BTM
                            last edited by

                            ... Yeah, that would help; it still works as it is though, because I switch it using .to_i later on.

                            ...Also, it seems to make a value of 1 to be 0.0254m, and my default is in meters. This value of 0.0254m also seems to be the value at which sketchyphysics joints like sliders use (if I type in 1 in the joint max, it's max is 0.0254m).

                            1 Reply Last reply Reply Quote 0
                            • Chris FullmerC Offline
                              Chris Fullmer
                              last edited by

                              It doesn't work for me the way its posted. I got an error teling me that it couldn't convert an array ( results) to an integer. For me I needed to convert each element of the array separately.

                              Unit conversions are still important. Here's the trick. SU works in the users default unit. So if you are in meters and type 1 into the box, its already in meters. Or you could over-ride it and enter 1cm into the box. But now its a string. Convert it to a length with .to_l Here are som examples to run one at a time:

                              distance = "2000cm".to_l.to_m
                              distance = "50km".to_l.to_m
                              distance = "2000'".to_l.to_m

                              the .to_l converts whatever it is given into the default base unit. Then .to_m converts whatever it is given to meters. Does that make sense? Play with those and check out the entire Numeric Class:

                              http://code.google.com/apis/sketchup/docs/ourdoc/numeric.html

                              Hope that helps with converting,

                              Chris

                              Lately you've been tan, suspicious for the winter.
                              All my Plugins I've written

                              1 Reply Last reply Reply Quote 0
                              • Chris FullmerC Offline
                                Chris Fullmer
                                last edited by

                                Hmm, I see, I think that I do have something wrong about the base units. I suppose SU always works in inches and you have to always convert back to .to_l to get to the default base unit? I've clearly confused myself.

                                Lately you've been tan, suspicious for the winter.
                                All my Plugins I've written

                                1 Reply Last reply Reply Quote 0
                                • B Offline
                                  BTM
                                  last edited by

                                  2 things;

                                  first; really? It didn't work for you at all? 😕 Ah well, I'm mostly playing around, and with it written out like you said, it works too.

                                  second; I don't think it's in the user's default length automatically, because as I said, for me it works as 0.0254m, or 1 inch. My default is set to meters.

                                  UPDATE: I wrote that before You finnished writing your last post. Sorry 😆

                                  1 Reply Last reply Reply Quote 0
                                  • Chris FullmerC Offline
                                    Chris Fullmer
                                    last edited by

                                    Yup, if I run it in the webconsole just as you have it written, I get this error:

                                    (eval):9:in ‘initialize’: undefined method ‘to_i’ for ["1", "1", "1"]:Array

                                    It doesn't like converting the array to an integer. It wants each element of the array to be converted separately on my machine. SU7

                                    Lately you've been tan, suspicious for the winter.
                                    All my Plugins I've written

                                    1 Reply Last reply Reply Quote 0
                                    • B Offline
                                      BTM
                                      last edited by

                                      ` model= Sketchup.active_model
                                      @ent= model.entities

                                      prompts = ["X", "Y", "Z"]
                                      defaults = [ 0.0.to_l, 0.0.to_l, 0.0.to_l]
                                      list = ["", "", ""]
                                      results = UI.inputbox prompts, defaults, list, "Input X, Y, Z."
                                      pt1= Geom::Point3d.new results
                                      pt2= [ 0, 0, 0]
                                      line = @ent.add_edges pt1, pt2`
                                      😉

                                      1 Reply Last reply Reply Quote 0
                                      • B Offline
                                        BTM
                                        last edited by

                                        That's strange. .to_i worked fine on my mac. 😕

                                        1 Reply Last reply Reply Quote 0
                                        • Chris FullmerC Offline
                                          Chris Fullmer
                                          last edited by

                                          Hey!!!! Great job. I was really confused how on earth to get the inputbox to work in the default units! That did the trick though, setting it to 0.0.to_l. I really couldn't figure that out.

                                          So there you have it, 0.0.to_l makes the inputbox work in the default units. Thanks for posting the solution before I went crazy!

                                          Chris

                                          Lately you've been tan, suspicious for the winter.
                                          All my Plugins I've written

                                          1 Reply Last reply Reply Quote 0
                                          • B Offline
                                            BTM
                                            last edited by

                                            @chris fullmer said:

                                            you might need to provide a way to make and place construction points.

                                            ` model = Sketchup.active_model
                                            @ent = model.entities

                                            prompts = ["X", "Y", "Z"]
                                            defaults = [ 0.0.to_l, 0.0.to_l, 0.0.to_l]
                                            list = ["", "", ""]
                                            results = UI.inputbox prompts, defaults, list, "Input X, Y, Z."
                                            pt1= Geom::Point3d.new results
                                            @ent.add_cpoint pt1`
                                            😄

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

                                            Advertisement