/** * Abstract Foliage Scriptographer Tool 0.4 * by Oliver "gencha" Salzburg * * www.dirty-motherfucker.org */ tool.eventInterval = 1; // Do you want the path of the mouse to be rendered? var drawMousePath = true; // The last point the mouse was at var lastPoint = new Point( 0, 0 ); // The current direction of the mouse movement var currentDirection = new Point( 0, 0 ); // The counter that keeps track of the mouse movement var distanceCounter = 0; // Use pointsToCurves( ) on finished branches? var usePointsToCurves = false; // If set to false, the size of sub branches and their curls is dependant on the speed of the mouse. // If set to true, the size is only dependant on the values you set (see below). // NOTE! If you set this to false, make sure the branch sizes are set to very low values! var normalizeMouseSpeed = true; var values = { // How far do you have to move the mouse until a new branch can be created? branchDistance: 5, // The maximum life time of a branch maxLifeTime: 100, // The minimum life time of a branch minLifeTime: 80, // The maximum amount of branches that can live at any given time maxBranches: 1000, /*******************************/ /* Growth modification section */ // Minimum branch size minBranchSize: 2, // Maximum branch size maxBranchSize: 10, // How likely is it that a branch will grow into the opposite movement direction? backBranchRate: 0.35, /* Modifiers for branches that grow backwards */ // The scaling to apply to the curling, higher values will create tighter and smaller curls backBranchCurlScale: 5, // The scaling to apply to the lifetime, lower values mean shorter life time backBranchLifeScale: 0.2, /**********************/ /* Sub-branch section */ // How likely is it that a branch can spawn another branch? // NOTE! This chance is equal in each growth state. Meaning each time the branch growth. // This is very often, so too high values will bring Illustrator to it's knees. // ...and the result won't look good anyway. branchBranchRate: 0.1, // What is the highest age a branch can have so it can spawn another branch? // This value is relative to the branches total life time. maxBranchAgeToBranch: 0.3, // How old does a branch have to be so it can branch at all? // This is an absolute value and it should help to limit the branching of deep subbranches. minBranchAgeToBranch: 30, /*******************/ /* Blossom section */ blossomRate: 0.9 }; function onOptions() { values = Dialog.prompt('Abstract Foliage:', { branchDistance: {description: 'branchDistance'}, maxLifeTime: {description: 'maxLifeTime'}, minLifeTime: {description: 'minLifeTime'}, maxBranches: {description: 'maxBranches'}, minBranchSize: {description: 'minBranchSize'}, maxBranchSize: {description: 'maxBranchSize'}, backBranchRate: {description: 'backBranchRate'}, backBranchCurlScale: {description: 'backBranchCurlScale'}, backBranchLifeScale: {description: 'backBranchLifeScale'}, branchBranchRate: {description: 'branchBranchRate'}, maxBranchAgeToBranch: {description: 'maxBranchAgeToBranch'}, minBranchAgeToBranch: {description: 'minBranchAgeToBranch'}, blossomRate: {description: 'blossomRate'} }, values); } function onMouseDown( event ) { lastPoint = event.point; branches = []; if( drawMousePath ) { mainBranch = new Path(); mainBranch.moveTo( event.point ); mainBranch.strokeWidth = 0.25; } } function onMouseUp( event ) { for ( var i in branches ) { branches[ i ].finish(); } if( drawMousePath ) { mainBranch.pointsToCurves(); } } function onMouseDrag( event ) { if( drawMousePath ) { mainBranch.lineTo( event.point ); } currentDirection = event.point - lastPoint; currentDirection = currentDirection.normalize() * (Math.random() * 10); // Spawn new branches if( canBranch() && distanceCounter > values.branchDistance ) { var group = new Group(); // Determine curling direction var rotationDirection = ( Math.random() > 0.5 ) ? 1 : -1; // Determing branch life time var lifeTime = ( Math.random() * ( values.maxLifeTime - values.minLifeTime ) ) + values.minLifeTime; // Determine branch direction var branchDirection = currentDirection; if( Math.random() < values.backBranchRate ) { // Grow the branch in the backwards direction branchDirection = -branchDirection; // Apply back branch modifiers rotationDirection *= values.backBranchCurlScale; lifeTime *= values.backBranchLifeScale; } branches.push( new Branch( event.point, group, branchDirection, rotationDirection, lifeTime ) ); distanceCounter = 0; } // Grow branches for( var i in branches ) { var retval = branches[ i ].grow(); if( retval == false ) { branches[ i ].finish(); branches.splice( i, 1 ); } } distanceCounter += Math.abs( lastPoint.getDistance( event.point ) ); lastPoint = event.point; } // Branch: function Branch( point, group, direction, rotationDirection, life ) { this.point = point; this.vector = direction; if( normalizeMouseSpeed ) { this.vector = this.vector.normalize(); } var vectorScale = ( Math.random() * ( values.maxBranchSize - values.minBranchSize ) ) + values.minBranchSize; this.vector = this.vector * vectorScale; this.rotate = rotationDirection / 100; this.rotationDirection = rotationDirection; this.life = life; this.lifeTime = life; this.path = new Path(); this.path.moveTo( point ); this.path.strokeWidth = 0.25; group.appendChild( this.path ); } Branch.prototype.grow = function() { // Animate branch this.vector = this.vector.rotate( this.rotate ); this.rotate += this.rotationDirection / 100; this.point = this.point + this.vector; this.path.lineTo( this.point ); // Possibly die branch and blossom if( --this.life <= 0 ) { // Branch died, does it blossom? if( Math.random() < values.blossomRate ) { rect = new Rectangle( 0, 0, 3, 3 ); rect.center = this.point; new Path.Oval(rect); } return false; } // Possibly create a new branch from this branch if( canBranch() && Math.random() < values.branchBranchRate && this.life < values.maxBranchAgeToBranch * this.lifeTime && this.life > values.minBranchAgeToBranch ) { branchBranch( this ); } } Branch.prototype.finish = function() { if( usePointsToCurves ) { this.path.pointsToCurves( ); } } function branchBranch( branch ) { var group = new Group(); branches.push( new Branch( branch.point, group, branch.vector * 0.5, branch.rotationDirection * -1, branch.life ) ); } function canBranch() { return ( branches.length < values.maxBranches ); }