Hi all,
I have a plugin that i operate from the extension menu.
I want to create an icon for it, that I can place on the toolbar.
How can I do it?
thank you
Hi all,
I have a plugin that i operate from the extension menu.
I want to create an icon for it, that I can place on the toolbar.
How can I do it?
thank you
Maybe this will help:
ICON_PATH = File.join(PLUGIN_PATH, "icons", "TEMPLATE.png").freeze
And:
unless @loaded
@loaded = true
cmd_TEMPLATE.large_icon = cmd_TEMPLATE.small_icon = ICON_PATH
cmd_TEMPLATE.tooltip = "TEMPLATE, TEMPLATE and TEMPLATE."
cmd_TEMPLATE.status_bar_text = "TEMPLATE."
UI.menu("Tools").add_item(cmd_TEMPLATE)
toolbar = UI::Toolbar.new("TEMPLATE")
toolbar.add_item(cmd_TEMPLATE)
toolbar.restore
end
Iād recommend a tweak to the toolbar code.
At the end use
#toolbar.restore
toolbar.show if toolbar.get_last_state.abs == 1 # TB_VISIBLE/NEVER
Otherwise you might annoy the user who has the toolbar switched off when it reopens when SketchUp next opensā¦
Hi TIG, I just did a test by disabling an extension in the Extension Manager and the extension / toolbar button did not load. Am I missing a case? I just saved what I shared as my TEMPLATE, so now would be the time to adjust it!
In my opinion and experience
toolbar.restore
does what TIGs code does. (There was a different scenarios in earlier versions but it is goneā¦)
Edit:
Just a quick search about it:
Because you are only posting snippets of code and not fully constructed modules etc, and we donāt even know if you have constructed this as an extension at allā¦
Either give us all of you files, or read up some more and try to make a fleshed-out simple extension with a toolbar button etcā¦
Okay, I read that but didnāt test. Maybe one difference was Johnās Mac (as he suggested)?
What I did test was opening SU ('24), disabling in Extension Manager and then NOT closing SU (both version of code). Then opening another instance of SU (Toolbar was present in both cases). Then, same as above but closing SU and then opening another instance of SU (Toolbar not visible: as expected on my machine). So I did not see a difference.
For completeness, this is my āruby mainā template:
require 'json'
module IDKProgramming
module TEMPLATE
extend self
@dialog = nil
@loaded = false
def show_html_dialog
@dialog ||= create_dialog
attach_callbacks unless @dialog.visible?
@dialog.visible? ? @dialog.bring_to_front : @dialog.show
end
def create_dialog
UI::HtmlDialog.new({
dialog_title: "TEMPLATE",
preferences_key: PREF_KEY,
scrollable: true,
resizable: true,
width: 800,
height: 600,
style: UI::HtmlDialog::STYLE_DIALOG
}).tap { |dialog| dialog.set_file(File.join(PLUGIN_PATH, 'html', 'TEMPLATE.html')) }
end
def attach_callbacks
# Attach a callbacks.
end
unless @loaded
@loaded = true
cmd_TEMPLATE = UI::Command.new("TEMPLATE") { show_html_dialog }
cmd_TEMPLATE.large_icon = cmd_TEMPLATE.small_icon = ICON_PATH
cmd_TEMPLATE.tooltip = "TEMPLATE, TEMPLATE and TEMPLATE."
cmd_TEMPLATE.status_bar_text = "TEMPLATE."
UI.menu("Tools").add_item(cmd_TEMPLATE)
toolbar = UI::Toolbar.new("TEMPLATE")
toolbar.add_item(cmd_TEMPLATE)
toolbar.restore
end
end
end
module IDKProgramming
module TEMPLATE
PLUGIN_PATH = File.dirname(__FILE__).freeze
PREF_KEY = Module.nesting[0].name.gsub('::', '_')
ICON_PATH = File.join(PLUGIN_PATH, "icons", "TEMPLATE.png").freeze
require File.join(PLUGIN_PATH, 'TEMPLATE_main.rb')
end
end
I did remove the following line of code for the html dialog because the OP had only mentioned the making the toolbar button.
cmd_TEMPLATE = UI::Command.new("TEMPLATE") { show_html_dialog }
Because there were an old bugs with UI::Toolbar#restore
and UI::Toolba#show
(as discussed in the topic linked above,) ā¦ I have been in the habit of using this:
toolbar.get_last_state == TB_NEVER_SHOWN ? toolbar.show : toolbar.restore
It always seemed to work as we expect, so Iāve never broke from this āhabitā.
Thomasā suggestion that UI::Toolbar#restore
does what my āhabitualā statement does, is still not declared in the documentation, now 6 years later.
Hi Everyone,
thank you for your responses,
I want to clarify myself,
I have the extension from TIG
and I want to create an Icon for it on the toolbar.
How can I do so?
Please give me the easy way, Iām newbie.
thank you.
That is a very old plugin [i.e. itās not written as an extension - but it will work and is editable.
First fnd the file in the Plugins folder named āTIG-Cut_to_planeā
Edit it with a plain text editor like Notepad++.exe
Towards the end of the code is the part which sets up the menu and context-menu items.
You need to add some extra toolbar codeā¦
Just before the closing part
end#if loaded
file_loaded(__FILE__)
add in this extra code
### TOOLBAR
cmd = UI::Command.new("TIG-Cut_to_plane"){Sketchup.active_model.select_tool(TIG::Cut_to_plane.new())}
cmd.tooltip = "TIG-Cut_to_plane"
cmd.status_bar_text = "TIG-Cut_to_plane"
c2pfolder = File.join(File.dirname(__FILE__), "TIG-Cut_to_plane")
cmd.small_icon = File.join(c2pfolder, 'c2p.svg')
cmd.large_icon = File.join(c2pfolder, 'c2p.svg')
c2ptoolbar = UI::Toolbar.new("TIG-Cut_to_plane")
c2ptoolbar.add_item(cmd)
c2ptoolbar.show if c2ptoolbar.get_last_state.abs == 1 # TB_VISIBLE/NEVER
###
You also need to add a subfolder into Plugins named āTIG-Cut_to_planeā
Inside this you need the image file to form the toolbar button icon.
Iāve named it āc2p.svgā.
Youāll need a tool like Inkscape to make the svgā¦
After making the changes/additions and saving, and restarting SketchUp the new toolbar should be available and workingā¦
Hello TIG,
Is this your plugin? it is perfect, It is my favorite plugin. You said it is old, if you have another one that works better I would like to get it.
Sorry, but I really didnāt understand how to do what you have kindly elaborated.
I am not a coder, and donāt know what does it mean closing part,
Can you please put the code in TIG cut to plane and send me, it will help me a lot.
Thank you in advance.
Eyal
This is the code TIG mentioned with the suggested code for the toolbar inserted. Look in the last āparagraphā of code to see it.
=begin
TIG (c) 2013
###
TIG-Cut_to_plane.rb
###
Installation: Place this file in the Plugins folder and restart Sketchup.
Usage: Plugins menu > 'TIG-Cut_to_plane'
or with a suitable selection use the context-menu 'TIG-Cut_to_plane'
Note for Pro >=v.8 only...
Preselect a 'solid' object [group or component_instance].
Activate the tool.
Follow the prompts and pick 3 points to define a plane.
Picking these points CWS cuts to leave the part ABOVE the plane.
Picking these points CCWS cuts to leave the part BELOW the plane.
If you press <Enter> instead of picking point 3 then the plane is defined
'vertically', the direction of the 'line' between the first 2 points will
determine what will be left behind, i.e. the part to the 'LEFT' of the 'line'.
If the points 1 and 2 are vertically aligned then no vertical plane can be
defined, there is a warning message and you need to pick point 3, OR abort,
say by pressing <Spacebar>.
The selected object will then be cut to the defined plane.
The new cut group made from the 'cut' operation retains the original object's
locked/hidden-state, shadow-casting/receiving-behavior, name*, material, layer
and any attribute-dictionaries attached to it.
*If the original was a group the 'cut' group takes its name, if it was a
component-instance the 'cut' group takes its definition name, but if that
instance also had a name then this is appended to the new name inside [].
The 'cutting' is one step undo-able.
Donations: PayPal.com info @ revitrev.org
Version:
1.0 20121007 First issue.
1.1 20130107 Now at Point 3 an alternative <Enter> press cuts vertically,
keeping left-side parts. Context-menu if selection suitable.
=end
###
require('sketchup.rb')
###
module TIG
class TIG::Cut_to_plane
def initialize()
unless Sketchup.is_pro? and Sketchup.version.to_i>=8
UI.messagebox("TIG-Cut_to_plane.rb\n\nOnly works with Pro, >=v.8")
return nil
end
@ip = nil
@ip1 = nil
@ip2 = nil
@ip3 = nil
end
def activate
@state=0
@pts = []
@ip = Sketchup::InputPoint.new
@ip1 = Sketchup::InputPoint.new
@ip2 = Sketchup::InputPoint.new
@ip3 = Sketchup::InputPoint.new
@model=Sketchup.active_model
@ss=@model.selection
@ents=@model.active_entities
unless self.selection_solid?()
UI.messagebox("TIG-Cut_to_plane:\n\nSelect ONE 'solid' group/component-instance !")
return nil
end
@msg="TIG-Cut_to_plane: Pick Point 1 on Plane..."
Sketchup.set_status_text(@msg)
@lok=@gp.locked?
@hid=@gp.hidden?
@shc=@gp.casts_shadows?
@shr=@gp.receives_shadows?
if @gp.is_a?(Sketchup::ComponentInstance)
@nam=@gp.definition.name
unless @gp.name.empty?
@nam=@nam+"["+@gp.name+"]"
end
else ### it's a Group
@nam=@gp.name ### might be "" !
end
@mat=@gp.material
@lay=@gp.layer
@ads=@gp.attribute_dictionaries
end
def deactivate(view)
view.invalidate
@ip1 = nil
@ip2 = nil
@ip3 = nil
return nil
end
def onCancel(flag, view)
view.invalidate
@ip1 = nil
@ip2 = nil
@ip3 = nil
Sketchup.send_action("selectSelectionTool:")
return nil
end
def resume(view=nil)
Sketchup.set_status_text(@msg)
end
def getExtents
bb=Geom::BoundingBox.new
if @ip.valid? && @ip.display?
bb.add(@ip.position)
end
@pts.each{|p|bb.add(p)}
return bb
end
def onMouseMove(flags, x, y, view)
return nil if @state>2
case @state
when 0 # getting the first point
@ip.pick(view, x, y)
if @ip.valid? && @ip != @ip1
@ip1.copy!(@ip)
end
view.invalidate
view.tooltip = @ip.tooltip if @ip.valid?
when 1 # getting the second point
@ip.pick(view, x, y, @ip1)
if @ip.valid? && @ip != @ip2
@ip2.copy!(@ip)
end
view.invalidate
view.tooltip = @ip.tooltip if @ip.valid?
when 2 # getting the third point
@ip.pick(view, x, y, @ip2)
if @ip.valid? && @ip != @ip3
@ip3.copy!(@ip)
end
view.invalidate
view.tooltip = @ip.tooltip if @ip.valid?
end
end
def onLButtonDown(flags, x, y, view)
return nil if @state>2
@ip.pick(view, x, y)
if @ip.valid?
case @state
when 0
if @ip.valid?
@pts[0] = @ip.position
@msg="TIG-Cut_to_plane: Pick Point 2 on Plane..."
Sketchup.set_status_text(@msg)
@state = 1
end
when 1
if @ip.valid? && @ip != @ip1
@pts[1] = @ip2.position
@state = 2
@msg="TIG-Cut_to_plane: Pick Point 3 on Plane, OR Press <Enter> for a Vertical Split..."
Sketchup.set_status_text(@msg)
end
when 2
if @ip.valid? && @ip != @ip1 && @ip != @ip2
@pts[2] = @ip3.position
@state = 3
view.invalidate
@msg="TIG-Cut_to_plane: Trimming..."
Sketchup.set_status_text(@msg)
self.trim(view)
view.lock_inference
return nil
end
end
end
end
def draw(view)
return unless @ip
return nil if @state>2
if @ip.valid? && @ip.display?
@ip.draw(view)
@drawn = true
end
if @state == 1
view.set_color_from_line(@ip1, @ip)
view.draw(GL_LINE_STRIP, @ip1.position, @ip.position)
@drawn = true
elsif @state == 2
view.drawing_color = "gray"
view.draw(GL_LINE_STRIP, @ip1.position, @ip2.position)
view.set_color_from_line(@ip2, @ip)
view.draw(GL_LINE_STRIP, @ip2.position, @ip.position)
@drawn = true
end
end
def onKeyDown(key, repeat, flags, view)
return nil if @state>2
if key == CONSTRAIN_MODIFIER_KEY && repeat == 1
@shift_down_time = Time.now
if view.inference_locked?
view.lock_inference
elsif @ip.valid?
view.lock_inference(@ip)
end
end
end
def onKeyUp(key, repeat, flags, view)
return nil if @state>2
if key == CONSTRAIN_MODIFIER_KEY && view.inference_locked? && (Time.now - @shift_down_time) > 0.5
view.lock_inference
end
end
def onReturn(view)
return nil unless @state==2
if @pts[0].vector_to(@pts[1]).parallel?(Z_AXIS)
UI.messagebox("TIG-Cut_to_plane:\n\nPoints 1 and 2 are Aligned Vertically.\nA Vertical Cut is Impossible !")
@msg="TIG-Cut_to_plane : Pick Point 3 on Plane..."
Sketchup.set_status_text(@msg)
return nil
else
@pts[2] = @pts[1].offset(Z_AXIS)
end
view.invalidate
@msg="TIG-Cut_to_plane : Trimming..."
Sketchup.set_status_text(@msg)
self.trim(view)
view.lock_inference
@state = 3
return nil
end
###
def selection_solid?()
return nil unless @ss
return nil unless @ss[0]
return nil if @ss[1]
@gp=@ss[0]
return nil unless @gp.is_a?(Sketchup::Group) || @gp.is_a?(Sketchup::ComponentInstance)
return nil unless @gp.manifold?
return true
end
def trim(view)
begin
@model.start_operation("Cut_to_plane")
ct=@pts[0]
v1=@pts[0].vector_to(@pts[1])
v2=@pts[0].vector_to(@pts[2])
ve=v1.cross(v2)
ve=Z_AXIS if ve.length==0
bb=@gp.bounds
ra=4*ct.distance(bb.center)
ra=2*bb.diagonal if 2*bb.diagonal>ra
tgp=@ents.add_group()
tents=tgp.entities
es=tents.add_circle(ct, ve, ra, 8)
fa=tents.add_face(es)
fa.pushpull(ra)
if ct.z==0 and ve.parallel?(Z_AXIS) and ve==Z_AXIS
fa.reverse!
end
ob=tgp.subtract(@gp)
if ob and ob.valid?
ob.locked=@lok
ob.hidden=@hid
ob.casts_shadows=@shc
ob.receives_shadows=@shr
ob.name=@nam
ob.material=@mat
ob.layer=@lay
@ads.each{|ad|
na=ad.name
ad.each_pair{|k,v|
ob.set_attribute(na, k, v)
}
}if @ads
@ss.add(ob)
end
@model.commit_operation
rescue
###
end
self.onCancel(0, view)
return nil
end
end#class
###
unless file_loaded?(__FILE__)
UI.menu("Plugins").add_item("TIG-Cut_to_plane"){Sketchup.active_model.select_tool(TIG::Cut_to_plane.new())}
UI.add_context_menu_handler{|menu|
ss=Sketchup.active_model.selection
if ss.length==1 && (ss[0].is_a?(Sketchup::Group) || ss[0].is_a?(Sketchup::ComponentInstance)) && ss[0].manifold?
menu.add_item("TIG-Cut_to_plane"){Sketchup.active_model.select_tool(TIG::Cut_to_plane.new())}
end
}
### Put the suggested code for the toolbar here.
cmd = UI::Command.new("TIG-Cut_to_plane"){Sketchup.active_model.select_tool(TIG::Cut_to_plane.new())}
cmd.tooltip = "TIG-Cut_to_plane"
cmd.status_bar_text = "TIG-Cut_to_plane"
c2pfolder = File.join(File.dirname(__FILE__), "TIG-Cut_to_plane")
cmd.small_icon = File.join(c2pfolder, 'c2p.svg')
cmd.large_icon = File.join(c2pfolder, 'c2p.svg')
c2ptoolbar = UI::Toolbar.new("TIG-Cut_to_plane")
c2ptoolbar.add_item(cmd)
c2ptoolbar.show if c2ptoolbar.get_last_state.abs == 1 # TB_VISIBLE/NEVER
end#if loaded
file_loaded(__FILE__)
###
end#module
You need to create the folder he mentioned and place it inside of your extension folder. It should be here: C:\Users\YourUserName\AppData\Roaming\SketchUp\SketchUp 2024\SketchUp\Plugins
Youāll need to create the icon and name it āc2p.svgā and put it in the folder.
Thank you 3DxJFD,
It is very helpful.
Good day.
Eyal