Programming Page

[last updated 19th Oct 2006]

Disclaimer : far from being a comprehensive manual, this page contains only the tips and hints that I find useful to be able to look up quickly on my web site




1. C/C++

1.1 Pointers to member functions

The syntax is as follows:

// Define a typedef called pf3 that improves readability later on. Assume CBase has a public
// member function called Func_NotInherited(int&, unsigned char) that returns an unsigned long

typedef unsigned long (CBase::*pf3)( int &, unsigned char);

// If you have to explicitly state the calling convention, you do it thus
typedef unsigned long (__cdecl CBase::*pf4)(int&, unsigned char);

void func()
{
CBase Base;// This is just for convenience, it's the pointer we actually want
CBase* pBase = &Base;
int i=8;
unsigned char a = 32;

// Define a variable called pFNI of type pf3 that points to a member function of the class
// CBase. Note our function pointer "pFNI" is only an offset into the classes V-table that
// is useless until we tell it which instance to actually dereference.

pf3 pFNI = &CBase::Func_NotInherited;

// Now tell our variable which instance of CBase it's to (de)reference when we call
// MyFunc_NotInherited

unsigned long res = (pBase->*pFNI)(i,a);
}

1.2 Static memory initialization

Initialize static memory at function scope to avoid undefined behaviour

when initializing static memory, the C++ standard tells us to do so at file scope like this

EIGENSTRUCT* MyClass::m_eigenstructures = 0;

but the order and moment in which these static members are initialized is not standardized and can be down to compiler choice / platform / whats in memory and other hideous unpredictable reasons however the standard is very clear about static initialization at function scope. Instead use the singleton pattern to initialize static variables (particularly where additional memory is allocated) like so;

constEIGENSTRUCT * getEigenValuesTable()
{
    staticEIGENSTRUCT* MyClass::m_eigenstructures = 0;
    if (!MyClass::m_eigenstructures) {
           // allocate memory and assign to / initialize m_eigenstructures here
    }
    return MyClass::m_eigenstructures;
}

Disclaimer: if I got any of the syntax wrong, its cause I didn't check it before it got posted. See the C++ FAQ Lite for the correct syntax

1.3 Symbol Table Utility (Linux)

Using the nm / ldd utilities

To debug Link errors use nm (and ldd)

nm -A -C dof.so | grep globalThreadCount

Is useful to track the source of an error message related to a mangled sym table name, eg.

D02001 {WARNING} TgPathDLOpen: Bad DSO found: dof.so (undefined symbol: _ZN3Imf17globalThreadCountEv)

and this;

man nm

will give the manual page

1.4 Threads on Linux

How to add threading to your c++ app

You need to link with CPPFLAGS -pthread before the include paths and LDLIBS -lpthread in your libs
Include this from the cpp file

#include< pthread.h>

The things to look up when searching for docs are;

struct pthread_attr_t
   pthread_create
   pthread_join

coming next ... interthread communication using kernel objects.


2. TCL

2.1 Syntax for function definition

## TCL comments are denoted by lines starting with '##'
## The syntax is as follows: proc myprocedure { myparam1 myparam2 .. } {

.
if { [$myparam1] == [$myparam2] } {

    ## Jumping ahead slightly to the IF statement, here is an example
    ## of how to use the paramaters passed in to 'myprocedure'
    ## Note that the open braces MUST be on the same line as the 'if' keyword
}
.
.

}
## Note that the paramaters are simply delimited by spaces, and have
## no qualifying type information as TCL is a weakly typed language


2.2 'For' loops

## The 'foreach' keyword syntax is very different for anyone used to C/C++
## Effectively property is the variable whose value changes with each iteration
## the result of the expression inside [ ] is an array and property is assigned
## the next element with each iteration

foreach property [$parent_app GetProperties -access * -type * -name *] {
## The 'foreach' keyword also defines the variable immediately following it
## in this case 'property'. This can then be used inside the loop with a $
## Each time the loop executes, '$property' will contain a new value

if { [$property GetConnection] == [$child_app GetID] } {

    ## Here GetConnection is a function of $property's class, and is being called
    ## because it is inside the evaluate expression operator, square brackets '[]'

    $property SetConnection [$newchild_app GetID]
}
}

3. Shaders

3.1 'Church Hall' Image-Based Volumetric Light Shader


.slim



.sl

This shader uses an arbitrary image as it's basis. In Maya you'd set up an MTOR coordinate system and a poly cube to represent the volume in which the effect will be rendered. The coordsys acts as the origin and orientation of the effect, so it should be placed flush up against one of the faces of the cube. The average of the RGB at each pixel is used as an initial length to create a beam of the same colour eminating into the volume from the corresponding position on the image plane. The image will appear within the coordsys, so it can be scaled and positioned to get the effect you want. Bear in mind that only the beams that intersect the cube will be rendered.



4. Slim Templates

Some quick rules for slim's template syntax:

  1. when you give a default value there has to be enclosing curly braces '{ }' for vectors and NONE for scalars
  2. The order of the paramaters blocks in the slim template (i.e. paramater { .... } ) has to be the same as the order of the paramaters in the actual RSLBody bit.
  3. 'collection type nm' : When the params in the collection are arbitrary, make 'type' the same string as 'nm' (short for 'name') ...e.g. 'collection MyName MyName {'
  4. there's no need to put "subtype vslider" for vectors.
  5. Texture map path names : use the string 'subtype texture' to get the browse and convert buttons added to a string box.

4.1 The "ColorToVector" adapter

An network showing an example use : a face image coming out of procedural noise

This slim template allows you to hook up nodes which output a colour, to a vector connection, which is otherwise not possible. It allows scale and bias of the colour, clamping upper and lower limits and normalization. The template demonstrates how to use collections amongst other things.

4.2 Polar coordinates manifold

This slim template allows you to make Euler coordinates into Polar coordinates.


5. Slim Script

5.1 TraceNames Script

I have written a well useful script for Slim that allows you to find rogue nodes that still exist but have dissapeared from every one of the Palette windows. This can be especially useful for finding and deleting rogue custom templates that have errors.

## Author : Dan Evans
## Purpose : Util to associate internal ID names with human readable names of shader nodes in Slim
## Date : Last updated 2nd February 2004
## Version : 1.0

proc tracenames {} {

        set TotalAppearances 0

        foreach Counter [slim GetAppearances] {
                incr TotalAppearances 1
        }

        set NumAppearances $TotalAppearances

        foreach appearance2 [slim GetAppearances] {

                ::RAT::LogMsg INFO "$appearance2 = [$appearance2 GetName]"
        }
}

5.2 Shader Network Batch Flatten Script

I have written a useful script for Pixar's Renderman Shader network tool, 'Slim', which batch flattens all shaders. This is run from the slim console window which is under the Renderman > Slim menu in Maya.



6. MEL

6.1 Truncate float to x decimal places

// x > = 1 : Truncates floats down to x decimal places
// x < 1 : returns the input $value unchanged

global proc float truncate( float $value, int $decimal_places ) {

if ( $decimal_places < 1 )
{
    return $value;
}

float $dp = pow( 10.0, abs($decimal_places) );

return trunc($value) + (trunc($dp * ($value - trunc($value))) / $dp);
}


6.2 Remove the "shape" part from $OBJNAME to give access to the parent transform node

// Purpose : String substitution to work around the problem of the attribute being in the
//         : transform, but $OBJPATH and $OBJNAME in Slim referring to the Shape
//         : which cannot have string attributes added to it.
//         : where "texture" needs to be renamed to whatever the Maya attribute
//         : is named (case sensitive)
//         : Usage is
// [mel "getAttr [mel "RemoveShape $OBJPATH $OBJNAME"].texture"]

global proc string RemoveShape(string $controlpath, string $controlname) {

string $result;

// $controlname is "string being substituted",
// $controlpath is "string to search in", and
// "" is the "new substitute string"

$result = `substitute $controlname $controlpath ""`;

return $result;

};

6.3 Extract face index from selected face string

// -fl means "flatten", and gives pShape5.f[1] pShape5.f[2] pShape5.f[3]
// instead of pShape5.f[1:3] when poly faces are selected

string $sel[] = `ls -sl -fl`;
string $objName = `match "[^.]+" $sel[0]`; // find everything before the dot in the DAG path to the face

// when extracting face index '3' from 'pShape5.f[3]', match the number inclusive of square backets
// first (because the DAG path may have numbers in it you don't want to match, like the '5')
// then from that string, extract the number on its own

string $res = `match "\[[0-9]+\]" $cursel`;
$res = `match "[0-9]+" $res`;

6.4 Make a NURBS curve along an objects' animated path

// Select the object with the animation keys on its translate X,Y,Z then 
// call this script with the frame range you want the curve for, e.g.
// de_makeCurveOnTranslateKeys(10, 256);

global proc string de_makeCurveOnTranslateKeys(int $start, int $end)
{
	string $sel[] = `ls -sl`;
	string $cmd = "curve -d 3 ";
	string $k = " -k 0 ";
	int $i = -2;
	int $j=$start;
	for ( $j=$start; $j<($end+1); $j+=1 )
	{
		float $pos[] = `keyframe -at t -t $j -q -eval $sel[0]`;
		$cmd += ( "-p "+$pos[0]+" "+$pos[1]+" "+$pos[2]+" " );
		if( $i > ($end-$start-3) )
		{
			$k += (" -k "+$i);
		}
		else
		{
			$i+=1;
			if( $i < 1 )
				$k += (" -k 0");
			else
				$k += (" -k "+$i);
		}
	}
	if ( $i == 0 )
		$i = 1;
	$k += (" -k "+$i);
	$cmd += $k;
	print( $cmd + "\n" );
	string $newcurve = eval($cmd);
	return $newcurve;
}


7. Perl

7.1 "ver.pl" : Extract Version Number

#! /usr/bin/perl
# takes a file name with a version number as input, and
# increments the version number then makes a copy with the new version

use Cwd;
use File::Copy cp;

# get the command line arg
my $input=$ARGV[0];

# pick out the version number, put in vnum
$vnum = $input;
$vnum =~ /(.*)([0-9]{4})\.(.*)/;
$vnum = $2;

print "$vnum\n";

7.2 "incr.pl" : Copy File & Increment Version Number


#! /usr/bin/perl

# takes a file name with a version number as input, and 
# increments the version number then makes a copy with the new version

use Cwd;
use File::Copy cp;

# get the command line arg
my $input=$ARGV[0];

# trim off the ./ from the start that the find command returns
$input =~ /(\.\/)(.*)/;
$input = $2;

# pick out the version number, put in vnum
$vnum = $input;
$vnum =~ /(.*)([0-9]{2})(.*)/;

# increment version number, and pad with zeros if necessary
$ver = $2 + 1;
if ($ver<10) {
	$ver = "0$ver";
}

# rebuild incremented name
$outname = "$1$ver$3";

# these both do the same thing
#my $currdir = getcwd;
my $currdir = $ENV{PWD};

$src = "$currdir/$input";
$dst = "$currdir/$outname";
cp($src, $dst);
print "copied $input to $outname\n";
					


8. Python

8.1 "normalize.py" : Shake Script to Normalize a Depth Sequence


#! /usr/bin/env python

import sys
import os
import re
import string
import tempfile

fullPath  = ""
rangePath = ""
tmpPath   = ""
srcPath	  = ""
srcFile   = ""

if (len(sys.argv)==3):
	fullPath  = sys.argv[1]
	rangePath = sys.argv[2]
	tmpPath   = tempfile.gettempdir() + "/"

resize  = " -resize 1 1"
stat    = " -stat width height 4 1 \"\""

maxNrm = 0.0

splitPath  = re.search("(^.*/)([^/]*$)", fullPath)
if (splitPath!=None) and (splitPath.lastindex==2):
	srcPath    = splitPath.group(1)
	srcFile    = splitPath.group(2)

fileparts  = re.search("(^[^#]*)[#]{1,4}(\.[a-zA-Z]{3})[ ]*",srcFile)
rangeParts = re.search("([0-9]*)[-]{1}([0-9]*$)", rangePath)


if (fileparts!=None) and (rangeParts!=None) and (fileparts.lastindex==2) and (rangeParts.lastindex==2):
	srcBase = fileparts.group(1)
	srcExt  = fileparts.group(2)
	start   = int( rangeParts.group(1) )
	end     = int( rangeParts.group(2) )
	for i in range(start, end+1):
		padIdx = '%04d' % i
		reconstructedFileIn = srcPath + srcBase + padIdx + srcExt
		shakeLine = "shakeFLY -fi "+reconstructedFileIn+stat+resize+" -fo "+tmpPath+"tmp.exr"
		os.popen4( shakeLine )
		exrpeekCmd = "exrpeek -xy 0 0 -c 0 "+tmpPath+"tmp.exr"
		put, get = os.popen4( exrpeekCmd, "r" )
		for outline in get.readlines():
			matchline = re.search("^(rgba = )([0-9]*[\.][0-9]*)(.*)$", outline)
			localMax = 0.0
			if (matchline!=None) and (matchline.lastindex==3):
				localMax = float( matchline.group(2) )
				print i, maxNrm, localMax
				if ( (localMax>0.0) and (localMax > maxNrm) ):
					maxNrm = localMax

	seq = str(start) + "-" + str(end) + "#" + srcExt
	invMax = str((1.0/float(maxNrm)))
	print "invMax=", invMax
	shakeLine2 = "shakeFLY -fi " + srcPath + srcBase + seq + " -mult " + invMax + " " + invMax + " " + invMax + " " + " -fo " + srcPath + srcBase + "NORMALIZED." + seq + " -t " + str(start) + "-" + str(end)
	os.popen4( shakeLine2 )
else:
	print "Usage: normalize /fullpath/mySequence___depth.#.exr 1-214"
					


9. tcsh

9.1 Handy Aliases


# usage [must cd to dir first] : 
# shinc doomPlanet_srf_v05.sl*

alias shinc		'find . -name "\!:1" -maxdepth 1 -exec /u/dde/tools/perl/incr.pl \{\} \;'

alias shlinc		'rm \!:1.sl ;   ln -s $PWD/VERSIONS/\!:1_v\!:2.sl \!:1.sl ;\
			 rm \!:1.slo ;  ln -s $PWD/VERSIONS/\!:1_v\!:2.slo \!:1.slo ; ll  \!:1.sl*'

alias shlimc		'rm \!:1.sl ;   ln -s $PWD/VERSIONS/\!:1_v\!:2.sl \!:1.sl ;\
			 rm \!:1.slo ;  ln -s $PWD/VERSIONS/\!:1_v\!:2.slo \!:1.slo ;\
			 rm \!:1.slim ; ln -s $PWD/VERSIONS/\!:1_v\!:2.slim \!:1.slim ; ll  \!:1.sl*'

alias shlinch		'rm \!:1.h ;    ln -s $PWD/VERSIONS/\!:1_v\!:2.h \!:1.h ; ll \!:1.h*'

alias cdr		'cd `ls -t -F | grep -e /$ | head -n 1`'
					

9.2 "loop" : File Sequence 'looped operations' script

place this in a file called loop and chmod a+x
example of use is moving subset from a sequence using filters

		loop 4 10 cg_myshot_blah_t004_v002 exr /some/dest/path/
			

ver.pl is a perl script to extract the version number from a file name and compare it with a loop variable. Click the link below to download it.


#!/bin/tcsh -f
# usage :
#
#	loop min max srcfilter srcext dstdir

set SEQ_MIN = $1
set SEQ_MAX = $2
set SRC		= $3
set SRCEXT	= $4
set DST_DIR = $5
@ SEQ_MAX++

foreach f ( $SRC*.$SRCEXT )
	set FOOBAR = `/u/dde/tools/perl/ver.pl $f`
	set MINVER = `printf "%04d" $SEQ_MIN`
	set MAXVER = `printf "%04d" $SEQ_MAX`
	if ( ($FOOBAR >= $MINVER) && ($FOOBAR < $MAXVER) ) then
		echo $FOOBAR : moving $f  --\>  $DST_DIR;
		mv $f $DST_DIR
	endif
end
					


10. Linux Shell

10.1 Using linux 'find' command to batch convert with the 'sho' command

This is a way of batch converting TEX files to TIFF format. In a terminal window in Linux, copy and paste the following bold text exactly as they appear, WITHOUT MODIFICATION.
For current dir and all recursive dir's under it use;

find . -name \*.tex -exec sho -dspy tiff -dspyfile \{\}.tif \{\} \;

For current dir only, you will also need the maxdepth 1 option:

find . -name \*.tex -maxdepth 1 -exec sho -dspy tiff -dspyfile \{\}.tif \{\} \;

For finding only recent files, use -amin +/-N where N is in minutes and - means newer than, + older than:
Here for example, find all shadow textures rendered in the last 10 minutes.

find . -name '*shd*tex' -amin -10

find all .mb or .ma files that have velvet in their name

find . -name '*.m[ab]' | grep -i 'velvet'

exr's less than 1 day old

find . -name '*.exr' -atime -1

exr's more than 1 day old

find . -name '*.exr' -atime +1

exr's less than 60 minutes old

find . -name '*.exr' -amin -60

10.2 A sample linux Makefile for gcc

Click here to download 'Makefile'

10.3 A Find files regex

This command will list all the file names in the current directory (.)
that start with c#- and end with .pdf where # is any single numeric digit

find . -name c\[0-9\]-\*.pdf

this command would find double digits ( c##- )

find . -name c\[0-9\]\[0-9\]-\*.pdf

10.4 wget for batch downloading from websites

This command will batch download all pdf's from the specified url.
Useful to go and get all of Numerical recipes in C from the web in one
go without clicking 100 times!

wget -r -l 1 -A pdf http://www.library.cornell.edu/nr/bookcpdf/

The paramaters:

-r

means recursive

-l 1

means how many links to recurse down

-A pdf

means only accept pdf files

10.5 env

type "env" in the shell and it will list all of your environment variables

env > somename.txt

will pipe it into a text file so you can search it easily.

10.6 top & mount

type

su machinename

to login to a machine from some other workstation (so substitute machinename for whatever the workstation name is). Now it's exactly as if you were sitting there.
type

top

and you get a list of processes currently running on that machine. You can use the PID to pass to 'kill' to shut down processess that have hanged.
also

mount -l

(lowercase 'L')

will list all of the devices that can be mounted (such as hard disks).

mount -a

will mount all of the devices according to your mount file in wherever it is.

10.7 USB mass storage

It wasn't obvious to me at first how to get my usb memory stick reader working on linux 7/9. So here's a couple of helpful links that got me on the right track

USB Mass storage HOW-TO: useful link #1
USB Mass storage HOW-TO: useful link #2

I created a directory under root called /mspro to mount my device to once i'd edited the fstab.
type

mount /mspro

to mount it, and then;

umount /mspro -l

when you want to unplug it (minus lowercase L for 'lazy'). At work i do this to mount the memory stick into /mnt/mspro/ in /etc/fstab;

/dev/sdb1 /mnt/mspro auto defaults,user,noauto 0 0

then in a shell

su
mount /dev/sdb1

On my home machine, I'd do this

mount /dev/sda1

Use;

fdisk -l

to figure out what to add to fstab. The number of blocks will be significantly less than your hard disks, so that's how you tell what one it is.
Apparently

dmesg

is a pretty useful thang too, lists hardware messages

10.8 Redirected output and multiple commands on one line

Example - I wanted to extract f-stop info in a batch for a whole load of image files, but metacam has no command line options to do this......
'metacam' is a command line util that prints to stdout from .THM thumbnail files, all the data about an image taken with a Canon D60 camera. E.g. f-stop exposure etc. etc.
1. pipe the output of metacam on every thumbnail file into a temp text file

find . -name \*.THM -exec metacam \{\} \; > temp.txt

2. grep it to list only the important lines containing filename (they all start with CRW_) and 'aperture'

grep -i -e 'CRW_\|Aperture:' temp.txt > apertures.txt

or as one line, stick a semi-colon between them (NOT an escape character)

find . -name \*.THM -exec metacam \{\} \; > temp.txt ; grep -i -e 'CRW_\|Aperture:' temp.txt > apertures.txt

10.9 Misc

Symbolic Link

Creates a symbolic link to /Acrobat5/bin/acroread in the directory /usr/local/bin. This is useful because /usr/local/bin is in the PATH env variable which means you can type the name of any exe's or scripts in that dir from any directory in a shell window and it will run. This effectively allows you to extent the set of Linux shell commands. Oh mental note I need to add the tiff2vnl++ script to this page, as it's well clever.

ln -s /usr/local/Acrobat5/bin/acroread /usr/local/bin

chmod : changes permissions on the file acroread

chmod a+w acroread

pwd : echoes the current directory

pwd

locate : a quick file locator search util

locate wx

tar -zxvf : extracts the files in a tar

tar -zxvf linux-508.tar.gz

gunzip piped into tar to extract tar.gz

gunzip -d STL_doc.tar.gz | tar -xvf -

ls and ll : lists directory contents including permissions

ls -al

touch : creates a file if it doesn't exist

touch somefile.whatever

CVS : Downloading FLTK

To grab the latest 2.0.x code, run the following commands:

export CVSROOT=:pserver:anonymous@cvs.sourceforge.net:/cvsroot/fltk
cvs login (press ENTER when asked for a password)
cvs -z3 get -d fltk-2.0.x fltk
cd fltk-2.0.x
autoconf

Once you have the code downloaded, run the following commands to keep your local copy up to date:

cd fltk-2.0.x
cvs -z3 update -dP autoconf

show free disk space

df -h
du . -sh

list processes that a string (use kill -9 on the leftmost number it gives)

pf maya

head

shader dnGlassBuilding.sl |& head

|& pipes the results of shader into head, which in turn only displays the first few lines of output messages.... quite handy if you have billions of errors and only want to see the first couple of them.


find : Part II

find . -name '*.sl' -exec grep 'mCorrosion' \{\} \;

the -print prints the file name to the stdout, this \; ends the -exec part and {} is a placeholder for the results from find


10.10 Helpful hints for using GDB

These are straight out of my .mycshrc file ....

(gdb) file /u/dde/dev/sw/window_matte/Linux-gcc322-debug/window_matte
(gdb) break 59
(gdb) run commandline1 commandline2 [ etc..]
(gdb) next [ = step over ]
(gdb) frame
(gdb) print foobar.size()
(gdb) clear
(gdb) continue [ like Run,F5 ]
(gdb) step [ = step into ]
(gdb)

10.11 Helpful hints for using CVS

Importing a new project -

Change to the top level directory of your new software project (E.g. /u/me/dev/sw/myApp) and execute:

cvs import -m "Initial import" sw/myApp DNEG BASE

The important bit is to be in the correct directory and to specify a correct repository name ('maya/myPlugin' in the above case). The repository name should normally match the local directory structure and project name within your dev area, making it easier to relate the cvs repository structure to you local sub directories under whatever your $DEV path points to.
If the import succeeded then your can backup/remove your project directory. You might like to move it somewhere safe until you are sure the import worked fully. E.g. rename the direcory with a leading underscore. You can then check out the version of your project from the cvs repository back into your local working area.


Checking out a project

To check out a project from the repository (such as the one you might have imported above) change directory to the top of your local dev area:

cd /u/dde/dev

Because cvs checks out files into your current directory you will normally want to be in /u/dde/dev.
Then use cvs to checkout the named directory, file or files:

cvs checkout sw/myApp

(will create /u/dde/dev/sw/myApp/)
After this you should have a new $DEV/maya/myPlugin directory and subsequent subdirectories. You can now go ahead and modify your source files.


Committing Changes to cvs

After making changes to your software project and building a working version your can do the following to save any changes back to the cvs repository - Change to your project top-level directory (E.g. /u/dde/dev/sw/myApp) and type:

cvs commit -m "Your checkin lable goes here"

The current directory and all subdirectories will be scanned and changes stored. Note that you must explicitly add and remove any files using cvs (see below).


Adding Files

If you add any files to your checkout project you must use the following command before they can be committed:

cvs add filenames...

Removing Files

To remove files from your project you must first remove the files from disk using 'rm' then use the following cvs command before a commit:

cvs rm filenames...

Merging Changes

If someone else has committed changes to files you have checkout then you can merge those changes (as long as they're not too significant) into your local project using the following command:

cvs update

10.12 Another sample Makefile

To use this, type

make clean ; make

It's an example of how to use a config file - wx-config in this case - inside a make file to get the include paths necessary.

PROJNAME = noisetweaker
OPENGL_LIBS = -lGL -lGLU
CPPFLAGS = `wx-config --cppflags`
LDLIBS = `wx-config --libs` -lwx_gtk_gl-2.4 $(OPENGL_LIBS)
OBJECTFILES = glCanvas.o perlinNoise.o slider.o $(PROJNAME).o

$(PROJNAME): $(OBJECTFILES)
nbsp;     g++ $(LDLIBS) $(OBJECTFILES) -o $(PROJNAME)

slider.o:
nbsp;     g++ $(CPPFLAGS) -c slider.cpp
$(PROJNAME).o:
      g++ $(CPPFLAGS) -c $(PROJNAME).cpp
glCanvas.o:
      g++ $(CPPFLAGS) -c glCanvas.cpp
perlinNoise.o :
      g++ $(CPPFLAGS) -c perlinNoise.cpp

clean:
      rm $(OBJECTFILES) $(PROJNAME)

10.13 Regex substitutions in NEDIT

In NEDIT; to regex find / replace

color(1,1,1) with { 1 1 1 }

or

color(0.5,0.5,0.5) with { 0.5 0.5 0.5 }

or

color(.5,.5,.5) with { .5 .5 .5 }

use find :

color\(([0]*\.*[0-9]),([0]*\.*[0-9]),([0]*\.*[0-9])\)

replace :

{ \1 \2 \3 }

and Alt+T to replace again. You have to use () around the regular expressions in 'find' that you want to use access again later on in the substitution otherwise it won't work.


To explain a bit what

color\(([0]*\.*[0-9]),([0]*\.*[0-9]),([0]*\.*[0-9])\)

does;


\(

- you have to escape actual occurences of the curved brackets characters, as they have a special regex use

[0]*

- match the character "zero" zero or more times.

\.*

- match the dot character (has to be escaped) zero or more times

[0-9]

- match any numeric character exactly once

( )

- these tell nedit that the result of the expression inside must be put in a \1 \2 \3 type result for substitution..

10.14 foreach operations on file sequences

consider the following sequence

mySequence.0001.exr
mySequence.0002.exr
.
.

to get just the basename.... "mySequence"

foreach f ( *.exr )
foreach? echo $f:r:r
foreach? end

to get just the extension.... "exr"

foreach f ( *.exr )
foreach? echo $f:e
foreach? end

to get just the frame number...."0001", "0002", etc

foreach f ( *.exr )
foreach? echo $f:r:e
foreach? end

here's the full list of modifiers... h Remove a trailing pathname component, leaving the head. t Remove all leading pathname components, leaving the tail. r Remove a filename extension \u2018.xxx\u2019, leaving the root name. e Remove all but the extension. u Uppercase the first lowercase letter. l Lowercase the first uppercase letter. s/l/r/ Substitute l for r. l is simply a string like r, not a regular expression as in the eponymous ed(1) command. Any character may be used as the delimiter in place of \u2018/\u2019; a \u2018\\u2019 can be used to quote the delimiter inside l and r. The character \u2018&\u2019 in the r is replaced by l; \u2018\\u2019 also quotes \u2018&\u2019. If l is empty (\u2018\u2018\u2019\u2019), the l from a previous substitution or the s from a previous \u2018?s?\u2019 event specification is used. The trailing delimiter may be omitted if it is immediately followed by a newline. & Repeat the previous substitution. g Apply the following modifier once to each word. a (+) Apply the following modifier as many times as possible to a single word. \u2018a\u2019 and \u2018g\u2019 can be used together to apply a modifier globally. In the current implementation, using the \u2018a\u2019 and \u2018s\u2019 modifiers together can lead to an infinite loop. For example, \u2018:as/f/ff/\u2019 will never terminate. This behavior might change in the future. p Print the new command line but do not execute it. q Quote the substituted words, preventing further substitutions. x Like q, but break into words at blanks, tabs and newlines.

11. Subversion (software configuration management 'SCM')

SVN basic work cycle docs...

11.1 Examining the dir structure

svnlook tree /tools/STAR/subversion/

11.2 Finding the revision numbers of a file

svn log -r 1:HEAD file:///tools/STAR/subversion/prman/shader/srf/starTecto_srf/trunk

This will output to the shell, all of the revision numbers associated with changes to files in this directory and their associated log message.
Use this to figure out which revision your file changed in, to enable you to checkout or diff previous versions...

11.3 Checking out the latest version of a file

svn checkout file:///tools/STAR/subversion/prman/shader/srf/starTecto_srf/trunk

The file checked out will go in whatever your current dir is, so make sure you know if something will be overwritten

11.4 Checking out a specific revision of a file (untested!)

svn checkout -r 40 file:///tools/STAR/subversion/prman/shader/srf/starTecto_srf/trunk

As above, but getting an older version instead of the latest one

11.5 Examining differences between old file revisions

svn diff -r 1:HEAD file:///tools/STAR/subversion/prman/shader/srf/starTecto_srf/trunk

HEAD is an alias for the highest revision number for this file. You can also just put a revision number here