This is the code I'm currently using. (Not my own). It detects when a controller has been plugged in, and outputs a few bits of relevant info. What I can't figure out is how to access the button data. Although it successfully recognises I've plugged in a PS3 controller, the values of the buttons don't seem to change when queried.
package;
import openfl.display.Sprite;
import openfl.events.GameInputEvent;
import openfl.ui.GameInputControl;
import openfl.ui.GameInputDevice;
import openfl.ui.GameInput;
import openfl.events.Event;
class Main extends Sprite {
private var gameInput:GameInput;
public function new(){
super();
gameInput = new GameInput();
gameInput.addEventListener(GameInputEvent.DEVICE_ADDED, controllerAdded);
gameInput.addEventListener(GameInputEvent.DEVICE_REMOVED, controllerRemoved);
gameInput.addEventListener(GameInputEvent.DEVICE_UNUSABLE, controllerProblem);
}
function controllerAdded(e:GameInputEvent){
//put code here to handle when a device is added
trace("GameInput.numDevices: "+GameInput.numDevices);//tells you how many gamepads are plugged in
var myDevice = GameInput.getDeviceAt(0);//1st gamepad is "0" - more gamepads would be "1", "2", "3", etc.
trace("myDevice.numControls: "+myDevice.numControls); //tells you how many inputs/controls the device has
myDevice.enabled = true; //enables the device
var cont = myDevice.getControlAt(12);//input reference (AXIS STICK, BUTTON, TRIGGER, etc) "0" is the 1st input
trace("id: "+cont.id);//the name of this control. Ex: "AXIS_0"
trace("value: " + cont.value); //value of this control - Axis: -1 to 1, Button: 0 OR 1, Trigger: 0 to 1
trace("cont: " + cont.device.name); //the name of the device. ie: "XBOX 360 Controller"
trace("device: " + cont.device);
trace("minValue: " + cont.minValue);//the minimum possible value for the control/input
trace("maxValue: " + cont.maxValue);//the maximum possible value for the control/input
}
function controllerRemoved(e:GameInputEvent){
trace('BLAH BLAH BLAH');
}
function controllerProblem(e:GameInputEvent){
//put code here to handle when there is a problem with the controller
trace("controller problem");
}
}
Here's the minimum amount of code needed to get controller input. It works with all controllers I have available (Xbox 360, Xbox One and a Logitech one):
import openfl.display.Sprite;
import openfl.ui.GameInput;
import openfl.ui.GameInputDevice;
import openfl.events.Event;
import openfl.events.GameInputEvent;
class Main extends Sprite {
public function new() {
super();
var gameInput = new GameInput();
var device:GameInputDevice;
gameInput.addEventListener(GameInputEvent.DEVICE_ADDED, function(event) {
device = event.device;
device.enabled = true;
});
stage.addEventListener(Event.ENTER_FRAME, function(event) {
trace([for (i in 0...device.numControls) device.getControlAt(i).value]);
});
}
}
That seems quite similar to what you tried, so I'd say chances are it's a driver issue, not a problem with your code. Note: I used OpenFL 4.7.3 and Lime 3.7.2 for testing.
I don't own a PS3 controller myself, but they're supposedly tricky to get to work on PC. ScpToolkit is often recommended and seems quite popular.
Btw, openfl-samples also has a GamepadInput sample you could give a try.
Related
Running ARKit 2.0 with an ARSCNView. iOS12
The application uses multithreading, that's why these functions are being performed on the main thread (just to be sure). I also tried without explicitly performing the functions on the main thread too, with no avail.
I'm using an .aiff sound file but have also tried a .wav. No joy.
I even tried removing audioNode_alarm from the node hierarchy & the sound still plays. I even remove the ARSCNView from the view hierarchy and the sound STILL plays. FFS
From what I can see, I'm doing things EXACTLY as I'm supposed to, to stop the audio from playing. The audio simply will not stop no matter what I try. Can anyone think why?!
weak var audioNode_alarm: SCNNode!
weak var audioPlayer_alarm: SCNAudioPlayer?
func setupAudioNode() {
let audioNode_alarm = SCNNode()
addChildNode(audioNode_alarm)
self.audioNode_alarm = audioNode_alarm
}
func playAlarm() {
DispatchQueue.main.async { [unowned self] in
self.audioNode_alarm.removeAllAudioPlayers()
if let audioSource_alarm = SCNAudioSource(fileNamed: "PATH_TO_MY_ALARM_SOUND.aiff") {
audioSource_alarm.loops = true
audioSource_alarm.load()
audioSource_alarm.isPositional = true
let audioPlayer_alarm = SCNAudioPlayer(source: audioSource_alarm)
self.audioNode_alarm.addAudioPlayer(audioPlayer_alarm)
self.audioPlayer_alarm = audioPlayer_alarm
}
}
}
func stopAlarm() {
DispatchQueue.main.async { [unowned self] in
self.audioNode_alarm?.removeAudioPlayer(self.audioPlayer_alarm!)
self.audioNode_alarm?.removeAllAudioPlayers()
}
}
What I ended up doing is stopping the sound and removing the player by
yourNode.audioPlayers.forEach { audioLocalPlayer in
audioLocalPlayer.audioNode?.engine?.stop()
yourNode.removeAudioPlayer(audioLocalPlayer)
}
According to the documentation SCNAudioPlayer has audioNode, which is supposed to be used "to vary parameters such as volume and reverb in real time during playback".
audioNode is of AVAudioNode type, so if we jump to engine prop and its type definition, we'll find all the controls we need.
I can not capture images in new thread
can you tell me what does it mean?
import qyvlik.thread.runnable 0.1
import qyvlik.utility 0.1
import QtMultimedia 5.5
QmlRunnable
{
id: runnable
Camera
{
id: cam
}
onMessageReceived:
{
cam.imageCapture.capture()
}
}
EDIT (#derM): It seems this is the source of the third-party modules.
As #KevinKrammer pointed out:
The error appears, as your class QmlRunnable has no default property, to which your Camera-object could be assigned. This is standard for most non-Item-QObjects in QML.
The author of your class knows of this problem, therefore he defines a property to store his DirSize-object in his example
Example:
import qyvlik.thread.runnable 0.1
import qyvlik.utility 0.1
QmlRunnable {
id: runnable
readonly property var __: DirSize {
id: dirsize
}
onMessageReceived: {
console.time("dirsize")
sendMessage(dirsize.dirSize(message));
console.timeEnd("dirsize")
}
}
From this I guess the solution would be this:
import qyvlik.thread.runnable 0.1
import qyvlik.utility 0.1
import QtMultimedia 5.5
QmlRunnable
{
id: runnable
property Camera cam: Camera // <--- create a property to assign it to.
{
}
onMessageReceived:
{
cam.imageCapture.capture()
}
}
You are using some third party QML modules, one of which apparently provides a QmlRunnable type.
Without any information on that type, such as a link to its documentation, the error would suggest that it is the one that does not have a default property.
When you try to create the Camera object inside the QmlRunnable the engine will try to assign that instance to the "parent's" default property.
Again, without any knowledge about the type it is difficult to provide any help.
Well, the QmlRunnable can not use the gui class, because it is Undetermined behavior
I tried to use both HaxeUI and HaxeFlixel, but what I obtain is HaxeUI's interface over a white background, covering everything underneath. Moreover, even if it was possible to somewhat make HaxeUI and HaxeFlixel work together, it's not clear how to change the UI of HaxeUI when the state change in HaxeFlixel. Here is the code I used:
private function setupGame():Void {
Toolkit.theme = new GradientTheme();
Toolkit.init();
var stageWidth:Int = Lib.current.stage.stageWidth;
var stageHeight:Int = Lib.current.stage.stageHeight;
if (zoom == -1) {
var ratioX:Float = stageWidth / gameWidth;
var ratioY:Float = stageHeight / gameHeight;
zoom = Math.min(ratioX, ratioY);
gameWidth = Math.ceil(stageWidth / zoom);
gameHeight = Math.ceil(stageHeight / zoom);
}
trace('stage: ${stageWidth}x${stageHeight}, game: ${gameWidth}x${gameHeight}, zoom=$zoom');
addChild(new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen));
Toolkit.openFullscreen(function(root:Root) {
var view:IDisplayObject = Toolkit.processXmlResource("assets/xml/haxeui-resource.xml");
root.addChild(view);
});
}
I can guess that, probably, both HaxeUI and HaxeFlixel have their own main loop and that their event handling might not be compatible, but just in case, can someone have a more definitive answer?
Edit:
Actually, it's much better when using openPopup:
Toolkit.openPopup( { x:20, y:150, width:100, height:100 }, function(root:Root) {
var view:IDisplayObject = Toolkit.processXmlResource("assets/xml/haxeui-naming.xml");
root.addChild(view);
});
It's possible to interact with the rest of the screen (managed with HaxeFlixel), but the mouse pointer present in the part of the screen managed with HaxeFlixel remains under the HaxeUI user interface elements.
When using Flixel and HaxeUI together, its almost like running two applications at once. However, they both rely on OpenFL as a back-end and each attach themselves to its display tree.
One technique I'm experimenting with right now is to open a Flixel sub state, and within the sub state, call Toolkit.openFullscreen(). From inside of this, you can set the alpha of the root's background to 0, which allows you to see through it onto the underlying bitmap that Flixel uses to render.
Here is a minimal example of how you might "embed" an editor interface inside a Flixel sub state:
import haxe.ui.toolkit.core.Toolkit;
import haxe.ui.toolkit.core.RootManager;
import haxe.ui.toolkit.themes.DefaultTheme;
import flixel.FlxG;
import flixel.FlxSubState;
// This would typically be a Haxe UI XMLController
import app.MainEditor;
class HaxeUIState extends FlxSubState
{
override public function create()
{
super.create();
// Flixel uses a sprite-based cursor by default,
// so you need to enable the system cursor to be
// able to see what you're clicking.
FlxG.mouse.useSystemCursor = true;
Toolkit.theme = new DefaultTheme();
Toolkit.init();
Toolkit.openFullscreen(function (root) {
var editor = new MainEditor();
// Allows you to see what's going on in the sub state
root.style.backgroundAlpha = 0;
root.addChild(editor.view);
});
}
override public function destroy()
{
super.destroy();
// Switch back to Flixel's cursor
FlxG.mouse.useSystemCursor = true;
// Not sure if this is the "correct" way to close the UI,
// but it works for my purposes. Alternatively you could
// try opening the editor in advance, but hiding it
// until the sub-state opens.
RootManager.instance.destroyAllRoots();
}
// As far as I can tell, the update function continues to get
// called even while Haxe UI is open.
override public function update() {
super.update();
if (FlxG.keys.justPressed.ESCAPE) {
// This will implicitly trigger destroy().
close();
}
}
}
In this way, you can associate different Flixel states with different Haxe UI controllers. (NOTE: They don't strictly have to be sub-states, that's just what worked best in my case.)
When you open a fullscreen or popup with haxeui, the program flow will be blocked (your update() and draw() function won't be called). You should probably have a look at flixel-ui instead.
From my experience haxeflixel and haxeui work well together but they are totally independent projects, and as such, any coordination between flixel states and displayed UI must be added by the coder.
I don't recall having the white background problem you mention, it shouldn't happen unless haxeui root sprite has a solid background, in that case it should be addressed to haxeui project maintainer.
I have recently been reading through the book of Geb and trying to get to grips with it as it seems like a great tool. I feel like I'm getting there but there's still some really core concepts that I can't seem to grasp.
As an example, take the website:-
http://www.escapistmagazine.com/videos/view/zero-punctuation
Now if I want to test that the first video listed links to the correct page my first thought was to do the following
class ZeroPunctuationIndexPage extends Page {
static url = "http://www.escapistmagazine.com/videos/view/zero-punctuation"
static at = {title == "Zero Punctuation Video Gallery | The Escapist"}
static content = {
selectFirstVideo {$("a", 0, class: "filmstrip_video")}
firstVideoTitle {$("i", 0, class: "filmstrip_video")}
}
}
class ZeroPunctuationIndexSpec extends GebReportingSpec {
def "Click the latest video and play it"(){
given:
to ZeroPunctuationIndexPage
when:
selectFirstVideo.click()
then:
title.endsWith(firstVideoTitle)
}
}
Essentially I thought if I pick the first class that contains the video (filmstrip_video) and then pick the link inside it then I could click that, and compare the video title from the link to the new page title.
Looking at it again I'm not surprised it didn't work, but I'm not sure what to do.
If anyone could give me a quick solution i'd appreciate it. I'm not doing anything in particular with the escapist page, I just picked somewhere with an index of videos to try out writing a test.
Thank you!
It was not getting the link and it was failing, so I fixed that and double checked. Now, it's working fine and it passes. Also, when you are selecting the first element, you don't need to write 0 explicitly as by default it will choose the 0th element.
class ZeroPunctuationIndexPage extends Page {
static url = "http://www.escapistmagazine.com/videos/view/zero-punctuation"
static at = {title == "Zero Punctuation Video Gallery | The Escapist"}
static content = {
selectFirstVideo {$("div.filmstrip_video").find('a')}
firstVideoTitle {$("div.filmstrip_video").find('i')}
}
}
class ZeroPunctuationIndexSpec extends GebReportingSpec {
def "Click the latest video and play it"(){
given:
to ZeroPunctuationIndexPage
when:
waitFor { selectFirstVideo.click() }
then:
title.endsWith(firstVideoTitle.text())
}
}
Cheers!
Try:
title.endsWith(firstVideoTitle.text())
I'm on my iPad, so I can't test it, but it should work.
hoping this is an easy enough question :)
Some details:
I am using Flash CS5, never touched Flex. Also the SWF that is doing the loading will be a client SWF, so hoping for a solution that could work with a simple couple of lines.
Basically inside the SWF I am working on contains just a simple string:
var theString = "theString";
trace("theString = "+theString);
Now I've been working on a test loader SWF that will load my String SWF and get the variable in the simplest way. Any thoughts? Below is my current broken code:
function loaderComplete(event:Event)
{
trace("... in loaderComplete");
getString = loader.content.toString();
trace("loader.content = "+loader.content);
trace("... getString = "+getString);
}
This is my output window:
theString = theString
... in loaderComplete
loader.content = [object MainTimeline]
... getString = [object MainTimeline]
I've searched on Stack and found similar questions, but none are exactly what I need:
tracking video files - embedding flv to swf
^ Basically what I'm trying to do as well, no answers yet
to pass variable from one swf to another swf in as3
^ sounded just like my problem, but answer was a Flex application example
pass var values from one swf to another swf who is loaded inside the firts one in AS3
^ This was close, but am not sure how to implement the chosen answer, also seems a bit more intricate then I need
Please help!
Let's clarify a bit:
1. The loader swf, we will call the parent.
2. The swf loaded by the parent we will call the child.
The Child contains a string, and you want the parent to be able to read that string>
So...
The Child must define a public variable for the string. (This means you have to use a Class file for it, since you cannot declare a property public on the timeline.)
Finally, the parent will try and get that property. You may want to wrap that in a try/catch to handle cases where the string will not be present.
Here is an example Child Class.
package
{
import flash.display.Sprite;
/**
* ...
* #author Zach Foley
*/
public class Child extends Sprite
{
public var value:String = "This is the child Value";
public function Child()
{
trace("Child Loaded");
}
}
}
And here is the parent loader class:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
/**
* ...
* #author Zach Foley
*/
public class Parent extends Sprite
{
private var loader:Loader;
public function Parent()
{
trace("PArent Init");
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
loader.load(new URLRequest("child.swf"));
}
private function onLoaded(e:Event):void
{
trace("Child Loaded");
trace(loader.content['value']);
}
}
}
The Output will be:
PArent Init
Child Loaded
Child Loaded
This is the child Value
you can access variables and code from the loaded swf. First, make sure that both the loader and the loaded content use the same AVM, this means that both project use the same version of language (both as3 or both as2)
Thank in the loader complete handler:
loaderComplete(evt:Event):void{
var mc:MovieClip = loader.content as MovieClip;
if(!mc){
trace("Error loading");
return;
}
trace("Your string: " + mc.theString);
}
I haven't tested this code but it should works