diff --git a/SConstruct b/SConstruct
index 3ee56f7cff1fe322f234e81d9b592cb5dcabf014..f8eef60a117fc1bb66d8a317cbe71b51aaad4aaa 100644
--- a/SConstruct
+++ b/SConstruct
@@ -286,7 +286,7 @@ Help(opts.GenerateHelpText(env))
 # default is new quieter output, but if you need to see the 
 # commands, do 'scons BF_QUIET=0'
 bf_quietoutput = B.arguments.get('BF_QUIET', '1')
-if bf_quietoutput=='1':
+if env['BF_QUIET']:
     B.set_quiet_output(env)
 else:
     if toolset=='msvc':
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 47bcb76441ff2a7aced85a1e770e3f9ec4d012b8..1b0d4448f1de1a26b707f68292f7547cf13f5c77 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -976,7 +976,7 @@ getClipboard(int flag
 		Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
 		owner = XGetSelectionOwner(m_display, Primary_atom);
 		if (owner == m_window) {
-			data = (unsigned char*) malloc(strlen(txt_cut_buffer));
+			data = (unsigned char*) malloc(strlen(txt_cut_buffer)+1);
 			strcpy((char*)data, txt_cut_buffer);
 			return (GHOST_TUns8*)data;
 		} else if (owner == None) {
@@ -986,7 +986,7 @@ getClipboard(int flag
 		Primary_atom = XInternAtom(m_display, "PRIMARY", False);
 		owner = XGetSelectionOwner(m_display, Primary_atom);
 		if (owner == m_window) {
-			data = (unsigned char*) malloc(strlen(txt_select_buffer));
+			data = (unsigned char*) malloc(strlen(txt_select_buffer)+1);
 			strcpy((char*)data, txt_select_buffer);
 			return (GHOST_TUns8*)data;
 		} else if (owner == None) {
@@ -1007,10 +1007,12 @@ getClipboard(int flag
 		XNextEvent(m_display, &xevent);
 		if(xevent.type == SelectionNotify) {
 			if(XGetWindowProperty(m_display, m_window, xevent.xselection.property, 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) {
-				tmp_data = (unsigned char*) malloc(strlen((char*)data));
-				strcpy((char*)tmp_data, (char*)data);
-				XFree(data);
-				return (GHOST_TUns8*)tmp_data;
+				if (data) {
+					tmp_data = (unsigned char*) malloc(strlen((char*)data)+1);
+					strcpy((char*)tmp_data, (char*)data);
+					XFree(data);
+					return (GHOST_TUns8*)tmp_data;
+				}
 			}
 			return NULL;
 		}
@@ -1031,13 +1033,13 @@ GHOST_TInt8 *buffer, int flag) const
 		Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
 		if(txt_cut_buffer) { free((void*)txt_cut_buffer); }
 		
-		txt_cut_buffer = (char*) malloc(strlen(buffer));
+		txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
 		strcpy(txt_cut_buffer, buffer);
 	} else {
 		Primary_atom = XInternAtom(m_display, "PRIMARY", False);
 		if(txt_select_buffer) { free((void*)txt_select_buffer); }
 		
-		txt_select_buffer = (char*) malloc(strlen(buffer));
+		txt_select_buffer = (char*) malloc(strlen(buffer)+1);
 		strcpy(txt_select_buffer, buffer);
 	}
 	
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index 20d3a5b07fcc1caa5ca5d70cdf4c71be226d41e7..af9443428f7972be9e39a1e3782066adc4a19e4a 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -114,8 +114,8 @@ static const char *check_memlist(MemHead *memh);
 volatile int totblock= 0;
 volatile unsigned long mem_in_use= 0, mmap_in_use= 0;
 
-volatile static struct localListBase _membase;
-volatile static struct localListBase *membase = &_membase;
+static volatile struct localListBase _membase;
+static volatile struct localListBase *membase = &_membase;
 static void (*error_callback)(char *) = NULL;
 static void (*thread_lock_callback)(void) = NULL;
 static void (*thread_unlock_callback)(void) = NULL;
diff --git a/release/scripts/flt_defaultp.py b/release/scripts/flt_defaultp.py
index 5dca8ba63d7fd3e4bdd1079c76d45150481af7b4..5c44fe29a6f275292fc4d410a1873aefdcb2589d 100644
--- a/release/scripts/flt_defaultp.py
+++ b/release/scripts/flt_defaultp.py
@@ -1 +1 @@
-pal = [-256,0,16711680,-16777216,-19529984,-19726592,-19923200,-20119808,-20316416,-20578560,-20840704,-21102848,-21364992,-21692672,-22020352,-22413568,-22806784,-23200000,-23658752,-24117504,-24641792,-25166080,-25755904,-26411264,-27066624,-27787520,-28573952,-29425920,-30343424,-31326464,-32375040,-33489152,-354550016,-371458304,-388366592,-405274880,-422183168,-439156992,-456130816,-473104640,-506855680,-540672256,-574488832,-608305408,-642121984,-676004096,-709886208,-760611072,-811335936,-862060800,-912851200,-980418816,-1048051968,-1115685120,-1183383808,-1267925248,-1352466688,-1453850880,-1555300608,-1656815872,-1775173888,-1893597440,-2028863744,2130771712,-1010376448,-1043996416,-1077681920,-1111367424,-1145052928,-1178738432,-1229201152,-1279663872,-1330126592,-1380654848,-1431183104,-1498488576,-1565794048,-1633165056,-1700536064,-1784684288,-1868832512,-1969823488,-2070814464,2123096320,2005262592,1887428864,1752752384,1601298688,1449779456,1281417472,1096278272,911073536,709026048,490201344,254533888,2023680,-1380857856,-1397700608,-1431320576,-1464940544,-1498560512,-1532180480,-1565865984,-1599551488,-1650014208,-1700476928,-1750939648,-1801402368,-1851865088,-1919170560,-1986476032,-2053781504,-2121086976,2089797632,2005649408,1904723968,1803798528,1686030336,1568262144,1450493952,1315883008,1164494848,1013041152,844810240,659736576,457885696,239192064,3655680,-1767919872,-1784762624,-1801605376,-1818448128,-1852068096,-1885688064,-1919308032,-1952928000,-1986547968,-2020167936,-2070565120,-2120962304,2123542272,2073079552,2022616832,1955376896,1888136960,1820897024,1736879872,1652797184,1568714496,1467854592,1366994688,1249357568,1131654912,997175040,862695168,711372544,560049920,391950080,207007488,5287680,2139657728,2122880512,2106103296,2089326080,2072548864,2055771648,2022217216,1988662784,1955108352,1921553920,1887933952,1854313984,1803916800,1753519616,1703122432,1652725248,1602328064,1535153664,1467979264,1400804864,1316853248,1232901632,1148950016,1048221184,947426816,846632448,729060864,611489280,477140480,326014464,174888448,6919680,1837268224,1820491008,1803713792,1786936576,1770159360,1753382144,1736604928,1719827712,1686273280,1652718848,1619164416,1585609984,1552055552,1518501120,1468169472,1417837824,1367506176,1317174528,1266842880,1199734016,1132625152,1065516288,998407424,914521344,830635264,729971968,629308672,528645376,411204864,293764352,159546624,8551680,-2086957824,-2103735040,-2120512256,-2137289472,2140900608,2107346176,2073791744,2040237056,2006682368,1973127680,1939572992,1906018304,1855686400,1805354496,1755022592,1704690688,1654358784,1587249664,1520140544,1453031424,1369145088,1285258496,1201371904,1100708096,1000044288,882603264,765162240,630943744,496725248,345729536,177956608,10183680,-1699438080,-1716215552,-1732993024,-1766547712,-1800102400,-1833657088,-1867211776,-1900766464,-1934321152,-1967875840,-2018207744,-2068539904,-2118872064,2125763072,2058653696,1991544320,1924434944,1857325568,1773438720,1689551872,1588887808,1488223744,1387559424,1270117888,1152676352,1018457600,884238592,733242368,565468672,397694976,213144064,11815680,-1311918848,-1345473536,-1379028224,-1412582912,-1446137600,-1479692544,-1513247488,-1546802432,-1597134592,-1647466752,-1697798912,-1748131072,-1798463488,-1865573120,-1932682752,-1999792384,-2083679232,2127400960,2043513856,1942849536,1842184960,1724743168,1607301376,1473082112,1338862848,1187866112,1020092160,852317952,667766528,466437632,248331264,13447680,-924399104,-957954048,-991508992,-1025063936,-1058618880,-1092173824,-1142505984,-1192838144,-1243170560,-1293502976,-1343835392,-1410945024,-1478054656,-1545164544,-1629051648,-1712938752,-1796826112,-1897490688,-1998155264,-2098820096,2078705152,1961262848,1827043328,1676046336,1525049344,1357274880,1172722944,971393792,753287168,518403072,283518720,15079680,-570434304,-603989248,-637544192,-671099136,-704654080,-754986496,-805318912,-855651328,-905983744,-973093632,-1040203520,-1107313408,-1174423296,-1258310656,-1342198016,-1442862848,-1543527680,-1644192512,-1761634816,-1879077120,-2013296896,2147450624,1996453376,1828678656,1660903936,1476351744,1275022080,1056914944,822030336,570368256,301928704,16711680,-503325440,-536880384,-570435328,-603990272,-637545216,-671100416,-721432832,-771765248,-822097664,-872430336,-922763008,-989872896,-1056982784,-1124092928,-1191203072,-1275090688,-1358978304,-1459643136,-1560308224,-1660973312,-1778415872,-1895858432,-2030078464,2113891328,1962893824,1795118848,1610566400,1426013696,1224683520,1006575872,771690752,520028160,-452993792,-469771520,-503326464,-536881408,-570436352,-603991552,-637546752,-671101952,-721434368,-771767040,-822099712,-872432384,-922765056,-989875200,-1056985344,-1124095744,-1191206144,-1275093760,-1358981632,-1459646720,-1560312064,-1677754624,-1795197440,-1912640512,-2046860800,2097108736,1946110720,1778335232,1593782272,1392451840,1174343936,939458560,-419439360,-436217088,-452994816,-469772544,-503327488,-536882688,-570437888,-603993088,-637548288,-671103744,-721436416,-771769088,-822101760,-872434688,-922767616,-989878016,-1056988416,-1124098816,-1207986688,-1291874560,-1375762688,-1476428032,-1577093632,-1694536704,-1811979776,-1946200320,-2080421120,2063547904,1912549376,1744773376,1560219904,1358888960,-385884928,-402662656,-419440384,-436218112,-452995840,-469773824,-503329024,-536884224,-570439424,-603994880,-637550336,-671105792,-721438464,-771771392,-822104320,-872437504,-922770688,-989881088,-1056991744,-1124102400,-1191213312,-1275101440,-1358989824,-1459655680,-1560321536,-1677764864,-1795208448,-1912652288,-2046873600,2097094912,1946095872,1778319360,-335553280,-352331008,-369108736,-385886464,-402664192,-419442176,-436220160,-452998144,-486553344,-520108800,-553664256,-587219712,-620775168,-654330880,-687886592,-738219776,-788552960,-838886144,-889219584,-939553024,-1006663936,-1073774848,-1140886016,-1224774656,-1308663296,-1392552192,-1493218560,-1593885184,-1711329280,-1828773632,-1962995456,-2097217536,-285221632,-301999360,-318777088,-335554816,-352332544,-369110528,-385888512,-402666496,-419444480,-436222720,-453000960,-469779200,-503334656,-536890368,-570446080,-604002048,-637558016,-671113984,-721447424,-771780864,-822114560,-872448256,-922782208,-989893632,-1057005056,-1124116736,-1191228672,-1275118080,-1359007744,-1459674880,-1560342272,-1677787136,-234889984,-234890496,-251668224,-268445952,-285223680,-302001664,-318779648,-335557632,-352335616,-369113856,-385892096,-402670336,-419448576,-436227072,-453005568,-469784320,-503340288,-536896256,-570452480,-604008704,-637565184,-671121664,-704678400,-755012608,-805346816,-855681280,-906016000,-973128192,-1040240640,-1107353344,-1174466304,-1258356736,-234889984,-234890496,-234891008,-234891520,-234892032,-234892800,-234893568,-234894336,-234895104,-251673344,-268451584,-285229824,-302008064,-318786560,-335565056,-352343808,-369122560,-385901312,-402680320,-419459328,-436238592,-453017856,-486574592,-520131584,-553688576,-587245824,-620803328,-654361088,-687919104,-738254592,-788590336,-838926336,-234889984,-234890496,-234891008,-234891520,-234892032,-234892800,-234893568,-234894336,-234895104,-234896128,-234897152,-234898176,-234899200,-234900480,-234901760,-234903296,-234904832,-234906368,-234908160,-234909952,-234912000,-251691264,-268470784,-285250560,-302030336,-318810368,-335590656,-352371200,-369152000,-385933056,-402714368,-419495936,-8960,-9472,-9984,-10496,-11008,-11776,-12544,-13312,-14080,-15104,-16128,-17152,-18176,-19456,-20736,-22272,-23808,-25344,-27136,-28928,-30976,-33024,-35328,-37888,-40448,-43264,-46336,-49664,-53248,-57088,-61184,-65536,-926464,-926976,-927488,-928000,-928512,-929280,-930048,-930816,-931584,-932608,-933632,-934656,-935680,-936960,-938240,-939776,-941312,-1008384,-1075712,-1143040,-1210624,-1278208,-1346048,-1414144,-1482240,-1550592,-1619200,-1688064,-1757184,-1826560,-1896192,-2031616,-926464,-926976,-927488,-928000,-928512,-929280,-930048,-996352,-1062656,-1129216,-1195776,-1262336,-1328896,-1395712,-1462528,-1529600,-1596672,-1663744,-1731072,-1798400,-1865984,-1999104,-2132480,-2266112,-2399744,-2533632,-2667776,-2867712,-3067904,-3268352,-3469056,-3670016,-926464,-992512,-1058560,-1124608,-1190656,-1256960,-1323264,-1389568,-1455872,-1522432,-1588992,-1655552,-1722112,-1788928,-1855744,-1988352,-2120960,-2253568,-2386432,-2519296,-2652416,-2785536,-2984448,-3183616,-3382784,-3582208,-3847424,-4112896,-4378624,-4644608,-4976384,-5308416,-1188608,-1254656,-1320704,-1386752,-1452800,-1519104,-1585408,-1651712,-1718016,-1784576,-1851136,-1983232,-2115328,-2247680,-2380032,-2512640,-2645248,-2777856,-2976256,-3174656,-3373312,-3571968,-3836416,-4101120,-4365824,-4630784,-4961536,-5292544,-5689344,-6086400,-6483712,-6946816,-1385216,-1451264,-1517312,-1583360,-1649408,-1715712,-1782016,-1848320,-1980160,-2112256,-2244352,-2376448,-2508544,-2640896,-2838784,-3036928,-3235072,-3433216,-3631616,-3895552,-4159744,-4423936,-4688384,-5018624,-5348864,-5744896,-6141184,-6537728,-7000064,-7462656,-7991040,-8585216,-1581824,-1647872,-1713920,-1779968,-1846016,-1977856,-2109696,-2241536,-2373376,-2505472,-2637568,-2769664,-2967296,-3165184,-3363072,-3561216,-3759360,-4023040,-4286976,-4550912,-4880640,-5210368,-5540352,-5936128,-6331904,-6793472,-7255296,-7782912,-8310784,-8904448,-9563904,-10223616,-1712896,-1778944,-1844992,-1976576,-2108160,-2240000,-2371840,-2503680,-2635520,-2767616,-2965248,-3162880,-3360512,-3558400,-3821824,-4085504,-4349184,-4612864,-4942336,-5271808,-5667072,-6062336,-6457856,-6919168,-7380480,-7907584,-8434944,-9028096,-9687040,-10346240,-11071232,-11862016,-1843968,-1975552,-2107136,-2238720,-2370304,-2502144,-2633984,-2765824,-2963200,-3160832,-3358464,-3556096,-3753728,-4017152,-4280576,-4544256,-4873472,-5202688,-5532160,-5927168,-6322432,-6783232,-7244288,-7771136,-8297984,-8890624,-9549056,-10207744,-10932224,-11722496,-12578560,-13500416,-1975040,-2106624,-2238208,-2369792,-2501376,-2633216,-2830592,-3027968,-3225344,-3422976,-3620608,-3883776,-4146944,-4410368,-4673792,-5003008,-5332224,-5726976,-6121984,-6582528,-7043328,-7504128,-8030720,-8623104,-9215488,-9873664,-10597632,-11387392,-12242944,-13164288,-14085888,-15138816,-2237184,-2368768,-2500352,-2631936,-2763520,-2960896,-3158272,-3355648,-3553024,-3816192,-4079360,-4342528,-4605696,-4934656,-5263616,-5658368,-6053120,-6447872,-6908416,-7368960,-7895296,-8421632,-9013760,-9671680,-10329600,-11053312,-11842816,-12698112,-13619200,-14606080,-15658752,-16777216]
\ No newline at end of file
+pal = [-1,255,16711935,-16776961,-19529729,-19726337,-19922945,-20119553,-20316161,-20578305,-20840449,-21102593,-21364737,-21692417,-22020097,-22413313,-22806529,-23199745,-23658497,-24117249,-24641537,-25165825,-25755649,-26411009,-27066369,-27787265,-28573697,-29425665,-30343169,-31326209,-32374785,-33488897,-354549761,-371458049,-388366337,-405274625,-422182913,-439156737,-456130561,-473104385,-506855425,-540672001,-574488577,-608305153,-642121729,-676003841,-709885953,-760610817,-811335681,-862060545,-912850945,-980418561,-1048051713,-1115684865,-1183383553,-1267924993,-1352466433,-1453850625,-1555300353,-1656815617,-1775173633,-1893597185,-2028863489,2130771967,-1010376193,-1043996161,-1077681665,-1111367169,-1145052673,-1178738177,-1229200897,-1279663617,-1330126337,-1380654593,-1431182849,-1498488321,-1565793793,-1633164801,-1700535809,-1784684033,-1868832257,-1969823233,-2070814209,2123096575,2005262847,1887429119,1752752639,1601298943,1449779711,1281417727,1096278527,911073791,709026303,490201599,254534143,2023935,-1380857601,-1397700353,-1431320321,-1464940289,-1498560257,-1532180225,-1565865729,-1599551233,-1650013953,-1700476673,-1750939393,-1801402113,-1851864833,-1919170305,-1986475777,-2053781249,-2121086721,2089797887,2005649663,1904724223,1803798783,1686030591,1568262399,1450494207,1315883263,1164495103,1013041407,844810495,659736831,457885951,239192319,3655935,-1767919617,-1784762369,-1801605121,-1818447873,-1852067841,-1885687809,-1919307777,-1952927745,-1986547713,-2020167681,-2070564865,-2120962049,2123542527,2073079807,2022617087,1955377151,1888137215,1820897279,1736880127,1652797439,1568714751,1467854847,1366994943,1249357823,1131655167,997175295,862695423,711372799,560050175,391950335,207007743,5287935,2139657983,2122880767,2106103551,2089326335,2072549119,2055771903,2022217471,1988663039,1955108607,1921554175,1887934207,1854314239,1803917055,1753519871,1703122687,1652725503,1602328319,1535153919,1467979519,1400805119,1316853503,1232901887,1148950271,1048221439,947427071,846632703,729061119,611489535,477140735,326014719,174888703,6919935,1837268479,1820491263,1803714047,1786936831,1770159615,1753382399,1736605183,1719827967,1686273535,1652719103,1619164671,1585610239,1552055807,1518501375,1468169727,1417838079,1367506431,1317174783,1266843135,1199734271,1132625407,1065516543,998407679,914521599,830635519,729972223,629308927,528645631,411205119,293764607,159546879,8551935,-2086957569,-2103734785,-2120512001,-2137289217,2140900863,2107346431,2073791999,2040237311,2006682623,1973127935,1939573247,1906018559,1855686655,1805354751,1755022847,1704690943,1654359039,1587249919,1520140799,1453031679,1369145343,1285258751,1201372159,1100708351,1000044543,882603519,765162495,630943999,496725503,345729791,177956863,10183935,-1699437825,-1716215297,-1732992769,-1766547457,-1800102145,-1833656833,-1867211521,-1900766209,-1934320897,-1967875585,-2018207489,-2068539649,-2118871809,2125763327,2058653951,1991544575,1924435199,1857325823,1773438975,1689552127,1588888063,1488223999,1387559679,1270118143,1152676607,1018457855,884238847,733242623,565468927,397695231,213144319,11815935,-1311918593,-1345473281,-1379027969,-1412582657,-1446137345,-1479692289,-1513247233,-1546802177,-1597134337,-1647466497,-1697798657,-1748130817,-1798463233,-1865572865,-1932682497,-1999792129,-2083678977,2127401215,2043514111,1942849791,1842185215,1724743423,1607301631,1473082367,1338863103,1187866367,1020092415,852318207,667766783,466437887,248331519,13447935,-924398849,-957953793,-991508737,-1025063681,-1058618625,-1092173569,-1142505729,-1192837889,-1243170305,-1293502721,-1343835137,-1410944769,-1478054401,-1545164289,-1629051393,-1712938497,-1796825857,-1897490433,-1998155009,-2098819841,2078705407,1961263103,1827043583,1676046591,1525049599,1357275135,1172723199,971394047,753287423,518403327,283518975,15079935,-570434049,-603988993,-637543937,-671098881,-704653825,-754986241,-805318657,-855651073,-905983489,-973093377,-1040203265,-1107313153,-1174423041,-1258310401,-1342197761,-1442862593,-1543527425,-1644192257,-1761634561,-1879076865,-2013296641,2147450879,1996453631,1828678911,1660904191,1476351999,1275022335,1056915199,822030591,570368511,301928959,16711935,-503325185,-536880129,-570435073,-603990017,-637544961,-671100161,-721432577,-771764993,-822097409,-872430081,-922762753,-989872641,-1056982529,-1124092673,-1191202817,-1275090433,-1358978049,-1459642881,-1560307969,-1660973057,-1778415617,-1895858177,-2030078209,2113891583,1962894079,1795119103,1610566655,1426013951,1224683775,1006576127,771691007,520028415,-452993537,-469771265,-503326209,-536881153,-570436097,-603991297,-637546497,-671101697,-721434113,-771766785,-822099457,-872432129,-922764801,-989874945,-1056985089,-1124095489,-1191205889,-1275093505,-1358981377,-1459646465,-1560311809,-1677754369,-1795197185,-1912640257,-2046860545,2097108991,1946110975,1778335487,1593782527,1392452095,1174344191,939458815,-419439105,-436216833,-452994561,-469772289,-503327233,-536882433,-570437633,-603992833,-637548033,-671103489,-721436161,-771768833,-822101505,-872434433,-922767361,-989877761,-1056988161,-1124098561,-1207986433,-1291874305,-1375762433,-1476427777,-1577093377,-1694536449,-1811979521,-1946200065,-2080420865,2063548159,1912549631,1744773631,1560220159,1358889215,-385884673,-402662401,-419440129,-436217857,-452995585,-469773569,-503328769,-536883969,-570439169,-603994625,-637550081,-671105537,-721438209,-771771137,-822104065,-872437249,-922770433,-989880833,-1056991489,-1124102145,-1191213057,-1275101185,-1358989569,-1459655425,-1560321281,-1677764609,-1795208193,-1912652033,-2046873345,2097095167,1946096127,1778319615,-335553025,-352330753,-369108481,-385886209,-402663937,-419441921,-436219905,-452997889,-486553089,-520108545,-553664001,-587219457,-620774913,-654330625,-687886337,-738219521,-788552705,-838885889,-889219329,-939552769,-1006663681,-1073774593,-1140885761,-1224774401,-1308663041,-1392551937,-1493218305,-1593884929,-1711329025,-1828773377,-1962995201,-2097217281,-285221377,-301999105,-318776833,-335554561,-352332289,-369110273,-385888257,-402666241,-419444225,-436222465,-453000705,-469778945,-503334401,-536890113,-570445825,-604001793,-637557761,-671113729,-721447169,-771780609,-822114305,-872448001,-922781953,-989893377,-1057004801,-1124116481,-1191228417,-1275117825,-1359007489,-1459674625,-1560342017,-1677786881,-234889729,-234890241,-251667969,-268445697,-285223425,-302001409,-318779393,-335557377,-352335361,-369113601,-385891841,-402670081,-419448321,-436226817,-453005313,-469784065,-503340033,-536896001,-570452225,-604008449,-637564929,-671121409,-704678145,-755012353,-805346561,-855681025,-906015745,-973127937,-1040240385,-1107353089,-1174466049,-1258356481,-234889729,-234890241,-234890753,-234891265,-234891777,-234892545,-234893313,-234894081,-234894849,-251673089,-268451329,-285229569,-302007809,-318786305,-335564801,-352343553,-369122305,-385901057,-402680065,-419459073,-436238337,-453017601,-486574337,-520131329,-553688321,-587245569,-620803073,-654360833,-687918849,-738254337,-788590081,-838926081,-234889729,-234890241,-234890753,-234891265,-234891777,-234892545,-234893313,-234894081,-234894849,-234895873,-234896897,-234897921,-234898945,-234900225,-234901505,-234903041,-234904577,-234906113,-234907905,-234909697,-234911745,-251691009,-268470529,-285250305,-302030081,-318810113,-335590401,-352370945,-369151745,-385932801,-402714113,-419495681,-8705,-9217,-9729,-10241,-10753,-11521,-12289,-13057,-13825,-14849,-15873,-16897,-17921,-19201,-20481,-22017,-23553,-25089,-26881,-28673,-30721,-32769,-35073,-37633,-40193,-43009,-46081,-49409,-52993,-56833,-60929,-65281,-926209,-926721,-927233,-927745,-928257,-929025,-929793,-930561,-931329,-932353,-933377,-934401,-935425,-936705,-937985,-939521,-941057,-1008129,-1075457,-1142785,-1210369,-1277953,-1345793,-1413889,-1481985,-1550337,-1618945,-1687809,-1756929,-1826305,-1895937,-2031361,-926209,-926721,-927233,-927745,-928257,-929025,-929793,-996097,-1062401,-1128961,-1195521,-1262081,-1328641,-1395457,-1462273,-1529345,-1596417,-1663489,-1730817,-1798145,-1865729,-1998849,-2132225,-2265857,-2399489,-2533377,-2667521,-2867457,-3067649,-3268097,-3468801,-3669761,-926209,-992257,-1058305,-1124353,-1190401,-1256705,-1323009,-1389313,-1455617,-1522177,-1588737,-1655297,-1721857,-1788673,-1855489,-1988097,-2120705,-2253313,-2386177,-2519041,-2652161,-2785281,-2984193,-3183361,-3382529,-3581953,-3847169,-4112641,-4378369,-4644353,-4976129,-5308161,-1188353,-1254401,-1320449,-1386497,-1452545,-1518849,-1585153,-1651457,-1717761,-1784321,-1850881,-1982977,-2115073,-2247425,-2379777,-2512385,-2644993,-2777601,-2976001,-3174401,-3373057,-3571713,-3836161,-4100865,-4365569,-4630529,-4961281,-5292289,-5689089,-6086145,-6483457,-6946561,-1384961,-1451009,-1517057,-1583105,-1649153,-1715457,-1781761,-1848065,-1979905,-2112001,-2244097,-2376193,-2508289,-2640641,-2838529,-3036673,-3234817,-3432961,-3631361,-3895297,-4159489,-4423681,-4688129,-5018369,-5348609,-5744641,-6140929,-6537473,-6999809,-7462401,-7990785,-8584961,-1581569,-1647617,-1713665,-1779713,-1845761,-1977601,-2109441,-2241281,-2373121,-2505217,-2637313,-2769409,-2967041,-3164929,-3362817,-3560961,-3759105,-4022785,-4286721,-4550657,-4880385,-5210113,-5540097,-5935873,-6331649,-6793217,-7255041,-7782657,-8310529,-8904193,-9563649,-10223361,-1712641,-1778689,-1844737,-1976321,-2107905,-2239745,-2371585,-2503425,-2635265,-2767361,-2964993,-3162625,-3360257,-3558145,-3821569,-4085249,-4348929,-4612609,-4942081,-5271553,-5666817,-6062081,-6457601,-6918913,-7380225,-7907329,-8434689,-9027841,-9686785,-10345985,-11070977,-11861761,-1843713,-1975297,-2106881,-2238465,-2370049,-2501889,-2633729,-2765569,-2962945,-3160577,-3358209,-3555841,-3753473,-4016897,-4280321,-4544001,-4873217,-5202433,-5531905,-5926913,-6322177,-6782977,-7244033,-7770881,-8297729,-8890369,-9548801,-10207489,-10931969,-11722241,-12578305,-13500161,-1974785,-2106369,-2237953,-2369537,-2501121,-2632961,-2830337,-3027713,-3225089,-3422721,-3620353,-3883521,-4146689,-4410113,-4673537,-5002753,-5331969,-5726721,-6121729,-6582273,-7043073,-7503873,-8030465,-8622849,-9215233,-9873409,-10597377,-11387137,-12242689,-13164033,-14085633,-15138561,-2236929,-2368513,-2500097,-2631681,-2763265,-2960641,-3158017,-3355393,-3552769,-3815937,-4079105,-4342273,-4605441,-4934401,-5263361,-5658113,-6052865,-6447617,-6908161,-7368705,-7895041,-8421377,-9013505,-9671425,-10329345,-11053057,-11842561,-12697857,-13618945,-14605825,-15658497,-16776961]
\ No newline at end of file
diff --git a/release/scripts/flt_import.py b/release/scripts/flt_import.py
index 3ba118c0d184149dfd2b70198e7f53f61c1b3f37..1df7c937842b2b05158983b98266039b6ecc9e12 100644
--- a/release/scripts/flt_import.py
+++ b/release/scripts/flt_import.py
@@ -6,6 +6,8 @@ Group: 'Import'
 Tip: 'Import OpenFlight (.flt)'
 """
 
+
+
 __author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle"
 __version__ = "2.0 11/21/07"
 __url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
@@ -952,8 +954,12 @@ class InterNode(Node):
 			except: #horrible...
 				pass
 		
+
 		if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene):
-				self.parent.object.makeParent([self.object])
+				self.parent.object.makeParent([self.object],1)
+
+		if self.matrix:
+			self.object.setMatrix(self.matrix)
 
 		if self.vis == False:
 			self.object.restrictDisplay = True
@@ -979,8 +985,6 @@ class InterNode(Node):
 					min= LODmin(min,lodlist[i])
 				min.vis = True
 				
-		if self.matrix:
-			self.object.setMatrix(self.matrix)
 			
 		Node.blender_import(self) # Attach faces to self.faceLs
 		
@@ -1324,11 +1328,17 @@ class XRef(InterNode):
 		self.props['comment'] = ''
 		self.parse_record()
 
-		xref_filename = self.props['3t200!filename']
+		xref_filename = self.props['3t200!filename'] #I dont even think there is a reason to keep this around...
+		
+		if not os.path.isabs(xref_filename):
+			absname = os.path.join(os.path.dirname(self.header.filename), xref_filename) 
+		else:
+			absname = xref_filename	
+		
 		self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well....
 		
-		if global_prefs['doxrefs'] and os.path.exists(xref_filename) and not self.header.grr.xrefs.has_key(xref_filename):
-			self.xref = Database(xref_filename, self.header.grr, self)
+		if global_prefs['doxrefs'] and os.path.exists(absname) and not self.header.grr.xrefs.has_key(xref_filename):
+			self.xref = Database(absname, self.header.grr, self)
 			self.header.grr.xrefs[xref_filename] = self.xref
 		else:
 			self.xref = None
@@ -1348,8 +1358,15 @@ class XRef(InterNode):
 		except:
 			pass
 			
+
+
+
 		if self.parent and self.parent.object:
-			self.parent.object.makeParent([self.object])
+			self.parent.object.makeParent([self.object],1)
+
+		if self.matrix:
+			self.object.setMatrix(self.matrix)
+
 
 		#id props import
 		self.object.properties['FLT'] = dict()
@@ -1361,8 +1378,7 @@ class XRef(InterNode):
 
 		self.object.Layer = current_layer
 		self.object.sel = 1
-		if self.matrix:
-			self.object.setMatrix(self.matrix)
+
 		Node.blender_import(self)
 		
 		
@@ -1843,6 +1859,9 @@ class Database(InterNode):
 			print 'Parsing:', filename
 			print
 		
+		#check to see if filename is a relative path
+		#filename = os.path.abspath(filename)
+		
 		self.fw = flt_filewalker.FltIn(filename)
 		self.filename = filename
 		self.bname = os.path.splitext(os.path.basename(filename))[0]
@@ -1902,7 +1921,7 @@ def fixscale(root,childhash):
 	for child in childhash[root]:
 		fixscale(child,childhash)
 	location = Blender.Mathutils.Vector(root.getLocation('worldspace'))
-	if location[0] != 0.0 and location[1] != 0.0 and location[2] != 0.0:
+	if location[0] != 0.0 or location[1] != 0.0 or location[2] != 0.0:
 		#direction = Blender.Mathutils.Vector(0-location[0],0-location[1],0-location[2]) #reverse vector
 		smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
 		root.setLocation(location * smat)
diff --git a/release/scripts/flt_toolbar.py b/release/scripts/flt_toolbar.py
index 213fac1bb3c9b0e5b4a0e5ac962224dbecff64f9..249c3f83dfccd72ec7d0c4a867ea288f1d383b0e 100644
--- a/release/scripts/flt_toolbar.py
+++ b/release/scripts/flt_toolbar.py
@@ -76,7 +76,8 @@ evcode = {
 	"IDPROP_COPY" : 501,
 	"IDPROP_KILL" : 502,
 	"CLIGHT_MAKE" : 700,
-	"DFROMACT" : 701
+	"DFROMACT" : 701,
+	"FIXCOL" : 702
 }
 
 XREF_PREFIX = None
@@ -92,6 +93,44 @@ IDPROP_COPY = None
 SCENE_UPDATE = None
 CLIGHT_MAKE = None
 DFROMACT = None
+FIXCOL = None
+
+
+def RGBtoHSV( r, g, b):
+	cmin = min( r, g, b )
+	cmax = max( r, g, b )
+	v = cmax				
+
+	if(cmax!=0.0):
+		s = (cmax-cmin)/cmax
+	else:
+		s = 0.0
+		h = 0.0
+	
+	if(s == 0.0):
+		h = -1.0
+	else:
+		cdelta = cmax-cmin
+		rc = (cmax-r)/cdelta
+		gc = (cmax-g)/cdelta
+		bc = (cmax-b)/cdelta
+		if(r==cmax):
+			h = bc-gc
+		else:
+			if(g==cmax):
+				h = 2.0+rc-bc
+			else:
+				h = 4.0+gc-rc
+		h = h*60.0
+		if(h<0.0):
+			h += 360.0
+			
+		
+	h = h/360.0
+	if(h < 0.0): 
+		h = 0.0
+	return (h,s,v)
+
 
 def update_state():
 	state = dict()
@@ -141,24 +180,130 @@ def idprops_copy(source):
 				for key in source.properties['FLT']:
 					object.properties['FLT'][key] = source.properties['FLT'][key]
 
-def update_all():
+def unpack_color(color):
+	return struct.unpack('>BBBB',struct.pack('>I',color))
+
+
+def findColorKey(colordict, hsv):
+	hdelta = 0.001
+	for key in colordict:
+		if not (((hsv[0] < (key[0] + hdelta)) and (hsv[0] > (key[0] - hdelta))) and ((hsv[1] < (key[1] + hdelta)) and (hsv[1] > (key[1] - hdelta)))):
+			return key
+	return None
+
+def hsvsort(a, b):
+	(index1, mag1) = a
+	(index2, mag2) = b
+	if mag1 > mag2:
+		return 1
+	elif mag1 < mag2:
+		return -1
+	return 0
+
+def fix_colors():
+	
+	editmode = 0
+	if Blender.Window.EditMode():
+		Blender.Window.EditMode(0)
+		editmode = 1
 	state = update_state()
-	#update the baked FLT colors for all meshes.
-	for object in state["activeScene"].objects:
-		if object.type == "Mesh":
+	
+	scene = state["activeScene"]
+	colors = None
+	if state["activeScene"].properties.has_key('FLT'):
+		try:
+			colors = state["activeScene"].properties['FLT']['Color Palette']
+		except:
+			pass
+	if not colors:
+		return
+	
+	#first build a HSV version of our palette
+	hsvpalette = list()
+	for swatch in colors:
+		color = unpack_color(swatch)
+		hsv = RGBtoHSV(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0)
+		hsvpalette.append(hsv)
+		
+	#collect all of our meshes
+	meshes = list()
+	for object in scene.objects.context:
+		if object.sel and object.type == 'Mesh':
 			mesh = object.getData(mesh=True)
-			if 'FLT_COL' in mesh.faces.properties:
-				mesh.activeColorLayer = "FLT_Fcol"
-				for face in mesh.faces:
-					(index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
-					color = struct.unpack('>BBBB',struct.pack('>I',state["colors"][index]))
-					#update the vertex colors for this face
-					for col in face.col:
-						col.r = int(color[0] * intensity)
-						col.g = int(color[1] * intensity)
-						col.b = int(color[2] * intensity)
-						col.a = 255
+			if "FLT_COL" in mesh.faces.properties:
+				meshes.append(mesh)
+				
+				
+	#Now go through our meshes, and build a dictionary of face lists keyed according to (hue,saturation) of the baked color
+	colordict = dict()
+	for mesh in meshes:
+		for face in mesh.faces:
+			hsv = RGBtoHSV(face.col[0].r/255.0, face.col[0].g/255.0, face.col[0].b/255.0) #retrieve baked color
+			if colordict.has_key((hsv[0],hsv[1])):
+				colordict[(hsv[0],hsv[1])].append(face)
+			else:
+				colordict[(hsv[0],hsv[1])] = [face]				
+	
 
+	#for each color key in the color dict, build a list of distances from it to the values in hsvpalette and then quicksort them for closest match
+	for key in colordict:
+		maglist = list()
+		for i, hsv in enumerate(hsvpalette):
+			norm = Blender.Mathutils.Vector(hsv[0], hsv[1]) - Blender.Mathutils.Vector(key[0],key[1])
+			maglist.append((i,norm.length))
+		maglist.sort(hsvsort)
+		print maglist[0]
+		for face in colordict[key]:
+			(index, intensity) = unpack_face_index(face.getProperty("FLT_COL"))
+			newfindex = pack_face_index(maglist[0][0],intensity)
+			face.setProperty("FLT_COL", int(newfindex))
+	
+	for mesh in meshes:
+		update_mesh_colors(colors,mesh)	
+	
+	if editmode:
+		Blender.Window.EditMode(1)	
+	
+
+def update_mesh_colors(colors, mesh):
+	if 'FLT_COL' in mesh.faces.properties:
+		mesh.activeColorLayer = "FLT_Fcol"
+		for face in mesh.faces:
+			(index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
+			color = struct.unpack('>BBBB',struct.pack('>I',colors[index]))
+			
+			if index == 0 and intensity == 0:
+				color = (255,255,255)
+				intensity  = 1.0
+			#update the vertex colors for this face
+			for col in face.col:
+				col.r = int(color[0] * intensity)
+				col.g = int(color[1] * intensity)
+				col.b = int(color[2] * intensity)
+				col.a = 255
+	
+		
+def update_all():
+	
+	editmode = 0
+	if Blender.Window.EditMode():
+		Blender.Window.EditMode(0)
+		editmode = 1
+	state = update_state()
+	
+	if state["activeScene"].properties.has_key('FLT'):
+		try:
+			colors = state["activeScene"].properties['FLT']['Color Palette']
+		except:
+			colors = None
+	if colors:
+		#update the baked FLT colors for all meshes.
+		for object in state["activeScene"].objects:
+			if object.type == "Mesh":
+				mesh = object.getData(mesh=True)
+				update_mesh_colors(colors,mesh)
+	if editmode:
+		Blender.Window.EditMode(1)
 
 #Change this to find the deep parent
 def xref_create():
@@ -528,6 +673,8 @@ def but_event(evt):
 		clight_make()
 	if evt == evcode["DFROMACT"]:
 		dfromact()
+	if evt == evcode["FIXCOL"]:
+		fix_colors()
 	Draw.Redraw(1)
 	Blender.Window.RedrawAll()
 
@@ -582,17 +729,20 @@ def draw_postcommon(x,y,finaly):
 
 
 def draw_propsheet(x,y):
-        global XREF_PREFIX
-        global XREF_MAKE
-        global XREF_EDIT
-        global XREF_SELECT
-        global XREF_POP
-        global FACE_MAKESUB
-        global FACE_SELSUB
-        global FACE_KILLSUB
-        global IDPROP_KILL
-        global IDPROP_COPY
-        global SCENE_UPDATE
+	global XREF_PREFIX
+	global XREF_MAKE
+	global XREF_EDIT
+	global XREF_SELECT
+	global XREF_POP
+	global FACE_MAKESUB
+	global FACE_SELSUB
+	global FACE_KILLSUB
+	global IDPROP_KILL
+	global IDPROP_COPY
+	global SCENE_UPDATE
+	global DFROMACT
+	global FIXCOL
+		
 	global CLIGHT_MAKE
 	global xrefprefix
 	global xrefstack
@@ -643,11 +793,13 @@ def draw_propsheet(x,y):
 	
 	y=y-20
 	DFROMACT = Blender.Draw.PushButton("Dof from Active", evcode["DFROMACT"],x,y,width,20,"Get Dof origin from active object")
-        draw_postcommon(origx, origy,y)
+	y=y-20
+	FIXCOL = Blender.Draw.PushButton("Fix Colors", evcode["FIXCOL"],x,y,width,20,"Fix baked FLT colors of selected meshes") 	
+	draw_postcommon(origx, origy,y)
 		
 def gui():
 	#draw the propsheet/toolbox.
-	psheety = 280
+	psheety = 300
 	#psheetx = psheety + 10
 	draw_propsheet(0,psheety)
 Draw.Register(gui,event,but_event)
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
index 0a042c1612ac9ac5a1b5dac7c81006e370313ddb..ae4cdbe1cfe2e22a1f9bf963705562e0b774d173 100644
--- a/source/blender/blenkernel/BKE_bad_level_calls.h
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -89,7 +89,7 @@ int EXPP_dict_set_item_str(struct PyObject *dict, char *key, struct PyObject *va
 void Node_SetStack(struct BPy_Node *self, struct bNodeStack **stack, int type);
 void InitNode(struct BPy_Node *self, struct bNode *node);
 void Node_SetShi(struct BPy_Node *self, struct ShadeInput *shi);
-struct BPy_NodeSockets *Node_CreateSockets(struct bNode *node);
+struct BPy_NodeSockets *Node_CreateSocketLists(struct bNode *node);
 int pytype_is_pynode(struct PyObject *pyob);
 /* writefile.c */
 struct Oops;
diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h
index ca40295515b3c28483c6cb9cfa98f13c90ddd826..9229397e674ef879278a3a9b5aa0881a006ee5d8 100644
--- a/source/blender/blenkernel/BKE_bmesh.h
+++ b/source/blender/blenkernel/BKE_bmesh.h
@@ -93,7 +93,7 @@ typedef struct BME_Edge
 	void *data;										/*custom edge data*/
 	int eflag1, eflag2;								/*reserved for use by eulers*/
 	int tflag1, tflag2;								/*reserved for use by tools*/
-	unsigned char flag, h;
+	unsigned short flag, h;
 	float crease, bweight;
 } BME_Edge;
 
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 463254b8e4f565ee7598cfc040c27f54c8c8d08c..3889721b8c925183cdeb0b1c099443a9c4c107a4 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -172,7 +172,8 @@ void bvh_free ( BVH * bvh );
 // checks two bounding volume hierarchies for potential collisions and returns some list with those
 
 
-// update bounding volumes, needs updated positions in bvh->x
+// update bounding volumes, needs updated positions in  bvh->current_xold (static) 
+// and also bvh->current_x if moving==1
 void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving);
 void bvh_update(BVH * bvh, int moving);
 
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index e0b935fc1064cfb8e4875c0a28730ef51b7f44e5..53960a71470ab68d667ce0fe62af7c92dc823bbe 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -212,7 +212,7 @@ int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
 void psys_free_settings(struct ParticleSettings *part);
 void free_child_path_cache(struct ParticleSystem *psys);
 void psys_free_path_cache(struct ParticleSystem *psys);
-void free_hair(struct ParticleSystem *psys);
+void free_hair(struct ParticleSystem *psys, int softbody);
 void free_keyed_keys(struct ParticleSystem *psys);
 void psys_free(struct Object * ob, struct ParticleSystem * psys);
 void psys_free_children(struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h
index e03e38bab75017fe393a9e90e7a3e2c805bd7f4f..5d7ed28f5613c1ded89a82d4c2fd4f2a1ab21c4c 100644
--- a/source/blender/blenkernel/BKE_sculpt.h
+++ b/source/blender/blenkernel/BKE_sculpt.h
@@ -59,9 +59,6 @@ typedef struct SculptSession {
 	
 	struct RadialControl *radialcontrol;
 	
-	/* For rotating around a pivot point */
-	vec3f pivot;
-
 	struct SculptStroke *stroke;
 } SculptSession;
 
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index 1da46149eac59ad41f838fc541e7e3658069af2a..d0d6a892a8125f1b189dae3c14f38e3d9152bccd 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -128,7 +128,7 @@ int EXPP_dict_set_item_str(struct PyObject *dict, char *key, struct PyObject *va
 void Node_SetStack(struct BPy_Node *self, struct bNodeStack **stack, int type){}
 void InitNode(struct BPy_Node *self, struct bNode *node){}
 void Node_SetShi(struct BPy_Node *self, struct ShadeInput *shi){}
-struct BPy_NodeSockets *Node_CreateSockets(struct bNode *node)
+struct BPy_NodeSockets *Node_CreateSocketLists(struct bNode *node)
 {
 	return 0;
 }
@@ -367,3 +367,6 @@ void harmonic_coordinates_bind(struct MeshDeformModifierData *mmd,
 void PE_free_particle_edit(struct ParticleSystem *psys) {}
 void PE_get_colors(char sel[4], char nosel[4]) {}
 void PE_recalc_world_cos(struct Object *ob, struct ParticleSystem *psys) {}
+
+/* text.c */
+void txt_copy_clipboard (struct Text *text){}
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 4e00e29029c81c48f8c28bf441c548236d773a1a..9dcb6b6e7fab1392dbaaebbf07259c59b9be5623 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -1293,7 +1293,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
 			VertDataMulN(nCo, 1.0f/numEdges);
 		}
 
-		if ((sharpCount>1 && v->numFaces) || seam) {
+		if (sharpCount>1 || seam) {
 			VertDataZero(q);
 
 			if (seam) {
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index b8c05f3bb7b7284b3c5691a6ad4ba2800b4ae2ed..3b4de305545a25576bcbf15ab54af278f26adbbe 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -295,7 +295,7 @@ void copy_pose(bPose **dst, bPose *src, int copycon)
 	
 	outPose= MEM_callocN(sizeof(bPose), "pose");
 	
-	duplicatelist (&outPose->chanbase, &src->chanbase);
+	duplicatelist(&outPose->chanbase, &src->chanbase);
 	
 	if (copycon) {
 		for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) {
@@ -314,11 +314,11 @@ void free_pose_channels(bPose *pose)
 	
 	if (pose->chanbase.first) {
 		for (pchan = pose->chanbase.first; pchan; pchan=pchan->next){
-			if(pchan->path)
+			if (pchan->path)
 				MEM_freeN(pchan->path);
 			free_constraints(&pchan->constraints);
 		}
-		BLI_freelistN (&pose->chanbase);
+		BLI_freelistN(&pose->chanbase);
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 7ec56bd08abbfb7915a60fa67a7b6d5f7cc6d864..4bb31c1e9b916cd6cf8a28c3df325ba4b1f3d950 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1389,18 +1389,26 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
 	bPoseChannel *pchan, *pchanp, pchanw;
 	bConstraint *con;
 	
-	if(frompose==NULL) return;
+	if (frompose==NULL) return;
 	
 	/* exception, armature local layer should be proxied too */
-	if(pose->proxy_layer)
+	if (pose->proxy_layer)
 		((bArmature *)ob->data)->layer= pose->proxy_layer;
 	
 	/* clear all transformation values from library */
 	rest_pose(frompose);
 	
-	pchan= pose->chanbase.first;
-	for(; pchan; pchan= pchan->next) {
-		if(pchan->bone->layer & layer_protected) {
+	/* copy over all of the proxy's bone groups */
+		/* TODO for later - implement 'local' bone groups as for constraints
+		 *	Note: this isn't trivial, as bones reference groups by index not by pointer, 
+		 *		 so syncing things correctly needs careful attention
+		 */
+	BLI_freelistN(&pose->agroups);
+	duplicatelist(&pose->agroups, &frompose->agroups);
+	pose->active_group= frompose->active_group;
+	
+	for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+		if (pchan->bone->layer & layer_protected) {
 			ListBase proxylocal_constraints = {NULL, NULL};
 			pchanp= get_pose_channel(frompose, pchan->name);
 			
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index d28345713165a99800260aad287b4936fefe7475..a58fdab8c91c391d556b61a3f5775f4a156fa871 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -190,11 +190,6 @@ BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
 	
 	// springs = cloth->springs;
 	// numsprings = cloth->numsprings;
-	
-	bvh->flags = 0;
-	bvh->leaf_tree = NULL;
-	bvh->leaf_root = NULL;
-	bvh->tree = NULL;
 
 	bvh->epsilon = epsilon;
 	bvh->numfaces = cloth->numfaces;
@@ -211,20 +206,9 @@ BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon)
 		return NULL;
 	}
 	
-	bvh->current_xold = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_xold" );
-	
-	if (bvh->current_xold == NULL) 
-	{
-		printf("bvh: Out of memory.\n");
-		MEM_freeN(bvh->current_x);
-		MEM_freeN(bvh);
-		return NULL;
-	}
-	
 	for(i = 0; i < bvh->numverts; i++)
 	{
 		VECCOPY(bvh->current_x[i].co, verts[i].tx);
-		VECCOPY(bvh->current_xold[i].co, verts[i].txold);
 	}
 	
 	bvh_build (bvh);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index a1c49ac465526ca32a18d972dc9d9136f695d881..61f2288f8e8a4e2f219d4b4f86a4a7aba8b4afa9 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -69,6 +69,7 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev
 		VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step);
 		VECSUB(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co);
 	}
+	bvh_update_from_mvert(collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1);
 }
 
 /* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */
@@ -86,11 +87,6 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig
 	// in the moment, return zero if no faces there
 	if(!numfaces)
 		return NULL;
-	
-	bvh->flags = 0;
-	bvh->leaf_tree = NULL;
-	bvh->leaf_root = NULL;
-	bvh->tree = NULL;
 
 	bvh->epsilon = epsilon;
 	bvh->numfaces = numfaces;
@@ -103,8 +99,7 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig
 	}
 
 	bvh->numverts = numverts;
-	bvh->current_x = MEM_dupallocN(x);	
-	bvh->current_xold = MEM_dupallocN(x);	
+	bvh->current_x = MEM_dupallocN(x);
 	
 	bvh_build(bvh);
 	
@@ -432,6 +427,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa
 	float w1, w2, w3, u1, u2, u3;
 	float v1[3], v2[3], relativeVelocity[3];
 	float magrelVel;
+	float epsilon2 = collmd->bvh->epsilon;
 	
 	cloth1 = clmd->clothObject;
 
@@ -515,7 +511,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa
 			
 			// Apply repulse impulse if distance too short
 			// I_r = -min(dt*kd, m(0,1d/dt - v_n))
-			d = clmd->coll_parms->epsilon*8.0/9.0 - collpair->distance;
+			d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance;
 			if((magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame) && (d > ALMOST_ZERO))
 			{
 				repulse = MIN2(d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel);
@@ -562,6 +558,7 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree
 	ClothVertex *verts1=NULL;
 	double distance = 0;
 	float epsilon = clmd->coll_parms->epsilon;
+	float epsilon2 = ((CollisionModifierData *)md2)->bvh->epsilon;
 	unsigned int i = 0;
 
 	for(i = 0; i < 4; i++)
@@ -646,9 +643,9 @@ void cloth_collision_static(ModifierData *md1, ModifierData *md2, CollisionTree
 					verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector);
 #else
 			// just be sure that we don't add anything
-			distance = 2.0 * (epsilon + ALMOST_ZERO);
+			distance = 2.0 * (epsilon + epsilon2 + ALMOST_ZERO);
 #endif	
-			if (distance <= (epsilon + ALMOST_ZERO))
+			if (distance <= (epsilon + epsilon2 + ALMOST_ZERO))
 			{
 				// printf("dist: %f\n", (float)distance);
 				
@@ -973,12 +970,15 @@ int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData *
 	
 	verts = cloth->verts;
 	
-	if (collmd->tree) 
+	if (collmd->bvh) 
 	{
-		BVH *coll_bvh = collmd->tree;
-				
+		/* get pointer to bounding volume hierarchy */
+		BVH *coll_bvh = collmd->bvh;
+		
+		/* move object to position (step) in time */
 		collision_move_object(collmd, step + dt, step);
-					
+		
+		/* search for overlapping collision pairs */
 		bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0);
 	}
 	else
@@ -993,7 +993,7 @@ int cloth_bvh_objcollisions_do(ClothModifierData * clmd, CollisionModifierData *
 	{
 		result = 0;
 				
-		if (collmd->tree) 
+		if (collmd->bvh) 
 			result += cloth_collision_response_static(clmd, collmd);
 				
 				// apply impulses in parallel
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index dcd8bc6d9ebcfb51494b60bfce40f52fa1affa14..0b33cc3a75b4549d8530077d61e319ee350f8c0a 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1976,13 +1976,16 @@ float calc_curve_subdiv_radius(Curve *cu, Nurb *nu, int cursubdiv)
 		if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) {
 			if (bp >= bplast) bp = bpfirst;
 			else bp++;
+		} else if ( bp > bplast ) {
+			/* this can happen in rare cases, refer to bug [#8596] */
+			bp = bplast;
 		}
 		
 		rad = prevrad = bp->radius;
 		
 		if ((bp == bplast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
 			bp= bpfirst;
-		} else if (bp != bplast) {
+		} else if (bp < bplast) {
 			bp++;
 		}
 		nextrad = bp->radius;
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 21e58f88aad00f0b45f1e72db1ff29178320ec0d..4c39f36800c0768fec5103bdbb1988ddadde6617 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -37,13 +37,11 @@
 #include "DNA_cloth_types.h"	
 #include "DNA_scene_types.h"
 
-
 #include "BKE_effect.h"
 #include "BKE_global.h"
 #include "BKE_cloth.h"
 #include "BKE_utildefines.h"
 
-
 #ifdef _WIN32
 #include <windows.h>
 static LARGE_INTEGER _itstart, _itend;
@@ -1458,11 +1456,11 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec
 			speed[0] = speed[1] = speed[2] = 0.0;
 			if(mfaces[i].v4)
 			{
-				pdDoEffectors(effectors, lX[i], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
+				pdDoEffectors(effectors, lX[mfaces[i].v4], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
 				VECCOPY(wind_normalized, speed);
 				Normalize(wind_normalized);
 				VecMulf(wind_normalized, -calculateVertexWindForce(speed, vertexnormal) * verts[mfaces[i].v4].mass);
-				VECADDS(lF[i], lF[i], wind_normalized, 0.25);
+				VECADDS(lF[mfaces[i].v4], lF[mfaces[i].v4], wind_normalized, 0.25);
 			}
 			
 		}
diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c
index 79a9559250fad870b0a47dced8d47ac16bb7b26e..9fb476614d33f69c40d6ce5405b26486dce58308 100644
--- a/source/blender/blenkernel/intern/kdop.c
+++ b/source/blender/blenkernel/intern/kdop.c
@@ -476,14 +476,15 @@ static void bvh_div_env_node(BVH *bvh, CollisionTree *tree, CollisionTree **face
 	// Sort along longest axis
 	if(laxis!=lastaxis)
 		bvh_sort_along_axis(face_list, start, end, laxis);
-
+	
+	// maximum is 4 since we have a quad tree
 	max_nodes = MIN2((end-start + 1 ),4);
 
 	for (i = 0; i < max_nodes; i++)
 	{
 		tree->count_nodes++;
 
-		if(end-start > 4)
+		if(end-start+1 > 4)
 		{
 			int quarter = ((float)((float)(end - start + 1) / 4.0f));
 			tstart = start + i * quarter;
@@ -537,18 +538,32 @@ void bvh_build (BVH *bvh)
 	CollisionTree *tree=NULL;
 	LinkNode *nlink = NULL;
 	
+	bvh->flags = 0;
+	bvh->leaf_tree = NULL;
+	bvh->leaf_root = NULL;
+	bvh->tree = NULL;
+	
+	if(!bvh->current_x)
+	{
+		bvh_free(bvh);
+		return;
+	}
+	
+	bvh->current_xold = MEM_dupallocN(bvh->current_x);
+	
 	tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
-	// TODO: check succesfull alloc
-	BLI_linklist_append(&bvh->tree, tree);
-
-	nlink = bvh->tree;
-
+	
 	if (tree == NULL) 
 	{
 		printf("bvh_build: Out of memory for nodes.\n");
 		bvh_free(bvh);
 		return;
 	}
+	
+	BLI_linklist_append(&bvh->tree, tree);
+
+	nlink = bvh->tree;
+
 	bvh->root = bvh->tree->link;
 	bvh->root->isleaf = 0;
 	bvh->root->parent = NULL;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 42cac46c241da52ff41839b637139828e07f6826..1b95ae14ecf854792e5292af7ba653163aeab7ce 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -633,9 +633,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
 	
 	if(ma->flarec==0) ma->flarec= 1;
 
-	/* add all texcoflags from mtex */
-	ma->texco= 0;
-	ma->mapto= 0;
+	/* add all texcoflags from mtex, texco and mapto were cleared in advance */
 	for(a=0; a<MAX_MTEX; a++) {
 		
 		/* separate tex switching */
@@ -730,6 +728,16 @@ void init_render_materials(int r_mode, float *amb)
 {
 	Material *ma;
 	
+	/* clear these flags before going over materials, to make sure they
+	 * are cleared only once, otherwise node materials contained in other
+	 * node materials can go wrong */
+	for(ma= G.main->mat.first; ma; ma= ma->id.next) {
+		if(ma->id.us) {
+			ma->texco= 0;
+			ma->mapto= 0;
+		}
+	}
+
 	/* two steps, first initialize, then or the flags for layers */
 	for(ma= G.main->mat.first; ma; ma= ma->id.next) {
 		/* is_used flag comes back in convertblender.c */
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3bfd605cf2732b37081f7b19ba9692e3a1f89080..9155a5ee444d8c35f216b153b574665931ccc204 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1109,9 +1109,13 @@ float (*mesh_getRefKeyCos(Mesh *me, int *numVerts_r))[3]
 	
 	if(me->key && me->key->refkey) {
 		if(numVerts_r) *numVerts_r= me->totvert;
-		cos= MEM_mallocN(sizeof(*cos)*me->totvert, "vertexcos1");
-
+		
 		kb= me->key->refkey;
+		
+		/* prevent accessing invalid memory */
+		if (me->totvert > kb->totelem)		cos= MEM_callocN(sizeof(*cos)*me->totvert, "vertexcos1");
+		else								cos= MEM_mallocN(sizeof(*cos)*me->totvert, "vertexcos1");
+		
 		totvert= MIN2(kb->totelem, me->totvert);
 
 		memcpy(cos, kb->data, sizeof(*cos)*totvert);
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 4db391ddc95e15bea641483b2b81643c9c224020..4aa69daa6d0606e5dc22a604338d4b467adb5abe 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -5037,8 +5037,8 @@ static void clothModifier_initData(ModifierData *md)
 {
 	ClothModifierData *clmd = (ClothModifierData*) md;
 	
-	clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings), "cloth sim parms");
-	clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings), "cloth coll parms");
+	clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
+	clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
 	
 	/* check for alloc failing */
 	if(!clmd->sim_parms || !clmd->coll_parms)
@@ -5055,7 +5055,12 @@ static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob,
 	
 	/* check for alloc failing */
 	if(!clmd->sim_parms || !clmd->coll_parms)
-		return derivedData;
+	{
+		clothModifier_initData(md);
+		
+		if(!clmd->sim_parms || !clmd->coll_parms)
+			return derivedData;
+	}
 
 	result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc);
 
@@ -5090,7 +5095,7 @@ static void clothModifier_updateDepgraph(
 				}
 			}
 		}
-	}	
+	}
 }
 
 CustomDataMask clothModifier_requiredDataMask(ModifierData *md)
@@ -5156,7 +5161,7 @@ static void collisionModifier_initData(ModifierData *md)
 	collmd->current_v = NULL;
 	collmd->time = -1;
 	collmd->numverts = 0;
-	collmd->tree = NULL;
+	collmd->bvh = NULL;
 }
 
 static void collisionModifier_freeData(ModifierData *md)
@@ -5165,8 +5170,8 @@ static void collisionModifier_freeData(ModifierData *md)
 	
 	if (collmd) 
 	{
-		if(collmd->tree)
-			bvh_free(collmd->tree);
+		if(collmd->bvh)
+			bvh_free(collmd->bvh);
 		if(collmd->x)
 			MEM_freeN(collmd->x);
 		if(collmd->xnew)
@@ -5188,7 +5193,7 @@ static void collisionModifier_freeData(ModifierData *md)
 		collmd->current_v = NULL;
 		collmd->time = -1;
 		collmd->numverts = 0;
-		collmd->tree = NULL;
+		collmd->bvh = NULL;
 		collmd->mfaces = NULL;
 	}
 }
@@ -5258,7 +5263,7 @@ static void collisionModifier_deformVerts(
 				
 				// TODO: epsilon
 				// create bounding box hierarchy
-				collmd->tree = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sbift);
+				collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
 				
 				collmd->time = current_time;
 			}
@@ -5281,14 +5286,14 @@ static void collisionModifier_deformVerts(
 				memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
 				
 				/* happens on file load (ONLY when i decomment changes in readfile.c */
-				if(!collmd->tree)
+				if(!collmd->bvh)
 				{
-					collmd->tree = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sbift);
+					collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
 				}
 				else
 				{
 					// recalc static bounding boxes
-					bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0);
+					bvh_update_from_mvert(collmd->bvh, collmd->current_x, numverts, NULL, 0);
 				}
 				
 				collmd->time = current_time;
@@ -5527,6 +5532,7 @@ static void particleSystemModifier_deformVerts(
 
 	/* make new dm */
 	psmd->dm=CDDM_copy(dm);
+	CDDM_apply_vert_coords(psmd->dm, vertexCos);
 	CDDM_calc_normals(psmd->dm);
 
 	if(needsFree){
@@ -6747,7 +6753,7 @@ static void meshdeformModifier_do(
                 float (*vertexCos)[3], int numVerts)
 {
 	MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
-	float imat[4][4], cagemat[4][4], icagemat[4][4], iobmat[3][3];
+	float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
 	float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3];
 	int a, b, totvert, totcagevert, defgrp_index;
 	DerivedMesh *tmpdm, *cagedm;
@@ -6773,8 +6779,9 @@ static void meshdeformModifier_do(
  	/* compute matrices to go in and out of cage object space */
 	Mat4Invert(imat, mmd->object->obmat);
 	Mat4MulMat4(cagemat, ob->obmat, imat);
-	Mat4Invert(icagemat, cagemat);
-	Mat3CpyMat4(iobmat, icagemat);
+	Mat4MulMat4(cmat, cagemat, mmd->bindmat);
+	Mat4Invert(iobmat, cmat);
+	Mat3CpyMat4(icagemat, iobmat);
 
 	/* bind weights if needed */
 	if(!mmd->bindcos)
@@ -6872,7 +6879,7 @@ static void meshdeformModifier_do(
 
 		if(totweight > 0.0f) {
 			VecMulf(co, fac/totweight);
-			Mat3MulVecfl(iobmat, co);
+			Mat3MulVecfl(icagemat, co);
 			if(G.rt != 527)
 				VECADD(vertexCos[b], vertexCos[b], co)
 			else
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index bc9aa23ee157e10378d2dfec062f9b41f08164e7..6c3775bcbaacd64cdbe281d2fde26f55174f1d94 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -534,6 +534,14 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
 					break;
 				}
 			}
+
+			/* set socket own_index to zero since it can still have a value
+			 * from being in a group before, otherwise it doesn't get a unique
+			 * index in group_verify_own_indices */
+			for(sock= node->inputs.first; sock; sock= sock->next)
+				sock->own_index= 0;
+			for(sock= node->outputs.first; sock; sock= sock->next)
+				sock->own_index= 0;
 		}
 	}
 
@@ -589,6 +597,10 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
 			}
 		}
 	}
+
+	/* update node levels */
+	ntreeSolveOrder(ntree);
+
 	return gnode;
 }
 
@@ -1356,11 +1368,21 @@ bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
 	bNode *node;
 	
 	if(ntree==NULL) return NULL;
+
+	/* check for group edit */
+    for(node= ntree->nodes.first; node; node= node->next)
+		if(node->flag & NODE_GROUP_EDIT)
+			break;
+
+	if(node)
+		ntree= (bNodeTree*)node->id;
 	
+	/* now find active node with this id */
 	for(node= ntree->nodes.first; node; node= node->next)
 		if(node->id && GS(node->id->name)==idtype)
 			if(node->flag & NODE_ACTIVE_ID)
 				break;
+
 	return node;
 }
 
@@ -1781,7 +1803,7 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group)
 		
 		if(is_group==0) {
 			for(sock= node->outputs.first; sock; sock= sock->next) {
-				bNodeStack *ns= ntree->stack[0] + sock->stack_index;
+				bNodeStack *ns= ntree->stack + sock->stack_index;
 				
 				if(sock->ns.data) {
 					ns->data= sock->ns.data;
@@ -1814,7 +1836,7 @@ static void composit_end_exec(bNodeTree *ntree, int is_group)
 			bNodeSocket *sock;
 		
 			for(sock= node->outputs.first; sock; sock= sock->next) {
-				ns= ntree->stack[0] + sock->stack_index;
+				ns= ntree->stack + sock->stack_index;
 				if(ns->data) {
 					sock->ns.data= ns->data;
 					ns->data= NULL;
@@ -1832,7 +1854,7 @@ static void composit_end_exec(bNodeTree *ntree, int is_group)
 	
 	if(is_group==0) {
 		/* internally, group buffers are not stored */
-		for(ns= ntree->stack[0], a=0; a<ntree->stacksize; a++, ns++) {
+		for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) {
 			if(ns->data) {
 				printf("freed leftover buffer from stack\n");
 				free_compbuf(ns->data);
@@ -1873,15 +1895,47 @@ static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack)
 /* per tree (and per group) unique indices are created */
 /* the index_ext we need to be able to map from groups to the group-node own stack */
 
+typedef struct bNodeThreadStack {
+	struct bNodeThreadStack *next, *prev;
+	bNodeStack *stack;
+	int used;
+} bNodeThreadStack;
+
+static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread)
+{
+	ListBase *lb= &ntree->threadstack[thread];
+	bNodeThreadStack *nts;
+
+	for(nts=lb->first; nts; nts=nts->next) {
+		if(!nts->used) {
+			nts->used= 1;
+			return nts;
+		}
+	}
+	
+	nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
+	nts->stack= MEM_dupallocN(ntree->stack);
+	nts->used= 1;
+	BLI_addtail(lb, nts);
+
+	return nts;
+}
+
+static void ntreeReleaseThreadStack(bNodeThreadStack *nts)
+{
+	nts->used= 0;
+}
+
 void ntreeBeginExecTree(bNodeTree *ntree)
 {
 	/* let's make it sure */
 	if(ntree->init & NTREE_EXEC_INIT)
 		return;
-	
-	/* allocate the stack pointer array */
-	ntree->stack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(void *), "stack array");
-	
+
+	/* allocate the thread stack listbase array */
+	if(ntree->type!=NTREE_COMPOSIT)
+		ntree->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array");
+
 	/* goes recursive over all groups */
 	ntree->stacksize= ntree_begin_exec_tree(ntree);
 
@@ -1891,7 +1945,7 @@ void ntreeBeginExecTree(bNodeTree *ntree)
 		int a;
 		
 		/* allocate the base stack */
-		ns=ntree->stack[0]= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack");
+		ns=ntree->stack= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack");
 		
 		/* tag inputs, the get_stack() gives own socket stackdata if not in use */
 		for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1;
@@ -1901,7 +1955,7 @@ void ntreeBeginExecTree(bNodeTree *ntree)
 			bNodeSocket *sock;
 			for(sock= node->inputs.first; sock; sock= sock->next) {
 				if(sock->link) {
-					ns= ntree->stack[0] + sock->link->fromsock->stack_index;
+					ns= ntree->stack + sock->link->fromsock->stack_index;
 					ns->hasoutput= 1;
 					ns->sockettype= sock->link->fromsock->type;
 				}
@@ -1909,16 +1963,11 @@ void ntreeBeginExecTree(bNodeTree *ntree)
 					sock->ns.sockettype= sock->type;
 			}
 			if(node->type==NODE_GROUP && node->id)
-				group_tag_used_outputs(node, ntree->stack[0]);
+				group_tag_used_outputs(node, ntree->stack);
 		}
 		
-		/* composite does 1 node per thread, so no multiple stacks needed */
 		if(ntree->type==NTREE_COMPOSIT)
 			composit_begin_exec(ntree, 0);
-		else {
-			for(a=1; a<BLENDER_MAX_THREADS; a++)
-				ntree->stack[a]= MEM_dupallocN(ntree->stack[0]);
-		}
 	}
 	
 	ntree->init |= NTREE_EXEC_INIT;
@@ -1928,6 +1977,7 @@ void ntreeEndExecTree(bNodeTree *ntree)
 {
 	
 	if(ntree->init & NTREE_EXEC_INIT) {
+		bNodeThreadStack *nts;
 		int a;
 		
 		/* another callback candidate! */
@@ -1935,14 +1985,21 @@ void ntreeEndExecTree(bNodeTree *ntree)
 			composit_end_exec(ntree, 0);
 		
 		if(ntree->stack) {
-			for(a=0; a<BLENDER_MAX_THREADS; a++)
-				if(ntree->stack[a])
-					MEM_freeN(ntree->stack[a]);
-		
 			MEM_freeN(ntree->stack);
 			ntree->stack= NULL;
 		}
 
+		if(ntree->threadstack) {
+			for(a=0; a<BLENDER_MAX_THREADS; a++) {
+				for(nts=ntree->threadstack[a].first; nts; nts=nts->next)
+					MEM_freeN(nts->stack);
+				BLI_freelistN(&ntree->threadstack[a]);
+			}
+
+			MEM_freeN(ntree->threadstack);
+			ntree->threadstack= NULL;
+		}
+
 		ntree->init &= ~NTREE_EXEC_INIT;
 	}
 }
@@ -1971,12 +2028,20 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
 	bNodeStack *nsin[MAX_SOCKET];	/* arbitrary... watch this */
 	bNodeStack *nsout[MAX_SOCKET];	/* arbitrary... watch this */
 	bNodeStack *stack;
+	bNodeThreadStack *nts = NULL;
 	
 	/* only when initialized */
 	if((ntree->init & NTREE_EXEC_INIT)==0)
 		ntreeBeginExecTree(ntree);
 		
-	stack= ntree->stack[thread];
+	/* composite does 1 node per thread, so no multiple stacks needed */
+	if(ntree->type==NTREE_COMPOSIT) {
+		stack= ntree->stack;
+	}
+	else {
+		nts= ntreeGetThreadStack(ntree, thread);
+		stack= nts->stack;
+	}
 	
 	for(node= ntree->nodes.first; node; node= node->next) {
 		if(node->typeinfo->execfunc) {
@@ -1988,6 +2053,9 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
 			node_group_execute(stack, callerdata, node, nsin, nsout); 
 		}
 	}
+
+	if(nts)
+		ntreeReleaseThreadStack(nts);
 }
 
 
@@ -2169,7 +2237,7 @@ static void freeExecutableNode(bNodeTree *ntree)
 	for(node= ntree->nodes.first; node; node= node->next) {
 		if(node->exec & NODE_FREEBUFS) {
 			for(sock= node->outputs.first; sock; sock= sock->next) {
-				bNodeStack *ns= ntree->stack[0] + sock->stack_index;
+				bNodeStack *ns= ntree->stack + sock->stack_index;
 				if(ns->data) {
 					free_compbuf(ns->data);
 					ns->data= NULL;
@@ -2223,7 +2291,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
 	
 	/* setup callerdata for thread callback */
 	thdata.rd= rd;
-	thdata.stack= ntree->stack[0];
+	thdata.stack= ntree->stack;
 	
 	/* fixed seed, for example noise texture */
 	BLI_srandom(rd->cfra);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 27c4091e36f032ec0bcffd1d20139e02f2ec757f..04e9d63b9b5b3274378d8643d8b9f3e956cc1021 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -275,7 +275,8 @@ void psys_free_settings(ParticleSettings *part)
 	if(part->pd)
 		MEM_freeN(part->pd);
 }
-void free_hair(ParticleSystem *psys)
+
+void free_hair(ParticleSystem *psys, int softbody)
 {
 	ParticleData *pa;
 	int i, totpart=psys->totpart;
@@ -288,7 +289,7 @@ void free_hair(ParticleSystem *psys)
 
 	psys->flag &= ~PSYS_HAIR_DONE;
 
-	if(psys->soft) {
+	if(softbody && psys->soft) {
 		sbFree(psys->soft);
 		psys->soft = NULL;
 	}
@@ -342,7 +343,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
 
 		psys_free_path_cache(psys);
 
-		free_hair(psys);
+		free_hair(psys, 1);
 
 		free_keyed_keys(psys);
 
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 568a3a34d912d8e12e5dd5f6702ca8658b820976..b48bfc4f2b88121544b11736e9d0b7c6d1149aac 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4476,7 +4476,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
 			part->rotfrom = PART_ROT_IINCR;
 		}
 		else
-			free_hair(psys);
+			free_hair(psys, 1);
 
 		psys->softflag= 0;
 		psys->recalc &= ~PSYS_TYPE;
@@ -4656,7 +4656,8 @@ void particle_system_update(Object *ob, ParticleSystem *psys){
 	if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)){
 		float hcfra=0.0f;
 		int i;
-		free_hair(psys);
+
+		free_hair(psys, 0);
 
 		/* first step is negative so particles get killed and reset */
 		psys->cfra=1.0f;
diff --git a/source/blender/blenkernel/intern/script.c b/source/blender/blenkernel/intern/script.c
index 099fedf460af34cc748af46b7b0bc2652d72156c..2836f5fd507d584fbea8800e4411bcf9860139b7 100644
--- a/source/blender/blenkernel/intern/script.c
+++ b/source/blender/blenkernel/intern/script.c
@@ -60,12 +60,5 @@
 void free_script (Script *script)
 {
 	if (!script) return;
-
-	if (script->py_globaldict || script->py_button ||
-			script->py_event || script->py_draw)
-	{
-		BPY_clear_script(script);
-	}
-
-	return;
+	BPY_clear_script(script);
 }
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 3b8292a791c9c3c7ffb82f3673486bbb8a9b37be..ab0aecdd36329737089e70a3fe105f20762e983d 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -55,6 +55,7 @@
 #include "DNA_image_types.h"
 #include "DNA_world_types.h"
 #include "DNA_brush_types.h"
+#include "DNA_node_types.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
@@ -75,6 +76,7 @@
 #include "BKE_icons.h"
 #include "BKE_ipo.h"
 #include "BKE_brush.h"
+#include "BKE_node.h"
 
 
 /* ------------------------------------------------------------------------- */
@@ -729,6 +731,7 @@ Tex *give_current_texture(Object *ob, int act)
 	Lamp *la = 0;
 	MTex *mtex = 0;
 	Tex *tex = 0;
+	bNode *node;
 	
 	if(ob==0) return 0;
 	if(ob->totcol==0) return 0;
@@ -739,7 +742,6 @@ Tex *give_current_texture(Object *ob, int act)
 			mtex= la->mtex[(int)(la->texact)];
 			if(mtex) tex= mtex->tex;
 		}
-		else tex= 0;
 	} else {
 		if(act>ob->totcol) act= ob->totcol;
 		else if(act==0) act= 1;
@@ -752,13 +754,25 @@ Tex *give_current_texture(Object *ob, int act)
 			
 			if(matarar && *matarar) ma= (*matarar)[act-1];
 			else ma= 0;
-			
+		}
+
+		if(ma && ma->use_nodes && ma->nodetree) {
+			node= nodeGetActiveID(ma->nodetree, ID_TE);
+
+			if(node) {
+				tex= (Tex *)node->id;
+				ma= NULL;
+			}
+			else {
+				node= nodeGetActiveID(ma->nodetree, ID_MA);
+				if(node)
+					ma= (Material*)node->id;
+			}
 		}
 		if(ma) {
 			mtex= ma->mtex[(int)(ma->texact)];
 			if(mtex) tex= mtex->tex;
 		}
-		else tex= 0;
 	}
 	
 	return tex;
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index 99e30bc91c0f1a589e8bcc35d779c25ed9511e43..3055f62ae3dea03b17505e2e36a2b61294028eaa 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -400,6 +400,16 @@ void DQuatNormalize(DualQuat *dq, float totweight);
 void DQuatMulVecfl(DualQuat *dq, float *co, float mat[][3]);
 void DQuatCpyDQuat(DualQuat *dq1, DualQuat *dq2);
 			  
+/* Tangent stuff */
+typedef struct VertexTangent {
+	float tang[3], uv[2];
+	struct VertexTangent *next;
+} VertexTangent;
+
+void sum_or_add_vertex_tangent(void *arena, VertexTangent **vtang, float *tang, float *uv);
+float *find_vertex_tangent(VertexTangent *vtang, float *uv);
+void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, float *co3, float *n, float *tang);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenlib/intern/BLI_storage.h b/source/blender/blenlib/intern/BLI_storage.h
index 9cbdfa327cd6e7393f0632adc9c7319caa33a0a4..2c9932b650768f147d50cbc0d0a75ee232d18953 100644
--- a/source/blender/blenlib/intern/BLI_storage.h
+++ b/source/blender/blenlib/intern/BLI_storage.h
@@ -31,10 +31,12 @@
 #ifndef BLI_STORAGE_H
 #define BLI_STORAGE_H
 
+#ifndef __APPLE__
 #ifndef WIN32
 #define _LARGEFILE_SOURCE 1
 #define _FILE_OFFSET_BITS 64
 #endif
+#endif
 
 #include "BLI_storage_types.h"
 
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index cd7de83b9c0386e1d4dfd1fd2952e6a24518a81e..3514e695f59111afc3160dc3868b7cd5d8679754 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -57,6 +57,7 @@
 
 #include <stdio.h>
 #include "BLI_arithb.h"
+#include "BLI_memarena.h"
 
 /* A few small defines. Keep'em local! */
 #define SMALL_NUMBER	1.e-8
@@ -4268,3 +4269,75 @@ void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3
 	mat[3][1] = loc[1];
 	mat[3][2] = loc[2];
 }
+
+/* Tangents */
+
+/* For normal map tangents we need to detect uv boundaries, and only average
+ * tangents in case the uvs are connected. Alternative would be to store 1 
+ * tangent per face rather than 4 per face vertex, but that's not compatible
+ * with games */
+
+
+/* from BKE_mesh.h */
+#define STD_UV_CONNECT_LIMIT	0.0001f
+
+void sum_or_add_vertex_tangent(void *arena, VertexTangent **vtang, float *tang, float *uv)
+{
+	VertexTangent *vt;
+
+	/* find a tangent with connected uvs */
+	for(vt= *vtang; vt; vt=vt->next) {
+		if(fabs(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabs(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT) {
+			VecAddf(vt->tang, vt->tang, tang);
+			return;
+		}
+	}
+
+	/* if not found, append a new one */
+	vt= BLI_memarena_alloc((MemArena *)arena, sizeof(VertexTangent));
+	VecCopyf(vt->tang, tang);
+	vt->uv[0]= uv[0];
+	vt->uv[1]= uv[1];
+
+	if(*vtang)
+		vt->next= *vtang;
+	*vtang= vt;
+}
+
+float *find_vertex_tangent(VertexTangent *vtang, float *uv)
+{
+	VertexTangent *vt;
+	static float nulltang[3] = {0.0f, 0.0f, 0.0f};
+
+	for(vt= vtang; vt; vt=vt->next)
+		if(fabs(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabs(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT)
+			return vt->tang;
+
+	return nulltang;	/* shouldn't happen, except for nan or so */
+}
+
+void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, float *co3, float *n, float *tang)
+{
+	float tangv[3], ct[3], e1[3], e2[3], s1, t1, s2, t2, det;
+
+	s1= uv2[0] - uv1[0];
+	s2= uv3[0] - uv1[0];
+	t1= uv2[1] - uv1[1];
+	t2= uv3[1] - uv1[1];
+	det= 1.0f / (s1 * t2 - s2 * t1);
+	
+	/* normals in render are inversed... */
+	VecSubf(e1, co1, co2);
+	VecSubf(e2, co1, co3);
+	tang[0] = (t2*e1[0] - t1*e2[0])*det;
+	tang[1] = (t2*e1[1] - t1*e2[1])*det;
+	tang[2] = (t2*e1[2] - t1*e2[2])*det;
+	tangv[0] = (s1*e2[0] - s2*e1[0])*det;
+	tangv[1] = (s1*e2[1] - s2*e1[1])*det;
+	tangv[2] = (s1*e2[2] - s2*e1[2])*det;
+	Crossf(ct, tang, tangv);
+
+	/* check flip */
+	if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f)
+		VecMulf(tang, -1.0f);
+}
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index f4a44b3a0dbb57e5d1a33a71c33ed2d8888d2d67..92fad291e83e886446e9631a33cbd4f63369f107 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -1,6 +1,6 @@
 /**
  *
- * $Id:
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -250,6 +250,8 @@ int BLI_system_thread_count( void )
 	mib[1] = HW_NCPU;
 	len = sizeof(t);
 	sysctl(mib, 2, &t, &len, NULL, 0);
+#	elif defined(__sgi)
+	t = sysconf(_SC_NPROC_ONLN);
 #	else
 	t = (int)sysconf(_SC_NPROCESSORS_ONLN);
 #	endif
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 09edfe90d02b79c58e061306e06cb9dd9e9cd8c7..b54d42080b0bd89575313b08a5e28e8e89a775ff 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -238,7 +238,7 @@ char *BLO_gethome(void);
 int BLO_has_bfile_extension(char *str);
 void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode);
 void BLO_library_append_(BlendHandle **libfiledata, struct direntry* filelist, int totfile, char *dir, char* file, short flag, int idcode);
-void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcode, short flag, struct Scene *scene);
+void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Scene *scene);
 
 BlendFileData* blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r);
 
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1557e970306db0cc31f00ab72071e794e90db0ca..330ae84f922da88550ffa07c984275d71ec71b98 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3051,11 +3051,14 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
 			clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
 			clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
 			
-			clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_LOADED;
-			clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE;
-			
-			if(clmd->sim_parms->presets > 10)
-				clmd->sim_parms->presets = 0;
+			if(clmd->sim_parms)
+			{
+				clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_LOADED;
+				clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE;
+				
+				if(clmd->sim_parms->presets > 10)
+					clmd->sim_parms->presets = 0;
+			}
 			
 		}
 		else if (md->type==eModifierType_Collision) {
@@ -3080,7 +3083,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
 			collmd->current_v = NULL;
 			collmd->time = -1;
 			collmd->numverts = 0;
-			collmd->tree = NULL;
+			collmd->bvh = NULL;
 			collmd->mfaces = NULL;
 			
 		}
@@ -7794,7 +7797,8 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
 					 * user.blend, lib.blend and lib_indirect.blend - if user.blend alredy references a "tree" from
 					 * lib_indirect.blend but lib.blend does too, linking in a Scene or Group from lib.blend can result in an
 					 * empty without the dupli group referenced. Once you save and reload the group would appier. - Campbell */
-					oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+					/* This crashes files, must look further into it */
+					/*oldnewmap_insert(fd->libmap, bhead->old, id, 1);*/
 					
 					change_idid_adr_fd(fd, bhead->old, id);
 					if(G.f & G_DEBUG) printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
@@ -8577,38 +8581,38 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r)
 /* common routine to append/link something from a library */
 
 static Library* library_append( Scene *scene, char* file, char *dir, int idcode,
-		int totsel, FileData *fd, struct direntry* filelist, int totfile, short flag)
+		int totsel, FileData **fd, struct direntry* filelist, int totfile, short flag)
 {
 	Main *mainl;
 	Library *curlib;
 
 	/* make mains */
-	blo_split_main(&fd->mainlist, G.main);
+	blo_split_main(&(*fd)->mainlist, G.main);
 
 	/* which one do we need? */
-	mainl = blo_find_main(fd, &fd->mainlist, dir, G.sce);
+	mainl = blo_find_main(*fd, &(*fd)->mainlist, dir, G.sce);
 	
-	mainl->versionfile= fd->fileversion;	/* needed for do_version */
+	mainl->versionfile= (*fd)->fileversion;	/* needed for do_version */
 	
 	curlib= mainl->curlib;
 	
 	if(totsel==0) {
-		append_named_part(fd, mainl, scene, file, idcode, flag);
+		append_named_part(*fd, mainl, scene, file, idcode, flag);
 	}
 	else {
 		int a;
 		for(a=0; a<totfile; a++) {
 			if(filelist[a].flags & ACTIVE) {
-				append_named_part(fd, mainl, scene, filelist[a].relname, idcode, flag);
+				append_named_part(*fd, mainl, scene, filelist[a].relname, idcode, flag);
 			}
 		}
 	}
 
 	/* make main consistant */
-	expand_main(fd, mainl);
+	expand_main(*fd, mainl);
 
 	/* do this when expand found other libs */
-	read_libraries(fd, &fd->mainlist);
+	read_libraries(*fd, &(*fd)->mainlist);
 
 	if(flag & FILE_STRINGCODE) {
 
@@ -8619,10 +8623,10 @@ static Library* library_append( Scene *scene, char* file, char *dir, int idcode,
 		BLI_makestringcode(G.sce, mainl->curlib->name);
 	}
 
-	blo_join_main(&fd->mainlist);
-	G.main= fd->mainlist.first;
+	blo_join_main(&(*fd)->mainlist);
+	G.main= (*fd)->mainlist.first;
 
-	lib_link_all(fd, G.main);
+	lib_link_all(*fd, G.main);
 	lib_verify_nodetree(G.main, 0);
 	fix_relpaths_library(G.sce, G.main); /* make all relative paths, relative to the open blend file */
 
@@ -8641,8 +8645,9 @@ static Library* library_append( Scene *scene, char* file, char *dir, int idcode,
 	/* 20041208: put back. It only linked direct, not indirect objects (ton) */
 	
 	/* patch to prevent switch_endian happens twice */
-	if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
-		blo_freefiledata( fd );
+	if((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
+		blo_freefiledata( *fd );
+		*fd = NULL;
 	}	
 
 	return curlib;
@@ -8653,11 +8658,11 @@ static Library* library_append( Scene *scene, char* file, char *dir, int idcode,
 /* append to G.scene */
 /* this should probably be moved into the Python code anyway */
 
-void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, 
+void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, 
 		int idcode, short flag, Scene *scene )
 {
 	/* try to append the requested object */
-	library_append( scene, name, dir, idcode, 0, (FileData *)bh, NULL, 0, flag );
+	library_append( scene, name, dir, idcode, 0, (FileData **)bh, NULL, 0, flag );
 
 	/* do we need to do this? */
 	DAG_scene_sort(G.scene);
@@ -8673,6 +8678,7 @@ void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
 void BLO_library_append_(BlendHandle** libfiledata, struct direntry* filelist, int totfile, char *dir, char* file, short flag, int idcode)
 {
 	FileData *fd= (FileData*) (*libfiledata);
+	int lastflags = fd->flags;
 	Library *curlib;
 	Base *centerbase;
 	Object *ob;
@@ -8705,12 +8711,7 @@ void BLO_library_append_(BlendHandle** libfiledata, struct direntry* filelist, i
 	
 	if(flag & FILE_AUTOSELECT) scene_deselect_all(G.scene);
 
-	curlib = library_append( G.scene, file, dir, idcode, totsel, fd, filelist, totfile,flag );
-
-	/* patch to prevent switch_endian happens twice */
-	if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
-		(*libfiledata)= 0;
-	}	
+	curlib = library_append( G.scene, file, dir, idcode, totsel, (FileData**) libfiledata, filelist, totfile,flag );
 
 	/* when not linking (appending)... */
 	if((flag & FILE_LINK)==0) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index d70fe17c67f04da69b3f26bef0c1c57a551ed246..4d8544ec09d542d6661a59f9c09210b8f09c4c33 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -859,8 +859,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
 		else if(md->type==eModifierType_Cloth) {
 			ClothModifierData *clmd = (ClothModifierData*) md;
 			
-			writestruct(wd, DATA, "SimulationSettings", 1, clmd->sim_parms);
-			writestruct(wd, DATA, "CollisionSettings", 1, clmd->coll_parms);
+			writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
+			writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
 			
 		} 
 		else if (md->type==eModifierType_Collision) {
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index dfa4e5831ba87de72ac684d6f80d838da574c63a..eaa80865f0877bada8085575928a7262b3994fa4 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -484,7 +484,7 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags)
 
 	/* allocate array for pixel data */
 	npixels = ibuf->x * ibuf->y;
-	if(ibuf->ftype & TIF_16BIT)
+	if(bitspersample == 16)
 		pixels16 = (unsigned short*)libtiff__TIFFmalloc(npixels *
 			samplesperpixel * sizeof(unsigned short));
 	else
@@ -499,7 +499,7 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags)
 	}
 
 	/* setup pointers */
-	if(ibuf->ftype & TIF_16BIT) {
+	if(bitspersample == 16) {
 		fromf = ibuf->rect_float;
 		to16   = pixels16;
 	}
diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h
index 82d6bb84281c3b45a3adb54b0e7211df8ddda05c..40c4df37f7186ead1ccb12e09843bc95153dbf49 100644
--- a/source/blender/include/BIF_transform.h
+++ b/source/blender/include/BIF_transform.h
@@ -107,7 +107,7 @@ int BIF_menuselectTransformOrientation(void);
 void BIF_selectTransformOrientation(struct TransformOrientation *ts);
 void BIF_selectTransformOrientationFromIndex(int index);
 
-char * BIF_menustringTransformOrientation(); /* the returned value was allocated and needs to be freed after use */
+char * BIF_menustringTransformOrientation(char *title); /* the returned value was allocated and needs to be freed after use */
 int BIF_countTransformOrientation();
 
 /* Drawing callbacks */
diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h
index c425cbc62ea6823e2365c73304b5def473903967..294c0ceb047ef19dba007abad4b7ad947b3f0254 100644
--- a/source/blender/include/BSE_drawview.h
+++ b/source/blender/include/BSE_drawview.h
@@ -59,6 +59,8 @@ unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsi
 
 void drawview3dspace(struct ScrArea *sa, void *spacedata);
 void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]);
+void draw_depth(struct ScrArea *sa, void *spacedata);
+void view3d_update_depths(struct View3D *v3d);
 
 int update_time(void);
 void calc_viewborder(struct View3D *v3d, struct rctf *viewborder_r);
diff --git a/source/blender/include/BSE_edit.h b/source/blender/include/BSE_edit.h
index 71f6b275fd84e4148e18f0de5bfd903cd68cbe12..cac022ab6c2e5b1823642274c6fb69228b8763be 100644
--- a/source/blender/include/BSE_edit.h
+++ b/source/blender/include/BSE_edit.h
@@ -40,6 +40,7 @@ int get_border(struct rcti *rect, short col);
 void countall(void);
 void snapmenu(void); 
 void mergemenu(void);
+void alignmenu(void); 
 void delete_context_selected(void);
 void duplicate_context_selected(void);
 void toggle_shading(void);
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 4ba1f4f02e868c4bf637d29cc08b43876cce5230..53fbd1ff72cb2381fa2427fb6ef7970a9c0f9998 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -44,7 +44,8 @@
 * as in stepsPerFrame comapred to the time step in the paper, I've used
 * variables with different names to minimize confusion.
 **/
-typedef struct SimulationSettings
+
+typedef struct ClothSimSettings
 {
 	short	vgroup_mass;	/* optional vertexgroup name for assigning weight.*/
 	short	vgroup_struct;  /* vertex group for scaling structural stiffness */
@@ -87,10 +88,10 @@ typedef struct SimulationSettings
 	short pad;
 	int pad2;
 }
-SimulationSettings;
+ClothSimSettings;
 
 
-typedef struct CollisionSettings
+typedef struct ClothCollSettings
 {
 	float	epsilon;		/* min distance for collisions.		*/
 	float	self_friction;		/* Fiction/damping with self contact.		 	*/
@@ -101,7 +102,7 @@ typedef struct CollisionSettings
 	int	flags;			/* collision flags defined in BKE_cloth.h */
 	float 	selfepsilon; 		/* for selfcollision */
 }
-CollisionSettings;
+ClothCollSettings;
 
 
 /**
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index dd1d8eb01b3bf3539b136c7bb4e7914af586cb7a..c62d012643a47b3f7a6d972afe3259b7fff11606 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -369,8 +369,8 @@ typedef struct ClothModifierData {
    ModifierData		modifier;
 
    struct Cloth *clothObject; /* The internal data structure for cloth. */
-   struct SimulationSettings *sim_parms; /* definition is in DNA_cloth_types.h */
-   struct CollisionSettings *coll_parms; /* definition is in DNA_cloth_types.h */
+   struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */
+   struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */
 } ClothModifierData;
 
 typedef struct CollisionModifierData {
@@ -381,15 +381,15 @@ typedef struct CollisionModifierData {
 	struct MVert *xold; /* unsued atm, but was discussed during sprint */
 	struct MVert *current_xnew; /* new position at the actual inter-frame step */
 	struct MVert *current_x; /* position at the actual inter-frame step */
-	struct MVert *current_v; /* position at the actual inter-frame step */
+	struct MVert *current_v; /* (xnew - x) at the actual inter-frame step */
 	
 	struct MFace *mfaces; /* object face data */
 	
 	unsigned int numverts;
 	unsigned int numfaces;
 	int pad;
-	float time;
-	struct BVH *tree;	/* collision tree for this cloth object */
+	float time;		/* cfra time of modifier */
+	struct BVH *bvh;	/* bounding volume hierarchy for this cloth object */
 } CollisionModifierData;
 
 typedef enum {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index f74e858c0e496e34b15708d33c55397ca2cc9579..eda37d952c111198ea82994845d3cdca135f5dc0 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -162,7 +162,8 @@ typedef struct bNodeTree {
 	
 	ListBase nodes, links;
 	
-	bNodeStack **stack;				/* stack is only while executing, no read/write in file */
+	bNodeStack *stack;				/* stack is only while executing, no read/write in file */
+	struct ListBase *threadstack;	/* same as above */
 	
 	int type, init;					/* set init on fileread */
 	int stacksize;					/* amount of elements in stack */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 869f1cb426d4b7a45e03570c53106954aaab3813..f31f9fff1424f1184a27a6bc37a9a91e05fc658e 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -468,6 +468,10 @@ typedef struct SculptData
 
 	/* Settings for each brush */
 	BrushData drawbrush, smoothbrush, pinchbrush, inflatebrush, grabbrush, layerbrush, flattenbrush;
+
+	/* For rotating around a pivot point */
+	float pivot[3];
+
 	short brush_type;
 
 	/* For the Brush Shape */
@@ -486,10 +490,10 @@ typedef struct SculptData
 	/* Symmetry is separate from the other BrushData because the same
 	   settings are always used for all brush types */
 	char symm;
-	
+
 	/* Added to store if the 'Rake' setting has been set */
 	char rake;
-	char pad[7];
+	char pad[3];
 } SculptData;
 
 typedef struct Scene {
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 180cbd2af37c720bc0cbbe12eba55687ae0b0fe4..df9ea872caa0bfe11b9d05507f0980e08bb6cbaf 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -103,7 +103,7 @@ typedef struct View3D {
 	
 	/**
 	 * The drawing mode for the 3d display. Set to OB_WIRE, OB_SOLID,
-	 * OB_SHADED or OB_TEXTURED */
+	 * OB_SHADED or OB_TEXTURE */
 	short drawtype;
 	short localview;
 	int lay, layact;
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_math.c b/source/blender/nodes/intern/CMP_nodes/CMP_math.c
index cf2af9bbc113b8da4784f6f527652c00f8c0af75..e317998b5fc92c2471b323d5296e367f30a85d9e 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_math.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_math.c
@@ -142,7 +142,6 @@ static void node_composit_exec_math(void *data, bNode *node, bNodeStack **in, bN
 	CompBuf *stackbuf; 
 
 	/* check for inputs and outputs for early out*/
-	if(in[0]->hasinput==0 && in[1]->hasinput==0) return;
 	if(out[0]->hasoutput==0) return;
 
 	/* no image-color operation */
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
index 662d8e8dde907bfc35795701a373e387685745dd..5e1803a6774baedb90cdbf81b1c60d582a003c1e 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c
@@ -63,7 +63,7 @@ static float avgLogLum(CompBuf *src, float* auto_key, float* Lav, float* Cav)
 }
 
 
-void static tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src)
+static void tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src)
 {
 	int x, y;
 	float dr, dg, db, al, igm = (ntm->gamma==0.f) ? 1 : (1.f / ntm->gamma);
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
index ec3a9f3e5d62e26de57a4bb16cd9ff1cbb84d0ed..36a3bd5b171565c9d08eb140aab149f2be99bd57 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
@@ -59,14 +59,6 @@ static PyObject *init_dynamicdict(void) {
 	return newscriptdict;
 }
 
-/* unused for now
-static void free_dynamicdict(PyObject *dict) {
-	if (dict!=NULL) {
-		Py_DECREF(dict);
-	}
-}
-*/
-
 static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
 {
 	bNodeType *ntype = list->first;
@@ -309,68 +301,6 @@ int nodeDynamicUnlinkText(ID *txtid) {
 	return 0; /* no pynodes used this text */
 }
 
-/*
-static void node_dynamic_free_all_typeinfos(ListBase *list)
-{
-	bNodeType *ntype, *ntnext;
-
-	ntype = list->first;
-
-	while (ntype) {
-		ntnext = ntype->next;
-		if (ntype->type == NODE_DYNAMIC && ntype->id) {
-			BLI_remlink(list, ntype);
-			node_dynamic_free_typeinfo_sockets(ntype);
-			node_dynamic_free_typeinfo(ntype);
-		}
-		ntype = ntnext;
-	}
-}
-*/
-/* Unload all pynodes: since the Game Engine restarts Python, we need
- * to recreate pynodes dicts and objects. First we get rid of them here: */
-/*
-void nodeDynamicUnloadAll(void)
-{
-	Material *ma;
-	bNode *nd;
-	PyGILState_STATE gilstate = PyGILState_Ensure();
-
-	for (ma= G.main->mat.first; ma; ma= ma->id.next) {
-		if (ma->nodetree) {
-			for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
-				if ((nd->type == NODE_DYNAMIC) && nd->id) {
-					node_dynamic_free_storage_cb(nd);
-					nd->typeinfo = NULL;
-					nd->custom1 = 0;
-					nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_LOADED);
-				}
-			}
-		}
-	}
-
-	node_dynamic_free_all_typeinfos(&node_all_shaders);
-
-	PyGILState_Release(gilstate);
-}
-
-void nodeDynamicReloadAll(void)
-{
-	Material *ma;
-	bNode *nd;
-
-	for (ma= G.main->mat.first; ma; ma= ma->id.next) {
-		if (ma->nodetree) {
-			for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
-				if ((nd->type == NODE_DYNAMIC) && nd->id) {
-					node_dynamic_setup(nd);
-				}
-			}
-		}
-	}
-}
-*/
-
 static void node_dynamic_pyerror_print(bNode *node)
 {
 	PyGILState_STATE gilstate = PyGILState_Ensure();
@@ -426,15 +356,17 @@ static int node_dynamic_parse(struct bNode *node)
 
 	while (PyDict_Next( (PyObject *)(nsd->dict), &pos, &key, &value)) {
 		/* look for the node object */
+		if (strcmp("Socket", PyString_AsString(key)) == 0)
+			continue; /* XXX ugly, fix it */
 		if (PyObject_TypeCheck(value, &PyType_Type)==1) {
-			BPy_NodeSockets *sockets = Node_CreateSockets(node);
+			BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node);
 
-			args = Py_BuildValue("(O)", sockets);
+			args = Py_BuildValue("(O)", socklists);
 
 			/* init it to get the input and output sockets */
 			pynode = PyObject_Call(value, args, NULL);
 
-			Py_DECREF(sockets);
+			Py_DECREF(socklists);
 			Py_DECREF(args);
 
 			if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) {
@@ -466,7 +398,7 @@ static int node_dynamic_parse(struct bNode *node)
 				node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
 				break;
 			}
-			break;
+			//break;
 		}
 	}
 
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index d7bd4f22fc6ccd990f0c2d332a9f792b57738472..bf7c4d7ad62fc2e5fb125ae03575987468caddcf 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -128,7 +128,9 @@ extern "C" {
 	void BPY_clear_script( struct Script *script );
 	void BPY_free_finished_script( struct Script *script );
 	void BPY_scripts_clear_pyobjects( void );
-
+	
+	void error_pyscript( void );
+	
 /* void BPY_Err_Handle(struct Text *text); */
 /* void BPY_clear_bad_scriptlink(struct ID *id, struct Text *byebye); */
 /* void BPY_clear_bad_scriptlist(struct ListBase *, struct Text *byebye); */
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index febf5e3ff31a009b7e920f39babefa15b41b97b1..1f028e4907054839fb2f27e6cbf9122e3ef2bc72 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -261,6 +261,7 @@ void BPY_start_python( int argc, char **argv )
 void BPY_end_python( void )
 {
 	Script *script = NULL;
+	Script *next_script = NULL;
 
 	PyGILState_Ensure(); /* finalizing, no need to grab the state */
 
@@ -281,8 +282,8 @@ void BPY_end_python( void )
 
 	/* Freeing all scripts here prevents problems with the order in which
 	 * Python is finalized and G.main is freed in exit_usiblender() */
-	for (script = G.main->script.first; script; script = script->id.next) {
-		BPY_clear_script(script);
+	for (script = G.main->script.first; script; script = next_script) {
+		next_script = script->id.next;
 		free_libblock( &G.main->script, script );
 	}
 
@@ -691,8 +692,7 @@ int BPY_txt_do_python_Text( struct Text *text )
 		BPY_Err_Handle( textname );
 		ReleaseGlobalDictionary( py_dict );
 		script->py_globaldict = NULL;
-		if( G.main->script.first )
-			free_libblock( &G.main->script, script );
+		free_libblock( &G.main->script, script );
 		PyGILState_Release(gilstate);
 		return 0;
 	} else {
@@ -785,14 +785,23 @@ int BPY_run_script(Script *script)
 		char fname[FILE_MAX];
 		char fpath[FILE_MAX];
 		char ftmp[FILE_MAX];
+		char *bpyhome = bpy_gethome(1);
 		
-		strcpy(ftmp, script->scriptname);
-		BLI_split_dirfile(ftmp, fpath, fname);
-		BLI_make_file_string("/", fpath, bpy_gethome(1), fname);
+		if (bpyhome) {
+			BLI_strncpy(ftmp, script->scriptname, sizeof(ftmp));
+			BLI_split_dirfile(ftmp, fpath, fname); /* get the filename only - fname */
+			BLI_strncpy(fpath, bpy_gethome(1), sizeof(fpath));
+			BLI_add_slash(fpath);
+			strcat(fpath, fname);
 		
-		if (BLI_exists(fpath)) {
-			strncpy(script->scriptname, fpath, sizeof(script->scriptname));
-		} else if (U.pythondir[0]) {
+			if (BLI_exists(fpath)) {
+				strncpy(script->scriptname, fpath, sizeof(script->scriptname));
+			} else {
+				bpyhome = NULL; /* a bit dodgy, this is so the line below runs */
+			}
+		}
+		
+		if (bpyhome == NULL && U.pythondir[0]) {
 			BLI_make_file_string("/", fpath, U.pythondir, fname);
 			if (BLI_exists(fpath)) {
 				strncpy(script->scriptname, fpath, sizeof(script->scriptname));
@@ -812,11 +821,13 @@ int BPY_run_script(Script *script)
 		Py_INCREF( Py_None );
 		pyarg = Py_None;
 	} else {
-		fp = fopen( script->scriptname, "rb" );
+		if (BLI_exists(script->scriptname)) {
+			fp = fopen( script->scriptname, "rb" );
+		}
+		
 		if( !fp ) {
 			printf( "Error loading script: couldn't open file %s\n", script->scriptname );
-			if( G.main->script.first )
-				free_libblock( &G.main->script, script );
+			free_libblock( &G.main->script, script );
 			PyGILState_Release(gilstate);
 			return 0;
 		}
@@ -842,8 +853,7 @@ int BPY_run_script(Script *script)
 
 	if( !setup_armature_weakrefs()){
 		printf("Oops - weakref dict\n");
-		if( G.main->script.first )
-			free_libblock( &G.main->script, script );
+		free_libblock( &G.main->script, script );
 		ReleaseGlobalDictionary( py_dict );
 		MEM_freeN( buffer );
 		PyGILState_Release(gilstate);
@@ -910,9 +920,8 @@ int BPY_run_script(Script *script)
 		BPY_Err_Handle( script->id.name + 2 );
 		ReleaseGlobalDictionary( py_dict );
 		script->py_globaldict = NULL;
-		if( G.main->script.first )
-			free_libblock( &G.main->script, script );
-		error( "Python script error: check console" );
+		free_libblock( &G.main->script, script );
+		error_pyscript(  );
 
 		PyGILState_Release(gilstate);
 		return 0;
@@ -1110,7 +1119,7 @@ void BPY_free_finished_script( Script * script )
 
 	if( PyErr_Occurred(  ) ) {	/* if script ended after filesel */
 		PyErr_Print(  );	/* eventual errors are handled now */
-		error( "Python script error: check console" );
+		error_pyscript(  );
 	}
 
 	PyGILState_Release(gilstate);
@@ -1146,6 +1155,7 @@ static void unlink_script( Script * script )
 	}
 }
 
+/* This is called from free_libblock( &G.main->script, script ); */
 void BPY_clear_script( Script * script )
 {
 	PyObject *dict;
@@ -2015,6 +2025,7 @@ float BPY_pydriver_eval(IpoDriver *driver)
 	}
 
 	result = ( float )PyFloat_AsDouble( retval );
+	Py_DECREF(retval);
 	
 	if (result == -1 && PyErr_Occurred()) {
 		result = pydriver_error(driver);
@@ -2961,3 +2972,7 @@ void BPY_scripts_clear_pyobjects( void )
 		SCRIPT_SET_NULL(script)
 	}
 }
+void error_pyscript( void )
+{
+	error("Python script error: check console");
+}
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index d520dded4861db3f8668612f509204413d62ec35..dbcd21f04f3b5a1d572f45a370e4cb16c9d218a3 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -865,8 +865,15 @@ static PyObject *Blender_Run(PyObject *self, PyObject *value)
 
 	if (script) script->flags |= SCRIPT_RUNNING; /* set */
 
-	if (!is_blender_text) free_libblock(&G.main->text, text);
-
+	if (!is_blender_text) {
+		
+		/* nice to remember the original filename, so the script can run on reload */
+		if (script) {
+			strncpy(script->scriptname, fname, sizeof(script->scriptname));
+			script->scriptarg[0] = '\0';
+		}	
+		free_libblock(&G.main->text, text);
+	}
 	Py_RETURN_NONE;
 }
 
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c
index 9ca0d8d2545863178048190d70ff4df7bda6f66d..844b9cc99ad5f20001f5b5b269f53a520282efa3 100644
--- a/source/blender/python/api2_2x/Constraint.c
+++ b/source/blender/python/api2_2x/Constraint.c
@@ -114,6 +114,8 @@ enum constraint_constants {
 	EXPP_CONSTR_LIMIT,
 	EXPP_CONSTR_CLAMP,
 	
+	EXPP_CONSTR_MODE,
+	
 	EXPP_CONSTR_LIMXMIN = LIMIT_XMIN,
 	EXPP_CONSTR_LIMXMAX = LIMIT_XMAX,
 	EXPP_CONSTR_LIMYMIN = LIMIT_YMIN,
@@ -904,6 +906,56 @@ static int stretchto_setter( BPy_Constraint *self, int type, PyObject *value )
 	}
 }
 
+static PyObject *distlimit_getter( BPy_Constraint * self, int type )
+{
+	bDistLimitConstraint *con = (bDistLimitConstraint *)(self->con->data);
+
+	switch( type ) {
+	case EXPP_CONSTR_TARGET:
+		return Object_CreatePyObject( con->tar );
+	case EXPP_CONSTR_BONE:
+		return PyString_FromString( con->subtarget );
+	case EXPP_CONSTR_RESTLENGTH:
+		return PyFloat_FromDouble( (double)con->dist );
+	case EXPP_CONSTR_MODE:
+		return PyInt_FromLong( (long)con->mode );
+	default:
+		return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+	}
+}
+
+static int distlimit_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+	bDistLimitConstraint *con = (bDistLimitConstraint *)(self->con->data);
+
+	switch( type ) {
+	case EXPP_CONSTR_TARGET: {
+		Object *obj = (( BPy_Object * )value)->object;
+		if( !BPy_Object_Check( value ) )
+			return EXPP_ReturnIntError( PyExc_TypeError, 
+					"expected BPy object argument" );
+		con->tar = obj;
+		return 0;
+		}
+	case EXPP_CONSTR_BONE: {
+		char *name = PyString_AsString( value );
+		if( !name )
+			return EXPP_ReturnIntError( PyExc_TypeError,
+					"expected string arg" );
+
+		BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+		return 0;
+		}
+	case EXPP_CONSTR_RESTLENGTH:
+		return EXPP_setFloatClamped( value, &con->dist, 0.0, 100.0 );
+	case EXPP_CONSTR_MODE:
+		return EXPP_setIValueRange( value, &con->mode, LIMITDIST_INSIDE, LIMITDIST_ONSURFACE, 'i' );
+	default:
+		return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+	}
+}
+
 static PyObject *followpath_getter( BPy_Constraint * self, int type )
 {
 	bFollowPathConstraint *con = (bFollowPathConstraint *)(self->con->data);
@@ -1391,11 +1443,40 @@ static PyObject *script_getter( BPy_Constraint * self, int type )
 	bPythonConstraint *con = (bPythonConstraint *)(self->con->data);
 
 	switch( type ) {
-		// FIXME!!!
-	//case EXPP_CONSTR_TARGET:
-	//	return Object_CreatePyObject( con->tar );
-	//case EXPP_CONSTR_BONE:
-	//	return PyString_FromString( con->subtarget );
+	case EXPP_CONSTR_TARGET:
+	case EXPP_CONSTR_BONE:
+		{
+			bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_PYTHON);
+			bConstraintTarget *ct;
+			PyObject *tlist=NULL, *val;
+			
+			if (cti) {
+				/* change space of targets */
+				if (cti->get_constraint_targets) {
+					ListBase targets = {NULL, NULL};
+					int num_tars=0, i=0;
+					
+					/* get targets, and create py-list for use temporarily */
+					num_tars= cti->get_constraint_targets(self->con, &targets);
+					if (num_tars) {
+						tlist= PyList_New(num_tars);
+						
+						for (ct=targets.first; ct; ct=ct->next, i++) {
+							if (type == EXPP_CONSTR_BONE)
+								val= PyString_FromString(ct->subtarget);
+							else
+								val= Object_CreatePyObject(ct->tar);
+							PyList_SET_ITEM(tlist, i, val);
+						}
+					}
+					
+					if (cti->flush_constraint_targets)
+						cti->flush_constraint_targets(self->con, &targets, 1);
+				}
+			}
+			
+			return tlist;
+		}
 	case EXPP_CONSTR_SCRIPT:
 		return Text_CreatePyObject( con->text );
 	case EXPP_CONSTR_PROPS:
@@ -1410,25 +1491,73 @@ static int script_setter( BPy_Constraint *self, int type, PyObject *value )
 	bPythonConstraint *con = (bPythonConstraint *)(self->con->data);
 
 	switch( type ) {
-		// FIXME!!!
-	//case EXPP_CONSTR_TARGET: {
-	//	Object *obj = (( BPy_Object * )value)->object;
-	//	if( !BPy_Object_Check( value ) )
-	//		return EXPP_ReturnIntError( PyExc_TypeError, 
-	//				"expected BPy object argument" );
-	//	con->tar = obj;
-	//	return 0;
-	//	}
-	//case EXPP_CONSTR_BONE: {
-	//	char *name = PyString_AsString( value );
-	//	if( !name )
-	//		return EXPP_ReturnIntError( PyExc_TypeError,
-	//				"expected string arg" );
-	//
-	//	BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
-	//
-	//	return 0;
-	//	}
+	case EXPP_CONSTR_TARGET:
+	case EXPP_CONSTR_BONE:
+		{
+			bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_PYTHON);
+			bConstraintTarget *ct;
+			int ok= 0;
+			
+			if (cti) {
+				/* change space of targets */
+				if (cti->get_constraint_targets) {
+					ListBase targets = {NULL, NULL};
+					int num_tars=0, i=0;
+					
+					/* get targets, and extract values from the given list */
+					num_tars= cti->get_constraint_targets(self->con, &targets);
+					if (num_tars) {
+						if ((PySequence_Check(value) == 0) || (PySequence_Size(value) != num_tars)) {
+							char errorstr[64];
+							sprintf(errorstr, "expected sequence of %d integer(s)", num_tars);
+							return EXPP_ReturnIntError(PyExc_TypeError, errorstr);
+						}
+						
+						for (ct=targets.first; ct; ct=ct->next, i++) {
+							PyObject *val= PySequence_ITEM(value, i);
+								
+							if (type == EXPP_CONSTR_BONE) {
+								char *name = PyString_AsString(val);
+								
+								if (name == NULL) {
+									// hrm... should we break here instead?
+									ok = EXPP_ReturnIntError(PyExc_TypeError, 
+												"expected string arg as member of list");
+									Py_DECREF(val);
+									
+									break;
+								}
+								
+								BLI_strncpy(ct->subtarget, name, sizeof(ct->subtarget));
+							}
+							else {
+								Object *obj = (( BPy_Object * )val)->object;
+								
+								if ( !BPy_Object_Check(value) ) {
+									// hrm... should we break here instead?
+									ok = EXPP_ReturnIntError(PyExc_TypeError, 
+												"expected BPy object argument as member of list");
+									Py_DECREF(val);
+									
+									break;
+								}
+								
+								ct->tar = obj;
+							}
+							
+							Py_DECREF(val);
+						}
+					}
+					
+					/* only flush changes to real constraints if all were successful */
+					if ((cti->flush_constraint_targets) && (ok == 0))
+						cti->flush_constraint_targets(self->con, &targets, 0);
+				}
+			}
+			
+			return ok;
+		}
+			break;
 	case EXPP_CONSTR_SCRIPT: {
 		Text *text = (( BPy_Text * )value)->text;
 		if( !BPy_Object_Check( value ) )
@@ -1806,6 +1935,8 @@ static PyObject *Constraint_getData( BPy_Constraint * self, PyObject * key )
 			return loclimit_getter( self, setting );
 		case CONSTRAINT_TYPE_SIZELIMIT:
 			return sizelimit_getter( self, setting );
+		case CONSTRAINT_TYPE_DISTLIMIT:
+			return distlimit_getter( self, setting );
 		case CONSTRAINT_TYPE_RIGIDBODYJOINT:
 			return rigidbody_getter( self, setting );
 		case CONSTRAINT_TYPE_CLAMPTO:
@@ -1883,6 +2014,9 @@ static int Constraint_setData( BPy_Constraint * self, PyObject * key,
 		case CONSTRAINT_TYPE_SIZELIMIT:
 			result = sizelimit_setter( self, key_int, arg);
 			break;
+		case CONSTRAINT_TYPE_DISTLIMIT:
+			result = distlimit_setter( self, key_int, arg);
+			break;
 		case CONSTRAINT_TYPE_RIGIDBODYJOINT:
 			result = rigidbody_setter( self, key_int, arg);
 			break;
@@ -2370,6 +2504,8 @@ static PyObject *M_Constraint_TypeDict( void )
 				PyInt_FromLong( CONSTRAINT_TYPE_ROTLIMIT ) );
 		PyConstant_Insert( d, "LIMITSIZE", 
 				PyInt_FromLong( CONSTRAINT_TYPE_SIZELIMIT ) );
+		PyConstant_Insert( d, "LIMITDIST",
+				PyInt_FromLong( CONSTRAINT_TYPE_DISTLIMIT ) );
 		PyConstant_Insert( d, "RIGIDBODYJOINT", 
 				PyInt_FromLong( CONSTRAINT_TYPE_RIGIDBODYJOINT ) );
 		PyConstant_Insert( d, "CLAMPTO", 
@@ -2563,6 +2699,15 @@ static PyObject *M_Constraint_SettingsDict( void )
 
 		PyConstant_Insert( d, "LOCK",
 				PyInt_FromLong( EXPP_CONSTR_LOCK ) );
+				
+		PyConstant_Insert( d, "LIMITMODE",
+				PyInt_FromLong( EXPP_CONSTR_MODE ) );
+		PyConstant_Insert( d, "LIMIT_INSIDE",
+				PyInt_FromLong( LIMITDIST_INSIDE ) );
+		PyConstant_Insert( d, "LIMIT_OUTSIDE",
+				PyInt_FromLong( LIMITDIST_OUTSIDE ) );
+		PyConstant_Insert( d, "LIMIT_ONSURFACE",
+				PyInt_FromLong( LIMITDIST_ONSURFACE ) );
 
 		PyConstant_Insert( d, "COPY",
 				PyInt_FromLong( EXPP_CONSTR_COPY ) );
diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c
index a4bbeba65ac31be3e7a0d25b2f63db7ad83fa8d7..76e33a1bcb726b93f1cac1778daa615b22ef88e7 100644
--- a/source/blender/python/api2_2x/Draw.c
+++ b/source/blender/python/api2_2x/Draw.c
@@ -617,7 +617,8 @@ static void exit_pydraw( SpaceScript * sc, short err )
 	if( err ) {
 		PyErr_Print(  );
 		script->flags = 0;	/* mark script struct for deletion */
-		error( "Python script error: check console" );
+		SCRIPT_SET_NULL(script);
+		error_pyscript();
 		scrarea_queue_redraw( sc->area );
 	}
 
@@ -837,7 +838,7 @@ static void exec_but_callback(void *pyobj, void *data)
 	if (!result) {
 		Py_DECREF(pyvalue);
 		PyErr_Print(  );
-		error( "Python script error: check console" );
+		error_pyscript(  );
 	}
 	Py_XDECREF( result );
 }
@@ -1109,7 +1110,7 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
 	
 	if (!result) {
 		PyErr_Print(  );
-		error( "Python script error: check console" );
+		error_pyscript(  );
 	} else {
 		/* copied from do_clever_numbuts in toolbox.c */
 		
diff --git a/source/blender/python/api2_2x/Library.c b/source/blender/python/api2_2x/Library.c
index 1aacaf5678686c08ac39ed0a2e62bc49d893a8bb..12e2ce3055b9e1c28fe86f637c90ce5e2565e387 100644
--- a/source/blender/python/api2_2x/Library.c
+++ b/source/blender/python/api2_2x/Library.c
@@ -175,7 +175,7 @@ static PyObject *M_Library_Open( PyObject * self, PyObject * value )
 	BLI_strncpy(filename, G.sce, sizeof(filename));
 	bpy_openlib = BLO_blendhandle_from_file( fname1 );
 	BLI_strncpy(G.sce, filename, sizeof(filename)); 
-	
+
 	if( !bpy_openlib )
 		return EXPP_ReturnPyObjError( PyExc_IOError, "file not found" );
 
@@ -344,6 +344,7 @@ static PyObject *oldM_Library_Load( PyObject * self, PyObject * args )
 	int blocktype = 0;
 	int linked = 0;
 
+	
 	if( !bpy_openlib ) {
 		return EXPP_ReturnPyObjError( PyExc_IOError,
 					      "no library file: you need to open one, first." );
@@ -359,12 +360,19 @@ static PyObject *oldM_Library_Load( PyObject * self, PyObject * args )
 	if( !blocktype )
 		return EXPP_ReturnPyObjError( PyExc_NameError,
 					      "no such Blender datablock type" );
-	
+
 	if (linked)
-		BLO_script_library_append( bpy_openlib, bpy_openlibname, name, blocktype, FILE_LINK, G.scene);
+		BLO_script_library_append( &bpy_openlib, bpy_openlibname, name, blocktype, FILE_LINK, G.scene);
 	else
-		BLO_script_library_append( bpy_openlib, bpy_openlibname, name, blocktype, 0, G.scene);
-	
+		BLO_script_library_append( &bpy_openlib, bpy_openlibname, name, blocktype, 0, G.scene);
+
+	/*
+		NOTE:  BLO_script_library_append() can close the library if there is
+		an endian issue.  if this happened, reopen for the next call.
+	*/
+	if ( !bpy_openlib )
+		bpy_openlib = BLO_blendhandle_from_file( bpy_openlibname );
+
 	if( update ) {
 		M_Library_Update( self );
 		Py_DECREF( Py_None );	/* incref'ed by above function */
@@ -610,7 +618,7 @@ PyObject *LibraryData_importLibData( BPy_LibraryData *self, char *name,
 	}
 
 	/* import from the libary */
-	BLO_script_library_append( openlib, longFilename, name, self->type, mode,
+	BLO_script_library_append( &openlib, longFilename, name, self->type, mode,
 			scene );
 
 	/*
diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c
index 803c0b96ef37b1a1d69fb2d9abd2c4c254d3b819..f9a23ed37b2d0cb6d204c8f234e456e051090aa7 100644
--- a/source/blender/python/api2_2x/Mesh.c
+++ b/source/blender/python/api2_2x/Mesh.c
@@ -75,6 +75,7 @@
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
+#include "BLI_memarena.h"
 
 #include "blendef.h"
 #include "mydevice.h"
@@ -7494,6 +7495,179 @@ static PyObject *Mesh_pointInside( BPy_Mesh * self, PyObject * args, PyObject *k
 }
 
 
+/* This is a bit nasty, Blenders tangents are computed for rendering, and this isnt compatible with a normal Mesh
+ * so we have to rewrite parts of it here, make sure these stay in sync */
+
+static PyObject *Mesh_getTangents( BPy_Mesh * self )
+{
+	/* python stuff */
+	PyObject *py_tanlist;
+	PyObject *py_tuple;
+	
+	
+	PyObject *py_vector;
+#if 0	/* BI-TANGENT */
+	PyObject *py_bivector;
+	PyObject *py_pair;
+	
+	float no[3];
+#endif
+	/* mesh vars */
+	Mesh *mesh = self->mesh;
+	MTFace *tf = mesh->mtface;
+	MFace *mf = mesh->mface;
+	MVert *v1, *v2, *v3, *v4;
+	int mf_vi[4];
+	
+	/* See convertblender.c */
+	float *uv1, *uv2, *uv3, *uv4;
+	float fno[3];
+	float tang[3];
+	float uv[4][2];
+	float *vtang;
+	
+	float (*orco)[3] = NULL;
+	
+	MemArena *arena= NULL;
+	VertexTangent **vtangents= NULL;
+	int i, j, len;
+	
+	
+	if(!mesh->mtface) {
+		if (!self->object)
+			return EXPP_ReturnPyObjError( PyExc_RuntimeError, "cannot get tangents when there are not UV's, or the mesh has no link to an object");
+		
+		orco = (float(*)[3])get_mesh_orco_verts(self->object);
+		
+		if (!orco)
+			return EXPP_ReturnPyObjError( PyExc_RuntimeError, "cannot get orco's for this objects tangents");
+	}
+	
+	/* vertex normals */
+	arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+	BLI_memarena_use_calloc(arena);
+	vtangents= MEM_callocN(sizeof(VertexTangent*)*mesh->totvert, "VertexTangent");
+	
+	for( i = 0, tf = mesh->mtface, mf = mesh->mface; i < mesh->totface; mf++, tf++, i++ ) {
+		v1 = &mesh->mvert[mf->v1];
+		v2 = &mesh->mvert[mf->v2];
+		v3 = &mesh->mvert[mf->v3];
+		if (mf->v4) {
+			v4 = &mesh->mvert[mf->v4];
+			
+			CalcNormFloat4( v1->co, v2->co, v3->co, v4->co, fno );
+		} else {
+			CalcNormFloat( v1->co, v2->co, v3->co, fno );
+		}
+		
+		if(mesh->mtface) {
+			uv1= tf->uv[0];
+			uv2= tf->uv[1];
+			uv3= tf->uv[2];
+			uv4= tf->uv[3];
+		} else {
+			uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+			spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+			spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+			spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+			if(v4)
+				spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
+		}
+		
+		tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
+		sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+		sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
+		sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+		
+		if (mf->v4) {
+			v4 = &mesh->mvert[mf->v4];
+			
+			tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
+			sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+			sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+			sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
+		}
+	}
+	
+	
+	py_tanlist = PyList_New(mesh->totface);
+	
+	for( i = 0, tf = mesh->mtface, mf = mesh->mface; i < mesh->totface; mf++, tf++, i++ ) {
+		 
+		len = mf->v4 ? 4 : 3; 
+		
+		if(mesh->mtface) {
+			uv1= tf->uv[0];
+			uv2= tf->uv[1];
+			uv3= tf->uv[2];
+			uv4= tf->uv[3];
+		} else {
+			uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+			spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+			spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+			spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+			if(len==4)
+				spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
+		}
+		
+		mf_vi[0] = mf->v1;
+		mf_vi[1] = mf->v2;
+		mf_vi[2] = mf->v3;
+		mf_vi[3] = mf->v4;
+		
+#if 0	/* BI-TANGENT */
+		/* now calculate the bitangent */
+		if (mf->flag & ME_SMOOTH) {
+			no[0] = (float)(mesh->mvert[mf_vi[j]]->no[0] / 32767.0);
+			no[1] = (float)(mesh->mvert[mf_vi[j]]->no[1] / 32767.0);
+			no[2] = (float)(mesh->mvert[mf_vi[j]]->no[2] / 32767.0);
+		} else {
+			/* calc face normal */
+			if (len==4)		CalcNormFloat4( mesh->mvert[0]->co, mesh->mvert[1]->co, mesh->mvert[2]->co, mesh->mvert[3]->co, no );
+			else			CalcNormFloat4( mesh->mvert[0]->co, mesh->mvert[1]->co, mesh->mvert[2]->co, no );
+		}
+#endif
+		
+		py_tuple = PyTuple_New( len );
+		
+		for (j=0; j<len; j++) {
+			vtang= find_vertex_tangent(vtangents[mf_vi[j]], mesh->mtface ? tf->uv[j] : uv[j]);	/* mf_vi[j] == mf->v1,   uv[j] == tf->uv[0] */
+			
+			py_vector = newVectorObject( vtang, 3, Py_NEW );
+			Normalize(((VectorObject *)py_vector)->vec);
+			
+#if 0		/* BI-TANGENT */
+			py_pair = PyTuple_New( 2 );
+			PyTuple_SetItem( py_pair, 0, py_vector );
+			PyTuple_SetItem( py_pair, 1, py_bivector );
+			
+			/* qdn: tangent space */
+			/* copied from texture.c */
+			float B[3], tv[3];
+			Crossf(B, shi->vn, shi->nmaptang);	/* bitangent */
+			/* transform norvec from tangent space to object surface in camera space */
+			tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*shi->vn[0];
+			tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*shi->vn[1];
+			tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*shi->vn[2];
+			shi->vn[0]= facm*shi->vn[0] + fact*tv[0];
+			shi->vn[1]= facm*shi->vn[1] + fact*tv[1];
+			shi->vn[2]= facm*shi->vn[2] + fact*tv[2];				
+			PyTuple_SetItem( py_tuple, j, py_pair );
+#else
+			PyTuple_SetItem( py_tuple, j, py_vector );
+#endif
+		}
+
+		PyList_SetItem( py_tanlist, i, py_tuple );
+	}
+	
+	BLI_memarena_free(arena);
+	if (orco) MEM_freeN( orco );
+	MEM_freeN( vtangents );
+	
+	return py_tanlist;
+}
+
 /*
  * "__copy__" return a copy of the mesh
  */
@@ -7571,7 +7745,9 @@ static struct PyMethodDef BPy_Mesh_methods[] = {
 		"Recalculates inside or outside normals (experimental)"},
 	{"pointInside", (PyCFunction)Mesh_pointInside, METH_VARARGS|METH_KEYWORDS,
 		"Recalculates inside or outside normals (experimental)"},
-	
+	{"getTangents", (PyCFunction)Mesh_getTangents, METH_VARARGS|METH_KEYWORDS,
+		"Return a list of face tangents"},
+		
 	/* mesh custom data layers */
 	{"addUVLayer", (PyCFunction)Mesh_addUVLayer, METH_VARARGS,
 		"adds a UV layer to this mesh"},
diff --git a/source/blender/python/api2_2x/Node.c b/source/blender/python/api2_2x/Node.c
index 0a68509d287b6777484d3897cf72e3b14249440f..0ceb6b3c2a245f2f40c84aa174dda19c00306bf4 100644
--- a/source/blender/python/api2_2x/Node.c
+++ b/source/blender/python/api2_2x/Node.c
@@ -43,6 +43,7 @@
 
 #include "BLI_blenlib.h"
 #include "gen_utils.h"
+#include "vector.h"
 
 static PyObject *Node_repr( BPy_Node * self );
 static int Node_compare(BPy_Node *a, BPy_Node *b);
@@ -50,101 +51,369 @@ static PyObject *ShadeInput_repr( BPy_ShadeInput * self );
 static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b);
 static BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi);
 
+/* node socket type */
+
+static PyObject *NodeSocket_getName(BPy_NodeSocket *self, void *unused)
+{
+	return PyString_FromString(self->name);
+}
+
+static int NodeSocket_setName(BPy_NodeSocket *self, PyObject *value, void *unused)
+{
+	char *name = NULL;
+
+	if (!PyString_Check(value))
+		return EXPP_ReturnIntError( PyExc_TypeError,
+			"expected a string" );
+
+	name = PyString_AsString(value);
+
+	if (!name)
+		return EXPP_ReturnIntError(PyExc_RuntimeError,
+			"couldn't convert value to string!");
+
+	BLI_strncpy(self->name, name, NODE_MAXSTR);
+
+	return 0;
+}
+
+static PyObject *NodeSocket_getVal(BPy_NodeSocket *self, void *unused)
+{
+	PyObject *pyret = NULL;
+
+	if (self->type == SOCK_VALUE) {
+		pyret = PyFloat_FromDouble(self->val[0]);
+	}
+	else { /* VECTOR or RGBA */
+		pyret = newVectorObject(self->val, self->type, Py_NEW);
+
+		if (!pyret)
+			return EXPP_ReturnPyObjError(PyExc_RuntimeError,
+				"couldn't create vector object!");
+	}
+
+	return pyret;
+}
+
+static int NodeSocket_setVal(BPy_NodeSocket *self, PyObject *value, void *unused)
+{
+	int error = 0;
+
+	if (PySequence_Check(value)) {
+		PyObject *item, *fpyval;
+		int i, len;
+
+		len = PySequence_Size(value);
+
+		if (len == 3 || len == 4) {
+			for (i = 0; i < len; i++) {
+				item = PySequence_GetItem(value, i);
+				fpyval = PyNumber_Float(item);
+				if (!fpyval) {
+					Py_DECREF(item);
+					error = 1;
+					break;
+				}
+				self->val[i] = (float)PyFloat_AsDouble(fpyval);
+				Py_DECREF(item);
+				Py_DECREF(fpyval);
+			}
+			if (len == 3)
+				self->type = SOCK_VECTOR;
+			else /* len == 4 */
+				self->type = SOCK_RGBA;
+		}
+		else error = 1;
+	}
+	else if (VectorObject_Check(value)) {
+		VectorObject *vecOb = (VectorObject *)value;
+		short vlen = vecOb->size;
+
+		if (vlen == 3 || vlen == 4) {
+			VECCOPY(self->val, vecOb->vec); /* copies 3 values */
+			if (vlen == 3)
+				self->type = SOCK_VECTOR;
+			else {
+				self->val[3] = vecOb->vec[3];
+				self->type = SOCK_RGBA;
+			}
+		}
+		else error = 1;
+	}
+	else if (PyNumber_Check(value)) {
+		self->val[0] = (float)PyFloat_AsDouble(value);
+		self->type = SOCK_VALUE;
+	}
+	else error = 1;
+
+	if (error)
+		return EXPP_ReturnIntError( PyExc_TypeError,
+			"expected a float or a sequence (or vector) of 3 or 4 floats" );
+	return 0;
+}
+
+static PyObject *NodeSocket_getMin(BPy_NodeSocket *self, void *unused)
+{
+	return PyFloat_FromDouble(self->min);
+}
+
+static int NodeSocket_setMin(BPy_NodeSocket *self, PyObject *value, void *unused)
+{
+	PyObject *pyval = PyNumber_Float(value);
+
+	if (!pyval)
+		return EXPP_ReturnIntError( PyExc_TypeError,
+			"expected a float number" );
+
+	self->min = (float)PyFloat_AsDouble(pyval);
+	Py_DECREF(pyval);
+
+	return 0;
+}
+
+static PyObject *NodeSocket_getMax(BPy_NodeSocket *self, void *unused)
+{
+	return PyFloat_FromDouble(self->max);
+}
+
+static int NodeSocket_setMax(BPy_NodeSocket *self, PyObject *value, void *unused)
+{
+	PyObject *pyval = PyNumber_Float(value);
+
+	if (!pyval)
+		return EXPP_ReturnIntError( PyExc_TypeError,
+			"expected a float number" );
+
+	self->max = (float)PyFloat_AsDouble(pyval);
+	Py_DECREF(pyval);
+
+	return 0;
+}
+
+static PyGetSetDef NodeSocket_getseters[] = {
+	{"name", (getter)NodeSocket_getName, (setter)NodeSocket_setName,
+		"This socket's name", NULL},
+	{"val", (getter)NodeSocket_getVal, (setter)NodeSocket_setVal,
+		"This socket's data value(s)", NULL},
+	{"min", (getter)NodeSocket_getMin, (setter)NodeSocket_setMin,
+		"This socket's min possible value (lower range limit)", NULL},
+	{"max", (getter)NodeSocket_getMax, (setter)NodeSocket_setMax,
+		"This socket's max possible value (upper range limit)", NULL},
+	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
+static void NodeSocket_dealloc(BPy_NodeSocket *self)
+{
+	self->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *NodeSocket_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject *pysocket = type->tp_alloc(type, 0);
+
+	if (!pysocket)
+		return EXPP_ReturnPyObjError(PyExc_RuntimeError, "couldn't create socket type!");
+
+	return pysocket;
+}
+
+static int NodeSocket_init(BPy_NodeSocket *self, PyObject *args, PyObject *kwargs)
+{
+	char *name = NULL;
+	float min = 0.0f, max = 1.0f;
+	PyObject *val = NULL;
+	static char *kwlist[] = {"name", "val", "min", "max", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Off", kwlist, &name, &val, &min, &max)){
+		return EXPP_ReturnIntError(PyExc_AttributeError, "expected a string and optionally:\n1) a float or a sequence (or vector) of 3 or 4 floats and\n2) two floats");
+	}
+
+	BLI_strncpy(self->name, name, NODE_MAXSTR);
+
+	self->min = min;
+	self->max = max;
+
+	if (val)
+		return NodeSocket_setVal(self, val, NULL);
+	/* else */
+	self->type = SOCK_VALUE;
+	self->val[0] = 0.0f;
+
+	return 0;
+}
+
+static PyObject *NodeSocket_copy(BPy_NodeSocket *self)
+{
+	BPy_NodeSocket *copied;
+
+	copied = (BPy_NodeSocket*)NodeSocket_new(&NodeSocket_Type, NULL, NULL);
+
+	if (!copied) return NULL; /* error already set in NodeSocket_new */
+
+	BLI_strncpy(copied->name, self->name, NODE_MAXSTR);
+	copied->min = self->min;
+	copied->max = self->max;
+	copied->type = self->type;
+	memcpy(copied->val, self->val, 4*sizeof(float));
+
+	return (PyObject *)copied;
+}
+
+static PyMethodDef BPy_NodeSocket_methods[] = {
+	{"__copy__", ( PyCFunction ) NodeSocket_copy, METH_NOARGS,
+	 "() - Makes a copy of this node socket."},
+	{"copy", ( PyCFunction ) NodeSocket_copy, METH_NOARGS,
+	 "() - Makes a copy of this node socket."},
+	{NULL, NULL, 0, NULL}
+};
+
+PyTypeObject NodeSocket_Type = {
+	PyObject_HEAD_INIT( NULL )  /* required py macro */
+	0,                          /* ob_size */
+	/*  For printing, in format "<module>.<name>" */
+	"Blender.Node.Socket",           /* char *tp_name; */
+	sizeof( BPy_NodeSocket ),       /* int tp_basicsize; */
+	0,                          /* tp_itemsize;  For allocation */
+
+	/* Methods to implement standard operations */
+
+	(destructor)NodeSocket_dealloc,/* destructor tp_dealloc; */
+	NULL,                       /* printfunc tp_print; */
+	NULL,                       /* getattrfunc tp_getattr; */
+	NULL,                       /* setattrfunc tp_setattr; */
+	NULL,                       /* cmpfunc tp_compare; */
+	NULL,                       /* reprfunc tp_repr; */
+
+	/* Method suites for standard classes */
+
+	NULL,      					/* PyNumberMethods *tp_as_number; */
+	NULL,					    /* PySequenceMethods *tp_as_sequence; */
+	NULL,      /* PyMappingMethods *tp_as_mapping; */
+
+	/* More standard operations (here for binary compatibility) */
+
+	NULL,                       /* hashfunc tp_hash; */
+	NULL,                       /* ternaryfunc tp_call; */
+	NULL,                       /* reprfunc tp_str; */
+	NULL,                       /* getattrofunc tp_getattro; */
+	NULL,                       /* setattrofunc tp_setattro; */
+
+	/* Functions to access object as input/input buffer */
+	NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+	Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* long tp_flags; */
+
+	NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+	/* call function for all accessible objects */
+	NULL,                       /* traverseproc tp_traverse; */
+
+	/* delete references to contained objects */
+	NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+	NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+	0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+	/*   Iterators */
+	0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
+	0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+	BPy_NodeSocket_methods,     /* struct PyMethodDef *tp_methods; */
+	NULL,                       /* struct PyMemberDef *tp_members; */
+	NodeSocket_getseters,       /* struct PyGetSetDef *tp_getset; */
+	NULL,                       /* struct _typeobject *tp_base; */
+	NULL,                       /* PyObject *tp_dict; */
+	NULL,                       /* descrgetfunc tp_descr_get; */
+	NULL,                       /* descrsetfunc tp_descr_set; */
+	0,                          /* long tp_dictoffset; */
+	(initproc)NodeSocket_init,  /* initproc tp_init; */
+	NULL,                       /* allocfunc tp_alloc; */
+	NodeSocket_new,				/* newfunc tp_new; */
+	/*  Low-level free-memory routine */
+	NULL,                       /* freefunc tp_free;  */
+	/* For PyObject_IS_GC */
+	NULL,                       /* inquiry tp_is_gc;  */
+	NULL,                       /* PyObject *tp_bases; */
+	/* method resolution order */
+	NULL,                       /* PyObject *tp_mro;  */
+	NULL,                       /* PyObject *tp_cache; */
+	NULL,                       /* PyObject *tp_subclasses; */
+	NULL,                       /* PyObject *tp_weaklist; */
+	NULL
+};
+
 /**
- * Take the descriptions from list and create sockets for those in socks
+ * Take the descriptions from tuple and create sockets for those in socks
  * socks is a socketstack from a bNodeTypeInfo
  */
-static int list_socks_to_typeinfo(PyObject *tuple, bNodeSocketType **socks, int stage, int limit) {
+static int pysockets_to_blendersockets(PyObject *tuple, bNodeSocketType **socks, int stage, int limit) {
 	int len = 0, a = 0, pos = 0, retval = 0;
-	//wPyObject *key = NULL, *value = NULL;
-	PyObject *item, *arg;
-	bNodeSocketType *newsocks = NULL;
-	char *s_name = NULL;
-	int s_type = SOCK_VALUE;
-	float s_val[4], s_min, s_max;
+	short stype;
+	BPy_NodeSocket *pysock;
+	bNodeSocketType *nsocks = NULL;
 
 	if (BTST2(stage, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST))
 		return 0; /* already has sockets */
 
 	len = PyTuple_Size(tuple);
 
-	newsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType in Node.c");
+	nsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType in Node.c");
 
 	for (pos = 0, a = 0; pos< len; pos++, a++) {
-		/* default socket values: */
-		s_name = NULL;
-		s_type = SOCK_VALUE;
-		s_min = 0.0f;
-		s_max = 1.0f;
-		s_val[0] = s_val[1] = s_val[2] = s_val[3] = 1.0f;
-
-		item = PyTuple_GetItem(tuple, pos);
+		pysock = (BPy_NodeSocket *)PyTuple_GetItem(tuple, pos);/*borrowed*/
 
-		if (!PySequence_Check(item)) {
-			PyErr_SetString(PyExc_AttributeError, "a socket must be a List of Lists or Tuples");
+		if (!BPy_NodeSocket_Check(pysock)) {
+			PyErr_SetString(PyExc_AttributeError, "expected a sequence of node sockets");
 			retval = -1;
 			break;
 		}
 
-		arg = PySequence_Tuple(item);
+		stype = pysock->type;
 
-		if (!PyArg_ParseTuple(arg, "s|iffffff", &s_name, &s_type,
-					&s_min, &s_max,
-					&s_val[0], &s_val[1], &s_val[2], &s_val[3] )) {
-			PyErr_SetString(PyExc_AttributeError, "socket definitions require a string and optionally an int and 6 floats");
-			retval = -1;
-			Py_DECREF(arg);
-			break;
-		}
+		nsocks[a].type = stype;
+		nsocks[a].limit = limit;
+
+		nsocks[a].name = BLI_strdupn(pysock->name, NODE_MAXSTR);
+
+		nsocks[a].min = pysock->min;
+		nsocks[a].max = pysock->max;
+
+		if (stype > SOCK_VALUE) {
+			float *vec = pysock->val;
 
-		newsocks[a].name = BLI_strdupn(s_name, NODE_MAXSTR);
-		newsocks[a].type = s_type;
-		newsocks[a].min = s_min;
-		newsocks[a].max = s_max;
-		newsocks[a].val1 = s_val[0];
-		newsocks[a].val2 = s_val[1];
-		newsocks[a].val3 = s_val[2];
-		newsocks[a].val4 = s_val[3];
-		newsocks[a].limit = limit;
-
-		Py_DECREF(arg);
+			nsocks[a].val1 = vec[0];
+			nsocks[a].val2 = vec[1];
+			nsocks[a].val3 = vec[2];
+
+			if (stype == SOCK_RGBA)
+				nsocks[a].val4 = vec[3];
+		}
+		else /* SOCK_VALUE */
+			nsocks[a].val1 = pysock->val[0];
 	}
 
-	newsocks[a].type = -1;
+	nsocks[a].type = -1;
 
-	*socks = newsocks;
+	*socks = nsocks;
 
 	return retval;
 }
 
-/* Get number of complying entries in a list.
- *
- */
-/* unused
-static int num_list_sockets(PyObject *list) {
-	int size = 0;
-	int i = 0, count = 0;
-	PyObject *element = NULL;
-
-	size = PyList_Size(list);
-	for(i = 0; i < size; i++) {
-		element = PyList_GetItem(list, i);
-		//wPy_INCREF(element);
-		if(PyList_Check(element) && PyList_Size(element) == 8)
-			count++;
-		//wPy_DECREF(element);
-	}
-	return count;
-}
-*/
-static void NodeSockets_dealloc(BPy_NodeSockets *self)
+static void NodeSocketLists_dealloc(BPy_NodeSocketLists *self)
 {
 	Py_DECREF(self->input);
 	Py_DECREF(self->output);
 	self->ob_type->tp_free((PyObject *)self);
 }
 
-static PyObject *Map_socketdef_getter(BPy_NodeSockets *self, void *closure)
+static PyObject *Map_socketdef_getter(BPy_NodeSocketLists *self, void *closure)
 {
 	PyObject *sockets = NULL;
 
@@ -167,7 +436,7 @@ static PyObject *Map_socketdef_getter(BPy_NodeSockets *self, void *closure)
 	return sockets;
 }
 
-static int Map_socketdef(BPy_NodeSockets *self, PyObject *args, void *closure)
+static int Map_socketdef(BPy_NodeSocketLists *self, PyObject *args, void *closure)
 {
 	bNode *node = NULL;
 	PyObject *tuple = NULL;
@@ -187,7 +456,8 @@ static int Map_socketdef(BPy_NodeSockets *self, PyObject *args, void *closure)
 			if (args) {
 				if(PySequence_Check(args)) {
 					tuple = PySequence_Tuple(args);
-					list_socks_to_typeinfo(tuple, &(node->typeinfo->inputs), node->custom1, 1);
+					pysockets_to_blendersockets(tuple,
+							&(node->typeinfo->inputs), node->custom1, 1);
 					Py_DECREF(self->input);
 					self->input = tuple;
 				} else {
@@ -199,7 +469,8 @@ static int Map_socketdef(BPy_NodeSockets *self, PyObject *args, void *closure)
 			if (args) {
 				if(PyList_Check(args)) {
 					tuple = PySequence_Tuple(args);
-					list_socks_to_typeinfo(tuple, &(node->typeinfo->outputs), node->custom1, 0);
+					pysockets_to_blendersockets(tuple,
+							&(node->typeinfo->outputs), node->custom1, 0);
 					Py_DECREF(self->output);
 					self->output = tuple;
 				} else {
@@ -214,7 +485,7 @@ static int Map_socketdef(BPy_NodeSockets *self, PyObject *args, void *closure)
 	return 0;
 }
 
-static PyGetSetDef NodeSockets_getseters[] = {
+static PyGetSetDef NodeSocketLists_getseters[] = {
 	{"input", (getter)Map_socketdef_getter, (setter)Map_socketdef,
 		"Set this node's input sockets (list of lists or tuples)",
 		(void *)'I'},
@@ -230,17 +501,17 @@ static PyGetSetDef NodeSockets_getseters[] = {
 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 };
 
-PyTypeObject NodeSockets_Type = {
+PyTypeObject NodeSocketLists_Type = {
 	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                          /* ob_size */
 	/*  For printing, in format "<module>.<name>" */
-	"Blender.Node.Sockets",           /* char *tp_name; */
-	sizeof( BPy_NodeSockets ),       /* int tp_basicsize; */
+	"Blender.Node.SocketLists",           /* char *tp_name; */
+	sizeof( BPy_NodeSocketLists ),       /* int tp_basicsize; */
 	0,                          /* tp_itemsize;  For allocation */
 
 	/* Methods to implement standard operations */
 
-	(destructor)NodeSockets_dealloc,/* destructor tp_dealloc; */
+	(destructor)NodeSocketLists_dealloc,/* destructor tp_dealloc; */
 	NULL,                       /* printfunc tp_print; */
 	NULL,                       /* getattrfunc tp_getattr; */
 	NULL,                       /* setattrfunc tp_setattr; */
@@ -290,7 +561,7 @@ PyTypeObject NodeSockets_Type = {
   /*** Attribute descriptor and subclassing stuff ***/
 	0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
 	NULL,                       /* struct PyMemberDef *tp_members; */
-	NodeSockets_getseters,      /* struct PyGetSetDef *tp_getset; */
+	NodeSocketLists_getseters,      /* struct PyGetSetDef *tp_getset; */
 	NULL,                       /* struct _typeobject *tp_base; */
 	NULL,                       /* PyObject *tp_dict; */
 	NULL,                       /* descrgetfunc tp_descr_get; */
@@ -312,17 +583,17 @@ PyTypeObject NodeSockets_Type = {
 	NULL
 };
 
-BPy_NodeSockets *Node_CreateSockets(bNode *node) {
-	BPy_NodeSockets *sockets = PyObject_NEW(BPy_NodeSockets, &NodeSockets_Type);
-	sockets->node = node;
-	sockets->input = PyList_New(0);
-	sockets->output = PyList_New(0);
-	return sockets;
+BPy_NodeSocketLists *Node_CreateSocketLists(bNode *node) {
+	BPy_NodeSocketLists *socklists = PyObject_NEW(BPy_NodeSocketLists, &NodeSocketLists_Type);
+	socklists->node = node;
+	socklists->input = PyList_New(0);
+	socklists->output = PyList_New(0);
+	return socklists;
 }
 
 /***************************************/
 
-static int sockinmap_len ( BPy_SockMap * self) {
+static int Sockinmap_len ( BPy_SockMap * self) {
 	bNode *node = self->node;
 	bNodeType *tinfo;
 	int a = 0;
@@ -340,16 +611,14 @@ static int sockinmap_len ( BPy_SockMap * self) {
 	return a;
 }
 
-static int sockinmap_has_key( BPy_SockMap *self, PyObject *key) {
+static int sockinmap_has_key( BPy_SockMap *self, char *strkey) {
 	bNode *node = self->node;
 	bNodeType *tinfo;
-	char *strkey = NULL;
 	int a = 0;
 
-	if (!node) return -1;
+	if (!node || !strkey) return -1;
 
 	tinfo = node->typeinfo;
-	strkey = PyString_AsString(key);
 
 	if(tinfo && tinfo->inputs){
 		while(self->node->typeinfo->inputs[a].type!=-1) {
@@ -362,17 +631,17 @@ static int sockinmap_has_key( BPy_SockMap *self, PyObject *key) {
 	return -1;
 }
 
-PyObject *sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) {
+PyObject *Sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) {
 	int idx;
 
 	if (!self->node)
 		return EXPP_ReturnPyObjError(PyExc_RuntimeError, "no access to Blender node data!");
 
 	if (PyString_Check(pyidx)) {
-		idx = sockinmap_has_key(self, pyidx);
+		idx = sockinmap_has_key(self, PyString_AsString(pyidx));
 	}
 	else if(PyInt_Check(pyidx)) {
-		int len = sockinmap_len(self);
+		int len = Sockinmap_len(self);
 		idx = (int)PyInt_AsLong(pyidx);
 		if (idx < 0 || idx >= len)
 			return EXPP_ReturnPyObjError(PyExc_IndexError, "index out of range");
@@ -405,10 +674,37 @@ PyObject *sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) {
 	Py_RETURN_NONE;
 }
 
+static PyObject *Sockinmap_getAttr(BPy_SockMap *self, char *attr)
+{
+	PyObject *pyob = NULL;
+	int idx;
+
+	idx = sockinmap_has_key(self, attr);
+
+	if (idx < 0)
+		return EXPP_ReturnPyObjError(PyExc_AttributeError, "unknown input socket name");
+
+	switch(self->node->typeinfo->inputs[idx].type) {
+		case SOCK_VALUE:
+			pyob = Py_BuildValue("f", self->stack[idx]->vec[0]);
+			break;
+		case SOCK_VECTOR:
+			pyob = Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
+			break;
+		case SOCK_RGBA:
+			pyob = Py_BuildValue("(ffff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2], self->stack[idx]->vec[3]);
+			break;
+		default:
+			break;
+	}
+
+	return pyob;
+}
+
 /* read only */
-static PyMappingMethods sockinmap_as_mapping = {
-	( inquiry ) sockinmap_len,  /* mp_length */
-	( binaryfunc ) sockinmap_subscript, /* mp_subscript */
+static PyMappingMethods Sockinmap_as_mapping = {
+	( inquiry ) Sockinmap_len,  /* mp_length */
+	( binaryfunc ) Sockinmap_subscript, /* mp_subscript */
 	( objobjargproc ) 0 /* mp_ass_subscript */
 };
 
@@ -424,7 +720,7 @@ PyTypeObject SockInMap_Type = {
 
 	NULL,/* destructor tp_dealloc; */
 	NULL,                       /* printfunc tp_print; */
-	NULL,                       /* getattrfunc tp_getattr; */
+	(getattrfunc) Sockinmap_getAttr,/* getattrfunc tp_getattr; */
 	NULL,                       /* setattrfunc tp_setattr; */
 	NULL,                       /* cmpfunc tp_compare; */
 	NULL,                       /* reprfunc tp_repr; */
@@ -433,7 +729,7 @@ PyTypeObject SockInMap_Type = {
 
 	NULL,      					/* PyNumberMethods *tp_as_number; */
 	NULL,					    /* PySequenceMethods *tp_as_sequence; */
-	&sockinmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
+	&Sockinmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
 
 	/* More standard operations (here for binary compatibility) */
 
@@ -494,7 +790,7 @@ PyTypeObject SockInMap_Type = {
 	NULL
 };
 
-static int sockoutmap_len ( BPy_SockMap * self) {
+static int Sockoutmap_len ( BPy_SockMap * self) {
 	bNode *node = self->node;
 	bNodeType *tinfo;
 	int a = 0;
@@ -510,16 +806,14 @@ static int sockoutmap_len ( BPy_SockMap * self) {
 	return a;
 }
 
-static int sockoutmap_has_key( BPy_SockMap *self, PyObject *key) {
+static int sockoutmap_has_key(BPy_SockMap *self, char *strkey) {
 	bNode *node = self->node;
 	bNodeType *tinfo;
 	int a = 0;
-	char *strkey = NULL;
 
 	if (!node) return -1;
 
 	tinfo = node->typeinfo;
-	strkey = PyString_AsString(key);
 
 	if(tinfo && tinfo->outputs){
 		while(self->node->typeinfo->outputs[a].type!=-1) {
@@ -532,8 +826,8 @@ static int sockoutmap_has_key( BPy_SockMap *self, PyObject *key) {
 	return -1;
 }
 
-static int sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObject *value) {
-	int i, idx, len, wanted_len = 0, ret = -1;
+static int Sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObject *value) {
+	int i, idx, len, type, wanted_len = 0;
 	PyObject *val;
 	PyObject *items[4];
 
@@ -542,11 +836,11 @@ static int sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObj
 
 	if (PyInt_Check(pyidx)) {
 		idx = (int)PyInt_AsLong(pyidx);
-		if (idx < 0 || idx >= sockinmap_len(self))
+		if (idx < 0 || idx >= Sockinmap_len(self))
 			return EXPP_ReturnIntError(PyExc_IndexError, "index out of range");
 	}
 	else if (PyString_Check(pyidx)) {
-		idx = sockoutmap_has_key(self, pyidx);
+		idx = sockoutmap_has_key(self, PyString_AsString(pyidx));
 	}
 	else if (PySlice_Check(pyidx)) {
 		return EXPP_ReturnIntError(PyExc_ValueError, "slices not yet implemented");
@@ -557,70 +851,129 @@ static int sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObj
 	if (idx < 0)
 		return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
 
-	val = PySequence_Fast(value, "expected a numeric tuple or list");
-	if (!val) return -1;
+	type = self->node->typeinfo->outputs[idx].type;
 
-	len = PySequence_Fast_GET_SIZE(val);
-
-	if (len == 0) {
+	if (type == SOCK_VALUE) {
+		val = PyNumber_Float(value);
+		if (!val)
+			return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
+		self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
 		Py_DECREF(val);
-		return EXPP_ReturnIntError(PyExc_AttributeError, "expected a non-empty numeric tuple or list");
 	}
+	else {
+		val = PySequence_Fast(value, "expected a numeric tuple or list");
+		if (!val) return -1;
+
+		len = PySequence_Fast_GET_SIZE(val);
 
-	for (i = 0; i < len; i++) {
-		items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
-		if (!PyNumber_Check(items[i])) {
+		if (type == SOCK_VECTOR) {
+			wanted_len = 3;
+		} else { /* SOCK_RGBA */
+			wanted_len = 4;
+		}
+
+		if (len != wanted_len) {
 			Py_DECREF(val);
-			return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
+			PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
+			fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
+			return -1;
 		}
-	}
 
-	switch(self->node->typeinfo->outputs[idx].type) {
-		case SOCK_VALUE:
-			wanted_len = 1;
-			if (len == 1) {
-				self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
-				ret = 0;
+		for (i = 0; i < len; i++) {
+			items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
+			if (!PyNumber_Check(items[i])) {
+				Py_DECREF(val);
+				return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
 			}
-			break;
-		case SOCK_VECTOR:
+		}
+
+		self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
+		self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
+		self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
+
+		if (type == SOCK_RGBA)
+			self->stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
+
+		Py_DECREF(val);
+	}
+
+	return 0;
+}
+
+static int sockoutmap_set_attr(bNodeStack **stack, short type, short idx, PyObject *value)
+{
+	PyObject *val;
+	PyObject *items[4];
+	int i;
+	short len, wanted_len;
+
+	if (type == SOCK_VALUE) {
+		val = PyNumber_Float(value);
+		if (!val)
+			return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
+		stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
+		Py_DECREF(val);
+	}
+	else {
+		val = PySequence_Fast(value, "expected a numeric tuple or list");
+		if (!val) return -1;
+
+		len = PySequence_Fast_GET_SIZE(val);
+
+		if (type == SOCK_VECTOR) {
 			wanted_len = 3;
-			if (len == 3) {
-				self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
-				self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
-				self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
-				ret = 0;
-			}
-			break;
-		case SOCK_RGBA:
+		} else { /* SOCK_RGBA */
 			wanted_len = 4;
-			if (len == 4) {
-				self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
-				self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
-				self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
-				self->stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
-				ret = 0;
+		}
+
+		if (len != wanted_len) {
+			Py_DECREF(val);
+			PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
+			fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
+			return -1;
+		}
+
+		for (i = 0; i < len; i++) {
+			items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
+			if (!PyNumber_Check(items[i])) {
+				Py_DECREF(val);
+				return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
 			}
-			break;
-		default:
-			break;
-	}
+		}
+
+		stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
+		stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
+		stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
 
-	Py_DECREF(val);
+		if (type == SOCK_RGBA)
+			stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
 
-	if (ret == -1) {
-		PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
-		fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
+		Py_DECREF(val);
 	}
 
-	return ret;
+	return 0;
 }
 
+static int Sockoutmap_setAttr(BPy_SockMap *self, char *name, PyObject *value) {
+	short idx, type;
+
+	if (!self->node)
+		return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
+
+	idx = sockoutmap_has_key(self, name);
+
+	if (idx < 0)
+		return EXPP_ReturnIntError(PyExc_AttributeError, "unknown output socket name");
+
+	type = self->node->typeinfo->outputs[idx].type;
+
+	return sockoutmap_set_attr(self->stack, type, idx, value);
+}
 /* write only */
-static PyMappingMethods sockoutmap_as_mapping = {
-	( inquiry ) sockoutmap_len,  /* mp_length */
+static PyMappingMethods Sockoutmap_as_mapping = {
+	( inquiry ) Sockoutmap_len,  /* mp_length */
 	( binaryfunc ) 0, /* mp_subscript */
-	( objobjargproc ) sockoutmap_assign_subscript /* mp_ass_subscript */
+	( objobjargproc ) Sockoutmap_assign_subscript /* mp_ass_subscript */
 };
 
 PyTypeObject SockOutMap_Type = {
@@ -636,7 +989,7 @@ PyTypeObject SockOutMap_Type = {
 	NULL,/* destructor tp_dealloc; */
 	NULL,                       /* printfunc tp_print; */
 	NULL,                       /* getattrfunc tp_getattr; */
-	NULL,                       /* setattrfunc tp_setattr; */
+	(setattrfunc) Sockoutmap_setAttr,/* setattrfunc tp_setattr; */
 	NULL,                       /* cmpfunc tp_compare; */
 	NULL,                       /* reprfunc tp_repr; */
 
@@ -644,7 +997,7 @@ PyTypeObject SockOutMap_Type = {
 
 	NULL,      					/* PyNumberMethods *tp_as_number; */
 	NULL,					    /* PySequenceMethods *tp_as_sequence; */
-	&sockoutmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
+	&Sockoutmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
 
 	/* More standard operations (here for binary compatibility) */
 
@@ -850,7 +1203,6 @@ static PyObject *Node_GetShi(BPy_Node *self) {
 static PyObject *node_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
 	PyObject *self;
-	assert(type!=NULL && type->tp_alloc!=NULL);
 	self = type->tp_alloc(type, 1);
 	return self;
 }
@@ -1161,7 +1513,9 @@ PyObject *Node_Init(void)
 		return NULL;
 	if( PyType_Ready( &ShadeInput_Type ) < 0 )
 		return NULL;
-	if( PyType_Ready( &NodeSockets_Type ) < 0 )
+	if( PyType_Ready( &NodeSocket_Type ) < 0 )
+		return NULL;
+	if( PyType_Ready( &NodeSocketLists_Type ) < 0 )
 		return NULL;
 	if( PyType_Ready( &SockInMap_Type ) < 0 )
 		return NULL;
@@ -1173,11 +1527,13 @@ PyObject *Node_Init(void)
 	PyModule_AddIntConstant(submodule, "RGBA", SOCK_RGBA);
 	PyModule_AddIntConstant(submodule, "VECTOR", SOCK_VECTOR);
 
+	Py_INCREF(&NodeSocket_Type);
+	PyModule_AddObject(submodule, "Socket", (PyObject *)&NodeSocket_Type);
+
 	Py_INCREF(&Node_Type);
-	PyModule_AddObject(submodule, "node", (PyObject *)&Node_Type);
+	PyModule_AddObject(submodule, "Scripted", (PyObject *)&Node_Type);
 
 	return submodule;
-
 }
 
 static int Node_compare(BPy_Node *a, BPy_Node *b)
@@ -1189,7 +1545,7 @@ static int Node_compare(BPy_Node *a, BPy_Node *b)
 static PyObject *Node_repr(BPy_Node *self)
 {
 	return PyString_FromFormat( "[Node \"%s\"]",
-			self->node ? self->node->id->name+2 : "empty node");
+		self->node ? self->node->id->name+2 : "empty node");
 }
 
 BPy_Node *Node_CreatePyObject(bNode *node)
diff --git a/source/blender/python/api2_2x/Node.h b/source/blender/python/api2_2x/Node.h
index e229e678fe95c1cd2b112e5f6ca340d6c6115b9f..49626599887abec8cffb68d19b3f01ccb223b665 100644
--- a/source/blender/python/api2_2x/Node.h
+++ b/source/blender/python/api2_2x/Node.h
@@ -40,11 +40,19 @@
 #include "RE_shader_ext.h"		/* <- ShadeInput Shaderesult TexResult */
 
 extern PyTypeObject Node_Type;
+extern PyTypeObject NodeSocket_Type;
+extern PyTypeObject NodeSocketLists_Type;
 extern PyTypeObject ShadeInput_Type;
 
 #define BPy_Node_Check(v) \
     ((v)->ob_type == &Node_Type)
 
+#define BPy_NodeSocket_Check(v) \
+    ((v)->ob_type == &NodeSocket_Type)
+
+#define BPy_NodeSocketLists_Check(v) \
+    ((v)->ob_type == &NodeSocketLists_Type)
+
 #define BPy_ShadeInput_Check(v) \
     ((v)->ob_type == &ShadeInput_Type)
 
@@ -64,7 +72,7 @@ typedef struct {
 	bNode *node;
 	PyObject *input;
 	PyObject *output;
-} BPy_NodeSockets;
+} BPy_NodeSocketLists;
 
 typedef struct BPy_Node {
 	PyObject_HEAD
@@ -74,10 +82,19 @@ typedef struct BPy_Node {
 	ShadeInput *shi;
 } BPy_Node;
 
+typedef struct BPy_NodeSocket {
+	PyObject_HEAD
+	char name[NODE_MAXSTR];
+	float min;
+	float max;
+	float val[4];
+	short type; /* VALUE, VECTOR or RGBA */
+} BPy_NodeSocket;
+
 extern PyObject *Node_Init(void);
 extern void InitNode(BPy_Node *self, bNode *node);
 extern BPy_Node *Node_CreatePyObject(bNode *node);
-extern BPy_NodeSockets *Node_CreateSockets(bNode *node);
+extern BPy_NodeSocketLists *Node_CreateSocketLists(bNode *node);
 extern void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type);
 extern void Node_SetShi(BPy_Node *self, ShadeInput *shi);
 extern int pytype_is_pynode(PyObject *pyob);
diff --git a/source/blender/python/api2_2x/SurfNurb.c b/source/blender/python/api2_2x/SurfNurb.c
index 3499ec099365f6e2af954aaf1378590558b83472..f1c038fc33c427d0d55355d2c96038a7d2244c7e 100644
--- a/source/blender/python/api2_2x/SurfNurb.c
+++ b/source/blender/python/api2_2x/SurfNurb.c
@@ -46,6 +46,8 @@ static int SurfNurb_setPoint( BPy_SurfNurb * self, int index, PyObject * ob );
 static int SurfNurb_length( PyInstanceObject * inst );
 static PyObject *SurfNurb_getIter( BPy_SurfNurb * self );
 static PyObject *SurfNurb_iterNext( BPy_SurfNurb * self );
+static PyObject *SurfNurb_getKnotsU( BPy_SurfNurb * self );
+static PyObject *SurfNurb_getKnotsV( BPy_SurfNurb * self );
 PyObject *SurfNurb_append( BPy_SurfNurb * self, PyObject * args );
 
 char M_SurfNurb_doc[] = "SurfNurb";
@@ -487,6 +489,58 @@ static int SurfNurb_setCyclicV( BPy_SurfNurb * self, PyObject * value )
 	return 0;
 }
 
+/*
+ * SurfNurb_getKnotsU
+ *
+ * Returns surface's knotsU in a tuple. Empty tuple is returned if
+ * surface isn't Nurbs or it doesn't have knots in U
+ */
+
+static PyObject *SurfNurb_getKnotsU( BPy_SurfNurb * self )
+{
+	if(self->nurb->knotsu) {
+		int len = KNOTSU(self->nurb);
+		int i;
+		PyObject *knotsu = PyTuple_New(len);
+		if( !knotsu )
+			return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+					"could not get SurfNurb.knotsU attribute" );
+
+		for(i = 0; i < len; ++i)
+			PyTuple_SetItem(knotsu, i,
+					PyFloat_FromDouble(self->nurb->knotsu[i]));
+
+		return knotsu;
+	}
+	return PyTuple_New(0);
+}
+
+/*
+ * SurfNurb_getKnotsV
+ *
+ * Returns surface's knotsV in a tuple.  Empty tuple is returned if
+ * curve doesn't have knots in V
+ */
+
+static PyObject *SurfNurb_getKnotsV( BPy_SurfNurb * self )
+{
+	if(self->nurb->knotsv) {
+		int len = KNOTSV(self->nurb);
+		int i;
+		PyObject *knotsv = PyTuple_New(len);
+		if( !knotsv )
+			return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+					"could not get SurfNurb.knotsV index" );
+
+		for(i = 0; i < len; ++i)
+			PyTuple_SetItem(knotsv, i,
+					PyFloat_FromDouble(self->nurb->knotsv[i] ));
+	
+		return knotsv;
+	}
+	return PyTuple_New(0);
+}
+
 
 /*
  * SurfNurb_getIter
@@ -723,6 +777,15 @@ static PyGetSetDef BPy_SurfNurb_getseters[] = {
 	{"orderV",
 	 (getter)SurfNurb_getOrderV, (setter)SurfNurb_setOrderV,
 	 "order setting for V direction", NULL},
+	{"knotsU",
+	 (getter)SurfNurb_getKnotsU, (setter)NULL,
+	 "The The knot vector in the U direction",
+	 NULL},
+	{"knotsV",
+	 (getter)SurfNurb_getKnotsV, (setter)NULL,
+	 "The The knot vector in the V direction",
+	 NULL},
+
 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 };
 
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index 5cfe796add8b648db290ccd7a9a01e7820994ee0..b4a14cc6ac81687269aa4176d049a64275d21119 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -47,6 +47,7 @@
 #include "BIF_space.h"
 #include "BIF_drawtext.h"
 #include "BIF_poseobject.h"
+#include "BIF_toolbox.h"	/* for error() */
 #include "DNA_view3d_types.h"
 #include "DNA_space_types.h"
 #include "DNA_scene_types.h"
@@ -513,6 +514,14 @@ static void getSelectedFile( char *name )
 			script = sc->script;
 		}
 	}
+	/* If 'script' is null,
+	 * The script must have had an error and closed,
+	 * but the fileselector was left open, show an error and exit */
+	if (!script) {
+		error("Python script error: script quit, cannot run callback");
+		return;
+	}
+		
 
 	pycallback = script->py_browsercallback;
 
@@ -526,10 +535,17 @@ static void getSelectedFile( char *name )
 				fprintf(stderr, "BPy error: Callback call failed!\n");
 		}
 		else Py_DECREF(result);
-
+		
+		
+			
 		if (script->py_browsercallback == pycallback) {
-			SCRIPT_SET_NULL(script);
+			if (script->flags & SCRIPT_GUI) {
+				script->py_browsercallback = NULL;
+			} else {
+				SCRIPT_SET_NULL(script);
+			}
 		}
+		
 		/* else another call to selector was made inside pycallback */
 
 		Py_DECREF(pycallback);
diff --git a/source/blender/python/api2_2x/doc/Constraint.py b/source/blender/python/api2_2x/doc/Constraint.py
index 61ee3c367002e2a0709984b29b4864d8c26f5cb0..0f9e4b5e07a043e36dd51088300350d43234cdba 100644
--- a/source/blender/python/api2_2x/doc/Constraint.py
+++ b/source/blender/python/api2_2x/doc/Constraint.py
@@ -31,17 +31,21 @@ Or to print all the constraints attached to each bone in a pose::
 @var Type: Constant Constraint dict used by L{Constraints.append()} and 
 	for comparison with L{Constraint.type}.  Values are
 	TRACKTO, IKSOLVER, FOLLOWPATH, COPYROT, COPYLOC, COPYSIZE, ACTION,
-	LOCKTRACK, STRETCHTO, FLOOR, LIMITLOC, LIMITROT, LIMITSIZE, CLAMPTO, 
-	PYTHON, CHILDOF, TRANSFORM, NULL
+	LOCKTRACK, STRETCHTO, FLOOR, LIMITLOC, LIMITROT, LIMITSIZE, LIMITDIST, 
+	CLAMPTO, PYTHON, CHILDOF, TRANSFORM, NULL
 
 @type Settings: readonly dictionary
 @var Settings: Constant dict used for changing constraint settings.
-	- Used for all constraints
-		- TARGET (Object) (Note: not used by Limit Location (LIMITLOC), 
-			Limit Rotation (LIMITROT), Limit Scale (LIMITSIZE))
-		- BONE (string): name of Bone sub-target (for armature targets) (Note: not
-			used by Stretch To (STRETCHTO), Limit Location (LIMITLOC), Limit Rotation 
-			(LIMITROT), Limit Scale (LIMITSIZE), Follow Path (FOLLOWPATH), Clamp To (CLAMPTO))
+	- Used for all single-target constraints 
+		(TRACKTO, FOLLOWPATH, COPYROT, COPYLOC, COPYSIZE, ACTION, LOCKTRACK, STRETCHTO, FLOOR, CLAMPTO, CHILDOF, TRANSFORM, LIMITDIST)
+		- TARGET (Object): target object
+		- BONE (string): name of Bone sub-target (for Armature targets), or name of Vertex Group sub-target
+			(for Geometry targets)
+	- Used for all multiple-target constraints
+		(PYTHON)
+		- TARGET (list of Objects): list of target objects, with one list slot = one target slot
+		- BONE (list of strings): list of names of Bone sub-target (for Armature targets) or name of Vertex Group
+			sub-targets (for Geometry targets)
 	- Used by some constraints:
 		- OWNERSPACE (int): for TRACKTO, COPYLOC, COPYROT, COPYSIZE, LIMITLOC, LIMITROT, LIMITSIZE, PYTHON, TRANSFORM
 			If the owner is an object, values are SPACE_WORLD, SPACE_LOCAL
@@ -123,6 +127,8 @@ Or to print all the constraints attached to each bone in a pose::
 		- YMAX (float): clamped to [0.0001,1000.0]
 		- ZMIN (float): clamped to [0.0001,1000.0]
 		- ZMAX (float): clamped to [0.0001,1000.0]
+	- Used by Limit Distance (LIMITDIST) constraint:
+		- LIMITMODE (int): any one of LIMIT_INSIDE, LIMIT_OUTSIDE, LIMIT_ONSURFACE
 	- Used by Python Script (PYTHON) constraint:
 		- SCRIPT (Text): script to use
 		- PROPERTIES (IDProperties): ID-Properties of constraint
diff --git a/source/blender/python/api2_2x/doc/Curve.py b/source/blender/python/api2_2x/doc/Curve.py
index c3760bc2c1deb8b872d1dfc9a2039d2c749c2b18..ba8d6d219708eae1220fb73d7d36e676c08a1445 100644
--- a/source/blender/python/api2_2x/doc/Curve.py
+++ b/source/blender/python/api2_2x/doc/Curve.py
@@ -694,6 +694,10 @@ class SurfNurb:
 	@ivar orderV: The order setting for the V direction.  Values are clamped
 	to the range [2:6] and not greater than the V dimension.
 	@type orderV: int
+	@ivar knotsU: The The knot vector in the U direction
+	@type knotsU: tuple
+	@ivar knotsV: The The knot vector in the V direction
+	@type knotsV: tuple
 	"""
 
 	def __setitem__( n, point ):
diff --git a/source/blender/python/api2_2x/doc/IpoCurve.py b/source/blender/python/api2_2x/doc/IpoCurve.py
index 873888cffb42a8d0146e2d7de52bd124039a6cd4..54d9136ec1e5a640048f1f60595ae68968678c98 100644
--- a/source/blender/python/api2_2x/doc/IpoCurve.py
+++ b/source/blender/python/api2_2x/doc/IpoCurve.py
@@ -11,6 +11,8 @@ This module provides access to the IpoCurve data in Blender.  An Ipo is
 composed of several IpoCurves, and an IpoCurve are composed of several 
 BezTriples.
 
+@warning: Ipo curves store euler rotations as degrees/10.0 so 180.0 would be 18.0
+
 Example::
   import Blender
   ipo = Blender.Ipo.Get('ObIpo')  # retrieves an Ipo object
diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py
index 0690b94712b9a283c689b3325a8e5ad6de99d522..8b49ce29d54b8a1a654cc7a0798d759b0e350a46 100644
--- a/source/blender/python/api2_2x/doc/Mesh.py
+++ b/source/blender/python/api2_2x/doc/Mesh.py
@@ -844,6 +844,44 @@ class Mesh:
 		@note: Only returns a valid result for mesh data that has no holes.
 		@note: Bubbles in the mesh work as expect.
 		"""
+	def getTangents():
+		"""
+		Calculates tangents for this mesh, returning a list of tuples,
+		each with 3 or 4 tangent vectors, these are alligned with the meshes faces.
+		
+		Example::
+			# Display the tangents as edges over a the active mesh object
+			from Blender import *
+			sce = Scene.GetCurrent()
+			ob = sce.objects.active
+			
+			me = ob.getData(mesh=1)
+			ts = me.getTangents()
+			me_disp = Mesh.New()
+			
+			verts = []
+			edges = []
+			for i, f in enumerate(me.faces):
+				ft = ts[i]
+				for j, v in enumerate(f):
+					tan = ft[j]
+					print tan
+					co = v.co
+					
+					verts.append(co)
+					verts.append(co+tan)
+					
+					i = len(verts)
+					edges.append((i-1, i-2))
+			
+			me_disp.verts.extend( verts )
+			me_disp.edges.extend( edges )
+			
+			sce.objects.new( me_disp )
+		
+		@note: The tangents are computed using the active UV layer, if there are no UV layers, orco coords are used.
+		"""
+	
 	
 	def transform(matrix, recalc_normals = False, selected_only=False):
 		"""
diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py
index 42fd5b564fe7178c600988247a91522bd270516c..97c7c0ecc44d6db6fa1a282be15901f4f72248ae 100644
--- a/source/blender/python/api2_2x/doc/Render.py
+++ b/source/blender/python/api2_2x/doc/Render.py
@@ -440,6 +440,7 @@ class RenderData:
     @type filename: string 
     @since: 2.40
     @requires: You must have an image currently rendered before calling this method
+    @warning: This wont work in background mode. use renderAnim instead.
     """
 
   def play():
diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c
index 4bf823bc938e808e23ca10f561758683eb4d725f..d0440e11b52eeeaeb6ecf10c0c869f7a9a20d064 100644
--- a/source/blender/python/api2_2x/sceneRender.c
+++ b/source/blender/python/api2_2x/sceneRender.c
@@ -534,7 +534,11 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args )
 	if( !PyArg_ParseTuple( args, "s|i", &name_str, &zbuff ) )
 		return EXPP_ReturnPyObjError( PyExc_TypeError,
 				"expected a filename (string) and optional int" );
-
+	
+	if (G.background)
+		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+				"saveRenderedImage does not work in background mode, use renderAnim() instead" );
+	
 	if( strlen(self->renderContext->pic) + strlen(name_str)
 			>= sizeof(filepath) )
 		return EXPP_ReturnPyObjError( PyExc_ValueError,
diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c
index aca5a0885f4a80284c15b3efdf3e273d41c2cc21..88c5e2197f97b459ab56d389c8aeb37d7f778108 100644
--- a/source/blender/radiosity/intern/source/radrender.c
+++ b/source/blender/radiosity/intern/source/radrender.c
@@ -121,6 +121,7 @@ static void findshoot_rr(Render *re, VlakRen **shoot_p, RadFace **shootrf_p)
 		if(maxenergy<RG.convergence) {
 			*shoot_p= NULL;
 			*shootrf_p= NULL;
+			return;
 		}
 		shootrf->flag |= RAD_SHOOT;
 	}
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 2aa6cc10468fa2d0daf3a528cecab29517617a1e..22fb2e70d8721f7f5683dc7f3122b3ff0af1462f 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -497,6 +497,7 @@ typedef struct LampRen {
 #define R_GLOB_NOPUNOFLIP	16
 #define R_NEED_TANGENT	32
 #define R_SKIP_MULTIRES	64
+#define R_BAKE_TRACE	128
 
 /* vlakren->flag (vlak = face in dutch) char!!! */
 #define R_SMOOTH		1
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index cf1eeae58ec689fc771e92ec815d73f8a14381c4..cdc348279e5a3ce0961773857df71e612950af59 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -40,8 +40,8 @@
 
 /* vector defines */
 
-#define CROSS(dest, a, b)		dest[0]= a[1] * b[2] - a[2] * b[1]; dest[1]= a[2] * b[0] - a[0] * b[2]; dest[2]= a[0] * b[1] - a[1] * b[0]
-#define VECMUL(dest, f)			dest[0]*= f; dest[1]*= f; dest[2]*= f
+#define CROSS(dest, a, b)		{ dest[0]= a[1] * b[2] - a[2] * b[1]; dest[1]= a[2] * b[0] - a[0] * b[2]; dest[2]= a[0] * b[1] - a[1] * b[0]; }
+#define VECMUL(dest, f)			{ dest[0]*= f; dest[1]*= f; dest[2]*= f; }
 
 struct HaloRen;
 struct ShadeInput;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 933125202be06562044472b2469fd9a3c14900bf..42191ff35adb602c6ddd32097cadb5f90dba4ff0 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -451,77 +451,6 @@ static void calc_edge_stress(Render *re, ObjectRen *obr, Mesh *me)
 	MEM_freeN(accum);
 }
 
-void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, float *co3, float *n, float *tang)
-{
-	float tangv[3], ct[3], e1[3], e2[3], s1, t1, s2, t2, det;
-
-	s1= uv2[0] - uv1[0];
-	s2= uv3[0] - uv1[0];
-	t1= uv2[1] - uv1[1];
-	t2= uv3[1] - uv1[1];
-	det= 1.0f / (s1 * t2 - s2 * t1);
-	
-	/* normals in render are inversed... */
-	VecSubf(e1, co1, co2);
-	VecSubf(e2, co1, co3);
-	tang[0] = (t2*e1[0] - t1*e2[0])*det;
-	tang[1] = (t2*e1[1] - t1*e2[1])*det;
-	tang[2] = (t2*e1[2] - t1*e2[2])*det;
-	tangv[0] = (s1*e2[0] - s2*e1[0])*det;
-	tangv[1] = (s1*e2[1] - s2*e1[1])*det;
-	tangv[2] = (s1*e2[2] - s2*e1[2])*det;
-	Crossf(ct, tang, tangv);
-
-	/* check flip */
-	if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f)
-		VecMulf(tang, -1.0f);
-}
-
-/* For normal map tangents we need to detect uv boundaries, and only average
- * tangents in case the uvs are connected. Alternative would be to store 1 
- * tangent per face rather than 4 per face vertex, but that's not compatible
- * with games */
-
-typedef struct VertexTangent {
-	float tang[3], uv[2];
-	struct VertexTangent *next;
-} VertexTangent;
-
-static void sum_or_add_vertex_tangent(MemArena *arena, VertexTangent **vtang, float *tang, float *uv)
-{
-	VertexTangent *vt;
-
-	/* find a tangent with connected uvs */
-	for(vt= *vtang; vt; vt=vt->next) {
-		if(fabs(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabs(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT) {
-			VECADD(vt->tang, vt->tang, tang);
-			return;
-		}
-	}
-
-	/* if not found, append a new one */
-	vt= BLI_memarena_alloc(arena, sizeof(VertexTangent));
-	VECCOPY(vt->tang, tang);
-	vt->uv[0]= uv[0];
-	vt->uv[1]= uv[1];
-
-	if(*vtang)
-		vt->next= *vtang;
-	*vtang= vt;
-}
-
-static float *find_vertex_tangent(VertexTangent *vtang, float *uv)
-{
-	VertexTangent *vt;
-	static float nulltang[3] = {0.0f, 0.0f, 0.0f};
-
-	for(vt= vtang; vt; vt=vt->next)
-		if(fabs(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabs(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT)
-			return vt->tang;
-
-	return nulltang;	/* shouldn't happen, except for nan or so */
-}
-
 /* gets tangent from tface or orco */
 static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemArena *arena, VlakRen *vlr, int do_nmap_tangent, int do_tangent)
 {
@@ -5318,7 +5247,6 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
 	ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL};
 	ListBase strandsurface;
 	int step;
-	ModifierData *md = NULL;
 	
 	re->i.infostr= "Calculating previous vectors";
 	re->r.mode |= R_SPEED;
@@ -5453,6 +5381,8 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
 	re->excludeob= actob;
 	if(type == RE_BAKE_LIGHT)
 		re->flag |= R_SKIP_MULTIRES;
+	if(actob)
+		re->flag |= R_BAKE_TRACE;
 
 	if(type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT)
 		re->flag |= R_NEED_TANGENT;
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index d0f9be3fd79ff98916c454fd172a01cd4400d905..d423abefe968044dc7b44f1df41eb9f52a720d02 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -82,6 +82,11 @@ static int vlr_check_intersect(Isect *is, int ob, RayFace *face)
 	ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)is->userdata, ob);
 	VlakRen *vlr = (VlakRen*)face;
 
+	/* for baking selected to active non-traceable materials might still
+	 * be in the raytree */
+	if(!(vlr->mat->mode & MA_TRACEBLE))
+		return 0;
+
 	/* I know... cpu cycle waste, might do smarter once */
 	if(is->mode==RE_RAY_MIRROR)
 		return !(vlr->mat->mode & MA_ONLYCAST);
@@ -125,7 +130,8 @@ void makeraytree(Render *re)
 		for(v=0;v<obr->totvlak;v++) {
 			if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
 			else vlr++;
-			if(vlr->mat->mode & MA_TRACEBLE) {	
+			/* baking selected to active needs non-traceable too */
+			if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) {	
 				if((vlr->mat->mode & MA_WIRE)==0) {	
 					VECCOPY(co1, vlr->v1->co);
 					VECCOPY(co2, vlr->v2->co);
@@ -186,7 +192,7 @@ void makeraytree(Render *re)
 			}
 			else vlr++;
 			
-			if(vlr->mat->mode & MA_TRACEBLE)
+			if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE))
 				if((vlr->mat->mode & MA_WIRE)==0)
 					RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr);
 		}
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index bedce5e36ee7fb31f822240d150318ed309c93e8..35e0815cc697eeb44402eb14767bea786918d47b 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -826,9 +826,9 @@ void shade_input_set_shade_texco(ShadeInput *shi)
 		else {
 			/* qdn: flat faces have tangents too,
 			   could pick either one, using average here */
-			tl= 1.0f;
-			tu= 1.0f/3.0f;
-			tv= 1.0f/3.0f;
+			tl= 1.0f/3.0f;
+			tu= -1.0f/3.0f;
+			tv= -1.0f/3.0f;
 		}
 
 		shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index 377d72325f00a8c622df7eb07fcdedea7756d503..6af3b71102813d0b51078fbcadf68806a238a81f 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -2488,21 +2488,29 @@ int externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *t
 void render_realtime_texture(ShadeInput *shi, Image *ima)
 {
 	TexResult texr;
-	static Tex tex1, tex2;	// threadsafe
+	static Tex imatex[BLENDER_MAX_THREADS];	// threadsafe
 	static int firsttime= 1;
 	Tex *tex;
 	float texvec[3], dx[2], dy[2];
 	ShadeInputUV *suv= &shi->uv[shi->actuv];
+	int a;
 
 	if(firsttime) {
-		firsttime= 0;
-		default_tex(&tex1);
-		default_tex(&tex2);
-		tex1.type= TEX_IMAGE;
-		tex2.type= TEX_IMAGE;
+		BLI_lock_thread(LOCK_IMAGE);
+		if(firsttime) {
+			for(a=0; a<BLENDER_MAX_THREADS; a++) {
+				memset(&imatex[a], 0, sizeof(Tex));
+				default_tex(&imatex[a]);
+				imatex[a].type= TEX_IMAGE;
+			}
+
+			firsttime= 0;
+		}
+		BLI_unlock_thread(LOCK_IMAGE);
 	}
 	
-	if(shi->ys & 1) tex= &tex1; else tex= &tex2;	// threadsafe
+	tex= &imatex[shi->thread];
+	tex->iuser.ok= ima->ok;
 	
 	texvec[0]= 0.5+0.5*suv->uv[0];
 	texvec[1]= 0.5+0.5*suv->uv[1];
@@ -2519,12 +2527,6 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
 	if(shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); 
 	else imagewrap(tex, ima, NULL, texvec, &texr); 
 
-	if (tex->ima && tex->ima->flag & IMA_DO_PREMUL) {
-		texr.tr *= texr.ta;
-		texr.tg *= texr.ta;
-		texr.tb *= texr.ta;
-	}
-		
 	shi->vcol[0]*= texr.tr;
 	shi->vcol[1]*= texr.tg;
 	shi->vcol[2]*= texr.tb;
diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c
index e8062422e2a7846dfa4f16be0621a74669883145..cdc46cde8b7d4bd670849a80785484ea1cdfedc1 100644
--- a/source/blender/src/butspace.c
+++ b/source/blender/src/butspace.c
@@ -319,6 +319,7 @@ static void curvemap_buttons_zoom_out(void *cumap_v, void *unused)
 				d1= cumap->curr.xmin - cumap->clipr.xmin;
 		cumap->curr.xmin-= d1;
 		
+		d1= d;
 		if(cumap->flag & CUMA_DO_CLIP) 
 			if(cumap->curr.xmax+d > cumap->clipr.xmax)
 				d1= -cumap->curr.xmax + cumap->clipr.xmax;
@@ -331,6 +332,7 @@ static void curvemap_buttons_zoom_out(void *cumap_v, void *unused)
 				d1= cumap->curr.ymin - cumap->clipr.ymin;
 		cumap->curr.ymin-= d1;
 		
+		d1= d;
 		if(cumap->flag & CUMA_DO_CLIP) 
 			if(cumap->curr.ymax+d > cumap->clipr.ymax)
 				d1= -cumap->curr.ymax + cumap->clipr.ymax;
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index edd9a2ff82753ec2fe66758f75deb74aae91ac2f..7dd9f2aa76529746dca2cd0f262ec04a5d49f289 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1254,9 +1254,9 @@ static void modifiers_convertParticles(void *obv, void *mdv)
 	ParticleCacheKey *key, **cache;
 	Mesh *me;
 	MVert *mvert;
-	MFace *mface;
+	MEdge *medge;
 	int a, k, kmax;
-	int totvert=0, totface=0, cvert=0;
+	int totvert=0, totedge=0, cvert=0;
 	int totpart=0, totchild=0;
 
 	if(md->type != eModifierType_ParticleSystem) return;
@@ -1277,15 +1277,15 @@ static void modifiers_convertParticles(void *obv, void *mdv)
 	cache= psys->pathcache;
 	for(a=0; a<totpart; a++) {
 		key= cache[a];
-		totvert+= (int)(key->col[3])+1;
-		totface+= (int)(key->col[3]);
+		totvert+= key->steps+1;
+		totedge+= key->steps;
 	}
 
 	cache= psys->childcache;
 	for(a=0; a<totchild; a++) {
 		key= cache[a];
-		totvert+= (int)(key->col[3])+1;
-		totface+= (int)(key->col[3]);
+		totvert+= key->steps+1;
+		totedge+= key->steps;
 	}
 
 	if(totvert==0) return;
@@ -1295,25 +1295,27 @@ static void modifiers_convertParticles(void *obv, void *mdv)
 	me= obn->data;
 	
 	me->totvert= totvert;
-	me->totface= totface;
+	me->totedge= totedge;
 	
 	me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
-	me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+	me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+	me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
 	
 	mvert= me->mvert;
-	mface= me->mface;
+	medge= me->medge;
 
 	/* copy coordinates */
 	cache= psys->pathcache;
-	for(a=0; a<totpart; a++){
+	for(a=0; a<totpart; a++) {
 		key= cache[a];
-		kmax= (int)(key->col[3]);
+		kmax= key->steps;
 		for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
 			VECCOPY(mvert->co,key->co);
-			if(k){
-				mface->v1= cvert-1;
-				mface->v2= cvert;
-				mface++;
+			if(k) {
+				medge->v1= cvert-1;
+				medge->v2= cvert;
+				medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
+				medge++;
 			}
 		}
 	}
@@ -1321,18 +1323,21 @@ static void modifiers_convertParticles(void *obv, void *mdv)
 	cache=psys->childcache;
 	for(a=0; a<totchild; a++) {
 		key=cache[a];
-		kmax=(int)(key->col[3]);
+		kmax=key->steps;
 		for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
 			VECCOPY(mvert->co,key->co);
-			if(k){
-				mface->v1=cvert-1;
-				mface->v2=cvert;
-				mface++;
+			if(k) {
+				medge->v1=cvert-1;
+				medge->v2=cvert;
+				medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
+				medge++;
 			}
 		}
 	}
-	make_edges(me, 0);
+
+	DAG_scene_sort(G.scene);
 }
+
 static void modifiers_applyModifier(void *obv, void *mdv)
 {
 	Object *ob = obv;
@@ -2686,7 +2691,7 @@ static void load_buts_vfont(char *name)
 
 static void set_unicode_text_fs(char *file)
 {
-	if (file > 0) paste_unicodeText(file); 
+	if (file) paste_unicodeText(file); 
 }
 
 void do_fontbuts(unsigned short event)
@@ -5244,10 +5249,10 @@ static void editing_panel_links(Object *ob)
 			std_libbuttons(block, 143, 130, 0, NULL, B_POSELIB_BROWSE, ID_AC, 0, (ID *)act, (ID *)ob, &(G.buts->menunr), B_POSELIB_ALONE, 0, B_POSELIB_DELETE, 0, 0);
 			uiBlockSetCol(block, TH_AUTO);
 			
-			uiDefBut(block, BUT, B_POSELIB_VALIDATE,  "Auto-Sync PoseLib",	xco,110,160,20, 0, 0, 0, 0, 0, "Syncs the current PoseLib with the poses available");
-			
 			/* PoseLib -  Pose editing controls */
 			if (act) {
+				uiDefBut(block, BUT, B_POSELIB_VALIDATE,  "Auto-Sync PoseLib",	xco,110,160,20, 0, 0, 0, 0, 0, "Syncs the current PoseLib with the poses available");
+				
 				uiBlockBeginAlign(block);
 					/* currently 'active' pose */
 					if (act->markers.first) {
@@ -6195,6 +6200,9 @@ static void editing_panel_mesh_texface(void)
 		uiDefButC(block, ROW, REDRAWVIEW3D, "Add",		660,80,60,19, &tf->transp, 2.0, (float)TF_ADD,	0, 0, "Render face transparent and add color of face");
 		uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha",	720,80,60,19, &tf->transp, 2.0, (float)TF_ALPHA,0, 0, "Render polygon transparent, depending on alpha channel of the texture");
 	}
+	else
+		uiDefBut(block,LABEL,B_NOP, "(No Active Face)", 10,200,150,19,0,0,0,0,0,"");
+
 }
 
 void do_uvcalculationbuts(unsigned short event)
@@ -6464,7 +6472,10 @@ void editing_panels()
 			editing_panel_mesh_tools(ob, ob->data);
 			editing_panel_mesh_tools1(ob, ob->data);
 			uiNewPanelTabbed("Mesh Tools 1", "Editing");
-			editing_panel_mesh_skgen(ob, ob->data);
+			
+			if (G.rt == 42) /* hidden for now, no time for docs */
+				editing_panel_mesh_skgen(ob, ob->data);
+			
 			editing_panel_mesh_uvautocalculation();
 			if (EM_texFaceCheck())
 				editing_panel_mesh_texface();
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 8fb4fab4a92d0fca300d3da78b66ac47abc5ec75..7a0d00c05931ded2f249a3d056697ebe97649fe1 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -2470,18 +2470,24 @@ static uiBlock *add_groupmenu(void *arg_unused)
 {
 	uiBlock *block;
 	Group *group;
-	short yco= 0;
+	short xco=0, yco= 0, index=0;
 	char str[32];
 	
 	block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
 	uiBlockSetButmFunc(block, do_add_groupmenu, NULL);
 
 	uiDefBut(block, BUTM, B_NOP, "ADD NEW",		0, 20, 160, 19, NULL, 0.0, 0.0, 1, -1, "");
-	for(group= G.main->group.first; group; group= group->id.next, yco++) {
+	for(group= G.main->group.first; group; group= group->id.next, index++) {
 		if(group->id.lib) strcpy(str, "L  ");
 		else strcpy(str, "   ");
 		strcat(str, group->id.name+2);
-		uiDefBut(block, BUTM, B_NOP, str,	0, -20*yco, 160, 19, NULL, 0.0, 0.0, 1, yco, "");
+		uiDefBut(block, BUTM, B_NOP, str,	xco*160, -20*yco, 160, 19, NULL, 0.0, 0.0, 1, index, "");
+		
+		yco++;
+		if(yco>24) {
+			yco= 0;
+			xco++;
+		}
 	}
 	
 	uiTextBoundsBlock(block, 50);
diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c
index 9dbcd656df643f65d8ae9600c73187f81e13fda0..1d3ece58db7e25a93b1bb33e4faebd023aeda18c 100644
--- a/source/blender/src/drawaction.c
+++ b/source/blender/src/drawaction.c
@@ -168,7 +168,7 @@ static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
 		for (i=1; i < key->totkey; i++) {
 			make_rvk_slider(block, ob, i, 
 							x, y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
-
+			
 			y-=CHANNELHEIGHT+CHANNELSKIP;
 			
 			/* see sliderval array in editkey.c */
@@ -176,7 +176,6 @@ static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
 		}
 	}
 	uiDrawBlock(block);
-
 }
 
 static void icu_slider_func(void *voidicu, void *voidignore) 
@@ -238,7 +237,7 @@ static void make_icu_slider(uiBlock *block, IpoCurve *icu,
 	/* create a slider for the ipo-curve*/
 	uiBut *but;
 	
-	if(icu==NULL) return;
+	if(icu == NULL) return;
 	
 	if (IS_EQ(icu->slide_max, icu->slide_min)) {
 		if (IS_EQ(icu->ymax, icu->ymin)) {
@@ -359,7 +358,7 @@ static void action_icu_buts(SpaceAction *saction)
 						// TODO...
 					}
 						break;
-				}	
+				}
 			}
 			
 			/* adjust y-position for next one */
@@ -905,7 +904,7 @@ void do_actionbuts(unsigned short event)
 	}
 }
 
-
+// currently not used...
 static void action_panel_properties(short cntrl)	// ACTION_HANDLER_PROPERTIES
 {
 	uiBlock *block;
@@ -913,10 +912,10 @@ static void action_panel_properties(short cntrl)	// ACTION_HANDLER_PROPERTIES
 	block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
 	uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
 	uiSetPanelHandler(ACTION_HANDLER_PROPERTIES);  // for close and esc
-	if(uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) return;
+	if (uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) 
+		return;
 
 	uiDefBut(block, LABEL, 0, "test text",		10,180,300,19, 0, 0, 0, 0, 0, "");
-
 }
 
 static void action_blockhandlers(ScrArea *sa)
@@ -924,17 +923,17 @@ static void action_blockhandlers(ScrArea *sa)
 	SpaceAction *sact= sa->spacedata.first;
 	short a;
 	
-	for(a=0; a<SPACE_MAXHANDLER; a+=2) {
+	for (a=0; a<SPACE_MAXHANDLER; a+=2) {
 		switch(sact->blockhandler[a]) {
-
-		case ACTION_HANDLER_PROPERTIES:
-			action_panel_properties(sact->blockhandler[a+1]);
-			break;
-		
+			case ACTION_HANDLER_PROPERTIES:
+				action_panel_properties(sact->blockhandler[a+1]);
+				break;
 		}
+		
 		/* clear action value for event */
 		sact->blockhandler[a+1]= 0;
 	}
+	
 	uiDrawBlocksPanels(sa, 0);
 }
 
@@ -959,7 +958,6 @@ void drawactionspace(ScrArea *sa, void *spacedata)
 
 	/* only try to refresh action that's displayed if not pinned */
 	if (G.saction->pin==0) {
-		/* TODO: allow more than one active action sometime? */
 		if (OBACT)
 			G.saction->action = OBACT->action;
 		else
@@ -1508,14 +1506,16 @@ void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, Act
 	if (agrp) {
 		/* loop through action channels */
 		for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
-			/* firstly, add keys from action channel's ipo block */
-			if (achan->ipo)
-				ipo_to_keylist(achan->ipo, keys, blocks, aki);
-			
-			/* then, add keys from constraint channels */
-			for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
-				if (conchan->ipo)
-					ipo_to_keylist(conchan->ipo, keys, blocks, aki);
+			if (VISIBLE_ACHAN(achan)) {
+				/* firstly, add keys from action channel's ipo block */
+				if (achan->ipo)
+					ipo_to_keylist(achan->ipo, keys, blocks, aki);
+				
+				/* then, add keys from constraint channels */
+				for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
+					if (conchan->ipo)
+						ipo_to_keylist(conchan->ipo, keys, blocks, aki);
+				}
 			}
 		}
 	}
diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c
index c94df84c7f7c8f10294c77c37043eec9f427006f..e13d0f4d0cd4da9ff85bd4725cd9fc5ae712a04c 100644
--- a/source/blender/src/drawipo.c
+++ b/source/blender/src/drawipo.c
@@ -2220,8 +2220,9 @@ void drawipospace(ScrArea *sa, void *spacedata)
 		
 		/* ipokeys */
 		if(sipo->showkey) {
-			if(sipo->ipokey.first==0) make_ipokey();
-			else update_ipokey_val();
+			//if(sipo->ipokey.first==0) make_ipokey();
+			//else update_ipokey_val();
+			make_ipokey();
 			draw_ipokey(sipo);
 		}
 		
diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c
index 2fe89727c43b63a98b6679995347d344f6852940..cea33685744429673be5bef7e690317d01639f69 100644
--- a/source/blender/src/drawnode.c
+++ b/source/blender/src/drawnode.c
@@ -356,9 +356,11 @@ static int node_buts_time(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *b
 
 		curvemap_buttons(block, node->storage, 's', B_NODE_EXEC+node->nr, B_REDR, butr);
 		
-		if(cumap) cumap->flag |= CUMA_DRAW_CFRA;
-		if(node->custom1<node->custom2)
-			cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
+		if(cumap) {
+			cumap->flag |= CUMA_DRAW_CFRA;
+			if(node->custom1<node->custom2)
+				cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
+		}
 
 		uiBlockBeginAlign(block);
 		uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Sta:",
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 260b0ab6656be0227b053458ec0c221cedb8de4b..9ddf5e405dd5e173e62d9608089a373d4bf33453 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -1995,7 +1995,7 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em)
 				Mat4MulVecfl(ob->obmat, v1);
 				Mat4MulVecfl(ob->obmat, v2);
 				Mat4MulVecfl(ob->obmat, v3);
-				if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
+				Mat4MulVecfl(ob->obmat, v4);
 			}
 			
 			e1= efa->e1;
diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c
index 73b1aa9856c1f5ba9674c4d3efa7f603ae710bca..327fcb341c7b16521a7f2773c6e17f3ddd1fc770 100644
--- a/source/blender/src/drawtext.c
+++ b/source/blender/src/drawtext.c
@@ -1442,7 +1442,7 @@ void run_python_script(SpaceText *st)
 		if (!st->text) return;
 
 		if (!strcmp(py_filename, st->text->id.name+2)) {
-			error("Python script error, check console");
+			error_pyscript(  );
 			if (lineno >= 0) {
 				txt_move_toline(text, lineno-1, 0);
 				txt_sel_line(text);
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index c4c221bcdf69bc5cc17314c37d6047f7d0db482e..e0919c7ba1c467526f6d9f697d6a15cdc392c381 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -1580,7 +1580,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
 	EditEdge *eed;
 	MDeformVert *dvert=NULL;
 	TransformProperties *tfp= G.vd->properties_storage;
-	float median[5];
+	float median[5], ve_median[5];
 	int tot, totw, totweight, totedge;
 	char defstr[320];
 	
@@ -1773,15 +1773,16 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
 		
 	}
 	else {	// apply
+		memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
 		
 		if(G.vd->flag & V3D_GLOBAL_STATS) {
 			Mat4Invert(ob->imat, ob->obmat);
 			Mat4MulVecfl(ob->imat, median);
-			Mat4MulVecfl(ob->imat, tfp->ve_median);
+			Mat4MulVecfl(ob->imat, ve_median);
 		}
-		VecSubf(median, tfp->ve_median, median);
-		median[3]= tfp->ve_median[3]-median[3];
-		median[4]= tfp->ve_median[4]-median[4];
+		VecSubf(median, ve_median, median);
+		median[3]= ve_median[3]-median[3];
+		median[4]= ve_median[4]-median[4];
 		
 		if(ob->type==OB_MESH) {
 			
@@ -1796,8 +1797,8 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
 			for(eed= em->edges.first; eed; eed= eed->next) {
 				if(eed->f & SELECT) {
 					/* ensure the median can be set to zero or one */
-					if(tfp->ve_median[3]==0.0f) eed->crease= 0.0f;
-					else if(tfp->ve_median[3]==1.0f) eed->crease= 1.0f;
+					if(ve_median[3]==0.0f) eed->crease= 0.0f;
+					else if(ve_median[3]==1.0f) eed->crease= 1.0f;
 					else {
 						eed->crease+= median[3];
 						CLAMP(eed->crease, 0.0, 1.0);
@@ -2888,6 +2889,108 @@ static void draw_sculpt_depths(View3D *v3d)
 	}
 }
 
+void draw_depth(ScrArea *sa, void *spacedata)
+{
+	View3D *v3d= spacedata;
+	Base *base;
+	Scene *sce;
+	short drawtype, zbuf, flag;
+	float glalphaclip;
+	/* temp set drawtype to solid */
+	
+	/* Setting these temporarily is not nice */
+	drawtype = v3d->drawtype;
+	zbuf = v3d->zbuf;
+	flag = v3d->flag;
+	glalphaclip = U.glalphaclip;
+	
+	U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
+	v3d->flag &= ~V3D_SELECT_OUTLINE;
+	if ((v3d->drawtype != OB_SOLID) && (v3d->drawtype != OB_TEXTURE)) 
+		v3d->drawtype = OB_SOLID;
+
+	setwinmatrixview3d(sa->winx, sa->winy, NULL);	/* 0= no pick rect */
+	setviewmatrixview3d();	/* note: calls where_is_object for camera... */
+	
+	Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
+	Mat4Invert(v3d->persinv, v3d->persmat);
+	Mat4Invert(v3d->viewinv, v3d->viewmat);
+	
+	glClear(GL_DEPTH_BUFFER_BIT);
+	
+	myloadmatrix(v3d->viewmat);
+	persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
+	
+	if(v3d->flag & V3D_CLIPPING) {
+		view3d_set_clipping(v3d);
+	}
+	
+	v3d->zbuf= TRUE;
+	glEnable(GL_DEPTH_TEST);
+	
+	/* draw set first */
+	if(G.scene->set) {
+		for(SETLOOPER(G.scene->set, base)) {
+			if(v3d->lay & base->lay) {
+				draw_object(base, 0);
+				if(base->object->transflag & OB_DUPLI) {
+					draw_dupli_objects_color(v3d, base, TH_WIRE);
+				}
+			}
+		}
+	}
+	
+	for(base= G.scene->base.first; base; base= base->next) {
+		if(v3d->lay & base->lay) {
+			
+			/* dupli drawing */
+			if(base->object->transflag & OB_DUPLI) {
+				draw_dupli_objects(v3d, base);
+			}
+			draw_object(base, 0);
+		}
+	}
+	
+	/* this isnt that nice, draw xray objects as if they are normal */
+	if (v3d->afterdraw.first) {
+		View3DAfter *v3da, *next;
+		int num = 0;
+		v3d->xray= TRUE;
+		
+		glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
+		for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+			next= v3da->next;
+			if(v3da->type==V3D_XRAY) {
+				draw_object(v3da->base, 0);
+				num++;
+			}
+			/* dont remove this time */
+		}
+		v3d->xray= FALSE;
+		
+		glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
+		for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+			next= v3da->next;
+			if(v3da->type==V3D_XRAY) {
+				v3d->xray= TRUE; v3d->transp= FALSE;  
+			} else if (v3da->type==V3D_TRANSP) {
+				v3d->xray= FALSE; v3d->transp= TRUE;
+			}
+			
+			draw_object(v3da->base, 0); /* Draw Xray or Transp objects normally */
+			BLI_remlink(&v3d->afterdraw, v3da);
+			MEM_freeN(v3da);
+		}
+		v3d->xray= FALSE;
+		v3d->transp= FALSE;
+	}
+	
+	v3d->drawtype = drawtype;
+	v3d->zbuf = zbuf;
+	U.glalphaclip = glalphaclip;
+	v3d->flag = flag;
+}
+
 static void draw_viewport_fps(ScrArea *sa);
 
 
diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c
index ecd546a67802caaadf48e966f649ed9448663e11..9190b3263f01f147d569a9be8be3d3e4a91ba741 100644
--- a/source/blender/src/edit.c
+++ b/source/blender/src/edit.c
@@ -1856,6 +1856,22 @@ void snapmenu()
 	}
 }
 
+void alignmenu()
+{
+	short val;
+	char *str_menu = BIF_menustringTransformOrientation("Align");
+	val= pupmenu(str_menu);
+	MEM_freeN(str_menu);
+
+	if (val >= 0)
+	{
+		short old_val = G.vd->twmode; 
+		G.vd->twmode = val;
+		initTransform(TFM_ALIGN, CTX_NO_PET|CTX_AUTOCONFIRM);
+		Transform();
+		G.vd->twmode = old_val;
+	}
+}
 
 #define MERGELIMIT 0.001
 void mergemenu(void)
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index d6d748f22135e565e5d6c89930a220ac3520d775..1a1bb9f4fb18ca43d37b9d3d3b6e63ce9a0a54e4 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -1088,7 +1088,7 @@ void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[])
 		return;
 	if (name[0] == 0)
 		return;
-		
+	
 	/* try to get the channels */
 	pchan= get_pose_channel(pose, name);
 	if (pchan == NULL) return;
@@ -1432,6 +1432,7 @@ void insertkey_action(void)
 	allqueue(REDRAWACTION, 0);
 	allqueue(REDRAWIPO, 0);
 	allqueue(REDRAWNLA, 0);
+	allqueue(REDRAWBUTSOBJECT, 0);
 }
 
 /* delete selected keyframes */
@@ -1529,7 +1530,7 @@ void delete_action_channels (void)
 		bConstraintChannel *conchan, *cnext;
 		next= ale->next;
 		
-		/* release reference to ipo users */
+		/* release references to ipo users */
 		if (achan->ipo)
 			achan->ipo->id.us--;
 			
@@ -1540,12 +1541,16 @@ void delete_action_channels (void)
 				conchan->ipo->id.us--;
 		}
 		
+		/* remove action-channel from group(s) */
+		if (achan->grp)
+			action_groups_removeachan(act, achan);
+		
 		/* free memory */
 		BLI_freelistN(&achan->constraintChannels);
 		BLI_freelinkN(&act->chanbase, achan);
 		BLI_freelinkN(&act_data, ale);
 	}
-		
+	
 	remake_action_ipos(data);
 	
 	BIF_undo_push("Delete Action Channels");
@@ -1867,7 +1872,7 @@ void paste_actdata ()
 				/* check if we have a corresponding action channel */
 				if ((no_name) || (strcmp(achan->name, achant->name)==0)) {
 					actname= achan->name;
-
+					
 					/* check if this is a constraint channel */
 					if (ale->type == ACTTYPE_CONCHAN) {
 						bConstraintChannel *conchant= ale->data;
@@ -1901,12 +1906,12 @@ void paste_actdata ()
 		/* this shouldn't happen, but it might */
 		if (ELEM(NULL, ipo_src, ipo_dst))
 			continue;
-
+		
 		/* loop over curves, pasting keyframes */
 		for (ico= ipo_src->curve.first; ico; ico= ico->next) {
 			icu= verify_ipocurve((ID*)OBACT, ico->blocktype, actname, conname, "", ico->adrcode);
-
-			if(icu) {
+			
+			if (icu) {
 				/* just start pasting, with the the first keyframe on the current frame, and so on */
 				for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) {						
 					/* temporarily apply offset to src beztriple while copying */
@@ -4233,7 +4238,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 				 */
 				if (IN_2D_VERT_SCROLL(mval))
 					selectall_action_keys(mval, 0, select_mode);
-		
+				
 				/* Clicking in the horizontal scrollbar selects
 				 * all of the keys within 0.5 of the nearest integer
 				 * frame
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index 55ed6252dae2c2267967db8e15c12c214b48567f..a93d81e04af803f1ffe426a4f163e11974584b24 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -2843,23 +2843,56 @@ void clear_armature(Object *ob, char mode)
 	bPoseChannel *pchan;
 	bArmature	*arm;
 
-	arm=get_armature(ob);
-	
-	if (!arm)
+	arm= get_armature(ob);
+	if (arm == NULL)
 		return;
 	
-	for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-		if(pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
-			if(arm->layer & pchan->bone->layer) {
+	/* only clear those channels that are not locked */
+	for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+		if (pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
+			if (arm->layer & pchan->bone->layer) {
 				switch (mode) {
 					case 'r':
-						pchan->quat[1]=pchan->quat[2]=pchan->quat[3]=0.0F; pchan->quat[0]=1.0F;
+						if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ)) {
+							float eul[3], oldeul[3], quat1[4];
+							
+							QUATCOPY(quat1, pchan->quat);
+							QuatToEul(pchan->quat, oldeul);
+							eul[0]= eul[1]= eul[2]= 0.0f;
+							
+							if (pchan->protectflag & OB_LOCK_ROTX)
+								eul[0]= oldeul[0];
+							if (pchan->protectflag & OB_LOCK_ROTY)
+								eul[1]= oldeul[1];
+							if (pchan->protectflag & OB_LOCK_ROTZ)
+								eul[2]= oldeul[2];
+							
+							EulToQuat(eul, pchan->quat);
+							/* quaternions flip w sign to accumulate rotations correctly */
+							if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
+								QuatMulf(pchan->quat, -1.0f);
+							}
+						}						
+						else { 
+							pchan->quat[1]=pchan->quat[2]=pchan->quat[3]=0.0F; 
+							pchan->quat[0]=1.0F;
+						}
 						break;
 					case 'g':
-						pchan->loc[0]=pchan->loc[1]=pchan->loc[2]=0.0F;
+						if ((pchan->protectflag & OB_LOCK_LOCX)==0)
+							pchan->loc[0]= 0.0f;
+						if ((pchan->protectflag & OB_LOCK_LOCY)==0)
+							pchan->loc[1]= 0.0f;
+						if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
+							pchan->loc[2]= 0.0f;
 						break;
 					case 's':
-						pchan->size[0]=pchan->size[1]=pchan->size[2]=1.0F;
+						if ((pchan->protectflag & OB_LOCK_SCALEX)==0)
+							pchan->size[0]= 1.0f;
+						if ((pchan->protectflag & OB_LOCK_SCALEY)==0)
+							pchan->size[1]= 1.0f;
+						if ((pchan->protectflag & OB_LOCK_SCALEZ)==0)
+							pchan->size[2]= 1.0f;
 						break;
 						
 				}
@@ -3003,7 +3036,6 @@ void deselectall_posearmature (Object *ob, int test, int doundo)
 int bone_looper(Object *ob, Bone *bone, void *data,
                         int (*bone_func)(Object *, Bone *, void *)) 
 {
-
     /* We want to apply the function bone_func to every bone 
      * in an armature -- feed bone_looper the first bone and 
      * a pointer to the bone_func and watch it go!. The int count 
@@ -3013,19 +3045,15 @@ int bone_looper(Object *ob, Bone *bone, void *data,
     int count = 0;
 
     if (bone) {
-
-        /* only do bone_func if the bone is non null
-         */
+		/* only do bone_func if the bone is non null */
         count += bone_func(ob, bone, data);
-
-        /* try to execute bone_func for the first child
-         */
-        count += bone_looper(ob, bone->childbase.first, data,
-                                    bone_func);
-
-        /* try to execute bone_func for the next bone at this
-         * depth of the recursion.
-         */
+		
+		/* try to execute bone_func for the first child */
+        count += bone_looper(ob, bone->childbase.first, data, bone_func);
+		
+		/* try to execute bone_func for the next bone at this
+		 * depth of the recursion.
+		 */
         count += bone_looper(ob, bone->next, data, bone_func);
     }
 
@@ -3063,15 +3091,15 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
 
 	if(!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
 		if (!(bone->flag & BONE_NO_DEFORM)) {
-			if(data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
+			if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
 				segments = bone->segments;
 			else
 				segments = 1;
-
+			
 			if (data->list != NULL) {
 				hbone = (Bone ***) &data->list;
 				
-				for(a=0; a<segments; a++) {
+				for (a=0; a<segments; a++) {
 					**hbone = bone;
 					++*hbone;
 				}
@@ -3085,9 +3113,9 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
 static int add_defgroup_unique_bone(Object *ob, Bone *bone, void *data) 
 {
     /* This group creates a vertex group to ob that has the
-     * same name as bone (provided the bone is skinnable). 
+      * same name as bone (provided the bone is skinnable). 
 	 * If such a vertex group aleady exist the routine exits.
-     */
+      */
 	if (!(bone->flag & BONE_NO_DEFORM)) {
 		if (!get_named_vertexgroup(ob,bone->name)) {
 			add_defgroup_name(ob, bone->name);
@@ -3126,19 +3154,19 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
 	int a, segments;
 	struct { Object *armob; void *list; int heat; } *data= datap;
 
-	if(!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+	if (!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
 	   if (!(bone->flag & BONE_NO_DEFORM)) {
-			if(data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
+			if (data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
 				segments = bone->segments;
 			else
 				segments = 1;
-
-			if(!(defgroup = get_named_vertexgroup(ob, bone->name)))
+			
+			if (!(defgroup = get_named_vertexgroup(ob, bone->name)))
 				defgroup = add_defgroup_name(ob, bone->name);
-
+			
 			if (data->list != NULL) {
 				hgroup = (bDeformGroup ***) &data->list;
-
+			
 				for(a=0; a<segments; a++) {
 					**hgroup = defgroup;
 					++*hgroup;
@@ -3170,15 +3198,15 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
 	/* for each vertex in the mesh */
 	for (i=0; i < mesh->totvert; i++) {
 		iflip = (dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
-
+		
 		/* for each skinnable bone */
 		for (j=0; j < numbones; ++j) {
 			if(!selected[j])
 				continue;
-
+			
 			bone = bonelist[j];
 			dgroup = dgrouplist[j];
-
+			
 			/* store the distance-factor from the vertex to the bone */
 			distance = distfactor_to_bone (verts[i], root[j], tip[j],
 				bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
@@ -3188,7 +3216,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
 				add_vert_to_defgroup (ob, dgroup, i, distance, WEIGHT_REPLACE);
 			else
 				remove_vert_defgroup (ob, dgroup, i);
-
+			
 			/* do same for mirror */
 			if (dgroupflip && dgroupflip[j] && iflip >= 0) {
 				if (distance!=0.0)
@@ -3273,7 +3301,7 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
 			if(segments == 0) {
 				segments = 1;
 				bbone = NULL;
-
+			
 				if(par->pose && (pchan=get_pose_channel(par->pose, bone->name))) {
 					if(bone->segments > 1) {
 						segments = bone->segments;
@@ -3281,10 +3309,10 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
 					}
 				}
 			}
-
+			
 			segments--;
 		}
-
+		
 		/* compute root and tip */
 		if(bbone) {
 			VECCOPY(root[j], bbone[segments].mat[3]);
@@ -3300,10 +3328,10 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
 			VECCOPY(root[j], bone->arm_head);
 			VECCOPY(tip[j], bone->arm_tail);
 		}
-
+		
 		Mat4MulVecfl(par->obmat, root[j]);
 		Mat4MulVecfl(par->obmat, tip[j]);
-
+		
 		/* set selected */
 		if(wpmode) {
 			if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
@@ -3311,7 +3339,7 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
 		}
 		else
 			selected[j] = 1;
-
+		
 		/* find flipped group */
 		if(mirror) {
 			char name[32];
@@ -3319,11 +3347,11 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
 			BLI_strncpy(name, dgroup->name, 32);
 			// 0 = don't strip off number extensions
 			bone_flip_name(name, 0);
-
+			
 			for (curdg = ob->defbase.first; curdg; curdg=curdg->next)
 				if (!strcmp(curdg->name, name))
 					break;
-
+			
 			dgroupflip[j] = curdg;
 		}
 	}
@@ -3335,12 +3363,12 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
 	if (wpmode) {
 		/* if in weight paint mode, use final verts from derivedmesh */
 		DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
-
+		
 		if(dm->foreachMappedVert) {
 			dm->foreachMappedVert(dm, add_vgroups__mapFunc, (void*)verts);
 			vertsfilled = 1;
 		}
-
+		
 		dm->release(dm);
 	}
 	else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
@@ -3406,9 +3434,9 @@ void create_vgroups_from_armature(Object *ob, Object *par)
 					add_defgroup_unique_bone);
 		if (ob->type == OB_MESH)
 			create_dverts(ob->data);
-
+		
 		break;
-
+	
 	case 3:
 	case 4:
 		/* Traverse the bone list, trying to create vertex groups 
@@ -3444,7 +3472,7 @@ void hide_selected_pose_bones(void)
 
 	bone_looper(OBACT, arm->bonebase.first, NULL, 
 				hide_selected_pose_bone);
-
+	
 	allqueue(REDRAWVIEW3D, 0);
 	allqueue(REDRAWBUTSEDIT, 0);
 	allqueue(REDRAWACTION, 0);
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
index ef656281d754ec10ebb97ce07528c2348def480a..fe68e0818bbf3002accef2e69d605bcc853ce3fa 100644
--- a/source/blender/src/editipo.c
+++ b/source/blender/src/editipo.c
@@ -1815,7 +1815,7 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char
 		if(achan) {
 			/* automatically assign achan to act-group based on pchan's grouping */
 			if (blocktype == ID_PO)
-			verify_pchan2achan_grouping(ob->action, ob->pose, actname);
+				verify_pchan2achan_grouping(ob->action, ob->pose, actname);
 			
 			/* constraint exception */
 			if(blocktype==ID_CO) {
@@ -2268,14 +2268,14 @@ void add_vert_ipo(void)
 	BIF_undo_push("Add Ipo vertex");
 }
 
-static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, IpoCurve *icu, int *vartype)
+static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype)
 {
-	if(blocktype==ID_PO) {
-		if(GS(id->name)==ID_OB) {
+	if (blocktype==ID_PO) {
+		if (GS(id->name)==ID_OB) {
 			Object *ob= (Object *)id;
 			bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
 			
-			if(pchan) {
+			if (pchan) {
 				*vartype= IPO_FLOAT;
 				return get_pchan_ipo_poin(pchan, icu->adrcode);
 			}
@@ -2284,6 +2284,35 @@ static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, IpoCurve
 		}
 		return NULL;
 	}
+	else if (blocktype==ID_CO) {
+		if ((GS(id->name)==ID_OB) && (constname && constname[0])) {
+			Object *ob= (Object *)id;
+			bConstraint *con;
+			
+			/* assume that we only want the influence (as only used for Constraint Channels) */
+			if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) {
+				for (con= ob->constraints.first; con; con= con->next) {
+					if (strcmp(constname, con->name)==0) {
+						*vartype= IPO_FLOAT;
+						return &con->enforce;
+					}
+				}
+			}
+			else if (ob->pose) {
+				bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
+				
+				if (pchan) {
+					for (con= pchan->constraints.first; con; con= con->next) {
+						if (strcmp(constname, con->name)==0) {
+							*vartype= IPO_FLOAT;
+							return &con->enforce;
+						}
+					}
+				}
+			}
+		}
+		return NULL;
+	}
 	else
 		return get_ipo_poin(id, icu, vartype);
 
@@ -2420,7 +2449,7 @@ static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *cons
 		
 		if(icu) {
 			
-			poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+			poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
 			
 			if(poin) {
 				curval= read_ipo_poin(poin, vartype);
@@ -2641,7 +2670,7 @@ void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcod
 		
 		if(icu) {
 			
-			poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+			poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
 			
 			if(poin) {
 				curval= read_ipo_poin(poin, vartype);
@@ -2683,7 +2712,7 @@ void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, in
 	
 	if(icu) {
 		
-		poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+		poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
 		
 		if(poin) {
 			curval= read_ipo_poin(poin, vartype);
@@ -2735,7 +2764,7 @@ void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int a
 	
 	if(icu) {
 		
-		poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+		poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
 		
 		if(poin) {
 			
diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c
index b99710f782f23c909f29b10695a11dc6598835ab..ca47741b6f105788100d2b64dcfe1518d0285080 100644
--- a/source/blender/src/editmesh_loop.c
+++ b/source/blender/src/editmesh_loop.c
@@ -488,11 +488,11 @@ static CutCurve *get_mouse_trail(int *len, char mode, char cutmode, struct GHash
 {
 	CutCurve *curve,*temp;
 	EditVert *snapvert;
-	float *scr, mval[2]={0.0,0.0}, lastx=0, lasty=0;
+	float *scr, mval[2]={0.0,0.0}, lastx=0, lasty=0, lockx=0, locky=0;
 	int i=0, j, blocks=1, lasti=0;
 	int dist, tolerance;
 	short event, val, qual, vsnap=0, ldown=0, restart=0, rubberband=0;
-	short mval1[2], lockaxis=0, lockx=0, locky=0, oldmode; 
+	short mval1[2], lockaxis=0, oldmode; 
 	
 	*len=0;
 	tolerance = 75;
diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c
index a308b42889450e777488d7a99bba928b72683ff0..ab2a36aa2d3ff2b05f461bd6da87bc20cf7dbf9b 100644
--- a/source/blender/src/editnode.c
+++ b/source/blender/src/editnode.c
@@ -1138,16 +1138,7 @@ void node_rename(SpaceNode *snode)
 /* used in buttons to check context, also checks for edited groups */
 bNode *editnode_get_active_idnode(bNodeTree *ntree, short id_code)
 {
-	bNode *node;
-	
-	/* check for edited group */
-	for(node= ntree->nodes.first; node; node= node->next)
-		if(node->flag & NODE_GROUP_EDIT)
-			break;
-	if(node)
-		return nodeGetActiveID((bNodeTree *)node->id, id_code);
-	else
-		return nodeGetActiveID(ntree, id_code);
+	return nodeGetActiveID(ntree, id_code);
 }
 
 /* used in buttons to check context, also checks for edited groups */
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 1a3775ac301c7ec67184bb4eaa9fb56c841feba4..07973926503cce3fd56f4f54f18833a6691433c7 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1030,18 +1030,31 @@ void clear_object(char mode)
 				 *	- with a mesh in weightpaint mode, it's related armature needs to be cleared
 				 *	- with clearing transform of object being edited at the time
 				 */
-				if ((G.f & G_WEIGHTPAINT) || ob==OBACT) {
+				if ((G.f & G_WEIGHTPAINT) || (ob==OBACT)) {
 					clear_armature(ob, mode);
 					armature_clear= 1;	/* silly system to prevent another dag update, so no action applied */
 				}
 			}
 			else if((G.f & G_WEIGHTPAINT)==0) {
-				
-				if(mode=='r') {
-					memset(ob->rot, 0, 3*sizeof(float));
-					memset(ob->drot, 0, 3*sizeof(float));
+				/* only clear transforms of 'normal' (not armature) object if:
+				 *	- not in weightpaint mode or editmode
+				 *	- if that object's transform locks are not enabled (this is done on a per-channel basis)
+				 */
+				if (mode=='r') {
+					/* eulers can only get cleared if they are not protected */
+					if ((ob->protectflag & OB_LOCK_ROTX)==0)
+						ob->rot[0]= ob->drot[0]= 0.0f;
+					if ((ob->protectflag & OB_LOCK_ROTY)==0)
+						ob->rot[1]= ob->drot[1]= 0.0f;
+					if ((ob->protectflag & OB_LOCK_ROTZ)==0)
+						ob->rot[2]= ob->drot[2]= 0.0f;
+					
+					/* quats here are not really used anymore anywhere, so it probably doesn't 
+					 * matter to not clear them whether the euler-based rotation is used
+					 */
 					QuatOne(ob->quat);
 					QuatOne(ob->dquat);
+					
 #ifdef WITH_VERSE
 					if(ob->vnode) {
 						struct VNode *vnode = (VNode*)ob->vnode;
@@ -1051,9 +1064,14 @@ void clear_object(char mode)
 #endif
 
 				}
-				else if(mode=='g') {
-					memset(ob->loc, 0, 3*sizeof(float));
-					memset(ob->dloc, 0, 3*sizeof(float));
+				else if (mode=='g') {
+					if ((ob->protectflag & OB_LOCK_LOCX)==0)
+						ob->loc[0]= ob->dloc[0]= 0.0f;
+					if ((ob->protectflag & OB_LOCK_LOCY)==0)
+						ob->loc[1]= ob->dloc[1]= 0.0f;
+					if ((ob->protectflag & OB_LOCK_LOCZ)==0)
+						ob->loc[2]= ob->dloc[2]= 0.0f;
+					
 #ifdef WITH_VERSE
 					if(ob->vnode) {
 						struct VNode *vnode = (VNode*)ob->vnode;
@@ -1063,11 +1081,19 @@ void clear_object(char mode)
 #endif
 
 				}
-				else if(mode=='s') {
-					memset(ob->dsize, 0, 3*sizeof(float));
-					ob->size[0]= 1.0;
-					ob->size[1]= 1.0;
-					ob->size[2]= 1.0;
+				else if (mode=='s') {
+					if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
+						ob->dsize[0]= 0.0f;
+						ob->size[0]= 1.0f;
+					}
+					if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
+						ob->dsize[1]= 0.0f;
+						ob->size[1]= 1.0f;
+					}
+					if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
+						ob->dsize[2]= 0.0f;
+						ob->size[2]= 1.0f;
+					}
 #ifdef WITH_VERSE
 					if(ob->vnode) {
 						struct VNode *vnode = (VNode*)ob->vnode;
diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c
index 10d6187fc76e88f1835e86a743fc63a9e073498d..d40d76785b46a76a132eaf3dd3b0abcfcd3b3226 100644
--- a/source/blender/src/editseq.c
+++ b/source/blender/src/editseq.c
@@ -176,7 +176,7 @@ Sequence *get_forground_frame_seq(int frame)
 /* seq funcs's for transforming internally
  notice the difference between start/end and left/right.
  
- left and right are the bounds at which the setuence is rendered,
+ left and right are the bounds at which the sequence is rendered,
 start and end are from the start and fixed length of the sequence.
 */
 int seq_tx_get_start(Sequence *seq) {
@@ -2245,6 +2245,22 @@ static Sequence *dupli_seq(Sequence *seq)
 	return seqn;
 }
 
+static Sequence * deep_dupli_seq(Sequence * seq)
+{
+	Sequence * seqn = dupli_seq(seq);
+	if (seq->type == SEQ_META) {
+		Sequence * s;
+		for(s= seq->seqbase.first; s; s = s->next) {
+			Sequence * n = deep_dupli_seq(s);
+			if (n) { 
+				BLI_addtail(&seqn->seqbase, n);
+			}
+		}
+	}
+	return seqn;
+}
+
+
 static void recurs_dupli_seq(ListBase *old, ListBase *new)
 {
 	Sequence *seq;
@@ -2271,15 +2287,98 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new)
 	}
 }
 
+static Sequence * cut_seq(Sequence * seq, int cutframe)
+{
+	TransSeq ts;
+	Sequence *seqn = 0;
+	int skip_dup = FALSE;
+
+	/* backup values */
+	ts.start= seq->start;
+	ts.machine= seq->machine;
+	ts.startstill= seq->startstill;
+	ts.endstill= seq->endstill;
+	ts.startdisp= seq->startdisp;
+	ts.enddisp= seq->enddisp;
+	ts.startofs= seq->startofs;
+	ts.endofs= seq->endofs;
+	ts.len= seq->len;
+	
+	/* First Strip! */
+	/* strips with extended stillfames before */
+	
+	if ((seq->startstill) && (cutframe <seq->start)) {
+		/* don't do funny things with METAs ... */
+		if (seq->type == SEQ_META) {
+			skip_dup = TRUE;
+			seq->startstill = seq->start - cutframe;
+		} else {
+			seq->start= cutframe -1;
+			seq->startstill= cutframe -seq->startdisp -1;
+			seq->endofs = seq->len - 1;
+			seq->endstill= 0;
+		}
+	}
+	/* normal strip */
+	else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
+		seq->endofs = (seq->start+seq->len) - cutframe;
+	}
+	/* strips with extended stillframes after */
+	else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
+		seq->endstill -= seq->enddisp - cutframe;
+		/* don't do funny things with METAs ... */
+		if (seq->type == SEQ_META) {
+			skip_dup = TRUE;
+		}
+	}
+	
+	calc_sequence(seq);
+	
+	if (!skip_dup) {
+		/* Duplicate AFTER the first change */
+		seqn = deep_dupli_seq(seq);
+	}
+	
+	if (seqn) { /* should never fail */
+		seqn->flag |= SELECT;
+			
+		/* Second Strip! */
+		/* strips with extended stillframes before */
+		if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
+			seqn->start = ts.start;
+			seqn->startstill= ts.start- cutframe;
+			seqn->endofs = ts.endofs;
+			seqn->endstill = ts.endstill;
+		}
+		
+		/* normal strip */
+		else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
+			seqn->startstill = 0;
+			seqn->startofs = cutframe - ts.start;
+			seqn->endofs = ts.endofs;
+			seqn->endstill = ts.endstill;
+		}				
+		
+		/* strips with extended stillframes after */
+		else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
+			seqn->start = cutframe - ts.len +1;
+			seqn->startofs = ts.len-1;
+			seqn->endstill = ts.enddisp - cutframe -1;
+			seqn->startstill = 0;
+		}
+		
+		calc_sequence(seqn);
+	}
+	return seqn;
+}
+
 /* like duplicate, but only duplicate and cut overlapping strips,
  * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
-static void recurs_cut_seq(ListBase *old, ListBase *new, int cutframe)
+static int cut_seq_list(ListBase *old, ListBase *new, int cutframe)
 {
+	int did_something = FALSE;
 	Sequence *seq, *seq_next;
-	Sequence *seqn = 0;
 	
-	TransSeq ts;
-
 	seq= old->first;
 	
 	while(seq) {
@@ -2287,87 +2386,13 @@ static void recurs_cut_seq(ListBase *old, ListBase *new, int cutframe)
 		
 		seq->tmp= NULL;
 		if(seq->flag & SELECT) {
-			if(cutframe > seq->startdisp && cutframe < seq->enddisp) {
-				
-				/* backup values */
-				ts.start= seq->start;
-				ts.machine= seq->machine;
-				ts.startstill= seq->startstill;
-				ts.endstill= seq->endstill;
-				ts.startdisp= seq->startdisp;
-				ts.enddisp= seq->enddisp;
-				ts.startofs= seq->startofs;
-				ts.endofs= seq->endofs;
-				ts.len= seq->len;
-				
-				/* First Strip! */
-				/* strips with extended stillfames before */
-				if(seq->type!=SEQ_META) {
-					
-					if ((seq->startstill) && (cutframe <seq->start)) {
-						seq->start= cutframe -1;
-						seq->startstill= cutframe -seq->startdisp -1;
-						seq->len= 1;
-						seq->endstill= 0;
-					}
-				
-					/* normal strip */
-					else if ((cutframe >=seq->start)&&(cutframe <=(seq->start+seq->len))) {
-						seq->endofs = (seq->start+seq->len) - cutframe;
-					}
-				
-					/* strips with extended stillframes after */
-					else if (((seq->start+seq->len) < cutframe) && (seq->endstill)) {
-						seq->endstill -= seq->enddisp - cutframe;
-					}
-					
-					calc_sequence(seq);
-				}
-				
-				/* Duplicate AFTER the first change */
-				seqn = dupli_seq(seq);
-				
-				if (seqn) { /* should never fail */
-					seqn->flag |= SELECT;
-					
-					
+			if(cutframe > seq->startdisp && 
+			   cutframe < seq->enddisp) {
+				Sequence * seqn = cut_seq(seq, cutframe);
+				if (seqn) {
 					BLI_addtail(new, seqn);
-					
-					/* dont transform meta's - just do their children then recalc */
-					if(seq->type==SEQ_META) {
-						recurs_cut_seq(&seq->seqbase,&seqn->seqbase, cutframe);
-					} else {
-						/* Second Strip! */
-						/* strips with extended stillframes before */
-						if ((seqn->startstill) && (cutframe == seqn->start + 1)) {
-							seqn->start = ts.start;
-							seqn->startstill= ts.start- cutframe;
-							seqn->len = ts.len;
-							seqn->endstill = ts.endstill;
-						}
-			
-						/* normal strip */
-						else if ((cutframe>=seqn->start)&&(cutframe<=(seqn->start+seqn->len))) {
-							seqn->startstill = 0;
-							seqn->startofs = cutframe - ts.start;
-							seqn->endofs = ts.endofs;
-							seqn->endstill = ts.endstill;
-						}				
-			
-						/* strips with extended stillframes after */
-						else if (((seqn->start+seqn->len) < cutframe) && (seqn->endstill)) {
-							seqn->start = cutframe - ts.len +1;
-							seqn->startofs = ts.len-1;
-							seqn->endstill = ts.enddisp - cutframe -1;
-							seqn->startstill = 0;
-						}
-					}
-					
-					if(seq->type==SEQ_META) /* account for strips within changing */
-						calc_sequence(seq);
-					
-					calc_sequence(seqn);
 				}
+				did_something = TRUE;
 			} else if (seq->enddisp <= cutframe) {
 				/* do nothing */
 			} else if (seq->startdisp >= cutframe) {
@@ -2378,6 +2403,7 @@ static void recurs_cut_seq(ListBase *old, ListBase *new, int cutframe)
 		}
 		seq = seq_next;
 	}
+	return did_something;
 }
 
 void seq_cut(int cutframe)
@@ -2385,14 +2411,16 @@ void seq_cut(int cutframe)
 	Editing *ed;
 	ListBase newlist;
 	char side;
+	int did_something;
+
 	ed= G.scene->ed;
 	if(ed==0) return;
 	
 	newlist.first= newlist.last= NULL;
 	
-	recurs_cut_seq(ed->seqbasep, &newlist, cutframe);
+	did_something = cut_seq_list(ed->seqbasep, &newlist, cutframe);
 	
-	if (newlist.first) { /* simple check to see if anything was done */
+	if (newlist.first) { /* got new strips ? */
 		Sequence *seq;
 		addlisttolist(ed->seqbasep, &newlist);
 		
@@ -2415,7 +2443,8 @@ void seq_cut(int cutframe)
 		
 		/* as last: */
 		sort_seq();
-		
+	}
+	if (did_something) {
 		allqueue(REDRAWSEQ, 0);
 		BIF_undo_push("Cut Strips, Sequencer");
 	}
diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c
index edaec5fb26817be0e0a2cd5626c6ffbea144353e..42e438b2022f3e315f890e4aaf4cc5a2925a7548 100644
--- a/source/blender/src/editview.c
+++ b/source/blender/src/editview.c
@@ -2197,13 +2197,75 @@ void view3d_border_zoom(void)
 	float new_dist;
 	float new_ofs[3];
 	
-	/* doesn't work fine for perspective */
-	if(G.vd->persp==1)
-		return;
-	
 	val = get_border(&rect, 3); //box select input
-	if(val)
-	{
+	if(!val) return;
+	
+	if (G.vd->persp==1) { /* perspective */
+		View3D *v3d = G.vd;
+		bglMats mats;
+		float depth, depth_close= MAXFLOAT;
+		double cent[2],  p[3], p_corner[3];
+		int xs, ys, had_depth = 0;
+		
+		/* convert border to 3d coordinates */
+		bgl_get_mats(&mats);
+		
+		draw_depth(curarea, (void *)v3d);
+		
+		/* force updating */
+		if (v3d->depths) {
+			had_depth = 1;
+			v3d->depths->damaged = 1;
+		}
+		
+		view3d_update_depths(v3d);
+		
+		/* Constrain rect to depth bounds */
+		if (rect.xmin < 0) rect.xmin = 0;
+		if (rect.ymin < 0) rect.ymin = 0;
+		if (rect.xmax >= G.vd->depths->w) rect.xmax = G.vd->depths->w-1;
+		if (rect.ymax >= G.vd->depths->h) rect.ymax = G.vd->depths->h-1;		
+		
+		for (xs=rect.xmin; xs < rect.xmax; xs++) {
+			for (ys=rect.ymin; ys < rect.ymax; ys++) {
+				depth= v3d->depths->depths[ys*v3d->depths->w+xs];
+				if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) {
+					if (depth_close > depth) {
+						depth_close = depth;
+					}
+				}
+			}
+		}
+		
+		if (had_depth==0) {
+			MEM_freeN(v3d->depths->depths);
+			v3d->depths->depths = NULL;
+		}
+		v3d->depths->damaged = 1;
+		
+		/* no depths to use*/
+		if (depth_close==MAXFLOAT) 
+			return;
+		
+		cent[0] = (((double)rect.xmin)+((double)rect.xmax)) / 2;
+		cent[1] = (((double)rect.ymin)+((double)rect.ymax)) / 2;
+		
+		if ((	!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, mats.viewport, &p[0], &p[1], &p[2])) || 
+			(	!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, mats.modelview, mats.projection, mats.viewport, &p_corner[0], &p_corner[1], &p_corner[2])))
+			return;
+		
+		dvec[0] = p[0]-p_corner[0];
+		dvec[1] = p[1]-p_corner[1];
+		dvec[2] = p[2]-p_corner[2];
+		
+		new_dist = VecLength(dvec);
+		if(new_dist <= G.vd->near*1.5) new_dist= G.vd->near*1.5; 
+		
+		new_ofs[0] = -p[0];
+		new_ofs[1] = -p[1];
+		new_ofs[2] = -p[2];
+		
+	} else { /* othographic */
 		/* find the current window width and height */
 		vb[0] = G.vd->area->winx;
 		vb[1] = G.vd->area->winy;
@@ -2228,10 +2290,9 @@ void view3d_border_zoom(void)
 		
 		/* zoom in as required, or as far as we can go */
 		new_dist = ((new_dist*scale) >= 0.001*G.vd->grid)? new_dist*scale:0.001*G.vd->grid;
-		
-		smooth_view(G.vd, new_ofs, NULL, &new_dist, NULL);
-		
 	}
+	
+	smooth_view(G.vd, new_ofs, NULL, &new_dist, NULL);
 }
 
 void fly(void)
diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c
index a31f92c4b689b99bdd4fcd94bd5e94cd8290b533..4bbb9f18263b42356f85b5cacbfed3c00ce07040 100644
--- a/source/blender/src/header_action.c
+++ b/source/blender/src/header_action.c
@@ -1528,7 +1528,7 @@ void action_buttons(void)
 	xco= std_libbuttons(block, xco, 0, B_ACTPIN, &G.saction->pin, 
 						B_ACTIONBROWSE, ID_AC, 0, (ID*)G.saction->action, 
 						from, &(G.saction->actnr), B_ACTALONE, 
-						B_ACTLOCAL, B_ACTIONDELETE, 0, 0);	
+						B_ACTLOCAL, B_ACTIONDELETE, 0, B_KEEPDATA);	
 
 	uiClearButLock();
 
diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c
index b5abf0947e49f48e989b9cf2a01c85ed4896d2f8..5bb9ffcba4e666bd34fed6a9776a7c128c1fcd0d 100644
--- a/source/blender/src/header_image.c
+++ b/source/blender/src/header_image.c
@@ -617,7 +617,7 @@ static uiBlock *image_selectmenu(void *arg_unused)
 
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
 
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
 
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unlink Selection|Alt L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
 	
diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c
index b8d13b493bbcab44cfb4b33d23cef8ffddcc9611..5ec730bd0972b46c479a75b080d0bc9f8a12172f 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -934,7 +934,7 @@ static uiBlock *view3d_select_objectmenu(void *arg_unused)
 	uiDefBut(block, SEPR, 0, "",				0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 	
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse",						0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Inverse|Ctrl I",						0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Random",							0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
 	
 	uiDefIconTextBlockBut(block, view3d_select_object_layermenu, NULL, ICON_RIGHTARROW_THIN, "Select All by Layer", 0, yco-=20, 120, 19, "");
@@ -1787,8 +1787,7 @@ static void do_view3d_transformmenu(void *arg, int event)
 		G.scene->snap_target = SCE_SNAP_TARGET_ACTIVE;
 		break;
 	case 21:
-		initTransform(TFM_ALIGN, CTX_NO_PET|CTX_AUTOCONFIRM);
-		Transform();
+		alignmenu();
 		break;
 	}
 	allqueue(REDRAWVIEW3D, 0);
@@ -1977,7 +1976,7 @@ static uiBlock *view3d_edit_object_transformmenu(void *arg_unused)
 	block= uiNewBlock(&curarea->uiblocks, "view3d_edit_object_transformmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
 	uiBlockSetButmFunc(block, do_view3d_edit_object_transformmenu, NULL);
 	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Scale/Rotationr to ObData|Ctrl A, 1",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Scale/Rotation to ObData|Ctrl A, 1",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Visual Transform|Ctrl A, 2",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Deformation|Ctrl Shift A",		0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
 	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Duplicates Real|Ctrl Shift A",		0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
@@ -5638,7 +5637,7 @@ void view3d_buttons(void)
 				xco+= XIC;
 			}
 			
-			str_menu = BIF_menustringTransformOrientation();
+			str_menu = BIF_menustringTransformOrientation("Orientation");
 			uiDefButS(block, MENU, B_MAN_MODE, str_menu,xco,0,70,YIC, &G.vd->twmode, 0, 0, 0, 0, "Transform Orientation (ALT+Space)");
 			MEM_freeN(str_menu);
 			
diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c
index dde5a512de97131967fcbbd5ee9d856698673b4d..43ca45ffb67ced8f8d4223b2969e23a3fb772ade 100644
--- a/source/blender/src/headerbuttons.c
+++ b/source/blender/src/headerbuttons.c
@@ -364,14 +364,13 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
 		}
 		
 		if(del) {
-
 			uiSetButLock (pin && *pinpoin, "Can't unlink pinned data");
 			if(parid && parid->lib);
 			else {
 				uiDefIconBut(block, BUT, del, ICON_X, xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Deletes link to this Datablock");
 				xco+= XIC;
 			}
-
+			
 			uiClearButLock();
 		}
 
@@ -385,7 +384,10 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
 			
 		}
 		if(keepbut) {
-			uiDefBut(block, BUT, keepbut, "F", xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Saves this datablock even if it has no users");  
+			if(id->flag & LIB_FAKEUSER)
+				uiDefBut(block, BUT, keepbut, "F", xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Don't save this datablock even if it has no users");  
+			else
+				uiDefBut(block, BUT, keepbut, "F", xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Saves this datablock even if it has no users");  
 			xco+= XIC;
 		}
 	}
@@ -918,23 +920,30 @@ void do_global_buttons(unsigned short event)
 		}
 		break;
 	case B_ACTIONDELETE:
-		act=ob->action;
-		
-		if (act)
-			act->id.us--;
-		ob->action=NULL;
-		if(ob->pose) {		// clear flag, also used for draw colors
-			bPoseChannel *pchan;
-			for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
-				pchan->flag= 0;
-		}
-		BIF_undo_push("Unlink Action");
-		
-		allqueue(REDRAWVIEW3D, 0);
-		allqueue(REDRAWACTION, 0);
-		allqueue(REDRAWNLA, 0);
-		allqueue(REDRAWIPO, 0);
-		allqueue(REDRAWBUTSEDIT, 0);
+		/* only available when not pinned */
+		if (G.saction->pin == 0) {
+			act= ob->action;
+			
+			/* decrement user-count of action (as ob no longer uses it) */
+			if (act)
+				act->id.us--;
+			
+			/* make sure object doesn't hold reference to it anymore */	
+			ob->action=NULL;
+			if (ob->pose) {		/* clear flag (POSE_LOC/ROT/SIZE), also used for draw colors */
+				bPoseChannel *pchan;
+				for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
+					pchan->flag= 0;
+			}
+			
+			BIF_undo_push("Unlink Action");
+			
+			allqueue(REDRAWVIEW3D, 0);
+			allqueue(REDRAWACTION, 0);
+			allqueue(REDRAWNLA, 0);
+			allqueue(REDRAWIPO, 0);
+			allqueue(REDRAWBUTSEDIT, 0);
+		}
 		break;
 	case B_ACTIONBROWSE:
 		if (!ob)
@@ -947,18 +956,16 @@ void do_global_buttons(unsigned short event)
 			return;
 		}
 		
-		if(G.saction->actnr < 0) break;
+		if (G.saction->actnr < 0) break;
 		
 		/*	See if we have selected a valid action */
 		for (idtest= G.main->action.first; idtest; idtest= idtest->next) {
-				if(nr==G.saction->actnr) {
-					break;
-				}
-				nr++;
-			
+			if (nr==G.saction->actnr)
+				break;
+			nr++;
 		}
 
-		if(G.saction->pin) {
+		if (G.saction->pin) {
 			if (idtest == NULL) {
 				/* assign new/copy of pinned action only - messy as it doesn't assign to any obj's */
 				if (G.saction->action)
@@ -972,9 +979,8 @@ void do_global_buttons(unsigned short event)
 			allqueue(REDRAWACTION, 0);
 		}
 		else {
-
 			/* Store current action */
-			if (!idtest) {
+			if (idtest == NULL) {
 				/* 'Add New' option: 
 				 * 	- make a copy of an exisiting action
 				 *	- or make a new empty action if no existing action
@@ -983,10 +989,37 @@ void do_global_buttons(unsigned short event)
 					idtest= (ID *)copy_action(act);
 				} 
 				else { 
-					if (ID_OB==ob->type) {
-						/* for empties */
-						idtest=(ID *)add_empty_action("ObAction");
-					} 
+					if ((ob->ipo) && (ob->ipoflag & OB_ACTION_OB)==0) {
+						/* object ipo - like if B_IPO_ACTION_OB is triggered */
+						bActionChannel *achan;
+						
+						if (has_ipo_code(ob->ipo, OB_LAY))
+							notice("Note: Layer Ipo doesn't work in Actions");
+						
+						ob->ipoflag |= OB_ACTION_OB;
+						
+						act = add_empty_action("ObAction");
+						idtest=(ID *)act;
+						
+						
+						achan= verify_action_channel(act, "Object");
+						achan->flag = (ACHAN_HILIGHTED|ACHAN_SELECTED|ACHAN_EXPANDED|ACHAN_SHOWIPO);
+						
+						if (achan->ipo==NULL) {
+							achan->ipo= ob->ipo;
+							ob->ipo= NULL;
+							
+							allqueue(REDRAWIPO, 0);
+							allqueue(REDRAWOOPS, 0);
+						}
+						
+						/* object constraints */
+						if (ob->constraintChannels.first) {
+							free_constraint_channels(&achan->constraintChannels);
+							achan->constraintChannels= ob->constraintChannels;
+							ob->constraintChannels.first= ob->constraintChannels.last= NULL;
+						}
+					}
 					else if (ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) {
 						/* shapekey - like if B_IPO_ACTION_KEY is triggered */
 						bActionChannel *achan;
@@ -1000,11 +1033,10 @@ void do_global_buttons(unsigned short event)
 						achan= verify_action_channel(act, "Shape");
 						achan->flag = (ACHAN_HILIGHTED|ACHAN_SELECTED|ACHAN_EXPANDED|ACHAN_SHOWIPO);
 						
-						if(achan->ipo==NULL && key->ipo) {
+						if ((achan->ipo==NULL) && (key->ipo)) {
 							achan->ipo= key->ipo;
 							key->ipo= NULL;
 							
-							allqueue(REDRAWVIEW3D, 0);
 							allqueue(REDRAWIPO, 0);
 							allqueue(REDRAWOOPS, 0);
 						}
@@ -1018,15 +1050,15 @@ void do_global_buttons(unsigned short event)
 			}
 			
 			
-			if(idtest!=id && ob) {
+			if ((idtest!=id) && (ob)) {
 				act= (bAction *)idtest;
 				
 				ob->action= act;
 				id_us_plus(idtest);
 				
-				if(id) id->us--;
+				if (id) id->us--;
 				
-				// Update everything
+				/* Update everything */
 				BIF_undo_push("Browse Action");
 				do_global_buttons (B_NEWFRAME);
 				allqueue(REDRAWVIEW3D, 0);
@@ -1096,7 +1128,7 @@ void do_global_buttons(unsigned short event)
 			}
 			if(idtest!=id && from) {
 				spaceipo_assign_ipo(G.sipo, (Ipo *)idtest);
-									
+				
 				BIF_undo_push("Browse Ipo");
 			}
 		}
@@ -1613,7 +1645,9 @@ void do_global_buttons(unsigned short event)
 			id = (ID *)G.sipo->ipo;
 		} else if(curarea->spacetype==SPACE_NODE) {
 			id = ((SpaceNode *)curarea->spacedata.first)->id;
-		} /* similar for other spacetypes ? */
+		} else if(curarea->spacetype==SPACE_ACTION) {
+			id= (ID *)G.saction->action;
+		}/* similar for other spacetypes ? */
 		if (id) {
 			if( id->flag & LIB_FAKEUSER) {
 				id->flag -= LIB_FAKEUSER;
diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c
index 7b8efd0ed75235177a3cfd539848e3920be068da..539fde5b14d258aa8d6e925396b1b04ec5a429d9 100644
--- a/source/blender/src/imagepaint.c
+++ b/source/blender/src/imagepaint.c
@@ -593,8 +593,10 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho
 
 			if(ibuf && ibuf->rect)
 				texpaint_pick_uv(s->ob, s->me, newfaceindex, mval, newuv);
-			else
+			else {
 				newimage = NULL;
+				newuv[0] = newuv[1] = 0.0f;
+			}
 		}
 		else
 			newuv[0] = newuv[1] = 0.0f;
diff --git a/source/blender/src/interface_panel.c b/source/blender/src/interface_panel.c
index 0752a5dd198ac282ad86b911d94640a11233b8ff..de1e70caeec04436adcd00a76e6c036597b79667 100644
--- a/source/blender/src/interface_panel.c
+++ b/source/blender/src/interface_panel.c
@@ -606,7 +606,9 @@ static int panel_has_tabs(Panel *panel)
 	if(panel==NULL) return 0;
 	
 	while(pa) {
-		if(pa->paneltab==panel) return 1;
+		if(pa->active && pa->paneltab==panel) {
+			return 1;
+		}
 		pa= pa->next;
 	}
 	return 0;
diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c
index 8ac0a1f2558b566ae128f38654c4f6e765de0e07..f40ecb749489fffdda070aa795580aa5a77bf27c 100644
--- a/source/blender/src/meshtools.c
+++ b/source/blender/src/meshtools.c
@@ -1097,15 +1097,17 @@ void objects_bake_render(short event, char **error_msg)
 			if(bkr.ready)
 				break;
 			
-			g_break= blender_test_break();
-			
-			timer++;
-			if(area && timer==20) {
-				Image *ima= RE_bake_shade_get_image();
-				if(ima) ((SpaceImage *)area->spacedata.first)->image= ima;
-				scrarea_do_windraw(area);
-				myswapbuffers();	
-				timer= 0;
+			if (!G.background) {
+				g_break= blender_test_break();
+				
+				timer++;
+				if(area && timer==20) {
+					Image *ima= RE_bake_shade_get_image();
+					if(ima) ((SpaceImage *)area->spacedata.first)->image= ima;
+					scrarea_do_windraw(area);
+					myswapbuffers();	
+					timer= 0;
+				}
 			}
 		}
 		BLI_end_threads(&threads);
diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c
index 3fda71bf8281f1f006ddacb8f08685303e069d82..715a0f47afaba1ae0c316baaaf240916a5a24b04 100644
--- a/source/blender/src/sculptmode.c
+++ b/source/blender/src/sculptmode.c
@@ -1231,7 +1231,7 @@ void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse)
 
 	/* Set the pivot to allow the model to rotate around the center of the brush */
 	if(get_depth(mouse[0],mouse[1]) < 1.0)
-		VecCopyf(&sculpt_session()->pivot.x, a->symm.center_3d);
+		VecCopyf(sd->pivot, a->symm.center_3d);
 
 	/* Now project the Up, Right, and Out normals from view to model coords */
 	unproject(zero_loc, 0, 0, 0);
@@ -1692,7 +1692,7 @@ void sculpt(void)
 			}
 			else {
 				do_symmetrical_brush_actions(a, mouse, mvalo);
-				unproject(&ss->pivot.x, mouse[0], mouse[1], a->depth);
+				unproject(sd->pivot, mouse[0], mouse[1], a->depth);
 			}
 
 			if(modifier_calculations || ob_get_keyblock(ob))
diff --git a/source/blender/src/seqaudio.c b/source/blender/src/seqaudio.c
index 8b669d034d0e58b34eff9c309ca5817d0fdfc278..eb362f7187e9fae74e7c19dbe19af4839d3499c3 100644
--- a/source/blender/src/seqaudio.c
+++ b/source/blender/src/seqaudio.c
@@ -359,37 +359,53 @@ static void audio_fill_hd_sound(Sequence *seq,
 }
 
 static void audio_fill_seq(Sequence * seq, void * mixdown,
-			   Uint8 *sstream, int len)
+			   Uint8 *sstream, int len, int advance_only)
 {
 	while(seq) {
 		if (seq->type == SEQ_META &&
 		    (!(seq->flag & SEQ_MUTE))) {
-			audio_fill_seq(seq->seqbase.first,
-				       mixdown, sstream, len);
+			if (seq->startdisp <= CFRA && seq->enddisp > CFRA) {
+				audio_fill_seq(seq->seqbase.first,
+					       mixdown, sstream, len, 
+					       advance_only);
+			} else {
+				audio_fill_seq(seq->seqbase.first,
+					       mixdown, sstream, len, 
+					       1);
+			}
 		}
 		if ( (seq->type == SEQ_RAM_SOUND) &&
 		     (seq->sound) &&
 		     (!(seq->flag & SEQ_MUTE))) {
-			audio_fill_ram_sound(seq, mixdown, sstream, len);
+			if (advance_only) {
+				seq->curpos += len;
+			} else {
+				audio_fill_ram_sound(
+					seq, mixdown, sstream, len);
+			}
 		}
 		if ( (seq->type == SEQ_HD_SOUND) &&
 		     (!(seq->flag & SEQ_MUTE)))	{
-			if (!seq->hdaudio) {
-				char name[FILE_MAXDIR+FILE_MAXFILE];
-
-				strncpy(name, seq->strip->dir, 
-					FILE_MAXDIR-1);
-				strncat(name, 
-					seq->strip->stripdata->name, 
-					FILE_MAXFILE-1);
-				BLI_convertstringcode(name, G.sce, 
-						      G.scene->r.cfra);
+			if (advance_only) {
+				seq->curpos += len;
+			} else {
+				if (!seq->hdaudio) {
+					char name[FILE_MAXDIR+FILE_MAXFILE];
+
+					strncpy(name, seq->strip->dir, 
+						FILE_MAXDIR-1);
+					strncat(name, 
+						seq->strip->stripdata->name, 
+						FILE_MAXFILE-1);
+					BLI_convertstringcode(name, G.sce, 
+							      G.scene->r.cfra);
 				
-				seq->hdaudio= sound_open_hdaudio(name);
-			}
-			if (seq->hdaudio) {
-				audio_fill_hd_sound(seq, mixdown, 
-						    sstream, len);
+					seq->hdaudio= sound_open_hdaudio(name);
+				}
+				if (seq->hdaudio) {
+					audio_fill_hd_sound(seq, mixdown, 
+							    sstream, len);
+				}
 			}
 		}
 		seq = seq->next;
@@ -404,7 +420,7 @@ void audio_fill(void *mixdown, Uint8 *sstream, int len)
 	ed = G.scene->ed;
 	if((ed) && (!(G.scene->audio.flag & AUDIO_MUTE))) {
 		seq = ed->seqbasep->first;
-		audio_fill_seq(seq, mixdown, sstream, len);
+		audio_fill_seq(seq, mixdown, sstream, len, 0);
 	}
        
 	audio_pos += len;    
@@ -501,7 +517,8 @@ void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown)
 		desired.format=AUDIO_S16SYS;
    		desired.channels=2;
    		desired.samples=U.mixbufsize;
-   		desired.userdata=0;	
+   		desired.userdata=0;
+
    		if (audio_init(&desired)==0) {
    			U.mixbufsize = 0;	/* no audio */
    		}
diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c
index 95cae4c888d4b6f9eda5867f5df7e6a975e26537..856935467898d290ce9cbf9c9474261cfab7651c 100644
--- a/source/blender/src/seqeffects.c
+++ b/source/blender/src/seqeffects.c
@@ -986,7 +986,7 @@ static void do_gammacross_effect_float(float facf0, float facf1,
 				       float *rect1, float *rect2, 
 				       float *out)
 {
-	float fac1, fac2, col;
+	float fac1, fac2;
 	int xo;
 	float *rt1, *rt2, *rt;
 
@@ -1015,7 +1015,7 @@ static void do_gammacross_effect_float(float facf0, float facf1,
 		x= xo * 4;
 		while(x--) {
 
-			col= gammaCorrect(
+			*rt= gammaCorrect(
 				fac1*invGammaCorrect(*rt1) 
 				+ fac2*invGammaCorrect(*rt2));
 
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 15ed21d3d1af96fdf4e55714611fe85139f3d2c6..0cc1764854aa3b78f555f6ff63f395fbd8134628 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -1793,10 +1793,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 				
 			case AKEY:
 				if (G.obedit == 0 && G.qual == (LR_CTRLKEY|LR_ALTKEY)) {
-					if(okee("Align to Transform Orientation")) {
-						initTransform(TFM_ALIGN, CTX_NO_PET|CTX_AUTOCONFIRM);
-						Transform();
-					}
+					alignmenu();
 				}
 				else if(G.qual & LR_CTRLKEY) { /* also with shift! */
 					apply_object();	
@@ -2156,18 +2153,17 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 				}
 				break;
 			case IKEY:
-				if(G.obedit) {
-					if(G.qual==LR_CTRLKEY) 
+				if(G.qual==LR_CTRLKEY) {
+					if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE)
+						pose_add_IK();
+					else if(ob && G.obedit)
 						selectswap_mesh();
-				} else if(G.qual==LR_CTRLKEY) {
-					if(ob && ob->type==OB_ARMATURE) 
-						if(ob->flag & OB_POSEMODE) 
-							pose_add_IK();
+					else
+						selectswap();
 				}
 				else if(G.qual==LR_ALTKEY) {
-					if(ob && ob->type==OB_ARMATURE) 
-						if(ob->flag & OB_POSEMODE) 
-							pose_clear_IK();
+					if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE)
+						pose_clear_IK();
 				}
 				break;
 				
@@ -5321,6 +5317,10 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 				else if((G.qual==0))
 					hide_tface_uv(0);		
 				break;
+			case IKEY:
+				if(G.qual==LR_CTRLKEY)
+					select_invert_tface_uv();
+				break;
 			case LKEY:
 				if(G.qual==0)
 					select_linked_tface_uv(0);
diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c
index d846ba2c19749d987f2739d28fcd1a342b60fe55..5838a09e1605c2082deb2cb439613f85e03de36b 100644
--- a/source/blender/src/transform.c
+++ b/source/blender/src/transform.c
@@ -467,7 +467,7 @@ static void viewRedrawPost(TransInfo *t)
 
 void BIF_selectOrientation() {
 	short val;
-	char *str_menu = BIF_menustringTransformOrientation();
+	char *str_menu = BIF_menustringTransformOrientation("Orientation");
 	val= pupmenu(str_menu);
 	MEM_freeN(str_menu);
 	
@@ -1288,21 +1288,43 @@ void ManipulatorTransform()
 			}
 			if(val) {
 				switch(event) {
-				case WHEELDOWNMOUSE:
 				case PADPLUSKEY:
-					if(Trans.flag & T_PROP_EDIT) {
+					if(G.qual & LR_ALTKEY && Trans.flag & T_PROP_EDIT) {
 						Trans.propsize*= 1.1f;
 						calculatePropRatio(&Trans);
-						Trans.redraw= 1;
 					}
+					Trans.redraw= 1;
+					break;
+				case PAGEUPKEY:
+				case WHEELDOWNMOUSE:
+					if (Trans.flag & T_AUTOIK) {
+						transform_autoik_update(&Trans, 1);
+					}
+					else if(Trans.flag & T_PROP_EDIT) {
+						Trans.propsize*= 1.1f;
+						calculatePropRatio(&Trans);
+					}
+					else view_editmove(event);
+					Trans.redraw= 1;
 					break;
-				case WHEELUPMOUSE:
 				case PADMINUS:
-					if(Trans.flag & T_PROP_EDIT) {
+					if(G.qual & LR_ALTKEY && Trans.flag & T_PROP_EDIT) {
+						Trans.propsize*= 0.90909090f;
+						calculatePropRatio(&Trans);
+					}
+					Trans.redraw= 1;
+					break;
+				case PAGEDOWNKEY:
+				case WHEELUPMOUSE:
+					if (Trans.flag & T_AUTOIK) {
+						transform_autoik_update(&Trans, -1);
+					}
+					else if (Trans.flag & T_PROP_EDIT) {
 						Trans.propsize*= 0.90909090f;
 						calculatePropRatio(&Trans);
-						Trans.redraw= 1;
 					}
+					else view_editmove(event);
+					Trans.redraw= 1;
 					break;
 				}
 							
@@ -2126,7 +2148,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
 
 	VecMulf(vec, td->factor);
 
-	if (t->flag & T_OBJECT) {
+	if (t->flag & (T_OBJECT|T_POSE)) {
 		Mat3MulVecfl(td->smtx, vec);
 	}
 
diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c
index 1502ea7058271698e81f99c5115a5c8f4b43ca55..849644e3791b1dabd2615fe9ad7616bc7ac9e4e6 100644
--- a/source/blender/src/transform_orientations.c
+++ b/source/blender/src/transform_orientations.c
@@ -313,18 +313,19 @@ void BIF_selectTransformOrientationFromIndex(int index) {
 	G.vd->twmode = V3D_MANIP_CUSTOM + index;
 }
 
-char * BIF_menustringTransformOrientation() {
-	char menu[] = "Orientation%t|Global%x0|Local%x1|Normal%x2|View%x3";
+char * BIF_menustringTransformOrientation(char *title) {
+	char menu[] = "%t|Global%x0|Local%x1|Normal%x2|View%x3";
 	ListBase *transform_spaces = &G.scene->transform_spaces;
 	TransformOrientation *ts;
 	int i = V3D_MANIP_CUSTOM;
 	char *str_menu, *p;
 	
 	
-	str_menu = MEM_callocN(strlen(menu) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix");
+	str_menu = MEM_callocN(strlen(menu) + strlen(title) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix");
 	p = str_menu;
 	
-	p += sprintf(str_menu, "%s", menu);
+	p += sprintf(str_menu, "%s", title);
+	p += sprintf(p, "%s", menu);
 	
 	for (ts = transform_spaces->first; ts; ts = ts->next) {
 		p += sprintf(p, "|%s%%x%d", ts->name, i++);
diff --git a/source/blender/src/view.c b/source/blender/src/view.c
index 7491fc6fbc8180f4b5d03d4885a7408327983cf0..24ee2f964796abc5207c46317956ead908753793 100644
--- a/source/blender/src/view.c
+++ b/source/blender/src/view.c
@@ -777,7 +777,7 @@ void viewmove(int mode)
 		use_sel= 1;
 		VecCopyf(ofs, G.vd->ofs);
 
-		VecCopyf(obofs,&sculpt_session()->pivot.x);
+		VecCopyf(obofs, sculpt_data()->pivot);
 		Mat4MulVecfl(ob->obmat, obofs);
 		obofs[0]= -obofs[0];
 		obofs[1]= -obofs[1];
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 271385bb144c227256132bf6c5549c4c0febb0c2..5a7423e00b18d7bb907d2ac5d745629b7d5fbeaa 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1670,7 +1670,7 @@ static KX_GameObject *gameobject_from_blenderobject(
 		break;
 	}
 	}
-	
+	gameobj->SetPhysicsEnvironment(kxscene->GetPhysicsEnvironment());
 	return gameobj;
 }
 
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index 465a021cd43c76c6fd4e4d3c2feec584f63303e4..ebbca137c5a8a18098b9c4e40c08c4f2f6d3b77f 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -888,6 +888,10 @@ void	KX_ConvertBulletObject(	class	KX_GameObject* gameobj,
 	{
 		ci.m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
 	}
+	if (objprop->m_ghost)
+	{
+		ci.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
+	}
 
 	ci.m_MotionState = motionstate;
 	ci.m_gravity = btVector3(0,0,0);
@@ -1141,10 +1145,11 @@ void	KX_ConvertBulletObject(	class	KX_GameObject* gameobj,
 	if (objprop->m_disableSleeping)
 		rbody->setActivationState(DISABLE_DEACTIVATION);
 	
-	if (objprop->m_ghost)
-	{
-		rbody->setCollisionFlags(rbody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
-	}
+	//Now done directly in ci.m_collisionFlags so that it propagates to replica
+	//if (objprop->m_ghost)
+	//{
+	//	rbody->setCollisionFlags(rbody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
+	//}
 	if (objprop->m_dyna && !objprop->m_angular_rigidbody)
 	{
 		/*
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index bc608d26c50a623ee9cdfcbfb1e2e831187610c7..6f172a11005c08fe222b771759500123e5378484 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -61,6 +61,7 @@ typedef unsigned long uint_ptr;
 #include "SG_Controller.h"
 #include "KX_ClientObjectInfo.h"
 #include "RAS_BucketManager.h"
+#include "KX_RayCast.h"
 
 #include "KX_PyMath.h"
 
@@ -80,7 +81,9 @@ KX_GameObject::KX_GameObject(
 	m_bUseObjectColor(false),
 	m_bVisible(true),
 	m_pPhysicsController1(NULL),
-	m_isDeformable(false)
+	m_pPhysicsEnvironment(NULL),
+	m_isDeformable(false),
+	m_pHitObject(NULL)
 {
 	m_ignore_activity_culling = false;
 	m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
@@ -657,6 +660,7 @@ PyMethodDef KX_GameObject::Methods[] = {
 	{"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
 	{"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS},
 	KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
+	KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
 	{NULL,NULL} //Sentinel
 };
 
@@ -1176,6 +1180,83 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
 	return NULL;
 }
 
+bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+{
+
+	KX_GameObject* hitKXObj = client->m_gameobject;
+	
+	if (client->m_type > KX_ClientObjectInfo::ACTOR)
+	{
+		// false hit
+		return false;
+	}
+
+	if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+	{
+		m_pHitObject = hitKXObj;
+		return true;
+	}
+
+	return false;
+	
+}
+
+KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
+"rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that match prop\n"
+" prop = property name that object must have; can be omitted => detect any object\n"
+" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
+" other = 3-tuple or object reference")
+{
+	MT_Point3 toPoint;
+	PyObject* pyarg;
+	float dist = 0.0f;
+	char *propName = NULL;
+
+	if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName))
+		return NULL;
+
+	if (!PyVecTo(pyarg, toPoint))
+	{
+		KX_GameObject *other;
+		PyErr_Clear();
+		if (!PyType_IsSubtype(pyarg->ob_type, &KX_GameObject::Type))
+			return NULL;
+		other = static_cast<KX_GameObject*>(pyarg);
+		toPoint = other->NodeGetWorldPosition();
+	}
+	MT_Point3 fromPoint = NodeGetWorldPosition();
+	if (dist != 0.0f)
+	{
+		MT_Vector3 toDir = toPoint-fromPoint;
+		toDir.normalize();
+		toPoint = fromPoint + (dist) * toDir;
+	}
+
+	MT_Point3 resultPoint;
+	MT_Vector3 resultNormal;
+	PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
+	KX_IPhysicsController *spc = GetPhysicsController();
+	KX_GameObject *parent = GetParent();
+	if (!spc && parent)
+		spc = parent->GetPhysicsController();
+	if (parent)
+		parent->Release();
+	
+	m_pHitObject = NULL;
+	if (propName)
+		m_testPropName = propName;
+	else
+		m_testPropName.SetLength(0);
+	KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
+
+    if (m_pHitObject)
+	{
+		m_pHitObject->AddRef();
+		return m_pHitObject;
+	}
+	Py_Return;
+}
+
 /* --------------------------------------------------------------------- 
  * Some stuff taken from the header
  * --------------------------------------------------------------------- */
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index db910a46a81991caf1ee35f17714485025af6cb9..945b769d8be0d891ae214c1425df4026c5974347 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -57,6 +57,7 @@
 struct KX_ClientObjectInfo;
 class RAS_MeshObject;
 class KX_IPhysicsController;
+class PHY_IPhysicsEnvironment;
 
 
 /**
@@ -82,6 +83,11 @@ protected:
 	bool       m_bVisible; 
 
 	KX_IPhysicsController*				m_pPhysicsController1;
+	// used for ray casting
+	PHY_IPhysicsEnvironment*			m_pPhysicsEnvironment;
+	STR_String							m_testPropName;
+	KX_GameObject*						m_pHitObject;
+
 	SG_Node*							m_pSGNode;
 
 	MT_CmMatrix4x4						m_OpenGL_4x4Matrix;
@@ -261,6 +267,19 @@ public:
 	);
 
 
+	/**
+	 * @return a pointer to the physics environment in use during the game, for rayCasting
+	 */
+	PHY_IPhysicsEnvironment* GetPhysicsEnvironment()
+	{
+		return m_pPhysicsEnvironment;
+	}
+
+	void SetPhysicsEnvironment(PHY_IPhysicsEnvironment* physicsEnvironment)
+	{
+		m_pPhysicsEnvironment = physicsEnvironment;
+	}
+
 	/**
 	 * @return a pointer to the physics controller owned by this class.
 	 */
@@ -341,6 +360,8 @@ public:
 		return m_bDyna; 
 	}
 	
+	bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+
 
 	/**
 	 * @section Physics accessors for this node.
@@ -608,6 +629,7 @@ public:
 	KX_PYMETHOD(KX_GameObject,GetMesh);
 	KX_PYMETHOD(KX_GameObject,GetParent);
 	KX_PYMETHOD(KX_GameObject,GetPhysicsId);
+	KX_PYMETHOD_DOC(KX_GameObject,rayCastTo);
 	KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo);
 private :
 
diff --git a/source/nan_compile.mk b/source/nan_compile.mk
index afea7a012390ff4c4a77ed13b0dba165b46724f8..665fdd3939b9b4e802e9da8bed08c8058e10e13f 100644
--- a/source/nan_compile.mk
+++ b/source/nan_compile.mk
@@ -50,6 +50,11 @@ else
    CPPFLAGS += -DNO_KETSJI
 endif
 
+ifeq ($(WITH_BF_OPENMP), true)
+    CFLAGS += -fopenmp
+    CCFLAGS += -fopenmp
+endif
+
 ifdef NAN_DEBUG
     CFLAGS += $(NAN_DEBUG)
     CCFLAGS += $(NAN_DEBUG)
diff --git a/source/nan_link.mk b/source/nan_link.mk
index e0745e9c1d43035e3ae53be21357243540396bb5..f4a90b0f927cefd6f393f4294d456c44b04459b6 100644
--- a/source/nan_link.mk
+++ b/source/nan_link.mk
@@ -173,4 +173,8 @@ ifeq ($(INTERNATIONAL),true)
    LLIBS += $(NAN_GETTEXT_LIB)
 endif
 
+ifeq ($(WITH_BF_OPENMP),true)
+   LLIBS += -lgomp
+endif
+
 LLIBS += $(NAN_PYTHON_LIB)
diff --git a/tools/btools.py b/tools/btools.py
index a1a953296d903345d60f059fe4e0cc863d2c008b..35b9682f6a3de34e42acf41dde3b2ba1a76db44d 100755
--- a/tools/btools.py
+++ b/tools/btools.py
@@ -6,7 +6,7 @@ import SCons.Options.BoolOption
 try:
     import subprocess
 except ImportError:
-	pass
+    pass
 import string
 import glob
 import shutil
@@ -59,7 +59,7 @@ def validate_arguments(args, bc):
             'WITHOUT_BF_INSTALL',
             'WITH_BF_OPENMP',
             'WITHOUT_BF_INSTALL',
-            'BF_FANCY',
+            'BF_FANCY', 'BF_QUIET'
             ]
 
     arg_list = ['BF_DEBUG', 'BF_QUIET', 'BF_CROSS', 'BF_UPDATE',
@@ -251,7 +251,7 @@ def read_opts(cfg, args):
         ('BF_FREETYPE_LIB', 'Freetype library', ''),
         ('BF_FREETYPE_LIBPATH', 'Freetype library path', ''),
 
-	(BoolOption('WITH_BF_OPENMP', 'Use OpenMP if true', 'false')),
+        (BoolOption('WITH_BF_OPENMP', 'Use OpenMP if true', 'false')),
 
         (BoolOption('WITH_BF_QUICKTIME', 'Use QuickTime if true', 'false')),
         ('BF_QUICKTIME', 'QuickTime base path', ''),
@@ -293,7 +293,7 @@ def read_opts(cfg, args):
         ('BF_DEBUG_FLAGS', 'Debug flags', ''),
 
         (BoolOption('BF_BSC', 'Create .bsc files (msvc only)', 'true')),
-        
+
         ('BF_BUILDDIR', 'Build dir', ''),
         ('BF_INSTALLDIR', 'Installation dir', ''),
 
@@ -306,7 +306,8 @@ def read_opts(cfg, args):
         (BoolOption('BF_SPLIT_SRC', 'Split src lib into several chunks if true', 'false')),
         (BoolOption('WITHOUT_BF_INSTALL', 'dont install if true', 'false')),
         (BoolOption('BF_FANCY', 'Enable fancy output if true', 'true')),
-		(BoolOption('WITH_BF_BINRELOC', 'Enable relocatable binary (linux only)', 'false')),
+        (BoolOption('BF_QUIET', 'Enable silent output if true', 'true')),
+        (BoolOption('WITH_BF_BINRELOC', 'Enable relocatable binary (linux only)', 'false')),
 
     ) # end of opts.AddOptions()