Skip to content

Commit

Permalink
Add separate window to display map data (Live visualizer) (#46)
Browse files Browse the repository at this point in the history
* Add: ability to calculate only specific part of beatmap in PpCalculator

* Misc: Move BeatmapHelpers to Types project

* Misc: Expose map Length & backgroundFile props in WorkingBeatmap

* Add: LiveVisualizer plugin
thanks to BlackShark for sharing his UI

* Misc: make time token available outside of play mode

* Fix: ppCalculator crashing when map has too few objects

* Misc: allow tokens to be Reset to their default value

* Fix: Live tokens not respecting "Clear live tokens after finishing playing" setting
  • Loading branch information
Piotrekol authored Mar 5, 2019
1 parent ad3cc75 commit a49bf39
Show file tree
Hide file tree
Showing 35 changed files with 3,196 additions and 44 deletions.
33 changes: 31 additions & 2 deletions PpCalculator/PpCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public abstract class PpCalculator

public virtual int Score { get; set; }

private string[] _Mods { get; set; } = { "--" };
private string[] _Mods { get; set; } = null;

public virtual string[] Mods
{
Expand Down Expand Up @@ -57,6 +57,26 @@ public void PreProcess(ProcessorWorkingBeatmap workingBeatmap)
protected string LastMods { get; set; } = null;
protected bool ResetPerformanceCalculator { get; set; }

public double Calculate(double startTime, double endTime = double.NaN, Dictionary<string, double> categoryAttribs = null)
{

var orginalWorkingBeatmap = WorkingBeatmap;
var tempMap = new Beatmap();
tempMap.HitObjects.AddRange(WorkingBeatmap.Beatmap.HitObjects.Where(h => h.StartTime >= startTime && h.StartTime <= endTime));
tempMap.ControlPointInfo = WorkingBeatmap.Beatmap.ControlPointInfo;
tempMap.BeatmapInfo = WorkingBeatmap.BeatmapInfo;

WorkingBeatmap = new ProcessorWorkingBeatmap(tempMap);

ResetPerformanceCalculator = true;
var result = Calculate(null, categoryAttribs);

WorkingBeatmap = orginalWorkingBeatmap;

ResetPerformanceCalculator = true;

return result;
}

public double Calculate(double? time = null, Dictionary<string, double> categoryAttribs = null)
{
Expand Down Expand Up @@ -107,7 +127,16 @@ public double Calculate(double? time = null, Dictionary<string, double> category
if (time.HasValue)
pp = PerformanceCalculator.Calculate(time.Value, categoryAttribs);
else
pp = PerformanceCalculator.Calculate(categoryAttribs);
{
try
{
pp = PerformanceCalculator.Calculate(categoryAttribs);
}
catch (InvalidOperationException)
{
pp = -1;
}
}

return pp;
}
Expand Down
10 changes: 7 additions & 3 deletions PpCalculator/ProcessorWorkingBeatmap.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.IO;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
Expand All @@ -12,6 +10,9 @@
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko;
using System;
using System.IO;
using System.Linq;

namespace PpCalculator
{
Expand All @@ -22,6 +23,9 @@ public class ProcessorWorkingBeatmap : WorkingBeatmap
{
private readonly Beatmap beatmap;
public int RulesetID => beatmap.BeatmapInfo.RulesetID;
public double Length => beatmap.HitObjects.Any() ? beatmap.HitObjects.Last().StartTime : 0;

public string BackgroundFile => beatmap.Metadata.BackgroundFile;
/// <summary>
/// Constructs a new <see cref="ProcessorWorkingBeatmap"/> from a .osu file.
/// </summary>
Expand All @@ -32,7 +36,7 @@ public ProcessorWorkingBeatmap(string file, int? beatmapId = null)
{
}

private ProcessorWorkingBeatmap(Beatmap beatmap, int? beatmapId = null)
internal ProcessorWorkingBeatmap(Beatmap beatmap, int? beatmapId = null)
: base(beatmap.BeatmapInfo)
{
this.beatmap = beatmap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
using System.Diagnostics;
using System.IO;
using CollectionManager.DataTypes;
using StreamCompanionTypes;
using System.IO;
using StreamCompanionTypes.DataTypes;
using StreamCompanionTypes.Interfaces;
using Beatmap = StreamCompanionTypes.DataTypes.Beatmap;

namespace BeatmapPpReplacements
namespace StreamCompanionTypes
{
public static class BeatmapHelpers
{
Expand All @@ -32,5 +29,20 @@ public static string GetFullSongsLocation(ISettingsHandler settings)
}
return dir;
}

public static string FullOsuFileLocation(this Beatmap beatmap, ISettingsHandler settings)
{
return beatmap.FullOsuFileLocation(GetFullSongsLocation(settings));
}

public static bool IsValidBeatmap(this Beatmap beatmap, ISettingsHandler settings, out string fullFileLocation)
{
fullFileLocation = beatmap.FullOsuFileLocation(settings);

if (!File.Exists(fullFileLocation)) return false;
FileInfo file = new FileInfo(fullFileLocation);

return file.Length != 0;
}
}
}
9 changes: 8 additions & 1 deletion StreamCompanionTypes/DataTypes/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ public Token Clone()

public class TokenWithFormat : Token
{
public TokenWithFormat(object value, TokenType type = TokenType.Normal, string format = null) : base(value, type)
private readonly object _defaultValue;

public TokenWithFormat(object value, TokenType type = TokenType.Normal, string format = null, object defaultValue = null) : base(value, type)
{
_defaultValue = defaultValue;
Format = format;
Value = base.Value;
}
Expand All @@ -49,6 +52,10 @@ public TokenWithFormat(object value, TokenType type = TokenType.Normal, string f
}
}

public void Reset()
{
Value = _defaultValue;
}
public string Format { get; set; }
public string FormatedValue { get; set; }
}
Expand Down
1 change: 1 addition & 0 deletions StreamCompanionTypes/StreamCompanionTypes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BeatmapHelpers.cs" />
<Compile Include="DataTypes\Beatmap.cs" />
<Compile Include="DataTypes\ConfigEntry.cs" />
<Compile Include="DataTypes\Enums.cs" />
Expand Down
15 changes: 15 additions & 0 deletions osu!StreamCompanion.sln
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu", "submodules\osu\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{330603A4-F36B-4073-82D3-41A95A6D35B2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveVisualizer", "plugins\LiveVisualizer\LiveVisualizer.csproj", "{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -381,6 +383,18 @@ Global
{330603A4-F36B-4073-82D3-41A95A6D35B2}.Remote debug|Any CPU.Build.0 = Release|Any CPU
{330603A4-F36B-4073-82D3-41A95A6D35B2}.Remote debug|x86.ActiveCfg = Release|Any CPU
{330603A4-F36B-4073-82D3-41A95A6D35B2}.Remote debug|x86.Build.0 = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Debug|x86.ActiveCfg = Debug|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Debug|x86.Build.0 = Debug|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Release|Any CPU.Build.0 = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Release|x86.ActiveCfg = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Release|x86.Build.0 = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Remote debug|Any CPU.ActiveCfg = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Remote debug|Any CPU.Build.0 = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Remote debug|x86.ActiveCfg = Release|Any CPU
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86}.Remote debug|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -409,6 +423,7 @@ Global
{4CEEFDDB-FBDE-4E4A-BD01-019AD6E16EDF} = {DDE5F7B5-68C3-4143-8726-0BB91B83EED3}
{A86B0A57-2968-460A-982D-4251FF02498A} = {DDE5F7B5-68C3-4143-8726-0BB91B83EED3}
{330603A4-F36B-4073-82D3-41A95A6D35B2} = {DDE5F7B5-68C3-4143-8726-0BB91B83EED3}
{6FB20D7D-F84A-41DE-B086-DA920C7B5E86} = {7357CB17-E9D7-493F-BC1B-354F717D7AA3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {90CD718D-2503-4BBC-867D-E8EF9C9DBC77}
Expand Down
1 change: 1 addition & 0 deletions osu!StreamCompanion.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=LiveVisualizer_002EAnnotations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=osu_005FStreamCompanion_002EAnnotations/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
2 changes: 1 addition & 1 deletion osu!StreamCompanion/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace osu_StreamCompanion
{
static class Program
{
public static string ScVersion ="v180629.20";
public static string ScVersion ="v190301.18";
private static Initializer _initializer;
/// <summary>
/// The main entry point for the application.
Expand Down
1 change: 0 additions & 1 deletion plugins/BeatmapPpReplacements/BeatmapPpReplacements.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BeatmapHelpers.cs" />
<Compile Include="PpReplacements.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down
16 changes: 8 additions & 8 deletions plugins/BeatmapPpReplacements/PpReplacements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using StreamCompanionTypes.DataTypes;
using StreamCompanionTypes.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;

namespace BeatmapPpReplacements
Expand Down Expand Up @@ -75,13 +76,11 @@ public Tokens GetMapReplacements(MapSearchResult map)
{"m600 000PP", new Token(null)},
};

if (!map.FoundBeatmaps) return ret;
var mapLocation = map.BeatmapsFound[0].FullOsuFileLocation(BeatmapHelpers.GetFullSongsLocation(_settings));

if (!File.Exists(mapLocation)) return ret;
FileInfo file = new FileInfo(mapLocation);

if (file.Length == 0) return ret;
if (!map.FoundBeatmaps ||
!map.BeatmapsFound[0].IsValidBeatmap(_settings, out var mapLocation)
)
return ret;


var workingBeatmap = new ProcessorWorkingBeatmap(mapLocation);

Expand All @@ -104,6 +103,7 @@ public Tokens GetMapReplacements(MapSearchResult map)
Mods mods = Mods.Omod;



if (playMode == PlayMode.OsuMania)
{
ret["1 000 000PP"] = new TokenWithFormat(GetPp(_ppCalculator, 0, mods, 1_000_000), format: PpFormat);
Expand All @@ -123,7 +123,7 @@ public Tokens GetMapReplacements(MapSearchResult map)
ret["95PP"] = new TokenWithFormat(GetPp(_ppCalculator, 95d), format: PpFormat);
ret["90PP"] = new TokenWithFormat(GetPp(_ppCalculator, 90d), format: PpFormat);
}

ret["MaxCombo"] = new TokenWithFormat(_ppCalculator.GetMaxCombo());

string modsStr;
Expand Down
66 changes: 66 additions & 0 deletions plugins/LiveVisualizer/Chart.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<UserControl x:Class="LiveVisualizer.Chart"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:LiveVisualizer"
xmlns:wpf="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"

mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.Resources>
<Style TargetType="lvc:LineSeries">
<Setter Property="StrokeThickness" Value="0"></Setter>
<Setter Property="Stroke" Value="White"></Setter>
<Setter Property="Fill" Value="{Binding FillColor}"></Setter>
<Setter Property="PointGeometrySize" Value="0"></Setter>
<Setter Property="LineSmoothness" Value="1"></Setter>
</Style>
</Grid.Resources>
<wpf:CartesianChart Name="chart" Width="700" Hoverable="False" DataTooltip="{x:Null}" >

<wpf:CartesianChart.Series>
<lvc:LineSeries Name="LineSeries" Values="{Binding Strains}" PointGeometry="{x:Null}" Fill="{Binding ChartColor}" />

</wpf:CartesianChart.Series>
<wpf:CartesianChart.AxisX>
<wpf:Axis IsMerged="True" Foreground="Transparent">
<wpf:Axis.Separator>
<wpf:Separator StrokeThickness="1" StrokeDashArray="2" IsEnabled="False">
<!--Here, see the IsEnabled => false-->
<wpf:Separator.Stroke>
<SolidColorBrush Color="{Binding FillColor}" />
</wpf:Separator.Stroke>
</wpf:Separator>
</wpf:Axis.Separator>
</wpf:Axis>
</wpf:CartesianChart.AxisX>
<wpf:CartesianChart.AxisY>
<lvc:Axis IsMerged="True" MaxValue="{Binding MaxYValue}" MinValue="0">
<lvc:Axis.Style>
<Style TargetType="lvc:Axis">
<Style.Triggers>
<DataTrigger Binding="{Binding ShowAxisYSeparator}" Value="False">
<Setter Property="Foreground" Value="Transparent"></Setter>
</DataTrigger>
</Style.Triggers>
<Style.Setters>
<Setter Property="Foreground" Value="#FFFFFF"></Setter>
</Style.Setters>
</Style>
</lvc:Axis.Style>
<lvc:Axis.Separator>
<lvc:Separator Name="AxisYSeparator" StrokeThickness="1" StrokeDashArray="1" IsEnabled="{Binding ShowAxisYSeparator}" Step="{Binding AxisYStep}" >
<!--Here, see the IsEnabled => false-->
<lvc:Separator.Stroke>
<SolidColorBrush Color="{Binding AxisYSeparatorColor}" />
</lvc:Separator.Stroke>
</lvc:Separator>
</lvc:Axis.Separator>
</lvc:Axis>
</wpf:CartesianChart.AxisY>
</wpf:CartesianChart>
</Grid>
</UserControl>
39 changes: 39 additions & 0 deletions plugins/LiveVisualizer/Chart.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using LiveCharts;
using LiveCharts.Helpers;
using LiveCharts.Wpf;
using LiveVisualizer.Annotations;
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using System.Windows.Data;
using Separator = LiveCharts.Wpf.Separator;

namespace LiveVisualizer
{
/// <summary>
/// Interaction logic for Chart.xaml
/// </summary>
public partial class Chart : UserControl
{
public Chart(IWpfVisualizerData data, string bindingName, bool isProgressChart)
{
InitializeComponent();

var binding = new Binding(bindingName);
binding.Source = data;
LineSeries.SetBinding(Series.FillProperty, binding);

if (isProgressChart)
{ //Disable drawing of AxisY separator
binding = new Binding();
AxisYSeparator.SetBinding(Separator.IsEnabledProperty, binding);
AxisYSeparator.SetValue(Separator.StrokeThicknessProperty, 0d);
}

DataContext = data;
}

}
}
Loading

0 comments on commit a49bf39

Please sign in to comment.