[Closed] Maxscript Melting Pot: Post your hot functions
Most of you who have been scripting for some time have obviously made a library of shortcut and grunt functions that have saved you hours of coding by a quick call. If you feel so inclined, it would be great to have a repositry of useful snippets. (similar to prettyPixel’s Geometrical Calculation thread). Even lines of code that condense what could be a difficult task into a few short calculations are helpful.
So post away and help build a growing community of kickass scripters.
Naturally, comment your code so we know where it came from when we use it!!!
Good idea erilaz
To begin, here are some functions for arrays.
This function inverts the array :
fn reverseArray array = (
local arrayCount=array.count
for i=0 to (arrayCount-1) collect array[(arrayCount-i)]
)
-- usage :
ar=#(25,2,12,86,99,0)
reverseArray ar
This function moves the elements of the array. The offset is negative :
fn offsetArray array offset = (
if offset>0 do (
local startSegArray=for i=(offset+1) to (array.count) collect array[i]
local endSegArray=for i=1 to offset collect array[i]
(startSegArray+endSegArray)
)--if
)
-- usage :
ar=#(25,2,12,86,99,0)
offsetArray2 ar 1
offsetArray2 ar 3
This function compares 2 arrays
fn compArray array1 array2 = (
local count=array1.count
if count!=array2.count then false
else (
for i=1 to count do ( if array1[i]!=array2[i] do return false )
true
)
)
-- usage :
ar=#(25,2,12,86,99,0)
compArray ar #(25,2,12,86,99,0,2)
compArray ar #(25,2,13,86,99,0)
compArray ar #(25,2,12,86,99,0)
compArray #(25,2,12,86,99,0) ar
This function finds the common part of 2 arrays :
fn unionArray array1 array2 = (
uA=#()
for array1Elem in array1 do ( if (findItem array2 array1Elem!=0) then append uA array1Elem )
uA
)
-- usage :
ar=#(25,2,12,86,99,0)
unionArray ar #(25,2,12,86,99,0)
unionArray ar #(56,48,2,95,25)
This function removes elements in an array. The elements to remove are stored in the second array :
fn substractArray array array2remove = (
for elem in array2remove do (
local idx=findItem array elem
if idx!=0 do deleteItem array idx
)
array
)
-- usage :
ar=#(25,2,12,86,99,0)
substractArray ar #(44,86,12,25)
There are many useful functions… Where to begin?
Hey PrettyPixel,
You can also use the string method to compare arrays of any kind:
fn theSame a b = (a as string) == (b as string)
Light
--FUNCTION TO GET ZERO-PADDED FRAME NUMBERS:
fn getZeros theNum = (substring "0000" 1 (4-(theStr = theNum as string).count) + theStr )
--Usage:
theFrame = 12
newPath = "c:\ em\\filename_" + getZeros theFrame +".tga"
-->"c: em\filename_0012.tga"
--NOTE: Works correctly in the range from 0 to 9999.
Alternative version of the same function:
fn reverseArray2 theArray = (for i = theArray.count to 1 by -1 collect theArray[i])
anArray = #(1,2,3,4,5,6,7,8,9,10)
#(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
reverseArray2 anArray
#(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
fn hasModifier theObjects theModClass = (
for o in theObjects where
(for m in o.modifiers where classof m == theModClass collect m).count > 0
collect o
)
--Usage:
--get those selected objects that have a Slice modifier applied:
theSliced = hasModifier selection SliceModifier
--get the objects named Box* that have a Bend modifier applied:
theBentBoxes = hasModifier $Box* Bend
So far most of these hot functions would be just about as easy to write anew as to copy paste from the thread…but hows about some good geometry funcs? You guys must have a lot of those…and they always trip me up
Here’s a bunch of rigging functions I use all the time. I should probably go through these again, seems like I’m also learning new scripting tricks to make functions like these better:
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : (MAPPED) A modified version of the freeze transform script that ships with Max.
# Creates a list controller for both the position and rotation of an object and then add new controllers
# which can be used to reset the object's position and rotation to it's initial state.
# Parameters : <node> obj : The object to freeze.
# <boolean> position : If true, freezes the object's position controller. Default:true
# <boolean> rotation : If true, freezes the object's rotation controller. Default:true
*/----------------------------------------------------------------------------------------------------------------------------------------------
mapped fn freezePosRot obj position:true rotation:true = (
-- feeze position
if position then (
obj.position.controller = Bezier_Position()
obj.position.controller = position_list()
obj.position.controller.available.controller = Position_XYZ()
obj.position.controller.setname 1 "dontUse"
obj.position.controller.setname 2 "animate"
obj.position.controller.SetActive 2
)
-- freeze rotation
if rotation then (
obj.rotation.controller = Euler_Xyz()
obj.rotation.controller = Rotation_list()
obj.rotation.controller.available.controller = Euler_xyz()
obj.rotation.controller.setname 1 "dontUse"
obj.rotation.controller.setname 2 "animate"
obj.rotation.controller.SetActive 2
-- set the axis order so that the Z axis (bend) will always rotate as expected in Gimbal mode
obj.rotation.controller[2].axisOrder = 6
)
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : Find the root of an object by getting the last parent object in the chain.
# Parameters : <node> obj : The object whose root you want to find.
*/----------------------------------------------------------------------------------------------------------------------------------------------
fn findRoot obj = (
local p1 = obj.parent
for i = 1 to 10000 do (
p2 = p1.parent
if p2 == undefined then return p1 else p1 = p2
)
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : Gets the matrix3 value defined by two point3 values. Uses positive Z for the world up vector.
# Parameters : <point3> p1 : The vector's start position.
# <point3> p2 : The vector's end position.
*/----------------------------------------------------------------------------------------------------------------------------------------------
fn buildMatrix p1 p2 = (
upVector = [0,0,1]
xVector = normalize (p2 - p1)
yVector = normalize (cross upVector xVector)
zVector = normalize (cross xVector yVector)
theMatrix = matrix3 xVector yVector zVector p1
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : Quicker way of creating a specific type of helper object. Sets display types off by default so that you only have to specify
# the exact one you want turned on. If other display types aren't specifically set to off, then the settings of the last selected
# point helper will be used.
# Parameters : <point3> pos : Position. Default: [0,0,0]
# <number> size : Size. Default: 1
# <string> name : Name. Default: uniqueName "Helper"
# <boolean> centerMarker : Sets the Center Marker checkbox. Default: off
# <boolean> axistripod : Sets the Axis Tripod checkbox. Default: off
# <boolean> cross : Sets the Cross checkbox. Default: off
# <boolean> box : Sets the Box checkbox. Default: off
# <boolean> constantScreenSize : Sets the Constant Screen Size checkbox. Default: off
# <boolean> drawOnTop : Sets the Draw On Top checkbox. Default: on
*/----------------------------------------------------------------------------------------------------------------------------------------------
fn createPointHelper pos:[0,0,0] size:1 name:"Helper" centerMarker:off axistripod:off cross:off box:off constantScreenSize:off drawOnTop:on wirecolor:(color 0 255 255)= (
p = point pos:pos name:name centerMarker:centerMarker axistripod:axistripod cross:cross box:box size:size constantscreensize:constantScreenSize drawontop:drawOnTop
p.wirecolor = wirecolor
p.showFrozenInGray = false
p
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : (MAPPED) Mirrors a spline across the world X axis, using a supplied point3 value as the center to mirror about.
# Parameters : <node> obj : The spline to mirror.
# <point3> centerPoint : The position in world space to mirror about.
*/----------------------------------------------------------------------------------------------------------------------------------------------
mapped fn mirrorSplines obj centerPoint = (
if superClassOf obj == shape then (
local n = numKnots obj
local knotPosArr = for i = 1 to n collect (getKnotPoint obj 1 i)
local inVecPosArr = for i = 1 to n collect (getInVec obj 1 i)
local outVectPosArr = for i = 1 to n collect (getOutVec obj 1 i)
obj.pos.x += 2 * (centerPoint - obj.pos.x)
for i = 1 to n do (
setKnotPoint obj 1 i [(knotPosArr[i][1] + 2 *(centerPoint - knotPosArr[i][1])),knotPosArr[i][2],knotPosArr[i][3]]
setInVec obj 1 i [(inVecPosArr[i][1] + 2 * (centerPoint - inVecPosArr[i][1])),inVecPosArr[i][2],inVecPosArr[i][3]]
setOutVec obj 1 i [(outVectPosArr[i][1] + 2 * (centerPoint - outVectPosArr[i][1])),outVectPosArr[i][2],outVectPosArr[i][3]]
)
updateShape obj
)
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : (MAPPED) Adds a Position Constraint controller to the supplied obj, and constrains the obj to the supplied constrainTo object.
# If the obj already has a Position List controller, then add the PC to the Available slot, if not then replace the position
# controller completely with the PC controller.
# Parameters : <node> obj : The obj to add the controller to.
# <node> constrainTo : The obj to be constrained to.
# <boolean> replaceList : If true, the new controller is not added to an existing list controller, but replaces it instead.
# Default:false
*/----------------------------------------------------------------------------------------------------------------------------------------------
mapped fn addPositionConstraint obj constrainTo keepOffset:false replaceList:false = (
local pc = Position_Constraint ()
-- if the position controller is a Position List then add the pc to the available slot
if classOf obj.position.controller == Position_List and replaceList == false then (
obj.position.controller.available.controller = pc
-- get the number of the pc controller
local numCon = obj.position.controller.getCount()
-- set the controller's name
obj.position.controller.setName numCon "posCon"
obj.position.controller.setActive numCon
)
-- replace position controller if it's not a Position List
if classOf obj.position.controller != Position_List or replaceList == true then (
obj.position.controller = pc
)
-- set the attributes of the controller
if classOf constrainTo != array then (pc.appendTarget constrainTo 100)
if classOf constrainTo == array then (
local n = constrainTo.count
for i = 1 to n do (
pc.appendTarget constrainTo[i] (100 / n)
)
)
pc.relative = keepOffset
-- return the position constraint controller
pc
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : (MAPPED) Adds a Path Constraint controller to the supplied obj, and constrains the obj to the supplied spline object.
# If the obj already has a Position List controller, then add the PC to the Available slot, if not then replace the position
# controller completely with the PC controller.
# Parameters : <node> obj : The obj to add the controller to.
# <node> pathSpl : The path to be constrained to.
# <number> percent : The percentage along the path to set the obj. Default: 0
# <boolean> replaceList : If true, the new controller is not added to an existing list controller, but replaces it instead.
# Default:false
*/----------------------------------------------------------------------------------------------------------------------------------------------
mapped fn addPathConstraint obj pathSpl percent:0 keepOffset:false replaceList:false = (
local pc = path_constraint()
-- if the position controller is a Position List then add the pc to the available slot
if classOf obj.position.controller == Position_List and replaceList == false then (
obj.position.controller.available.controller = pc
-- get the number of the pc controller
local numCon = obj.position.controller.getCount()
-- set the controller's name
obj.position.controller.setName numCon "pathCon"
obj.position.controller.setActive numCon
)
-- replace position controller if it's not a Position List
if classOf obj.position.controller != Position_List or replaceList == true then (
obj.position.controller = pc
)
-- set the attributes of the controller
pc.path = pathSpl
pc.percent = percent
pc.follow = off
pc.constantVel = on
pc.loop = off
pc.relative = keepOffset
-- remove keys
deleteKeys pc
-- return the path constraint controller
pc
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : (MAPPED) Adds a Look At controller to the supplied obj, and constrains the obj to the supplied constrainTo object.
# If the obj already has a Rotation List controller, then add the Look At to the Available slot, if not then replace the rotation
# controller completely with the controller.
# Parameters : <node> obj : The obj to add the controller to.
# <node> lookAtObj : The obj to look at.
# <node> upnode : The Upnode to use. If not defined, then the Upnode is set to World.
# <string> sourceAxis : The Source Axis to use. Default: "X"
# <boolean> flipSourceAxis : Whether or not the Source Axis is flipped. Default: off
# <string> upnodeAxis : The Aligned To Upnode Axis to use. Default: "X"
# <boolean> replaceList : If true, the new controller is not added to an existing list controller, but replaces it instead.
# Default:false
*/----------------------------------------------------------------------------------------------------------------------------------------------
mapped fn addLookAt obj lookAtObj upnode:undefined lookAtAxis:"X" flipLookAtAxis:off sourceAxis:"X" flipSourceAxis:off upnodeAxis:"X" keepOffset:false replaceList:false = (
local lac = LookAt_Constraint ()
-- if the rotation controller is a Rotation List then add the lac to the available slot
if classOf obj.rotation.controller == Rotation_List and replaceList == false then (
obj.rotation.controller.available.controller = lac
-- get the number of the pc controller
local numCon = obj.rotation.controller.getCount()
-- set the controller's name
obj.rotation.controller.setName numCon "rotLookAt"
obj.rotation.controller.setActive numCon
)
-- replace rotation controller if it's not a Rotation List
if classOf obj.rotation.controller != Rotation_List or replaceList == true then (
obj.rotation.controller = lac
)
-- set the attributes of the controller
lac.appendTarget lookAtObj 100
lac.lookat_vector_length = 0
lac.relative = keepOffset
if upnode == undefined then lac.upnode_world = on
if upnode != undefined then (
lac.upnode_world = off
lac.pickUpNode = upnode
)
lac.target_axis = case lookAtAxis of (
"X":0
"Y":1
"Z":2
)
lac.target_axisFlip = flipLookAtAxis
lac.StoUP_axis = case sourceAxis of (
"X":0
"Y":1
"Z":2
)
lac.StoUP_axisFlip = flipSourceAxis
lac.upnode_axis = case upnodeAxis of (
"X":0
"Y":1
"Z":2
)
-- return the look at controller
lac
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : (MAPPED) Adds an Orientation Constraint controller to the supplied obj, and constrains the obj to the supplied constrainTo object.
# If the obj already has a Rotation List controller, then add the PC to the Available slot, if not then replace the position
# controller completely with the PC controller.
# Parameters : <node> obj : The obj to add the controller to.
# <node> constrainTo : The obj to be constrained to.
# <boolean> replaceList : If true, the new controller is not added to an existing list controller, but replaces it instead.
# Default:false
*/----------------------------------------------------------------------------------------------------------------------------------------------
mapped fn addOrientationConstraint obj constrainTo keepOffset:false replaceList:false = (
local oc = Orientation_Constraint ()
-- add the oc to the available slot of the rotation list controller
if classOf obj.rotation.controller == Rotation_List and replaceList == false then (
obj.rotation.controller.available.controller = oc
-- get the number of the pc controller
local numCon = obj.rotation.controller.getCount()
-- set the controller's name
obj.rotation.controller.setName numCon "orientCon"
obj.rotation.controller.setActive numCon
)
-- replace rotation controller
if classOf obj.rotation.controller != Rotation_List or replaceList == true then (
obj.rotation.controller = oc
)
-- set the attributes of the controller
oc.appendTarget constrainTo 100
oc.relative = keepOffset
-- return the orientation constraint controller
oc
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : Creates a new bone such that the X axis is the twist, the Y axis is side to side rotation, and the Z axis is the bend.
# Also freezes the transform of the bone after creation, so that doesn't need to be done seperately.
# Parameters : <matrix3> p1 : The start point of the bone.
# <number> p2 : The end point of the bone.
# <number> width : Width of the bone. Default: 1
# <number> height : Height of the bone. Default: 1
# <string> name : Name of the bone. Adds a number at the end of the name to keep it unique. Default: "Bone"
# <string> side : Either "LT" (left), "RT" (right), or "CTR" (center). Used to determine what color the bone is.
# Defualt: "CTR"
# <boolean> stretchy : Set the Freeze Length attribute of the bone. Default: false
*/----------------------------------------------------------------------------------------------------------------------------------------------
fn createNewBone p1 p2 width:1 height:1 name:"Bone" side:"CTR" stretchy:false = (
local matrix = buildMatrix p1 p2
local length = distance p1 p2
local startPos = matrix.position
local endPos = [startPos.x + length,startPos.y,startPos.z]
local b = boneSys.createBone startPos endPos [0,1,0]
-- set properties of the bone
b.width = width
b.height = height
b.taper = 30
b.sideFins = off
b.frontFin = off
b.backFin = off
-- rotate bone into place
in coordsys matrix (b.rotation = (quat 1 0 0 1))
-- set the color of the bone
if side == "LT" then b.wirecolor = (color 28 28 177)
if side == "RT" then b.wirecolor = (color 6 134 6)
if side == "CTR" then b.wirecolor = (color 8 110 134)
-- set name of bone
b.name = name
-- set freeze length attribute
if stretchy then b.boneFreezeLength = false
-- turn off the "Show Frozen In Gray" property, I hate that :)
b.showFrozenInGray = false
return b
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : Creates a chain of bones using either an array of point3 values or objects. This function calls the "createNewBone" function
# to create the individual bones.
# Parameters : <array> arr : Array that contains the positions or objects to use as end points for the bones.
# <number> width : The width of the bones. Default: 1
# <number> height : The height of the bones. Default: 1
# <boolean> constrainToHelpers : Settings this to true applies both a position and look at constraint to each of the bones,
# and assigns the helper objects as targets. This lets you use helpers objects to move and rotate
# the bones. Default: false
# <boolean> stretchy : Set the Freeze Length attribute of the bone. Default: false
*/----------------------------------------------------------------------------------------------------------------------------------------------
fn createBoneChain arr width:1 height:1 constrainToHelpers:false stretchy:false = (
local boneArr = #()
for i = 2 to arr.count do (
-- check to see what type of values the array is using.
-- should be either point3 or some type of object.
local theClass = classOf arr[1]
-- get the two points to use as the beginning and end of the bone.
-- if the array is not made up of point3 values, use the object's position.
local p1 = if theClass == point3 then arr[i - 1] else arr[i - 1].transform.position
local p2 = if theClass == point3 then arr[i] else arr[i].transform.position
-- set some defaults for the bone's name.
local hlpName = if theClass == point3 then "Bone" else arr[i].name
-- make the bone using the "createNewBone" function
local bn = createNewBone p1 p2 width:width height:height name:hlpName stretchy:stretchy
-- change "HLP" to "BN" in the bone's name if needed
local n = findString bn.name "HLP"
if n != undefined then (bn.name = replace bn.name n 3 "BN")
-- add the position and look at constraints if constrainToHelpers is set to true
if constrainToHelpers then (addLookAt bn arr[i] upnode:arr[i])
if constrainToHelpers then (addPositionConstraint bn arr[i - 1])
-- add the new bone to the bone array
append boneArr bn
-- create nub
if i == arr.count then (
-- make the nub bone using the "createNewBone" function
local bnNub = createNewBone p2 (p2 + ((distance p1 p2) * .1)) width:(width * .25) height:(height * .25) name:(bn.name + "_nub")
in coordsys bn (bnNub.rotation = (quat 0 0 0 1))
bnNub.pos = p2
-- add the position constraint if constrainToHelpers is set to true.
-- no look at controller is needed because this bone at the end of the chain with nothing to look at.
if constrainToHelpers then (addPositionConstraint bnNub arr[i])
-- add the new bone to the bone array
append boneArr bnNub
)
)
-- link bones
for i = 2 to boneArr.count do (
boneArr[i].parent = boneArr[i - 1]
)
-- return the bone array
boneArr
)
/*----------------------------------------------------------------------------------------------------------------------------------------------
# Description : Returns an array of nodeTansformMonitor objects for created loose references to noded. If only one object is passed in instead
# of an array, one nodeTansformMonitor object is returned.
# Parameters : <array> arr : Array of nodes to reference.
# <bool> forwardTransformChangeMsgs : From the help file: "If true (default), node transform messages from the monitored node
# invalidate the dependents of the NodeTransformMonitor instance. If false, only deletion
# of the monitored node invalidates the dependents of the NodeTransformMonitor instance."
# Default: false
*/----------------------------------------------------------------------------------------------------------------------------------------------
fn getLooseReference arr forwardMessages:false = (
local tempArr = undefined
if classOf arr != array then tempArr = #(arr) else tempArr = arr
nodeArr = for obj in tempArr collect (
ntm = nodeTransformMonitor()
ntm.node = obj
ntm.forwardTransformChangeMsgs = forwardMessages
ntm
)
if nodeArr.count == 1 then return nodeArr[1]
else return nodeArr
) -- end getLooseReference
Here’s some compositing functions you guys might find useful if you ever have to do any straight composites with render passes. No comments because I’m an awful coder, just pass the functions two pixels (as color values) and an optional opacity value (as opacityV:<float>), and they’ll return the composite as a color value. The first three functions are necessary.
edit: Ok the code is fixed, opacityMod() definition was missing an argument.
fn cToV colorVal =
(
tempVal = colorVal as point3
return [(tempVal.x/255), (tempVal.y/255), (tempVal.z/255)]
)
fn vToC valueVal =
(
return [(valueVal.x*255 as integer), (valueVal.y*255 as integer), (valueVal.z*255 as integer)] as color
)
fn opacityMod pixelR pixelB opacityV =
(
pixelR.x = pixelB.x + (pixelR.x - pixelB.x)*opacityV
pixelR.y = pixelB.y + (pixelR.y - pixelB.y)*opacityV
pixelR.z = pixelB.z + (pixelR.z - pixelB.z)*opacityV
return pixelR
)
fn normalBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [pixelS.x, pixelS.y, pixelS.z]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn averageBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [(pixelB.x+pixelS.x)/2, (pixelB.y+pixelS.y)/2, (pixelB.z+pixelS.z)/2]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn multiplyBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [pixelB.x*pixelS.x, pixelB.y*pixelS.y, pixelB.z*pixelS.z]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn screenBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [pixelB.x+pixelS.x-pixelB.x*pixelS.x, pixelB.y+pixelS.y-pixelB.y*pixelS.y, pixelB.z+pixelS.z-pixelB.z*pixelS.z]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn darkenBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [0,0,0]
if pixelB.x > pixelS.x then pixelR.x = pixelS.x else pixelR.x = pixelB.x
if pixelB.y > pixelS.y then pixelR.y = pixelS.y else pixelR.y = pixelB.y
if pixelB.z > pixelS.z then pixelR.z = pixelS.z else pixelR.z = pixelB.z
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn lightenBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [0,0,0]
if pixelB.x < pixelS.x then pixelR.x = pixelS.x else pixelR.x = pixelB.x
if pixelB.y < pixelS.y then pixelR.y = pixelS.y else pixelR.y = pixelB.y
if pixelB.z < pixelS.z then pixelR.z = pixelS.z else pixelR.z = pixelB.z
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn differenceBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [abs (pixelB.x-pixelS.x), abs (pixelB.y-pixelS.y), abs (pixelB.z-pixelS.z)]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn negationBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [1-(abs (1-pixelB.x-pixelS.x)), 1-(abs (1-pixelB.y-pixelS.y)), 1-(abs (1-pixelB.z-pixelS.z))]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn exclusionBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [pixelB.x+pixelS.x-2*pixelB.x*pixelS.x, pixelB.y+pixelS.y-2*pixelB.y*pixelS.y, pixelB.z+pixelS.z-2*pixelB.z*pixelS.z]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn overlayBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [0,0,0]
if pixelB.x <= 0.5 then
(
pixelR.x = 2*pixelB.x*pixelS.x
)
else
(
pixelR.x = 1-2*(1-pixelB.x)*(1-pixelS.x)
)
if pixelB.y <= 0.5 then
(
pixelR.y = 2*pixelB.y*pixelS.y
)
else
(
pixelR.y = 1-2*(1-pixelB.y)*(1-pixelS.y)
)
if pixelB.z <= 0.5 then
(
pixelR.z = 2*pixelB.z*pixelS.z
)
else
(
pixelR.z = 1-2*(1-pixelB.z)*(1-pixelS.z)
)
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn hardLightBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [0,0,0]
if pixelS.x <= 0.5 then
(
pixelR.x = 2*pixelB.x*pixelS.x
)
else
(
pixelR.x = 1-2*(1-pixelB.x)*(1-pixelS.x)
)
if pixelS.y <= 0.5 then
(
pixelR.y = 2*pixelB.y*pixelS.y
)
else
(
pixelR.y = 1-2*(1-pixelB.y)*(1-pixelS.y)
)
if pixelS.z <= 0.5 then
(
pixelR.z = 2*pixelB.z*pixelS.z
)
else
(
pixelR.z = 1-2*(1-pixelB.z)*(1-pixelS.z)
)
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn softLightBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [2*pixelB.x*pixelS.x+(pow pixelB.x 2)-2*(pow pixelB.x 2)*pixelS.x, 2*pixelB.y*pixelS.y+(pow pixelB.y 2)-2*(pow pixelB.y 2)*pixelS.y, 2*pixelB.z*pixelS.z+(pow pixelB.z 2)-2*(pow pixelB.z 2)*pixelS.z]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn colorDodgeBlend pixelB pixelS opacityV: =
(
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [pixelB.x/(1-pixelS.x), pixelB.y/(1-pixelS.y), pixelB.z/(1-pixelS.z)]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
fn inverseDodgeBlend pixelB pixelS opacityV: =
[font=Lucida Console](
pixelB = cToV pixelB
pixelS = cToV pixelS
pixelR = [pixelS.x/(1-pixelB.x), pixelS.y/(1-pixelB.y), pixelS.z/(1-pixelB.z)]
if not opacityV == unsupplied then
return vToC (opacityMod pixelR pixelB opacityV)
else
return vToC pixelR
)
[/font]