@@ -99,7 +99,8 @@ function TalentViewer:ApplyCurrencySpending(treeCurrency)
9999 return treeCurrency
100100end
101101
102- function TalentViewer :ResetTree ()
102+ --- @param lockLevelingBuild ? boolean # by default, a new leveling build is created and activated when this function is called, passing true will prevent that
103+ function TalentViewer :ResetTree (lockLevelingBuild )
103104 local talentFrame = self :GetTalentFrame ()
104105 wipe (self .purchasedRanks );
105106 wipe (self .selectedEntries );
@@ -111,8 +112,13 @@ function TalentViewer:ResetTree()
111112 talentFrame :UpdateClassVisuals ();
112113 talentFrame :UpdateSpecBackground ();
113114 talentFrame :UpdateLevelingBuildHighlights ();
114- self :ClearLevelingBuild ();
115- self :StartRecordingLevelingBuild ();
115+ local isRecordingLevelingBuild = self :IsRecordingLevelingBuild ();
116+ if not lockLevelingBuild then
117+ self :ClearLevelingBuild ();
118+ if isRecordingLevelingBuild then
119+ self :StartRecordingLevelingBuild ();
120+ end
121+ end
116122end
117123
118124function TalentViewer :GetActiveRank (nodeID )
@@ -273,14 +279,15 @@ function TalentViewer:ToggleTalentView()
273279end
274280
275281function TalentViewer :InitFrame ()
276- if self .frameInitialized then return end
277- self .frameInitialized = true
278- UpdateScaleForFit (TalentViewer_DF , 200 , 270 )
279- table.insert (UISpecialFrames , ' TalentViewer_DF' )
280- TalentViewer_DFInset :Hide ()
281- self :InitDropDown ()
282- self :InitCheckbox ()
283- self :InitSpecSelection ()
282+ if self .frameInitialized then return ; end
283+ self .frameInitialized = true ;
284+ UpdateScaleForFit (TalentViewer_DF , 200 , 270 );
285+ table.insert (UISpecialFrames , ' TalentViewer_DF' );
286+ TalentViewer_DFInset :Hide ();
287+ self :InitDropDown ();
288+ self :InitCheckbox ();
289+ self :InitSpecSelection ();
290+ self :InitLevelingBuildUIs ();
284291end
285292
286293function TalentViewer :SelectSpec (classId , specId )
@@ -434,26 +441,36 @@ end
434441--- @param buildID number
435442--- @return nil | TalentViewer_LevelingBuildEntry[]
436443function TalentViewer :GetLevelingBuild (buildID )
437- return self .levelingBuilds [buildID ] or nil ;
444+ return self .levelingBuilds [self . selectedSpecId ] and self . levelingBuilds [ self . selectedSpecId ][ buildID ] or nil ;
438445end
439446
440- function TalentViewer :ApplyLevelingBuild (buildID , level )
447+ --- @param lockLevelingBuild boolean # by default, a new leveling build is created and activated when this function is called, passing true will prevent that
448+ function TalentViewer :ApplyLevelingBuild (buildID , level , lockLevelingBuild )
441449 local buildEntries = self :GetLevelingBuild (buildID );
442- if (not buildEntries or not next ( buildEntries ) ) then
450+ if (not buildEntries ) then
443451 return ;
444452 end
445453
446- self .recordingInfo .active = false ; -- todo: fix
447-
454+ self .recordingInfo .buildID = buildID ;
455+ self . recordingInfo . active = false ;
448456 self :GetTalentFrame ():SetLevelingBuildID (buildID );
449- self :GetTalentFrame ():ApplyLevelingBuild (level );
457+ self :GetTalentFrame ():ApplyLevelingBuild (level , lockLevelingBuild );
450458 self .recordingInfo .active = true ;
451459end
452460
461+ --- @param buildEntries TalentViewer_LevelingBuildEntry[]
462+ function TalentViewer :ImportLevelingBuild (buildEntries )
463+ self :ClearLevelingBuild ();
464+ for _ , entry in ipairs (buildEntries ) do
465+ self :RecordLevelingEntry (entry .nodeID , entry .targetRank , entry .entryID );
466+ end
467+ end
468+
453469function TalentViewer :StartRecordingLevelingBuild ()
454470 self .recordingInfo .active = true ;
455471 self :GetTalentFrame ().StartRecordingButton :Hide ();
456472 self :GetTalentFrame ().StopRecordingButton :Show ();
473+ self :ApplyLevelingBuild (self :GetCurrentLevelingBuildID (), ns .MAX_LEVEL , true );
457474end
458475
459476function TalentViewer :StopRecordingLevelingBuild ()
@@ -467,9 +484,11 @@ function TalentViewer:ClearLevelingBuild()
467484 button :SetOrder ({});
468485 end
469486 self .recordingInfo = CopyTable (defaultRecordingInfo );
470- self :StopRecordingLevelingBuild ();
471- table.insert (self .levelingBuilds , self .recordingInfo .entries );
472- self .recordingInfo .buildID = # self .levelingBuilds ;
487+ self .levelingBuilds [self .selectedSpecId ] = self .levelingBuilds [self .selectedSpecId ] or {};
488+ table.insert (self .levelingBuilds [self .selectedSpecId ], self .recordingInfo .entries );
489+ self .recordingInfo .buildID = # self .levelingBuilds [self .selectedSpecId ];
490+
491+ self :GetTalentFrame ():SetLevelingBuildID (self .recordingInfo .buildID );
473492end
474493
475494function TalentViewer :IsRecordingLevelingBuild ()
@@ -514,6 +533,96 @@ function TalentViewer:UpdateRecordedLevelingChoiceEntry(nodeID, entryID)
514533 end
515534end
516535
536+ function TalentViewer :InitLevelingBuildUIs ()
537+ local slider = self :GetTalentFrame ().LevelingBuildLevelSlider ;
538+ local minValue = 9 ;
539+ local maxValue = ns .MAX_LEVEL ;
540+ local steps = maxValue - minValue ;
541+ local formatters = {
542+ [MinimalSliderWithSteppersMixin .Label .Left ] = function () return L [' Level' ] end ,
543+ [MinimalSliderWithSteppersMixin .Label .Right ] = function (value ) return value end ,
544+ };
545+ local currentValue = 9 ;
546+ slider :Init (currentValue , minValue , maxValue , steps , formatters );
547+ slider :RegisterCallback (MinimalSliderWithSteppersMixin .Event .OnValueChanged , function (_ , value )
548+ if value ~= currentValue then
549+ currentValue = value ;
550+ self :ApplyLevelingBuild (self :GetCurrentLevelingBuildID (), value , true );
551+ self :StopRecordingLevelingBuild ();
552+ end
553+ end );
554+ slider :RegisterCallback (MinimalSliderWithSteppersMixin .Event .OnInteractStart , function (_ , value )
555+ GameTooltip :SetOwner (slider , " ANCHOR_RIGHT" , 0 , 0 );
556+ GameTooltip :SetText (L [' Leveling build' ]);
557+ GameTooltip :AddLine (L [' Select the level to apply the leveling build to' ]);
558+ GameTooltip :AddLine (L [' This will lag out your game!' ]);
559+ GameTooltip :Show ();
560+ end );
561+ slider :RegisterCallback (MinimalSliderWithSteppersMixin .Event .OnInteractEnd , function (_ , value )
562+ GameTooltip :Hide ();
563+ end );
564+
565+ local dropDownButton = self :GetTalentFrame ().LevelingBuildDropDownButton ;
566+ dropDownButton :HookScript (' OnEnter' , function (self )
567+ GameTooltip :SetOwner (self , " ANCHOR_RIGHT" , 0 , 0 );
568+ GameTooltip :SetText (L [' Leveling build' ]);
569+ GameTooltip :AddLine (L [' Select a leveling build to apply' ]);
570+ GameTooltip :AddLine (L [' This will reset your current talent choices!' ]);
571+ GameTooltip :Show ();
572+ end );
573+
574+ local dropDown = LibDD :Create_UIDropDownMenu (nil , TalentViewer_DF );
575+
576+ dropDownButton = Mixin (dropDownButton , DropDownToggleButtonMixin );
577+ dropDownButton :OnLoad_Intrinsic ();
578+ local function buildMenu ()
579+ self .menuListLevelingBuilds = {};
580+ local menu = self .menuListLevelingBuilds ;
581+ table.insert (menu , {
582+ text = ' Leveling builds can be saved and loaded with TalentLoadoutManager' ,
583+ notClickable = true ,
584+ notCheckable = true ,
585+ });
586+ table.insert (menu , {
587+ text = ' You can also export/import leveling builds, or link them in chat' ,
588+ notClickable = true ,
589+ notCheckable = true ,
590+ });
591+ if (not IsAddOnLoaded (' TalentLoadoutManager' )) then
592+ table.insert (menu , {
593+ text = ' Click to download TalentLoadoutManager' ,
594+ notCheckable = true ,
595+ func = function ()
596+ StaticPopup_Show (" TalentViewerExportDialog" , nil , nil , ' https://www.curseforge.com/wow/addons/talent-loadout-manager' );
597+ end ,
598+ });
599+ end
600+ for buildID , buildEntries in ipairs (self .levelingBuilds [self .selectedSpecId ] or {}) do
601+ table.insert (menu , {
602+ text = string.format (
603+ ' Leveling build %d (%d points spent)' ,
604+ buildID ,
605+ # buildEntries
606+ ),
607+ func = function (_ , buildID )
608+ self :ApplyLevelingBuild (buildID , currentValue , true );
609+ self :StopRecordingLevelingBuild ();
610+ end ,
611+ checked = self :GetCurrentLevelingBuildID () == buildID ,
612+ arg1 = buildID ,
613+ });
614+ end
615+ end
616+ dropDownButton :SetScript (' OnMouseDown' , function (self )
617+ buildMenu ();
618+ LibDD :ToggleDropDownMenu (1 , nil , dropDown , self , 5 , 0 , TalentViewer .menuListLevelingBuilds or nil );
619+ end )
620+
621+ dropDown :Hide ();
622+ buildMenu ();
623+ LibDD :EasyMenu (self .menuListLevelingBuilds , dropDown , dropDown , 0 , 0 );
624+ end
625+
517626---- ---------------------
518627--- Button highlights ---
519628---- ---------------------
0 commit comments