MainWindow.cpp 168 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <ISystem.h>
  9. #include <IConsole.h>
  10. #include <Editor/View/Windows/MainWindow.h>
  11. #include <Editor/GraphCanvas/AutomationIds.h>
  12. #include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
  13. #include <QSplitter>
  14. #include <QListView>
  15. #include <QShortcut>
  16. #include <QKeySequence>
  17. #include <QKeyEvent>
  18. #include <QApplication>
  19. #include <QClipboard>
  20. #include <QHBoxLayout>
  21. #include <QVBoxLayout>
  22. #include <QGraphicsScene>
  23. #include <QGraphicsView>
  24. #include <QGraphicsSceneEvent>
  25. #include <QMimeData>
  26. #include <QCoreApplication>
  27. #include <QMessageBox>
  28. #include <QDir>
  29. #include <QDirIterator>
  30. #include <QProgressDialog>
  31. #include <QToolButton>
  32. #include <ScriptEvents/ScriptEventsAsset.h>
  33. #include <Editor/GraphCanvas/Components/MappingComponent.h>
  34. #include <Editor/View/Dialogs/UnsavedChangesDialog.h>
  35. #include <Editor/View/Dialogs/SettingsDialog.h>
  36. #include <Editor/View/Widgets/ScriptCanvasNodePaletteDockWidget.h>
  37. #include <Editor/View/Widgets/PropertyGrid.h>
  38. #include <Editor/View/Widgets/CommandLine.h>
  39. #include <Editor/View/Widgets/GraphTabBar.h>
  40. #include <Editor/View/Widgets/CanvasWidget.h>
  41. #include <Editor/View/Widgets/LogPanel.h>
  42. #include <Editor/View/Widgets/LoggingPanel/LoggingWindow.h>
  43. #include <Editor/View/Widgets/MainWindowStatusWidget.h>
  44. #include <Editor/View/Widgets/NodePalette/NodePaletteModel.h>
  45. #include <Editor/View/Widgets/StatisticsDialog/ScriptCanvasStatisticsDialog.h>
  46. #include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
  47. #include <Editor/View/Widgets/UnitTestPanel/UnitTestDockWidget.h>
  48. #include <Editor/View/Widgets/ValidationPanel/GraphValidationDockWidget.h>
  49. #include <Editor/View/Windows/ui_mainwindow.h>
  50. #include <Editor/Model/EntityMimeDataHandler.h>
  51. #include <Editor/Utilities/RecentAssetPath.h>
  52. #include <Editor/Settings.h>
  53. #include <Editor/Nodes/NodeCreateUtils.h>
  54. #include <AzCore/Asset/AssetManager.h>
  55. #include <AzCore/Asset/AssetManagerBus.h>
  56. #include <AzCore/Utils/Utils.h>
  57. #include <AzCore/Component/ComponentApplicationBus.h>
  58. #include <AzCore/Component/EntityUtils.h>
  59. #include <AzCore/Component/TransformBus.h>
  60. #include <AzCore/IO/FileIO.h>
  61. #include <AzCore/Math/Color.h>
  62. #include <AzCore/Math/Vector2.h>
  63. #include <AzCore/Math/Vector3.h>
  64. #include <AzCore/Math/Vector4.h>
  65. #include <AzCore/Serialization/IdUtils.h>
  66. #include <AzCore/Serialization/Utils.h>
  67. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  68. #include <AzCore/std/containers/array.h>
  69. #include <AzCore/std/containers/set.h>
  70. #include <AzCore/std/smart_ptr/make_shared.h>
  71. #include <AzFramework/Asset/AssetCatalog.h>
  72. #include <AzFramework/StringFunc/StringFunc.h>
  73. #include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
  74. #include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
  75. #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
  76. #include <AzToolsFramework/API/EntityCompositionRequestBus.h>
  77. #include <AzToolsFramework/API/ToolsApplicationAPI.h>
  78. #include <AzToolsFramework/ToolsComponents/EditorEntityIdContainer.h>
  79. #include <AzToolsFramework/ToolsComponents/GenericComponentWrapper.h>
  80. #include <AzToolsFramework/ToolsComponents/ToolsAssetCatalogBus.h>
  81. #include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
  82. #include <AzQtComponents/Components/Widgets/FileDialog.h>
  83. #include <AzQtComponents/Components/Widgets/TabWidget.h>
  84. #include <ScriptCanvas/Core/ScriptCanvasBus.h>
  85. #include <ScriptCanvas/Core/Graph.h>
  86. #include <ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h>
  87. #include <GraphCanvas/GraphCanvasBus.h>
  88. #include <GraphCanvas/Components/Nodes/NodeBus.h>
  89. #include <GraphCanvas/Components/GeometryBus.h>
  90. #include <GraphCanvas/Components/GridBus.h>
  91. #include <GraphCanvas/Components/ViewBus.h>
  92. #include <GraphCanvas/Components/VisualBus.h>
  93. #include <GraphCanvas/Components/MimeDataHandlerBus.h>
  94. #include <GraphCanvas/Components/Connections/ConnectionBus.h>
  95. #include <GraphCanvas/Styling/Parser.h>
  96. #include <GraphCanvas/Styling/Style.h>
  97. #include <GraphCanvas/Widgets/AssetEditorToolbar/AssetEditorToolbar.h>
  98. #include <GraphCanvas/Widgets/Bookmarks/BookmarkDockWidget.h>
  99. #include <GraphCanvas/Widgets/GraphCanvasMimeContainer.h>
  100. #include <GraphCanvas/Widgets/MiniMapGraphicsView/MiniMapGraphicsView.h>
  101. #include <GraphCanvas/Widgets/GraphCanvasEditor/GraphCanvasEditorCentralWidget.h>
  102. #include <GraphCanvas/Widgets/GraphCanvasGraphicsView/GraphCanvasGraphicsView.h>
  103. #include <GraphCanvas/Widgets/EditorContextMenu/EditorContextMenu.h>
  104. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/BookmarkContextMenu.h>
  105. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/CollapsedNodeGroupContextMenu.h>
  106. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/ConnectionContextMenu.h>
  107. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/NodeGroupContextMenu.h>
  108. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/NodeContextMenu.h>
  109. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/CommentContextMenu.h>
  110. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/SceneContextMenu.h>
  111. #include <GraphCanvas/Widgets/EditorContextMenu/ContextMenus/SlotContextMenu.h>
  112. #include <GraphCanvas/Utils/ConversionUtils.h>
  113. #include <GraphCanvas/Utils/NodeNudgingController.h>
  114. #include <GraphCanvas/Types/ConstructPresets.h>
  115. #include <Editor/View/Windows/ScriptCanvasContextMenus.h>
  116. #include <Editor/View/Windows/ScriptEventMenu.h>
  117. #include <Editor/View/Windows/EBusHandlerActionMenu.h>
  118. #include <Editor/View/Widgets/NodePalette/CreateNodeMimeEvent.h>
  119. #include <Editor/View/Widgets/NodePalette/EBusNodePaletteTreeItemTypes.h>
  120. #include <Editor/View/Windows/Tools/InterpreterWidget/InterpreterWidget.h>
  121. #include <Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h>
  122. #include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
  123. #include <Editor/View/Widgets/VariablePanel/VariableConfigurationWidget.h>
  124. // Save Format Conversion
  125. #include <AzCore/Component/EntityUtils.h>
  126. #include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
  127. ////
  128. #include <Editor/Assets/ScriptCanvasAssetHelpers.h>
  129. #include <ScriptCanvas/Asset/AssetDescription.h>
  130. #include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
  131. #include <Editor/QtMetaTypes.h>
  132. #include <GraphCanvas/Components/SceneBus.h>
  133. #include <Editor/LyViewPaneNames.h>
  134. namespace ScriptCanvasEditor
  135. {
  136. using namespace AzToolsFramework;
  137. namespace
  138. {
  139. template <typename T>
  140. class ScopedVariableSetter
  141. {
  142. public:
  143. ScopedVariableSetter(T& value)
  144. : m_oldValue(value)
  145. , m_value(value)
  146. {
  147. }
  148. ScopedVariableSetter(T& value, const T& newValue)
  149. : m_oldValue(value)
  150. , m_value(value)
  151. {
  152. m_value = newValue;
  153. }
  154. ~ScopedVariableSetter()
  155. {
  156. m_value = m_oldValue;
  157. }
  158. private:
  159. T m_oldValue;
  160. T& m_value;
  161. };
  162. template<typename MimeDataDelegateHandler, typename ... ComponentArgs>
  163. AZ::EntityId CreateMimeDataDelegate(ComponentArgs... componentArgs)
  164. {
  165. AZ::Entity* mimeDelegateEntity = aznew AZ::Entity("MimeData Delegate");
  166. mimeDelegateEntity->CreateComponent<MimeDataDelegateHandler>(AZStd::forward<ComponentArgs>(componentArgs) ...);
  167. mimeDelegateEntity->Init();
  168. mimeDelegateEntity->Activate();
  169. return mimeDelegateEntity->GetId();
  170. }
  171. } // anonymous namespace.
  172. void Workspace::Save()
  173. {
  174. auto workspace = AZ::UserSettings::CreateFind<EditorSettings::EditorWorkspace>(AZ_CRC("ScriptCanvasEditorWindowState", 0x10c47d36), AZ::UserSettings::CT_LOCAL);
  175. if (workspace)
  176. {
  177. workspace->Init(m_mainWindow->saveState(), m_mainWindow->saveGeometry());
  178. Widget::GraphTabBar* tabBar = m_mainWindow->m_tabBar;
  179. AZStd::vector<EditorSettings::EditorWorkspace::WorkspaceAssetSaveData> activeAssets;
  180. SourceHandle focusedAssetId = tabBar->FindAssetId(tabBar->currentIndex());
  181. if (m_rememberOpenCanvases)
  182. {
  183. activeAssets.reserve(tabBar->count());
  184. for (int i = 0; i < tabBar->count(); ++i)
  185. {
  186. SourceHandle assetId = tabBar->FindAssetId(i);
  187. const Tracker::ScriptCanvasFileState& fileState = m_mainWindow->GetAssetFileState(assetId);
  188. if (fileState == Tracker::ScriptCanvasFileState::MODIFIED || fileState == Tracker::ScriptCanvasFileState::UNMODIFIED)
  189. {
  190. SourceHandle sourceId = GetSourceAssetId(assetId);
  191. if (sourceId.IsGraphValid())
  192. {
  193. EditorSettings::EditorWorkspace::WorkspaceAssetSaveData assetSaveData;
  194. assetSaveData.m_assetId = sourceId;
  195. activeAssets.push_back(assetSaveData);
  196. }
  197. }
  198. else if (assetId.AnyEquals(focusedAssetId))
  199. {
  200. focusedAssetId.Clear();
  201. }
  202. }
  203. // The assetId needs to be the file AssetId to restore the workspace
  204. if (focusedAssetId.IsGraphValid())
  205. {
  206. focusedAssetId = GetSourceAssetId(focusedAssetId);
  207. }
  208. // If our currently focused asset won't be restored, just show the first element.
  209. if (!focusedAssetId.IsGraphValid())
  210. {
  211. if (!activeAssets.empty())
  212. {
  213. focusedAssetId = activeAssets.front().m_assetId;
  214. }
  215. }
  216. }
  217. workspace->Clear();
  218. if (!activeAssets.empty())
  219. {
  220. workspace->ConfigureActiveAssets(focusedAssetId, activeAssets);
  221. }
  222. }
  223. }
  224. // Workspace
  225. void Workspace::Restore()
  226. {
  227. auto workspace = AZ::UserSettings::Find<EditorSettings::EditorWorkspace>(AZ_CRC("ScriptCanvasEditorWindowState", 0x10c47d36), AZ::UserSettings::CT_LOCAL);
  228. if (workspace)
  229. {
  230. workspace->Restore(qobject_cast<QMainWindow*>(m_mainWindow));
  231. if (m_rememberOpenCanvases)
  232. {
  233. for (const auto& assetSaveData : workspace->GetActiveAssetData())
  234. {
  235. m_loadingAssets.push_back(assetSaveData.m_assetId);
  236. }
  237. if (m_loadingAssets.empty())
  238. {
  239. m_mainWindow->OnWorkspaceRestoreEnd(SourceHandle());
  240. }
  241. else
  242. {
  243. m_mainWindow->OnWorkspaceRestoreStart();
  244. }
  245. m_queuedAssetFocus = workspace->GetFocusedAssetId();
  246. // #sc-asset-editor
  247. //for (const auto& assetSaveData : workspace->GetActiveAssetData())
  248. {
  249. // load all the files
  250. // AssetTrackerNotificationBus::MultiHandler::BusConnect(assetSaveData.m_assetId);
  251. //
  252. // Callbacks::OnAssetReadyCallback onAssetReady = [this, assetSaveData](ScriptCanvasMemoryAsset& asset)
  253. // {
  254. // // If we get an error callback. Just remove it from out active lists.
  255. // if (asset.IsSourceInError())
  256. // {
  257. // if (assetSaveData.m_assetId == m_queuedAssetFocus)
  258. // {
  259. // m_queuedAssetFocus = SourceHandle();
  260. // }
  261. //
  262. // SignalAssetComplete(asset.GetFileAssetId());
  263. // }
  264. // };
  265. //
  266. // bool loadedFile = true;
  267. // AssetTrackerRequestBus::BroadcastResult(loadedFile, &AssetTrackerRequests::Load, assetSaveData.m_assetId, assetSaveData.m_assetType, onAssetReady);
  268. //
  269. // if (!loadedFile)
  270. // {
  271. // if (assetSaveData.m_assetId == m_queuedAssetFocus)
  272. // {
  273. // m_queuedAssetFocus = SourceHandle();
  274. // }
  275. //
  276. // SignalAssetComplete(assetSaveData.m_assetId);
  277. // }
  278. }
  279. }
  280. else
  281. {
  282. m_mainWindow->OnWorkspaceRestoreEnd(SourceHandle());
  283. }
  284. }
  285. }
  286. void Workspace::SignalAssetComplete(const SourceHandle& /*fileAssetId*/)
  287. {
  288. // When we are done loading all assets we can safely set the focus to the recorded asset
  289. // auto it = AZStd::find(m_loadingAssets.begin(), m_loadingAssets.end(), fileAssetId);
  290. // if (it != m_loadingAssets.end())
  291. // {
  292. // m_loadingAssets.erase(it);
  293. // }
  294. //
  295. // if (m_loadingAssets.empty())
  296. // {
  297. // m_mainWindow->OnWorkspaceRestoreEnd(m_queuedAssetFocus);
  298. // m_queuedAssetFocus.SetInvalid();
  299. // }
  300. }
  301. SourceHandle Workspace::GetSourceAssetId(const SourceHandle& memoryAssetId) const
  302. {
  303. return memoryAssetId;
  304. }
  305. ////////////////
  306. // MainWindow
  307. ////////////////
  308. MainWindow::MainWindow(QWidget* parent)
  309. : QMainWindow(parent, Qt::Widget | Qt::WindowMinMaxButtonsHint)
  310. , ui(new Ui::MainWindow)
  311. , m_loadingNewlySavedFile(false)
  312. , m_isClosingTabs(false)
  313. , m_enterState(false)
  314. , m_ignoreSelection(false)
  315. , m_isRestoringWorkspace(false)
  316. , m_preventUndoStateUpdateCount(0)
  317. , m_queueCloseRequest(false)
  318. , m_hasQueuedClose(false)
  319. , m_isInAutomation(false)
  320. , m_allowAutoSave(true)
  321. , m_systemTickActions(0)
  322. , m_closeCurrentGraphAfterSave(false)
  323. , m_styleManager(ScriptCanvasEditor::AssetEditorId, "ScriptCanvas/StyleSheet/graphcanvas_style.json")
  324. {
  325. AZ_PROFILE_FUNCTION(ScriptCanvas);
  326. VariablePaletteRequestBus::Handler::BusConnect();
  327. GraphCanvas::AssetEditorAutomationRequestBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
  328. AZStd::array<char, AZ::IO::MaxPathLength> unresolvedPath;
  329. AZ::IO::FileIOBase::GetInstance()->ResolvePath("@products@/translation/scriptcanvas_en_us.qm", unresolvedPath.data(), unresolvedPath.size());
  330. QString translationFilePath(unresolvedPath.data());
  331. if ( m_translator.load(QLocale::Language::English, translationFilePath) )
  332. {
  333. if ( !qApp->installTranslator(&m_translator) )
  334. {
  335. AZ_Warning("ScriptCanvas", false, "Error installing translation %s!", unresolvedPath.data());
  336. }
  337. }
  338. else
  339. {
  340. AZ_Warning("ScriptCanvas", false, "Error loading translation file %s", unresolvedPath.data());
  341. }
  342. AzToolsFramework::AssetBrowser::AssetBrowserModel* assetBrowserModel = nullptr;
  343. AzToolsFramework::AssetBrowser::AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AzToolsFramework::AssetBrowser::AssetBrowserComponentRequests::GetAssetBrowserModel);
  344. {
  345. m_scriptEventsAssetModel = new ScriptCanvasAssetBrowserModel(this);
  346. AzToolsFramework::AssetBrowser::AssetGroupFilter* scriptEventAssetFilter = new AzToolsFramework::AssetBrowser::AssetGroupFilter();
  347. scriptEventAssetFilter->SetAssetGroup(ScriptEvents::ScriptEventsAsset::GetGroup());
  348. scriptEventAssetFilter->SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down);
  349. m_scriptEventsAssetModel->setSourceModel(assetBrowserModel);
  350. }
  351. {
  352. m_scriptCanvasAssetModel = new ScriptCanvasAssetBrowserModel(this);
  353. AzToolsFramework::AssetBrowser::AssetGroupFilter* scriptCanvasAssetFilter = new AzToolsFramework::AssetBrowser::AssetGroupFilter();
  354. scriptCanvasAssetFilter->SetAssetGroup(ScriptCanvas::SubgraphInterfaceAssetDescription().GetGroupImpl());
  355. scriptCanvasAssetFilter->SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down);
  356. m_scriptCanvasAssetModel->setSourceModel(assetBrowserModel);
  357. }
  358. m_nodePaletteModel.AssignAssetModel(m_scriptCanvasAssetModel);
  359. ui->setupUi(this);
  360. CreateMenus();
  361. UpdateRecentMenu();
  362. m_host = new QWidget();
  363. m_layout = new QVBoxLayout();
  364. m_emptyCanvas = aznew GraphCanvas::GraphCanvasEditorEmptyDockWidget(this);
  365. m_emptyCanvas->SetDragTargetText(tr("Use the File Menu or drag out a node from the Node Palette to create a new script.").toStdString().c_str());
  366. m_emptyCanvas->SetEditorId(ScriptCanvasEditor::AssetEditorId);
  367. m_emptyCanvas->RegisterAcceptedMimeType(Widget::NodePaletteDockWidget::GetMimeType());
  368. m_emptyCanvas->RegisterAcceptedMimeType(AzToolsFramework::EditorEntityIdContainer::GetMimeType());
  369. m_editorToolbar = aznew GraphCanvas::AssetEditorToolbar(ScriptCanvasEditor::AssetEditorId);
  370. // Custom Actions
  371. {
  372. m_assignToSelectedEntity = new QToolButton();
  373. m_assignToSelectedEntity->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/attach_to_entity.png"));
  374. m_assignToSelectedEntity->setToolTip("Assigns the currently active graph to all of the currently selected entities.");
  375. m_selectedEntityMenu = new QMenu();
  376. m_assignToSelectedEntity->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup);
  377. m_assignToSelectedEntity->setMenu(m_selectedEntityMenu);
  378. m_assignToSelectedEntity->setEnabled(false);
  379. m_editorToolbar->AddCustomAction(m_assignToSelectedEntity);
  380. QObject::connect(m_selectedEntityMenu, &QMenu::aboutToShow, this, &MainWindow::OnSelectedEntitiesAboutToShow);
  381. QObject::connect(m_assignToSelectedEntity, &QToolButton::clicked, this, &MainWindow::OnAssignToSelectedEntities);
  382. }
  383. // Creation Actions
  384. {
  385. m_createScriptCanvas = new QToolButton();
  386. m_createScriptCanvas->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/create_graph.png"));
  387. m_createScriptCanvas->setToolTip("Creates a new Script Canvas Graph");
  388. QObject::connect(m_createScriptCanvas, &QToolButton::clicked, this, &MainWindow::OnFileNew);
  389. m_editorToolbar->AddCreationAction(m_createScriptCanvas);
  390. RegisterObject(AutomationIds::CreateScriptCanvasButton, m_createScriptCanvas);
  391. }
  392. {
  393. m_createFunctionInput = new QToolButton();
  394. m_createFunctionInput->setToolTip("Creates an Execution Nodeling on the leftmost side of the graph to be used as input for the graph.");
  395. m_createFunctionInput->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/create_function_input.png"));
  396. m_createFunctionInput->setEnabled(false);
  397. }
  398. m_editorToolbar->AddCustomAction(m_createFunctionInput);
  399. connect(m_createFunctionInput, &QToolButton::clicked, this, &MainWindow::CreateFunctionInput);
  400. {
  401. m_createFunctionOutput = new QToolButton();
  402. m_createFunctionOutput->setToolTip("Creates an Execution Nodeling on the rightmost side of the graph to be used as output for the graph.");
  403. m_createFunctionOutput->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/create_function_output.png"));
  404. m_createFunctionOutput->setEnabled(false);
  405. }
  406. m_editorToolbar->AddCustomAction(m_createFunctionOutput);
  407. connect(m_createFunctionOutput, &QToolButton::clicked, this, &MainWindow::CreateFunctionOutput);
  408. {
  409. m_validateGraphToolButton = new QToolButton();
  410. m_validateGraphToolButton->setToolTip("Will run a validation check on the current graph and report any warnings/errors discovered.");
  411. m_validateGraphToolButton->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/validate_icon.png"));
  412. m_validateGraphToolButton->setEnabled(false);
  413. }
  414. m_editorToolbar->AddCustomAction(m_validateGraphToolButton);
  415. // Screenshot
  416. {
  417. m_takeScreenshot = new QToolButton();
  418. m_takeScreenshot->setToolTip("Captures a full resolution screenshot of the entire graph or selected nodes into the clipboard");
  419. m_takeScreenshot->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/scriptcanvas_screenshot.png"));
  420. m_takeScreenshot->setEnabled(false);
  421. }
  422. m_editorToolbar->AddCustomAction(m_takeScreenshot);
  423. connect(m_takeScreenshot, &QToolButton::clicked, this, &MainWindow::OnScreenshot);
  424. connect(m_validateGraphToolButton, &QToolButton::clicked, this, &MainWindow::OnValidateCurrentGraph);
  425. m_layout->addWidget(m_editorToolbar);
  426. // Tab bar
  427. {
  428. m_tabWidget = new AzQtComponents::TabWidget(m_host);
  429. m_tabBar = new Widget::GraphTabBar(m_tabWidget);
  430. m_tabWidget->setCustomTabBar(m_tabBar);
  431. m_tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  432. connect(m_tabBar, &QTabBar::tabCloseRequested, this, &MainWindow::OnTabCloseButtonPressed);
  433. connect(m_tabBar, &Widget::GraphTabBar::TabCloseNoButton, this, &MainWindow::OnTabCloseRequest);
  434. connect(m_tabBar, &Widget::GraphTabBar::SaveTab, this, &MainWindow::SaveTab);
  435. connect(m_tabBar, &Widget::GraphTabBar::CloseAllTabsSignal, this, &MainWindow::CloseAllTabs);
  436. connect(m_tabBar, &Widget::GraphTabBar::CloseAllTabsButSignal, this, &MainWindow::CloseAllTabsBut);
  437. connect(m_tabBar, &Widget::GraphTabBar::CopyPathToClipboard, this, &MainWindow::CopyPathToClipboard);
  438. connect(m_tabBar, &Widget::GraphTabBar::OnActiveFileStateChanged, this, &MainWindow::OnActiveFileStateChanged);
  439. AzQtComponents::TabWidget::applySecondaryStyle(m_tabWidget, false);
  440. m_tabWidget->setObjectName("ScriptCanvasTabs");
  441. m_layout->addWidget(m_tabWidget);
  442. }
  443. m_commandLine = new Widget::CommandLine(this);
  444. m_commandLine->setBaseSize(QSize(size().width(), m_commandLine->size().height()));
  445. m_commandLine->setObjectName("CommandLine");
  446. m_layout->addWidget(m_commandLine);
  447. m_layout->addWidget(m_emptyCanvas);
  448. // Minimap should be a child of the dock widget. But until performance concerns are resolved
  449. // we want to hide it(mostly to avoid re-setting up all of the structural code around it).
  450. //
  451. // If this is a child, it appears on the default context menu to show/hide.
  452. m_minimap = aznew GraphCanvas::MiniMapDockWidget(ScriptCanvasEditor::AssetEditorId);
  453. m_minimap->setObjectName("MiniMapDockWidget");
  454. m_statusWidget = aznew MainWindowStatusWidget(this);
  455. statusBar()->addWidget(m_statusWidget,1);
  456. QObject::connect(m_statusWidget, &MainWindowStatusWidget::OnErrorButtonPressed, this, &MainWindow::OnShowValidationErrors);
  457. QObject::connect(m_statusWidget, &MainWindowStatusWidget::OnWarningButtonPressed, this, &MainWindow::OnShowValidationWarnings);
  458. m_nodePaletteModel.RepopulateModel();
  459. // Order these are created denotes the order for an auto-generate Qt menu. Keeping this construction order
  460. // in sync with the order we display under tools for consistency.
  461. {
  462. const bool isInContextMenu = false;
  463. Widget::ScriptCanvasNodePaletteConfig nodePaletteConfig(m_nodePaletteModel, m_scriptEventsAssetModel, isInContextMenu);
  464. m_nodePalette = aznew Widget::NodePaletteDockWidget(tr("Node Palette"), this, nodePaletteConfig);
  465. m_nodePalette->setObjectName("NodePalette");
  466. RegisterObject(AutomationIds::NodePaletteDockWidget, m_nodePalette);
  467. RegisterObject(AutomationIds::NodePaletteWidget, m_nodePalette->GetNodePaletteWidget());
  468. }
  469. m_propertyGrid = new Widget::PropertyGrid(this, "Node Inspector");
  470. m_propertyGrid->setObjectName("NodeInspector");
  471. m_bookmarkDockWidget = aznew GraphCanvas::BookmarkDockWidget(ScriptCanvasEditor::AssetEditorId, this);
  472. QObject::connect(m_variableDockWidget, &VariableDockWidget::OnVariableSelectionChanged, this, &MainWindow::OnVariableSelectionChanged);
  473. // This needs to happen after the node palette is created, because we scrape for the variable data from inside
  474. // of there.
  475. m_variableDockWidget->PopulateVariablePalette(m_variablePaletteTypes);
  476. m_validationDockWidget = aznew GraphValidationDockWidget(this);
  477. m_validationDockWidget->setObjectName("ValidationDockWidget");
  478. // End Construction list
  479. m_ebusHandlerActionMenu = aznew EBusHandlerActionMenu();
  480. m_statisticsDialog = aznew StatisticsDialog(m_nodePaletteModel, m_scriptCanvasAssetModel, nullptr);
  481. m_statisticsDialog->hide();
  482. m_presetEditor = aznew GraphCanvas::ConstructPresetDialog(nullptr);
  483. m_presetEditor->SetEditorId(ScriptCanvasEditor::AssetEditorId);
  484. m_presetWrapper = new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionAutoTitleBarButtons);
  485. m_presetWrapper->setGuest(m_presetEditor);
  486. m_presetWrapper->hide();
  487. m_host->setLayout(m_layout);
  488. setCentralWidget(m_host);
  489. m_workspace = new Workspace(this);
  490. QTimer::singleShot(0, [this]() {
  491. SetDefaultLayout();
  492. if (m_activeGraph.IsGraphValid())
  493. {
  494. m_queuedFocusOverride = m_activeGraph;
  495. }
  496. m_workspace->Restore();
  497. m_workspace->Save();
  498. });
  499. m_entityMimeDelegateId = CreateMimeDataDelegate<ScriptCanvasEditor::EntityMimeDataHandler>();
  500. ScriptCanvasEditor::GeneralRequestBus::Handler::BusConnect();
  501. ScriptCanvasEditor::AutomationRequestBus::Handler::BusConnect();
  502. UIRequestBus::Handler::BusConnect();
  503. UndoNotificationBus::Handler::BusConnect();
  504. GraphCanvas::AssetEditorRequestBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
  505. GraphCanvas::AssetEditorSettingsRequestBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
  506. ScriptCanvas::BatchOperationNotificationBus::Handler::BusConnect();
  507. AssetGraphSceneBus::Handler::BusConnect();
  508. AzToolsFramework::ToolsApplicationNotificationBus::Handler::BusConnect();
  509. AzToolsFramework::AssetSystemBus::Handler::BusConnect();
  510. ScriptCanvas::ScriptCanvasSettingsRequestBus::Handler::BusConnect();
  511. AZ::SystemTickBus::Handler::BusConnect();
  512. UINotificationBus::Broadcast(&UINotifications::MainWindowCreationEvent, this);
  513. m_userSettings = AZ::UserSettings::CreateFind<EditorSettings::ScriptCanvasEditorSettings>(AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL);
  514. if (m_userSettings)
  515. {
  516. m_allowAutoSave = m_userSettings->m_autoSaveConfig.m_enabled;
  517. m_showUpgradeTool = m_userSettings->m_showUpgradeDialog;
  518. m_autoSaveTimer.setInterval(m_userSettings->m_autoSaveConfig.m_timeSeconds * 1000);
  519. m_userSettings->m_constructPresets.SetEditorId(ScriptCanvasEditor::AssetEditorId);
  520. }
  521. // These should be created after we load up the user settings so we can
  522. // initialize the user presets
  523. m_sceneContextMenu = aznew SceneContextMenu(m_nodePaletteModel, m_scriptEventsAssetModel);
  524. m_connectionContextMenu = aznew ConnectionContextMenu(m_nodePaletteModel, m_scriptEventsAssetModel);
  525. connect(m_nodePalette, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  526. connect(m_minimap, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  527. connect(m_propertyGrid, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  528. connect(m_bookmarkDockWidget, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  529. connect(m_variableDockWidget, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  530. connect(m_loggingWindow, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  531. connect(m_validationDockWidget, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  532. m_autoSaveTimer.setSingleShot(true);
  533. connect(&m_autoSaveTimer, &QTimer::timeout, this, &MainWindow::OnAutoSave);
  534. UpdateMenuState(false);
  535. }
  536. MainWindow::~MainWindow()
  537. {
  538. m_workspace->Save();
  539. ScriptCanvas::BatchOperationNotificationBus::Handler::BusDisconnect();
  540. GraphCanvas::AssetEditorRequestBus::Handler::BusDisconnect();
  541. UndoNotificationBus::Handler::BusDisconnect();
  542. UIRequestBus::Handler::BusDisconnect();
  543. ScriptCanvasEditor::GeneralRequestBus::Handler::BusDisconnect();
  544. GraphCanvas::AssetEditorAutomationRequestBus::Handler::BusDisconnect();
  545. ScriptCanvas::ScriptCanvasSettingsRequestBus::Handler::BusDisconnect();
  546. AzToolsFramework::AssetSystemBus::Handler::BusDisconnect();
  547. Clear();
  548. delete m_nodePalette;
  549. delete m_unitTestDockWidget;
  550. delete m_statisticsDialog;
  551. delete m_presetEditor;
  552. delete m_workspace;
  553. delete m_sceneContextMenu;
  554. delete m_connectionContextMenu;
  555. }
  556. void MainWindow::CreateMenus()
  557. {
  558. // File menu
  559. connect(ui->action_New_Script, &QAction::triggered, this, &MainWindow::OnFileNew);
  560. ui->action_New_Script->setShortcut(QKeySequence(QKeySequence::New));
  561. connect(ui->action_Open, &QAction::triggered, this, &MainWindow::OnFileOpen);
  562. ui->action_Open->setShortcut(QKeySequence(QKeySequence::Open));
  563. connect(ui->action_UpgradeTool, &QAction::triggered, this, &MainWindow::RunUpgradeTool);
  564. ui->action_UpgradeTool->setVisible(true);
  565. connect(ui->action_Interpreter, &QAction::triggered, this, &MainWindow::ShowInterpreter);
  566. ui->action_Interpreter->setVisible(true);
  567. connect(ui->actionAdd_Script_Event_Helpers, &QAction::triggered, this, &MainWindow::OnScriptEventAddHelpers);
  568. connect(ui->actionClear_Script_Event_Status, &QAction::triggered, this, &MainWindow::OnScriptEventClearStatus);
  569. connect(ui->actionOpen_Script_Event, &QAction::triggered, this, &MainWindow::OnScriptEventOpen);
  570. connect(ui->actionParse_As_Script_Event, &QAction::triggered, this, &MainWindow::OnScriptEventParseAs);
  571. connect(ui->actionSave_As_ScriptEvent, &QAction::triggered, this, &MainWindow::OnScriptEventSaveAs);
  572. connect(ui->menuScript_Events_PREVIEW, &QMenu::aboutToShow, this, &MainWindow::OnScriptEventMenuPreShow);
  573. // List of recent files.
  574. {
  575. QMenu* recentMenu = new QMenu("Open &Recent");
  576. for (int i = 0; i < m_recentActions.size(); ++i)
  577. {
  578. QAction* action = new QAction(this);
  579. action->setVisible(false);
  580. m_recentActions[i] = AZStd::make_pair(action, QMetaObject::Connection());
  581. recentMenu->addAction(action);
  582. }
  583. connect(recentMenu, &QMenu::aboutToShow, this, &MainWindow::UpdateRecentMenu);
  584. recentMenu->addSeparator();
  585. // Clear Recent Files.
  586. {
  587. QAction* action = new QAction("&Clear Recent Files", this);
  588. QObject::connect(action,
  589. &QAction::triggered,
  590. [this](bool /*checked*/)
  591. {
  592. ClearRecentFile();
  593. UpdateRecentMenu();
  594. });
  595. recentMenu->addAction(action);
  596. }
  597. ui->menuFile->insertMenu(ui->action_Save, recentMenu);
  598. ui->menuFile->insertSeparator(ui->action_Save);
  599. }
  600. connect(ui->action_Save, &QAction::triggered, this, &MainWindow::OnFileSaveCaller);
  601. ui->action_Save->setShortcut(QKeySequence(QKeySequence::Save));
  602. connect(ui->action_Save_As, &QAction::triggered, this, &MainWindow::OnFileSaveAsCaller);
  603. ui->action_Save_As->setShortcut(QKeySequence(tr("Ctrl+Shift+S", "File|Save As...")));
  604. QObject::connect(ui->action_Close,
  605. &QAction::triggered,
  606. [this](bool /*checked*/)
  607. {
  608. m_tabBar->tabCloseRequested(m_tabBar->currentIndex());
  609. });
  610. ui->action_Close->setShortcut(QKeySequence(QKeySequence::Close));
  611. // Edit Menu
  612. SetupEditMenu();
  613. // View menu
  614. connect(ui->action_ViewNodePalette, &QAction::triggered, this, &MainWindow::OnViewNodePalette);
  615. connect(ui->action_ViewMiniMap, &QAction::triggered, this, &MainWindow::OnViewMiniMap);
  616. connect(ui->action_ViewProperties, &QAction::triggered, this, &MainWindow::OnViewProperties);
  617. connect(ui->action_ViewBookmarks, &QAction::triggered, this, &MainWindow::OnBookmarks);
  618. m_variableDockWidget = new VariableDockWidget(this);
  619. m_variableDockWidget->setObjectName("VariableManager");
  620. connect(ui->action_ViewVariableManager, &QAction::triggered, this, &MainWindow::OnVariableManager);
  621. connect(m_variableDockWidget, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  622. m_loggingWindow = aznew LoggingWindow(this);
  623. m_loggingWindow->setObjectName("LoggingWindow");
  624. connect(ui->action_ViewLogWindow, &QAction::triggered, this, &MainWindow::OnViewLogWindow);
  625. connect(m_loggingWindow, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  626. connect(ui->action_ViewDebugger, &QAction::triggered, this, &MainWindow::OnViewDebugger);
  627. connect(ui->action_ViewCommandLine, &QAction::triggered, this, &MainWindow::OnViewCommandLine);
  628. connect(ui->action_ViewLog, &QAction::triggered, this, &MainWindow::OnViewLog);
  629. connect(ui->action_GraphValidation, &QAction::triggered, this, &MainWindow::OnViewGraphValidation);
  630. connect(ui->action_Debugging, &QAction::triggered, this, &MainWindow::OnViewDebuggingWindow);
  631. connect(ui->action_ViewUnitTestManager, &QAction::triggered, this, &MainWindow::OnViewUnitTestManager);
  632. connect(ui->action_NodeStatistics, &QAction::triggered, this, &MainWindow::OnViewStatisticsPanel);
  633. connect(ui->action_PresetsEditor, &QAction::triggered, this, &MainWindow::OnViewPresetsEditor);
  634. connect(ui->action_ViewRestoreDefaultLayout, &QAction::triggered, this, &MainWindow::OnRestoreDefaultLayout);
  635. }
  636. void MainWindow::SignalActiveSceneChanged(SourceHandle assetId)
  637. {
  638. AZ::EntityId graphId;
  639. if (assetId.IsGraphValid())
  640. {
  641. EditorGraphRequestBus::EventResult(graphId, assetId.Get()->GetScriptCanvasId(), &EditorGraphRequests::GetGraphCanvasGraphId);
  642. }
  643. m_autoSaveTimer.stop();
  644. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorNotifications::PreOnActiveGraphChanged);
  645. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorNotifications::OnActiveGraphChanged, graphId);
  646. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorNotifications::PostOnActiveGraphChanged);
  647. // The paste action refreshes based on the scene's mimetype
  648. RefreshPasteAction();
  649. bool enabled = false;
  650. if (graphId.IsValid())
  651. {
  652. GraphCanvas::ViewId viewId;
  653. GraphCanvas::SceneRequestBus::EventResult(viewId, graphId, &GraphCanvas::SceneRequests::GetViewId);
  654. if (viewId.IsValid())
  655. {
  656. GraphCanvas::ViewNotificationBus::Handler::BusDisconnect();
  657. GraphCanvas::ViewNotificationBus::Handler::BusConnect(viewId);
  658. enabled = true;
  659. }
  660. else
  661. {
  662. AZ_Error("ScriptCanvasEditor", viewId.IsValid(), "SceneRequest must return a valid ViewId");
  663. }
  664. }
  665. UpdateMenuState(enabled);
  666. }
  667. void MainWindow::UpdateRecentMenu()
  668. {
  669. QStringList recentFiles = ReadRecentFiles();
  670. int recentCount = 0;
  671. for (auto filename : recentFiles)
  672. {
  673. if (!QFile::exists(filename))
  674. {
  675. continue;
  676. }
  677. auto& recent = m_recentActions[recentCount++];
  678. recent.first->setText(QString("&%1 %2").arg(QString::number(recentCount), filename));
  679. recent.first->setData(filename);
  680. recent.first->setVisible(true);
  681. QObject::disconnect(recent.second);
  682. recent.second = QObject::connect(recent.first,
  683. &QAction::triggered,
  684. [this, filename](bool /*checked*/)
  685. {
  686. OpenFile(filename.toUtf8().data());
  687. });
  688. }
  689. for (int i = recentCount; i < m_recentActions.size(); ++i)
  690. {
  691. auto& recent = m_recentActions[recentCount++];
  692. recent.first->setVisible(false);
  693. }
  694. }
  695. void MainWindow::OnViewVisibilityChanged(bool)
  696. {
  697. UpdateViewMenu();
  698. }
  699. void MainWindow::closeEvent(QCloseEvent* event)
  700. {
  701. // If we are in the middle of saving a graph. We don't want to close ourselves down and potentially retrigger the saving logic.
  702. if (m_queueCloseRequest)
  703. {
  704. m_hasQueuedClose = true;
  705. event->ignore();
  706. return;
  707. }
  708. for (int tabCounter = 0; tabCounter < m_tabBar->count(); ++tabCounter)
  709. {
  710. SourceHandle assetId = m_tabBar->FindAssetId(tabCounter);
  711. const Tracker::ScriptCanvasFileState& fileState = GetAssetFileState(assetId);
  712. if (fileState == Tracker::ScriptCanvasFileState::UNMODIFIED)
  713. {
  714. continue;
  715. }
  716. // Query the user.
  717. SetActiveAsset(assetId);
  718. QString tabName = m_tabBar->tabText(tabCounter);
  719. UnsavedChangesOptions shouldSaveResults = ShowSaveDialog(tabName);
  720. if (shouldSaveResults == UnsavedChangesOptions::SAVE)
  721. {
  722. SaveAssetImpl(assetId, Save::InPlace);
  723. event->ignore();
  724. return;
  725. }
  726. else if (shouldSaveResults == UnsavedChangesOptions::CANCEL_WITHOUT_SAVING)
  727. {
  728. event->ignore();
  729. return;
  730. }
  731. else if (shouldSaveResults == UnsavedChangesOptions::CONTINUE_WITHOUT_SAVING &&
  732. (fileState == Tracker::ScriptCanvasFileState::NEW || fileState == Tracker::ScriptCanvasFileState::SOURCE_REMOVED))
  733. {
  734. CloseScriptCanvasAsset(assetId);
  735. --tabCounter;
  736. }
  737. }
  738. m_workspace->Save();
  739. event->accept();
  740. }
  741. UnsavedChangesOptions MainWindow::ShowSaveDialog(const QString& filename)
  742. {
  743. bool wasActive = m_autoSaveTimer.isActive();
  744. if (wasActive)
  745. {
  746. m_autoSaveTimer.stop();
  747. }
  748. UnsavedChangesOptions shouldSaveResults = UnsavedChangesOptions::INVALID;
  749. UnsavedChangesDialog dialog(filename, this);
  750. dialog.exec();
  751. shouldSaveResults = dialog.GetResult();
  752. // If the auto save timer was active, and we cancelled our save dialog, we want
  753. // to resume the auto save timer.
  754. if (shouldSaveResults == UnsavedChangesOptions::CANCEL_WITHOUT_SAVING
  755. || shouldSaveResults == UnsavedChangesOptions::INVALID)
  756. {
  757. RestartAutoTimerSave(wasActive);
  758. }
  759. return shouldSaveResults;
  760. }
  761. void MainWindow::TriggerUndo()
  762. {
  763. GeneralEditorNotificationBus::Event(GetActiveScriptCanvasId(), &GeneralEditorNotifications::OnUndoRedoBegin);
  764. DequeuePropertyGridUpdate();
  765. UndoRequestBus::Event(GetActiveScriptCanvasId(), &UndoRequests::Undo);
  766. SignalSceneDirty(m_activeGraph);
  767. m_propertyGrid->ClearSelection();
  768. GeneralEditorNotificationBus::Event(GetActiveScriptCanvasId(), &GeneralEditorNotifications::OnUndoRedoEnd);
  769. }
  770. void MainWindow::TriggerRedo()
  771. {
  772. GeneralEditorNotificationBus::Event(GetActiveScriptCanvasId(), &GeneralEditorNotifications::OnUndoRedoBegin);
  773. DequeuePropertyGridUpdate();
  774. UndoRequestBus::Event(GetActiveScriptCanvasId(), &UndoRequests::Redo);
  775. SignalSceneDirty(m_activeGraph);
  776. m_propertyGrid->ClearSelection();
  777. GeneralEditorNotificationBus::Event(GetActiveScriptCanvasId(), &GeneralEditorNotifications::OnUndoRedoEnd);
  778. }
  779. void MainWindow::RegisterVariableType(const ScriptCanvas::Data::Type& variableType)
  780. {
  781. m_variablePaletteTypes.insert(ScriptCanvas::Data::ToAZType(variableType));
  782. }
  783. bool MainWindow::IsValidVariableType(const ScriptCanvas::Data::Type& dataType) const
  784. {
  785. return m_variableDockWidget->IsValidVariableType(dataType);
  786. }
  787. VariablePaletteRequests::VariableConfigurationOutput MainWindow::ShowVariableConfigurationWidget
  788. ( const VariablePaletteRequests::VariableConfigurationInput& input, const QPoint& scenePosition)
  789. {
  790. VariablePaletteRequests::VariableConfigurationOutput output;
  791. m_slotTypeSelector = new VariableConfigurationWidget(GetActiveScriptCanvasId(), input, this); // Recreate the widget every time because of https://bugreports.qt.io/browse/QTBUG-76509
  792. m_slotTypeSelector->PopulateVariablePalette(m_variablePaletteTypes);
  793. // Only set the slot name if the user has already configured this slot, so if they are creating
  794. // for the first time they will see the placeholder text instead
  795. bool isValidVariableType = false;
  796. VariablePaletteRequestBus::BroadcastResult(isValidVariableType, &VariablePaletteRequests::IsValidVariableType, input.m_currentType);
  797. if (isValidVariableType)
  798. {
  799. m_slotTypeSelector->SetSlotName(input.m_currentName);
  800. }
  801. m_slotTypeSelector->move(scenePosition);
  802. m_slotTypeSelector->setEnabled(true);
  803. m_slotTypeSelector->update();
  804. if (m_slotTypeSelector->exec() != QDialog::Rejected)
  805. {
  806. output.m_name = m_slotTypeSelector->GetSlotName();
  807. output.m_type = Data::FromAZType(m_slotTypeSelector->GetSelectedType());
  808. output.m_actionIsValid = true;
  809. output.m_nameChanged = input.m_currentName != output.m_name;
  810. output.m_typeChanged = input.m_currentType != output.m_type;
  811. }
  812. delete m_slotTypeSelector;
  813. return output;
  814. }
  815. void MainWindow::OpenValidationPanel()
  816. {
  817. if (!m_validationDockWidget->isVisible())
  818. {
  819. OnViewGraphValidation();
  820. }
  821. }
  822. void MainWindow::PostUndoPoint(ScriptCanvas::ScriptCanvasId scriptCanvasId)
  823. {
  824. bool isIdle = true;
  825. UndoRequestBus::EventResult(isIdle, scriptCanvasId, &UndoRequests::IsIdle);
  826. if (m_preventUndoStateUpdateCount == 0 && isIdle)
  827. {
  828. ScopedUndoBatch scopedUndoBatch("Modify Graph Canvas Scene");
  829. UndoRequestBus::Event(scriptCanvasId, &UndoRequests::AddGraphItemChangeUndo, "Graph Change");
  830. UpdateFileState(m_activeGraph, Tracker::ScriptCanvasFileState::MODIFIED);
  831. }
  832. const bool forceTimer = true;
  833. RestartAutoTimerSave(forceTimer);
  834. }
  835. void MainWindow::SourceFileChanged
  836. ( [[maybe_unused]] AZStd::string relativePath
  837. , AZStd::string scanFolder
  838. , [[maybe_unused]] AZ::Uuid fileAssetId)
  839. {
  840. auto handle = CompleteDescription(SourceHandle(nullptr, fileAssetId));
  841. if (handle)
  842. {
  843. if (!IsRecentSave(*handle))
  844. {
  845. UpdateFileState(*handle, Tracker::ScriptCanvasFileState::MODIFIED);
  846. }
  847. else
  848. {
  849. AZ_TracePrintf
  850. ( "ScriptCanvas"
  851. , "Ignoring source file modification notification (possibly external), as a it was recently saved by the editor: %s"
  852. , relativePath.c_str());
  853. }
  854. }
  855. }
  856. void MainWindow::SourceFileRemoved
  857. ( AZStd::string relativePath
  858. , [[maybe_unused]] AZStd::string scanFolder
  859. , AZ::Uuid fileAssetId)
  860. {
  861. SourceHandle handle = SourceHandle::FromRelativePath(nullptr, fileAssetId, relativePath);
  862. {
  863. if (!IsRecentSave(handle))
  864. {
  865. UpdateFileState(handle, Tracker::ScriptCanvasFileState::SOURCE_REMOVED);
  866. }
  867. else
  868. {
  869. AZ_TracePrintf
  870. ( "ScriptCanvas"
  871. , "Ignoring source file removed notification (possibly external), as a it was recently saved by the editor: %s"
  872. , relativePath.c_str());
  873. }
  874. }
  875. }
  876. void MainWindow::SignalSceneDirty(SourceHandle assetId)
  877. {
  878. UpdateFileState(assetId, Tracker::ScriptCanvasFileState::MODIFIED);
  879. }
  880. void MainWindow::PushPreventUndoStateUpdate()
  881. {
  882. ++m_preventUndoStateUpdateCount;
  883. }
  884. void MainWindow::PopPreventUndoStateUpdate()
  885. {
  886. if (m_preventUndoStateUpdateCount > 0)
  887. {
  888. --m_preventUndoStateUpdateCount;
  889. }
  890. }
  891. void MainWindow::ClearPreventUndoStateUpdate()
  892. {
  893. m_preventUndoStateUpdateCount = 0;
  894. }
  895. void MainWindow::UpdateFileState(const SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState)
  896. {
  897. m_tabBar->UpdateFileState(assetId, fileState);
  898. }
  899. AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAssetId(const SourceHandle& fileAssetId, Tracker::ScriptCanvasFileState fileState)
  900. {
  901. if (fileAssetId.Id().IsNull())
  902. {
  903. return AZ::Failure(AZStd::string("Unable to open asset with invalid asset id"));
  904. }
  905. int outTabIndex = m_tabBar->FindTab(fileAssetId);
  906. if (outTabIndex >= 0)
  907. {
  908. m_tabBar->SelectTab(fileAssetId);
  909. return AZ::Success(outTabIndex);
  910. }
  911. auto result = LoadFromFile(fileAssetId.AbsolutePath().c_str());
  912. if (!result)
  913. {
  914. return AZ::Failure(AZStd::string::format("Failed to load graph at %s", fileAssetId.AbsolutePath().c_str()));
  915. }
  916. AZ_Warning("ScriptCanvas", result.m_deserializeResult.m_jsonResults.empty()
  917. , "ScriptCanvas graph loaded with skippable errors: %s", result.m_deserializeResult.m_jsonResults.c_str());
  918. auto loadedGraph = result.m_handle;
  919. CompleteDescriptionInPlace(loadedGraph);
  920. outTabIndex = CreateAssetTab(loadedGraph, fileState);
  921. if (outTabIndex >= 0)
  922. {
  923. AddRecentFile(loadedGraph.AbsolutePath().c_str());
  924. OpenScriptCanvasAssetImplementation(loadedGraph, fileState);
  925. return AZ::Success(outTabIndex);
  926. }
  927. else
  928. {
  929. return AZ::Failure(AZStd::string("Specified asset is in an error state and cannot be properly displayed."));
  930. }
  931. }
  932. AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAssetImplementation(const SourceHandle& scriptCanvasAsset, Tracker::ScriptCanvasFileState fileState, int tabIndex)
  933. {
  934. const SourceHandle& fileAssetId = scriptCanvasAsset;
  935. // if (!fileAssetId.IsDescriptionValid())
  936. // {
  937. // return AZ::Failure(AZStd::string("Unable to open asset with invalid asset id"));
  938. // }
  939. //
  940. // if (!scriptCanvasAsset.IsDescriptionValid())
  941. // {
  942. // if (!m_isRestoringWorkspace)
  943. // {
  944. // AZStd::string errorPath = scriptCanvasAsset.Path().c_str();
  945. //
  946. // if (errorPath.empty())
  947. // {
  948. // errorPath = m_errorFilePath;
  949. // }
  950. //
  951. // if (m_queuedFocusOverride.AnyEquals(fileAssetId))
  952. // {
  953. // m_queuedFocusOverride = fileAssetId;
  954. // }
  955. //
  956. // QMessageBox::warning(this, "Unable to open source file", QString("Source File(%1) is in error and cannot be opened").arg(errorPath.c_str()), QMessageBox::StandardButton::Ok);
  957. // }
  958. //
  959. // return AZ::Failure(AZStd::string("Source File is in error"));
  960. // }
  961. int outTabIndex = m_tabBar->FindTab(fileAssetId);
  962. if (outTabIndex >= 0)
  963. {
  964. m_tabBar->setCurrentIndex(outTabIndex);
  965. SetActiveAsset(scriptCanvasAsset);
  966. return AZ::Success(outTabIndex);
  967. }
  968. outTabIndex = CreateAssetTab(fileAssetId, fileState, tabIndex);
  969. SetActiveAsset(scriptCanvasAsset);
  970. if (outTabIndex == -1)
  971. {
  972. return AZ::Failure(AZStd::string::format("Unable to open existing Script Canvas Asset with id %s in the Script Canvas Editor"
  973. , fileAssetId.ToString().c_str()));
  974. }
  975. m_tabBar->setCurrentIndex(outTabIndex);
  976. AZStd::string assetPath = scriptCanvasAsset.AbsolutePath().c_str();
  977. if (!assetPath.empty() && !m_loadingNewlySavedFile)
  978. {
  979. AddRecentFile(assetPath.c_str());
  980. }
  981. GraphCanvas::GraphId graphCanvasGraphId = GetGraphCanvasGraphId(scriptCanvasAsset.Get()->GetScriptCanvasId());
  982. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorNotifications::OnGraphLoaded, graphCanvasGraphId);
  983. GeneralAssetNotificationBus::Event(fileAssetId, &GeneralAssetNotifications::OnAssetVisualized);
  984. return AZ::Success(outTabIndex);
  985. }
  986. AZ::Outcome<int, AZStd::string> MainWindow::OpenScriptCanvasAsset(SourceHandle scriptCanvasAssetId, Tracker::ScriptCanvasFileState fileState, int tabIndex)
  987. {
  988. if (scriptCanvasAssetId.IsGraphValid())
  989. {
  990. return OpenScriptCanvasAssetImplementation(scriptCanvasAssetId, fileState, tabIndex);
  991. }
  992. else
  993. {
  994. return OpenScriptCanvasAssetId(scriptCanvasAssetId, fileState);
  995. }
  996. }
  997. int MainWindow::CreateAssetTab(const SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState, int tabIndex)
  998. {
  999. return m_tabBar->InsertGraphTab(tabIndex, assetId, fileState);
  1000. }
  1001. void MainWindow::RemoveScriptCanvasAsset(const SourceHandle& assetId)
  1002. {
  1003. AZ_TracePrintf("ScriptCanvas", "RemoveScriptCanvasAsset : %s\n", assetId.ToString().c_str());
  1004. m_assetCreationRequests.erase(assetId);
  1005. GeneralAssetNotificationBus::Event(assetId, &GeneralAssetNotifications::OnAssetUnloaded);
  1006. if (assetId.IsGraphValid())
  1007. {
  1008. // Disconnect scene and asset editor buses
  1009. GraphCanvas::SceneNotificationBus::MultiHandler::BusDisconnect(assetId.Get()->GetScriptCanvasId());
  1010. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId
  1011. , &GraphCanvas::AssetEditorNotifications::OnGraphUnloaded, assetId.Get()->GetGraphCanvasGraphId());
  1012. }
  1013. int tabIndex = m_tabBar->FindTab(assetId);
  1014. QVariant tabdata = m_tabBar->tabData(tabIndex);
  1015. if (tabdata.isValid())
  1016. {
  1017. auto tabAssetId = tabdata.value<Widget::GraphTabMetadata>();
  1018. SetActiveAsset(tabAssetId.m_assetId);
  1019. }
  1020. }
  1021. int MainWindow::CloseScriptCanvasAsset(const SourceHandle& assetId)
  1022. {
  1023. int tabIndex = -1;
  1024. if (IsTabOpen(assetId, tabIndex))
  1025. {
  1026. OnTabCloseRequest(tabIndex);
  1027. }
  1028. return tabIndex;
  1029. }
  1030. bool MainWindow::CreateScriptCanvasAssetFor(const TypeDefs::EntityComponentId& requestingEntityId)
  1031. {
  1032. for (auto createdAssetPair : m_assetCreationRequests)
  1033. {
  1034. if (createdAssetPair.second == requestingEntityId)
  1035. {
  1036. return OpenScriptCanvasAssetId(createdAssetPair.first, Tracker::ScriptCanvasFileState::NEW).IsSuccess();
  1037. }
  1038. }
  1039. SourceHandle previousAssetId = m_activeGraph;
  1040. OnFileNew();
  1041. bool createdNewAsset = !(m_activeGraph.AnyEquals(previousAssetId));
  1042. if (createdNewAsset)
  1043. {
  1044. m_assetCreationRequests[m_activeGraph] = requestingEntityId;
  1045. }
  1046. if (m_isRestoringWorkspace)
  1047. {
  1048. m_queuedFocusOverride = m_activeGraph;
  1049. }
  1050. return createdNewAsset;
  1051. }
  1052. bool MainWindow::IsScriptCanvasAssetOpen(const SourceHandle& assetId) const
  1053. {
  1054. return m_tabBar->FindTab(assetId) >= 0;
  1055. }
  1056. const CategoryInformation* MainWindow::FindNodePaletteCategoryInformation(AZStd::string_view categoryPath) const
  1057. {
  1058. return m_nodePaletteModel.FindBestCategoryInformation(categoryPath);
  1059. }
  1060. const NodePaletteModelInformation* MainWindow::FindNodePaletteModelInformation(const ScriptCanvas::NodeTypeIdentifier& nodeType) const
  1061. {
  1062. return m_nodePaletteModel.FindNodePaletteInformation(nodeType);
  1063. }
  1064. void MainWindow::OpenFile(const char* fullPath)
  1065. {
  1066. auto tabIndex = m_tabBar->FindTabByPath(fullPath);
  1067. if (tabIndex.IsGraphValid())
  1068. {
  1069. SetActiveAsset(tabIndex);
  1070. return;
  1071. }
  1072. AZStd::string watchFolder;
  1073. AZ::Data::AssetInfo assetInfo;
  1074. bool sourceInfoFound{};
  1075. AzToolsFramework::AssetSystemRequestBus::BroadcastResult
  1076. ( sourceInfoFound
  1077. , &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, fullPath, assetInfo, watchFolder);
  1078. if (!sourceInfoFound)
  1079. {
  1080. QMessageBox::warning(this, "Invalid Source Asset", QString("'%1' is not a valid asset path.").arg(fullPath), QMessageBox::Ok);
  1081. m_errorFilePath = fullPath;
  1082. AZ_Warning("ScriptCanvas", false, "Unable to open file as a ScriptCanvas graph: %s", fullPath);
  1083. return;
  1084. }
  1085. auto result = LoadFromFile(fullPath);
  1086. if (!result)
  1087. {
  1088. QMessageBox::warning(this, "Invalid Source File"
  1089. , QString("'%1' failed to load properly.\nFailure: %2").arg(fullPath).arg(result.m_fileReadErrors.c_str()), QMessageBox::Ok);
  1090. m_errorFilePath = fullPath;
  1091. AZ_Warning("ScriptCanvas", false, "Unable to open file as a ScriptCanvas graph: %s. Failure: %s"
  1092. , fullPath, result.m_fileReadErrors.c_str());
  1093. return;
  1094. }
  1095. else
  1096. {
  1097. AZ_Warning("ScriptCanvas", result.m_deserializeResult.m_jsonResults.empty()
  1098. , "File loaded succesfully with deserialiation errors: %s", result.m_deserializeResult.m_jsonResults.c_str());
  1099. }
  1100. m_errorFilePath.clear();
  1101. auto activeGraph = SourceHandle::FromRelativePath(result.m_handle, assetInfo.m_assetId.m_guid, assetInfo.m_relativePath);
  1102. activeGraph = SourceHandle::MarkAbsolutePath(activeGraph, fullPath);
  1103. auto openOutcome = OpenScriptCanvasAsset(activeGraph, Tracker::ScriptCanvasFileState::UNMODIFIED);
  1104. if (openOutcome)
  1105. {
  1106. RunGraphValidation(false);
  1107. SetActiveAsset(activeGraph);
  1108. SetRecentAssetId(activeGraph);
  1109. }
  1110. else
  1111. {
  1112. AZ_Warning("Script Canvas", openOutcome, "%s", openOutcome.GetError().data());
  1113. }
  1114. }
  1115. GraphCanvas::Endpoint MainWindow::HandleProposedConnection(const GraphCanvas::GraphId&, const GraphCanvas::ConnectionId&
  1116. , const GraphCanvas::Endpoint& endpoint, const GraphCanvas::NodeId& nodeId, const QPoint& screenPoint)
  1117. {
  1118. GraphCanvas::Endpoint retVal;
  1119. GraphCanvas::ConnectionType connectionType = GraphCanvas::ConnectionType::CT_Invalid;
  1120. GraphCanvas::SlotRequestBus::EventResult(connectionType, endpoint.GetSlotId(), &GraphCanvas::SlotRequests::GetConnectionType);
  1121. GraphCanvas::NodeId currentTarget = nodeId;
  1122. while (!retVal.IsValid() && currentTarget.IsValid())
  1123. {
  1124. AZStd::vector<AZ::EntityId> targetSlotIds;
  1125. GraphCanvas::NodeRequestBus::EventResult(targetSlotIds, currentTarget, &GraphCanvas::NodeRequests::GetSlotIds);
  1126. AZStd::list< GraphCanvas::Endpoint > endpoints;
  1127. for (const auto& targetSlotId : targetSlotIds)
  1128. {
  1129. GraphCanvas::Endpoint proposedEndpoint(currentTarget, targetSlotId);
  1130. bool canCreate = false;
  1131. GraphCanvas::SlotRequestBus::EventResult(canCreate, endpoint.GetSlotId(), &GraphCanvas::SlotRequests::CanCreateConnectionTo, proposedEndpoint);
  1132. if (canCreate)
  1133. {
  1134. GraphCanvas::SlotGroup slotGroup = GraphCanvas::SlotGroups::Invalid;
  1135. GraphCanvas::SlotRequestBus::EventResult(slotGroup, targetSlotId, &GraphCanvas::SlotRequests::GetSlotGroup);
  1136. bool isVisible = slotGroup != GraphCanvas::SlotGroups::Invalid;
  1137. GraphCanvas::SlotLayoutRequestBus::EventResult(isVisible, currentTarget, &GraphCanvas::SlotLayoutRequests::IsSlotGroupVisible, slotGroup);
  1138. if (isVisible)
  1139. {
  1140. endpoints.push_back(proposedEndpoint);
  1141. }
  1142. }
  1143. }
  1144. if (!endpoints.empty())
  1145. {
  1146. if (endpoints.size() == 1)
  1147. {
  1148. retVal = endpoints.front();
  1149. }
  1150. else
  1151. {
  1152. QMenu menu;
  1153. for (GraphCanvas::Endpoint proposedEndpoint : endpoints)
  1154. {
  1155. QAction* action = aznew EndpointSelectionAction(proposedEndpoint);
  1156. menu.addAction(action);
  1157. }
  1158. QAction* result = menu.exec(screenPoint);
  1159. if (result != nullptr)
  1160. {
  1161. EndpointSelectionAction* selectedEnpointAction = static_cast<EndpointSelectionAction*>(result);
  1162. retVal = selectedEnpointAction->GetEndpoint();
  1163. }
  1164. else
  1165. {
  1166. retVal.Clear();
  1167. }
  1168. }
  1169. if (retVal.IsValid())
  1170. {
  1171. // Double safety check. This should be gauranteed by the previous checks. But just extra safety.
  1172. bool canCreateConnection = false;
  1173. GraphCanvas::SlotRequestBus::EventResult(canCreateConnection, endpoint.GetSlotId(), &GraphCanvas::SlotRequests::CanCreateConnectionTo, retVal);
  1174. if (!canCreateConnection)
  1175. {
  1176. retVal.Clear();
  1177. }
  1178. }
  1179. }
  1180. else
  1181. {
  1182. retVal.Clear();
  1183. }
  1184. if (!retVal.IsValid())
  1185. {
  1186. bool isWrapped = false;
  1187. GraphCanvas::NodeRequestBus::EventResult(isWrapped, currentTarget, &GraphCanvas::NodeRequests::IsWrapped);
  1188. if (isWrapped)
  1189. {
  1190. GraphCanvas::NodeRequestBus::EventResult(currentTarget, currentTarget, &GraphCanvas::NodeRequests::GetWrappingNode);
  1191. }
  1192. else
  1193. {
  1194. currentTarget.SetInvalid();
  1195. }
  1196. }
  1197. }
  1198. return retVal;
  1199. }
  1200. void MainWindow::OnFileNew()
  1201. {
  1202. static int scriptCanvasEditorDefaultNewNameCount = 0;
  1203. AZStd::string assetPath;
  1204. AZStd::string newAssetName;
  1205. for (;;)
  1206. {
  1207. newAssetName = AZStd::string::format(SourceDescription::GetAssetNamePattern()
  1208. , ++scriptCanvasEditorDefaultNewNameCount);
  1209. AZStd::array<char, AZ::IO::MaxPathLength> assetRootArray;
  1210. if (!AZ::IO::FileIOBase::GetInstance()->ResolvePath(SourceDescription::GetSuggestedSavePath()
  1211. , assetRootArray.data(), assetRootArray.size()))
  1212. {
  1213. AZ_ErrorOnce("Script Canvas", false, "Unable to resolve @projectroot@ path");
  1214. }
  1215. AzFramework::StringFunc::Path::Join(assetRootArray.data(), (newAssetName + SourceDescription::GetFileExtension()).data(), assetPath);
  1216. AZ::Data::AssetInfo assetInfo;
  1217. if (!AssetHelpers::GetSourceInfo(assetPath, assetInfo))
  1218. {
  1219. break;
  1220. }
  1221. }
  1222. auto createOutcome = CreateScriptCanvasAsset(newAssetName);
  1223. if (!createOutcome.IsSuccess())
  1224. {
  1225. AZ_Warning("Script Canvas", createOutcome, "%s", createOutcome.GetError().data());
  1226. }
  1227. }
  1228. int MainWindow::InsertTabForAsset(AZStd::string_view assetPath, SourceHandle assetId, int tabIndex)
  1229. {
  1230. int outTabIndex = -1;
  1231. {
  1232. // Insert tab block
  1233. AZStd::string tabName;
  1234. AzFramework::StringFunc::Path::GetFileName(assetPath.data(), tabName);
  1235. m_tabBar->InsertGraphTab(tabIndex, assetId, Tracker::ScriptCanvasFileState::NEW);
  1236. if (!IsTabOpen(assetId, outTabIndex))
  1237. {
  1238. AZ_Assert(false, AZStd::string::format("Unable to open new Script Canvas Asset with id %s in the Script Canvas Editor", assetId.ToString().c_str()).c_str());
  1239. return -1;
  1240. }
  1241. m_tabBar->setTabToolTip(outTabIndex, assetPath.data());
  1242. }
  1243. return outTabIndex;
  1244. }
  1245. void MainWindow::UpdateUndoCache(SourceHandle)
  1246. {
  1247. UndoCache* undoCache = nullptr;
  1248. UndoRequestBus::EventResult(undoCache, GetActiveScriptCanvasId(), &UndoRequests::GetSceneUndoCache);
  1249. if (undoCache)
  1250. {
  1251. undoCache->UpdateCache(GetActiveScriptCanvasId());
  1252. }
  1253. }
  1254. AZ::Outcome<int, AZStd::string> MainWindow::CreateScriptCanvasAsset(AZStd::string_view assetPath, int tabIndex)
  1255. {
  1256. int outTabIndex = -1;
  1257. ScriptCanvas::DataPtr graph = EditorGraph::Create();
  1258. AZ::Uuid assetId = AZ::Uuid::CreateRandom();
  1259. auto relativeOption = ScriptCanvasEditor::CreateFromAnyPath(SourceHandle(graph, assetId), assetPath);
  1260. SourceHandle handle = relativeOption ? *relativeOption : SourceHandle(graph, assetId);
  1261. outTabIndex = InsertTabForAsset(assetPath, handle, tabIndex);
  1262. if (outTabIndex == -1)
  1263. {
  1264. return AZ::Failure(AZStd::string::format("Script Canvas Asset %.*s is not open in a tab"
  1265. , static_cast<int>(assetPath.size()), assetPath.data()));
  1266. }
  1267. SetActiveAsset(handle);
  1268. PushPreventUndoStateUpdate();
  1269. AZ::EntityId scriptCanvasEntityId = graph->GetGraph()->GetScriptCanvasId();
  1270. GraphCanvas::SceneNotificationBus::MultiHandler::BusDisconnect(scriptCanvasEntityId);
  1271. AZ::EntityId graphCanvasGraphId = GetGraphCanvasGraphId(scriptCanvasEntityId);
  1272. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId
  1273. , &GraphCanvas::AssetEditorNotifications::OnGraphRefreshed, graphCanvasGraphId, graphCanvasGraphId);
  1274. if (IsTabOpen(handle, tabIndex))
  1275. {
  1276. AZStd::string tabName;
  1277. AzFramework::StringFunc::Path::GetFileName(assetPath.data(), tabName);
  1278. m_tabBar->setTabToolTip(tabIndex, assetPath.data());
  1279. m_tabBar->SetTabText(tabIndex, tabName.c_str(), Tracker::ScriptCanvasFileState::NEW);
  1280. }
  1281. if (graphCanvasGraphId.IsValid())
  1282. {
  1283. GraphCanvas::SceneNotificationBus::MultiHandler::BusConnect(graphCanvasGraphId);
  1284. GraphCanvas::SceneMimeDelegateRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneMimeDelegateRequests::AddDelegate, m_entityMimeDelegateId);
  1285. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::SetMimeType, Widget::NodePaletteDockWidget::GetMimeType());
  1286. GraphCanvas::SceneMemberNotificationBus::Event(graphCanvasGraphId, &GraphCanvas::SceneMemberNotifications::OnSceneReady);
  1287. }
  1288. if (IsTabOpen(handle, outTabIndex))
  1289. {
  1290. RefreshActiveAsset();
  1291. }
  1292. PopPreventUndoStateUpdate();
  1293. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId
  1294. , &GraphCanvas::AssetEditorNotifications::OnGraphLoaded, graphCanvasGraphId);
  1295. return AZ::Success(outTabIndex);
  1296. }
  1297. bool MainWindow::OnFileSave()
  1298. {
  1299. auto metaData = m_tabBar->GetTabData(m_activeGraph);
  1300. if (!metaData)
  1301. {
  1302. return false;
  1303. }
  1304. if (metaData && metaData->m_fileState == Tracker::ScriptCanvasFileState::NEW)
  1305. {
  1306. return SaveAssetImpl(m_activeGraph, Save::As);
  1307. }
  1308. else
  1309. {
  1310. return SaveAssetImpl(m_activeGraph, Save::InPlace);
  1311. }
  1312. }
  1313. bool MainWindow::OnFileSaveAs()
  1314. {
  1315. return SaveAssetImpl(m_activeGraph, Save::As);
  1316. }
  1317. bool MainWindow::SaveAssetImpl(const SourceHandle& sourceHandleIn, Save save)
  1318. {
  1319. SourceHandle sourceHandle = sourceHandleIn;
  1320. if (!sourceHandle.IsGraphValid())
  1321. {
  1322. return false;
  1323. }
  1324. if (sourceHandle.Get()->IsScriptEventExtension())
  1325. {
  1326. QMessageBox mb
  1327. ( QMessageBox::Warning
  1328. , QObject::tr("Select ScriptCanvas or ScriptEvent source type:")
  1329. , QObject::tr("Graph defines a ScriptEvent. Press 'Discard' and use Script Event menu to save it as .scriptevent, or 'Ok' to continue to save as .scriptcanvas")
  1330. , QMessageBox::Ok | QMessageBox::Discard
  1331. , nullptr);
  1332. if (mb.exec() == QMessageBox::Discard)
  1333. {
  1334. return false;
  1335. }
  1336. }
  1337. if (sourceHandle.AbsolutePath().Extension() == ".scriptevents")
  1338. {
  1339. auto newPath = sourceHandle.AbsolutePath();
  1340. newPath.ReplaceExtension(".scriptcanvas");
  1341. if (auto relativeOption = ScriptCanvasEditor::CreateFromAnyPath(sourceHandle, newPath))
  1342. {
  1343. sourceHandle = *relativeOption;
  1344. }
  1345. sourceHandle = SourceHandle::MarkAbsolutePath(sourceHandle, newPath);
  1346. }
  1347. if (!m_activeGraph.AnyEquals(sourceHandle))
  1348. {
  1349. OnChangeActiveGraphTab(sourceHandle);
  1350. }
  1351. PrepareAssetForSave(sourceHandle);
  1352. AZStd::string suggestedFilename;
  1353. AZStd::string suggestedDirectoryPath;
  1354. AZStd::string suggestedFileFilter;
  1355. bool isValidFileName = false;
  1356. AZ::IO::FixedMaxPath projectSourcePath = AZ::Utils::GetProjectPath();
  1357. projectSourcePath /= "ScriptCanvas//";
  1358. QString selectedFile;
  1359. if (save == Save::InPlace)
  1360. {
  1361. isValidFileName = true;
  1362. suggestedFileFilter = SourceDescription::GetFileExtension();
  1363. auto sourceHandlePath = sourceHandleIn.AbsolutePath();
  1364. selectedFile = sourceHandleIn.AbsolutePath().Native().c_str();
  1365. suggestedFilename = sourceHandleIn.AbsolutePath().Filename().Native();
  1366. sourceHandlePath.RemoveFilename();
  1367. suggestedDirectoryPath = sourceHandlePath.Native();
  1368. }
  1369. else
  1370. {
  1371. suggestedFileFilter = SourceDescription::GetFileExtension();
  1372. if (sourceHandle.RelativePath().empty() || sourceHandle.RelativePath() == sourceHandle.RelativePath().Filename())
  1373. {
  1374. suggestedDirectoryPath = projectSourcePath.Native();
  1375. suggestedFilename += sourceHandle.RelativePath().Filename().Native();
  1376. }
  1377. else
  1378. {
  1379. auto sourceHandlePath = sourceHandle.AbsolutePath();
  1380. suggestedFilename = sourceHandle.AbsolutePath().Native();
  1381. sourceHandlePath.RemoveFilename();
  1382. suggestedDirectoryPath = sourceHandlePath.Native();
  1383. }
  1384. selectedFile = suggestedFilename.c_str();
  1385. }
  1386. QString filter = suggestedFileFilter.c_str();
  1387. while (!isValidFileName)
  1388. {
  1389. selectedFile = AzQtComponents::FileDialog::GetSaveFileName(this, QObject::tr("Save As..."), suggestedDirectoryPath.data(), QObject::tr("All ScriptCanvas Files (*.scriptcanvas)"));
  1390. // If the selected file is empty that means we just cancelled.
  1391. // So we want to break out.
  1392. if (!selectedFile.isEmpty())
  1393. {
  1394. AZStd::string filePath = selectedFile.toUtf8().data();
  1395. if (!AZ::StringFunc::EndsWith(filePath, SourceDescription::GetFileExtension(), false))
  1396. {
  1397. filePath += SourceDescription::GetFileExtension();
  1398. }
  1399. AZStd::string fileName;
  1400. if (AzFramework::StringFunc::Path::GetFileName(filePath.c_str(), fileName))
  1401. {
  1402. isValidFileName = !(fileName.empty());
  1403. }
  1404. else
  1405. {
  1406. QMessageBox::information(this, "Unable to Save", "File name cannot be empty");
  1407. }
  1408. }
  1409. else
  1410. {
  1411. break;
  1412. }
  1413. }
  1414. if (isValidFileName)
  1415. {
  1416. AZStd::string internalStringFile = selectedFile.toUtf8().data();
  1417. if (!AZ::StringFunc::EndsWith(internalStringFile, SourceDescription::GetFileExtension(), false))
  1418. {
  1419. internalStringFile += SourceDescription::GetFileExtension();
  1420. }
  1421. if (!AssetHelpers::IsValidSourceFile(internalStringFile, GetActiveScriptCanvasId()))
  1422. {
  1423. QMessageBox::warning(this, "Unable to Save", QString("File\n'%1'\n\nDoes not match the asset type of the current Graph.").arg(selectedFile));
  1424. return false;
  1425. }
  1426. SaveAs(internalStringFile, sourceHandle);
  1427. m_newlySavedFile = internalStringFile;
  1428. // Forcing the file add here, since we are creating a new file
  1429. AddRecentFile(m_newlySavedFile.c_str());
  1430. return true;
  1431. }
  1432. return false;
  1433. }
  1434. void MainWindow::OnSaveCallBack(const VersionExplorer::FileSaveResult& result)
  1435. {
  1436. const bool saveSuccess = result.IsSuccess();
  1437. int saveTabIndex = -1;
  1438. SourceHandle memoryAsset;
  1439. {
  1440. int saverIndex = m_tabBar->FindTab(m_fileSaver->GetSource());
  1441. if (saverIndex >= 0)
  1442. {
  1443. saveTabIndex = saverIndex;
  1444. memoryAsset = m_fileSaver->GetSource();
  1445. }
  1446. else
  1447. {
  1448. auto completeDescription = CompleteDescription(m_fileSaver->GetSource());
  1449. if (completeDescription)
  1450. {
  1451. memoryAsset = *completeDescription;
  1452. saveTabIndex = m_tabBar->FindTab(memoryAsset);
  1453. }
  1454. }
  1455. }
  1456. AZ_VerifyWarning("ScriptCanvas", saveTabIndex >= 0, "MainWindow::OnSaveCallback failed to find saved graph in tab. Data has been saved, but the ScriptCanvas Editor needs to be closed and re-opened.s")
  1457. AZStd::string tabName = saveTabIndex >= 0 ? m_tabBar->tabText(saveTabIndex).toUtf8().data() : "";
  1458. if (saveSuccess)
  1459. {
  1460. SourceHandle& fileAssetId = memoryAsset;
  1461. int currentTabIndex = m_tabBar->currentIndex();
  1462. AZ::Data::AssetInfo assetInfo;
  1463. AZ_VerifyWarning("ScriptCanvas", AssetHelpers::GetSourceInfo(fileAssetId.RelativePath().c_str(), assetInfo)
  1464. , "Failed to find asset info for source file just saved: %s", fileAssetId.RelativePath().c_str());
  1465. fileAssetId = SourceHandle::FromRelativePath(fileAssetId, assetInfo.m_assetId.m_guid, assetInfo.m_relativePath);
  1466. fileAssetId = SourceHandle::MarkAbsolutePath(fileAssetId, result.absolutePath);
  1467. // this path is questionable, this is a save request that is not the current graph
  1468. // We've saved as over a new graph, so we need to close the old one.
  1469. if (saveTabIndex != currentTabIndex)
  1470. {
  1471. // Invalidate the file asset id so we don't delete trigger the asset flow.
  1472. m_tabBar->setTabData(saveTabIndex, QVariant::fromValue(Widget::GraphTabMetadata()));
  1473. m_tabBar->CloseTab(saveTabIndex);
  1474. saveTabIndex = -1;
  1475. }
  1476. AzFramework::StringFunc::Path::GetFileName(memoryAsset.RelativePath().c_str(), tabName);
  1477. if (tabName.at(tabName.size() - 1) == '*' || tabName.at(tabName.size() - 1) == '^')
  1478. {
  1479. tabName = tabName.substr(0, tabName.size() - 2);
  1480. }
  1481. auto tabData = m_tabBar->GetTabData(saveTabIndex);
  1482. tabData->m_fileState = Tracker::ScriptCanvasFileState::UNMODIFIED;
  1483. tabData->m_assetId = fileAssetId;
  1484. m_tabBar->SetTabData(*tabData, saveTabIndex);
  1485. m_tabBar->SetTabText(saveTabIndex, tabName.c_str());
  1486. m_activeGraph = fileAssetId;
  1487. }
  1488. else
  1489. {
  1490. const auto failureMessage = AZStd::string::format("Failed to save %s: %s", tabName.c_str(), result.fileSaveError.c_str());
  1491. QMessageBox::critical(this, QString(), QObject::tr(failureMessage.data()));
  1492. }
  1493. if (m_tabBar->currentIndex() != saveTabIndex && saveTabIndex >= 0)
  1494. {
  1495. m_tabBar->setCurrentIndex(saveTabIndex);
  1496. }
  1497. UpdateAssignToSelectionState();
  1498. OnSaveToast toast(tabName, GetActiveGraphCanvasGraphId(), saveSuccess);
  1499. const bool displayAsNotification = true;
  1500. RunGraphValidation(displayAsNotification);
  1501. m_closeCurrentGraphAfterSave = false;
  1502. EnableAssetView(memoryAsset);
  1503. UpdateSaveState(true);
  1504. UnblockCloseRequests();
  1505. m_fileSaver.reset();
  1506. }
  1507. bool MainWindow::ActivateAndSaveAsset(const SourceHandle& unsavedAssetId)
  1508. {
  1509. SetActiveAsset(unsavedAssetId);
  1510. return OnFileSave();
  1511. }
  1512. void MainWindow::SaveAs(AZStd::string_view path, SourceHandle sourceHandle)
  1513. {
  1514. // clear the AZ::Uuid because it will change
  1515. if (auto relativeOption = ScriptCanvasEditor::CreateFromAnyPath(SourceHandle(sourceHandle, AZ::Uuid::CreateNull()), path))
  1516. {
  1517. sourceHandle = *relativeOption;
  1518. }
  1519. else
  1520. {
  1521. sourceHandle = SourceHandle::FromRelativePath(SourceHandle(sourceHandle, AZ::Uuid::CreateNull()), path);
  1522. }
  1523. DisableAssetView(sourceHandle);
  1524. UpdateSaveState(false);
  1525. m_fileSaver = AZStd::make_unique<VersionExplorer::FileSaver>
  1526. ( nullptr
  1527. , [this](const VersionExplorer::FileSaveResult& fileSaveResult) { OnSaveCallBack(fileSaveResult); });
  1528. MarkRecentSave(sourceHandle);
  1529. m_fileSaver->Save(sourceHandle, path);
  1530. BlockCloseRequests();
  1531. }
  1532. void MainWindow::OnFileOpen()
  1533. {
  1534. const auto sourcePath = AZ::IO::FixedMaxPath(AZ::Utils::GetProjectPath()) / "scriptcanvas";
  1535. const QStringList nameFilters = { "All ScriptCanvas Files (*.scriptcanvas)" };
  1536. QFileDialog dialog(nullptr, tr("Open..."), sourcePath.c_str());
  1537. dialog.setFileMode(QFileDialog::ExistingFiles);
  1538. dialog.setNameFilters(nameFilters);
  1539. if (dialog.exec() == QDialog::Accepted)
  1540. {
  1541. m_filesToOpen = dialog.selectedFiles();
  1542. OpenNextFile();
  1543. }
  1544. }
  1545. void MainWindow::SetupEditMenu()
  1546. {
  1547. ui->action_Undo->setShortcut(QKeySequence::Undo);
  1548. ui->action_Cut->setShortcut(QKeySequence(QKeySequence::Cut));
  1549. ui->action_Copy->setShortcut(QKeySequence(QKeySequence::Copy));
  1550. ui->action_Paste->setShortcut(QKeySequence(QKeySequence::Paste));
  1551. ui->action_Delete->setShortcut(QKeySequence(QKeySequence::Delete));
  1552. connect(ui->menuEdit, &QMenu::aboutToShow, this, &MainWindow::OnEditMenuShow);
  1553. // Edit Menu
  1554. connect(ui->action_Undo, &QAction::triggered, this, &MainWindow::TriggerUndo);
  1555. connect(ui->action_Redo, &QAction::triggered, this, &MainWindow::TriggerRedo);
  1556. connect(ui->action_Cut, &QAction::triggered, this, &MainWindow::OnEditCut);
  1557. connect(ui->action_Copy, &QAction::triggered, this, &MainWindow::OnEditCopy);
  1558. connect(ui->action_Paste, &QAction::triggered, this, &MainWindow::OnEditPaste);
  1559. connect(ui->action_Duplicate, &QAction::triggered, this, &MainWindow::OnEditDuplicate);
  1560. connect(ui->action_Delete, &QAction::triggered, this, &MainWindow::OnEditDelete);
  1561. connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &MainWindow::RefreshPasteAction);
  1562. connect(ui->action_RemoveUnusedNodes, &QAction::triggered, this, &MainWindow::OnRemoveUnusedNodes);
  1563. connect(ui->action_RemoveUnusedVariables, &QAction::triggered, this, &MainWindow::OnRemoveUnusedVariables);
  1564. connect(ui->action_RemoveUnusedElements, &QAction::triggered, this, &MainWindow::OnRemoveUnusedElements);
  1565. connect(ui->action_Screenshot, &QAction::triggered, this, &MainWindow::OnScreenshot);
  1566. connect(ui->action_SelectAll, &QAction::triggered, this, &MainWindow::OnSelectAll);
  1567. connect(ui->action_SelectInputs, &QAction::triggered, this, &MainWindow::OnSelectInputs);
  1568. connect(ui->action_SelectOutputs, &QAction::triggered, this, &MainWindow::OnSelectOutputs);
  1569. connect(ui->action_SelectConnected, &QAction::triggered, this, &MainWindow::OnSelectConnected);
  1570. connect(ui->action_ClearSelection, &QAction::triggered, this, &MainWindow::OnClearSelection);
  1571. connect(ui->action_EnableSelection, &QAction::triggered, this, &MainWindow::OnEnableSelection);
  1572. connect(ui->action_DisableSelection, &QAction::triggered, this, &MainWindow::OnDisableSelection);
  1573. connect(ui->action_AlignTop, &QAction::triggered, this, &MainWindow::OnAlignTop);
  1574. connect(ui->action_AlignBottom, &QAction::triggered, this, &MainWindow::OnAlignBottom);
  1575. connect(ui->action_AlignLeft, &QAction::triggered, this, &MainWindow::OnAlignLeft);
  1576. connect(ui->action_AlignRight, &QAction::triggered, this, &MainWindow::OnAlignRight);
  1577. ui->action_ZoomIn->setShortcuts({ QKeySequence(Qt::CTRL + Qt::Key_Plus),
  1578. QKeySequence(Qt::CTRL + Qt::Key_Equal)
  1579. });
  1580. // View Menu
  1581. connect(ui->action_ShowEntireGraph, &QAction::triggered, this, &MainWindow::OnShowEntireGraph);
  1582. connect(ui->action_ZoomIn, &QAction::triggered, this, &MainWindow::OnZoomIn);
  1583. connect(ui->action_ZoomOut, &QAction::triggered, this, &MainWindow::OnZoomOut);
  1584. connect(ui->action_ZoomSelection, &QAction::triggered, this, &MainWindow::OnZoomToSelection);
  1585. connect(ui->action_GotoStartOfChain, &QAction::triggered, this, &MainWindow::OnGotoStartOfChain);
  1586. connect(ui->action_GotoEndOfChain, &QAction::triggered, this, &MainWindow::OnGotoEndOfChain);
  1587. connect(ui->action_GlobalPreferences, &QAction::triggered, [this]()
  1588. {
  1589. ScriptCanvasEditor::SettingsDialog(ui->action_GlobalPreferences->text(), ScriptCanvas::ScriptCanvasId(), this).exec();
  1590. if (m_userSettings)
  1591. {
  1592. if (m_userSettings->m_autoSaveConfig.m_enabled)
  1593. {
  1594. m_allowAutoSave = true;
  1595. m_autoSaveTimer.setInterval(m_userSettings->m_autoSaveConfig.m_timeSeconds * 1000);
  1596. }
  1597. else
  1598. {
  1599. m_allowAutoSave = false;
  1600. }
  1601. }
  1602. });
  1603. connect(ui->action_GraphPreferences, &QAction::triggered, [this]() {
  1604. ScriptCanvas::ScriptCanvasId scriptCanvasId = GetActiveScriptCanvasId();
  1605. if (!scriptCanvasId.IsValid())
  1606. {
  1607. return;
  1608. }
  1609. m_autoSaveTimer.stop();
  1610. ScriptCanvasEditor::SettingsDialog(ui->action_GraphPreferences->text(), scriptCanvasId, this).exec();
  1611. });
  1612. }
  1613. void MainWindow::OnEditMenuShow()
  1614. {
  1615. RefreshGraphPreferencesAction();
  1616. ui->action_Screenshot->setEnabled(GetActiveGraphCanvasGraphId().IsValid());
  1617. ui->menuSelect->setEnabled(GetActiveGraphCanvasGraphId().IsValid());
  1618. ui->action_ClearSelection->setEnabled(GetActiveGraphCanvasGraphId().IsValid());
  1619. ui->menuAlign->setEnabled(GetActiveGraphCanvasGraphId().IsValid());
  1620. }
  1621. void MainWindow::RefreshPasteAction()
  1622. {
  1623. AZStd::string copyMimeType;
  1624. GraphCanvas::SceneRequestBus::EventResult(copyMimeType, GetActiveGraphCanvasGraphId(), &GraphCanvas::SceneRequests::GetCopyMimeType);
  1625. const bool pasteableClipboard = (!copyMimeType.empty() && QApplication::clipboard()->mimeData()->hasFormat(copyMimeType.c_str()))
  1626. || GraphVariablesTableView::HasCopyVariableData();
  1627. ui->action_Paste->setEnabled(pasteableClipboard);
  1628. }
  1629. void MainWindow::RefreshGraphPreferencesAction()
  1630. {
  1631. ui->action_GraphPreferences->setEnabled(GetActiveGraphCanvasGraphId().IsValid());
  1632. }
  1633. void MainWindow::OnEditCut()
  1634. {
  1635. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1636. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::CutSelection);
  1637. }
  1638. void MainWindow::OnEditCopy()
  1639. {
  1640. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1641. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::CopySelection);
  1642. }
  1643. void MainWindow::OnEditPaste()
  1644. {
  1645. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1646. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Paste);
  1647. }
  1648. void MainWindow::OnEditDuplicate()
  1649. {
  1650. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1651. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::DuplicateSelection);
  1652. }
  1653. void MainWindow::OnEditDelete()
  1654. {
  1655. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1656. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::DeleteSelection);
  1657. }
  1658. void MainWindow::OnRemoveUnusedVariables()
  1659. {
  1660. AZ::EntityId scriptCanvasGraphId = GetActiveScriptCanvasId();
  1661. EditorGraphRequestBus::Event(scriptCanvasGraphId, &EditorGraphRequests::RemoveUnusedVariables);
  1662. }
  1663. void MainWindow::OnRemoveUnusedNodes()
  1664. {
  1665. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1666. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::RemoveUnusedNodes);
  1667. }
  1668. void MainWindow::OnRemoveUnusedElements()
  1669. {
  1670. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1671. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::RemoveUnusedElements);
  1672. }
  1673. void MainWindow::OnScreenshot()
  1674. {
  1675. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1676. GraphCanvas::ViewId viewId;
  1677. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1678. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::ScreenshotSelection);
  1679. }
  1680. void MainWindow::OnSelectAll()
  1681. {
  1682. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1683. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::SelectAll);
  1684. }
  1685. void MainWindow::OnSelectInputs()
  1686. {
  1687. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1688. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::SelectAllRelative, GraphCanvas::ConnectionType::CT_Input);
  1689. }
  1690. void MainWindow::OnSelectOutputs()
  1691. {
  1692. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1693. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::SelectAllRelative, GraphCanvas::ConnectionType::CT_Output);
  1694. GraphCanvas::ViewId viewId;
  1695. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1696. }
  1697. void MainWindow::OnSelectConnected()
  1698. {
  1699. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1700. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::SelectConnectedNodes);
  1701. }
  1702. void MainWindow::OnClearSelection()
  1703. {
  1704. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1705. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::ClearSelection);
  1706. }
  1707. void MainWindow::OnEnableSelection()
  1708. {
  1709. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1710. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::EnableSelection);
  1711. }
  1712. void MainWindow::OnDisableSelection()
  1713. {
  1714. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1715. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::DisableSelection);
  1716. }
  1717. void MainWindow::OnAlignTop()
  1718. {
  1719. GraphCanvas::AlignConfig alignConfig;
  1720. alignConfig.m_horAlign = GraphCanvas::GraphUtils::HorizontalAlignment::None;
  1721. alignConfig.m_verAlign = GraphCanvas::GraphUtils::VerticalAlignment::Top;
  1722. alignConfig.m_alignTime = GetAlignmentTime();
  1723. AlignSelected(alignConfig);
  1724. }
  1725. void MainWindow::OnAlignBottom()
  1726. {
  1727. GraphCanvas::AlignConfig alignConfig;
  1728. alignConfig.m_horAlign = GraphCanvas::GraphUtils::HorizontalAlignment::None;
  1729. alignConfig.m_verAlign = GraphCanvas::GraphUtils::VerticalAlignment::Bottom;
  1730. alignConfig.m_alignTime = GetAlignmentTime();
  1731. AlignSelected(alignConfig);
  1732. }
  1733. void MainWindow::OnAlignLeft()
  1734. {
  1735. GraphCanvas::AlignConfig alignConfig;
  1736. alignConfig.m_horAlign = GraphCanvas::GraphUtils::HorizontalAlignment::Left;
  1737. alignConfig.m_verAlign = GraphCanvas::GraphUtils::VerticalAlignment::None;
  1738. alignConfig.m_alignTime = GetAlignmentTime();
  1739. AlignSelected(alignConfig);
  1740. }
  1741. void MainWindow::OnAlignRight()
  1742. {
  1743. GraphCanvas::AlignConfig alignConfig;
  1744. alignConfig.m_horAlign = GraphCanvas::GraphUtils::HorizontalAlignment::Right;
  1745. alignConfig.m_verAlign = GraphCanvas::GraphUtils::VerticalAlignment::None;
  1746. alignConfig.m_alignTime = GetAlignmentTime();
  1747. AlignSelected(alignConfig);
  1748. }
  1749. void MainWindow::AlignSelected(const GraphCanvas::AlignConfig& alignConfig)
  1750. {
  1751. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1752. AZStd::vector< GraphCanvas::NodeId > selectedNodes;
  1753. GraphCanvas::SceneRequestBus::EventResult(selectedNodes, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetSelectedNodes);
  1754. GraphCanvas::GraphUtils::AlignNodes(selectedNodes, alignConfig);
  1755. }
  1756. void MainWindow::OnShowEntireGraph()
  1757. {
  1758. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1759. GraphCanvas::ViewId viewId;
  1760. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1761. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::ShowEntireGraph);
  1762. }
  1763. void MainWindow::OnZoomIn()
  1764. {
  1765. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1766. GraphCanvas::ViewId viewId;
  1767. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1768. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::ZoomIn);
  1769. }
  1770. void MainWindow::OnZoomOut()
  1771. {
  1772. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1773. GraphCanvas::ViewId viewId;
  1774. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1775. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::ZoomOut);
  1776. }
  1777. void MainWindow::OnZoomToSelection()
  1778. {
  1779. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1780. GraphCanvas::ViewId viewId;
  1781. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1782. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::CenterOnSelection);
  1783. }
  1784. void MainWindow::OnGotoStartOfChain()
  1785. {
  1786. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1787. GraphCanvas::ViewId viewId;
  1788. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1789. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::CenterOnStartOfChain);
  1790. }
  1791. void MainWindow::OnGotoEndOfChain()
  1792. {
  1793. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1794. GraphCanvas::ViewId viewId;
  1795. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  1796. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::CenterOnEndOfChain);
  1797. }
  1798. void MainWindow::OnCanUndoChanged(bool canUndo)
  1799. {
  1800. ui->action_Undo->setEnabled(canUndo);
  1801. }
  1802. void MainWindow::OnCanRedoChanged(bool canRedo)
  1803. {
  1804. ui->action_Redo->setEnabled(canRedo);
  1805. }
  1806. bool MainWindow::CanShowNetworkSettings()
  1807. {
  1808. return m_userSettings->m_experimentalSettings.GetShowNetworkProperties();
  1809. }
  1810. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::HandleContextMenu(GraphCanvas::EditorContextMenu& editorContextMenu, const AZ::EntityId& memberId, const QPoint& screenPoint, const QPointF& scenePoint) const
  1811. {
  1812. AZ::Vector2 sceneVector(aznumeric_cast<float>(scenePoint.x()), aznumeric_cast<float>(scenePoint.y()));
  1813. GraphCanvas::GraphId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  1814. editorContextMenu.RefreshActions(graphCanvasGraphId, memberId);
  1815. QAction* result = editorContextMenu.exec(screenPoint);
  1816. GraphCanvas::ContextMenuAction* contextMenuAction = qobject_cast<GraphCanvas::ContextMenuAction*>(result);
  1817. if (contextMenuAction)
  1818. {
  1819. return contextMenuAction->TriggerAction(graphCanvasGraphId, sceneVector);
  1820. }
  1821. else
  1822. {
  1823. return GraphCanvas::ContextMenuAction::SceneReaction::Nothing;
  1824. }
  1825. }
  1826. void MainWindow::OnAutoSave()
  1827. {
  1828. if (m_allowAutoSave)
  1829. {
  1830. const Tracker::ScriptCanvasFileState& fileState = GetAssetFileState(m_activeGraph);
  1831. if (fileState != Tracker::ScriptCanvasFileState::INVALID && fileState != Tracker::ScriptCanvasFileState::NEW)
  1832. {
  1833. OnFileSaveCaller();
  1834. }
  1835. }
  1836. }
  1837. //! GeneralRequestBus
  1838. void MainWindow::OnChangeActiveGraphTab(SourceHandle assetId)
  1839. {
  1840. SetActiveAsset(assetId);
  1841. }
  1842. AZ::EntityId MainWindow::GetActiveGraphCanvasGraphId() const
  1843. {
  1844. AZ::EntityId graphId{};
  1845. if (m_activeGraph.IsGraphValid())
  1846. {
  1847. EditorGraphRequestBus::EventResult
  1848. ( graphId, m_activeGraph.Get()->GetScriptCanvasId(), &EditorGraphRequests::GetGraphCanvasGraphId);
  1849. }
  1850. return graphId;
  1851. }
  1852. ScriptCanvas::ScriptCanvasId MainWindow::GetActiveScriptCanvasId() const
  1853. {
  1854. return FindScriptCanvasIdByAssetId(m_activeGraph);
  1855. }
  1856. GraphCanvas::GraphId MainWindow::GetGraphCanvasGraphId(const ScriptCanvas::ScriptCanvasId& scriptCanvasId) const
  1857. {
  1858. AZ::EntityId graphId{};
  1859. EditorGraphRequestBus::EventResult(graphId, scriptCanvasId, &EditorGraphRequests::GetGraphCanvasGraphId);
  1860. return graphId;
  1861. }
  1862. GraphCanvas::GraphId MainWindow::FindGraphCanvasGraphIdByAssetId(const SourceHandle& assetId) const
  1863. {
  1864. AZ::EntityId graphId{};
  1865. if (assetId.IsGraphValid())
  1866. {
  1867. EditorGraphRequestBus::EventResult
  1868. ( graphId, assetId.Get()->GetScriptCanvasId(), &EditorGraphRequests::GetGraphCanvasGraphId);
  1869. }
  1870. return graphId;
  1871. }
  1872. ScriptCanvas::ScriptCanvasId MainWindow::FindScriptCanvasIdByAssetId(const SourceHandle& assetId) const
  1873. {
  1874. return assetId.IsGraphValid() ? assetId.Get()->GetScriptCanvasId() : ScriptCanvas::ScriptCanvasId{};
  1875. }
  1876. ScriptCanvas::ScriptCanvasId MainWindow::GetScriptCanvasId(const GraphCanvas::GraphId& graphCanvasGraphId) const
  1877. {
  1878. return m_tabBar->FindScriptCanvasIdFromGraphCanvasId(graphCanvasGraphId);
  1879. }
  1880. bool MainWindow::IsInUndoRedo(const AZ::EntityId& graphCanvasGraphId) const
  1881. {
  1882. bool isActive = false;
  1883. UndoRequestBus::EventResult(isActive, GetScriptCanvasId(graphCanvasGraphId), &UndoRequests::IsActive);
  1884. return isActive;
  1885. }
  1886. bool MainWindow::IsScriptCanvasInUndoRedo(const ScriptCanvas::ScriptCanvasId& scriptCanvasId) const
  1887. {
  1888. if (GetActiveScriptCanvasId() == scriptCanvasId)
  1889. {
  1890. bool isInUndoRedo = false;
  1891. UndoRequestBus::BroadcastResult(isInUndoRedo, &UndoRequests::IsActive);
  1892. return isInUndoRedo;
  1893. }
  1894. return false;
  1895. }
  1896. bool MainWindow::IsActiveGraphInUndoRedo() const
  1897. {
  1898. bool isActive = false;
  1899. UndoRequestBus::EventResult(isActive, GetActiveScriptCanvasId(), &UndoRequests::IsActive);
  1900. return isActive;
  1901. }
  1902. QVariant MainWindow::GetTabData(const SourceHandle& assetId)
  1903. {
  1904. for (int tabIndex = 0; tabIndex < m_tabBar->count(); ++tabIndex)
  1905. {
  1906. QVariant tabdata = m_tabBar->tabData(tabIndex);
  1907. if (tabdata.isValid())
  1908. {
  1909. auto tabAssetId = tabdata.value<Widget::GraphTabMetadata>();
  1910. if (tabAssetId.m_assetId.AnyEquals(assetId))
  1911. {
  1912. return tabdata;
  1913. }
  1914. }
  1915. }
  1916. return QVariant();
  1917. }
  1918. bool MainWindow::IsTabOpen(const SourceHandle& fileAssetId, int& outTabIndex) const
  1919. {
  1920. int tabIndex = m_tabBar->FindTab(fileAssetId);
  1921. if (-1 != tabIndex)
  1922. {
  1923. outTabIndex = tabIndex;
  1924. return true;
  1925. }
  1926. return false;
  1927. }
  1928. void MainWindow::ReconnectSceneBuses(SourceHandle previousAsset, SourceHandle nextAsset)
  1929. {
  1930. // Disconnect previous asset
  1931. AZ::EntityId previousScriptCanvasSceneId;
  1932. if (previousAsset.IsGraphValid())
  1933. {
  1934. previousScriptCanvasSceneId = previousAsset.Get()->GetScriptCanvasId();
  1935. GraphCanvas::SceneNotificationBus::MultiHandler::BusDisconnect(previousScriptCanvasSceneId);
  1936. }
  1937. AZ::EntityId nextAssetGraphCanvasId;
  1938. if (nextAsset.IsGraphValid())
  1939. {
  1940. // Connect the next asset
  1941. EditorGraphRequestBus::EventResult(nextAssetGraphCanvasId, nextAsset.Get()->GetScriptCanvasId(), &EditorGraphRequests::GetGraphCanvasGraphId);
  1942. if (nextAssetGraphCanvasId.IsValid())
  1943. {
  1944. GraphCanvas::SceneNotificationBus::MultiHandler::BusConnect(nextAssetGraphCanvasId);
  1945. GraphCanvas::SceneMimeDelegateRequestBus::Event(nextAssetGraphCanvasId, &GraphCanvas::SceneMimeDelegateRequests::AddDelegate, m_entityMimeDelegateId);
  1946. GraphCanvas::SceneRequestBus::Event(nextAssetGraphCanvasId, &GraphCanvas::SceneRequests::SetMimeType, Widget::NodePaletteDockWidget::GetMimeType());
  1947. GraphCanvas::SceneMemberNotificationBus::Event(nextAssetGraphCanvasId, &GraphCanvas::SceneMemberNotifications::OnSceneReady);
  1948. }
  1949. }
  1950. // Notify about the graph refresh
  1951. GraphCanvas::AssetEditorNotificationBus::Event(ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorNotifications::OnGraphRefreshed, previousScriptCanvasSceneId, nextAssetGraphCanvasId);
  1952. }
  1953. void MainWindow::SetActiveAsset(const SourceHandle& fileAssetId)
  1954. {
  1955. if (m_activeGraph.AnyEquals(fileAssetId))
  1956. {
  1957. return;
  1958. }
  1959. AZ_TracePrintf("ScriptCanvas", "SetActiveAsset : from: %s to %s\n", m_activeGraph.ToString().c_str(), fileAssetId.ToString().c_str());
  1960. if (fileAssetId.IsGraphValid())
  1961. {
  1962. if (m_tabBar->FindTab(fileAssetId) >= 0)
  1963. {
  1964. QSignalBlocker signalBlocker(m_tabBar);
  1965. m_tabBar->SelectTab(fileAssetId);
  1966. }
  1967. }
  1968. if (m_activeGraph.IsGraphValid())
  1969. {
  1970. // If we are saving the asset, the Id may have changed from the in-memory to the file asset Id, in that case,
  1971. // there's no need to hide the view or remove the widget
  1972. auto oldTab = m_tabBar->FindTab(m_activeGraph);
  1973. if (auto view = m_tabBar->ModTabView(oldTab))
  1974. {
  1975. view->hide();
  1976. m_layout->removeWidget(view);
  1977. m_tabBar->ClearTabView(oldTab);
  1978. }
  1979. }
  1980. if (fileAssetId.IsGraphValid())
  1981. {
  1982. SourceHandle previousAssetId = m_activeGraph;
  1983. m_activeGraph = fileAssetId;
  1984. RefreshActiveAsset();
  1985. ReconnectSceneBuses(previousAssetId, m_activeGraph);
  1986. }
  1987. else
  1988. {
  1989. SourceHandle previousAssetId = m_activeGraph;
  1990. m_activeGraph.Clear();
  1991. m_emptyCanvas->show();
  1992. ReconnectSceneBuses(previousAssetId, m_activeGraph);
  1993. SignalActiveSceneChanged(SourceHandle());
  1994. }
  1995. UpdateUndoCache(fileAssetId);
  1996. RefreshSelection();
  1997. }
  1998. void MainWindow::RefreshActiveAsset()
  1999. {
  2000. if (m_activeGraph.IsGraphValid())
  2001. {
  2002. AZ_TracePrintf("ScriptCanvas", "RefreshActiveAsset : m_activeGraph (%s)\n", m_activeGraph.ToString().c_str());
  2003. if (auto view = m_tabBar->ModOrCreateTabView(m_tabBar->FindTab(m_activeGraph)))
  2004. {
  2005. view->ShowScene(m_activeGraph.Get()->GetScriptCanvasId());
  2006. m_layout->addWidget(view);
  2007. view->show();
  2008. m_emptyCanvas->hide();
  2009. SignalActiveSceneChanged(m_activeGraph);
  2010. }
  2011. else
  2012. {
  2013. SetActiveAsset({});
  2014. }
  2015. }
  2016. }
  2017. void MainWindow::Clear()
  2018. {
  2019. m_tabBar->CloseAllTabs();
  2020. SetActiveAsset({});
  2021. }
  2022. void MainWindow::OnTabCloseButtonPressed(int index)
  2023. {
  2024. QVariant tabdata = m_tabBar->tabData(index);
  2025. if (tabdata.isValid())
  2026. {
  2027. Widget::GraphTabMetadata tabMetadata = tabdata.value<Widget::GraphTabMetadata>();
  2028. Tracker::ScriptCanvasFileState fileState = tabMetadata.m_fileState;
  2029. UnsavedChangesOptions saveDialogResults = UnsavedChangesOptions::CONTINUE_WITHOUT_SAVING;
  2030. if (fileState == Tracker::ScriptCanvasFileState::NEW
  2031. || fileState == Tracker::ScriptCanvasFileState::MODIFIED
  2032. || fileState == Tracker::ScriptCanvasFileState::SOURCE_REMOVED)
  2033. {
  2034. SetActiveAsset(tabMetadata.m_assetId);
  2035. saveDialogResults = ShowSaveDialog(m_tabBar->tabText(index).toUtf8().constData());
  2036. }
  2037. if (saveDialogResults == UnsavedChangesOptions::SAVE)
  2038. {
  2039. m_closeCurrentGraphAfterSave = true;
  2040. SaveAssetImpl(tabMetadata.m_assetId, fileState == Tracker::ScriptCanvasFileState::NEW ? Save::As : Save::InPlace);
  2041. }
  2042. else if (saveDialogResults == UnsavedChangesOptions::CONTINUE_WITHOUT_SAVING)
  2043. {
  2044. OnTabCloseRequest(index);
  2045. }
  2046. }
  2047. }
  2048. void MainWindow::SaveTab(int index)
  2049. {
  2050. QVariant tabdata = m_tabBar->tabData(index);
  2051. if (tabdata.isValid())
  2052. {
  2053. auto assetId = tabdata.value<Widget::GraphTabMetadata>();
  2054. SaveAssetImpl(assetId.m_assetId, Save::InPlace);
  2055. }
  2056. }
  2057. void MainWindow::CloseAllTabs()
  2058. {
  2059. m_isClosingTabs = true;
  2060. m_skipTabOnClose.Clear();
  2061. CloseNextTab();
  2062. }
  2063. void MainWindow::CloseAllTabsBut(int index)
  2064. {
  2065. QVariant tabdata = m_tabBar->tabData(index);
  2066. if (tabdata.isValid())
  2067. {
  2068. auto assetId = tabdata.value<Widget::GraphTabMetadata>().m_assetId;
  2069. m_isClosingTabs = true;
  2070. m_skipTabOnClose = assetId;
  2071. CloseNextTab();
  2072. }
  2073. }
  2074. void MainWindow::CopyPathToClipboard(int index)
  2075. {
  2076. QVariant tabdata = m_tabBar->tabData(index);
  2077. if (tabdata.isValid())
  2078. {
  2079. QClipboard* clipBoard = QGuiApplication::clipboard();
  2080. auto assetId = tabdata.value<Widget::GraphTabMetadata>();
  2081. if (!assetId.m_assetId.AbsolutePath().empty())
  2082. {
  2083. clipBoard->setText(assetId.m_assetId.AbsolutePath().c_str());
  2084. }
  2085. else
  2086. {
  2087. clipBoard->setText(m_tabBar->tabText(index));
  2088. }
  2089. }
  2090. }
  2091. void MainWindow::OnActiveFileStateChanged()
  2092. {
  2093. UpdateAssignToSelectionState();
  2094. }
  2095. void MainWindow::CloseNextTab()
  2096. {
  2097. if (m_isClosingTabs)
  2098. {
  2099. if (m_tabBar->count() == 0
  2100. || (m_tabBar->count() == 1 && m_skipTabOnClose.IsGraphValid()))
  2101. {
  2102. m_isClosingTabs = false;
  2103. m_skipTabOnClose.Clear();
  2104. return;
  2105. }
  2106. int tab = 0;
  2107. while (tab < m_tabBar->count())
  2108. {
  2109. QVariant tabdata = m_tabBar->tabData(tab);
  2110. if (tabdata.isValid())
  2111. {
  2112. auto assetId = tabdata.value<Widget::GraphTabMetadata>();
  2113. if (!assetId.m_assetId.AnyEquals(m_skipTabOnClose))
  2114. {
  2115. break;
  2116. }
  2117. }
  2118. tab++;
  2119. }
  2120. m_tabBar->tabCloseRequested(tab);
  2121. }
  2122. }
  2123. void MainWindow::OnTabCloseRequest(int index)
  2124. {
  2125. QVariant tabdata = m_tabBar->tabData(index);
  2126. if (tabdata.isValid())
  2127. {
  2128. auto tabAssetId = tabdata.value<Widget::GraphTabMetadata>();
  2129. if (tabAssetId.m_canvasWidget)
  2130. {
  2131. tabAssetId.m_canvasWidget->hide();
  2132. }
  2133. bool activeSet = false;
  2134. if (tabAssetId.m_assetId.AnyEquals(m_activeGraph))
  2135. {
  2136. SetActiveAsset({});
  2137. activeSet = true;
  2138. }
  2139. m_tabBar->CloseTab(index);
  2140. m_tabBar->update();
  2141. RemoveScriptCanvasAsset(tabAssetId.m_assetId);
  2142. if (!activeSet && m_tabBar->count() == 0)
  2143. {
  2144. // The last tab has been removed.
  2145. SetActiveAsset({});
  2146. }
  2147. // Handling various close all events because the save is async need to deal with this in a bunch of different ways
  2148. // Always want to trigger this, even if we don't have any active tabs to avoid doubling the clean-up
  2149. // information
  2150. AddSystemTickAction(SystemTickActionFlag::CloseNextTabAction);
  2151. }
  2152. }
  2153. void MainWindow::OnNodeAdded(const AZ::EntityId& nodeId, bool isPaste)
  2154. {
  2155. // Handle special-case where if a method node is created that has an AZ::Event output slot,
  2156. // we will automatically create the AZ::Event Handler node for the user
  2157. GraphCanvas::GraphId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  2158. AZStd::vector<GraphCanvas::SlotId> outputDataSlotIds;
  2159. GraphCanvas::NodeRequestBus::EventResult(outputDataSlotIds, nodeId, &GraphCanvas::NodeRequests::FindVisibleSlotIdsByType, GraphCanvas::CT_Output, GraphCanvas::SlotTypes::DataSlot);
  2160. for (const auto& slotId : outputDataSlotIds)
  2161. {
  2162. if (!IsInUndoRedo(graphCanvasGraphId) && !isPaste && CreateAzEventHandlerSlotMenuAction::FindBehaviorMethodWithAzEventReturn(graphCanvasGraphId, slotId))
  2163. {
  2164. CreateAzEventHandlerSlotMenuAction eventHandlerAction(this);
  2165. eventHandlerAction.RefreshAction(graphCanvasGraphId, slotId);
  2166. AZ::Vector2 position;
  2167. GraphCanvas::GeometryRequestBus::EventResult(position, nodeId, &GraphCanvas::GeometryRequests::GetPosition);
  2168. eventHandlerAction.TriggerAction(graphCanvasGraphId, position);
  2169. break;
  2170. }
  2171. }
  2172. }
  2173. void MainWindow::OnSelectionChanged()
  2174. {
  2175. QueuePropertyGridUpdate();
  2176. }
  2177. void MainWindow::OnVariableSelectionChanged(const AZStd::vector<AZ::EntityId>& variablePropertyIds)
  2178. {
  2179. m_selectedVariableIds = variablePropertyIds;
  2180. QueuePropertyGridUpdate();
  2181. }
  2182. void MainWindow::QueuePropertyGridUpdate()
  2183. {
  2184. // Selection will be ignored when a delete operation is are taking place to prevent slowdown from processing
  2185. // too many events at once.
  2186. if (!m_ignoreSelection && !m_isInAutomation)
  2187. {
  2188. AddSystemTickAction(SystemTickActionFlag::RefreshPropertyGrid);
  2189. }
  2190. }
  2191. void MainWindow::DequeuePropertyGridUpdate()
  2192. {
  2193. RemoveSystemTickAction(SystemTickActionFlag::RefreshPropertyGrid);
  2194. }
  2195. void MainWindow::SetDefaultLayout()
  2196. {
  2197. // Disable updates while we restore the layout to avoid temporary glitches
  2198. // as the panes are moved around
  2199. setUpdatesEnabled(false);
  2200. if (m_commandLine)
  2201. {
  2202. m_commandLine->hide();
  2203. }
  2204. if (m_validationDockWidget)
  2205. {
  2206. addDockWidget(Qt::BottomDockWidgetArea, m_validationDockWidget);
  2207. m_validationDockWidget->setFloating(false);
  2208. m_validationDockWidget->hide();
  2209. }
  2210. if (m_logPanel)
  2211. {
  2212. addDockWidget(Qt::BottomDockWidgetArea, m_logPanel);
  2213. m_logPanel->setFloating(false);
  2214. m_logPanel->hide();
  2215. }
  2216. if (m_minimap)
  2217. {
  2218. addDockWidget(Qt::LeftDockWidgetArea, m_minimap);
  2219. m_minimap->setFloating(false);
  2220. m_minimap->show();
  2221. }
  2222. if (m_nodePalette)
  2223. {
  2224. addDockWidget(Qt::LeftDockWidgetArea, m_nodePalette);
  2225. m_nodePalette->setFloating(false);
  2226. m_nodePalette->show();
  2227. }
  2228. if (m_variableDockWidget)
  2229. {
  2230. addDockWidget(Qt::RightDockWidgetArea, m_variableDockWidget);
  2231. m_variableDockWidget->setFloating(false);
  2232. m_variableDockWidget->show();
  2233. }
  2234. if (m_unitTestDockWidget)
  2235. {
  2236. addDockWidget(Qt::LeftDockWidgetArea, m_unitTestDockWidget);
  2237. m_unitTestDockWidget->setFloating(false);
  2238. m_unitTestDockWidget->hide();
  2239. }
  2240. if (m_loggingWindow)
  2241. {
  2242. addDockWidget(Qt::BottomDockWidgetArea, m_loggingWindow);
  2243. m_loggingWindow->setFloating(false);
  2244. m_loggingWindow->hide();
  2245. }
  2246. if (m_propertyGrid)
  2247. {
  2248. addDockWidget(Qt::RightDockWidgetArea, m_propertyGrid);
  2249. m_propertyGrid->setFloating(false);
  2250. m_propertyGrid->show();
  2251. }
  2252. if (m_bookmarkDockWidget)
  2253. {
  2254. addDockWidget(Qt::RightDockWidgetArea, m_bookmarkDockWidget);
  2255. m_bookmarkDockWidget->setFloating(false);
  2256. m_bookmarkDockWidget->hide();
  2257. }
  2258. if (m_minimap)
  2259. {
  2260. addDockWidget(Qt::RightDockWidgetArea, m_minimap);
  2261. m_minimap->setFloating(false);
  2262. m_minimap->show();
  2263. }
  2264. resizeDocks(
  2265. { m_nodePalette, m_propertyGrid },
  2266. { static_cast<int>(size().width() * 0.15f), static_cast<int>(size().width() * 0.2f) },
  2267. Qt::Horizontal);
  2268. resizeDocks({ m_nodePalette, m_minimap },
  2269. { static_cast<int>(size().height() * 0.70f), static_cast<int>(size().height() * 0.30f) },
  2270. Qt::Vertical);
  2271. resizeDocks({ m_propertyGrid, m_variableDockWidget },
  2272. { static_cast<int>(size().height() * 0.70f), static_cast<int>(size().height() * 0.30f) },
  2273. Qt::Vertical);
  2274. resizeDocks({ m_validationDockWidget }, { static_cast<int>(size().height() * 0.01) }, Qt::Vertical);
  2275. // Disabled until debugger is implemented
  2276. //resizeDocks({ m_logPanel }, { static_cast<int>(size().height() * 0.1f) }, Qt::Vertical);
  2277. // Re-enable updates now that we've finished adjusting the layout
  2278. setUpdatesEnabled(true);
  2279. m_defaultLayout = saveState();
  2280. UpdateViewMenu();
  2281. }
  2282. void MainWindow::RefreshSelection()
  2283. {
  2284. ScriptCanvas::ScriptCanvasId scriptCanvasId = GetActiveScriptCanvasId();
  2285. AZ::EntityId graphCanvasGraphId;
  2286. EditorGraphRequestBus::EventResult(graphCanvasGraphId, scriptCanvasId, &EditorGraphRequests::GetGraphCanvasGraphId);
  2287. bool hasCopiableSelection = false;
  2288. bool hasSelection = false;
  2289. if (m_activeGraph.IsGraphValid())
  2290. {
  2291. if (graphCanvasGraphId.IsValid())
  2292. {
  2293. // Get the selected nodes.
  2294. GraphCanvas::SceneRequestBus::EventResult(hasCopiableSelection, graphCanvasGraphId, &GraphCanvas::SceneRequests::HasCopiableSelection);
  2295. }
  2296. AZStd::vector< AZ::EntityId > selection;
  2297. GraphCanvas::SceneRequestBus::EventResult(selection, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetSelectedItems);
  2298. selection.reserve(selection.size() + m_selectedVariableIds.size());
  2299. selection.insert(selection.end(), m_selectedVariableIds.begin(), m_selectedVariableIds.end());
  2300. if (!selection.empty())
  2301. {
  2302. hasSelection = true;
  2303. m_propertyGrid->SetSelection(selection);
  2304. }
  2305. else
  2306. {
  2307. m_propertyGrid->ClearSelection();
  2308. }
  2309. }
  2310. else
  2311. {
  2312. m_propertyGrid->ClearSelection();
  2313. }
  2314. // cut, copy and duplicate only works for specified items
  2315. ui->action_Cut->setEnabled(hasCopiableSelection);
  2316. ui->action_Copy->setEnabled(hasCopiableSelection);
  2317. ui->action_Duplicate->setEnabled(hasCopiableSelection);
  2318. // Delete will work for anything that is selectable
  2319. ui->action_Delete->setEnabled(hasSelection);
  2320. }
  2321. void MainWindow::OnViewNodePalette()
  2322. {
  2323. if (m_nodePalette)
  2324. {
  2325. m_nodePalette->toggleViewAction()->trigger();
  2326. }
  2327. }
  2328. void MainWindow::OnViewMiniMap()
  2329. {
  2330. if (m_minimap)
  2331. {
  2332. m_minimap->toggleViewAction()->trigger();
  2333. }
  2334. }
  2335. void MainWindow::OnViewLogWindow()
  2336. {
  2337. if (m_loggingWindow)
  2338. {
  2339. m_loggingWindow->toggleViewAction()->trigger();
  2340. }
  2341. }
  2342. void MainWindow::OnViewGraphValidation()
  2343. {
  2344. if (m_validationDockWidget)
  2345. {
  2346. m_validationDockWidget->toggleViewAction()->trigger();
  2347. }
  2348. }
  2349. void MainWindow::OnViewDebuggingWindow()
  2350. {
  2351. if (m_loggingWindow)
  2352. {
  2353. m_loggingWindow->toggleViewAction()->trigger();
  2354. }
  2355. }
  2356. void MainWindow::OnViewUnitTestManager()
  2357. {
  2358. if (m_unitTestDockWidget == nullptr)
  2359. {
  2360. CreateUnitTestWidget();
  2361. }
  2362. if (m_unitTestDockWidget)
  2363. {
  2364. m_unitTestDockWidget->show();
  2365. m_unitTestDockWidget->raise();
  2366. m_unitTestDockWidget->activateWindow();
  2367. }
  2368. }
  2369. void MainWindow::OnViewStatisticsPanel()
  2370. {
  2371. if (m_statisticsDialog)
  2372. {
  2373. m_statisticsDialog->InitStatisticsWindow();
  2374. m_statisticsDialog->show();
  2375. m_statisticsDialog->raise();
  2376. m_statisticsDialog->activateWindow();
  2377. }
  2378. }
  2379. void MainWindow::OnViewPresetsEditor()
  2380. {
  2381. if (m_presetEditor && m_presetWrapper)
  2382. {
  2383. QSize boundingBox = size();
  2384. QPointF newPosition = mapToGlobal(QPoint(aznumeric_cast<int>(boundingBox.width() * 0.5f), aznumeric_cast<int>(boundingBox.height() * 0.5f)));
  2385. m_presetEditor->show();
  2386. m_presetWrapper->show();
  2387. m_presetWrapper->raise();
  2388. m_presetWrapper->activateWindow();
  2389. QRect geometry = m_presetWrapper->geometry();
  2390. QSize originalSize = geometry.size();
  2391. newPosition.setX(newPosition.x() - geometry.width() * 0.5f);
  2392. newPosition.setY(newPosition.y() - geometry.height() * 0.5f);
  2393. geometry.setTopLeft(newPosition.toPoint());
  2394. geometry.setWidth(originalSize.width());
  2395. geometry.setHeight(originalSize.height());
  2396. m_presetWrapper->setGeometry(geometry);
  2397. }
  2398. }
  2399. void MainWindow::OnViewProperties()
  2400. {
  2401. if (m_propertyGrid)
  2402. {
  2403. m_propertyGrid->toggleViewAction()->trigger();
  2404. }
  2405. }
  2406. void MainWindow::OnViewDebugger()
  2407. {
  2408. }
  2409. void MainWindow::OnViewCommandLine()
  2410. {
  2411. if (m_commandLine->isVisible())
  2412. {
  2413. m_commandLine->hide();
  2414. }
  2415. else
  2416. {
  2417. m_commandLine->show();
  2418. }
  2419. }
  2420. void MainWindow::OnViewLog()
  2421. {
  2422. if (m_logPanel)
  2423. {
  2424. m_logPanel->toggleViewAction()->trigger();
  2425. }
  2426. }
  2427. void MainWindow::OnBookmarks()
  2428. {
  2429. if (m_bookmarkDockWidget)
  2430. {
  2431. m_bookmarkDockWidget->toggleViewAction()->trigger();
  2432. }
  2433. }
  2434. void MainWindow::OnVariableManager()
  2435. {
  2436. if (m_variableDockWidget)
  2437. {
  2438. m_variableDockWidget->toggleViewAction()->trigger();
  2439. }
  2440. }
  2441. void MainWindow::OnRestoreDefaultLayout()
  2442. {
  2443. if (!m_defaultLayout.isEmpty())
  2444. {
  2445. restoreState(m_defaultLayout);
  2446. UpdateViewMenu();
  2447. }
  2448. }
  2449. void MainWindow::UpdateViewMenu()
  2450. {
  2451. if (ui->action_ViewBookmarks->isChecked() != m_bookmarkDockWidget->isVisible())
  2452. {
  2453. QSignalBlocker signalBlocker(ui->action_ViewBookmarks);
  2454. ui->action_ViewBookmarks->setChecked(m_bookmarkDockWidget->isVisible());
  2455. }
  2456. if (ui->action_ViewMiniMap->isChecked() != m_minimap->isVisible())
  2457. {
  2458. QSignalBlocker signalBlocker(ui->action_ViewMiniMap);
  2459. ui->action_ViewMiniMap->setChecked(m_minimap->isVisible());
  2460. }
  2461. if (ui->action_ViewNodePalette->isChecked() != m_nodePalette->isVisible())
  2462. {
  2463. QSignalBlocker signalBlocker(ui->action_ViewNodePalette);
  2464. ui->action_ViewNodePalette->setChecked(m_nodePalette->isVisible());
  2465. }
  2466. if (ui->action_ViewProperties->isChecked() != m_propertyGrid->isVisible())
  2467. {
  2468. QSignalBlocker signalBlocker(ui->action_ViewProperties);
  2469. ui->action_ViewProperties->setChecked(m_propertyGrid->isVisible());
  2470. }
  2471. if (ui->action_ViewVariableManager->isChecked() != m_variableDockWidget->isVisible())
  2472. {
  2473. QSignalBlocker signalBlocker(ui->action_ViewVariableManager);
  2474. ui->action_ViewVariableManager->setChecked(m_variableDockWidget->isVisible());
  2475. }
  2476. if (ui->action_ViewLogWindow->isChecked() != m_loggingWindow->isVisible())
  2477. {
  2478. QSignalBlocker signalBlocker(ui->action_ViewLogWindow);
  2479. ui->action_ViewLogWindow->setChecked(m_loggingWindow->isVisible());
  2480. }
  2481. if (ui->action_GraphValidation->isChecked() != m_validationDockWidget->isVisible())
  2482. {
  2483. QSignalBlocker signalBlocker(ui->action_GraphValidation);
  2484. ui->action_GraphValidation->setChecked(m_validationDockWidget->isVisible());
  2485. }
  2486. if (ui->action_Debugging->isChecked() != m_loggingWindow->isVisible())
  2487. {
  2488. ui->action_Debugging->setChecked(m_loggingWindow->isVisible());
  2489. }
  2490. // Want these two elements to be mutually exclusive.
  2491. if (m_statusWidget->isVisible() == m_validationDockWidget->isVisible())
  2492. {
  2493. statusBar()->setVisible(!m_validationDockWidget->isVisible());
  2494. m_statusWidget->setVisible(!m_validationDockWidget->isVisible());
  2495. }
  2496. }
  2497. void MainWindow::DeleteNodes(const AZ::EntityId& graphCanvasGraphId, const AZStd::vector<AZ::EntityId>& nodes)
  2498. {
  2499. // clear the selection then delete the nodes that were selected
  2500. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::ClearSelection);
  2501. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, AZStd::unordered_set<AZ::EntityId>{ nodes.begin(), nodes.end() });
  2502. }
  2503. void MainWindow::DeleteConnections(const AZ::EntityId& graphCanvasGraphId, const AZStd::vector<AZ::EntityId>& connections)
  2504. {
  2505. ScopedVariableSetter<bool> scopedIgnoreSelection(m_ignoreSelection, true);
  2506. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, AZStd::unordered_set<AZ::EntityId>{ connections.begin(), connections.end() });
  2507. }
  2508. void MainWindow::DisconnectEndpoints(const AZ::EntityId& graphCanvasGraphId, const AZStd::vector<GraphCanvas::Endpoint>& endpoints)
  2509. {
  2510. AZStd::unordered_set<AZ::EntityId> connections;
  2511. for (const auto& endpoint : endpoints)
  2512. {
  2513. AZStd::vector<AZ::EntityId> endpointConnections;
  2514. GraphCanvas::SceneRequestBus::EventResult(endpointConnections, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetConnectionsForEndpoint, endpoint);
  2515. connections.insert(endpointConnections.begin(), endpointConnections.end());
  2516. }
  2517. DeleteConnections(graphCanvasGraphId, { connections.begin(), connections.end() });
  2518. }
  2519. void MainWindow::ShowInterpreter()
  2520. {
  2521. using namespace ScriptCanvasEditor;
  2522. if (!m_interpreterWidget)
  2523. {
  2524. m_interpreterWidget = AZStd::make_unique<InterpreterWidget>();
  2525. }
  2526. if (m_interpreterWidget)
  2527. {
  2528. m_interpreterWidget->show();
  2529. m_interpreterWidget->raise();
  2530. m_interpreterWidget->activateWindow();
  2531. }
  2532. }
  2533. void MainWindow::RunUpgradeTool()
  2534. {
  2535. using namespace VersionExplorer;
  2536. auto versionExplorer = AZStd::make_unique<Controller>(this);
  2537. versionExplorer->exec();
  2538. const ModificationResults* result = nullptr;
  2539. ModelRequestsBus::BroadcastResult(result, &ModelRequestsTraits::GetResults);
  2540. if (result && !result->m_failures.empty())
  2541. {
  2542. // If there are graphs that need manual correction, show the helper
  2543. UpgradeHelper* upgradeHelper = new UpgradeHelper(this);
  2544. upgradeHelper->show();
  2545. }
  2546. }
  2547. void MainWindow::OnShowValidationErrors()
  2548. {
  2549. m_userSettings->m_showValidationErrors = true;
  2550. if (!m_validationDockWidget->isVisible())
  2551. {
  2552. OnViewGraphValidation();
  2553. // If the window wasn't visible, it doesn't seem to get the signals.
  2554. // So need to manually prompt it to get the desired result
  2555. m_validationDockWidget->OnShowErrors();
  2556. }
  2557. }
  2558. void MainWindow::OnShowValidationWarnings()
  2559. {
  2560. m_userSettings->m_showValidationWarnings = true;
  2561. if (!m_validationDockWidget->isVisible())
  2562. {
  2563. OnViewGraphValidation();
  2564. // If the window wasn't visible, it doesn't seem to get the signals.
  2565. // So need to manually prompt it to get the desired result
  2566. m_validationDockWidget->OnShowWarnings();
  2567. }
  2568. }
  2569. void MainWindow::OnValidateCurrentGraph()
  2570. {
  2571. const bool displayToastNotification = false;
  2572. RunGraphValidation(displayToastNotification);
  2573. }
  2574. void MainWindow::RunGraphValidation(bool displayToastNotification)
  2575. {
  2576. m_validationDockWidget->OnRunValidator(displayToastNotification);
  2577. if (m_validationDockWidget->HasValidationIssues())
  2578. {
  2579. OpenValidationPanel();
  2580. }
  2581. }
  2582. void MainWindow::OnViewParamsChanged(const GraphCanvas::ViewParams& viewParams)
  2583. {
  2584. AZ_UNUSED(viewParams);
  2585. RestartAutoTimerSave();
  2586. }
  2587. void MainWindow::OnZoomChanged(qreal)
  2588. {
  2589. RestartAutoTimerSave();
  2590. }
  2591. void MainWindow::AfterEntitySelectionChanged(const AzToolsFramework::EntityIdList&, const AzToolsFramework::EntityIdList&)
  2592. {
  2593. UpdateAssignToSelectionState();
  2594. }
  2595. void MainWindow::UpdateMenuState(bool enabled)
  2596. {
  2597. m_validateGraphToolButton->setEnabled(enabled);
  2598. ui->menuRemove_Unused->setEnabled(enabled);
  2599. ui->action_RemoveUnusedNodes->setEnabled(enabled);
  2600. ui->action_RemoveUnusedVariables->setEnabled(enabled);
  2601. ui->action_RemoveUnusedElements->setEnabled(enabled);
  2602. ui->action_ZoomIn->setEnabled(enabled);
  2603. ui->action_ZoomOut->setEnabled(enabled);
  2604. ui->action_ZoomSelection->setEnabled(enabled);
  2605. ui->action_ShowEntireGraph->setEnabled(enabled);
  2606. ui->menuGo_To->setEnabled(enabled);
  2607. ui->action_GotoStartOfChain->setEnabled(enabled);
  2608. ui->action_GotoEndOfChain->setEnabled(enabled);
  2609. ui->actionZoom_To->setEnabled(enabled);
  2610. ui->action_EnableSelection->setEnabled(enabled);
  2611. ui->action_DisableSelection->setEnabled(enabled);
  2612. m_createFunctionOutput->setEnabled(enabled);
  2613. m_createFunctionInput->setEnabled(enabled);
  2614. m_takeScreenshot->setEnabled(enabled);
  2615. // File Menu
  2616. ui->action_Close->setEnabled(enabled);
  2617. RefreshGraphPreferencesAction();
  2618. UpdateAssignToSelectionState();
  2619. UpdateUndoRedoState();
  2620. }
  2621. void MainWindow::OnWorkspaceRestoreStart()
  2622. {
  2623. m_isRestoringWorkspace = true;
  2624. }
  2625. void MainWindow::OnWorkspaceRestoreEnd(SourceHandle lastFocusAsset)
  2626. {
  2627. if (m_isRestoringWorkspace)
  2628. {
  2629. m_isRestoringWorkspace = false;
  2630. if (m_queuedFocusOverride.IsGraphValid())
  2631. {
  2632. SetActiveAsset(m_queuedFocusOverride);
  2633. m_queuedFocusOverride.Clear();
  2634. }
  2635. else if (lastFocusAsset.IsGraphValid())
  2636. {
  2637. SetActiveAsset(lastFocusAsset);
  2638. }
  2639. if (!m_activeGraph.IsGraphValid())
  2640. {
  2641. if (m_tabBar->count() > 0)
  2642. {
  2643. if (m_tabBar->currentIndex() != 0)
  2644. {
  2645. m_tabBar->setCurrentIndex(0);
  2646. }
  2647. else
  2648. {
  2649. SetActiveAsset(m_tabBar->FindAssetId(0));
  2650. }
  2651. }
  2652. else
  2653. {
  2654. SetActiveAsset({});
  2655. }
  2656. }
  2657. }
  2658. }
  2659. void MainWindow::UpdateAssignToSelectionState()
  2660. {
  2661. bool buttonEnabled = m_activeGraph.IsGraphValid();
  2662. if (buttonEnabled)
  2663. {
  2664. const Tracker::ScriptCanvasFileState& fileState = GetAssetFileState(m_activeGraph);
  2665. if (fileState == Tracker::ScriptCanvasFileState::INVALID || fileState == Tracker::ScriptCanvasFileState::NEW || fileState == Tracker::ScriptCanvasFileState::SOURCE_REMOVED)
  2666. {
  2667. buttonEnabled = false;
  2668. }
  2669. m_assignToSelectedEntity->setEnabled(buttonEnabled);
  2670. }
  2671. else
  2672. {
  2673. m_assignToSelectedEntity->setEnabled(false);
  2674. }
  2675. }
  2676. void MainWindow::UpdateUndoRedoState()
  2677. {
  2678. bool isEnabled = false;
  2679. UndoRequestBus::EventResult(isEnabled, GetActiveScriptCanvasId(), &UndoRequests::CanUndo);
  2680. ui->action_Undo->setEnabled(isEnabled);
  2681. isEnabled = false;
  2682. UndoRequestBus::EventResult(isEnabled, GetActiveScriptCanvasId(), &UndoRequests::CanRedo);
  2683. ui->action_Redo->setEnabled(isEnabled);
  2684. }
  2685. void MainWindow::UpdateSaveState(bool enabled)
  2686. {
  2687. ui->action_Save->setEnabled(enabled);
  2688. ui->action_Save_As->setEnabled(enabled);
  2689. }
  2690. void MainWindow::CreateFunctionInput()
  2691. {
  2692. PushPreventUndoStateUpdate();
  2693. CreateFunctionDefinitionNode(-1);
  2694. PopPreventUndoStateUpdate();
  2695. PostUndoPoint(GetActiveScriptCanvasId());
  2696. }
  2697. void MainWindow::CreateFunctionOutput()
  2698. {
  2699. PushPreventUndoStateUpdate();
  2700. CreateFunctionDefinitionNode(1);
  2701. PopPreventUndoStateUpdate();
  2702. PostUndoPoint(GetActiveScriptCanvasId());
  2703. }
  2704. void MainWindow::CreateFunctionDefinitionNode(int positionOffset)
  2705. {
  2706. ScriptCanvas::ScriptCanvasId scriptCanvasId = GetActiveScriptCanvasId();
  2707. GraphCanvas::GraphId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  2708. GraphCanvas::ViewId viewId;
  2709. GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
  2710. QRectF viewBounds;
  2711. GraphCanvas::ViewRequestBus::EventResult(viewBounds, viewId, &GraphCanvas::ViewRequests::GetCompleteArea);
  2712. const bool isInput = positionOffset < 0;
  2713. const AZStd::string rootName = isInput ? "New Input" : "New Output";
  2714. NodeIdPair nodeIdPair = Nodes::CreateFunctionDefinitionNode(scriptCanvasId, isInput, rootName);
  2715. GraphCanvas::SceneRequests* sceneRequests = GraphCanvas::SceneRequestBus::FindFirstHandler(graphCanvasGraphId);
  2716. if (sceneRequests == nullptr)
  2717. {
  2718. return;
  2719. }
  2720. QPointF pasteOffset = sceneRequests->SignalGenericAddPositionUseBegin();
  2721. sceneRequests->AddNode(nodeIdPair.m_graphCanvasId, GraphCanvas::ConversionUtils::QPointToVector(pasteOffset), false);
  2722. sceneRequests->SignalGenericAddPositionUseEnd();
  2723. if (!viewBounds.isEmpty())
  2724. {
  2725. QPointF topLeftPoint = viewBounds.center();
  2726. int widthOffset = aznumeric_cast<int>((viewBounds.width() * 0.5f) * positionOffset);
  2727. topLeftPoint.setX(topLeftPoint.x() + widthOffset);
  2728. QGraphicsItem* graphicsItem = nullptr;
  2729. GraphCanvas::SceneMemberUIRequestBus::EventResult(graphicsItem, nodeIdPair.m_graphCanvasId, &GraphCanvas::SceneMemberUIRequests::GetRootGraphicsItem);
  2730. GraphCanvas::NodeUIRequestBus::Event(nodeIdPair.m_graphCanvasId, &GraphCanvas::NodeUIRequests::AdjustSize);
  2731. qreal width = graphicsItem->sceneBoundingRect().width();
  2732. // If we are going negative we need to move over the width of the node.
  2733. if (positionOffset < 0)
  2734. {
  2735. topLeftPoint.setX(topLeftPoint.x() - width);
  2736. }
  2737. // Center the node.
  2738. qreal height = graphicsItem->sceneBoundingRect().height();
  2739. topLeftPoint.setY(topLeftPoint.y() - height * 0.5);
  2740. // Offset by the width step.
  2741. AZ::Vector2 minorStep = AZ::Vector2::CreateZero();
  2742. AZ::EntityId gridId;
  2743. GraphCanvas::SceneRequestBus::EventResult(gridId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetGrid);
  2744. GraphCanvas::GridRequestBus::EventResult(minorStep, gridId, &GraphCanvas::GridRequests::GetMinorPitch);
  2745. QRectF sceneBoundaries = sceneRequests->AsQGraphicsScene()->sceneRect();
  2746. sceneBoundaries.adjust(minorStep.GetX(), minorStep.GetY(), -minorStep.GetX(), -minorStep.GetY());
  2747. topLeftPoint.setX(topLeftPoint.x() + minorStep.GetX() * positionOffset);
  2748. // Sanitizes the position of the node to ensure it's always 'visible'
  2749. while (topLeftPoint.x() + width <= sceneBoundaries.left())
  2750. {
  2751. topLeftPoint.setX(topLeftPoint.x() + width);
  2752. }
  2753. while (topLeftPoint.x() >= sceneBoundaries.right())
  2754. {
  2755. topLeftPoint.setX(topLeftPoint.x() - width);
  2756. }
  2757. while (topLeftPoint.y() + height <= sceneBoundaries.top())
  2758. {
  2759. topLeftPoint.setY(topLeftPoint.y() + height);
  2760. }
  2761. while (topLeftPoint.y() >= sceneBoundaries.bottom())
  2762. {
  2763. topLeftPoint.setY(topLeftPoint.y() - height);
  2764. }
  2765. ////
  2766. GraphCanvas::GeometryRequestBus::Event(nodeIdPair.m_graphCanvasId, &GraphCanvas::GeometryRequests::SetPosition, GraphCanvas::ConversionUtils::QPointToVector(topLeftPoint));
  2767. GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::CenterOnArea, graphicsItem->sceneBoundingRect());
  2768. }
  2769. }
  2770. NodeIdPair MainWindow::ProcessCreateNodeMimeEvent(GraphCanvas::GraphCanvasMimeEvent* mimeEvent, const AZ::EntityId& graphCanvasGraphId, AZ::Vector2 nodeCreationPos)
  2771. {
  2772. if (!m_isInAutomation)
  2773. {
  2774. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::ClearSelection);
  2775. }
  2776. NodeIdPair retVal;
  2777. if (azrtti_istypeof<CreateNodeMimeEvent>(mimeEvent))
  2778. {
  2779. CreateNodeMimeEvent* createEvent = static_cast<CreateNodeMimeEvent*>(mimeEvent);
  2780. if (createEvent->ExecuteEvent(nodeCreationPos, nodeCreationPos, graphCanvasGraphId))
  2781. {
  2782. retVal = createEvent->GetCreatedPair();
  2783. }
  2784. }
  2785. else if (azrtti_istypeof<SpecializedCreateNodeMimeEvent>(mimeEvent))
  2786. {
  2787. SpecializedCreateNodeMimeEvent* specializedCreationEvent = static_cast<SpecializedCreateNodeMimeEvent*>(mimeEvent);
  2788. retVal = specializedCreationEvent->ConstructNode(graphCanvasGraphId, nodeCreationPos);
  2789. }
  2790. return retVal;
  2791. }
  2792. const GraphCanvas::GraphCanvasTreeItem* MainWindow::GetNodePaletteRoot() const
  2793. {
  2794. return m_nodePalette->GetTreeRoot();
  2795. }
  2796. void MainWindow::SignalAutomationBegin()
  2797. {
  2798. m_isInAutomation = true;
  2799. }
  2800. void MainWindow::SignalAutomationEnd()
  2801. {
  2802. m_isInAutomation = false;
  2803. }
  2804. void MainWindow::ForceCloseActiveAsset()
  2805. {
  2806. OnTabCloseRequest(m_tabBar->currentIndex());
  2807. }
  2808. bool MainWindow::RegisterObject(AZ::Crc32 elementId, QObject* object)
  2809. {
  2810. auto lookupIter = m_automationLookUpMap.find(elementId);
  2811. if (lookupIter != m_automationLookUpMap.end())
  2812. {
  2813. AZ_Error("ScriptCanvas", false, "Attempting to register two elements with the id %llu", (unsigned int)elementId);
  2814. return false;
  2815. }
  2816. m_automationLookUpMap[elementId] = object;
  2817. return true;
  2818. }
  2819. bool MainWindow::UnregisterObject(AZ::Crc32 elementId)
  2820. {
  2821. auto eraseCount = m_automationLookUpMap.erase(elementId);
  2822. return eraseCount > 0;
  2823. }
  2824. QObject* MainWindow::FindObject(AZ::Crc32 elementId)
  2825. {
  2826. auto lookupIter = m_automationLookUpMap.find(elementId);
  2827. if (lookupIter != m_automationLookUpMap.end())
  2828. {
  2829. return lookupIter->second;
  2830. }
  2831. return nullptr;
  2832. }
  2833. QObject* MainWindow::FindElementByName(QString elementName)
  2834. {
  2835. return findChild<QObject*>(elementName);
  2836. }
  2837. AZ::EntityId MainWindow::FindEditorNodeIdByAssetNodeId([[maybe_unused]] const SourceHandle& assetId
  2838. , [[maybe_unused]] AZ::EntityId assetNodeId) const
  2839. {
  2840. AZ::EntityId editorEntityId{};
  2841. // AssetTrackerRequestBus::BroadcastResult
  2842. // ( editorEntityId, &AssetTrackerRequests::GetEditorEntityIdFromSceneEntityId, assetId.Id(), assetNodeId);
  2843. // #sc_editor_asset_redux fix logger
  2844. return editorEntityId;
  2845. }
  2846. AZ::EntityId MainWindow::FindAssetNodeIdByEditorNodeId([[maybe_unused]] const SourceHandle& assetId
  2847. , [[maybe_unused]] AZ::EntityId editorNodeId) const
  2848. {
  2849. AZ::EntityId sceneEntityId{};
  2850. // AssetTrackerRequestBus::BroadcastResult
  2851. // ( sceneEntityId, &AssetTrackerRequests::GetSceneEntityIdFromEditorEntityId, assetId.Id(), editorNodeId);
  2852. // #sc_editor_asset_redux fix logger
  2853. return sceneEntityId;
  2854. }
  2855. GraphCanvas::Endpoint MainWindow::CreateNodeForProposalWithGroup(const AZ::EntityId& connectionId
  2856. , const GraphCanvas::Endpoint& endpoint, const QPointF& scenePoint, const QPoint& screenPoint, AZ::EntityId groupTarget)
  2857. {
  2858. PushPreventUndoStateUpdate();
  2859. GraphCanvas::Endpoint retVal;
  2860. AZ::EntityId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  2861. // Handle the special-case if we are creating a node proposal for an AZ::Event, then we show
  2862. // a small menu with only that applicable action
  2863. if (CreateAzEventHandlerSlotMenuAction::FindBehaviorMethodWithAzEventReturn(graphCanvasGraphId, endpoint.GetSlotId()))
  2864. {
  2865. GraphCanvas::EditorContextMenu menu(ScriptCanvasEditor::AssetEditorId);
  2866. menu.AddMenuAction(aznew CreateAzEventHandlerSlotMenuAction(&menu));
  2867. HandleContextMenu(menu, endpoint.GetSlotId(), screenPoint, scenePoint);
  2868. }
  2869. // For everything else, show the full scene context menu
  2870. else
  2871. {
  2872. m_sceneContextMenu->FilterForSourceSlot(graphCanvasGraphId, endpoint.GetSlotId());
  2873. m_sceneContextMenu->RefreshActions(graphCanvasGraphId, connectionId);
  2874. m_sceneContextMenu->SetupDisplayForProposal();
  2875. QAction* action = m_sceneContextMenu->exec(screenPoint);
  2876. // If the action returns null. We need to check if it was our widget, or just a close command.
  2877. if (action == nullptr)
  2878. {
  2879. GraphCanvas::GraphCanvasMimeEvent* mimeEvent = m_sceneContextMenu->GetNodePalette()->GetContextMenuEvent();
  2880. if (mimeEvent)
  2881. {
  2882. NodeIdPair finalNode = ProcessCreateNodeMimeEvent(mimeEvent, graphCanvasGraphId, AZ::Vector2(aznumeric_cast<float>(scenePoint.x()), aznumeric_cast<float>(scenePoint.y())));
  2883. if (finalNode.m_graphCanvasId.IsValid())
  2884. {
  2885. GraphCanvas::VisualRequestBus::Event(finalNode.m_graphCanvasId, &GraphCanvas::VisualRequests::SetVisible, false);
  2886. retVal = HandleProposedConnection(graphCanvasGraphId, connectionId, endpoint, finalNode.m_graphCanvasId, screenPoint);
  2887. }
  2888. if (retVal.IsValid())
  2889. {
  2890. AZStd::unordered_set<GraphCanvas::ConnectionId> createdConnections = GraphCanvas::GraphUtils::CreateOpportunisticConnectionsBetween(endpoint, retVal);
  2891. GraphCanvas::VisualRequestBus::Event(finalNode.m_graphCanvasId, &GraphCanvas::VisualRequests::SetVisible, true);
  2892. AZ::Vector2 position;
  2893. GraphCanvas::GeometryRequestBus::EventResult(position, retVal.GetNodeId(), &GraphCanvas::GeometryRequests::GetPosition);
  2894. QPointF connectionPoint;
  2895. GraphCanvas::SlotUIRequestBus::EventResult(connectionPoint, retVal.GetSlotId(), &GraphCanvas::SlotUIRequests::GetConnectionPoint);
  2896. qreal verticalOffset = connectionPoint.y() - position.GetY();
  2897. position.SetY(aznumeric_cast<float>(scenePoint.y() - verticalOffset));
  2898. qreal horizontalOffset = connectionPoint.x() - position.GetX();
  2899. position.SetX(aznumeric_cast<float>(scenePoint.x() - horizontalOffset));
  2900. GraphCanvas::GeometryRequestBus::Event(retVal.GetNodeId(), &GraphCanvas::GeometryRequests::SetPosition, position);
  2901. GraphCanvas::GraphUtils::AddElementToGroup(finalNode.m_graphCanvasId, groupTarget);
  2902. GraphCanvas::SceneNotificationBus::Event(graphCanvasGraphId, &GraphCanvas::SceneNotifications::PostCreationEvent);
  2903. }
  2904. else
  2905. {
  2906. GraphCanvas::GraphUtils::DeleteOutermostNode(graphCanvasGraphId, finalNode.m_graphCanvasId);
  2907. }
  2908. }
  2909. }
  2910. }
  2911. PopPreventUndoStateUpdate();
  2912. return retVal;
  2913. }
  2914. void MainWindow::OnWrapperNodeActionWidgetClicked(const AZ::EntityId& wrapperNode, const QRect& actionWidgetBoundingRect, const QPointF& scenePoint, const QPoint& screenPoint)
  2915. {
  2916. if (EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(wrapperNode) != nullptr)
  2917. {
  2918. m_ebusHandlerActionMenu->SetEbusHandlerNode(wrapperNode);
  2919. // We don't care about the result, since the actions are done on demand with the menu
  2920. m_ebusHandlerActionMenu->exec(screenPoint);
  2921. }
  2922. else if (ScriptCanvasWrapperNodeDescriptorRequestBus::FindFirstHandler(wrapperNode) != nullptr)
  2923. {
  2924. ScriptCanvasWrapperNodeDescriptorRequestBus::Event(wrapperNode, &ScriptCanvasWrapperNodeDescriptorRequests::OnWrapperAction, actionWidgetBoundingRect, scenePoint, screenPoint);
  2925. }
  2926. }
  2927. void MainWindow::OnSelectionManipulationBegin()
  2928. {
  2929. m_ignoreSelection = true;
  2930. }
  2931. void MainWindow::OnSelectionManipulationEnd()
  2932. {
  2933. m_ignoreSelection = false;
  2934. OnSelectionChanged();
  2935. }
  2936. AZ::EntityId MainWindow::CreateNewGraph()
  2937. {
  2938. AZ::EntityId graphId;
  2939. OnFileNew();
  2940. if (m_activeGraph.IsGraphValid())
  2941. {
  2942. graphId = GetActiveGraphCanvasGraphId();
  2943. }
  2944. return graphId;
  2945. }
  2946. bool MainWindow::ContainsGraph(const GraphCanvas::GraphId&) const
  2947. {
  2948. return false;
  2949. }
  2950. bool MainWindow::CloseGraph(const GraphCanvas::GraphId&)
  2951. {
  2952. return false;
  2953. }
  2954. void MainWindow::CustomizeConnectionEntity(AZ::Entity* connectionEntity)
  2955. {
  2956. connectionEntity->CreateComponent<SceneMemberMappingComponent>();
  2957. }
  2958. void MainWindow::ShowAssetPresetsMenu(GraphCanvas::ConstructType constructType)
  2959. {
  2960. OnViewPresetsEditor();
  2961. if (m_presetEditor)
  2962. {
  2963. m_presetEditor->SetActiveConstructType(constructType);
  2964. }
  2965. }
  2966. //! Hook for receiving context menu events for each QGraphicsScene
  2967. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowSceneContextMenuWithGroup(const QPoint& screenPoint, const QPointF& scenePoint, AZ::EntityId groupTarget)
  2968. {
  2969. bool tryDaisyChain = (QApplication::keyboardModifiers() & Qt::KeyboardModifier::ShiftModifier) != 0;
  2970. GraphCanvas::GraphId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  2971. ScriptCanvas::ScriptCanvasId scriptCanvasGraphId = GetActiveScriptCanvasId();
  2972. if (!graphCanvasGraphId.IsValid() || !scriptCanvasGraphId.IsValid())
  2973. {
  2974. // Nothing to do.
  2975. return GraphCanvas::ContextMenuAction::SceneReaction::Nothing;
  2976. }
  2977. m_sceneContextMenu->ResetSourceSlotFilter();
  2978. m_sceneContextMenu->RefreshActions(graphCanvasGraphId, AZ::EntityId());
  2979. QAction* action = m_sceneContextMenu->exec(screenPoint);
  2980. GraphCanvas::ContextMenuAction::SceneReaction reaction = GraphCanvas::ContextMenuAction::SceneReaction::Nothing;
  2981. if (action == nullptr)
  2982. {
  2983. GraphCanvas::GraphCanvasMimeEvent* mimeEvent = m_sceneContextMenu->GetNodePalette()->GetContextMenuEvent();
  2984. NodeIdPair finalNode = ProcessCreateNodeMimeEvent(mimeEvent, graphCanvasGraphId, AZ::Vector2(aznumeric_cast<float>(scenePoint.x()), aznumeric_cast<float>(scenePoint.y())));
  2985. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::ClearSelection);
  2986. if (finalNode.m_graphCanvasId.IsValid())
  2987. {
  2988. GraphCanvas::VisualRequestBus::Event(finalNode.m_graphCanvasId, &GraphCanvas::VisualRequests::SetVisible, true);
  2989. AZ::Vector2 position;
  2990. GraphCanvas::GeometryRequestBus::EventResult(position, finalNode.m_graphCanvasId, &GraphCanvas::GeometryRequests::GetPosition);
  2991. GraphCanvas::GeometryRequestBus::Event(finalNode.m_graphCanvasId, &GraphCanvas::GeometryRequests::SetPosition, position);
  2992. // If we have a valid group target. We're going to want to add the element to the group.
  2993. GraphCanvas::GraphUtils::AddElementToGroup(finalNode.m_graphCanvasId, groupTarget);
  2994. GraphCanvas::SceneNotificationBus::Event(graphCanvasGraphId, &GraphCanvas::SceneNotifications::PostCreationEvent);
  2995. if (tryDaisyChain)
  2996. {
  2997. QTimer::singleShot(50, [graphCanvasGraphId, finalNode, screenPoint, scenePoint, groupTarget]()
  2998. {
  2999. GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::HandleProposalDaisyChainWithGroup, finalNode.m_graphCanvasId, GraphCanvas::SlotTypes::ExecutionSlot, GraphCanvas::CT_Output, screenPoint, scenePoint, groupTarget);
  3000. });
  3001. }
  3002. }
  3003. }
  3004. else
  3005. {
  3006. GraphCanvas::ContextMenuAction* contextMenuAction = qobject_cast<GraphCanvas::ContextMenuAction*>(action);
  3007. if (contextMenuAction)
  3008. {
  3009. PushPreventUndoStateUpdate();
  3010. AZ::Vector2 mousePoint(aznumeric_cast<float>(scenePoint.x()), aznumeric_cast<float>(scenePoint.y()));
  3011. reaction = contextMenuAction->TriggerAction(graphCanvasGraphId, mousePoint);
  3012. PopPreventUndoStateUpdate();
  3013. }
  3014. }
  3015. return reaction;
  3016. }
  3017. //! Hook for receiving context menu events for each QGraphicsScene
  3018. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowNodeContextMenu(const AZ::EntityId& nodeId, const QPoint& screenPoint, const QPointF& scenePoint)
  3019. {
  3020. GraphCanvas::NodeContextMenu contextMenu(ScriptCanvasEditor::AssetEditorId);
  3021. NodeDescriptorType descriptorType = NodeDescriptorType::Unknown;
  3022. NodeDescriptorRequestBus::EventResult(descriptorType, nodeId, &NodeDescriptorRequests::GetType);
  3023. if (descriptorType == NodeDescriptorType::GetVariable || descriptorType == NodeDescriptorType::SetVariable)
  3024. {
  3025. contextMenu.AddMenuAction(aznew ConvertVariableNodeToReferenceAction(&contextMenu));
  3026. }
  3027. if (descriptorType == NodeDescriptorType::FunctionDefinitionNode)
  3028. {
  3029. NodeDescriptorComponent* descriptor = nullptr;
  3030. NodeDescriptorRequestBus::EventResult(descriptor, nodeId, &NodeDescriptorRequests::GetDescriptorComponent);
  3031. contextMenu.AddMenuAction(aznew RenameFunctionDefinitionNodeAction(descriptor, &contextMenu));
  3032. contextMenu.addSeparator();
  3033. }
  3034. return HandleContextMenu(contextMenu, nodeId, screenPoint, scenePoint);
  3035. }
  3036. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowCommentContextMenu(const AZ::EntityId& nodeId, const QPoint& screenPoint, const QPointF& scenePoint)
  3037. {
  3038. GraphCanvas::CommentContextMenu contextMenu(ScriptCanvasEditor::AssetEditorId);
  3039. return HandleContextMenu(contextMenu, nodeId, screenPoint, scenePoint);
  3040. }
  3041. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowNodeGroupContextMenu(const AZ::EntityId& groupId, const QPoint& screenPoint, const QPointF& scenePoint)
  3042. {
  3043. GraphCanvas::NodeGroupContextMenu contextMenu(ScriptCanvasEditor::AssetEditorId);
  3044. return HandleContextMenu(contextMenu, groupId, screenPoint, scenePoint);
  3045. }
  3046. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowCollapsedNodeGroupContextMenu(const AZ::EntityId& nodeId, const QPoint& screenPoint, const QPointF& scenePoint)
  3047. {
  3048. GraphCanvas::CollapsedNodeGroupContextMenu contextMenu(ScriptCanvasEditor::AssetEditorId);
  3049. return HandleContextMenu(contextMenu, nodeId, screenPoint, scenePoint);
  3050. }
  3051. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowBookmarkContextMenu(const AZ::EntityId& bookmarkId, const QPoint& screenPoint, const QPointF& scenePoint)
  3052. {
  3053. GraphCanvas::BookmarkContextMenu contextMenu(ScriptCanvasEditor::AssetEditorId);
  3054. return HandleContextMenu(contextMenu, bookmarkId, screenPoint, scenePoint);
  3055. }
  3056. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowConnectionContextMenuWithGroup(const AZ::EntityId& connectionId, const QPoint& screenPoint, const QPointF& scenePoint, AZ::EntityId groupTarget)
  3057. {
  3058. PushPreventUndoStateUpdate();
  3059. GraphCanvas::ContextMenuAction::SceneReaction reaction = GraphCanvas::ContextMenuAction::SceneReaction::Nothing;
  3060. AZ::Vector2 sceneVector(aznumeric_cast<float>(scenePoint.x()), aznumeric_cast<float>(scenePoint.y()));
  3061. GraphCanvas::GraphId graphCanvasGraphId = GetActiveGraphCanvasGraphId();
  3062. m_connectionContextMenu->RefreshActions(graphCanvasGraphId, connectionId);
  3063. QAction* result = m_connectionContextMenu->exec(screenPoint);
  3064. GraphCanvas::ContextMenuAction* contextMenuAction = qobject_cast<GraphCanvas::ContextMenuAction*>(result);
  3065. // If the action returns null. We need to check if it was our widget, or just a close command.
  3066. if (contextMenuAction)
  3067. {
  3068. reaction = contextMenuAction->TriggerAction(graphCanvasGraphId, sceneVector);
  3069. }
  3070. else
  3071. {
  3072. GraphCanvas::GraphCanvasMimeEvent* mimeEvent = m_connectionContextMenu->GetNodePalette()->GetContextMenuEvent();
  3073. if (mimeEvent)
  3074. {
  3075. NodeIdPair finalNode = ProcessCreateNodeMimeEvent(mimeEvent, graphCanvasGraphId, AZ::Vector2(aznumeric_cast<float>(scenePoint.x()), aznumeric_cast<float>(scenePoint.y())));
  3076. GraphCanvas::Endpoint sourceEndpoint;
  3077. GraphCanvas::ConnectionRequestBus::EventResult(sourceEndpoint, connectionId, &GraphCanvas::ConnectionRequests::GetSourceEndpoint);
  3078. GraphCanvas::Endpoint targetEndpoint;
  3079. GraphCanvas::ConnectionRequestBus::EventResult(targetEndpoint, connectionId, &GraphCanvas::ConnectionRequests::GetTargetEndpoint);
  3080. if (finalNode.m_graphCanvasId.IsValid())
  3081. {
  3082. GraphCanvas::ConnectionSpliceConfig spliceConfig;
  3083. spliceConfig.m_allowOpportunisticConnections = true;
  3084. if (!GraphCanvas::GraphUtils::SpliceNodeOntoConnection(finalNode.m_graphCanvasId, connectionId, spliceConfig))
  3085. {
  3086. GraphCanvas::GraphUtils::DeleteOutermostNode(graphCanvasGraphId, finalNode.m_graphCanvasId);
  3087. }
  3088. else
  3089. {
  3090. reaction = GraphCanvas::ContextMenuAction::SceneReaction::PostUndo;
  3091. // Now we can deal with the alignment of the node.
  3092. GraphCanvas::VisualRequestBus::Event(finalNode.m_graphCanvasId, &GraphCanvas::VisualRequests::SetVisible, true);
  3093. AZ::Vector2 position(0,0);
  3094. GraphCanvas::GeometryRequestBus::EventResult(position, finalNode.m_graphCanvasId, &GraphCanvas::GeometryRequests::GetPosition);
  3095. QPointF sourceConnectionPoint(0,0);
  3096. GraphCanvas::SlotUIRequestBus::EventResult(sourceConnectionPoint, spliceConfig.m_splicedSourceEndpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetConnectionPoint);
  3097. QPointF targetConnectionPoint(0,0);
  3098. GraphCanvas::SlotUIRequestBus::EventResult(targetConnectionPoint, spliceConfig.m_splicedTargetEndpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetConnectionPoint);
  3099. // Average our two points so we splice roughly in the center of our node.
  3100. QPointF connectionPoint = (sourceConnectionPoint + targetConnectionPoint) * 0.5f;
  3101. qreal verticalOffset = connectionPoint.y() - position.GetY();
  3102. position.SetY(aznumeric_cast<float>(scenePoint.y() - verticalOffset));
  3103. qreal horizontalOffset = connectionPoint.x() - position.GetX();
  3104. position.SetX(aznumeric_cast<float>(scenePoint.x() - horizontalOffset));
  3105. GraphCanvas::GeometryRequestBus::Event(finalNode.m_graphCanvasId, &GraphCanvas::GeometryRequests::SetPosition, position);
  3106. if (IsNodeNudgingEnabled())
  3107. {
  3108. GraphCanvas::NodeNudgingController nudgingController(graphCanvasGraphId, { finalNode.m_graphCanvasId });
  3109. nudgingController.FinalizeNudging();
  3110. }
  3111. GraphCanvas::GraphUtils::AddElementToGroup(finalNode.m_graphCanvasId, groupTarget);
  3112. GraphCanvas::SceneNotificationBus::Event(graphCanvasGraphId, &GraphCanvas::SceneNotifications::PostCreationEvent);
  3113. }
  3114. }
  3115. }
  3116. }
  3117. PopPreventUndoStateUpdate();
  3118. return reaction;
  3119. }
  3120. GraphCanvas::ContextMenuAction::SceneReaction MainWindow::ShowSlotContextMenu(const AZ::EntityId& slotId, const QPoint& screenPoint, const QPointF& scenePoint)
  3121. {
  3122. GraphCanvas::SlotContextMenu contextMenu(ScriptCanvasEditor::AssetEditorId);
  3123. contextMenu.AddMenuAction(aznew ConvertReferenceToVariableNodeAction(&contextMenu));
  3124. contextMenu.AddMenuAction(aznew ExposeSlotMenuAction(&contextMenu));
  3125. contextMenu.AddMenuAction(aznew CreateAzEventHandlerSlotMenuAction(&contextMenu));
  3126. auto setSlotTypeAction = aznew SetDataSlotTypeMenuAction(&contextMenu);
  3127. contextMenu.AddMenuAction(setSlotTypeAction);
  3128. return HandleContextMenu(contextMenu, slotId, screenPoint, scenePoint);
  3129. }
  3130. void MainWindow::OnSystemTick()
  3131. {
  3132. if (HasSystemTickAction(SystemTickActionFlag::RefreshPropertyGrid))
  3133. {
  3134. RemoveSystemTickAction(SystemTickActionFlag::RefreshPropertyGrid);
  3135. RefreshSelection();
  3136. }
  3137. if (HasSystemTickAction(SystemTickActionFlag::CloseWindow))
  3138. {
  3139. RemoveSystemTickAction(SystemTickActionFlag::CloseWindow);
  3140. qobject_cast<QWidget*>(parent())->close();
  3141. }
  3142. if (HasSystemTickAction(SystemTickActionFlag::CloseCurrentGraph))
  3143. {
  3144. RemoveSystemTickAction(SystemTickActionFlag::CloseCurrentGraph);
  3145. if (m_tabBar)
  3146. {
  3147. m_tabBar->tabCloseRequested(m_tabBar->currentIndex());
  3148. }
  3149. }
  3150. if (HasSystemTickAction(SystemTickActionFlag::CloseNextTabAction))
  3151. {
  3152. RemoveSystemTickAction(SystemTickActionFlag::CloseNextTabAction);
  3153. CloseNextTab();
  3154. }
  3155. ClearStaleSaves();
  3156. }
  3157. void MainWindow::OnCommandStarted(AZ::Crc32)
  3158. {
  3159. PushPreventUndoStateUpdate();
  3160. }
  3161. void MainWindow::OnCommandFinished(AZ::Crc32)
  3162. {
  3163. PopPreventUndoStateUpdate();
  3164. }
  3165. void MainWindow::PrepareActiveAssetForSave()
  3166. {
  3167. PrepareAssetForSave(m_activeGraph);
  3168. }
  3169. void MainWindow::PrepareAssetForSave(const SourceHandle& /*assetId*/)
  3170. {
  3171. }
  3172. void MainWindow::RestartAutoTimerSave(bool forceTimer)
  3173. {
  3174. if (m_autoSaveTimer.isActive() || forceTimer)
  3175. {
  3176. m_autoSaveTimer.stop();
  3177. m_autoSaveTimer.start();
  3178. }
  3179. }
  3180. void MainWindow::OnSelectedEntitiesAboutToShow()
  3181. {
  3182. AzToolsFramework::EntityIdList selectedEntityIds;
  3183. AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
  3184. m_selectedEntityMenu->clear();
  3185. for (const AZ::EntityId& entityId : selectedEntityIds)
  3186. {
  3187. bool isLayerEntity = false;
  3188. AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(isLayerEntity, entityId, &AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
  3189. if (isLayerEntity)
  3190. {
  3191. continue;
  3192. }
  3193. AZ::NamedEntityId namedEntityId(entityId);
  3194. QAction* actionElement = new QAction(namedEntityId.GetName().data(), m_selectedEntityMenu);
  3195. QObject::connect(actionElement, &QAction::triggered, [this, entityId]() {
  3196. OnAssignToEntity(entityId);
  3197. });
  3198. m_selectedEntityMenu->addAction(actionElement);
  3199. }
  3200. }
  3201. void MainWindow::OnAssignToSelectedEntities()
  3202. {
  3203. Tracker::ScriptCanvasFileState fileState = GetAssetFileState(m_activeGraph);;
  3204. bool isDocumentOpen = false;
  3205. AzToolsFramework::EditorRequests::Bus::BroadcastResult(isDocumentOpen, &AzToolsFramework::EditorRequests::IsLevelDocumentOpen);
  3206. if (fileState == Tracker::ScriptCanvasFileState::NEW || fileState == Tracker::ScriptCanvasFileState::SOURCE_REMOVED || !isDocumentOpen)
  3207. {
  3208. return;
  3209. }
  3210. AzToolsFramework::EntityIdList selectedEntityIds;
  3211. AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
  3212. auto selectedEntityIdIter = selectedEntityIds.begin();
  3213. bool isLayerAmbiguous = false;
  3214. AZ::EntityId targetLayer;
  3215. while (selectedEntityIdIter != selectedEntityIds.end())
  3216. {
  3217. bool isLayerEntity = false;
  3218. AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(isLayerEntity, (*selectedEntityIdIter), &AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
  3219. if (isLayerEntity)
  3220. {
  3221. if (targetLayer.IsValid())
  3222. {
  3223. isLayerAmbiguous = true;
  3224. }
  3225. targetLayer = (*selectedEntityIdIter);
  3226. selectedEntityIdIter = selectedEntityIds.erase(selectedEntityIdIter);
  3227. }
  3228. else
  3229. {
  3230. ++selectedEntityIdIter;
  3231. }
  3232. }
  3233. if (selectedEntityIds.empty())
  3234. {
  3235. AZ::EntityId createdId;
  3236. AzToolsFramework::EditorRequests::Bus::BroadcastResult(createdId, &AzToolsFramework::EditorRequests::CreateNewEntity, AZ::EntityId());
  3237. selectedEntityIds.emplace_back(createdId);
  3238. if (targetLayer.IsValid() && !isLayerAmbiguous)
  3239. {
  3240. AZ::TransformBus::Event(createdId, &AZ::TransformBus::Events::SetParent, targetLayer);
  3241. }
  3242. }
  3243. for (const AZ::EntityId& entityId : selectedEntityIds)
  3244. {
  3245. AssignGraphToEntityImpl(entityId);
  3246. }
  3247. }
  3248. void MainWindow::OnAssignToEntity(const AZ::EntityId& entityId)
  3249. {
  3250. Tracker::ScriptCanvasFileState fileState = GetAssetFileState(m_activeGraph);
  3251. if (fileState == Tracker::ScriptCanvasFileState::MODIFIED
  3252. || fileState == Tracker::ScriptCanvasFileState::UNMODIFIED)
  3253. {
  3254. AssignGraphToEntityImpl(entityId);
  3255. }
  3256. }
  3257. ScriptCanvasEditor::Tracker::ScriptCanvasFileState MainWindow::GetAssetFileState(SourceHandle assetId) const
  3258. {
  3259. auto dataOptional = m_tabBar->GetTabData(assetId);
  3260. return dataOptional ? dataOptional->m_fileState : Tracker::ScriptCanvasFileState::INVALID;
  3261. }
  3262. void MainWindow::AssignGraphToEntityImpl(const AZ::EntityId& entityId)
  3263. {
  3264. bool isLayerEntity = false;
  3265. AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(isLayerEntity, entityId, &AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
  3266. if (isLayerEntity)
  3267. {
  3268. return;
  3269. }
  3270. EditorScriptCanvasComponentRequests* firstRequestBus = nullptr;
  3271. EditorScriptCanvasComponentRequests* firstEmptyRequestBus = nullptr;
  3272. EditorScriptCanvasComponentRequestBus::EnumerateHandlersId(entityId, [&firstRequestBus, &firstEmptyRequestBus](EditorScriptCanvasComponentRequests* scriptCanvasRequests)
  3273. {
  3274. if (firstRequestBus == nullptr)
  3275. {
  3276. firstRequestBus = scriptCanvasRequests;
  3277. }
  3278. if (!scriptCanvasRequests->HasAssetId())
  3279. {
  3280. firstEmptyRequestBus = scriptCanvasRequests;
  3281. }
  3282. return firstRequestBus == nullptr || firstEmptyRequestBus == nullptr;
  3283. });
  3284. auto usableRequestBus = firstEmptyRequestBus;
  3285. if (usableRequestBus == nullptr)
  3286. {
  3287. usableRequestBus = firstRequestBus;
  3288. }
  3289. if (usableRequestBus == nullptr)
  3290. {
  3291. AzToolsFramework::EntityCompositionRequestBus::Broadcast(&EntityCompositionRequests::AddComponentsToEntities, AzToolsFramework::EntityIdList{ entityId }
  3292. , AZ::ComponentTypeList{ azrtti_typeid<EditorScriptCanvasComponent>() });
  3293. usableRequestBus = EditorScriptCanvasComponentRequestBus::FindFirstHandler(entityId);
  3294. }
  3295. if (usableRequestBus)
  3296. {
  3297. usableRequestBus->SetAssetId(m_activeGraph.Describe());
  3298. }
  3299. }
  3300. bool MainWindow::HasSystemTickAction(SystemTickActionFlag action)
  3301. {
  3302. return (m_systemTickActions & action) != 0;
  3303. }
  3304. void MainWindow::RemoveSystemTickAction(SystemTickActionFlag action)
  3305. {
  3306. m_systemTickActions = m_systemTickActions & (~action);
  3307. }
  3308. void MainWindow::AddSystemTickAction(SystemTickActionFlag action)
  3309. {
  3310. m_systemTickActions |= action;
  3311. }
  3312. void MainWindow::BlockCloseRequests()
  3313. {
  3314. m_queueCloseRequest = true;
  3315. }
  3316. void MainWindow::UnblockCloseRequests()
  3317. {
  3318. if (m_queueCloseRequest)
  3319. {
  3320. m_queueCloseRequest = false;
  3321. if (m_hasQueuedClose)
  3322. {
  3323. qobject_cast<QWidget*>(parent())->close();
  3324. }
  3325. }
  3326. }
  3327. void MainWindow::OpenNextFile()
  3328. {
  3329. if (!m_filesToOpen.empty())
  3330. {
  3331. QString nextFile = m_filesToOpen.front();
  3332. m_filesToOpen.pop_front();
  3333. OpenFile(nextFile.toUtf8().data());
  3334. OpenNextFile();
  3335. }
  3336. else
  3337. {
  3338. m_errorFilePath.clear();
  3339. }
  3340. }
  3341. double MainWindow::GetSnapDistance() const
  3342. {
  3343. if (m_userSettings)
  3344. {
  3345. return m_userSettings->m_snapDistance;
  3346. }
  3347. return 10.0;
  3348. }
  3349. bool MainWindow::IsGroupDoubleClickCollapseEnabled() const
  3350. {
  3351. if (m_userSettings)
  3352. {
  3353. return m_userSettings->m_enableGroupDoubleClickCollapse;
  3354. }
  3355. return true;
  3356. }
  3357. bool MainWindow::IsBookmarkViewportControlEnabled() const
  3358. {
  3359. if (m_userSettings)
  3360. {
  3361. return m_userSettings->m_allowBookmarkViewpointControl;
  3362. }
  3363. return false;
  3364. }
  3365. bool MainWindow::IsDragNodeCouplingEnabled() const
  3366. {
  3367. if (m_userSettings)
  3368. {
  3369. return m_userSettings->m_dragNodeCouplingConfig.m_enabled;
  3370. }
  3371. return false;
  3372. }
  3373. AZStd::chrono::milliseconds MainWindow::GetDragCouplingTime() const
  3374. {
  3375. if (m_userSettings)
  3376. {
  3377. return AZStd::chrono::milliseconds(m_userSettings->m_dragNodeCouplingConfig.m_timeMS);
  3378. }
  3379. return AZStd::chrono::milliseconds(500);
  3380. }
  3381. bool MainWindow::IsDragConnectionSpliceEnabled() const
  3382. {
  3383. if (m_userSettings)
  3384. {
  3385. return m_userSettings->m_dragNodeSplicingConfig.m_enabled;
  3386. }
  3387. return false;
  3388. }
  3389. AZStd::chrono::milliseconds MainWindow::GetDragConnectionSpliceTime() const
  3390. {
  3391. if (m_userSettings)
  3392. {
  3393. return AZStd::chrono::milliseconds(m_userSettings->m_dragNodeSplicingConfig.m_timeMS);
  3394. }
  3395. return AZStd::chrono::milliseconds(500);
  3396. }
  3397. bool MainWindow::IsDropConnectionSpliceEnabled() const
  3398. {
  3399. if (m_userSettings)
  3400. {
  3401. return m_userSettings->m_dropNodeSplicingConfig.m_enabled;
  3402. }
  3403. return false;
  3404. }
  3405. AZStd::chrono::milliseconds MainWindow::GetDropConnectionSpliceTime() const
  3406. {
  3407. if (m_userSettings)
  3408. {
  3409. return AZStd::chrono::milliseconds(m_userSettings->m_dropNodeSplicingConfig.m_timeMS);
  3410. }
  3411. return AZStd::chrono::milliseconds(500);
  3412. }
  3413. bool MainWindow::IsNodeNudgingEnabled() const
  3414. {
  3415. if (m_userSettings)
  3416. {
  3417. return m_userSettings->m_allowNodeNudging;
  3418. }
  3419. return false;
  3420. }
  3421. bool MainWindow::IsShakeToDespliceEnabled() const
  3422. {
  3423. if (m_userSettings)
  3424. {
  3425. return m_userSettings->m_shakeDespliceConfig.m_enabled;
  3426. }
  3427. return false;
  3428. }
  3429. int MainWindow::GetShakesToDesplice() const
  3430. {
  3431. if (m_userSettings)
  3432. {
  3433. return m_userSettings->m_shakeDespliceConfig.m_shakeCount;
  3434. }
  3435. return 3;
  3436. }
  3437. float MainWindow::GetMinimumShakePercent() const
  3438. {
  3439. if (m_userSettings)
  3440. {
  3441. return m_userSettings->m_shakeDespliceConfig.GetMinimumShakeLengthPercent();
  3442. }
  3443. return 0.03f;
  3444. }
  3445. float MainWindow::GetShakeDeadZonePercent() const
  3446. {
  3447. if (m_userSettings)
  3448. {
  3449. return m_userSettings->m_shakeDespliceConfig.GetDeadZonePercent();
  3450. }
  3451. return 0.01f;
  3452. }
  3453. float MainWindow::GetShakeStraightnessPercent() const
  3454. {
  3455. if (m_userSettings)
  3456. {
  3457. return m_userSettings->m_shakeDespliceConfig.GetStraightnessPercent();
  3458. }
  3459. return 0.75f;
  3460. }
  3461. AZStd::chrono::milliseconds MainWindow::GetMaximumShakeDuration() const
  3462. {
  3463. if (m_userSettings)
  3464. {
  3465. return AZStd::chrono::milliseconds(m_userSettings->m_shakeDespliceConfig.m_maximumShakeTimeMS);
  3466. }
  3467. return AZStd::chrono::milliseconds(500);
  3468. }
  3469. AZStd::chrono::milliseconds MainWindow::GetAlignmentTime() const
  3470. {
  3471. if (m_userSettings)
  3472. {
  3473. return AZStd::chrono::milliseconds(m_userSettings->m_alignmentTimeMS);
  3474. }
  3475. return AZStd::chrono::milliseconds(250);
  3476. }
  3477. float MainWindow::GetMaxZoom() const
  3478. {
  3479. if (m_userSettings)
  3480. {
  3481. return m_userSettings->m_zoomSettings.GetMaxZoom();
  3482. }
  3483. return 2.0f;
  3484. }
  3485. float MainWindow::GetEdgePanningPercentage() const
  3486. {
  3487. if (m_userSettings)
  3488. {
  3489. return m_userSettings->m_edgePanningSettings.GetEdgeScrollPercent();
  3490. }
  3491. return 0.1f;
  3492. }
  3493. float MainWindow::GetEdgePanningScrollSpeed() const
  3494. {
  3495. if (m_userSettings)
  3496. {
  3497. return m_userSettings->m_edgePanningSettings.GetEdgeScrollSpeed();
  3498. }
  3499. return 100.0f;
  3500. }
  3501. GraphCanvas::EditorConstructPresets* MainWindow::GetConstructPresets() const
  3502. {
  3503. if (m_userSettings)
  3504. {
  3505. return &m_userSettings->m_constructPresets;
  3506. }
  3507. return nullptr;
  3508. }
  3509. const GraphCanvas::ConstructTypePresetBucket* MainWindow::GetConstructTypePresetBucket(GraphCanvas::ConstructType constructType) const
  3510. {
  3511. GraphCanvas::EditorConstructPresets* presets = GetConstructPresets();
  3512. if (presets)
  3513. {
  3514. return presets->FindPresetBucket(constructType);
  3515. }
  3516. return nullptr;
  3517. }
  3518. GraphCanvas::Styling::ConnectionCurveType MainWindow::GetConnectionCurveType() const
  3519. {
  3520. if (m_userSettings)
  3521. {
  3522. return m_userSettings->m_stylingSettings.GetConnectionCurveType();
  3523. }
  3524. return GraphCanvas::Styling::ConnectionCurveType::Straight;
  3525. }
  3526. GraphCanvas::Styling::ConnectionCurveType MainWindow::GetDataConnectionCurveType() const
  3527. {
  3528. if (m_userSettings)
  3529. {
  3530. return m_userSettings->m_stylingSettings.GetDataConnectionCurveType();
  3531. }
  3532. return GraphCanvas::Styling::ConnectionCurveType::Straight;
  3533. }
  3534. bool MainWindow::AllowNodeDisabling() const
  3535. {
  3536. return true;
  3537. }
  3538. bool MainWindow::AllowDataReferenceSlots() const
  3539. {
  3540. return true;
  3541. }
  3542. void MainWindow::CreateUnitTestWidget()
  3543. {
  3544. // Dock Widget will be unable to dock with this as it doesn't have a parent.
  3545. // Going to orphan this as a floating window to more mimic its behavior as a pop-up window rather then a dock widget.
  3546. m_unitTestDockWidget = aznew UnitTestDockWidget(this);
  3547. m_unitTestDockWidget->setObjectName("TestManager");
  3548. m_unitTestDockWidget->setAllowedAreas(Qt::NoDockWidgetArea);
  3549. m_unitTestDockWidget->setFloating(true);
  3550. m_unitTestDockWidget->hide();
  3551. // Restore this if we want the dock widget to again be a toggleable thing.
  3552. //connect(m_unitTestDockWidget, &QDockWidget::visibilityChanged, this, &MainWindow::OnViewVisibilityChanged);
  3553. }
  3554. void MainWindow::DisableAssetView(const SourceHandle& memoryAssetId)
  3555. {
  3556. if (auto view = m_tabBar->ModTabView(m_tabBar->FindTab(memoryAssetId)))
  3557. {
  3558. view->DisableView();
  3559. }
  3560. m_tabBar->setEnabled(false);
  3561. m_bookmarkDockWidget->setEnabled(false);
  3562. m_variableDockWidget->setEnabled(false);
  3563. m_propertyGrid->DisableGrid();
  3564. m_editorToolbar->OnViewDisabled();
  3565. m_createFunctionInput->setEnabled(false);
  3566. m_createFunctionOutput->setEnabled(false);
  3567. m_createScriptCanvas->setEnabled(false);
  3568. UpdateMenuState(false);
  3569. ui->action_New_Script->setEnabled(false);
  3570. m_autoSaveTimer.stop();
  3571. }
  3572. void MainWindow::EnableAssetView(const SourceHandle& memoryAssetId)
  3573. {
  3574. if (auto view = m_tabBar->ModTabView(m_tabBar->FindTab(memoryAssetId)))
  3575. {
  3576. view->EnableView();
  3577. }
  3578. m_tabBar->setEnabled(true);
  3579. m_bookmarkDockWidget->setEnabled(true);
  3580. m_variableDockWidget->setEnabled(true);
  3581. m_propertyGrid->EnableGrid();
  3582. m_editorToolbar->OnViewEnabled();
  3583. m_createScriptCanvas->setEnabled(true);
  3584. ui->action_New_Script->setEnabled(true);
  3585. UpdateMenuState(true);
  3586. UpdateUndoRedoState();
  3587. }
  3588. void MainWindow::ClearStaleSaves()
  3589. {
  3590. AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
  3591. auto timeNow = AZStd::chrono::system_clock::now();
  3592. AZStd::erase_if(m_saves, [&timeNow](const auto& item)
  3593. {
  3594. AZStd::sys_time_t delta = AZStd::chrono::seconds(timeNow - item.second).count();
  3595. return delta > 2.0f;
  3596. });
  3597. }
  3598. bool MainWindow::IsRecentSave(const SourceHandle& handle) const
  3599. {
  3600. AZStd::lock_guard<AZStd::recursive_mutex> lock(const_cast<MainWindow*>(this)->m_mutex);
  3601. AZStd::string key = handle.AbsolutePath().Native();
  3602. AZStd::to_lower(key.begin(), key.end());
  3603. auto iter = m_saves.find(key);
  3604. return iter != m_saves.end();
  3605. }
  3606. void MainWindow::MarkRecentSave(const SourceHandle& handle)
  3607. {
  3608. AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
  3609. AZStd::string key = handle.AbsolutePath().Native();
  3610. AZStd::to_lower(key.begin(), key.end());
  3611. m_saves[key] = AZStd::chrono::system_clock::now();
  3612. }
  3613. void MainWindow::OnScriptEventAddHelpers()
  3614. {
  3615. if (ScriptEvents::Editor::MakeHelpersAction(m_activeGraph).first)
  3616. {
  3617. GraphCanvas::GraphModelRequestBus::Event
  3618. ( m_activeGraph.Mod()->GetEntityId()
  3619. , &GraphCanvas::GraphModelRequests::RequestUndoPoint);
  3620. }
  3621. }
  3622. void MainWindow::OnScriptEventClearStatus()
  3623. {
  3624. ScriptEvents::Editor::ClearStatusAction(m_activeGraph);
  3625. }
  3626. void MainWindow::OnScriptEventMenuPreShow()
  3627. {
  3628. auto result = ScriptEvents::Editor::UpdateMenuItemsEnabled(m_activeGraph);
  3629. ui->actionAdd_Script_Event_Helpers->setEnabled(result.m_addHelpers);
  3630. ui->actionClear_Script_Event_Status->setEnabled(result.m_clear);
  3631. ui->actionParse_As_Script_Event->setEnabled(result.m_parse);
  3632. ui->actionSave_As_ScriptEvent->setEnabled(result.m_save);
  3633. }
  3634. void MainWindow::OnScriptEventOpen()
  3635. {
  3636. AZStd::pair<ScriptCanvas::SourceHandle, AZStd::string> result = ScriptEvents::Editor::OpenAction();
  3637. if (result.first.Get())
  3638. {
  3639. OpenScriptCanvasAssetImplementation(result.first, Tracker::ScriptCanvasFileState::UNMODIFIED);
  3640. }
  3641. else
  3642. {
  3643. QMessageBox mb
  3644. ( QMessageBox::Warning
  3645. , tr("Failed to open ScriptEvent file into ScriptCanvas Editor.")
  3646. , result.second.c_str()
  3647. , QMessageBox::Close
  3648. , nullptr);
  3649. mb.exec();
  3650. }
  3651. }
  3652. void MainWindow::OnScriptEventParseAs()
  3653. {
  3654. if (!m_activeGraph.IsGraphValid())
  3655. {
  3656. return;
  3657. }
  3658. AZStd::pair<bool, AZStd::vector<AZStd::string>> result = ScriptEvents::Editor::ParseAsAction(m_activeGraph);
  3659. if (result.first)
  3660. {
  3661. QMessageBox mb
  3662. ( QMessageBox::Information
  3663. , QObject::tr("Success!")
  3664. , QObject::tr("Graph parsed as ScriptEvent, and may be saved as one.")
  3665. , QMessageBox::Close
  3666. , nullptr);
  3667. mb.exec();
  3668. }
  3669. else
  3670. {
  3671. AZStd::string parseErrorString;
  3672. if (!result.second.empty())
  3673. {
  3674. parseErrorString = "Parse Errors:\n";
  3675. for (auto& entry : result.second)
  3676. {
  3677. parseErrorString += "* ";
  3678. parseErrorString += entry;
  3679. parseErrorString += "\n";
  3680. }
  3681. }
  3682. QMessageBox mb
  3683. ( QMessageBox::Warning
  3684. , QObject::tr("Graph did not parse as ScriptEvent, please fix issues below to save as a ScriptEvent")
  3685. , parseErrorString.c_str()
  3686. , QMessageBox::Close
  3687. , nullptr);
  3688. mb.exec();
  3689. }
  3690. }
  3691. void MainWindow::OnScriptEventSaveAs()
  3692. {
  3693. auto result = ScriptEvents::Editor::SaveAsAction(m_activeGraph);
  3694. if (result.first)
  3695. {
  3696. OnSaveToast toast
  3697. ( result.second
  3698. , GetActiveGraphCanvasGraphId()
  3699. , true
  3700. , AZStd::string("Graph Saved .scriptevent, and this editor can open that file.\n"
  3701. "No .scriptcanvas file was saved from this graph."));
  3702. }
  3703. else
  3704. {
  3705. QMessageBox mb
  3706. ( QMessageBox::Warning
  3707. , QObject::tr("Failed to Save As Script Event")
  3708. , result.second.c_str()
  3709. , QMessageBox::Close
  3710. , nullptr);
  3711. mb.exec();
  3712. }
  3713. }
  3714. #include <Editor/View/Windows/moc_MainWindow.cpp>
  3715. }