sketchucation logo sketchucation
    • Login
    1. Home
    2. MSP_Greg
    3. Posts
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info
    M
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 2
    • Posts 46
    • Groups 1

    Posts

    Recent Best Controversial
    • RE: SVG Toolbar Icons - Gradients Missing

      @placidfury said:

      or manually edit the SVG code so SketchUp will read it properly

      Well, SVG is XML and Nokogiri would certainly be up to the task. Wouldn't even need SketchUp to do the processing...

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Socket.so sketchup 8 and 13

      For windows, the file at https://dl.bintray.com/oneclick/rubyinstaller/ruby-1.8.7-p370-i386-mingw32.7z
      contains a socket so file.

      I'd suggest you thoroughly test it. I added it to both, it loaded, and Ruby responded correctly when I called a method with incorrect arguments.

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Collaborate on develop an extension or two?

      @mingteck said:

      simple acoustical modelling

      It depends on what you mean by simple. Using standard formulas based on volume and surface area by absorption is one thing, much past that and the calc time might be a bit long...

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: No output text on Windows 7 system command

      Jiva,

      It's complicated. I started using Ruby years ago with SketchUp. Been away from SketchUp for while, but I'm still using Ruby.

      As I recall, the files get split into two locations, you have to edit the SketchUp.exe file, etc.

      I've also been building Ruby for quite a while, so the files I used were my own and built with current compilers & toolchains. With SU 2017, it can only run with Ruby 2.3 due to the changes that occurred in Ruby 2.4.

      There may be a publicly available build of Ruby 2.3 in the (hopefully near) future...

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: No output text on Windows 7 system command

      The problem is the ruby build currently included in SU 2017. Not sure why output varies by Windows version.

      If one replaces it with a different build, command output will appear in the console.

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Get mac address in ruby

      Over in that other place, there's a thread addressing some similar questions for OSX and Windows.

      Re Windows, since Ruby backticks don't work as expected, trying to grab return text from an external command is messy. In the other place, I think Dan posted code using cmd redirection to a file, which will work.

      If you want a Windows MAC address and can assume a version of SU with the Ruby std-lib included, I posted a WIN32OLE example here

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Module-class

      Mario,

      This might help (I reformatted your code a bit), see the last couple of lines --

      
      # require 'sketchup.rb'   # why?  not needed for this code
      module McF3D
        class McF3DTools 
          def initialize
            @mod = Sketchup.active_model  # Open model
            @ent = @mod.entities          # All entities in model
            @sel = @mod.selection         # Current selection
          end
          def perceOuv
            unless @sel[0].is_a?(Sketchup;;ComponentInstance) &&
                @sel[0].definition.behavior.cuts_opening?
              UI.messagebox "Sélectionnez un composant F3D !"
            end  
          end 
        end # class McF3DTools
      end # module McF3D
      obj = McF3D;;McF3DTools.new()
      obj.perceOuv()
       
      

      The topic of modules & classes in programming is very complex. Conversely, what most people writing a SketchUp extension need to do is a very small subset of that topic.

      HTH,

      Greg

      SUMD SketchUp Misc Docs

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Module-class

      Mario,

      Glad that helped.

      @mariocha said:

      is the def Initialize a must ?

      Technically, no. But, if there's no need for it, one might ask the question 'should this be a module?' The answer would vary amongst programmers, and isn't dependent on that single criteria.

      [EDIT] I should add that when you create a class, it is a Ruby Class object, which has a :new method, which calls initialize if it exists. Just in case you were wondering...

      Greg

      SUMD SketchUp Misc Docs

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: UI.inputbox with Web Dialog

      Nathan,

      Simply put, the best solution is to have your program flow based on callbacks from the WebDialog. This often creates problems for people, as the UI.inputbox is blocking. So the code is something like this:

      
      def start_method
        # some code to initialize and load inputbox
        UI.inputbox(*args)
        # more code for operation
      end
      
      

      The above is very linear and not easily changed to an event driven style. Better to start with something like:

      
      def start_method
        # some code to initialize and load inputbox
        UI.inputbox(*args1)
        ui_input_done(args2)
      end
      
      def ui_input_done(*args2)
        # more code for operation
      end
      

      Then, if you decide a WebDialog is needed:

      
      def start_method
        @dlg = UI;;WebDialog.new()
        # load @dlg html, etc
        @dlg.add_action_callback { |dlg, ret|
          # gather data from dlg
          ui_input_done(*args2)
        }
        @dlg.show()
      end
      
      

      To really give the user a good UI experience, one has to write javascript for the WebDialog.

      Greg

      [anchor="1" goto="http://msp-greg.github.io/su_info/index.html":17i7mw7a]GitHub.io SketchUp Misc Docs[/anchor:17i7mw7a]

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Linear Algebra & Analytic Geometry

      @bomastudio said:

      Hi Guys, I have an agony-problem with a 3D rotation.

      The transform that TIG suggested (rotation) works for your need. The docs on transformations aren’t very clear, especially for people who aren’t familiar with 3D transforms or linear algebra. They’re also a little quirky, as the trans.to_a method returns a matrix that is the transpose of what I would expect. FWIW, I had a lot of linear algebra (long time ago)...

      Anyway, the rotation method returns a transformation based on a rotation in a plane, which is defined by the ‘axis’ parameter, which should be the normal to the plane of rotation.

      If the start and end vectors are parallel, they do not define a unique plane, hence, both my original ‘linear algebra’ algorithm and the rotation method fail. The code below accounts for that –

      Greg

      module SUMath
        def self.transVector2Vector(vStart, vEnd, pt = nil)
          ptRot = pt || [0,0,0]
      
          if vStart.samedirection?(vEnd)
            # return identity transformation, vectors are in the same direction
            Geom;;Transformation.new 
          elsif vStart.parallel?(vEnd)
            #return 180 transformation, vStart and vEnd in opposite direction
            Geom;;Transformation.axes(ptRot, [-1,0,0], [0,-1,0], [0,0,-1] )
          else
            # return rotation transform based on vStart and vEnd
            # vCross is normal to plane of rotation
            vCross = vStart.cross(vEnd)
            ang = vStart.angle_between(vEnd)
            Geom;;Transformation.rotation(ptRot, vCross, ang)
          end
        end
      
        def self.rotateFace(face, vector_end, pt = nil)
          # for demo purposes, the next 2 statements chose an arbitrary face
          # if no face passed
          unless face
            entities = Sketchup.active_model.entities
            faces = entities.grep(Sketchup;;Face)
            face = faces[0]
          end
      
          face_normal = face.normal
          t = transVector2Vector(face_normal, vector_end, pt)
          entities.transform_entities(t, face)
      
          # below is just for a demo confirmation
          sd = face.normal.samedirection?(vector_end)
          sVEnd = "[#{vector_end.join(",")}]"
          puts "face.normal.samedirection?(#{sVEnd}) = #{sd}"
        end
      end
      # load module thru console
      # type SUMath.rotateFace(nil, [0,0,1]) into console with whatever vector
      # you want, it can be typed as often as you'd like.
      # As a demo, best done with one face in the model
      
      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Linear Algebra & Analytic Geometry

      Try the following --

      module SUMath
        def self.transVector2Vector (vStart, vEnd)
          v1 = vStart.normalize
          v2 = vEnd.normalize
          return Geom;;Transformation.new if v1.samedirection?(v2)
          v3 = v2.cross(v1)
          v4 = v3.cross(v1)
          c = v2.dot(v1)
          s = v2.dot(v4.normalize)
      
          m1 = Geom;;Transformation.axes( [0,0,0], v1, v4, v3)
          m2 = Geom;;Transformation.axes( [0,0,0], [c,s,0], [-s,c,0], [0,0,1] )
          mT = m1 * m2 * m1.inverse
        end
      
        def self.rotateFace(s_vector_end)
          vector_end = s_vector_end.split(",").collect { |i| i.to_f }
          entities = Sketchup.active_model.entities
          faces = entities.grep(Sketchup;;Face)
          face = faces[0]
          face_normal = face.normal
          t = transVector2Vector(face_normal, vector_end)
          entities.transform_entities(t, face)
          par = face.normal.samedirection?(vector_end)
          puts "face.normal.samedirection?([#{s_vector_end}]) = #{par}"
        end
      end
      
      # load module thru console
      # type SUMath.rotateFace("0,0,1") into console, or use whatever vector,
      # you can type repeatedly.  Best to have just one face in the model...
      

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: How to make toolbar in method(def..end) has parameters

      Try the following (class variable just in case...)

      @@valueq = 1
      
      def slab(valueq)
        puts "valueq = #{valueq}"
      end
      
      # below is for testing
      command = UI;;Command.new("ss") { slab(@@valueq) ; @@valueq += 1 }
      # normal line is below, as before
      # command = UI;;Command.new("ss") { slab(@@valueq) }
      
      command.small_icon = command.large_icon = path + "/slab.png"
      command.tooltip = command.status_bar_text = "s"
      menu.add_item command
      toolbar.add_item command
      toolbar.show
      

      As you click the icon, you should see valueq increment each time.

      Note, inside of braces/blocks, the || are only used when the calling code has parameters to pass. Command.new doesn't do that. Methods like .each (and others) do...

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: [Code] wrapping operations

      One can also wrap Dan's code in a method

      def self.operation(opName, procElse = nil, procEnsure = nil)
        if (block_given? && String === opName)
          am = Sketchup.active_model
          begin
            am.start_operation(opName, true)
            yield
            am.commit_operation
          rescue => e
            am.abort_operation
            puts("Error operation block #<#{e.class.name};#{e.message}.>")
            puts(e.backtrace) if $VERBOSE
          else
            procElse.call()   if (Proc === procElse)
          ensure
            procEnsure.call() if (Proc === procEnsure)
          end
        else
          raise "Error operation parameters - No block given or opName not a String!"
        end
      end
      
      # call by
      # operation("My operation") { operation block }
      
      

      Note that if either procElse and procEnsure are used, they should probably be lambdas. One should also be careful about return statements in the block passed to the method.

      BTW, I'll use snake case for methods, maybe not variables...

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: How to make toolbar in method(def..end) has parameters

      Using instance variables

      def slab(var1, ..., varN)
      ...
      end
      
      command = UI;;Command.new("ss") { |@var1, ..., @varN| slab(@var1, ..., @varN) }
      

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Executing one call_back executes another.

      @sdmitch said:

      "initializeForm" is called when the html is loaded but I am not knowingly doing anything that would cause the html to reload when the select button is clicked.

      Remove the form tags. Forms have some odd default behavior, in this case, reloading the html...

      Attached an rb file with some changes --

      1. Uses 'html is loaded' for callback
      2. Changed 'InitializeForm' execute_script statements to pass arrays

      I did remove the top of the code.

      Greg


      Select by Attribute_WD 1.1.rb

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: &lt;canvas&gt;

      Thom,

      @tt_su said:

      I think I've seen this when you hook into the load event. Though hooking into the DOMContentLoaded appear to not suffer from this. Hooking into this might differ from browser to browser (glares at IE).

      I updated my post with the code to use the DOMContentLoaded event, if available...

      Thanks,

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: &lt;canvas&gt;

      The following will draw a canvas line on load, then will draw three more lines via button click.

      Shows callbacks from WebDialog to Ruby, both on WD init and from button clicks. Also shows execute_script (Ruby calls into WD javascript)

      Thom - I'm one of the old-fashioned guys that think jQuery is overkill for
      environments like SU

      HTH...

      Greg

      
      def canvasTest()
        cntr = 0      # counter for button clicks
        aPtSt = []    # 2 element array for line start point [x,y]
        aPtEnd = []   # 2 element array for line end point   [x,y]
      
        html = <<-HTML
      <!DOCTYPE html>
      <html lang="en-US">
        <head>
        <meta charset="utf-8" />
        <meta content="IE=edge" http-equiv="X-UA-Compatible" />
          <style type="text/css">
            em {text-decoration;underline; font-style;normal; }
            #myCanvas {border;3px solid #d3d3d3; }
            #bNext {height;2em; width;100px; margin-left;50px; }
          </style>
          <script type="text/javascript">
            'use strict';
            var $el = function(x) { return document.getElementById(x); },
                ctx,
                inSU = true;
      
            // dLine - draw canvas line
            function dLine(stX, stY, endX, endY) {
              ctx.moveTo(stX,stY); ctx.lineTo(endX,endY); ctx.stroke();
            };
      
            // clkBtn - button click
            function clkBtn(e) { talk("Next"); };
            
            // winLoad - set doc variables, attach events to DOM elements,
            //           then tell SU we're ready
            function winLoad() {
              ctx = $el("myCanvas").getContext("2d");
              $el("bNext").addEventListener('click', clkBtn, false);
              talk('winLoad');
            };
      
            // talk - used for SU callbacks, also script debugging
            //        set inSU = false to output to browser console
            function talk(sSend) {
              if (inSU) window.location = 'skp;' + sSend;
              else      console.log(sSend);
            };
            
            if ('DOMContentLoaded' in document)
              document.addEventListener('DOMContentLoaded', winLoad, false);
            else
              window.addEventListener('load', winLoad, false);
          </script>
        </head>
        <body>
          <div><canvas id="myCanvas" width="200" height="200" /></div>
          <button id="bNext" accesskey="n"><em>N</em>ext Line</button>
        </body>
      </html>
        HTML
      
        dlgCvs = UI;;WebDialog.new("Canvas", false, "WDID", 300, 300, 10, 10, true)
         
        # add callback for onload event
        dlgCvs.add_action_callback("winLoad") { |dlg,ret|
          dlgCvs.execute_script("dLine(50,50,50,150);")
        }
      
        # add callback for button click, loop thru lines for drawing square
        dlgCvs.add_action_callback("Next") { |dlg,ret|
          case cntr
          when 0 then aPtSt = [50,150]  ; aPtEnd = [150,150]
          when 1 then aPtSt = [150,150] ; aPtEnd = [150,50]
          when 2 then aPtSt = [150,50]  ; aPtEnd = [50,50]
          end
          if (cntr < 3)
            cntr += 1
            dlg.execute_script("dLine(#{aPtSt.join(',')},#{aPtEnd.join(',')});")
          end
        }
      
        dlgCvs.set_html(html)
        dlgCvs.show
      end
      canvasTest()
      
      
      posted in Developers' Forum
      M
      MSP_Greg
    • RE: &lt;canvas&gt;

      Sam,

      @sdmitch said:

      Greg,
      Based on your example, I now know it is possible to reference a function using dlg.execute_script.

      Glad that helped. On Windows, the dlgCvs.show code executes immediately and steps to the next line of code, so you have to muc around with the 'load' event, since the DOM isn't yet loaded in the WD. Just the way it works, which does make sense, given that the show_modal method blocks (at least on Windows) until the dialog is closed.

      You can also string together several method calls in execute_script. Hence, if the following is the code in the Ruby winLoad method

      
      str = dLine(50,50,50,150);dLine(50,150,150,150);dLine(150,150,150,50);dLine(150,50,50,50);"
      dlgCvs.execute_script(str)
      
      

      a square will be drawn. BTW, there might be a limit to how long the parameter string can be in execute_script, but I don't know what it is...

      As an aside, I did a canvas project (unrelated to SU) a while back. With good code, canvas is very fast...

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: &lt;canvas&gt;

      John,

      @driven said:

      not on a mac...
      it requires a right click to see the first content...

      I agree about jQuery as it's hard to debug in SU...
      john

      Cool...

      Okay, being a Windows type, I don't have a mac handy to test with. If I try the html in Chrome (and set the inSU flag to false), I do see the callback to winLoad in the console.

      Hence, do you (or Thom, or anyone on a mac) have any idea why this happens? FWIW, the main feature of my plugin is exporting and importing files with other software. Those software packages only run on a pc. Hence, I've never felt a need to make my plugin run on a mac...

      Thanks,

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • RE: Arrange component names

      SDMitch (Mitch?),

      @sdmitch said:

      Tried your code and found two problems.

      1. if(reInc.match(cd)) needs to be if(reInc.match(cd.name))

      Thanks for the catches. I edited & corrected the second post. I tested mine with a string array, not an array of cd's. Hence, no name prop.

      @sdmitch said:

      1. the prefix of the new name entered gets incremented as well.

      That's why you had the new cd name assign at the end of the loop. That's why I shouldn't change code after I've tested it...

      Thanks,

      Greg

      posted in Developers' Forum
      M
      MSP_Greg
    • 1
    • 2
    • 3
    • 1 / 3