Feedback

Please leave feedback and comments. I am always interested to hear how people get on using these LScripts!

Thursday 28 March 2013

Free Stuff - Tin Cans (Object)


Free objects for LightWave : Various high quality sub-division modeled tin cans (10).

Compatible with Newtek LightWave 9.6 and above.

Download - zipped object (.zip)

Tuesday 26 March 2013

LScript - Image_Alpha

LScript (Layout) to create compressed video artifact effect.

Compatible with Newtek LightWave 9.6 and above.

// LScript Image Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Image Filter - Alpha

    Image_Alpha.ls

*/

@version 2.5
@warnings
@script image
@name *Alpha

    // Title
    sTitle = "*Alpha";

    // Version
    sVersion = "v1.0";

    aType = @"Solid","Luma","Luma (Invert)"@;
    iType = 1;

create
{
    setdesc(sTitle + " - " + aType[iType]);
}

process: ifo
{

    if(iType == 1) // Solid
      {

      iProgress = ifo.height;
      if(runningUnder() != SCREAMERNET) moninit(iProgress);
      for(i = 1;i <= ifo.height;++i)
        {
        for(j = 1;j <= ifo.width;++j)
          {
          ifo.alpha[j,i] = 1.0;
          }
        if(runningUnder() != SCREAMERNET) if(monstep()) return;
        }

      }

    if(iType == 2) // Luma
      {

      iProgress = ifo.height;
      if(runningUnder() != SCREAMERNET) moninit(iProgress);
      for(i = 1;i <= ifo.height;++i)
        {
        for(j = 1;j <= ifo.width;++j)
          {
          ifo.alpha[j,i] = clip(0.0,1.0,(ifo.red[j,i] + ifo.green[j,i] + ifo.blue[j,i]) * (1 / 3));
          }
        if(runningUnder() != SCREAMERNET) if(monstep()) return;
        }

      }

    if(iType == 3) // Luma (Invert)
      {

      iProgress = ifo.height;
      if(runningUnder() != SCREAMERNET) moninit(iProgress);
      for(i = 1;i <= ifo.height;++i)
        {
        for(j = 1;j <= ifo.width;++j)
          {
          ifo.alpha[j,i] = clip(0.0,1.0,1.0 - ((ifo.red[j,i] + ifo.green[j,i] + ifo.blue[j,i]) * (1 / 3)));
          }
        if(runningUnder() != SCREAMERNET) if(monstep()) return;
        }

      }

}

// CLIP

clip: min,max,n
{
    if(n < min) n = min;
    if(n > max) n = max;
    return(n);
}

load: what,io
{
    if(what == SCENEMODE)
    {
        iType = io.read().asInt();

        setdesc(sTitle + " - " + aType[iType]);
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
        io.writeln(iType);
    }
}

options
{
    reqbegin(sTitle + " " + sVersion);


    // Control
    ctrl_c0 = ctlchoice("Type",iType,@"Solid","Luma","Luma Invert"@); // Type

    // Developer
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    return if !reqpost();

    iType = getvalue(ctrl_c0);

    setdesc(sTitle + " - " + aType[iType]);

    reqend();
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

Friday 15 March 2013

LScript - Image_Pixelate

LScript (Layout) to create a pixelated effect with envelope control.

Changes
  • Override alpha

Compatible with Newtek LightWave 9.6 and above.

// LScript Image Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Image Filter - Pixelate

    Image_Pixelate.ls

*/

@version 2.5
@warnings
@script image
@name *Pixelate

    // Title
    sTitle = "*Pixelate";

    // Version
    sVersion = "v1.0";

    // Envelope
    envSize; // Size

    // Control
    ctrl_c0;

create
{
    setdesc(sTitle);

    // Envelope
    envSize = Envelope("Size (" + sTitle + ")",CHAN_NUMBER,sTitle); // Size
    envSize.persist(false);
    envSize.createKey(0,20.0);
}

process: ifo
{
    // Variable
    iSize = ceil(envSize.value(Scene().currenttime));

    // Error
    if(iSize < 2){return;}
    if(ifo.width < 1 || ifo.height < 1){return;}

    iGridX = ceil(ifo.width / iSize);
    iGridY = ceil(ifo.height / iSize);

    iGridXOffset = abs((ifo.width - (iGridX * iSize)) * 0.5);
    iGridYOffset = abs((ifo.height - (iGridY * iSize)) * 0.5);

    iProgress = iGridX * iGridY;
    if(runningUnder() != SCREAMERNET) moninit(iProgress);

    for(y = 0;y <= iGridY - 1; ++y)
      {

      for(x = 0;x <= iGridX - 1; ++x)
        {
        v1 = ;
        v2 = ;

        // Draw 
        pixelateIFO(ifo,v1,v2);

        if(runningUnder() != SCREAMERNET) if(monstep()) return;
        }      
      }
  
}

pixelateIFO: ifo,v1,v2 // vector,red,green,blue
{
    // Order
    if(v1.x > v2.x){n = v2.x;v2.x = v1.x; v1.x = n;}
    if(v1.y > v2.y){n = v2.y;v2.y = v1.y; v1.y = n;}

    if(v1.x < 1 || v2.x > ifo.width ||
       v1.y < 1 || v2.y > ifo.height)
      {
      // Offscreen
      if(v2.x < 1){return;}
      if(v1.x > ifo.width){return;}
      if(v2.y < 1){return;}
      if(v1.y > ifo.width){return;}
  
      // Clip
      if(v1.x < 1){v1.x = 1;}
      if(v1.x > ifo.width){v1.x = ifo.width;}
      if(v1.y < 1){v1.y = 1;}
      if(v1.y > ifo.height){v1.y = ifo.height;}
      if(v2.x < 1){v2.x = 1;}
      if(v2.x > ifo.width){v2.x = ifo.width;}
      if(v2.y < 1){v2.y = 1;}
      if(v2.y > ifo.height){v2.y = ifo.height;}
      }

    r = 0;
    g = 0;
    b = 0;
    c = 0;
    
    // Average
    for(y = v1.y; y <= v2.y; ++y)
      {
      for(x = v1.x; x <= v2.x; ++x)
        {
        r += ifo.red[x,y];
        g += ifo.green[x,y];
        b += ifo.blue[x,y];
        ++c;
        }
      }

    if(c > 1)
      {
      r *= 1 / c;
      g *= 1 / c;
      b *= 1 / c;
      }

    // Draw
    for(y = v1.y; y <= v2.y; ++y)
      {
      for(x = v1.x; x <= v2.x; ++x)
        {
        ifo.red[x,y] = r;
        ifo.green[x,y] = g;
        ifo.blue[x,y] = b;
        ifo.alpha[x,y] = 1.0;
        }
      }
}

load: what,io
{
    if(what == SCENEMODE)   // processing an ASCII scene file
    {
        if(io.read().asStr() == sTitle + " " + sVersion)
            {
            // Envelope
            envSize.load(); // Size
            }
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {    
        // Header
        io.writeln(sTitle + " " + sVersion);

        // Envelope
        envSize.save(); // Size
    }
}

options
{
    if(reqisopen())
        {
        reqend();
        return;
        }

    reqbegin(sTitle + " " + sVersion);

    ctrl_c0 = ctlpercent("Size",envSize.value(Scene().currenttime) * 0.01); // Size
    ctrl_c1e = ctlbutton("E",20,"button_c1e"); // Button

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    // Refresh
    ctlrefresh(ctrl_c0,"refresh_c0"); // Size

    reqopen();
}

button_c1e // Size
{
    envSize.edit();
}

refresh_c0:value // Size
{
    setvalue(ctrl_c0,max(0.0,value));
    iKey = envSize.keyExists(Scene().currenttime);
    if(iKey == nil)
        {envSize.createKey(Scene().currenttime,max(0.0,value * 100));}
    else
        {envSize.setKeyValue(iKey,max(0.0,value * 100));}
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

Monday 11 March 2013

LScript - Image_DigitalArtifacts

LScript (Layout) to create compressed video artifact effect.

Compatible with Newtek LightWave 9.6 and above.

// LScript Image Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Image Filter - Digital Artifacts

    Image_DigitalArtifacts.ls

*/

@version 2.5
@warnings
@script image
@name *Digital Artifacts

    // Title
    sTitle = "*Digital Artifacts";

    // Version
    sVersion = "v1.0";

    iBlockSize = 8;
    iLifeRed = 2;
    iLifeGreen = 2;
    iLifeBlue = 2;
    nErrorRed = 0.03;
    nErrorGreen = 0.03;
    nErrorBlue = 0.03;
    bColorSync = false;

    aBlock = nil; // Block

    // Control
    ctrl_pr0,ctrl_c0,ctrl_c1,ctrl_c2,ctrl_c3,ctrl_c4,ctrl_c5,ctrl_c6,ctrl_c7; 

create
{
    setdesc(sTitle);
}

process: ifo
{

    // Error
    if(ifo.width < 1 || ifo.height < 1){return;}

    // Variable

    iBlock = 1;
    iBlockMultiplier = 1 / (iBlockSize * iBlockSize);
    iGridX = floor(ifo.width / iBlockSize);
    iGridY = floor(ifo.height / iBlockSize);
    _nErrorRed = nErrorRed * (iBlockSize * iBlockSize);
    _nErrorGreen = nErrorGreen * (iBlockSize * iBlockSize);
    _nErrorBlue = nErrorBlue * (iBlockSize * iBlockSize);

    // Init Block
    if(aBlock.size() <> (iGridX * iGridY) || ifo.frame == 0)
      {
      for(b = 1; b <= (iGridX * iGridY); ++b)
        {
        aBlock[b,1] = 0; // Red Count 
        aBlock[b,2] = 0; // Green Count 
        aBlock[b,3] = 0; // Blue Count 
        aBlock[b,4] = 0.0; // Red
        aBlock[b,5] = 0.0; // Green
        aBlock[b,6] = 0.0; // Blue
        } 
      }   

    iProgress = iGridX * iGridY;
    if(runningUnder() != SCREAMERNET) moninit(iProgress);

    for(gy = 0;gy <= iGridY - 1; ++gy)
      {

      for(gx = 0;gx <= iGridX - 1; ++gx)
        {
 
        _gx = gx * iBlockSize; 
        _gy = gy * iBlockSize; 

        r = 0;
        g = 0;
        b = 0;

        // Average
        for(i = 1;i <= iBlockSize; ++i)
          {
          for(j = 1;j <= iBlockSize; ++j)
            {
            r += ifo.red[j + _gx,i + _gy]; // Red
            g += ifo.green[j + _gx,i + _gy]; // Green
            b += ifo.blue[j + _gx,i + _gy]; // Blue
            }
          }

        r *= iBlockMultiplier;
        g *= iBlockMultiplier;
        b *= iBlockMultiplier;

        // Difference 
        rd = 0;
        gd = 0;
        bd = 0;

        for(i = 1;i <= iBlockSize; ++i)
          {
          for(j = 1;j <= iBlockSize; ++j)
            {
            rd += abs(ifo.red[j + _gx,i + _gy] - r);
            gd += abs(ifo.green[j + _gx,i + _gy] - g);
            bd += abs(ifo.blue[j + _gx,i + _gy] - b);
            }
          }

        // Update Block
        if(bColorSync)
          { 
          if((aBlock[iBlock,1] <= 0 && rd < _nErrorRed) || 
             (aBlock[iBlock,2] <= 0 && gd < _nErrorGreen) || 
             (aBlock[iBlock,3] <= 0 && bd < _nErrorBlue)) 
            {
            c = random(1,3);
            aBlock[iBlock,1] = c;
            aBlock[iBlock,2] = c;
            aBlock[iBlock,3] = c;
            }
          aBlock[iBlock,4] = r;
         aBlock[iBlock,5] = g;
         aBlock[iBlock,6] = b;
         }
       else
         {
         if(aBlock[iBlock,1] <= 0 && rd < _nErrorRed) // Red
           {
           aBlock[iBlock,1] = random(1,iLifeRed);
           aBlock[iBlock,4] = r;
           }

         if(aBlock[iBlock,2] <= 0 && gd < _nErrorGreen) // Green
           {
           aBlock[iBlock,2] = random(1,iLifeGreen);
           aBlock[iBlock,5] = g;
           }

         if(aBlock[iBlock,3] <= 0 && bd < _nErrorBlue) // Blue
           {
           aBlock[iBlock,3] = random(1,iLifeBlue);
           aBlock[iBlock,6] = b;
           }
         }
        
        // Read Block
        rd = aBlock[iBlock,1];
        --aBlock[iBlock,1];
        r =  aBlock[iBlock,4];
        gd = aBlock[iBlock,2];
        --aBlock[iBlock,2];
        g =  aBlock[iBlock,5];
        bd = aBlock[iBlock,3];
        --aBlock[iBlock,3];
        b =  aBlock[iBlock,6];

        // Draw Block
        for(i = 1;i <= iBlockSize; ++i)
          {
          for(j = 1;j <= iBlockSize; ++j)
            {
            if(rd > 0){ifo.red[j + _gx,i + _gy] = r;}
            if(gd > 0){ifo.green[j + _gx,i + _gy] = g;}
            if(bd > 0){ifo.blue[j + _gx,i + _gy] = b;}
            }
          }

        ++iBlock;

        if(runningUnder() != SCREAMERNET) if(monstep()) return;
        }      
      }
  
}

// CLIP

clip: min,max,n
{
    if(n < min) n = min;
    if(n > max) n = max;
    return(n);
}

load: what,io
{
    if(what == SCENEMODE)
    {
        bColorSync = io.read().asInt();
        iBlockSize = io.read().asInt();
        iLifeRed = io.read().asInt();
        iLifeGreen = io.read().asInt();
        iLifeBlue = io.read().asInt();
        nErrorRed = io.read().asNum();
        nErrorGreen = io.read().asNum();
        nErrorBlue = io.read().asNum();
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
        io.writeln(bColorSync);                
        io.writeln(iBlockSize);         
        io.writeln(iLifeRed);  
        io.writeln(iLifeGreen);
        io.writeln(iLifeBlue);        
        io.writeln(nErrorRed);         
        io.writeln(nErrorGreen);         
        io.writeln(nErrorBlue);         
    }
}

options
{
    reqbegin(sTitle + " " + sVersion);

    // Control
    ctrl_pr0 = ctlpopup("Preset",1, @"Low",
                                     "Medium",
                                     "High",
                                     "Extreme"@);

    ctlsep();
    ctrl_c0 = ctlinteger("Block Size",iBlockSize);
    ctrl_c1 = ctlcheckbox("Color Sync",bColorSync);
    ctrl_c2 = ctlinteger("Life Red",iLifeRed);
    ctrl_c3 = ctlinteger("     Green",iLifeGreen);
    ctrl_c4 = ctlinteger("     Blue",iLifeBlue);
    ctrl_c5 = ctlpercent("Error Red",nErrorRed);
    ctrl_c6 = ctlpercent("      Green",nErrorGreen);
    ctrl_c7 = ctlpercent("      Blue",nErrorBlue);

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    // Refresh
    ctlrefresh(ctrl_pr0,"refresh_preset"); // Preset
    ctlrefresh(ctrl_c0,"refresh_c0"); // Block Size
    ctlrefresh(ctrl_c2,"refresh_c2"); // Life Red
    ctlrefresh(ctrl_c3,"refresh_c3"); // Life Green
    ctlrefresh(ctrl_c4,"refresh_c4"); // Life Blue

    ctlrefresh(ctrl_c5,"refresh_c5"); // Error Red
    ctlrefresh(ctrl_c6,"refresh_c6"); // Error Green
    ctlrefresh(ctrl_c7,"refresh_c7"); // Error Blue

    return if !reqpost();

    iBlockSize = max(1,getvalue(ctrl_c0));
    bColorSync = getvalue(ctrl_c1);
    iLifeRed = max(1,getvalue(ctrl_c2));
    iLifeGreen = max(1,getvalue(ctrl_c3));
    iLifeBlue = max(1,getvalue(ctrl_c4));
    iErroRed = max(0.0,getvalue(ctrl_c5));
    iErrorGreen = max(0.0,getvalue(ctrl_c6));
    iErrorBlue = max(0.0,getvalue(ctrl_c7));

    reqend();
}

refresh_preset:value
{
    if(value == 1) // Low
      {
      setvalue(ctrl_c0,8); // Block Size
      setvalue(ctrl_c1,0); // Sync Color
      setvalue(ctrl_c2,1); // Life Red
      setvalue(ctrl_c3,1); // Life Green
      setvalue(ctrl_c4,1); // Life Blue
      setvalue(ctrl_c5,0.02); // Error Red
      setvalue(ctrl_c6,0.02); // Error Green
      setvalue(ctrl_c7,0.02); // Error Blue
      }  

    if(value == 2) // Medium
      {
      setvalue(ctrl_c0,8); // Block Size
      setvalue(ctrl_c1,0); // Sync Color
      setvalue(ctrl_c2,2); // Life Red
      setvalue(ctrl_c3,2); // Life Green
      setvalue(ctrl_c4,2); // Life Blue
      setvalue(ctrl_c5,0.02); // Error Red
      setvalue(ctrl_c6,0.03); // Error Green
      setvalue(ctrl_c7,0.04); // Error Blue
      } 

    if(value == 3) // High
      {
      setvalue(ctrl_c0,8); // Block Size
      setvalue(ctrl_c1,0); // Sync Color
      setvalue(ctrl_c2,3); // Life Red
      setvalue(ctrl_c3,3); // Life Green
      setvalue(ctrl_c4,3); // Life Blue
      setvalue(ctrl_c5,0.02); // Error Red
      setvalue(ctrl_c6,0.04); // Error Green
      setvalue(ctrl_c7,0.06); // Error Blue
      }

    if(value == 4) // Extreme
      {
      setvalue(ctrl_c0,8); // Block Size
      setvalue(ctrl_c1,0); // Sync Color
      setvalue(ctrl_c2,9); // Life Red
      setvalue(ctrl_c3,9); // Life Green
      setvalue(ctrl_c4,9); // Life Blue
      setvalue(ctrl_c5,0.1); // Error Red
      setvalue(ctrl_c6,0.1); // Error Green
      setvalue(ctrl_c7,0.1); // Error Blue
      }
}

refresh_c0:value // Block Size
{
    iBlockSize = max(1,value);
    setvalue(ctrl_c0,iBlockSize);
}

refresh_c2:value // Life Red
{
    iLifeRed = max(1,value);
    setvalue(ctrl_c2,iLifeRed);
}

refresh_c3:value // Life Green
{
    iLifeGreen = max(1,value);
    setvalue(ctrl_c3,iLifeGreen);
}

refresh_c4:value // Life Blue
{
    iLifeBlue = max(1,value);
    setvalue(ctrl_c4,iLifeBlue);
}

refresh_c5:value // Error Red
{
    nErrorRed = clip(0.0,1.0,value);
    setvalue(ctrl_c5,nErrorRed);
}

refresh_c6:value // Error Green
{
    nErrorGreen = clip(0.0,1.0,value);
    setvalue(ctrl_c6,nErrorGreen);
}

refresh_c7:value // Error Blue
{
    nErrorBlue = clip(0.0,1.0,value);
    setvalue(ctrl_c7,nErrorBlue);
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

Monday 4 March 2013

LScript - Image_DepthDesaturation


LScript (Layout) desaturates the image based on depth buffer.

Compatible with Newtek LightWave 9.6 and above.

// LScript Image Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Image Filter - Depth Desaturate

    Image_DepthDesaturate.ls

*/

@version 2.5
@warnings
@script image
@name *Depth Desaturate

    // Title
    sTitle = "*Depth Desaturate";

    // Version
    sVersion = "v1.0";

    nAmount = 1.0;  
    nMin = 1.0;
    nMax = 10.0;

    // Control
    ctrl_c0;  

create
{
    setdesc(sTitle);
}

process: ifo
{
    iProgress = ifo.height;
    if(runningUnder() != SCREAMERNET) moninit(iProgress);
    for(i = 1;i <= ifo.height;++i)
      {
      for(j = 1;j <= ifo.width;++j)
        {
        nAverage = (ifo.red[j,i] + ifo.green[j,i] + ifo.blue[j,i]) * 0.3333333333;
        nDepth = clip(0.0,1.0,maprange01(nMin,nMax,ifo.depth[j,i]));        
        ifo.red[j,i] = ifo.red[j,i] - (nAmount * nDepth) * (ifo.red[j,i] - nAverage);
        ifo.green[j,i] = ifo.green[j,i] - (nAmount * nDepth) * (ifo.green[j,i] - nAverage);
        ifo.blue[j,i] = ifo.blue[j,i] - (nAmount * nDepth) * (ifo.blue[j,i] - nAverage);
        }
      if(runningUnder() != SCREAMERNET) if(monstep()) return;
      }
}

// CLIP

clip: min,max,n
{
    if(n < min) n = min;
    if(n > max) n = max;
    return(n);
}

// MAP RANGE

maprange01: n1,n2,i
{    
    if(n2-n1 == 0.0){return(0.0);}
  else
    {return((1/(n2-n1)) * (i-n1));}
}

load: what,io
{
    if(what == SCENEMODE)
    {
        nAmount = io.read().asNum();
        nMin = io.read().asNum();
        nMax = io.read().asNum();
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
        io.writeln(nAmount);         
        io.writeln(nMin);         
        io.writeln(nMax);         
    }
}


options
{
    reqbegin(sTitle + " " + sVersion);

    // Control
    ctrl_c0 = ctlpercent("Amount",nAmount);
    ctrl_c1 = ctlnumber("Min (m)",nMin);
    ctrl_c2 = ctlnumber("Max (m)",nMax);

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    // Refresh
    ctlrefresh(ctrl_c0,"refresh_c0"); // Amount

    return if !reqpost();

    nAmount = clip(0.0,1.0,getvalue(ctrl_c0));
    nMin = getvalue(ctrl_c1);
    nMax = getvalue(ctrl_c2);

    reqend();
}

refresh_c0:value // Amount
{
    nAmount = clip(0.0,1.0,value);
    setvalue(ctrl_c0,nAmount);
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

LScript - Image_Depth


LScript (Layout) to create a grey scale representation of the depth buffer.

Compatible with Newtek LightWave 9.6 and above.

// LScript Image Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Image Filter - Depth

    Image_Depth.ls

*/

@version 2.5
@warnings
@script image
@name *Depth

    // Title
    sTitle = "*Depth";

    // Version
    sVersion = "v1.0";

    nMin = 0.0;
    nMax = 10.0;

create
{
    setdesc(sTitle);
}

process: ifo
{
    iProgress = ifo.height;
    if(runningUnder() != SCREAMERNET) moninit(iProgress);
    for(i = 1;i <= ifo.height;++i)
      {
      for(j = 1;j <= ifo.width;++j)
        {
        nDepth = 1 - clip(0.0,1.0,maprange01(nMin,nMax,ifo.depth[j,i]));        
        ifo.red[j,i] = nDepth;
        ifo.green[j,i] = nDepth;
        ifo.blue[j,i] = nDepth;
        }
      if(runningUnder() != SCREAMERNET) if(monstep()) return;
      }
}

// CLIP

clip: min,max,n
{
    if(n < min) n = min;
    if(n > max) n = max;
    return(n);
}

// MAP RANGE

maprange01: n1,n2,i
{    
    if(n2-n1 == 0.0){return(0.0);}
  else
    {return((1/(n2-n1)) * (i-n1));}
}

load: what,io
{
    if(what == SCENEMODE)
    {
        nMin = io.read().asNum();
        nMax = io.read().asNum();
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
        io.writeln(nMin);         
        io.writeln(nMax);         
    }
}

options
{
    reqbegin(sTitle + " " + sVersion);

    // Control
    ctrl_c0 = ctlnumber("Min (m)",nMin);
    ctrl_c1 = ctlnumber("Max (m)",nMax);

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    return if !reqpost();

    nMin = getvalue(ctrl_c0);
    nMax = getvalue(ctrl_c1);

    reqend();
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs