My First Controller Plug-in... Questions--

My First Controller Plug-in... Questions--

michael_lawler
Enthusiast Enthusiast
1,267 Views
12 Replies
Message 1 of 13

My First Controller Plug-in... Questions--

michael_lawler
Enthusiast
Enthusiast

Ok, so I've been reviewing/reading the SDK and I have some questions as I attempt my first controller plug-in (starting out as an ASCII win32 project). So here goes (a question may have multiple parts):

Question 1.
(a) Is it possible to customize the controller gizmo apparatus?

(b) Is the controller gizmo governed by gizmo.h (there are a few gizmo type headers-- I'm not sure which one relates to controller gizmos)?

(c) If it is possible to modify, how would I go about adding a resultant vector arrow for the position move tool mode/position controller (rather than hitting/manipulating X, Y, or Z axis or grabbing a "plane")? (e.g., using the LookAt() legacy matrix3 controller, what I want to achieve is a position mode vector that would point at the LookAt target from the camera node and hitting and manipulating this vector would allow you to modify the targetDistance parameter along the "LookAt Radial axis" and thus move the camera accordingly.)

0 Likes
1,268 Views
12 Replies
Replies (12)
Message 2 of 13

michael_lawler
Enthusiast
Enthusiast

So I found in the SDK the answer to question 1(a) is yes.  Specifically the SDK states:


Controllers that want to have a gizmo (apparatus) available in the scene will implement these methods

Control :: Display(TimeValue t, INode* inode,  ViewExp *vpt, int flags)

Control :: HitTest(TimeValue t, INode* inode, int type,  int crossing, int flags, IPoint2 *p, ViewExp *vpt)

Control :: GetWorldBoundBox(TimeValue t,INode* inode,  ViewExp *vpt, Box3& box)

Control :: ActivateSubobjSel(int level, XFormModes& modes)

Control :: SelectSubComponent(CtrlHitRecord *hitRec,  BOOL selected, BOOL all, BOOL invert=FALSE)

Control :: ClearSelection(int selLevel)

Control :: SubObjectIndex(CtrlHitRecord *hitRec)

Control :: SelectAll(int selLevel)

Control :: InvertSelection(int selLevel)


So my new controller would need to implement its own Display() and HitTest() methods (but are those the only two?) ...what about the "Modify Sub-object apparatuses" that the SDK discusses (i.e., SubMove, Subrotate, SubScale...)?  Are those needed by a controller gizmo or are they only for Modifier-type gizmos?

0 Likes
Message 3 of 13

michael_lawler
Enthusiast
Enthusiast

So continuing my search for bread crumbs within the SDK documentation... I found some classes in "objmode.h" pertaining to the control apparatus:

class MoveCtrlApparatus
class RotateCtrlApparatus
class ScaleCtrlApparatus
class SelectCtrlApparatus
class TransformCtrlApparatus

All of these take a pointer to a Control as a formal parameter... so it seems these classes are what are responsible for updating user interactions (Move, Rotate, Scale, Select) with a controller's transform gizmo-- am I correct???

I don't like to experiment "in-the-blind" but I guess I will just have to try and implement a "LookAt vector" (similar to the X,Y, Z arrows) to append to the move gizmo for the legacy LookAt Matrix3 controller (as a test case)... then figure out how to HitTest it.

 

Any guidance from another Controller developer would be greatly appreciated.  Thanks.

0 Likes
Message 4 of 13

lucas.yang
Alumni
Alumni

Let me answer the questions about several Control methods and HitTest.

 

1.

Control:: GetWorldBoundBox(TimeValue t,INode* inode, ViewExp *vpt, Box3& box)
Control:: ActivateSubobjSel(int level, XFormModes& modes)
Control:: SelectSubComponent(CtrlHitRecord *hitRec, BOOL selected, BOOL all, BOOL invert=FALSE)
Control:: ClearSelection(int selLevel)
Control:: SubObjectIndex(CtrlHitRecord *hitRec)
Control:: SelectAll(int selLevel)
Control:: InvertSelection(int selLevel)

All above functions have default implementation, but you can implement your specific function.

Also here are some examples in the SDK directory, they would help for you:

samples\controllers\exprctrl.cpp

samples\controllers\indescale.cpp
samples\controllers\block
samples\controllers\spring


2.  HitTest:

 

Following is an example about Gizmo Hit Testing using Polylines
http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__files_GUID_0B01E195_BCA5_4058_9502_03CBCDE23E4...

 

Following is Sub-Object Hit Testing
http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__files_GUID_1435A4DC_878D_420F_A4FF_8F4B1E3E1D0...

 

More details about the Hit testing in the following link:

http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__files_GUID_C545DC05_32C5_4947_A067_CC27534BF6D...

 

Now let me answer the question b and c

 

Answer for question b:

Is the controller gizmo governed by gizmo.h (there are a few gizmo type headers-- I'm not sure which one 

relates to controller gizmos)?

You can see that the method Control::GetWorldBoundBox also can be used to calculated for the world space 

bounding box of the controllers gizmo, thus gizmo.h is not the only one to related to the controller gizmos.

Answer for question c:

I can give a new idea about deciding the distance between moving camera and the hit point.

You can try to use the Ray

 

http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__cpp_ref_class_ray_html

This class has two data members: Point p(point of origin) and Point dir(direction vector)

After you have these two points, you can use the formula 

ptDistance = ray.p + ray.dir * distance to compute the targetDistance;

I wish this can help you. Thank you very much.


Lucas Yang
Developer Technical Services
Autodesk Developer Network


0 Likes
Message 5 of 13

michael_lawler
Enthusiast
Enthusiast

Thanks Lucas... I will take a deeper look at the references you provided and will post any follow-up questions I have.

0 Likes
Message 6 of 13

lucas.yang
Alumni
Alumni

Please check the sample code in the sdk 2015

Thanks


Lucas Yang
Developer Technical Services
Autodesk Developer Network


0 Likes
Message 7 of 13

michael_lawler
Enthusiast
Enthusiast

Lucas,

 

None of the files or folders in the Zip file you just provided contains the missing header and resource file for the FootStep control project you cited earlier.

 

I created a FootStepControl wizard project and copied in the footstep.cpp file as my FootStepControl.cpp file.

 

The FootStep Control file ( footstep.cpp ) is located in the folder:  ..\maxsdk\howto\SourceCodeExamples  -- but there is no header file or resource.h file for the footstep.cpp thus I get scores of errors due to unknown resource strings when I try to compile it.

 

I think all I need is the actual FootStep resource.h file to replace the default one the wizard has created for me.

 

Output Window errors:

Compiling...
FootStepControl.cpp
FootStepControl.cpp(115) : error C2065: 'IDS_RB_FOOTSTEPSAMPLE' : undeclared identifier
FootStepControl.cpp(115) : error C3861: 'GetResString': identifier not found, even with argument-dependent lookup
FootStepControl.cpp(579) : error C2065: 'IDC_SHOWFOOTPRINTS' : undeclared identifier
FootStepControl.cpp(588) : error C2065: 'IDC_ACTIVE_X' : undeclared identifier
FootStepControl.cpp(588) : error C2051: case expression not constant
FootStepControl.cpp(590) : error C2065: 'IDC_ACTIVE_Y' : undeclared identifier
FootStepControl.cpp(590) : error C2051: case expression not constant
FootStepControl.cpp(592) : error C2065: 'IDC_ACTIVE_Z' : undeclared identifier
FootStepControl.cpp(592) : error C2051: case expression not constant
FootStepControl.cpp(594) : error C2065: 'IDC_ACTIVE_XY' : undeclared identifier
FootStepControl.cpp(594) : error C2051: case expression not constant
FootStepControl.cpp(596) : error C2065: 'IDC_ACTIVE_YZ' : undeclared identifier
FootStepControl.cpp(596) : error C2051: case expression not constant
FootStepControl.cpp(598) : error C2065: 'IDC_ACTIVE_ZX' : undeclared identifier
FootStepControl.cpp(598) : error C2051: case expression not constant
FootStepControl.cpp(601) : error C2065: 'IDC_ACTIVE_SYS' : undeclared identifier
FootStepControl.cpp(601) : error C2051: case expression not constant
FootStepControl.cpp(603) : error C2065: 'IDC_ACTIVE_SEL' : undeclared identifier
FootStepControl.cpp(603) : error C2051: case expression not constant
FootStepControl.cpp(605) : error C2065: 'IDC_ACTIVE_LOCAL' : undeclared identifier
FootStepControl.cpp(605) : error C2051: case expression not constant
FootStepControl.cpp(608) : error C2065: 'IDC_ACTIVE_VIEW' : undeclared identifier
FootStepControl.cpp(608) : error C2051: case expression not constant
FootStepControl.cpp(610) : error C2065: 'IDC_ACTIVE_SCREEN' : undeclared identifier
FootStepControl.cpp(610) : error C2051: case expression not constant
FootStepControl.cpp(612) : error C2065: 'IDC_ACTIVE_WORLD' : undeclared identifier
FootStepControl.cpp(612) : error C2051: case expression not constant
FootStepControl.cpp(614) : error C2065: 'IDC_ACTIVE_PARENT' : undeclared identifier
FootStepControl.cpp(614) : error C2051: case expression not constant
FootStepControl.cpp(616) : error C2065: 'IDC_ACTIVE_LOCALSYS' : undeclared identifier
FootStepControl.cpp(616) : error C2051: case expression not constant
FootStepControl.cpp(618) : error C2065: 'IDC_ACTIVE_OBJECT' : undeclared identifier
FootStepControl.cpp(618) : error C2051: case expression not constant
FootStepControl.cpp(622) : error C2065: 'IDC_ENABLE_X' : undeclared identifier
FootStepControl.cpp(622) : error C2051: case expression not constant
FootStepControl.cpp(626) : error C2065: 'IDC_ENABLE_Y' : undeclared identifier
FootStepControl.cpp(626) : error C2051: case expression not constant
FootStepControl.cpp(630) : error C2065: 'IDC_ENABLE_Z' : undeclared identifier
FootStepControl.cpp(630) : error C2051: case expression not constant
FootStepControl.cpp(634) : error C2065: 'IDC_ENABLE_XY' : undeclared identifier
FootStepControl.cpp(634) : error C2051: case expression not constant
FootStepControl.cpp(635) : error C2065: 'IDC_ENABLE_YZ' : undeclared identifier
FootStepControl.cpp(635) : error C2051: case expression not constant
FootStepControl.cpp(636) : error C2065: 'IDC_ENABLE_ZX' : undeclared identifier
FootStepControl.cpp(636) : error C2051: case expression not constant
FootStepControl.cpp(641) : error C2065: 'IDC_ENABLE_SYS' : undeclared identifier
FootStepControl.cpp(641) : error C2051: case expression not constant
FootStepControl.cpp(642) : error C2065: 'IDC_ENABLE_SEL' : undeclared identifier
FootStepControl.cpp(642) : error C2051: case expression not constant
FootStepControl.cpp(643) : error C2065: 'IDC_ENABLE_LOCAL' : undeclared identifier
FootStepControl.cpp(643) : error C2051: case expression not constant
FootStepControl.cpp(648) : error C2065: 'IDC_ENABLE_VIEW' : undeclared identifier
FootStepControl.cpp(648) : error C2051: case expression not constant
FootStepControl.cpp(649) : error C2065: 'IDC_ENABLE_SCREEN' : undeclared identifier
FootStepControl.cpp(649) : error C2051: case expression not constant
FootStepControl.cpp(650) : error C2065: 'IDC_ENABLE_WORLD' : undeclared identifier
FootStepControl.cpp(650) : error C2051: case expression not constant
FootStepControl.cpp(651) : error C2065: 'IDC_ENABLE_PARENT' : undeclared identifier
FootStepControl.cpp(651) : error C2051: case expression not constant
FootStepControl.cpp(652) : error C2065: 'IDC_ENABLE_LOCALSYS' : undeclared identifier
FootStepControl.cpp(652) : error C2051: case expression not constant
FootStepControl.cpp(653) : error C2065: 'IDC_ENABLE_OBJECT' : undeclared identifier
FootStepControl.cpp(653) : error C2051: case expression not constant
FootStepControl.cpp(659) : error C3861: 'IDC_SHOWFOOTPRINTS': identifier not found, even with argument-dependent lookup
FootStepControl.cpp(659) : error C2051: case expression not constant
FootStepControl.cpp(660) : error C3861: 'IDC_SHOWFOOTPRINTS': identifier not found, even with argument-dependent lookup
FootStepControl.cpp(666) : warning C4060: switch statement contains no 'case' or 'default' labels
FootStepControl.cpp(680) : error C2228: left of '.getHInst' must have class/struct/union type
        type is ''unknown-type''
FootStepControl.cpp(680) : error C2065: 'RES_ID_RB' : undeclared identifier
FootStepControl.cpp(681) : error C2065: 'IDD_FOOTSTEPPARAMS' : undeclared identifier
FootStepControl.cpp(683) : error C2065: 'IDS_RB_FOOTSTEPPARAMS' : undeclared identifier
FootStepControl.cpp(680) : error C3861: 'getResMgr': identifier not found, even with argument-dependent lookup
FootStepControl.cpp(683) : error C3861: 'GetResString': identifier not found, even with argument-dependent lookup
FootStepControl.cpp(694) : error C2065: 'IDS_RB_FOOTPRINT' : undeclared identifier
FootStepControl.cpp(694) : error C3861: 'GetResString': identifier not found, even with argument-dependent lookup
DllEntry.cpp

 

 

Can you please provide the necessary resource file for the FootStep control ( ...which you cited as reference for me to look at... ) so that I can get it to build. 

 

Thanks.

0 Likes
Message 8 of 13

lucas.yang
Alumni
Alumni

Sorry, still working on this....


Lucas Yang
Developer Technical Services
Autodesk Developer Network


Message 9 of 13

michael_lawler
Enthusiast
Enthusiast

Thanks Lucas,

 

With the legacy "FootStep" resource files you provided I was able to copy over the missing resources I needed to overcome the errors and get the FootStep Control "howto" sample to compile (..but it doesn't really seem to do much except draw a pattern of footprints).  The only dialog it has in the motion panel is the "FootStep Parameters" (maybe I missed some?).  Still... it should help me with some of my questions regarding display() and hittest() methods for my real first controller project.

 

I appreciate you digging up these example files.

0 Likes
Message 10 of 13

michael_lawler
Enthusiast
Enthusiast

Lucas,

 

I still need some help/guidance on parameter block coding with the SDK... I don't find any kind of tutorials or examples of "how-to" properly code a parameter and controller UI rollout within the Motion Panel.

 

Currently I am stuck trying to fully comprehend parameter blocks in the SDK.  In Maxscript parameter blocks and rollout UI are easily grasped-- but to me there seems to be a lack of tutorial/example material of doing parameter blocks in the SDK.

Lucas, in the  "footstep control" example project that I sent you...  using that sample project to flesh out some behavior for my first controller project...

 

I modified the "translation" gizmo handling such that any translation (or combinations thereof) would result in the node being moved along (i.e., projected along...) a target vector.  I also added code so that the node could not be dragged thru the target location along the target vector (i.e., avoid the flip side)... this makes it stop at the target location and coincident.

 

What I want to do now is have a "targetDistance" parameter (like objects with targets-- I found the UpdateTargDistance() function in Camera Object...) with a float spinner in the controller's motion panel UIl... such that changes to this targetDistance parameter would also affect node translation along the target vector.  Does that make sense?

 

I'm confused as to how to achieve this? 

 

So to summarize... currently:

 

manipulating the translation gizmo in Move Mode (along any axis or combinations of axes) causes the node to move along the target vector between the node's current position and a target node (currently I was just using the origin-- but I'm in the process of adding a selectable target node)... and the user cannot move it thru the target location (it stops there).

 

I also want to have a controller UI parameter block FLOAT spinner for "targetDistance" that would also move the node along the target vector... I've been studying the parameter blocks and enums of the other constraint controllers, but I'm not sure how to achieve the above.  Secondly, I'm not sure if these two move methods should be related?

 

How is the best way to go about achieving this?

 

Thanks!

0 Likes
Message 11 of 13

michael_lawler
Enthusiast
Enthusiast

I am currently studying the 3ds Max 2012 July2012 Webcast on plugin development-- specifically Module 5, Parameter Blocks.  Hopefully this will remedy my ignorance.

0 Likes
Message 12 of 13

michael_lawler
Enthusiast
Enthusiast

Ok... so I have the parameter block and its UI working... I also have added the PRS Key Info Dialog Rollout and the Inheritance LinkInfo Dialog Rollout (borrowed from the PRS controller).  But attempting to interact with either the KeyInfo or LinkInfo dialogs results in a crash because I don't have the *pos, *rot, *scl controllers implemented yet... they're just NULL.

 

...and this is where I need to chat with an Autodesk Plugin Programmer-- preferrably one with experience writing Transform Controller plugins; because I know what I want to achieve, and so I've got to make some architectural decisions on the inner workings of my controller and I need advice.

 

Thanks!

0 Likes
Message 13 of 13

michael_lawler
Enthusiast
Enthusiast

Ok... so I have my matrix3 transform controller loading now when it is assigned to a node from the "Assign Controller" rollout on the Motion Panel. The controller's UI is mostly functional-- at least when it comes to adding/deleting target nodes to the listbox (as done in the LookAt, Position, and Orientation Constraints).

I've also added the "PRS Key Info" and "Inheritance Link Info" Dialogs (taken from the PRS controller's code)... I've gotten these additional dialogs showing up as additional rollouts (on their respective panels).

What I don't like, and would like to change, is how when I add a node to the listbox it appends its respective weight controller as a sub-anim directly to the main transform controller, like so (assuming 3 nodes have been added to the target listbox):

(-) Transform: myController
 └-- myController Weight 0
 └-- myController Weight 1
 └-- myController Weight 2
 └(+) Position: Position XYZ
 └(+) Rotation: Euler XYZ
 └-- Scale: Bezier Scale

All of the constraint controllers behave this way (that is to say-- adding the individual weight controllers directly underneath the owning controller)... and since my transform controller is based mostly on the LookAt and Link Constraint controllers' code, it behaves this same way.

...whereas, I would rather all these weight controllers, associated with their respective nodes in the listbox, to appear under a "Weights:" hierarchy like this:

(-) Transform: myController
 ├(-) Weights: 
 │ └-- myController Weight 0
 │ └-- myController Weight 1
 │ └-- myController Weight 2
 └(+) Position: Position XYZ
 └(+) Rotation: Euler XYZ
 └-- Scale: Bezier Scale

Does that make sense? So if you look at any of the LookAt, Position, or Orientation constraint's code then the solution would equally apply to my own controller.

So how would I re-structure the Parameter Block to rollup the weight controllers like that-- rather than have them all individually listed directly under the main transform controller?

0 Likes