////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Here are a few parameters that you can change to modify the behavior of the patterm // Feel free to modify the values, don't change the variable names modelParameters = { // scaling of the input pattern patternScale : 1, // Offset in pixels between two rings of the spiral // Value of 1 will create tightly packed spiral, higher value will create bigger gap between spiral rings ringOffset : 0, // use a value between -50 and 100. The default is 0. // Controls how close the elements are along the spiral. // Use value from 0.3 to 1.5, it is a multiplicative factor for the angle between subsequent segments. // The default is 1. patternOffset : 1, // Add spacing in pixels around each patterns in pixels. Note that this value will increase the offset between spiral rings spacing : 0, // use a value between -10 to 20. The default is 0. // Keep each pattern upright. keepPatternUpright : false, // The default is false. // Variation of color of the pattern. // For example, value of 0.2 means that each of the red, green, and blue color components // will be multiplied by a DIFFERENT random value from interval 0.8 and 1.2. // Set to 0 if you do not want to modify the pattern color. colorRandomness : 0.05, // use a value between 0 and 1. The default is 0.05. // Variation of pattern brightness. // For example, value of 0.6 means that each of the red, green, and blue color components // will be multiplied by THE SAME random value from interval 0.4 and 1.6. // Set to 0 if you do not want to modify the pattern brightness. brightnessRandomness : 0.1, // use a value between 0 and 1. The default is 0.1. } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // You can modify the code below but keep in mind that as with any scripting // you can break things. Keep a backup copy. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get pattern and its size var pattern = RenderAPI.getParameter(kpsPattern) var patternSize = pattern.getParameter(kpsSize) var patternSizeForDialog = Math.max (patternSize.x, patternSize.y) // For the script to work with a menu with preview, you need to define a run method with the following three parameters: // 1. api - render api to be used. Do not use RenderAPI directly, since preview uses a different renderer // 2. parameter - contains model parameters. Do not refer directly to modelParameters inside the run method or methods called from it. // 3. scale - preview can be scaled up or down depending on the size of the input pattern. Accomodate scale inside the run method. function run (api, parameters, scale) { // get size of the output area var outputSize = api.getParameter(kpsSize) var patternSize = pattern.getParameter(kpsSize) patternSize *= parameters.patternScale //pattern.setParameter(kpsMaxPatternCacheSize, patternSize.x * patternSize.y * 7 * 8 * 180) // to finetune the progress bar, specify how many pixels are covered by patterns - the bigger the spacing the lower the value, for example api.setParameter(kpsPixelCoverage, 0.5 * patternSize.y / (patternSize.y + parameters.ringOffset) * patternSize.x / (patternSize.x + parameters.patternOffset)) // possibly add spacing if (patternSize.x + parameters.spacing >= Math.min (5, patternSize.x) ) patternSize.x += parameters.spacing else patternSize.x = Math.min (5, patternSize.x) if (patternSize.y + parameters.spacing >= Math.min (5, patternSize.y)) patternSize.y += parameters.spacing else patternSize.y = Math.min (5, patternSize.y) // scale up if the patternsize is 1 to avoid long loop if (patternSize.x == 1 && patternSize.y == 1) { if (scale == 1) scale = 20 keepPatternUpright = true // 1x1 patterns that are scaled up do not rotate gracefully } patternSize *= scale var angle = -90 var angleStep api.getParameter (kpsSelectedPaths) // if the visible area is smaller than the selection, center the spiral in the center of the visible area var visibleSize = api.getParameter(kpsVisibleSize) var visibleOrigin = api.getParameter(kpsVisibleOrigin) var outputOrigin = api.getParameter(kpsOrigin) var spiralCenter if (visibleSize.x < outputSize.x) // if the visible area is smaller than the selection, center the spiral in the center of the visible area spiralCenter = new Vector2 (visibleOrigin.x - outputOrigin.x + visibleSize.x / 2, visibleOrigin.y - outputOrigin.y+ visibleSize.y / 2) else // center in the output area (this is the selection) spiralCenter = new Vector2 (outputSize.x / 2, outputSize.y / 2) api.translate(spiralCenter.x, spiralCenter.y) var num = 0 // get the longest of distances from the center to each corner var x1 = spiralCenter.x var x2 = outputSize.x - spiralCenter.x var y1 = spiralCenter.y var y2 = outputSize.y - spiralCenter.y var diagonalSq = Math.max (Math.max (x1 * x1 + y1 * y1, x1 * x1 + y2 * y2), Math.max (x2 * x2 + y1 * y1, x2 * x2 + y2 * y2)) var diagonal = Math.sqrt(diagonalSq) + Math.sqrt(patternSize.x * patternSize.x + patternSize.y *patternSize.y) * 0.5 for (var radius = 0; Math.abs(radius) < diagonal ; ) { radius = patternSize.y/2 + ((patternSize.y - 1 + parameters.ringOffset * scale) / 360) * angle // In one revolution (360 degrees) we want to add patternSize.y to the radius angleStep = 360 / ( 6.28 * (radius - patternSize.y/2)/ (patternSize.x + parameters.patternOffset * scale)) api.pushMatrix() // Set the seed based on the current row and column - this assures that the color will be modified // in the same way for the pattern in the neighboring selected area var seed = Math.floor(((angle * 214013) % 0x7fffffff)) var rc = parameters.colorRandomness // color randomness var br = 1 - parameters.brightnessRandomness + Engine.rand(seed) * parameters.brightnessRandomness*2 // brightness api.Color (kFillColor, br *(1 - rc + Engine.rand()*rc*2), br*(1 - rc + Engine.rand()*rc*2), br*(1 - rc + Engine.rand()*rc*2)) // rotate around the center of the selection api.translate(-outputSize.x / 2, -outputSize.y / 2) api.rotate(angle) api.translate(outputSize.x / 2, outputSize.y / 2) api.translateRel(0, radius) // translate relative to the rotated frame api.scale (scale, scale) if (parameters.keepPatternUpright) // cancel the rotation above api.rotate(-angle) else // Adjust the rotation set above so that the pattern itself is rotated only in multiples of 2 degrees api.rotate( - angle + 2 * Math.floor(0.5+angle/2)) api.scale(parameters.patternScale) pattern.render(api) api.popMatrix() angle += angleStep } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Menu start // If you want to create a menu in which you change some of the script parameters, include the following code: // For shipped scripts we can include localized strings, prefixed with $$$/ - call method localize(string) on the prefixed string // For your own strings, you can query app.locale and select several language versions (for example, your native language and english). Try alert ("Language is: " + app.locale) var decoMenu = { // an object that defines the menu menuTitle : localize("$$$/DecoScripts/Spiral/Spiral=Spiral"), menuBackground : [0.93, 0.93, 0.93, 1], previewBackground : [1, 1, 1, 1], panels : [ { panelName : "", leftColumnWidth : 180, unitsWidth : 65, dropdownlistWidth : 160, panelMenu : [ { itemName : localize("$$$/DecoScripts/PatternScale=Pattern Scale:") , itemUnit : "", itemType : 'slider', itemValue : modelParameters.patternScale, itemMin : 0.1, itemMax : 1.25, itemStep : 0.01, varName : 'patternScale' }, { itemName : localize("$$$/DecoScripts/Spiral/RingOffset=Ring spacing:"), itemUnit : localize("$$$/DecoScripts/Units/pixels=pixels"), itemType : 'slider', itemValue : modelParameters.ringOffset, itemMin : Math.min(-20, -1 * patternSizeForDialog), itemMax : Math.max(100, 2 * patternSizeForDialog), itemStep : 1, varName : 'ringOffset' }, { itemName : localize("$$$/DecoScripts/Spiral/PatternSpacing=Pattern spacing:"), itemUnit : localize("$$$/DecoScripts/Units/pixels=pixels"), itemType : 'slider', itemValue : modelParameters.patternOffset, itemMin : Math.min(-20, -1 * patternSizeForDialog), itemMax : Math.max(100, 1 * patternSizeForDialog), itemStep : 1, varName : 'patternOffset' }, { itemName : localize("$$$/DecoScripts/Spiral/KeepUpright=Keep pattern upright:"), itemUnit : '', itemType : 'checkbox', itemValue : modelParameters.keepPatternUpright, itemMin : 0, itemMax : 0, varName : 'keepPatternUpright' }, { itemName : localize("$$$/DecoScripts/ColorRandomness=Color randomness:"), itemUnit : "", itemType : 'slider', itemValue : modelParameters.colorRandomness, itemMin : 0, itemMax : 1, itemStep : 0.01, varName : 'colorRandomness' }, { itemName : localize("$$$/DecoScripts/BrightnessRandomness=Brightness randomness:"), itemUnit : "", itemType : 'slider', itemValue : modelParameters.brightnessRandomness, itemMin : 0, itemMax : 1, itemStep : 0.01, varName : 'brightnessRandomness' }, //{ itemName : "Pattern rotate angle:", itemUnit : 'degrees', itemType : 'slider', itemValue : " + rotateAngle + ", itemMin : -180, itemMax : 180, itemStep : 1, varName : 'rotateAngle' }, ] } ] // end of panels } // end of menu // If livePreview is set to 1, the preview image is updated live. Note that due to limitations of scripted menus the update is slow and the flickering may be disturbing. livePreview = 0 // recommended value is 0 // Call Photoshop Script that creates the menu Engine.evalFile ("_Deco Menu.jsx") // Menu finished ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (typeof skipRun == 'undefined' || !skipRun) // run unles we exited the preview window without pressing a button run(RenderAPI, modelParameters, 1)