Unity problem with call api and set data after it - unity3d

I have a call to my Firebase database that retrieves data from a player, and then it sends this data to an object. (In this object there is a list containing the weapons).
Except that in another file, I call the function to retrieve the weapons in the list. This one is empty when the game starts, because the then is not passed yet.
I solved the problem by setting an isReady variable to true when the then is passed, and I put in a void Update() the call of the function on the list.
I don't think this is the right solution, and there must be a better one, do you have an idea ? I start on unity
Here is the code :
This method will search in the list.
public void DisplayIfOwned()
{
if (GameObject.Find("PlayerManager").GetComponent<GetDataSoldier>().soldier.weaponsList.Contains(id)) weapon.SetActive(true);
else weapon.SetActive(false);
}
This method calls api to retrieve the player.
public void FillSoldierData()
{
RestClient.Get<Soldier>("https://minisoldiers-fdd66.firebaseio.com/Soldiers/" + SoldierCreation.soldierName + ".json")
.Then(response =>
{
soldier = response;
UpdateSoldier();
isReady = true;
});
}

You really should provide more clear information, I needed to make assumptions of how exactly you did things. Don't hesitate to add more code snippets, it's very helpful :)
If my assumptions are correct though, then why not just call DisplayIfOwned method directly inside Then(...? You said you're doing that in Update, so you surely have class level reference that has access to that method.
If it's done in some other way, then this might be what you want: Action

Related

Is there an function for "wait frame to end" like "WaitForEndOfFrame" in unity?

I need to do some calculations between every update(), so I need to ensure that a function is processed before the next frame.
Is there any way to achieve this? Just like "WaitForEndOfFrame" in Unity?
You can override the updateTree in your FlameGame (or in your Component, if you only want it to happen before the updates of a subtree) and do your calculations right before all the other components start updating. This would be right after the last frame, except for the first frame, but that one you can skip by setting a boolean.
So something like this:
class MyGame extends FlameGame {
bool isFirstTick = true;
#override
void updateTree(double dt) {
if(!isFirstTick) {
// Do your calculations
} else {
isFirstTick = false;
}
super.updateTree(dt);
}
}
But I have to ask, why do you need to do this? render won't be called until all the update calls are done, do can't you just put your calculations in the normal update method?
In Flutter we don't get an update() function unlike Unity. That is in the default API that we use, there are ways to tap into something of that effect. Normally we use a Ticker and create an animation to get periodic updates synced with screen refresh rate.
However, if what you are trying to do is to run something in between build() calls, WidgetsBinding.instance!.addPostFrameCallback() may be what you are looking for.
Here is a detailed answer that may help in this regard: https://stackoverflow.com/a/51273797/679553

QApplication::processEvents never returns

In my application I need to wait until external program (using QProcess) is finished. I want to keep the application responsible so blocking methods are unacceptable.
Also I need to disallow user input. I've tried to make QEventLoop and exec it with QEventLoop::ExcludeUserInputEvents flag, but as documentation says it only delays an event handling:
the events are not discarded; they will be delivered the next time processEvents() is called without the ExcludeUserInputEvents flag.
So I implemented simple event filter and install it on qApp (the idea is took from Qt Application: Simulating modal behaviour (enable/disable user input)). It works well, but sometimes QApplication::processEvents function never returns even if I specify the maximum timeout. Could anyone help me to understand for what reasons it periodically happens?
class UserInputEater : public QObject
{
public:
bool eventFilter(QObject *object, QEvent *event)
{
switch(event->type())
{
case QEvent::UpdateRequest:
case QEvent::UpdateLater:
case QEvent::Paint:
return QObject::eventFilter(object, event);
default:
return true;
}
}
};
-
UserInputEater eventEater;
qApp->installEventFilter(&eventEater);
QProcess prc;
prc.start("...");
while(!prc.waitForFinished(10))
{
if(qApp->hasPendingEvents())
{
// Sometimes it never returns from processEvents
qApp->processEvents(QEventLoop::AllEvents, 100);
}
}
qApp->removeEventFilter(&eventEater);
UPD: Seems like it depends of the timeout value for QProcess::waitForFinished.
I guess you are filtering some useful events (for example, QEvent::SockAct could be involved). Try to add some debug output and find out which event types you're actually filtering. Or it might be better to specify the black list of events you want to block instead of white list of events you want to allow. See this answer.
Also you shouldn't use return QObject::eventFilter(object, event);. You should use return false. All other event filters will be called automatically.
This solution however seems weird and unreasonable to me because you can just call setEnabled(false) for your top level widget to block user input, and then you can use QApplication::processEvents without any flags.

iTextSharp difference between implicit explicit NewPage

I use the onStartPage event handler to write a header, works great, but I need to know whether I issued a NewPage() or it was issued due to a page overflow. Is there an elegant way to tell?
Thanks in advance for any help!
You've written a page event implementation, and you've implemented one or more of its methods. You create an instance of this event like this:
MyPageEvent event = new MyPageEvent();
writer.setPageEvent(event);
Whenever the onStartPage() is called, you want to know if it was called from within iText or from your code using the newPage() method. As iText uses the same newPage() method internally, you'll have to use a trick.
Add a memberVariable to your page event application. Something like:
protected boolean myNewPage = false;
Now add this method to your event:
public void newPage(Document document) {
myNewPage = true;
document.newPage();
myNewPage = false;
}
Now whenever you want to trigger a new page, don't use:
document.newPage();
Use this instead:
event.newPage(document);
The onStartPage() method will be called internally for every new page that is initialized, and at that moment, the value of myNewPage will be true whenever the newPage() was triggered by yourself; otherwise it will be false.
I hope this helps; I didn't test it, I'm just telling you what I would try.
(PS: I'm the original developer of iText.)

pause viewmodel process for user input

I've been looking at a view examples of the typical "raise dialog from viewmodel" problem, noting 3 main solutions:
use attached behaviors
use a mediator pattern
use a service
I'm getting a bit bogged down though and struggling to find a solution that easily fits into my problem space - which is a very simple file copy problem:
My viewmodel is processing a loop (copying a list of files)
When a file already exists at the destination I need to raise a modal dialog to get confirmation to replace
The vm needs to wait for and receive confirmation before continuing
The "modal dialog" is actually not a new window but a hidden overlay in my MainWindow, as per http://www.codeproject.com/KB/WPF/wpfmodaldialog.aspx (thanks Ronald!)
I'm mostly there but the biggest struggles I have are:
- how to pause the loop in the viewmodel while it waits for input
- how to get input back to the viewmodel within the loop so it can carry on
So far I'm leaning towards the service solution because it seems a direct method call with a return that the vm must wait for. However, it does mean the service needs to tie directly to the view in order to make an element visible?
If anyone can post some simple code that deals directly with this problem I (and the net) would be very happy! Thanks!
For example, you have a service called IDialogService with the following interface:
public interface IDialogService
{
bool ConfirmAction(string title, string confirmationText);
}
As you mentioned, in order for the service to be able to show the actual dialog it needs to have a reference to the view that will show the actual overlay element. But instead of directly referencing the view I prefer to reference it via an interface. Lets call it ICanShowDialog and it will have the following members:
public interface ICanShowDialog
{
void ShowDialog(object dialogContent);
void HideDialog();
}
This interface will be implemented by your view that owns the dialog overlay (e.g. your main window).
Now the interesting part: suspending the code execution while the dialog is shown. First of all, I would recommend you not to use overlay elements but use usual windows if possible. Then you will not have that problem. You can style the dialog window so it will look just like the overlay element.
Anyway, if you still want to use overlay elements then you can do the following trick to suspend the code execution:
Here is pseudo code of the ConfirmAction method of the IDialogService inteface:
public bool ConfirmAction(string title, string confirmationText)
{
ConfirmationDialogView dialogView = new ConfirmationDialogView(title, confirmationText);
DialogShower.ShowDialog(dialogView); // DialogShower is of type ICanShowDialog
while (!dialogView.ResultAvailable)
{
DispatcherUtils.DoEvents();
}
DialogShower.HideDialog();
return dialogView.Result;
}
Here is the code of DispatcherUtils.DoEvents() (that was taken from here: http://dedjo.blogspot.com/2007/08/how-to-doevents-in-wpf.html):
public static class DispatcherUtils
{
public static void DoEvents()
{
DispatcherFrame f = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Background,
(SendOrPostCallback)delegate(object arg) {
DispatcherFrame fr = arg as DispatcherFrame;
fr.Continue=True;
}, f);
Dispatcher.PushFrame(frame);
}
}
But I must warn you. Using DoEvents can result in some subtle bugs caused by inner dispatcher loops.
As an alternative to suspending the code execution while a dialog is shown you can use callbacks:
public interface IDialogService
{
void ConfirmAction(string title, string confirmationText, Action<bool> dialogResultCallback);
}
But it will not be so convenient to use.

Deleting data in Silverlight 3 with .NET RIA Data Services

We're trying to play around with RIA Services. I can't seem to figure out how to delete a record. Here's the code I'm trying to use.
SomeDomainContext _SomeDomainContext = (SomeDomainContext)(productDataSource.DomainContext);
Product luckyProduct = (Product)(TheDataGrid.SelectedItem);
_SomeDomainContext.Products.Remove(luckyProduct);
productDataSource.SubmitChanges();
The removing the object from the Entity part works fine, but it doesn't seem to do anything to the DB. Am I using the objects like I'm supposed to, or is there a different way of saving things?
The error system is a little finicky. Try this o get the error if there is one and that will give you an idea. My problem was dependencies to other tables needing deletion first before the object could be. Ex: Tasks deleted before deleting the Ticket.
System.Windows.Ria.Data.SubmitOperation op = productDataSource.SubmitChanges();
op.Completed += new EventHandler(op_Completed);
void TicketsLoaded_Completed(object sender, EventArgs e) {
System.Windows.Ria.Data.SubmitOperation op = (System.Windows.Ria.Data.SubmitOperation)sender;
if (op.Error != null) {
ErrorWindow view = new ErrorWindow(op.Error);
view.Show();
}
}
In the code snippet above, I'd suggest using the callback parameter rather than an event handler.
productsDataSource.SubmitChanges(delegate(SubmitOperation operation) {
if (operation.HasError) {
MessageBox.Show(operation.Error.Message);
}
}, null);
The callback model is designed for the caller of Load/SubmitChanges, while the event is designed for other code that gets a reference to a LoadOperation/SubmitOperation.
Hope that helps...