Why doesn't the method work in the OnMessage event? - c#

I use WebSocketSharp to write a client, in Start I add the ChangeColor method to the OnMessage event, and the method is executed but not to the end, it does not change the color of the object, although it should. I tried to call the method in Update on button click and it worked correctly. What is the problem?
The server sends correct data, I checked
WebSocket ws;
private Renderer objectRenderer;
private Color matColor;
private string reciveData;
private void Start()
{
objectRenderer = GetComponent<Renderer>();
ws = new WebSocket("ws://127.0.0.1:8080");
ws.Connect();
ws.OnMessage += (sender, e) =>
{
reciveData = e.Data;
ChangeColor(e.Data); // its dosent work!
};
}
void Update()
{
if (ws == null)
return;
// its work
// if (Input.GetKeyDown(KeyCode.Space))
// {
// ChangeColor(reciveData);
// objectRenderer.material.color = matColor;
// }
}
public void ChangeColor(string data)
{
string[] colors = data.Split(',');
matColor = new Color()
{
r = float.Parse(colors[0]) / 255.0f,
g = float.Parse(colors[1]) / 255.0f,
b = float.Parse(colors[2]) / 255.0f,
a = float.Parse(colors[3]) / 255.0f
};
objectRenderer.material.color = matColor;
}

It does not work, because the WebSocketSharp callbacks run on a worker thread. Unity does not allow to interact with your objectRenderer in any other thread than the main thread.
You can cache the data as you did and process it in update method (which is called in main thread).
Use a boolean to tell the Update method to call your ChangeColour method.
WebSocket ws;
private Renderer objectRenderer;
private Color matColor;
private string reciveData;
private bool newDataToBeProcessed;
private void Start()
{
objectRenderer = GetComponent<Renderer>();
ws = new WebSocket("ws://127.0.0.1:8080");
ws.Connect();
ws.OnMessage += (sender, e) =>
{
reciveData = e.Data;
newDataToBeProcessed = true;
};
}
void Update()
{
if (ws == null)
return;
if (newDataToBeProcessed == true)
{
newDataToBeProcessed = false;
ChangeColor(reciveData);
objectRenderer.material.color = matColor;
}
}
public void ChangeColor(string data)
{
string[] colors = data.Split(',');
matColor = new Color()
{
r = float.Parse(colors[0]) / 255.0f,
g = float.Parse(colors[1]) / 255.0f,
b = float.Parse(colors[2]) / 255.0f,
a = float.Parse(colors[3]) / 255.0f
};
objectRenderer.material.color = matColor;
}

Related

How do I get keyboard events in the topmost NSPanel?

I have created an app using Xamarin to help watching movies online. It shows the subtitles on top of all other windows. This has been done using the NSPanel, as it was the only way to make it work on MacOS Mojave.
The app works well. Now I want to improve the app by making NSPanel respond to the keyboard events, so I can control the app by using the keyboard for pausing, playing, going backward or going forward.
How do I get keyboard events in the topmost NSPanel?
I tried to use this code:
NSEvent.AddLocalMonitorForEventsMatchingMask(NSEventMask.KeyDown, KeyboardEventHandler);
private static NSEvent KeyboardEventHandler(NSEvent keyEvent)
{
// handle key down events here
return (keyEvent);
}
But it only works when the app is not in the full-screen mode.
The full SubtitlesViewer-MACOS project can be found here.
Here is the part of the code that creates the panel:
public override void ViewWillAppear()
{
base.ViewWillAppear();
SetupView();
}
private void SetupView()
{
var screenRes = screenResolution();
int PANEL_HEIGHT = 200;
subtitlesPanel = new NSPanel
(
new CoreGraphics.CGRect(40, 50, screenRes.Width - 80, PANEL_HEIGHT),
NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Miniaturizable | NSWindowStyle.DocModal,
NSBackingStore.Buffered, true
)
{
BackgroundColor = NSColor.FromCalibratedRgba(0, 0, 0, 0.0f),
ReleasedWhenClosed = true,
HidesOnDeactivate = false,
FloatingPanel = true,
StyleMask = NSWindowStyle.NonactivatingPanel,
Level = NSWindowLevel.MainMenu - 1,
IsMovable = true,
CollectionBehavior = NSWindowCollectionBehavior.CanJoinAllSpaces |
NSWindowCollectionBehavior.FullScreenAuxiliary
};
subtitlesPanel.OrderFront(null);
subtitleTextButton = new NSButton(new CoreGraphics.CGRect(40, 0, screenRes.Width - 120, PANEL_HEIGHT-30))
{
Title = "",
WantsLayer = true
};
subtitleTextButton.Layer.BackgroundColor = NSColor.Clear.CGColor;
subtitleTextField = new NSTextField(new CoreGraphics.CGRect(40, 0, screenRes.Width - 120, PANEL_HEIGHT-30))
{
Alignment = NSTextAlignment.Center
};
subtitleTextField.Cell.Alignment = NSTextAlignment.Center;
forwardButton = new NSButton(new CoreGraphics.CGRect(0, 0, 40, 30));
forwardButton.Title = ">>";
forwardButton.Activated += (object sender, EventArgs e) => {
subtitlesProvider.Forward();
};
backButton = new NSButton(new CoreGraphics.CGRect(0, 30, 40, 30));
backButton.Title = "<<";
backButton.Activated += (object sender, EventArgs e) => {
subtitlesProvider.Back();
};
startStopButton = new NSButton(new CoreGraphics.CGRect(0, 60, 40, 30));
startStopButton.Title = "Play";
startStopButton.Activated += (object sender, EventArgs e) => {
subtitlesProvider.StartStop(subtitlesProvider.Playing);
};
subtitlesPanel.ContentView.AddSubview(subtitleTextButton, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(subtitleTextField, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(forwardButton, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(backButton, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(startStopButton, NSWindowOrderingMode.Below, null);
SetupSubtitlesProvider();
}
Please kindly advice what else should I try to make it work.
I have found the solution here:
keyDown not being called
This is my implementation of NSPanelExt class to handle the keys.
public class NSPanelExt : NSPanel
{
public KeyPressedHandler KeyPressed;
public delegate void KeyPressedHandler(KeyCodeEventArgs e);
public NSPanelExt(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation) : base(contentRect, aStyle, bufferingType, deferCreation)
{
}
public override bool CanBecomeMainWindow => true;
public override bool CanBecomeKeyWindow => true;
public override bool AcceptsFirstResponder()
{
return true;
}
public override void KeyDown(NSEvent theEvent)
{
// this function is never called
KeyPressed?.Invoke(new KeyCodeEventArgs { Key = GetKeyCode(theEvent.KeyCode) });
}
private KeyCode GetKeyCode(ushort keyCode)
{
KeyCode result = KeyCode.Unknown;
switch (keyCode)
{
case 123:
result = KeyCode.Left;
break;
case 49:
result = KeyCode.Space;
break;
case 124:
result = KeyCode.Right;
break;
case 53:
result = KeyCode.Esc;
break;
}
return result;
}
I have also updated the ViewController to keep NSPanel always active.
public partial class ViewController : NSViewController
{
// ...
private NSButton startStopButton;
Timer _timer = new Timer();
private void SetupView()
{
// ...
subtitlesPanel.KeyPressed += SubtitlesPanel_KeyPressed;
// ...
IntializeKeepWindowFocusedTimer();
}
void SubtitlesPanel_KeyPressed(KeyCodeEventArgs e)
{
switch(e.Key)
{
case KeyCode.Left:
backButton.PerformClick(this);
break;
case KeyCode.Right:
forwardButton.PerformClick(this);
break;
case KeyCode.Space:
startStopButton.PerformClick(this);
break;
case KeyCode.Esc:
_timer.Stop();
break;
}
}
private void IntializeKeepWindowFocusedTimer()
{
_timer.Interval = 200; //in milliseconds
_timer.Elapsed += Timer_Elapsed;;
_timer.AutoReset = true;
_timer.Enabled = true;
}
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
NSApplication.SharedApplication.BeginInvokeOnMainThread(() =>
{
subtitlesPanel.MakeKeyWindow();
if (SetSubtitleNeeded)
{
subtitlesProvider.SetSubTitle(0);
startStopButton.Title = "Stop";
SetSubtitleNeeded = false;
_timer.Interval = 5000;
}
});
}
private bool SetSubtitleNeeded = false;
partial void ClickedButton(NSObject sender)
{
_timer.Stop();
var nsUrl = subtitleFileSelector.GetFile();
if (nsUrl == null)
return;
fileName = nsUrl.Path;
subtitlesProvider.ReadFromFile(fileName);
SetSubtitleNeeded = true;
_timer.Start();
}

CS1061 error Xamarin/Visual Studio

I am trying to run some source code that I downloaded from here
This is essentially an app that will allow users to manage contacts and calendar appointments etc.
I am currently experiencing 3 errors, all seemingly related...
CS1061 - UIImageView does not contain a definition for 'SetImage' and no extension method 'SetImage' accepting a first argument of type 'UIImageView' could be found (are you missing a using directive or an assembly reference?)
It seems that SetImage is not defined somewhere?
Would someone be able to tell me what i need to do to resolve the error. I post my code below...
using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using MessageUI;
using Microsoft.Office365.OutlookServices;
using FiveMinuteMeeting.Shared.ViewModels;
using CoreGraphics;
using FiveMinuteMeeting.Shared;
namespace FiveMinuteMeeting.iOS
{
partial class ContactDetailViewController : UIViewController
{
public ContactDetailViewController(IntPtr handle)
: base(handle)
{
}
public DetailsViewModel ViewModel
{
get;
set;
}
UIBarButtonItem save;
public override void ViewDidLoad()
{
base.ViewDidLoad();
NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
save = new UIBarButtonItem(UIBarButtonSystemItem.Save,
async (sender, args) =>
{
ViewModel.FirstName = TextFirst.Text.Trim();
ViewModel.LastName = TextLast.Text.Trim();
ViewModel.Email = TextEmail.Text.Trim();
ViewModel.Phone = TextPhone.Text.Trim();
//BigTed.BTProgressHUD.Show("Saving contact...");
await ViewModel.SaveContact();
//BigTed.BTProgressHUD.Dismiss();
NavigationController.PopToRootViewController(true);
});
TextEmail.ShouldReturn += ShouldReturn;
TextFirst.ShouldReturn += ShouldReturn;
TextPhone.ShouldReturn += ShouldReturn;
TextLast.ShouldReturn += ShouldReturn;
TextEmail.ValueChanged += (sender, args) =>
{
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(TextEmail.Text, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
};
var color = new CGColor(17.0F / 255.0F, 113.0F / 255.0F, 197.0F / 255F);
TextEmail.Layer.BorderColor = color;
TextFirst.Layer.BorderColor = color;
TextPhone.Layer.BorderColor = color;
TextLast.Layer.BorderColor = color;
ButtonCall.Clicked += (sender, args) => PlaceCall();
NSNotificationCenter.DefaultCenter.AddObserver
(UIKeyboard.DidShowNotification, KeyBoardUpNotification);
// Keyboard Down
NSNotificationCenter.DefaultCenter.AddObserver
(UIKeyboard.WillHideNotification, KeyBoardDownNotification);
double min = Math.Min((float)ImagePhoto.Frame.Width, (float)ImagePhoto.Frame.Height);
ImagePhoto.Layer.CornerRadius = (float)(min / 2.0);
ImagePhoto.Layer.MasksToBounds = false;
ImagePhoto.Layer.BorderColor = new CGColor(1, 1, 1);
ImagePhoto.Layer.BorderWidth = 3;
ImagePhoto.ClipsToBounds = true;
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (ViewModel == null)
{
ViewModel = new DetailsViewModel();
NavigationItem.RightBarButtonItem = save;
}
else
{
this.Title = ViewModel.FirstName;
TextEmail.Text = ViewModel.Email;
TextFirst.Text = ViewModel.FirstName;
TextLast.Text = ViewModel.LastName;
TextPhone.Text = ViewModel.Phone;
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(ViewModel.Contact.EmailAddresses[0].Address, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
NavigationItem.RightBarButtonItem = null;
}
}
private bool ShouldReturn(UITextField field)
{
field.ResignFirstResponder();
return true;
}
private void PlaceCall()
{
var alertPrompt = new UIAlertView("Dial Number?",
"Do you want to call " + TextPhone.Text + "?",
null, "No", "Yes");
alertPrompt.Dismissed += (sender, e) =>
{
if ((int)e.ButtonIndex >= (int)alertPrompt.FirstOtherButtonIndex)
{
var url = new NSUrl("tel:" + TextPhone.Text);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Not supported",
"Scheme 'tel:' is not supported on this device",
null,
"OK",
null);
av.Show();
}
else
{
UIApplication.SharedApplication.OpenUrl(url);
}
}
};
alertPrompt.Show();
}
/*private async void SendEmail()
{
var mailController = new MFMailComposeViewController();
mailController.SetToRecipients(new string[] { TextEmail.Text });
mailController.SetSubject("5 Minute Meeting");
mailController.SetMessageBody("We are having a 5 minute stand up tomorrow at this time! Check your calendar.", false);
mailController.Finished += (object s, MFComposeResultEventArgs args) =>
{
Console.WriteLine(args.Result.ToString());
args.Controller.DismissViewController(true, (Action)null);
};
PresentViewControllerAsync(mailController, true);
}*/
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
switch(segue.Identifier)
{
case "email":
{
var vc = segue.DestinationViewController as SendEmailViewController;
vc.ViewModel.FirstName = ViewModel.FirstName;
vc.ViewModel.LastName = ViewModel.LastName;
vc.ViewModel.Email = ViewModel.Email;
}
break;
case "meeting":
{
var vc = segue.DestinationViewController as NewEventDurationViewController;
vc.ViewModel.FirstName = ViewModel.FirstName;
vc.ViewModel.LastName = ViewModel.LastName;
vc.ViewModel.Email = ViewModel.Email;
}
break;
}
}
#region Keyboard
private UIView activeview; // Controller that activated the keyboard
private float scrollamount; // amount to scroll
private float bottom; // bottom point
private const float Offset = 68.0f; // extra offset
private bool moveViewUp; // which direction are we moving
private void KeyBoardDownNotification(NSNotification notification)
{
if (moveViewUp) { ScrollTheView(false); }
}
private void ScrollTheView(bool move)
{
// scroll the view up or down
UIView.BeginAnimations(string.Empty, System.IntPtr.Zero);
UIView.SetAnimationDuration(0.3);
CGRect frame = (CGRect)View.Frame;
if (move)
{
frame.Y -= scrollamount;
}
else
{
frame.Y += scrollamount;
scrollamount = 0;
}
View.Frame = frame;
UIView.CommitAnimations();
}
private void KeyBoardUpNotification(NSNotification notification)
{
// get the keyboard size
var r = (CGRect)UIKeyboard.FrameBeginFromNotification((NSNotification)notification);
// Find what opened the keyboard
foreach (UIView view in this.View.Subviews)
{
if (view.IsFirstResponder)
activeview = view;
}
// Bottom of the controller = initial position + height + offset
bottom = ((float)activeview.Frame.Y + (float)activeview.Frame.Height + Offset);
// Calculate how far we need to scroll
scrollamount = ((float)r.Height - ((float)View.Frame.Size.Height - bottom));
// Perform the scrolling
if (scrollamount > 0)
{
moveViewUp = true;
ScrollTheView(moveViewUp);
}
else
{
moveViewUp = false;
}
}
#endregion
}
}
I am very new to Xamarin & app development and I just wanted to run this because it is a very similar project to one that I am creating.
Thanks for your help
SetImage is a extension method contained in Xamarin.SDWebImage. Ensure, that you have restored all nuget packages or have installed it via
Install-Package Xamarin.SDWebImage
see: https://www.nuget.org/packages/Xamarin.SDWebImage/
Here a explanation of the error.
https://msdn.microsoft.com/en-us/library/bb383961.aspx
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
CS1061 - UIImageView does not contain a definition for 'SetImage' and no extension method 'SetImage' accepting a first argument of type 'UIImageView' could be found (are you missing a using directive or an assembly reference?)
In your code I don't watch a declaration of ImagePhoto check right click goto definition. And verify that for imagePhoto exist a method setImage ImagePhoto I'm asumming that is object of type UIImage
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(TextEmail.Text, 172)),
placeholder: UIImage.FromBundle("missing.png")
);

UIProgressView not updating from BackgroundWorker.ProgressChanged

I'm in the process of porting my Xamarin.Android app to Xamarin.iOS, I can't make my progress bar update, where am I going wrong?
The values are set in updateProgressBar() correctly and progressBarValue in this example is set as 0.25 as expected, but the UIProgressView is not updated on the screen. progressBar is a UIProgressView on the storyboard.
public BackgroundWorker backgroundWorker { get; private set; }
private float progressBarValue { get; set; }
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
startBackgroundWorker();
}
private void startBackgroundWorker()
{
if (backgroundWorker == null || backgroundWorker.CancellationPending) backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s, e) =>
{
//do stuff
backgroundWorker.ReportProgress(25);
//do stuff
};
backgroundWorker.RunWorkerCompleted += (s, e) => { //do stuff };
backgroundWorker.ProgressChanged += (s, e) => { updateProgressBar(e.ProgressPercentage); };
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.RunWorkerAsync();
}
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
progressBar.Progress = progressBarValue;
}
}
I also tried using SetProgress(progressBarValue,true)
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
progressBar.SetProgress(progressBarValue,true);
}
}
and using InvokeOnMainThread
private void updateProgressBar(float v)
{
if (v > 0){
float value = v / 100;
progressBarValue = progressBarValue + value;
if (progressBarValue > 1) progressBarValue = 1;
InvokeOnMainThread ( () => {
// manipulate UI controls
progressBar.SetProgress(progressBarValue,true);
});
}
}
you need to be sure your UI updates are running on the main thread
InvokeOnMainThread ( () => {
// manipulate UI controls
progressBar.SetProgress(progressBarValue,true);
});
As is often the case, my problem was not related to my code in the question, or the question at all, I copied it into a new solution and it worked fine.
Incase anyone finds this in the future and has made the same mistake:
My problem was that I had set UIProgressView.TintColor to an invalid value elsewhere in my code so the ProgressView was updating all along but it just wasn't visible.
progressView.TintColor = iOSHelpers.GetColor(GenericHelpers.colorPrimaryGreenRGBA);
iOSHelpers
public static UIColor GetColor(int[] rgba)
{
if (rgba.Length == 4)
return UIColor.FromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
else return UIColor.Black;
}
GenericHelpers
public static int[] colorPrimaryGreenRGBA = { 140, 185, 50, 1 };
Once I had changed thecolorPrimaryGreenRGBA values to floats and divided the RGB channels by 255 in the GetColor method it was then a visible color.

Play three sounds simultaneously c#

I want to play three sounds simultaneously, but second sound must play after one seconds, third sound after two seconds. I have this code:
private void Play()
{
AxWindowsMediaPlayer player1 = new AxWindowsMediaPlayer();
player1.CreateControl();
AxWindowsMediaPlayer player2 = new AxWindowsMediaPlayer();
player2.CreateControl();
AxWindowsMediaPlayer player3 = new AxWindowsMediaPlayer();
player3.CreateControl();
player1.URL = "sounds\\1.wav";
player1.Ctlcontrols.play();
System.Threading.Thread.Sleep(1000);
player2.URL = "sounds\\2.wav";
player2.Ctlcontrols.play();
System.Threading.Thread.Sleep(1000);
player3.URL = "sounds\\3.wav";
player3.Ctlcontrols.play();
Why all this sounds are playing in one time after two seconds?
I ended up using SharpDX (available via NuGet packages SharpDX
and SharpDX.XAudio2.
An example of its usage can be found in one of my GitHub projects: 2DAI
You can hear the various sounds overlapping in this screen recording as well.
Playing a sound:
var backgroundMusicSound = new AudioClip(#".\Assets\Sounds\Music\Background.wav" /*Sound path*/, 1.0 /* Volumne*/, true /*Loop Forever?*/)
backgroundMusicSound.Play();
The class that I pieced together:
public class AudioClip
{
private XAudio2 _xaudio = new XAudio2();
private WaveFormat _waveFormat;
private AudioBuffer _buffer;
private SoundStream _soundstream;
private SourceVoice _singleSourceVoice;
private bool _loopForever;
private bool _isPlaying = false; //Only applicable when _loopForever == false;
private bool _isFading;
private string _wavFilePath; //For debugging.
private float _initialVolumne;
public AudioClip(string wavFilePath, float initialVolumne = 1, bool loopForever = false)
{
_loopForever = loopForever;
_wavFilePath = wavFilePath;
_initialVolumne = initialVolumne;
var masteringsound = new MasteringVoice(_xaudio); //Yes, this is required.
var nativefilestream = new NativeFileStream(wavFilePath,
NativeFileMode.Open, NativeFileAccess.Read, NativeFileShare.Read);
_soundstream = new SoundStream(nativefilestream);
_waveFormat = _soundstream.Format;
_buffer = new AudioBuffer
{
Stream = _soundstream.ToDataStream(),
AudioBytes = (int)_soundstream.Length,
Flags = BufferFlags.EndOfStream
};
if (loopForever)
{
_buffer.LoopCount = 100;
}
}
public void Play()
{
lock (this)
{
if (_loopForever == true)
{
if (_isPlaying)
{
if (_isFading)
{
_isFading = false;
_singleSourceVoice.SetVolume(_initialVolumne);
}
return;
}
_singleSourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
_singleSourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
_singleSourceVoice.SetVolume(_initialVolumne);
_singleSourceVoice.Start();
_isPlaying = true;
return;
}
}
var sourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
sourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
sourceVoice.SetVolume(_initialVolumne);
sourceVoice.Start();
}
public void Fade()
{
if (_isPlaying && _isFading == false)
{
_isFading = true;
(new Thread(FadeThread)).Start();
}
}
private void FadeThread()
{
float volumne;
_singleSourceVoice.GetVolume(out volumne);
while (_isFading && volumne > 0)
{
volumne -= 0.25f;
volumne = volumne < 0 ? 0 : volumne;
_singleSourceVoice.SetVolume(volumne);
Thread.Sleep(100);
}
Stop();
}
public void Stop()
{
if (_loopForever == true)
{
if (_singleSourceVoice != null && _isPlaying)
{
_singleSourceVoice.Stop();
}
_isPlaying = false;
_isFading = false;
}
else
{
throw new Exception("Cannot stop overlapped audio.");
}
}
}
It should also be notes that loading the sounds can be a heavy process, so if you are doing it a lot then you might want to cache them as I did:
private Dictionary<string, AudioClip> _audioClips { get; set; } = new Dictionary<string, AudioClip>();
public AudioClip GetSoundCached(string wavFilePath, float initialVolumne, bool loopForever = false)
{
lock (_audioClips)
{
AudioClip result = null;
wavFilePath = wavFilePath.ToLower();
if (_audioClips.ContainsKey(wavFilePath))
{
result = _audioClips[wavFilePath];
}
else
{
result = new AudioClip(wavFilePath, initialVolumne, loopForever);
_audioClips.Add(wavFilePath, result);
}
return result;
}
}

Multi thread for joystick input

Hi there i am trying to make a question answer game. ( Whoever presses joystick button first answers the question first )
So far i ' ve used SharpDX , threading since i cant handle the button press event via SharpDX
My problem is i cant get it worked . I dont know the reason but let me explain my code.
On my page load i ' ve initialized 2 different threads ;
//Initializing the constants
private bool q = true;
private Thread th1;
private Thread th2;
private Guid joy1Guid = Guid.Empty;
private Guid joy2Guid = Guid.Empty;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var directInput = new DirectInput();
foreach (var deviceInstance in directInput.GetDevices())
{
if (deviceInstance.Subtype == 258)
{
//My joysticks connected to pc via usb.
if (joy1Guid == Guid.Empty)
joy1Guid = deviceInstance.InstanceGuid;
else if (joy2Guid == Guid.Empty)
joy2Guid = deviceInstance.InstanceGuid;
}
}
th1 = new Thread(Joy1Start);
th2 = new Thread(Joy2Start);
th1.IsBackground = true;
th2.IsBackground = true;
}
Below my Thread methods
private void Joy1Start()
{
var directInput = new DirectInput();
var joystick = new Joystick(directInput, joy1Guid);
joystick.Properties.BufferSize = 128;
joystick.Acquire();
while (q)
{
joystick.Poll();
var state = joystick.GetCurrentState();
var counter = 0;
foreach (bool isPressed in state.Buttons)
{
if (isPressed)
{
Action a1 = () => textBox1.Text = "JOY1";
textBox1.Invoke(a1);
th1.Abort();
th2.Abort();
q = false;
break;
}
counter++;
}
}
}
private void Joy2Start()
{
var directInput = new DirectInput();
var joystick = new Joystick(directInput, joy2Guid);
joystick.Properties.BufferSize = 128;
joystick.Acquire();
while (q)
{
joystick.Poll();
var state = joystick.GetCurrentState();
var counter = 0;
foreach (bool isPressed in state.Buttons)
{
if (isPressed)
{
Action a2 = () => textBox1.Text = "JOY2";
textBox1.Invoke(a2);
th1.Abort();
q = false;
break;
}
counter++;
}
}
}
I am firing thread starts with a button
private void button1_Click(object sender, EventArgs e)
{
th1.Start();
th2.Start();
}
So the problem is i can't get any response if i work with two threads.
When i only start th1 or th2 it works like a charm.
Can you please show me where is the wrong part of this algorithm ?

Categories

Resources