hi,
sorry for the late reply.
using a customDataTag works (at least on R22)
the header for the custom tag (based on the SDK example)
#ifndef _PC12498_H__
#define _PC12498_H__
#include "maxon/lib_math.h"
#include "lib_customdatatag.h"
#include "maxon/apibase.h"
#include "maxon/datatype.h"
#include "maxon/mesh_attribute_base.h"
static const maxon::Int32 ID_POLYGGONID_TAG = 1054949;
namespace maxon
{
//----------------------------------------------------------------------------------------
/// Polygon Information
/// This class is used to store the polygon ID.
/// It have been created because of a bug in the customdatatag and because the data size must be 64bits
// This class provides a way to store in a custom data tag an int32 index for each component.
// Internally the modeling system uses some bits to define some special behaviours.
// For this reason we shift _polygonIndex by 4 bytes using _privateBuffer.
//----------------------------------------------------------------------------------------
class PolygonInformation
{
public:
PolygonInformation() = default;
MAXON_IMPLICIT PolygonInformation(Int32 index) : _privateBuffer(0), _polygonIndex(index) { }
PolygonInformation& operator =(const PolygonInformation& src)
{
_polygonIndex = src._polygonIndex;
_privateBuffer = src._privateBuffer;
return *this;
}
inline Bool operator ==(const PolygonInformation& other) const
{
return _polygonIndex == other._polygonIndex;
}
inline Bool operator <(const PolygonInformation& other) const
{
return _polygonIndex < other._polygonIndex;
}
MAXON_OPERATOR_COMPARISON(PolygonInformation);
inline String ToString(const FormatStatement* formatStatement) const
{
return String::IntToString(_polygonIndex);
}
Int32 _privateBuffer = 0; /// not used just here for the size of the class
Int32 _polygonIndex = NOTOK;
};
//----------------------------------------------------------------------------------------
/// Declaration of a new DataType.
/// This will be store inside the new mesh attribute
//----------------------------------------------------------------------------------------
MAXON_DATATYPE(PolygonInformation, "net.maxonexample.meshattribute.polygonid");
//----------------------------------------------------------------------------------------
/// Declaration of the new MeshAttribute
//----------------------------------------------------------------------------------------
MAXON_MESHATTRIBUTE(PolygonInformation, POLYGONID);
//----------------------------------------------------------------------------------------
/// Declaration of the new DataTape for the mesh attribute
//----------------------------------------------------------------------------------------
MAXON_DATATYPE(POLYGONID_MESHATTRIBUTE, "net.maxonexample.meshattribute.polygonidattribute");
namespace CustomDataTagClasses
{
//----------------------------------------------------------------------------------------
/// Declaration of the CustomDataTag class for the polygonID itself
//----------------------------------------------------------------------------------------
MAXON_DECLARATION(maxon::CustomDataTagClasses::EntryType, POLYGONID, "net.maxonexample.mesh_misc.customdatatagclass.polygonid");
} // namespace CustomDataTagClasses
}; // namespace maxon
#endif
.cpp for the tag itself
namespace maxon
{ // Register the datatype
MAXON_DATATYPE_REGISTER(PolygonInformation);
MAXON_DATATYPE_REGISTER(POLYGONID_MESHATTRIBUTE);
// Tag implementation
class PolygroupIDTagImpl : public Component<PolygroupIDTagImpl, CustomDataTagClassInterface>
{
MAXON_COMPONENT();
MAXON_CUSTOMDATATAG(ID_POLYGGONID_TAG, "polygon id"_s, ""_s, CustomDataTagClasses::POLYGONID.GetId(), 0, NOTOK, 0); // notice the last value is 0, this mean the tag is not VISIBLE and not multiple
public:
MAXON_METHOD const DataType& GetDataType() const
{
return maxon::GetDataType<POLYGONID_MESHATTRIBUTE>();
}
// There's no interpolation between the polygons
MAXON_METHOD void InterpolateLinear(void* data1, const void* data2, Float blendValue) const { }
MAXON_METHOD void InterpolateInOutline(void* data, const Block<void*>& outline, const Block<Float>& weights) const { }
// default value is 0 (polygon not assigned)
MAXON_METHOD void GetDefaultValue(void* data) const
{
if (!data)
return;
PolygonInformation* v = static_cast<PolygonInformation*>(data);
if (v)
{
(*v)._polygonIndex = -1;
}
}
MAXON_METHOD Bool AtrLessThen(const void* data1, const void* data2) const
{
if (MAXON_UNLIKELY(data1 == nullptr || data2 == nullptr))
return false;
const PolygonInformation* a = static_cast<const PolygonInformation*>(data1);
const PolygonInformation* b = static_cast<const PolygonInformation*>(data2);
return a->_polygonIndex < b->_polygonIndex;
}
MAXON_METHOD Bool AtrIsEqual(const void* data1, const void* data2) const
{
if (MAXON_UNLIKELY(data1 == nullptr || data2 == nullptr))
return false;
const PolygonInformation* a = static_cast<const PolygonInformation*>(data1);
const PolygonInformation* b = static_cast<const PolygonInformation*>(data2);
return a->_polygonIndex == b->_polygonIndex;
}
MAXON_METHOD void AtrAdd(void* data1, const void* data2) const
{
if (MAXON_UNLIKELY(data1 == nullptr || data2 == nullptr))
return;
PolygonInformation* a = static_cast<PolygonInformation*>(data1);
const PolygonInformation* b = static_cast<const PolygonInformation*>(data2);
a->_polygonIndex = 42;
}
MAXON_METHOD void AtrSubstract(void* data1, const void* data2) const { }
MAXON_METHOD void AtrMultiply(void* data1, const void* data2) const { }
MAXON_METHOD void AtrMultiply(void* data, Float value) const { }
MAXON_METHOD void AtrDivide(void* data1, const void* data2) const { }
MAXON_METHOD void AtrDivide(void* data, Float value) const { }
MAXON_METHOD String AtrToString(const void* data, const FormatStatement* formatStatement) const
{
const PolygonInformation* v = static_cast<const PolygonInformation*>(data);
return FormatString("(@)", v->_polygonIndex);
}
MAXON_METHOD Result<void> Read(void* data, HyperFile* hf, Int32 level) const
{
if (!hf || !data)
return IllegalArgumentError(MAXON_SOURCE_LOCATION);
PolygonInformation* dataPtr = static_cast<PolygonInformation*>(data);
if (!dataPtr)
return OutOfMemoryError(MAXON_SOURCE_LOCATION);
if (!hf->ReadInt32(&dataPtr->_polygonIndex))
return IllegalStateError(MAXON_SOURCE_LOCATION);
return OK;
}
MAXON_METHOD Bool Message(GeListNode* node, Int32 type, void* data) const
{
return true;
}
MAXON_METHOD maxon::Result<void> Write(const void* data, HyperFile* hf) const
{
if (!data || !hf)
return IllegalArgumentError(MAXON_SOURCE_LOCATION);
const PolygonInformation* dataPtr = static_cast<const PolygonInformation*>(data);
if (!dataPtr)
return OutOfMemoryError(MAXON_SOURCE_LOCATION);
if (!hf->WriteInt32(dataPtr->_polygonIndex))
return IllegalStateError(MAXON_SOURCE_LOCATION);
return OK;
}
MAXON_METHOD Int32 GetIcon(Bool perPolyVertex) const
{
return NOTOK;
}
};
MAXON_COMPONENT_OBJECT_REGISTER(PolygroupIDTagImpl, CustomDataTagClasses::POLYGONID);
}// namespace maxon
and inside your command you can do something like this. Just create the tag, use the Split command and read back the tag.
// Creates the customDataTag on the passed object
static maxon::Result<void> CreateCustomDataTag(BaseObject* op)
{
iferr_scope;
if (MAXON_UNLIKELY(op == nullptr || !op->IsInstanceOf(Opolygon)))
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
// Have a look at the SDK example for mor information and comments.
const maxon::Int32 polygonCount = ToPoly(op)->GetPolygonCount();
BaseTag* tagCreated = CustomDataTag::Alloc(ID_POLYGGONID_TAG);
if (tagCreated == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
CustomDataTag* polygroupTag = static_cast<CustomDataTag*>(tagCreated);
if (polygroupTag == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
op->InsertTag(polygroupTag);
polygroupTag->InitData() iferr_return;
polygroupTag->SetMode(CUSTOMDATATAG_MODE::POLYVERTEX);
polygroupTag->Resize(polygonCount) iferr_return;
polygroupTag->SetName("Polygon IDs"_s);
for (maxon::Int32 polygonIndex = 0; polygonIndex < polygonCount; ++polygonIndex)
{
for (maxon::Int32 pointIndex = 0; pointIndex < 4; pointIndex++)
{
polygroupTag->SetPolyVertexData<maxon::PolygonInformation>(polygonIndex, pointIndex, maxon::PolygonInformation(polygonIndex));
}
}
return maxon::OK;
}
static maxon::Result<void> pc12498(BaseDocument* doc)
{
iferr_scope;
if (MAXON_UNLIKELY(doc == nullptr))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
BaseObject* op = doc->GetActiveObject();
if (MAXON_UNLIKELY(op == nullptr || !op->IsInstanceOf(Opolygon)))
{
MessageDialog("select at least one polygon object"_s);
return maxon::OK;
}
PolygonObject* obj{ nullptr };
if (op->IsInstanceOf(Opolygon))
obj = static_cast<PolygonObject*>(op);
if (MAXON_UNLIKELY(obj == nullptr))
return maxon::NullptrError(MAXON_SOURCE_LOCATION);
// Create the custom data tag on the object to store the actual polygon IDs
CreateCustomDataTag(op) iferr_return;
// Use the modeling command data to split the polygon, the customData will follow
ModelingCommandData mcd;
mcd.op = obj;
mcd.doc = doc;
mcd.mode = MODELINGCOMMANDMODE::POLYGONSELECTION;
if (!SendModelingCommand(MCOMMAND_SPLIT, mcd))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
PolygonObject* result{ nullptr };
result = static_cast<PolygonObject*>(mcd.result->GetIndex(0));
if (MAXON_UNLIKELY(result == nullptr))
return maxon::NullptrError(MAXON_SOURCE_LOCATION);
doc->InsertObject(result, nullptr, nullptr);
// Read the customData tag information
BaseTag* basePolygonIDTag = result->GetTag(ID_POLYGGONID_TAG);
if (basePolygonIDTag != nullptr)
{
CustomDataTag* polygonIDTag = static_cast<CustomDataTag*>(basePolygonIDTag);
if (MAXON_UNLIKELY(polygonIDTag == nullptr))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
const maxon::Int32 splittedPolyCnt{ result->GetPolygonCount() };
for (maxon::Int32 polygonIndex = 0; polygonIndex < splittedPolyCnt; polygonIndex++)
{
const maxon::PolygonInformation value = polygonIDTag->GetPolyVertexData<maxon::PolygonInformation>(polygonIndex, 1);
ApplicationOutput("the polygon @ was polygon @", polygonIndex, value);
}
}
return maxon::OK;
Cheers,
Manuel