Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c6e3b0f
集成 ba-click-fx 特效渲染器
CialloKing Jul 25, 2026
a367fc7
修复 vendor 哈希在 CI 中不一致
CialloKing Jul 25, 2026
7c1f536
同步 ba-click-fx v1.2.11 产物
CialloKing Jul 27, 2026
9d66440
保持强制取消即时清理轨迹
CialloKing Jul 27, 2026
49c1aaf
固定浅色背景兼容轮廓参数
CialloKing Jul 27, 2026
3ca52f7
同步 ba-click-fx v1.2.15 产物
CialloKing Jul 30, 2026
b209988
适配透明桌面完整渲染后端
CialloKing Jul 30, 2026
563368e
同步 ba-click-fx v1.2.16 产物
CialloKing Jul 31, 2026
557bad1
同步 ba-click-fx v1.2.19 产物
CialloKing Aug 1, 2026
8b9b019
默认启用DOM Add合成
CialloKing Aug 1, 2026
fa7d971
同步上游主仓库更新
CialloKing Aug 2, 2026
4014e0c
同步本地上游宿主合成产物
CialloKing Aug 2, 2026
f0f8266
接入透明窗口合成状态合同
CialloKing Aug 2, 2026
d1cfb15
同步 ba-click-fx v1.2.20 产物
CialloKing Aug 2, 2026
446c823
同步 ba-click-fx v1.2.21 产物
CialloKing Aug 2, 2026
ee7195c
同步 ba-click-fx v1.2.23 产物
CialloKing Aug 8, 2026
747c8d8
切换宿主合成为 DOM Add 近似
CialloKing Aug 8, 2026
3b6c16a
启用浅色背景透明合成配置
CialloKing Aug 8, 2026
9846990
同步 ba-click-fx v1.2.25 产物
CialloKing Aug 11, 2026
51fd20b
默认使用相对 OKLCH 主题颜色
CialloKing Aug 11, 2026
9af4ff7
接入输入采样率运行时 API
CialloKing Aug 11, 2026
f7423d0
对齐输入采样率宿主配置
CialloKing Aug 11, 2026
4be05af
更新颜色与采样率使用说明
CialloKing Aug 11, 2026
b9c96b9
收紧采样率宿主类型边界
CialloKing Aug 11, 2026
0bcedfe
统一输入采样率回退文案
CialloKing Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
*.iss linguist-vendored=true
*.isl linguist-vendored=true
*.py linguist-vendored=true

# Preserve the reviewed vendor artifact byte-for-byte on Windows and Unix.
src/Web/vendor/ba-click-fx.iife.js -text
9 changes: 9 additions & 0 deletions .github/workflows/pr-build-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ jobs:
with:
dotnet-version: '8.0.x'

- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Run Web tests
shell: pwsh
run: node --test tests/Web/fx-adapter.test.mjs tests/Web/vendor-contract.test.mjs

- name: Run tests
shell: pwsh
run: dotnet test BASpark.sln -c Release --verbosity normal
Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ jobs:
with:
dotnet-version: '8.0.x'

- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Run Web tests
shell: pwsh
run: node --test tests/Web/fx-adapter.test.mjs tests/Web/vendor-contract.test.mjs

- name: Run .NET tests
shell: pwsh
run: dotnet test BASpark.sln -c Release --verbosity normal

- name: Build Packaged Files
shell: pwsh
run: |
Expand Down Expand Up @@ -61,4 +74,4 @@ jobs:
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 3 additions & 3 deletions pages/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ In the "Visual Performance" sub-settings menu, you can adjust the following para
* **Global Opacity**: Adjusts the overall visual intensity and transparency of the effects.
* **Animation Speed**: Adjusts the overall playback speed of the effects.
* **Speed Synchronization**: Enabled by default. Unchecking this allows you to independently adjust "Click Speed" and "Trail Speed".
* **Trail Refresh Rate**: Supports up to 240Hz. Higher values offer smoother paths but consume relatively more system resources.
* **Input Sampling Rate Limit**: Accepts `0` (unlimited) or `1`–`1000Hz`, with a default of `40Hz`. Lower rates retain fewer pointer samples and create more angular paths; this setting is independent of animation speed and rendering frame rate.

### Theme Colors
Click the **"Change Color"** button to bring up the color palette and customize the core color of the particles.
Click the **"Change Color"** button to bring up the color palette and customize the effect theme. BASpark uses the recommended relative OKLCH mapping so hue, chroma, and perceptual lightness are adjusted before HDR and Bloom processing.

### Reset to Default
Click the **"Restore Default Settings"** button to selectively reset items to their default values.
Expand Down Expand Up @@ -119,4 +119,4 @@ No need to visit the website manually. In the **"About"** page of the software,
* **Auto Comparison**: The system automatically detects version discrepancies between your local build and the server.
* **One-Click Upgrade**: Provides automatic pop-up notifications containing update changelogs when a new version is detected.

*Note: The automatic update feature requires an internet connection. Data fetching might fail under strict firewall environments.*
*Note: The automatic update feature requires an internet connection. Data fetching might fail under strict firewall environments.*
4 changes: 2 additions & 2 deletions pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ features:
- title: 🧠 Smart Environment Filter
details: Context-aware detection that auto-pauses in full-screen games/videos. Supports customizable Blacklist and Whitelist modes.
- title: 🎨 Precise Visual Tuning
details: Fully customize scale ratio, opacity, animation speed, and trail refresh rates (up to 240Hz) via sliders or precise inputs.
details: Fully customize scale, opacity, animation speed, theme color, and input sampling rates from unlimited through 1000Hz.
- title: 🖥️ Multi-Screen Management
details: Intelligent monitor hardware ID memory. Independently toggle effects for each screen with dynamic topology refresh.
- title: 🌐 Global Optimization
details: Built-in network source selection (Mainland China / Global) ensures stable cloud notices and one-click auto-updates worldwide.
---
---
2 changes: 2 additions & 0 deletions src/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Runtime.CompilerServices;
using System.Windows;

[assembly: InternalsVisibleTo("BASpark.Tests")]
[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
Expand Down
16 changes: 15 additions & 1 deletion src/BASpark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,21 @@
<ItemGroup>
<Resource Include="app.ico" />
<Resource Include="Web\index.html" />
<Resource Include="Web\index.legacy.html" />
<Resource Include="Web\fx-adapter.js" />
<Resource Include="Web\vendor\ba-click-fx.iife.js" />
</ItemGroup>

<ItemGroup>
<None Update="licenses\ba-click-fx\LICENSE"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
<None Update="licenses\ba-click-fx\THIRD_PARTY_NOTICES.md"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
<None Update="licenses\ba-click-fx\VERSION.txt"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>

</Project>
</Project>
29 changes: 23 additions & 6 deletions src/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum VisualAppearanceResetFlags
EffectScale = 1 << 0,
EffectOpacity = 1 << 1,
UnifiedAnimationSpeed = 1 << 2,
TrailRefreshRate = 1 << 3,
InputSamplingRate = 1 << 3,
ParticleColor = 1 << 4,
TrailAnimationSpeed = 1 << 5,
ClickAnimationSpeed = 1 << 6
Expand Down Expand Up @@ -61,6 +61,9 @@ public class ScreenSelectionState
public static class ConfigManager
{
private const string RegPath = @"Software\BASpark";
public const int DefaultInputSamplingRate = 40;
public const int MinimumInputSamplingRate = 0;
public const int MaximumInputSamplingRate = 1000;

public static string ParticleColor { get; set; } = "45,175,255";
public static bool IsEffectEnabled { get; set; } = true;
Expand All @@ -79,7 +82,7 @@ public static class ConfigManager
public static bool ApplyCurveDraw { get; set; } = false;
public static double TrailAnimationSpeed { get; set; } = 1.0;
public static double ClickAnimationSpeed { get; set; } = 1.0;
public static int TrailRefreshRate { get; set; } = 40;
public static int InputSamplingRate { get; set; } = DefaultInputSamplingRate;
public static bool EnableEnvironmentFilter { get; set; } = false;
public static bool HideInFullscreen { get; set; } = true;
public static bool ShowEffectOnDesktop { get; set; } = true;
Expand Down Expand Up @@ -141,7 +144,13 @@ public static void Load()
ApplyCurveDraw = Convert.ToBoolean(key.GetValue("ApplyCurveDraw", false));
TrailAnimationSpeed = Math.Clamp(Convert.ToDouble(key.GetValue("TrailAnimationSpeed", EffectSpeed), CultureInfo.InvariantCulture), 0.2, 3.0);
ClickAnimationSpeed = Math.Clamp(Convert.ToDouble(key.GetValue("ClickAnimationSpeed", EffectSpeed), CultureInfo.InvariantCulture), 0.2, 3.0);
TrailRefreshRate = Math.Clamp(Convert.ToInt32(key.GetValue("TrailRefreshRate", 40), CultureInfo.InvariantCulture), 10, 240);
object legacyInputSamplingRate = key.GetValue(
"TrailRefreshRate",
DefaultInputSamplingRate) ?? DefaultInputSamplingRate;
InputSamplingRate = NormalizeInputSamplingRate(
Convert.ToInt32(
key.GetValue("InputSamplingRate", legacyInputSamplingRate),
CultureInfo.InvariantCulture));
EnableEnvironmentFilter = Convert.ToBoolean(key.GetValue("EnableEnvironmentFilter", false));
HideInFullscreen = Convert.ToBoolean(key.GetValue("HideInFullscreen", true));
ShowEffectOnDesktop = Convert.ToBoolean(key.GetValue("ShowEffectOnDesktop", true));
Expand Down Expand Up @@ -262,6 +271,14 @@ public static NetworkRegionOption ParseNetworkRegion(string? raw)
return NetworkRegionOption.Auto;
}

public static int NormalizeInputSamplingRate(int rateHz)
{
return Math.Clamp(
rateHz,
MinimumInputSamplingRate,
MaximumInputSamplingRate);
}

public static void GetAnimationSpeedsForOverlay(out double trailSpeed, out double clickSpeed)
{
if (UseLinkedAnimationSpeed)
Expand Down Expand Up @@ -340,9 +357,9 @@ public static void ApplyVisualAppearanceDefaults(VisualAppearanceResetFlags flag
Save("ClickAnimationSpeed", 1.0);
}

if (flags.HasFlag(VisualAppearanceResetFlags.TrailRefreshRate))
if (flags.HasFlag(VisualAppearanceResetFlags.InputSamplingRate))
{
Save("TrailRefreshRate", 40);
Save("InputSamplingRate", DefaultInputSamplingRate);
}

if (flags.HasFlag(VisualAppearanceResetFlags.ParticleColor))
Expand Down Expand Up @@ -576,7 +593,7 @@ public static void ResetAndClear()
ApplyCurveDraw = false;
TrailAnimationSpeed = 1.0;
ClickAnimationSpeed = 1.0;
TrailRefreshRate = 40;
InputSamplingRate = DefaultInputSamplingRate;
EnableEnvironmentFilter = false;
HideInFullscreen = true;
ShowEffectOnDesktop = true;
Expand Down
16 changes: 9 additions & 7 deletions src/ControlPanelWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -522,11 +522,11 @@

<CheckBox Name="CheckLinkedAnimationSpeed" Content="拖尾与点击使用同一动画速度" Style="{StaticResource ToggleSwitch}" Margin="0,0,0,4"
Checked="LinkedAnimationSpeed_Changed" Unchecked="LinkedAnimationSpeed_Changed"/>
<TextBlock x:Name="TxtLinkedSpeedHint" Text="关闭此项后可单独加快或减慢拖尾衰减与移动粒子,而不影响点击波纹与爆发粒子,与下方「拖尾刷新率」不同。" FontSize="11" Foreground="#999" Margin="0,0,0,10" TextWrapping="Wrap"/>
<TextBlock x:Name="TxtLinkedSpeedHint" Text="关闭此项后可单独加快或减慢拖尾衰减与移动粒子,而不影响点击波纹与爆发粒子,与下方「输入采样率上限」不同。" FontSize="11" Foreground="#999" Margin="0,0,0,10" TextWrapping="Wrap"/>

<CheckBox Name="CheckApplyCurveDraw" Content="采用曲线拖尾" Style="{StaticResource ToggleSwitch}" Margin="0,0,0,4"
Checked="CurveDraw_Changed" Unchecked="CurveDraw_Changed"/>
<TextBlock x:Name="TxtCurveDrawHint" Text="建议在60Hz及以上刷新率开启" FontSize="11" Foreground="#999" Margin="0,0,0,10" TextWrapping="Wrap"/>
<TextBlock x:Name="TxtCurveDrawHint" Text="输入采样率为 60 Hz 及以上时建议开启" FontSize="11" Foreground="#999" Margin="0,0,0,10" TextWrapping="Wrap"/>

<StackPanel Name="PanelUnifiedAnimationSpeed" Margin="0,0,0,15">
<DockPanel LastChildFill="False">
Expand Down Expand Up @@ -582,19 +582,21 @@

<StackPanel Margin="0,0,0,15">
<DockPanel LastChildFill="False">
<TextBlock x:Name="TxtTrailRefresh" Text="拖尾刷新率" Foreground="#555" FontSize="13" VerticalAlignment="Center"/>
<TextBlock x:Name="TxtInputSamplingRate" Text="输入采样率上限" Foreground="#555" FontSize="13" VerticalAlignment="Center"/>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Right">
<TextBox Width="40" Height="20" FontSize="12" Foreground="#45AFFF" FontWeight="Bold"
<TextBox Width="48" Height="20" FontSize="12" Foreground="#45AFFF" FontWeight="Bold"
TextAlignment="Right" VerticalAlignment="Center"
BorderThickness="0,0,0,1" BorderBrush="#DDD" Background="Transparent"
Text="{Binding ElementName=SliderTrailRefresh, Path=Value, StringFormat={}{0:F0}, UpdateSourceTrigger=LostFocus}"
Text="{Binding ElementName=SliderInputSamplingRate, Path=Value, StringFormat={}{0:F0}, UpdateSourceTrigger=LostFocus}"
PreviewTextInput="NumberValidationTextBox" KeyDown="TextBox_KeyDown"
InputMethod.IsInputMethodEnabled="False"/>
<TextBlock Text=" Hz" Foreground="#999" FontSize="12" VerticalAlignment="Center" Margin="2,0,0,0"/>
</StackPanel>
</DockPanel>
<Slider Name="SliderTrailRefresh" Minimum="10" Maximum="240" TickFrequency="10" IsSnapToTickEnabled="True"
ValueChanged="EffectSlider_ValueChanged" Margin="0,5,0,0"/>
<Slider Name="SliderInputSamplingRate" Minimum="0" Maximum="1000" TickFrequency="1" IsSnapToTickEnabled="True"
SmallChange="1" LargeChange="10" ValueChanged="EffectSlider_ValueChanged" Margin="0,5,0,0"/>
<TextBlock x:Name="TxtInputSamplingRateHint" Text="0 表示不限频;较低值会形成更明显的折线拖尾。"
Foreground="#999" FontSize="11" TextWrapping="Wrap" Margin="0,4,0,0"/>
</StackPanel>

<Separator Background="#F0F2F5" Margin="0,2,0,12"/>
Expand Down
17 changes: 10 additions & 7 deletions src/ControlPanelWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@
SliderSpeed.Value = ConfigManager.EffectSpeed;
SliderTrailAnimSpeed.Value = ConfigManager.TrailAnimationSpeed;
SliderClickAnimSpeed.Value = ConfigManager.ClickAnimationSpeed;
SliderTrailRefresh.Value = ConfigManager.TrailRefreshRate;
SliderInputSamplingRate.Value = ConfigManager.InputSamplingRate;
UpdateAnimationSpeedPanelVisibility();

if (ConfigManager.ScrollbarVisibility == PanelScrollbarVisibility.Always)
Expand Down Expand Up @@ -1231,7 +1231,10 @@
VisualResetItems.Add(new VisualResetItem(VisualAppearanceResetFlags.UnifiedAnimationSpeed, Localization.Get("VisualReset_UnifiedSpeed"), Localization.Get("VisualReset_UnifiedSpeed_Sub")));
VisualResetItems.Add(new VisualResetItem(VisualAppearanceResetFlags.TrailAnimationSpeed, Localization.Get("VisualReset_TrailSpeed"), Localization.Get("VisualReset_TrailSpeed_Sub")));
VisualResetItems.Add(new VisualResetItem(VisualAppearanceResetFlags.ClickAnimationSpeed, Localization.Get("VisualReset_ClickSpeed"), Localization.Get("VisualReset_ClickSpeed_Sub")));
VisualResetItems.Add(new VisualResetItem(VisualAppearanceResetFlags.TrailRefreshRate, Localization.Get("VisualReset_TrailRefresh"), Localization.Get("VisualReset_TrailRefresh_Sub")));
VisualResetItems.Add(new VisualResetItem(
VisualAppearanceResetFlags.InputSamplingRate,
Localization.Get("VisualReset_InputSamplingRate"),
Localization.Get("VisualReset_InputSamplingRate_Sub")));
VisualResetItems.Add(new VisualResetItem(VisualAppearanceResetFlags.ParticleColor, Localization.Get("VisualReset_Color"), Localization.Get("VisualReset_Color_Sub")));
}

Expand Down Expand Up @@ -1311,13 +1314,13 @@
ConfigManager.ApplyVisualAppearanceDefaults(flags);
LoadSettings();

int trailRefreshRate = (int)Math.Round(SliderTrailRefresh.Value);
int inputSamplingRate = (int)Math.Round(SliderInputSamplingRate.Value);
ConfigManager.GetAnimationSpeedsForOverlay(out double trailSp, out double clickSp);
double effectScale = Math.Round(SliderScale.Value, 2);
double effectOpacity = Math.Round(SliderOpacity.Value / 100.0, 2);
App.Overlay?.UpdateColor(ConfigManager.ParticleColor);
App.Overlay?.UpdateEffectSettings(effectScale, effectOpacity, trailSp, clickSp);
App.Overlay?.UpdateTrailRefreshRate(trailRefreshRate);
App.Overlay?.UpdateInputSamplingRate(inputSamplingRate);
App.Overlay?.SetCurveDraw(CheckApplyCurveDraw.IsChecked ?? false);

VisualResetOverlay.Visibility = Visibility.Collapsed;
Expand Down Expand Up @@ -1378,7 +1381,7 @@
effectSpeedForRegistry = clickAnimSpeed;
}

int trailRefreshRate = (int)Math.Round(SliderTrailRefresh.Value);
int inputSamplingRate = (int)Math.Round(SliderInputSamplingRate.Value);
bool autoStartEnabled = CheckAutoStart.IsChecked ?? false;
bool startSilentEnabled = CheckStartSilent.IsChecked ?? false;
bool runAsAdminEnabled = CheckRunAsAdmin.IsChecked ?? false;
Expand Down Expand Up @@ -1409,7 +1412,7 @@
ConfigManager.Save("EffectSpeed", effectSpeedForRegistry);
ConfigManager.Save("TrailAnimationSpeed", trailAnimSpeed);
ConfigManager.Save("ClickAnimationSpeed", clickAnimSpeed);
ConfigManager.Save("TrailRefreshRate", trailRefreshRate);
ConfigManager.Save("InputSamplingRate", inputSamplingRate);
ConfigManager.Save("TotalClicks", ConfigManager.TotalClicks);
ConfigManager.Save("EnableAlwaysTrailEffect", CheckAlwaysTrailEffectSwitch.IsChecked ?? false);
var scrollbarVisibility = RadioScrollbarAlways.IsChecked == true
Expand Down Expand Up @@ -1483,7 +1486,7 @@
App.Overlay?.UpdateColor(ConfigManager.ParticleColor);
GetUiAnimationSpeeds(out double overlayTrail, out double overlayClick);
App.Overlay?.UpdateEffectSettings(effectScale, effectOpacity, overlayTrail, overlayClick);
App.Overlay?.UpdateTrailRefreshRate(trailRefreshRate);
App.Overlay?.UpdateInputSamplingRate(inputSamplingRate);
App.Overlay?.RefreshEnvironmentFilterState();
App.Overlay?.UpdateTouchMode(isTouchscreenEnabled);
App.Overlay?.UpdateScreenshotCompatibilityMode(screenshotCompatibilityEnabled);
Expand Down Expand Up @@ -1590,7 +1593,7 @@
string? exePath = AutoStartManager.ResolveExecutablePath(
Environment.ProcessPath,
Process.GetCurrentProcess().MainModule?.FileName,
Assembly.GetExecutingAssembly().Location,

Check warning on line 1596 in src/ControlPanelWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build

'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
AppDomain.CurrentDomain.BaseDirectory);

if (string.IsNullOrEmpty(exePath)) return;
Expand Down
4 changes: 2 additions & 2 deletions src/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
ResizeMode="NoResize"
Left="0" Top="0"
IsHitTestVisible="False">
<Grid>
<Grid x:Name="webViewHost">
<wv2:WebView2 Name="webView" DefaultBackgroundColor="Transparent"/>
</Grid>
</Window>
</Window>
Loading
Loading