HowTo : Can you give me a getting started guide for complex custom objects ?
Article | 60001640 |
Type | HowTo |
Product | Engine |
Version | 6 |
Date Added | 3/13/2012 |
Submitted by | |
Keywords | |
Subject
Can you give me a getting started guide for complex custom objects ?
Summary
Can you give me a getting started guide for complex custom objects ?
Solution
I will try to give you a good description on Custom
Objects and how you should try to approach such an implementation.
My guide is for a .NET project in c# which is mainly
the programming language that we use.
First of all you will have to create a solution with
2 projects like it is implemented in our samples. One project will be a very
simple form with a control (Scrollable , framed doesn't matter) , preferably
vdFramedControl because the vdFramedControl having the Properties List and
the commandLine will give you a good debug project. In any case the code you
will write for the vdFramedControl it is the same for the
vdScrollableControl.
So we have a project with a vdFramedControl and some
buttons to be used for testing the custom object.
The second project will be a dll which will contain
your custom objects (exactly as it is in our samples). A reference for this
project is required to the other project with the form so you can use your
custom object for testing.Once you finish the
implementation of your custom object then the dll can be referenced in your
main application without a problem and you can have this solution for
testing and debugging your custom object.
Now after these initial setup lets start with the
Custom Object.
First of all you will need to have some properties for
your custom object that have to do with it's Geometry and how this object
will be drawn.
I believe that you should go for a vdFigure object.
So we first define the object like this
public
class
vdBox
: vdFigure,
IvdProxyFigure
The vdBox being a vdFigure
has already a pencolor , a layer , a penstyle etc... will could be used in
drawing the object (will explain later in the draw method)
The IvdProxyFigure is required
for such a custom object.
Add an empty constructor for the object (required
always)
And also a help constructor passing a Document. You
can also add a constructor passing some of the basic properties but this can
be added later after we finish with the properties.
/// Empty constructor
of the object always required for creating a custom object.
public vdBox()
{
}
///
Helpfull constructor that also initializes the object with Document's
defaults.
///
<param name="Doc">The
Document that the object will use.</param>
public
vdBox(vdDocument
Doc)
{
SetUnRegisterDocument(Doc);
setDocumentDefaults();
}We will also add
some properties for the object:
We will need a VertexList
(collection of points) in order to keep the points of the little rectagles
You will also need a
centerpoint (gPoint) for the main rectangle
and a MainWidth/MainHeight
(double values) for the main
and also LittleWidth/LittleHeight
(double values) for the little rectangles
You should add the properties
like explained in all our custom objects samples , like below
private
gPoint
mInsertionPoint = null;
///
<summary>
/// The Insertion
Point of the vdBox object.
///
</summary>
[EditorAttribute(typeof(VectorDraw.Professional.PropertyList.vdPickPointDialog),
typeof(System.Drawing.Design.UITypeEditor))]
[GlobalizedCategory("Geometry")]
[GlobalizedDisplayName("InsertionPoint")]
[GlobalizedDescription("Get/Set
the Insertion Point of the vdTable object in World Coordinative System.")]
public
gPoint
InsertionPoint
{
get
{ if
(mInsertionPoint ==
null)mInsertionPoint =
new
gPoint();
return
mInsertionPoint; }
set
{
if
(InsertionPoint.AreEqual(value))
return;
AddHistory("InsertionPoint",
value);
//For the Undo/Redo implementation of VectorDraw
mInsertionPoint.CopyFrom(value);
}
}The Globalized... are used in the
properties list to display a description on the button , the name of the
property and also it's category. You do not have to add these if you do not
intend to use our propertieslist in your application.
Now that we have finished the properties (more
properties can be added later while the implementation progresses but at
least we have the geometrical properties in order to draw the object.
We override the Draw method.
public
override
VectorDraw.Render.vdRender.DrawStatus
Draw(VectorDraw.Render.vdRender
render)
{
vdRender.DrawStatus
doDraw = base.Draw(render);
if
(doDraw == vdRender.DrawStatus.Successed)
{
//Draw stuff here
}
AfterDraw(render);
return
doDraw;
}
If the base.Draw is called then the AfterDraw
must always be called!!!! Be careful with any try{} catch statements.
These calls basically initialize some features for the draw and also set the
base color to be drawn with the vdFigure's pencolor etc...
So for example if we draw a line inside the draw method and the pencolor of
the object is red then the line will be red.
You can change colors by using PushPenStyle methods and PopPenStyle (always
after) of the render like below
render.PushPenstyle(BackGroundColor,
false);
render.DrawSolidPolygon(this,
mSegments, vdRender.PolygonType.Simple);
render.PopPenstyle();
Now lets draw the main rectangle but prior
explain about the ECS matrix ;
I'm sure you have seen the ECSMatrix in our
custom objects and also in our VDF objects. It is much easier to draw
your object in user Coordinate System , lets say 0,0,0 and then by using the
ECSMatrix transform the object where it is supposed to be drawn. For example
we will draw the main rectangle by having the centerpoint to 0,0,0 and then
use the InsertionPoint on the ECSMatrix to translate the object there.
double
wid = 3.0; //(this
Value will Be property among others)
render.PushMatrix(ECSMatrix);
gPoints
pts = new gPoints();
pts.Add(new
gPoint (-wid,-wid,0.0));
pts.Add(new
gPoint(wid, -wid,
0.0));
pts.Add(new
gPoint(wid, wid,
0.0));
pts.Add(new
gPoint(-wid, wid,
0.0));
pts.Add(new
gPoint
(-wid,-wid,0.0));
render.DrawPLine(this,
pts);
render.PopMatrix();
This will draw a rectangle
Now we override the ECSMatrix and set the
InsertionPoint
public
override
Matrix
ECSMatrix
{
get
{
if
(mEcsMatrix != null)
return
mEcsMatrix;
mEcsMatrix = new
Matrix();
mEcsMatrix.TranslateMatrix(InsertionPoint.x, InsertionPoint.y,
InsertionPoint.z);
return
mEcsMatrix;
}
}
To the EcsMatrix you can add properties Like
ExtrusionVector , Rotation , Scale etc... Check our samples.
The last thing that needs implementation before we see our object drawn is
the BoundingBox.
public
override
Box
BoundingBox
{
get
{
if
(mBoundBox.IsEmpty)
{
mBoundBox = new
Box();
mBoundBox.AddPoint(new
gPoint());
mBoundBox.AddWidth(3.0);
mBoundBox.TransformBy(ECSMatrix);
}
return
mBoundBox;
}
}
The BoundingBox has to be calculated depending the various properties of the
object and it is a box that always contains the object.
Now after this initial coding our custom object is ready to be added in the
entities of a model ( of a Document) and to see it drawn.
Lets go to the Sample application that is used for debugging and after adding
the references required lets add this custom object to the Document.
Add the code to a simple test button :
vdBox
box = new
vdBox(vdFramedControl1.BaseControl.ActiveDocument);
box.InsertionPoint =
new
gPoint(10,
10, 0);
vdFramedControl1.BaseControl.ActiveDocument.Model.Entities.AddItem(box);
vdFramedControl1.BaseControl.ActiveDocument.Redraw(true);
A rectangle is drawn at 10,10 with width 3.0 !!!!
You will notice that this rectangle is already
selectable , and you can see it's properties to the framedControl's
propertiesList and also change them to see how they interact with the
object.
After we finish the draw of the object and
it's draw properties then we will have to implement some basic override
methods which are required for several methods of vdraw.
First of all we add the Serialize / DeSerialize override methods so the
object is saved in vdml/vdcl (Implementation is saving all the properties of
the object and can be seen in our samples).
The
Update override is called every time a redraw of the item is required. Here
you can initialize some private data that have to do with the draw of the
object. If you change the color of the object or any other property then
this method will be called. For example if you have a hard calculation that
is required (and needs time to calculate) for the draw of the object you can
keep the result in a private structure. Then in the draw method only do this
calculation if the value of the result is null , and set this value = null
to the update method. This way if the object is not changed then the
calculation will not be called unless an update of the object is required.
You only call update outside the custom object in your application if you
change a basic property.
Transformby override is called when the object is
moved , scaled etc.... For example you can call the CmdMove command and
select your object. If you implement the TransformBy then you can move you
object by changing it's InsertionPoint in this method.
GetGripPoints is the3 method where you add the grips
that you will need for your object.
OnDocumentSelected override is called when the
object is added to a Document's Entities. You can do intialization stuff
here for the object.
MatchProperties override is required to Clone the
object. Clone is used by VectorDraw for example when you call the move
command then a cloned object is created and is drawn so you see the object
moving. See how this method is implemented using the properties' of the
custom object in our samples.
Explode Method is called when you explode the custom
object and you should return here VectorDraw primitive Objects like vdRect ,
vdPolyline , vdCircle etc... This method will also be called if you want to
export your object in DWG/DXF file so the result will be saved in these
formats.
getOsnapPoints override is used for Osnaps if you
want your custom object to show Osnaps while in a command.
After the above implementations your custom object
is ready to be added in a Document's Entities , drawn , saved / exported in
a format. You can add this object with code.
Now you will have to create a command
CreateBox for example.
A simple command like below can be performed
by asking your user for a simple point and a width and then create your
object.
public
static
bool
CreateBox(vdDocument
Doc)
{
gPoint
cen = new
gPoint();
Doc.Prompt("Insertion
Point : ");
object
ret = Doc.ActionUtility.getUserPoint();
Doc.Prompt(null);
if
(ret == null
|| !(ret is
gPoint))
return
false;
cen = ret as
gPoint;
Doc.Prompt("Width : ");
ret = Doc.ActionUtility.getUserDist(cen);
Doc.Prompt(null);
if
(ret == null)
return
false;
double
Width = (double)ret;
vdBox
box = new
vdBox(Doc);
box.InsertionPoint = cen;
Doc.Model.Entities.AddItem(box);
return
true;
}
And call this method in a test button
vdBox.CreateBox(vdFramedControl1.BaseControl.ActiveDocument);
A more complex action can be implemented if you want
your user to have interaction and your object to be drawn real-time during
the command (for example if you want to see your custom object to be drawn
while you select the Width of the Box) using the
ActionEntityEx. You can
see a good example
to the VectorDrawPolygon command
CmdPolygon.
Further information can be provided if you
have a specific issue creating your custom object. It is impossible to
explain all the various implementations that you may want for your custom
object. For example you may want different draws in 2D or in 3D , you may
want to only select by clicking specific figures , you may want your action
to draw other things that do not draw with the object , you may want not to
see these objects in viewports and the list/capabilities is endless...