Get an up-to-date material preview image file path

Get an up-to-date material preview image file path

m.vallee
Advocate Advocate
1,670 Views
6 Replies
Message 1 of 7

Get an up-to-date material preview image file path

m.vallee
Advocate
Advocate

Hi,

 

I thought the new Revit 2018.1 API dedicated to materials would help me solve a quite old issue, but it seems that it is not the case.

 

I want to retrieve (then show) the image preview of a material. It is the image at the top of the rendering tab (or asset) in the material editor.

From what I have understood, this image is updated/regenerated :

  • if not created yet, when you open the rendering tab for the first time
  • when you change one of the rendering properties

 

The image location path seems to be stored in the AssetProperty called "thumbnail". It can be :

  • relative, if it points to a preset material image in the ADSK library. For instance "Mats\WallPaint\Presets\t_Paint-057.png".
  • absolute. For instance it can point to the "temp" folder when you just regenerated the file. In that case the path is like "materialthumbnails_pid_NNN\XXX.png" or "MaterialRapidRT_PIDNNNNN\XXX.png"

 

So I write this piece of code to get the wanted path :

 

 

AppearanceAssetElement aae = _document.GetElement(mat.AppearanceAssetId) as AppearanceAssetElement;
                        if (null != aae)
                        {
                            Asset asset = aae.GetRenderingAsset();
                            if (null != asset)
                            {
                                if (asset[SchemaCommon.Thumbnail] is AssetPropertyString ap)
                                {
                                    string path = ap.Value;

                                    if (path.StartsWith("Mats") || path.StartsWith("Maps")) // Revit default
                                    {
                                        path = path.Insert(0, @"C:\Program Files (x86)\Common Files\Autodesk Shared\Materials\2018\assetlibrary_base.fbm\");
                                    }
                                    else if (path.StartsWith("material", true, System.Globalization.CultureInfo.CurrentCulture))
                                    {
                                        path = path.Insert(0, @"%tmp%\");
                                    }

                                    if (!string.IsNullOrEmpty(path) && File.Exists(path))
                                    {
                                        Bitmap bmp_representation = new Bitmap(Image.FromFile(path), size); 
                                    }
                                }
                            }
                        }

This works fine for some materials, but for most of them the retrieved path does not exist. Why ? I think it is because the image has not been regenerated in the current Revit session. So ideally I would like the API to have a function that updates a material preview image, so that the corresponding path points to an existing and up-to-date PNG file.

 

 

I also tried to first edit the rendering asset (without making any changes), in the hope that would update the preview image, but no success : for nearly all the materials, the preview image is the UnifiedBitmap default PNG.

 

using (Transaction trans = new Transaction(_document, "Fake transaction"))
                        {
                            trans.Start();
                            using (AppearanceAssetEditScope editScope = new AppearanceAssetEditScope(_document))
                            {
                                Asset editableAsset = editScope.Start(mat.AppearanceAssetId);
                                
                                editScope.Commit(true);
                            }
                            trans.Commit();
                        }

 

Thanks for your ideas/suggestions.

 

Maxime

0 Likes
1,671 Views
6 Replies
Replies (6)
Message 2 of 7

jeremytammik
Autodesk
Autodesk

Dear Maxime,

 

Thank you for your query.

 

I'm surprised the new functionality does not already provide all you need out of the box.

 

I asked the development team for you, in any case.

 

I hope this helps.

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 7

bshafiro
Autodesk
Autodesk

Dear Maxime,

 

Thank you for your query.

 

Yes, I agree that an appropriate convenience method to get the preview image for a Material is missing in the current Materials API. I'll file an issue for our developers.

 

On the workaround that you tried: I think you almost solved it. The problem is that you created an empty transaction that did not change anything. If you open a transaction (and edit scope), then actually change one of the properties in the Asset (that causes the new image to be generated), also store the old value. Commit the edit scope, close the transaction. Then open transaction again (and edit scope), change the same property of the same Asset back to the stored old value. Commit the scope, close the transaction. So, the Material is now in the original unchanged state, but it is guaranteed to have the preview image generated.

 

I hope this helps.



Boris Shafiro
Senior Manager, Software Development
LinkedIn
0 Likes
Message 4 of 7

m.vallee
Advocate
Advocate

Hi,

 

Thanks for your answers.

 

@bshafiro I tried what you say, but it didn't work. I modified a color then reset it like it was with two consecutive transactions :

 

 

                        Bitmap bmp_representation = null;
                        Size size = new Size(64, 64);
                        int factor = 25;

                        using (Transaction trans = new Transaction(_document, "Fake transaction"))
                        {
                            trans.Start();
                            using (AppearanceAssetEditScope editScope = new AppearanceAssetEditScope(_document))
                            {
                                Asset editableAsset = editScope.Start(mat.AppearanceAssetId);
                                AssetPropertyDoubleArray4d metalColorProp = editableAsset["common_Tint_color"] as AssetPropertyDoubleArray4d;

                                Autodesk.Revit.DB.Color color = metalColorProp.GetValueAsColor();
                                byte red = color.Red;
                                byte green = color.Green;
                                byte blue = color.Blue;
                                red = (byte)LimitValue(red + factor);
                                green = (byte)LimitValue(green + factor);
                                blue = (byte)LimitValue(blue + factor);

                                if (metalColorProp.IsValidValue(color))
                                    metalColorProp.SetValueAsColor(new Autodesk.Revit.DB.Color(red, green, blue));
                                editScope.Commit(true);
                            }
                            trans.Commit();
                        }
                        using (Transaction trans = new Transaction(_document, "Fake transaction"))
                        {
                            trans.Start();
                            using (AppearanceAssetEditScope editScope = new AppearanceAssetEditScope(_document))
                            {
                                Asset editableAsset = editScope.Start(mat.AppearanceAssetId);
                                AssetPropertyDoubleArray4d metalColorProp = editableAsset["common_Tint_color"] as AssetPropertyDoubleArray4d;

                                Autodesk.Revit.DB.Color color = metalColorProp.GetValueAsColor();
                                byte red = color.Red;
                                byte green = color.Green;
                                byte blue = color.Blue;
                                red = (byte)LimitValue(red - factor);
                                green = (byte)LimitValue(green - factor);
                                blue = (byte)LimitValue(blue - factor);

                                if (metalColorProp.IsValidValue(color))
                                    metalColorProp.SetValueAsColor(new Autodesk.Revit.DB.Color(red, green, blue));
                                editScope.Commit(true);
                            }
                            trans.Commit();
                        }

The paths of the image previews I get after that are "" or "Maps\UnifiedBitmap\UnifiedBitmap.png". There is no preview image generated in my "temp" folder.

 

 

I think the image previews are regenerated only when they are shown in the Material Editor UI, and that we can't do it programmatically as of today...

 

Best regards.

Maxime

0 Likes
Message 5 of 7

bshafiro
Autodesk
Autodesk

Hi Maxime,

 

Yes, you are correct. It looks like preview is generated only when visible in UI. I am afraid that you cannot write the code without additional API being available... I'll see what we can do about that.

 

Best regards,

-Boris.



Boris Shafiro
Senior Manager, Software Development
LinkedIn
0 Likes
Message 6 of 7

m.vallee
Advocate
Advocate

Hi,

 

Thank you for your answer.

 

I stay tune for more information.

 

Maxime

0 Likes
Message 7 of 7

cliceaHGEUZ
Explorer
Explorer

Hello Boris,

I am working on an application that could also use the material appearance asset preview generated in the UI. If this capability can be made available in the API, it would be greatly appreciated. 

Thank you,

Carlo

0 Likes