canvas_item_editor_plugin.cpp 248 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452
  1. /*************************************************************************/
  2. /* canvas_item_editor_plugin.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "canvas_item_editor_plugin.h"
  31. #include "core/os/input.h"
  32. #include "core/os/keyboard.h"
  33. #include "core/print_string.h"
  34. #include "core/project_settings.h"
  35. #include "editor/editor_node.h"
  36. #include "editor/editor_scale.h"
  37. #include "editor/editor_settings.h"
  38. #include "editor/plugins/animation_player_editor_plugin.h"
  39. #include "editor/plugins/script_editor_plugin.h"
  40. #include "editor/script_editor_debugger.h"
  41. #include "scene/2d/light_2d.h"
  42. #include "scene/2d/particles_2d.h"
  43. #include "scene/2d/polygon_2d.h"
  44. #include "scene/2d/skeleton_2d.h"
  45. #include "scene/2d/sprite.h"
  46. #include "scene/2d/touch_screen_button.h"
  47. #include "scene/gui/grid_container.h"
  48. #include "scene/gui/nine_patch_rect.h"
  49. #include "scene/gui/viewport_container.h"
  50. #include "scene/main/canvas_layer.h"
  51. #include "scene/main/viewport.h"
  52. #include "scene/resources/dynamic_font.h"
  53. #include "scene/resources/packed_scene.h"
  54. #include <stdlib.h>
  55. // Min and Max are power of two in order to play nicely with successive increment.
  56. // That way, we can naturally reach a 100% zoom from boundaries.
  57. #define MIN_ZOOM 1. / 128
  58. #define MAX_ZOOM 128
  59. #define RULER_WIDTH (15 * EDSCALE)
  60. #define SCALE_HANDLE_DISTANCE 25
  61. class SnapDialog : public ConfirmationDialog {
  62. GDCLASS(SnapDialog, ConfirmationDialog);
  63. friend class CanvasItemEditor;
  64. SpinBox *grid_offset_x;
  65. SpinBox *grid_offset_y;
  66. SpinBox *grid_step_x;
  67. SpinBox *grid_step_y;
  68. SpinBox *primary_grid_steps;
  69. SpinBox *rotation_offset;
  70. SpinBox *rotation_step;
  71. SpinBox *scale_step;
  72. public:
  73. SnapDialog() {
  74. const int SPIN_BOX_GRID_RANGE = 16384;
  75. const int SPIN_BOX_ROTATION_RANGE = 360;
  76. const float SPIN_BOX_SCALE_MIN = 0.01f;
  77. const float SPIN_BOX_SCALE_MAX = 100;
  78. Label *label;
  79. VBoxContainer *container;
  80. GridContainer *child_container;
  81. set_title(TTR("Configure Snap"));
  82. container = memnew(VBoxContainer);
  83. add_child(container);
  84. child_container = memnew(GridContainer);
  85. child_container->set_columns(3);
  86. container->add_child(child_container);
  87. label = memnew(Label);
  88. label->set_text(TTR("Grid Offset:"));
  89. child_container->add_child(label);
  90. label->set_h_size_flags(SIZE_EXPAND_FILL);
  91. grid_offset_x = memnew(SpinBox);
  92. grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
  93. grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
  94. grid_offset_x->set_allow_lesser(true);
  95. grid_offset_x->set_allow_greater(true);
  96. grid_offset_x->set_suffix("px");
  97. grid_offset_x->set_h_size_flags(SIZE_EXPAND_FILL);
  98. child_container->add_child(grid_offset_x);
  99. grid_offset_y = memnew(SpinBox);
  100. grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
  101. grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
  102. grid_offset_y->set_allow_lesser(true);
  103. grid_offset_y->set_allow_greater(true);
  104. grid_offset_y->set_suffix("px");
  105. grid_offset_y->set_h_size_flags(SIZE_EXPAND_FILL);
  106. child_container->add_child(grid_offset_y);
  107. label = memnew(Label);
  108. label->set_text(TTR("Grid Step:"));
  109. child_container->add_child(label);
  110. label->set_h_size_flags(SIZE_EXPAND_FILL);
  111. grid_step_x = memnew(SpinBox);
  112. grid_step_x->set_min(0.01);
  113. grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
  114. grid_step_x->set_allow_greater(true);
  115. grid_step_x->set_suffix("px");
  116. grid_step_x->set_h_size_flags(SIZE_EXPAND_FILL);
  117. child_container->add_child(grid_step_x);
  118. grid_step_y = memnew(SpinBox);
  119. grid_step_y->set_min(0.01);
  120. grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
  121. grid_step_y->set_allow_greater(true);
  122. grid_step_y->set_suffix("px");
  123. grid_step_y->set_h_size_flags(SIZE_EXPAND_FILL);
  124. child_container->add_child(grid_step_y);
  125. child_container = memnew(GridContainer);
  126. child_container->set_columns(2);
  127. container->add_child(child_container);
  128. label = memnew(Label);
  129. label->set_text(TTR("Primary Line Every:"));
  130. label->set_h_size_flags(SIZE_EXPAND_FILL);
  131. child_container->add_child(label);
  132. primary_grid_steps = memnew(SpinBox);
  133. primary_grid_steps->set_min(0);
  134. primary_grid_steps->set_step(1);
  135. primary_grid_steps->set_max(100);
  136. primary_grid_steps->set_allow_greater(true);
  137. primary_grid_steps->set_suffix(TTR("steps"));
  138. primary_grid_steps->set_h_size_flags(SIZE_EXPAND_FILL);
  139. child_container->add_child(primary_grid_steps);
  140. container->add_child(memnew(HSeparator));
  141. // We need to create another GridContainer with the same column count,
  142. // so we can put an HSeparator above
  143. child_container = memnew(GridContainer);
  144. child_container->set_columns(2);
  145. container->add_child(child_container);
  146. label = memnew(Label);
  147. label->set_text(TTR("Rotation Offset:"));
  148. child_container->add_child(label);
  149. label->set_h_size_flags(SIZE_EXPAND_FILL);
  150. rotation_offset = memnew(SpinBox);
  151. rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
  152. rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
  153. rotation_offset->set_suffix("deg");
  154. rotation_offset->set_h_size_flags(SIZE_EXPAND_FILL);
  155. child_container->add_child(rotation_offset);
  156. label = memnew(Label);
  157. label->set_text(TTR("Rotation Step:"));
  158. child_container->add_child(label);
  159. label->set_h_size_flags(SIZE_EXPAND_FILL);
  160. rotation_step = memnew(SpinBox);
  161. rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
  162. rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
  163. rotation_step->set_suffix("deg");
  164. rotation_step->set_h_size_flags(SIZE_EXPAND_FILL);
  165. child_container->add_child(rotation_step);
  166. container->add_child(memnew(HSeparator));
  167. child_container = memnew(GridContainer);
  168. child_container->set_columns(2);
  169. container->add_child(child_container);
  170. label = memnew(Label);
  171. label->set_text(TTR("Scale Step:"));
  172. child_container->add_child(label);
  173. label->set_h_size_flags(SIZE_EXPAND_FILL);
  174. scale_step = memnew(SpinBox);
  175. scale_step->set_min(SPIN_BOX_SCALE_MIN);
  176. scale_step->set_max(SPIN_BOX_SCALE_MAX);
  177. scale_step->set_allow_greater(true);
  178. scale_step->set_h_size_flags(SIZE_EXPAND_FILL);
  179. scale_step->set_step(0.01f);
  180. child_container->add_child(scale_step);
  181. }
  182. void set_fields(const Point2 p_grid_offset, const Point2 p_grid_step, const int p_primary_grid_steps, const float p_rotation_offset, const float p_rotation_step, const float p_scale_step) {
  183. grid_offset_x->set_value(p_grid_offset.x);
  184. grid_offset_y->set_value(p_grid_offset.y);
  185. grid_step_x->set_value(p_grid_step.x);
  186. grid_step_y->set_value(p_grid_step.y);
  187. primary_grid_steps->set_value(p_primary_grid_steps);
  188. rotation_offset->set_value(p_rotation_offset * (180 / Math_PI));
  189. rotation_step->set_value(p_rotation_step * (180 / Math_PI));
  190. scale_step->set_value(p_scale_step);
  191. }
  192. void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, int &p_primary_grid_steps, float &p_rotation_offset, float &p_rotation_step, float &p_scale_step) {
  193. p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value());
  194. p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value());
  195. p_primary_grid_steps = int(primary_grid_steps->get_value());
  196. p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI);
  197. p_rotation_step = rotation_step->get_value() / (180 / Math_PI);
  198. p_scale_step = scale_step->get_value();
  199. }
  200. };
  201. bool CanvasItemEditor::_is_node_locked(const Node *p_node) {
  202. return p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_");
  203. }
  204. bool CanvasItemEditor::_is_node_movable(const Node *p_node, bool p_popup_warning) {
  205. if (_is_node_locked(p_node)) {
  206. return false;
  207. }
  208. if (Object::cast_to<Control>(p_node) && Object::cast_to<Container>(p_node->get_parent())) {
  209. if (p_popup_warning) {
  210. _popup_warning_temporarily(warning_child_of_container, 3.0);
  211. }
  212. return false;
  213. }
  214. return true;
  215. }
  216. void CanvasItemEditor::_snap_if_closer_float(
  217. float p_value,
  218. float &r_current_snap, SnapTarget &r_current_snap_target,
  219. float p_target_value, SnapTarget p_snap_target,
  220. float p_radius) {
  221. float radius = p_radius / zoom;
  222. float dist = Math::abs(p_value - p_target_value);
  223. if ((p_radius < 0 || dist < radius) && (r_current_snap_target == SNAP_TARGET_NONE || dist < Math::abs(r_current_snap - p_value))) {
  224. r_current_snap = p_target_value;
  225. r_current_snap_target = p_snap_target;
  226. }
  227. }
  228. void CanvasItemEditor::_snap_if_closer_point(
  229. Point2 p_value,
  230. Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
  231. Point2 p_target_value, SnapTarget p_snap_target,
  232. real_t rotation,
  233. float p_radius) {
  234. Transform2D rot_trans = Transform2D(rotation, Point2());
  235. p_value = rot_trans.inverse().xform(p_value);
  236. p_target_value = rot_trans.inverse().xform(p_target_value);
  237. r_current_snap = rot_trans.inverse().xform(r_current_snap);
  238. _snap_if_closer_float(
  239. p_value.x,
  240. r_current_snap.x,
  241. r_current_snap_target[0],
  242. p_target_value.x,
  243. p_snap_target,
  244. p_radius);
  245. _snap_if_closer_float(
  246. p_value.y,
  247. r_current_snap.y,
  248. r_current_snap_target[1],
  249. p_target_value.y,
  250. p_snap_target,
  251. p_radius);
  252. r_current_snap = rot_trans.xform(r_current_snap);
  253. }
  254. void CanvasItemEditor::_snap_other_nodes(
  255. const Point2 p_value,
  256. const Transform2D p_transform_to_snap,
  257. Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
  258. const SnapTarget p_snap_target, List<const CanvasItem *> p_exceptions,
  259. const Node *p_current) {
  260. const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current);
  261. // Check if the element is in the exception
  262. bool exception = false;
  263. for (List<const CanvasItem *>::Element *E = p_exceptions.front(); E; E = E->next()) {
  264. if (E->get() == p_current) {
  265. exception = true;
  266. break;
  267. }
  268. };
  269. if (canvas_item && !exception) {
  270. Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
  271. if (fmod(ci_transform.get_rotation() - p_transform_to_snap.get_rotation(), (real_t)360.0) == 0.0) {
  272. if (canvas_item->_edit_use_rect()) {
  273. Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position());
  274. Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size());
  275. _snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, begin, p_snap_target, ci_transform.get_rotation());
  276. _snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, end, p_snap_target, ci_transform.get_rotation());
  277. } else {
  278. Point2 position = ci_transform.xform(Point2());
  279. _snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, position, p_snap_target, ci_transform.get_rotation());
  280. }
  281. }
  282. }
  283. for (int i = 0; i < p_current->get_child_count(); i++) {
  284. _snap_other_nodes(p_value, p_transform_to_snap, r_current_snap, r_current_snap_target, p_snap_target, p_exceptions, p_current->get_child(i));
  285. }
  286. }
  287. Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsigned int p_forced_modes, const CanvasItem *p_self_canvas_item, List<CanvasItem *> p_other_nodes_exceptions) {
  288. snap_target[0] = SNAP_TARGET_NONE;
  289. snap_target[1] = SNAP_TARGET_NONE;
  290. bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
  291. // Smart snap using the canvas position
  292. Vector2 output = p_target;
  293. real_t rotation = 0.0;
  294. if (p_self_canvas_item) {
  295. rotation = p_self_canvas_item->get_global_transform_with_canvas().get_rotation();
  296. // Parent sides and center
  297. if ((is_snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
  298. if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
  299. Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
  300. Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
  301. _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_PARENT, rotation);
  302. _snap_if_closer_point(p_target, output, snap_target, (begin + end) / 2.0, SNAP_TARGET_PARENT, rotation);
  303. _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_PARENT, rotation);
  304. } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_self_canvas_item->get_parent())) {
  305. if (parent_ci->_edit_use_rect()) {
  306. Point2 begin = p_self_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
  307. Point2 end = p_self_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size());
  308. _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_PARENT, rotation);
  309. _snap_if_closer_point(p_target, output, snap_target, (begin + end) / 2.0, SNAP_TARGET_PARENT, rotation);
  310. _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_PARENT, rotation);
  311. } else {
  312. Point2 position = p_self_canvas_item->get_transform().affine_inverse().xform(Point2());
  313. _snap_if_closer_point(p_target, output, snap_target, position, SNAP_TARGET_PARENT, rotation);
  314. }
  315. }
  316. }
  317. // Self anchors
  318. if ((is_snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) {
  319. if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
  320. Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
  321. Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
  322. _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF_ANCHORS, rotation);
  323. _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF_ANCHORS, rotation);
  324. }
  325. }
  326. // Self sides
  327. if ((is_snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
  328. if (p_self_canvas_item->_edit_use_rect()) {
  329. Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position());
  330. Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position() + p_self_canvas_item->_edit_get_rect().get_size());
  331. _snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF, rotation);
  332. _snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF, rotation);
  333. }
  334. }
  335. // Self center
  336. if ((is_snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) {
  337. if (p_self_canvas_item->_edit_use_rect()) {
  338. Point2 center = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position() + p_self_canvas_item->_edit_get_rect().get_size() / 2.0);
  339. _snap_if_closer_point(p_target, output, snap_target, center, SNAP_TARGET_SELF, rotation);
  340. } else {
  341. Point2 position = p_self_canvas_item->get_global_transform_with_canvas().xform(Point2());
  342. _snap_if_closer_point(p_target, output, snap_target, position, SNAP_TARGET_SELF, rotation);
  343. }
  344. }
  345. }
  346. // Other nodes sides
  347. if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
  348. Transform2D to_snap_transform = Transform2D();
  349. List<const CanvasItem *> exceptions = List<const CanvasItem *>();
  350. for (List<CanvasItem *>::Element *E = p_other_nodes_exceptions.front(); E; E = E->next()) {
  351. exceptions.push_back(E->get());
  352. }
  353. if (p_self_canvas_item) {
  354. exceptions.push_back(p_self_canvas_item);
  355. to_snap_transform = p_self_canvas_item->get_global_transform_with_canvas();
  356. }
  357. _snap_other_nodes(
  358. p_target, to_snap_transform,
  359. output, snap_target,
  360. SNAP_TARGET_OTHER_NODE,
  361. exceptions,
  362. get_tree()->get_edited_scene_root());
  363. }
  364. if (((is_snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, (real_t)360.0) == 0.0) {
  365. // Guides
  366. if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
  367. Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
  368. for (int i = 0; i < vguides.size(); i++) {
  369. _snap_if_closer_float(p_target.x, output.x, snap_target[0], vguides[i], SNAP_TARGET_GUIDE);
  370. }
  371. }
  372. if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
  373. Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
  374. for (int i = 0; i < hguides.size(); i++) {
  375. _snap_if_closer_float(p_target.y, output.y, snap_target[1], hguides[i], SNAP_TARGET_GUIDE);
  376. }
  377. }
  378. }
  379. if (((grid_snap_active && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) {
  380. // Grid
  381. Point2 offset = grid_offset;
  382. if (snap_relative) {
  383. List<CanvasItem *> selection = _get_edited_canvas_items();
  384. if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) {
  385. offset = Object::cast_to<Node2D>(selection[0])->get_global_position();
  386. } else if (selection.size() > 0) {
  387. offset = _get_encompassing_rect_from_list(selection).position;
  388. }
  389. }
  390. Point2 grid_output;
  391. grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x;
  392. grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y;
  393. _snap_if_closer_point(p_target, output, snap_target, grid_output, SNAP_TARGET_GRID, 0.0, -1.0);
  394. }
  395. if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) {
  396. // Pixel
  397. output = output.snapped(Size2(1, 1));
  398. }
  399. snap_transform = Transform2D(rotation, output);
  400. return output;
  401. }
  402. float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
  403. return (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target;
  404. }
  405. void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
  406. Ref<InputEventKey> k = p_ev;
  407. if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
  408. return;
  409. if (k->get_scancode() == KEY_CONTROL || k->get_scancode() == KEY_ALT || k->get_scancode() == KEY_SHIFT) {
  410. viewport->update();
  411. }
  412. if (k->is_pressed() && !k->get_control() && !k->is_echo()) {
  413. if ((grid_snap_active || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
  414. // Multiply the grid size
  415. grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
  416. viewport->update();
  417. } else if ((grid_snap_active || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
  418. // Divide the grid size
  419. Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1);
  420. if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0)
  421. grid_step_multiplier--;
  422. viewport->update();
  423. }
  424. }
  425. }
  426. Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
  427. CanvasItem *ci = Object::cast_to<CanvasItem>(p_what);
  428. if (!ci)
  429. return NULL;
  430. return memnew(CanvasItemEditorSelectedItem);
  431. }
  432. void CanvasItemEditor::_keying_changed() {
  433. if (AnimationPlayerEditor::singleton->get_track_editor()->is_visible_in_tree())
  434. animation_hb->show();
  435. else
  436. animation_hb->hide();
  437. }
  438. Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_list) {
  439. ERR_FAIL_COND_V(p_list.empty(), Rect2());
  440. // Handles the first element
  441. CanvasItem *canvas_item = p_list.front()->get();
  442. Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2());
  443. // Expand with the other ones
  444. for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) {
  445. CanvasItem *canvas_item2 = E->get();
  446. Transform2D xform = canvas_item2->get_global_transform_with_canvas();
  447. Rect2 current_rect = canvas_item2->_edit_get_rect();
  448. rect.expand_to(xform.xform(current_rect.position));
  449. rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0)));
  450. rect.expand_to(xform.xform(current_rect.position + current_rect.size));
  451. rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y)));
  452. }
  453. return rect;
  454. }
  455. void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, bool include_locked_nodes) {
  456. if (!p_node)
  457. return;
  458. if (Object::cast_to<Viewport>(p_node))
  459. return;
  460. const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
  461. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  462. if (canvas_item && !canvas_item->is_set_as_toplevel()) {
  463. _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
  464. } else {
  465. const CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
  466. _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
  467. }
  468. }
  469. if (canvas_item && canvas_item->is_visible_in_tree() && (include_locked_nodes || !_is_node_locked(canvas_item))) {
  470. Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
  471. Rect2 rect = canvas_item->_edit_get_rect();
  472. if (r_first) {
  473. r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2());
  474. r_first = false;
  475. }
  476. r_rect.expand_to(xform.xform(rect.position));
  477. r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
  478. r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
  479. r_rect.expand_to(xform.xform(rect.position + rect.size));
  480. }
  481. }
  482. Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) {
  483. Rect2 rect;
  484. bool first = true;
  485. _expand_encompassing_rect_using_children(rect, p_node, first);
  486. return rect;
  487. }
  488. void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
  489. if (!p_node)
  490. return;
  491. if (Object::cast_to<Viewport>(p_node))
  492. return;
  493. const real_t grab_distance = EDITOR_GET("editors/poly_editor/point_grab_radius");
  494. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
  495. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  496. if (canvas_item) {
  497. if (!canvas_item->is_set_as_toplevel()) {
  498. _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
  499. } else {
  500. _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform);
  501. }
  502. } else {
  503. CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
  504. _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, Transform2D(), cl ? cl->get_transform() : p_canvas_xform);
  505. }
  506. }
  507. if (canvas_item && canvas_item->is_visible_in_tree()) {
  508. Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse();
  509. const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length() / zoom;
  510. if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) {
  511. Node2D *node = Object::cast_to<Node2D>(canvas_item);
  512. _SelectResult res;
  513. res.item = canvas_item;
  514. res.z_index = node ? node->get_z_index() : 0;
  515. res.has_z = node;
  516. r_items.push_back(res);
  517. }
  518. }
  519. }
  520. void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) {
  521. Node *scene = editor->get_edited_scene();
  522. _find_canvas_items_at_pos(p_pos, scene, r_items);
  523. //Remove invalid results
  524. for (int i = 0; i < r_items.size(); i++) {
  525. Node *node = r_items[i].item;
  526. // Make sure the selected node is in the current scene, or editable
  527. if (node && node != get_tree()->get_edited_scene_root()) {
  528. node = scene->get_deepest_editable_node(node);
  529. }
  530. // Replace the node by the group if grouped
  531. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(node);
  532. while (node && node != scene->get_parent()) {
  533. CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node);
  534. if (canvas_item_tmp && node->has_meta("_edit_group_")) {
  535. canvas_item = canvas_item_tmp;
  536. }
  537. node = node->get_parent();
  538. }
  539. // Check if the canvas item is already in the list (for groups or scenes)
  540. bool duplicate = false;
  541. for (int j = 0; j < i; j++) {
  542. if (r_items[j].item == canvas_item) {
  543. duplicate = true;
  544. break;
  545. }
  546. }
  547. //Remove the item if invalid
  548. if (!canvas_item || duplicate || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || _is_node_locked(canvas_item)) {
  549. r_items.remove(i);
  550. i--;
  551. } else {
  552. r_items.write[i].item = canvas_item;
  553. }
  554. }
  555. }
  556. void CanvasItemEditor::_get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) {
  557. Point2 screen_pos = transform.xform(p_pos);
  558. for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
  559. Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
  560. Vector<Vector2> bone_shape;
  561. if (!_get_bone_shape(&bone_shape, NULL, E))
  562. continue;
  563. // Check if the point is inside the Polygon2D
  564. if (Geometry::is_point_in_polygon(screen_pos, bone_shape)) {
  565. // Check if the item is already in the list
  566. bool duplicate = false;
  567. for (int i = 0; i < r_items.size(); i++) {
  568. if (r_items[i].item == from_node) {
  569. duplicate = true;
  570. break;
  571. }
  572. }
  573. if (duplicate)
  574. continue;
  575. // Else, add it
  576. _SelectResult res;
  577. res.item = from_node;
  578. res.z_index = from_node ? from_node->get_z_index() : 0;
  579. res.has_z = from_node;
  580. r_items.push_back(res);
  581. }
  582. }
  583. }
  584. bool CanvasItemEditor::_get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *outline_shape, Map<BoneKey, BoneList>::Element *bone) {
  585. int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
  586. int bone_outline_width = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
  587. Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().from));
  588. Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().to));
  589. if (!from_node)
  590. return false;
  591. if (!from_node->is_inside_tree())
  592. return false; //may have been removed
  593. if (!to_node && bone->get().length == 0)
  594. return false;
  595. Vector2 from = transform.xform(from_node->get_global_position());
  596. Vector2 to;
  597. if (to_node)
  598. to = transform.xform(to_node->get_global_position());
  599. else
  600. to = transform.xform(from_node->get_global_transform().xform(Vector2(bone->get().length, 0)));
  601. Vector2 rel = to - from;
  602. Vector2 relt = rel.tangent().normalized() * bone_width;
  603. Vector2 reln = rel.normalized();
  604. Vector2 reltn = relt.normalized();
  605. if (shape) {
  606. shape->clear();
  607. shape->push_back(from);
  608. shape->push_back(from + rel * 0.2 + relt);
  609. shape->push_back(to);
  610. shape->push_back(from + rel * 0.2 - relt);
  611. }
  612. if (outline_shape) {
  613. outline_shape->clear();
  614. outline_shape->push_back(from + (-reln - reltn) * bone_outline_width);
  615. outline_shape->push_back(from + (-reln + reltn) * bone_outline_width);
  616. outline_shape->push_back(from + rel * 0.2 + relt + reltn * bone_outline_width);
  617. outline_shape->push_back(to + (reln + reltn) * bone_outline_width);
  618. outline_shape->push_back(to + (reln - reltn) * bone_outline_width);
  619. outline_shape->push_back(from + rel * 0.2 - relt - reltn * bone_outline_width);
  620. }
  621. return true;
  622. }
  623. void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
  624. if (!p_node)
  625. return;
  626. if (Object::cast_to<Viewport>(p_node))
  627. return;
  628. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
  629. Node *scene = editor->get_edited_scene();
  630. bool editable = p_node == scene || p_node->get_owner() == scene || p_node == scene->get_deepest_editable_node(p_node);
  631. bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
  632. bool locked = _is_node_locked(p_node);
  633. if (!lock_children || !editable) {
  634. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  635. if (canvas_item) {
  636. if (!canvas_item->is_set_as_toplevel()) {
  637. _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
  638. } else {
  639. _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform);
  640. }
  641. } else {
  642. CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
  643. _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
  644. }
  645. }
  646. }
  647. if (canvas_item && canvas_item->is_visible_in_tree() && !locked && editable) {
  648. Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
  649. if (canvas_item->_edit_use_rect()) {
  650. Rect2 rect = canvas_item->_edit_get_rect();
  651. if (p_rect.has_point(xform.xform(rect.position)) &&
  652. p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) &&
  653. p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) &&
  654. p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) {
  655. r_items->push_back(canvas_item);
  656. }
  657. } else {
  658. if (p_rect.has_point(xform.xform(Point2()))) {
  659. r_items->push_back(canvas_item);
  660. }
  661. }
  662. }
  663. }
  664. bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append) {
  665. bool still_selected = true;
  666. if (p_append) {
  667. if (editor_selection->is_selected(item)) {
  668. // Already in the selection, remove it from the selected nodes
  669. editor_selection->remove_node(item);
  670. still_selected = false;
  671. } else {
  672. // Add the item to the selection
  673. editor_selection->add_node(item);
  674. }
  675. } else {
  676. if (!editor_selection->is_selected(item)) {
  677. // Select a new one and clear previous selection
  678. editor_selection->clear();
  679. editor_selection->add_node(item);
  680. // Reselect
  681. if (Engine::get_singleton()->is_editor_hint()) {
  682. selected_from_canvas = true;
  683. editor->call("edit_node", item);
  684. }
  685. }
  686. }
  687. viewport->update();
  688. return still_selected;
  689. }
  690. List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool retreive_locked, bool remove_canvas_item_if_parent_in_selection) {
  691. List<CanvasItem *> selection;
  692. for (Map<Node *, Object *>::Element *E = editor_selection->get_selection().front(); E; E = E->next()) {
  693. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
  694. if (canvas_item && canvas_item->is_visible_in_tree() && canvas_item->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (retreive_locked || !_is_node_locked(canvas_item))) {
  695. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  696. if (se) {
  697. selection.push_back(canvas_item);
  698. }
  699. }
  700. }
  701. if (remove_canvas_item_if_parent_in_selection) {
  702. List<CanvasItem *> filtered_selection;
  703. for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
  704. if (!selection.find(E->get()->get_parent())) {
  705. filtered_selection.push_back(E->get());
  706. }
  707. }
  708. return filtered_selection;
  709. } else {
  710. return selection;
  711. }
  712. }
  713. Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) {
  714. ERR_FAIL_COND_V(!p_control, Vector2());
  715. Transform2D parent_transform = p_control->get_transform().affine_inverse();
  716. Rect2 parent_rect = p_control->get_parent_anchorable_rect();
  717. return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y));
  718. }
  719. Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) {
  720. ERR_FAIL_COND_V(!p_control, Vector2());
  721. Rect2 parent_rect = p_control->get_parent_anchorable_rect();
  722. Vector2 output = Vector2();
  723. output.x = (parent_rect.size.x == 0) ? 0.0 : (p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
  724. output.y = (parent_rect.size.y == 0) ? 0.0 : (p_control->get_transform().xform(position).y - parent_rect.position.y) / parent_rect.size.y;
  725. return output;
  726. }
  727. void CanvasItemEditor::_save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state) {
  728. if (p_bones_length)
  729. *p_bones_length = List<float>();
  730. if (p_bones_state)
  731. *p_bones_state = List<Dictionary>();
  732. const Node2D *bone = Object::cast_to<Node2D>(p_canvas_item);
  733. if (bone && bone->has_meta("_edit_bone_")) {
  734. // Check if we have an IK chain
  735. List<const Node2D *> bone_ik_list;
  736. bool ik_found = false;
  737. bone = Object::cast_to<Node2D>(bone->get_parent());
  738. while (bone) {
  739. bone_ik_list.push_back(bone);
  740. if (bone->has_meta("_edit_ik_")) {
  741. ik_found = true;
  742. break;
  743. } else if (!bone->has_meta("_edit_bone_")) {
  744. break;
  745. }
  746. bone = Object::cast_to<Node2D>(bone->get_parent());
  747. }
  748. //Save the bone state and length if we have an IK chain
  749. if (ik_found) {
  750. bone = Object::cast_to<Node2D>(p_canvas_item);
  751. Transform2D bone_xform = bone->get_global_transform();
  752. for (List<const Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) {
  753. bone_xform = bone_xform * bone->get_transform().affine_inverse();
  754. const Node2D *parent_bone = bone_E->get();
  755. if (p_bones_length)
  756. p_bones_length->push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position()));
  757. if (p_bones_state)
  758. p_bones_state->push_back(parent_bone->_edit_get_state());
  759. bone = parent_bone;
  760. }
  761. }
  762. }
  763. }
  764. void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) {
  765. for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
  766. CanvasItem *canvas_item = E->get();
  767. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  768. if (se) {
  769. se->undo_state = canvas_item->_edit_get_state();
  770. se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
  771. if (canvas_item->_edit_use_rect()) {
  772. se->pre_drag_rect = canvas_item->_edit_get_rect();
  773. } else {
  774. se->pre_drag_rect = Rect2();
  775. }
  776. // If we have a bone, save the state of all nodes in the IK chain
  777. _save_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_length), &(se->pre_drag_bones_undo_state));
  778. }
  779. }
  780. }
  781. void CanvasItemEditor::_restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state) {
  782. CanvasItem *canvas_item = p_canvas_item;
  783. for (const List<Dictionary>::Element *E = p_bones_state->front(); E; E = E->next()) {
  784. canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
  785. canvas_item->_edit_set_state(E->get());
  786. }
  787. }
  788. void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) {
  789. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  790. CanvasItem *canvas_item = E->get();
  791. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  792. if (se) {
  793. canvas_item->_edit_set_state(se->undo_state);
  794. if (restore_bones) {
  795. _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
  796. }
  797. }
  798. }
  799. }
  800. void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones) {
  801. List<CanvasItem *> modified_canvas_items;
  802. for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
  803. CanvasItem *canvas_item = E->get();
  804. Dictionary old_state = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item)->undo_state;
  805. Dictionary new_state = canvas_item->_edit_get_state();
  806. if (old_state.hash() != new_state.hash()) {
  807. modified_canvas_items.push_back(canvas_item);
  808. }
  809. }
  810. if (modified_canvas_items.empty()) {
  811. return;
  812. }
  813. undo_redo->create_action(action_name);
  814. for (List<CanvasItem *>::Element *E = modified_canvas_items.front(); E; E = E->next()) {
  815. CanvasItem *canvas_item = E->get();
  816. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  817. if (se) {
  818. undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
  819. undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
  820. if (commit_bones) {
  821. for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
  822. canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
  823. undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
  824. undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
  825. }
  826. }
  827. }
  828. }
  829. undo_redo->add_do_method(viewport, "update");
  830. undo_redo->add_undo_method(viewport, "update");
  831. undo_redo->commit_action();
  832. }
  833. void CanvasItemEditor::_snap_changed() {
  834. ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, primary_grid_steps, snap_rotation_offset, snap_rotation_step, snap_scale_step);
  835. grid_step_multiplier = 0;
  836. viewport->update();
  837. }
  838. void CanvasItemEditor::_selection_result_pressed(int p_result) {
  839. if (selection_results.size() <= p_result)
  840. return;
  841. CanvasItem *item = selection_results[p_result].item;
  842. if (item)
  843. _select_click_on_item(item, Point2(), selection_menu_additive_selection);
  844. }
  845. void CanvasItemEditor::_selection_menu_hide() {
  846. selection_results.clear();
  847. selection_menu->clear();
  848. selection_menu->set_size(Vector2(0, 0));
  849. }
  850. bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
  851. Ref<InputEventMouseButton> b = p_event;
  852. Ref<InputEventMouseMotion> m = p_event;
  853. if (drag_type == DRAG_NONE) {
  854. if (show_guides && show_rulers && EditorNode::get_singleton()->get_edited_scene()) {
  855. Transform2D xform = viewport_scrollable->get_transform() * transform;
  856. // Retrieve the guide lists
  857. Array vguides;
  858. if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
  859. vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
  860. }
  861. Array hguides;
  862. if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
  863. hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
  864. }
  865. // Hover over guides
  866. float minimum = 1e20;
  867. is_hovering_h_guide = false;
  868. is_hovering_v_guide = false;
  869. if (m.is_valid() && m->get_position().x < RULER_WIDTH) {
  870. // Check if we are hovering an existing horizontal guide
  871. for (int i = 0; i < hguides.size(); i++) {
  872. if (ABS(xform.xform(Point2(0, hguides[i])).y - m->get_position().y) < MIN(minimum, 8)) {
  873. is_hovering_h_guide = true;
  874. is_hovering_v_guide = false;
  875. break;
  876. }
  877. }
  878. } else if (m.is_valid() && m->get_position().y < RULER_WIDTH) {
  879. // Check if we are hovering an existing vertical guide
  880. for (int i = 0; i < vguides.size(); i++) {
  881. if (ABS(xform.xform(Point2(vguides[i], 0)).x - m->get_position().x) < MIN(minimum, 8)) {
  882. is_hovering_v_guide = true;
  883. is_hovering_h_guide = false;
  884. break;
  885. }
  886. }
  887. }
  888. // Start dragging a guide
  889. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
  890. // Press button
  891. if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) {
  892. // Drag a new double guide
  893. drag_type = DRAG_DOUBLE_GUIDE;
  894. dragged_guide_index = -1;
  895. return true;
  896. } else if (b->get_position().x < RULER_WIDTH) {
  897. // Check if we drag an existing horizontal guide
  898. dragged_guide_index = -1;
  899. for (int i = 0; i < hguides.size(); i++) {
  900. if (ABS(xform.xform(Point2(0, hguides[i])).y - b->get_position().y) < MIN(minimum, 8)) {
  901. dragged_guide_index = i;
  902. }
  903. }
  904. if (dragged_guide_index >= 0) {
  905. // Drag an existing horizontal guide
  906. drag_type = DRAG_H_GUIDE;
  907. } else {
  908. // Drag a new vertical guide
  909. drag_type = DRAG_V_GUIDE;
  910. }
  911. return true;
  912. } else if (b->get_position().y < RULER_WIDTH) {
  913. // Check if we drag an existing vertical guide
  914. dragged_guide_index = -1;
  915. for (int i = 0; i < vguides.size(); i++) {
  916. if (ABS(xform.xform(Point2(vguides[i], 0)).x - b->get_position().x) < MIN(minimum, 8)) {
  917. dragged_guide_index = i;
  918. }
  919. }
  920. if (dragged_guide_index >= 0) {
  921. // Drag an existing vertical guide
  922. drag_type = DRAG_V_GUIDE;
  923. } else {
  924. // Drag a new vertical guide
  925. drag_type = DRAG_H_GUIDE;
  926. }
  927. drag_from = xform.affine_inverse().xform(b->get_position());
  928. return true;
  929. }
  930. }
  931. }
  932. }
  933. if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE || drag_type == DRAG_H_GUIDE) {
  934. // Move the guide
  935. if (m.is_valid()) {
  936. Transform2D xform = viewport_scrollable->get_transform() * transform;
  937. drag_to = xform.affine_inverse().xform(m->get_position());
  938. dragged_guide_pos = xform.xform(snap_point(drag_to, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES));
  939. viewport->update();
  940. return true;
  941. }
  942. // Release confirms the guide move
  943. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
  944. if (show_guides && EditorNode::get_singleton()->get_edited_scene()) {
  945. Transform2D xform = viewport_scrollable->get_transform() * transform;
  946. // Retrieve the guide lists
  947. Array vguides;
  948. if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
  949. vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
  950. }
  951. Array hguides;
  952. if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
  953. hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
  954. }
  955. Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES);
  956. if (drag_type == DRAG_V_GUIDE) {
  957. Array prev_vguides = vguides.duplicate();
  958. if (b->get_position().x > RULER_WIDTH) {
  959. // Adds a new vertical guide
  960. if (dragged_guide_index >= 0) {
  961. vguides[dragged_guide_index] = edited.x;
  962. undo_redo->create_action(TTR("Move Vertical Guide"));
  963. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
  964. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
  965. undo_redo->add_undo_method(viewport, "update");
  966. undo_redo->commit_action();
  967. } else {
  968. vguides.push_back(edited.x);
  969. undo_redo->create_action(TTR("Create Vertical Guide"));
  970. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
  971. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
  972. undo_redo->add_undo_method(viewport, "update");
  973. undo_redo->commit_action();
  974. }
  975. } else {
  976. if (dragged_guide_index >= 0) {
  977. vguides.remove(dragged_guide_index);
  978. undo_redo->create_action(TTR("Remove Vertical Guide"));
  979. if (vguides.empty()) {
  980. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_vertical_guides_");
  981. } else {
  982. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
  983. }
  984. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
  985. undo_redo->add_undo_method(viewport, "update");
  986. undo_redo->commit_action();
  987. }
  988. }
  989. } else if (drag_type == DRAG_H_GUIDE) {
  990. Array prev_hguides = hguides.duplicate();
  991. if (b->get_position().y > RULER_WIDTH) {
  992. // Adds a new horizontal guide
  993. if (dragged_guide_index >= 0) {
  994. hguides[dragged_guide_index] = edited.y;
  995. undo_redo->create_action(TTR("Move Horizontal Guide"));
  996. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
  997. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
  998. undo_redo->add_undo_method(viewport, "update");
  999. undo_redo->commit_action();
  1000. } else {
  1001. hguides.push_back(edited.y);
  1002. undo_redo->create_action(TTR("Create Horizontal Guide"));
  1003. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
  1004. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
  1005. undo_redo->add_undo_method(viewport, "update");
  1006. undo_redo->commit_action();
  1007. }
  1008. } else {
  1009. if (dragged_guide_index >= 0) {
  1010. hguides.remove(dragged_guide_index);
  1011. undo_redo->create_action(TTR("Remove Horizontal Guide"));
  1012. if (hguides.empty()) {
  1013. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_horizontal_guides_");
  1014. } else {
  1015. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
  1016. }
  1017. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
  1018. undo_redo->add_undo_method(viewport, "update");
  1019. undo_redo->commit_action();
  1020. }
  1021. }
  1022. } else if (drag_type == DRAG_DOUBLE_GUIDE) {
  1023. Array prev_hguides = hguides.duplicate();
  1024. Array prev_vguides = vguides.duplicate();
  1025. if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) {
  1026. // Adds a new horizontal guide a new vertical guide
  1027. vguides.push_back(edited.x);
  1028. hguides.push_back(edited.y);
  1029. undo_redo->create_action(TTR("Create Horizontal and Vertical Guides"));
  1030. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
  1031. undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
  1032. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
  1033. undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
  1034. undo_redo->add_undo_method(viewport, "update");
  1035. undo_redo->commit_action();
  1036. }
  1037. }
  1038. }
  1039. drag_type = DRAG_NONE;
  1040. viewport->update();
  1041. return true;
  1042. }
  1043. }
  1044. return false;
  1045. }
  1046. bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) {
  1047. Ref<InputEventMouseButton> b = p_event;
  1048. if (b.is_valid() && !p_already_accepted) {
  1049. const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control();
  1050. if (pan_on_scroll) {
  1051. // Perform horizontal scrolling first so we can check for Shift being held.
  1052. if (b->is_pressed() &&
  1053. (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_UP))) {
  1054. // Pan left
  1055. view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
  1056. update_viewport();
  1057. return true;
  1058. }
  1059. if (b->is_pressed() &&
  1060. (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_DOWN))) {
  1061. // Pan right
  1062. view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
  1063. update_viewport();
  1064. return true;
  1065. }
  1066. }
  1067. if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) {
  1068. // Scroll or pan down
  1069. if (pan_on_scroll) {
  1070. view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
  1071. update_viewport();
  1072. } else {
  1073. float new_zoom = _get_next_zoom_value(-1);
  1074. if (b->get_factor() != 1.f) {
  1075. new_zoom = zoom * ((new_zoom / zoom - 1.f) * b->get_factor() + 1.f);
  1076. }
  1077. _zoom_on_position(new_zoom, b->get_position());
  1078. }
  1079. return true;
  1080. }
  1081. if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_UP) {
  1082. // Scroll or pan up
  1083. if (pan_on_scroll) {
  1084. view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
  1085. update_viewport();
  1086. } else {
  1087. float new_zoom = _get_next_zoom_value(1);
  1088. if (b->get_factor() != 1.f) {
  1089. new_zoom = zoom * ((new_zoom / zoom - 1.f) * b->get_factor() + 1.f);
  1090. }
  1091. _zoom_on_position(new_zoom, b->get_position());
  1092. }
  1093. return true;
  1094. }
  1095. if (!panning) {
  1096. if (b->is_pressed() &&
  1097. (b->get_button_index() == BUTTON_MIDDLE ||
  1098. b->get_button_index() == BUTTON_RIGHT ||
  1099. (b->get_button_index() == BUTTON_LEFT && tool == TOOL_PAN) ||
  1100. (b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) {
  1101. // Pan the viewport
  1102. panning = true;
  1103. }
  1104. }
  1105. if (panning) {
  1106. if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != BUTTON_WHEEL_DOWN && b->get_button_index() != BUTTON_WHEEL_UP))) {
  1107. // Stop panning the viewport (for any mouse button press except zooming)
  1108. panning = false;
  1109. }
  1110. }
  1111. }
  1112. Ref<InputEventKey> k = p_event;
  1113. if (k.is_valid()) {
  1114. bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->is_shortcut(p_event);
  1115. if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) {
  1116. if (!panning) {
  1117. if (k->is_pressed() && !k->is_echo()) {
  1118. //Pan the viewport
  1119. panning = true;
  1120. }
  1121. } else {
  1122. if (!k->is_pressed()) {
  1123. // Stop panning the viewport (for any mouse button press)
  1124. panning = false;
  1125. }
  1126. }
  1127. }
  1128. if (is_pan_key)
  1129. pan_pressed = k->is_pressed();
  1130. }
  1131. Ref<InputEventMouseMotion> m = p_event;
  1132. if (m.is_valid()) {
  1133. if (panning) {
  1134. // Pan the viewport
  1135. Point2i relative;
  1136. if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
  1137. relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
  1138. } else {
  1139. relative = m->get_relative();
  1140. }
  1141. view_offset.x -= relative.x / zoom;
  1142. view_offset.y -= relative.y / zoom;
  1143. update_viewport();
  1144. return true;
  1145. }
  1146. }
  1147. Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
  1148. if (magnify_gesture.is_valid() && !p_already_accepted) {
  1149. // Zoom gesture
  1150. _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
  1151. return true;
  1152. }
  1153. Ref<InputEventPanGesture> pan_gesture = p_event;
  1154. if (pan_gesture.is_valid() && !p_already_accepted) {
  1155. // If control key pressed, then zoom instead of pan
  1156. if (pan_gesture->get_control()) {
  1157. const float factor = pan_gesture->get_delta().y;
  1158. float new_zoom = _get_next_zoom_value(-1);
  1159. if (factor != 1.f) {
  1160. new_zoom = zoom * ((new_zoom / zoom - 1.f) * factor + 1.f);
  1161. }
  1162. _zoom_on_position(new_zoom, pan_gesture->get_position());
  1163. return true;
  1164. }
  1165. // Pan gesture
  1166. const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta();
  1167. view_offset.x += delta.x;
  1168. view_offset.y += delta.y;
  1169. update_viewport();
  1170. return true;
  1171. }
  1172. return false;
  1173. }
  1174. bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
  1175. Ref<InputEventMouseMotion> m = p_event;
  1176. Ref<InputEventMouseButton> b = p_event;
  1177. Ref<InputEventKey> k = p_event;
  1178. // Drag the pivot (in pivot mode / with V key)
  1179. if (drag_type == DRAG_NONE) {
  1180. if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
  1181. (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V)) {
  1182. List<CanvasItem *> selection = _get_edited_canvas_items();
  1183. // Filters the selection with nodes that allow setting the pivot
  1184. drag_selection = List<CanvasItem *>();
  1185. for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
  1186. CanvasItem *canvas_item = E->get();
  1187. if (canvas_item->_edit_use_pivot()) {
  1188. drag_selection.push_back(canvas_item);
  1189. }
  1190. }
  1191. // Start dragging if we still have nodes
  1192. if (drag_selection.size() > 0) {
  1193. _save_canvas_item_state(drag_selection);
  1194. drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position());
  1195. Vector2 new_pos;
  1196. if (drag_selection.size() == 1) {
  1197. new_pos = snap_point(drag_from, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, drag_selection[0]);
  1198. } else {
  1199. new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, NULL, drag_selection);
  1200. }
  1201. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1202. CanvasItem *canvas_item = E->get();
  1203. canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
  1204. }
  1205. drag_type = DRAG_PIVOT;
  1206. }
  1207. return true;
  1208. }
  1209. }
  1210. if (drag_type == DRAG_PIVOT) {
  1211. // Move the pivot
  1212. if (m.is_valid()) {
  1213. drag_to = transform.affine_inverse().xform(m->get_position());
  1214. _restore_canvas_item_state(drag_selection);
  1215. Vector2 new_pos;
  1216. if (drag_selection.size() == 1)
  1217. new_pos = snap_point(drag_to, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, drag_selection[0]);
  1218. else
  1219. new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
  1220. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1221. CanvasItem *canvas_item = E->get();
  1222. canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
  1223. }
  1224. return true;
  1225. }
  1226. // Confirm the pivot move
  1227. if (drag_selection.size() >= 1 &&
  1228. ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
  1229. (k.is_valid() && !k->is_pressed() && k->get_scancode() == KEY_V))) {
  1230. _commit_canvas_item_state(
  1231. drag_selection,
  1232. vformat(
  1233. TTR("Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"),
  1234. drag_selection[0]->get_name(),
  1235. drag_selection[0]->_edit_get_pivot().x,
  1236. drag_selection[0]->_edit_get_pivot().y));
  1237. drag_type = DRAG_NONE;
  1238. return true;
  1239. }
  1240. // Cancel a drag
  1241. if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
  1242. _restore_canvas_item_state(drag_selection);
  1243. drag_type = DRAG_NONE;
  1244. viewport->update();
  1245. return true;
  1246. }
  1247. }
  1248. return false;
  1249. }
  1250. void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) {
  1251. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node);
  1252. if (se) {
  1253. int nb_bones = se->pre_drag_bones_undo_state.size();
  1254. if (nb_bones > 0) {
  1255. // Build the node list
  1256. Point2 leaf_pos = target_position;
  1257. List<Node2D *> joints_list;
  1258. List<Point2> joints_pos;
  1259. Node2D *joint = leaf_node;
  1260. Transform2D joint_transform = leaf_node->get_global_transform_with_canvas();
  1261. for (int i = 0; i < nb_bones + 1; i++) {
  1262. joints_list.push_back(joint);
  1263. joints_pos.push_back(joint_transform.get_origin());
  1264. joint_transform = joint_transform * joint->get_transform().affine_inverse();
  1265. joint = Object::cast_to<Node2D>(joint->get_parent());
  1266. }
  1267. Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin();
  1268. // Restraints the node to a maximum distance is necessary
  1269. float total_len = 0;
  1270. for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
  1271. total_len += E->get();
  1272. }
  1273. if ((root_pos.distance_to(leaf_pos)) > total_len) {
  1274. Vector2 rel = leaf_pos - root_pos;
  1275. rel = rel.normalized() * total_len;
  1276. leaf_pos = root_pos + rel;
  1277. }
  1278. joints_pos[0] = leaf_pos;
  1279. // Run the solver
  1280. int solver_iterations = 64;
  1281. float solver_k = 0.3;
  1282. // Build the position list
  1283. for (int i = 0; i < solver_iterations; i++) {
  1284. // Handle the leaf joint
  1285. int node_id = 0;
  1286. for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
  1287. Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized();
  1288. int len = E->get();
  1289. if (E == se->pre_drag_bones_length.front()) {
  1290. joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k);
  1291. } else if (E == se->pre_drag_bones_length.back()) {
  1292. joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k);
  1293. } else {
  1294. Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0;
  1295. joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k);
  1296. joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k);
  1297. }
  1298. node_id++;
  1299. }
  1300. }
  1301. // Set the position
  1302. for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) {
  1303. Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized();
  1304. Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized();
  1305. float rot = current.angle_to(target);
  1306. if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) {
  1307. rot = -rot;
  1308. }
  1309. joints_list[node_id]->rotate(rot);
  1310. }
  1311. }
  1312. }
  1313. }
  1314. bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
  1315. Ref<InputEventMouseButton> b = p_event;
  1316. Ref<InputEventMouseMotion> m = p_event;
  1317. // Start rotation
  1318. if (drag_type == DRAG_NONE) {
  1319. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
  1320. if ((b->get_command() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
  1321. List<CanvasItem *> selection = _get_edited_canvas_items();
  1322. // Remove not movable nodes
  1323. for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
  1324. if (!_is_node_movable(E->get(), true))
  1325. selection.erase(E);
  1326. }
  1327. drag_selection = selection;
  1328. if (drag_selection.size() > 0) {
  1329. drag_type = DRAG_ROTATE;
  1330. drag_from = transform.affine_inverse().xform(b->get_position());
  1331. CanvasItem *canvas_item = drag_selection[0];
  1332. if (canvas_item->_edit_use_pivot()) {
  1333. drag_rotation_center = canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_pivot());
  1334. } else {
  1335. drag_rotation_center = canvas_item->get_global_transform_with_canvas().get_origin();
  1336. }
  1337. _save_canvas_item_state(drag_selection);
  1338. return true;
  1339. }
  1340. }
  1341. }
  1342. }
  1343. if (drag_type == DRAG_ROTATE) {
  1344. // Rotate the node
  1345. if (m.is_valid()) {
  1346. _restore_canvas_item_state(drag_selection);
  1347. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1348. CanvasItem *canvas_item = E->get();
  1349. drag_to = transform.affine_inverse().xform(m->get_position());
  1350. //Rotate the opposite way if the canvas item's compounded scale has an uneven number of negative elements
  1351. bool opposite = (canvas_item->get_global_transform().get_scale().sign().dot(canvas_item->get_transform().get_scale().sign()) == 0);
  1352. canvas_item->_edit_set_rotation(snap_angle(canvas_item->_edit_get_rotation() + (opposite ? -1 : 1) * (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), canvas_item->_edit_get_rotation()));
  1353. viewport->update();
  1354. }
  1355. return true;
  1356. }
  1357. // Confirms the node rotation
  1358. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
  1359. if (drag_selection.size() != 1) {
  1360. _commit_canvas_item_state(
  1361. drag_selection,
  1362. vformat(TTR("Rotate %d CanvasItems"), drag_selection.size()),
  1363. true);
  1364. } else {
  1365. _commit_canvas_item_state(
  1366. drag_selection,
  1367. vformat(TTR("Rotate CanvasItem \"%s\" to %d degrees"),
  1368. drag_selection[0]->get_name(),
  1369. Math::rad2deg(drag_selection[0]->_edit_get_rotation())),
  1370. true);
  1371. }
  1372. if (key_auto_insert_button->is_pressed()) {
  1373. _insert_animation_keys(false, true, false, true);
  1374. }
  1375. drag_type = DRAG_NONE;
  1376. return true;
  1377. }
  1378. // Cancel a drag
  1379. if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
  1380. _restore_canvas_item_state(drag_selection);
  1381. drag_type = DRAG_NONE;
  1382. viewport->update();
  1383. return true;
  1384. }
  1385. }
  1386. return false;
  1387. }
  1388. bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event) {
  1389. Ref<InputEventMouseButton> b = p_event;
  1390. // Open a sub-scene on double-click
  1391. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) {
  1392. List<CanvasItem *> selection = _get_edited_canvas_items();
  1393. if (selection.size() == 1) {
  1394. CanvasItem *canvas_item = selection[0];
  1395. if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) {
  1396. editor->open_request(canvas_item->get_filename());
  1397. return true;
  1398. }
  1399. }
  1400. }
  1401. return false;
  1402. }
  1403. bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
  1404. Ref<InputEventMouseButton> b = p_event;
  1405. Ref<InputEventMouseMotion> m = p_event;
  1406. // Starts anchor dragging if needed
  1407. if (drag_type == DRAG_NONE) {
  1408. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
  1409. List<CanvasItem *> selection = _get_edited_canvas_items();
  1410. if (selection.size() == 1) {
  1411. Control *control = Object::cast_to<Control>(selection[0]);
  1412. if (control && _is_node_movable(control)) {
  1413. Vector2 anchor_pos[4];
  1414. anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP));
  1415. anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP));
  1416. anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM));
  1417. anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM));
  1418. Rect2 anchor_rects[4];
  1419. for (int i = 0; i < 4; i++) {
  1420. anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i]));
  1421. anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size());
  1422. anchor_rects[i].position -= anchor_handle->get_size() * Vector2(float(i == 0 || i == 3), float(i <= 1));
  1423. }
  1424. DragType dragger[] = {
  1425. DRAG_ANCHOR_TOP_LEFT,
  1426. DRAG_ANCHOR_TOP_RIGHT,
  1427. DRAG_ANCHOR_BOTTOM_RIGHT,
  1428. DRAG_ANCHOR_BOTTOM_LEFT,
  1429. };
  1430. for (int i = 0; i < 4; i++) {
  1431. if (anchor_rects[i].has_point(b->get_position())) {
  1432. if ((anchor_pos[0] == anchor_pos[2]) && (anchor_pos[0].distance_to(b->get_position()) < anchor_handle->get_size().length() / 3.0)) {
  1433. drag_type = DRAG_ANCHOR_ALL;
  1434. } else {
  1435. drag_type = dragger[i];
  1436. }
  1437. drag_from = transform.affine_inverse().xform(b->get_position());
  1438. drag_selection = List<CanvasItem *>();
  1439. drag_selection.push_back(control);
  1440. _save_canvas_item_state(drag_selection);
  1441. return true;
  1442. }
  1443. }
  1444. }
  1445. }
  1446. }
  1447. }
  1448. if (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT || drag_type == DRAG_ANCHOR_BOTTOM_RIGHT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT || drag_type == DRAG_ANCHOR_ALL) {
  1449. // Drag the anchor
  1450. if (m.is_valid()) {
  1451. _restore_canvas_item_state(drag_selection);
  1452. Control *control = Object::cast_to<Control>(drag_selection[0]);
  1453. drag_to = transform.affine_inverse().xform(m->get_position());
  1454. Transform2D xform = control->get_global_transform_with_canvas().affine_inverse();
  1455. Point2 previous_anchor;
  1456. previous_anchor.x = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT) ? control->get_anchor(MARGIN_LEFT) : control->get_anchor(MARGIN_RIGHT);
  1457. previous_anchor.y = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT) ? control->get_anchor(MARGIN_TOP) : control->get_anchor(MARGIN_BOTTOM);
  1458. previous_anchor = xform.affine_inverse().xform(_anchor_to_position(control, previous_anchor));
  1459. Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER, control));
  1460. new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001));
  1461. bool use_single_axis = m->get_shift();
  1462. Vector2 drag_vector = xform.xform(drag_to) - xform.xform(drag_from);
  1463. bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
  1464. switch (drag_type) {
  1465. case DRAG_ANCHOR_TOP_LEFT:
  1466. if (!use_single_axis || !use_y) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
  1467. if (!use_single_axis || use_y) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
  1468. break;
  1469. case DRAG_ANCHOR_TOP_RIGHT:
  1470. if (!use_single_axis || !use_y) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
  1471. if (!use_single_axis || use_y) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
  1472. break;
  1473. case DRAG_ANCHOR_BOTTOM_RIGHT:
  1474. if (!use_single_axis || !use_y) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
  1475. if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
  1476. break;
  1477. case DRAG_ANCHOR_BOTTOM_LEFT:
  1478. if (!use_single_axis || !use_y) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
  1479. if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
  1480. break;
  1481. case DRAG_ANCHOR_ALL:
  1482. if (!use_single_axis || !use_y) {
  1483. control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
  1484. control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
  1485. }
  1486. if (!use_single_axis || use_y) {
  1487. control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
  1488. control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
  1489. }
  1490. break;
  1491. default:
  1492. break;
  1493. }
  1494. return true;
  1495. }
  1496. // Confirms new anchor position
  1497. if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
  1498. _commit_canvas_item_state(
  1499. drag_selection,
  1500. vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name()));
  1501. drag_type = DRAG_NONE;
  1502. return true;
  1503. }
  1504. // Cancel a drag
  1505. if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
  1506. _restore_canvas_item_state(drag_selection);
  1507. drag_type = DRAG_NONE;
  1508. viewport->update();
  1509. return true;
  1510. }
  1511. }
  1512. return false;
  1513. }
  1514. bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
  1515. Ref<InputEventMouseButton> b = p_event;
  1516. Ref<InputEventMouseMotion> m = p_event;
  1517. // Drag resize handles
  1518. if (drag_type == DRAG_NONE) {
  1519. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
  1520. List<CanvasItem *> selection = _get_edited_canvas_items();
  1521. if (selection.size() == 1) {
  1522. CanvasItem *canvas_item = selection[0];
  1523. if (canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) {
  1524. Rect2 rect = canvas_item->_edit_get_rect();
  1525. Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
  1526. Vector2 endpoints[4] = {
  1527. xform.xform(rect.position),
  1528. xform.xform(rect.position + Vector2(rect.size.x, 0)),
  1529. xform.xform(rect.position + rect.size),
  1530. xform.xform(rect.position + Vector2(0, rect.size.y))
  1531. };
  1532. DragType dragger[] = {
  1533. DRAG_TOP_LEFT,
  1534. DRAG_TOP,
  1535. DRAG_TOP_RIGHT,
  1536. DRAG_RIGHT,
  1537. DRAG_BOTTOM_RIGHT,
  1538. DRAG_BOTTOM,
  1539. DRAG_BOTTOM_LEFT,
  1540. DRAG_LEFT
  1541. };
  1542. DragType resize_drag = DRAG_NONE;
  1543. float radius = (select_handle->get_size().width / 2) * 1.5;
  1544. for (int i = 0; i < 4; i++) {
  1545. int prev = (i + 3) % 4;
  1546. int next = (i + 1) % 4;
  1547. Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
  1548. ofs *= (select_handle->get_size().width / 2);
  1549. ofs += endpoints[i];
  1550. if (ofs.distance_to(b->get_position()) < radius)
  1551. resize_drag = dragger[i * 2];
  1552. ofs = (endpoints[i] + endpoints[next]) / 2;
  1553. ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
  1554. if (ofs.distance_to(b->get_position()) < radius)
  1555. resize_drag = dragger[i * 2 + 1];
  1556. }
  1557. if (resize_drag != DRAG_NONE) {
  1558. drag_type = resize_drag;
  1559. drag_from = transform.affine_inverse().xform(b->get_position());
  1560. drag_selection = List<CanvasItem *>();
  1561. drag_selection.push_back(canvas_item);
  1562. _save_canvas_item_state(drag_selection);
  1563. return true;
  1564. }
  1565. }
  1566. }
  1567. }
  1568. }
  1569. if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM ||
  1570. drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
  1571. // Resize the node
  1572. if (m.is_valid()) {
  1573. CanvasItem *canvas_item = drag_selection[0];
  1574. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  1575. //Reset state
  1576. canvas_item->_edit_set_state(se->undo_state);
  1577. bool uniform = m->get_shift();
  1578. bool symmetric = m->get_alt();
  1579. Rect2 local_rect = canvas_item->_edit_get_rect();
  1580. float aspect = local_rect.get_size().y / local_rect.get_size().x;
  1581. Point2 current_begin = local_rect.get_position();
  1582. Point2 current_end = local_rect.get_position() + local_rect.get_size();
  1583. Point2 max_begin = (symmetric) ? (current_begin + current_end - canvas_item->_edit_get_minimum_size()) / 2.0 : current_end - canvas_item->_edit_get_minimum_size();
  1584. Point2 min_end = (symmetric) ? (current_begin + current_end + canvas_item->_edit_get_minimum_size()) / 2.0 : current_begin + canvas_item->_edit_get_minimum_size();
  1585. Point2 center = (current_begin + current_end) / 2.0;
  1586. drag_to = transform.affine_inverse().xform(m->get_position());
  1587. Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse();
  1588. Point2 drag_to_snapped_begin;
  1589. Point2 drag_to_snapped_end;
  1590. // last call decides which snapping lines are drawn
  1591. if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT) {
  1592. drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, canvas_item);
  1593. drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, canvas_item);
  1594. } else {
  1595. drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, canvas_item);
  1596. drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, canvas_item);
  1597. }
  1598. Point2 drag_begin = xform.xform(drag_to_snapped_begin);
  1599. Point2 drag_end = xform.xform(drag_to_snapped_end);
  1600. // Horizontal resize
  1601. if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
  1602. current_begin.x = MIN(drag_begin.x, max_begin.x);
  1603. } else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) {
  1604. current_end.x = MAX(drag_end.x, min_end.x);
  1605. }
  1606. // Vertical resize
  1607. if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
  1608. current_begin.y = MIN(drag_begin.y, max_begin.y);
  1609. } else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
  1610. current_end.y = MAX(drag_end.y, min_end.y);
  1611. }
  1612. // Uniform resize
  1613. if (uniform) {
  1614. if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT) {
  1615. current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x);
  1616. } else if (drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM) {
  1617. current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect;
  1618. } else {
  1619. if (aspect >= 1.0) {
  1620. if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
  1621. current_begin.y = current_end.y - aspect * (current_end.x - current_begin.x);
  1622. } else {
  1623. current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x);
  1624. }
  1625. } else {
  1626. if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
  1627. current_begin.x = current_end.x - (current_end.y - current_begin.y) / aspect;
  1628. } else {
  1629. current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect;
  1630. }
  1631. }
  1632. }
  1633. }
  1634. // Symmetric resize
  1635. if (symmetric) {
  1636. if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
  1637. current_end.x = 2.0 * center.x - current_begin.x;
  1638. } else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) {
  1639. current_begin.x = 2.0 * center.x - current_end.x;
  1640. }
  1641. if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
  1642. current_end.y = 2.0 * center.y - current_begin.y;
  1643. } else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
  1644. current_begin.y = 2.0 * center.y - current_end.y;
  1645. }
  1646. }
  1647. canvas_item->_edit_set_rect(Rect2(current_begin, current_end - current_begin));
  1648. return true;
  1649. }
  1650. // Confirm resize
  1651. if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
  1652. const Node2D *node2d = Object::cast_to<Node2D>(drag_selection[0]);
  1653. if (node2d) {
  1654. // Extends from Node2D.
  1655. // Node2D doesn't have an actual stored rect size, unlike Controls.
  1656. _commit_canvas_item_state(
  1657. drag_selection,
  1658. vformat(
  1659. TTR("Scale Node2D \"%s\" to (%s, %s)"),
  1660. drag_selection[0]->get_name(),
  1661. Math::stepify(drag_selection[0]->_edit_get_scale().x, 0.01),
  1662. Math::stepify(drag_selection[0]->_edit_get_scale().y, 0.01)),
  1663. true);
  1664. } else {
  1665. // Extends from Control.
  1666. _commit_canvas_item_state(
  1667. drag_selection,
  1668. vformat(
  1669. TTR("Resize Control \"%s\" to (%d, %d)"),
  1670. drag_selection[0]->get_name(),
  1671. drag_selection[0]->_edit_get_rect().size.x,
  1672. drag_selection[0]->_edit_get_rect().size.y),
  1673. true);
  1674. }
  1675. if (key_auto_insert_button->is_pressed()) {
  1676. _insert_animation_keys(false, false, true, true);
  1677. }
  1678. snap_target[0] = SNAP_TARGET_NONE;
  1679. snap_target[1] = SNAP_TARGET_NONE;
  1680. drag_type = DRAG_NONE;
  1681. viewport->update();
  1682. return true;
  1683. }
  1684. // Cancel a drag
  1685. if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
  1686. _restore_canvas_item_state(drag_selection);
  1687. snap_target[0] = SNAP_TARGET_NONE;
  1688. snap_target[1] = SNAP_TARGET_NONE;
  1689. drag_type = DRAG_NONE;
  1690. viewport->update();
  1691. return true;
  1692. }
  1693. }
  1694. return false;
  1695. }
  1696. bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
  1697. Ref<InputEventMouseButton> b = p_event;
  1698. Ref<InputEventMouseMotion> m = p_event;
  1699. // Drag resize handles
  1700. if (drag_type == DRAG_NONE) {
  1701. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) {
  1702. List<CanvasItem *> selection = _get_edited_canvas_items();
  1703. if (selection.size() == 1) {
  1704. CanvasItem *canvas_item = selection[0];
  1705. if (_is_node_movable(canvas_item)) {
  1706. Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
  1707. Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
  1708. Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
  1709. drag_type = DRAG_SCALE_BOTH;
  1710. Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE);
  1711. Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
  1712. if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) {
  1713. drag_type = DRAG_SCALE_X;
  1714. }
  1715. Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
  1716. if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) {
  1717. drag_type = DRAG_SCALE_Y;
  1718. }
  1719. drag_from = transform.affine_inverse().xform(b->get_position());
  1720. drag_selection = List<CanvasItem *>();
  1721. drag_selection.push_back(canvas_item);
  1722. _save_canvas_item_state(drag_selection);
  1723. return true;
  1724. }
  1725. }
  1726. }
  1727. }
  1728. if (drag_type == DRAG_SCALE_BOTH || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) {
  1729. // Resize the node
  1730. if (m.is_valid()) {
  1731. _restore_canvas_item_state(drag_selection);
  1732. CanvasItem *canvas_item = drag_selection[0];
  1733. drag_to = transform.affine_inverse().xform(m->get_position());
  1734. Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse();
  1735. Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized();
  1736. Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform;
  1737. bool uniform = m->get_shift();
  1738. bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
  1739. Point2 drag_from_local = simple_xform.xform(drag_from);
  1740. Point2 drag_to_local = simple_xform.xform(drag_to);
  1741. Point2 offset = drag_to_local - drag_from_local;
  1742. Size2 scale = canvas_item->call("get_scale");
  1743. float ratio = scale.y / scale.x;
  1744. if (drag_type == DRAG_SCALE_BOTH) {
  1745. Size2 scale_factor = drag_to_local / drag_from_local;
  1746. if (uniform) {
  1747. scale *= (scale_factor.x + scale_factor.y) / 2.0;
  1748. } else {
  1749. scale *= scale_factor;
  1750. }
  1751. } else {
  1752. Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE;
  1753. Size2 parent_scale = parent_xform.get_scale();
  1754. scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y);
  1755. if (drag_type == DRAG_SCALE_X) {
  1756. scale.x += scale_factor.x;
  1757. if (uniform) {
  1758. scale.y = scale.x * ratio;
  1759. }
  1760. } else if (drag_type == DRAG_SCALE_Y) {
  1761. scale.y += scale_factor.y;
  1762. if (uniform) {
  1763. scale.x = scale.y / ratio;
  1764. }
  1765. }
  1766. }
  1767. if (snap_scale && !is_ctrl) {
  1768. scale.x = roundf(scale.x / snap_scale_step) * snap_scale_step;
  1769. scale.y = roundf(scale.y / snap_scale_step) * snap_scale_step;
  1770. }
  1771. canvas_item->call("set_scale", scale);
  1772. return true;
  1773. }
  1774. // Confirm resize
  1775. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
  1776. if (drag_selection.size() != 1) {
  1777. _commit_canvas_item_state(
  1778. drag_selection,
  1779. vformat(TTR("Scale %d CanvasItems"), drag_selection.size()),
  1780. true);
  1781. } else {
  1782. _commit_canvas_item_state(
  1783. drag_selection,
  1784. vformat(TTR("Scale CanvasItem \"%s\" to (%s, %s)"),
  1785. drag_selection[0]->get_name(),
  1786. Math::stepify(drag_selection[0]->_edit_get_scale().x, 0.01),
  1787. Math::stepify(drag_selection[0]->_edit_get_scale().y, 0.01)),
  1788. true);
  1789. }
  1790. if (key_auto_insert_button->is_pressed()) {
  1791. _insert_animation_keys(false, false, true, true);
  1792. }
  1793. drag_type = DRAG_NONE;
  1794. viewport->update();
  1795. return true;
  1796. }
  1797. // Cancel a drag
  1798. if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
  1799. _restore_canvas_item_state(drag_selection);
  1800. drag_type = DRAG_NONE;
  1801. viewport->update();
  1802. return true;
  1803. }
  1804. }
  1805. return false;
  1806. }
  1807. bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
  1808. Ref<InputEventMouseButton> b = p_event;
  1809. Ref<InputEventMouseMotion> m = p_event;
  1810. Ref<InputEventKey> k = p_event;
  1811. if (drag_type == DRAG_NONE) {
  1812. //Start moving the nodes
  1813. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
  1814. if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) {
  1815. List<CanvasItem *> selection = _get_edited_canvas_items();
  1816. drag_selection.clear();
  1817. for (int i = 0; i < selection.size(); i++) {
  1818. if (_is_node_movable(selection[i], true)) {
  1819. drag_selection.push_back(selection[i]);
  1820. }
  1821. }
  1822. if (selection.size() > 0) {
  1823. drag_type = DRAG_MOVE;
  1824. drag_from = transform.affine_inverse().xform(b->get_position());
  1825. _save_canvas_item_state(drag_selection);
  1826. }
  1827. return true;
  1828. }
  1829. }
  1830. }
  1831. if (drag_type == DRAG_MOVE) {
  1832. // Move the nodes
  1833. if (m.is_valid()) {
  1834. // Save the ik chain for reapplying before IK solve
  1835. Vector<List<Dictionary> > all_bones_ik_states;
  1836. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1837. List<Dictionary> bones_ik_states;
  1838. _save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states);
  1839. all_bones_ik_states.push_back(bones_ik_states);
  1840. }
  1841. _restore_canvas_item_state(drag_selection, true);
  1842. drag_to = transform.affine_inverse().xform(m->get_position());
  1843. Point2 previous_pos;
  1844. if (!drag_selection.empty()) {
  1845. if (drag_selection.size() == 1) {
  1846. Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
  1847. previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
  1848. } else {
  1849. previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
  1850. }
  1851. }
  1852. Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES, 0, NULL, drag_selection);
  1853. bool single_axis = m->get_shift();
  1854. if (single_axis) {
  1855. if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) {
  1856. new_pos.y = previous_pos.y;
  1857. } else {
  1858. new_pos.x = previous_pos.x;
  1859. }
  1860. }
  1861. bool force_no_IK = m->get_alt();
  1862. int index = 0;
  1863. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1864. CanvasItem *canvas_item = E->get();
  1865. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  1866. if (se) {
  1867. Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
  1868. Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
  1869. if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
  1870. real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
  1871. _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
  1872. real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
  1873. node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
  1874. _solve_IK(node2d, new_pos);
  1875. } else {
  1876. canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
  1877. }
  1878. }
  1879. index++;
  1880. }
  1881. return true;
  1882. }
  1883. // Confirm the move (only if it was moved)
  1884. if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
  1885. if (transform.affine_inverse().xform(b->get_position()) != drag_from) {
  1886. if (drag_selection.size() != 1) {
  1887. _commit_canvas_item_state(
  1888. drag_selection,
  1889. vformat(TTR("Move %d CanvasItems"), drag_selection.size()),
  1890. true);
  1891. } else {
  1892. _commit_canvas_item_state(
  1893. drag_selection,
  1894. vformat(
  1895. TTR("Move CanvasItem \"%s\" to (%d, %d)"),
  1896. drag_selection[0]->get_name(),
  1897. drag_selection[0]->_edit_get_position().x,
  1898. drag_selection[0]->_edit_get_position().y),
  1899. true);
  1900. }
  1901. }
  1902. if (key_auto_insert_button->is_pressed()) {
  1903. _insert_animation_keys(true, false, false, true);
  1904. }
  1905. //Make sure smart snapping lines disappear.
  1906. snap_target[0] = SNAP_TARGET_NONE;
  1907. snap_target[1] = SNAP_TARGET_NONE;
  1908. drag_type = DRAG_NONE;
  1909. viewport->update();
  1910. return true;
  1911. }
  1912. // Cancel a drag
  1913. if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
  1914. _restore_canvas_item_state(drag_selection, true);
  1915. snap_target[0] = SNAP_TARGET_NONE;
  1916. snap_target[1] = SNAP_TARGET_NONE;
  1917. drag_type = DRAG_NONE;
  1918. viewport->update();
  1919. return true;
  1920. }
  1921. }
  1922. // Move the canvas items with the arrow keys
  1923. if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
  1924. (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
  1925. if (!k->is_echo()) {
  1926. // Start moving the canvas items with the keyboard
  1927. drag_selection = _get_edited_canvas_items();
  1928. drag_type = DRAG_KEY_MOVE;
  1929. drag_from = Vector2();
  1930. drag_to = Vector2();
  1931. _save_canvas_item_state(drag_selection, true);
  1932. }
  1933. if (drag_selection.size() > 0) {
  1934. // Save the ik chain for reapplying before IK solve
  1935. Vector<List<Dictionary> > all_bones_ik_states;
  1936. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1937. List<Dictionary> bones_ik_states;
  1938. _save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states);
  1939. all_bones_ik_states.push_back(bones_ik_states);
  1940. }
  1941. _restore_canvas_item_state(drag_selection, true);
  1942. bool move_local_base = k->get_alt();
  1943. bool move_local_base_rotated = k->get_control() || k->get_metakey();
  1944. Vector2 dir;
  1945. if (k->get_scancode() == KEY_UP)
  1946. dir += Vector2(0, -1);
  1947. else if (k->get_scancode() == KEY_DOWN)
  1948. dir += Vector2(0, 1);
  1949. else if (k->get_scancode() == KEY_LEFT)
  1950. dir += Vector2(-1, 0);
  1951. else if (k->get_scancode() == KEY_RIGHT)
  1952. dir += Vector2(1, 0);
  1953. if (k->get_shift())
  1954. dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
  1955. drag_to += dir;
  1956. if (k->get_shift())
  1957. drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier));
  1958. Point2 previous_pos;
  1959. if (drag_selection.size() == 1) {
  1960. Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
  1961. previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
  1962. } else {
  1963. previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
  1964. }
  1965. Point2 new_pos;
  1966. if (drag_selection.size() == 1) {
  1967. Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]);
  1968. if (node_2d && move_local_base_rotated) {
  1969. Transform2D m2;
  1970. m2.rotate(node_2d->get_rotation());
  1971. new_pos += m2.xform(drag_to);
  1972. } else if (move_local_base) {
  1973. new_pos += drag_to;
  1974. } else {
  1975. new_pos = previous_pos + (drag_to - drag_from);
  1976. }
  1977. } else {
  1978. new_pos = previous_pos + (drag_to - drag_from);
  1979. }
  1980. int index = 0;
  1981. for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
  1982. CanvasItem *canvas_item = E->get();
  1983. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  1984. if (se) {
  1985. Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
  1986. Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
  1987. if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
  1988. real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
  1989. _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
  1990. real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
  1991. node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
  1992. _solve_IK(node2d, new_pos);
  1993. } else {
  1994. canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
  1995. }
  1996. }
  1997. index++;
  1998. }
  1999. }
  2000. return true;
  2001. }
  2002. if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
  2003. (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
  2004. // Confirm canvas items move by arrow keys
  2005. if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) &&
  2006. (!Input::get_singleton()->is_key_pressed(KEY_DOWN)) &&
  2007. (!Input::get_singleton()->is_key_pressed(KEY_LEFT)) &&
  2008. (!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) {
  2009. if (drag_selection.size() > 1) {
  2010. _commit_canvas_item_state(
  2011. drag_selection,
  2012. vformat(TTR("Move %d CanvasItems"), drag_selection.size()),
  2013. true);
  2014. } else if (drag_selection.size() == 1) {
  2015. _commit_canvas_item_state(
  2016. drag_selection,
  2017. vformat(TTR("Move CanvasItem \"%s\" to (%d, %d)"),
  2018. drag_selection[0]->get_name(),
  2019. drag_selection[0]->_edit_get_position().x,
  2020. drag_selection[0]->_edit_get_position().y),
  2021. true);
  2022. }
  2023. drag_type = DRAG_NONE;
  2024. }
  2025. viewport->update();
  2026. return true;
  2027. }
  2028. return (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)); // Accept the key event in any case
  2029. }
  2030. bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
  2031. Ref<InputEventMouseButton> b = p_event;
  2032. Ref<InputEventMouseMotion> m = p_event;
  2033. Ref<InputEventKey> k = p_event;
  2034. if (drag_type == DRAG_NONE) {
  2035. if (b.is_valid() &&
  2036. ((b->get_button_index() == BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) ||
  2037. (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT))) {
  2038. // Popup the selection menu list
  2039. Point2 click = transform.affine_inverse().xform(b->get_position());
  2040. _get_canvas_items_at_pos(click, selection_results);
  2041. if (selection_results.size() == 1) {
  2042. CanvasItem *item = selection_results[0].item;
  2043. selection_results.clear();
  2044. _select_click_on_item(item, click, b->get_shift());
  2045. return true;
  2046. } else if (!selection_results.empty()) {
  2047. // Sorts items according the their z-index
  2048. selection_results.sort();
  2049. NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
  2050. StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
  2051. for (int i = 0; i < selection_results.size(); i++) {
  2052. CanvasItem *item = selection_results[i].item;
  2053. Ref<Texture> icon = EditorNode::get_singleton()->get_object_icon(item, "Node");
  2054. String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path());
  2055. selection_menu->add_item(item->get_name());
  2056. selection_menu->set_item_icon(i, icon);
  2057. selection_menu->set_item_metadata(i, node_path);
  2058. selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path);
  2059. }
  2060. selection_menu_additive_selection = b->get_shift();
  2061. selection_menu->set_global_position(b->get_global_position());
  2062. selection_menu->popup();
  2063. return true;
  2064. }
  2065. }
  2066. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
  2067. // Single item selection
  2068. Point2 click = transform.affine_inverse().xform(b->get_position());
  2069. Node *scene = editor->get_edited_scene();
  2070. if (!scene)
  2071. return true;
  2072. // Find the item to select
  2073. CanvasItem *canvas_item = NULL;
  2074. // Retrieve the bones
  2075. Vector<_SelectResult> selection = Vector<_SelectResult>();
  2076. _get_bones_at_pos(click, selection);
  2077. if (!selection.empty()) {
  2078. canvas_item = selection[0].item;
  2079. } else {
  2080. // Retrieve the canvas items
  2081. selection = Vector<_SelectResult>();
  2082. _get_canvas_items_at_pos(click, selection);
  2083. if (!selection.empty()) {
  2084. canvas_item = selection[0].item;
  2085. }
  2086. }
  2087. if (!canvas_item) {
  2088. // Start a box selection
  2089. if (!b->get_shift()) {
  2090. // Clear the selection if not additive
  2091. editor_selection->clear();
  2092. viewport->update();
  2093. selected_from_canvas = true;
  2094. };
  2095. drag_from = click;
  2096. drag_type = DRAG_BOX_SELECTION;
  2097. box_selecting_to = drag_from;
  2098. return true;
  2099. } else {
  2100. bool still_selected = _select_click_on_item(canvas_item, click, b->get_shift());
  2101. // Start dragging
  2102. if (still_selected) {
  2103. // Drag the node(s) if requested
  2104. List<CanvasItem *> selection2 = _get_edited_canvas_items();
  2105. drag_selection.clear();
  2106. for (int i = 0; i < selection2.size(); i++) {
  2107. if (_is_node_movable(selection2[i], true)) {
  2108. drag_selection.push_back(selection2[i]);
  2109. }
  2110. }
  2111. if (selection2.size() > 0) {
  2112. drag_type = DRAG_MOVE;
  2113. drag_from = click;
  2114. _save_canvas_item_state(drag_selection);
  2115. }
  2116. }
  2117. // Select the item
  2118. return true;
  2119. }
  2120. }
  2121. }
  2122. if (drag_type == DRAG_BOX_SELECTION) {
  2123. if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
  2124. // Confirms box selection
  2125. Node *scene = editor->get_edited_scene();
  2126. if (scene) {
  2127. List<CanvasItem *> selitems;
  2128. Point2 bsfrom = drag_from;
  2129. Point2 bsto = box_selecting_to;
  2130. if (bsfrom.x > bsto.x)
  2131. SWAP(bsfrom.x, bsto.x);
  2132. if (bsfrom.y > bsto.y)
  2133. SWAP(bsfrom.y, bsto.y);
  2134. _find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems);
  2135. for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) {
  2136. editor_selection->add_node(E->get());
  2137. }
  2138. }
  2139. drag_type = DRAG_NONE;
  2140. viewport->update();
  2141. return true;
  2142. }
  2143. if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
  2144. // Cancel box selection
  2145. drag_type = DRAG_NONE;
  2146. viewport->update();
  2147. return true;
  2148. }
  2149. if (m.is_valid()) {
  2150. // Update box selection
  2151. box_selecting_to = transform.affine_inverse().xform(m->get_position());
  2152. viewport->update();
  2153. return true;
  2154. }
  2155. }
  2156. if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
  2157. // Unselect everything
  2158. editor_selection->clear();
  2159. viewport->update();
  2160. }
  2161. return false;
  2162. }
  2163. bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) {
  2164. if (tool != TOOL_RULER) {
  2165. ruler_tool_active = false;
  2166. return false;
  2167. }
  2168. Ref<InputEventMouseButton> b = p_event;
  2169. Ref<InputEventMouseMotion> m = p_event;
  2170. Point2 previous_origin = ruler_tool_origin;
  2171. if (!ruler_tool_active)
  2172. ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset);
  2173. if (b.is_valid() && b->get_button_index() == BUTTON_LEFT) {
  2174. if (b->is_pressed()) {
  2175. ruler_tool_active = true;
  2176. } else {
  2177. ruler_tool_active = false;
  2178. }
  2179. viewport->update();
  2180. return true;
  2181. }
  2182. if (m.is_valid() && (ruler_tool_active || (grid_snap_active && previous_origin != ruler_tool_origin))) {
  2183. viewport->update();
  2184. return true;
  2185. }
  2186. return false;
  2187. }
  2188. bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) {
  2189. Ref<InputEventMouseMotion> m = p_event;
  2190. if (m.is_valid()) {
  2191. Point2 click = transform.affine_inverse().xform(m->get_position());
  2192. // Checks if the hovered items changed, update the viewport if so
  2193. Vector<_SelectResult> hovering_results_items;
  2194. _get_canvas_items_at_pos(click, hovering_results_items);
  2195. hovering_results_items.sort();
  2196. // Compute the nodes names and icon position
  2197. Vector<_HoverResult> hovering_results_tmp;
  2198. for (int i = 0; i < hovering_results_items.size(); i++) {
  2199. CanvasItem *canvas_item = hovering_results_items[i].item;
  2200. if (canvas_item->_edit_use_rect())
  2201. continue;
  2202. _HoverResult hover_result;
  2203. hover_result.position = canvas_item->get_global_transform_with_canvas().get_origin();
  2204. hover_result.icon = EditorNode::get_singleton()->get_object_icon(canvas_item);
  2205. hover_result.name = canvas_item->get_name();
  2206. hovering_results_tmp.push_back(hover_result);
  2207. }
  2208. // Check if changed, if so, update.
  2209. bool changed = false;
  2210. if (hovering_results_tmp.size() == hovering_results.size()) {
  2211. for (int i = 0; i < hovering_results_tmp.size(); i++) {
  2212. _HoverResult a = hovering_results_tmp[i];
  2213. _HoverResult b = hovering_results[i];
  2214. if (a.icon != b.icon || a.name != b.name || a.position != b.position) {
  2215. changed = true;
  2216. break;
  2217. }
  2218. }
  2219. } else {
  2220. changed = true;
  2221. }
  2222. if (changed) {
  2223. hovering_results = hovering_results_tmp;
  2224. viewport->update();
  2225. }
  2226. return true;
  2227. }
  2228. return false;
  2229. }
  2230. void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
  2231. bool accepted = false;
  2232. if (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || !pan_pressed) {
  2233. if ((accepted = _gui_input_rulers_and_guides(p_event))) {
  2234. //printf("Rulers and guides\n");
  2235. } else if ((accepted = editor->get_editor_plugins_over()->forward_gui_input(p_event))) {
  2236. //printf("Plugin\n");
  2237. } else if ((accepted = _gui_input_open_scene_on_double_click(p_event))) {
  2238. //printf("Open scene on double click\n");
  2239. } else if ((accepted = _gui_input_scale(p_event))) {
  2240. //printf("Set scale\n");
  2241. } else if ((accepted = _gui_input_pivot(p_event))) {
  2242. //printf("Set pivot\n");
  2243. } else if ((accepted = _gui_input_resize(p_event))) {
  2244. //printf("Resize\n");
  2245. } else if ((accepted = _gui_input_rotate(p_event))) {
  2246. //printf("Rotate\n");
  2247. } else if ((accepted = _gui_input_move(p_event))) {
  2248. //printf("Move\n");
  2249. } else if ((accepted = _gui_input_anchors(p_event))) {
  2250. //printf("Anchors\n");
  2251. } else if ((accepted = _gui_input_select(p_event))) {
  2252. //printf("Selection\n");
  2253. } else if ((accepted = _gui_input_ruler_tool(p_event))) {
  2254. //printf("Measure\n");
  2255. } else {
  2256. //printf("Not accepted\n");
  2257. }
  2258. }
  2259. accepted = (_gui_input_zoom_or_pan(p_event, accepted) || accepted);
  2260. if (accepted)
  2261. accept_event();
  2262. // Handles the mouse hovering
  2263. _gui_input_hover(p_event);
  2264. // Compute an eventual rotation of the cursor
  2265. CursorShape rotation_array[4] = { CURSOR_HSIZE, CURSOR_BDIAGSIZE, CURSOR_VSIZE, CURSOR_FDIAGSIZE };
  2266. int rotation_array_index = 0;
  2267. List<CanvasItem *> selection = _get_edited_canvas_items();
  2268. if (selection.size() == 1) {
  2269. float angle = Math::fposmod((double)selection[0]->get_global_transform_with_canvas().get_rotation(), Math_PI);
  2270. if (angle > Math_PI * 7.0 / 8.0) {
  2271. rotation_array_index = 0;
  2272. } else if (angle > Math_PI * 5.0 / 8.0) {
  2273. rotation_array_index = 1;
  2274. } else if (angle > Math_PI * 3.0 / 8.0) {
  2275. rotation_array_index = 2;
  2276. } else if (angle > Math_PI * 1.0 / 8.0) {
  2277. rotation_array_index = 3;
  2278. } else {
  2279. rotation_array_index = 0;
  2280. }
  2281. }
  2282. // Choose the correct cursor
  2283. CursorShape c = CURSOR_ARROW;
  2284. switch (drag_type) {
  2285. case DRAG_NONE:
  2286. switch (tool) {
  2287. case TOOL_MOVE:
  2288. c = CURSOR_MOVE;
  2289. break;
  2290. case TOOL_EDIT_PIVOT:
  2291. c = CURSOR_CROSS;
  2292. break;
  2293. case TOOL_PAN:
  2294. c = CURSOR_DRAG;
  2295. break;
  2296. case TOOL_RULER:
  2297. c = CURSOR_CROSS;
  2298. break;
  2299. default:
  2300. break;
  2301. }
  2302. break;
  2303. case DRAG_LEFT:
  2304. case DRAG_RIGHT:
  2305. c = rotation_array[rotation_array_index];
  2306. break;
  2307. case DRAG_V_GUIDE:
  2308. c = CURSOR_HSIZE;
  2309. break;
  2310. case DRAG_TOP:
  2311. case DRAG_BOTTOM:
  2312. c = rotation_array[(rotation_array_index + 2) % 4];
  2313. break;
  2314. case DRAG_H_GUIDE:
  2315. c = CURSOR_VSIZE;
  2316. break;
  2317. case DRAG_TOP_LEFT:
  2318. case DRAG_BOTTOM_RIGHT:
  2319. c = rotation_array[(rotation_array_index + 3) % 4];
  2320. break;
  2321. case DRAG_DOUBLE_GUIDE:
  2322. c = CURSOR_FDIAGSIZE;
  2323. break;
  2324. case DRAG_TOP_RIGHT:
  2325. case DRAG_BOTTOM_LEFT:
  2326. c = rotation_array[(rotation_array_index + 1) % 4];
  2327. break;
  2328. case DRAG_MOVE:
  2329. c = CURSOR_MOVE;
  2330. break;
  2331. default:
  2332. break;
  2333. }
  2334. if (is_hovering_h_guide)
  2335. c = CURSOR_VSIZE;
  2336. else if (is_hovering_v_guide)
  2337. c = CURSOR_HSIZE;
  2338. viewport->set_default_cursor_shape(c);
  2339. // Grab focus
  2340. if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
  2341. viewport->call_deferred("grab_focus");
  2342. }
  2343. }
  2344. void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) {
  2345. Color color = get_color("font_color", "Editor");
  2346. color.a = 0.8;
  2347. Ref<Font> font = get_font("font", "Label");
  2348. Size2 text_size = font->get_string_size(p_string);
  2349. switch (p_side) {
  2350. case MARGIN_LEFT:
  2351. p_position += Vector2(-text_size.x - 5, text_size.y / 2);
  2352. break;
  2353. case MARGIN_TOP:
  2354. p_position += Vector2(-text_size.x / 2, -5);
  2355. break;
  2356. case MARGIN_RIGHT:
  2357. p_position += Vector2(5, text_size.y / 2);
  2358. break;
  2359. case MARGIN_BOTTOM:
  2360. p_position += Vector2(-text_size.x / 2, text_size.y + 5);
  2361. break;
  2362. }
  2363. viewport->draw_string(font, p_position, p_string, color);
  2364. }
  2365. void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) {
  2366. String str = vformat("%d px", p_value);
  2367. if (p_value != 0) {
  2368. _draw_text_at_position(p_position, str, p_side);
  2369. }
  2370. }
  2371. void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) {
  2372. String str = vformat("%.1f %%", p_value * 100.0);
  2373. if (p_value != 0) {
  2374. _draw_text_at_position(p_position, str, p_side);
  2375. }
  2376. }
  2377. void CanvasItemEditor::_draw_focus() {
  2378. // Draw the focus around the base viewport
  2379. if (viewport->has_focus()) {
  2380. get_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size()));
  2381. }
  2382. }
  2383. void CanvasItemEditor::_draw_guides() {
  2384. Color guide_color = EditorSettings::get_singleton()->get("editors/2d/guides_color");
  2385. Transform2D xform = viewport_scrollable->get_transform() * transform;
  2386. // Guides already there
  2387. if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
  2388. Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
  2389. for (int i = 0; i < vguides.size(); i++) {
  2390. if (drag_type == DRAG_V_GUIDE && i == dragged_guide_index)
  2391. continue;
  2392. float x = xform.xform(Point2(vguides[i], 0)).x;
  2393. viewport->draw_line(Point2(x, 0), Point2(x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
  2394. }
  2395. }
  2396. if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
  2397. Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
  2398. for (int i = 0; i < hguides.size(); i++) {
  2399. if (drag_type == DRAG_H_GUIDE && i == dragged_guide_index)
  2400. continue;
  2401. float y = xform.xform(Point2(0, hguides[i])).y;
  2402. viewport->draw_line(Point2(0, y), Point2(viewport->get_size().x, y), guide_color, Math::round(EDSCALE));
  2403. }
  2404. }
  2405. // Dragged guide
  2406. Color text_color = get_color("font_color", "Editor");
  2407. text_color.a = 0.5;
  2408. if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
  2409. String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x));
  2410. Ref<Font> font = get_font("font", "Label");
  2411. Size2 text_size = font->get_string_size(str);
  2412. viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color);
  2413. viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
  2414. }
  2415. if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
  2416. String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y));
  2417. Ref<Font> font = get_font("font", "Label");
  2418. Size2 text_size = font->get_string_size(str);
  2419. viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, text_color);
  2420. viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE));
  2421. }
  2422. }
  2423. void CanvasItemEditor::_draw_smart_snapping() {
  2424. Color line_color = EditorSettings::get_singleton()->get("editors/2d/smart_snapping_line_color");
  2425. if (snap_target[0] != SNAP_TARGET_NONE && snap_target[0] != SNAP_TARGET_GRID) {
  2426. viewport->draw_set_transform_matrix(viewport->get_transform() * transform * snap_transform);
  2427. viewport->draw_line(Point2(0, -1.0e+10F), Point2(0, 1.0e+10F), line_color);
  2428. viewport->draw_set_transform_matrix(viewport->get_transform());
  2429. }
  2430. if (snap_target[1] != SNAP_TARGET_NONE && snap_target[1] != SNAP_TARGET_GRID) {
  2431. viewport->draw_set_transform_matrix(viewport->get_transform() * transform * snap_transform);
  2432. viewport->draw_line(Point2(-1.0e+10F, 0), Point2(1.0e+10F, 0), line_color);
  2433. viewport->draw_set_transform_matrix(viewport->get_transform());
  2434. }
  2435. }
  2436. void CanvasItemEditor::_draw_rulers() {
  2437. Color bg_color = get_color("dark_color_2", "Editor");
  2438. Color graduation_color = get_color("font_color", "Editor").linear_interpolate(bg_color, 0.5);
  2439. Color font_color = get_color("font_color", "Editor");
  2440. font_color.a = 0.8;
  2441. Ref<Font> font = get_font("rulers", "EditorFonts");
  2442. // The rule transform
  2443. Transform2D ruler_transform = Transform2D();
  2444. if (show_grid || grid_snap_active) {
  2445. List<CanvasItem *> selection = _get_edited_canvas_items();
  2446. if (snap_relative && selection.size() > 0) {
  2447. ruler_transform.translate(_get_encompassing_rect_from_list(selection).position);
  2448. ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
  2449. } else {
  2450. ruler_transform.translate(grid_offset);
  2451. ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
  2452. }
  2453. while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) {
  2454. ruler_transform.scale_basis(Point2(2, 2));
  2455. }
  2456. } else {
  2457. float basic_rule = 100;
  2458. for (int i = 0; basic_rule * zoom > 100; i++) {
  2459. basic_rule /= (i % 2) ? 5.0 : 2.0;
  2460. }
  2461. for (int i = 0; basic_rule * zoom < 100; i++) {
  2462. basic_rule *= (i % 2) ? 2.0 : 5.0;
  2463. }
  2464. ruler_transform.scale(Size2(basic_rule, basic_rule));
  2465. }
  2466. // Subdivisions
  2467. int major_subdivision = 2;
  2468. Transform2D major_subdivide = Transform2D();
  2469. major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision));
  2470. int minor_subdivision = 5;
  2471. Transform2D minor_subdivide = Transform2D();
  2472. minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision));
  2473. // First and last graduations to draw (in the ruler space)
  2474. Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2(RULER_WIDTH, RULER_WIDTH));
  2475. Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size());
  2476. // Draw top ruler
  2477. viewport->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color);
  2478. for (int i = Math::ceil(first.x); i < last.x; i++) {
  2479. Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0));
  2480. if (i % (major_subdivision * minor_subdivision) == 0) {
  2481. viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
  2482. float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
  2483. viewport->draw_string(font, Point2(position.x + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
  2484. } else {
  2485. if (i % minor_subdivision == 0) {
  2486. viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
  2487. } else {
  2488. viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.75), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
  2489. }
  2490. }
  2491. }
  2492. // Draw left ruler
  2493. viewport->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color);
  2494. for (int i = Math::ceil(first.y); i < last.y; i++) {
  2495. Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i));
  2496. if (i % (major_subdivision * minor_subdivision) == 0) {
  2497. viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
  2498. float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y;
  2499. Transform2D text_xform = Transform2D(-Math_PI / 2.0, Point2(font->get_height(), position.y - 2));
  2500. viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform);
  2501. viewport->draw_string(font, Point2(), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
  2502. viewport->draw_set_transform_matrix(viewport->get_transform());
  2503. } else {
  2504. if (i % minor_subdivision == 0) {
  2505. viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
  2506. } else {
  2507. viewport->draw_line(Point2(RULER_WIDTH * 0.75, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
  2508. }
  2509. }
  2510. }
  2511. // Draw the top left corner
  2512. viewport->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
  2513. }
  2514. void CanvasItemEditor::_draw_grid() {
  2515. if (show_grid || grid_snap_active) {
  2516. // Draw the grid
  2517. Vector2 real_grid_offset;
  2518. const List<CanvasItem *> selection = _get_edited_canvas_items();
  2519. if (snap_relative && selection.size() > 0) {
  2520. const Vector2 topleft = _get_encompassing_rect_from_list(selection).position;
  2521. real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier));
  2522. real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier));
  2523. } else {
  2524. real_grid_offset = grid_offset;
  2525. }
  2526. // Draw a "primary" line every several lines to make measurements easier.
  2527. // The step is configurable in the Configure Snap dialog.
  2528. const Color secondary_grid_color = EditorSettings::get_singleton()->get("editors/2d/grid_color");
  2529. const Color primary_grid_color =
  2530. Color(secondary_grid_color.r, secondary_grid_color.g, secondary_grid_color.b, secondary_grid_color.a * 2.5);
  2531. const Size2 viewport_size = viewport->get_size();
  2532. const Transform2D xform = transform.affine_inverse();
  2533. int last_cell = 0;
  2534. if (grid_step.x != 0) {
  2535. for (int i = 0; i < viewport_size.width; i++) {
  2536. const int cell =
  2537. Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier))));
  2538. if (i == 0) {
  2539. last_cell = cell;
  2540. }
  2541. if (last_cell != cell) {
  2542. Color grid_color;
  2543. if (primary_grid_steps == 0) {
  2544. grid_color = secondary_grid_color;
  2545. } else {
  2546. grid_color = cell % primary_grid_steps == 0 ? primary_grid_color : secondary_grid_color;
  2547. }
  2548. viewport->draw_line(Point2(i, 0), Point2(i, viewport_size.height), grid_color, Math::round(EDSCALE));
  2549. }
  2550. last_cell = cell;
  2551. }
  2552. }
  2553. if (grid_step.y != 0) {
  2554. for (int i = 0; i < viewport_size.height; i++) {
  2555. const int cell =
  2556. Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier))));
  2557. if (i == 0) {
  2558. last_cell = cell;
  2559. }
  2560. if (last_cell != cell) {
  2561. Color grid_color;
  2562. if (primary_grid_steps == 0) {
  2563. grid_color = secondary_grid_color;
  2564. } else {
  2565. grid_color = cell % primary_grid_steps == 0 ? primary_grid_color : secondary_grid_color;
  2566. }
  2567. viewport->draw_line(Point2(0, i), Point2(viewport_size.width, i), grid_color, Math::round(EDSCALE));
  2568. }
  2569. last_cell = cell;
  2570. }
  2571. }
  2572. }
  2573. }
  2574. void CanvasItemEditor::_draw_ruler_tool() {
  2575. if (tool != TOOL_RULER)
  2576. return;
  2577. if (ruler_tool_active) {
  2578. Color ruler_primary_color = get_color("accent_color", "Editor");
  2579. Color ruler_secondary_color = ruler_primary_color;
  2580. ruler_secondary_color.a = 0.5;
  2581. Point2 begin = (ruler_tool_origin - view_offset) * zoom;
  2582. Point2 end = snap_point(viewport->get_local_mouse_position() / zoom + view_offset) * zoom - view_offset * zoom;
  2583. Point2 corner = Point2(begin.x, end.y);
  2584. Vector2 length_vector = (begin - end).abs() / zoom;
  2585. bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
  2586. viewport->draw_line(begin, end, ruler_primary_color, Math::round(EDSCALE * 3), true);
  2587. if (draw_secondary_lines) {
  2588. viewport->draw_line(begin, corner, ruler_secondary_color, Math::round(EDSCALE));
  2589. viewport->draw_line(corner, end, ruler_secondary_color, Math::round(EDSCALE));
  2590. }
  2591. Ref<Font> font = get_font("bold", "EditorFonts");
  2592. Color font_color = get_color("font_color", "Editor");
  2593. Color font_secondary_color = font_color;
  2594. font_secondary_color.a = 0.5;
  2595. float text_height = font->get_height();
  2596. const float text_width = 76;
  2597. const float angle_text_width = 54;
  2598. Point2 text_pos = (begin + end) / 2 - Vector2(text_width / 2, text_height / 2);
  2599. text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
  2600. text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
  2601. viewport->draw_string(font, text_pos, vformat("%.2f px", length_vector.length()), font_color);
  2602. if (draw_secondary_lines) {
  2603. const float horizontal_angle_rad = atan2(length_vector.y, length_vector.x);
  2604. const float vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad;
  2605. const int horizontal_angle = round(180 * horizontal_angle_rad / Math_PI);
  2606. const int vertical_angle = round(180 * vertical_angle_rad / Math_PI);
  2607. Point2 text_pos2 = text_pos;
  2608. text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
  2609. viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.y), font_secondary_color);
  2610. Point2 v_angle_text_pos = Point2();
  2611. v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
  2612. v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
  2613. viewport->draw_string(font, v_angle_text_pos, vformat("%d deg", vertical_angle), font_secondary_color);
  2614. text_pos2 = text_pos;
  2615. text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
  2616. viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.x), font_secondary_color);
  2617. Point2 h_angle_text_pos = Point2();
  2618. h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
  2619. if (begin.y < end.y) {
  2620. h_angle_text_pos.y = end.y + text_height * 1.5;
  2621. if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
  2622. int height_multiplier = 1.5 + (int)grid_snap_active;
  2623. h_angle_text_pos.y = MAX(text_pos.y + height_multiplier * text_height, MAX(end.y + text_height * 1.5, text_pos2.y + height_multiplier * text_height));
  2624. }
  2625. } else {
  2626. h_angle_text_pos.y = end.y - text_height * 0.5;
  2627. if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
  2628. int height_multiplier = 1 + (int)grid_snap_active;
  2629. h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
  2630. }
  2631. }
  2632. viewport->draw_string(font, h_angle_text_pos, vformat("%d deg", horizontal_angle), font_secondary_color);
  2633. // Angle arcs
  2634. int arc_point_count = 8;
  2635. float arc_radius_max_length_percent = 0.1;
  2636. float ruler_length = length_vector.length() * zoom;
  2637. float arc_max_radius = 50.0;
  2638. float arc_line_width = 2.0;
  2639. const Vector2 end_to_begin = (end - begin);
  2640. float arc_1_start_angle =
  2641. end_to_begin.x < 0 ?
  2642. (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0) :
  2643. (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad);
  2644. float arc_1_end_angle = arc_1_start_angle + vertical_angle_rad;
  2645. // Constrain arc to triangle height & max size
  2646. float arc_1_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.y)), arc_max_radius);
  2647. float arc_2_start_angle =
  2648. end_to_begin.x < 0 ?
  2649. (end_to_begin.y < 0 ? 0.0 : -horizontal_angle_rad) :
  2650. (end_to_begin.y < 0 ? Math_PI - horizontal_angle_rad : Math_PI);
  2651. float arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad;
  2652. // Constrain arc to triangle width & max size
  2653. float arc_2_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.x)), arc_max_radius);
  2654. viewport->draw_arc(begin, arc_1_radius, arc_1_start_angle, arc_1_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width));
  2655. viewport->draw_arc(end, arc_2_radius, arc_2_start_angle, arc_2_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width));
  2656. }
  2657. if (grid_snap_active) {
  2658. text_pos = (begin + end) / 2 + Vector2(-text_width / 2, text_height / 2);
  2659. text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
  2660. text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2);
  2661. if (draw_secondary_lines) {
  2662. viewport->draw_string(font, text_pos, vformat("%.2f units", (length_vector / grid_step).length()), font_color);
  2663. Point2 text_pos2 = text_pos;
  2664. text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
  2665. viewport->draw_string(font, text_pos2, vformat("%d units", roundf(length_vector.y / grid_step.y)), font_secondary_color);
  2666. text_pos2 = text_pos;
  2667. text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2);
  2668. viewport->draw_string(font, text_pos2, vformat("%d units", roundf(length_vector.x / grid_step.x)), font_secondary_color);
  2669. } else {
  2670. viewport->draw_string(font, text_pos, vformat("%d units", roundf((length_vector / grid_step).length())), font_color);
  2671. }
  2672. }
  2673. } else {
  2674. if (grid_snap_active) {
  2675. Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons");
  2676. viewport->draw_texture(get_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
  2677. }
  2678. }
  2679. }
  2680. void CanvasItemEditor::_draw_control_anchors(Control *control) {
  2681. Transform2D xform = transform * control->get_global_transform_with_canvas();
  2682. RID ci = viewport->get_canvas_item();
  2683. if (tool == TOOL_SELECT && !Object::cast_to<Container>(control->get_parent())) {
  2684. // Compute the anchors
  2685. float anchors_values[4];
  2686. anchors_values[0] = control->get_anchor(MARGIN_LEFT);
  2687. anchors_values[1] = control->get_anchor(MARGIN_TOP);
  2688. anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
  2689. anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
  2690. Vector2 anchors_pos[4];
  2691. for (int i = 0; i < 4; i++) {
  2692. Vector2 value = Vector2((i % 2 == 0) ? anchors_values[i] : anchors_values[(i + 1) % 4], (i % 2 == 1) ? anchors_values[i] : anchors_values[(i + 1) % 4]);
  2693. anchors_pos[i] = xform.xform(_anchor_to_position(control, value));
  2694. }
  2695. // Draw the anchors handles
  2696. Rect2 anchor_rects[4];
  2697. anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size());
  2698. anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y));
  2699. anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size());
  2700. anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y));
  2701. for (int i = 0; i < 4; i++) {
  2702. anchor_handle->draw_rect(ci, anchor_rects[i]);
  2703. }
  2704. }
  2705. }
  2706. void CanvasItemEditor::_draw_control_helpers(Control *control) {
  2707. Transform2D xform = transform * control->get_global_transform_with_canvas();
  2708. if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
  2709. // Draw the helpers
  2710. Color color_base = Color(0.8, 0.8, 0.8, 0.5);
  2711. // Compute the anchors
  2712. float anchors_values[4];
  2713. anchors_values[0] = control->get_anchor(MARGIN_LEFT);
  2714. anchors_values[1] = control->get_anchor(MARGIN_TOP);
  2715. anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
  2716. anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
  2717. Vector2 anchors[4];
  2718. Vector2 anchors_pos[4];
  2719. for (int i = 0; i < 4; i++) {
  2720. anchors[i] = Vector2((i % 2 == 0) ? anchors_values[i] : anchors_values[(i + 1) % 4], (i % 2 == 1) ? anchors_values[i] : anchors_values[(i + 1) % 4]);
  2721. anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i]));
  2722. }
  2723. // Get which anchor is dragged
  2724. int dragged_anchor = -1;
  2725. switch (drag_type) {
  2726. case DRAG_ANCHOR_ALL:
  2727. case DRAG_ANCHOR_TOP_LEFT:
  2728. dragged_anchor = 0;
  2729. break;
  2730. case DRAG_ANCHOR_TOP_RIGHT:
  2731. dragged_anchor = 1;
  2732. break;
  2733. case DRAG_ANCHOR_BOTTOM_RIGHT:
  2734. dragged_anchor = 2;
  2735. break;
  2736. case DRAG_ANCHOR_BOTTOM_LEFT:
  2737. dragged_anchor = 3;
  2738. break;
  2739. default:
  2740. break;
  2741. }
  2742. if (dragged_anchor >= 0) {
  2743. // Draw the 4 lines when dragged
  2744. bool anchor_snapped;
  2745. Color color_snapped = Color(0.64, 0.93, 0.67, 0.5);
  2746. Vector2 corners_pos[4];
  2747. for (int i = 0; i < 4; i++) {
  2748. corners_pos[i] = xform.xform(_anchor_to_position(control, Vector2((i == 0 || i == 3) ? ANCHOR_BEGIN : ANCHOR_END, (i <= 1) ? ANCHOR_BEGIN : ANCHOR_END)));
  2749. }
  2750. Vector2 line_starts[4];
  2751. Vector2 line_ends[4];
  2752. for (int i = 0; i < 4; i++) {
  2753. float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i];
  2754. line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val);
  2755. line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val);
  2756. anchor_snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0;
  2757. viewport->draw_line(line_starts[i], line_ends[i], anchor_snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1);
  2758. }
  2759. // Display the percentages next to the lines
  2760. float percent_val;
  2761. percent_val = anchors_values[(dragged_anchor + 2) % 4] - anchors_values[dragged_anchor];
  2762. percent_val = (dragged_anchor >= 2) ? -percent_val : percent_val;
  2763. _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 1) % 4]) / 2, (Margin)((dragged_anchor + 1) % 4));
  2764. percent_val = anchors_values[(dragged_anchor + 3) % 4] - anchors_values[(dragged_anchor + 1) % 4];
  2765. percent_val = ((dragged_anchor + 1) % 4 >= 2) ? -percent_val : percent_val;
  2766. _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Margin)(dragged_anchor));
  2767. percent_val = anchors_values[(dragged_anchor + 1) % 4];
  2768. percent_val = ((dragged_anchor + 1) % 4 >= 2) ? ANCHOR_END - percent_val : percent_val;
  2769. _draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Margin)(dragged_anchor));
  2770. percent_val = anchors_values[dragged_anchor];
  2771. percent_val = (dragged_anchor >= 2) ? ANCHOR_END - percent_val : percent_val;
  2772. _draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Margin)((dragged_anchor + 1) % 4));
  2773. }
  2774. // Draw the margin values and the node width/height when dragging control side
  2775. float ratio = 0.33;
  2776. Transform2D parent_transform = xform * control->get_transform().affine_inverse();
  2777. float node_pos_in_parent[4];
  2778. Rect2 parent_rect = control->get_parent_anchorable_rect();
  2779. node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * parent_rect.size.width + control->get_margin(MARGIN_LEFT) + parent_rect.position.x;
  2780. node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * parent_rect.size.height + control->get_margin(MARGIN_TOP) + parent_rect.position.y;
  2781. node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * parent_rect.size.width + control->get_margin(MARGIN_RIGHT) + parent_rect.position.x;
  2782. node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * parent_rect.size.height + control->get_margin(MARGIN_BOTTOM) + parent_rect.position.y;
  2783. Point2 start, end;
  2784. switch (drag_type) {
  2785. case DRAG_LEFT:
  2786. case DRAG_TOP_LEFT:
  2787. case DRAG_BOTTOM_LEFT:
  2788. _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
  2789. FALLTHROUGH;
  2790. case DRAG_MOVE:
  2791. start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio));
  2792. end = start - Vector2(control->get_margin(MARGIN_LEFT), 0);
  2793. _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP);
  2794. viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
  2795. break;
  2796. default:
  2797. break;
  2798. }
  2799. switch (drag_type) {
  2800. case DRAG_RIGHT:
  2801. case DRAG_TOP_RIGHT:
  2802. case DRAG_BOTTOM_RIGHT:
  2803. _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
  2804. FALLTHROUGH;
  2805. case DRAG_MOVE:
  2806. start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio));
  2807. end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0);
  2808. _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM);
  2809. viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
  2810. break;
  2811. default:
  2812. break;
  2813. }
  2814. switch (drag_type) {
  2815. case DRAG_TOP:
  2816. case DRAG_TOP_LEFT:
  2817. case DRAG_TOP_RIGHT:
  2818. _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT);
  2819. FALLTHROUGH;
  2820. case DRAG_MOVE:
  2821. start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]);
  2822. end = start - Vector2(0, control->get_margin(MARGIN_TOP));
  2823. _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT);
  2824. viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
  2825. break;
  2826. default:
  2827. break;
  2828. }
  2829. switch (drag_type) {
  2830. case DRAG_BOTTOM:
  2831. case DRAG_BOTTOM_LEFT:
  2832. case DRAG_BOTTOM_RIGHT:
  2833. _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT);
  2834. FALLTHROUGH;
  2835. case DRAG_MOVE:
  2836. start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]);
  2837. end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM));
  2838. _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT);
  2839. viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
  2840. break;
  2841. default:
  2842. break;
  2843. }
  2844. switch (drag_type) {
  2845. //Draw the ghost rect if the node if rotated/scaled
  2846. case DRAG_LEFT:
  2847. case DRAG_TOP_LEFT:
  2848. case DRAG_TOP:
  2849. case DRAG_TOP_RIGHT:
  2850. case DRAG_RIGHT:
  2851. case DRAG_BOTTOM_RIGHT:
  2852. case DRAG_BOTTOM:
  2853. case DRAG_BOTTOM_LEFT:
  2854. case DRAG_MOVE:
  2855. if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) {
  2856. Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size());
  2857. viewport->draw_rect(parent_transform.xform(rect), color_base, false, Math::round(EDSCALE));
  2858. }
  2859. break;
  2860. default:
  2861. break;
  2862. }
  2863. }
  2864. }
  2865. void CanvasItemEditor::_draw_selection() {
  2866. Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons");
  2867. Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons");
  2868. Ref<Texture> previous_position_icon = get_icon("EditorPositionPrevious", "EditorIcons");
  2869. RID ci = viewport->get_canvas_item();
  2870. List<CanvasItem *> selection = _get_edited_canvas_items(true, false);
  2871. bool single = selection.size() == 1;
  2872. for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
  2873. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
  2874. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  2875. bool item_locked = canvas_item->has_meta("_edit_lock_");
  2876. // Draw the previous position if we are dragging the node
  2877. if (show_helpers &&
  2878. (drag_type == DRAG_MOVE || drag_type == DRAG_ROTATE ||
  2879. drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM ||
  2880. drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT)) {
  2881. const Transform2D pre_drag_xform = transform * se->pre_drag_xform;
  2882. const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7);
  2883. if (canvas_item->_edit_use_rect()) {
  2884. Vector2 pre_drag_endpoints[4] = {
  2885. pre_drag_xform.xform(se->pre_drag_rect.position),
  2886. pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)),
  2887. pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size),
  2888. pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y))
  2889. };
  2890. for (int i = 0; i < 4; i++) {
  2891. viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, Math::round(2 * EDSCALE), true);
  2892. }
  2893. } else {
  2894. viewport->draw_texture(previous_position_icon, (pre_drag_xform.xform(Point2()) - (previous_position_icon->get_size() / 2)).floor());
  2895. }
  2896. }
  2897. Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
  2898. // Draw the selected items position / surrounding boxes
  2899. if (canvas_item->_edit_use_rect()) {
  2900. Rect2 rect = canvas_item->_edit_get_rect();
  2901. Vector2 endpoints[4] = {
  2902. xform.xform(rect.position),
  2903. xform.xform(rect.position + Vector2(rect.size.x, 0)),
  2904. xform.xform(rect.position + rect.size),
  2905. xform.xform(rect.position + Vector2(0, rect.size.y))
  2906. };
  2907. Color c = Color(1, 0.6, 0.4, 0.7);
  2908. if (item_locked) {
  2909. c = Color(0.7, 0.7, 0.7, 0.7);
  2910. }
  2911. for (int i = 0; i < 4; i++) {
  2912. viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, Math::round(2 * EDSCALE), true);
  2913. }
  2914. } else {
  2915. Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
  2916. Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
  2917. viewport->draw_set_transform_matrix(simple_xform);
  2918. viewport->draw_texture(position_icon, -(position_icon->get_size() / 2));
  2919. viewport->draw_set_transform_matrix(viewport->get_transform());
  2920. }
  2921. if (single && !item_locked && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks
  2922. // Draw the pivot
  2923. if (canvas_item->_edit_use_pivot()) {
  2924. // Draw the node's pivot
  2925. Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
  2926. Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
  2927. viewport->draw_set_transform_matrix(simple_xform);
  2928. viewport->draw_texture(pivot_icon, -(pivot_icon->get_size() / 2).floor());
  2929. viewport->draw_set_transform_matrix(viewport->get_transform());
  2930. }
  2931. // Draw control-related helpers
  2932. Control *control = Object::cast_to<Control>(canvas_item);
  2933. if (control && _is_node_movable(control)) {
  2934. _draw_control_anchors(control);
  2935. _draw_control_helpers(control);
  2936. }
  2937. // Draw the resize handles
  2938. if (tool == TOOL_SELECT && canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) {
  2939. Rect2 rect = canvas_item->_edit_get_rect();
  2940. Vector2 endpoints[4] = {
  2941. xform.xform(rect.position),
  2942. xform.xform(rect.position + Vector2(rect.size.x, 0)),
  2943. xform.xform(rect.position + rect.size),
  2944. xform.xform(rect.position + Vector2(0, rect.size.y))
  2945. };
  2946. for (int i = 0; i < 4; i++) {
  2947. int prev = (i + 3) % 4;
  2948. int next = (i + 1) % 4;
  2949. Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
  2950. ofs *= Math_SQRT2 * (select_handle->get_size().width / 2);
  2951. select_handle->draw(ci, (endpoints[i] + ofs - (select_handle->get_size() / 2)).floor());
  2952. ofs = (endpoints[i] + endpoints[next]) / 2;
  2953. ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
  2954. select_handle->draw(ci, (ofs - (select_handle->get_size() / 2)).floor());
  2955. }
  2956. }
  2957. // Draw the rescale handles
  2958. bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
  2959. bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
  2960. if ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) {
  2961. if (_is_node_movable(canvas_item)) {
  2962. Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
  2963. Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
  2964. Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE);
  2965. bool uniform = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
  2966. Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom;
  2967. if (drag_type == DRAG_SCALE_X) {
  2968. scale_factor.x += offset.x;
  2969. if (uniform) {
  2970. scale_factor.y += offset.x;
  2971. }
  2972. } else if (drag_type == DRAG_SCALE_Y) {
  2973. scale_factor.y -= offset.y;
  2974. if (uniform) {
  2975. scale_factor.x -= offset.y;
  2976. }
  2977. }
  2978. viewport->draw_set_transform_matrix(simple_xform);
  2979. Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
  2980. viewport->draw_rect(x_handle_rect, get_color("axis_x_color", "Editor"));
  2981. viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_color("axis_x_color", "Editor"), Math::round(EDSCALE), true);
  2982. Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
  2983. viewport->draw_rect(y_handle_rect, get_color("axis_y_color", "Editor"));
  2984. viewport->draw_line(Point2(), Point2(0, -scale_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE), true);
  2985. viewport->draw_set_transform_matrix(viewport->get_transform());
  2986. }
  2987. }
  2988. }
  2989. }
  2990. if (drag_type == DRAG_BOX_SELECTION) {
  2991. // Draw the dragging box
  2992. Point2 bsfrom = transform.xform(drag_from);
  2993. Point2 bsto = transform.xform(box_selecting_to);
  2994. viewport->draw_rect(
  2995. Rect2(bsfrom, bsto - bsfrom),
  2996. get_color("box_selection_fill_color", "Editor"));
  2997. viewport->draw_rect(
  2998. Rect2(bsfrom, bsto - bsfrom),
  2999. get_color("box_selection_stroke_color", "Editor"),
  3000. false,
  3001. Math::round(EDSCALE));
  3002. }
  3003. if (drag_type == DRAG_ROTATE) {
  3004. // Draw the line when rotating a node
  3005. viewport->draw_line(
  3006. transform.xform(drag_rotation_center),
  3007. transform.xform(drag_to),
  3008. get_color("accent_color", "Editor") * Color(1, 1, 1, 0.6),
  3009. Math::round(2 * EDSCALE),
  3010. true);
  3011. }
  3012. }
  3013. void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_color) {
  3014. // Draw a line going through the whole screen from a vector
  3015. RID ci = viewport->get_canvas_item();
  3016. Vector<Point2> points;
  3017. Point2 from = transform.xform(p_from);
  3018. Point2 to = transform.xform(p_to);
  3019. Size2 viewport_size = viewport->get_size();
  3020. if (to.x == from.x) {
  3021. // Vertical line
  3022. points.push_back(Point2(to.x, 0));
  3023. points.push_back(Point2(to.x, viewport_size.y));
  3024. } else if (to.y == from.y) {
  3025. // Horizontal line
  3026. points.push_back(Point2(0, to.y));
  3027. points.push_back(Point2(viewport_size.x, to.y));
  3028. } else {
  3029. float y_for_zero_x = (to.y * from.x - from.y * to.x) / (from.x - to.x);
  3030. float x_for_zero_y = (to.x * from.y - from.x * to.y) / (from.y - to.y);
  3031. float y_for_viewport_x = ((to.y - from.y) * (viewport_size.x - from.x)) / (to.x - from.x) + from.y;
  3032. float x_for_viewport_y = ((to.x - from.x) * (viewport_size.y - from.y)) / (to.y - from.y) + from.x; // faux
  3033. //bool start_set = false;
  3034. if (y_for_zero_x >= 0 && y_for_zero_x <= viewport_size.y) {
  3035. points.push_back(Point2(0, y_for_zero_x));
  3036. }
  3037. if (x_for_zero_y >= 0 && x_for_zero_y <= viewport_size.x) {
  3038. points.push_back(Point2(x_for_zero_y, 0));
  3039. }
  3040. if (y_for_viewport_x >= 0 && y_for_viewport_x <= viewport_size.y) {
  3041. points.push_back(Point2(viewport_size.x, y_for_viewport_x));
  3042. }
  3043. if (x_for_viewport_y >= 0 && x_for_viewport_y <= viewport_size.x) {
  3044. points.push_back(Point2(x_for_viewport_y, viewport_size.y));
  3045. }
  3046. }
  3047. if (points.size() >= 2) {
  3048. VisualServer::get_singleton()->canvas_item_add_line(ci, points[0], points[1], p_color);
  3049. }
  3050. }
  3051. void CanvasItemEditor::_draw_axis() {
  3052. if (show_origin) {
  3053. _draw_straight_line(Point2(), Point2(1, 0), get_color("axis_x_color", "Editor") * Color(1, 1, 1, 0.75));
  3054. _draw_straight_line(Point2(), Point2(0, 1), get_color("axis_y_color", "Editor") * Color(1, 1, 1, 0.75));
  3055. }
  3056. if (show_viewport) {
  3057. RID ci = viewport->get_canvas_item();
  3058. Color area_axis_color = EditorSettings::get_singleton()->get("editors/2d/viewport_border_color");
  3059. Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
  3060. Vector2 screen_endpoints[4] = {
  3061. transform.xform(Vector2(0, 0)),
  3062. transform.xform(Vector2(screen_size.width, 0)),
  3063. transform.xform(Vector2(screen_size.width, screen_size.height)),
  3064. transform.xform(Vector2(0, screen_size.height))
  3065. };
  3066. for (int i = 0; i < 4; i++) {
  3067. VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color);
  3068. }
  3069. }
  3070. }
  3071. void CanvasItemEditor::_draw_bones() {
  3072. RID ci = viewport->get_canvas_item();
  3073. if (skeleton_show_bones) {
  3074. Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
  3075. Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
  3076. Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
  3077. Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color");
  3078. Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
  3079. for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
  3080. Vector<Vector2> bone_shape;
  3081. Vector<Vector2> bone_shape_outline;
  3082. if (!_get_bone_shape(&bone_shape, &bone_shape_outline, E))
  3083. continue;
  3084. Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
  3085. if (!from_node->is_visible_in_tree())
  3086. continue;
  3087. Vector<Color> colors;
  3088. if (from_node->has_meta("_edit_ik_")) {
  3089. colors.push_back(bone_ik_color);
  3090. colors.push_back(bone_ik_color);
  3091. colors.push_back(bone_ik_color);
  3092. colors.push_back(bone_ik_color);
  3093. } else {
  3094. colors.push_back(bone_color1);
  3095. colors.push_back(bone_color2);
  3096. colors.push_back(bone_color1);
  3097. colors.push_back(bone_color2);
  3098. }
  3099. Vector<Color> outline_colors;
  3100. if (editor_selection->is_selected(from_node)) {
  3101. outline_colors.push_back(bone_selected_color);
  3102. outline_colors.push_back(bone_selected_color);
  3103. outline_colors.push_back(bone_selected_color);
  3104. outline_colors.push_back(bone_selected_color);
  3105. outline_colors.push_back(bone_selected_color);
  3106. outline_colors.push_back(bone_selected_color);
  3107. } else {
  3108. outline_colors.push_back(bone_outline_color);
  3109. outline_colors.push_back(bone_outline_color);
  3110. outline_colors.push_back(bone_outline_color);
  3111. outline_colors.push_back(bone_outline_color);
  3112. outline_colors.push_back(bone_outline_color);
  3113. outline_colors.push_back(bone_outline_color);
  3114. }
  3115. VisualServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors);
  3116. VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID());
  3117. }
  3118. }
  3119. }
  3120. void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
  3121. ERR_FAIL_COND(!p_node);
  3122. Node *scene = editor->get_edited_scene();
  3123. if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner()))
  3124. return;
  3125. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
  3126. if (canvas_item && !canvas_item->is_visible())
  3127. return;
  3128. Transform2D parent_xform = p_parent_xform;
  3129. Transform2D canvas_xform = p_canvas_xform;
  3130. if (canvas_item && !canvas_item->is_set_as_toplevel()) {
  3131. parent_xform = parent_xform * canvas_item->get_transform();
  3132. } else {
  3133. CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
  3134. parent_xform = Transform2D();
  3135. canvas_xform = cl ? cl->get_transform() : p_canvas_xform;
  3136. }
  3137. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  3138. _draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform);
  3139. }
  3140. if (canvas_item && !canvas_item->_edit_use_rect() && (!editor_selection->is_selected(canvas_item) || _is_node_locked(canvas_item))) {
  3141. Transform2D xform = transform * canvas_xform * parent_xform;
  3142. // Draw the node's position
  3143. Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons");
  3144. Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
  3145. Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
  3146. viewport->draw_set_transform_matrix(simple_xform);
  3147. viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5));
  3148. viewport->draw_set_transform_matrix(viewport->get_transform());
  3149. }
  3150. }
  3151. void CanvasItemEditor::_draw_hover() {
  3152. List<Rect2> previous_rects;
  3153. for (int i = 0; i < hovering_results.size(); i++) {
  3154. Ref<Texture> node_icon = hovering_results[i].icon;
  3155. String node_name = hovering_results[i].name;
  3156. Ref<Font> font = get_font("font", "Label");
  3157. Size2 node_name_size = font->get_string_size(node_name);
  3158. Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3));
  3159. Point2 pos = transform.xform(hovering_results[i].position) - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4);
  3160. // Rectify the position to avoid overlapping items
  3161. for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) {
  3162. if (E->get().intersects(Rect2(pos, item_size))) {
  3163. pos.y = E->get().get_position().y - item_size.y;
  3164. }
  3165. }
  3166. previous_rects.push_back(Rect2(pos, item_size));
  3167. // Draw icon
  3168. viewport->draw_texture(node_icon, pos, Color(1.0, 1.0, 1.0, 0.5));
  3169. // Draw name
  3170. viewport->draw_string(font, pos + Point2(node_icon->get_size().x + 4, item_size.y - 3), node_name, Color(1.0, 1.0, 1.0, 0.5));
  3171. }
  3172. }
  3173. void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
  3174. ERR_FAIL_COND(!p_node);
  3175. Node *scene = editor->get_edited_scene();
  3176. if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner()))
  3177. return;
  3178. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
  3179. if (canvas_item && !canvas_item->is_visible())
  3180. return;
  3181. Transform2D parent_xform = p_parent_xform;
  3182. Transform2D canvas_xform = p_canvas_xform;
  3183. if (canvas_item && !canvas_item->is_set_as_toplevel()) {
  3184. parent_xform = parent_xform * canvas_item->get_transform();
  3185. } else {
  3186. CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
  3187. parent_xform = Transform2D();
  3188. canvas_xform = cl ? cl->get_transform() : p_canvas_xform;
  3189. }
  3190. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  3191. _draw_locks_and_groups(p_node->get_child(i), parent_xform, canvas_xform);
  3192. }
  3193. RID viewport_canvas_item = viewport->get_canvas_item();
  3194. if (canvas_item) {
  3195. float offset = 0;
  3196. Ref<Texture> lock = get_icon("LockViewport", "EditorIcons");
  3197. if (p_node->has_meta("_edit_lock_") && show_edit_locks) {
  3198. lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
  3199. offset += lock->get_size().x;
  3200. }
  3201. Ref<Texture> group = get_icon("GroupViewport", "EditorIcons");
  3202. if (canvas_item->has_meta("_edit_group_") && show_edit_locks) {
  3203. group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
  3204. //offset += group->get_size().x;
  3205. }
  3206. }
  3207. }
  3208. bool CanvasItemEditor::_build_bones_list(Node *p_node) {
  3209. ERR_FAIL_COND_V(!p_node, false);
  3210. bool has_child_bones = false;
  3211. for (int i = 0; i < p_node->get_child_count(); i++) {
  3212. if (_build_bones_list(p_node->get_child(i))) {
  3213. has_child_bones = true;
  3214. }
  3215. }
  3216. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
  3217. Node *scene = editor->get_edited_scene();
  3218. if (!canvas_item || !canvas_item->is_visible() || (canvas_item != scene && canvas_item->get_owner() != scene && canvas_item != scene->get_deepest_editable_node(canvas_item))) {
  3219. return false;
  3220. }
  3221. Node *parent = canvas_item->get_parent();
  3222. if (Object::cast_to<Bone2D>(canvas_item)) {
  3223. if (Object::cast_to<Bone2D>(parent)) {
  3224. // Add as bone->parent relationship
  3225. BoneKey bk;
  3226. bk.from = parent->get_instance_id();
  3227. bk.to = canvas_item->get_instance_id();
  3228. if (!bone_list.has(bk)) {
  3229. BoneList b;
  3230. b.length = 0;
  3231. bone_list[bk] = b;
  3232. }
  3233. bone_list[bk].last_pass = bone_last_frame;
  3234. }
  3235. if (!has_child_bones) {
  3236. // Add a last bone if the Bone2D has no Bone2D child
  3237. BoneKey bk;
  3238. bk.from = canvas_item->get_instance_id();
  3239. bk.to = 0;
  3240. if (!bone_list.has(bk)) {
  3241. BoneList b;
  3242. b.length = 0;
  3243. bone_list[bk] = b;
  3244. }
  3245. bone_list[bk].last_pass = bone_last_frame;
  3246. }
  3247. return true;
  3248. }
  3249. if (canvas_item->has_meta("_edit_bone_")) {
  3250. // Add a "custom bone"
  3251. BoneKey bk;
  3252. bk.from = parent->get_instance_id();
  3253. bk.to = canvas_item->get_instance_id();
  3254. if (!bone_list.has(bk)) {
  3255. BoneList b;
  3256. b.length = 0;
  3257. bone_list[bk] = b;
  3258. }
  3259. bone_list[bk].last_pass = bone_last_frame;
  3260. }
  3261. return false;
  3262. }
  3263. void CanvasItemEditor::_draw_viewport() {
  3264. // Update the transform
  3265. transform = Transform2D();
  3266. transform.scale_basis(Size2(zoom, zoom));
  3267. transform.elements[2] = -view_offset * zoom;
  3268. editor->get_scene_root()->set_global_canvas_transform(transform);
  3269. // hide/show buttons depending on the selection
  3270. bool all_locked = true;
  3271. bool all_group = true;
  3272. List<Node *> selection = editor_selection->get_selected_node_list();
  3273. if (selection.empty()) {
  3274. all_locked = false;
  3275. all_group = false;
  3276. } else {
  3277. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  3278. if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_lock_")) {
  3279. all_locked = false;
  3280. break;
  3281. }
  3282. }
  3283. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  3284. if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_group_")) {
  3285. all_group = false;
  3286. break;
  3287. }
  3288. }
  3289. }
  3290. lock_button->set_visible(!all_locked);
  3291. lock_button->set_disabled(selection.empty());
  3292. unlock_button->set_visible(all_locked);
  3293. group_button->set_visible(!all_group);
  3294. group_button->set_disabled(selection.empty());
  3295. ungroup_button->set_visible(all_group);
  3296. info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
  3297. _draw_grid();
  3298. _draw_ruler_tool();
  3299. _draw_axis();
  3300. if (editor->get_edited_scene()) {
  3301. _draw_locks_and_groups(editor->get_edited_scene());
  3302. _draw_invisible_nodes_positions(editor->get_edited_scene());
  3303. }
  3304. _draw_selection();
  3305. RID ci = viewport->get_canvas_item();
  3306. VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
  3307. EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
  3308. if (!over_plugin_list->empty()) {
  3309. over_plugin_list->forward_canvas_draw_over_viewport(viewport);
  3310. }
  3311. EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over();
  3312. if (!force_over_plugin_list->empty()) {
  3313. force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport);
  3314. }
  3315. _draw_bones();
  3316. if (show_rulers)
  3317. _draw_rulers();
  3318. if (show_guides)
  3319. _draw_guides();
  3320. _draw_smart_snapping();
  3321. _draw_focus();
  3322. _draw_hover();
  3323. }
  3324. void CanvasItemEditor::update_viewport() {
  3325. _update_scrollbars();
  3326. viewport->update();
  3327. }
  3328. void CanvasItemEditor::set_current_tool(Tool p_tool) {
  3329. _button_tool_select(p_tool);
  3330. }
  3331. void CanvasItemEditor::_notification(int p_what) {
  3332. if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
  3333. EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
  3334. bool has_container_parents = false;
  3335. int nb_control = 0;
  3336. int nb_having_pivot = 0;
  3337. // Update the viewport if the canvas_item changes
  3338. List<CanvasItem *> selection = _get_edited_canvas_items(true);
  3339. for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
  3340. CanvasItem *canvas_item = E->get();
  3341. CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
  3342. Rect2 rect;
  3343. if (canvas_item->_edit_use_rect()) {
  3344. rect = canvas_item->_edit_get_rect();
  3345. } else {
  3346. rect = Rect2();
  3347. }
  3348. Transform2D xform = canvas_item->get_transform();
  3349. if (rect != se->prev_rect || xform != se->prev_xform) {
  3350. viewport->update();
  3351. se->prev_rect = rect;
  3352. se->prev_xform = xform;
  3353. }
  3354. Control *control = Object::cast_to<Control>(canvas_item);
  3355. if (control) {
  3356. float anchors[4];
  3357. Vector2 pivot;
  3358. pivot = control->get_pivot_offset();
  3359. anchors[MARGIN_LEFT] = control->get_anchor(MARGIN_LEFT);
  3360. anchors[MARGIN_RIGHT] = control->get_anchor(MARGIN_RIGHT);
  3361. anchors[MARGIN_TOP] = control->get_anchor(MARGIN_TOP);
  3362. anchors[MARGIN_BOTTOM] = control->get_anchor(MARGIN_BOTTOM);
  3363. if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) {
  3364. se->prev_pivot = pivot;
  3365. se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT];
  3366. se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT];
  3367. se->prev_anchors[MARGIN_TOP] = anchors[MARGIN_TOP];
  3368. se->prev_anchors[MARGIN_BOTTOM] = anchors[MARGIN_BOTTOM];
  3369. viewport->update();
  3370. }
  3371. nb_control++;
  3372. if (Object::cast_to<Container>(control->get_parent())) {
  3373. has_container_parents = true;
  3374. }
  3375. }
  3376. if (canvas_item->_edit_use_pivot()) {
  3377. nb_having_pivot++;
  3378. }
  3379. }
  3380. // Activate / Deactivate the pivot tool
  3381. pivot_button->set_disabled(nb_having_pivot == 0);
  3382. // Show / Hide the layout and anchors mode buttons
  3383. if (nb_control > 0 && nb_control == selection.size()) {
  3384. presets_menu->set_visible(true);
  3385. anchor_mode_button->set_visible(true);
  3386. // Disable if the selected node is child of a container
  3387. if (has_container_parents) {
  3388. presets_menu->set_disabled(true);
  3389. presets_menu->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
  3390. anchor_mode_button->set_disabled(true);
  3391. anchor_mode_button->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
  3392. } else {
  3393. presets_menu->set_disabled(false);
  3394. presets_menu->set_tooltip(TTR("Presets for the anchors and margins values of a Control node."));
  3395. anchor_mode_button->set_disabled(false);
  3396. anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their margins."));
  3397. }
  3398. } else {
  3399. presets_menu->set_visible(false);
  3400. anchor_mode_button->set_visible(false);
  3401. }
  3402. // Update the viewport if bones changes
  3403. for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
  3404. Object *b = ObjectDB::get_instance(E->key().from);
  3405. if (!b) {
  3406. viewport->update();
  3407. break;
  3408. }
  3409. Node2D *b2 = Object::cast_to<Node2D>(b);
  3410. if (!b2 || !b2->is_inside_tree()) {
  3411. continue;
  3412. }
  3413. Transform2D global_xform = b2->get_global_transform();
  3414. if (global_xform != E->get().xform) {
  3415. E->get().xform = global_xform;
  3416. viewport->update();
  3417. }
  3418. Bone2D *bone = Object::cast_to<Bone2D>(b);
  3419. if (bone && bone->get_default_length() != E->get().length) {
  3420. E->get().length = bone->get_default_length();
  3421. viewport->update();
  3422. }
  3423. }
  3424. }
  3425. if (p_what == NOTIFICATION_ENTER_TREE) {
  3426. select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons"));
  3427. for (int i = 0; i < 4; i++) {
  3428. select_sb->set_margin_size(Margin(i), 4);
  3429. select_sb->set_default_margin(Margin(i), 4);
  3430. }
  3431. AnimationPlayerEditor::singleton->get_track_editor()->connect("visibility_changed", this, "_keying_changed");
  3432. _keying_changed();
  3433. get_tree()->connect("node_added", this, "_tree_changed", varray());
  3434. get_tree()->connect("node_removed", this, "_tree_changed", varray());
  3435. } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
  3436. select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons"));
  3437. }
  3438. if (p_what == NOTIFICATION_EXIT_TREE) {
  3439. get_tree()->disconnect("node_added", this, "_tree_changed");
  3440. get_tree()->disconnect("node_removed", this, "_tree_changed");
  3441. }
  3442. if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
  3443. select_button->set_icon(get_icon("ToolSelect", "EditorIcons"));
  3444. list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
  3445. move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
  3446. scale_button->set_icon(get_icon("ToolScale", "EditorIcons"));
  3447. rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons"));
  3448. smart_snap_button->set_icon(get_icon("Snap", "EditorIcons"));
  3449. grid_snap_button->set_icon(get_icon("SnapGrid", "EditorIcons"));
  3450. snap_config_menu->set_icon(get_icon("GuiTabMenuHl", "EditorIcons"));
  3451. skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
  3452. override_camera_button->set_icon(get_icon("Camera2D", "EditorIcons"));
  3453. pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
  3454. ruler_button->set_icon(get_icon("Ruler", "EditorIcons"));
  3455. pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
  3456. select_handle = get_icon("EditorHandle", "EditorIcons");
  3457. anchor_handle = get_icon("EditorControlAnchor", "EditorIcons");
  3458. lock_button->set_icon(get_icon("Lock", "EditorIcons"));
  3459. unlock_button->set_icon(get_icon("Unlock", "EditorIcons"));
  3460. group_button->set_icon(get_icon("Group", "EditorIcons"));
  3461. ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons"));
  3462. key_loc_button->set_icon(get_icon("KeyPosition", "EditorIcons"));
  3463. key_rot_button->set_icon(get_icon("KeyRotation", "EditorIcons"));
  3464. key_scale_button->set_icon(get_icon("KeyScale", "EditorIcons"));
  3465. key_insert_button->set_icon(get_icon("Key", "EditorIcons"));
  3466. key_auto_insert_button->set_icon(get_icon("AutoKey", "EditorIcons"));
  3467. // Use a different color for the active autokey icon to make them easier
  3468. // to distinguish from the other key icons at the top. On a light theme,
  3469. // the icon will be dark, so we need to lighten it before blending it
  3470. // with the red color.
  3471. const Color key_auto_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25);
  3472. key_auto_insert_button->add_color_override("icon_color_pressed", key_auto_color.linear_interpolate(Color(1, 0, 0), 0.55));
  3473. animation_menu->set_icon(get_icon("GuiTabMenuHl", "EditorIcons"));
  3474. zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
  3475. zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
  3476. presets_menu->set_icon(get_icon("ControlLayout", "EditorIcons"));
  3477. PopupMenu *p = presets_menu->get_popup();
  3478. p->clear();
  3479. p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_MARGINS_PRESET_TOP_LEFT);
  3480. p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT);
  3481. p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT);
  3482. p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT);
  3483. p->add_separator();
  3484. p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT);
  3485. p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_MARGINS_PRESET_CENTER_TOP);
  3486. p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT);
  3487. p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM);
  3488. p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_MARGINS_PRESET_CENTER);
  3489. p->add_separator();
  3490. p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE);
  3491. p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_MARGINS_PRESET_TOP_WIDE);
  3492. p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE);
  3493. p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE);
  3494. p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE);
  3495. p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE);
  3496. p->add_separator();
  3497. p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_MARGINS_PRESET_WIDE);
  3498. p->add_icon_item(get_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO);
  3499. p->add_separator();
  3500. p->add_submenu_item(TTR("Anchors only"), "Anchors");
  3501. p->set_item_icon(21, get_icon("Anchor", "EditorIcons"));
  3502. anchors_popup->clear();
  3503. anchors_popup->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT);
  3504. anchors_popup->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT);
  3505. anchors_popup->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT);
  3506. anchors_popup->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT);
  3507. anchors_popup->add_separator();
  3508. anchors_popup->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT);
  3509. anchors_popup->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP);
  3510. anchors_popup->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT);
  3511. anchors_popup->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM);
  3512. anchors_popup->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_PRESET_CENTER);
  3513. anchors_popup->add_separator();
  3514. anchors_popup->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE);
  3515. anchors_popup->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE);
  3516. anchors_popup->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE);
  3517. anchors_popup->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE);
  3518. anchors_popup->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE);
  3519. anchors_popup->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE);
  3520. anchors_popup->add_separator();
  3521. anchors_popup->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_PRESET_WIDE);
  3522. anchor_mode_button->set_icon(get_icon("Anchor", "EditorIcons"));
  3523. Ref<DynamicFont> font = zoom_reset->get_font("font")->duplicate(false);
  3524. font->set_outline_size(1);
  3525. font->set_outline_color(Color(0, 0, 0));
  3526. zoom_reset->add_font_override("font", font);
  3527. zoom_reset->add_color_override("font_color", Color(1, 1, 1));
  3528. }
  3529. if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
  3530. if (!is_visible() && override_camera_button->is_pressed()) {
  3531. ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
  3532. debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
  3533. override_camera_button->set_pressed(false);
  3534. }
  3535. }
  3536. }
  3537. void CanvasItemEditor::_selection_changed() {
  3538. // Update the anchors_mode
  3539. int nbValidControls = 0;
  3540. int nbAnchorsMode = 0;
  3541. List<Node *> selection = editor_selection->get_selected_node_list();
  3542. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  3543. Control *control = Object::cast_to<Control>(E->get());
  3544. if (!control)
  3545. continue;
  3546. if (Object::cast_to<Container>(control->get_parent()))
  3547. continue;
  3548. nbValidControls++;
  3549. if (control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_")) {
  3550. nbAnchorsMode++;
  3551. }
  3552. }
  3553. anchors_mode = (nbValidControls == nbAnchorsMode);
  3554. anchor_mode_button->set_pressed(anchors_mode);
  3555. if (!selected_from_canvas) {
  3556. drag_type = DRAG_NONE;
  3557. }
  3558. selected_from_canvas = false;
  3559. }
  3560. void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
  3561. Array selection = editor_selection->get_selected_nodes();
  3562. if (selection.size() != 1 || (Node *)selection[0] != p_canvas_item) {
  3563. drag_type = DRAG_NONE;
  3564. // Clear the selection
  3565. editor_selection->clear(); //_clear_canvas_items();
  3566. editor_selection->add_node(p_canvas_item);
  3567. }
  3568. }
  3569. void CanvasItemEditor::_queue_update_bone_list() {
  3570. if (bone_list_dirty)
  3571. return;
  3572. call_deferred("_update_bone_list");
  3573. bone_list_dirty = true;
  3574. }
  3575. void CanvasItemEditor::_update_bone_list() {
  3576. bone_last_frame++;
  3577. if (editor->get_edited_scene()) {
  3578. _build_bones_list(editor->get_edited_scene());
  3579. }
  3580. List<Map<BoneKey, BoneList>::Element *> bone_to_erase;
  3581. for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
  3582. if (E->get().last_pass != bone_last_frame) {
  3583. bone_to_erase.push_back(E);
  3584. continue;
  3585. }
  3586. Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E->key().from));
  3587. if (!node || !node->is_inside_tree() || (node != get_tree()->get_edited_scene_root() && !get_tree()->get_edited_scene_root()->is_a_parent_of(node))) {
  3588. bone_to_erase.push_back(E);
  3589. continue;
  3590. }
  3591. }
  3592. while (bone_to_erase.size()) {
  3593. bone_list.erase(bone_to_erase.front()->get());
  3594. bone_to_erase.pop_front();
  3595. }
  3596. bone_list_dirty = false;
  3597. }
  3598. void CanvasItemEditor::_tree_changed(Node *) {
  3599. _queue_update_bone_list();
  3600. }
  3601. void CanvasItemEditor::_update_scrollbars() {
  3602. updating_scroll = true;
  3603. // Move the zoom buttons.
  3604. Point2 controls_vb_begin = Point2(5, 5);
  3605. controls_vb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2();
  3606. controls_vb->set_begin(controls_vb_begin);
  3607. Size2 hmin = h_scroll->get_minimum_size();
  3608. Size2 vmin = v_scroll->get_minimum_size();
  3609. // Get the visible frame.
  3610. Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
  3611. Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
  3612. _queue_update_bone_list();
  3613. // Calculate scrollable area.
  3614. Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
  3615. if (editor->get_edited_scene()) {
  3616. Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene());
  3617. canvas_item_rect.expand_to(content_rect.position);
  3618. canvas_item_rect.expand_to(content_rect.position + content_rect.size);
  3619. }
  3620. canvas_item_rect.size += screen_rect * 2;
  3621. canvas_item_rect.position -= screen_rect;
  3622. // Constraints the view offset and updates the scrollbars.
  3623. Size2 size = viewport->get_size();
  3624. Point2 begin = canvas_item_rect.position;
  3625. Point2 end = canvas_item_rect.position + canvas_item_rect.size - local_rect.size / zoom;
  3626. bool constrain_editor_view = bool(EditorSettings::get_singleton()->get("editors/2d/constrain_editor_view"));
  3627. if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) {
  3628. float centered = -(size.y / 2) / zoom + screen_rect.y / 2;
  3629. if (constrain_editor_view && ABS(centered - previous_update_view_offset.y) < ABS(centered - view_offset.y)) {
  3630. view_offset.y = previous_update_view_offset.y;
  3631. }
  3632. v_scroll->hide();
  3633. } else {
  3634. if (constrain_editor_view && view_offset.y > end.y && view_offset.y > previous_update_view_offset.y) {
  3635. view_offset.y = MAX(end.y, previous_update_view_offset.y);
  3636. }
  3637. if (constrain_editor_view && view_offset.y < begin.y && view_offset.y < previous_update_view_offset.y) {
  3638. view_offset.y = MIN(begin.y, previous_update_view_offset.y);
  3639. }
  3640. v_scroll->show();
  3641. v_scroll->set_min(MIN(view_offset.y, begin.y));
  3642. v_scroll->set_max(MAX(view_offset.y, end.y) + screen_rect.y);
  3643. v_scroll->set_page(screen_rect.y);
  3644. }
  3645. if (canvas_item_rect.size.width <= (local_rect.size.x / zoom)) {
  3646. float centered = -(size.x / 2) / zoom + screen_rect.x / 2;
  3647. if (constrain_editor_view && ABS(centered - previous_update_view_offset.x) < ABS(centered - view_offset.x)) {
  3648. view_offset.x = previous_update_view_offset.x;
  3649. }
  3650. h_scroll->hide();
  3651. } else {
  3652. if (constrain_editor_view && view_offset.x > end.x && view_offset.x > previous_update_view_offset.x) {
  3653. view_offset.x = MAX(end.x, previous_update_view_offset.x);
  3654. }
  3655. if (constrain_editor_view && view_offset.x < begin.x && view_offset.x < previous_update_view_offset.x) {
  3656. view_offset.x = MIN(begin.x, previous_update_view_offset.x);
  3657. }
  3658. h_scroll->show();
  3659. h_scroll->set_min(MIN(view_offset.x, begin.x));
  3660. h_scroll->set_max(MAX(view_offset.x, end.x) + screen_rect.x);
  3661. h_scroll->set_page(screen_rect.x);
  3662. }
  3663. // Move and resize the scrollbars, avoiding overlap.
  3664. v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
  3665. v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
  3666. h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
  3667. h_scroll->set_end(Point2(size.width - (v_scroll->is_visible() ? vmin.width : 0), size.height));
  3668. // Calculate scrollable area.
  3669. v_scroll->set_value(view_offset.y);
  3670. h_scroll->set_value(view_offset.x);
  3671. previous_update_view_offset = view_offset;
  3672. updating_scroll = false;
  3673. }
  3674. void CanvasItemEditor::_popup_warning_depop(Control *p_control) {
  3675. ERR_FAIL_COND(!popup_temporarily_timers.has(p_control));
  3676. Timer *timer = popup_temporarily_timers[p_control];
  3677. timer->queue_delete();
  3678. p_control->hide();
  3679. popup_temporarily_timers.erase(p_control);
  3680. info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
  3681. }
  3682. void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const float p_duration) {
  3683. Timer *timer;
  3684. if (!popup_temporarily_timers.has(p_control)) {
  3685. timer = memnew(Timer);
  3686. timer->connect("timeout", this, "_popup_warning_depop", varray(p_control));
  3687. timer->set_one_shot(true);
  3688. add_child(timer);
  3689. popup_temporarily_timers[p_control] = timer;
  3690. } else {
  3691. timer = popup_temporarily_timers[p_control];
  3692. }
  3693. timer->start(p_duration);
  3694. p_control->show();
  3695. info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
  3696. }
  3697. void CanvasItemEditor::_update_scroll(float) {
  3698. if (updating_scroll)
  3699. return;
  3700. view_offset.x = h_scroll->get_value();
  3701. view_offset.y = v_scroll->get_value();
  3702. viewport->update();
  3703. }
  3704. void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) {
  3705. List<Node *> selection = editor_selection->get_selected_node_list();
  3706. undo_redo->create_action(TTR("Change Anchors and Margins"));
  3707. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  3708. Control *control = Object::cast_to<Control>(E->get());
  3709. if (control) {
  3710. undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
  3711. switch (p_preset) {
  3712. case PRESET_TOP_LEFT:
  3713. case PRESET_TOP_RIGHT:
  3714. case PRESET_BOTTOM_LEFT:
  3715. case PRESET_BOTTOM_RIGHT:
  3716. case PRESET_CENTER_LEFT:
  3717. case PRESET_CENTER_TOP:
  3718. case PRESET_CENTER_RIGHT:
  3719. case PRESET_CENTER_BOTTOM:
  3720. case PRESET_CENTER:
  3721. undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
  3722. break;
  3723. case PRESET_LEFT_WIDE:
  3724. case PRESET_TOP_WIDE:
  3725. case PRESET_RIGHT_WIDE:
  3726. case PRESET_BOTTOM_WIDE:
  3727. case PRESET_VCENTER_WIDE:
  3728. case PRESET_HCENTER_WIDE:
  3729. case PRESET_WIDE:
  3730. undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE);
  3731. break;
  3732. }
  3733. undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
  3734. }
  3735. }
  3736. undo_redo->commit_action();
  3737. anchors_mode = false;
  3738. anchor_mode_button->set_pressed(anchors_mode);
  3739. }
  3740. void CanvasItemEditor::_set_anchors_and_margins_to_keep_ratio() {
  3741. List<Node *> selection = editor_selection->get_selected_node_list();
  3742. undo_redo->create_action(TTR("Change Anchors and Margins"));
  3743. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  3744. Control *control = Object::cast_to<Control>(E->get());
  3745. if (control) {
  3746. Point2 top_left_anchor = _position_to_anchor(control, Point2());
  3747. Point2 bottom_right_anchor = _position_to_anchor(control, control->get_size());
  3748. undo_redo->add_do_method(control, "set_anchor", MARGIN_LEFT, top_left_anchor.x, false, true);
  3749. undo_redo->add_do_method(control, "set_anchor", MARGIN_RIGHT, bottom_right_anchor.x, false, true);
  3750. undo_redo->add_do_method(control, "set_anchor", MARGIN_TOP, top_left_anchor.y, false, true);
  3751. undo_redo->add_do_method(control, "set_anchor", MARGIN_BOTTOM, bottom_right_anchor.y, false, true);
  3752. undo_redo->add_do_method(control, "set_meta", "_edit_use_anchors_", true);
  3753. bool use_anchors = control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_");
  3754. undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
  3755. undo_redo->add_undo_method(control, "set_meta", "_edit_use_anchors_", use_anchors);
  3756. anchors_mode = true;
  3757. anchor_mode_button->set_pressed(anchors_mode);
  3758. }
  3759. }
  3760. undo_redo->commit_action();
  3761. }
  3762. void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
  3763. List<Node *> selection = editor_selection->get_selected_node_list();
  3764. undo_redo->create_action(TTR("Change Anchors"));
  3765. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  3766. Control *control = Object::cast_to<Control>(E->get());
  3767. if (control) {
  3768. undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
  3769. undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
  3770. }
  3771. }
  3772. undo_redo->commit_action();
  3773. }
  3774. float CanvasItemEditor::_get_next_zoom_value(int p_increment_count) const {
  3775. // Base increment factor defined as the twelveth root of two.
  3776. // This allow a smooth geometric evolution of the zoom, with the advantage of
  3777. // visiting all integer power of two scale factors.
  3778. // note: this is analogous to the 'semitones' interval in the music world
  3779. // In order to avoid numerical imprecisions, we compute and edit a zoom index
  3780. // with the following relation: zoom = 2 ^ (index / 12)
  3781. if (zoom < CMP_EPSILON || p_increment_count == 0) {
  3782. return 1.f;
  3783. }
  3784. // Remove Editor scale from the index computation
  3785. float zoom_noscale = zoom / MAX(1, EDSCALE);
  3786. // zoom = 2**(index/12) => log2(zoom) = index/12
  3787. float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f));
  3788. float new_zoom_index = closest_zoom_index + p_increment_count;
  3789. float new_zoom = Math::pow(2.f, new_zoom_index / 12.f);
  3790. // Restore Editor scale transformation
  3791. new_zoom *= MAX(1, EDSCALE);
  3792. return new_zoom;
  3793. }
  3794. void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) {
  3795. p_zoom = CLAMP(p_zoom, MIN_ZOOM, MAX_ZOOM);
  3796. if (p_zoom == zoom)
  3797. return;
  3798. float prev_zoom = zoom;
  3799. zoom = p_zoom;
  3800. view_offset += p_position / prev_zoom - p_position / zoom;
  3801. // We want to align in-scene pixels to screen pixels, this prevents blurry rendering
  3802. // in small details (texts, lines).
  3803. // This correction adds a jitter movement when zooming, so we correct only when the
  3804. // zoom factor is an integer. (in the other cases, all pixels won't be aligned anyway)
  3805. float closest_zoom_factor = Math::round(zoom);
  3806. if (Math::is_zero_approx(zoom - closest_zoom_factor)) {
  3807. // make sure scene pixel at view_offset is aligned on a screen pixel
  3808. Vector2 view_offset_int = view_offset.floor();
  3809. Vector2 view_offset_frac = view_offset - view_offset_int;
  3810. view_offset = view_offset_int + (view_offset_frac * closest_zoom_factor).round() / closest_zoom_factor;
  3811. }
  3812. _update_zoom_label();
  3813. update_viewport();
  3814. }
  3815. void CanvasItemEditor::_update_zoom_label() {
  3816. String zoom_text;
  3817. // The zoom level displayed is relative to the editor scale
  3818. // (like in most image editors). Its lower bound is clamped to 1 as some people
  3819. // lower the editor scale to increase the available real estate,
  3820. // even if their display doesn't have a particularly low DPI.
  3821. if (zoom >= 10) {
  3822. // Don't show a decimal when the zoom level is higher than 1000 %.
  3823. zoom_text = rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100)) + " %";
  3824. } else {
  3825. zoom_text = rtos(Math::stepify((zoom / MAX(1, EDSCALE)) * 100, 0.1)) + " %";
  3826. }
  3827. zoom_reset->set_text(zoom_text);
  3828. }
  3829. void CanvasItemEditor::_button_zoom_minus() {
  3830. _zoom_on_position(_get_next_zoom_value(-6), viewport_scrollable->get_size() / 2.0);
  3831. }
  3832. void CanvasItemEditor::_button_zoom_reset() {
  3833. _zoom_on_position(1.0 * MAX(1, EDSCALE), viewport_scrollable->get_size() / 2.0);
  3834. }
  3835. void CanvasItemEditor::_button_zoom_plus() {
  3836. _zoom_on_position(_get_next_zoom_value(6), viewport_scrollable->get_size() / 2.0);
  3837. }
  3838. void CanvasItemEditor::_button_toggle_smart_snap(bool p_status) {
  3839. smart_snap_active = p_status;
  3840. viewport->update();
  3841. }
  3842. void CanvasItemEditor::_button_toggle_grid_snap(bool p_status) {
  3843. grid_snap_active = p_status;
  3844. viewport->update();
  3845. }
  3846. void CanvasItemEditor::_button_override_camera(bool p_pressed) {
  3847. ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
  3848. if (p_pressed) {
  3849. debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_2D);
  3850. } else {
  3851. debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
  3852. }
  3853. }
  3854. void CanvasItemEditor::_button_tool_select(int p_index) {
  3855. ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button };
  3856. for (int i = 0; i < TOOL_MAX; i++) {
  3857. tb[i]->set_pressed(i == p_index);
  3858. }
  3859. tool = (Tool)p_index;
  3860. viewport->update();
  3861. }
  3862. void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, bool p_scale, bool p_on_existing) {
  3863. Map<Node *, Object *> &selection = editor_selection->get_selection();
  3864. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  3865. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
  3866. if (!canvas_item || !canvas_item->is_visible_in_tree())
  3867. continue;
  3868. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  3869. continue;
  3870. if (Object::cast_to<Node2D>(canvas_item)) {
  3871. Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
  3872. if (key_pos && p_location)
  3873. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), p_on_existing);
  3874. if (key_rot && p_rotation)
  3875. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), p_on_existing);
  3876. if (key_scale && p_scale)
  3877. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), p_on_existing);
  3878. if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) {
  3879. //look for an IK chain
  3880. List<Node2D *> ik_chain;
  3881. Node2D *n = Object::cast_to<Node2D>(n2d->get_parent_item());
  3882. bool has_chain = false;
  3883. while (n) {
  3884. ik_chain.push_back(n);
  3885. if (n->has_meta("_edit_ik_")) {
  3886. has_chain = true;
  3887. break;
  3888. }
  3889. if (!n->get_parent_item())
  3890. break;
  3891. n = Object::cast_to<Node2D>(n->get_parent_item());
  3892. }
  3893. if (has_chain && ik_chain.size()) {
  3894. for (List<Node2D *>::Element *F = ik_chain.front(); F; F = F->next()) {
  3895. if (key_pos)
  3896. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), p_on_existing);
  3897. if (key_rot)
  3898. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), p_on_existing);
  3899. if (key_scale)
  3900. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), p_on_existing);
  3901. }
  3902. }
  3903. }
  3904. } else if (Object::cast_to<Control>(canvas_item)) {
  3905. Control *ctrl = Object::cast_to<Control>(canvas_item);
  3906. if (key_pos)
  3907. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
  3908. if (key_rot)
  3909. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), p_on_existing);
  3910. if (key_scale)
  3911. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
  3912. }
  3913. }
  3914. }
  3915. void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) {
  3916. List<CanvasItem *> selection = _get_edited_canvas_items(false, false);
  3917. for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
  3918. Control *control = Object::cast_to<Control>(E->get());
  3919. if (!control || Object::cast_to<Container>(control->get_parent()))
  3920. continue;
  3921. control->set_meta("_edit_use_anchors_", p_status);
  3922. }
  3923. anchors_mode = p_status;
  3924. viewport->update();
  3925. }
  3926. void CanvasItemEditor::_update_override_camera_button(bool p_game_running) {
  3927. if (p_game_running) {
  3928. override_camera_button->set_disabled(false);
  3929. override_camera_button->set_tooltip(TTR("Game Camera Override\nOverrides game camera with editor viewport camera."));
  3930. } else {
  3931. override_camera_button->set_disabled(true);
  3932. override_camera_button->set_pressed(false);
  3933. override_camera_button->set_tooltip(TTR("Game Camera Override\nNo game instance running."));
  3934. }
  3935. }
  3936. void CanvasItemEditor::_popup_callback(int p_op) {
  3937. last_option = MenuOption(p_op);
  3938. switch (p_op) {
  3939. case SHOW_GRID: {
  3940. show_grid = !show_grid;
  3941. int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
  3942. view_menu->get_popup()->set_item_checked(idx, show_grid);
  3943. viewport->update();
  3944. } break;
  3945. case SHOW_ORIGIN: {
  3946. show_origin = !show_origin;
  3947. int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN);
  3948. view_menu->get_popup()->set_item_checked(idx, show_origin);
  3949. viewport->update();
  3950. } break;
  3951. case SHOW_VIEWPORT: {
  3952. show_viewport = !show_viewport;
  3953. int idx = view_menu->get_popup()->get_item_index(SHOW_VIEWPORT);
  3954. view_menu->get_popup()->set_item_checked(idx, show_viewport);
  3955. viewport->update();
  3956. } break;
  3957. case SHOW_EDIT_LOCKS: {
  3958. show_edit_locks = !show_edit_locks;
  3959. int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS);
  3960. view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
  3961. viewport->update();
  3962. } break;
  3963. case SNAP_USE_NODE_PARENT: {
  3964. snap_node_parent = !snap_node_parent;
  3965. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
  3966. smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
  3967. } break;
  3968. case SNAP_USE_NODE_ANCHORS: {
  3969. snap_node_anchors = !snap_node_anchors;
  3970. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
  3971. smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
  3972. } break;
  3973. case SNAP_USE_NODE_SIDES: {
  3974. snap_node_sides = !snap_node_sides;
  3975. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
  3976. smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
  3977. } break;
  3978. case SNAP_USE_NODE_CENTER: {
  3979. snap_node_center = !snap_node_center;
  3980. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER);
  3981. smartsnap_config_popup->set_item_checked(idx, snap_node_center);
  3982. } break;
  3983. case SNAP_USE_OTHER_NODES: {
  3984. snap_other_nodes = !snap_other_nodes;
  3985. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
  3986. smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
  3987. } break;
  3988. case SNAP_USE_GUIDES: {
  3989. snap_guides = !snap_guides;
  3990. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
  3991. smartsnap_config_popup->set_item_checked(idx, snap_guides);
  3992. } break;
  3993. case SNAP_USE_ROTATION: {
  3994. snap_rotation = !snap_rotation;
  3995. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
  3996. snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation);
  3997. } break;
  3998. case SNAP_USE_SCALE: {
  3999. snap_scale = !snap_scale;
  4000. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_SCALE);
  4001. snap_config_menu->get_popup()->set_item_checked(idx, snap_scale);
  4002. } break;
  4003. case SNAP_RELATIVE: {
  4004. snap_relative = !snap_relative;
  4005. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
  4006. snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
  4007. viewport->update();
  4008. } break;
  4009. case SNAP_USE_PIXEL: {
  4010. snap_pixel = !snap_pixel;
  4011. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
  4012. snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
  4013. } break;
  4014. case SNAP_CONFIGURE: {
  4015. ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, primary_grid_steps, snap_rotation_offset, snap_rotation_step, snap_scale_step);
  4016. snap_dialog->popup_centered(Size2(220, 160) * EDSCALE);
  4017. } break;
  4018. case SKELETON_SHOW_BONES: {
  4019. skeleton_show_bones = !skeleton_show_bones;
  4020. int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
  4021. skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
  4022. viewport->update();
  4023. } break;
  4024. case SHOW_HELPERS: {
  4025. show_helpers = !show_helpers;
  4026. int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
  4027. view_menu->get_popup()->set_item_checked(idx, show_helpers);
  4028. viewport->update();
  4029. } break;
  4030. case SHOW_RULERS: {
  4031. show_rulers = !show_rulers;
  4032. int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
  4033. view_menu->get_popup()->set_item_checked(idx, show_rulers);
  4034. _update_scrollbars();
  4035. viewport->update();
  4036. } break;
  4037. case SHOW_GUIDES: {
  4038. show_guides = !show_guides;
  4039. int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
  4040. view_menu->get_popup()->set_item_checked(idx, show_guides);
  4041. viewport->update();
  4042. } break;
  4043. case LOCK_SELECTED: {
  4044. undo_redo->create_action(TTR("Lock Selected"));
  4045. List<Node *> selection = editor_selection->get_selected_node_list();
  4046. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  4047. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
  4048. if (!canvas_item || !canvas_item->is_inside_tree())
  4049. continue;
  4050. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4051. continue;
  4052. undo_redo->add_do_method(canvas_item, "set_meta", "_edit_lock_", true);
  4053. undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_lock_");
  4054. undo_redo->add_do_method(this, "emit_signal", "item_lock_status_changed");
  4055. undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed");
  4056. }
  4057. undo_redo->add_do_method(viewport, "update", Variant());
  4058. undo_redo->add_undo_method(viewport, "update", Variant());
  4059. undo_redo->commit_action();
  4060. } break;
  4061. case UNLOCK_SELECTED: {
  4062. undo_redo->create_action(TTR("Unlock Selected"));
  4063. List<Node *> selection = editor_selection->get_selected_node_list();
  4064. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  4065. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
  4066. if (!canvas_item || !canvas_item->is_inside_tree())
  4067. continue;
  4068. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4069. continue;
  4070. undo_redo->add_do_method(canvas_item, "remove_meta", "_edit_lock_");
  4071. undo_redo->add_undo_method(canvas_item, "set_meta", "_edit_lock_", true);
  4072. undo_redo->add_do_method(this, "emit_signal", "item_lock_status_changed");
  4073. undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed");
  4074. }
  4075. undo_redo->add_do_method(viewport, "update", Variant());
  4076. undo_redo->add_undo_method(viewport, "update", Variant());
  4077. undo_redo->commit_action();
  4078. } break;
  4079. case GROUP_SELECTED: {
  4080. undo_redo->create_action(TTR("Group Selected"));
  4081. List<Node *> selection = editor_selection->get_selected_node_list();
  4082. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  4083. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
  4084. if (!canvas_item || !canvas_item->is_inside_tree())
  4085. continue;
  4086. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4087. continue;
  4088. undo_redo->add_do_method(canvas_item, "set_meta", "_edit_group_", true);
  4089. undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_group_");
  4090. undo_redo->add_do_method(this, "emit_signal", "item_group_status_changed");
  4091. undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed");
  4092. }
  4093. undo_redo->add_do_method(viewport, "update", Variant());
  4094. undo_redo->add_undo_method(viewport, "update", Variant());
  4095. undo_redo->commit_action();
  4096. } break;
  4097. case UNGROUP_SELECTED: {
  4098. undo_redo->create_action(TTR("Ungroup Selected"));
  4099. List<Node *> selection = editor_selection->get_selected_node_list();
  4100. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  4101. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
  4102. if (!canvas_item || !canvas_item->is_inside_tree())
  4103. continue;
  4104. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4105. continue;
  4106. undo_redo->add_do_method(canvas_item, "remove_meta", "_edit_group_");
  4107. undo_redo->add_undo_method(canvas_item, "set_meta", "_edit_group_", true);
  4108. undo_redo->add_do_method(this, "emit_signal", "item_group_status_changed");
  4109. undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed");
  4110. }
  4111. undo_redo->add_do_method(viewport, "update", Variant());
  4112. undo_redo->add_undo_method(viewport, "update", Variant());
  4113. undo_redo->commit_action();
  4114. } break;
  4115. case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: {
  4116. _set_anchors_and_margins_preset(PRESET_TOP_LEFT);
  4117. } break;
  4118. case ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT: {
  4119. _set_anchors_and_margins_preset(PRESET_TOP_RIGHT);
  4120. } break;
  4121. case ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT: {
  4122. _set_anchors_and_margins_preset(PRESET_BOTTOM_LEFT);
  4123. } break;
  4124. case ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT: {
  4125. _set_anchors_and_margins_preset(PRESET_BOTTOM_RIGHT);
  4126. } break;
  4127. case ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT: {
  4128. _set_anchors_and_margins_preset(PRESET_CENTER_LEFT);
  4129. } break;
  4130. case ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT: {
  4131. _set_anchors_and_margins_preset(PRESET_CENTER_RIGHT);
  4132. } break;
  4133. case ANCHORS_AND_MARGINS_PRESET_CENTER_TOP: {
  4134. _set_anchors_and_margins_preset(PRESET_CENTER_TOP);
  4135. } break;
  4136. case ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM: {
  4137. _set_anchors_and_margins_preset(PRESET_CENTER_BOTTOM);
  4138. } break;
  4139. case ANCHORS_AND_MARGINS_PRESET_CENTER: {
  4140. _set_anchors_and_margins_preset(PRESET_CENTER);
  4141. } break;
  4142. case ANCHORS_AND_MARGINS_PRESET_TOP_WIDE: {
  4143. _set_anchors_and_margins_preset(PRESET_TOP_WIDE);
  4144. } break;
  4145. case ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE: {
  4146. _set_anchors_and_margins_preset(PRESET_LEFT_WIDE);
  4147. } break;
  4148. case ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE: {
  4149. _set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
  4150. } break;
  4151. case ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE: {
  4152. _set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
  4153. } break;
  4154. case ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE: {
  4155. _set_anchors_and_margins_preset(PRESET_VCENTER_WIDE);
  4156. } break;
  4157. case ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE: {
  4158. _set_anchors_and_margins_preset(PRESET_HCENTER_WIDE);
  4159. } break;
  4160. case ANCHORS_AND_MARGINS_PRESET_WIDE: {
  4161. _set_anchors_and_margins_preset(Control::PRESET_WIDE);
  4162. } break;
  4163. case ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO: {
  4164. _set_anchors_and_margins_to_keep_ratio();
  4165. } break;
  4166. case ANCHORS_PRESET_TOP_LEFT: {
  4167. _set_anchors_preset(PRESET_TOP_LEFT);
  4168. } break;
  4169. case ANCHORS_PRESET_TOP_RIGHT: {
  4170. _set_anchors_preset(PRESET_TOP_RIGHT);
  4171. } break;
  4172. case ANCHORS_PRESET_BOTTOM_LEFT: {
  4173. _set_anchors_preset(PRESET_BOTTOM_LEFT);
  4174. } break;
  4175. case ANCHORS_PRESET_BOTTOM_RIGHT: {
  4176. _set_anchors_preset(PRESET_BOTTOM_RIGHT);
  4177. } break;
  4178. case ANCHORS_PRESET_CENTER_LEFT: {
  4179. _set_anchors_preset(PRESET_CENTER_LEFT);
  4180. } break;
  4181. case ANCHORS_PRESET_CENTER_RIGHT: {
  4182. _set_anchors_preset(PRESET_CENTER_RIGHT);
  4183. } break;
  4184. case ANCHORS_PRESET_CENTER_TOP: {
  4185. _set_anchors_preset(PRESET_CENTER_TOP);
  4186. } break;
  4187. case ANCHORS_PRESET_CENTER_BOTTOM: {
  4188. _set_anchors_preset(PRESET_CENTER_BOTTOM);
  4189. } break;
  4190. case ANCHORS_PRESET_CENTER: {
  4191. _set_anchors_preset(PRESET_CENTER);
  4192. } break;
  4193. case ANCHORS_PRESET_TOP_WIDE: {
  4194. _set_anchors_preset(PRESET_TOP_WIDE);
  4195. } break;
  4196. case ANCHORS_PRESET_LEFT_WIDE: {
  4197. _set_anchors_preset(PRESET_LEFT_WIDE);
  4198. } break;
  4199. case ANCHORS_PRESET_RIGHT_WIDE: {
  4200. _set_anchors_preset(PRESET_RIGHT_WIDE);
  4201. } break;
  4202. case ANCHORS_PRESET_BOTTOM_WIDE: {
  4203. _set_anchors_preset(PRESET_BOTTOM_WIDE);
  4204. } break;
  4205. case ANCHORS_PRESET_VCENTER_WIDE: {
  4206. _set_anchors_preset(PRESET_VCENTER_WIDE);
  4207. } break;
  4208. case ANCHORS_PRESET_HCENTER_WIDE: {
  4209. _set_anchors_preset(PRESET_HCENTER_WIDE);
  4210. } break;
  4211. case ANCHORS_PRESET_WIDE: {
  4212. _set_anchors_preset(Control::PRESET_WIDE);
  4213. } break;
  4214. case ANIM_INSERT_KEY:
  4215. case ANIM_INSERT_KEY_EXISTING: {
  4216. bool existing = p_op == ANIM_INSERT_KEY_EXISTING;
  4217. _insert_animation_keys(true, true, true, existing);
  4218. } break;
  4219. case ANIM_INSERT_POS: {
  4220. key_pos = key_loc_button->is_pressed();
  4221. } break;
  4222. case ANIM_INSERT_ROT: {
  4223. key_rot = key_rot_button->is_pressed();
  4224. } break;
  4225. case ANIM_INSERT_SCALE: {
  4226. key_scale = key_scale_button->is_pressed();
  4227. } break;
  4228. case ANIM_COPY_POSE: {
  4229. pose_clipboard.clear();
  4230. Map<Node *, Object *> &selection = editor_selection->get_selection();
  4231. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  4232. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
  4233. if (!canvas_item || !canvas_item->is_visible_in_tree())
  4234. continue;
  4235. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4236. continue;
  4237. if (Object::cast_to<Node2D>(canvas_item)) {
  4238. Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
  4239. PoseClipboard pc;
  4240. pc.pos = n2d->get_position();
  4241. pc.rot = n2d->get_rotation();
  4242. pc.scale = n2d->get_scale();
  4243. pc.id = n2d->get_instance_id();
  4244. pose_clipboard.push_back(pc);
  4245. }
  4246. }
  4247. } break;
  4248. case ANIM_PASTE_POSE: {
  4249. if (!pose_clipboard.size())
  4250. break;
  4251. undo_redo->create_action(TTR("Paste Pose"));
  4252. for (List<PoseClipboard>::Element *E = pose_clipboard.front(); E; E = E->next()) {
  4253. Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->get().id));
  4254. if (!n2d)
  4255. continue;
  4256. undo_redo->add_do_method(n2d, "set_position", E->get().pos);
  4257. undo_redo->add_do_method(n2d, "set_rotation", E->get().rot);
  4258. undo_redo->add_do_method(n2d, "set_scale", E->get().scale);
  4259. undo_redo->add_undo_method(n2d, "set_position", n2d->get_position());
  4260. undo_redo->add_undo_method(n2d, "set_rotation", n2d->get_rotation());
  4261. undo_redo->add_undo_method(n2d, "set_scale", n2d->get_scale());
  4262. }
  4263. undo_redo->commit_action();
  4264. } break;
  4265. case ANIM_CLEAR_POSE: {
  4266. Map<Node *, Object *> &selection = editor_selection->get_selection();
  4267. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  4268. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
  4269. if (!canvas_item || !canvas_item->is_visible_in_tree())
  4270. continue;
  4271. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4272. continue;
  4273. if (Object::cast_to<Node2D>(canvas_item)) {
  4274. Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
  4275. if (key_pos)
  4276. n2d->set_position(Vector2());
  4277. if (key_rot)
  4278. n2d->set_rotation(0);
  4279. if (key_scale)
  4280. n2d->set_scale(Vector2(1, 1));
  4281. } else if (Object::cast_to<Control>(canvas_item)) {
  4282. Control *ctrl = Object::cast_to<Control>(canvas_item);
  4283. if (key_pos)
  4284. ctrl->set_position(Point2());
  4285. /*
  4286. if (key_scale)
  4287. AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
  4288. */
  4289. }
  4290. }
  4291. } break;
  4292. case CLEAR_GUIDES: {
  4293. Node *const root = EditorNode::get_singleton()->get_edited_scene();
  4294. if (root && (root->has_meta("_edit_horizontal_guides_") || root->has_meta("_edit_vertical_guides_"))) {
  4295. undo_redo->create_action(TTR("Clear Guides"));
  4296. if (root->has_meta("_edit_horizontal_guides_")) {
  4297. Array hguides = root->get_meta("_edit_horizontal_guides_");
  4298. undo_redo->add_do_method(root, "remove_meta", "_edit_horizontal_guides_");
  4299. undo_redo->add_undo_method(root, "set_meta", "_edit_horizontal_guides_", hguides);
  4300. }
  4301. if (root->has_meta("_edit_vertical_guides_")) {
  4302. Array vguides = root->get_meta("_edit_vertical_guides_");
  4303. undo_redo->add_do_method(root, "remove_meta", "_edit_vertical_guides_");
  4304. undo_redo->add_undo_method(root, "set_meta", "_edit_vertical_guides_", vguides);
  4305. }
  4306. undo_redo->add_undo_method(viewport, "update");
  4307. undo_redo->commit_action();
  4308. }
  4309. } break;
  4310. case VIEW_CENTER_TO_SELECTION:
  4311. case VIEW_FRAME_TO_SELECTION: {
  4312. _focus_selection(p_op);
  4313. } break;
  4314. case PREVIEW_CANVAS_SCALE: {
  4315. bool preview = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE));
  4316. preview = !preview;
  4317. VS::get_singleton()->canvas_set_disable_scale(!preview);
  4318. view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE), preview);
  4319. } break;
  4320. case SKELETON_MAKE_BONES: {
  4321. Map<Node *, Object *> &selection = editor_selection->get_selection();
  4322. undo_redo->create_action(TTR("Create Custom Bone(s) from Node(s)"));
  4323. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  4324. Node2D *n2d = Object::cast_to<Node2D>(E->key());
  4325. if (!n2d)
  4326. continue;
  4327. if (!n2d->is_visible_in_tree())
  4328. continue;
  4329. if (!n2d->get_parent_item())
  4330. continue;
  4331. if (n2d->has_meta("_edit_bone_") && n2d->get_meta("_edit_bone_"))
  4332. continue;
  4333. undo_redo->add_do_method(n2d, "set_meta", "_edit_bone_", true);
  4334. undo_redo->add_undo_method(n2d, "remove_meta", "_edit_bone_");
  4335. }
  4336. undo_redo->add_do_method(this, "_queue_update_bone_list");
  4337. undo_redo->add_undo_method(this, "_queue_update_bone_list");
  4338. undo_redo->add_do_method(viewport, "update");
  4339. undo_redo->add_undo_method(viewport, "update");
  4340. undo_redo->commit_action();
  4341. } break;
  4342. case SKELETON_CLEAR_BONES: {
  4343. Map<Node *, Object *> &selection = editor_selection->get_selection();
  4344. undo_redo->create_action(TTR("Clear Bones"));
  4345. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  4346. Node2D *n2d = Object::cast_to<Node2D>(E->key());
  4347. if (!n2d)
  4348. continue;
  4349. if (!n2d->is_visible_in_tree())
  4350. continue;
  4351. if (!n2d->has_meta("_edit_bone_"))
  4352. continue;
  4353. undo_redo->add_do_method(n2d, "remove_meta", "_edit_bone_");
  4354. undo_redo->add_undo_method(n2d, "set_meta", "_edit_bone_", n2d->get_meta("_edit_bone_"));
  4355. }
  4356. undo_redo->add_do_method(this, "_queue_update_bone_list");
  4357. undo_redo->add_undo_method(this, "_queue_update_bone_list");
  4358. undo_redo->add_do_method(viewport, "update");
  4359. undo_redo->add_undo_method(viewport, "update");
  4360. undo_redo->commit_action();
  4361. } break;
  4362. case SKELETON_SET_IK_CHAIN: {
  4363. List<Node *> selection = editor_selection->get_selected_node_list();
  4364. undo_redo->create_action(TTR("Make IK Chain"));
  4365. for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
  4366. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
  4367. if (!canvas_item || !canvas_item->is_visible_in_tree())
  4368. continue;
  4369. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4370. continue;
  4371. if (canvas_item->has_meta("_edit_ik_") && canvas_item->get_meta("_edit_ik_"))
  4372. continue;
  4373. undo_redo->add_do_method(canvas_item, "set_meta", "_edit_ik_", true);
  4374. undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_ik_");
  4375. }
  4376. undo_redo->add_do_method(viewport, "update");
  4377. undo_redo->add_undo_method(viewport, "update");
  4378. undo_redo->commit_action();
  4379. } break;
  4380. case SKELETON_CLEAR_IK_CHAIN: {
  4381. Map<Node *, Object *> &selection = editor_selection->get_selection();
  4382. undo_redo->create_action(TTR("Clear IK Chain"));
  4383. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  4384. CanvasItem *n2d = Object::cast_to<CanvasItem>(E->key());
  4385. if (!n2d)
  4386. continue;
  4387. if (!n2d->is_visible_in_tree())
  4388. continue;
  4389. if (!n2d->has_meta("_edit_ik_"))
  4390. continue;
  4391. undo_redo->add_do_method(n2d, "remove_meta", "_edit_ik_");
  4392. undo_redo->add_undo_method(n2d, "set_meta", "_edit_ik_", n2d->get_meta("_edit_ik_"));
  4393. }
  4394. undo_redo->add_do_method(viewport, "update");
  4395. undo_redo->add_undo_method(viewport, "update");
  4396. undo_redo->commit_action();
  4397. } break;
  4398. }
  4399. }
  4400. void CanvasItemEditor::_focus_selection(int p_op) {
  4401. Vector2 center(0.f, 0.f);
  4402. Rect2 rect;
  4403. int count = 0;
  4404. Map<Node *, Object *> &selection = editor_selection->get_selection();
  4405. for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
  4406. CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
  4407. if (!canvas_item) continue;
  4408. if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
  4409. continue;
  4410. // counting invisible items, for now
  4411. //if (!canvas_item->is_visible_in_tree()) continue;
  4412. ++count;
  4413. Rect2 item_rect;
  4414. if (canvas_item->_edit_use_rect()) {
  4415. item_rect = canvas_item->_edit_get_rect();
  4416. } else {
  4417. item_rect = Rect2();
  4418. }
  4419. Vector2 pos = canvas_item->get_global_transform().get_origin();
  4420. Vector2 scale = canvas_item->get_global_transform().get_scale();
  4421. real_t angle = canvas_item->get_global_transform().get_rotation();
  4422. Transform2D t(angle, Vector2(0.f, 0.f));
  4423. item_rect = t.xform(item_rect);
  4424. Rect2 canvas_item_rect(pos + scale * item_rect.position, scale * item_rect.size);
  4425. if (count == 1) {
  4426. rect = canvas_item_rect;
  4427. } else {
  4428. rect = rect.merge(canvas_item_rect);
  4429. }
  4430. };
  4431. if (count == 0) return;
  4432. if (p_op == VIEW_CENTER_TO_SELECTION) {
  4433. center = rect.position + rect.size / 2;
  4434. Vector2 offset = viewport->get_size() / 2 - editor->get_scene_root()->get_global_canvas_transform().xform(center);
  4435. view_offset.x -= Math::round(offset.x / zoom);
  4436. view_offset.y -= Math::round(offset.y / zoom);
  4437. update_viewport();
  4438. } else { // VIEW_FRAME_TO_SELECTION
  4439. if (rect.size.x > CMP_EPSILON && rect.size.y > CMP_EPSILON) {
  4440. float scale_x = viewport->get_size().x / rect.size.x;
  4441. float scale_y = viewport->get_size().y / rect.size.y;
  4442. zoom = scale_x < scale_y ? scale_x : scale_y;
  4443. zoom *= 0.90;
  4444. viewport->update();
  4445. _update_zoom_label();
  4446. call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION);
  4447. }
  4448. }
  4449. }
  4450. void CanvasItemEditor::_bind_methods() {
  4451. ClassDB::bind_method("_button_zoom_minus", &CanvasItemEditor::_button_zoom_minus);
  4452. ClassDB::bind_method("_button_zoom_reset", &CanvasItemEditor::_button_zoom_reset);
  4453. ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus);
  4454. ClassDB::bind_method("_button_toggle_smart_snap", &CanvasItemEditor::_button_toggle_smart_snap);
  4455. ClassDB::bind_method("_button_toggle_grid_snap", &CanvasItemEditor::_button_toggle_grid_snap);
  4456. ClassDB::bind_method(D_METHOD("_button_override_camera", "pressed"), &CanvasItemEditor::_button_override_camera);
  4457. ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button);
  4458. ClassDB::bind_method("_button_toggle_anchor_mode", &CanvasItemEditor::_button_toggle_anchor_mode);
  4459. ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
  4460. ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars);
  4461. ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback);
  4462. ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
  4463. ClassDB::bind_method("_button_tool_select", &CanvasItemEditor::_button_tool_select);
  4464. ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed);
  4465. ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
  4466. ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
  4467. ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport);
  4468. ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
  4469. ClassDB::bind_method("_queue_update_bone_list", &CanvasItemEditor::_update_bone_list);
  4470. ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list);
  4471. ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed);
  4472. ClassDB::bind_method("_selection_changed", &CanvasItemEditor::_selection_changed);
  4473. ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop);
  4474. ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
  4475. ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
  4476. ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state);
  4477. ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport);
  4478. ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
  4479. ADD_SIGNAL(MethodInfo("item_group_status_changed"));
  4480. }
  4481. Dictionary CanvasItemEditor::get_state() const {
  4482. Dictionary state;
  4483. // Take the editor scale into account.
  4484. state["zoom"] = zoom / MAX(1, EDSCALE);
  4485. state["ofs"] = view_offset;
  4486. state["grid_offset"] = grid_offset;
  4487. state["grid_step"] = grid_step;
  4488. state["primary_grid_steps"] = primary_grid_steps;
  4489. state["snap_rotation_offset"] = snap_rotation_offset;
  4490. state["snap_rotation_step"] = snap_rotation_step;
  4491. state["snap_scale_step"] = snap_scale_step;
  4492. state["smart_snap_active"] = smart_snap_active;
  4493. state["grid_snap_active"] = grid_snap_active;
  4494. state["snap_node_parent"] = snap_node_parent;
  4495. state["snap_node_anchors"] = snap_node_anchors;
  4496. state["snap_node_sides"] = snap_node_sides;
  4497. state["snap_node_center"] = snap_node_center;
  4498. state["snap_other_nodes"] = snap_other_nodes;
  4499. state["snap_guides"] = snap_guides;
  4500. state["show_grid"] = show_grid;
  4501. state["show_origin"] = show_origin;
  4502. state["show_viewport"] = show_viewport;
  4503. state["show_rulers"] = show_rulers;
  4504. state["show_guides"] = show_guides;
  4505. state["show_helpers"] = show_helpers;
  4506. state["show_zoom_control"] = zoom_hb->is_visible();
  4507. state["show_edit_locks"] = show_edit_locks;
  4508. state["snap_rotation"] = snap_rotation;
  4509. state["snap_scale"] = snap_scale;
  4510. state["snap_relative"] = snap_relative;
  4511. state["snap_pixel"] = snap_pixel;
  4512. state["skeleton_show_bones"] = skeleton_show_bones;
  4513. return state;
  4514. }
  4515. void CanvasItemEditor::set_state(const Dictionary &p_state) {
  4516. bool update_scrollbars = false;
  4517. Dictionary state = p_state;
  4518. if (state.has("zoom")) {
  4519. // Compensate the editor scale, so that the editor scale can be changed
  4520. // and the zoom level will still be the same (relative to the editor scale).
  4521. zoom = float(p_state["zoom"]) * MAX(1, EDSCALE);
  4522. _update_zoom_label();
  4523. }
  4524. if (state.has("ofs")) {
  4525. view_offset = p_state["ofs"];
  4526. previous_update_view_offset = view_offset;
  4527. update_scrollbars = true;
  4528. }
  4529. if (state.has("grid_offset")) {
  4530. grid_offset = state["grid_offset"];
  4531. }
  4532. if (state.has("grid_step")) {
  4533. grid_step = state["grid_step"];
  4534. }
  4535. if (state.has("primary_grid_steps")) {
  4536. primary_grid_steps = state["primary_grid_steps"];
  4537. }
  4538. if (state.has("snap_rotation_step")) {
  4539. snap_rotation_step = state["snap_rotation_step"];
  4540. }
  4541. if (state.has("snap_rotation_offset")) {
  4542. snap_rotation_offset = state["snap_rotation_offset"];
  4543. }
  4544. if (state.has("snap_scale_step")) {
  4545. snap_scale_step = state["snap_scale_step"];
  4546. }
  4547. if (state.has("smart_snap_active")) {
  4548. smart_snap_active = state["smart_snap_active"];
  4549. smart_snap_button->set_pressed(smart_snap_active);
  4550. }
  4551. if (state.has("grid_snap_active")) {
  4552. grid_snap_active = state["grid_snap_active"];
  4553. grid_snap_button->set_pressed(grid_snap_active);
  4554. }
  4555. if (state.has("snap_node_parent")) {
  4556. snap_node_parent = state["snap_node_parent"];
  4557. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
  4558. smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
  4559. }
  4560. if (state.has("snap_node_anchors")) {
  4561. snap_node_anchors = state["snap_node_anchors"];
  4562. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
  4563. smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
  4564. }
  4565. if (state.has("snap_node_sides")) {
  4566. snap_node_sides = state["snap_node_sides"];
  4567. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
  4568. smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
  4569. }
  4570. if (state.has("snap_node_center")) {
  4571. snap_node_center = state["snap_node_center"];
  4572. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER);
  4573. smartsnap_config_popup->set_item_checked(idx, snap_node_center);
  4574. }
  4575. if (state.has("snap_other_nodes")) {
  4576. snap_other_nodes = state["snap_other_nodes"];
  4577. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
  4578. smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
  4579. }
  4580. if (state.has("snap_guides")) {
  4581. snap_guides = state["snap_guides"];
  4582. int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
  4583. smartsnap_config_popup->set_item_checked(idx, snap_guides);
  4584. }
  4585. if (state.has("show_grid")) {
  4586. show_grid = state["show_grid"];
  4587. int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
  4588. view_menu->get_popup()->set_item_checked(idx, show_grid);
  4589. }
  4590. if (state.has("show_origin")) {
  4591. show_origin = state["show_origin"];
  4592. int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN);
  4593. view_menu->get_popup()->set_item_checked(idx, show_origin);
  4594. }
  4595. if (state.has("show_viewport")) {
  4596. show_viewport = state["show_viewport"];
  4597. int idx = view_menu->get_popup()->get_item_index(SHOW_VIEWPORT);
  4598. view_menu->get_popup()->set_item_checked(idx, show_viewport);
  4599. }
  4600. if (state.has("show_rulers")) {
  4601. show_rulers = state["show_rulers"];
  4602. int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
  4603. view_menu->get_popup()->set_item_checked(idx, show_rulers);
  4604. update_scrollbars = true;
  4605. }
  4606. if (state.has("show_guides")) {
  4607. show_guides = state["show_guides"];
  4608. int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
  4609. view_menu->get_popup()->set_item_checked(idx, show_guides);
  4610. }
  4611. if (state.has("show_helpers")) {
  4612. show_helpers = state["show_helpers"];
  4613. int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
  4614. view_menu->get_popup()->set_item_checked(idx, show_helpers);
  4615. }
  4616. if (state.has("show_edit_locks")) {
  4617. show_edit_locks = state["show_edit_locks"];
  4618. int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS);
  4619. view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
  4620. }
  4621. if (state.has("show_zoom_control")) {
  4622. // This one is not user-controllable, but instrumentable
  4623. zoom_hb->set_visible(state["show_zoom_control"]);
  4624. }
  4625. if (state.has("snap_rotation")) {
  4626. snap_rotation = state["snap_rotation"];
  4627. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
  4628. snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation);
  4629. }
  4630. if (state.has("snap_scale")) {
  4631. snap_scale = state["snap_scale"];
  4632. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_SCALE);
  4633. snap_config_menu->get_popup()->set_item_checked(idx, snap_scale);
  4634. }
  4635. if (state.has("snap_relative")) {
  4636. snap_relative = state["snap_relative"];
  4637. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
  4638. snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
  4639. }
  4640. if (state.has("snap_pixel")) {
  4641. snap_pixel = state["snap_pixel"];
  4642. int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
  4643. snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
  4644. }
  4645. if (state.has("skeleton_show_bones")) {
  4646. skeleton_show_bones = state["skeleton_show_bones"];
  4647. int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
  4648. skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
  4649. }
  4650. if (update_scrollbars) {
  4651. _update_scrollbars();
  4652. }
  4653. viewport->update();
  4654. }
  4655. void CanvasItemEditor::add_control_to_info_overlay(Control *p_control) {
  4656. ERR_FAIL_COND(!p_control);
  4657. p_control->set_h_size_flags(p_control->get_h_size_flags() & ~Control::SIZE_EXPAND_FILL);
  4658. info_overlay->add_child(p_control);
  4659. info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
  4660. }
  4661. void CanvasItemEditor::remove_control_from_info_overlay(Control *p_control) {
  4662. info_overlay->remove_child(p_control);
  4663. info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
  4664. }
  4665. void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
  4666. ERR_FAIL_COND(!p_control);
  4667. hb->add_child(p_control);
  4668. }
  4669. void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) {
  4670. hb->remove_child(p_control);
  4671. }
  4672. HSplitContainer *CanvasItemEditor::get_palette_split() {
  4673. return palette_split;
  4674. }
  4675. VSplitContainer *CanvasItemEditor::get_bottom_split() {
  4676. return bottom_split;
  4677. }
  4678. void CanvasItemEditor::focus_selection() {
  4679. _focus_selection(VIEW_CENTER_TO_SELECTION);
  4680. }
  4681. CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
  4682. key_pos = true;
  4683. key_rot = true;
  4684. key_scale = false;
  4685. show_grid = false;
  4686. show_origin = true;
  4687. show_viewport = true;
  4688. show_helpers = false;
  4689. show_rulers = true;
  4690. show_guides = true;
  4691. show_edit_locks = true;
  4692. zoom = 1.0 / MAX(1, EDSCALE);
  4693. view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH);
  4694. previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen
  4695. grid_offset = Point2();
  4696. grid_step = Point2(8, 8); // A power-of-two value works better as a default
  4697. primary_grid_steps = 8; // A power-of-two value works better as a default
  4698. grid_step_multiplier = 0;
  4699. snap_rotation_offset = 0;
  4700. snap_rotation_step = 15 / (180 / Math_PI);
  4701. snap_scale_step = 0.1f;
  4702. smart_snap_active = false;
  4703. grid_snap_active = false;
  4704. snap_node_parent = true;
  4705. snap_node_anchors = true;
  4706. snap_node_sides = true;
  4707. snap_node_center = true;
  4708. snap_other_nodes = true;
  4709. snap_guides = true;
  4710. snap_rotation = false;
  4711. snap_scale = false;
  4712. snap_relative = false;
  4713. snap_pixel = false;
  4714. snap_target[0] = SNAP_TARGET_NONE;
  4715. snap_target[1] = SNAP_TARGET_NONE;
  4716. selected_from_canvas = false;
  4717. anchors_mode = false;
  4718. skeleton_show_bones = true;
  4719. drag_type = DRAG_NONE;
  4720. drag_from = Vector2();
  4721. drag_to = Vector2();
  4722. dragged_guide_pos = Point2();
  4723. dragged_guide_index = -1;
  4724. is_hovering_h_guide = false;
  4725. is_hovering_v_guide = false;
  4726. panning = false;
  4727. pan_pressed = false;
  4728. ruler_tool_active = false;
  4729. ruler_tool_origin = Point2();
  4730. bone_last_frame = 0;
  4731. bone_list_dirty = false;
  4732. tool = TOOL_SELECT;
  4733. undo_redo = p_editor->get_undo_redo();
  4734. editor = p_editor;
  4735. editor_selection = p_editor->get_editor_selection();
  4736. editor_selection->add_editor_plugin(this);
  4737. editor_selection->connect("selection_changed", this, "update");
  4738. editor_selection->connect("selection_changed", this, "_selection_changed");
  4739. editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true));
  4740. editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false));
  4741. hb = memnew(HBoxContainer);
  4742. add_child(hb);
  4743. hb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
  4744. bottom_split = memnew(VSplitContainer);
  4745. add_child(bottom_split);
  4746. bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
  4747. palette_split = memnew(HSplitContainer);
  4748. bottom_split->add_child(palette_split);
  4749. palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
  4750. viewport_scrollable = memnew(Control);
  4751. palette_split->add_child(viewport_scrollable);
  4752. viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS);
  4753. viewport_scrollable->set_clip_contents(true);
  4754. viewport_scrollable->set_v_size_flags(SIZE_EXPAND_FILL);
  4755. viewport_scrollable->set_h_size_flags(SIZE_EXPAND_FILL);
  4756. viewport_scrollable->connect("draw", this, "_update_scrollbars");
  4757. ViewportContainer *scene_tree = memnew(ViewportContainer);
  4758. viewport_scrollable->add_child(scene_tree);
  4759. scene_tree->set_stretch(true);
  4760. scene_tree->set_anchors_and_margins_preset(Control::PRESET_WIDE);
  4761. scene_tree->add_child(p_editor->get_scene_root());
  4762. controls_vb = memnew(VBoxContainer);
  4763. controls_vb->set_begin(Point2(5, 5));
  4764. zoom_hb = memnew(HBoxContainer);
  4765. // Bring the zoom percentage closer to the zoom buttons
  4766. zoom_hb->add_constant_override("separation", Math::round(-8 * EDSCALE));
  4767. controls_vb->add_child(zoom_hb);
  4768. viewport = memnew(CanvasItemEditorViewport(p_editor, this));
  4769. viewport_scrollable->add_child(viewport);
  4770. viewport->set_mouse_filter(MOUSE_FILTER_PASS);
  4771. viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE);
  4772. viewport->set_clip_contents(true);
  4773. viewport->set_focus_mode(FOCUS_ALL);
  4774. viewport->connect("draw", this, "_draw_viewport");
  4775. viewport->connect("gui_input", this, "_gui_input_viewport");
  4776. info_overlay = memnew(VBoxContainer);
  4777. info_overlay->set_anchors_and_margins_preset(Control::PRESET_BOTTOM_LEFT);
  4778. info_overlay->set_margin(MARGIN_LEFT, 10);
  4779. info_overlay->set_margin(MARGIN_BOTTOM, -15);
  4780. info_overlay->set_v_grow_direction(Control::GROW_DIRECTION_BEGIN);
  4781. info_overlay->add_constant_override("separation", 10);
  4782. viewport_scrollable->add_child(info_overlay);
  4783. Theme *info_overlay_theme = memnew(Theme);
  4784. info_overlay_theme->copy_default_theme();
  4785. info_overlay->set_theme(info_overlay_theme);
  4786. StyleBoxFlat *info_overlay_label_stylebox = memnew(StyleBoxFlat);
  4787. info_overlay_label_stylebox->set_bg_color(Color(0.0, 0.0, 0.0, 0.2));
  4788. info_overlay_label_stylebox->set_expand_margin_size_all(4);
  4789. info_overlay_theme->set_stylebox("normal", "Label", info_overlay_label_stylebox);
  4790. warning_child_of_container = memnew(Label);
  4791. warning_child_of_container->hide();
  4792. warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
  4793. warning_child_of_container->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor"));
  4794. warning_child_of_container->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts"));
  4795. add_control_to_info_overlay(warning_child_of_container);
  4796. h_scroll = memnew(HScrollBar);
  4797. viewport->add_child(h_scroll);
  4798. h_scroll->connect("value_changed", this, "_update_scroll");
  4799. h_scroll->hide();
  4800. v_scroll = memnew(VScrollBar);
  4801. viewport->add_child(v_scroll);
  4802. v_scroll->connect("value_changed", this, "_update_scroll");
  4803. v_scroll->hide();
  4804. viewport->add_child(controls_vb);
  4805. zoom_minus = memnew(ToolButton);
  4806. zoom_hb->add_child(zoom_minus);
  4807. zoom_minus->connect("pressed", this, "_button_zoom_minus");
  4808. zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS));
  4809. zoom_minus->set_focus_mode(FOCUS_NONE);
  4810. zoom_reset = memnew(ToolButton);
  4811. zoom_hb->add_child(zoom_reset);
  4812. zoom_reset->connect("pressed", this, "_button_zoom_reset");
  4813. zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0));
  4814. zoom_reset->set_focus_mode(FOCUS_NONE);
  4815. zoom_reset->set_text_align(Button::TextAlign::ALIGN_CENTER);
  4816. // Prevent the button's size from changing when the text size changes
  4817. zoom_reset->set_custom_minimum_size(Size2(75 * EDSCALE, 0));
  4818. zoom_plus = memnew(ToolButton);
  4819. zoom_hb->add_child(zoom_plus);
  4820. zoom_plus->connect("pressed", this, "_button_zoom_plus");
  4821. zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KEY_MASK_CMD | KEY_EQUAL)); // Usually direct access key for PLUS
  4822. zoom_plus->set_focus_mode(FOCUS_NONE);
  4823. updating_scroll = false;
  4824. select_button = memnew(ToolButton);
  4825. hb->add_child(select_button);
  4826. select_button->set_toggle_mode(true);
  4827. select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECT));
  4828. select_button->set_pressed(true);
  4829. select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q));
  4830. select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection"));
  4831. hb->add_child(memnew(VSeparator));
  4832. move_button = memnew(ToolButton);
  4833. hb->add_child(move_button);
  4834. move_button->set_toggle_mode(true);
  4835. move_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_MOVE));
  4836. move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W));
  4837. move_button->set_tooltip(TTR("Move Mode"));
  4838. rotate_button = memnew(ToolButton);
  4839. hb->add_child(rotate_button);
  4840. rotate_button->set_toggle_mode(true);
  4841. rotate_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_ROTATE));
  4842. rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E));
  4843. rotate_button->set_tooltip(TTR("Rotate Mode"));
  4844. scale_button = memnew(ToolButton);
  4845. hb->add_child(scale_button);
  4846. scale_button->set_toggle_mode(true);
  4847. scale_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SCALE));
  4848. scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), KEY_S));
  4849. scale_button->set_tooltip(TTR("Scale Mode"));
  4850. hb->add_child(memnew(VSeparator));
  4851. list_select_button = memnew(ToolButton);
  4852. hb->add_child(list_select_button);
  4853. list_select_button->set_toggle_mode(true);
  4854. list_select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_LIST_SELECT));
  4855. list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
  4856. pivot_button = memnew(ToolButton);
  4857. hb->add_child(pivot_button);
  4858. pivot_button->set_toggle_mode(true);
  4859. pivot_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_EDIT_PIVOT));
  4860. pivot_button->set_tooltip(TTR("Click to change object's rotation pivot."));
  4861. pan_button = memnew(ToolButton);
  4862. hb->add_child(pan_button);
  4863. pan_button->set_toggle_mode(true);
  4864. pan_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PAN));
  4865. pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), KEY_G));
  4866. pan_button->set_tooltip(TTR("Pan Mode"));
  4867. ruler_button = memnew(ToolButton);
  4868. hb->add_child(ruler_button);
  4869. ruler_button->set_toggle_mode(true);
  4870. ruler_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_RULER));
  4871. ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), KEY_R));
  4872. ruler_button->set_tooltip(TTR("Ruler Mode"));
  4873. hb->add_child(memnew(VSeparator));
  4874. smart_snap_button = memnew(ToolButton);
  4875. hb->add_child(smart_snap_button);
  4876. smart_snap_button->set_toggle_mode(true);
  4877. smart_snap_button->connect("toggled", this, "_button_toggle_smart_snap");
  4878. smart_snap_button->set_tooltip(TTR("Toggle smart snapping."));
  4879. smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KEY_MASK_SHIFT | KEY_S));
  4880. grid_snap_button = memnew(ToolButton);
  4881. hb->add_child(grid_snap_button);
  4882. grid_snap_button->set_toggle_mode(true);
  4883. grid_snap_button->connect("toggled", this, "_button_toggle_grid_snap");
  4884. grid_snap_button->set_tooltip(TTR("Toggle grid snapping."));
  4885. grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KEY_MASK_SHIFT | KEY_G));
  4886. snap_config_menu = memnew(MenuButton);
  4887. hb->add_child(snap_config_menu);
  4888. snap_config_menu->set_h_size_flags(SIZE_SHRINK_END);
  4889. snap_config_menu->set_tooltip(TTR("Snapping Options"));
  4890. snap_config_menu->set_switch_on_hover(true);
  4891. PopupMenu *p = snap_config_menu->get_popup();
  4892. p->connect("id_pressed", this, "_popup_callback");
  4893. p->set_hide_on_checkable_item_selection(false);
  4894. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
  4895. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_scale_snap", TTR("Use Scale Snap")), SNAP_USE_SCALE);
  4896. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
  4897. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
  4898. p->add_submenu_item(TTR("Smart Snapping"), "SmartSnapping");
  4899. p->add_separator();
  4900. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap...")), SNAP_CONFIGURE);
  4901. smartsnap_config_popup = memnew(PopupMenu);
  4902. p->add_child(smartsnap_config_popup);
  4903. smartsnap_config_popup->set_name("SmartSnapping");
  4904. smartsnap_config_popup->connect("id_pressed", this, "_popup_callback");
  4905. smartsnap_config_popup->set_hide_on_checkable_item_selection(false);
  4906. smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to Parent")), SNAP_USE_NODE_PARENT);
  4907. smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to Node Anchor")), SNAP_USE_NODE_ANCHORS);
  4908. smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to Node Sides")), SNAP_USE_NODE_SIDES);
  4909. smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_center", TTR("Snap to Node Center")), SNAP_USE_NODE_CENTER);
  4910. smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to Other Nodes")), SNAP_USE_OTHER_NODES);
  4911. smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to Guides")), SNAP_USE_GUIDES);
  4912. hb->add_child(memnew(VSeparator));
  4913. lock_button = memnew(ToolButton);
  4914. hb->add_child(lock_button);
  4915. lock_button->connect("pressed", this, "_popup_callback", varray(LOCK_SELECTED));
  4916. lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
  4917. unlock_button = memnew(ToolButton);
  4918. hb->add_child(unlock_button);
  4919. unlock_button->connect("pressed", this, "_popup_callback", varray(UNLOCK_SELECTED));
  4920. unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved)."));
  4921. group_button = memnew(ToolButton);
  4922. hb->add_child(group_button);
  4923. group_button->connect("pressed", this, "_popup_callback", varray(GROUP_SELECTED));
  4924. group_button->set_tooltip(TTR("Makes sure the object's children are not selectable."));
  4925. ungroup_button = memnew(ToolButton);
  4926. hb->add_child(ungroup_button);
  4927. ungroup_button->connect("pressed", this, "_popup_callback", varray(UNGROUP_SELECTED));
  4928. ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected."));
  4929. hb->add_child(memnew(VSeparator));
  4930. skeleton_menu = memnew(MenuButton);
  4931. hb->add_child(skeleton_menu);
  4932. skeleton_menu->set_tooltip(TTR("Skeleton Options"));
  4933. skeleton_menu->set_switch_on_hover(true);
  4934. p = skeleton_menu->get_popup();
  4935. p->set_hide_on_checkable_item_selection(false);
  4936. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
  4937. p->add_separator();
  4938. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
  4939. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
  4940. p->add_separator();
  4941. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Custom Bone(s) from Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
  4942. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Custom Bones")), SKELETON_CLEAR_BONES);
  4943. p->connect("id_pressed", this, "_popup_callback");
  4944. hb->add_child(memnew(VSeparator));
  4945. override_camera_button = memnew(ToolButton);
  4946. hb->add_child(override_camera_button);
  4947. override_camera_button->connect("toggled", this, "_button_override_camera");
  4948. override_camera_button->set_toggle_mode(true);
  4949. override_camera_button->set_disabled(true);
  4950. _update_override_camera_button(false);
  4951. hb->add_child(memnew(VSeparator));
  4952. view_menu = memnew(MenuButton);
  4953. view_menu->set_text(TTR("View"));
  4954. hb->add_child(view_menu);
  4955. view_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
  4956. view_menu->set_switch_on_hover(true);
  4957. p = view_menu->get_popup();
  4958. p->set_hide_on_checkable_item_selection(false);
  4959. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_MASK_CTRL | KEY_G), SHOW_GRID);
  4960. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS);
  4961. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS);
  4962. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);
  4963. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN);
  4964. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT);
  4965. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS);
  4966. p->add_separator();
  4967. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
  4968. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
  4969. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTR("Clear Guides")), CLEAR_GUIDES);
  4970. p->add_separator();
  4971. p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_P), PREVIEW_CANVAS_SCALE);
  4972. presets_menu = memnew(MenuButton);
  4973. presets_menu->set_text(TTR("Layout"));
  4974. hb->add_child(presets_menu);
  4975. presets_menu->hide();
  4976. presets_menu->set_switch_on_hover(true);
  4977. p = presets_menu->get_popup();
  4978. p->connect("id_pressed", this, "_popup_callback");
  4979. anchors_popup = memnew(PopupMenu);
  4980. p->add_child(anchors_popup);
  4981. anchors_popup->set_name("Anchors");
  4982. anchors_popup->connect("id_pressed", this, "_popup_callback");
  4983. anchor_mode_button = memnew(ToolButton);
  4984. hb->add_child(anchor_mode_button);
  4985. anchor_mode_button->set_toggle_mode(true);
  4986. anchor_mode_button->hide();
  4987. anchor_mode_button->connect("toggled", this, "_button_toggle_anchor_mode");
  4988. animation_hb = memnew(HBoxContainer);
  4989. hb->add_child(animation_hb);
  4990. animation_hb->add_child(memnew(VSeparator));
  4991. animation_hb->hide();
  4992. key_loc_button = memnew(Button);
  4993. key_loc_button->set_toggle_mode(true);
  4994. key_loc_button->set_flat(true);
  4995. key_loc_button->set_pressed(true);
  4996. key_loc_button->set_focus_mode(FOCUS_NONE);
  4997. key_loc_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_POS));
  4998. key_loc_button->set_tooltip(TTR("Translation mask for inserting keys."));
  4999. animation_hb->add_child(key_loc_button);
  5000. key_rot_button = memnew(Button);
  5001. key_rot_button->set_toggle_mode(true);
  5002. key_rot_button->set_flat(true);
  5003. key_rot_button->set_pressed(true);
  5004. key_rot_button->set_focus_mode(FOCUS_NONE);
  5005. key_rot_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_ROT));
  5006. key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys."));
  5007. animation_hb->add_child(key_rot_button);
  5008. key_scale_button = memnew(Button);
  5009. key_scale_button->set_toggle_mode(true);
  5010. key_scale_button->set_flat(true);
  5011. key_scale_button->set_focus_mode(FOCUS_NONE);
  5012. key_scale_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_SCALE));
  5013. key_scale_button->set_tooltip(TTR("Scale mask for inserting keys."));
  5014. animation_hb->add_child(key_scale_button);
  5015. key_insert_button = memnew(Button);
  5016. key_insert_button->set_flat(true);
  5017. key_insert_button->set_focus_mode(FOCUS_NONE);
  5018. key_insert_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_KEY));
  5019. key_insert_button->set_tooltip(TTR("Insert keys (based on mask)."));
  5020. key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), KEY_INSERT));
  5021. animation_hb->add_child(key_insert_button);
  5022. key_auto_insert_button = memnew(Button);
  5023. key_auto_insert_button->set_flat(true);
  5024. key_auto_insert_button->set_toggle_mode(true);
  5025. key_auto_insert_button->set_focus_mode(FOCUS_NONE);
  5026. //key_auto_insert_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_KEY));
  5027. key_auto_insert_button->set_tooltip(TTR("Auto insert keys when objects are translated, rotated or scaled (based on mask).\nKeys are only added to existing tracks, no new tracks will be created.\nKeys must be inserted manually for the first time."));
  5028. key_auto_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_auto_insert_key", TTR("Auto Insert Key")));
  5029. animation_hb->add_child(key_auto_insert_button);
  5030. animation_menu = memnew(MenuButton);
  5031. animation_menu->set_tooltip(TTR("Animation Key and Pose Options"));
  5032. animation_hb->add_child(animation_menu);
  5033. animation_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
  5034. animation_menu->set_switch_on_hover(true);
  5035. p = animation_menu->get_popup();
  5036. p->add_shortcut(ED_GET_SHORTCUT("canvas_item_editor/anim_insert_key"), ANIM_INSERT_KEY);
  5037. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_MASK_CMD + KEY_INSERT), ANIM_INSERT_KEY_EXISTING);
  5038. p->add_separator();
  5039. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_copy_pose", TTR("Copy Pose")), ANIM_COPY_POSE);
  5040. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_paste_pose", TTR("Paste Pose")), ANIM_PASTE_POSE);
  5041. p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_clear_pose", TTR("Clear Pose"), KEY_MASK_SHIFT | KEY_K), ANIM_CLEAR_POSE);
  5042. snap_dialog = memnew(SnapDialog);
  5043. snap_dialog->connect("confirmed", this, "_snap_changed");
  5044. add_child(snap_dialog);
  5045. select_sb = Ref<StyleBoxTexture>(memnew(StyleBoxTexture));
  5046. selection_menu = memnew(PopupMenu);
  5047. add_child(selection_menu);
  5048. selection_menu->set_custom_minimum_size(Vector2(100, 0));
  5049. selection_menu->connect("id_pressed", this, "_selection_result_pressed");
  5050. selection_menu->connect("popup_hide", this, "_selection_menu_hide");
  5051. multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
  5052. divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
  5053. pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE);
  5054. skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true);
  5055. singleton = this;
  5056. set_process_unhandled_key_input(true);
  5057. // Update the menus' checkboxes
  5058. call_deferred("set_state", get_state());
  5059. }
  5060. CanvasItemEditor *CanvasItemEditor::singleton = NULL;
  5061. void CanvasItemEditorPlugin::edit(Object *p_object) {
  5062. canvas_item_editor->set_undo_redo(&get_undo_redo());
  5063. canvas_item_editor->edit(Object::cast_to<CanvasItem>(p_object));
  5064. }
  5065. bool CanvasItemEditorPlugin::handles(Object *p_object) const {
  5066. return p_object->is_class("CanvasItem");
  5067. }
  5068. void CanvasItemEditorPlugin::make_visible(bool p_visible) {
  5069. if (p_visible) {
  5070. canvas_item_editor->show();
  5071. canvas_item_editor->set_physics_process(true);
  5072. VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false);
  5073. } else {
  5074. canvas_item_editor->hide();
  5075. canvas_item_editor->set_physics_process(false);
  5076. VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), true);
  5077. }
  5078. }
  5079. Dictionary CanvasItemEditorPlugin::get_state() const {
  5080. return canvas_item_editor->get_state();
  5081. }
  5082. void CanvasItemEditorPlugin::set_state(const Dictionary &p_state) {
  5083. canvas_item_editor->set_state(p_state);
  5084. }
  5085. CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) {
  5086. editor = p_node;
  5087. canvas_item_editor = memnew(CanvasItemEditor(editor));
  5088. canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  5089. editor->get_viewport()->add_child(canvas_item_editor);
  5090. canvas_item_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
  5091. canvas_item_editor->hide();
  5092. }
  5093. CanvasItemEditorPlugin::~CanvasItemEditorPlugin() {
  5094. }
  5095. void CanvasItemEditorViewport::_on_mouse_exit() {
  5096. if (!selector->is_visible()) {
  5097. _remove_preview();
  5098. }
  5099. }
  5100. void CanvasItemEditorViewport::_on_select_type(Object *selected) {
  5101. CheckBox *check = Object::cast_to<CheckBox>(selected);
  5102. String type = check->get_text();
  5103. selector->set_title(vformat(TTR("Add %s"), type));
  5104. label->set_text(vformat(TTR("Adding %s..."), type));
  5105. }
  5106. void CanvasItemEditorViewport::_on_change_type_confirmed() {
  5107. if (!button_group->get_pressed_button())
  5108. return;
  5109. CheckBox *check = Object::cast_to<CheckBox>(button_group->get_pressed_button());
  5110. default_type = check->get_text();
  5111. _perform_drop_data();
  5112. selector->hide();
  5113. }
  5114. void CanvasItemEditorViewport::_on_change_type_closed() {
  5115. _remove_preview();
  5116. }
  5117. void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
  5118. bool add_preview = false;
  5119. for (int i = 0; i < files.size(); i++) {
  5120. String path = files[i];
  5121. RES res = ResourceLoader::load(path);
  5122. ERR_FAIL_COND(res.is_null());
  5123. Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
  5124. Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
  5125. if (texture != NULL || scene != NULL) {
  5126. if (texture != NULL) {
  5127. Sprite *sprite = memnew(Sprite);
  5128. sprite->set_texture(texture);
  5129. sprite->set_modulate(Color(1, 1, 1, 0.7f));
  5130. preview_node->add_child(sprite);
  5131. label->show();
  5132. label_desc->show();
  5133. } else {
  5134. if (scene.is_valid()) {
  5135. Node *instance = scene->instance();
  5136. if (instance) {
  5137. preview_node->add_child(instance);
  5138. }
  5139. }
  5140. }
  5141. add_preview = true;
  5142. }
  5143. }
  5144. if (add_preview)
  5145. editor->get_scene_root()->add_child(preview_node);
  5146. }
  5147. void CanvasItemEditorViewport::_remove_preview() {
  5148. if (preview_node->get_parent()) {
  5149. for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
  5150. Node *node = preview_node->get_child(i);
  5151. node->queue_delete();
  5152. preview_node->remove_child(node);
  5153. }
  5154. editor->get_scene_root()->remove_child(preview_node);
  5155. label->hide();
  5156. label_desc->hide();
  5157. }
  5158. }
  5159. bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
  5160. if (p_desired_node->get_filename() == p_target_scene_path) {
  5161. return true;
  5162. }
  5163. int childCount = p_desired_node->get_child_count();
  5164. for (int i = 0; i < childCount; i++) {
  5165. Node *child = p_desired_node->get_child(i);
  5166. if (_cyclical_dependency_exists(p_target_scene_path, child)) {
  5167. return true;
  5168. }
  5169. }
  5170. return false;
  5171. }
  5172. void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point) {
  5173. child->set_name(path.get_file().get_basename());
  5174. Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(ResourceCache::get(path)));
  5175. Size2 texture_size = texture->get_size();
  5176. if (parent) {
  5177. editor_data->get_undo_redo().add_do_method(parent, "add_child", child);
  5178. editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
  5179. editor_data->get_undo_redo().add_do_reference(child);
  5180. editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child);
  5181. } else { // if we haven't parent, lets try to make a child as a parent.
  5182. editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
  5183. editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
  5184. editor_data->get_undo_redo().add_do_reference(child);
  5185. editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
  5186. }
  5187. if (parent) {
  5188. String new_name = parent->validate_child_name(child);
  5189. ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
  5190. editor_data->get_undo_redo().add_do_method(sed, "live_debug_create_node", editor->get_edited_scene()->get_path_to(parent), child->get_class(), new_name);
  5191. editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
  5192. }
  5193. // handle with different property for texture
  5194. String property = "texture";
  5195. List<PropertyInfo> props;
  5196. child->get_property_list(&props);
  5197. for (const List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
  5198. if (E->get().name == "config/texture") { // Particles2D
  5199. property = "config/texture";
  5200. break;
  5201. } else if (E->get().name == "texture/texture") { // Polygon2D
  5202. property = "texture/texture";
  5203. break;
  5204. } else if (E->get().name == "normal") { // TouchScreenButton
  5205. property = "normal";
  5206. break;
  5207. }
  5208. }
  5209. editor_data->get_undo_redo().add_do_property(child, property, texture);
  5210. // make visible for certain node type
  5211. if (default_type == "NinePatchRect") {
  5212. editor_data->get_undo_redo().add_do_property(child, "rect/size", texture_size);
  5213. } else if (default_type == "Polygon2D") {
  5214. PoolVector<Vector2> list;
  5215. list.push_back(Vector2(0, 0));
  5216. list.push_back(Vector2(texture_size.width, 0));
  5217. list.push_back(Vector2(texture_size.width, texture_size.height));
  5218. list.push_back(Vector2(0, texture_size.height));
  5219. editor_data->get_undo_redo().add_do_property(child, "polygon", list);
  5220. }
  5221. // Compute the global position
  5222. Transform2D xform = canvas_item_editor->get_canvas_transform();
  5223. Point2 target_position = xform.affine_inverse().xform(p_point);
  5224. // there's nothing to be used as source position so snapping will work as absolute if enabled
  5225. target_position = canvas_item_editor->snap_point(target_position);
  5226. editor_data->get_undo_redo().add_do_method(child, "set_global_position", target_position);
  5227. }
  5228. bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
  5229. Ref<PackedScene> sdata = ResourceLoader::load(path);
  5230. if (!sdata.is_valid()) { // invalid scene
  5231. return false;
  5232. }
  5233. Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
  5234. if (!instanced_scene) { // error on instancing
  5235. return false;
  5236. }
  5237. if (editor->get_edited_scene()->get_filename() != "") { // cyclical instancing
  5238. if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) {
  5239. memdelete(instanced_scene);
  5240. return false;
  5241. }
  5242. }
  5243. instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
  5244. editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene);
  5245. editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene());
  5246. editor_data->get_undo_redo().add_do_reference(instanced_scene);
  5247. editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instanced_scene);
  5248. String new_name = parent->validate_child_name(instanced_scene);
  5249. ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
  5250. editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name);
  5251. editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
  5252. CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent);
  5253. if (parent_ci) {
  5254. Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point);
  5255. target_pos = canvas_item_editor->snap_point(target_pos);
  5256. target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos);
  5257. // Preserve instance position of the original scene.
  5258. CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instanced_scene);
  5259. if (instance_ci) {
  5260. target_pos += instance_ci->_edit_get_position();
  5261. }
  5262. editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
  5263. }
  5264. return true;
  5265. }
  5266. void CanvasItemEditorViewport::_perform_drop_data() {
  5267. _remove_preview();
  5268. // Without root dropping multiple files is not allowed
  5269. if (!target_node && selected_files.size() > 1) {
  5270. accept->set_text(TTR("Cannot instantiate multiple nodes without root."));
  5271. accept->popup_centered_minsize();
  5272. return;
  5273. }
  5274. Vector<String> error_files;
  5275. editor_data->get_undo_redo().create_action(TTR("Create Node"));
  5276. for (int i = 0; i < selected_files.size(); i++) {
  5277. String path = selected_files[i];
  5278. RES res = ResourceLoader::load(path);
  5279. if (res.is_null()) {
  5280. continue;
  5281. }
  5282. Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
  5283. if (scene != NULL && scene.is_valid()) {
  5284. if (!target_node) {
  5285. // Without root node act the same as "Load Inherited Scene"
  5286. Error err = EditorNode::get_singleton()->load_scene(path, false, true);
  5287. if (err != OK) {
  5288. error_files.push_back(path);
  5289. }
  5290. } else {
  5291. bool success = _create_instance(target_node, path, drop_pos);
  5292. if (!success) {
  5293. error_files.push_back(path);
  5294. }
  5295. }
  5296. } else {
  5297. Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
  5298. if (texture != NULL && texture.is_valid()) {
  5299. Node *child;
  5300. if (default_type == "Light2D")
  5301. child = memnew(Light2D);
  5302. else if (default_type == "Particles2D")
  5303. child = memnew(Particles2D);
  5304. else if (default_type == "Polygon2D")
  5305. child = memnew(Polygon2D);
  5306. else if (default_type == "TouchScreenButton")
  5307. child = memnew(TouchScreenButton);
  5308. else if (default_type == "TextureRect")
  5309. child = memnew(TextureRect);
  5310. else if (default_type == "NinePatchRect")
  5311. child = memnew(NinePatchRect);
  5312. else
  5313. child = memnew(Sprite); // default
  5314. _create_nodes(target_node, child, path, drop_pos);
  5315. }
  5316. }
  5317. }
  5318. editor_data->get_undo_redo().commit_action();
  5319. if (error_files.size() > 0) {
  5320. String files_str;
  5321. for (int i = 0; i < error_files.size(); i++) {
  5322. files_str += error_files[i].get_file().get_basename() + ",";
  5323. }
  5324. files_str = files_str.substr(0, files_str.length() - 1);
  5325. accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str()));
  5326. accept->popup_centered_minsize();
  5327. }
  5328. }
  5329. bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
  5330. Dictionary d = p_data;
  5331. if (d.has("type")) {
  5332. if (String(d["type"]) == "files") {
  5333. Vector<String> files = d["files"];
  5334. bool can_instance = false;
  5335. for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least once
  5336. RES res = ResourceLoader::load(files[i]);
  5337. if (res.is_null()) {
  5338. continue;
  5339. }
  5340. String type = res->get_class();
  5341. if (type == "PackedScene") {
  5342. Ref<PackedScene> sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
  5343. Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
  5344. if (!instanced_scene) {
  5345. continue;
  5346. }
  5347. memdelete(instanced_scene);
  5348. } else if (type == "Texture" ||
  5349. type == "ImageTexture" ||
  5350. type == "ViewportTexture" ||
  5351. type == "CurveTexture" ||
  5352. type == "GradientTexture" ||
  5353. type == "StreamTexture" ||
  5354. type == "AtlasTexture" ||
  5355. type == "LargeTexture") {
  5356. Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
  5357. if (!texture.is_valid()) {
  5358. continue;
  5359. }
  5360. } else {
  5361. continue;
  5362. }
  5363. can_instance = true;
  5364. break;
  5365. }
  5366. if (can_instance) {
  5367. if (!preview_node->get_parent()) { // create preview only once
  5368. _create_preview(files);
  5369. }
  5370. Transform2D trans = canvas_item_editor->get_canvas_transform();
  5371. preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
  5372. label->set_text(vformat(TTR("Adding %s..."), default_type));
  5373. }
  5374. return can_instance;
  5375. }
  5376. }
  5377. label->hide();
  5378. return false;
  5379. }
  5380. void CanvasItemEditorViewport::_show_resource_type_selector() {
  5381. _remove_preview();
  5382. List<BaseButton *> btn_list;
  5383. button_group->get_buttons(&btn_list);
  5384. for (int i = 0; i < btn_list.size(); i++) {
  5385. CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]);
  5386. check->set_pressed(check->get_text() == default_type);
  5387. }
  5388. selector->set_title(vformat(TTR("Add %s"), default_type));
  5389. selector->popup_centered_minsize();
  5390. }
  5391. bool CanvasItemEditorViewport::_only_packed_scenes_selected() const {
  5392. for (int i = 0; i < selected_files.size(); ++i) {
  5393. if (ResourceLoader::load(selected_files[i])->get_class() != "PackedScene") {
  5394. return false;
  5395. }
  5396. }
  5397. return true;
  5398. }
  5399. void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
  5400. bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
  5401. bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
  5402. selected_files.clear();
  5403. Dictionary d = p_data;
  5404. if (d.has("type") && String(d["type"]) == "files") {
  5405. selected_files = d["files"];
  5406. }
  5407. if (selected_files.size() == 0)
  5408. return;
  5409. List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
  5410. if (list.size() == 0) {
  5411. Node *root_node = editor->get_edited_scene();
  5412. if (root_node) {
  5413. list.push_back(root_node);
  5414. } else {
  5415. drop_pos = p_point;
  5416. target_node = NULL;
  5417. }
  5418. }
  5419. if (list.size() > 0) {
  5420. target_node = list[0];
  5421. if (is_shift && target_node != editor->get_edited_scene()) {
  5422. target_node = target_node->get_parent();
  5423. }
  5424. }
  5425. drop_pos = p_point;
  5426. if (is_alt && !_only_packed_scenes_selected()) {
  5427. _show_resource_type_selector();
  5428. } else {
  5429. _perform_drop_data();
  5430. }
  5431. }
  5432. void CanvasItemEditorViewport::_notification(int p_what) {
  5433. switch (p_what) {
  5434. case NOTIFICATION_ENTER_TREE: {
  5435. connect("mouse_exited", this, "_on_mouse_exit");
  5436. label->add_color_override("font_color", get_color("warning_color", "Editor"));
  5437. } break;
  5438. case NOTIFICATION_EXIT_TREE: {
  5439. disconnect("mouse_exited", this, "_on_mouse_exit");
  5440. } break;
  5441. default: break;
  5442. }
  5443. }
  5444. void CanvasItemEditorViewport::_bind_methods() {
  5445. ClassDB::bind_method(D_METHOD("_on_select_type"), &CanvasItemEditorViewport::_on_select_type);
  5446. ClassDB::bind_method(D_METHOD("_on_change_type_confirmed"), &CanvasItemEditorViewport::_on_change_type_confirmed);
  5447. ClassDB::bind_method(D_METHOD("_on_change_type_closed"), &CanvasItemEditorViewport::_on_change_type_closed);
  5448. ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit);
  5449. }
  5450. CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor) {
  5451. default_type = "Sprite";
  5452. // Node2D
  5453. types.push_back("Sprite");
  5454. types.push_back("Light2D");
  5455. types.push_back("Particles2D");
  5456. types.push_back("Polygon2D");
  5457. types.push_back("TouchScreenButton");
  5458. // Control
  5459. types.push_back("TextureRect");
  5460. types.push_back("NinePatchRect");
  5461. target_node = NULL;
  5462. editor = p_node;
  5463. editor_data = editor->get_scene_tree_dock()->get_editor_data();
  5464. canvas_item_editor = p_canvas_item_editor;
  5465. preview_node = memnew(Node2D);
  5466. accept = memnew(AcceptDialog);
  5467. editor->get_gui_base()->add_child(accept);
  5468. selector = memnew(AcceptDialog);
  5469. editor->get_gui_base()->add_child(selector);
  5470. selector->set_title(TTR("Change Default Type"));
  5471. selector->connect("confirmed", this, "_on_change_type_confirmed");
  5472. selector->connect("popup_hide", this, "_on_change_type_closed");
  5473. VBoxContainer *vbc = memnew(VBoxContainer);
  5474. selector->add_child(vbc);
  5475. vbc->set_h_size_flags(SIZE_EXPAND_FILL);
  5476. vbc->set_v_size_flags(SIZE_EXPAND_FILL);
  5477. vbc->set_custom_minimum_size(Size2(240, 260) * EDSCALE);
  5478. btn_group = memnew(VBoxContainer);
  5479. vbc->add_child(btn_group);
  5480. btn_group->set_h_size_flags(0);
  5481. button_group.instance();
  5482. for (int i = 0; i < types.size(); i++) {
  5483. CheckBox *check = memnew(CheckBox);
  5484. btn_group->add_child(check);
  5485. check->set_text(types[i]);
  5486. check->connect("button_down", this, "_on_select_type", varray(check));
  5487. check->set_button_group(button_group);
  5488. }
  5489. label = memnew(Label);
  5490. label->add_color_override("font_color_shadow", Color(0, 0, 0, 1));
  5491. label->add_constant_override("shadow_as_outline", 1 * EDSCALE);
  5492. label->hide();
  5493. canvas_item_editor->get_controls_container()->add_child(label);
  5494. label_desc = memnew(Label);
  5495. label_desc->set_text(TTR("Drag & drop + Shift : Add node as sibling\nDrag & drop + Alt : Change node type"));
  5496. label_desc->add_color_override("font_color", Color(0.6f, 0.6f, 0.6f, 1));
  5497. label_desc->add_color_override("font_color_shadow", Color(0.2f, 0.2f, 0.2f, 1));
  5498. label_desc->add_constant_override("shadow_as_outline", 1 * EDSCALE);
  5499. label_desc->add_constant_override("line_spacing", 0);
  5500. label_desc->hide();
  5501. canvas_item_editor->get_controls_container()->add_child(label_desc);
  5502. VS::get_singleton()->canvas_set_disable_scale(true);
  5503. }
  5504. CanvasItemEditorViewport::~CanvasItemEditorViewport() {
  5505. memdelete(preview_node);
  5506. }