[Code]Text label system
-
Hej, i'm new to ruby but i'm trying to make an label/adressing system.
I would like to make a tool when i select a component and i run the tool (by shortcut), it places an text label at a fixed position relative to the center of the component or at the right-front-upper corner of the boundingbox.
next step in my todo list is that the textlabel will be automatically increasing.
workflow of my tool should be:
->select component
-> run tool
-> label gets placed "1"
-> select next component
-> run tool
-> label gets placed "2"
-> etcIm not asking for a complete ready code, but ive got some problems with taking of:)
heres wat ive got for now, but the issue i have now is that the boudingbox is not working
<span class="syntaxdefault"></span><span class="syntaxkeyword">class </span><span class="syntaxdefault">AdressingTool<br /><br />def Start <br /> </span><span class="syntaxkeyword">@</span><span class="syntaxdefault">inpp</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">10</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">10</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">10 </span><span class="syntaxcomment">#inputpoint will be replaced by the value of the center of the boundingbox<br /> </span><span class="syntaxkeyword">@</span><span class="syntaxdefault">vec</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">10</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">10</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">10 </span><span class="syntaxcomment">#Distance<br /> <br /> </span><span class="syntaxdefault">bb </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Geom</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">BoundingBox</span><span class="syntaxkeyword">.new;<br /> </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">selection</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each </span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">| </span><span class="syntaxdefault">bb</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">bounds</span><span class="syntaxkeyword">) ; }<br /> </span><span class="syntaxdefault">boundb </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">bb</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">bounds<br /> center </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">boundb</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">center<br /> UI</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">messagebox center<br /> <br /> mod</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model<br /> ent</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities<br /> txt</span><span class="syntaxkeyword">=</span><span class="syntaxstring">'Adress comes here'<br /> </span><span class="syntaxdefault">t</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">ent</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_text txt</span><span class="syntaxkeyword">,@</span><span class="syntaxdefault">inpp</span><span class="syntaxkeyword">,@</span><span class="syntaxdefault">vec<br />end<br /><br />end </span><span class="syntaxcomment">#end of Class AdressingTool<br /><br /> </span><span class="syntaxdefault">plugin_menu </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">UI</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">menu</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"Plugins"</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">add_item</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"Add adress"</span><span class="syntaxkeyword">) { <br /> </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">select_tool AdressingTool</span><span class="syntaxkeyword">.new } </span><span class="syntaxdefault"></span>
-
@patrickbel said:
heres wat ive got for now, but the issue i have now is that the boudingbox is not working
Exactly what "isn't working"? You need to be more specific before we can assist.
-
A few things I can see...
Methods [def xxx] always start with a lowercase letter, so it's NEVER
def **S**tart
However, the 'start method' that is called when a class is run is always named
def **initialize**()
anyway !You then use this method to setup your references -
@model=
etc...
In a very simple tool you can include all of your code in that method too...Specify points and vectors as arrays
[x,y,z]
OR as proper objectsGeom::Vector3d(x,y,z)
etc.As you currently use only the one method then there is no need to use '@' references [which are used so as to be recognized across the class's methods...] - so a plain reference of '
vec
' rather than@vec
will suffice because you aren't going to use it in another method...You create a boundingbox, then add the bounds of everything selected into it - thus making one giant boundingbox.
I assume you want to use the boundingbox of each selected object to place some text ?
If so, do it thus:
` Sketchup.active_model.selection.each**{**|e| bb=e.boundsdo an iterated text placement here on 'bb'
} ### finally close the 'block' here with the } ...`
You already have a boundingbox [
bb
], so there's NO need to confuse things by redefining it withboundb = bb.bounds
which actually breaks it !You currently get the boundingbox center with
center = **bb**.center
BUT then you don't use it.
Also note that as it's the object's 'center' it might mean that the text is 'internal' to the object
Why not usept=bb.max
=="top-right corner" - then use 'pt
' in theadd_text()
code as the point used to insert the text, rather than the now completely redundant '@inpt
'...Note how [ruby:3fg66dk7]ent=model.entities[/ruby:3fg66dk7] would be better set as [ruby:3fg66dk7]ent=model.active_entities[/ruby:3fg66dk7], because otherwise you could be adding text related to an object in the model's context when you are actually editing a containing group's context ! ... [ruby:3fg66dk7]model.active_entities[/ruby:3fg66dk7] can actually be [ruby:3fg66dk7]model.entities[/ruby:3fg66dk7] OR say [ruby:3fg66dk7]group.entities[/ruby:3fg66dk7] etc depending on the current context...
It seems your 'txt' isn't always to be the same ? So not [ruby:3fg66dk7]txt='Adress comes here'[/ruby:3fg66dk7] BUT rather an incrementing [ruby:3fg66dk7]'1'[/ruby:3fg66dk7], [ruby:3fg66dk7]'2'[/ruby:3fg66dk7] etc.
To enable this you need to set a [ruby:3fg66dk7]@@txt[/ruby:3fg66dk7] reference in the class itself BUT just before the [ruby:3fg66dk7]def initialize()[/ruby:3fg66dk7] line as [ruby:3fg66dk7]@@txt='0'[/ruby:3fg66dk7].
Now make the first line of the [ruby:3fg66dk7]...each{|e| bb=e.bounds[/ruby:3fg66dk7] to be like this
[ruby:3fg66dk7]...each{|e| @@txt.next!
bb=e.bounds
###...[/ruby:3fg66dk7]
Then the [ruby:3fg66dk7]@@txt[/ruby:3fg66dk7] should be used in theadd_text()
code rather than current '[ruby:3fg66dk7]txt[/ruby:3fg66dk7]'.
Explanation: when the tool is first loaded [at startup] the reference [ruby:3fg66dk7]@@txt[/ruby:3fg66dk7] is initially set to be [ruby:3fg66dk7]'0'[/ruby:3fg66dk7].
When the tool is first run the first selected object is processed and the reference is incremented to be [ruby:3fg66dk7]'1'[/ruby:3fg66dk7], when the next object is processed the iteration steps up to be [ruby:3fg66dk7]'2'[/ruby:3fg66dk7] etc. If you use the tool later on [in that same session] the [ruby:3fg66dk7]@@txt[/ruby:3fg66dk7] reference will have been remembered with its last used value, so the next use it'll be say [ruby:3fg66dk7]'3'[/ruby:3fg66dk7] ...I won't go into making it modular too much but it'd be along these lines
require 'sketchup.rb' module PatrickBEL UI.menu("Plugins").add_item("Add address"){Sketchup.active_model.select_tool(self;;AdressingTool.new())} class self;;AdressingTool def initialize() ### code goes here end end#class ens#module
Also note how it's easier if you enclose big lumps of code inside a [ code ] block rather than a [ ruby ] one...
Also note that since this uses none of the 'Tool' methods [like point picking etc] it doesn't need [ruby:3fg66dk7]{Sketchup.active_model.select_tool(...)}[/ruby:3fg66dk7] and a simple [ruby:3fg66dk7]{self::AdressingTool.new()}[/ruby:3fg66dk7] will suffice. If you were to rewrite it to let you pick objects in turn then it would become a 'Tool' and you WILL need to be run as such !Hope all of this helps... sorry about the stream-of-consciousness format...
-
Hej TIG,thanks alot!!
I'm working on it now i'll post the result later. -
Hej, This is what i got for now.
It works as should but now i need some improvements.
-I would like to have a gui or a data input, where i can change the adr,offset,univ values
I found some information about making input dialogs and so but im not really sure where to put it.-the general worflow of the tool could be.
Plugin menu 1 item, 2submenus: Adress and Adress options.
select component, run by shortcut Adress (label gets placed)
select next component, run by shortcut Adress (incremented label gets placed)The problem now is that the AdressTool doesn't "quit" automaticly to go back to selection mode. so i can select the next component and run the tool again.
require 'sketchup.rb' module PatrickBEL #UI.menu("Plugins").add_item("Add address"){Sketchup.active_model.select_tool(self;;AdressingTool.new())} submenu = UI.menu("Plugins").add_submenu("Adressing") submenu.add_item("Add address"){Sketchup.active_model.select_tool(self;;AdressingTool.new())} class self;;AdressingTool @@adr= 1 @@offset= 5 @@univ='A' @@count= 0 def initialize() vec= [10,10,10] #Distance bb = Geom;;BoundingBox.new Sketchup.active_model.selection.each {|i| bb=i.bounds @@txt =@@univ + "." + @@adr.to_s @@adr = @@adr + @@offset pt=bb.max UI.messagebox(@@txt) model=Sketchup.active_model ent=model.active_entities t=ent.add_text @@txt,pt,vec } end end#class end#module
-
Within your existing module []just before the class ends make a new method with the dialog's details
def self.dialog() results=inputbox(["Start Number; ","Offset Number; ","Prefix String; "],[@@adr, @@offset, @@univ],"AdressingTool-Settings") return nil unless results ### i.e. the user canceled! @@adr, @@offset, @@univ = results end
Run this from a second item in the submenu code [added just after the first submenu entry]...
submenu.add_item("Settings"){self;;AdressingTool.dialog()}
Also [TIP} to make it one step undo-able add
Sketchup.active_model.start_operation('AdressingTool')
just before you process the selection andSketchup.active_model.commit_operation
after the closing '}'. Also remove the UI.messagebox between each text placement and define 'model=' and 'ent=' at the initialize method's start rather than every iteration of the selection!
To exit the tool at the end of the initialize method [after the closing '}'] insert
Sketchup.send_action("selectSelectionTool:")
If you want to be able to select objects whilst within the tool then this is a whole extra area where you make it a Tool with activate() and other methods to read mouse position and clicks etc and deduce the object below the cursor etc etc... Let's get this working first !
There's a lot that could be tidied but you are getting there -
This is my code for now, and works perfect except for 1 thing.
If i select more then one component, it doesn't work, it seems like it only runs one time the iteration.
Just out of interest, i'm not sure why i'm using @@ now for each variable.
Is there a way to adopt the layout of my text and change the size to "height" instead of point -size.
require 'sketchup.rb' module PatrickBEL #UI.menu("Plugins").add_item("Add address"){Sketchup.active_model.select_tool(self;;AdressingTool.new())} submenu = UI.menu("Plugins").add_submenu("Adressing") submenu.add_item("Add address"){Sketchup.active_model.select_tool(self;;AdressingTool.new())} submenu.add_item("Settings"){self;;AdressingTool.dialog()} class self;;AdressingTool @@adr= 1 @@offset= 1 @@univ='A' @@count= 0 @@vec= [0,0,0] #Distance def initialize() model=Sketchup.active_model ent=model.active_entities bb = Geom;;BoundingBox.new Sketchup.active_model.selection.each {|i| Sketchup.active_model.start_operation('AdressingTool') bb=i.bounds @@txt =@@univ + "." + @@adr.to_s @@adr = @@adr + @@offset pt=bb.max t=ent.add_text @@txt,pt,@@vec t.display_leader = False Sketchup.send_action("selectSelectionTool;") } Sketchup.active_model.commit_operation end def self.dialog() results=inputbox(["Start Adress; ","Offset Number; ","Universe; ","Adr-posx;","Adr-posy;","Adr-posz;"],[@@adr, @@offset, @@univ, @@vec[0],@@vec[1],@@vec[2]],"PatrickBel-AdressingTool") return nil unless results ### i.e. the user canceled! @@adr, @@offset, @@univ, @@vec[0],@@vec[1],@@vec[2] = results end end#class end#module
-
Plain variables, or perhaps more correctly 'references', [e.g. x] are only used/changed in their specific def [method] that defines them.
Ones starting with @ [e.g. @x] - their current value is accessible to all methods during that instance of the class/module. Any method can define or redefine them,
Ones starting with @@ [e.g. @@x] are similar to @ ones, BUT their current value is remembered across multiple uses of that class/module - e.g. good for remebering values last used in dialogs. They need to be 'declared' outside of any method, but after that any method can then redefine them.
Constants [starting with a capital letter, or commonly with all caps, e.g. Z_AXIS] are similar to @@ ones, they are remembered across all uses of that class/method, BUT they are not readily changeable - because they are 'constants'!Move your 'start_operation' out of the iteration block [to match the 'commit_'] that way all we become 'undo-able' in one go.
The selection.each{} block adds a piece of text to every selected object when the code starts.However, the Sketchup.send_action("selectSelectionTool:") will stop more that one iteration.
It simply exits the tool and activates the 'Select' tool.If you want to be able to 'pick objects' in turn you will need to [re]write/launch this as a proper Tool... this will involve getting input-points, reading mouse-positions and mouse-clicks etc... Then using those for new text objects etc...
See the API and examples - 'linetool.rb' etc - for some Tool method ideas/examples...
Or other authors' tools' .rb files - like say some of my 2dTools...There is limited access to 'Text' objects' properties through the API - see the relevant pages - http://code.google.com/apis/sketchup/docs/ - height is not one of them - unless you make it as '3d-text'... It's a long standing request...
Advertisement