Component browser current selection?
-
Dear all,
i searched but can't find a good solution to my problem - therefore my first post here. Maybe someone can point me in the right direction (if it can be done at all)?
Consider the following szenario:
In the component browser i have a couple of components for which i'd like to implement a custom component movement/placement tool.
E.g. when dragging these components from the browser for placing them in the model i'd like to check clearance when moving the components around and prevent placement if the component would end up too close to some obstacle.My first thought was to
- tag these components by adding an attribute
and - install a ToolsObserver watching for the ComponentTool in its onActiveToolChanged callback (i.e. detecting the native tool when the user drags a component from the browser to place it in the model).
Then, if the chosen component has the attribute set, i'd just call my custom placement tool (automatically canceling the native placement tool)
The ToolsObserver fires as expected whenever i click on a component inside the component browser window, but i can't find a way to get the component definition chosen.
I'd need this info to check for the tag and pass the definition to my own tool if appropriate.
For the materials browser there's Sketchup.active_model.materials.current to retrieve the current selection but there's nothing similar (i know of) for the components browser.The ToolsObserver would have an additional benefit that extending it to do obstacle checking when moving tagged components already instantiated in the model should be fairly straightforward:
In the ToolsObserver additionally watch for the MoveTool and call the custom move/place tool with the definition of the currently selected component instance (if tagged)...The only workaround alternative i can think of:
Instead of observing tools, i could monitor the model definitions using a DefinitionsObserver. It fires an onComponentAdded when the component is selected in the browser for the first time (i.e. when its definition is added to the model) and it reports the definition as needed.
But dragging the same component from the browser again doesn't add a new definition to the model and the observer doesn't fire ...
So - workaround for the workaround would be:
in the onComponentAdded callback function- clone the chosen original component definition without the tag (to avoid endless loop)
- destroy the original definition so the original is added to the DefinitionList (and the observer fires) next time again
- and place the clone by my own tool.
Now - isn't that ugly (and a nightmare for the undostack)? You'd have to make sure these components never occur in original form at any time inside your model or otherwise the observer wouldn't work.
So i'd really prefer sticking to a ToolsObserver if possible.
Has anyone done something similar? Is there a "hack" or workaround to retrieve the selected component from the browser (Windows, script is for personal use, so what?) or does someone know a plugin/script i should take a look at?Sorry for the long text and thanks in advance!
Michael S.
- tag these components by adding an attribute
-
Since your tool doesn't need to kick in until the instance is placed, why not use an entities observer ?
As your tool loads add it to the model.entities and any definitions.entities. Also add an app observer to ensure new models get the same entities observer added to them.That observer spots when a new instance is added and checks if its definition has some distinguishing feature - like a name or custom attribute set true - and if so your tool kicks in selecting the instance and letting the user do whatever your tool does...
You could also have a selection observer to spot if a relevant instance is selected and perhaps do some checking etc ?
-
Thank you for the quick response TIG.
"Since your tool doesn't need to kick in until the instance is placed..."
well - not exactly. Sorry, I wasn't clear enough on this.Actually i wanted to prevent placing the instance in the first place and - more importantly - have a visual feedback when hovering with the mouse over the model while trying to place the instance. (I really should have mentioned this in my first post...)
My custom tool would draw a simplified "ghost" of the component using opengl functionality in the model at the mouse position (using inputpoint or pickhelper) if placing is ok.
Otherwise i'd draw a red cross or similar indicating that placing the instance at the inputpoint is not allowed.
A left click on a forbidden place wouldn't do anything while a left click in a place where it's ok finally inserts the component instance into the model and exit the tool.Your suggested method works - i tried something like this before - but gives no visual feedback while placing the instance.
The "tool" can only remove the just placed instance if it was dropped in a forbidden place and reinvoke Sketchup.active_model.place_component to try again.Since i can't access the onMouseMove or draw callbacks of the builtin component placement tool, i can't have realtime visual feedback with it - therefore i intended to write my own tool.
Michael S
-
OK, when it is placed and the observer spots it, then immediately kick in your Tool.
Attach the instance by its insertion-point onto the cursor, then move it with the cursor, doing what ever checks are needed etc, allow the user to click to place it only when its 'right'...
You need to define your extension as a 'Tool' to add the extra functions regarding reading the cursor's location, on_clicks etc...
You get the instance.transformation and its .origin for the insertion point, and transform the instance from there to the cursor, initially to grab it, then again each mouse move... -
Ok - thanks TIG - i tried again over the weekend.
Unfortunately i can't get it working the way i want. I think the available observers and methods are just not providing the necessary functionality.I can intercept the default MoveTool for a component instance contained in the model using a ToolsObserver and let my tool run instead - fine.
I can spot when an instance was placed using a ModelObserver with onPlaceComponent and let my tool run - fineBut i can't intercept the placement of a component before an instance was actually added to the model.
The ToolsObserver fires when i click on a component in the components browser but doesn't provide info on the chosen definition.
On that first click in the browser the definition is added to the model's definitionlist (only once as i stated before) and a DefinitionsObserver can spot this (once).
The component now sticks to the mouse pointer and i can hover over the model. There's no change to the model's entities collection yet.
The instance is placed when i click (a second time) somewhere in the model.
Now the component instance is added to the model entities collection and at this point an Entities-Observer or Model-Observer (onPlaceComponent) can spot it.
But this is already too late for visual feedback while placing.Nevertheless... keeping on sketch(up)ing
Michael S.
Advertisement