TransactionStart change in tools (Sketchup 2016)

Hello everyone, I’m having problems with version 2016 of Sketchup,I need something that is triggered when the user has just begun to rotate some instance, this could be done with onTransactionStart (along with other things), but in version 2016 this has changed and break all scripts that depended on this behavior. Now I do not know how to detect this event. anyone knows any alternative?, In SketchUp team might consider returning to the usual behavior ?. Such changes really make it very difficult the job of developer.
(google translator)

Apparently, due to “unsafe” behavior, 2016 incorporates some structural changes in the Observer class explained here. It is indeed unfortunate that this will require developers to rework existing code that worked up until now,

1 Like

The change in SU2016 was that no observers are triggered while there is an active operation - we defer them until the operation is commited. This was done because interrupting active operations was a big source of trouble.

We also change Ruby operations to not send out onTransactionStart/Commit for intermediate Ruby operations - but you should still get a notification for the start and end.

Can you elaborate a bit more on exactly what you do? Sample reproducible snippet?
Have you looked at the ToolsObserver? (Seeing how you mentioned needing to react to when an object is being rotated.)

basically I need to have the transformation matrix before and after the rotation, I was doing this

class MyModelObserver < Sketchup::ModelObserver
  
  def mov_rot_scl?(id)
	[21048,21129,21236].index(id)
  end  
  
  def instances_selec(sel)
	sel.select{|e| e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)}
  end
  
  def onTransactionStart(model)
	sel = instances_selec(model.selection)
	if mov_rot_scl?(model.tools.active_tool_id) && sel.size>0
	  p ("tr initial: " + sel.first.transformation.origin.to_s)
	end
  end
  
end

observer = MyModelObserver.new
Sketchup.active_model.add_observer(observer)

adding some code to remove unwanted or repeated results
in Sketchup 2016 I can achieve in the case of the scale or movement with something like this

class MyToolsObserver < Sketchup::ToolsObserver
  
  def mov_rot_scl?(id)
	[21048,21129,21236].index(id)
  end  
  
  def instances_selec(sel)
	sel.select{|e| e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)}
  end
  
  def onToolStateChanged(tools, tool_name, tool_id, state)
	sel = instances_selec(tools.model.selection)
	if mov_rot_scl?(tool_id) && state==1 && sel.size>0
	  p ("tr initial: " + sel.first.transformation.origin.to_s)
	end
  end
  
end

toolobserver = MyToolsObserver.new
Sketchup.active_model.tools.add_observer(toolobserver)

but the rotation does not react in any way when started the action :confused:, I wonder why they have not corrected it to react like the scale or the movement, It seems very easy to make. Any suggestions?
(Google translator)

I still do not see an easy solution, Does anyone have an idea?

I haven’t coded observers (I really try to avoid them). I can offer a suggestion.
The API for:
http://www.sketchup.com/intl/en/developer/docs/ourdoc/modelobserver#onTransactionStart
states that onTransactionStart is invoked when a Model start_operation occurs.

According to @tt_su, SU2016 has implemented observers differently.
The tool that performs the start_operation is now going to be allowed to perform a Model “commit_operation” before calling any observers. That kind of supercedes any reason to use onTransactionStart. Is onTransactionStart being called ever? In that method, you could try:

puts "onTransactionStart being called"

The current output “p” statement is inside an “if” that may not be working.

According to @tt_su,

You may need to perform a scale or movement, then exit the move, rotation, or scale tool and return to the select tool before the observer is triggered.
If it still isn’t being called, you need to consider another method. The next choice is “onTransactionCommit”. See if a “puts” statement will work in it.
If that observer method is triggered, then you can expect the transaction to have completed. (I didn’t “try this at home”, I’m just speculating).

I recall needing to react to Move, Rotate and Scale myself - and there was some differences in how they changed their states. I don’t recall the details, but I’ll see if I can find what extension it was and what notes I made.

onTransactionStart is called - but it’s deferred until the operation is committed. Again this is to prevent third parties from interfering with open operation.

Found the extension: AutoSmooth/core.rb at 1.1 · thomthom/AutoSmooth · GitHub

But my comment didn’t explain whether any states changed before starting the operation. But you might be able to tap into tool activation and cache your data and then on state change react?

(Probably need to have a look at how the states changes again - just throwing some ideas out there.)

Thanks for answering.

I was thinking something like what you say, I’m analyzing different scenarios:

1) The user has selected instances, chooses the rotate tool and performs the rotation.

2) The user has not selected entities, chooses the rotate tool, poses the cursor over an entity and executes the rotation.

3) The user has selected instances, chooses the rotate tool, right-click on an empty space and deselect the instances.

4) The user has selected objects chooses the rotate tool, right-click and then left click on an entity which was not part of the initial selection.

For case 1) I can use onActiveTabChanged, to capture the case 3) I can use onSelectionCleared but for the second there are not many options, Case 4) can be detected onSelectionBulkChange, I Observe that onSelectionAdded is activated in case situation 2) in the way I need, but I think this may change in future versions because this behavior is not documented in the API.

Someone comes up with an idea?

At some point, before my time at SketchUp, it was said that onSelectionAdded and onSelectionRemoved wasn’t firing - and their events removed from the API docs. But there clearly are cases where they do - I think API triggered selection changes do this. Not sure what the full story is here, but it’s on our list to look into.

I think that there was a bug where they did not fire from the Outliner (or only fired from the Outliner,) and rather than fix all the code to call the correctly named callbacks, those two were just deprecated.

I remember posting a suggestion (for Ruby extension authors,) that those deprecated callbacks be aliased into the non-deprecated ones.

The whole problem could be corrected properly if the SketchUp team would make the rotation tool will return a value just before executing a rotation, in the same way as does the scale tool or move (Through onToolStateChanged), in this time simply does not react, I want to know whether the development team Sketchup considered fix this, I think it’s not complicated to do.
(Google translator)

1 Like