A sneak peek
The promised video has come. It is just a preview of a selection instrument, but should give the idea of what’s going on. I hope you can understand my English and enjoy the new features.
The promised video has come. It is just a preview of a selection instrument, but should give the idea of what’s going on. I hope you can understand my English and enjoy the new features.
I’ve been advancing quickly in lasts few days defining the second instrument: Track Selection. It is completed for vertex selection and must be translated into edges and faces, the procedure is straightforward. But before starting the translation and a little bit of optimization in data containers memory wise, I want to code the cosmetic interface that should make the meat quite juicy. You can call it a simple visual eye candy, but I guess it is much more than that, providing real time visual feed back on the ongoing user operation.
It still needs to be practically tested and it could be not up the expectations, but I’d like to write it in the right way from the very beginning, to be a dynamic object that can adjust to different scenarios, and maybe provide the backbone for a multi purpose graphical interface for many instruments. I know this sound a little ambitious, and I stacked up a lot of words without actually showing anything yet, but I must keep saying: “very soon”. Then I’ll need some feedback to fine tune the tool.
Meanwhile I’ve looked into the fearsome 3ds Max Undo System, because Painter Interface instances have to manage their own Restore object to put on the undo stack. Edit Poly Modifier, because of its nature, takes care of almost everything, while Editable Poly Objects must be manually handled, and that’s where the pain begins. Fortunately Autodesk is so kind to provide source code for Editable Polys, where the TopoChange class can be found to handle Topology changes. I’ve just taken that straight, because it is so complex and require so much knowledge about the ins and outs of 3ds Max geometry pipeline and Editable Poly databases, that I would never have been able to code it all by myself. Anyway, it seems to work as is supposed to. I only have to check some pointers here and there to be sure nothing is deleted when it isn’t supposed to. Keep the finger crossed, because it is a very thin line to walk.
Never ever assume that something simple in MaxScript will be there as simple as expected in the SDK. I learnt it the hard way when looking for the simple event handler “on rollout open/close do()”. That’s not there, or I cannot find a way to get it. It is possible to register a callback for Rollout DragAndDrop (!?!), a callback to modify the Rollout Right Click Menu, even for the behaviour of the hand that grabs the Rollout for scrolling when longer than screen space, but no, nothing to capture the on open/close user action. I tried some hacks by getting the handler of the Rollout header and attaching a WindowProc() without any luck, it breaks the interface redrawing. So, I’m stuck on this. After spending a whole day trying to figure out a solution, I just decided to dump it for a while. It is needed to resize the whole floating interface upon user action, but as already decided, first release should be made by a single Dialog, so I can just ditch it for a while.
Meanwhile I remembered the Qt library for C++ and started looking at its documentation, even if it is not free for commercial use and coming at a price of about three thousand euro for the most limited license, is not cheap at all and something to evaluate carefully before starting a full interface development based on that. Anyway, it really does look Qt (cute). During spare time I’d like to run some test with the open version to get an impression of its potential within 3ds Max.
Growing too bored of fighting with those Win32 APIs, code that pitch into programmers from what twenty? thirty? years ago with no clue of what object oriented programming is, I decided to turn a little bit to the fun part, coding actual functions for instruments. The very first Paint Selection tool can be considered quite done. It is basic, does exactly what it is supposed to: a sort of RayCast selection. I guess I’ll have a small demo video very soon.
I’m starting to shape a graphical interface concept to associate to advanced instruments which support dragging and dropping to define a gesture or a line of action. It looks good in my mind and on paper, but I’m eager to code it and test its functionality. Cannot tell much more at this stage, but it will probably come with the next selection instrument, Track Selection, modelled after current Pick, but more advanced handling quite beautifully Span selections too with real time preview.
The User Interface doesn’t let me go. I usually have some difficulties to bail out something still unsolved, or that isn’t as good as I’d like. This is the case. I know it is a good quality, but can turn out to be a flaw too, because of the time spent on details, or on things that can be gradually improved with time and subsequent upgrades. In the end, I guess I have to bare with myself.
Coming to the development, the User Interface is starting to get in line, I think I identified all the bigger issues and traced guidelines to solve them. Now comes the coding and test phase. It will be nothing fancy, most like the current one. The plan is to rebuild it, as is, and maybe offer some different sizes for buttons and rollouts, considered computer screen are getting bigger and bigger, and most notably wider, there is no reason in keeping it so compact. Anyway this isn’t a top priority.
After coding my own class to build DialogTemplates I found it doesn’t give any real advantage over the use of Resource Editor, because every dimension must still be defined in Dialog Units, and the whole interface adjustment to get pixel accuracy has to be done the same way. It adds the nuisance to define control ids and prevent collision with those defined by the Resource Editor. So after finding that “Microsoft Sans Serif” set at a dimension of 5 allows to get a 1:1 correspondence between Dialog Units and Pixels in relation to the horizontal dimension, I just shaped a couple of dialogs accordingly and dropped on them some controls.
The issue with Image Tag has been avoided through a possible trick, or cheat. I don’t really need event handlers on images I’m going to display in the UI, but simple static images, without any border or decoration. I still need to test this, but I’m positive it should work well. I’m goint to use a Custom Button Control, set it to be borderless with “I_EXE_CB_NO_BORDER”, disable it and assign the image I want to display through an ImageList associated to the unchecked and disabled state. No one should notice the difference. The only caveat is to be sure it displays properly in newer 3ds Max versions and most recent Operative Systems like Vista and Seven.
The other issues are: UI dragging, which gets properties reset upon left mouse up, showing the border again; UI docking and floating, which makes a mess with the whole components position; UI resizing on rollout opening and closing, which must get information from Windows through System Metrics. This is what I’ll be working on the next few days. After this little tour de force on the User Interface, before going back to actual instruments, I’d like to take a look at Acceleration Tables to create Actions for customization, just to be sure nothing insidious lays there.
User Interface creation through Win32 API seems to be more challenging than expected. Resource Editor seems to be unavoidable too, limiting the possibility of a clean class to handle UI construction. I cannot tell it for sure because my Windows programming knowledge is really low. But as is said, from knowing nothing, you can only improve.
It has been a little shocking finding that ImgTag is a control available in MaxScript only, while Custom Image Control comes with a horrendous recessed effect border and has no way to handle callbacks from the system. I guess I’ll try making the very same ImgTag class to be used with the SDK, even if I don’t have a clue about how to do it right now.
After trying a bunch of different solutions, deciphering the scattered bits of information in the SDK help, I was able to recreate the structure of current IC.Shape user interface. It is way more harder to manage, and I’m starting to think to different solutions with similar functionality, maybe even taking the rollouts away. It all depends on how clean is the outcome. I think the user interface is one of the key features of a sofware and I do not accept compromises. Anyway, to avoid spending a lot of time on it, given the first set of instruments will be for selection only, I think I’ll start with something very simple, just a clean dialog with an header.
Next step is to put together the UI, implement the basic functions like dragging and the Right Click Menu, then a look at how to create Actions to associate with custom shortcuts, then the real instrument coding, resuming from the Paint Selection prototype.
After poking at Win32 API to handle the .ini files, I couldn’t stop so suddenly, so I decided to tale a look at the User Interface. This is one of the feature I really miss from MaxScript, even if it gives headaches sometimes, it is so much easier to to handle that I cannot find anything to blame after latest experience with “CreateCUIFrameWindow”, “CreateDialogParam” and such. I don’t even want to start a futile speech against the DialogUnits, unique way to design user interfaces in Visual Studio, based on the average dimension of the character currently set. To get measures in pixels for a fixed size interface you must shift/resize every control upon initialization, with the nice MoveWindow() function.
After understanding every “mechanical” aspect of the UI creation I guess I’ll build a class to handle the content way more gracefully, and maybe even avoiding the resource editor at all, considering the whole interface has to be “rebuilt” as soon as it is initialized. I must see how demanding is to build commands by hand, but should be a simple CreateWindow() of the specified CustomControl, then the setting of a bunch of parameters, and the definition of a unique ID in the String Table.
I still have to look at RightClickMenus, said to be obsolete since the introduction of Quad Menus, but still very useful and clean in some cases, in particular when dealing with Dialogs and not for direct Action calling during the usual work.
Before diving into maths, is better to make every support programming clear. That’s what I’m dedicating to these days, just to be sure to avoid hitting some walls at an advanced development state.
Unfortunately MaxScript has some nice functions to handle .ini files, while the SDK has to entrust this job to the nice Win32 API. Fortunately it is not such an hard task, but the meat comes with the parser needed to handle different data types stored as strings in a plain text file. I’m talking about storing configuration through sessions for each Brush used by the PainterInterface, backbone tool of the whole plugin. The PainterInterface comes with a BrushManager, but looks a little too complicated and integrated into the system to fit my needs. I guess I’ll end up rewriting something simpler.
Meanwhile I’m refining the PainterInterface adding subtle functionalities that will help a lot to better define instrument behaviours.
Sometimes, when running tests, I find myself fiddling with the selection tool, amazed at how it beautifully works with preview mode. I particularly enjoy the face Extrude, but I realize it’s just me, because right now it still doesn’t look so much different from the “Preview Selection” available since version 2008 I guess, except its standard colour is “puke yellow” as a friend called it, while mine would probably be light blue, but is still to be decided.
The winning streak is going on! Maybe it is a little too soon to consider it done, because it still needs to be well tested, but it seems I could support the “preview mode” with selection instruments.
Do you remember the nice preview you got by standard 3ds Max tools like Extrude, Chamfer, Bevel and so on? When that command mode is active, you can conveniently adjust the selection to your liking seeing what’s the final result before actually applying it. Well that sort of behaviour involves the previous saving of a temporary state, then the command applies, showing the modification in the topology that can be tweaked. If the command is accepted the modification is applied and a new restore point is put onto the undo stack, while if the modification is discarded, the mesh is reverted to the saved temporary state. So far, so good.
The PainterInterface needs a pointer to an ObjectState to get the geometry to work with. I don’t want to enter into too technical details right now, just consider it like the appearance of the mesh in the viewport at the time the PainterInterface is initialized. The issue was that taking the ObjectState straight from the node, it suffered the modification previewed by any command like Extrude and such. The solution, after a peek at the Editable Poly source code provided, is to take a sort of snapshot (it is actually a shallow copy) and initialize the PainterInterface with it. Any modification applied by the system to the node is not reflected on the snapshot, letting the PI work as expected. The only inconvenience with it is that when PI is initialized, there shouldn’t be any preview active, or the snapshot is messed up. It shouldn’t be too hard to code a solution that looks for any active modification, suspend it for an instant, take the snapshot and revert the preview back.
What does this achievement mean? New selection tools for Editable Poly and Edit Poly Modifier, able to select in example full and half loops and rings, as well as restricted spans while seeing the effect of a Chamfer or Extrude edge. The most notable case is when you want to add supporting edges to make a hard edge in subdivision surface modelling. Then put an Editable Poly Modifier onto the Modifier Stack, go in edge sub-object level, activate the Chamfer, or extrude with height equal to zero, as you like, then start the IC.Shape selection instrument and get all those nice loops and rings by a simple click and drag action. Now that is nice! Hopefully I’m not running too far with fantasy.
After all these words, I hope to show something soon, in a small demo video.
The second development day ends with a quite positive balance. Today I’ve been able to deal with and solve one of the reasons why I stopped the progress on the first round: poly face highlighting. In other words I can now highlight vertexes, edges, faces in an Editable Poly Object and Edit Poly Modifier. The process is quite straightforward for vertexes and edges, but becomes a little trickier with faces, where a Mesh object has to be built and rendered to the graphic windows.
Today’s achievements:
I’m not starting a war, just taking over the challenge with 3ds Max SDK, again. So in my mind this is a little a war day, let’s call it D(evelopment)-Day One.
I just finished some nurbs modelling work for product rapid prototyping and decided to start over with programming. I’ve been training for months and still going on, picking up another handbook, “C++ Primer 4th Ed.” by Lippman, Lajoie, Moo, after studying the excellent “Thinking in C++ 2nd Ed.” by Bruce Eckel, more than one year ago. I still miss some final chapters, but I feel ready to start, getting those concepts along the way.
My goal is to recover all the code written about one year ago and resume the development of what will hopefully become IC.Shape 3. I’ll start with a very small part in order to have something working in a short amount of time, ready to be released for testing. Selections will be the beginning of this new adventure.
There are some issues I still need to figure out, but this time I’ve got the help of a very talented and proficient friend of mine, who offered his help to tackle such mysterious questions. It gives me hope to be able to accomplish the great task.
Today’s achievements:
if ( (!changeSizeMode) && (!changeSizeMode) ) // is supposed to be: if ( (!changeSizeMode) && (!changeStrengthMode) )
Even if it may look not so much, I feel satisfied by the outcome of this first day considering I couldn’t solve these issues in the first round. I hope to keep going on steadily and post progresses on a daily basis.
Enjoy the ride!