SceneObjectPart.cs 201 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Drawing;
  30. using System.IO;
  31. using System.Reflection;
  32. using System.Threading;
  33. using System.Text;
  34. using System.Xml;
  35. using System.Xml.Serialization;
  36. using log4net;
  37. using OpenMetaverse;
  38. using OpenMetaverse.Packets;
  39. using OpenSim.Framework;
  40. using OpenSim.Region.Framework.Interfaces;
  41. using OpenSim.Region.Framework.Scenes.Serialization;
  42. using OpenSim.Region.PhysicsModules.SharedBase;
  43. using PermissionMask = OpenSim.Framework.PermissionMask;
  44. namespace OpenSim.Region.Framework.Scenes
  45. {
  46. #region Enumerations
  47. [Flags]
  48. public enum Changed : uint
  49. {
  50. INVENTORY = 1,
  51. COLOR = 2,
  52. SHAPE = 4,
  53. SCALE = 8,
  54. TEXTURE = 16,
  55. LINK = 32,
  56. ALLOWED_DROP = 64,
  57. OWNER = 128,
  58. REGION = 256,
  59. TELEPORT = 512,
  60. REGION_RESTART = 1024,
  61. MEDIA = 2048,
  62. ANIMATION = 16384,
  63. POSITION = 32768
  64. }
  65. [Flags]
  66. public enum TextureAnimFlags : byte
  67. {
  68. NONE = 0x00,
  69. ANIM_ON = 0x01,
  70. LOOP = 0x02,
  71. REVERSE = 0x04,
  72. PING_PONG = 0x08,
  73. SMOOTH = 0x10,
  74. ROTATE = 0x20,
  75. SCALE = 0x40
  76. }
  77. public enum PrimType : int
  78. {
  79. BOX = 0,
  80. CYLINDER = 1,
  81. PRISM = 2,
  82. SPHERE = 3,
  83. TORUS = 4,
  84. TUBE = 5,
  85. RING = 6,
  86. SCULPT = 7
  87. }
  88. #endregion Enumerations
  89. public class SceneObjectPart : EntityBase, IDisposable
  90. {
  91. /// <value>
  92. /// Denote all sides of the prim
  93. /// </value>
  94. public const int ALL_SIDES = -1;
  95. private const scriptEvents PhysicsNeededSubsEvents = (
  96. scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
  97. scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
  98. );
  99. private const scriptEvents PhyscicsPhantonSubsEvents = (
  100. scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
  101. );
  102. private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
  103. scriptEvents.collision_start | scriptEvents.collision_end
  104. );
  105. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  106. /// <summary>
  107. /// Dynamic attributes can be created and deleted as required.
  108. /// </summary>
  109. public DAMap DynAttrs { get; set; }
  110. private DOMap m_dynObjs;
  111. /// <summary>
  112. /// Dynamic objects that can be created and deleted as required.
  113. /// </summary>
  114. public DOMap DynObjs
  115. {
  116. get
  117. {
  118. if (m_dynObjs == null)
  119. m_dynObjs = new DOMap();
  120. return m_dynObjs;
  121. }
  122. set
  123. {
  124. m_dynObjs = value;
  125. }
  126. }
  127. /// <value>
  128. /// Is this a root part?
  129. /// </value>
  130. /// <remarks>
  131. /// This will return true even if the whole object is attached to an avatar.
  132. /// </remarks>
  133. public bool IsRoot
  134. {
  135. get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
  136. }
  137. /// <summary>
  138. /// Is an explicit sit target set for this part?
  139. /// </summary>
  140. public bool IsSitTargetSet
  141. {
  142. get
  143. {
  144. // assume SitTargetOrientation is normalized (as needed elsewhere)
  145. if( SitTargetPosition != Vector3.Zero ||
  146. SitTargetOrientation.X != 0f ||
  147. SitTargetOrientation.Y != 0f ||
  148. SitTargetOrientation.Z != 0f)
  149. return true;
  150. return false;
  151. }
  152. }
  153. #region Fields
  154. public bool AllowedDrop;
  155. public bool DIE_AT_EDGE;
  156. public bool RETURN_AT_EDGE;
  157. public bool BlockGrab { get; set; }
  158. public bool StatusSandbox;
  159. public Vector3 StatusSandboxPos;
  160. [XmlIgnore]
  161. public int PseudoCRC; // this is local to region. should only be stored on its db.
  162. // This is just a number that needs to change to invalidate prim data caches
  163. [XmlIgnore]
  164. public int[] PayPrice = {-2,-2,-2,-2,-2};
  165. [XmlIgnore]
  166. /// <summary>
  167. /// The representation of this part in the physics scene.
  168. /// </summary>
  169. /// <remarks>
  170. /// If you use this property more than once in a section of code then you must take a reference and use that.
  171. /// If another thread is simultaneously turning physics off on this part then this refernece could become
  172. /// null at any time.
  173. /// </remarks>
  174. public PhysicsActor PhysActor { get; set; }
  175. //Xantor 20080528 Sound stuff:
  176. // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet.
  177. // Not a big problem as long as the script that sets it remains in the prim on startup.
  178. // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script)
  179. public UUID Sound;
  180. public byte SoundFlags;
  181. public double SoundGain;
  182. public double SoundRadius;
  183. /// <summary>
  184. /// Should sounds played from this prim be queued?
  185. /// </summary>
  186. /// <remarks>
  187. /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
  188. /// </remarks>
  189. public bool SoundQueueing { get; set; }
  190. [XmlIgnore]
  191. public Quaternion AttachRotation = Quaternion.Identity;
  192. [XmlIgnore]
  193. public int STATUS_ROTATE_X; // this should not be used
  194. [XmlIgnore]
  195. public int STATUS_ROTATE_Y; // this should not be used
  196. [XmlIgnore]
  197. public int STATUS_ROTATE_Z; // this should not be used
  198. private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
  199. /// <value>
  200. /// The UUID of the user inventory item from which this object was rezzed if this is a root part.
  201. /// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item.
  202. /// </value>
  203. private UUID m_fromUserInventoryItemID;
  204. public UUID FromUserInventoryItemID
  205. {
  206. get { return m_fromUserInventoryItemID; }
  207. set { m_fromUserInventoryItemID = value; }
  208. }
  209. public scriptEvents AggregatedScriptEvents;
  210. public Vector3 AttachedPos { get; set; }
  211. // rotation locks on local X,Y and or Z axis bit flags
  212. // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum
  213. // but reversed logic: bit cleared means free to rotate
  214. public byte RotationAxisLocks = 0;
  215. // WRONG flag in libOmvPrimFlags
  216. private const uint primFlagVolumeDetect = (uint)PrimFlags.JointLP2P;
  217. public bool VolumeDetectActive
  218. {
  219. get
  220. {
  221. return (m_flags & (PrimFlags)primFlagVolumeDetect) != 0;
  222. }
  223. set
  224. {
  225. if(value)
  226. m_flags |= (PrimFlags)primFlagVolumeDetect;
  227. else
  228. m_flags &= (PrimFlags)(~primFlagVolumeDetect);
  229. }
  230. }
  231. public bool IsWaitingForFirstSpinUpdatePacket;
  232. public Quaternion SpinOldOrientation = Quaternion.Identity;
  233. protected bool m_APIDActive = false;
  234. protected Quaternion m_APIDTarget = Quaternion.Identity;
  235. protected float m_APIDDamp = 0;
  236. protected float m_APIDStrength = 0;
  237. /// <summary>
  238. /// This part's inventory
  239. /// </summary>
  240. public IEntityInventory Inventory
  241. {
  242. get { return m_inventory; }
  243. }
  244. protected SceneObjectPartInventory m_inventory;
  245. public bool Undoing;
  246. public bool IgnoreUndoUpdate = false;
  247. private float m_damage = -1.0f;
  248. private byte[] m_TextureAnimation;
  249. private byte m_clickAction;
  250. private Color m_color = Color.Black;
  251. private List<uint> m_lastColliders = new List<uint>();
  252. private bool m_lastLandCollide;
  253. private int m_linkNum;
  254. private int m_scriptAccessPin;
  255. private readonly Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
  256. private Quaternion m_sitTargetOrientation = Quaternion.Identity;
  257. private Vector3 m_sitTargetPosition;
  258. private string m_sitAnimation = "SIT";
  259. private UndoRedoState m_UndoRedo = null;
  260. private readonly object m_UndoLock = new object();
  261. private bool m_passTouches = false;
  262. private bool m_passCollisions = false;
  263. protected Vector3 m_acceleration;
  264. protected Vector3 m_angularVelocity;
  265. //unkown if this will be kept, added as a way of removing the group position from the group class
  266. protected Vector3 m_groupPosition;
  267. protected Material m_material = OpenMetaverse.Material.Wood;
  268. protected Vector3 m_offsetPosition;
  269. protected SceneObjectGroup m_parentGroup;
  270. protected byte[] m_particleSystem = Utils.EmptyBytes;
  271. protected double m_particleSystemExpire = -1;
  272. protected ulong m_regionHandle;
  273. protected Quaternion m_rotationOffset = Quaternion.Identity;
  274. protected PrimitiveBaseShape m_shape;
  275. protected Vector3 m_lastPosition;
  276. protected Quaternion m_lastRotation;
  277. protected Vector3 m_lastVelocity;
  278. protected Vector3 m_lastAcceleration; // acceleration is a derived var with high noise
  279. protected Vector3 m_lastAngularVelocity;
  280. protected double m_lastUpdateSentTime;
  281. protected float m_buoyancy = 0.0f;
  282. protected Vector3 m_force;
  283. protected Vector3 m_torque;
  284. protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
  285. protected float m_density = 1000.0f; // in kg/m^3
  286. protected float m_gravitymod = 1.0f;
  287. protected float m_friction = 0.6f; // wood
  288. protected float m_bounce = 0.5f; // wood
  289. protected bool m_isSelected = false;
  290. // TODO: Those have to be changed into persistent properties at some later point,
  291. // or sit-camera on vehicles will break on sim-crossing.
  292. private Vector3 m_cameraEyeOffset;
  293. private Vector3 m_cameraAtOffset;
  294. private bool m_forceMouselook;
  295. // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
  296. private sbyte m_collisionSoundType = 0;
  297. private UUID m_collisionSound;
  298. private float m_collisionSoundVolume;
  299. private int LastColSoundSentTime;
  300. private SOPVehicle m_vehicleParams = null;
  301. private PhysicsInertiaData m_physicsInertia;
  302. public KeyframeMotion KeyframeMotion
  303. {
  304. get; set;
  305. }
  306. #endregion Fields
  307. // ~SceneObjectPart()
  308. // {
  309. // Console.WriteLine(
  310. // "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}",
  311. // Name, LocalId, ParentGroup.Name, ParentGroup.LocalId);
  312. // m_log.DebugFormat(
  313. // "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}",
  314. // Name, LocalId, ParentGroup.Name, ParentGroup.LocalId);
  315. // }
  316. #region Constructors
  317. /// <summary>
  318. /// No arg constructor called by region restore db code
  319. /// </summary>
  320. public SceneObjectPart()
  321. {
  322. m_TextureAnimation = Utils.EmptyBytes;
  323. m_particleSystem = Utils.EmptyBytes;
  324. Rezzed = DateTime.UtcNow;
  325. //Description = String.Empty;
  326. PseudoCRC = (int)DateTime.UtcNow.Ticks; // random could be as good; fallbak if not on region db
  327. m_inventory = new SceneObjectPartInventory(this);
  328. LastColSoundSentTime = Util.EnvironmentTickCount();
  329. }
  330. public static osUTF8 defaultName = new osUTF8("Object", true);
  331. /// <summary>
  332. /// Create a completely new SceneObjectPart (prim). This will need to be added separately to a SceneObjectGroup
  333. /// </summary>
  334. /// <param name="ownerID"></param>
  335. /// <param name="shape"></param>
  336. /// <param name="position"></param>
  337. /// <param name="rotationOffset"></param>
  338. /// <param name="offsetPosition"></param>
  339. public SceneObjectPart(
  340. UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
  341. Quaternion rotationOffset, Vector3 offsetPosition) : this()
  342. {
  343. osUTF8Name = defaultName;
  344. osUTF8LargeName = defaultName;
  345. CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
  346. RezzerID = LastOwnerID = CreatorID = OwnerID = ownerID;
  347. UUID = UUID.Random();
  348. Shape = shape;
  349. OwnershipCost = 0;
  350. ObjectSaleType = 0;
  351. SalePrice = 0;
  352. Category = 0;
  353. GroupPosition = groupPosition;
  354. OffsetPosition = offsetPosition;
  355. RotationOffset = rotationOffset;
  356. Velocity = Vector3.Zero;
  357. AngularVelocity = Vector3.Zero;
  358. Acceleration = Vector3.Zero;
  359. APIDActive = false;
  360. m_flags = 0;
  361. CreateSelected = false;
  362. TrimPermissions();
  363. AggregateInnerPerms();
  364. }
  365. ~SceneObjectPart()
  366. {
  367. Dispose(false);
  368. }
  369. public void Dispose()
  370. {
  371. Dispose(true);
  372. GC.SuppressFinalize(this);
  373. }
  374. private bool disposed = false;
  375. protected void Dispose(bool disposing)
  376. {
  377. if (!disposed)
  378. {
  379. disposed = true;
  380. IsDeleted = true;
  381. if (KeyframeMotion != null)
  382. {
  383. KeyframeMotion.Delete();
  384. KeyframeMotion = null;
  385. }
  386. if (PhysActor != null)
  387. RemoveFromPhysics();
  388. if (m_inventory != null)
  389. {
  390. m_inventory.Dispose();
  391. m_inventory = null;
  392. }
  393. }
  394. }
  395. #endregion Constructors
  396. #region XML Schema
  397. private UUID _rezzerID;
  398. private UUID _lastOwnerID;
  399. private UUID _ownerID;
  400. private UUID _groupID;
  401. private int _ownershipCost;
  402. private byte _objectSaleType;
  403. private int _salePrice;
  404. private uint _category;
  405. private Int32 _creationDate;
  406. private uint _parentID = 0;
  407. private uint _baseMask = (uint)(PermissionMask.All | PermissionMask.Export);
  408. private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
  409. private uint _groupMask = (uint)PermissionMask.None;
  410. private uint _everyoneMask = (uint)PermissionMask.None;
  411. private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Transfer);
  412. private PrimFlags m_flags = PrimFlags.None;
  413. private PrimFlags m_localFlags = PrimFlags.None;
  414. private DateTime m_expires;
  415. private DateTime m_rezzed;
  416. private bool m_createSelected = false;
  417. private UUID _creatorID;
  418. public UUID CreatorID
  419. {
  420. get { return _creatorID; }
  421. set { _creatorID = value; }
  422. }
  423. private string m_creatorData = string.Empty;
  424. /// <summary>
  425. /// Data about the creator in the form home_url;name
  426. /// </summary>
  427. public string CreatorData
  428. {
  429. get { return m_creatorData; }
  430. set { m_creatorData = value; }
  431. }
  432. /// <summary>
  433. /// Used by the DB layer to retrieve / store the entire user identification.
  434. /// The identification can either be a simple UUID or a string of the form
  435. /// uuid[;home_url[;name]]
  436. /// </summary>
  437. public string CreatorIdentification
  438. {
  439. get
  440. {
  441. if (!string.IsNullOrEmpty(CreatorData))
  442. return CreatorID.ToString() + ';' + CreatorData;
  443. else
  444. return CreatorID.ToString();
  445. }
  446. set
  447. {
  448. CreatorData = string.Empty;
  449. if ((value == null) || (value != null && value == string.Empty))
  450. return;
  451. // value is uuid or uuid;homeuri;firstname lastname
  452. string[] parts = value.Split(';');
  453. if (parts.Length > 0)
  454. {
  455. UUID uuid = UUID.Zero;
  456. UUID.TryParse(parts[0], out uuid);
  457. CreatorID = uuid;
  458. if (parts.Length > 1)
  459. {
  460. CreatorData = parts[1];
  461. if (!CreatorData.EndsWith("/"))
  462. CreatorData += "/";
  463. if (parts.Length > 2)
  464. CreatorData += ';' + parts[2];
  465. else
  466. CreatorData += ";Unknown User";
  467. }
  468. }
  469. }
  470. }
  471. /// <summary>
  472. /// A relic from when we we thought that prims contained folder objects. In
  473. /// reality, prim == folder
  474. /// Exposing this is not particularly good, but it's one of the least evils at the moment to see
  475. /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim.
  476. /// </summary>
  477. public UUID FolderID
  478. {
  479. get { return UUID; }
  480. set { } // Don't allow assignment, or legacy prims wil b0rk - but we need the setter for legacy serialization.
  481. }
  482. /// <value>
  483. /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
  484. /// </value>
  485. public uint InventorySerial
  486. {
  487. get { return m_inventory.Serial; }
  488. set { m_inventory.Serial = value; }
  489. }
  490. /// <value>
  491. /// Get the inventory list
  492. /// </value>
  493. public TaskInventoryDictionary TaskInventory
  494. {
  495. get {
  496. return m_inventory.Items;
  497. }
  498. set {
  499. m_inventory.Items = value;
  500. }
  501. }
  502. /// <summary>
  503. /// This is idential to the Flags property, except that the returned value is uint rather than PrimFlags
  504. /// </summary>
  505. [Obsolete("Use Flags property instead")]
  506. public uint ObjectFlags
  507. {
  508. get { return (uint)Flags; }
  509. set { Flags = (PrimFlags)value; }
  510. }
  511. public override UUID UUID
  512. {
  513. get { return m_uuid; }
  514. set
  515. {
  516. m_uuid = value;
  517. // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part
  518. if (Inventory != null)
  519. Inventory.ResetObjectID();
  520. }
  521. }
  522. // several code still depends on large uncontroled names
  523. private osUTF8 osUTF8LargeName;
  524. public override string Name
  525. {
  526. get
  527. {
  528. return osUTF8LargeName == null ? string.Empty : osUTF8LargeName.ToString();
  529. }
  530. set
  531. {
  532. if(string.IsNullOrEmpty(value))
  533. {
  534. osUTF8LargeName = null;
  535. osUTF8Name = null;
  536. PhysicsActor pa = PhysActor;
  537. if (pa != null)
  538. pa.SOPName = string.Empty;
  539. }
  540. else
  541. {
  542. osUTF8LargeName = new osUTF8(value);
  543. osUTF8Name = new osUTF8(value, 63);
  544. PhysicsActor pa = PhysActor;
  545. if (pa != null)
  546. pa.SOPName = value;
  547. }
  548. if (ParentGroup != null)
  549. ParentGroup.InvalidatePartsLinkMaps();
  550. }
  551. }
  552. [XmlIgnore]
  553. public bool PassTouches
  554. {
  555. get { return m_passTouches; }
  556. set
  557. {
  558. m_passTouches = value;
  559. if (ParentGroup != null)
  560. ParentGroup.HasGroupChanged = true;
  561. }
  562. }
  563. public bool PassCollisions
  564. {
  565. get { return m_passCollisions; }
  566. set
  567. {
  568. m_passCollisions = value;
  569. if (ParentGroup != null)
  570. ParentGroup.HasGroupChanged = true;
  571. }
  572. }
  573. public bool IsSelected
  574. {
  575. get { return m_isSelected; }
  576. set
  577. {
  578. m_isSelected = value;
  579. if (ParentGroup != null)
  580. ParentGroup.PartSelectChanged(value);
  581. }
  582. }
  583. public Dictionary<int, string> CollisionFilter
  584. {
  585. get { return m_CollisionFilter; }
  586. set
  587. {
  588. m_CollisionFilter = value;
  589. }
  590. }
  591. protected bool APIDActive
  592. {
  593. get { return m_APIDActive; }
  594. set { m_APIDActive = value; }
  595. }
  596. protected Quaternion APIDTarget
  597. {
  598. get { return m_APIDTarget; }
  599. set { m_APIDTarget = value; }
  600. }
  601. protected float APIDDamp
  602. {
  603. get { return m_APIDDamp; }
  604. set { m_APIDDamp = value; }
  605. }
  606. protected float APIDStrength
  607. {
  608. get { return m_APIDStrength; }
  609. set { m_APIDStrength = value; }
  610. }
  611. public ulong RegionHandle
  612. {
  613. get { return m_regionHandle; }
  614. set { m_regionHandle = value; }
  615. }
  616. public int ScriptAccessPin
  617. {
  618. get { return m_scriptAccessPin; }
  619. set { m_scriptAccessPin = (int)value; }
  620. }
  621. public Byte[] TextureAnimation
  622. {
  623. get { return m_TextureAnimation; }
  624. set { m_TextureAnimation = value; }
  625. }
  626. public Byte[] ParticleSystem
  627. {
  628. get
  629. {
  630. if(m_particleSystemExpire > 0 && Util.GetTimeStamp() > m_particleSystemExpire)
  631. {
  632. m_particleSystemExpire = -1;
  633. m_particleSystem = new byte[0];
  634. }
  635. return m_particleSystem;
  636. }
  637. set { m_particleSystem = value; }
  638. }
  639. public DateTime Expires
  640. {
  641. get { return m_expires; }
  642. set { m_expires = value; }
  643. }
  644. public DateTime Rezzed
  645. {
  646. get { return m_rezzed; }
  647. set { m_rezzed = value; }
  648. }
  649. public float Damage
  650. {
  651. get { return m_damage; }
  652. set { m_damage = value; }
  653. }
  654. public void setGroupPosition(Vector3 pos)
  655. {
  656. m_groupPosition = pos;
  657. }
  658. /// <summary>
  659. /// The position of the entire group that this prim belongs to.
  660. /// </summary>
  661. ///
  662. public Vector3 GroupPosition
  663. {
  664. get
  665. {
  666. // If this is a linkset, we don't want the physics engine mucking up our group position here.
  667. if (_parentID == 0)
  668. {
  669. PhysicsActor actor = PhysActor;
  670. if (actor != null)
  671. m_groupPosition = actor.Position;
  672. return m_groupPosition;
  673. }
  674. // If I'm an attachment, my position is reported as the position of who I'm attached to
  675. if (ParentGroup.IsAttachment)
  676. {
  677. ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
  678. if (sp != null)
  679. return sp.AbsolutePosition;
  680. }
  681. // use root prim's group position. Physics may have updated it
  682. if (ParentGroup.RootPart != this)
  683. m_groupPosition = ParentGroup.RootPart.GroupPosition;
  684. return m_groupPosition;
  685. }
  686. set
  687. {
  688. m_groupPosition = value;
  689. PhysicsActor actor = PhysActor;
  690. if (actor != null && ParentGroup.Scene.PhysicsScene != null)
  691. {
  692. try
  693. {
  694. // Root prim actually goes at Position
  695. if (_parentID == 0)
  696. {
  697. actor.Position = value;
  698. }
  699. else
  700. {
  701. // The physics engine always sees all objects (root or linked) in world coordinates.
  702. actor.Position = GetWorldPosition();
  703. actor.Orientation = GetWorldRotation();
  704. }
  705. // Tell the physics engines that this prim changed.
  706. if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
  707. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
  708. }
  709. catch (Exception e)
  710. {
  711. m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
  712. }
  713. }
  714. }
  715. }
  716. public void setOffsetPosition(Vector3 pos)
  717. {
  718. m_offsetPosition = pos;
  719. }
  720. public Vector3 OffsetPosition
  721. {
  722. get { return m_offsetPosition; }
  723. set
  724. {
  725. Vector3 oldpos = m_offsetPosition;
  726. m_offsetPosition = value;
  727. if (ParentGroup != null && !ParentGroup.IsDeleted)
  728. {
  729. if((oldpos - m_offsetPosition).LengthSquared() > 1.0f)
  730. ParentGroup.InvalidBoundsRadius();
  731. PhysicsActor actor = PhysActor;
  732. if (_parentID != 0 && actor != null)
  733. {
  734. actor.Position = GetWorldPosition();
  735. actor.Orientation = GetWorldRotation();
  736. // Tell the physics engines that this prim changed.
  737. if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
  738. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
  739. }
  740. if (!m_parentGroup.m_dupeInProgress)
  741. {
  742. List<ScenePresence> avs = ParentGroup.GetSittingAvatars();
  743. foreach (ScenePresence av in avs)
  744. {
  745. if (av.ParentID == m_localId)
  746. {
  747. Vector3 offset = (m_offsetPosition - oldpos);
  748. av.AbsolutePosition += offset;
  749. // av.SendAvatarDataToAllAgents();
  750. av.SendTerseUpdateToAllClients();
  751. }
  752. }
  753. }
  754. }
  755. TriggerScriptChangedEvent(Changed.POSITION);
  756. }
  757. }
  758. public Vector3 RelativePosition
  759. {
  760. get
  761. {
  762. if (IsRoot)
  763. {
  764. if (ParentGroup.IsAttachment)
  765. return AttachedPos;
  766. else
  767. return AbsolutePosition;
  768. }
  769. else
  770. {
  771. return OffsetPosition;
  772. }
  773. }
  774. }
  775. public void setRotationOffset(Quaternion q)
  776. {
  777. m_rotationOffset = q;
  778. }
  779. public Quaternion RotationOffset
  780. {
  781. get
  782. {
  783. // We don't want the physics engine mucking up the rotations in a linkset
  784. PhysicsActor actor = PhysActor;
  785. // If this is a root of a linkset, the real rotation is what the physics engine thinks.
  786. // If not a root prim, the offset rotation is computed by SOG and is relative to the root.
  787. if (_parentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
  788. m_rotationOffset = actor.Orientation;
  789. return m_rotationOffset;
  790. }
  791. set
  792. {
  793. // StoreUndoState();
  794. m_rotationOffset = value;
  795. m_rotationOffset.Normalize();
  796. PhysicsActor actor = PhysActor;
  797. if (actor != null)
  798. {
  799. try
  800. {
  801. // Root prim gets value directly
  802. if (_parentID == 0)
  803. {
  804. actor.Orientation = value;
  805. //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
  806. }
  807. else
  808. {
  809. // Child prim we have to calculate it's world rotationwel
  810. Quaternion resultingrotation = GetWorldRotation();
  811. actor.Orientation = resultingrotation;
  812. //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
  813. }
  814. if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
  815. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
  816. //}
  817. }
  818. catch (Exception ex)
  819. {
  820. m_log.Error("[SCENEOBJECTPART]: ROTATIONOFFSET" + ex.Message);
  821. }
  822. }
  823. }
  824. }
  825. /// <summary></summary>
  826. public override Vector3 Velocity
  827. {
  828. get
  829. {
  830. PhysicsActor actor = PhysActor;
  831. if (actor != null)
  832. {
  833. if (actor.IsPhysical)
  834. {
  835. m_velocity = actor.Velocity;
  836. }
  837. }
  838. return m_velocity;
  839. }
  840. set
  841. {
  842. if (Util.IsNanOrInfinity(value))
  843. m_velocity = Vector3.Zero;
  844. else
  845. m_velocity = value;
  846. PhysicsActor actor = PhysActor;
  847. if (actor != null)
  848. {
  849. if (actor.IsPhysical)
  850. {
  851. actor.Velocity = m_velocity;
  852. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
  853. }
  854. }
  855. }
  856. }
  857. /// <summary>Update angular velocity and schedule terse update.</summary>
  858. public void UpdateAngularVelocity(Vector3 avel)
  859. {
  860. AngularVelocity = avel;
  861. ScheduleTerseUpdate();
  862. ParentGroup.HasGroupChanged = true;
  863. }
  864. /// <summary>Get or set angular velocity. Does not schedule update.</summary>
  865. public Vector3 AngularVelocity
  866. {
  867. get
  868. {
  869. PhysicsActor actor = PhysActor;
  870. if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
  871. {
  872. m_angularVelocity = actor.RotationalVelocity;
  873. }
  874. return m_angularVelocity;
  875. }
  876. set
  877. {
  878. if (Util.IsNanOrInfinity(value))
  879. m_angularVelocity = Vector3.Zero;
  880. else
  881. m_angularVelocity = value;
  882. PhysicsActor actor = PhysActor;
  883. if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
  884. {
  885. actor.RotationalVelocity = m_angularVelocity;
  886. }
  887. }
  888. }
  889. /// <summary></summary>
  890. public Vector3 Acceleration
  891. {
  892. get
  893. {
  894. PhysicsActor actor = PhysActor;
  895. if (actor != null && actor.IsPhysical)
  896. {
  897. m_acceleration = actor.Acceleration;
  898. }
  899. return m_acceleration;
  900. }
  901. set
  902. {
  903. if (Util.IsNanOrInfinity(value))
  904. m_acceleration = Vector3.Zero;
  905. else
  906. m_acceleration = value;
  907. PhysicsActor actor = PhysActor;
  908. if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
  909. {
  910. actor.Acceleration = m_acceleration;
  911. }
  912. }
  913. }
  914. public osUTF8 osUTF8Description;
  915. public string Description
  916. {
  917. get {return osUTF8Description == null ? string.Empty : osUTF8Description.ToString(); }
  918. set { osUTF8Description = string.IsNullOrEmpty(value) ? null : new osUTF8(value, 127);}
  919. }
  920. /// <value>
  921. /// Text color.
  922. /// </value>
  923. public Color Color
  924. {
  925. get { return m_color; }
  926. set { m_color = value; }
  927. }
  928. public osUTF8 osUTF8Text;
  929. public string Text
  930. {
  931. get { return osUTF8Text == null ? string.Empty : osUTF8Text.ToString(); }
  932. set { osUTF8Text = string.IsNullOrEmpty(value) ? null : new osUTF8(value, 254); }
  933. }
  934. public osUTF8 osUTF8SitName;
  935. public string SitName
  936. {
  937. get { return osUTF8SitName == null ? string.Empty : osUTF8SitName.ToString(); }
  938. set { osUTF8SitName = string.IsNullOrEmpty(value) ? null : new osUTF8(value, 36); }
  939. }
  940. public osUTF8 osUTF8TouchName;
  941. public string TouchName
  942. {
  943. get { return osUTF8TouchName == null ? string.Empty : osUTF8TouchName.ToString(); }
  944. set { osUTF8TouchName = string.IsNullOrEmpty(value) ? null : new osUTF8(value, 36); }
  945. }
  946. public int LinkNum
  947. {
  948. get { return m_linkNum; }
  949. set
  950. {
  951. // if (ParentGroup != null)
  952. // {
  953. // m_log.DebugFormat(
  954. // "[SCENE OBJECT PART]: Setting linknum of {0}@{1} to {2} from {3}",
  955. // Name, AbsolutePosition, value, m_linkNum);
  956. // Util.PrintCallStack();
  957. // }
  958. m_linkNum = value;
  959. }
  960. }
  961. public byte ClickAction
  962. {
  963. get { return m_clickAction; }
  964. set
  965. {
  966. m_clickAction = value;
  967. }
  968. }
  969. public PrimitiveBaseShape Shape
  970. {
  971. get { return m_shape; }
  972. set
  973. {
  974. m_shape = value;
  975. }
  976. }
  977. /// <summary>
  978. /// Change the scale of this part.
  979. /// </summary>
  980. public Vector3 Scale
  981. {
  982. get { return m_shape.Scale; }
  983. set
  984. {
  985. if (m_shape != null)
  986. {
  987. Vector3 oldscale = m_shape.Scale;
  988. m_shape.Scale = value;
  989. if (ParentGroup != null && ((value - oldscale).LengthSquared() >1.0f))
  990. ParentGroup.InvalidBoundsRadius();
  991. PhysicsActor actor = PhysActor;
  992. if (actor != null)
  993. {
  994. if (ParentGroup.Scene != null)
  995. {
  996. if (ParentGroup.Scene.PhysicsScene != null)
  997. {
  998. actor.Size = m_shape.Scale;
  999. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
  1000. }
  1001. }
  1002. }
  1003. }
  1004. TriggerScriptChangedEvent(Changed.SCALE);
  1005. }
  1006. }
  1007. public float maxSimpleArea()
  1008. {
  1009. float a,b;
  1010. float sx = m_shape.Scale.X;
  1011. float sy = m_shape.Scale.Y;
  1012. float sz = m_shape.Scale.Z;
  1013. if( sx > sy)
  1014. {
  1015. a = sx;
  1016. if(sy > sz)
  1017. b = sy;
  1018. else
  1019. b = sz;
  1020. }
  1021. else
  1022. {
  1023. a = sy;
  1024. if(sx > sz)
  1025. b = sx;
  1026. else
  1027. b = sz;
  1028. }
  1029. return a * b;
  1030. }
  1031. public PrimUpdateFlags UpdateFlag { get; set; }
  1032. public PrimUpdateFlags GetAndClearUpdateFlag()
  1033. {
  1034. lock(UpdateFlagLock)
  1035. {
  1036. PrimUpdateFlags ret = UpdateFlag;
  1037. UpdateFlag = PrimUpdateFlags.None;
  1038. return ret;
  1039. }
  1040. }
  1041. private readonly object UpdateFlagLock = new object();
  1042. /// <summary>
  1043. /// Used for media on a prim.
  1044. /// </summary>
  1045. /// Do not change this value directly - always do it through an IMoapModule.
  1046. public osUTF8 osUTFMediaUrl;
  1047. public string MediaUrl
  1048. {
  1049. get
  1050. {
  1051. return osUTFMediaUrl == null ? string.Empty : osUTFMediaUrl.ToString();
  1052. }
  1053. set
  1054. {
  1055. osUTF8 old = osUTFMediaUrl;
  1056. if (string.IsNullOrEmpty(value))
  1057. {
  1058. osUTFMediaUrl = null;
  1059. if (old != null && ParentGroup != null)
  1060. ParentGroup.HasGroupChanged = true;
  1061. }
  1062. else
  1063. {
  1064. osUTFMediaUrl = new osUTF8(value, 254);
  1065. if (ParentGroup != null && !osUTFMediaUrl.Equals(old))
  1066. ParentGroup.HasGroupChanged = true;
  1067. }
  1068. }
  1069. }
  1070. public bool CreateSelected
  1071. {
  1072. get { return m_createSelected; }
  1073. set
  1074. {
  1075. // m_log.DebugFormat("[SOP]: Setting CreateSelected to {0} for {1} {2}", value, Name, UUID);
  1076. m_createSelected = value;
  1077. }
  1078. }
  1079. #endregion
  1080. //---------------
  1081. #region Public Properties with only Get
  1082. public override Vector3 AbsolutePosition
  1083. {
  1084. get
  1085. {
  1086. if (_parentID == 0)
  1087. return GroupPosition;
  1088. return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
  1089. }
  1090. }
  1091. public SceneObjectGroup ParentGroup
  1092. {
  1093. get { return m_parentGroup; }
  1094. private set { m_parentGroup = value; }
  1095. }
  1096. public scriptEvents ScriptEvents
  1097. {
  1098. get { return AggregatedScriptEvents; }
  1099. }
  1100. public Quaternion SitTargetOrientation
  1101. {
  1102. get { return m_sitTargetOrientation; }
  1103. set
  1104. {
  1105. m_sitTargetOrientation = value;
  1106. // m_log.DebugFormat("[SCENE OBJECT PART]: Set sit target orientation {0} for {1} {2}", m_sitTargetOrientation, Name, LocalId);
  1107. }
  1108. }
  1109. public Vector3 SitTargetPosition
  1110. {
  1111. get { return m_sitTargetPosition; }
  1112. set
  1113. {
  1114. m_sitTargetPosition = value;
  1115. // m_log.DebugFormat("[SCENE OBJECT PART]: Set sit target position to {0} for {1} {2}", m_sitTargetPosition, Name, LocalId);
  1116. }
  1117. }
  1118. // This sort of sucks, but I'm adding these in to make some of
  1119. // the mappings more consistant.
  1120. public Vector3 SitTargetPositionLL
  1121. {
  1122. get { return m_sitTargetPosition; }
  1123. set { m_sitTargetPosition = value; }
  1124. }
  1125. public Quaternion SitTargetOrientationLL
  1126. {
  1127. get { return m_sitTargetOrientation; }
  1128. set { m_sitTargetOrientation = value; }
  1129. }
  1130. public float SitActiveRange { get; set;}
  1131. public Vector3 StandOffset { get; set;}
  1132. public bool Stopped
  1133. {
  1134. get {
  1135. double threshold = 0.02;
  1136. return (Math.Abs(Velocity.X) < threshold &&
  1137. Math.Abs(Velocity.Y) < threshold &&
  1138. Math.Abs(Velocity.Z) < threshold &&
  1139. Math.Abs(AngularVelocity.X) < threshold &&
  1140. Math.Abs(AngularVelocity.Y) < threshold &&
  1141. Math.Abs(AngularVelocity.Z) < threshold);
  1142. }
  1143. }
  1144. /// <summary>
  1145. /// The parent ID of this part.
  1146. /// </summary>
  1147. /// <remarks>
  1148. /// If this is a root part which is not attached to an avatar then the value will be 0.
  1149. /// If this is a root part which is attached to an avatar then the value is the local id of that avatar.
  1150. /// If this is a child part then the value is the local ID of the root part.
  1151. /// </remarks>
  1152. public uint ParentID
  1153. {
  1154. get { return _parentID; }
  1155. set { _parentID = value; }
  1156. }
  1157. public int CreationDate
  1158. {
  1159. get { return _creationDate; }
  1160. set { _creationDate = value; }
  1161. }
  1162. public uint Category
  1163. {
  1164. get { return _category; }
  1165. set { _category = value; }
  1166. }
  1167. public int SalePrice
  1168. {
  1169. get { return _salePrice; }
  1170. set { _salePrice = value; }
  1171. }
  1172. public byte ObjectSaleType
  1173. {
  1174. get { return _objectSaleType; }
  1175. set { _objectSaleType = value; }
  1176. }
  1177. public int OwnershipCost
  1178. {
  1179. get { return _ownershipCost; }
  1180. set { _ownershipCost = value; }
  1181. }
  1182. public UUID GroupID
  1183. {
  1184. get { return _groupID; }
  1185. set { _groupID = value; }
  1186. }
  1187. public UUID OwnerID
  1188. {
  1189. get { return _ownerID; }
  1190. set { _ownerID = value; }
  1191. }
  1192. public UUID LastOwnerID
  1193. {
  1194. get { return _lastOwnerID; }
  1195. set {
  1196. _lastOwnerID = value; }
  1197. }
  1198. public UUID RezzerID
  1199. {
  1200. get { return _rezzerID; }
  1201. set { _rezzerID = value; }
  1202. }
  1203. public uint BaseMask
  1204. {
  1205. get { return _baseMask; }
  1206. set { _baseMask = value; }
  1207. }
  1208. public uint OwnerMask
  1209. {
  1210. get { return _ownerMask; }
  1211. set { _ownerMask = value; }
  1212. }
  1213. public uint GroupMask
  1214. {
  1215. get { return _groupMask; }
  1216. set { _groupMask = value; }
  1217. }
  1218. public uint EveryoneMask
  1219. {
  1220. get { return _everyoneMask; }
  1221. set { _everyoneMask = value; }
  1222. }
  1223. public uint NextOwnerMask
  1224. {
  1225. get { return _nextOwnerMask; }
  1226. set { _nextOwnerMask = value; }
  1227. }
  1228. /// <summary>
  1229. /// Property flags. See OpenMetaverse.PrimFlags
  1230. /// </summary>
  1231. /// <remarks>
  1232. /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge
  1233. /// </remarks>
  1234. public PrimFlags Flags
  1235. {
  1236. get { return m_flags; }
  1237. set
  1238. {
  1239. //m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value);
  1240. m_flags = value & ~(PrimFlags.Touch | PrimFlags.Money | PrimFlags.AllowInventoryDrop);
  1241. }
  1242. }
  1243. /// <summary>
  1244. /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
  1245. /// </summary>
  1246. public UUID SitTargetAvatar { get; set; }
  1247. /// <summary>
  1248. /// IDs of all avatars sat on this part.
  1249. /// </summary>
  1250. /// <remarks>
  1251. /// We need to track this so that we can stop sat upon prims from being attached.
  1252. /// </remarks>
  1253. /// <value>
  1254. /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
  1255. /// </value>
  1256. private HashSet<ScenePresence> m_sittingAvatars;
  1257. public virtual UUID RegionID
  1258. {
  1259. get
  1260. {
  1261. if (ParentGroup.Scene != null)
  1262. return ParentGroup.Scene.RegionInfo.RegionID;
  1263. else
  1264. return UUID.Zero;
  1265. }
  1266. set {} // read only
  1267. }
  1268. private UUID _parentUUID = UUID.Zero;
  1269. public UUID ParentUUID
  1270. {
  1271. get
  1272. {
  1273. if (ParentGroup != null)
  1274. _parentUUID = ParentGroup.UUID;
  1275. return _parentUUID;
  1276. }
  1277. set { _parentUUID = value; }
  1278. }
  1279. public string SitAnimation
  1280. {
  1281. get { return m_sitAnimation; }
  1282. set { m_sitAnimation = value; }
  1283. }
  1284. public readonly UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
  1285. // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
  1286. // runtime thing.. do not persist
  1287. [XmlIgnore]
  1288. public sbyte CollisionSoundType
  1289. {
  1290. get
  1291. {
  1292. return m_collisionSoundType;
  1293. }
  1294. set
  1295. {
  1296. UUID old = m_collisionSound;
  1297. m_collisionSoundType = value;
  1298. if (value == -1)
  1299. m_collisionSound = invalidCollisionSoundUUID;
  1300. else if (value == 0)
  1301. m_collisionSound = UUID.Zero;
  1302. if(m_collisionSound != old && ParentGroup != null)
  1303. ParentGroup.HasGroupChanged = true;
  1304. }
  1305. }
  1306. public UUID CollisionSound
  1307. {
  1308. get { return m_collisionSound; }
  1309. set
  1310. {
  1311. UUID olds = m_collisionSound;
  1312. m_collisionSound = value;
  1313. if (value == invalidCollisionSoundUUID)
  1314. m_collisionSoundType = -1;
  1315. else if (value == UUID.Zero)
  1316. m_collisionSoundType = 0;
  1317. else
  1318. m_collisionSoundType = 1;
  1319. if(m_collisionSound != olds && ParentGroup != null)
  1320. ParentGroup.HasGroupChanged = true;
  1321. }
  1322. }
  1323. public float CollisionSoundVolume
  1324. {
  1325. get { return m_collisionSoundVolume; }
  1326. set
  1327. {
  1328. float oldvalue = m_collisionSoundVolume;
  1329. if(value >= 0)
  1330. m_collisionSoundVolume = value;
  1331. else
  1332. m_collisionSoundVolume = 0.0f;
  1333. if(m_collisionSoundVolume != oldvalue && ParentGroup != null)
  1334. ParentGroup.HasGroupChanged = true;
  1335. }
  1336. }
  1337. public float Buoyancy
  1338. {
  1339. get
  1340. {
  1341. if (ParentGroup.RootPart == this)
  1342. return m_buoyancy;
  1343. return ParentGroup.RootPart.Buoyancy;
  1344. }
  1345. set
  1346. {
  1347. if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
  1348. {
  1349. ParentGroup.RootPart.Buoyancy = value;
  1350. return;
  1351. }
  1352. m_buoyancy = value;
  1353. if (PhysActor != null)
  1354. PhysActor.Buoyancy = value;
  1355. }
  1356. }
  1357. public Vector3 Force
  1358. {
  1359. get
  1360. {
  1361. if (ParentGroup.RootPart == this)
  1362. return m_force;
  1363. return ParentGroup.RootPart.Force;
  1364. }
  1365. set
  1366. {
  1367. if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
  1368. {
  1369. ParentGroup.RootPart.Force = value;
  1370. return;
  1371. }
  1372. m_force = value;
  1373. if (PhysActor != null)
  1374. PhysActor.Force = value;
  1375. }
  1376. }
  1377. public Vector3 Torque
  1378. {
  1379. get
  1380. {
  1381. if (ParentGroup.RootPart == this)
  1382. return m_torque;
  1383. return ParentGroup.RootPart.Torque;
  1384. }
  1385. set
  1386. {
  1387. if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
  1388. {
  1389. ParentGroup.RootPart.Torque = value;
  1390. return;
  1391. }
  1392. m_torque = value;
  1393. if (PhysActor != null)
  1394. PhysActor.Torque = value;
  1395. }
  1396. }
  1397. public byte Material
  1398. {
  1399. get { return (byte)m_material; }
  1400. set
  1401. {
  1402. if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
  1403. {
  1404. bool update = false;
  1405. if (m_material != (Material)value)
  1406. {
  1407. update = true;
  1408. m_material = (Material)value;
  1409. }
  1410. if (m_friction != SOPMaterialData.friction(m_material))
  1411. {
  1412. update = true;
  1413. m_friction = SOPMaterialData.friction(m_material);
  1414. }
  1415. if (m_bounce != SOPMaterialData.bounce(m_material))
  1416. {
  1417. update = true;
  1418. m_bounce = SOPMaterialData.bounce(m_material);
  1419. }
  1420. if (update)
  1421. {
  1422. if (PhysActor != null)
  1423. {
  1424. PhysActor.SetMaterial((int)value);
  1425. }
  1426. if(ParentGroup != null)
  1427. {
  1428. ParentGroup.HasGroupChanged = true;
  1429. ScheduleFullUpdate();
  1430. }
  1431. }
  1432. }
  1433. }
  1434. }
  1435. // not a propriety to move to methods place later
  1436. private bool HasMesh()
  1437. {
  1438. if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
  1439. return true;
  1440. return false;
  1441. }
  1442. // not a propriety to move to methods place later
  1443. public byte DefaultPhysicsShapeType()
  1444. {
  1445. byte type;
  1446. if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
  1447. type = (byte)PhysShapeType.convex;
  1448. else
  1449. type = (byte)PhysShapeType.prim;
  1450. return type;
  1451. }
  1452. [XmlIgnore]
  1453. public bool UsesComplexCost
  1454. {
  1455. get
  1456. {
  1457. byte pst = PhysicsShapeType;
  1458. if(pst == (byte) PhysShapeType.none || HasMesh())
  1459. return true;
  1460. return false;
  1461. }
  1462. }
  1463. [XmlIgnore]
  1464. public float PhysicsCost
  1465. {
  1466. get
  1467. {
  1468. if(PhysicsShapeType == (byte)PhysShapeType.none)
  1469. return 0;
  1470. float cost = 0.1f;
  1471. if (PhysActor != null)
  1472. cost = PhysActor.PhysicsCost;
  1473. else
  1474. cost = 0.1f;
  1475. if ((m_flags & PrimFlags.Physics) != 0)
  1476. cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
  1477. return cost;
  1478. }
  1479. }
  1480. [XmlIgnore]
  1481. public float StreamingCost
  1482. {
  1483. get
  1484. {
  1485. float cost;
  1486. if (PhysActor != null)
  1487. cost = PhysActor.StreamCost;
  1488. else
  1489. cost = 1.0f;
  1490. return 1.0f;
  1491. }
  1492. }
  1493. [XmlIgnore]
  1494. public float SimulationCost
  1495. {
  1496. get
  1497. {
  1498. // ignoring scripts. Don't like considering them for this
  1499. if((m_flags & PrimFlags.Physics) != 0)
  1500. return 1.0f;
  1501. return 0.5f;
  1502. }
  1503. }
  1504. public byte PhysicsShapeType
  1505. {
  1506. get
  1507. {
  1508. // if (PhysActor != null)
  1509. // m_physicsShapeType = PhysActor.PhysicsShapeType;
  1510. return m_physicsShapeType;
  1511. }
  1512. set
  1513. {
  1514. byte oldv = m_physicsShapeType;
  1515. if (value >= 0 && value <= (byte)PhysShapeType.convex)
  1516. {
  1517. if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
  1518. m_physicsShapeType = DefaultPhysicsShapeType();
  1519. else
  1520. m_physicsShapeType = value;
  1521. }
  1522. else
  1523. m_physicsShapeType = DefaultPhysicsShapeType();
  1524. if (m_physicsShapeType != oldv && ParentGroup != null)
  1525. {
  1526. if (m_physicsShapeType == (byte)PhysShapeType.none)
  1527. {
  1528. if (PhysActor != null)
  1529. {
  1530. ParentGroup.Scene.RemovePhysicalPrim(1);
  1531. RemoveFromPhysics();
  1532. // Stop();
  1533. }
  1534. }
  1535. else if (PhysActor == null)
  1536. {
  1537. if(oldv == (byte)PhysShapeType.none)
  1538. {
  1539. ApplyPhysics((uint)m_flags, VolumeDetectActive, false);
  1540. UpdatePhysicsSubscribedEvents();
  1541. }
  1542. }
  1543. else
  1544. PhysActor.PhysicsShapeType = m_physicsShapeType;
  1545. ParentGroup.HasGroupChanged = true;
  1546. }
  1547. }
  1548. }
  1549. public float Density // in kg/m^3
  1550. {
  1551. get { return m_density; }
  1552. set
  1553. {
  1554. if (value >=1 && value <= 22587.0)
  1555. {
  1556. m_density = value;
  1557. if (ParentGroup != null)
  1558. {
  1559. ParentGroup.HasGroupChanged = true;
  1560. ScheduleFullUpdate();
  1561. }
  1562. PhysicsActor pa = PhysActor;
  1563. if (pa != null)
  1564. pa.Density = m_density;
  1565. }
  1566. }
  1567. }
  1568. public float GravityModifier
  1569. {
  1570. get { return m_gravitymod; }
  1571. set
  1572. {
  1573. if( value >= -1 && value <=28.0f)
  1574. {
  1575. m_gravitymod = value;
  1576. if (ParentGroup != null)
  1577. {
  1578. ParentGroup.HasGroupChanged = true;
  1579. ScheduleFullUpdate();
  1580. }
  1581. PhysicsActor pa = PhysActor;
  1582. if (pa != null)
  1583. pa.GravModifier = m_gravitymod;
  1584. }
  1585. }
  1586. }
  1587. public float Friction
  1588. {
  1589. get { return m_friction; }
  1590. set
  1591. {
  1592. if (value >= 0 && value <= 255.0f)
  1593. {
  1594. m_friction = value;
  1595. if (ParentGroup != null)
  1596. {
  1597. ParentGroup.HasGroupChanged = true;
  1598. ScheduleFullUpdate();
  1599. }
  1600. PhysicsActor pa = PhysActor;
  1601. if (pa != null)
  1602. pa.Friction = m_friction;
  1603. }
  1604. }
  1605. }
  1606. public float Restitution
  1607. {
  1608. get { return m_bounce; }
  1609. set
  1610. {
  1611. if (value >= 0 && value <= 1.0f)
  1612. {
  1613. m_bounce = value;
  1614. if (ParentGroup != null)
  1615. {
  1616. ParentGroup.HasGroupChanged = true;
  1617. ScheduleFullUpdate();
  1618. }
  1619. PhysicsActor pa = PhysActor;
  1620. if (pa != null)
  1621. pa.Restitution = m_bounce;
  1622. }
  1623. }
  1624. }
  1625. #endregion Public Properties with only Get
  1626. private uint ApplyMask(uint val, bool set, uint mask)
  1627. {
  1628. if (set)
  1629. {
  1630. return val |= mask;
  1631. }
  1632. else
  1633. {
  1634. return val &= ~mask;
  1635. }
  1636. }
  1637. /// <summary>
  1638. /// Clear all pending updates of parts to clients
  1639. /// </summary>
  1640. public void ClearUpdateSchedule()
  1641. {
  1642. lock(UpdateFlagLock)
  1643. UpdateFlag = PrimUpdateFlags.None;
  1644. }
  1645. /// <summary>
  1646. /// Send this part's properties (name, description, inventory serial, base mask, etc.) to a client
  1647. /// </summary>
  1648. /// <param name="client"></param>
  1649. public void SendPropertiesToClient(IClientAPI client)
  1650. {
  1651. client.SendObjectPropertiesReply(this);
  1652. }
  1653. // TODO: unused:
  1654. // private void handleTimerAccounting(uint localID, double interval)
  1655. // {
  1656. // if (localID == LocalId)
  1657. // {
  1658. // float sec = (float)interval;
  1659. // if (m_parentGroup != null)
  1660. // {
  1661. // if (sec == 0)
  1662. // {
  1663. // if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001)
  1664. // m_parentGroup.scriptScore = 0;
  1665. //
  1666. // m_parentGroup.scriptScore += 0.001f;
  1667. // return;
  1668. // }
  1669. //
  1670. // if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec))
  1671. // m_parentGroup.scriptScore = 0;
  1672. // m_parentGroup.scriptScore += (0.001f / sec);
  1673. // }
  1674. // }
  1675. // }
  1676. #region Public Methods
  1677. public void ResetExpire()
  1678. {
  1679. Expires = DateTime.UtcNow + new TimeSpan(600000000);
  1680. }
  1681. public void AddFlag(PrimFlags flag)
  1682. {
  1683. if ((m_flags & flag) == 0)
  1684. {
  1685. //m_log.Debug("Adding flag: " + ((PrimFlags) flag).ToString());
  1686. m_flags |= flag;
  1687. if (flag == PrimFlags.TemporaryOnRez)
  1688. ResetExpire();
  1689. }
  1690. // m_log.Debug("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
  1691. }
  1692. public void AddNewParticleSystem(Primitive.ParticleSystem pSystem, bool expire)
  1693. {
  1694. if(expire && pSystem.MaxAge > 0.0001)
  1695. m_particleSystemExpire = Util.GetTimeStamp() + pSystem.MaxAge + 0.1;
  1696. else
  1697. m_particleSystemExpire = -1;
  1698. m_particleSystem = pSystem.GetBytes();
  1699. }
  1700. public void RemoveParticleSystem()
  1701. {
  1702. m_particleSystem = new byte[0];
  1703. }
  1704. public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
  1705. {
  1706. byte[] data;
  1707. if (pTexAnim.Flags == Primitive.TextureAnimMode.ANIM_OFF)
  1708. {
  1709. data = Utils.EmptyBytes;
  1710. }
  1711. else
  1712. {
  1713. data = new byte[16];
  1714. data[0] = (byte)pTexAnim.Flags;
  1715. data[1] = (byte)pTexAnim.Face;
  1716. data[2] = (byte)pTexAnim.SizeX;
  1717. data[3] = (byte)pTexAnim.SizeY;
  1718. Utils.FloatToBytesSafepos(pTexAnim.Start, data, 4);
  1719. Utils.FloatToBytesSafepos(pTexAnim.Length, data, 8);
  1720. Utils.FloatToBytesSafepos(pTexAnim.Rate, data, 12);
  1721. }
  1722. m_TextureAnimation = data;
  1723. }
  1724. public void AdjustSoundGain(double volume)
  1725. {
  1726. if (volume > 1)
  1727. volume = 1;
  1728. if (volume < 0)
  1729. volume = 0;
  1730. ParentGroup.Scene.ForEachRootClient(delegate(IClientAPI client)
  1731. {
  1732. client.SendAttachedSoundGainChange(UUID, (float)volume);
  1733. });
  1734. }
  1735. /// <summary>
  1736. /// hook to the physics scene to apply impulse
  1737. /// This is sent up to the group, which then finds the root prim
  1738. /// and applies the force on the root prim of the group
  1739. /// </summary>
  1740. /// <param name="impulsei">Vector force</param>
  1741. /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
  1742. public void ApplyImpulse(Vector3 impulse, bool localGlobalTF)
  1743. {
  1744. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  1745. return;
  1746. if (localGlobalTF)
  1747. impulse *= GetWorldRotation();
  1748. ParentGroup.applyImpulse(impulse);
  1749. }
  1750. // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
  1751. public void SetVelocity(Vector3 pVel, bool localGlobalTF)
  1752. {
  1753. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  1754. return;
  1755. if (ParentGroup.IsAttachment)
  1756. return; // don't work on attachments (for now ??)
  1757. SceneObjectPart root = ParentGroup.RootPart;
  1758. if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
  1759. return;
  1760. PhysicsActor pa = root.PhysActor;
  1761. if (pa == null || !pa.IsPhysical)
  1762. return;
  1763. if (localGlobalTF)
  1764. pVel *= GetWorldRotation();
  1765. ParentGroup.Velocity = pVel;
  1766. }
  1767. // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
  1768. public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
  1769. {
  1770. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  1771. return;
  1772. if (ParentGroup.IsAttachment)
  1773. return; // don't work on attachments (for now ??)
  1774. SceneObjectPart root = ParentGroup.RootPart;
  1775. if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
  1776. return;
  1777. PhysicsActor pa = root.PhysActor;
  1778. if (pa == null || !pa.IsPhysical)
  1779. return;
  1780. if (localGlobalTF)
  1781. pAngVel *= GetWorldRotation();
  1782. root.AngularVelocity = pAngVel;
  1783. }
  1784. /// <summary>
  1785. /// hook to the physics scene to apply angular impulse
  1786. /// This is sent up to the group, which then finds the root prim
  1787. /// and applies the force on the root prim of the group
  1788. /// </summary>
  1789. /// <param name="impulsei">Vector force</param>
  1790. /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
  1791. public void ApplyAngularImpulse(Vector3 impulse, bool localGlobalTF)
  1792. {
  1793. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  1794. return;
  1795. if (localGlobalTF)
  1796. ParentGroup.ApplyAngularImpulse(impulse * GetWorldRotation());
  1797. else
  1798. ParentGroup.ApplyAngularImpulse(impulse);
  1799. }
  1800. /// <summary>
  1801. /// hook to the physics scene to apply angular impulse
  1802. /// This is sent up to the group, which then finds the root prim
  1803. /// and applies the force on the root prim of the group
  1804. /// </summary>
  1805. /// <param name="impulsei">Vector force</param>
  1806. /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
  1807. // this is actualy Set Torque.. keeping naming so not to edit lslapi also
  1808. public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
  1809. {
  1810. Vector3 torque = torquei;
  1811. if (localGlobalTF)
  1812. torque *= GetWorldRotation();
  1813. Torque = torque;
  1814. }
  1815. /// <summary>
  1816. /// Apply physics to this part.
  1817. /// </summary>
  1818. /// <param name="rootObjectFlags"></param>
  1819. /// <param name="VolumeDetectActive"></param>
  1820. /// <param name="building"></param>
  1821. public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
  1822. {
  1823. VolumeDetectActive = _VolumeDetectActive;
  1824. if (!ParentGroup.Scene.CollidablePrims)
  1825. return;
  1826. if (PhysicsShapeType == (byte)PhysShapeType.none)
  1827. {
  1828. if(ParentID == 0)
  1829. m_physicsShapeType = DefaultPhysicsShapeType();
  1830. else
  1831. return;
  1832. }
  1833. bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
  1834. bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
  1835. if (_VolumeDetectActive)
  1836. isPhantom = true;
  1837. if (IsJoint())
  1838. {
  1839. DoPhysicsPropertyUpdate(isPhysical, true);
  1840. }
  1841. else
  1842. {
  1843. if ((!isPhantom || isPhysical || _VolumeDetectActive)
  1844. && !ParentGroup.IsAttachmentCheckFull()
  1845. && !(Shape.PathCurve == (byte)Extrusion.Flexible))
  1846. {
  1847. AddToPhysics(isPhysical, isPhantom, building, isPhysical);
  1848. UpdatePhysicsSubscribedEvents(); // not sure if appliable here
  1849. }
  1850. else
  1851. {
  1852. PhysActor = null; // just to be sure
  1853. RemFlag(PrimFlags.CameraDecoupled);
  1854. }
  1855. }
  1856. }
  1857. /// <summary>
  1858. /// Duplicates this part.
  1859. /// </summary>
  1860. /// <param name="localID"></param>
  1861. /// <param name="AgentID"></param>
  1862. /// <param name="GroupID"></param>
  1863. /// <param name="linkNum"></param>
  1864. /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
  1865. /// <returns></returns>
  1866. public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
  1867. {
  1868. // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
  1869. // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
  1870. // but not between regions on different simulators). Really, all copying should be done explicitly.
  1871. SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone();
  1872. dupe.m_shape = m_shape.Copy();
  1873. dupe.m_regionHandle = m_regionHandle;
  1874. if (userExposed)
  1875. dupe.UUID = UUID.Random();
  1876. dupe.PhysActor = null;
  1877. dupe.OwnerID = AgentID;
  1878. dupe.GroupID = GroupID;
  1879. dupe.GroupPosition = GroupPosition;
  1880. dupe.OffsetPosition = OffsetPosition;
  1881. dupe.RotationOffset = RotationOffset;
  1882. dupe.Velocity = Velocity;
  1883. dupe.Acceleration = Acceleration;
  1884. dupe.AngularVelocity = AngularVelocity;
  1885. dupe.m_flags = m_flags;
  1886. dupe.OwnershipCost = OwnershipCost;
  1887. dupe.ObjectSaleType = ObjectSaleType;
  1888. dupe.SalePrice = SalePrice;
  1889. dupe.Category = Category;
  1890. dupe.m_rezzed = m_rezzed;
  1891. dupe.m_UndoRedo = null;
  1892. dupe.m_isSelected = false;
  1893. dupe.IgnoreUndoUpdate = false;
  1894. dupe.Undoing = false;
  1895. dupe.m_inventory = new SceneObjectPartInventory(dupe);
  1896. dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
  1897. if (userExposed)
  1898. {
  1899. dupe.ResetIDs(linkNum);
  1900. dupe.m_inventory.HasInventoryChanged = true;
  1901. }
  1902. else
  1903. {
  1904. dupe.m_inventory.HasInventoryChanged = m_inventory.HasInventoryChanged;
  1905. }
  1906. // Move afterwards ResetIDs as it clears the localID
  1907. dupe.LocalId = plocalID;
  1908. // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
  1909. if(OwnerID != GroupID)
  1910. dupe.LastOwnerID = OwnerID;
  1911. else
  1912. dupe.LastOwnerID = LastOwnerID; // redundant ?
  1913. dupe.RezzerID = RezzerID;
  1914. byte[] extraP = new byte[Shape.ExtraParams.Length];
  1915. Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
  1916. dupe.Shape.ExtraParams = extraP;
  1917. dupe.m_sittingAvatars = new HashSet<ScenePresence>();
  1918. dupe.SitTargetAvatar = UUID.Zero;
  1919. // safeguard actual copy is done in sog.copy
  1920. dupe.KeyframeMotion = null;
  1921. dupe.PayPrice = (int[])PayPrice.Clone();
  1922. if(DynAttrs != null)
  1923. dupe.DynAttrs.CopyFrom(DynAttrs);
  1924. if (userExposed)
  1925. {
  1926. bool UsePhysics = ((dupe.m_flags & PrimFlags.Physics) != 0);
  1927. dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
  1928. }
  1929. if (dupe.PhysActor != null)
  1930. dupe.PhysActor.LocalID = plocalID;
  1931. dupe.PseudoCRC = (int)(DateTime.UtcNow.Ticks);
  1932. ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
  1933. // m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
  1934. return dupe;
  1935. }
  1936. /// <summary>
  1937. /// Do a physics property update for a NINJA joint.
  1938. /// </summary>
  1939. /// <param name="UsePhysics"></param>
  1940. /// <param name="isNew"></param>
  1941. protected void DoPhysicsPropertyUpdateForNinjaJoint(bool UsePhysics, bool isNew)
  1942. {
  1943. if (UsePhysics)
  1944. {
  1945. // by turning a joint proxy object physical, we cause creation of a joint in the ODE scene.
  1946. // note that, as a special case, joints have no bodies or geoms in the physics scene, even though they are physical.
  1947. PhysicsJointType jointType;
  1948. if (IsHingeJoint())
  1949. {
  1950. jointType = PhysicsJointType.Hinge;
  1951. }
  1952. else if (IsBallJoint())
  1953. {
  1954. jointType = PhysicsJointType.Ball;
  1955. }
  1956. else
  1957. {
  1958. jointType = PhysicsJointType.Ball;
  1959. }
  1960. List<string> bodyNames = new List<string>();
  1961. string RawParams = Description;
  1962. string[] jointParams = RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
  1963. string trackedBodyName = null;
  1964. if (jointParams.Length >= 2)
  1965. {
  1966. for (int iBodyName = 0; iBodyName < 2; iBodyName++)
  1967. {
  1968. string bodyName = jointParams[iBodyName];
  1969. bodyNames.Add(bodyName);
  1970. if (bodyName != "NULL")
  1971. {
  1972. if (trackedBodyName == null)
  1973. {
  1974. trackedBodyName = bodyName;
  1975. }
  1976. }
  1977. }
  1978. }
  1979. SceneObjectPart trackedBody = ParentGroup.Scene.GetSceneObjectPart(trackedBodyName); // FIXME: causes a sequential lookup
  1980. Quaternion localRotation = Quaternion.Identity;
  1981. if (trackedBody != null)
  1982. {
  1983. localRotation = Quaternion.Inverse(trackedBody.RotationOffset) * this.RotationOffset;
  1984. }
  1985. else
  1986. {
  1987. // error, output it below
  1988. }
  1989. PhysicsJoint joint;
  1990. joint = ParentGroup.Scene.PhysicsScene.RequestJointCreation(Name, jointType,
  1991. AbsolutePosition,
  1992. this.RotationOffset,
  1993. Description,
  1994. bodyNames,
  1995. trackedBodyName,
  1996. localRotation);
  1997. if (trackedBody == null)
  1998. {
  1999. ParentGroup.Scene.jointErrorMessage(joint, "warning: tracked body name not found! joint location will not be updated properly. joint: " + Name);
  2000. }
  2001. }
  2002. else
  2003. {
  2004. if (isNew)
  2005. {
  2006. // if the joint proxy is new, and it is not physical, do nothing. There is no joint in ODE to
  2007. // delete, and if we try to delete it, due to asynchronous processing, the deletion request
  2008. // will get processed later at an indeterminate time, which could cancel a later-arriving
  2009. // joint creation request.
  2010. }
  2011. else
  2012. {
  2013. // here we turn off the joint object, so remove the joint from the physics scene
  2014. ParentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed?
  2015. // make sure client isn't interpolating the joint proxy object
  2016. Stop();
  2017. }
  2018. }
  2019. }
  2020. /// <summary>
  2021. /// Do a physics propery update for this part.
  2022. /// now also updates phantom and volume detector
  2023. /// </summary>
  2024. /// <param name="UsePhysics"></param>
  2025. /// <param name="isNew"></param>
  2026. public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew)
  2027. {
  2028. if (ParentGroup.Scene == null)
  2029. return;
  2030. if (!ParentGroup.Scene.PhysicalPrims && UsePhysics)
  2031. return;
  2032. if (IsJoint())
  2033. {
  2034. DoPhysicsPropertyUpdateForNinjaJoint(UsePhysics, isNew);
  2035. }
  2036. else
  2037. {
  2038. PhysicsActor pa = PhysActor;
  2039. if (pa != null)
  2040. {
  2041. if (UsePhysics != pa.IsPhysical)
  2042. ClampScale(UsePhysics);
  2043. if (UsePhysics != pa.IsPhysical || isNew)
  2044. {
  2045. if (pa.IsPhysical) // implies UsePhysics==false for this block
  2046. {
  2047. if (!isNew) // implies UsePhysics==false for this block
  2048. {
  2049. ParentGroup.Scene.RemovePhysicalPrim(1);
  2050. Stop();
  2051. if (pa.Phantom && !VolumeDetectActive)
  2052. {
  2053. RemoveFromPhysics();
  2054. return;
  2055. }
  2056. pa.IsPhysical = UsePhysics;
  2057. pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
  2058. pa.OnOutOfBounds -= PhysicsOutOfBounds;
  2059. pa.delink();
  2060. if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
  2061. {
  2062. // destroy all joints connected to this now deactivated body
  2063. ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
  2064. }
  2065. }
  2066. }
  2067. if (pa.IsPhysical != UsePhysics)
  2068. pa.IsPhysical = UsePhysics;
  2069. if (UsePhysics)
  2070. {
  2071. if (ParentGroup.RootPart.KeyframeMotion != null)
  2072. ParentGroup.RootPart.KeyframeMotion.Stop();
  2073. ParentGroup.RootPart.KeyframeMotion = null;
  2074. ParentGroup.Scene.AddPhysicalPrim(1);
  2075. PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
  2076. PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
  2077. if (_parentID != 0 && _parentID != LocalId)
  2078. {
  2079. PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
  2080. if (parentPa != null)
  2081. {
  2082. pa.link(parentPa);
  2083. }
  2084. }
  2085. }
  2086. }
  2087. bool phan = ((m_flags & PrimFlags.Phantom) != 0);
  2088. if (pa.Phantom != phan)
  2089. pa.Phantom = phan;
  2090. // some engines dont' have this check still
  2091. // if (VolumeDetectActive != pa.IsVolumeDtc)
  2092. {
  2093. if (VolumeDetectActive)
  2094. pa.SetVolumeDetect(1);
  2095. else
  2096. pa.SetVolumeDetect(0);
  2097. }
  2098. // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
  2099. // mesh data.
  2100. // if (Shape.SculptEntry)
  2101. // CheckSculptAndLoad();
  2102. // else
  2103. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
  2104. }
  2105. }
  2106. }
  2107. /// <summary>
  2108. /// Restore this part from the serialized xml representation.
  2109. /// </summary>
  2110. /// <param name="xmlReader"></param>
  2111. /// <returns></returns>
  2112. public static SceneObjectPart FromXml(XmlReader xmlReader)
  2113. {
  2114. SceneObjectPart part = SceneObjectSerializer.Xml2ToSOP(xmlReader);
  2115. // for tempOnRez objects, we have to fix the Expire date.
  2116. if ((part.m_flags & PrimFlags.TemporaryOnRez) != 0)
  2117. part.ResetExpire();
  2118. return part;
  2119. }
  2120. public bool GetDieAtEdge()
  2121. {
  2122. if (ParentGroup.IsDeleted)
  2123. return false;
  2124. return ParentGroup.RootPart.DIE_AT_EDGE;
  2125. }
  2126. public bool GetReturnAtEdge()
  2127. {
  2128. if (ParentGroup.IsDeleted)
  2129. return false;
  2130. return ParentGroup.RootPart.RETURN_AT_EDGE;
  2131. }
  2132. public void SetReturnAtEdge(bool p)
  2133. {
  2134. if (ParentGroup.IsDeleted)
  2135. return;
  2136. ParentGroup.RootPart.RETURN_AT_EDGE = p;
  2137. }
  2138. public void SetStatusSandbox(bool p)
  2139. {
  2140. if (ParentGroup.IsDeleted)
  2141. return;
  2142. StatusSandboxPos = ParentGroup.RootPart.AbsolutePosition;
  2143. ParentGroup.RootPart.StatusSandbox = p;
  2144. }
  2145. public bool GetStatusSandbox()
  2146. {
  2147. if (ParentGroup.IsDeleted)
  2148. return false;
  2149. return ParentGroup.RootPart.StatusSandbox;
  2150. }
  2151. public int GetAxisRotation(int axis)
  2152. {
  2153. if (!ParentGroup.IsDeleted)
  2154. return ParentGroup.GetAxisRotation(axis);
  2155. return 0;
  2156. }
  2157. public uint GetEffectiveObjectFlags()
  2158. {
  2159. uint eff = (uint)(m_flags | m_localFlags);
  2160. if(m_inventory == null || m_inventory.Count == 0)
  2161. eff |= (uint)PrimFlags.InventoryEmpty;
  2162. return eff;
  2163. }
  2164. // some of this lines need be moved to other place later
  2165. // effective permitions considering only this part inventory contents perms
  2166. public uint AggregatedInnerOwnerPerms {get; private set; }
  2167. public uint AggregatedInnerGroupPerms {get; private set; }
  2168. public uint AggregatedInnerEveryonePerms {get; private set; }
  2169. private readonly object InnerPermsLock = new object();
  2170. public void AggregateInnerPerms()
  2171. {
  2172. // assuming child prims permissions masks are irrelevant on a linkset
  2173. // root part is handle at SOG since its masks are the sog masks
  2174. const uint mask = (uint)PermissionMask.AllEffective;
  2175. uint owner = mask;
  2176. uint group = mask;
  2177. uint everyone = mask;
  2178. lock(InnerPermsLock) // do we really need this?
  2179. {
  2180. if(Inventory != null)
  2181. Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone);
  2182. AggregatedInnerOwnerPerms = owner & mask;
  2183. AggregatedInnerGroupPerms = group & mask;
  2184. AggregatedInnerEveryonePerms = everyone & mask;
  2185. }
  2186. if(ParentGroup != null)
  2187. ParentGroup.InvalidateEffectivePerms();
  2188. }
  2189. // same as above but called during group Effective Permission validation
  2190. public void AggregatedInnerPermsForGroup()
  2191. {
  2192. // assuming child prims permissions masks are irrelevant on a linkset
  2193. // root part is handle at SOG since its masks are the sog masks
  2194. const uint mask = (uint)PermissionMask.AllEffective;
  2195. uint owner = mask;
  2196. uint group = mask;
  2197. uint everyone = mask;
  2198. lock(InnerPermsLock) // do we really need this?
  2199. {
  2200. if(Inventory != null)
  2201. Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone);
  2202. AggregatedInnerOwnerPerms = owner & mask;
  2203. AggregatedInnerGroupPerms = group & mask;
  2204. AggregatedInnerEveryonePerms = everyone & mask;
  2205. }
  2206. }
  2207. public Vector3 GetGeometricCenter()
  2208. {
  2209. // this is not real geometric center but a average of positions relative to root prim acording to
  2210. // http://wiki.secondlife.com/wiki/llGetGeometricCenter
  2211. // ignoring tortured prims details since sl also seems to ignore
  2212. // so no real use in doing it on physics
  2213. if (ParentGroup.IsDeleted)
  2214. return new Vector3(0, 0, 0);
  2215. return ParentGroup.GetGeometricCenter();
  2216. }
  2217. public float GetMass()
  2218. {
  2219. PhysicsActor pa = PhysActor;
  2220. if (pa != null)
  2221. return pa.Mass;
  2222. else
  2223. return 0;
  2224. }
  2225. public Vector3 GetCenterOfMass()
  2226. {
  2227. if (ParentGroup.RootPart == this)
  2228. {
  2229. if (ParentGroup.IsDeleted)
  2230. return AbsolutePosition;
  2231. return ParentGroup.GetCenterOfMass();
  2232. }
  2233. PhysicsActor pa = PhysActor;
  2234. if (pa != null)
  2235. {
  2236. Vector3 tmp = pa.CenterOfMass;
  2237. return tmp;
  2238. }
  2239. else
  2240. return AbsolutePosition;
  2241. }
  2242. public Vector3 GetPartCenterOfMass()
  2243. {
  2244. PhysicsActor pa = PhysActor;
  2245. if (pa != null)
  2246. {
  2247. Vector3 tmp = pa.CenterOfMass;
  2248. return tmp;
  2249. }
  2250. else
  2251. return AbsolutePosition;
  2252. }
  2253. public Vector3 GetForce()
  2254. {
  2255. return Force;
  2256. }
  2257. /// <summary>
  2258. /// Method for a prim to get it's world position from the group.
  2259. /// </summary>
  2260. /// <remarks>
  2261. /// Remember, the Group Position simply gives the position of the group itself
  2262. /// </remarks>
  2263. /// <returns>A Linked Child Prim objects position in world</returns>
  2264. public Vector3 GetWorldPosition()
  2265. {
  2266. if (_parentID == 0)
  2267. return GroupPosition;
  2268. // If a child SOP, my position is relative to the root SOP so take
  2269. // my info and add the root's position and rotation to
  2270. // get my world position.
  2271. return ParentGroup.AbsolutePosition + OffsetPosition * ParentGroup.RootPart.RotationOffset;
  2272. }
  2273. /// <summary>
  2274. /// Gets the rotation of this prim offset by the group rotation
  2275. /// </summary>
  2276. /// <returns></returns>
  2277. public Quaternion GetWorldRotation()
  2278. {
  2279. if (_parentID == 0)
  2280. return RotationOffset;
  2281. // A child SOP's rotation is relative to the root SOP's rotation.
  2282. // Combine them to get my absolute rotation.
  2283. return ParentGroup.RootPart.RotationOffset * RotationOffset;
  2284. }
  2285. /// <summary>
  2286. /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
  2287. /// </summary>
  2288. /// <param name="height">Height to hover. Height of zero disables hover.</param>
  2289. /// <param name="hoverType">Determines what the height is relative to </param>
  2290. /// <param name="tau">Number of seconds over which to reach target</param>
  2291. public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
  2292. {
  2293. ParentGroup.SetHoverHeight(height, hoverType, tau);
  2294. }
  2295. public void StopHover()
  2296. {
  2297. ParentGroup.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
  2298. }
  2299. public virtual void OnGrab(Vector3 offsetPos, IClientAPI remoteClient)
  2300. {
  2301. }
  2302. public bool CollisionFilteredOut(UUID objectID, string objectName)
  2303. {
  2304. if(CollisionFilter.Count == 0)
  2305. return false;
  2306. if (CollisionFilter.ContainsValue(objectID.ToString()) ||
  2307. CollisionFilter.ContainsValue(objectID.ToString() + objectName) ||
  2308. CollisionFilter.ContainsValue(UUID.Zero.ToString() + objectName))
  2309. {
  2310. if (CollisionFilter.ContainsKey(1))
  2311. return false;
  2312. return true;
  2313. }
  2314. if (CollisionFilter.ContainsKey(1))
  2315. return true;
  2316. return false;
  2317. }
  2318. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
  2319. private DetectedObject CreateDetObject(SceneObjectPart obj)
  2320. {
  2321. return new DetectedObject()
  2322. {
  2323. keyUUID = obj.UUID,
  2324. nameStr = obj.Name,
  2325. ownerUUID = obj.OwnerID,
  2326. posVector = obj.AbsolutePosition,
  2327. rotQuat = obj.GetWorldRotation(),
  2328. velVector = obj.Velocity,
  2329. colliderType = 0,
  2330. groupUUID = obj.GroupID,
  2331. linkNumber = LinkNum
  2332. };
  2333. }
  2334. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
  2335. private DetectedObject CreateDetObject(ScenePresence av)
  2336. {
  2337. DetectedObject detobj = new DetectedObject()
  2338. {
  2339. keyUUID = av.UUID,
  2340. nameStr = av.ControllingClient.Name,
  2341. ownerUUID = av.UUID,
  2342. posVector = av.AbsolutePosition,
  2343. rotQuat = av.Rotation,
  2344. velVector = av.Velocity,
  2345. colliderType = av.IsNPC ? 0x20 : 0x1, // OpenSim\Region\ScriptEngine\Shared\Helpers.cs
  2346. groupUUID = av.ControllingClient.ActiveGroupId,
  2347. linkNumber = LinkNum
  2348. };
  2349. if(av.IsSatOnObject)
  2350. detobj.colliderType |= 0x4; //passive
  2351. else if(detobj.velVector != Vector3.Zero)
  2352. detobj.colliderType |= 0x2; //active
  2353. return detobj;
  2354. }
  2355. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
  2356. private DetectedObject CreateDetObjectForGround()
  2357. {
  2358. return new DetectedObject()
  2359. {
  2360. keyUUID = UUID.Zero,
  2361. nameStr = "",
  2362. ownerUUID = UUID.Zero,
  2363. posVector = ParentGroup.RootPart.AbsolutePosition,
  2364. rotQuat = Quaternion.Identity,
  2365. velVector = Vector3.Zero,
  2366. colliderType = 0,
  2367. groupUUID = UUID.Zero,
  2368. linkNumber = LinkNum
  2369. };
  2370. }
  2371. private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
  2372. {
  2373. ColliderArgs colliderArgs = new ColliderArgs();
  2374. List<DetectedObject> colliding = new List<DetectedObject>();
  2375. Scene parentScene = ParentGroup.Scene;
  2376. foreach (uint localId in colliders)
  2377. {
  2378. if (localId == 0)
  2379. continue;
  2380. SceneObjectPart obj = parentScene.GetSceneObjectPart(localId);
  2381. if (obj != null)
  2382. {
  2383. if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
  2384. colliding.Add(CreateDetObject(obj));
  2385. }
  2386. else
  2387. {
  2388. ScenePresence av = parentScene.GetScenePresence(localId);
  2389. if (av != null && (!av.IsChildAgent))
  2390. {
  2391. if (!dest.CollisionFilteredOut(av.UUID, av.Name))
  2392. colliding.Add(CreateDetObject(av));
  2393. }
  2394. }
  2395. }
  2396. colliderArgs.Colliders = colliding;
  2397. return colliderArgs;
  2398. }
  2399. private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
  2400. private void SendCollisionEvent(scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
  2401. {
  2402. if (colliders.Count > 0)
  2403. {
  2404. ColliderArgs CollidingMessage;
  2405. if ((ScriptEvents & ev) != 0)
  2406. {
  2407. CollidingMessage = CreateColliderArgs(this, colliders);
  2408. if (CollidingMessage.Colliders.Count > 0)
  2409. notify(LocalId, CollidingMessage);
  2410. if (!PassCollisions)
  2411. return;
  2412. }
  2413. SceneObjectPart root = ParentGroup.RootPart;
  2414. uint rootID = root.LocalId;
  2415. if (rootID != LocalId && (root.ScriptEvents & ev) != 0)
  2416. {
  2417. CollidingMessage = CreateColliderArgs(root, colliders);
  2418. if (CollidingMessage.Colliders.Count > 0)
  2419. notify(rootID, CollidingMessage);
  2420. }
  2421. }
  2422. }
  2423. private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
  2424. {
  2425. ColliderArgs LandCollidingMessage = new ColliderArgs();
  2426. LandCollidingMessage.Colliders = new List<DetectedObject>()
  2427. {
  2428. CreateDetObjectForGround()
  2429. };
  2430. if ((ScriptEvents & ev) != 0)
  2431. {
  2432. notify(LocalId, LandCollidingMessage);
  2433. if(!PassCollisions)
  2434. return;
  2435. }
  2436. SceneObjectPart root = ParentGroup.RootPart;
  2437. if(LocalId != root.LocalId && (root.ScriptEvents & ev) != 0)
  2438. notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
  2439. }
  2440. public void PhysicsCollision(EventArgs e)
  2441. {
  2442. if (ParentGroup.Scene == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  2443. return;
  2444. CollisionEventUpdate a = (CollisionEventUpdate)e;
  2445. Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList;
  2446. EventManager eventManager;
  2447. scriptEvents combinedEvents = ScriptEvents | ParentGroup.RootPart.ScriptEvents;
  2448. int ncollisions = collissionswith.Count;
  2449. if (ncollisions == 0)
  2450. {
  2451. if (m_lastColliders.Count == 0 && !m_lastLandCollide)
  2452. return; // nothing to do
  2453. eventManager = ParentGroup.Scene.EventManager;
  2454. combinedEvents = ScriptEvents | ParentGroup.RootPart.ScriptEvents;
  2455. if (m_lastColliders.Count > 0 && (combinedEvents & scriptEvents.collision_end) != 0)
  2456. SendCollisionEvent(scriptEvents.collision_end, m_lastColliders, eventManager.TriggerScriptCollidingEnd);
  2457. if (m_lastLandCollide && !VolumeDetectActive && (combinedEvents & scriptEvents.land_collision_end) != 0)
  2458. SendLandCollisionEvent(scriptEvents.land_collision_end, eventManager.TriggerScriptLandCollidingEnd);
  2459. m_lastColliders.Clear();
  2460. m_lastLandCollide = false;
  2461. return;
  2462. }
  2463. bool thisHitLand = false;
  2464. bool startLand = false;
  2465. List<uint> thisHitColliders = new List<uint>(ncollisions);
  2466. List<uint> endedColliders = new List<uint>(m_lastColliders.Count);
  2467. List<uint> startedColliders = new List<uint>(ncollisions);
  2468. // calculate things that started colliding this time
  2469. // and build up list of colliders this time
  2470. if (!VolumeDetectActive && CollisionSoundType >= 0)
  2471. {
  2472. List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
  2473. CollisionForSoundInfo soundinfo;
  2474. ContactPoint curcontact;
  2475. foreach (uint id in collissionswith.Keys)
  2476. {
  2477. if(id == 0)
  2478. {
  2479. thisHitLand = true;
  2480. startLand = !m_lastLandCollide;
  2481. if (startLand)
  2482. {
  2483. curcontact = collissionswith[id];
  2484. if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
  2485. {
  2486. soundinfo = new CollisionForSoundInfo()
  2487. {
  2488. colliderID = id,
  2489. position = curcontact.Position,
  2490. relativeVel = curcontact.RelativeSpeed
  2491. };
  2492. soundinfolist.Add(soundinfo);
  2493. }
  2494. }
  2495. }
  2496. else
  2497. {
  2498. thisHitColliders.Add(id);
  2499. if (!m_lastColliders.Contains(id))
  2500. {
  2501. startedColliders.Add(id);
  2502. curcontact = collissionswith[id];
  2503. if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
  2504. {
  2505. soundinfo = new CollisionForSoundInfo()
  2506. {
  2507. colliderID = id,
  2508. position = curcontact.Position,
  2509. relativeVel = curcontact.RelativeSpeed
  2510. };
  2511. soundinfolist.Add(soundinfo);
  2512. }
  2513. }
  2514. }
  2515. }
  2516. // play sounds.
  2517. if (soundinfolist.Count > 0)
  2518. CollisionSounds.PartCollisionSound(this, soundinfolist);
  2519. }
  2520. else
  2521. {
  2522. foreach (uint id in collissionswith.Keys)
  2523. {
  2524. if(id == 0)
  2525. {
  2526. thisHitLand = true;
  2527. startLand = !m_lastLandCollide;
  2528. }
  2529. else
  2530. {
  2531. thisHitColliders.Add(id);
  2532. if (!m_lastColliders.Contains(id))
  2533. startedColliders.Add(id);
  2534. }
  2535. }
  2536. }
  2537. // calculate things that ended colliding
  2538. foreach (uint localID in m_lastColliders)
  2539. {
  2540. if (!thisHitColliders.Contains(localID))
  2541. endedColliders.Add(localID);
  2542. }
  2543. eventManager = ParentGroup.Scene.EventManager;
  2544. combinedEvents = ScriptEvents | ParentGroup.RootPart.ScriptEvents;
  2545. if ((combinedEvents & scriptEvents.anyobjcollision) != 0)
  2546. {
  2547. if ((combinedEvents & scriptEvents.collision_start) != 0)
  2548. SendCollisionEvent(scriptEvents.collision_start, startedColliders, eventManager.TriggerScriptCollidingStart);
  2549. if ((combinedEvents & scriptEvents.collision_end) != 0)
  2550. SendCollisionEvent(scriptEvents.collision_end , endedColliders , eventManager.TriggerScriptCollidingEnd);
  2551. }
  2552. if (!VolumeDetectActive)
  2553. {
  2554. if ((combinedEvents & scriptEvents.collision) != 0)
  2555. SendCollisionEvent(scriptEvents.collision, m_lastColliders, eventManager.TriggerScriptColliding);
  2556. if ((combinedEvents & scriptEvents.anylandcollision) != 0)
  2557. {
  2558. if (thisHitLand)
  2559. {
  2560. if (startLand && (combinedEvents & scriptEvents.land_collision_start) != 0)
  2561. SendLandCollisionEvent(scriptEvents.land_collision_start, eventManager.TriggerScriptLandCollidingStart);
  2562. if ((combinedEvents & scriptEvents.land_collision) != 0)
  2563. SendLandCollisionEvent(scriptEvents.land_collision, eventManager.TriggerScriptLandColliding);
  2564. }
  2565. else if(m_lastLandCollide && (combinedEvents & scriptEvents.land_collision_end) != 0)
  2566. SendLandCollisionEvent(scriptEvents.land_collision_end, eventManager.TriggerScriptLandCollidingEnd);
  2567. }
  2568. }
  2569. m_lastColliders = thisHitColliders;
  2570. m_lastLandCollide = thisHitLand;
  2571. }
  2572. // The Collision sounds code calls this
  2573. public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
  2574. {
  2575. if (soundID == UUID.Zero)
  2576. return;
  2577. ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
  2578. if (soundModule == null)
  2579. return;
  2580. if (volume > 1)
  2581. volume = 1;
  2582. if (volume < 0)
  2583. volume = 0;
  2584. int now = Util.EnvironmentTickCount();
  2585. if(Util.EnvironmentTickCountSubtract(now, LastColSoundSentTime) < 200)
  2586. return;
  2587. LastColSoundSentTime = now;
  2588. UUID ownerID = OwnerID;
  2589. UUID objectID = ParentGroup.RootPart.UUID;
  2590. UUID parentID = ParentGroup.UUID;
  2591. ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
  2592. soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle);
  2593. }
  2594. public void PhysicsOutOfBounds(Vector3 pos)
  2595. {
  2596. // Note: This is only being called on the root prim at this time.
  2597. m_log.ErrorFormat(
  2598. "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.",
  2599. Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition);
  2600. RemFlag(PrimFlags.Physics);
  2601. DoPhysicsPropertyUpdate(false, true);
  2602. }
  2603. public void PhysicsRequestingTerseUpdate()
  2604. {
  2605. PhysicsActor pa = PhysActor;
  2606. if (pa != null)
  2607. {
  2608. Vector3 newpos = pa.Position;
  2609. if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
  2610. {
  2611. // Setting position outside current region will start region crossing
  2612. ParentGroup.AbsolutePosition = newpos;
  2613. return;
  2614. }
  2615. //ParentGroup.RootPart.m_groupPosition = newpos;
  2616. }
  2617. ScheduleTerseUpdate();
  2618. }
  2619. public void RemFlag(PrimFlags flag)
  2620. {
  2621. // PrimFlags prevflag = Flags;
  2622. if ((m_flags & flag) != 0)
  2623. {
  2624. //m_log.Debug("Removing flag: " + ((PrimFlags)flag).ToString());
  2625. m_flags &= ~flag;
  2626. }
  2627. //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
  2628. //ScheduleFullUpdate();
  2629. }
  2630. public void RemoveScriptEvents(UUID scriptid)
  2631. {
  2632. lock (m_scriptEvents)
  2633. {
  2634. if (m_scriptEvents.TryGetValue(scriptid, out scriptEvents ev))
  2635. {
  2636. if((ev & (scriptEvents.anyTarget)) != 0 && ParentGroup != null)
  2637. ParentGroup.RemoveScriptTargets(scriptid);
  2638. m_scriptEvents.Remove(scriptid);
  2639. aggregateScriptEvents();
  2640. }
  2641. }
  2642. }
  2643. public void RemoveScriptTargets(UUID scriptid)
  2644. {
  2645. if(ParentGroup != null)
  2646. ParentGroup.RemoveScriptTargets(scriptid);
  2647. }
  2648. /// <summary>
  2649. /// Reset UUIDs for this part. This involves generate this part's own UUID and
  2650. /// generating new UUIDs for all the items in the inventory.
  2651. /// </summary>
  2652. /// <param name="linkNum">Link number for the part</param>
  2653. public void ResetIDs(int linkNum)
  2654. {
  2655. UUID = UUID.Random();
  2656. LinkNum = linkNum;
  2657. LocalId = 0;
  2658. Inventory.ResetInventoryIDs();
  2659. ++PseudoCRC;
  2660. }
  2661. private void ClampScale(bool isPhysical)
  2662. {
  2663. float minsize = isPhysical ? ParentGroup.Scene.m_minPhys : ParentGroup.Scene.m_minNonphys;
  2664. float maxsize = isPhysical ? ParentGroup.Scene.m_maxPhys : ParentGroup.Scene.m_maxNonphys;
  2665. Vector3 scale = Scale;
  2666. bool changed = false;
  2667. if (scale.X < minsize)
  2668. {
  2669. scale.X = minsize;
  2670. changed = true;
  2671. }
  2672. else if (scale.X > maxsize)
  2673. {
  2674. scale.X = maxsize;
  2675. changed = true;
  2676. }
  2677. if (scale.Y < minsize)
  2678. {
  2679. scale.Y = minsize;
  2680. changed = true;
  2681. }
  2682. else if (scale.Y > maxsize)
  2683. {
  2684. scale.Y = maxsize;
  2685. changed = true;
  2686. }
  2687. if (scale.Z < minsize)
  2688. {
  2689. scale.Z = minsize;
  2690. changed = true;
  2691. }
  2692. else if (scale.Z > maxsize)
  2693. {
  2694. scale.Z = maxsize;
  2695. changed = true;
  2696. }
  2697. if (changed)
  2698. Scale = scale;
  2699. }
  2700. /// <summary>
  2701. /// Set the scale of this part.
  2702. /// </summary>
  2703. /// <remarks>
  2704. /// Unlike the scale property, this checks the new size against scene limits and schedules a full property
  2705. /// update to viewers.
  2706. /// </remarks>
  2707. /// <param name="scale"></param>
  2708. public void Resize(Vector3 scale)
  2709. {
  2710. PhysicsActor pa = PhysActor;
  2711. if (ParentGroup.Scene != null)
  2712. {
  2713. float minsize = ParentGroup.Scene.m_minNonphys;
  2714. float maxsize = ParentGroup.Scene.m_maxNonphys;
  2715. if (pa != null && pa.IsPhysical)
  2716. {
  2717. minsize = ParentGroup.Scene.m_minPhys;
  2718. maxsize = ParentGroup.Scene.m_maxPhys;
  2719. }
  2720. scale.X = Util.Clamp(scale.X, minsize, maxsize);
  2721. scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
  2722. scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
  2723. }
  2724. // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
  2725. Scale = scale;
  2726. ParentGroup.HasGroupChanged = true;
  2727. ScheduleFullUpdate();
  2728. }
  2729. public void RotLookAt(Quaternion target, float strength, float damping)
  2730. {
  2731. if(ParentGroup.IsDeleted)
  2732. return;
  2733. // for now we only handle physics case
  2734. if(!ParentGroup.UsesPhysics || ParentGroup.IsAttachment)
  2735. return;
  2736. // physical is SOG
  2737. if(ParentGroup.RootPart != this)
  2738. {
  2739. ParentGroup.RotLookAt(target, strength, damping);
  2740. return;
  2741. }
  2742. APIDDamp = damping;
  2743. APIDStrength = strength;
  2744. APIDTarget = target;
  2745. if (APIDStrength <= 0)
  2746. {
  2747. m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength);
  2748. return;
  2749. }
  2750. APIDActive = true;
  2751. // Necessary to get the lookat deltas applied
  2752. ParentGroup.QueueForUpdateCheck();
  2753. }
  2754. public void StartLookAt(Quaternion target, float strength, float damping)
  2755. {
  2756. if(ParentGroup.IsDeleted)
  2757. return;
  2758. // non physical is done on LSL
  2759. if(ParentGroup.IsAttachment || !ParentGroup.UsesPhysics)
  2760. return;
  2761. // physical is SOG
  2762. if(ParentGroup.RootPart != this)
  2763. ParentGroup.RotLookAt(target, strength, damping);
  2764. else
  2765. RotLookAt(target,strength,damping);
  2766. }
  2767. public void StopLookAt()
  2768. {
  2769. if(ParentGroup.IsDeleted)
  2770. return;
  2771. if(ParentGroup.RootPart != this && ParentGroup.UsesPhysics)
  2772. ParentGroup.StopLookAt();
  2773. // just in case do this always
  2774. if(APIDActive)
  2775. AngularVelocity = Vector3.Zero;
  2776. APIDActive = false;
  2777. }
  2778. /// <summary>
  2779. /// Schedules this prim for a full update
  2780. /// </summary>
  2781. public void ScheduleFullUpdate()
  2782. {
  2783. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null)
  2784. return;
  2785. ++PseudoCRC;
  2786. if (ParentGroup.Scene.GetNumberOfClients() == 0)
  2787. return;
  2788. ParentGroup.QueueForUpdateCheck(); // just in case
  2789. lock(UpdateFlagLock)
  2790. UpdateFlag |= PrimUpdateFlags.FullUpdate;
  2791. ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
  2792. }
  2793. public void ScheduleFullAnimUpdate()
  2794. {
  2795. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null)
  2796. return;
  2797. ++PseudoCRC;
  2798. if (ParentGroup.Scene.GetNumberOfClients() == 0)
  2799. return;
  2800. PrimUpdateFlags update = PrimUpdateFlags.FullUpdatewithAnim;
  2801. if (Animations == null || !ParentGroup.RootPart.Shape.MeshFlagEntry)
  2802. update = PrimUpdateFlags.FullUpdate;
  2803. ParentGroup.QueueForUpdateCheck(); // just in case
  2804. lock (UpdateFlagLock)
  2805. UpdateFlag |= update;
  2806. ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
  2807. }
  2808. /// <summary>
  2809. /// Schedule a terse update for this prim. Terse updates only send position,
  2810. /// rotation, velocity and rotational velocity information.
  2811. /// </summary>
  2812. public void ScheduleTerseUpdate()
  2813. {
  2814. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null)
  2815. return;
  2816. ++PseudoCRC;
  2817. ParentGroup.HasGroupChanged = true;
  2818. if(ParentGroup.Scene.GetNumberOfClients() == 0)
  2819. return;
  2820. ParentGroup.QueueForUpdateCheck();
  2821. bool isfull = false;
  2822. PrimUpdateFlags update;
  2823. if (ParentGroup.IsAttachment)
  2824. {
  2825. update = PrimUpdateFlags.FullUpdate;
  2826. isfull = true;
  2827. }
  2828. else
  2829. update = PrimUpdateFlags.TerseUpdate;
  2830. lock (UpdateFlagLock)
  2831. UpdateFlag |= update;
  2832. ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull);
  2833. }
  2834. public void ScheduleUpdate(PrimUpdateFlags update)
  2835. {
  2836. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null)
  2837. return;
  2838. if (Animations == null)
  2839. update &= ~PrimUpdateFlags.Animations;
  2840. if (update == PrimUpdateFlags.None)
  2841. return;
  2842. ++PseudoCRC;
  2843. ParentGroup.HasGroupChanged = true;
  2844. if (ParentGroup.Scene.GetNumberOfClients() == 0)
  2845. return;
  2846. bool isfull = false;
  2847. if (ParentGroup.IsAttachment)
  2848. {
  2849. update |= PrimUpdateFlags.FullUpdate;
  2850. isfull = true;
  2851. }
  2852. lock (UpdateFlagLock)
  2853. UpdateFlag |= update;
  2854. ParentGroup.QueueForUpdateCheck();
  2855. ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull);
  2856. }
  2857. public void ScriptSetPhysicsStatus(bool UsePhysics)
  2858. {
  2859. ParentGroup.ScriptSetPhysicsStatus(UsePhysics);
  2860. }
  2861. /// <summary>
  2862. /// Send a full update to the client for the given part
  2863. /// </summary>
  2864. /// <param name="remoteClient"></param>
  2865. protected internal void SendFullUpdate(IClientAPI remoteClient)
  2866. {
  2867. if (ParentGroup == null)
  2868. return;
  2869. if (ParentGroup.IsAttachment)
  2870. {
  2871. ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
  2872. if (sp != null)
  2873. sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate);
  2874. }
  2875. else
  2876. {
  2877. SendUpdateToClient(remoteClient, PrimUpdateFlags.FullUpdate);
  2878. }
  2879. }
  2880. protected internal void SendUpdate(IClientAPI remoteClient, PrimUpdateFlags update)
  2881. {
  2882. if (ParentGroup == null)
  2883. return;
  2884. if (ParentGroup.IsAttachment)
  2885. {
  2886. ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
  2887. if (sp != null)
  2888. sp.SendAttachmentUpdate(this, update);
  2889. }
  2890. else
  2891. {
  2892. SendUpdateToClient(remoteClient, update);
  2893. }
  2894. }
  2895. /// <summary>
  2896. /// Send a full update for this part to all clients.
  2897. /// </summary>
  2898. public void SendFullUpdateToAllClientsNoAttachment()
  2899. {
  2900. if (ParentGroup == null)
  2901. return;
  2902. ++PseudoCRC;
  2903. // Update the "last" values
  2904. lock (UpdateFlagLock)
  2905. {
  2906. m_lastPosition = AbsolutePosition;
  2907. m_lastRotation = RotationOffset;
  2908. m_lastVelocity = Velocity;
  2909. m_lastAcceleration = Acceleration;
  2910. m_lastAngularVelocity = AngularVelocity;
  2911. m_lastUpdateSentTime = Util.GetTimeStampMS();
  2912. UpdateFlag &= ~PrimUpdateFlags.FullUpdate;
  2913. }
  2914. ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
  2915. {
  2916. SendUpdateToClient(avatar.ControllingClient, PrimUpdateFlags.FullUpdate);
  2917. });
  2918. }
  2919. public void SendFullUpdateToAllClients()
  2920. {
  2921. if (ParentGroup == null)
  2922. return;
  2923. ++PseudoCRC;
  2924. // Update the "last" values
  2925. lock (UpdateFlagLock)
  2926. {
  2927. m_lastPosition = AbsolutePosition;
  2928. m_lastRotation = RotationOffset;
  2929. m_lastVelocity = Velocity;
  2930. m_lastAcceleration = Acceleration;
  2931. m_lastAngularVelocity = AngularVelocity;
  2932. m_lastUpdateSentTime = Util.GetTimeStampMS();
  2933. UpdateFlag &= ~PrimUpdateFlags.FullUpdate;
  2934. }
  2935. if (ParentGroup.IsAttachment)
  2936. {
  2937. ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
  2938. if (sp != null)
  2939. sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate);
  2940. }
  2941. else
  2942. {
  2943. ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
  2944. {
  2945. SendUpdateToClient(avatar.ControllingClient, PrimUpdateFlags.FullUpdate);
  2946. });
  2947. }
  2948. }
  2949. private const float ROTATION_TOLERANCE = 0.01f;
  2950. private const float VELOCITY_TOLERANCE = 0.1f;
  2951. private const float ANGVELOCITY_TOLERANCE = 0.005f;
  2952. private const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
  2953. private const double TIME_MS_TOLERANCE = 250.0; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
  2954. private Vector3 ClampVectorForTerseUpdate(Vector3 v, float max)
  2955. {
  2956. float a, b;
  2957. a = Math.Abs(v.X);
  2958. b = Math.Abs(v.Y);
  2959. if (b > a)
  2960. a = b;
  2961. b = Math.Abs(v.Z);
  2962. if (b > a)
  2963. a = b;
  2964. if (a > max)
  2965. {
  2966. a = max / a;
  2967. v.X *= a;
  2968. v.Y *= a;
  2969. v.Z *= a;
  2970. }
  2971. return v;
  2972. }
  2973. /// <summary>
  2974. /// Tell all the prims which have had updates scheduled
  2975. /// </summary>
  2976. public void SendScheduledUpdates(double now)
  2977. {
  2978. PrimUpdateFlags current;
  2979. lock (UpdateFlagLock)
  2980. {
  2981. current = UpdateFlag;
  2982. if (current == PrimUpdateFlags.None)
  2983. return;
  2984. if(current == PrimUpdateFlags.TerseUpdate)
  2985. {
  2986. while(true) // just to avoid ugly goto
  2987. {
  2988. double elapsed = now - m_lastUpdateSentTime;
  2989. if (elapsed > TIME_MS_TOLERANCE)
  2990. break;
  2991. if ( !Acceleration.ApproxEquals(m_lastAcceleration, VELOCITY_TOLERANCE))
  2992. break;
  2993. Vector3 curvel = ClampVectorForTerseUpdate(Velocity, 128f);
  2994. Vector3 tmp = ClampVectorForTerseUpdate(m_lastVelocity, 128f);
  2995. if (!curvel.ApproxEquals(tmp, VELOCITY_TOLERANCE))
  2996. break;
  2997. if (Math.Abs(curvel.X) < 1e-4 && Math.Abs(curvel.Y) < 1e-4 && Math.Abs(curvel.Z) < 1e-4)
  2998. {
  2999. if (!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
  3000. break;
  3001. if ( Math.Abs(m_lastVelocity.X) > 1e-4 ||
  3002. Math.Abs(m_lastVelocity.Y) > 1e-4 ||
  3003. Math.Abs(m_lastVelocity.Z) > 1e-4
  3004. )
  3005. break;
  3006. }
  3007. Vector3 angvel = ClampVectorForTerseUpdate(AngularVelocity, 64f);
  3008. tmp = ClampVectorForTerseUpdate(m_lastAngularVelocity, 64f);
  3009. if (!angvel.ApproxEquals(tmp, ANGVELOCITY_TOLERANCE))
  3010. break;
  3011. if ( Math.Abs(AngularVelocity.X) < 1e-4 &&
  3012. Math.Abs(AngularVelocity.Y) < 1e-4 &&
  3013. Math.Abs(AngularVelocity.Z) < 1e-4 &&
  3014. !RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
  3015. )
  3016. break;
  3017. return;
  3018. }
  3019. }
  3020. if((current & PrimUpdateFlags.TerseUpdate) != 0)
  3021. {
  3022. m_lastPosition = AbsolutePosition;
  3023. m_lastRotation = RotationOffset;
  3024. m_lastVelocity = Velocity;
  3025. m_lastAcceleration = Acceleration;
  3026. m_lastAngularVelocity = AngularVelocity;
  3027. m_lastUpdateSentTime = now;
  3028. }
  3029. UpdateFlag = PrimUpdateFlags.None;
  3030. }
  3031. ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
  3032. {
  3033. SendUpdateToClient(avatar.ControllingClient, current);
  3034. });
  3035. }
  3036. /// <summary>
  3037. /// Send a terse update to all clients
  3038. /// </summary>
  3039. public void SendTerseUpdateToAllClientsInternal()
  3040. {
  3041. if (ParentGroup == null || ParentGroup.Scene == null)
  3042. return;
  3043. lock(UpdateFlagLock)
  3044. {
  3045. UpdateFlag &= ~PrimUpdateFlags.TerseUpdate;
  3046. // Update the "last" values
  3047. m_lastPosition = AbsolutePosition;
  3048. m_lastRotation = RotationOffset;
  3049. m_lastVelocity = Velocity;
  3050. m_lastAcceleration = Acceleration;
  3051. m_lastAngularVelocity = AngularVelocity;
  3052. m_lastUpdateSentTime = Util.GetTimeStampMS();
  3053. }
  3054. ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
  3055. {
  3056. SendTerseUpdateToClient(client);
  3057. });
  3058. }
  3059. public void SendTerseUpdateToAllClients()
  3060. {
  3061. if (ParentGroup == null || ParentGroup.Scene == null)
  3062. return;
  3063. lock(UpdateFlagLock)
  3064. {
  3065. UpdateFlag &= ~PrimUpdateFlags.TerseUpdate;
  3066. // Update the "last" values
  3067. m_lastPosition = AbsolutePosition;
  3068. m_lastRotation = RotationOffset;
  3069. m_lastVelocity = Velocity;
  3070. m_lastAcceleration = Acceleration;
  3071. m_lastAngularVelocity = AngularVelocity;
  3072. m_lastUpdateSentTime = Util.GetTimeStampMS();
  3073. }
  3074. if (ParentGroup.IsAttachment)
  3075. {
  3076. ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
  3077. if (sp != null)
  3078. {
  3079. sp.SendAttachmentUpdate(this, PrimUpdateFlags.TerseUpdate);
  3080. }
  3081. }
  3082. else
  3083. {
  3084. ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
  3085. {
  3086. SendTerseUpdateToClient(client);
  3087. });
  3088. }
  3089. }
  3090. public void SetAxisRotation(int axis, int rotate)
  3091. {
  3092. ParentGroup.SetAxisRotation(axis, rotate);
  3093. //Cannot use ScriptBaseClass constants as no referance to it currently.
  3094. if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
  3095. STATUS_ROTATE_X = rotate;
  3096. if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
  3097. STATUS_ROTATE_Y = rotate;
  3098. if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
  3099. STATUS_ROTATE_Z = rotate;
  3100. }
  3101. public void SetBuoyancy(float fvalue)
  3102. {
  3103. Buoyancy = fvalue;
  3104. }
  3105. public void SetDieAtEdge(bool p)
  3106. {
  3107. if (ParentGroup.IsDeleted)
  3108. return;
  3109. ParentGroup.RootPart.DIE_AT_EDGE = p;
  3110. }
  3111. public void SetFloatOnWater(int floatYN)
  3112. {
  3113. PhysicsActor pa = PhysActor;
  3114. if (pa != null)
  3115. pa.FloatOnWater = (floatYN == 1);
  3116. }
  3117. public void SetForce(Vector3 force)
  3118. {
  3119. Force = force;
  3120. }
  3121. public PhysicsInertiaData PhysicsInertia
  3122. {
  3123. get
  3124. {
  3125. return m_physicsInertia;
  3126. }
  3127. set
  3128. {
  3129. m_physicsInertia = value;
  3130. }
  3131. }
  3132. public SOPVehicle VehicleParams
  3133. {
  3134. get
  3135. {
  3136. return m_vehicleParams;
  3137. }
  3138. set
  3139. {
  3140. m_vehicleParams = value;
  3141. }
  3142. }
  3143. public int VehicleType
  3144. {
  3145. get
  3146. {
  3147. if (m_vehicleParams == null)
  3148. return (int)Vehicle.TYPE_NONE;
  3149. else
  3150. return (int)m_vehicleParams.Type;
  3151. }
  3152. set
  3153. {
  3154. SetVehicleType(value);
  3155. }
  3156. }
  3157. public void SetVehicleType(int type)
  3158. {
  3159. m_vehicleParams = null;
  3160. if (type == (int)Vehicle.TYPE_NONE)
  3161. {
  3162. if (_parentID ==0 && PhysActor != null)
  3163. PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
  3164. return;
  3165. }
  3166. m_vehicleParams = new SOPVehicle();
  3167. m_vehicleParams.ProcessTypeChange((Vehicle)type);
  3168. {
  3169. if (_parentID ==0 && PhysActor != null)
  3170. PhysActor.VehicleType = type;
  3171. return;
  3172. }
  3173. }
  3174. public void SetVehicleFlags(int param, bool remove)
  3175. {
  3176. if (m_vehicleParams == null)
  3177. return;
  3178. m_vehicleParams.ProcessVehicleFlags(param, remove);
  3179. if (_parentID == 0 && PhysActor != null)
  3180. {
  3181. PhysActor.VehicleFlags(param, remove);
  3182. }
  3183. }
  3184. public void SetVehicleFloatParam(int param, float value)
  3185. {
  3186. if (m_vehicleParams == null)
  3187. return;
  3188. m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
  3189. if (_parentID == 0 && PhysActor != null)
  3190. {
  3191. PhysActor.VehicleFloatParam(param, value);
  3192. }
  3193. }
  3194. public void SetVehicleVectorParam(int param, Vector3 value)
  3195. {
  3196. if (m_vehicleParams == null)
  3197. return;
  3198. m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
  3199. if (_parentID == 0 && PhysActor != null)
  3200. {
  3201. PhysActor.VehicleVectorParam(param, value);
  3202. }
  3203. }
  3204. public void SetVehicleRotationParam(int param, Quaternion rotation)
  3205. {
  3206. if (m_vehicleParams == null)
  3207. return;
  3208. m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
  3209. if (_parentID == 0 && PhysActor != null)
  3210. {
  3211. PhysActor.VehicleRotationParam(param, rotation);
  3212. }
  3213. }
  3214. /// <summary>
  3215. /// Set the color & alpha of prim faces
  3216. /// </summary>
  3217. /// <param name="face"></param>
  3218. /// <param name="color"></param>
  3219. /// <param name="alpha"></param>
  3220. public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha)
  3221. {
  3222. Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f);
  3223. float clippedAlpha = alpha.HasValue ?
  3224. Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0;
  3225. // The only way to get a deep copy/ If we don't do this, we can
  3226. // never detect color changes further down.
  3227. Byte[] buf = Shape.Textures.GetBytes();
  3228. Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
  3229. Color4 texcolor;
  3230. int nsides = GetNumberOfSides();
  3231. if (face >= 0 && face < nsides)
  3232. {
  3233. texcolor = tex.CreateFace((uint)face).RGBA;
  3234. texcolor.R = clippedColor.X;
  3235. texcolor.G = clippedColor.Y;
  3236. texcolor.B = clippedColor.Z;
  3237. if (alpha.HasValue)
  3238. {
  3239. texcolor.A = clippedAlpha;
  3240. }
  3241. tex.FaceTextures[face].RGBA = texcolor;
  3242. UpdateTextureEntry(tex);
  3243. return;
  3244. }
  3245. else if (face == ALL_SIDES)
  3246. {
  3247. for (uint i = 0; i < nsides; i++)
  3248. {
  3249. if (tex.FaceTextures[i] != null)
  3250. {
  3251. texcolor = tex.FaceTextures[i].RGBA;
  3252. texcolor.R = clippedColor.X;
  3253. texcolor.G = clippedColor.Y;
  3254. texcolor.B = clippedColor.Z;
  3255. if (alpha.HasValue)
  3256. {
  3257. texcolor.A = clippedAlpha;
  3258. }
  3259. tex.FaceTextures[i].RGBA = texcolor;
  3260. }
  3261. texcolor = tex.DefaultTexture.RGBA;
  3262. texcolor.R = clippedColor.X;
  3263. texcolor.G = clippedColor.Y;
  3264. texcolor.B = clippedColor.Z;
  3265. if (alpha.HasValue)
  3266. {
  3267. texcolor.A = clippedAlpha;
  3268. }
  3269. tex.DefaultTexture.RGBA = texcolor;
  3270. }
  3271. UpdateTextureEntry(tex);
  3272. return;
  3273. }
  3274. }
  3275. /// <summary>
  3276. /// Get the number of sides that this part has.
  3277. /// </summary>
  3278. /// <returns></returns>
  3279. public int GetNumberOfSides()
  3280. {
  3281. int ret = 0;
  3282. int cut;
  3283. if(Shape.SculptEntry)
  3284. {
  3285. if (Shape.SculptType != (byte)SculptType.Mesh)
  3286. return 1; // sculp
  3287. //hack to detect new upload with faces data enconded on pbs
  3288. if ((Shape.ProfileCurve & 0xf0) != (byte)HollowShape.Triangle)
  3289. // old broken upload TODO
  3290. return 8;
  3291. }
  3292. PrimType primType = GetPrimType(true);
  3293. switch (primType)
  3294. {
  3295. case PrimType.BOX:
  3296. ret = 6;
  3297. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut case
  3298. {
  3299. // removed sides
  3300. if (Shape.ProfileBegin > 0)
  3301. {
  3302. cut = Shape.ProfileBegin;
  3303. cut /= 12500;
  3304. ret -= cut;
  3305. }
  3306. if (Shape.ProfileEnd > 0)
  3307. {
  3308. cut = Shape.ProfileEnd;
  3309. cut /= 12500;
  3310. ret -= cut;
  3311. }
  3312. ret += 2;
  3313. }
  3314. break;
  3315. case PrimType.PRISM:
  3316. ret = 5;
  3317. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut case
  3318. {
  3319. // removed sides
  3320. if (Shape.ProfileBegin > 0)
  3321. {
  3322. cut = (Shape.ProfileBegin);
  3323. if(cut >= 16667 )
  3324. ret--;
  3325. if(cut >= 33333 )
  3326. ret--;
  3327. }
  3328. if (Shape.ProfileEnd > 0)
  3329. {
  3330. cut = (Shape.ProfileEnd);
  3331. if(cut >= 16667 )
  3332. ret--;
  3333. if(cut >= 33333 )
  3334. ret--;
  3335. }
  3336. ret += 2; // both cut faces
  3337. }
  3338. break;
  3339. case PrimType.CYLINDER:
  3340. ret = 3;
  3341. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut
  3342. ret += 2;
  3343. break;
  3344. case PrimType.SPHERE:
  3345. ret = 1;
  3346. // cut faces exist if cut or skew or unequal twist limits
  3347. if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
  3348. ret += 2;
  3349. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0 || Shape.ProfileHollow > 0) // dimple also if hollow
  3350. ret += 2;
  3351. break;
  3352. case PrimType.TORUS:
  3353. ret = 1;
  3354. if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
  3355. || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
  3356. || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
  3357. ret += 2;
  3358. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
  3359. ret += 2;
  3360. break;
  3361. case PrimType.TUBE:
  3362. ret = 4;
  3363. if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
  3364. || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
  3365. || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
  3366. ret += 2;
  3367. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
  3368. {
  3369. if (Shape.ProfileBegin > 0)
  3370. {
  3371. cut = Shape.ProfileBegin;
  3372. cut /= 12500;
  3373. ret -= cut;
  3374. }
  3375. if (Shape.ProfileEnd > 0)
  3376. {
  3377. cut = Shape.ProfileEnd;
  3378. cut /= 12500;
  3379. ret -= cut;
  3380. }
  3381. ret += 2;
  3382. }
  3383. break;
  3384. case PrimType.RING:
  3385. ret = 3;
  3386. if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
  3387. || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
  3388. || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
  3389. ret += 2;
  3390. if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
  3391. {
  3392. if (Shape.ProfileBegin > 0)
  3393. {
  3394. cut = Shape.ProfileBegin;
  3395. if(cut >= 16667 )
  3396. ret--;
  3397. if(cut >= 33333 )
  3398. ret--;
  3399. }
  3400. if (Shape.ProfileEnd > 0)
  3401. {
  3402. cut = Shape.ProfileEnd;
  3403. if(cut >= 16667 )
  3404. ret--;
  3405. if(cut >= 33333 )
  3406. ret--;
  3407. }
  3408. ret += 2;
  3409. }
  3410. break;
  3411. }
  3412. // hollow face commum to all
  3413. if (Shape.ProfileHollow > 0)
  3414. ret += 1;
  3415. return ret;
  3416. }
  3417. /// <summary>
  3418. /// Tell us what type this prim is
  3419. /// </summary>
  3420. /// <param name="primShape"></param>
  3421. /// <returns></returns>
  3422. public PrimType GetPrimType(bool ignoreSculpt = false)
  3423. {
  3424. if (Shape.SculptEntry && !ignoreSculpt)
  3425. return PrimType.SCULPT;
  3426. ProfileShape ps = (ProfileShape)(Shape.ProfileCurve & 0x07);
  3427. if (ps == ProfileShape.Square)
  3428. {
  3429. if (Shape.PathCurve == (byte)Extrusion.Straight)
  3430. return PrimType.BOX;
  3431. else if (Shape.PathCurve == (byte)Extrusion.Curve1)
  3432. return PrimType.TUBE;
  3433. }
  3434. else if (ps == ProfileShape.Circle)
  3435. {
  3436. if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible)
  3437. return PrimType.CYLINDER;
  3438. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  3439. else if (Shape.PathCurve == (byte)Extrusion.Curve1)
  3440. return PrimType.TORUS;
  3441. }
  3442. else if (ps == ProfileShape.HalfCircle)
  3443. {
  3444. if (Shape.PathCurve == (byte)Extrusion.Curve1 || Shape.PathCurve == (byte)Extrusion.Curve2)
  3445. return PrimType.SPHERE;
  3446. }
  3447. else if (ps == ProfileShape.EquilateralTriangle)
  3448. {
  3449. if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible)
  3450. return PrimType.PRISM;
  3451. else if (Shape.PathCurve == (byte)Extrusion.Curve1)
  3452. return PrimType.RING;
  3453. }
  3454. return PrimType.BOX;
  3455. }
  3456. public void SetGroup(UUID groupID, IClientAPI client)
  3457. {
  3458. // Scene.AddNewPrims() calls with client == null so can't use this.
  3459. // m_log.DebugFormat(
  3460. // "[SCENE OBJECT PART]: Setting group for {0} to {1} for {2}",
  3461. // Name, groupID, OwnerID);
  3462. ++PseudoCRC;
  3463. GroupID = groupID;
  3464. // if (client != null)
  3465. // SendPropertiesToClient(client);
  3466. lock(UpdateFlagLock)
  3467. UpdateFlag |= PrimUpdateFlags.FullUpdate;
  3468. }
  3469. /// <summary>
  3470. /// Set the parent group of this prim.
  3471. /// </summary>
  3472. public void SetParent(SceneObjectGroup parent)
  3473. {
  3474. ParentGroup = parent;
  3475. }
  3476. // Use this for attachments! LocalID should be avatar's localid
  3477. public void SetParentLocalId(uint localID)
  3478. {
  3479. ParentID = localID;
  3480. }
  3481. public void SetPhysicsAxisRotation()
  3482. {
  3483. PhysicsActor pa = PhysActor;
  3484. if (pa != null)
  3485. {
  3486. pa.LockAngularMotion(RotationAxisLocks);
  3487. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
  3488. }
  3489. }
  3490. /// <summary>
  3491. /// Set the events that this part will pass on to listeners.
  3492. /// </summary>
  3493. /// <param name="scriptid"></param>
  3494. /// <param name="events"></param>
  3495. public void SetScriptEvents(UUID scriptid, ulong events)
  3496. {
  3497. // m_log.DebugFormat(
  3498. // "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}",
  3499. // scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name);
  3500. // scriptEvents oldparts;
  3501. lock (m_scriptEvents)
  3502. {
  3503. if (m_scriptEvents.TryGetValue(scriptid, out scriptEvents ev))
  3504. {
  3505. if (ev == (scriptEvents)events)
  3506. return;
  3507. }
  3508. m_scriptEvents[scriptid] = (scriptEvents) events;
  3509. }
  3510. aggregateScriptEvents();
  3511. }
  3512. /// <summary>
  3513. /// Set the text displayed for this part.
  3514. /// </summary>
  3515. /// <param name="text"></param>
  3516. public void SetText(string text)
  3517. {
  3518. osUTF8 old = osUTF8Text;
  3519. if(string.IsNullOrEmpty(text))
  3520. {
  3521. osUTF8Text = null;
  3522. if (old != null && ParentGroup != null)
  3523. {
  3524. ParentGroup.HasGroupChanged = true;
  3525. ScheduleFullUpdate();
  3526. }
  3527. }
  3528. else
  3529. {
  3530. osUTF8Text = new osUTF8(text, 254);
  3531. if (ParentGroup != null && !osUTF8Text.Equals(old))
  3532. {
  3533. ParentGroup.HasGroupChanged = true;
  3534. ScheduleFullUpdate();
  3535. }
  3536. }
  3537. }
  3538. /// <summary>
  3539. /// Set the text displayed for this part.
  3540. /// </summary>
  3541. /// <param name="text"></param>
  3542. /// <param name="color"></param>
  3543. /// <param name="alpha"></param>
  3544. public void SetText(string text, Vector3 color, double alpha)
  3545. {
  3546. Color oldcolor = Color;
  3547. Color = Color.FromArgb((int) (alpha * 0xff),
  3548. (int) (color.X * 0xff),
  3549. (int) (color.Y * 0xff),
  3550. (int) (color.Z * 0xff));
  3551. osUTF8 old = osUTF8Text;
  3552. if(string.IsNullOrEmpty(text))
  3553. {
  3554. osUTF8Text = null;
  3555. if (ParentGroup != null && (oldcolor != Color || old != null))
  3556. {
  3557. ParentGroup.HasGroupChanged = true;
  3558. ScheduleFullUpdate();
  3559. }
  3560. }
  3561. else
  3562. {
  3563. osUTF8Text = new osUTF8(text, 254);
  3564. if (ParentGroup != null && (oldcolor != Color || !osUTF8Text.Equals(old)))
  3565. {
  3566. ParentGroup.HasGroupChanged = true;
  3567. ScheduleFullUpdate();
  3568. }
  3569. }
  3570. }
  3571. public void StoreUndoState(ObjectChangeType change)
  3572. {
  3573. lock (m_UndoLock)
  3574. {
  3575. if (m_UndoRedo == null)
  3576. m_UndoRedo = new UndoRedoState(5);
  3577. if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
  3578. {
  3579. m_UndoRedo.StoreUndo(this, change);
  3580. }
  3581. }
  3582. }
  3583. /// <summary>
  3584. /// Return number of undos on the stack. Here temporarily pending a refactor.
  3585. /// </summary>
  3586. public int UndoCount
  3587. {
  3588. get
  3589. {
  3590. if (m_UndoRedo == null)
  3591. return 0;
  3592. return m_UndoRedo.Count;
  3593. }
  3594. }
  3595. public void Undo()
  3596. {
  3597. lock (m_UndoLock)
  3598. {
  3599. if (m_UndoRedo == null || Undoing || ParentGroup == null)
  3600. return;
  3601. Undoing = true;
  3602. m_UndoRedo.Undo(this);
  3603. Undoing = false;
  3604. }
  3605. }
  3606. public void Redo()
  3607. {
  3608. lock (m_UndoLock)
  3609. {
  3610. if (m_UndoRedo == null || Undoing || ParentGroup == null)
  3611. return;
  3612. Undoing = true;
  3613. m_UndoRedo.Redo(this);
  3614. Undoing = false;
  3615. }
  3616. }
  3617. public void ClearUndoState()
  3618. {
  3619. lock (m_UndoLock)
  3620. {
  3621. if (m_UndoRedo == null || Undoing)
  3622. return;
  3623. m_UndoRedo.Clear();
  3624. }
  3625. }
  3626. public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters)
  3627. {
  3628. // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes
  3629. // This breaks down into the ray---> plane equation.
  3630. // TODO: Change to take shape into account
  3631. Vector3[] vertexes = new Vector3[8];
  3632. // float[] distance = new float[6];
  3633. Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
  3634. Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
  3635. Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
  3636. Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
  3637. Vector3[] normals = new Vector3[6]; // Normal for Facei
  3638. Vector3[] AAfacenormals = new Vector3[6]; // Axis Aligned face normals
  3639. AAfacenormals[0] = new Vector3(1, 0, 0);
  3640. AAfacenormals[1] = new Vector3(0, 1, 0);
  3641. AAfacenormals[2] = new Vector3(-1, 0, 0);
  3642. AAfacenormals[3] = new Vector3(0, -1, 0);
  3643. AAfacenormals[4] = new Vector3(0, 0, 1);
  3644. AAfacenormals[5] = new Vector3(0, 0, -1);
  3645. Vector3 AmBa = new Vector3(0, 0, 0); // Vertex A - Vertex B
  3646. Vector3 AmBb = new Vector3(0, 0, 0); // Vertex B - Vertex C
  3647. Vector3 cross = new Vector3();
  3648. Vector3 pos = GetWorldPosition();
  3649. Quaternion rot = GetWorldRotation();
  3650. Quaternion AXrot = rot;
  3651. AXrot.Normalize();
  3652. Vector3 AXpos = pos;
  3653. // tScale is the offset to derive the vertex based on the scale.
  3654. // it's different for each vertex because we've got to rotate it
  3655. // to get the world position of the vertex to produce the Oriented Bounding Box
  3656. Vector3 tScale = Vector3.Zero;
  3657. Vector3 AXscale = new Vector3(m_shape.Scale.X * 0.5f, m_shape.Scale.Y * 0.5f, m_shape.Scale.Z * 0.5f);
  3658. //Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale));
  3659. //Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1));
  3660. // rScale is the rotated offset to find a vertex based on the scale and the world rotation.
  3661. Vector3 rScale = new Vector3();
  3662. // Get Vertexes for Faces Stick them into ABCD for each Face
  3663. // Form: Face<vertex>[face] that corresponds to the below diagram
  3664. #region ABCD Face Vertex Map Comment Diagram
  3665. // A _________ B
  3666. // | |
  3667. // | 4 top |
  3668. // |_________|
  3669. // C D
  3670. // A _________ B
  3671. // | Back |
  3672. // | 3 |
  3673. // |_________|
  3674. // C D
  3675. // A _________ B B _________ A
  3676. // | Left | | Right |
  3677. // | 0 | | 2 |
  3678. // |_________| |_________|
  3679. // C D D C
  3680. // A _________ B
  3681. // | Front |
  3682. // | 1 |
  3683. // |_________|
  3684. // C D
  3685. // C _________ D
  3686. // | |
  3687. // | 5 bot |
  3688. // |_________|
  3689. // A B
  3690. #endregion
  3691. #region Plane Decomposition of Oriented Bounding Box
  3692. tScale = new Vector3(AXscale.X, -AXscale.Y, AXscale.Z);
  3693. rScale = tScale * AXrot;
  3694. vertexes[0] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3695. // vertexes[0].X = pos.X + vertexes[0].X;
  3696. //vertexes[0].Y = pos.Y + vertexes[0].Y;
  3697. //vertexes[0].Z = pos.Z + vertexes[0].Z;
  3698. FaceA[0] = vertexes[0];
  3699. FaceB[3] = vertexes[0];
  3700. FaceA[4] = vertexes[0];
  3701. tScale = AXscale;
  3702. rScale = tScale * AXrot;
  3703. vertexes[1] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3704. // vertexes[1].X = pos.X + vertexes[1].X;
  3705. // vertexes[1].Y = pos.Y + vertexes[1].Y;
  3706. //vertexes[1].Z = pos.Z + vertexes[1].Z;
  3707. FaceB[0] = vertexes[1];
  3708. FaceA[1] = vertexes[1];
  3709. FaceC[4] = vertexes[1];
  3710. tScale = new Vector3(AXscale.X, -AXscale.Y, -AXscale.Z);
  3711. rScale = tScale * AXrot;
  3712. vertexes[2] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3713. //vertexes[2].X = pos.X + vertexes[2].X;
  3714. //vertexes[2].Y = pos.Y + vertexes[2].Y;
  3715. //vertexes[2].Z = pos.Z + vertexes[2].Z;
  3716. FaceC[0] = vertexes[2];
  3717. FaceD[3] = vertexes[2];
  3718. FaceC[5] = vertexes[2];
  3719. tScale = new Vector3(AXscale.X, AXscale.Y, -AXscale.Z);
  3720. rScale = tScale * AXrot;
  3721. vertexes[3] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3722. //vertexes[3].X = pos.X + vertexes[3].X;
  3723. // vertexes[3].Y = pos.Y + vertexes[3].Y;
  3724. // vertexes[3].Z = pos.Z + vertexes[3].Z;
  3725. FaceD[0] = vertexes[3];
  3726. FaceC[1] = vertexes[3];
  3727. FaceA[5] = vertexes[3];
  3728. tScale = new Vector3(-AXscale.X, AXscale.Y, AXscale.Z);
  3729. rScale = tScale * AXrot;
  3730. vertexes[4] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3731. // vertexes[4].X = pos.X + vertexes[4].X;
  3732. // vertexes[4].Y = pos.Y + vertexes[4].Y;
  3733. // vertexes[4].Z = pos.Z + vertexes[4].Z;
  3734. FaceB[1] = vertexes[4];
  3735. FaceA[2] = vertexes[4];
  3736. FaceD[4] = vertexes[4];
  3737. tScale = new Vector3(-AXscale.X, AXscale.Y, -AXscale.Z);
  3738. rScale = tScale * AXrot;
  3739. vertexes[5] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3740. // vertexes[5].X = pos.X + vertexes[5].X;
  3741. // vertexes[5].Y = pos.Y + vertexes[5].Y;
  3742. // vertexes[5].Z = pos.Z + vertexes[5].Z;
  3743. FaceD[1] = vertexes[5];
  3744. FaceC[2] = vertexes[5];
  3745. FaceB[5] = vertexes[5];
  3746. tScale = new Vector3(-AXscale.X, -AXscale.Y, AXscale.Z);
  3747. rScale = tScale * AXrot;
  3748. vertexes[6] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3749. // vertexes[6].X = pos.X + vertexes[6].X;
  3750. // vertexes[6].Y = pos.Y + vertexes[6].Y;
  3751. // vertexes[6].Z = pos.Z + vertexes[6].Z;
  3752. FaceB[2] = vertexes[6];
  3753. FaceA[3] = vertexes[6];
  3754. FaceB[4] = vertexes[6];
  3755. tScale = new Vector3(-AXscale.X, -AXscale.Y, -AXscale.Z);
  3756. rScale = tScale * AXrot;
  3757. vertexes[7] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  3758. // vertexes[7].X = pos.X + vertexes[7].X;
  3759. // vertexes[7].Y = pos.Y + vertexes[7].Y;
  3760. // vertexes[7].Z = pos.Z + vertexes[7].Z;
  3761. FaceD[2] = vertexes[7];
  3762. FaceC[3] = vertexes[7];
  3763. FaceD[5] = vertexes[7];
  3764. #endregion
  3765. // Get our plane normals
  3766. for (int i = 0; i < 6; i++)
  3767. {
  3768. //m_log.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]);
  3769. // Our Plane direction
  3770. AmBa = FaceA[i] - FaceB[i];
  3771. AmBb = FaceB[i] - FaceC[i];
  3772. cross = Vector3.Cross(AmBb, AmBa);
  3773. // normalize the cross product to get the normal.
  3774. normals[i] = cross / cross.Length();
  3775. //m_log.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString());
  3776. //distance[i] = (normals[i].X * AmBa.X + normals[i].Y * AmBa.Y + normals[i].Z * AmBa.Z) * -1;
  3777. }
  3778. EntityIntersection result = new EntityIntersection()
  3779. {
  3780. distance = 1024
  3781. };
  3782. float c = 0;
  3783. float a = 0;
  3784. float d = 0;
  3785. Vector3 q = new Vector3();
  3786. #region OBB Version 2 Experiment
  3787. //float fmin = 999999;
  3788. //float fmax = -999999;
  3789. //float s = 0;
  3790. //for (int i=0;i<6;i++)
  3791. //{
  3792. //s = iray.Direction.Dot(normals[i]);
  3793. //d = normals[i].Dot(FaceB[i]);
  3794. //if (s == 0)
  3795. //{
  3796. //if (iray.Origin.Dot(normals[i]) > d)
  3797. //{
  3798. //return result;
  3799. //}
  3800. // else
  3801. //{
  3802. //continue;
  3803. //}
  3804. //}
  3805. //a = (d - iray.Origin.Dot(normals[i])) / s;
  3806. //if (iray.Direction.Dot(normals[i]) < 0)
  3807. //{
  3808. //if (a > fmax)
  3809. //{
  3810. //if (a > fmin)
  3811. //{
  3812. //return result;
  3813. //}
  3814. //fmax = a;
  3815. //}
  3816. //}
  3817. //else
  3818. //{
  3819. //if (a < fmin)
  3820. //{
  3821. //if (a < 0 || a < fmax)
  3822. //{
  3823. //return result;
  3824. //}
  3825. //fmin = a;
  3826. //}
  3827. //}
  3828. //}
  3829. //if (fmax > 0)
  3830. // a= fmax;
  3831. //else
  3832. // a=fmin;
  3833. //q = iray.Origin + a * iray.Direction;
  3834. #endregion
  3835. // Loop over faces (6 of them)
  3836. for (int i = 0; i < 6; i++)
  3837. {
  3838. AmBa = FaceA[i] - FaceB[i];
  3839. AmBb = FaceB[i] - FaceC[i];
  3840. d = Vector3.Dot(normals[i], FaceB[i]);
  3841. //if (faceCenters)
  3842. //{
  3843. // c = normals[i].Dot(normals[i]);
  3844. //}
  3845. //else
  3846. //{
  3847. c = Vector3.Dot(iray.Direction, normals[i]);
  3848. //}
  3849. if (c == 0)
  3850. continue;
  3851. a = (d - Vector3.Dot(iray.Origin, normals[i])) / c;
  3852. if (a < 0)
  3853. continue;
  3854. // If the normal is pointing outside the object
  3855. if (Vector3.Dot(iray.Direction, normals[i]) < 0 || !frontFacesOnly)
  3856. {
  3857. //if (faceCenters)
  3858. //{ //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f;
  3859. // q = iray.Origin + a * normals[i];
  3860. //}
  3861. //else
  3862. //{
  3863. q = iray.Origin + iray.Direction * a;
  3864. //}
  3865. float distance2 = Vector3.Distance(q, AXpos);
  3866. // Is this the closest hit to the object's origin?
  3867. //if (faceCenters)
  3868. //{
  3869. // distance2 = (float)GetDistanceTo(q, iray.Origin);
  3870. //}
  3871. if (distance2 < result.distance)
  3872. {
  3873. result.distance = distance2;
  3874. result.HitTF = true;
  3875. result.ipoint = q;
  3876. result.face = i;
  3877. //m_log.Info("[FACE]:" + i.ToString());
  3878. //m_log.Info("[POINT]: " + q.ToString());
  3879. //m_log.Info("[DIST]: " + distance2.ToString());
  3880. if (faceCenters)
  3881. {
  3882. result.normal = AAfacenormals[i] * AXrot;
  3883. Vector3 scaleComponent = AAfacenormals[i];
  3884. float ScaleOffset = 0.5f;
  3885. if (scaleComponent.X != 0) ScaleOffset = AXscale.X;
  3886. if (scaleComponent.Y != 0) ScaleOffset = AXscale.Y;
  3887. if (scaleComponent.Z != 0) ScaleOffset = AXscale.Z;
  3888. ScaleOffset = Math.Abs(ScaleOffset);
  3889. Vector3 offset = result.normal * ScaleOffset;
  3890. result.ipoint = AXpos + offset;
  3891. ///pos = (intersectionpoint + offset);
  3892. }
  3893. else
  3894. {
  3895. result.normal = normals[i];
  3896. }
  3897. result.AAfaceNormal = AAfacenormals[i];
  3898. }
  3899. }
  3900. }
  3901. return result;
  3902. }
  3903. /// <summary>
  3904. /// Serialize this part to xml.
  3905. /// </summary>
  3906. /// <param name="xmlWriter"></param>
  3907. public void ToXml(XmlTextWriter xmlWriter)
  3908. {
  3909. SceneObjectSerializer.SOPToXml2(xmlWriter, this, new Dictionary<string, object>());
  3910. }
  3911. public void TriggerScriptChangedEvent(Changed val, object data = null)
  3912. {
  3913. //if (ParentGroup != null && ParentGroup.Scene != null && (ScriptEvents & scriptEvents.changed) != 0)
  3914. if ((ScriptEvents & scriptEvents.changed) != 0)
  3915. ParentGroup.Scene.EventManager.TriggerOnScriptChangedEvent(LocalId, (uint)val, data);
  3916. }
  3917. public void TrimPermissions()
  3918. {
  3919. BaseMask &= (uint)(PermissionMask.All | PermissionMask.Export);
  3920. OwnerMask &= (uint)(PermissionMask.All | PermissionMask.Export);
  3921. GroupMask &= (uint)PermissionMask.All;
  3922. EveryoneMask &= (uint)(PermissionMask.All | PermissionMask.Export);
  3923. NextOwnerMask &= (uint)PermissionMask.All;
  3924. }
  3925. public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
  3926. {
  3927. m_shape.ReadInUpdateExtraParam(type, inUse, data);
  3928. if (ParentGroup != null)
  3929. {
  3930. ParentGroup.HasGroupChanged = true;
  3931. ScheduleFullAnimUpdate();
  3932. }
  3933. }
  3934. public void UpdateGroupPosition(Vector3 newPos)
  3935. {
  3936. Vector3 oldPos = GroupPosition;
  3937. if ((newPos.X != oldPos.X) ||
  3938. (newPos.Y != oldPos.Y) ||
  3939. (newPos.Z != oldPos.Z))
  3940. {
  3941. GroupPosition = newPos;
  3942. ScheduleTerseUpdate();
  3943. }
  3944. }
  3945. /// <summary>
  3946. /// Update this part's offset position.
  3947. /// </summary>
  3948. /// <param name="pos"></param>
  3949. public void UpdateOffSet(Vector3 newPos)
  3950. {
  3951. Vector3 oldPos = OffsetPosition;
  3952. if ((newPos.X != oldPos.X) ||
  3953. (newPos.Y != oldPos.Y) ||
  3954. (newPos.Z != oldPos.Z))
  3955. {
  3956. if (ParentGroup.RootPart.GetStatusSandbox())
  3957. {
  3958. if (Vector3.DistanceSquared(ParentGroup.RootPart.StatusSandboxPos, newPos) > 100)
  3959. {
  3960. ParentGroup.RootPart.ScriptSetPhysicsStatus(false);
  3961. newPos = OffsetPosition;
  3962. ParentGroup.Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
  3963. ChatTypeEnum.DebugChannel, 0x7FFFFFFF, ParentGroup.RootPart.AbsolutePosition, Name, UUID, false);
  3964. }
  3965. }
  3966. OffsetPosition = newPos;
  3967. ScheduleTerseUpdate();
  3968. }
  3969. }
  3970. /// <summary>
  3971. /// Update permissions on the SOP. Should only be called from SOG.UpdatePermissions because the SOG
  3972. /// will handle the client notifications once all of its parts are updated.
  3973. /// </summary>
  3974. /// <param name="AgentID"></param>
  3975. /// <param name="field"></param>
  3976. /// <param name="localID"></param>
  3977. /// <param name="mask"></param>
  3978. /// <param name="addRemTF"></param>
  3979. public void UpdatePermissions(UUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
  3980. {
  3981. bool set = addRemTF == 1;
  3982. bool god = ParentGroup.Scene.Permissions.IsGod(AgentID);
  3983. uint baseMask = BaseMask;
  3984. if (god)
  3985. baseMask = 0x7ffffff0;
  3986. bool canChange = (AgentID == OwnerID) || god;
  3987. if(!canChange)
  3988. canChange = ParentGroup.Scene.Permissions.CanEditObjectPermissions(ParentGroup, AgentID);
  3989. if (canChange)
  3990. {
  3991. switch (field)
  3992. {
  3993. case 1:
  3994. if (god)
  3995. {
  3996. BaseMask = ApplyMask(BaseMask, set, mask);
  3997. Inventory.ApplyGodPermissions(BaseMask);
  3998. }
  3999. break;
  4000. case 2:
  4001. OwnerMask = ApplyMask(OwnerMask, set, mask) &
  4002. baseMask;
  4003. break;
  4004. case 4:
  4005. GroupMask = ApplyMask(GroupMask, set, mask) &
  4006. baseMask;
  4007. break;
  4008. case 8:
  4009. // Trying to set export permissions - extra checks
  4010. if (set && (mask & (uint)PermissionMask.Export) != 0)
  4011. {
  4012. if ((OwnerMask & (uint)PermissionMask.Export) == 0 || (BaseMask & (uint)PermissionMask.Export) == 0 || (NextOwnerMask & (uint)PermissionMask.All) != (uint)PermissionMask.All)
  4013. mask &= ~(uint)PermissionMask.Export;
  4014. }
  4015. EveryoneMask = ApplyMask(EveryoneMask, set, mask) &
  4016. baseMask;
  4017. break;
  4018. case 16:
  4019. // Force full perm if export
  4020. if ((EveryoneMask & (uint)PermissionMask.Export) != 0)
  4021. {
  4022. NextOwnerMask = (uint)PermissionMask.All;
  4023. break;
  4024. }
  4025. NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
  4026. baseMask;
  4027. // Prevent the client from creating no copy, no transfer
  4028. // objects
  4029. if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
  4030. NextOwnerMask |= (uint)PermissionMask.Transfer;
  4031. NextOwnerMask |= (uint)PermissionMask.Move;
  4032. break;
  4033. }
  4034. AggregateInnerPerms();
  4035. SendFullUpdateToAllClients();
  4036. }
  4037. }
  4038. public void ClonePermissions(SceneObjectPart source)
  4039. {
  4040. uint prevOwnerMask = OwnerMask;
  4041. uint prevGroupMask = GroupMask;
  4042. uint prevEveryoneMask = EveryoneMask;
  4043. uint prevNextOwnerMask = NextOwnerMask;
  4044. OwnerMask = source.OwnerMask & BaseMask;
  4045. GroupMask = source.GroupMask & BaseMask;
  4046. EveryoneMask = source.EveryoneMask & BaseMask;
  4047. NextOwnerMask = source.NextOwnerMask & BaseMask;
  4048. AggregateInnerPerms();
  4049. if (OwnerMask != prevOwnerMask || GroupMask != prevGroupMask ||
  4050. EveryoneMask != prevEveryoneMask || NextOwnerMask != prevNextOwnerMask)
  4051. SendFullUpdateToAllClients();
  4052. }
  4053. public bool IsHingeJoint()
  4054. {
  4055. // For now, we use the NINJA naming scheme for identifying joints.
  4056. // In the future, we can support other joint specification schemes such as a
  4057. // custom checkbox in the viewer GUI.
  4058. if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
  4059. {
  4060. string hingeString = "hingejoint";
  4061. return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString);
  4062. }
  4063. else
  4064. {
  4065. return false;
  4066. }
  4067. }
  4068. public bool IsBallJoint()
  4069. {
  4070. // For now, we use the NINJA naming scheme for identifying joints.
  4071. // In the future, we can support other joint specification schemes such as a
  4072. // custom checkbox in the viewer GUI.
  4073. if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
  4074. {
  4075. string ballString = "balljoint";
  4076. return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString);
  4077. }
  4078. else
  4079. {
  4080. return false;
  4081. }
  4082. }
  4083. public bool IsJoint()
  4084. {
  4085. // For now, we use the NINJA naming scheme for identifying joints.
  4086. // In the future, we can support other joint specification schemes such as a
  4087. // custom checkbox in the viewer GUI.
  4088. if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
  4089. {
  4090. return IsHingeJoint() || IsBallJoint();
  4091. }
  4092. else
  4093. {
  4094. return false;
  4095. }
  4096. }
  4097. public void UpdateExtraPhysics(ExtraPhysicsData physdata)
  4098. {
  4099. if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
  4100. return;
  4101. byte newtype = (byte)physdata.PhysShapeType;
  4102. if (PhysicsShapeType != newtype)
  4103. PhysicsShapeType = newtype;
  4104. if(Density != physdata.Density)
  4105. Density = physdata.Density;
  4106. if(GravityModifier != physdata.GravitationModifier)
  4107. GravityModifier = physdata.GravitationModifier;
  4108. if(Friction != physdata.Friction)
  4109. Friction = physdata.Friction;
  4110. if(Restitution != physdata.Bounce)
  4111. Restitution = physdata.Bounce;
  4112. }
  4113. /// <summary>
  4114. /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
  4115. /// </summary>
  4116. /// <param name="UsePhysics"></param>
  4117. /// <param name="SetTemporary"></param>
  4118. /// <param name="SetPhantom"></param>
  4119. /// <param name="SetVD"></param>
  4120. public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
  4121. {
  4122. bool wasUsingPhysics = ((m_flags & PrimFlags.Physics) != 0);
  4123. bool wasTemporary = ((m_flags & PrimFlags.TemporaryOnRez) != 0);
  4124. bool wasPhantom = ((m_flags & PrimFlags.Phantom) != 0);
  4125. bool wasVD = VolumeDetectActive;
  4126. if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
  4127. {
  4128. UpdatePhysicsSubscribedEvents();
  4129. return;
  4130. }
  4131. VolumeDetectActive = SetVD;
  4132. // volume detector implies phantom we need to decouple this mess
  4133. if (SetVD)
  4134. SetPhantom = true;
  4135. else if(wasVD)
  4136. SetPhantom = false;
  4137. if (UsePhysics)
  4138. AddFlag(PrimFlags.Physics);
  4139. else
  4140. RemFlag(PrimFlags.Physics);
  4141. if (SetPhantom)
  4142. AddFlag(PrimFlags.Phantom);
  4143. else
  4144. RemFlag(PrimFlags.Phantom);
  4145. if (SetTemporary)
  4146. AddFlag(PrimFlags.TemporaryOnRez);
  4147. else
  4148. RemFlag(PrimFlags.TemporaryOnRez);
  4149. if (ParentGroup.Scene == null)
  4150. return;
  4151. PhysicsActor pa = PhysActor;
  4152. if (pa != null && building && pa.Building != building)
  4153. pa.Building = building;
  4154. if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
  4155. || (Shape.PathCurve == (byte)Extrusion.Flexible))
  4156. {
  4157. Stop();
  4158. if (pa != null)
  4159. {
  4160. if(wasUsingPhysics)
  4161. ParentGroup.Scene.RemovePhysicalPrim(1);
  4162. RemoveFromPhysics();
  4163. }
  4164. }
  4165. else
  4166. {
  4167. if (ParentGroup.Scene.CollidablePrims)
  4168. {
  4169. if (pa == null)
  4170. {
  4171. AddToPhysics(UsePhysics, SetPhantom, building, false);
  4172. pa = PhysActor;
  4173. if (pa != null)
  4174. {
  4175. pa.SetMaterial(Material);
  4176. DoPhysicsPropertyUpdate(UsePhysics, true);
  4177. }
  4178. }
  4179. else // it already has a physical representation
  4180. {
  4181. DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
  4182. if(UsePhysics && !SetPhantom && m_localId == ParentGroup.RootPart.LocalId &&
  4183. m_vehicleParams != null && m_vehicleParams.CameraDecoupled)
  4184. AddFlag(PrimFlags.CameraDecoupled);
  4185. else
  4186. RemFlag(PrimFlags.CameraDecoupled);
  4187. if (pa.Building != building)
  4188. pa.Building = building;
  4189. }
  4190. UpdatePhysicsSubscribedEvents();
  4191. }
  4192. }
  4193. // and last in case we have a new actor and not building
  4194. if (ParentGroup != null)
  4195. {
  4196. ParentGroup.HasGroupChanged = true;
  4197. ScheduleFullUpdate();
  4198. }
  4199. // m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
  4200. }
  4201. /// <summary>
  4202. /// Adds this part to the physics scene.
  4203. /// and sets the PhysActor property
  4204. /// </summary>
  4205. /// <param name="isPhysical">Add this prim as physical.</param>
  4206. /// <param name="isPhantom">Add this prim as phantom.</param>
  4207. /// <param name="building">tells physics to delay full construction of object</param>
  4208. /// <param name="applyDynamics">applies velocities, force and torque</param>
  4209. private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
  4210. {
  4211. if (ParentGroup.Scene != null)
  4212. ClampScale(isPhysical);
  4213. PhysicsActor pa;
  4214. Vector3 velocity = Velocity;
  4215. Vector3 rotationalVelocity = AngularVelocity; ;
  4216. try
  4217. {
  4218. pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
  4219. string.Format("{0}/{1}", Name, UUID),
  4220. Shape,
  4221. AbsolutePosition,
  4222. Scale,
  4223. GetWorldRotation(),
  4224. isPhysical,
  4225. isPhantom,
  4226. PhysicsShapeType,
  4227. m_localId);
  4228. }
  4229. catch (Exception e)
  4230. {
  4231. m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
  4232. pa = null;
  4233. }
  4234. if (pa != null)
  4235. {
  4236. pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
  4237. pa.SetMaterial(Material);
  4238. pa.Density = Density;
  4239. pa.GravModifier = GravityModifier;
  4240. pa.Friction = Friction;
  4241. pa.Restitution = Restitution;
  4242. pa.Buoyancy = Buoyancy;
  4243. if(LocalId == ParentGroup.RootPart.LocalId)
  4244. {
  4245. pa.LockAngularMotion(RotationAxisLocks);
  4246. }
  4247. if (VolumeDetectActive) // change if not the default only
  4248. pa.SetVolumeDetect(1);
  4249. bool isroot = (m_localId == ParentGroup.RootPart.LocalId);
  4250. if(isroot && m_physicsInertia != null)
  4251. pa.SetInertiaData(m_physicsInertia);
  4252. if (isroot && m_vehicleParams != null )
  4253. {
  4254. m_vehicleParams.SetVehicle(pa);
  4255. if(isPhysical && !isPhantom && m_vehicleParams.CameraDecoupled)
  4256. AddFlag(PrimFlags.CameraDecoupled);
  4257. else
  4258. RemFlag(PrimFlags.CameraDecoupled);
  4259. }
  4260. else
  4261. RemFlag(PrimFlags.CameraDecoupled);
  4262. // we are going to tell rest of code about physics so better have this here
  4263. PhysActor = pa;
  4264. // DoPhysicsPropertyUpdate(isPhysical, true);
  4265. // lets expand it here just with what it really needs to do
  4266. if (isPhysical)
  4267. {
  4268. if (ParentGroup.RootPart.KeyframeMotion != null)
  4269. ParentGroup.RootPart.KeyframeMotion.Stop();
  4270. ParentGroup.RootPart.KeyframeMotion = null;
  4271. ParentGroup.Scene.AddPhysicalPrim(1);
  4272. pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
  4273. pa.OnOutOfBounds += PhysicsOutOfBounds;
  4274. if (_parentID != 0 && _parentID != LocalId)
  4275. {
  4276. PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
  4277. if (parentPa != null)
  4278. {
  4279. pa.link(parentPa);
  4280. }
  4281. }
  4282. }
  4283. if (applyDynamics && LocalId == ParentGroup.RootPart.LocalId)
  4284. // do independent of isphysical so parameters get setted (at least some)
  4285. {
  4286. Velocity = velocity;
  4287. AngularVelocity = rotationalVelocity;
  4288. // if not vehicle and root part apply force and torque
  4289. if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE))
  4290. {
  4291. pa.Force = Force;
  4292. pa.Torque = Torque;
  4293. }
  4294. }
  4295. // if (Shape.SculptEntry)
  4296. // CheckSculptAndLoad();
  4297. // else
  4298. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
  4299. if (!building)
  4300. pa.Building = false;
  4301. }
  4302. PhysActor = pa;
  4303. ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
  4304. }
  4305. /// <summary>
  4306. /// This removes the part from the physics scene.
  4307. /// </summary>
  4308. /// <remarks>
  4309. /// This isn't the same as turning off physical, since even without being physical the prim has a physics
  4310. /// representation for collision detection.
  4311. /// </remarks>
  4312. public void RemoveFromPhysics()
  4313. {
  4314. PhysicsActor pa = PhysActor;
  4315. if (pa != null)
  4316. {
  4317. pa.OnCollisionUpdate -= PhysicsCollision;
  4318. pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
  4319. pa.OnOutOfBounds -= PhysicsOutOfBounds;
  4320. ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
  4321. ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
  4322. }
  4323. RemFlag(PrimFlags.CameraDecoupled);
  4324. PhysActor = null;
  4325. }
  4326. /// <summary>
  4327. /// This updates the part's rotation and sends out an update to clients if necessary.
  4328. /// </summary>
  4329. /// <param name="rot"></param>
  4330. public void UpdateRotation(Quaternion rot)
  4331. {
  4332. if (rot != RotationOffset)
  4333. {
  4334. RotationOffset = rot;
  4335. if (ParentGroup != null)
  4336. {
  4337. ParentGroup.HasGroupChanged = true;
  4338. ScheduleTerseUpdate();
  4339. }
  4340. }
  4341. }
  4342. /// <summary>
  4343. /// Update the shape of this part.
  4344. /// </summary>
  4345. /// <param name="shapeBlock"></param>
  4346. public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock)
  4347. {
  4348. m_shape.PathBegin = shapeBlock.PathBegin;
  4349. m_shape.PathEnd = shapeBlock.PathEnd;
  4350. m_shape.PathScaleX = shapeBlock.PathScaleX;
  4351. m_shape.PathScaleY = shapeBlock.PathScaleY;
  4352. m_shape.PathShearX = shapeBlock.PathShearX;
  4353. m_shape.PathShearY = shapeBlock.PathShearY;
  4354. m_shape.PathSkew = shapeBlock.PathSkew;
  4355. m_shape.ProfileBegin = shapeBlock.ProfileBegin;
  4356. m_shape.ProfileEnd = shapeBlock.ProfileEnd;
  4357. m_shape.PathCurve = shapeBlock.PathCurve;
  4358. m_shape.ProfileCurve = shapeBlock.ProfileCurve;
  4359. m_shape.ProfileHollow = shapeBlock.ProfileHollow;
  4360. m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset;
  4361. m_shape.PathRevolutions = shapeBlock.PathRevolutions;
  4362. m_shape.PathTaperX = shapeBlock.PathTaperX;
  4363. m_shape.PathTaperY = shapeBlock.PathTaperY;
  4364. m_shape.PathTwist = shapeBlock.PathTwist;
  4365. m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
  4366. PhysicsActor pa = PhysActor;
  4367. if (pa != null)
  4368. {
  4369. pa.Shape = m_shape;
  4370. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
  4371. }
  4372. // This is what makes vehicle trailers work
  4373. // A script in a child prim re-issues
  4374. // llSetPrimitiveParams(PRIM_TYPE) every few seconds. That
  4375. // prevents autoreturn. This is not well known. It also works
  4376. // in SL.
  4377. //
  4378. if (ParentGroup.RootPart != this)
  4379. ParentGroup.RootPart.Rezzed = DateTime.UtcNow;
  4380. ParentGroup.HasGroupChanged = true;
  4381. TriggerScriptChangedEvent(Changed.SHAPE);
  4382. ScheduleFullUpdate();
  4383. }
  4384. public void UpdateSlice(float begin, float end)
  4385. {
  4386. if (end < begin)
  4387. {
  4388. float temp = begin;
  4389. begin = end;
  4390. end = temp;
  4391. }
  4392. end = Math.Min(1f, Math.Max(0f, end));
  4393. begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f);
  4394. if (begin < 0.02f && end < 0.02f)
  4395. {
  4396. begin = 0f;
  4397. end = 0.02f;
  4398. }
  4399. ushort uBegin = (ushort)(50000.0 * begin);
  4400. ushort uEnd = (ushort)(50000.0 * (1f - end));
  4401. bool updatePossiblyNeeded = false;
  4402. PrimType primType = GetPrimType();
  4403. if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING)
  4404. {
  4405. if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd)
  4406. {
  4407. m_shape.ProfileBegin = uBegin;
  4408. m_shape.ProfileEnd = uEnd;
  4409. updatePossiblyNeeded = true;
  4410. }
  4411. }
  4412. else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd)
  4413. {
  4414. m_shape.PathBegin = uBegin;
  4415. m_shape.PathEnd = uEnd;
  4416. updatePossiblyNeeded = true;
  4417. }
  4418. if (updatePossiblyNeeded && ParentGroup != null)
  4419. {
  4420. ParentGroup.HasGroupChanged = true;
  4421. }
  4422. if (updatePossiblyNeeded && PhysActor != null)
  4423. {
  4424. PhysActor.Shape = m_shape;
  4425. ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
  4426. }
  4427. if (updatePossiblyNeeded)
  4428. {
  4429. ScheduleFullUpdate();
  4430. }
  4431. }
  4432. /// <summary>
  4433. /// Update the texture entry for this part.
  4434. /// </summary>
  4435. /// <param name="serializedTextureEntry"></param>
  4436. public void UpdateTextureEntry(byte[] serializedTextureEntry)
  4437. {
  4438. Primitive.TextureEntry newTex = new Primitive.TextureEntry(serializedTextureEntry, 0, serializedTextureEntry.Length);
  4439. Primitive.TextureEntry oldTex = Shape.Textures;
  4440. Changed changeFlags = 0;
  4441. Primitive.TextureEntryFace defaultNewFace = newTex.DefaultTexture;
  4442. Primitive.TextureEntryFace defaultOldFace = oldTex.DefaultTexture;
  4443. // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all
  4444. // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point.
  4445. if (defaultNewFace == null)
  4446. {
  4447. defaultNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
  4448. newTex.DefaultTexture = defaultNewFace;
  4449. }
  4450. if (defaultOldFace == null)
  4451. {
  4452. defaultOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
  4453. oldTex.DefaultTexture = defaultOldFace;
  4454. }
  4455. // Materials capable viewers can send a ObjectImage packet
  4456. // when nothing in TE has changed. MaterialID should be updated
  4457. // by the RenderMaterials CAP handler, so updating it here may cause a
  4458. // race condtion. Therefore, if no non-materials TE fields have not changed,
  4459. // we should ignore any changes and not update Shape.TextureEntry
  4460. bool otherFieldsChanged = false;
  4461. int nsides = GetNumberOfSides();
  4462. for (int i = 0; i < nsides; i++)
  4463. {
  4464. Primitive.TextureEntryFace newFace = defaultNewFace;
  4465. Primitive.TextureEntryFace oldFace = defaultOldFace;
  4466. if (oldTex.FaceTextures[i] != null)
  4467. oldFace = oldTex.FaceTextures[i];
  4468. if (newTex.FaceTextures[i] != null)
  4469. newFace = newTex.FaceTextures[i];
  4470. if (oldFace.TextureID != newFace.TextureID)
  4471. changeFlags |= Changed.TEXTURE;
  4472. Color4 oldRGBA = oldFace.RGBA;
  4473. Color4 newRGBA = newFace.RGBA;
  4474. if (oldRGBA.R != newRGBA.R ||
  4475. oldRGBA.G != newRGBA.G ||
  4476. oldRGBA.B != newRGBA.B ||
  4477. oldRGBA.A != newRGBA.A)
  4478. changeFlags |= Changed.COLOR;
  4479. // Max change, skip the rest of testing
  4480. if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
  4481. break;
  4482. if (!otherFieldsChanged)
  4483. {
  4484. if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
  4485. if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
  4486. if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
  4487. if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
  4488. if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
  4489. if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
  4490. if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
  4491. if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
  4492. if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
  4493. if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
  4494. if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
  4495. if (otherFieldsChanged)
  4496. changeFlags |= Changed.TEXTURE;
  4497. }
  4498. }
  4499. if (changeFlags == 0)
  4500. return;
  4501. // we do need better compacter do just the trivial case
  4502. if(nsides == 1 && newTex.FaceTextures[0] != null)
  4503. {
  4504. newTex.DefaultTexture = newTex.GetFace(0);
  4505. newTex.FaceTextures[0] = null;
  4506. }
  4507. m_shape.TextureEntry = newTex.GetBytes(nsides);
  4508. TriggerScriptChangedEvent(changeFlags);
  4509. ParentGroup.HasGroupChanged = true;
  4510. ScheduleUpdate(PrimUpdateFlags.Textures);
  4511. }
  4512. /// <summary>
  4513. /// Update the texture entry for this part.
  4514. /// </summary>
  4515. /// <param name="newTex"></param>
  4516. public void UpdateTextureEntry(Primitive.TextureEntry newTex)
  4517. {
  4518. TextureAttributes dirty = newTex.GetDirtyFlags(32, true);
  4519. dirty &= ~TextureAttributes.MaterialID;
  4520. if(dirty == TextureAttributes.None)
  4521. return;
  4522. Changed changeFlags = 0;
  4523. if((dirty & TextureAttributes.RGBA) != 0)
  4524. {
  4525. changeFlags = Changed.COLOR;
  4526. dirty &= ~TextureAttributes.RGBA;
  4527. }
  4528. if (dirty != TextureAttributes.None)
  4529. changeFlags |= Changed.TEXTURE;
  4530. if (changeFlags == 0)
  4531. return;
  4532. m_shape.TextureEntry = newTex.GetBytes(9);
  4533. TriggerScriptChangedEvent(changeFlags);
  4534. ParentGroup.HasGroupChanged = true;
  4535. ScheduleUpdate(PrimUpdateFlags.Textures);
  4536. }
  4537. internal void UpdatePhysicsSubscribedEvents()
  4538. {
  4539. PhysicsActor pa = PhysActor;
  4540. if (pa == null)
  4541. return;
  4542. pa.OnCollisionUpdate -= PhysicsCollision;
  4543. bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((m_flags & PrimFlags.Physics) != 0));
  4544. scriptEvents CombinedEvents = AggregatedScriptEvents;
  4545. // merge with root part
  4546. if (ParentGroup != null && ParentGroup.RootPart != null)
  4547. CombinedEvents |= ParentGroup.RootPart.AggregatedScriptEvents;
  4548. // submit to this part case
  4549. if (VolumeDetectActive)
  4550. CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
  4551. else if ((m_flags & PrimFlags.Phantom) != 0)
  4552. CombinedEvents &= PhyscicsPhantonSubsEvents;
  4553. else
  4554. CombinedEvents &= PhysicsNeededSubsEvents;
  4555. if (hassound || CombinedEvents != 0)
  4556. {
  4557. // subscribe to physics updates.
  4558. pa.OnCollisionUpdate += PhysicsCollision;
  4559. pa.SubscribeEvents(50); // 20 reports per second
  4560. }
  4561. else
  4562. {
  4563. pa.UnSubscribeEvents();
  4564. }
  4565. }
  4566. public void aggregateScriptEvents()
  4567. {
  4568. if (ParentGroup == null || ParentGroup.RootPart == null)
  4569. return;
  4570. AggregatedScriptEvents = 0;
  4571. // Aggregate script events
  4572. lock (m_scriptEvents)
  4573. {
  4574. foreach (scriptEvents s in m_scriptEvents.Values)
  4575. {
  4576. AggregatedScriptEvents |= s;
  4577. }
  4578. }
  4579. uint objectflagupdate = 0;
  4580. if ((AggregatedScriptEvents & scriptEvents.anytouch) != 0 )
  4581. {
  4582. objectflagupdate |= (uint) PrimFlags.Touch;
  4583. }
  4584. if ((AggregatedScriptEvents & scriptEvents.money) != 0)
  4585. {
  4586. objectflagupdate |= (uint) PrimFlags.Money;
  4587. }
  4588. if (AllowedDrop)
  4589. {
  4590. objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
  4591. }
  4592. m_localFlags = (PrimFlags)objectflagupdate;
  4593. if (ParentGroup != null && ParentGroup.RootPart == this)
  4594. {
  4595. ParentGroup.aggregateScriptEvents();
  4596. }
  4597. else
  4598. {
  4599. // m_log.DebugFormat(
  4600. // "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
  4601. UpdatePhysicsSubscribedEvents();
  4602. ScheduleFullUpdate();
  4603. }
  4604. }
  4605. public void SetCameraAtOffset(Vector3 v)
  4606. {
  4607. m_cameraAtOffset = v;
  4608. }
  4609. public void SetCameraEyeOffset(Vector3 v)
  4610. {
  4611. m_cameraEyeOffset = v;
  4612. }
  4613. public void SetForceMouselook(bool force)
  4614. {
  4615. m_forceMouselook = force;
  4616. }
  4617. public Vector3 GetCameraAtOffset()
  4618. {
  4619. return m_cameraAtOffset;
  4620. }
  4621. public Vector3 GetCameraEyeOffset()
  4622. {
  4623. return m_cameraEyeOffset;
  4624. }
  4625. public bool GetForceMouselook()
  4626. {
  4627. return m_forceMouselook;
  4628. }
  4629. public override string ToString()
  4630. {
  4631. return String.Format("{0} {1} (parent {2}))", Name, UUID, ParentGroup);
  4632. }
  4633. #endregion Public Methods
  4634. public void SendUpdateToClient(IClientAPI remoteClient, PrimUpdateFlags update)
  4635. {
  4636. if (ParentGroup.IsDeleted || !remoteClient.IsActive)
  4637. return;
  4638. if (Animations == null)
  4639. {
  4640. update &= ~PrimUpdateFlags.Animations;
  4641. if (update == PrimUpdateFlags.None)
  4642. return;
  4643. }
  4644. if (ParentGroup.IsAttachment &&
  4645. (ParentGroup.RootPart != this || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint))
  4646. return;
  4647. remoteClient.SendEntityUpdate(this, update);
  4648. ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
  4649. }
  4650. public void SendTerseUpdateToClient(IClientAPI remoteClient)
  4651. {
  4652. if (ParentGroup.IsDeleted)
  4653. return;
  4654. if (ParentGroup.IsAttachment
  4655. && (ParentGroup.RootPart != this
  4656. || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint))
  4657. return;
  4658. // Causes this thread to dig into the Client Thread Data.
  4659. // Remember your locking here!
  4660. remoteClient.SendEntityUpdate(this, PrimUpdateFlags.TerseUpdate);
  4661. ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
  4662. }
  4663. public void AddScriptLPS(int count)
  4664. {
  4665. ParentGroup.AddScriptLPS(count);
  4666. }
  4667. /// <summary>
  4668. /// Sets a prim's owner and permissions when it's rezzed.
  4669. /// </summary>
  4670. /// <param name="item">The inventory item from which the item was rezzed</param>
  4671. /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
  4672. /// <param name="scene">The scene the prim is being rezzed into</param>
  4673. public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
  4674. {
  4675. if ((OwnerID != item.Owner) || ((item.CurrentPermissions & (uint)PermissionMask.Slam) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
  4676. {
  4677. if (scene.Permissions.PropagatePermissions())
  4678. {
  4679. if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
  4680. {
  4681. // Apply the item's permissions to the object
  4682. //LogPermissions("Before applying item permissions");
  4683. if (userInventory)
  4684. {
  4685. EveryoneMask = item.EveryOnePermissions;
  4686. NextOwnerMask = item.NextPermissions;
  4687. }
  4688. else
  4689. {
  4690. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  4691. EveryoneMask = item.EveryOnePermissions;
  4692. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  4693. NextOwnerMask = item.NextPermissions;
  4694. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  4695. GroupMask = item.GroupPermissions;
  4696. }
  4697. //LogPermissions("After applying item permissions");
  4698. }
  4699. }
  4700. GroupMask = 0; // DO NOT propagate here
  4701. }
  4702. if (OwnerID != item.Owner)
  4703. {
  4704. if(OwnerID != GroupID)
  4705. LastOwnerID = OwnerID;
  4706. OwnerID = item.Owner;
  4707. Inventory.ChangeInventoryOwner(item.Owner);
  4708. if (scene.Permissions.PropagatePermissions())
  4709. ApplyNextOwnerPermissions();
  4710. }
  4711. }
  4712. /// <summary>
  4713. /// Logs the prim's permissions. Useful when debugging permission problems.
  4714. /// </summary>
  4715. /// <param name="message"></param>
  4716. private void LogPermissions(String message)
  4717. {
  4718. PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
  4719. }
  4720. public void ApplyNextOwnerPermissions()
  4721. {
  4722. // Export needs to be preserved in the base and everyone
  4723. // mask, but removed in the owner mask as a next owner
  4724. // can never change the export status
  4725. BaseMask &= (NextOwnerMask | (uint)PermissionMask.Export);
  4726. OwnerMask &= NextOwnerMask;
  4727. EveryoneMask &= (NextOwnerMask | (uint)PermissionMask.Export);
  4728. GroupMask = 0; // Giving an object zaps group permissions
  4729. Inventory.ApplyNextOwnerPermissions();
  4730. AggregateInnerPerms();
  4731. }
  4732. public void UpdateLookAt()
  4733. {
  4734. try
  4735. {
  4736. if (APIDActive)
  4737. {
  4738. PhysicsActor pa = ParentGroup.RootPart.PhysActor;
  4739. if (pa == null || !pa.IsPhysical || APIDStrength < 0.04)
  4740. {
  4741. StopLookAt();
  4742. return;
  4743. }
  4744. Quaternion currRot = GetWorldRotation();
  4745. currRot.Normalize();
  4746. // difference between current orientation and desired orientation
  4747. Quaternion dR = currRot / APIDTarget;
  4748. // find axis and angle of rotation to rotate to desired orientation
  4749. dR.GetAxisAngle(out Vector3 axis, out float angle);
  4750. axis = axis * currRot;
  4751. // clamp strength to avoid overshoot
  4752. float strength = 1.0f / APIDStrength;
  4753. if (strength > 1.0) strength = 1.0f;
  4754. // set angular velocity to rotate to desired orientation
  4755. // with velocity proportional to strength and angle
  4756. AngularVelocity = axis * angle * strength * (float)Math.PI;
  4757. // This ensures that we'll check this object on the next iteration
  4758. ParentGroup.QueueForUpdateCheck();
  4759. }
  4760. }
  4761. catch (Exception ex)
  4762. {
  4763. m_log.Error("[Physics] " + ex);
  4764. }
  4765. }
  4766. public Color4 GetTextColor()
  4767. {
  4768. Color color = Color;
  4769. return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
  4770. }
  4771. public void ResetOwnerChangeFlag()
  4772. {
  4773. List<UUID> inv = Inventory.GetInventoryList();
  4774. foreach (UUID itemID in inv)
  4775. {
  4776. TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
  4777. item.OwnerChanged = false;
  4778. Inventory.UpdateInventoryItem(item, false, false);
  4779. }
  4780. AggregateInnerPerms();
  4781. }
  4782. /// <summary>
  4783. /// Record an avatar sitting on this part.
  4784. /// </summary>
  4785. /// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks>
  4786. /// <returns>
  4787. /// true if the avatar was not already recorded, false otherwise.
  4788. /// </returns>
  4789. /// <param name='avatarId'></param>
  4790. protected internal bool AddSittingAvatar(ScenePresence sp)
  4791. {
  4792. lock (ParentGroup.m_sittingAvatars)
  4793. {
  4794. if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
  4795. SitTargetAvatar = sp.UUID;
  4796. if (m_sittingAvatars == null)
  4797. m_sittingAvatars = new HashSet<ScenePresence>();
  4798. if (m_sittingAvatars.Add(sp))
  4799. {
  4800. if(!ParentGroup.m_sittingAvatars.Contains(sp))
  4801. ParentGroup.m_sittingAvatars.Add(sp);
  4802. return true;
  4803. }
  4804. return false;
  4805. }
  4806. }
  4807. /// <summary>
  4808. /// Remove an avatar recorded as sitting on this part.
  4809. /// </summary>
  4810. /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
  4811. /// <returns>
  4812. /// true if the avatar was present and removed, false if it was not present.
  4813. /// </returns>
  4814. /// <param name='avatarId'></param>
  4815. protected internal bool RemoveSittingAvatar(ScenePresence sp)
  4816. {
  4817. lock (ParentGroup.m_sittingAvatars)
  4818. {
  4819. if (SitTargetAvatar == sp.UUID)
  4820. SitTargetAvatar = UUID.Zero;
  4821. if (m_sittingAvatars == null)
  4822. return false;
  4823. if (m_sittingAvatars.Remove(sp))
  4824. {
  4825. if (m_sittingAvatars.Count == 0)
  4826. m_sittingAvatars = null;
  4827. if(ParentGroup.m_sittingAvatars.Remove(sp))
  4828. ParentGroup.InvalidatePartsLinkMaps(false);
  4829. return true;
  4830. }
  4831. return false;
  4832. }
  4833. }
  4834. /// <summary>
  4835. /// Get a copy of the list of sitting avatars.
  4836. /// </summary>
  4837. /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
  4838. /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
  4839. public HashSet<ScenePresence> GetSittingAvatars()
  4840. {
  4841. lock (ParentGroup.m_sittingAvatars)
  4842. {
  4843. if (m_sittingAvatars == null)
  4844. return null;
  4845. else
  4846. return new HashSet<ScenePresence>(m_sittingAvatars);
  4847. }
  4848. }
  4849. /// <summary>
  4850. /// Gets the number of sitting avatars.
  4851. /// </summary>
  4852. /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
  4853. /// <returns></returns>
  4854. public int GetSittingAvatarsCount()
  4855. {
  4856. lock (ParentGroup.m_sittingAvatars)
  4857. {
  4858. if (m_sittingAvatars == null)
  4859. return 0;
  4860. else
  4861. return m_sittingAvatars.Count;
  4862. }
  4863. }
  4864. public void Stop()
  4865. {
  4866. Velocity = Vector3.Zero;
  4867. AngularVelocity = Vector3.Zero;
  4868. Acceleration = Vector3.Zero;
  4869. APIDActive = false;
  4870. }
  4871. // handle osVolumeDetect
  4872. public void ScriptSetVolumeDetect(bool makeVolumeDetect)
  4873. {
  4874. if(ParentGroup.IsDeleted)
  4875. return;
  4876. if(_parentID == 0)
  4877. {
  4878. // if root prim do it is like llVolumeDetect
  4879. ParentGroup.ScriptSetVolumeDetect(makeVolumeDetect);
  4880. return;
  4881. }
  4882. if(ParentGroup.IsVolumeDetect)
  4883. return; // entire linkset is phantom already
  4884. bool wasUsingPhysics = ParentGroup.UsesPhysics;
  4885. bool wasTemporary = ParentGroup.IsTemporary;
  4886. bool wasPhantom = ParentGroup.IsPhantom;
  4887. if(PhysActor != null)
  4888. PhysActor.Building = true;
  4889. UpdatePrimFlags(wasUsingPhysics, wasTemporary, wasPhantom, makeVolumeDetect, false);
  4890. }
  4891. protected static int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL);
  4892. public static int NextObjectAnimationSequenceNumber
  4893. {
  4894. get
  4895. {
  4896. int ret = Interlocked.Increment(ref m_animationSequenceNumber);
  4897. if (ret <= 0)
  4898. {
  4899. m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0xafff5fL);
  4900. ret = Interlocked.Increment(ref m_animationSequenceNumber);
  4901. }
  4902. return ret;
  4903. }
  4904. }
  4905. private readonly object animsLock = new object();
  4906. public Dictionary<UUID, int> Animations = null;
  4907. public Dictionary<UUID, string> AnimationsNames = null;
  4908. public bool AddAnimation(UUID animId, string animName)
  4909. {
  4910. if (animId == UUID.Zero || string.IsNullOrEmpty(animName) ||
  4911. ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  4912. return false;
  4913. lock (animsLock)
  4914. {
  4915. if (Animations == null)
  4916. Animations = new Dictionary<UUID, int>(1);
  4917. if (AnimationsNames == null)
  4918. AnimationsNames = new Dictionary<UUID, string>(1);
  4919. if (Animations.ContainsKey(animId))
  4920. return false;
  4921. Animations[animId] = NextObjectAnimationSequenceNumber;
  4922. AnimationsNames[animId] = animName;
  4923. ScheduleUpdate(PrimUpdateFlags.Animations);
  4924. }
  4925. return true;
  4926. }
  4927. public bool RemoveAnimation(UUID animId)
  4928. {
  4929. if (animId == UUID.Zero || ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  4930. return false;
  4931. lock (animsLock)
  4932. {
  4933. if (Animations == null)
  4934. return false;
  4935. if (Animations.ContainsKey(animId))
  4936. {
  4937. Animations.Remove(animId);
  4938. if(AnimationsNames!=null)
  4939. AnimationsNames.Remove(animId);
  4940. ScheduleUpdate(PrimUpdateFlags.Animations);
  4941. return true;
  4942. }
  4943. }
  4944. return false;
  4945. }
  4946. public int ClearObjectAnimations()
  4947. {
  4948. int ret = 0;
  4949. if(Animations != null)
  4950. {
  4951. ret = Animations.Count;
  4952. Animations.Clear();
  4953. AnimationsNames.Clear();
  4954. }
  4955. else
  4956. {
  4957. Animations = new Dictionary<UUID, int>();
  4958. AnimationsNames = new Dictionary<UUID, string>();
  4959. }
  4960. ScheduleUpdate(PrimUpdateFlags.Animations);
  4961. return ret;
  4962. }
  4963. public int GetAnimations(out UUID[] ids, out int[] seqs)
  4964. {
  4965. ids = null;
  4966. seqs = null;
  4967. if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
  4968. return -1;
  4969. lock (animsLock)
  4970. {
  4971. if (Animations == null)
  4972. return -1;
  4973. if(Animations.Count == 0)
  4974. return 0;
  4975. ids = new UUID[Animations.Count];
  4976. Animations.Keys.CopyTo(ids, 0);
  4977. seqs = new int[Animations.Count];
  4978. Animations.Values.CopyTo(seqs, 0);
  4979. return Animations.Count;
  4980. }
  4981. }
  4982. public Byte[] SerializeAnimations()
  4983. {
  4984. if (AnimationsNames == null)
  4985. return null;
  4986. lock (animsLock)
  4987. {
  4988. if (AnimationsNames.Count == 0)
  4989. return new byte[] { 0 };
  4990. using (MemoryStream ms = new MemoryStream())
  4991. {
  4992. byte[] tmp = Utils.UInt16ToBytes((ushort)Animations.Count);
  4993. ms.Write(tmp, 0, 2);
  4994. foreach(KeyValuePair<UUID,string> kvp in AnimationsNames)
  4995. {
  4996. tmp = kvp.Key.GetBytes();
  4997. ms.Write(tmp, 0, 16);
  4998. if(string.IsNullOrEmpty(kvp.Value))
  4999. ms.WriteByte(0);
  5000. else
  5001. {
  5002. byte[] str = Util.StringToBytes(kvp.Value, 64);
  5003. int len = str.Length - 1;
  5004. ms.WriteByte((byte)len);
  5005. ms.Write(str, 0 , len);
  5006. }
  5007. }
  5008. return ms.ToArray();
  5009. }
  5010. }
  5011. }
  5012. public void DeSerializeAnimations(Byte[] data)
  5013. {
  5014. if(data == null)
  5015. {
  5016. Animations = null;
  5017. AnimationsNames = null;
  5018. return;
  5019. }
  5020. if (data.Length < 2)
  5021. {
  5022. Animations = new Dictionary<UUID, int>();
  5023. AnimationsNames = new Dictionary<UUID, string>();
  5024. return;
  5025. }
  5026. try
  5027. {
  5028. int count = (int)Utils.BytesToUInt16(data, 0);
  5029. if(count == 0)
  5030. return;
  5031. Animations = new Dictionary<UUID, int>(count);
  5032. AnimationsNames = new Dictionary<UUID, string>(count);
  5033. int pos = 2;
  5034. while(--count >= 0)
  5035. {
  5036. UUID id = new UUID(data, pos);
  5037. if(id == UUID.Zero)
  5038. break;
  5039. pos += 16;
  5040. int strlen = data[pos++];
  5041. string name = UTF8Encoding.UTF8.GetString(data, pos, strlen);
  5042. if(string.IsNullOrEmpty(name))
  5043. break;
  5044. pos += strlen;
  5045. Animations[id] = NextObjectAnimationSequenceNumber;
  5046. AnimationsNames[id] = name;
  5047. }
  5048. return;
  5049. }
  5050. catch { }
  5051. Animations = null;
  5052. AnimationsNames = null;
  5053. }
  5054. }
  5055. }