sketchucation logo sketchucation
    • Login
    1. Home
    2. Dan Rathbun
    3. Posts
    Oops, your profile's looking a bit empty! To help us tailor your experience, please fill in key details like your SketchUp version, skill level, operating system, and more. Update and save your info on your profile page today!
    ⚠️ Important | Libfredo 15.6b introduces important bugfixes for Fredo's Extensions Update
    Offline
    • Profile
    • Following 0
    • Followers 1
    • Topics 92
    • Posts 4,904
    • Groups 2

    Posts

    Recent Best Controversial
    • RE: Timer < 1.0 seconds ?

      I think I'm seeing 1/64th (0.016) sec resolution with Kernel.sleep (+/- 0.001) sec.

      Is it possible to use sleep in a subthread, without pausing execution in the main thread?
      (Note examples in the 'Pick-Axe' Ruby book, under Kernel.sleep and class Thread.)

      Here'e the test program I wrote this eve.


      TimerTest.rb

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: By value or by reference?

      @chris fullmer said:

      I just tested by displaying the object id of a variable passed between different methods, and it keeps the same object id. So it sounds like it passes a reference.
      `

      def m2(a)
      >   puts a.id
      > end
      > 
      > def m1
      >   a = "hi"
      >   puts a.id
      >   m2(a)
      > end
      

      `Correction (line 8): "m2(a)" was "ms(a)"

      What I think ya'll are misunderstanding (and contrary to what most programming tutorials say,) about Ruby, is that Ruby DOES NOT really have TRUE VARIABLES.

      'True variables', I mean in the sense that other languages such as the old BASIC or Pascal had variables, that were declared to 'BE' a certain datatype (int, real, string, etc.) AND kept a table in memory of those (variable) identifiers along with the current VALUE that was 'HELD' by them.

      Ruby doesn't do this. EVERYTHING in Ruby is an OBJECT, including objects of the BASE classes (ie: Integer, Float, String, etc.) So when you code:
      aVar = 8
      in Ruby, you are NOT assigning the integer value 8 to a variable identifier, ... you are instead creating a reference, with the name aVar that POINTS at the first class object 8. The object 8 is an instance of class Integer, and so inherits methods from it's class, and superclasses, ie:
      ` 8.id

      an id number
      aVar.id
      the same id number since it points at object 8
      bVar = aVar
      bVar.id
      the same id number since it points at object 8`
      And as Chris said, Fixnum is special in that there can be ONLY 1 object for each ordinal in the Fixnum set.

      The same is not truefor other more complex types, such as Array, String, etc.
      The best illustration of "how thinking" of Ruby references as variables (like in other languages,) can lead you to 'hair-pulling' frustration, was given in the forum over at Google Groups. (I answered and solved the poster's problem, but refered in my answer, to his 'reference' as 'an alias'; perhaps not so good as alias is a special kind of reference in Ruby for methods and don't work for "variables".)
      Any how.. read that post, and examine flesk's code, and the solution TIG and I gave him (TIG and I are about 5/6 hours apart and posted about the same time, I think.)
      Google Groups (Sketchup ruby API): Variable value error

      So how would you 'pass by value'? (In the sense that you would in Pascal. You should have an idea, after reading that post.)
      Let's modify Chris' code a bit:`

      def m2(a)
        puts 'a in m2 has id; '+a.id.to_s
      end
      
      def m1
        a = "hi"
        puts 'a in m1 has id; '+a.id.to_s
        m2(a.dup)
      end
      

      Or if you wish to paste into the console, then (1 line at a time): def m2(a); puts 'a in m2 has id: '+a.id.to_s; end def m1; a = "hi"; puts 'a in m1 has id: '+a.id.to_s; m2(a.dup); endand then type: m1`
      You'll see the id numbers differ.
      NOTE: If you think this will save time or memory, it won't. Ruby will create an anonymous reference to the duplicated object, so there is still a 'reference assignment' behind the scenes. In fact if you look up at the modified code, at the 2 puts statements, the String arguments 'a in m1 has id: ' are also transparently assigned an anonymous reference, so I might just as well have stored the string in a named reference of my own, so both methods could use the same String object, but change the method name. Of course it's not necessary, as these objects will not 'live' long.

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Timer < 1.0 seconds ?

      @thomthom said:

      Anyone found a way to create a timer with resolution of less than a second?

      So your saying that my 'wait half-second for console' technique, as shown in posting Re: idea: show console on script error, ie:
      Sketchup.send_action(CMD_RUBY_CONSOLE) UI.start_timer(0.5, false) { puts e.message }
      is really waiting a full second?

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Sketchup registry key ?

      @fizgig said:

      Does anyone have any tips for making a ruby script installer for windows? I need to be able to *copy a directory to the c:* and then copy a loader script into the plugins folder.

      Fiz, 99% of users HATE (and don't want,) software installed in the root directory of our boot drives!

      Plugins should be usually be installed in a subfolder of Plugins. (If it's a stanalone plugin that adds some functionality to Sketchup, such as a tool or report generator.)

      IF it's an 'behind the scenes' enhancement used by MANY plugins, (which would not appear on a menu,) it might go in a subfolder of another Sketchup folder such as Tools (in order to prevent menu building scripts from putting it on a menu.) BUT in this case, you should ask the user to confirm or specify a different folder (as some users also HATE non-Google scripts down in the Tools folder heirarchy.)

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Does "C" equal "C" ?

      @martinrinehart said:

      ... I stumbled acrossthe Ruby File.expand_path() method that looks like a better replacement for the little fixup() function I wrote. If you File.expand_path(__FILE__) you get the full path back to the root, on a Mac, or the drive, on a PC. Perfect!

      If you look back at the original thread, and reread more carefully, you'll see ThomThom told you to use File.expand_path() two weeks before you "stumbled across" it!

      I've been wondering why you didn't take his advice... (and do you have a copy of the 'Pick-Axe' Ruby book in chm format?)

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Idea: show console on script error

      @jim said:

      The Ruby Console is not required to be visible for using stdout, and SketchUp doesn't wait for the Ruby Console to be opened. The puts will be long finished before the Ruby Console has a chance to appear.

      I solved this on a little ruby I wrote to display SU Options.
      Here's the lister method:

      def self.list_options(output=$stdout)
        # param chooses stdout or messagebox
        case output
        when $stdout, STDOUT
          Sketchup.send_action( CMD_RUBY_CONSOLE )
          UI.start_timer(0.5, false) { $stdout.write( get_options_text ) }
        when 'messagebox',;messagebox, 'MB', ;MB
          UI.messagebox( get_options_text,MB_MULTILINE,' OPTIONS')
        end
      end
      
      

      So the 'trick' is to pause for a half-second allowing the console dialog time to load and initialize, etc. So TIG's example can work like this:

      begin
        ##
        ### do all of your code here
        ###
      rescue Exception => e
        if $VERBOSE  # true is verbose mode
          Sketchup.send_action(CMD_RUBY_CONSOLE)
          UI.start_timer(0.5, false) { puts e.message }
        elsif $VERBOSE.nil?  # nil is silent mode
          logfile.write( e.message )
        else  # $VERBOSE is false (medium mode)
          puts e.message 
          raise # (optional)
        end
      end
      
      

      pssst! JJ, it's not necessary to requote codeblocks unless your suggesting changes.

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Idea: show console on script error

      @jim said:

      A better solution is to write output to a file from Ruby. One option is to redefine puts to write to a file instead of stdout. Another option is to create your own log method for debug output.

      Has anyone tried running the standard Ruby simple logger (logger.rb) under SU embedded Ruby?

      It looks easy to use. Example from logger.rb RDoc
      (with module wrapper, require statement and method wrapper added by me.)

      
      # A simple example ...
      module A_Logger_Test
      require 'logger.rb'
      def log_file_error( path )
        log = Logger.new(STDOUT)
        log.level = Logger;;WARN
      
        log.debug("Created logger")
        log.info("Program started")
        log.warn("Nothing to do!")
      
        begin
          File.each_line(path) do |line|
            unless line =~ /^(\w+) = (.*)$/
              log.error("Line in wrong format; #{line}")
            end
          end
        rescue => err
          log.fatal("Caught exception; exiting")
          log.fatal(err)
        end
      end # method
      end # module
      
      

      It can also output to log files (with auto file aging and max file sizes.)

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Webdialogs and Javascript void

      @martinrinehart said:

      Dan, I enjoyed your very deep response. Thank you!
      But my question was really about the original proposed use. I get the intended result with:
      %(#804000)[<a href=']%(#8000BF)[javascript&#058;return null]%(#804000)[' ondblclick=']%(#8000BF)[...]%(#804000)['>doubleclick-only link!</a>]
      without offending Doug Crockford.
      (1) Not in my opinion,... you are 'misusing' return in the same way that offends Doug regarding the misuse of void.
      And that is, misusing the function (or operator,) by forcing the processing of a meaningless literal expression such as 0, (ie: void(0);) when it is preferred for clarity, and faster for processing, to simply use return; (as return with no expression returns undefined.)
      Doug also seems to imply that the choice of the word 'void' for the Js "return_undefined_after_eval" function name, is confusing because of it's accepted use in other languages. I give him that. The inventer of Js could have named it the noreturn operator.
      (2) As mentioned above, there can be compatibility problems with the use of null. (And, once again, why force the machine to process the null expression if it is not necessary?)

      @martinrinehart said:

      And do you agree with Crockford? **> @unknownuser said:

      **.
      **In most C-like languages, void is a type. In JavaScript, void is a prefix operator that always returns undefined."
      **[Dan inserts: 2 statements of fact - agreement not necessary.] **> @unknownuser said:

      **.
      JSLint does not expect to see void because it is confusing and not very useful.

      Two opinions:
      (1) "confusing" - The void operator, is only confusing when it's misused, (as stated above.)
      (2) "usefulness" - The void operator was impletemented for a real purpose. When the expression to be evaluated, is a valid expression (processing work needs to be done to evaluate it, and that evaluation is necessary;) but the results need to be prevented from returning to the caller.
      The perfect exampleis the problem Todd was having with Js callbacks to a Sketchup Ruby. In that situation, the proper use of void is a valid answer to the problem.
      See SCF topic: Anyone seen this web dialog bug?

      @martinrinehart said:

      Why "prefix operator"?
      A prefix operator is one that is stated before an expression (ie: it operates on the expression that follows itself.)
      In Ruby, we have some "double-duty" reserved words that can also be used as prefix operators. Examples are if and unless. (Although the Ruby manual calls them 'modifiers' when they are used in this way.)
      ( *expression that does something* ) **if** ( *boolean expression* )
      or
      ( *expression that does something* ) **unless** ( *boolean expression* )

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: [FIXED!!!] Anyone seen this web dialog bug?

      @unknownuser said:

      So.... being the inquisitive guy I am... I removed the "false" from return false;. That did the trick!! Go figure.

      return [( [expression] [)];]

      @unknownuser said:

      "If expression is omitted, or no return statement is executed from within the function, the expression that called the current function is assigned the value undefined."
      http://msdn.microsoft.com/en-us/library/22a685h9(VS.85).aspx

      void expression

      @unknownuser said:

      "The void operator evaluates its expression, and returns undefined. It is most useful in situations where you want an expression evaluated but do not want the results visible to the remainder of the script.
      The expressionargument is any valid JScript expression."
      http://msdn.microsoft.com/en-us/library/e17c7cbe(VS.85).aspx

      .. this is why you often see void(0); used in the HREF attribute for controls (such as a <A> tag,) that display popups or alert boxes.
      ADDED: See SCF topic: [url=http://forums.sketchucation.com/viewtopic.php?f=180&t=25252:dqe1rmdx]Webdialogs and Javascript void[/url:dqe1rmdx]

      therefore... you should be able to do it in the input tag thus:
      onclick="void( window.location='skp:setvalue@' + toHex(document.getElementById('ifield').value) );"
      .. and shouldn't need to have a function call.

      EDIT: put MSDN quotes in quoteboxes for clarity.

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Default constants

      from Windows SDK, WinUser.h, line 2373...
      [language=C]:
      *` %(#008B8B)[/

      • Key State Masks for Mouse Messages
        /
        #define MK_LBUTTON 0x0001
        #define MK_RBUTTON 0x0002
        #define MK_SHIFT 0x0004
        #define MK_CONTROL 0x0008
        #define MK_MBUTTON 0x0010
        #if(_WIN32_WINNT >= 0x0500)
        #define MK_XBUTTON1 0x0020
        #define MK_XBUTTON2 0x0040
        #endif /
        _WIN32_WINNT >= 0x0500 /]`*
      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: [FIXED!!!] Anyone seen this web dialog bug?

      @dan rathbun said:

      therefore... you should be able to do it in the input tag thus:
      onclick="void( window.location='skp:setvalue@' + toHex(document.getElementById('ifield').value) );"
      .. and shouldn't need to have a function call.

      ON second thot... chances are we'll forget and have the same 'bug' again on other projects.
      Let's promote Jim Foltz's idea of using a generic callback function.

      from Jim's v6 webconsole:
      %(#8000BF)[

      // Javascript
          function cb(name, args) { // CALLBACK
              window.location='skp;'+name+'@'+args;
          }
      
      

      ]
      modified with a void operator and a bit of typechecking:
      %(#8000BF)[

      // Javascript
          function cb(name, args) { // CALLBACK
            if typeof(name)=='string' {
              if typeof(args)!='string' { args=args.toString }
              void( window.location='skp;'+name+'@'+args; ); 
            }
            else {
              void( window.location='skp;webError@Callback name is not a string!';);
            }
          }
      
      

      ]
      So, Todd's callback could be:
      onclick="cb( 'setvalue',toHex(document.getElementById('ifield').value) );"

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Default constants

      @thomthom said:

      How can I find out what is SU constants and what is plugin constants?

      It's easy.

      (1) Make a COPY of the Sketchup folder and subfolders (EXCEPT Plugins)
      Call it "Google Sketchup 7 Nude" (or similar)
      (2) Make an empty 'Plugins' folder, under the "nude" copy.
      (3) Either create an NEW user account (or use your Administrator account)
      (4) Switch to the other account (Log off if you wish, or not.)
      (5) On the other account, make a shortcut to to the "Nude" Sketchup.
      Don't run the "Nude" Sketchup on your 'normal' account as it will change the settings in your 'normal' Registry Hive!!!
      (6) Run 'Nude' Sketchup on the New (or other account). Check Prference Settings for those things in the 'Tools' folder so that they are at minimum (probably DC only.)

      Now you have a way to check what comes with the base API, by switching users and running the 'Nude version.'

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: Default constants

      @thomthom said:

      ... I see no reference in the manual to them. Are they added by a plugin? How can I find out what is SU constants and what is plugin constants?

      I can't find the reference now.. but I 'think' these were added by Google when they fixed the onMButtonDown and onMButtonUp callbacks (Tool Class) in SU 7.0 ... but the constants I 'think' are meant to be used with Tool.onKeyDown and Tool.onKeyUp.
      ie:
      def onKeyDown(key, repeat, flags, view) %(#F0F0F0)[__]if key = MK_LBUTTON %(#F0F0F0)[____]if flags = MK_ALT %(#F0F0F0)[______]# do something special %(#F0F0F0)[____]else %(#F0F0F0)[______]# do normal pick %(#F0F0F0)[____]end %(#F0F0F0)[__]end end

      My brain 'thinks' I read it in a non-official mention, perhaps an offhand remark in the forums by a Google SUTM.

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • RE: [plugin] Ruby Code Editor - UPDATED to v3.0 3/4/2013

      BY the way... you announced a ver 1.1.1, but...

      The Revision block at the top of as_rubyeditor.rb says version: 1.2
      (The extension registration/loader script says version: 1.1.1)

      The thread topic (title of the first post,) still says version 1.1

      posted in Plugins
      Dan RathbunD
      Dan Rathbun
    • RE: [plugin] Ruby Code Editor - UPDATED to v3.0 3/4/2013

      @alexschreyer said:

      1. ... So the undo option is meant for undoing the SU action. ...
        OK just so you know, and hopefully the users will also.

      I thought of a scenario: What if a user wishes to actually experient themselves with the undo API feature, writing the .start_operation, .commit_operation calls into the snippet editor? What would happen in ruby with double nested operations? Perhaps a checkbox next to the UNDO button to turn on|off the editor's Undo calls, ie(as_rubyeditor.rb):
      line 74: Sketchup.active_model.start_operation "RubyEditor" **if @undo_is_on**
      line 82: Sketchup.active_model.abort_operation **if @undo_is_on**
      line 84: Sketchup.active_model.commit_operation **if @undo_is_on**

      @alexschreyer said:

      1. Until there is a multi-file version of the editor, the multi-instance option is actually useful. Question: On close, can I destroy an instance like "UI::WebDialog = nil".
        Agreed, and actually even with a multi-file version (if you don't have a split screen feature,) then allowing two instances can satisfy those who'd want a split screen feature, (ie: 'cut & pasting' between two windows.) But we need to control instancing, and limit it (with a default limit, which might be overridden by the user.) I'm using a class variable: @@max_num
        Garbage Collection. You would not set the class to nil. You are suppossed to be able to set the instance to nil and then call GC.start, but I've never witnessed GC disposing of the instance variable. It just sits around with a nil value (at least it's not taking up much space.) So ..
        dlg=Namespace::RubyEditor.new( *arglist* ) #.. set it up.. show it .. use it .. close it dlg=nil GC.start
        Anyway... in this case: we first must use a symbol to hold a reference to each instance. In editor code (line 205) in the add menu item command block you have (as Jim did,): "RubyEditor.new" which is not storing a reference to the instance, even though the object.new method always returns a reference to the newly created instance of the object class (which is the third main task of the new method in ruby.)
        I'm using an Array class variable: @@instances=[]
        and when I construct the instance, I push it's reference into the array:
        if @@instances.size < @@max_num %(#F0F0F0)[__]num = @@instances.size+1 %(#F0F0F0)[__]if dlgi = WebConsole.new(num) # non-nil if success %(#F0F0F0)[____]@@instances.push( dlgi ) %(#F0F0F0)[____]# add menu link for instance %(#F0F0F0)[__]end end
        The num var is used both to insert into instance menu text (similar to an editor's untitled(1), untitled(2) captions,) and is passed to new, so the instance itself can know which one it is (it's position in the class array var @@instances,) and to append as text onto the instance's Preferences Key suffix.
        All that if block, above is wrapped within a UI::Commandclass instance @@cmd
        __
      posted in Plugins
      Dan RathbunD
      Dan Rathbun
    • RE: [plugin] Ruby Code Editor - UPDATED to v3.0 3/4/2013

      @alexschreyer said:

      The remaining issue is ...

      Actually I see a few (in as_rubyeditor.rb)

      (1) You removed the module wrapper around the dialog class !!!
      This is a no-no. ONLY Ruby Baseclasses (like Integer, String, Module, Class .. etc.,) should be defined at the TOP_LEVEL, in the Objectspace. The lightweight version I'm working on (update to Jim's) will be double wrapped, something like:
      SUutil::Ruby::WebConsole

      (2) down ~line 181
      # Callback to undo the last code execution
      add_action_callback("undo") do |d, p|
      (a) Just want to stress (seeing your code comment,) that Undo is a Sketchup function, not a Ruby function. It only undoes changes to the model. It does not undo ruby statements. For instance, if you define a method, run it, and click undo; The method is still defined in Ruby (whether right or wrong.) The same holds true for variables, constants, object instances, etc.
      (b) I consider using 'p' as a varname dangerous because of method Object.p (and try to avoid single char varnames; usually put a number like t1, t2 for time vars, or x1,y1 for coords, etc.
      Jim had a weird bug in a previous version that had to do with the use of 'd' as a varname, see:Sketchup Developer's Google Group post: "What is so special about d?"
      ***** For WebDialog callbacks I've settled on a personal standard |dlg,arg|

      (3) Instancing.
      (a) The way it's written now (ie the way Jim had it,) the object constructor is within the menu item block, and creates a new instance each time the menu (or toolbar button,) is clicked.
      When the .close method is called, it's only the OS window object (and it's instances of the webpage, CSS and Js that are destroyed,) along with any text in the HTML controls.
      But the Ruby UI::WebDialog instance object still exists, and can be reshown. When this happens, Sketchup Ruby reloads the webpage assigned to it. Anyway think about that for a future revision.
      (b) I think I will limit my version to two (2) instances and greyout the "new" menu item after that. (A user can only 'cut & paste' between two windows at a time.) I'm also going to dynamically add links to the menu as the instances are created, so those instances can be reused, rather than waste memory.
      (c) This brings up the problem of Preference control. Which window will be (or should be,) allowed to update the settings? It takes a bit of thought, as I wish to have each instance save it's own size and position, and likely for the Mac, whether individually they will be 'always on top' or can go behind other windows, including SU.
      _

      posted in Plugins
      Dan RathbunD
      Dan Rathbun
    • RE: [plugin] Ruby Code Editor - UPDATED to v3.0 3/4/2013

      as ruby code editor ver 1.1
      MSIEver 7.0.5730.11

      Errors:
      (1) ui.html - Line 113 - invalid argument
      %(#804000)[<a] %(#40BFBF)[class]=%(#FF8040)["button"] %(#40BFBF)[onClick]=%(#FF8040)["u();"] ... %(#804000)[>]
      removed ";" and error went away
      %(#804000)[<a] %(#40BFBF)[class]=%(#FF8040)["button"] %(#40BFBF)[onClick]=%(#FF8040)["u()"] ... %(#804000)[>]

      .. but then (after reloading page,)
      (2) ui.js - Line 165 - Char 3 - Object doesn't support this property or method
      [seems that line wants to load stylesheet(s)]

      ... the page looks exactly like driven posted for the Mac. (but with MS fonts)

      posted in Plugins
      Dan RathbunD
      Dan Rathbun
    • RE: [plugin] Ruby Code Editor - UPDATED to v3.0 3/4/2013

      @alexschreyer said:

      @Dan: I can do that the next time.

      OK. no problem... I've posted here so this thread popped to the top, when you posted.

      @alexschreyer said:

      WebKit doesn't seem to want to save cookies from a local page somehow, so I might have to do a local preference storage (as suggested before) after all...

      Well I've already done the work.. let me have a look at as_rubyeditor.rb, and I'll get back to ya' today or tomarrow.

      posted in Plugins
      Dan RathbunD
      Dan Rathbun
    • RE: [plugin] Ruby Code Editor - UPDATED to v3.0 3/4/2013

      Dang... Alex we are supposed to use the same original thread, and post the plugin in the first message. Then when updated, you replace the file attachment there in the first message.
      (But in your case, you'd update the link to the download.. same difference.)

      As the thread 'starter' you can can change the Topic to reflect '[UPDATE]' and release version. etc.

      That way..
      (1) there is not a separate thread for each new release.
      (2) Since I posted in the original thread, I expected (when an update came,) to see the thread pop to the top of the 'Your Posts' page (which is kind of my 'homepage' at SCF, how I enter the site.)

      {Maybe ThomThom can stitch the 2 threads together if you agree.]

      posted in Plugins
      Dan RathbunD
      Dan Rathbun
    • RE: SU 6.0 latest version?

      @thomthom said:

      That's odd - I keep an SU6 installation side by side SU7 to test plugins while I white them, and it keeps nagging me to update to SU7.

      Ver 7 has a checkbox: Preferences > General > Software Updates
      Did version 6 have this?

      If not, Registry: HKCU\...\Preferences > UpdateDefaultOn = 0|1
      (at least ver 7 has the registry key...)

      posted in Developers' Forum
      Dan RathbunD
      Dan Rathbun
    • 1
    • 2
    • 234
    • 235
    • 236
    • 237
    • 238
    • 245
    • 246
    • 236 / 246