Notifications
Clear all

[Closed] scripted line creation tool

Hiya.

I want to make a script that works similar to the regular line tool that automatically adds a modifier and turns it all to an editable poly.
The modifier and editable poly conversion is no problem, but I can’t seem to tget the line creation to work at all.
I read over the “How To…” samples, in paticular the “Draw Free Spline”, but the more I read the docs, and forum/internet searches, I seem to overcomplicate things and it is just driving me nuts.

(this is probably laughably easy, isn’t it?)

The functions are taken from/based on the FreeSpline samples, and putting the creation stuff in the “tool Create” was an idea I got from one of the other “How To…” samples.

well here is what I have at the moment:


plugin simpleObject createLineTest
name:"Base"
category:"Testing"
ClassID:#(0x1a8f435b, 0x7f6d43c6)

(
	rollout baseRollout "Create Line Test" width:162 --height:300
	(
	
	global old_pos
	global new_spline
	global second_knot_set
	global get_mouse_pos
	
			fn get_mouse_pos old_pen_pos =
					(					
					 if old_pos == undefined then old_pos = old_pen_pos
					 else
					 (
						old_pos = pen_pos
					 )
						updateShape new_spline
					) -- end fn
					
			fn draw_new_line old_pen_pos =
					(
					pickPoint mouseMoveCallback:#(get_mouse_pos, old_pen_pos)
					)
	
	button btn1 images:#("image.bmp", undefined, 1, 1, 1, 1, 1) align:#left offset:[0,40] width:84 height:100
		on btn1 pressed  do 
			(	
			) -- end button
	
	) -- end rollout

 tool create
 (
    on mousePoint click do
	(				
		new_spline = splineShape()
		old_pos = pickPoint()
		if old_pen_pos == #RightClick then
		(
			delete new_spline
		)
		else
		(
		select new_spline
		new_spline.pos = old_pen_pos
		addNewSpline new_spline
		addKnot new_spline 1 #corner #line old_pen_pos
		addKnot new_spline 1 #corner #line old_pen_pos
		second_knot_set = false
		draw_new_line old_pen_pos
		)
		updateshape new_spline
		
	)
	
	on mouseMove click do
	(
		if old_pen_pos == #RightClick then
		(
			deselect new_spline
		)
		else
		(
		select new_spline
		new_spline.pos = old_pen_pos
		addNewSpline new_spline
		addKnot new_spline 1 #corner #line old_pen_pos
		addKnot new_spline 1 #corner #line old_pen_pos
		second_knot_set = false
		draw_new_line old_pen_pos
		)
		updateshape new_spline
	)
 ) -- end tool create
 
) -- end plugin

The button(s) in the rollout will be for selecting a modifier, but are empty right now.
I just need to figure out the line-creating bit.

The line only needs to be of “corner” type.
Thanks to anyone with good word

12 Replies

Quote from MAXScript Reference (and I did not write this, it was John Wainwright, so I would listen)


[left]A SimpleObject plug-in must not perform any scene related actions such as creating scene nodes or building modifier stacks. It should basically only be adjusting its parameters in the mouse tool handlers and constructing a mesh in the buildMesh handler. Attempting to create scene nodes or applying modifiers in a SimpleObject plug-in will cause all kinds off strange interactions with the in-progress scene node creation.
[/left]
[left]”
[/left]
[left]

[/left]
[left]So what you are doing is dangerous and should not be done. You can create a scripted tool that does this, but not inside a simpleObject scripted plugin. (No plugin at all, if you ask me). Why don’t you use what is already there – all the scripts you quoted?

[/left]

Basically, a great deal of the work I do right now is REALLY tedious and is involving the same actions of drawing straight, corner lines, then adding a particular modifier, the converting to Editable Poly…over, and over.
So I thought It’d be nice to have it in the create panel so I can do it all in one action.

I completely missed that about not using a simpleObject for creating geometry.
I decided to use it when I saw in the “How To… Create Scripted Geometry Plugin” which uses:


plugin simpleObject AntiStar

name:"AntiStar"

category:"HowTo"

classID:#(0xe855567c, 0xbcd73b8b)

(

parameters main rollout:params

(

Funny that.

I will certainly heed your advice on not using a “simpleObject” for this.
So I suppose I should use a “Geometry” superclass with a create tool?

Am I at least heading in the right direction with the code I have in the first post?

Thanks.

Funnily enough, you quote pieces of code I have written at different occasions, so I am probably the right person to talk to

Anyway, the geometry class is for creating geometry. The antiStar one was used to create a procedural mesh, not splines.

You want to draw a spline interactively in the viewport, so a scripted plugin is out of the question IMHO. What stops you from using the Freehand spline code you used as template? What is the main difference to what you want to achieve?

I am not looking for so much of a “drawing” tool like the FreehandSpline script is.
I am making a lot of staright lines going from Point A to B to C to D, etc., (rarely coming back to A so no welding)
I tried to break down the FreeSpline and remove the parts about :
“if distance pen_pos old_pos > 10 then”
and then to keep more clicks available, but i just can’t get it to go.
I understand how the breakdown is and the “theory” of how it is all working (with the addKnots, keeping the 2nd one un-set, etc.) but putting it together is a bit beyond me.

Just visually, I’d like to have it on the create panel, but if its better off not being a plugin, then I guess I can live with a tool bar button. :rolleyes:

Ah, I see.
The Freehand stuff draws while you are moving the mouse (using a mouse callback).
What you want is to click N times and draw a spline just the way the real Line plugin does?
But then be able to add modifiers and stuff on top?
If you want to modify the result on the stack after that, it will have to go on a toolbar as a MacroScript.

Here’s a little more specific on what I am doing now.
Maybe there is a better script approach than what I am trying.
There are several custom shapes that I use repeatedly as a profile for the sweep modifier.
I find myself having to draw a bunch ( and I mean a BUNCH) of lines (always cornered), then (to not have to keep drawing the profile for each file) I merge the profile shape I need into the current scene, use it with the sweep modifier, then drop ecerything to an Editable Poly.

My idea was to have a script that would have a funtion that creates the shape(easy) then add a sweep modifier to my lines with the new shape as the profile (adding the sweep modifier is easy enough, but the using the newly generated shape as the profile doesn’t seem to be as straight-forward)

Would there be an easier way than this?

Thanks again.

Assigning a custom shape to the Sweep is really easy (and is documented, I even wrote an example! )

So the only question now is how to get the cross-section library into your scene.
I would actually suggest that you keep some of your workflow and only automatize it.
Create a Max file containing all sorts of cross-sections you typically use.
Write a script where you select the shapes to be sweeped, then pick the type of cross-section from a list that then merges the right shape from the library AUTOMATICALLY, adds the sweep modifiers and assigns the merged shape to the sweeps.

You know, workflow and ease of use should always have priority over code style. If it works, don’t overcompicate it.

Now you could of course parametrize these shapes by storing their coordinates in an INI file and rebuilding the shape from scratch using custom size values to scale the coordinates. Instead of merging a max shape from a MAX file, you would read some knot points from a text file and recreate the shape on the fly, then assign to the sweep.
Acually, this is how I would have done it. (The sweep itself keeps info about custom shape classes in an INI file btw)

Hey…I was actually just trying that…
I wrote a script that lets me pick a spline and it adds the modifier.
So yes the cross section…
I tried this a few minutes ago:


fn createLine01Shape = 
(
	ln = line();
	splIdx = addNewSpline ln;
		addKnot ln splIdx #corner #curve [-24.1082,48.0935,0];
		addKnot ln splIdx #corner #curve [-21.1562,-41.2054,0];
		addKnot ln splIdx #corner #curve [20.1722,-41.9434,0];
		addKnot ln splIdx #corner #curve [23.1242,-5.78106,0];
		addKnot ln splIdx #corner #curve [0.984011,3.81304,0];
		addKnot ln splIdx #corner #curve [0.984011,37.0234,0];
	close ln splIdx;
	updateShape ln;
	convertToSplineShape ln;
	ln.wireColor = (color 229 154 215);
	ln.name = uniqueName "Line01";
	select ln;
	return ln;
)

	rollout selRoll "Selection" width:162
	(
		pickbutton btnPick "Pick Spline" height:30 width:90 filter:shapeFilt
		on btnPick picked o do
		(
			if o != undefined do
			(
						
			addModifier o (sweep CurrentBuiltInShape:4 YOffset:10)
			convertTo o (Editable_Poly)
			select o


			)
		)	
	)

(the function for creating the shape comes from Comet’s “splineToMXS” macro(that’s a nonsense shape, btw)))

In this example, I am only applying the built-in shape, and it works quick and easy.
but when I tried:


theMod = sweep()
theMod.CustomShape = 1
theMod.CustomShapeName = <name>
addModifier o theMod

the MaxScriptListener was telling me that the “CustomShapeName” parameter was read-only and wouldn’t let me do it…?

I’d like to keep the shape definition within the script, rather than in a seperate Max file, or preferrably even outside of the *.ini (possible?) mostly for portability, like if this becomes handy for someone else when it is done.

You don’t assign the name, you assign to the first element of the array!
(Don’t you guys ever read the fine manual ? ;))

QUOTE:

[left]<sweep>.Shapes ArrayParameter default: #(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, …) – maxObject array; SubAnim
[/left]
[left]This is an array of 100 elements and is used to store the cross-section shapes.
[/left]
[left]All elements but the first one are read-only.

[/left]
[left]Elements 2 to 100 are used to store the class instances defined by the Build-in types controlled by the .CurrentBuiltInShape property and the “Build-in section” drop-down list.
[/left]
[left]In the beginning, element 2 is assigned an instance of the class defined by the first (default) cross-section in the \plugcfg[i][/i]sweep.ini file (Angle by default). Selecting other elements from the list or setting .CurrentBuiltInShape to other values than 1 will create new shape class instances and store them in the respective CurrentBuiltInShape+1 elements of the array.

[/left]
[left]You can assign a new class instance of any shape to the first element of the array in order to make it available as custom shape when the .CustomShape property is set to 1.

[/left]
[left]For example,
[/left]
[left]theShape = circle radius:100 [color=green]–create a circle[/color]
[/left]
[left]theMod = sweep() [color=green]–create a sweep modifier[/color]
[/left]
[left]addModifier theShape theMod [color=green]–add the sweep to the circle[/color]
[/left]
[left][color=green]–[/color][color=green]A[/color][color=green]ssing an instance of class Helix to first element of the shapes array:[/color]
[/left]
[left]theMod.shapes[1] = Helix()
[/left]
[left]theMod.customShape = 1 [color=green]–enable the use of the custom shape[/color]
[/left]

Page 1 / 2