8200 would be VarType ( VT_ARRAY | VT_BSTR ). While GetSceneMaterialNamesScript outputs VarType (VT_ARRAY | VT_VARIANT). This was the reason I wrote up this different function to get around that error.
Which version of V-Ray For Rhino / V-Ray For Matrix are you running and getting the said error with GetSceneMaterialNamesScript?
Possible typo, strObjects should be strObject. If i understand it correctly, it should be an array of objects but i cannot test it as i do not get past the GetSceneMaterialNamesScript method at this point.
Btw. you might use Option Explicit to avoid writing variable names which have not been declared before.
@clement can you try running this code instead (which uses Rhino.MaterialName instead)
f = "C:\WhiteReflective.vismat"
Call Rhino.Command("-visLoadVismat " + f)
Dim arrMaterials: arrMaterials = Rhino.MaterialIndices
Dim strObject: strObject = Rhino.GetObject("select")
Dim vRay, mat_name, i, name, f, mat_index, materials, str_name, thisStr, obj_index, newIndex
Set vRay = Rhino.GetPluginObject("{E8CFE179-B60C-411A-8416-62A893334519}")
mat_name = vRay.GetMaterialNameFromVismat(f, False)
str_name = "WhiteReflective"
For i = 0 to UBound(arrMaterials)
thisStr = Rhino.MaterialName(arrMaterials(i))
If InStr(thisStr, str_name) <> 0 Then
Exit For
End If
Next
obj_index = Rhino.ObjectMaterialIndex(strObject)
vRay.ApplyVRayMaterialToObjects mat_name, 1, strObject
Can you describe what are you trying to accomplish with your script ?
I´ve tried to run it and get the same “unsupported property or method” error using VRay.ApplyMaterialToObjects. But i guess this is because i´m using the older VRay version.
Ah, that’s a shame. Well, what I’m trying to achieve is the supremely elusive and seemingly vindictive task of assigning a material to an object. In this case, I have added a ground plane right before this code snippet and here I’m trying to assign add the WhiteReflective material to it.
Here is my workaround when ApplyVRayMaterialToObjects is not working:
Option Explicit
Call Main()
Sub Main()
Dim f, strObject, rid, vRay, mat_name, cmd, result
f = "C:\White Plastic.vismat"
Call Rhino.Command("-visLoadVismat " + CHR(34) + f + CHR(34))
strObject = Rhino.GetObject("select object", 8+16+32, True, True)
If IsNull(strObject) Then Exit Sub
rid = "{E8CFE179-B60C-411A-8416-62A893334519}"
Set vRay = Rhino.GetPluginObject(rid)
If Not IsObject(vRay) Then Exit Sub
mat_name = vRay.GetMaterialNameFromVismat(f, True)
If len(mat_name) = 0 Then Exit Sub
cmd = "-visApplyMaterial " + CHR(34) + mat_name + CHR(34)
result = Rhino.Command(cmd, False)
If result = False Then Rhino.Print "error assigning material"
End Sub
Note that i have a different material and that i put the material name (mat_name) in extra quotes. If you would not do this it would fail using a material name with spaces in the name.
@clement I don’t know if I’m doing something wrong but visApplyMaterial does not seem to do the job for me. The script executes fine, but the material does not seem to apply in the render. So far, I’ve only been able to assign material successfully with rs.CopyMaterial (that was in Rhino Python). Weirdly, when I try Rhino.CopyMaterial (or Rhino.MatchMaterial), I get this error message ‘Type mismatch in parameter. Float required’. Float required?! Aren’t the indices of integer type?
Alright, got this to work. The issue was that Rhino.MaterialIndex needs a material identifier (Rhino.MaterialId) as parameter and not a material name.
Dim vRay, mat_name, i, name, f, mat_index, materials, str_name, thisStr
f = "C:\WhiteReflective.vismat"
Call Rhino.Command("-visLoadVismat " + f)
Dim idMaterials: idMaterials = Rhino.MaterialIds
Dim indexMaterials: indexMaterials = Rhino.MaterialIndices
Dim strObject: strObject = Rhino.GetObject("select")
Set vRay = Rhino.GetPluginObject("{E8CFE179-B60C-411A-8416-62A893334519}")
mat_name = vRay.GetMaterialNameFromVismat(f, False)
str_name = "WhiteReflective"
For i = 0 to UBound(indexMaterials)
thisStr = Rhino.MaterialName(indexMaterials(i))
If InStr(thisStr, str_name) <> 0 Then
mat_index = Rhino.MaterialIndex(idMaterials(i))
Exit For
End If
Next
If IsNull(mat_index) Then
Rhino.Print("Wow, Null")
Rhino.Print("But looks like we have" + thisStr)
Else
Rhino.Print("I'm Neo" + CStr(mat_index))
End If
Rhino.ObjectMaterialIndex strObject, mat_Index
I forgot to mention that -visApplyMaterial only works if your object(s) are selected beforehand. If nothing is selected it will just run through doing nothing. If it assigns the material properly, -visApplyMaterial reports the success to the commandline as well.
Yesterday i´ve tried something which was identical using your last code snippet above but i´ve found something strange: If i get the material index using RhinoScript methods and assign that index to the object, the material name gets assigned as usual, the plugin box gets checked in properties BUT: the edit Button stays greyed out. Somehow this cannot be right. So i´ve done the version above using -visApplyMaterial which seems to fix that.
So as a last comment to your last code, i do not think that it is required to get the index, then compare the material name with all scene material names and finaly assign it. The VRay material name is enough to assign it, at least with the version using -visApplyMaterial. Downside is, it requires the object selection.
I’ll have to check that; I haven’t observed the edit button. Somehow, visApplyMaterial doesn’t work for me and I’m not going to investigate it further. Much thanks for your inputs, @clement. Before we seal this thread for good, do you know of any way of assigning a material from the material library without having to call visLoadVismat?
type visApplyMaterial (without the - sign in front)
A dialog pops up, showing all scene materials
Choose one to assign it to the surface, click ok
Look into properties / material and check for:
A: Is the material name assigned ?
B: Is the plugin box checked ?
C: Is the edit button clickable or grayed out ?
In my case, A B C all work using visApplyMaterial. I can do the same using a script, if i put the - sign in front of -visApplyMaterial, the dialog is suppressed, then i can simply type the material name eg. “\White Plastic”. If the material has spaces in it, i need to type this in quotes. Note the \ in front of the material name. In your last script, you´re just missing this, you might print out the results of your variables to find such errors faster and handle them.
If i run your last posted script, i do not get any of A, B, C, no material gets assigned at all. Using visApplyMaterial is the easiest method to get all things in one go. If you do not use it, you have to control (script) the material source (ByObject, ByLayer) as well. Your script does not do that.
In general, it is required to understand what material indices are. A material index can be any positive integer, including zero.
To assign one material from the scene materials, you might use the vRay.GetSceneMaterialNamesScript method and pop up a listbox filled with the materials array. Then assign the choosen material using visApplyMaterial. Note that the object(s) to assign to need to be selected beforehand. If not, it will not work. Just enter “visApplyMaterial” to the commandline and read what it prints to the command line.
@clement have you had any success working with V-Ray scripting methods for Rhinoscript/Python? I seem to be having the same issues still, so I have stopped wrangling with them and I’m using Rhinoscript methods for material calling.
Yes, below one example how to apply a loaded VRay materials using material indices. If no materials have been loaded, nothing will happen. Short description:
Get all non deleted material names and their material indices
put them in dictionary to remove duplicates
open listbox to select one material by name
ask for objects to apply picked material (ByObject) using its index
import rhinoscriptsyntax as rs
import scriptcontext
def ApplyLoadedVRayMaterial():
vRay = rs.GetPlugInObject("E8CFE179-B60C-411A-8416-62A893334519")
if not vRay:
print "VRAY not found or not loaded !"
return
d = {}
materials = scriptcontext.doc.Materials
for m in materials:
if not m.IsDeleted:
d[m.Name] = m.MaterialIndex
if len(d) == 0: return
mat_name = rs.ListBox(d.keys(), "Select", "Title")
if not mat_name: return
ids = rs.GetObjects("Objects", 8+16+32, False, False, False)
if not ids: return
rs.ObjectMaterialSource(ids, 1)
for id in ids: rs.ObjectMaterialIndex(id, d[mat_name])
print "Applied {0} to {1} objects".format(mat_name, len(ids))
if __name__=="__main__":
ApplyLoadedVRayMaterial()
tested with Rhino5 SR12 and VRay 2.00.25962 (x64).
This looks great! But you haven’t used any of the actual vRay scripting methods, have you? I mean like GetSceneMaterialNames and others listed in the VRayforRhinoExports file?
That is correct. I was not able to get the GetSceneMaterialNames and GetSceneMaterialNamesScript methods do work. They where reported to be available using
hasattr(vRay, 'GetSceneMaterialNames')
but accessing them or putting their return values into a variable was not possible. However all the options related stuff discussed here was working fine.
list = clr.Reference[System.Object]()
vRay.GetSceneMaterialNamesScipt(list)
RhinoApp.WriteLine(list.ToString())
and this one below will work in the latest service release
import clr
from Rhino import *
import Rhino
def LoadPlugin(path):
if path == None:
return False
# MRhinoPlugIn will be null if it is a C++ plugin
plugin = Rhino.RhinoApp.GetPlugInObject(path)
return plugin
def RunCommand():
hPlugIn = LoadPlugin("V-Ray for Rhino")
clr.AddReferenceToFileAndPath("C:\ProgramData\ASGVIS\VfR564\VRayForRhinoNETInterface.dll")
import VRayForRhinoNETInterface
names = VRayForRhinoNETInterface.VRayInterface.GetSceneMaterialNames()
RhinoApp.WriteLine(str(names))
RunCommand()
There are a few more samples scripts installed in on the latest service release:
C:\ProgramData\ASGVIS\VfR564\SampleScripts