What is the difference between TOUCH_BEGIN, TOUCH_OVER and TOUCH_ROLL_OVER in the TouchEvent for AS3?
I'm trying to find the correct one to use for an "on-tap"/while tapping state, and also one for after the button has been "tapped".
Count TOUCH_BEGIN as touchpad's MOUSE_DOWN version, with an additional parameter - the index of the touching point (0-based), so that you won't mix up touch events. TOUCH_END is the touchpad's MOUSE_UP, TOUCH_ROLLOVER is roughly mapped to MOUSE_DOWN condition and MOUSE_OVER event at once.
Related
I last created Mods back before Cataclysm. It's been a long time. Just now getting back into it. I'm just trying to write a very basic mod that cancels attacking with the right mouse button.
WorldFrame:HookScript("OnMouseUp", function(self, button)
if button == "RightButton" then
local mouseoverName = UnitName("mouseover") or "Unknown";
local reaction = UnitReaction("mouseover", "player") or 10;
if reaction < 5 then
DEFAULT_CHAT_FRAME:AddMessage("Stopped Attack on: "..mouseoverName);
MouselookStop();
else
DEFAULT_CHAT_FRAME:AddMessage(mouseoverName.." is friendly! "..reaction);
end
end
end)
The code I have should be working (from what I can tell) - but it's not. The code always returns Unknown & 10. If I swap out mouseover for player it works fine (but doesn't actually give me the data I need).
Also, if I swap out and hook-into OnMouseDown it also works, but then I can't actually interrupt the attack.
Any insight on why it's not working or how to fix it would be appreciated... Also if there is just a better way to do things I'm all ears.
UnitName("mouseover") indeed returns nil while any mouse button is pressed.
This is quite a smart idea to prevent attacking hostile units with mouse click. It probably doesn't work because Blizard really made sure to protect any possible thing to do with the WorldFrame that could be abused.
https://wow.gamepedia.com/API_GetCursorInfo sadly also doesn't return if the cursor is currently the sword icon, only if it's holding something.
The Appium Java client version 6.0.0 removed the driver.swipe(fromX, toX, fromY, toY, duration) API. From what I can tell, we are now supposed to use the TouchAction class to achieve the same, using the following code:
(new TouchAction(driver))
.press(PointOption.point(fromX, fromY))
.waitAction(WaitOptions.waitOptions(Duration.ofMillis(1000)))
.moveTo(PointOption.point(offsetX, offsetY))
.release()
.perform();
I think we have a gap there, because the duration of the swipe sounds like something that should be passed along in the moveTo() call and there is no method overload to achieve that.
The code I pasted above performs the actions: press, wait, move, release. What I would like to do is: press, then immediately start moving and make sure the swipe gesture spans exactly 1 second, then release. What would be the proper way to achieve this?
You will need to chain the waitAction() to happen after the moveTo() rather than after the press(). This will control the moveTo() gesture to take as long as you're defining in the waitAction():
(new TouchAction(driver))
.press(PointOption.point(fromX, fromY))
.moveTo(PointOption.point(offsetX, offsetY))
.waitAction(WaitOptions.waitOptions(Duration.ofMillis(1000)))
.release()
.perform();
I'm using MVVM architecture and I have two signals:
RACSignal *internetEnabledSignal = RACObserve(self.regWizardVehicleViewModel, internetConnectionEnabled);
RACSignal *executingRegistrationSignal = RACObserve(self.regWizardVehicleViewModel, isExecuting);
I need to combine and bind signals on button enabled property. Button needs to be disabled if there is not any connection OR when some method is executing. I was searching and searching for solution but I don't know how to combine signals with OR. Is there any way to do that? Next question is: I'm using MBProgressHUD. I want to show that HUD while executing my async method in my Model. MBProgressHUD has show and hide methods, can't bind it to a property like button enabled?
There is a convenience method, -and which makes working with "boolean" value signals easier:
Returns a signal that applies AND to each NSNumber in the tuple.
To get a tuple with NSNumbers, use combineLatestWith: like this:
RAC(self.button, enabled) =[[[executingRegistrationSignal not]
combineLatestWith:internetEnabledSignal]
and];
If I'm not misunderstanding you, then the functionality should be easily achievable with combineLatest:reduce:, like so:
RACSignal * enabledSignal =
[RACSignal combineLatest:#[internetEnabledSignal, executingRegistrationSignal]
reduce:^id(NSNumber * internetEnabled, NSNumber * isExecuting) {
return #(internetEnabled.boolValue && !isExecuting.boolValue);
}].distinctUntilChanged;
RAC(self.button, enabled) = enabledSignal;
combineLatest:reduce: won't send any next events until all signals have fired at least once, so please keep that in mind.
Edit: Please see MichaĆ's answer for a much cooler solution via convenience methods.
As for your other question, I'm not very familiar with MBProgressHUD but this should do the trick:
[self.hud rac_liftSelector:#selector(show:) withSignalsFromArray:#[
[enabledSignal ignore:#NO]
]];
[self.hud rac_liftSelector:#selector(hide:) withSignalsFromArray:#[
[[enabledSignal ignore:#YES] mapReplace:#YES]
]];
This is a bit of a cheat, we're leveraging RAC's eager subscription to these signals to fire side effects, but if you're a pragmatist and not a pedantic idealist like me, you probably don't mind.
What's happening with this code is that we're asking RAC to perform the given selector after every one of the signals in the array we supplied fires, so it's a lot like combineLatest:. We're using mapReplace: because it'll use that signal as the (BOOL)animated argument (this is another reason why it's a cheat).
I'm making an iOS app which lets you remotely control music in an app playing on your desktop.
One of the hardest problems is being able to update the position of the "tracker" (which shows the time position and duration of the currently playing song) correctly. There are several sources of input here:
At launch, the remote sends a network request to get the initial position and duration of the currently playing song.
When the user adjusts the position of the tracker using the remote, it sends a network request to the music app to change the position of the song.
If the user uses the app on the desktop to change the position of the tracker, the app sends a network request to the remote with the new position of the tracker.
If the song is currently playing, the position of the tracker is updated every 0.5 seconds or so.
At the moment, the tracker is a UISlider which is backed by a "Player" model. Whenever the user changes the position on the slider, it updates the model and sends a network request, like so:
In NowPlayingViewController.m
[[slider rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UISlider *x) {
[playerModel seekToPosition:x.value];
}];
[RACObserve(playerModel, position) subscribeNext:^(id x) {
slider.value = player.position;
}];
In PlayerModel.m:
#property (nonatomic) NSTimeInterval position;
- (void)seekToPosition:(NSTimeInterval)position
{
self.position = position;
[self.client newRequestWithMethod:#"seekTo" params:#[positionArg] callback:NULL];
}
- (void)receivedPlayerUpdate:(NSDictionary *)json
{
self.position = [json objectForKey:#"position"]
}
The problem is when a user "fiddles" with the slider, and queues up a number of network requests which all come back at different times. The user could be have moved the slider again when a response is received, moving the slider back to a previous value.
My question: How do I use ReactiveCocoa correctly in this example, ensuring that updates from the network are dealt with, but only if the user hasn't moved the slider since?
In your GitHub thread about this you say that you want to consider the remote's updates as canonical. That's good, because (as Josh Abernathy suggested there), RAC or not, you need to pick one of the two sources to take priority (or you need timestamps, but then you need a reference clock...).
Given your code and disregarding RAC, the solution is just setting a flag in seekToPosition: and unsetting it using a timer. Check the flag in recievedPlayerUpdate:, ignoring the update if it's set.
By the way, you should use the RAC() macro to bind your slider's value, rather than the subscribeNext: that you've got:
RAC(slider, value) = RACObserve(playerModel, position);
You can definitely construct a signal chain to do what you want, though. You've got four signals you need to combine.
For the last item, the periodic update, you can use interval:onScheduler::
[[RACSignal interval:kPositionFetchSeconds
onScheduler:[RACScheduler scheduler]] map:^(id _){
return /* Request position over network */;
}];
The map: just ignores the date that the interval:... signal produces, and fetches the position. Since your requests and messages from the desktop have equal priority, merge: those together:
[RACSignal merge:#[desktopPositionSignal, timedRequestSignal]];
You decided that you don't want either of those signals going through if the user has touched the slider, though. This can be accomplished in one of two ways. Using the flag I suggested, you could filter: that merged signal:
[mergedSignal filter:^BOOL (id _){ return userFiddlingWithSlider; }];
Better than that -- avoiding extra state -- would be to build an operation out of a combination of throttle: and sample: that passes a value from a signal at a certain interval after another signal has not sent anything:
[mergedSignal sample:
[sliderSignal throttle:kUserFiddlingWithSliderInterval]];
(And you might, of course, want to throttle/sample the interval:onScheduler: signal in the same way -- before the merge -- in order to avoid unncessary network requests.)
You can put this all together in PlayerModel, binding it to position. You'll just need to give the PlayerModel the slider's rac_signalForControlEvents:, and then merge in the slider value. Since you're using the same signal multiple places in one chain, I believe that you want to "multicast" it.
Finally, use startWith: to get your first item above, the inital position from the desktop app, into the stream.
RAC(self, position) =
[[RACSignal merge:#[sampledSignal,
[sliderSignal map:^id(UISlider * slider){
return [slider value];
}]]
] startWith:/* Request position over network */];
The decision to break each signal out into its own variable or string them all together Lisp-style I'll leave to you.
Incidentally, I've found it helpful to actually draw out the signal chains when working on problems like this. I made a quick diagram for your scenario. It helps with thinking of the signals as entities in their own right, as opposed to worrying about the values that they carry.
I want to be able to detect physical keyboard (e.g. bluetooth) events in an iOS app.
I came across this post: iOS: how to respond to up/down/left/right arrow event from physical keyboard? which suggests over riding UIApplication:sendEvent .
After over riding UIApplication, I can tell that keypresses are "UIInternalEvent" and do not fit into one of the 3 documented event types. Using the debugger I'm unable to differentiate when a user clicks "a" from when they click "left arrow". Any suggestions?
my code:
- (void)sendEvent:(UIEvent *)event{
UIEventType u = [event type];
if(u != UIEventTypeTouches){
}
[super sendEvent:event];
}
The debugger break point is within the if statement.
EDIT: apparently UIInternalEvent is a wrapper for GSEvent. GSEvent info can be found here: https://github.com/kennytm/iphone-private-frameworks/blob/master/GraphicsServices/GSEvent.h but I still don't know how to make use of it.
Using the private framework GraphicsServices, you can get the GSEventRecord using the UIEvent object in the sendEvent of the UIApplication. More less like this:
GSEventRef e = [UIEventObject _gsEvent];
const GSEventRecord *record = GSEventGetGSEventRecord(e);
Then try looking at the flag value of the record structure, it changes when you press shift, control, etc.