The Viewport Maxscript Editor - NEW


#1

Here ya go:

The Viewport Maxscript Editor Version1.2c - released 2011.03.26
Download and extract .zip contents, run .ms file.

Prior releases:
The Viewport Maxscript Editor Version1.2b - released 2011.03.11
Download and extract .zip contents, run light or dark .ms file.
The Viewport Maxscript Editor Version 1.2 (with Lite and Dark skins) - released 2011.03.06
Download and extract .zip contents, run .ms file.
The Viewport Maxscript Editor Version 1.1 - released 2011.02.27
The Viewport Maxscript Editor Version 1.0 - released 2011.02.23

 I'm happy to release a new script that allows you to create scripts using objects in max's viewport.
         I call it "The Viewport Maxscript Editor", and it's existence is the direct result of [this post](http://forums.cgsociety.org/showthread.php?f=98&t=955342).
         
         It was written with the idea that it could replace the long outdated and basically useless "Visual Maxscript Editor" - it's even named the same acronym.
         
         Enough talk.  [Here's a demo of how it might save you time.](http://www.youtube.com/watch?v=qA_-wU8khiE)
         
         Here's the process to get started using it:
       [img]http://www.garrickcampsey.com/media/VMEhowTo.gif[/img]
         
         This is a version 1 release, so if people like it/use it/have feedback, then I'll be happy to update it.
       
       Use it, break it, dig thru it, tell me how it can be made better.
       
       --

j83:
I would suggest never use the Visual Maxscript editor, it creates messy code, spaghetti-like UI controls, and hard-codes all UI positions which makes it very time consuming to manage and add new functionality. The Visual Maxscript editor was abandoned by Autodesk a long time ago and I don’t think they’re going to finish it.

       This comment was used like a guide.  I've tried to format the code the script writes in a simple and straight forward manner, and the script itself was created to allow additional UI elements to be added later on, as well as groups/presets of UI elements.  Unfortunately, for this release, I've hard-coded the UI positions - but I plan on adding a checkbox to toggle between writing offset: instead of pos:.  Default events would be easy to write as well, so that may be an update.  Here's the code from the above .gif image:
global Rectangle001
       try destroyDialog Rectangle001 catch()
       rollout Rectangle001 " Rectangle001"
       (
           --UI ELEMENTS
           button Rectangle002 "caption" pos:[100.0,135.0] width:100.0 height:30.0
       )--close rollout
       createDialog Rectangle001 300 300 250 100 lockWidth:true lockHeight:true style:#(#style_toolwindow, #style_sysmenu, #style_resizing)
  Hope people find it useful!  :)

#2

Nice one, thanks for sharing.


#3

Great, thanks! :buttrock:


#4

TheGrak, looks awesome. Thanks a lot for releasing it and sharing with us!


#5

@scrimski, 48design, and IkerCLoN: I’m happy to help! Let me know if you guys use it/want any changes to it.

I brainstormed more on my way to work (long commute).
Here’s some crazy ideas based on writing scripts with objects in the viewport:

With this image, I’ve taken Euclid’s ‘Greatest Common Denominator’ algorithm and displayed it as a flowchart and as code. Then I merged the two ideas to create node-based coding, which is tentatively named “FlowCode” for now. Here’s my inspiration for doing this. You may notice that I put a function inside the main function. That’s to simulate recursion, but still allows the function to accept parameters. I’m not sure if the code would work that way, thats just how I’ve written it out.

The idea behind this ‘flow code’ was to bridge the worlds of visual design and code design. Using nodes, you can define relationships using links or lines. The nodes are evaluated according to their links, just like a script is evaluated top to bottom, left to right.

Now I’m not saying this way of coding is better or even possible, but… I can foresee the ability to drag a variable node into a function node and (based on node distance) link the variable into the function automatically. This would save my hands from copying + pasting variable names into functions. This could also be extended to statements like ‘if/then’ or ‘fileIn()’. It’s objective tasks like these that I am certain can be automated or simplified. If nothing else, it’s just a different perspective on writing code.

These ideas are scattered for sure, but I hope to build a working example of ‘FlowCode’ before the end of Feb, so Max users can start to play around with it. :slight_smile:


#6

Thanks for sharing this with us. I like your ideas on node based scripting. I think that might make it a little more approachable by users with less scripting experiance. I think autodesk should be thinking about adding somthin like this in XBR.


#7

Viro: I think autodesk should be thinking about adding somthin like this in XBR.

That’s one of the big motivators for why I’m doing this.
If I can write something that people actually use and it helps them in their day to day tasks, then I’m happy. If it ships with 2012, then that makes me happier. If it gets more people into writing code, then I’m even happier. And I’m not looking to sell this idea, Autodesk can just have it… no strings attached. Or hire me as a ‘conceptual developer’ - whatever that is. :smiley:


#8

You’re actually describing here FSM’s or finite state machines. Basically states controlled by conditions triggered by inputs.

a = 10

if a > 20 : greater condition - input 20

then a == 20 - branch off


#9

Much respect Eek! I’ll be absorbing some concepts from Finite State Machines.
Do you see value in this approach (writing code using objects)?


#10

Just updated the script. You can download it from the first post of this thread.

VME can now build (rough) clones of itself, via a drop down item.

I also forgot to illustrate how VME can manipulate the actual size of the UI elements:

And a stress test:

Also cleaned up the code a bit with a new function.
I think I’m just going to develop ‘FlowCode’ into this script after the UI elements are polished a bit more.


#11

It makes it incredibly modular, its one reason node based workflows catch on so well - take ICE, Houdini or Shake for example. In terms of complexity though things can get very hair raising and complicated very quickly and you can tend to blow out the system for systems sake i.e you add a state just for the flow to keep working - when a custom piece of logic does a better job.

Essentially you want the best of both worlds - one that motionbuilder does nice with the relation constraint. It’s a controller powered by nodes, states, switches etc by that can have scripted input i.e custom python input for a node.

I.e you want base logic to be easy to create but that can wrap custom logic - i.e like ICE compounds. Its one reason i LOVE the script controller in max - i use it for everything thing - it would be neat to wrap that into a nodal work flow.


#12

@ Eek, thanks for the thoughts. Very motivating. :slight_smile:

I’ve been thinking more about flowCode. Here are ten examples of how I’m seeing various nodes working:

  1. illustrates a variable node. the VME IDs would exist as custom parameters on the line object. the VME IDs would describe the properties of that variable, for example: type = string, value = “myString”.
  2. illustrates ‘code canvases’, which are essentially representations of sets of brackets. these sets of brackets can be of type: function(), rollout(), or just a pair (). I’m sure there are more types. these canvases contain statements and variables, and also help to illustrate…
  3. variable scope in a very intuitive manner. Variables 1 and 2 are parameters of Function A, variable 3 is in the scope of Function A, variables 4 and 5 are in the scope of Function B, and variable 6 exists in global scope.

Let’s move on to statement nodes, starting with the fileIn() node.

  1. illustrates the fileIn() nodes VME IDs, consisting of an editText value you can enter, or a pickButton that lets you select a node. When a value or node is entered/selected, the object updates itself with a small triangle to visually indicate that it is linked.
  2. illustrates a string variable linked to a fileIn() node. I envision extra data being displayed in the viewport when an object is selected, for example clicking on the fileIn node would popup the data “fileIn()” then underneath it the values assigned to it’s parameters… in this case it’s just a string variable, since fileIn() only accepts a single value and it must be a string.
  3. illustrates running a file from the scripts directory, based on a fileName variable. these nodes are placed within a bracket canvas, and you might notice the “+” node adds the string variable to the getDir node string.
  4. illustrates a new kind of user-interaction based on this layer of nodal abstraction. here I’m dragging a different variable string into the bracket canvas, and based on proximity (a circle object representing a ‘weld’ tolerance value), max recognizes that I want to replace the variable and prompts me with a yes/no messagebox. now I can drag and drop variables into brackets without copying and pasting, or even typing. Coding with the stylus :slight_smile:

Moving on, lets check out if/then/else and case of statements:

  1. illustrates the VME IDs of an if/then/else node. notice that ‘else’ is controlled by a check box, enabling the user to toggle between if/then and if/then/else states. The outgoing links are labeled A and B, referring to then() and else() respectively.
  2. illustrates a if(…)then(fileIn(…))else(print …) statement in ‘flowCode’ form. Notice the print node has text input or pickNode VME Ids.
  3. illustrates a case statement. the bold node is the case node, which evaluates to the connected nodes. there can also be a default node. it has a spinner to set the number of case statements. while this particular concept is functional, it is also inherently limiting and I’m not totally happy with it so far.

I plan on building functional variable nodes within a few days, then move into building basic logic nodes, assignment nodes, and also figuring out how to link nodes in the viewport based on proximity. I’m also planning to update the UI of the VME script to separate UI elements from nodes, so you don’t have a dropDown with 2,000 items. In addition to all that, I’d like for the VMeditor to be able to build a fully functional copy of itself with just a click. This will pave the way for building preset UI elements, with nodes, in groups, so you could save UI elements and code (node sets) as presets.

This will eventually lead to: A C# compiler node. A XML reader node. etc… possibilities are endless… even more far fetched: a Python installer node… or a node that would compile a string into a frozen python binary, allowing the user to visually write python .exes in maxscript. many ideas…


#13

Nice one :slight_smile: Be sure to take a look at impure in case you haven’t done so already.


#14

@Swordslayer: Thanks! Impure is inspiring.

I figured out a more elegant way to represent if/then/else, case of, and fileIn() statements. This idea is built on top of the assumption that any set of brackets would be represented in the viewport with a bracket canvas. This also allows me to ‘name’ the rectangles based on what they represent.

This simplifies the visuals a bit. Notice the default statement on the ‘case of’. I think this approach is much closer to representing the actual code. There’s a lot more to be developed. :slight_smile:

A couple of fun things:

  1. To save a script’s UI that you are developing, just save the .max file.
  2. Since each Custom Attribute stays with the object, you can merge and xref UI elements.

I also had the far-fetched idea of writing a .PSD import node - allowing a user to build the UI as layers in Photoshop. Then based on layer name, example: “PickButton”, the VMeditor could load in the .PSD, parse the layers to UI elements (compare layer string name to library of strings), then load in the appropriate bitmaps (assuming you’ve already sliced up the elements and saved them as images). I think this type of node would let users customize their scripts UI very quickly and professionally. This idea is a variation on the PSDtoCSS web service available here. It’s also similar to how Adobe Encore can import .PSDs to build DVD menus based on layer name. Food for thought. :slight_smile:


#15

I think you need to sort out base logic first:

if/then/else
continue/exit
while/for
try/catch/throw
case of

One thing your’ll have to start thinking about is combining different logic, i.e the result of a case statement driving a if statement etc - nodes handle this with a line connecting them.

What you’r actually depicting is actually a circuit diagram i think - with hints of state flow code logic.


#16

@Eek: Very good points. You got me thinking about base logic. Here’s some concepts:

  1. illustrates an if/then/else statement.
  2. illustrates a for/do
  3. illustrates a while/do
  4. illustrates a try/catch

All these concepts are building off the ‘bracket canvas’ node. The ‘bracket canvas’ really helps to visually show scope. The ‘bracket canvas’ is essentially a code block of empty parentheses.

I also think I can ‘compile’ the nodes using a check on each canvases bounding box, so the nodes don’t need to be linked. Instead, the nodes need only to exist within the bounding box of the bracket canvas. This means the rollout bracket canvas can contain other bracket canvases with additional nodes, and the script can recognize which nodes exist within which brackets, then build the code accordingly.

There are some complications with how to visually show the ‘flow direction’ thru the nodes using canvases that I’ll need to address. Questions such as ‘How does the script know which node is the first node to be evaluated within the canvas?’ and ‘How do you link canvases to canvases?’ and 'Can a canvas be linked to multiple canvases?".

An interesting thought: See how the for/do and while/do are structured the same? That means they can easily replace each other - allowing a user the ability to drag and drop for/do nodes on top of while/do nodes. While this may not seem useful at first, it illustrates the modular nature of the nodes.


#17

Here’s an attempt at translating some real world code into flowcode.
For this example, I’m using the updateOffsets function that is a part of the VMeditor’s code.

First, here is the updateOffsets function code:


fn updateOffsets = 
(
local myParent = $.parent
local myOffsetX = ((abs(floor(myParent.children[1].pos.x-$.pos.x)))-($.width/2)) as string
local myOffsetZ = ((abs(floor(myParent.children[1].pos.z-$.pos.z)))-($.length/2)) as string
$.objectData.xoffset = myOffsetX
$.objectData.yoffset = myOffsetZ
$.objectData.paramsRollout.xoffsetlabel.text = myOffsetX
$.objectData.paramsRollout.yoffsetlabel.text = myOffsetZ
)

The code could be cleaned up a bit more, but this works for a test. Here is the (rough) flowCode:

Triangles are variables. For now, the double-triangle refers to $.
Squares are bracket canvases (which determine the order of evaluation and scope).
Circles are statements, assignments, and operators.

While it (visually) isn’t as simple as I’d like it to be, it does begin to show that ‘flow nodes’ can be used to represent any piece of code.

Here is an idea: looking at the diagram, I can see a possible way that the 2 larger canvases could be condensed into 1 canvas with different variables being plugged in at different times. So you could describe the process in English as “for this function, perform these tasks with these variables. then perform the same task with the same function again, substituting these variables”. This may be a node that is added into the canvas that gives the canvas those special properties. Looking at the code in this light means the other canvases could be condensed into 1 canvas as well, further simplifying the diagram.

It needs more development, but my intention here is to get these ideas out and in the public, so people can point out where the flaws and problems are. Having only 1 perspective means you miss many potentially elegant solutions, thus the reason for my ‘forum-sourcing’ of this idea. Any input is welcome, speak your mind! :slight_smile:


#18

I really liked the idea of using 3d elements to draw the UI. Great job !

The first thing that can be improved in the code is that the repetition of same code for different UI elements can be avoided. Second the need to manually link can be eliminated by auto linking based on whether the UI element lies in the rollout margins (or in BB perhaps).

Other things like, different wirecolors for different elements and auto positioning when created (so that the new one does not overlap the older elements. And giving them names instead of “Rectangle01” etc.

I’ll watch this thread and contribute whenever possible.


#19

A little concern i have is that in exposing maxscript to a new interface you’ve introduced new graphical understanding that will be needed. Crucially you want this to be humanly readable - another reason nodal systems work.

Remember you’re abstracting this to be more easily understood. First example:

Compared with:

Lets look at ICE (very nice):

Houdini:

Houdini really is my cuppa tea - (wish i could have some time to learn it mmm… macbook pro…) Anyway, houdini’s VOPs are amazing - basically there nodal operators which contain VEX’s which are inturn customizable vector expressions.


#20

Eek: Remember you’re abstracting this to be more easily understood.

Very good point. This is my main goal with flowCode. So far, it’s complicating things further. This has inspired me to take a different approach.

Here are more thoughts on the ‘values’. These would be strings, integers, floats, arrays, data types…
These represent nodes better. I think I’ll shelf the triangle idea for now, but keep the bracket canvas idea (squares). So, most everything would be in a circle now, including accessing a node’s properties, operators, and methods.

The ‘ca’ dot represents a custom attribute, the dots afterward would have to be blank as there would be no way to visually describe a custom user-set attribute. For example, not everyone uses ‘objectData’ for the ca name, so it would be futile to create ‘objData’ text inside a circle to serve as a node that represents that particular attribute.

Oormi:
The first thing that can be improved in the code is that the repetition of same code for different UI elements can be avoided. Second the need to manually link can be eliminated by auto linking based on whether the UI element lies in the rollout margins (or in BB perhaps).
Other things like, different wirecolors for different elements and auto positioning when created (so that the new one does not overlap the older elements. And giving them names instead of “Rectangle01” etc.
I’ll watch this thread and contribute whenever possible.

@Oormi - good thoughts! I need to clean up the code a bit more, and also restructure some aspects of it to accommodate writing values and other statements. The code posted so far is the result of a 10 hour coding spree, so it needs around another 300 hours of development before I’d be proud of it. I agree and think that auto-linking is an important feature, along with using the canvas’ boundingBox to determine what nodes belong to what canvas.

Here are my thoughts on color and name: the nodes are being designed with the idea that the user would ultimately have control over their color and name. Therefore, all the nodes would be created in a neutral color (grey), and use other visual means to describe them (in the example above, this would be the text ‘$’, ‘node’, etc…). This allows the user to color-code the nodes how they see fit.
I can see this being useful later on, as the script can turn nodes that produce errors a red wirecolor. This would help the debugging process because you’d be able to see where errors were (in red) at a glance.

With the current VMeditor script, the name of the object you create in the viewport becomes the name of the script’s UI element. So, the first rectangle that is created is named ‘rectangle01’ or something, so that becomes the rollout’s name. If you change the objects name to ‘myRollout’ the rollout updates to reflect that. I thought of storing the name using custom attributes, but that only adds more steps to what the user has to do/learn.

I want this to be intuitive and simple, but also dynamic and powerful - so the design must respect that. I have a feeling that there will be many revisions, so please continue to contribute your thoughts. I’ll consider and implement as many as I can, while still steering the script in the direction of intuitive, simple, dynamic, powerful.

Now I’ve got some coding to do… :wink: