-
-
Save WRHerbert/8ae0ca145a81989824f0c9b871035454 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Snowflake Generator | |
This module contains all the procedures that are needed for to generate a large scale snowflake | |
and control the snowflake's variables using a user interface. To make this nested procedure | |
based script easily only one procedure has to be executed from the Maya Script Editor, this | |
procedure being displayUI(). However, the user interface can be bypassed allowing the user to | |
input any values for the variables if they wish to create more experimental snowflakes. | |
''' | |
import maya.cmds as cmds | |
import math | |
import random | |
def delete(*args): | |
''' | |
Selects all of the objects in the scene and deletes them. | |
On Exit : all objects in scene are deleted | |
''' | |
cmds.select(all=True) | |
cmds.delete() | |
def makeSnowflake(sName, Msize, ratio, thickness, branchNum, decay, angle, sideSplit, iterations): | |
''' | |
Is the main containing procedure that generates the snowflake and creates all the variables | |
for the nested sub-procedures to use. | |
Msize : determins the master size of the snowflake | |
ratio : is the ratio between the size of the entire snowflake and the size of the centre | |
thickness : controls the thickness of the centre and branches | |
branchNum : is the number of main branches that protrude from the centre | |
decay : determins the rate at which the branches shrink in size for each iteration | |
angle : controls the angle that the branches protrude from their parent branch | |
sideSplit : is the number of branches that protrude from one side of a parent branch | |
iterations : determins the number of times the branches split from the main branch | |
On Exit : a snowflake is generated using the following procedures with the defined variables | |
''' | |
Csize = ratio*Msize | |
Bsize = Msize - Csize | |
listBranches = [] | |
cmds.setAttr("lambert1.color", 1.0, 1.0, 1.0) | |
if cmds.objExists(sName+'_snowflake'): | |
errorPopup() | |
quit('Error: That snowflake name is already in use.') | |
def makeCentre(): | |
''' | |
Creates the centre portion of the snowflake using the variable defined in the | |
makeSnowflake procedure. | |
On Exit : a polyTorus is created and manipulated due to previously defined variables | |
''' | |
cmds.polyTorus(ax=[0, 0, 1], n=sName+'_snowflake', r=Csize | |
,sr=(0.1*Csize*thickness) | |
,sx=branchNum, sy=4, tw=45) | |
cmds.rotate(0, 0, 90, sName+'_snowflake') | |
cmds.scale(1, 1, 1*(1.0/(0.1*Csize*thickness))) | |
def makeMainBranches(): | |
''' | |
Generates the first iteration of branches that protrudes from the centre, and parents | |
them to the central torus. These are the main branches that the sub branches grow from. | |
On Exit : A number of polyCubes are created and manipulated to form the main branches | |
subject to the previously defined variables | |
''' | |
for i in range(1, branchNum+1): | |
cmds.polyCube(n=sName+'_branch'+str(i), h=Bsize) | |
listBranches.append(sName+'_branch'+str(i)) | |
cmds.xform(sName+'_branch'+str(i), piv=[0, -(Bsize/2), 0]) | |
cmds.move(0, Bsize/2, 0, sName+'_branch'+str(i)) | |
cmds.rotate(0, 0, (360/branchNum)*(i-1), sName+'_branch'+str(i)) | |
cmds.move(0, Csize+(Bsize/2), 0, sName+'_branch'+str(i), os=True) | |
cmds.parent(sName+'_branch'+str(i), sName+'_snowflake') | |
def firstSplit(): | |
''' | |
Creates the first iteration of sub branches that protrude from the main branches. | |
On Exit : A number of polyCubes are created and manipulated, forming the first set of | |
sub branches according to the previously defined variables | |
''' | |
for i in range(0, branchNum): | |
for j in range(1, (sideSplit*2)+1, 2): | |
cmds.duplicate(listBranches[i], name=listBranches[i]+'s'+str(j)) | |
cmds.move(0, (Bsize/(sideSplit*2.0))*j, 0, listBranches[i]+'s'+str(j), r=True, os=True) | |
cmds.rotate(0, 0, angle, listBranches[i]+'s'+str(j), r=True) | |
cmds.scale(decay, decay, decay, listBranches[i]+'s'+str(j), r=True) | |
cmds.duplicate(listBranches[i], name=listBranches[i]+'s'+str(j+1)) | |
cmds.move(0, (Bsize/(sideSplit*2.0))*j, 0, listBranches[i]+'s'+str(j+1), r=True, os=True) | |
cmds.rotate(0, 0, -angle, listBranches[i]+'s'+str(j+1), r=True) | |
cmds.scale(decay, decay, decay, listBranches[i]+'s'+str(j+1), r=True) | |
def furtherSplit(): | |
''' | |
Generates and arranges the remaining branches according the defined variables. | |
On Exit : A number of polyCubes are created and manipulated to create the remaining | |
branches for the snowflake subject to the previously defined variables | |
''' | |
y = 0 | |
z = 0 | |
for i in range(0, iterations): | |
x = math.pow((2*sideSplit),i) | |
z = y + x | |
y = z | |
splits = z | |
for i in range(0, branchNum): | |
for j in range(1, splits): | |
for h in range(1,(sideSplit+1)): | |
sel = cmds.duplicate(listBranches[i]+'s'+str(j)) | |
cmds.move(0, (Bsize/(sideSplit+1))*h, 0, sel, r=True, os=True) | |
cmds.rotate(0, 0, angle, sel, r=True) | |
cmds.scale(decay*decay, decay*decay, decay*decay, sel, r=True) | |
sel = cmds.duplicate(listBranches[i]+'s'+str(j)) | |
cmds.move(0, (Bsize/(sideSplit+1))*h, 0, sel, r=True, os=True) | |
cmds.rotate(0, 0, -angle, sel, r=True) | |
cmds.scale(decay*decay, decay*decay, decay*decay, sel, r=True) | |
makeCentre() | |
makeMainBranches() | |
firstSplit() | |
furtherSplit() | |
def createUI(): | |
''' | |
Creates thes basic window for the user interface after checking if one already exists. | |
On Exit : a simple user interface window is created | |
''' | |
if cmds.window("snowflakeUI", exists=True): | |
cmds.deleteUI("snowflakeUI") | |
cmds.window("snowflakeUI", title="Snowflake Generator") | |
cmds.frameLayout(marginHeight=5, marginWidth=5, labelVisible=False) | |
cmds.columnLayout() | |
cmds.showWindow("snowflakeUI") | |
def fillUI(a, b, c, d, e, f, g, h): | |
''' | |
Adds all the components to the user interface that allows the user to control the snowflake | |
variables including name fields, buttons and sliders. | |
On Exit : variable controlling components are added to the user interface window | |
''' | |
cmds.text(label="This is a generator that creates large scale individual snowflake models using polygons. Please refer to the instructions before use.", w= 250, ww=True) | |
cmds.separator(h=10, style="none") | |
cmds.button(label='Instructions', command=instrucPopup) | |
cmds.separator(h=10, style="none") | |
global nameField | |
cmds.text(label=" Snowflake Name") | |
nameField = cmds.textField(text = 'default') | |
cmds.separator(h=10, style="none") | |
global MsizeSlider | |
cmds.text(label=" Overall Size (Diameter)") | |
MsizeSlider = cmds.floatSliderGrp(field=True, minValue=15.0, maxValue=50.0, value=a) | |
cmds.separator(h=10, style="none") | |
global ratioSlider | |
cmds.text(label=" Centre Size to Overall Size Ratio") | |
ratioSlider = cmds.floatSliderGrp(field=True, minValue=0.2, maxValue=0.5, value=b) | |
cmds.separator(h=10, style="none") | |
global thicknessSlider | |
cmds.text(label=" Centre Thickness") | |
thicknessSlider = cmds.floatSliderGrp(field=True, minValue=1.0, maxValue=7.0, value=c) | |
cmds.separator(h=10, style="none") | |
global branchNumSlider | |
cmds.text(label=" Number of Initial Branches") | |
branchNumSlider = cmds.intSliderGrp(field=True, minValue=3, maxValue=8, value=d) | |
cmds.separator(h=10, style="none") | |
global decaySlider | |
cmds.text(label=" Rate of Branch Size Decay") | |
decaySlider = cmds.floatSliderGrp(field=True, minValue=0.3, maxValue=0.7, value=e) | |
cmds.separator(h=10, style="none") | |
global angleSlider | |
cmds.text(label=" Angle that Branches Protrude From") | |
angleSlider = cmds.intSliderGrp(field=True, minValue=1, maxValue=179, value=f) | |
cmds.separator(h=10, style="none") | |
global sideSplitSlider | |
cmds.text(label=" Number of Branches that Protrude from one Side") | |
sideSplitSlider = cmds.intSliderGrp(field=True, minValue=1, maxValue=6, value=g) | |
cmds.separator(h=10, style="none") | |
global iterationsSlider | |
cmds.text(label=" Number of Branch Split Iterations") | |
iterationsSlider = cmds.intSliderGrp(field=True, minValue=0, maxValue=4, value=h) | |
cmds.separator(h=10, style="none") | |
cmds.button(label="Input Random Values", command=randomVariables) | |
cmds.separator(h=10, style="none") | |
cmds.button(label="Generate Snowflake", command=getVariables) | |
cmds.separator(h=10, style="none") | |
cmds.button(label="Delete All", command=delete) | |
cmds.separator(h=10, style="none") | |
cmds.button(label="Close Window", command=closeUI) | |
def closeUI(*args): | |
''' | |
Closes the user interface. To be used with a button. | |
On Exit : the user interface closes | |
''' | |
cmds.deleteUI("snowflakeUI") | |
def randomVariables(*args): | |
createUI() | |
fillUI(30.0, 0.4, 3.5, 4, 0.5, 45, 2, 2) | |
def getVariables(*args): | |
''' | |
Collects the information from the text fields and sliders that the user defines and stores | |
it in a list to be used for the snowflake generation. Then runs the snowflake generator | |
through the makeSnowflake procedure according to the list information. | |
On Exit : varList is populated with information and the makeSnowflake procedure is executed | |
''' | |
varList[0] = cmds.textField(nameField, q=True, text=True) | |
varList[1] = cmds.floatSliderGrp(MsizeSlider, q=True, v=True) | |
varList[2] = cmds.floatSliderGrp(ratioSlider, q=True, v=True) | |
varList[3] = cmds.floatSliderGrp(thicknessSlider, q=True, v=True) | |
varList[4] = cmds.intSliderGrp(branchNumSlider, q=True, v=True) | |
varList[5] = cmds.floatSliderGrp(decaySlider, q=True, v=True) | |
varList[6] = cmds.intSliderGrp(angleSlider, q=True, v=True) | |
varList[7] = cmds.intSliderGrp(sideSplitSlider, q=True, v=True) | |
varList[8] = cmds.intSliderGrp(iterationsSlider, q=True, v=True) | |
makeSnowflake(varList[0], varList[1], varList[2], varList[3], varList[4], varList[5], varList[6], | |
varList[7], varList[8]) | |
def instrucPopup(*args): | |
''' | |
Creates and opens a popup window containing all the instructions for using the snowflake | |
generator user interface. To be used with a button. | |
On Exit : opens the instructions window | |
''' | |
if cmds.window("instrucUI", exists=True): | |
cmds.deleteUI("instrucUI") | |
if cmds.windowPref("instrucUI", q=True, exists=True): | |
cmds.windowPref("instrucUI", remove=True) | |
cmds.window("instrucUI", title="Instructions", w = 410, h = 300) | |
cmds.frameLayout(marginHeight=5, marginWidth=5, labelVisible=False) | |
cmds.columnLayout() | |
cmds.text(label="Instructions", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="This is the instructions page for the snowflake generator, which should explain most of the aspects of this modelling script. To achieve the best results some experimentation is required to find combinations of values that suit your needs. All ranges of snowflakes can be created, some ordinary and some experimental, try to use the default values as a initial guide to creating an effective snowflake. If you wish to create even more experimental snowflakes, use the script module to run the procedure makeSnowflake('sName', Msize, ratio, thickness, branchNum, decay, angle, sideSplit, iterations) to input any variables you wish.", ww=True) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Snowflake Name' field will append a name prefix to the model, for example the default creating the name 'default_snowflake'. Unfortunately two snowflakes cannot have the same name and using an identical name will bring up the error dialog.", ww=True) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Overall Size (Diameter)' slider will control the overall size of the snowflake.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Centre Size to Overall Size Ratio' value controls the ratio between the size of the entire snowflake and the size of the centre section.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Centre Thickness' slider determins the thickness of the central ring.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Number of Initial Branches' silder controls the number of main branches that protrude from the central ring. Increasing this variable to a high value can result in long loading times.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Rate of Branch Size Decay' slider will determin the size decrease of each branch for each iteration.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Angle that Branches Protrude From' slider will change that angle that the branches protrude at.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Number of Branches that Protrude from one Side' slider will control how many branches protrude from one side of thir respective parent branch. Increasing this variable to a high value can result in long loading times.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.text(label="The 'Number of Branch Split Iterations' slider will determin how man times the branches of the snowflake will split from the main branch. Increasing this variable to a high value can result in long loading times.", ww=True, w=400) | |
cmds.separator(h=10, style="none") | |
cmds.button(label="Close Window", command=closeInstrucPopup) | |
cmds.showWindow("instrucUI") | |
def closeInstrucPopup(*args): | |
''' | |
Closes the instructions popup window. To be used with a button. | |
On Exit : the instructions popup closes | |
''' | |
cmds.deleteUI("instrucUI") | |
def errorPopup(): | |
''' | |
Creates and displays a error popup explaining that two snowflakes cannot have the same name. | |
To be used with a button. | |
On Exit : opens the error window | |
''' | |
if cmds.window("errorUI", exists=True): | |
cmds.deleteUI("errorUI") | |
if cmds.windowPref("errorUI", q=True, exists=True): | |
cmds.windowPref("errorUI", remove=True) | |
cmds.window("errorUI", title="Duplicate Name", w = 210, h = 80) | |
cmds.frameLayout(marginHeight=5, marginWidth=5, labelVisible=False) | |
cmds.columnLayout() | |
cmds.text(label="Error: The snowflake could not be generated because the snowflake name is already in use.", ww=True, w=200) | |
cmds.separator(h=10, style="none") | |
cmds.button(label="Close Window", w = 200, command=closeErrorPopup) | |
cmds.showWindow("errorUI") | |
def closeErrorPopup(*args): | |
''' | |
Closes the error popup window. To be used with a button. | |
On Exit : the error popup closes | |
''' | |
cmds.deleteUI("errorUI") | |
def displayUI(): | |
''' | |
Is the main procedure to be used to open the snowflake generator user interface. Creates the | |
list varList and inputs default snowflake values. | |
On Exit : creates varList and inputs default values while opening the snowflake generator | |
user interface | |
''' | |
global varList | |
varList = ['default', 20.0, 0.3, 3.0, 6, 0.6, 50, 3, 3] | |
createUI() | |
fillUI(20.0, 0.3, 3.0, 6, 0.6, 50, 3, 3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment