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

    Instructor content

    Scheduled Pinned Locked Moved Developers' Forum
    84 Posts 8 Posters 7.9k Views 8 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.
    • Dan RathbunD Offline
      Dan Rathbun
      last edited by

      @bentleykfrog said:

      I'm still trying to wrap my head around this. In the code's current state, using the default mode, the script_folder argument just specifies a relative path from any of the $LOAD_PATH's to the 'instructor' folder's parent.

      Exactly as it should be, and what File.dirname(@@tool_filepath) would do, which is why I suggest it as the default value for your script_folder argument.

      @bentleykfrog said:

      So absolute paths from different volumes won't work with this, unfortunately. The default mode assumes that you'll have access to the $LOAD_PATH's, or use a script that adds accessible folder to the $LOAD_PATH. Some plugin loader's don't do this 😞

      They are not supposed to if they are not needed. Kernel.require() can use absolute paths, but it's better, memory wise, if you will be loading multiple scripts from a custom plugins folder (or library folder, using the standard Ruby library folders as an example,) to push that path onto $LOAD_PATH, so that when scripts are loaded, only the relative part, gets pushed into the $" (aka $LOADED_FEATURES) array. Pay no mind to the erroroneous way that Sketchup.require() pushes absolute paths onto $". It's a bug.. and I have entered a report on this.

      @bentleykfrog said:

      Ahh, I see. In my case, using Alex's Plugin Loader, when a new script is loaded $LOAD_PATH's aren't updated to show the file's folder location.

      They are not supposed to. If the script can be found by using one of the members in the $LOAD_PATH array, then there is already an appropriate load path in the array.

      It is not customary to push every specific plugin folder into $LOAD_PATH if there is already a path in the array, for one of the plugin folder's ancestor directories. (You would run the risk of confusing the require() method, resulting in scripts or library modules getting loaded more than once. That can reset class and module variables causing problems.)

      @bentleykfrog said:

      So I'm thinking of instances where a Sketchup user doesn't have access to the $LOAD_PATH's but does have a plugin loader script installed.

      I don't follow you. The $LOAD_PATH array is a Ruby global. It cannot be garbage collected. A user will always have access to it. However, a script might make a mistake and wipe the members out, resulting in an empty $LOAD_PATH array. There is also the possibility that a user may feel, sometime after startup, that they have loaded all that needs to be loaded from say, the Tools path, and could "pop" that path off the array. But it's more likely they would insert other custom paths at the beginning of the array (if say, they are using a common plugins folder some where else, which can have a drive letter at the beginning.) The require() method does not mind absolute paths on other drives.

      @bentleykfrog said:

      So in this case, you would need to bundle up load_instructor.rb with your plugin's files. Then, we need to pass an absolute path to require() representing the location of load_instructor.rb.

      Again.. No. You are confounding the issues of finding and loading a library file, with the issues of finding and loading a script and it's help content. Apples and Oranges.

      @bentleykfrog said:

      I was thinking that you would use File.dirname( @@tool_filepath ) for this, or in my Advanced Use example for .rb files I use File.dirname( __FILE__ ).

      Oh.. you are refering to the example in Section 3.4
      That should not be necessary. Unless the author needs to customize the mixin module for his/her own use. In which case they would need to change the module name, or the methods would overwrite a previously loaded edition from another place (required by another tool plugin.)
      But.. this defeats the general idea of a library. I cannot think of any good reason why that example (3.4) would ever be needed, and it just confuses the issue.
      ALL users and authors, should just simply follow the instructions in 2.1 and 2.2, and they will then never have any problems requiring or including the load instructor mixin module.


      So really,.. remove the example in Section 3.4 and consider the issue of finding and loading 'mixin/instructor.rb' done. It's not a problem.


      I'm not here much anymore.

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

        Just a quick reply before I have to run some errands.

        @bentleykfrog said:

        Ahh, I see. In my case, using Alex's Plugin Loader, when a new script is loaded $LOAD_PATH's aren't updated to show the file's folder location.

        I should have elaborated on what I meant by $LOAD_PATH. In this case, I meant the folders that are represented in the $LOAD_PATH array. As a case example, take my University. There's only read access granted to anything below C:/Program Files & C:/Program Files (x86). They don't provide a script that will load some read/writeable directories to the $LOAD_PATH array. I'm asserting that if there was a similar setup, but had Alex's Plugin Loader underneath one of the $LOAD_PATH's in C:/Program Files & C:/Program Files (x86), you would need to bundle load_instructor.rb with your script, and provide an absolute path to it using require(). This is probably quite rare though, but its one of the reasons I provide the Advanced Use of the Load Instructor.

        got to go, will respond to your post in more detail when I get some more free time.

        -niall

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

          @bentleykfrog said:

          As a case example, take my University. There's only read access granted to anything below C:/Program Files & C:/Program Files (x86).

          OK I now understand where your coming from. Yes this is one of the issues that caused this topic to begin with.

          @bentleykfrog said:

          They don't provide a script that will load some read/writeable directories to the $LOAD_PATH array.

          They should! Someone needs to convince them to put a simple script that pushes the user's home directory + "/Plugins" onto the $LOAD_PATH array. It's a one-liner.

          SO am I correct in that each time you run Sketchup at University, you must open the Console and type that one-liner manually? Or perhaps:
          require_all( "ENV['HOMEPATH']/Plugins" )
          which will push that path onto $LOAD_PATH for you?

          @bentleykfrog said:

          I'm asserting that if there was a similar setup, but had Alex's Plugin Loader underneath one of the $LOAD_PATH's in C:/Program Files & C:/Program Files (x86), you would need to bundle load_instructor.rb with your script, and provide an absolute path to it using require().

          Bundle perhaps... but even in a specific user's homepath, the library files do not belong beneath any of the script subfolders.

          The mixin needs to still be installed into a "mixin" folder, or a "lib/mixin" folder.

          Otherwise what is going happen is users will wind up with more that one copy of your mixin script (perhaps of differing versions,) installed in multiple places. They will insist they have the latest version, but an older version below some plugin's subfolder wil be loading after the newest version, overwriting methods.

          This will be a headache for you as a library author, because they will come whining to you (in the forums.)
          Save yourself the trouble... always insist it be only installed once, in a mixin library folder only. (So again Section 3.4 is a bad idea.)

          Also.. bundling libraries with plugins, generically, is bound to lead to revisioning conflicts. The plugin version is likely to remain stable (once all the kinks are ironed out,) but the libraries will continue to be updated.
          It is better to have your users follow a link and download a library file (of the latest version,) from the library download page, and install it separately. (I would never allow any plugin author to bundle any of my library files. And I'm sure ThomThom, TIG and other gurus around here wouldn't either. Users need to go to the source and always get the latest library version.)

          @bentleykfrog said:

          This is probably quite rare though, but its one of the reasons I provide the Advanced Use of the Load Instructor.

          Well, the issue of having shared scripts, down in the Program Application path, was a stupid one. And I'm sure it looks really dumb to the guy who originally made the decision, now that he has many more years of experience 'under his belt.'

          It is not that rare in a network environment, (both Alex and TIG have this problem at their University.)

          It will become more and more of a problem, as XP support is withdrawn, and more machines are migrated to the "linux-like" Windows 6+.

          The weird thing is that the Mac edition automatically checks the user library path, but Google did not do it on the PC. (Perhaps because %APPDATA% is by default a hidden / system path.) The answer is simple.. and I've set up my machine this way this past week.
          I have created user folders under "My Documents/Google Sketchup" and beneath that a "Common", "Sketchup 6", "Sketchup 7" and "Sketchup 8" folders.
          Your mixin library script has the honor of being the first to be installed into my "Common/Plugins/Mixin" folder. (Now the laborious task of copying all those files from the Program App paths to my new Folders.)

          I'm not here much anymore.

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


            Here's a version cleaned up and made into a Mixin module.


            Added Class Variables declarations:

                # CLASS VARIABLES
                @@relative_instructor_path = ''
                @@temp_instructor_folder = false
            
                @@tool_filepath = ''  # must be redefined in the Tool class for rbs files
            
            

            Added method definitions:

                public
                
                def relative_instructor_path
                  return @@relative_instructor_path
                end
                
                def temp_instructor_folder
                  return @@temp_instructor_folder
                end
            
             
                private
                
                # initialize()
                #
                # Likely to be redefined in the Tool class definition.
                # We define it here just in case the Tool author does not.
                #
                def initialize
                  help_setup()
                end
            
            
                # help_setup( instructor_folder=false, temp_folder=false )
                #
                # Sets up and inits some instance variables used for
                # the tool's Instructor help system.
                #
                # ** Must be called by the Tool's initialize() method. **
                #
            		def help_setup(instructor_folder=false, temp_folder=false)
                  #
                  if @@tool_filepath.empty?
                    if __FILE__ != '(eval)' && File.exist?(File.expand_path(__FILE__))
                      @@tool_filepath = __FILE__
                    else
                      raise(ScriptError,"#{self.class.name}; @@tool_filepath class variable error. @@tool_filepath must be declared for rbs files!")
                    end
                  else
                    unless File.exist?(File.expand_path(@@tool_filepath))
                      raise(ScriptError,"#{self.class.name}; @@tool_filepath class variable error. File '#{@@tool_filepath}' does not exist!")
                    end
                  end
                  #
            			if instructor_folder
            				@instructor_folder = instructor_folder
            			else
            				@instructor_folder = getDefaultInstructorFolder()
            			end
            			if temp_folder
            				@temp_folder = temp_folder
            			elsif RUBY_PLATFORM =~ /darwin/i # on a Mac
            				@temp_folder = @instructor_folder
            			else
            				@temp_folder = getDefaultTempFolder()
            			end
                  #
                  @@relative_instructor_path = returnRelativePath()
                  #
            		end #def help_setup()
            
            

            and:

                # getInstructorContentDirectory()
                #
                # Callback for tool to give Sketchup the relative path
                # to the tool's help directory.
                #
                def getInstructorContentDirectory
                  unless @@temp_instructor_folder
                    # copy help files
                    copyInstructor()
                    @@temp_instructor_folder = returnTempInstructorFolderName()
                  end
                  return @@relative_instructor_path
                end #def
            
            

            I did not make any changes to the "engine" methods, except:

            getDefaultInstructorFolder()
            changed all __FILE__ to @@tool_filepath

            returnTempInstructorFolderName()
            inserted a 'short circuit' as the first line, for Macs
            return @temp_folder if @temp_folder == @instructor_folder

            File Removed - Get the latest version in Niall's [ code ] topic:
            [ code ] Load Instructor

            I also wonder if there should be an AppObserver instance that deletes the temp/instructor file at the end of the session ??

            I'm not here much anymore.

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

            Advertisement