Tuesday, March 2, 2010

How To Use NaroCAD To View A Custom Shape (Part III)

This is the last part in the series and describe at large how NaroCAD works internally skipping irrelevant information. So in Part I you find how you can store custom data that Naro will save and restore along with all other data that it stores usually. In Part II you find how to create your custom shape and to create them by invoking the corresponding Lua command added by you. This part describes how to create your visual action that reacts on clicks inside NaroCAD.

Actions, Metaactions and Model-View-Controller
Model-View-Controller is a design pattern in programming that separates logically the program in three components: storage and persistence (named Model), visualization and interaction (named View) and the logic in-between named Controller. The View will display the Model's content and will notify controller if any clicks, other events happen so Controller can change the model.
Being said that, the Actions are the logical component of NaroCAD that "take ownership" of the Controller code in NaroCAD. Because they are that powerful as they can change the model (the data), they can change the view (like create helper shapes without having to relate with the stored data) or they can do completely other things (like launching the renderer), they are constrained by making them to query resources.
So a simple design is like this: NaroCAD have a Model (the Document with a tree of nodes), a Controller logic that switch actions with one active, a view (the tree view, the property grid, the OpenCascade view). An action have to ask specifically for the used resources named Inputs. The inputs give data in a Pipe and Filters manner.
In PartModelling action you will see a minimalist action that does the Delete (when you press delete) as named: Naro.PartModeling.Modifiers.Delete.
In Constructor will ask for the resources:
public Delete(WorkItem workItem) : base(ModifierNames.Delete)
{
RegisterInput(InputNames.Context);
RegisterInput(InputNames.Document);
RegisterInput(InputNames.UiElementsItem);
(...)
Later it will get the resources by translating the input's data:
protected override void OnReceiveInputData(string inputName, object data)
{
switch (inputName)
{
case InputNames.Document:
_document = data as Document; break;
case InputNames.Context:
_context = data as OCAIS_InteractiveContext; break;
(...);
And later it can get the selected shape from _context and delete it from _document.

MetaActions
Meta-actions are actions that are "Command Line"-aware. They are more compact if they are solved directly from function's dependencies but are tricky a bit elsewhere.
What is specific for those actions is that those actions are made from steps and you can override the steps.
One simple meta-action shape is this:
public class RectangleMetaAction : MetaActionBase
{
public override void FillUiDependencies()
{
MetaActionDependencies dependency = Dependency;
dependency.FunctionName = FunctionNames.Rectangle;
dependency.CalculateIntersections = true;
dependency.AutoReset = true;
dependency.Steps[0].HintText = Resources.ModelingResources.RectangleStep1;
dependency.Steps[1].HintText = Resources.ModelingResources.RectangleStep2;
dependency.Steps[2].HintText = Resources.ModelingResources.RectangleStep3;
}
}
Internally NaroCAD will call Rectangle automatically and build everything for preview it. So if you will want to have a mouse/command line aware, you may want to start from MetaActionBase and provide your function's name, and voila, you are ready to go.
To make it accessible, you will have to register this new command, as rectangle's MetaAction is registered as following: (look in: DefaultMetaModifiers.cs from PartModelling)
modifierContainer.Register(ModifierNames.Rectangle3D, "rectangle", new RectangleMetaAction());
Hopefully this mini-series will make you to discover some of the hidden gems that Naro gives to you just on the tips of your fingers. If you're interested in digging in Naro's code, you can find build instructions here.

No comments: