But I found, the scale of the bitmap texture be changed on the firs time value setting, if I change the value of the scale again, the scale of the bitmap texture doesn’t change.
Could you help me to check the program?
PS:
We need to use above code to change the scale of the bitmap texture.
The project, I compile on Rhino6. DESNewSample.zip (110.3 KB)
In DESNewSample.zip there are
checkmat small.jpg and my project
I’m afraid this kind of texture mapping code is outside my zone of knowledge. I’ll ask one of our resident mapping experts for advice. @Jussi_Aaltonen Could you take a look at this code and see if you can figure out what’s wrong? Thanks.
The easiest way to clear out unused materials is to run a special command. You need to know the document you are working on (I’ll assume it’s called doc). Try this:
const auto doc_sn = doc.RuntimeSerialNumber();
RhinoApp().RunScript(doc_sn, L"RenderRemoveUnusedMaterials", 0);
Please note that if you are doing this from within a command, it will only work if your command is derived from CRhinoScriptCommand.
I will show you how to do these steps using the new system. This uses CRhRdkContent instead of ON_Material.
const wchar_t* name = L"Panel_1_Back";
// Find the content by name.
CRhRdkContentArray aContent;
doc.Contents().Find(CRhRdkContent::Kinds::Material, name,
false, false, aContent);
if (aContent.Count() == 0)
{
RhinoApp().Print(L"'%s' was not found\n", name);
return failure;
}
// Check if the content is in use (assume only 1 match).
const auto& c = *aContent[0];
if (c.UseCount() > 0)
{
RhinoApp().Print(L"'%s' is in use\n", name);
return failure;
}
// Detach the content from the document.
auto& contents = doc.Contents().BeginChange(RhRdkChangeContext::Program);
auto* pDetach = contents.Detach(c);
contents.EndChange();
if (nullptr != pDetach)
{
// Delete the content.
pDetach->Uninitialize();
delete pDetach;
}
Can I delete the object and the object material in the Rhino Material at the same time?
Because when I delete object, I check CRhRdkContent::UseCount() of the material of the object, it still in use.
context.m_doc.UnselectAll();
context.m_doc.Regen();
unsigned int geometry_filter =
CRhinoGetObject::surface_object |
CRhinoGetObject::polysrf_object |
CRhinoGetObject::mesh_object;
CRhinoGetObject go;
go.SetCommandPrompt(L"Select surface, polysurface, or mesh to delete and del Material");
go.SetGeometryFilter(geometry_filter);
go.EnablePreSelect(TRUE);
go.EnableSubObjectSelect(FALSE);
go.GetObjects(1, 1);
if (go.CommandResult() != CRhinoCommand::success)
return go.CommandResult();
const CRhinoObjRef& object_ref = go.Object(0);
const CRhinoObject* object = object_ref.Object();
if (0 == object)
return CRhinoCommand::failure;
ON_Material material = object->ObjectMaterial();
ON_Material M = object->ObjectMaterial();
CRhinoObjRef refObj(object);
const CRhRdkContent* pMaterial = context.m_doc.Contents().Find(object->ObjectMaterial().RdkMaterialInstanceId());
ON_wString N = pMaterial->InstanceName();
context.m_doc.DeleteObject(refObj, true, true);
object = NULL;
// Find the content by name.
CRhRdkContentArray aContent;
context.m_doc.Contents().Find(CRhRdkContent::Kinds::Material, N, false, false, aContent);
if (aContent.Count() > 0)
{
const CRhRdkContent* c = *aContent.First();
if (c->UseCount() > 0)
{
// the material of the object is not unused material
int n = c->UseCount();
}
}
context.m_doc.Regen();
return CRhinoCommand::success;
When an object is deleted, Rhino does not update the content usage straight away because it can be slow when there are a lot of items. Instead, it does it later when it has time. This means that your code won’t work because Rhino hasn’t had time to update yet. But you can force it to update immediately by adding this (just after object = NULL):
About Add Texture /C++ - #21 by angelwang @Jussi_Aaltonen & @johnc
I load the plugin on Rhino7 and set scale on the dialog, it work OK.
If I load the plugin on Rhino6 and set scale on the dialog, it doesn’t work.
I want to know why it work on Rhino6 has problem.
Hi @johnc
When I add or modify the bitmap texture on the material, if the type of the Texture Mapping is not Surface, can I change the type of Texture Mapping to be Surface by coding?
// The object has a material so it wants to add or modify the bitmap texture on the material.
// Find the RDK material.
ON_Material Material = myObj->ObjectMaterial();
auto* pMaterial = pDoc->Contents().Find(Material.RdkMaterialInstanceId());
if (pMaterial != nullptr)
{
// Find the material's child bitmap texture.
const auto* pTexture = pMaterial->FindChild(CS_MAT_BITMAP_TEXTURE);
if (pTexture == nullptr)
{
// Texture not found; create it and set it as a child of the material.
CRhRdkSimulatedTexture tex;
pTexture = ::RhRdkNewBitmapTexture(tex, pDoc);
auto& m = pMaterial->BeginChange(RhRdkChangeContext::UI);
m.SetChild(pTexture, CS_MAT_BITMAP_TEXTURE);
m.EndChange();
}
if (pTexture != nullptr)
{
auto currentFileName = pTexture->GetParameter(FS_TEX_FILENAME).AsString();
if (currentFileName != m_BmpFile)
{
// Make the operation undoable.
CRhRdkContentUndo cu(*pDoc);
cu.ModifyContent(*pMaterial);
// Begin the change operation.
auto& texture = pTexture->BeginChange(RhRdkChangeContext::UI);
// Set the child texture's file name.
const wchar_t* filename = m_BmpFile;
texture.SetParameter(FS_TEX_FILENAME, filename);
// Set the name of the material from the file name.
ON_wString sName;
ON_FileSystemPath::SplitPath(m_BmpFile, nullptr, nullptr, &sName, nullptr);
texture.SetInstanceName(sName);
// End the change operation.
texture.EndChange();
if (!pMaterial->ChildSlotOn(CS_MAT_BITMAP_TEXTURE))
{
// Turn the bitmap child slot on.
auto& m = pMaterial->BeginChange(RhRdkChangeContext::UI);
m.SetChildSlotOn(CS_MAT_BITMAP_TEXTURE, true);
m.EndChange();
}
}
}
}
You can change a mapping on an object back to surface by deleting the mapping. Surface mapping is the default when there is no actual mapping:
auto attr = myObj->Attributes();
const int channel = 1; // Usually mappings are on channel 1.
const auto plugin_id = RhinoApp().GetDefaultRenderApp();
if (!attr.m_rendering_attributes.DeleteMappingChannel(plugin_id, channel))
return failure;
if (!pDoc->ModifyObjectAttributes(CRhinoObjRef(myObj), attr, true))
return failure;
return success;
Hi @angelwang, you reported some time ago that the view does not react when you change the Scale value on the dialog. I looked into this issue and it appears to be the CDES_RenderMeshRMP render mesh provider that is causing this issue. So to solve it you need make sure that CDES_RenderMeshRMP::BuildCustomMeshes gets called for the object whose texture mapping you modify. You can do this by calling ::RhRdkCustomRenderMeshManager().OnRhinoObjectChanged and these are the options where you can call it:
in the end of the CDlgSampleTexture::UpdateObj before pDoc->Regen();
in the CSampleRhinoEventWatcher::TextureMappingTableEvent
Option 1) is easier since there you know which object that texture mapping affects.
Hi @johnc
When I select an object, how to know the material of the object is plastic and not custom by coding?
And how to change the material of the object to be custom by coding?
I tried this by writing the following test code. If an object is not selected it will prompt for one, then get the assigned material. If it is not a Custom (Basic) Material, it will replace it with a new Custom Material.
CRhinoGetObject go;
if (CRhinoGet::object != go.GetObjects(1, 1))
return failure;
const auto* pObject = go.Object(0).Object();
if (nullptr == pObject)
return failure;
ON_COMPONENT_INDEX ci;
const auto* pMaterial = pObject->ObjectRdkMaterial(ci);
if (nullptr == pMaterial)
return failure;
if (pMaterial->TypeId() == uuidBasicMaterialType)
{
// This is a Custom Material.
}
else
{
// Change the material to a Custom Material.
auto* pNewMaterial = ::RhRdkNewBasicMaterial(ON_Material(), pDoc);
if (nullptr == pNewMaterial)
return failure;
auto& c = pDoc->Contents().BeginChange(RhRdkChangeContext::Program);
c.Replace(*pMaterial, *pNewMaterial); // Deletes pMaterial.
c.EndChange();
pMaterial = pNewMaterial;
}
If you’re not doing this in a command, you might want to react to the CRhinoEventWatcher::OnSelectObjects() event. Be aware that you are not allowed to change the document inside that event handler. Please see the comments in rhinoSdkEventWatcher.h.