2018.1 VisualMaterials API: Set Render Color


#1

I only have a very basic knowledge of C#, and even less understanding of python, but am trying to convert code from one to the other to work in a Dynamo graph…

Unfortunately, I am struggling to get something that works. Any suggestions here?

C# method, from page 9 of http://thebuildingcoder.typepad.com/files/sd124625_visual_appearance_of_materials_api_boris_shafiro_handout.pdf:

public void SetDiffuseColor(Material material, Color color)
	{
		ElementId appearanceAssetId = material.AppearanceAssetId;
		AppearanceAssetElement assetElem = material.Document.GetElement(appearanceAssetId) as AppearanceAssetElement;
		// A transaction is necessary.  
		// Multiple changes to the same asset can be made in one transaction if required.
		using (Transaction t = new Transaction(assetElem.Document, "Change material color"))
		{
			t.Start();
			using (AppearanceAssetEditScope editScope = new AppearanceAssetEditScope(assetElem.Document))
			{
				Asset editableAsset = editScope.Start(assetElem.Id);
				// returns an editable copy of the appearance asset
				// unlike AppearanceAssetElement.GetRenderingAsset(), the edit scope
				// sets up the asset for editing using the classes and utilities from
				// MaterialsManager. If the Asset was not obtained from an edit scope,
				// the setter operations for asset properties will throw.
				// Try to change values
				AssetPropertyDoubleArray4d genericDiffuseProperty = editableAsset["generic_diffuse"] as AssetPropertyDoubleArray4d;
				Color col = color as Color;
				genericDiffuseProperty.SetValueAsColor(col);
				// Commit the entire edit scope.  
				// If the appearance asset element is used in one or more materials, 
				// they will be updated to match any changes made.
				editScope.Commit(true);
			}
			t.Commit();
		}
	}

Attempted Python code:

def SetDiffuseColor(material, color):
	doc = DocumentManager.Instance.CurrentDBDocument
	try:
		appearanceAssetId = ElementId(material.AppearanceAssetId)
		assetElem = AppearanceAssetElement(doc.GetElement(appearanceAssetId))
		# A transaction is necessary.  
		# Multiple changes to the same asset can be made in one transaction if required.
		with Transaction(assetElem.Document, "Change material color") as t:
			t.Start()
			with AppearanceAssetEditScope(assetElem.Document) as editScope:
				editableAsset = Asset(editScope.Start(assetElem.Id))
				# returns an editable copy of the appearance asset
				# unlike AppearanceAssetElement.GetRenderingAsset(), the edit scope
				# sets up the asset for editing using the classes and utilities from
				# MaterialsManager. If the Asset was not obtained from an edit scope,
				# the setter operations for asset properties will throw.
				# Try to change values
				genericDiffuseProperty = AssetPropertyDoubleArray4d(editableAsset["generic_diffuse"])
				col = Color(color)
				genericDiffuseProperty.SetValueAsColor(col)
				# Commit the entire edit scope.  
				# If the appearance asset element is used in one or more materials, 
				# they will be updated to match any changes made.
				editScope.Commit(true)
			t.Commit()
		return material
	except:
		return None

#2

OK, I think I have something that works now:

def SetDiffuseColor(material, color):
	doc = DocumentManager.Instance.CurrentDBDocument
	try:
		appearanceAssetId = material.AppearanceAssetId
		assetElem = doc.GetElement(appearanceAssetId)
		# A transaction is necessary.  
		# Multiple changes to the same asset can be made in one transaction if required.
		TransactionManager.Instance.EnsureInTransaction(doc)
		with Visual.AppearanceAssetEditScope(assetElem.Document) as editScope:
			editableAsset = editScope.Start(assetElem.Id)
			# returns an editable copy of the appearance asset
			# unlike AppearanceAssetElement.GetRenderingAsset(), the edit scope
			# sets up the asset for editing using the classes and utilities from
			# MaterialsManager. If the Asset was not obtained from an edit scope,
			# the setter operations for asset properties will throw.
			# Try to change values
			genericDiffuseProperty = editableAsset.FindByName("generic_diffuse")
			genericDiffuseProperty.SetValueAsColor(color)
			# Commit the entire edit scope.  
			# If the appearance asset element is used in one or more materials, 
			# they will be updated to match any changes made.
			editScope.Commit(True)
		TransactionManager.Instance.TransactionTaskDone()
		return material
	except:
		return None