@@ -92,6 +92,7 @@ public CrafterBuffs(StatusList? statuses)
9292
9393 private ILoadedTextureIcon ExpertBadge { get ; }
9494 private ILoadedTextureIcon CollectibleBadge { get ; }
95+ private ILoadedTextureIcon CosmicExplorationBadge { get ; }
9596 private ILoadedTextureIcon SplendorousBadge { get ; }
9697 private ILoadedTextureIcon SpecialistBadge { get ; }
9798 private ILoadedTextureIcon NoManipulationBadge { get ; }
@@ -116,7 +117,7 @@ public MacroEditor(CharacterStats characterStats, RecipeData recipeData, Crafter
116117 RecipeData = recipeData ;
117118 Buffs = buffs ;
118119 MacroSetter = setter ;
119- DefaultActions = actions . ToArray ( ) ;
120+ DefaultActions = [ .. actions ] ;
120121
121122 HQIngredientCounts = [ .. ingredientHqCounts ?? Enumerable . Repeat ( 0 , RecipeData . Ingredients . Count ) ] ;
122123
@@ -126,6 +127,7 @@ public MacroEditor(CharacterStats characterStats, RecipeData recipeData, Crafter
126127
127128 ExpertBadge = IconManager . GetAssemblyTexture ( "Graphics.expert_badge.png" ) ;
128129 CollectibleBadge = IconManager . GetAssemblyTexture ( "Graphics.collectible_badge.png" ) ;
130+ CosmicExplorationBadge = IconManager . GetIcon ( 60810 ) ;
129131 SplendorousBadge = IconManager . GetAssemblyTexture ( "Graphics.splendorous.png" ) ;
130132 SpecialistBadge = IconManager . GetAssemblyTexture ( "Graphics.specialist.png" ) ;
131133 NoManipulationBadge = IconManager . GetAssemblyTexture ( "Graphics.no_manip.png" ) ;
@@ -319,29 +321,18 @@ void DrawStat(string name, int value, Action<int> setter)
319321 ImGui . TableSetupColumn ( "col3" , ImGuiTableColumnFlags . WidthStretch , 2 ) ;
320322
321323 ImGui . TableNextColumn ( ) ;
322- var levelTextWidth = ImGui . CalcTextSize ( SqText . ToLevelString ( 100 ) ) . X + ImGui . GetStyle ( ) . FramePadding . X * 2 + 5 ;
323- ImGuiUtils . AlignCentered (
324- ImGui . CalcTextSize ( SqText . LevelPrefix . ToIconString ( ) ) . X + 5 +
325- levelTextWidth ) ;
324+ ImGuiUtils . AlignCentered ( GetLevelEntryWidth ( ) ) ;
326325
327- ImGui . AlignTextToFramePadding ( ) ;
328- ImGui . TextUnformatted ( SqText . LevelPrefix . ToIconString ( ) ) ;
329- ImGui . SameLine ( 0 , 3 ) ;
330- ImGui . SetNextItemWidth ( levelTextWidth ) ;
331- var levelText = SqText . ToLevelString ( CharacterStats . Level ) ;
332- bool textChanged ;
333- unsafe
334326 {
335- textChanged = ImGui . InputText ( "##levelText" , ref levelText , 12 , ImGuiInputTextFlags . CallbackCharFilter | ImGuiInputTextFlags . AutoSelectAll , LevelInputCallback ) ;
336- }
337- if ( textChanged )
338- CharacterStats = CharacterStats with
327+ var level = CharacterStats . Level ;
328+ if ( DrawLevelEntry ( ref level ) )
339329 {
340- Level =
341- SqText . TryParseLevelString ( levelText , out var newLevel )
342- ? Math . Clamp ( newLevel , 1 , 100 )
343- : 1
344- } ;
330+ CharacterStats = CharacterStats with
331+ {
332+ Level = level
333+ } ;
334+ }
335+ }
345336
346337 var disabledTint = new Vector4 ( 0.5f , 0.5f , 0.5f , 0.75f ) ;
347338 var imageButtonPadding = ( int ) ( ImGui . GetStyle ( ) . FramePadding . Y / 2f ) ;
@@ -576,19 +567,6 @@ void DrawStat(string name, int value, Action<int> setter)
576567 return oldStats != CharacterStats ;
577568 }
578569
579- private static unsafe int LevelInputCallback ( ImGuiInputTextCallbackData * data )
580- {
581- if ( data ->EventFlag == ImGuiInputTextFlags . CallbackCharFilter )
582- {
583- if ( SqText . LevelNumReplacements . TryGetValue ( ( char ) data ->EventChar , out var seChar ) )
584- data ->EventChar = seChar . ToIconChar ( ) ;
585- else
586- return 1 ;
587- }
588-
589- return 0 ;
590- }
591-
592570 private static string FormatItemBuff ( ( uint ItemId , bool IsHQ ) input )
593571 {
594572 if ( input . ItemId == 0 )
@@ -748,24 +726,39 @@ public bool Equals(RecipeWrapper other) =>
748726 private bool DrawRecipeParams ( )
749727 {
750728 var oldStartingQuality = StartingQuality ;
729+ var adjustedJobLevel = RecipeData . AdjustedJobLevel ;
751730
752731 ImGuiUtils . TextCentered ( "Recipe" ) ;
753732
754733 var textStars = new string ( '★' , RecipeData ! . Table . Stars ) ;
755734 var textStarsSize = Vector2 . Zero ;
756735 if ( ! string . IsNullOrEmpty ( textStars ) )
757736 textStarsSize = AxisFont . CalcTextSize ( textStars ) ;
758- var textLevel = SqText . LevelPrefix . ToIconChar ( ) + SqText . ToLevelString ( RecipeData . RecipeInfo . ClassJobLevel ) ;
737+
738+ string ? textLevel = null ;
739+ float textLevelSize ;
740+ if ( adjustedJobLevel is { } adjJobLevel )
741+ {
742+ textLevelSize = GetLevelEntryWidth ( ) ;
743+ }
744+ else
745+ {
746+ textLevel = SqText . LevelPrefix . ToIconChar ( ) + SqText . ToLevelString ( RecipeData . RecipeInfo . ClassJobLevel ) ;
747+ textLevelSize = ImGui . CalcTextSize ( textLevel ) . X ;
748+ }
749+
759750 var isExpert = RecipeData . RecipeInfo . IsExpert ;
760751 var isCollectable = RecipeData . IsCollectable ;
752+ var isAdjustable = RecipeData . AdjustedJobLevel . HasValue ;
761753 var imageSize = ImGui . GetFrameHeight ( ) ;
762754 var textSize = ImGui . GetFontSize ( ) ;
763755 var badgeSize = new Vector2 ( textSize * ( ExpertBadge . AspectRatio ?? 1 ) , textSize ) ;
764756 var badgeOffset = ( imageSize - badgeSize . Y ) / 2 ;
765757
766758 var rightSideWidth =
767- 5 + ImGui . CalcTextSize ( textLevel ) . X +
759+ 5 + textLevelSize +
768760 ( textStarsSize != Vector2 . Zero ? textStarsSize . X + 3 : 0 ) +
761+ ( isAdjustable ? imageSize + 3 : 0 ) +
769762 ( isCollectable ? badgeSize . X + 3 : 0 ) +
770763 ( isExpert ? badgeSize . X + 3 : 0 ) ;
771764 ImGui . AlignTextToFramePadding ( ) ;
@@ -818,8 +811,19 @@ private bool DrawRecipeParams()
818811 }
819812 }
820813
814+ ushort ? newAdjustedJobLevel = null ;
821815 ImGui . SameLine ( 0 , 5 ) ;
822- ImGui . TextUnformatted ( textLevel ) ;
816+ if ( adjustedJobLevel . HasValue )
817+ {
818+ var level = ( int ) adjustedJobLevel . Value ;
819+ if ( DrawLevelEntry ( ref level ) )
820+ {
821+ newAdjustedJobLevel = ( ushort ) level ;
822+ }
823+ }
824+ else {
825+ ImGui . TextUnformatted ( textLevel ) ;
826+ }
823827
824828 if ( textStarsSize != Vector2 . Zero )
825829 {
@@ -830,6 +834,14 @@ private bool DrawRecipeParams()
830834 AxisFont . Text ( textStars ) ;
831835 }
832836
837+ if ( isAdjustable )
838+ {
839+ ImGui . SameLine ( 0 , 3 ) ;
840+ ImGui . Image ( CosmicExplorationBadge . ImGuiHandle , new ( imageSize ) ) ;
841+ if ( ImGui . IsItemHovered ( ) )
842+ ImGuiUtils . Tooltip ( $ "Cosmic Exploration") ;
843+ }
844+
833845 if ( isCollectable )
834846 {
835847 ImGui . SameLine ( 0 , 3 ) ;
@@ -907,15 +919,26 @@ private bool DrawRecipeParams()
907919 }
908920 }
909921
922+ var modified = false ;
923+
924+ if ( newAdjustedJobLevel is { } jobLevel )
925+ {
926+ RecipeData = new ( ( ushort ) RecipeData . Recipe . RowId , jobLevel ) ;
927+ modified = true ;
928+ }
929+
910930 if ( newRecipe is { } recipeId )
911931 {
912- RecipeData = new ( recipeId ) ;
932+ RecipeData = new ( recipeId , RecipeData . AdjustedJobLevel ) ;
913933 HQIngredientCounts . Clear ( ) ;
914934 HQIngredientCounts . AddRange ( Enumerable . Repeat ( 0 , RecipeData . Ingredients . Count ) ) ;
915- return true ;
935+ modified = true ;
916936 }
917937
918- return oldStartingQuality != StartingQuality ;
938+ if ( oldStartingQuality != StartingQuality )
939+ modified = true ;
940+
941+ return modified ;
919942 }
920943
921944 private void DrawIngredientHQEntry ( int idx )
@@ -973,6 +996,54 @@ private void DrawIngredientHQEntry(int idx)
973996 ImGuiUtils . TextCentered ( $ "{ ingredient . Amount } ") ;
974997 }
975998
999+ private const int MAX_LEVEL = 100 ;
1000+ private float GetLevelEntryWidth ( )
1001+ {
1002+ var levelTextWidth = ImGui . CalcTextSize ( SqText . ToLevelString ( MAX_LEVEL ) ) . X + ImGui . GetStyle ( ) . FramePadding . X * 2 + 5 ;
1003+ return ImGui . CalcTextSize ( SqText . LevelPrefix . ToIconString ( ) ) . X + 5 + levelTextWidth ;
1004+ }
1005+
1006+ private bool DrawLevelEntry ( ref int level )
1007+ {
1008+ static unsafe int LevelInputCallback ( ImGuiInputTextCallbackData * data )
1009+ {
1010+ if ( data ->EventFlag == ImGuiInputTextFlags . CallbackCharFilter )
1011+ {
1012+ if ( SqText . LevelNumReplacements . TryGetValue ( ( char ) data ->EventChar , out var seChar ) )
1013+ data ->EventChar = seChar . ToIconChar ( ) ;
1014+ else
1015+ return 1 ;
1016+ }
1017+
1018+ return 0 ;
1019+ }
1020+
1021+ var levelTextWidth = ImGui . CalcTextSize ( SqText . ToLevelString ( MAX_LEVEL ) ) . X + ImGui . GetStyle ( ) . FramePadding . X * 2 + 5 ;
1022+
1023+ ImGui . AlignTextToFramePadding ( ) ;
1024+ ImGui . TextUnformatted ( SqText . LevelPrefix . ToIconString ( ) ) ;
1025+ ImGui . SameLine ( 0 , 3 ) ;
1026+ ImGui . SetNextItemWidth ( levelTextWidth ) ;
1027+ var levelText = SqText . ToLevelString ( level ) ;
1028+ bool textChanged ;
1029+ unsafe
1030+ {
1031+ textChanged = ImGui . InputText ( "##levelText" , ref levelText , 12 , ImGuiInputTextFlags . CallbackCharFilter | ImGuiInputTextFlags . AutoSelectAll , LevelInputCallback ) ;
1032+ }
1033+ if ( textChanged )
1034+ {
1035+ var newLevel = SqText . TryParseLevelString ( levelText , out var lv )
1036+ ? Math . Clamp ( lv , 1 , MAX_LEVEL )
1037+ : 1 ;
1038+ if ( newLevel != level )
1039+ {
1040+ level = newLevel ;
1041+ return true ;
1042+ }
1043+ }
1044+ return false ;
1045+ }
1046+
9761047 private void DrawActionHotbars ( )
9771048 {
9781049 var sim = CreateSim ( State ) ;
@@ -1657,6 +1728,7 @@ public void Dispose()
16571728
16581729 ExpertBadge . Dispose ( ) ;
16591730 CollectibleBadge . Dispose ( ) ;
1731+ CosmicExplorationBadge . Dispose ( ) ;
16601732 SplendorousBadge . Dispose ( ) ;
16611733 SpecialistBadge . Dispose ( ) ;
16621734 NoManipulationBadge . Dispose ( ) ;
0 commit comments