diff options
110 files changed, 2592 insertions, 978 deletions
diff --git a/SConstruct b/SConstruct index 3ee56f7cff1..f8eef60a117 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 47bcb76441f..1b0d4448f1d 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 20d3a5b07fc..af9443428f7 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 5dca8ba63d7..5c44fe29a6f 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 3ba118c0d18..1df7c937842 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 213fac1bb3c..249c3f83dfc 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 0a042c1612a..ae4cdbe1cfe 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 ca40295515b..9229397e674 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 463254b8e4f..3889721b8c9 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 e0b935fc106..53960a71470 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 e03e38bab75..5d7ed28f561 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 1da46149eac..d0d6a892a81 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 4e00e29029c..9dcb6b6e7fa 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 b8c05f3bb7b..3b4de305545 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 7ec56bd08ab..4bb31c1e9b9 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 d2834571316..a58fdab8c91 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 a1c49ac4655..61f2288f8e8 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 dcd8bc6d9eb..0b33cc3a75b 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 21e58f88aad..4c39f36800c 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 79a9559250f..9fb476614d3 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 42cac46c241..1b95ae14ecf 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 3bfd605cf27..9155a5ee444 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 4db391ddc95..4aa69daa6d0 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 bc9aa23ee15..6c3775bcbaa 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 27c4091e36f..04e9d63b9b5 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 568a3a34d91..b48bfc4f2b8 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 099fedf460a..2836f5fd507 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 3b8292a791c..ab0aecdd363 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 99e30bc91c0..3055f62ae3d 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 9cbdfa327cd..2c9932b6507 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 cd7de83b9c0..3514e695f59 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 f4a44b3a0db..92fad291e83 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 09edfe90d02..b54d42080b0 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 1557e970306..330ae84f922 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 d70fe17c67f..4d8544ec09d 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 dfa4e5831ba..eaa80865f08 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 82d6bb84281..40c4df37f71 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 c425cbc62ea..294c0ceb047 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 71f6b275fd8..cac022ab6c2 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 4ba1f4f02e8..53fbd1ff72c 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 dd1d8eb01b3..c62d012643a 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 f74e858c0e4..eda37d952c1 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 869f1cb426d..f31f9fff142 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 180cbd2af37..df9ea872caa 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 cf2af9bbc11..e317998b5fc 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 662d8e8dde9..5e1803a6774 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 ec3a9f3e5d6..36a3bd5b171 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 d7bd4f22fc6..bf7c4d7ad62 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 febf5e3ff31..1f028e49070 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 d520dded486..dbcd21f04f3 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 9ca0d8d2545..844b9cc99ad 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 a4bbeba65ac..76e33a1bcb7 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 1aacaf56786..12e2ce3055b 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 803c0b96ef3..f9a23ed37b2 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 0a68509d287..0ceb6b3c2a2 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 e229e678fe9..49626599887 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 3499ec09936..f1c038fc33c 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 5cfe796add8..b4a14cc6ac8 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 61ee3c36700..0f9e4b5e07a 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 c3760bc2c1d..ba8d6d21970 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 873888cffb4..54d9136ec1e 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 0690b94712b..8b49ce29d54 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 42fd5b564fe..97c7c0ecc44 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 4bf823bc938..d0440e11b52 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 aca5a0885f4..88c5e2197f9 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 2aa6cc10468..22fb2e70d87 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 cf1eeae58ec..cdc348279e5 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 933125202be..42191ff35ad 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 d0f9be3fd79..d423abefe96 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 bedce5e36ee..35e0815cc69 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 377d72325f0..6af3b711028 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 e8062422e2a..cdc46cde8b7 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 edd9a2ff827..7dd9f2aa765 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 8fb4fab4a92..7a0d00c0593 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 9dbcd656df6..1d3ece58db7 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 c94df84c7f7..e13d0f4d0cd 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 2fe89727c43..cea33685744 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 260b0ab6656..9ddf5e405dd 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 73b1aa9856c..327fcb341c7 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 c4c221bcdf6..e0919c7ba1c 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 ecd546a6780..9190b3263f0 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 d6d748f2213..1a1bb9f4fb1 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 55ed6252dae..a93d81e04af 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 ef656281d75..fe68e0818bb 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 b99710f782f..ca47741b6f1 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 a308b428894..ab2a36aa2d3 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 1a3775ac301..07973926503 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 10d6187fc76..d40d76785b4 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 edaec5fb268..42e438b2022 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 a31f92c4b68..4bbb9f18263 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 b5abf0947e4..5bb9ffcba4e 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 b8d13b493bb..5ec730bd097 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 dde5a512de9..43ca45ffb67 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 7b8efd0ed75..539fde5b14d 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 0752a5dd198..de1e70caeec 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 8ac0a1f2558..f40ecb74948 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 3fda71bf828..715a0f47afa 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 8b669d034d0..eb362f7187e 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 95cae4c888d..85693546789 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 15ed21d3d1a..0cc1764854a 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 d846ba2c197..5838a09e160 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 1502ea70582..849644e3791 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 7491fc6fbc8..24ee2f96479 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 271385bb144..5a7423e00b1 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 465a021cd43..ebbca137c5a 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 bc608d26c50..6f172a11005 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 db910a46a81..945b769d8be 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; @@ -262,6 +268,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 afea7a01239..665fdd3939b 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 e0745e9c1d4..f4a90b0f927 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 a1a953296d9..35b9682f6a3 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() |