Skip to content

Instantly share code, notes, and snippets.

@mattcox
Last active July 12, 2018 21:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattcox/b9ec4dd4ae56888526b47c82b9ac05de to your computer and use it in GitHub Desktop.
Save mattcox/b9ec4dd4ae56888526b47c82b9ac05de to your computer and use it in GitHub Desktop.
This example demonstrates how to manually implement a tool operation item.
/*
*
* This example demonstrates how to manually implement a tool operation
* item.
*
*/
#include <lxsdk/lx_mesh.hpp>
#include <lxsdk/lx_tool.hpp>
#include <lxsdk/lx_toolui.hpp>
#include <lxsdk/lx_vector.hpp>
#include <lxsdk/lxu_attributes.hpp>
#include <lxsdk/lxu_math.hpp>
#include <lxsdk/lxu_modifier.hpp>
#include <lxsdk/lxu_package.hpp>
#include <lxsdk/lx_layer.hpp>
#include <cmath>
static const char *sPackageName = "plane.tool.item";
static const char *sToolOpName = "plane.tool.operation";
static const char *sToolName = "plane.tool";
static const char *sModifierName = "plane.tool.modifier";
static const char *sAttrSize = "size";
static LXtTextValueHint sHintMinZero[] =
{
0, "%min",
-1, NULL
};
class Package :
public CLxDefaultPackage
{
public:
static void
initialize()
{
CLxGenericPolymorph *srv = new CLxPolymorph<Package>;
srv->AddInterface(new CLxIfc_Package<Package>);
srv->AddInterface(new CLxIfc_StaticDesc<Package>);
lx::AddServer(sPackageName, srv);
}
LXxO_Package_SetupChannels // LxResult (ILxUnknownID addChan)
{
CLxUser_AddChannel channel(addChan);
if(LXx_OK(channel.NewChannel(sAttrSize, LXsTYPE_DISTANCE)))
{
channel.SetDefault(0.5, 0);
channel.SetHint(sHintMinZero);
}
if(LXx_OK(channel.NewChannel(LXsICHAN_TOOL_OBJ, LXsTYPE_OBJREF)))
{
channel.SetInternal();
}
return LXe_OK;
}
static LXtTagInfoDesc descInfo[];
};
LXtTagInfoDesc Package::descInfo[] =
{
{ LXsPKG_SUPERTYPE, LXsITYPE_TOOLOP },
{ LXsPKG_TOOL_TASK, LXs_TASK_ACTR },
{ LXsPKG_TOOL_ORDER, LXs_ORD_ACTR },
{ LXsPKG_TOOL_CHANNEL, LXsICHAN_TOOL_OBJ },
{ 0 }
};
enum ePacketOffset
{
ePacketOffset_Subject2,
ePacketOffset_MAX
};
class ToolOperation :
public CLxImpl_ToolOperation
{
public:
static void
initialize()
{
CLxGenericPolymorph *srv = new CLxPolymorph<ToolOperation>;
srv->AddInterface(new CLxIfc_ToolOperation<ToolOperation>);
lx::AddSpawner(sToolOpName, srv);
}
static ToolOperation*
Spawn(
void **ppvObj)
{
static CLxSpawner<ToolOperation> spawner(sToolOpName);
return spawner.Alloc(ppvObj);
}
ToolOperation()
{
for(unsigned int i = 0; i < ePacketOffset_MAX; i++)
{
mPacketOffsets[i] = 0;
}
}
LXxO_ToolOperation_Evaluate // LxResult (ILxUnknownID vts)
{
CLxUser_VectorStack vector(vts);
if(true == vector.test())
{
CLxUser_Subject2Packet subjectPacket;
if(true == vector.ReadObject(mPacketOffsets[ePacketOffset_Subject2], subjectPacket))
{
CLxUser_LayerScan layerScan;
if(true == subjectPacket.BeginScan(LXf_LAYERSCAN_EDIT, layerScan))
{
unsigned int count = layerScan.NumLayers();
for(unsigned int i = 0; i < count; i++)
{
CLxUser_Mesh mesh;
if(true == layerScan.EditMeshByIndex(i, mesh))
createPlane(mesh, mSize);
}
return LXe_OK;
}
}
}
return LXe_FAILED;
}
void
createPlane(
CLxUser_Mesh &mesh,
double size)
{
if(false == mesh.test() || lx::Compare(size, 0.0) == LXi_EQUAL_TO)
return;
static double positions[4][3] = {{-1.0, 0.0, -1.0},
{ 1.0, 0.0, -1.0},
{ 1.0, 0.0, 1.0},
{-1.0, 0.0, 1.0}};
CLxUser_Point point(mesh);
LXtPointID pointIDs[4];
for(unsigned int i = 0; i < 4; i++)
{
LXtVector temp;
LXx_VSCL3(temp, positions[i], mSize);
point.New(temp, &pointIDs[i]);
}
CLxUser_Polygon polygon(mesh);
LXtPolygonID polygonID = NULL;
polygon.New(LXiPTYP_FACE, pointIDs, 4, 1, &polygonID);
mesh.SetMeshEdits(LXf_MESHEDIT_GEOMETRY);
}
void
setSize(
double size)
{
mSize = std::fabs(size);
}
bool
setPacketOffset(
unsigned int index,
unsigned int offset)
{
if(index >= ePacketOffset_MAX)
return false;
mPacketOffsets[index] = offset;
return true;
}
private:
unsigned int mPacketOffsets[ePacketOffset_MAX];
double mSize;
};
class Tool :
public CLxImpl_Tool,
public CLxImpl_ToolModel,
public CLxDynamicAttributes
{
public:
static void
initialize ()
{
CLxGenericPolymorph *srv = new CLxPolymorph<Tool>;
srv->AddInterface(new CLxIfc_Tool<Tool>);
srv->AddInterface(new CLxIfc_ToolModel<Tool>);
srv->AddInterface(new CLxIfc_Attributes<Tool>);
srv->AddInterface(new CLxIfc_AttributesUI<Tool>);
srv->AddInterface(new CLxIfc_StaticDesc<Tool>);
lx::AddSpawner(sToolName, srv);
}
static Tool*
Spawn(
void **ppvObj)
{
static CLxSpawner<Tool> spawner(sToolName);
return spawner.Alloc(ppvObj);
}
Tool()
{
dyna_Add(sAttrSize, LXsTYPE_DISTANCE);
attr_SetFlt(0, 0.5);
for(unsigned int i = 0; i < ePacketOffset_MAX; i++)
{
mPacketOffsets[i] = 0;
}
CLxUser_PacketService pktSvc;
if(true == pktSvc.NewVectorType(LXsCATEGORY_TOOL, mVecType))
{
if(LXx_OK(pktSvc.AddPacket(mVecType, LXsP_TOOL_SUBJECT2, LXfVT_GET)))
mPacketOffsets[ePacketOffset_Subject2] = pktSvc.GetOffset(LXsCATEGORY_TOOL, LXsP_TOOL_SUBJECT2);
}
}
LXxO_Tool_VectorType // LXtObjectID (void)
{
return mVecType.m_loc;
}
LXxO_Tool_Order // const char * (void)
{
return LXs_ORD_ACTR;
}
LXxO_Tool_Task // LXtID4 (void)
{
return LXi_TASK_ACTR;
}
LXxO_Tool_GetOp // LxResult (void **ppvObj, unsigned flags)
{
*ppvObj = NULL;
ToolOperation *toolOp = ToolOperation::Spawn(ppvObj);
if(NULL != toolOp)
{
toolOp->setSize(dyna_Float(0, 0.5));
for(unsigned int i = 0; i < ePacketOffset_MAX; i++)
{
toolOp->setPacketOffset(i, mPacketOffsets[i]);
}
}
return ((NULL != *ppvObj) ? LXe_OK : LXe_FAILED);
}
static LXtTagInfoDesc descInfo[];
private:
CLxUser_VectorType mVecType;
unsigned int mPacketOffsets[ePacketOffset_MAX];
};
LXtTagInfoDesc Tool::descInfo[] =
{
{ LXsTOOL_USETOOLOP, "." },
{ 0 }
};
class ModifierElement :
public CLxItemModifierElement
{
public:
ModifierElement(
CLxUser_Evaluation &eval,
ILxUnknownID item)
{
mSizeChannel = -1;
mToolChannel = -1;
CLxUser_Item modifierItem(item);
if(true == eval.test() && true == modifierItem.test())
{
mSizeChannel = eval.AddChan(item, sAttrSize, LXfECHAN_READ);
mToolChannel = eval.AddChan(item, LXsICHAN_TOOL_OBJ, LXfECHAN_WRITE);
}
}
void
Eval(
CLxUser_Evaluation &eval,
CLxUser_Attributes &attr) LXx_OVERRIDE
{
if(false == eval.test() || false == attr.test() || mSizeChannel < 0 || mToolChannel < 0)
return;
ILxUnknownID object = NULL;
Tool *tool = Tool::Spawn((void**)&object);
if(NULL != tool)
{
CLxUser_ValueReference valueReference;
if (true == attr.ObjectRW ((unsigned int) mToolChannel, valueReference))
{
valueReference.SetObject(object);
CLxUser_Attributes toolAttr(object);
if(true == toolAttr.test())
toolAttr.Set(0, attr.Float((unsigned int) mSizeChannel));
}
lx::UnkRelease(object);
}
}
private:
int mSizeChannel, mToolChannel;
};
class ModifierServer :
public CLxItemModifierServer
{
public:
static void
initialize()
{
CLxGenericPolymorph *srv = new CLxPolymorph<ModifierServer>;
srv->AddInterface(new CLxIfc_EvalModifier<ModifierServer>);
srv->AddInterface(new CLxIfc_TagDescription<ModifierServer>);
lx::AddServer(sModifierName, srv);
}
const char*
ItemType() LXx_OVERRIDE
{
return sPackageName;
}
CLxItemModifierElement*
Alloc(
CLxUser_Evaluation &eval,
ILxUnknownID item) LXx_OVERRIDE
{
return new ModifierElement(eval, item);
}
};
void
initialize()
{
Package::initialize();
ToolOperation::initialize();
Tool::initialize();
ModifierServer::initialize();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment