Sunday, June 27, 2010

Plugin Sample and MetaAction Code Separation

Adding features makes a lot of code to be added in one place as and makes that code to have some problems known as anti-patterns. The biggest one is code coupling and which means that adding an external component will simply mean to change NaroCAD code.
In the last days I've tried to cleanup a bit the code just targeting this.
So I've decided to make a simple task: to add dynamically from Lua a new shape, that is a "SimpleLine" that is created by defining just its two points. The Line in NaroCAD is more powerful as it can express relations with other lines (the normal line shape is covered by the NaroCAD's line shape). Also I've wanted that this shape to be defined in a separate assembly as it would be an natural way to extend NaroCAD.
So what I've found out?
NaroCAD is written in an Object Oriented Programming (OOP) manner, meaning that most of the created entities are defined in (abstract) factories, and the factory have a registering mechanism. If you want to add your new shape, you will have to define your Function based class, and to register to the corresponding Factory (named intuitively as FunctionFactory). In a proper extend it was visible that Lua have no access to this entities and some were needed to exist.
This makes to show which factories are really exposed, and which are really coupled in NaroCAD's core. One of them was standing out: the MetaActions's Factory. As MetaActions were defined to a NaroCAD component named PartModelling under the CommandLineAction, the code was just inside PartModelling and at least no other external meta-action was possible to be registered (without making hacks).
The factories exposed are for: Functions, Lua methods, Inputs meaning new data sources for NaroCAD based actions, new Actions, new Options dialog pages and new custom Property Grid dialogs.
The single missing part is that you cannot add it to ribbon tab as the code, but excluding that you can do it just starting from Lua and your C# component, you can customize NaroCAD fairly dramatic. As you can register commands like Meta-Actions, you can add your custom command line tools. I will try to create a small tutorial how to create your custom shape and register it to NaroCAD as running and to make it working.
But as I thought that most of people wants just to create their custom OCC shape and to be ready to go, I've made a simple Lua API that you can execute your function (even registered in Lua) and fill its dependencies.
So I've created this SimpleLinePlugin that defines internally the SimpleLine function, and without registering to Lua (you should register your Function though), you can write a code as follows:
loadPlugin("SimpleLinePlugin");

defineShape("SimpleLine");
setPoint(100,100,0);
setPoint(200,200,0);
executeShape();

The SimpleLine function is defined as follows:
public class SimpleLine : FunctionBase
{
public SimpleLine() : base("SimpleLine")
{
// First point of line
Dependency.AddAttributeType(InterpreterNames.Point3D);
// Second point of line
Dependency.AddAttributeType(InterpreterNames.Point3D);
}

public override bool Execute()
{
// Get the two line points
var firstPoint = Dependency[0].Point3D.GpPnt;
var secondPoint = Dependency[1].Point3D.GpPnt;
if (firstPoint.IsEqual(secondPoint, OCPrecision.Confusion()))
return false;

var aEdge = new OCBRepBuilderAPI_MakeEdge(firstPoint, secondPoint).Edge();
var wire = new OCBRepBuilderAPI_MakeWire(aEdge).Wire();
Shape = wire;

return true;
}
And is registered by creating a class in the SimpleLinePlugin class library the class named: FunctionRegister and you should write the following:
public class FunctionRegister : PluginFunctionBase
{
public void Register()
{
FunctionFactory.Register<SimpleLine>();
}
}

Doing so, your Lua code will work as is.
A note: to make your plugin work, you should have as reference the PluginInterface.dll to your plugin to have acess to PluginFunctionBase type. Also the FunctionRegister class is hardcoded, so you will have to name it just as this to make your registering work.
So for now, excluding that you want to dramatically change the UI (mostly the Ribbon tabs), you can change almost all functionality of NaroCAD by registering from Lua a new plugin that can come with it's shapes, Lua commands, etc. I think that someone will use it and will add new things to NaroCAD.

No comments: