@@ -111,6 +111,8 @@ function TalentViewer:ResetTree()
111111 talentFrame :UpdateClassVisuals ();
112112 talentFrame :UpdateSpecBackground ();
113113 talentFrame :UpdateLevelingBuildHighlights ();
114+ self :ClearLevelingBuild ();
115+ self :StartRecordingLevelingBuild ();
114116end
115117
116118function TalentViewer :GetActiveRank (nodeID )
@@ -137,18 +139,40 @@ end
137139function TalentViewer :PurchaseRank (nodeID )
138140 self :ReduceCurrency (nodeID )
139141 self .purchasedRanks [nodeID ] = (self .purchasedRanks [nodeID ] or 0 ) + 1
142+
143+ if self :IsRecordingLevelingBuild () then
144+ self :RecordLevelingEntry (nodeID , self .purchasedRanks [nodeID ])
145+ end
140146end
141147
142148function TalentViewer :RefundRank (nodeID )
143149 self :RestoreCurrency (nodeID )
144150 self .purchasedRanks [nodeID ] = (self .purchasedRanks [nodeID ] or 0 ) - 1
151+
152+ if self :IsRecordingLevelingBuild () then
153+ self :RemoveLastRecordedLevelingEntry (nodeID )
154+ end
145155end
146156
147157function TalentViewer :SetSelection (nodeID , entryID )
148- if (entryID and not self .selectedEntries [nodeID ]) then
158+ local hasPreviousSelection = self .selectedEntries [nodeID ] ~= nil
159+
160+ if (entryID and hasPreviousSelection and entryID ~= self .selectedEntries [nodeID ]) then
161+ if self :IsRecordingLevelingBuild () then
162+ self :UpdateRecordedLevelingChoiceEntry (nodeID , entryID )
163+ end
164+ elseif (entryID and not hasPreviousSelection ) then
149165 self :ReduceCurrency (nodeID )
150- elseif (not entryID and self .selectedEntries [nodeID ]) then
166+
167+ if self :IsRecordingLevelingBuild () then
168+ self :RecordLevelingEntry (nodeID , 1 , entryID )
169+ end
170+ elseif (not entryID and hasPreviousSelection ) then
151171 self :RestoreCurrency (nodeID )
172+
173+ if self :IsRecordingLevelingBuild () then
174+ self :RemoveLastRecordedLevelingEntry (nodeID )
175+ end
152176 end
153177
154178 self .selectedEntries [nodeID ] = entryID
@@ -393,13 +417,101 @@ end
393417---- -------------------
394418--- Leveling builds ---
395419---- -------------------
420+ local defaultRecordingInfo = {
421+ active = true ,
422+ buildID = 0 , -- matches #levelingBuilds, effectively an auto increment
423+ currentIndex = 0 ,
424+ entries = {},
425+ }
426+ --- @type table<number , TalentViewer_LevelingBuildEntry[]> # [buildID] = entries
427+ TalentViewer .levelingBuilds = {};
428+ TalentViewer .recordingInfo = CreateFromMixins (defaultRecordingInfo );
429+
430+ function TalentViewer :GetCurrentLevelingBuildID ()
431+ return self .recordingInfo .buildID ;
432+ end
433+
434+ --- @param buildID number
435+ --- @return nil | TalentViewer_LevelingBuildEntry[]
396436function TalentViewer :GetLevelingBuild (buildID )
397- return ; -- TODO
437+ return self . levelingBuilds [ buildID ] or nil ;
398438end
399439
400440function TalentViewer :ApplyLevelingBuild (buildID , level )
401- self :GetTalentFrame ():SetLevelingBuildID (buildID )
402- self :GetTalentFrame ():ApplyLevelingBuild (level )
441+ local buildEntries = self :GetLevelingBuild (buildID );
442+ if (not buildEntries or not next (buildEntries )) then
443+ return ;
444+ end
445+
446+ self .recordingInfo .active = false ; -- todo: fix
447+
448+ self :GetTalentFrame ():SetLevelingBuildID (buildID );
449+ self :GetTalentFrame ():ApplyLevelingBuild (level );
450+ self .recordingInfo .active = true ;
451+ end
452+
453+ function TalentViewer :StartRecordingLevelingBuild ()
454+ self .recordingInfo .active = true ;
455+ self :GetTalentFrame ().StartRecordingButton :Hide ();
456+ self :GetTalentFrame ().StopRecordingButton :Show ();
457+ end
458+
459+ function TalentViewer :StopRecordingLevelingBuild ()
460+ self .recordingInfo .active = false ;
461+ self :GetTalentFrame ().StartRecordingButton :Show ();
462+ self :GetTalentFrame ().StopRecordingButton :Hide ();
463+ end
464+
465+ function TalentViewer :ClearLevelingBuild ()
466+ for _ , button in ipairs (self :GetTalentFrame ().levelingOrderButtons ) do
467+ button :SetOrder ({});
468+ end
469+ self .recordingInfo = CopyTable (defaultRecordingInfo );
470+ self :StopRecordingLevelingBuild ();
471+ table.insert (self .levelingBuilds , self .recordingInfo .entries );
472+ self .recordingInfo .buildID = # self .levelingBuilds ;
473+ end
474+
475+ function TalentViewer :IsRecordingLevelingBuild ()
476+ return self .recordingInfo .active ;
477+ end
478+
479+ --- @param nodeID number
480+ --- @param targetRank number
481+ --- @param entryID ? number
482+ function TalentViewer :RecordLevelingEntry (nodeID , targetRank , entryID )
483+ local currentIndex = self .recordingInfo .currentIndex + 1 ;
484+ self .recordingInfo .entries [currentIndex ] = {
485+ nodeID = nodeID ,
486+ targetRank = targetRank ,
487+ entryID = entryID ,
488+ };
489+ self .recordingInfo .currentIndex = currentIndex ;
490+
491+ self :GetTalentFrame ():GetTalentButtonByNodeID (nodeID ).LevelingOrder :AppendToOrder (currentIndex );
492+ end
493+
494+ function TalentViewer :RemoveLastRecordedLevelingEntry (nodeID )
495+ local currentIndex = self .recordingInfo .currentIndex ;
496+ for i = currentIndex , 1 , - 1 do
497+ local entry = self .recordingInfo .entries [i ];
498+ if (entry .nodeID == nodeID ) then
499+ table.remove (self .recordingInfo .entries , i );
500+ self .recordingInfo .currentIndex = i - 1 ;
501+ return ;
502+ end
503+ end
504+ end
505+
506+ function TalentViewer :UpdateRecordedLevelingChoiceEntry (nodeID , entryID )
507+ local currentIndex = self .recordingInfo .currentIndex ;
508+ for i = currentIndex , 1 , - 1 do
509+ local entry = self .recordingInfo .entries [i ];
510+ if (entry .nodeID == nodeID ) then
511+ entry .entryID = entryID ;
512+ return ;
513+ end
514+ end
403515end
404516
405517---- ---------------------
0 commit comments