Playing sound when moving inside room - want to make a YouTube tutorial.

135 views
Skip to first unread message

Mr. M.

unread,
Aug 9, 2011, 9:43:50 AM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
I want to make a simple tutorial on YouTube - similar to this
http://labs.plugins.ro/suave.htm

I think Sketchup would be a great way to learn programming... and this
would be an interesting tutorial.
Students could easily build some rooms, and have various sound files
play.
Concept:
When you enter a "room" - a sound file will play.
I have downloaded the zip file from http://labs.plugins.ro/suave.htm,
I have the Sketchup file loaded...
I don't think the .dll works on a Mac...

But... I want to see the source of the .rb file to learn how to do
this.
The only .rp file seems to be encrypted... (see below)

Question:
How do I see the ruby code to learn how to do this?
I know playing a sound file is easy...
it is just detecting if I'm in the room I don't know where to start.


Thanks,
Rob


File:
suave_load.rb

Contents:
eval %{JDoucHVzaCBTa2V0Y2h1cC5maW5kX3N1cHBvcnRfZmlsZSgiUGx1Z2lucy9T
VUFWRS8iKQpyZXF1aXJlICJTVUFWRSIKCmNsYXNzIFNVQVZFQW5pbWF0aW9u
CiAgZGVmIGluaXRpYWxpemUKICAgIGUgPSBTa2V0Y2h1cC5hY3RpdmVfbW9k
ZWwuZW50aXRpZXMKICAgIGlmIGUubGVuZ3RoIDwgMyAKICAgICAgVUkubWVz
c2FnZWJveCAoIkkgbmVlZCAzIGVudGl0aWVzIHRvIHBsYXkgU1VBVkUgZGVt
byIpCiAgICAgIHJldHVybiBmYWxzZQogICAgZW5kCiAgICBwYXRoID0gU2tl
dGNodXAuZmluZF9zdXBwb3J0X2ZpbGUoIlBsdWdpbnMvU1VBVkUvIikKICAg
IGVbMF0uYWRkX211c2ljKHBhdGgrIm1vcm5pbmZpemlrLm1vMyIpCiAgICBl
WzFdLmFkZF9tdXNpYyhwYXRoKyJwZWVuLm1vMyIpCiAgICBlWzJdLmFkZF9t
dXNpYyhwYXRoKyJwYXRjaG91bGkubW8zIikKICBlbmQKCiAgZGVmIG5leHRG
cmFtZSh2aWV3KQogICAgYmVnaW4KICAgICAgU1VBVkUuY2Ftc2V0M0Qodmll
dy5jYW1lcmEuZXllLnRvX2EpCiAgICByZXNjdWUgPT4gZXJyCiAgICAgIHAg
ZXJyCiAgICBlbmQKICAgIHJldHVybiB0cnVlCiAgZW5kCgogIGRlZiBzdG9w
CiAgICBTVUFWRS5zdG9wX2FsbAogIGVuZAplbmQKCm1vZHVsZSBTa2V0Y2h1
cAoKICBjbGFzcyBEcmF3aW5nZWxlbWVudAogICAgYXR0cl9yZWFkZXIgKDpt
dXNpYykKCiAgICBkZWYgYWRkX211c2ljKGZpbGVuYW1lKQogICAgICBAbXVz
aWMgPSBTVUFWRS5uZXcoZmlsZW5hbWUpIGlmIGZpbGVuYW1lCiAgICAgIHNl
bGYucGxheQogICAgZW5kCgogICAgZGVmIHBsYXkKICAgICAgQG11c2ljLnBs
YXkKICAgICAgc2VsZi5wb3Nfc2V0CiAgICBlbmQKCiAgICBkZWYgcG9zX3Nl
dAogICAgICBTa2V0Y2h1cC5hY3RpdmVfbW9kZWwuZW50aXRpZXMuYWRkX2Nw
b2ludCBzZWxmLmJvdW5kcy5jZW50ZXIudG9fYQogICAgICBAbXVzaWMuc2V0
M0Qgc2VsZi5ib3VuZHMuY2VudGVyLnRvX2EKICAgIGVuZAoKICAgIGRlZiBz
dG9wCiAgICAgIEBtdXNpYy5zdG9wCiAgICBlbmQKCiAgICBkZWYgbGV2ZWwK
ICAgICAgQG11c2ljLmxldmVsCiAgICBlbmQKCiAgICBkZWYgaGFzX211c2lj
PwogICAgICBAbXVzaWMgIT0gbmlsCiAgICBlbmQKCiAgZW5kCmVuZAoKaWYo
IG5vdCBmaWxlX2xvYWRlZD8oInN1YXZlX2xvYWQucmIiKSApCQogIHN1YXZl
X21lbnUgPSBVSS5tZW51KCJQbHVnaW5zIikuYWRkX3N1Ym1lbnUoIltUQkRd
IFNVQVZFIikKICBzdWF2ZV9tZW51LmFkZF9pdGVtICgnRGVtbycpICAgICAg
ICAgICAge1NrZXRjaHVwLmFjdGl2ZV9tb2RlbC5hY3RpdmVfdmlldy5hbmlt
YXRpb24gPSBTVUFWRUFuaW1hdGlvbi5uZXd9CiAgc3VhdmVfbWVudS5hZGRf
aXRlbSAoJ1N0b3AnKSAgICAgICAgICAgIHtTa2V0Y2h1cC5hY3RpdmVfbW9k
ZWwuYWN0aXZlX3ZpZXcuYW5pbWF0aW9uID0gbmlsfQogIHN1YXZlX21lbnUu
YWRkX2l0ZW0gKCdTdG9wIEFsbCBTb3VuZHMnKSB7U1VBVkUuc3RvcF9hbGx9
CmVuZApmaWxlX2xvYWRlZCgic3VhdmVfbG9hZC5yYiIpCg==
}.unpack("m").to_s

TIG

unread,
Aug 9, 2011, 11:16:22 AM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
It's not been encrypted but it has been 'packed' to keep it away from
casually prying eyes...
It is possible to 'unpack' it into readable ruby-code... BUT you
haven't even posted the whole file!
What's after the == ? etc ??
For what it's worth this is what the file says...

$:.push Sketchup.find_support_file("Plugins/SUAVE/")
require "SUAVE"

class SUAVEAnimation
def initialize
e = Sketchup.active_model.entities
if e.length < 3
UI.messagebox ("I need 3 entities to play SUAVE demo")
return false
end
path = Sketchup.find_support_file("Plugins/SUAVE/")
e[0].add_music(path+"morninfizik.mo3")
e[1].add_music(path+"peen.mo3")
e[2].add_music(path+"patchouli.mo3")
end

def nextFrame(view)
begin
SUAVE.camset3D(view.camera.eye.to_a)
rescue => err
p err
end
return true
end

def stop
SUAVE.stop_all
end
end

module Sketchup

class Drawingelement
attr_reader (:music)

def add_music(filename)
@music = SUAVE.new(filename) if filename
self.play
end

def play
@music.play
self.pos_set
end

def pos_set
Sketchup.active_model.entities.add_cpoint
self.bounds.center.to_a
@music.set3D self.bounds.center.to_a
end

def stop
@music.stop
end

def level
@music.level
end

def has_music?
@music != nil
end

end
end

if( not file_loaded?("suave_load.rb") )
suave_menu = UI.menu("Plugins").add_submenu("[TBD] SUAVE")
suave_menu.add_item ('Demo')
{Sketchup.active_model.active_view.animation = SUAVEAnimation.new}
suave_menu.add_item ('Stop')
{Sketchup.active_model.active_view.animation = nil}
suave_menu.add_item ('Stop All Sounds') {SUAVE.stop_all}
end
file_loaded("suave_load.rb")



It uses a 'SUAVE.so' file - so that isn't readable...
What id it [in words] you want to do ?



On Aug 9, 2:43 pm, "Mr. M." <mrmccorm...@gmail.com> wrote:
> I want to make a simple tutorial on YouTube - similar to thishttp://labs.plugins.ro/suave.htm
>
> I think Sketchup would be a great way to learn programming... and this
> would be an interesting tutorial.
> Students could easily build some rooms, and have various sound files
> play.
> Concept:
> When you enter a "room" - a sound file will play.
> I have downloaded the zip file fromhttp://labs.plugins.ro/suave.htm,

Mr. M.

unread,
Aug 9, 2011, 12:12:40 PM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
Hey TIG:

- Thanks very much for response - appreciate the help.

- What I'm trying to do is much simpler than that example - and will
open up lots of possibilities for my tutorial.

- Here is a what I want to do for my tutorial:
https://sites.google.com/site/rubysketchuptutorial/

Task:
As user moves around, sense how close the camera is to an object and
pop up a messagebox (eventually play a sound file and add more
objects)

Logic:
If the Camera is within 2 feet of Susan, then
UI::messagebox( 'Hello I am Susan' )

If Camera is within 2 feet of Sang, then
UI::messagebox( 'Hello I am Sang' )


Reference:
I'm studying this plugin (camera parameters)
but again, much more than I need - and requires user to activate by
menu.
http://rhin.crai.archi.fr/rld/plugin_details.php?id=55


TIG

unread,
Aug 9, 2011, 12:42:41 PM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
To find the camera's eye=position use
eye=Sketchup.active_model.active_view.camera.eye
To find the distance to an object [center] use
dis=eye.distance(object.bounds.center)
Then decide what to do
if dis < 3.feet
### do this
end
The 'do this' could be a
UI.messagebox("Too near !")
or a beep
UI.beep
or a sound
UI.play_sound(path_to_sound_file)
or anything else you think of,,,,,,,,
???

Mr. M.

unread,
Aug 9, 2011, 1:21:17 PM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
TIG:

. This helps a lot, I test by writing a plugin for it today - and
activate it by the Plugin menu....

. Just occurred to me, I would be also be interested, to cause a sound
file to play, if the user CLICKED
on the model - but I been unable to figure that out... and have
spent time searching for such a seemingly simple thing.

i.e
onClick on model Susan, play a sound file...

It this can be done, interactive game-like worlds could be built....

Thanks again, my progress seems slow... but will keep at it..

Rob





.

TIG

unread,
Aug 9, 2011, 3:06:48 PM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
You'll need to write a Tool [class] and launch it as a 'tool'.
Then under a 'mouse_click' method you'll test for certain objects
below the cursor [see 'pick_helper'] and if it's the required object
'play_the_sound'.
You could perhaps even have the tool running in a separate loop
[timer] that lets you do other stuff and only 'beeps' when you click
those special objects ??

Mr. M.

unread,
Aug 9, 2011, 7:28:12 PM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
Thanks, I'm getting there... but sure doesn't seem a direct solution
compared to other languages I know.

Never would have got this far without your help...

Progress today:
---
> You'll need to write a Tool [class] and launch it as a 'tool'.
. OK, I have done that, and understand it.
---
> Then under a 'mouse_click' method you'll test for certain objects
> below the cursor [see 'pick_helper'] and if it's the required object
. OK, I got the pick_helper figured out.
I know this returns "entity"
best = ph.best_picked

------------------------------------------------------
But here is the ROAD BLOCK I have hit and can't seem to go further.

Question:
Say I click on Susan, how do I pick up
the name entered into the 'Entity Info' box
(that would identify the object I clicked on)


Here is my code so far, with references to what I have researched...

=========
class Clf_highlight_bb


def activate
Sketchup.active_model.selection.clear
@@ph= Sketchup.active_model.active_view.pick_helper
end #activate

def onLButtonDown(flags, x, y, view)

puts "you clicked on something"

# this does work from Ruby console - but can't seem to identify the
object I clicked on.
#model = Sketchup.active_model
#desc = model.description
#puts desc

#Reference...
# http://www.google.com/support/forum/p/sketchup/thread?tid=528eaedce86fde48&hl=en
#We are trying to access objects in RUBY, but can't seem to access
individual objects names that are entered in the Name entered into the
'Entity Info' box.

ph = view.pick_helper
ph.do_pick x,y
best = ph.best_picked


#best_picked reference
#The best_picked method is used to retrieve the "best" entity picked
(entity that you would have picked if you were using the select tool).
#Syntax
#entity = pickhelper.best_picked
#Return Value
#entity - the best picked entity


end #onLButtonDown

end #class

Sketchup.active_model.select_tool( Clf_highlight_bb.new )

=========


NOTE:
I also added a menu under Plugin - since once I select another tool,
my tool stops working.

=========
# First we pull in the standard API hooks.
require 'sketchup.rb'

# Show the Ruby Console at startup so we can
# see any programming errors we may make.
Sketchup.send_action "showRubyPanel:"




# Add a menu item to launch our plugin.
UI.menu("PlugIns").add_item("RobTestTools") {
UI.messagebox("I'm about RobTestTools!")

Sketchup.active_model.select_tool( Clf_highlight_bb.new )

}



Dan Rathbun

unread,
Aug 9, 2011, 11:22:47 PM8/9/11
to Google SketchUp Developers - SketchUp Ruby API
TBD ... modified the Sketchup::Drawingelement class ??

Could this have been done another way?

TIG

unread,
Aug 10, 2011, 4:28:49 AM8/10/11
to Google SketchUp Developers - SketchUp Ruby API
Sorry Dan, I don't understand the reference to modifying a base-class
- which is always a bad idea...

On the question of the 'pick' tool...
Your Tool gets 'best' which is a reference to the best picked thing.
You test for it being a component-instance and then of a certain
name...

sounds=File.join(File.dirname(__FILE__),'Sounds')
### can test if subfolder '../Sounds' exists etc
###...

if best.class==Sketchup::ComponentInstance
defn=best.definition
name=den.name
case name
when 'AAA'
UI.play_sound(File.join(sounds,'AAA.wav'))
when 'BBB'
UI.play_sound(File.join(sounds,'BBB.wav'))
else
###puts 'Nothing to do!'
end#case test
end#if test

###
To get it to run while you do other stuff too try running the tool
inside a timer
You make two menu items to start and stop the sound playing.
You need to add a class variable @@timer within your Tool's class
methods to remember the timer so we can stop it later

@@timer=nil ### with class code

def Clf_highlight_bb::start_timer()
UI.stop_timer(@@timer) if @@timer ### to ensure we only have one!
@@timer=UI.start_timer(0, true)
{Sketchup.active_model.select_tool( Clf_highlight_bb.new() ) )
end

def Clf_highlight_bb::stop_timer()
UI.stop_timer(@@timer) if @@timer
end

### Now the menu
menu=UI.menu("PlugIns").add_submeny("RobTestTools...")
menu.add_item('Start'){Clf_highlight_bb::start_timer()}
menu.add_item('Stop'){Clf_highlight_bb::stop_timer()}

### Now when you start it, it runs 'in the background' waiting until
you click on a specific object and then playing the associated sound
file [or whatever other 'action[s]' you want - e.g. open a web-site],
if you want to reduce the checking in your Tool's 'onLButtonDown'
method add an initial line into to test for 'Select' being the active
tool...
Obviously you'll also rem# out the unneeded 'puts' once it's working!

I haven't tested this idea but it might work ? Try it!

Dan Rathbun

unread,
Aug 10, 2011, 2:11:52 PM8/10/11
to Google SketchUp Developers - SketchUp Ruby API
On Aug 10, 4:28 am, TIG <tantrig_email-sketc...@yahoo.co.uk> wrote:
> Sorry Dan, I don't understand the reference to modifying a base-class
> - which is always a bad idea...

Yes.. generally so without community agreement.
(.. and never without wrapping in a conditional to prevent overriding
of future native API methods.)
To be fare, it's a concept, and an old one at that.

But I was wondering why Drawingelement (which would be inherited by
Edge and Face, etc.,) and not Sketchup::Group and
Sketchup::ComponentInstance specifically, instead.

Another way, would be to append to the DynamicComponent click
functions.

TIG

unread,
Aug 10, 2011, 3:03:06 PM8/10/11
to Google SketchUp Developers - SketchUp Ruby API
Aha!

I finally clicked!
I agree that there seems no good reason to change a base-class!

Anyway - looks like other ways are favored...

Mr. M.

unread,
Aug 11, 2011, 6:18:56 PM8/11/11
to Google SketchUp Developers - SketchUp Ruby API
TIG:

Your help was extremely useful, thanks once again.

I just completed my first example and demonstration of trapping the
mouse and keystrokes.

I made a YouTube of my example in action:
http://youtu.be/qFm0XFW3YRs

All files (sounds/.skp/.rp) may be found at:
http://code.google.com/p/sketchup-ruby-tutorial/

I have tried to do things correctly and comment the code, but being
NEW to Ruby/SketchUp -
there may be things wrong.

Any comments/suggestions/improvements from community would be most
welcome.

Rob

Mr. M.

unread,
Aug 11, 2011, 6:38:47 PM8/11/11
to Google SketchUp Developers - SketchUp Ruby API
View source code:

Here is highlighted source code for easy reference:

Two files are used:
---------------
File to load:
ltpOnClickExampleLoad.rb


Main file:
(how to use in this file)

ltpOnClickExample.rb
http://codepaste.appspot.com/show?id=545121

~Rob

Mr. M.

unread,
Aug 11, 2011, 6:58:32 PM8/11/11
to Google SketchUp Developers - SketchUp Ruby API
I missed this one:

> File to load:
ltpOnClickExampleLoad.rb
http://codepaste.appspot.com/show?id=546121

TBD

unread,
Aug 16, 2011, 4:42:15 AM8/16/11
to sketch...@googlegroups.com
hehe, the code was back in 2006 and it was more a proof of concept of doing mp3/module playing with 3D capabilities inside Sketchup.

maybe I will open source it for people to fork and "fix" it - any takers ?

TBD

Dan Rathbun

unread,
Aug 16, 2011, 6:11:03 AM8/16/11
to Google SketchUp Developers - SketchUp Ruby API
On Aug 16, 4:42 am, TBD wrote:
>
> maybe I will open source it for people to fork and "fix" it - any takers ?
>
> TBD

I asked Scott to take a look at this from a DC click function point of
view.
http://forums.sketchucation.com/viewtopic.php?f=180&t=17047&p=348848#p348848
Message has been deleted

Dan Rathbun

unread,
Aug 16, 2011, 7:08:34 PM8/16/11
to Google SketchUp Developers - SketchUp Ruby API
On Aug 16, 1:16 pm, TIG wrote:
> This is how to make an onClick on a DC play a sound...
...
> This Ruby code goes in a file file called say add_func.rb in the
> Plugins folder and auto-loads.

Which will fail unless:
require("dynamiccomponents.rb")
statement is added at the top.

> You can include any 'custom-functions' in it [I've shown just three
> atan2/volume/playsound]
> This is the way to define 'custom-functions' that are not directly
> available with the DC built-in functions...

Except that, the DC Functions are no longer V1 !!!!

And at the top of the thread you admonished the world for changing API
classes ... and then you post code showing how to do just that.

I asked Scott for the simple reason, that the DCs are "his baby"...
and the code is copyright by Google.

TIG

unread,
Aug 17, 2011, 4:54:06 AM8/17/11
to Google SketchUp Developers - SketchUp Ruby API
Dan
You are quite right - in cutting and pasting this snippet I had
missed out the initial require etc that I had in my main test code for
require('dynamiccomponents.rb').
So note that you need to add it if you are trying this code...

The DC functions might no longer be 'V1' BUT it still works with the
class DCFunctionsV1 ???
What do you think it should be instead?
Presumably v7 users still have the earlier version and so it's been
kept for backward compatibility ?
Using
Module.constants.sort
only lists these seven 'DC' classes on my system: "DCConverter",
"DCDownloader", "DCFunctionsV1", "DCInteractTool", "DCObservers",
"DCProgressBar", "DM_Create".
There's no 'alternative' and there is no other module/class name
=~/ [Ff]unction/
at all ???
So it looks like 'DCFunctionsV1' it is then...

I understand it this IS the intended way to add extra functions?
How else might it be done?
I agree that modifying a 'base class' is not a great idea... but I am
not changing an existing function-method - but adding new ones.
However, since Google [or other authors even] might add these very
same functions later... a simple work around might be like this...


require('dynamiccomponents.rb')

class DCFunctionsV1

if not DCFunctionsV1.method_defined?(:playsound)
def playsound(a)
puts sound=a[0].gsub(/%2F/,'/').gsub(/%3A/,':').gsub(/%5C/,'\\')
UI.play_sound(sound)
end#def
end#if

### add an if...end test for each new function-method that is added...

end#class


This way it will only add 'new' function-methods, and it will never
overwrite 'existing' ones, e.g. if Google have already added them as
'native' functions in a new DC version...

???

Todd Burch

unread,
Aug 17, 2011, 10:00:09 AM8/17/11
to sketch...@googlegroups.com
Why not just subclass DCFunctionsV1 and stay completely away from
adding methods to the base class?

Todd


require('dynamiccomponents.rb')

class DCFunctionsV1

end#class

???

--
You received this message because you are subscribed to the Google
Groups "SketchUp Ruby API" group.
To post to this group, send email to sketch...@googlegroups.com.
To unsubscribe from this group, send email to sketchupruby...@googlegroups.com
.
For more options, visit this group at http://groups.google.com/group/sketchupruby?hl=en
.


Message has been deleted

TIG

unread,
Aug 17, 2011, 12:43:05 PM8/17/11
to Google SketchUp Developers - SketchUp Ruby API
Todd

I'm not sure I follow you...
The DCs automatically use the DCFunctionsV1 class via their compiled
code, so adding to it is recognized as a new method/function...
Can you give an example of how it might be done without directly
affecting that class but whilst still providing code that's used by
the DCs in the same way...
???

Todd Burch

unread,
Aug 17, 2011, 2:14:28 PM8/17/11
to sketch...@googlegroups.com
Hi Tig.

Sorry, I'm not 100% up on how DCs are implemented, and how to interact
with them in Ruby.

If you are not instantiating DC objects, then you can't subclass
DCFunctionsV1 to add a play_sound() in your subclass.

Todd

BTW, where is the Ruby doc for DCs?

TIG

unread,
Aug 17, 2011, 3:59:23 PM8/17/11
to Google SketchUp Developers - SketchUp Ruby API
There aren't any good DC API docs just do a search and glean what you
can.
The DC API stuff is encrypted and loads many built-in spread-sheet-
like functions and a few SKP things like automate and redraw.
If you want a function that's not built-in you can add it as a method
to the DCFunctionsV1 class, as I explained ...and then the DC
recognizes it as a possible function - so you can do many more things
with DCs than the Help notes say...
However I can't see how we can do this without adding methods to the
class - although of course we can trap for them being added by Google
in updates using the code I suggested, so only new methods are added
and existing ones are not affected...

Dan Rathbun

unread,
Aug 17, 2011, 4:50:01 PM8/17/11
to Google SketchUp Developers - SketchUp Ruby API
The short answer is:

that Todd is correct, in that the "plan" was to create new Function
class versions ...
DCFunctionsV1_1, DCFunctionsV1_1_p2, DCFunctionsV2, etc.

BUT... the kicker is that the Functions are versioned ALONG with the
DynamicComponents class, so..

DynamicComponentsV1 loads DCFunctionsV1

then (future) ...
DynamicComponentsV1_1 loads DCFunctionsV1_1

if there's a path, then:
DynamicComponentsV1_1_p1 loads DCFunctionsV1_1_p1 (if it has a patch,
otherwise just the latest Functions ver.)

The way it is now... if the DCFunctions version goes up.. then the
DynamicComponents version MUST ALSO go up.

It is NOT automated. It requires writing new subclass versions who's
superclass is the previous version.

ANYWAY... although TIG's "hack" will work... he is crow barring a
newer version into the old one. The version is saved into each and
every DC, under the "_format_version" attribute.
IF you add an entry for a new function, that function call gets saved
into the DC. But then THAT DC is no longer itself V1, even though the
"_format_version" attribute indicates it is.

So now a person without the "hack" loaded, gets one of these "naughty"
DCs, and clicks it. What happens?? A warning box? (This is what is
supposed to happen if the versioning system is working correctly. The
user would have only DCv1.0 installed, and the DC itself should
indicate it is v1.1 or something higher. A warning messagebox would
popup.)

I've been thinking a long while about a DC patching / extension
system, and have some code snippets toward that end, but much more
work is required.

TIG

unread,
Aug 17, 2011, 5:36:09 PM8/17/11
to Google SketchUp Developers - SketchUp Ruby API
So... if I understand correctly... it's a great idea but it just won't
work because a suitable framework is not in place... You recommend sub-
classing to a new class based on the V1 - say V1_1 but it'll not work
as the DCloader never looks for more than V1 - as it IS the current
V1.
I still fail to see how this could work without lots of extra files
loading and changing some existing files that ship with standard
Sketchup - so it'd be even more questionable than 'carefully' adding
methods to an existing class...
None of the existing .rb's code will do this and as far as I can see
it would mean messing on in the sacrosanct Tools and its subfolder/
files...
As many people might write new functions then shouldn't these go into
the V1 class [as the most current 'official' class]?

When you add a new function [in a way that preserves any future
changes to the existing [V1] class methods] the DC will then work if
that .rb loads those methods. If it doesn't work because it's been
disabled or simply not installed, then the DC will fail with an error
messages saying something like "undefined method 'playsound'"... Just
like running a script needing progressbar.rb with it being available
in a 'require' or is never 'required' an error when the script tries
to execute the class-method...

If Google decide change the way DCs load and use versioned functions
in SU0+ then they will also need to address backward compatibility ??
The adding of customized functions into the base V1 class 'carefully'
will work... and the only possible clash is if someone else's DC
defines its own functions with the very same name but that do
different things - only one will load and the other will fail or
produce odd results...
I suppose the conditional def of the new functions could have a
UI.message box telling us if it's already defined and recommending a
check on affected DCs operation - OR give our new functions more
specific names - like 'tig_playsound' - which would be unlikely to be
replicated in another author's code... but let's face it there seems
to be hardly anyone writing this kind of additional functions
anyway ???

???

Dan Rathbun

unread,
Aug 17, 2011, 7:59:03 PM8/17/11
to Google SketchUp Developers - SketchUp Ruby API
On Aug 17, 5:36 pm, TIG wrote:
> So... if I understand correctly... it's a great idea but it just won't
> work because a suitable framework is not in place...

Well .. the foundations for a framework are in place. But the the ruby
methods have not been added into the package, yet. (And it's not that
difficult.)

> You recommend sub-
> classing to a new class based on the V1 - say V1_1 but it'll not work
> as the DCloader never looks for more than V1 - as it IS the current
> V1.

Actually DCloader loads the DCObservers singleton class (which really
should be called "DCManager", as it's not an Observer itself, it
manages the whole system.)
It's the DCObservers object that hardcodedly (currently,) only loads
DynamicComponentsV1, which again in hardcode explictly loads
DCFunctionsV1.

> I still fail to see how this could work without lots of extra files
> loading and changing some existing files that ship with standard
> Sketchup -

NO... not really. Extra files yes.. but they will NOT change the
existing class versions (and therefore the files of ver 1.0.) They are
subclasses that inherit all the previous version's functionality, but
simply change the values of a few instance variables, and add new
methods. (Forget about patching the DC bugs, for this discussion, it's
a different issue. Lets stay on the subject of extending the DC system
with new versions, that add new functioanality.) So creating a
subclass file, will only take a handfull of lines to implement.

> so it'd be even more questionable than 'carefully' adding
> methods to an existing class...

NO... it won't because it's the way that Scott intended it to work in
the future. (He just did not have the time, or the budget for V1
didn't allow him to, ... fully implement the extensibility he
envisioned.)

> None of the existing .rb's code will do this and as far as I can see
> it would mean messing on in the sacrosanct Tools and its subfolder/
> files...

Well.. you know that I'm very much against "dropping" scripts into the
Plugins dir, where they end up living on forever. Most especially a
"hack" like you posted. Months, or more from now, a user won't
remember it's there, and will wonder what is changing his DC's
functionality. He may not even remember where he got it. (One reason
why this group is a bad place to post code snippets. We cannot edit
them here.)

I would implement this as a SketchupExtension, that can be totally
turned off at will. And then the "DC Extensor" would be a similar sub-
system, where you could decide what versions to load or not.
Secondly, I would probably put it in it's OWN subdir of the Tools
folder. I would not mix anything into the DC subfolder tree. Nor would
I need to change any of those Google files in there.

> As many people might write new functions then shouldn't these go into
> the V1 class [as the most current 'official' class]?

NO again... if anyone does that... the class is no longer V1 !!!
(It's no different than, if I walk onto construction site, grab a saw,
and cut a new doorway thru a wall, because I personally believe there
should be a door there. l may have good reason to think a door should
be there, and others may agree. But if there's no door at that
location in the plans... was the building built to plan?)

> When you add a new function [in a way that preserves any future
> changes to the existing [V1] class methods] the DC will then work if
> that .rb loads those methods.

Which is acceptable ?? A system of proper versioning, configuration
management, and controlled releases... or everyone and anyone willy-
nilly making changes.

> If it doesn't work because it's been
> disabled or simply not installed, then the DC will fail with an error
> messages saying something like "undefined method 'playsound'"...

There is a trap for "Unknown Function"... but a trap by it's nature is
meant to prevent a runtime error from causing the code to exit
ungracefully. Circumventing the way things are supposed to work, may
cause the trap to fail. The trap is meant to prevent (or hide,) the
Ruby exception.

> If Google decide change the way DCs load and use versioned functions
> in SU0+ then they will also need to address backward compatibility ??

I believe Scott already addressed this in the code.. but the
versioning system needs to be respected. Period.

> The adding of customized functions into the base V1 class 'carefully'
> will work...

IT WON'T because obviously, you cannot see (or have not seen,) how the
code is written. (The copyright, and the NDA I signed, prevents me
from sharing it with you. Sorry.) It seems that your motivation is
that your unwilling to wait, for the proper framework.

> and the only possible clash is if someone else's DC
> defines its own functions with the very same name but that do
> different things - only one will load and the other will fail or
> produce odd results...

Obviously.. there needs to be some community review for new candidate
functions, and beta testing. (Which means the system must support beta
versioning.) Then an official release of new function sets.

So my answer to having many people hacking out new functions, and
releasing them at will, is a recipe for disaster.

And I wish you, in hindsight, had not publically posted that "hack."
The DC system is a VERY complex system. The last thing we need, is to
be teaching "newbies" how to hack or short-circuit a package this
complex and important. The DCs need to really be thought of as part of
the Sketchup application. If this hacking gets out of hand, I would
not be surprised if (in the future,) it gets compiled into a DLL, or
similar, where dynamic changes are not possible.

I am reminded of a snarky jab made in the SCF forums last beta cycle,
by Mr. Hauswirth, concerning his distaste for hacking where we should
not.

> I suppose the conditional def of the new functions could have a
> UI.message box telling us if it's already defined and recommending a
> check on affected DCs operation - ..[snip]...

I would hope that we could get Scott involved, as "editor in chief" or
whatever, like how a project engineer has to sign off on the drawings.
A new package doesn't get released until he OKs it

TIG

unread,
Aug 18, 2011, 6:22:04 AM8/18/11
to Google SketchUp Developers - SketchUp Ruby API
I did not invent this 'hack' it is in the public domain - and it has
been published in some form or another for almost THREE years now !
http://markmail.org/message/4je7itfefjkc4htd and
http://www.cfcl.com/rdm/weblog/archives/001716.html
and again two years ago at SCF and even a few months ago [by you Dan!]
http://forums.sketchucation.com/viewtopic.php?p=326877#p326877
http://forums.sketchucation.com/viewtopic.php?p=327231#p327231

Because nothing has been done to make 'a better system' in well over
THREE years [!!!] it seems to me that authors might have to do what
they can with what they've got, if they want to add extra DC
functions... It's hardly like DCs were just invented, and we have
been told that an update is imminent and we've 'jumped in' ill-
advisedly ?

IF there's a better [or safer] way of doing custom functions for DCs
within the the existing framework, then please post an example
here... We'd all like to know.

I think my recently posted ideas protect the existing class as far as
possible given the longstanding and still current constraints.

Any 'privately' used DC will be documented and then users should know
that additional functions are added by a special .rb auto-loading.
Bit let's bring a reality check... I know of no 'public' DCs that are
using custom functions loading from a .rb - BUT if they were available
then they'd come packaged with the .rb file and hopefully an
explanation 'readme' file etc etc - which would be not very different
that the image-files needed for a custom-made toolbar's buttons, which
can just as easily be uninstalled to break a tool! The custom-
functioned-DC could even include a part in its description saying that
it needs 'xxxxx.rb' loaded to provide the 'xxxxx' custom function[s] ?

Making the custom-function .rb load as an 'extension' would simply add
an extra layer of complexity [from time to time we see at SCF that a
user installs a new .rb based tool and complains that it doesn't work
- because it's an extension and he's not activated it!]. What benefit
would a user have with the DC-custom-function[s] being an extension,
and being able to deactivate it - with its custom-function[s]
vanishing on a restart and thereby breaking some infrequently used DC
that used the custom-function[s], with an error message that pops up
perhaps weeks later? I can't ever see that being useful - it just
makes it easier to break a DC by the un-ticking of a box, rather that
the [accidental] removal of a .rb file itself. It just doesn't seem
logical to me... First they'd have to remember to activate the
extension on every installation before any DCs using the custom-
function[s] would work [and that'd be just plain annoying]... and then
they'll inevitably leave the extension permanently 'activated' anyway,
because why would they ever want to have it NOT work? And if someone
did deactivate the extension then the DC would continue to work for
that session if it were run and then only fail after a restart - but
perhaps that might be weeks later, since the DC is unlikely to be used
everyday - so let's say a week later the DC is used and it stops
working but no one can remember deactivating some extension way back
that broke it and without detailed documentation telling them to
activate it they're lost... This is just making an extra way to break
things, that will need more support to track down the cause and fix
it...

NOTE:
I've removed my earlier post and below is my best go at doing this
within the framework NOW .
Dan, do you have a 'better way' [other that just not doing it at all]?

[1]
- The 'Chimer' DC's Attributes:-

Description: Chimer - needs add_funcs.rb for customized_playsound
function.
onClick: REDRAW(sound());
sound: =customized_playsound("DCsounds/chimes.wav")

[Note: the path to the sound-file is either relative to the
'add_funcs.rb' file - e.g. in the ../Plugins/ folder - here it assumes
there's a subfolder kept with the .rb called 'DCsounds' containing
the .wav file; OR you give a full-path to the file hard-coded like "C:/
DCresources/DCsounds/chimes.wav"]

[2]
- A file named "add_funcs.rb" that will auto-load to add new
function[s], containing this code:-

require('dynamiccomponents.rb')

if defined?($dc_observers)
### To add Custom Functions to SketchUp's Dynamic Component Functions
(V1) class if the DC extension is active.

class DCFunctionsV1

protected

### =customized_playsound
### It's only added if it's not already a defined function.
if not DCFunctionsV1.method_defined?(:customized_playsound)
def customized_playsound(a)
sound=a[0].gsub(/%2F/,'/').gsub(/%3A/,':').gsub(/%5C/,'\\')
UI.play_sound(sound)
end#def
end#if

end#class

end#if



What else can one do?

Dan Rathbun

unread,
Aug 18, 2011, 9:41:21 AM8/18/11
to Google SketchUp Developers - SketchUp Ruby API

On Aug 18, 6:22 am, TIG wrote:
> I did not invent this 'hack' it is in the public domain - and it has
> been published in some form or another for almost THREE years now

Fair enuff.. I did not say you did.
HELL NO !!

1) I did NOT start those Posts, ...
2) I only made a correction to the conversion (degrees/radians)
3) I said then IN BIG BOLD TYPE, in BOTH posts, and I quote myself:
"NOTE: modifying this class no longer makes it version 1"


> Because nothing has been done to make 'a better system' in well over
> THREE years [!!!] ...

OK.. as I suspected. Your tired of waiting.

Do what you want, you shall anyway no doubt.

> IF there's a better [or safer] way of doing custom functions for DCs
> within the the existing framework, then please post an example
> here...  We'd all like to know.

And I said there is more work to do ...

Dan Rathbun

unread,
Aug 18, 2011, 10:16:27 AM8/18/11
to Google SketchUp Developers - SketchUp Ruby API

On Aug 18, 9:41 am, Dan Rathbun wrote:
> On Aug 18, 6:22 am, TIG wrote:
>
> > Because nothing has been done to make 'a better system' in well over
> > THREE years [!!!] ...

Just want to say, although I've known of the issue for several
months...

I have not taken an interest in solving this issue, until NOW.

So give me a break. I'm not going to post a solution, without proper
testing.
And when it's done.. it will be an installable Extension package, not
a code snippet.

I do have other projects I'm working on a the moment.

TIG

unread,
Aug 18, 2011, 2:20:21 PM8/18/11
to Google SketchUp Developers - SketchUp Ruby API
I too have other fish to fry...

I don't think it's a 'major issue' because there are very few [none?]
making customized-functions for DCs at this time anyway...

I trust that when a 'better' way of adding customized-functions to DCs
is eventually available it will be widely publicized, with clear
guidance, so that we can all benefit form it...

Y

unread,
Nov 10, 2016, 9:06:19 AM11/10/16
to SketchUp Ruby API
I'm quite late to this discussion... but wondering if anything has changed since? 
1. Sketchup 2017 just came out, I assume with some changes/improvements to dynamic components?  Though I am unaware to what they might be... cause it doesn't say much in the release notes. 
 
2. Is there a simple/clean way to add additional functions to DCs now?  (3 years + 5 years since the last post here)
3. Is there any clear documentation for accessing / manipulating DCs with ruby?
4. I am quite new to Ruby so I don't pretend to understand everything in this thread, but from the way it looks, the reason nobody is/was making any customized-functions for DCs was because it's just not quite "fully baked" - It seams to me like you can't quite rely on it to work when the versions keep changing. (I'm not totally sure I understood what the version changes mean...  "DCFunctionsV1"...  "DCFunctionsV1_1"  Is that the version of the DC plugin?  Is it related to the version of Sketchup?  If so, what version is it now!?? (2017)  (quite confused with regard to this part)

Any pointers will help...
Cheers ;)
Reply all
Reply to author
Forward
0 new messages