Start a new topic

Random Scale Script

Im looking for a script or info on how to create a script that will scale all of the references or lods I have selected, randomly, ideally with a range I can set in creator, but if I have to set it in the script, thats fine. Any help would be appreciated! Thanks, Joe

wow, looks good, i will try it out tomorrow. thanks so much!

Here is an OpenFlight script that should get you started. It can be customized (see the "parameters" section near the top of the script). Making GUIs for Scripts is not trivial so for now, just change the values near the top of the script to customize it. Of course you could make a C/C++ plugin complete with a custom GUI but we'll leave that for another day.


The trick in this script is figuring out the "scale center". This will depend on the kind of geometry you want to run through this. You can choose (also in the "parameters" section):

  • CENTERBOTTOM : scale about the center bottom of the object
  • CENTER :  scale about the center of the object
  • ORIGIN : scale about the global origin of the scene
If your geometry does not already have a Translate Transform, you will likely choose CENTER or CENTERBOTTOM.
If your geometry already has a Translate, you will probably want to choose ORIGIN.

You will certainly need to play with this to get it right for your specific geometry. If you have any questions let us know.

 

import random

# these are "enums" for how the center of the scale is calculated
CENTERBOTTOM = 0				# scale about the center bottom of the object
CENTER = 1						# scale about the center of the object
ORIGIN = 2						# scale about the origin 

# these are the "parameters" of the script.
# change them here and then run the script
MinScale = 0.5					# the minimum value to scale
MaxScale = 2.0					# the maximum value to scale
									# the scale will be random between MinScale and MaxScale
UniformScale = True			# True makes X,Y and Z scale values the same, False lets X,Y and Z scale be all different
ScaleCenter = CENTERBOTTOM	# the center of the scale (chosen from list aboe)

# this is all for "Undo/Redo"
class undoData():
	def __init__(self):
		self.undoList = []
		self.readyForUndo = True
		
class undoScaleXform():
	def __init__(self, xform, node):
		self.xform = xform
		self.node = node
	def undo(self):
		mgDetach(self.xform)
	def redo(self):
		mgAppend(self.node, self.xform)
	def cleanup(self):
		mgDelete(self.xform)

def RedoFunc (db, undoData):
	for i in undoData.undoList:
		i.redo()
	undoData.readyForUndo = True
	mgEditorAddUndoForRedo (UndoFunc, UndoCleanupFunc, undoData)

def UndoFunc (db, undoData):
	for i in undoData.undoList:
		i.undo()
	undoData.readyForUndo = False
	mgEditorAddRedo (RedoFunc, UndoCleanupFunc, undoData)

def UndoCleanupFunc (db, reason, undoData):
	if (undoData.readyForUndo == False):
		for i in undoData.undoList:
			i.cleanup()

class randomScaleData():
	def __init__(self, db):
		self.undoData = undoData ()
	def appendUndo(self, xform, node):
		undoOne = undoScaleXform (xform, node)
		self.undoData.undoList.append (undoOne)

def RandomValueBetween(v1, v2):
	"""Return a random value between v1 and v2."""
	amount = random.random()		# between 0 and 1
	oneMinusAmount = 1.0 - amount
	r = (v1 * oneMinusAmount) + (v2 * amount)
	return r

def GetScaleCenter(node):
	"""Calculate scale center for a node."""
	c = mgMakeCoord3d(0.0, 0.0, 0.0)
	b, box = mgGetBounds(node)
	if (b) :
		if (ScaleCenter == CENTERBOTTOM):
			c = mgBoxGetCenterBottom(box)
		elif (ScaleCenter == CENTER):
			c = mgBoxGetCenter(box)
		elif (ScaleCenter == ORIGIN):
			c = mgMakeCoord3d(0.0, 0.0, 0.0)
	return c
	
def ApplyRandomScale(node, min, max):
	"""Create a scale transform with random values and attach to node."""
	xform = mgNewRec(fltXmScale)
	scaleX = RandomValueBetween(MinScale, MaxScale)
	if (UniformScale == True):
		scaleY = scaleX
		scaleZ = scaleX
	else:
		scaleY = RandomValueBetween(MinScale, MaxScale)
		scaleZ = RandomValueBetween(MinScale, MaxScale)
	center = GetScaleCenter(node)
	mgSetCoord3d(xform, fltXmScaleCenter, center.x, center.y, center.z)
	mgSetAttList(xform, fltXmScaleX, scaleX, fltXmScaleY, scaleY, fltXmScaleZ, scaleZ)
	mgAppend(node, xform)
	return xform
	
def RandomScale():
	toolName = "Random Scale"
	
	editorContext = mgNewEditorContext (toolName)

	if (not editorContext): 
		mgSendMessage (MMSG_ERROR, "Failed creating Editor Context")
		return

	mgSendMessage (MMSG_STATUS, "Editor Context Created");

	db = mgEditorGetDbRec (editorContext)
	geometry = mgGetSelectList (db)
	num = mgGetRecListCount (geometry)

	if (num == 0): 
		mgSendMessage (MMSG_ERROR, "Nothing Selected")
		return
 	data = randomScaleData (db)
	
	for i in range (0, num):
		rec,matrix = mgGetNextRecInList (geometry)
		xform = ApplyRandomScale(rec, MinScale, MaxScale)
		data.appendUndo(xform, rec)
		
	mgEditorAddUndo (editorContext, toolName,
					UndoFunc, UndoCleanupFunc, data.undoData) 

RandomScale()
				

 

For some added info, what I am doing is using populate to place trees, and I want to scale them. So I need to be able to scale them from the min z value of the reference or object, or the origin of the reference file would be great if that is possible. Or, is it possible to add this functionality to the populate feature? I'd guess not, but .. might as well dream.
Login to post a comment