[Plugin][WIP] Layers Panel - Dev
-
-
I see you add a method to the base classes of the SketchUp API. Please do not do this. You risk clashing with other plugins. Or if the method is implemented in the future you will overwrite it. Safest thing is to keep everything in your own namespace.
More explanation and more general info:
http://www.thomthom.net/thoughts/2012/01/golden-rules-of-sketchup-plugin-development/List of things to beware of when developing and publishing SketchUp plugins:
http://www.thomthom.net/thoughts/2013/02/sketchup-plugin-checklist/As for your random bugsplat - when you deal with observers you need to be careful to validate all the info you get from the observers. You could be getting invalid data.
Also, I don't know if you do, but avoid modifying the model during observer events - this includes attributes. They can interfere with third party and native operations. -
Also, that method you used to delete a layer didn't wrap up in start_operation and commit_operation - so it'd flood the undo stack with lots of operations. I didn't see anywhere in your code where you do this.
-
@addLayerFromRuby = 'addLayerFromRuby("' + layer.name + '");'
Using the + operator to build string is slow.@addLayerFromRuby = "addLayerFromRuby('#{layer.name}');"
This is faster and shorter. (note I flipped the quotes) -
# Load TIG's layer-delete.rb require Sketchup.find_support_file('layer-delete.rb', 'Plugins/Layers Panel')
You cannot rely on plugins to be install in the Plugins folder.
See this article for more info:
http://www.thomthom.net/thoughts/2012/09/sketchup-plugins-can-be-installed-anywhere/ -
Hi,
If this is your first SketchUp plugin you sir are on your way to creating a masterpiece!
I hope that with the help of fellow sketchUcation members you solve the issues thomthom mentioned.
Cheers!
-
Thanks a lot TT for your answers and advice ! I'll take a look at all of this.
@thomthom said:
Safest thing is to keep everything in your own namespace.
It thought I did. Can you show what piece of code is wrong ?
@thomthom said:
(note I flipped the quotes)
Is there a reason for that ? It's better that way ?
-
@jiminy-billy-bob said:
What's NOT working :
[list][*]From ruby to WebDialog : Real-time rename layer, hide/show layer. Due to limitations of the LayersObserver. I'll need to detect changes either when the webdialog gets focus (But you won't have real-time visual feedback), or every xxx ms.
Actually, it may work. Not with the LayersObserver, but with the EntityObserver, which detects hide/show and rename events.
-
@jiminy-billy-bob said:
@thomthom said:
Safest thing is to keep everything in your own namespace.
It thought I did. Can you show what piece of code is wrong ?
The snippet that modified Sketchup::Layer .@jiminy-billy-bob said:
@thomthom said:
(note I flipped the quotes)
Is there a reason for that ? It's better that way ?
Because with double quoted strings you can do interpolation - like this
"Hello #{some_variable}"
where as in single quoted you cannot. -
@thomthom said:
The snippet that modified Sketchup::Layer
Ho, ok. I assumed TIG's work was clean. But this snippet is actually 4 years old, I guess he wasn't aware of that back then.
Thanks !
-
Basically, any modification of the Ruby or SketchUp API classes is bad practice. So are global variables.
There's some old code lingering around from the days before people started to figure out what best practices where. -
If I understand ruby classes correctly, I have to rewrite the code, right ?
I can't have something likelayer.delete()
while keeping it in my own namespace. Am I right ? -
Correct. Make a method under your own namespace that takes the layer as an argument.
Not as pretty, but it'll work and it will be safe from clashing with anything else.
-
Ok, here is a new version.
- Added Toolbar and menu item (Window > Layers Panel), with toggle
- Change things you TT told me : Undo, +operator, filename...
- Deleting layers now work properly. The method is wrapped in my namespace. When a layer has geometry, you are promped to choose to delete the content or move it to the default layer.
- Added a menu for some options. For now you can only purge layers.
- I also don't have bugsplats anymore. Don't know why exactly... If people get some, please tell me.
Still no saving, I'm getting used to ruby before attacking this big piece.
Also, I can't get my WebDialog callbacks to work if the dialog is not in a global variable. I tried local, instance, and class variables, nothing works. What am I doing wrong ?
-
Hmm, so a class variable in a class ? That makes sense ^^
Thanks for the tip, I'll try that. -
I hope that naming the Class "TEST" didn't confuse you since the class name doesn't have anything to do with the variables (var test = true) in html.
I guess what i am trying to say is that the "var test" in html has nothing to do with "Class TEST" in ruby.
Not sure if you are confusing them both but just in case.
Note: Will edit the name of the class on my last post to "PLUG".
-
Hi,
@jiminy-billy-bob said:
Also, I can't get my WebDialog callbacks to work if the dialog is not in a global variable. I tried local, instance, and class variables, nothing works. What am I doing wrong ?
If you want to change something from ruby to web-dialog you can do this...
In Html & Javascript:
<html> <head> <title>Example</title> </head> <body onLoad="startup(), stopwatch(this.value);"> </body> </html> <script> var delay = 1000/5 ; #this will update 5 frames per second var timerID = false ; var test = true ; #this is the value you will change from ruby function startup() { nextFrame(); } function stopwatch() { SD=window.setTimeout("stopwatch();", 100); } function nextFrame() { try { test = test setFrame() ; top.timerID = self.setTimeout("nextFrame()", delay) ; } //try catch (e) { alert("push_frame; " + e) ; } } //nextFrame() function setFrame() { url = 'skp;push_frame@' ; url += '&test=' + test; window.location.href = url ; } </script>
In Ruby:
module SU_PLUG class PLUG @@model = Sketchup.active_model ; @@dir = File.dirname(__FILE__) # this plugin's folder @@path = File.join(@@dir, '/Folder/') @@dlg = "test.html" ; @@test_dlg = nil ; def initialize() @test_1_file = File.join(@@path, @@dlg) if @@test_dlg == nil @@test_dlg = UI;;WebDialog.new("Test", false, "Test", 300, 600, 70, 95, true) ; @@test_dlg.add_action_callback("push_frame") do |d,p| push_frame(d,p) end end @@test_dlg.set_size(300, 600) ; @@test_dlg.set_file(@test_1_file) ; @@test_dlg.show() ; end #def def push_frame(dialog,data) params = query_to_hash(data) ; # parse state information if params['test'].to_s == "true" #Example of a condition. change = false script = "top.test= " + change.to_s + ";" #this sets test=true to test=false dialog.execute_script(script); #this execute it end end #def def unescape(string) if string != nil string = string.gsub(/\+/, ' ').gsub(/((?;%[0-9a-fA-F]{2})+)/n) do [$1.delete('%')].pack('H*') end end return string end #def def query_to_hash(query) param_pairs = query.split('&') param_hash = {} for param in param_pairs name, value = param.split('=') name = unescape(name) value = unescape(value) param_hash[name] = value end return param_hash end #def end #class end #module
Hope this helps and again very good plugin!
-
Ruby uses 2 space indentation. HTML & Javascript 4 space indentation.
NOTHING uses 3 or odd number spaced indents ! -
@jiminy-billy-bob said:
Also, I can't get my WebDialog callbacks to work if the dialog is not in a global variable. I tried local, instance, and class variables, nothing works. What am I doing wrong ?
See this other post: Re: Webdialog scripting issues
Use
local
vars INSIDE methods as temporary variables. They get garbage collected when the method ends.Use
@@vars
INSIDE modules or for class-wide access.Use
@vars
in class instance methods (define and init them inside theinitialize
method.) -
Thanks a lot, I'll try that.
Advertisement