Setting validation Proc

why this daoesn’t grey out icon when face with colour only or with no material is selected

# greying out option  -  enabled when face with image texture selected
cmd_PNG_cut.set_validation_proc {
  if Sketchup.active_model.selection[0].is_a? Sketchup::Face
	if (Sketchup.active_model.selection[0].material.texture.filename[-4..-1] == ".png")
          MF_ENABLED
	else
	  MF_GRAYED
	end  
  else
    MF_GRAYED
  end
}

if material doesn’t have a texture then …material.texture…part should give nil which in not == “.png” , which gives false…
or is passing a nil to .filename giving some error which is treated as “something” which means true??

In reality your code is throwing an exception and bailing out of the block of code. You’ll have to test for the presence of a material before calling the texture method on it. There are several ways to code this test.

Error: #<NoMethodError: undefined method `texture' for nil:NilClass>
1 Like

If you don’t catch an Exception with a rescue clause in your code the validation_proc callback block will abort. I haven’t checked in this specific situation, but in general uncaught Ruby Exceptions are reported to the Ruby Console. So, you should always have the RC open when test-running code.

In fact only exceptions from code invoked from the Ruby console evaluation loop throws exceptions there. Everything invoked by events (webdialog callbacks, validation procs, command procs) is silent.

It is not obvious for beginners that you should not only use a code block { ... } (seen from simplest minimal examples) but also a begin ... rescue ... end inside. It’s not necessary if the code is bug-free, but since we can never assume (especially during development) that our code is bug-free, we want to know about failures. Most tutorials and Ruby examples don’t show that.

cmd_png_cut.set_validation_proc {
  begin
    # ...
  rescue => error
    puts(e.message)
    puts(error.backtrace)
  end
}

Maybe a feature request to make the SketchUp API event code handler blocks print a warning or exception for uncaught exceptions.


@tjdrgas, validation procs are called very often whenever the UI refreshes its state (because of that validation procs should not do heavy operations). That means your code has to handle anything that could be selected, not only what you expect to be selected.
Besides the check for Sketchup::Face and !material.nil? you also need to consider untextured materials either by

!material.texture.nil?

or

material.materialType >= Sketchup::Material::MATERIAL_TEXTURED
1 Like

In Ruby, it’s preferred to write variables and methods lowercase with underscores (only class names uppercase): cmd_png_cut

Don’t repeat long expressions, use a temporary variable instead:
first_selected = Sketchup.active_model.selection[0]
This is also safer for methods where you cannot assume they always return the same result (like rand()).

Use parenthesis around method calls: first_selected.is_a?(Sketchup::Face)

You could also use higher-level libraries (that do the low-level stuff for you), like:
File.extname(texture.filename) == '.png'

2 Likes

I did it with catching an exception… just cos I have never done it before…

cmd_PNG_cut.set_validation_proc {
  if ((sel =Sketchup.active_model.selection).size == 1) && (sel[0].is_a? Sketchup::Face)
	#catching an error from passing nil to .filename if material has no texture
	begin
	if (sel[0].material.texture.filename[-4..-1] == ".png")
      MF_ENABLED
	else
	  MF_GRAYED
	end     # if (sel[0]

	  rescue
	  MF_GRAYED #...
   end #begin
	
	else
    MF_GRAYED
  end # ((sel =Sketchup.a
}

I could check if material is textured but I was reading a lot about exceptions and I just had to use it…
I will use every bit of your advise guys… and thanks to all for increadibly fast response…

–that agrees with my experience… I had no error or exception messages in Ruby Console…