Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Last revision Both sides next revision
developer:dotnetpluginessentials [2015/10/06]
sandy
developer:dotnetpluginessentials [2016/04/05]
sandy
Line 1: Line 1:
-====== Essentials of DotNET ​plug-in programming ​======+====== Essentials of DotNET ​Plug-in Programming ​======
  
 =====So, you are new to DotNET?​===== =====So, you are new to DotNET?​=====
Line 15: Line 15:
  
  
-Unfortunately,​ none of these three groups has a smooth transitional period. It's difficult for C++ programmers because the DotNET paradigm differs in key areas from "unmanaged" ​code (no pointers, no references, no memory management). It's difficult for RhinoScripters because they suddenly have to deal with [[http://​en.wikipedia.org/​wiki/​Object-oriented_programming|OOP]]. And it's difficult for dyed-in-the-wool DotNETters because the Rhino SDK doesn'​t work much like the DotNET platform namespaces and classes.+Unfortunately,​ none of these three groups has a smooth transitional period. It's difficult for C++ programmers because the DotNET paradigm differs in key areas from unmanaged code (no pointers, no references, no memory management). It's difficult for RhinoScripters because they suddenly have to deal with [[http://​en.wikipedia.org/​wiki/​Object-oriented_programming|object-oriented programming (OOP)]]. And it's difficult for dyed-in-the-wool DotNETters because the Rhino SDK doesn'​t work much like the DotNET platform namespaces and classes.
  
 \\ \\
Line 35: Line 35:
 Every class in the Rhino SDK comes in two flavors, a const and a non-const one. Const instances all start with "​I"​ (such as IOnPlane, IOnBoundingBox). Every class in the Rhino SDK comes in two flavors, a const and a non-const one. Const instances all start with "​I"​ (such as IOnPlane, IOnBoundingBox).
  
-IRhinoCurveObject and IRhinoEventWatcher). You are not allowed to change these instances, and indeed ​they lack all the functions that would in some way alter the memory state. For example, IOn3dPoint ​allows ​you to retrieve x, y and z coordinates,​ but not set them.+**IRhinoCurveObject and IRhinoEventWatcher).** You cannot ​change these instances, and they lack all the functions that would alter the memory state. For example, IOn3dPoint ​lets you retrieve x, y and z coordinates,​ but not set them.
  
-Non-const objects start with "​On"​ if they are part of opennurbs. They start with "​MRhino"​ if they are part of Rhino (such as OnPlane, OnBoundingBox,​ MRhinoCurveObject and MRhinoEventWatcher). These instances can be altered without problems.+Non-const objects start with "​On"​ if they are part of openNURBS. They start with "​MRhino"​ if they are part of Rhino (such as OnPlane, OnBoundingBox,​ MRhinoCurveObject and MRhinoEventWatcher). These instances can be altered without problems.
  
- +If you need to alter a plane, but the instance you've got is of type IOnPlane, you need to make a copy of the const instance. All the types in the SDK have copy constructors,​ which take another instance of the same type and make an exact (but always non-const) duplicate:
-If you need to alter a plane, but the instance you've got is of type IOnPlane, you'​ll ​need to make a copy of the const instance. All the types in the SDK have //copy constructors//, which take another instance of the same type and make an exact (but always non-const) duplicate:+
  
 \\ \\
Line 65: Line 64:
  
 | **Gotcha for C++ developers** | | **Gotcha for C++ developers** |
-| You've probably caught on to that having two versions for each class is a way to mimic the '​const'​ keyword in C++. Rhino is written in C++ and uses constness all over the place. However, the DotNET framework lacks a keyword that operates like 'const'. So we had to use this horrific hack to let DotNET plug-ins to use Rhino'​s unmanaged C++ kernel. ​Hence, On3dPoint in DotNET is the same as ON_3dPoint in C++ and IOn3dPoint is the same as const ON_3dPoint. |+| You've probably caught on to that having two versions for each class is a way to mimic the '​const'​ keyword in C++. Rhino is written in C++ and uses constness all over the place. However, the DotNET framework lacks a keyword that operates like const. So we had to use this horrific hack to let DotNET plug-ins to use Rhino'​s unmanaged C++ kernel. ​So, On3dPoint in DotNET is the same as ON_3dPoint in C++ and IOn3dPoint is the same as const ON_3dPoint. |
  
-\\ 
 \\ \\
  
Line 73: Line 71:
 ======SDK class hierarchy====== ======SDK class hierarchy======
  
-The class hierarchy in opennurbs ​and Rhino is straightforward,​ although a bit counter-intuitive at times. For example, any curve object in Rhino is an instance of MRhinoCurveObject. (Object is something that can be selected with the mouse.) MRhinoCurveObject itself has a member of the abstract type OnCurve, meaning that it can contain all the different curve types that inherit from this abstract class (such as OnNurbsCurve,​ OnArcCurve, OnLineCurve,​ and OnPolyCurve). But, you'll find types in opennurbs ​which are clearly mathematical curves, and they do not derive from OnCurve. Examples are OnCircle, OnArc, OnLine, and OnBezierCurve. The thinking is that these classes are so atomic, that they should be as light-weight as possible. That is why there is both an OnArc and an OnArcCurve class.+The class hierarchy in openNURBS ​and Rhino is straightforward,​ although a bit counter-intuitive at times. For example, any curve object in Rhino is an instance of MRhinoCurveObject. (Object is something that can be selected with the mouse.) MRhinoCurveObject itself has a member of the abstract type OnCurve, meaning that it can contain all the different curve types that inherit from this abstract class (such as OnNurbsCurve,​ OnArcCurve, OnLineCurve,​ and OnPolyCurve). But, you'll find types in openNURBS ​which are clearly mathematical curves, and they do not derive from OnCurve. Examples are OnCircle, OnArc, OnLine, and OnBezierCurve. The thinking is that these classes are so atomic, that they should be as light-weight as possible. That is why there is both an OnArc and an OnArcCurve class.
  
-\\ 
  
 | //Atomic type// ​  | //Curve type// | | //Atomic type// ​  | //Curve type// |
Line 112: Line 109:
  
  
-Everything inside the Document is fixed. You are not allowed to change anything. This may sound odd, since you're changing things all the time as a regular user. The thing to realize is that '​changing'​ is not the same as '​replacing'​. Once a curve makes it into the Rhino document, the only way to modify ​it is to replace it with another curve that looks similar. The reason for this bottlenecking is that we need to keep track of all the changes made, so we can keep the undo records in synch. If plug-ins changed the object colors without telling anybody, there'​d be no way to maintain a correct undo-stack.+Everything inside the Document is fixed. You are not allowed to change anything. This may sound odd, since you're changing things all the time as a regular user. The thing to realize is that '​changing'​ is not the same as '​replacing'​. Once a curve makes it into the Rhino document, the only way to change ​it is to replace it with another curve that looks similar. The reason for this bottlenecking is that we need to keep track of all the changes made, so we can keep the undo records in synch. If plug-ins changed the object colors without telling anybody, there'​d be no way to maintain a correct undo-stack.
  
  
Line 150: Line 147:
 This particular example is a bit redundant, since the Document already has a function called TransformObject() which does all this duplicating and replacing behind the scenes. This particular example is a bit redundant, since the Document already has a function called TransformObject() which does all this duplicating and replacing behind the scenes.
  
-\\ 
 \\ \\
  
Line 161: Line 157:
  
  
-For example, if you stick with commands, you never have to worry about undo-records,​ scriptability,​ and error trapping since Rhino takes care of all this. As soon as you start doing stuff 'out of the blue', you are responsible for making sure everything keeps on running smoothly. A prime example of non-command features are the ones initiated from a non modal dialog. Non modal dialogs are usually displayed by calling a certain command, but because they are **non** modal, the command immediately completes while leaving the dialog on the screen. There is no reason why you couldn'​t use the code from within a button on a non modal dialog, but in practice there is a huge difference:+For example, if you stick with commands, you never have to worry about undo-records,​ scriptability,​ and error trapping since Rhino takes care of all this. As soon as you start doing stuff out of the blue, you are responsible for making sure everything keeps on running smoothly. A prime example of non-command features are the ones initiated from a non modal dialog. Non modal dialogs are usually displayed by calling a certain command, but because they are **non** modal, the command immediately completes while leaving the dialog on the screen. There is no reason why you couldn'​t use the code from within a button on a non modal dialog, but in practice there is a huge difference:
  
   * Any exceptions that you fail to catch in time will crash Rhino. Commands themselves are smart enough not to allow crashes to propagate too far.   * Any exceptions that you fail to catch in time will crash Rhino. Commands themselves are smart enough not to allow crashes to propagate too far.
Line 168: Line 164:
   * There is no failsafe against multiple things running at the same time. Some commands can be nested, but typically you are not allowed to do naughty stuff while a command is running. If a user decides to delete an object that you are using **while** you are using it, you will most likely crash out.   * There is no failsafe against multiple things running at the same time. Some commands can be nested, but typically you are not allowed to do naughty stuff while a command is running. If a user decides to delete an object that you are using **while** you are using it, you will most likely crash out.
  
-\\ 
  
 If you do want to use non modal dialogs, the best way to solve these issues is to make commands for all the features in your plug-in, and have your dialog buttons call those commands instead of running the code themselves. If you do want to use non modal dialogs, the best way to solve these issues is to make commands for all the features in your plug-in, and have your dialog buttons call those commands instead of running the code themselves.
developer/dotnetpluginessentials.txt · Last modified: 2016/04/05 by sandy