Saturday, March 28, 2009

Pipes and Filters explained and working

I'm not completely sure how much I've explained why and what was changed.

The actions in 3D have a non uniform input code. This makes it really hard both to extend and to make things working in an environment like: multi-click because the click may have a completely different meaning. Also, some actions in 3D do not need a click at all: like (Top will setup the view to make things appear in top).

For that reason there was a need to be able to define different non uniform inputs to the actions to work with, that remains simple enough for the user. The multiple inputs have some limitations, like the most similar ones to share a very similar code. The most common case is the mouse click on a view: the simple click may mean many things: this click may have more meanings like:

- the point projected to a 3D plane, or even more, to be aligned to all closed geometry (so it should pass through a solver) when you draw a 2D shape like a line;
- or some actions can not use the 3D component at all, like to make a zoom to an area
- may look for the object which is under the mouse, or to extract the plane for it

For that reason, there is a pressing need for combining the inputs (to not duplicate code is another reason).At the end of the consuming of events stand the actions, which say which inputs and pipes are needed.


So, as a rough scheme: Input -> Optionally pipe -> Optionally pipe -> Action3D

Here is the code for a pretty complex action:
public class Line3D : Action3d
{
Mouse3dEventsPipe mouseIn;
ViewInput viewIn;
DocumentInput doc;
public Line3D()
: base("Line3D", new List() { "View", "Mouse3dPosition", "Document" })
{
}

protected override void OnSetup()
{
viewIn = Inputs["View"] as ViewInput;
mouseIn = Inputs["Mouse3dPosition"] as Mouse3dEventsPipe;
mouseIn.HasDataNotify += OnRecievedData;
doc = Inputs["Document"] as DocumentInput;
}

public override void Deactivate()
{
base.Deactivate();
mouseIn.HasDataNotify -= OnRecievedData;
}

List points = new List();
void OnRecievedData(Object data)
{
(...)


So from scratch this action can change only the View, Mouse3dPosition and Document.
Mouse3dPosition is a pipe, and Naro API knows its dependencies and tracks them and makes a chain till all of them are connected. Because of that, there is no need for the user to create all the things and to connect them, this thing is done automatically.
Also, in the past was not done, but right now it is, the actions have a deactivate code, this will prevent actions from remaining in an uncertain state at any moment, no matter is canceled or so. This avoids a lot of cases of leaks.

Also, the deactivate cleans automatically all links and break the graph of Inputs and Pipes, it makes the Inputs ready for the next action.

Was it worth doing?
Both in short and long terms it was: it is possible almost to not a single code to create a brand new action without a copy, it is possible to give a (new) meaning to mouse click, the code is safer (as there is a Deactivate method) and also less prone to errors (as it works with less components that need to be saved).
Based on the last two weeks refactor, it enables NaroCAD to work with a new infrastructure, it is of a much higher level than the previous code, it is better detached, it propagates automatically the events, it is debuggable. The actions don't do copy-paste both in 2D and in 3D to achieve a multi-click action.
Anyway, the single action in 3D that works with multiclick is Line for now. I will continue to work for the others. Also, I would like to add the possibility that if mouse stands on a face for more than 3 seconds, to be selected as the face to be drawn.

As there are many refactored parts, I will try also to write documentation to this so if you feel courageous a bit and you like C#, and you want to look a bit at OpenCascade, it will be a great start to extend the NaroCAD code. It will let you to use NaroCAD as the base software and extend it where you need it.


What is the achievement over the last three weeks of refactor?

Based on the fact that you will also get scripting possibility pretty soon, you can extend in NaroCAD almost everything: data storage (as attribute data that can be extended to any component), business logic (tree attributes interpreters), custom shapes (as functions, that are simplified greatly to work with, and all changes are tracked automatically by NaroCAD framework), view presentation (as actions).

Note: NaroCAD also has a debug window (in case you did not know it) that makes almost instant navigation to the scene tree.

No comments: