RyLiveTools/Source/FrmEffects.xaml.cs
如果当时 0ec1400de9 ### 2024-04-12更新
------
####  V1.0.2404.1201
- 新增支持手动运行规则。
- 规则播放时间间隔不再针对全局声效,而只针对当前规则声效。
- 修复规则中播放文件夹可能导致无法执行的BUG。
- 修复规则不勾选礼物和点赞,则无法执行的BUG。
2024-04-13 10:13:30 +08:00

379 lines
20 KiB
C#

using CommunityToolkit.Mvvm.Messaging;
using LiveTools.Data;
using Newtonsoft.Json.Linq;
using ryCommon;
using System.Collections;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace LiveTools
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class FrmEffects : Window
{
public FrmEffects()
{
InitializeComponent();
cvsGround.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#00ff00"));
this.Background = cvsGround.Background;
}
public DirectInfo DirectInfo { get; set; } = new DirectInfo();
public BitmapImage GetImage(string path)
{
BitmapImage bi = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block.
bi.BeginInit();
bi.UriSource = new Uri(path, UriKind.RelativeOrAbsolute);
bi.EndInit();
return bi;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
List<BitmapImage> imgList = new List<BitmapImage>();
imgList.Add(GetImage("C:\\Users\\李凤鑫\\Desktop\\微信图片_20240329144830.png"));
imgList.Add(GetImage("C:\\Users\\李凤鑫\\Desktop\\微信图片_20240307182811.png"));
imgList.Add(GetImage("C:\\Users\\李凤鑫\\Desktop\\微信图片_20240329144727.png"));
for (int i = 0; i < 10; i++)
{
Random rd2 = new Random(Guid.NewGuid().GetHashCode());
Image simpleImage = new Image();
simpleImage.Width = 50;
//Canvas.SetLeft(simpleImage, i * 300);
// Set the image source.
simpleImage.Source = imgList[rd2.Next(0,imgList.Count)];
cvsGround.Children.Add(simpleImage);
RotateTransform rotateTransform = new RotateTransform(rd2.Next(0,181));
simpleImage.RenderTransform = rotateTransform;
KK(simpleImage);
}
//KK(GroupboxArea);
//KK(GroupboxArea3);
}
void KK(Image grid)
{
var IsLandscape = false;//是否是横屏
Random rd = new Random(Guid.NewGuid().GetHashCode());
var endPos = new Point(this.Width / 2, this.Height / 2);
var mm = rd.Next(0, 4);
var startPos = new Point(0, rd.Next(0, 500));
switch (mm)
{
case 0://左边
startPos = new Point(0, rd.NextDouble() * this.Height);
break;
case 1://上边
startPos = new Point(this.Width * rd.NextDouble(), 0);
break;
case 2://右边
startPos = new Point(this.Width, rd.NextDouble() * this.Height);
break;
case 3://下边
startPos = new Point(rd.NextDouble() * this.Width, this.Height);
break;
}
var story = StartAnim(startPos, endPos);
story.Completed += delegate (object? sender2, EventArgs e2)
{
cvsGround.Children.Remove(grid);
};//完成后要做的事
story.Begin();
//story.RepeatBehavior = RepeatBehavior.Forever;//无限次循环,需要的自己加上
Storyboard StartAnim(Point startPos, Point endPos)
{
var Duration = rd.NextDouble() * 0.4;
// 创建两个DoubleAnimation来描述X和Y方向的移动
DoubleAnimation animX = new DoubleAnimation();
animX.From = startPos.X;//起点
animX.To = endPos.X; // 目标X坐标值
animX.Duration = TimeSpan.FromSeconds(Duration); // 动画持续时间
DoubleAnimation animY = new DoubleAnimation();
animY.From = startPos.Y; // 目标Y坐标值
animY.To = endPos.Y; // 目标Y坐标值
animY.Duration = TimeSpan.FromSeconds(Duration); // 动画持续时间
//
// 使用Storyboard来关联动画和物体
Storyboard.SetTarget(animX, grid);
Storyboard.SetTargetProperty(animX, new PropertyPath(Canvas.LeftProperty));
Storyboard.SetTarget(animY, grid);
Storyboard.SetTargetProperty(animY, new PropertyPath(Canvas.TopProperty));
Storyboard _story = new Storyboard();
_story.Children.Add(animX);
_story.Children.Add(animY);
//第二段动画
// 创建两个DoubleAnimation来描述X和Y方向的移动
//DoubleAnimation animX_end = new DoubleAnimation();
//animX_end.From = endPos.X;//起点
//animX_end.To = startPos.X; // 目标X坐标值
//animX_end.BeginTime = TimeSpan.FromSeconds(Duration);
//animX_end.Duration = TimeSpan.FromSeconds(1.5); // 动画持续时间
//PathGeometry pathGeometry = PathGeometry.CreateFromGeometry(Geometry.Parse("M "+ endPos.X+ ","+ endPos.Y+ " Q "+ (endPos.X+20)+ ","+ (endPos.Y+20)+ " "+ (endPos.X+10)+ ",0"));
// Y轴方向上的动画
//DoubleAnimationUsingPath animationY = new DoubleAnimationUsingPath
//{
// Source = PathAnimationSource.Y,
// BeginTime = TimeSpan.FromSeconds(Duration),
// Duration = TimeSpan.FromSeconds(Duration),
// PathGeometry = pathGeometry
//};
//DoubleAnimation animY_end = new DoubleAnimation();
//animY_end.From = endPos.Y; // 目标Y坐标值
//animY_end.To = this.Height; // 目标Y坐标值
//animY_end.BeginTime = TimeSpan.FromSeconds(Duration);
//animY_end.Duration = TimeSpan.FromSeconds(Duration); // 动画持续时间
//animY_end.AccelerationRatio = 0.6;
var offset = rd.Next(-200, 200);
var offset2 = offset > 0 ? offset + 200 : offset - 200;
var time = rd.NextDouble();
var xx = IsLandscape ? endPos.Y : endPos.X;
var yy = IsLandscape ? endPos.X : endPos.Y;
DoubleAnimationUsingKeyFrames animationX = new DoubleAnimationUsingKeyFrames();
animationX.BeginTime = TimeSpan.FromSeconds(Duration);
animationX.KeyFrames.Add(new LinearDoubleKeyFrame(xx, TimeSpan.FromSeconds(0))); // X from 0
animationX.KeyFrames.Add(new LinearDoubleKeyFrame(xx + offset, TimeSpan.FromSeconds(0.3))); // X to 50 in 1 second
animationX.KeyFrames.Add(new LinearDoubleKeyFrame(xx + offset2, TimeSpan.FromSeconds(time * 2))); // X to 100 in another 1 second
DoubleAnimationUsingKeyFrames animationY = new DoubleAnimationUsingKeyFrames();
animationY.BeginTime = TimeSpan.FromSeconds(Duration);
animationY.KeyFrames.Add(new EasingDoubleKeyFrame(yy, TimeSpan.FromSeconds(0), new QuadraticEase() { EasingMode = EasingMode.EaseOut })); // Y from 0
animationY.KeyFrames.Add(new EasingDoubleKeyFrame(yy - rd.Next(50, 200), TimeSpan.FromSeconds(0.3), new QuadraticEase() { EasingMode = EasingMode.EaseIn })); // Y to -50 in 1 second
animationY.KeyFrames.Add(new EasingDoubleKeyFrame(IsLandscape ? 0 : this.Height, TimeSpan.FromSeconds(time * 2), new BounceEase() { EasingMode = EasingMode.EaseOut })); // Y to 300 in another 1 second
Storyboard.SetTarget(animationX, grid);
Storyboard.SetTargetProperty(animationX, new PropertyPath(Canvas.LeftProperty));
Storyboard.SetTarget(animationY, grid);
Storyboard.SetTargetProperty(animationY, new PropertyPath(Canvas.TopProperty));
_story.Children.Add(animationX);
_story.Children.Add(animationY);
return _story;
}
}
private bool IsProcUse { get; set; } = false;
/// <summary>
/// 正在播放的列表
/// </summary>
Hashtable PlayingList { get; set; } = new Hashtable();
/// <summary>
/// 上一次播放时间
/// </summary>
Hashtable LastPlayTimeList { get; set; } = new Hashtable();
private void OnReceive(object recipient, MsgToken message)
{
if(message.Value is EffectInfo info)
{
if(message.Msg== "Close" && message.From == "Web")
{
IsProcUse = true;
this.Close();
return;
}
if ((info.ID == DirectInfo.Id || info.ID==0) && message.From=="Web")
{
///如果已经过期
if (Config.UserInfo.UserId.Length==0 || Config.UserInfo.OutTime<DateTime.Now.ToInt64() ||Config.UserInfo.isOut==1)
{
return;
}
if(info.ActionList!=null)
{
for (int a = 0; a < info.ActionList.Count; a++)
{
var action_item = (JObject)info.ActionList[a];
var name = action_item.GetJsonValue("Name","");
switch (name)
{
case "Rule_ShowPic":
ShowPic();
void ShowPic()
{
#region
var PicPath = API.GetTruePath(action_item.GetJsonValue("PicPath", ""));
if (System.IO.File.Exists(PicPath))
{
for (int m = 0; m < info.LoopCount; m++)
{
var count = action_item.GetJsonValue("PicCount", 10);
for (int i = 0; i < count; i++)
{
Random rd2 = new Random(Guid.NewGuid().GetHashCode());
this.Dispatcher.Invoke(new Action(() =>
{
Image simpleImage = new Image();
simpleImage.Width = action_item.GetJsonValue("PicSize", 70);
//Canvas.SetLeft(simpleImage, i * 300);
// Set the image source.
simpleImage.Source = GetImage(PicPath);
cvsGround.Children.Add(simpleImage);
RotateTransform rotateTransform = new RotateTransform(rd2.Next(0, 181));
simpleImage.RenderTransform = rotateTransform;
KK(simpleImage);
}));
}
}
if (action_item.GetJsonValue("PlaySound", true))
{
var th = new Thread(StartPlay);
th.Start();
void StartPlay()
{
//var md5 = rySafe.MD5Sha1.GetMD5("AA|" +info.ID+"|"+ DateTime.Now + "|" + Guid.NewGuid());
if (System.IO.File.Exists(Config.SysDbFolder + "\\audio\\砸.mp3"))
{
Thread.Sleep(300);
LiveTools.SoundPlay sound = new LiveTools.SoundPlay
{
Volume = 100 / 100f
};
sound.Play(Config.SysDbFolder + "\\audio\\砸.mp3");
}
}
}
}
#endregion
}
break;
case "Rule_SoundPlay":
MSoundPlay();
void MSoundPlay()
{
if (!action_item.GetJsonValue("MultiPlaySound", false))
{
if (info.RuleID > 0)
{
if (IsPlaying) { return; }
if (PlayingList.Count > 0) { return; }
if (LastPlayTimeList.ContainsKey(info.RuleID))
{
var time= (DateTime)LastPlayTimeList[info.RuleID];
if (time >= DateTime.Now.AddSeconds(-action_item.GetJsonValue("PlaySoundInterval", 10)))
{
return;
}
}
}
}
var th = new Thread(StartPlay);
th.Start();
void StartPlay()
{
IsPlaying = true;
var PlayCustomSound_Path =API.GetTruePath(action_item.GetJsonValue("PlayCustomSound_Path", ""));
var md5 = rySafe.MD5Sha1.GetMD5(PlayCustomSound_Path + "|" + DateTime.Now + "|" + Guid.NewGuid());
if (System.IO.File.Exists(PlayCustomSound_Path))
{
LiveTools.SoundPlay sound = new LiveTools.SoundPlay
{
Volume = action_item.GetJsonValue("Vol", 100) / 100f
};
PlayingList[md5]=sound;
sound.Play(PlayCustomSound_Path);
PlayingList.Remove(md5);
}
else if (System.IO.Directory.Exists(PlayCustomSound_Path))
{
var files = RyFiles.GetFiles(PlayCustomSound_Path, "*.mp3;*.wav;*.flac;*.wma");
if (files.Count > 0)
{
Random rd = new Random(Guid.NewGuid().GetHashCode());
LiveTools.SoundPlay sound = new LiveTools.SoundPlay
{
Volume = action_item.GetJsonValue("Vol", 100) / 100f
};
PlayingList[md5]= sound;
sound.Play(files[rd.Next(0, files.Count)]);
PlayingList.Remove(md5);
}
}
if (LastPlayTimeList.ContainsKey(info.RuleID))
{
LastPlayTimeList[info.RuleID] = DateTime.Now;
}
else
{
LastPlayTimeList[info.RuleID]= DateTime.Now;
}
IsPlaying = false;
}
}
break;
}
}
}
}
}
}
private DateTime LastPlayTime = DateTime.Now;
private bool IsPlaying =false;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Title = DirectInfo.Name + "[" + DirectInfo.Platform + "]特效";
WeakReferenceMessenger.Default.Register<MsgToken>(this, OnReceive);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (!IsProcUse)
{
if (HandyControl.Controls.MessageBox.Show("关闭特效窗口,将导致当前直播特效对应Web功能也同步关闭.\r\n是否确定要关闭?", "关闭确认", MessageBoxButton.OKCancel) != MessageBoxResult.OK)
{
e.Cancel = true;
}
else
{
EffectInfo effectInfo = new EffectInfo();
effectInfo.ID = DirectInfo.Id;
effectInfo.EffectMode = -1;
WeakReferenceMessenger.Default.Send<MsgToken>(new MsgToken(effectInfo) { ID = MsgTokenId.Effects, From = "Effects", Msg = "Close" });
}
}
try
{
foreach (var item in PlayingList.Values)
{
if (item is LiveTools.SoundPlay sound)
{
sound.Stop();
}
}
}
catch { }
}
}
/// <summary>
/// 特效信息
/// </summary>
public class EffectInfo
{
public int ID { get; set; } = 0;
public int RuleID { get; set; } = 0;
/// <summary>
/// 事件类型,0表示发生特效,-1表示要关闭当前窗口。
/// </summary>
public int EffectMode { get; set; } = 0;
/// <summary>
/// 循环次数
/// </summary>
public int LoopCount { get; set; } = 1;
/// <summary>
/// 动作列表
/// </summary>
public JArray ActionList { get; set; } =null;
}
}