A small thing, just noticed a typo that I don't think is already covered. The entry for EntityObserver.onChangeEntity method states:
@unknownuser said:
The onEraseEntity method is invoked when your entity is modified.
Mike
A small thing, just noticed a typo that I don't think is already covered. The entry for EntityObserver.onChangeEntity method states:
@unknownuser said:
The onEraseEntity method is invoked when your entity is modified.
Mike
@chrisglasier said:
@designforlife said:
...so the answer is that I am barking up the wrong program tree? Damn! So near, yet so far.
Not necessarily, but web dialogs are very good if you want flexibility and interoperability including human interaction. Why not give them a try?
Chris
Could you explain a bit about web dialogs? How do they relate? I tried a few of the methods from the API page to display a web page in Sketchup. Beyond that, I am trying to imagine the potential.
Actually, the name initially suggested to me they might work the other way round - to display sketchup in a web page but I believe that requires the web user to download and install a browser add-on.
Mike
...so the answer is that I am barking up the wrong program tree? Damn! So near, yet so far.
Hi Chris, thanks for the reply and yes, I have got the camera to move without using the animation class or pages. So the step I can't solve is how to avoid the need for user intervention.
I began with some code I found on the Google blog here: http://sketchupapi.blogspot.com/2008/11/storing-and-retrieving-with.html. This creates a simple group with attributes attached. The group is placed at the current view and takes the current camera parameters as its attributes. A context menu item allows you to go to that view with a few clicks.
I use the reveal_view method to first set up the views I want but the go_to_view method is not convenient for viewing in a particular sequence - you may not be able to see the next location to click on it. An advantage of my idea is you can even hide the cameras or turn off the layer they are on so the model is not cluttered with camera groups.
I also made a modified version of reveal_view so that I don't have to go to each location to create the camera for that view. With this version, a context menu becomes available when an edge is selected and its start and end point become the eye and target of the camera.
Since these 'cameras' are all placed on their own layer, I can use layer.name=="cameras"
to store them in an array. It should then be a simple matter of extracting the attributes from each in turn (with info=cam.attribute_dictionary("is_a_camera")
) and sending the view to that location (with view.camera=Sketchup::Camera.new(info["eye"]
...etc) but Ruby doesn't have the good grace to wait unless I use messageboxes, which is a bit self defeating.
Anyway, here is my code:
def do_tour
ents=Sketchup.active_model.entities
cams=[]
e=0
num=ents.length
while e < num
if ents[e].layer.name=="cameras"
cams.push(ents[e])
end
e+=1
end
cam_no=0
cam_indx=cams.length
# while cam_no<cam_indx
cams.each do |cam|
info=cam.attribute_dictionary("is_a_camera")
m=Sketchup.active_model
view=m.active_view
UI.start_timer(3, false) {puts cam_no, cam}
### For some reason this timer now does not pause, but it did previously. The view moves
### immediately to the last camera position and halts. It does verify in the console that
### the script is stepping through the camera group list. Only the last camera number is
### displayed (cam_indx times). If the flag is set to true instead of false, you can see
### in the console it is looping endlessly but the view remains the same.
view.camera=Sketchup;;Camera.new(info["eye"],info["target"],info["up"],info["persp"],info["fov"]), 3
# UI.messagebox("camera no.; " + cam_no.to_s) ### uncomment this line to see how the script
### (almost) should work.
view.invalidate ### I read somewhere that if this is placed after the messagebox call, the
### box won't appear. But it does.
cam_no += 1
### I also tried the following snippet but it merely behaves like start_timer
# time_mark = ( Time.now + 3 )
# while time_mark > Time.now
# end
end
end
This would be activated by a Plugin menu item.
I've attached a Sketchup file with some cameras already created. It is not pretty but should save time for you.
test_anim.skp
If the problem is a simple bug or wrong syntax, it eludes me. My conceptual understanding of Ruby is weak (hence my wholesale copying of Google's code). But if I can get past this, I can think about different transition times, changing attributes (to pan maybe), and maybe allowing a user to pause whenever they want.
Mike
I am trying to use Ruby to automate a tour through my model but I have hit a wall trying to get my script to wait for the view to update. I want the script to step through the model and find each entity that matches a particular criteria, perform some action and only then go to the next matching entity and repeat. Every structure I try, like 'array.each do|x|' or 'while' or 'if n<number_of_entities', steps through the whole model but perform the desired action only on the last matching entity.
Searching this forum, I have found several posts on similar issues but none of the given solutions work for me and I just cannot figure out why. One solution is 'view.invalidate'. As far as I can see, this has absolutely no visible effect on the model or view or script execution. The other suggestion is 'UI.start_timer'. Yes, execution pauses for the set interval but then acts on the last match as above. The only thing that works - sort of - is 'UI.messagebox' This allows the action to be performed on each chosen entity in turn but of course the box pops up with that irritating noise and requires user intervention to cancel so the script can continue. I have searched in vain for a work around, like repositioning the box off screen and setting a timeout to automatically close the box (plus silencing the beep). Sadly, no such options appear to exist. (It seems Visual Basic and the Windows API can do it but that's way beyond me.)
Can anyone explain the correct use of view.invalidate and/or start_timer? Or direct me to some existing tutorial on these? The usual newbie disclaimer and apologies apply... Thank you.
Mike