Working out how to use Source Filmmaker takes time and involves plenty of small discoveries. Even if a use for these discoveries is not immediately obvious, it could come in handy later.

## GeneralEdit

- SFM disables sv_cheats each map load. If it is not re-enabled, the rendering dialogue can experience errors (such as a negative percentage) and produce invalid video files

## Dme Element EditorEdit

- You can shift the position of individual takes - eg. if you wanted a scout to get blown up by a rocket but mis-timed it, you don't necessarily have to re-record it
- Browse to "clipBin/sequence/subClipTrackGroup/tracks/Film/children/shot/scene/children/take*/transform", where take* is the relevant take. You can then edit the position to shift the recording
- Note that this affects everything in that take, including world objects like medpacks and doors. If you want to affect individual takes, expand take*/children, find the relevant model(s), then adjust their transform/position

- Some of the editor's settings are stored in the Dme Element Editor - this includes things like the position of the handles in the animation set editor and even the colour overlay when you start using the animation set editor

### Interpolation MethodsEdit

- The Dme Element Editor allows access to a feature that is not available in the GUI (as far as I can tell) - the interpolation method the Animation Set Editor uses. Usually it applies a linear interpolation within the handle's falloff area when using the sliders. However, there are other options available:
**Note:**Invalid options seem to default to Ease**Note:**Sometimes it refuses to change the interpolation method. Select another field and then try again**Note:**Directions (start and end) are written relative to the left interpolator. That is, "start" is farthest away from handle, "end" is closest- 0 - Steeper Ease
*(not sure the "real" name of this one)* - 1 - Variation on Ease
- 2 - Ease In
*(changes fastest at start, slowest at end)* - 3 - Ease Out
*(changes slowest at start, fastest at end)* - 4 - Ease
*(changes faster in the middle than at either end)* - 5 - Linear with offset
*(jerks slightly at start and end?)* - 6 - Linear
*(default)* - 7 - Several of these are slight variations on the Ease method
- 13 - Polynomial
*(basically, it creates a "bump" of the max value in between the start and end of the falloff area. Looks pretty glitchy, not to mention it causes overlap on the GUI)* - 14 - Much more dramatic Ease Out
- 15 - No interpolation
- 16 - Ease variation. This seems to be the last valid option

- To use any of these, just enter the valid number in settings/timeSelection/interpolator_left or settings/timeSelection/interpolator_right. While you're at it, you can also control the exact position and falloff size of the handles (times are in 10s of milliseconds. 10000 is 1 second)

### Expression field commandsEdit

- This is a list of known commands for expression fields, along with their arguments

- Note that if you enter an invalid expression, it evaluates up to the point of error. For example, the expression "1+sign(-)+4" equals 1, as it stopped evaluating when it encountered the missing argument

- Similarily, you must close all brackets correctly
- General Number-Work:
- round( val ) -
**Rounds to the nearest whole number***((val-val%1>=0.5) ? val%1+1 : val%1)* - ceiling( val ) -
**Rounds up** - floor( val ) -
**Rounds down** - sqrt( val ) -
**Returns the square root of the number** - sqr( val ) -
**Squares the number***(val*val)* - abs( val ) -
**Absolute function. Makes the number positive***((val>0) ? val : -val)* - pow( val, power ) -
**Raises val to a power** - exp( power ) -
**Raises e to a power**

- round( val ) -
- Trigonometry:
- rtod( val ) -
**Converts value from radians to degrees** - dtor( val ) -
**Converts value from degrees to radians** - sin, cos, tan( val ) -
**They all do what they say on the tin. Value must be in radians** - asin, acos( val ) -
**Take arcsine / arccosine of value** - atan2( y, x ) -
**Returns angle (in radians) from positive x axis to vector (x, y)**

- rtod( val ) -
- Logic:
**Note:**Unless otherwise stated, logic functions return 1 or 0 (true or false)- sign( val ) -
**Returns the sign of the number (1 or -1). 0 is considered positive***((val>=0) ? 1 : -1)* - max( val, val2 ) -
**Returns the larger of the two numbers***((val>val2) ? val : val2)* - min( val, val2 ) -
**Returns the smaller of the two numbers** - inrange( val, lo, hi ) -
**Returns 1 if value is larger than/equal to lo and smaller than/equal to hi. Note that lo should be smaller than hi***(val<hi && val>lo)*

- Scaling:
- lerp( val, lo, hi ) -
**Linearly interpolates a value from 0-1 to lo-hi. Note that it accepts any value, so -1 will return -hi***(lo+val*(hi-lo))* - clerp( val, lo, hi ) -
**Clamps val from 0-1 before linearly interpolating***(lerp(clamp(val,0,1),lo,hi))* - ramp( val, lo, hi ) -
**Returns the "position" between lo and hi that val is, scaled to 0-1. Note that if val is not within the range you may get #INF as a result***((val-lo)/(hi-lo))* - cramp( val, lo, hi ) -
**Clamps val from lo-hi before determining its "position" using ramp***(ramp(clamp(val,lo,hi),lo,hi))* - clamp (val, lo, hi) -
**Clamps the value to the range lo-hi. Note that lo should be smaller than hi***((val>hi) ? hi : ((val<min) ? min : val))* - rescale( val, lo, hi, newlo, newhi ) -
**Scales a value from one range to another. Note that order is very important***((val-lo)/(hi-lo)*(newhi-newlo)+newlo)* - crescale( val, lo, hi, newlo, newhi ) -
**Clamps the value before rescaling it***(rescale(clamp(val,lo,hi),lo,hi,newlo,newhi))*

- lerp( val, lo, hi ) -
- Unknown:
- elerp( val, lo, hi ) -
**I'd expect this to be exponential interpolation, but I've seen no difference from lerp within val range 0-1 and it's gone weird outside of that. lo and hi cannot be 0***(lo*pow(hi/lo,val))*

- elerp( val, lo, hi ) -
- Not Tested:
- noise
- modf
- ceil
- atan
- exp10
- log10

- General Number-Work: