sketchucation logo sketchucation
    • Login
    πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    [??] How to pass a variable from main.rb to a boxtool

    Scheduled Pinned Locked Moved Developers' Forum
    11 Posts 4 Posters 166 Views 4 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.
    • R Offline
      rvs1977
      last edited by

      Hi β˜€ !

      I have 2 files:

      • main.rb, and
      • rs_boxtool.rb

      I would like to pass a variable from main.rb to rs_boxtool.rb, setting the size of the box. The idea is to use @boxheight as a variable. Is that possible?

      main.rb:

      require ('as_plugins/as_rubyeditor/snippets/rs_boxtool.rb')
      @boxheight = 100 # It's a variable inside the tool, but it dont work!
      boxtool = BOX_tool.new
      Sketchup.active_model.select_tool boxtool
      

      rs_boxtool.rb:

      class BOX_tool
        def initialize
          @mod = Sketchup.active_model 
          @ent = @mod.entities 
          @view = Sketchup.active_model.active_view
         
          @state = 0
          inches = 1
          @mm = inches.to_mm
          
          #@boxheight = 1800/@mm # --> This sould be accessed from the rs_boxcall.rb file
      
           #---box def.start---
           @pts = []        
           @pts[0] = [0,0,0]
           @pts[1] = [0,0,@boxheight]
           @pts[2] = [0,@boxheight,@boxheight]
           @pts[3] = [0,@boxheight,0] 
                     
           #---box def.slut---  
        end
      
        def activate 
           
        end 
      
        def onMouseMove(flags, x, y, view) 
           
           if (@state == 0) # Create box_group
             ip = Sketchup;;InputPoint.new
             ip.pick view, x,y
             ip = ip.position 
       
            @yv_group =Sketchup.active_model.entities.add_group
            @yv_face1 = @yv_group.entities.add_face (@pts[0], @pts[1], @pts[2], @pts[3]) # basis side
                
            point = Geom;;Point3d.new ip 
            new_transform = Geom;;Transformation.new point  
            @yv_group.transformation = new_transform
            @state = 1
          end
      
          if (@state == 1) # box follow mousemove
            ip = Sketchup;;InputPoint.new
            ip.pick view, x,y
            ip = ip.position       
            
            Sketchup.status_text = "@state = 1 ; Inputpoint; ", ip 
            point = Geom;;Point3d.new ip 
            new_transform = Geom;;Transformation.new (point)
            @yv_group.transformation =  new_transform
          end
      
          if (@state == 2) # onLMouseButton place boxgroup in choosen position
            ip = Sketchup;;InputPoint.new
            ip.pick view, x,y
            ip = ip.position 
            ip = ip.x-0.1/@mm, ip.y , ip.z
      
            Sketchup.status_text = "@state = 2 ; Inputpoint; ", ip 
            point = Geom;;Point3d.new ip 
            new_transform = Geom;;Transformation.new (point)
            @yv_group.transformation = new_transform
            @ip1 = ip
            @state = 3
                       
          end   
        def onLButtonDown(flags, x, y, view)
          if (@state == 3)
             self.reset
          end
      
          if (@state == 1)
            @state = 2
          end
        end # onLButtonDown
      
      end
      
        def reset
          @state = 0
        end
      end # class BOX_tool
       
           #boxtool = BOX_tool.new 
           #Sketchup.active_model.select_tool boxtool
      

      Thanks in advance.

      -Rasmus


      Get a Ruby

      1 Reply Last reply Reply Quote 0
      • A Offline
        Aerilius
        last edited by

        @unknownuser said:

        @boxheight = 100 # It's a variable inside the tool, but it dont work!

        In main.rb, it's an (undefined) variable outside the tool.
        In rs_boxtool.rb, it's an instance variable that does not exist as long as you haven't created an instance of the class (that's what you do later with boxtool = BOX_tool.new)

        One possibility is to make the instance variable available from outside via attr_accessor [the link is for Module but it works for class instances too (?)]. You can then change the instance variable (under the condition that you first create the instance):

        require ('as_plugins/as_rubyeditor/snippets/rs_boxtool.rb')
        boxtool = BOX_tool.new
        boxtool.boxheight = 100
        Sketchup.active_model.select_tool boxtool
        
        class BOX_tool
          attr_accessor ;boxheight
          # ...
        end
        

        attribute_accessor basically creates a new method (with the same name like the variable) to change the variable's value.

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

          Typically...
          Common named Modules share @variables across sessions, until overwritten.
          Common named Classes share @@variables across sessions, AND @variables per class-instance, until overwritten.

          TIG

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

            @rvs1977 said:

            I would like to pass a variable from "main.rb" to "rs_boxtool.rb", ....

            In Ruby.. the file does not create a namespace context (like it does in Python.)

            In other words... the beginning and end of a file, means nothing to Ruby. It is not the beginning and ending of code, in Ruby's eyes, it's just a bunch of lines of code.

            You must explicitly declare your own namespace (using module,) in BOTH files, so that the code from each file, runs within the same context. In that way.. the files can access variables defined in either file.

            If you do not wrap your code within an author module (say module RVS as an example,) then the code will run within the TOPLEVEL_BINDING which is class Object.
            The problem is that EVERYTHING in Ruby is an object, and therefor a subclass of Object, and your variables, methods, etc. in the unwrapped code will propagate into EVERYONE's classes and modules.. ie ALL other objects.

            See these threads where other persons asked almost the same question:
            how toget a Settings Menu to communicate with a Main Menu?
            and:
            Program format

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • R Offline
              rvs1977
              last edited by

              First of all, thank you for all the answers. Its really helpful.

              Even though its a little abstract to me right now, I know which direction to go. I belive the answer is using an author module. I will try to find out the difference between module and class


              Get a Ruby

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

                @rvs1977 said:

                I will try to find out the difference between module and class

                The difference is simple:

                class Class is a subclass of class Module.

                Generally... when you need ONE copy of some code, you use a Module. (Also when you need to create a namespace, or subnamespaces, to separate the execution context of some code, from all other code,... be it your code or the code from the rest of the world.)

                When you need instances (multiple copies,) of some code, you use a Class, and create instances using the class' constructor method new(). (There are situations when you must use a Class, but only ONE instance is allowed. This is called a singleton class.)

                Good rules to follow for classes:

                1) Only Ruby base classes should be defined as a global class, at the toplevel.

                2) Author classes that will be used by more than one of your plugins, should be defined, just inside your author toplevel namespace (module.)

                3) Each one of your plugins should be defined within a submodule (at some nesting level that YOU choose,) inside your author toplevel namespace (module.)

                4) An author class, that is specific to a certain plugin, should be defined within that plugin's submodule.

                Just as you would organize your directory hierarchy, where your code files reside... you can organize your namespace hierarchy in the same manner.

                I talk about it in this tutorial:
                [ Code ] SketchupExtension and rbs rubies

                I'm not here much anymore.

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

                  BTW.. did you install the full Ruby version ??
                  Ruby (v1.8.6-p287) Windows One-Click Installer

                  When you do.. you will have the full CHM file for
                  "Programming Ruby - The Pragmatic Programmer's Guide, 1st Ed."
                  in your "C:/Ruby186/doc" directory.

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • R Offline
                    rvs1977
                    last edited by

                    I get the point using namespaces, so I decided to find out how module works by making the simpelts possible example... and it dont work πŸ˜•

                    Again with 2 files:

                    • rs_main.rb, and
                    • rs_moduletest.rb

                    From rs_main.rb I call a method defined inside rs_moduletest.rb. The method then should write in a messagebox "Hello World".

                    rs_main.rb:

                    module RVS; end
                    module RVS;;MyPlugin 
                    
                        # declare module vars and constants first
                        @@myHelloVar = 'Hello World'
                        
                        
                        # require other parts of this plugin;
                        require('as_plugins/as_rubyeditor/snippets/rs_moduletest.rb')
                        
                        # main plugin script, menu items, etc.
                        MyPlugin.test() # Calling the test-method from rs_moduletest.rb
                    
                    end #module RVS;;MyPlugin 
                    

                    rs_moduletest.rb

                    module RVS;;MyPlugin 
                    	public
                    	def self.test ()
                    		UI.messagebox @@myHelloVar 
                    	end
                    	
                    end #module RVS;;MyPlugin 
                    

                    how should this be written to work?


                    Get a Ruby

                    1 Reply Last reply Reply Quote 0
                    • R Offline
                      rvs1977
                      last edited by

                      @dan rathbun said:

                      BTW.. did you install the full Ruby version ??
                      Ruby (v1.8.6-p287) Windows One-Click Installer

                      When you do.. you will have the full CHM file for
                      "Programming Ruby - The Pragmatic Programmer's Guide, 1st Ed."
                      in your "C:/Ruby186/doc" directory.

                      No I havn't. But I will πŸ˜„


                      Get a Ruby

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

                        "rs_moduletest.rb":
                        remove the space between the method name and the opening "(" for the argument list. Never put spaces between them, either when defining them, or calling a method. An error can occur that gives very weird messages in Ruby 1.8.6.

                        "rs_main.rb":
                        What you are doing wrong is trying to call a method from within namespace RVS::MyPlugin that is first looking within that namespace for a constant identifying an object named MyPlugin, but there not one.. so second, Ruby goes up to the top level and looks there again for a constant identifying an object named MyPlugin, but again does not find one, so it raises a NameError exception.

                        Either:

                        1) use the self keyword, which within a module, returns a reference to the module itself.
                        so line 12, can be:
                        self.test()

                        or 2) define your plugin methods within a proxy class block:
                        "rs_moduletest.rb":

                        module RVS;;MyPlugin
                          class << self
                            public
                            def test()
                              UI.messagebox( @@myHelloVar )
                            end
                          end # proxy class 
                        end #module RVS;;MyPlugin
                        

                        Notice how in this case you do not define the method prefixed with " self." ??
                        then in "rs_main.rb", you simply call the method by name only, as you would in a class instance:
                        test()
                        You may also use the global method private (instead of public,) if you wished your module's test method to be called only (easily,) from within it's module.

                        Also... the method test() is a very important global method for testing files and directories, and it is inherited by your modules.
                        But since, they are YOUR modules, you are allowed to override inherited methods. If you still wanted access to the global method, you would need to qualify it's call as:
                        Kernel.test(?d,"C:/Ruby186")
                        which tests if "C:/Ruby186" exists and is a directory.

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • R Offline
                          rvs1977
                          last edited by

                          Finally it works!!... πŸ˜„

                          BUT I had to move the rs_main.rb from the "\Plugins\as_plugins\as_rubyeditor\snippets"-folder to the "\Plugins"-folder, and then restart SU. At start up it showed the Alertbox "Helle World".

                          BUT It won't work if I use the playbutton in AS-code editor. It seems like, when using modules, it has to be loaded into SU at startup.

                          I wonder if there is a way to come around this?

                          EDITED 1: It can be run directly from the snippet folder with ruby console (then SU requires no restart):
                          load 'c:\path to the program\Google SketchUp 7\Plugins\as_plugins\as_rubyeditor\snippets\rs_main.rb'

                          EDITED 2: in rs_main.rb require is changed to load. Then it updates the variables when its changed.

                          So far so good! Thank you...


                          Get a Ruby

                          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