mirror of https://github.com/axmolengine/axmol.git
issue #4895:Get events from controller to engine[android]
This commit is contained in:
parent
3c614d5670
commit
5ed581758e
|
@ -0,0 +1,365 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 cocos2d-x.org
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "CCController.h"
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
|
||||
#include "CCGamepad.h"
|
||||
#include "CCControllerDirectionPad.h"
|
||||
#include "CCControllerButtonInput.h"
|
||||
#include "CCControllerAxisInput.h"
|
||||
#include "CCControllerThumbstick.h"
|
||||
|
||||
#include "ccMacros.h"
|
||||
#include "CCEventDispatcher.h"
|
||||
#include "CCEventController.h"
|
||||
#include "CCEventListenerController.h"
|
||||
#include "CCDirector.h"
|
||||
|
||||
#include "jni/JniHelper.h"
|
||||
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
enum class AndroidControllerCode
|
||||
{
|
||||
THUMBSTICK_LEFT_X = 100,
|
||||
THUMBSTICK_LEFT_Y = 101,
|
||||
THUMBSTICK_RIGHT_X = 102,
|
||||
THUMBSTICK_RIGHT_Y = 103,
|
||||
BUTTON_A = 110,
|
||||
BUTTON_B = 111,
|
||||
BUTTON_C = 112,
|
||||
BUTTON_X = 113,
|
||||
BUTTON_Y = 114,
|
||||
BUTTON_Z = 115,
|
||||
BUTTON_LEFT_SHOULDER = 120,
|
||||
BUTTON_RIGHT_SHOULDER = 121,
|
||||
BUTTON_LEFT_TRIGGER = 122,
|
||||
BUTTON_RIGHT_TRIGGER = 123,
|
||||
BUTTON_DPAD_UP = 130,
|
||||
BUTTON_DPAD_DOWN = 131,
|
||||
BUTTON_DPAD_LEFT = 132,
|
||||
BUTTON_DPAD_RIGHT = 133,
|
||||
BUTTON_DPAD_CENTER = 134,
|
||||
BUTTON_LEFT_THUMBSTICK = 140,
|
||||
BUTTON_RIGHT_THUMBSTICK = 141,
|
||||
BUTTON_START = 150,
|
||||
BUTTON_SELECT = 151,
|
||||
};
|
||||
|
||||
class ControllerImpl
|
||||
{
|
||||
public:
|
||||
ControllerImpl(Controller* controller)
|
||||
: _controller(controller)
|
||||
, _controllerID(-1)
|
||||
{
|
||||
}
|
||||
|
||||
static std::vector<Controller*>::iterator findController(const std::string& vendorName, int controllerID)
|
||||
{
|
||||
auto iter = std::find_if(Controller::_controllers.begin(), Controller::_controllers.end(), [&](Controller* controller){
|
||||
return (vendorName == controller->getVendorName()) && (controllerID == controller->_impl->_controllerID);
|
||||
});
|
||||
}
|
||||
|
||||
static void onConnected(const std::string& vendorName, int controllerID)
|
||||
{
|
||||
// Check whether the controller is already connected.
|
||||
auto iter = findController(vendorName, controllerID);
|
||||
if (iter != Controller::_controllers.end())
|
||||
return;
|
||||
|
||||
// It's a new controller being connected.
|
||||
auto controller = new cocos2d::Controller();
|
||||
controller->_vendorName = vendorName;
|
||||
Controller::_controllers.push_back(controller);
|
||||
controller->_impl->_controllerID = controllerID;
|
||||
EventController evt(EventController::ControllerEventType::CONNECTION, controller, true);
|
||||
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evt);
|
||||
}
|
||||
|
||||
static void onDisconnected(const std::string& vendorName, int controllerID)
|
||||
{
|
||||
auto iter = findController(vendorName, controllerID);
|
||||
if (iter == Controller::_controllers.end())
|
||||
{
|
||||
CCLOGERROR("Could not find the controller!");
|
||||
return;
|
||||
}
|
||||
|
||||
EventController evt(EventController::ControllerEventType::CONNECTION, *iter, false);
|
||||
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evt);
|
||||
|
||||
Controller::_controllers.erase(iter);
|
||||
}
|
||||
|
||||
void sendEventButton(ControllerButtonInput* button, bool isPressed, float value, bool isAnalog)
|
||||
{
|
||||
button->setPressed(isPressed);
|
||||
if (!isAnalog)
|
||||
button->setValue(value);
|
||||
button->setAnalog(isAnalog);
|
||||
EventController evt(EventController::ControllerEventType::BUTTON_STATUS_CHANGED, _controller, button);
|
||||
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evt);
|
||||
}
|
||||
|
||||
void sendEventAxis(ControllerAxisInput* axis, float value, bool isAnalog)
|
||||
{
|
||||
axis->setValue(value);
|
||||
axis->setAnalog(isAnalog);
|
||||
EventController evt(EventController::ControllerEventType::AXIS_STATUS_CHANGED, _controller, axis);
|
||||
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evt);
|
||||
}
|
||||
|
||||
static void onButtonEvent(const std::string& vendorName, int controllerID, AndroidControllerCode btnCode, bool isPressed, float value, bool isAnalog)
|
||||
{
|
||||
auto iter = findController(vendorName, controllerID);
|
||||
if (iter == Controller::_controllers.end())
|
||||
{
|
||||
onConnected(vendorName, controllerID);
|
||||
iter = findController(vendorName, controllerID);
|
||||
}
|
||||
|
||||
auto gamepad = (*iter)->getGamepad();
|
||||
auto thiz = (*iter)->getImpl();
|
||||
switch(btnCode)
|
||||
{
|
||||
case AndroidControllerCode::BUTTON_A:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getButtonA(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_B:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getButtonB(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_X:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getButtonX(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_Y:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getButtonY(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_LEFT_SHOULDER:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getLeftShoulder(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_RIGHT_SHOULDER:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getRightShoulder(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_LEFT_TRIGGER:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getLeftTrigger(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_RIGHT_TRIGGER:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getRightTrigger(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_DPAD_UP:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getDirectionPad()->getUp(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_DPAD_DOWN:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getDirectionPad()->getDown(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_DPAD_LEFT:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getDirectionPad()->getLeft(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_DPAD_RIGHT:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getDirectionPad()->getRight(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_START:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getButtonStart(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_SELECT:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getButtonSelect(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_LEFT_THUMBSTICK:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getLeftThumbstick()->getButton(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
case AndroidControllerCode::BUTTON_RIGHT_THUMBSTICK:
|
||||
{
|
||||
thiz->sendEventButton(gamepad->getRightThumbstick()->getButton(), isPressed, value, isAnalog);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// CCASSERT(false, "Invalid controller button code!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void onAxisEvent(const std::string& vendorName, int controllerID, AndroidControllerCode axisCode, float value, bool isAnalog)
|
||||
{
|
||||
// log("vendorName: %s, controller id: %d, axis: %d, value: %f", vendorName.c_str(), controllerID, axisCode, value);
|
||||
auto iter = findController(vendorName, controllerID);
|
||||
if (iter == Controller::_controllers.end())
|
||||
{
|
||||
onConnected(vendorName, controllerID);
|
||||
iter = findController(vendorName, controllerID);
|
||||
}
|
||||
auto gamepad = (*iter)->getGamepad();
|
||||
auto thiz = (*iter)->getImpl();
|
||||
switch (axisCode)
|
||||
{
|
||||
case AndroidControllerCode::THUMBSTICK_LEFT_X:
|
||||
thiz->sendEventAxis(gamepad->getLeftThumbstick()->getAxisX(), value, isAnalog);
|
||||
break;
|
||||
case AndroidControllerCode::THUMBSTICK_LEFT_Y:
|
||||
thiz->sendEventAxis(gamepad->getLeftThumbstick()->getAxisY(), value, isAnalog);
|
||||
break;
|
||||
case AndroidControllerCode::THUMBSTICK_RIGHT_X:
|
||||
thiz->sendEventAxis(gamepad->getRightThumbstick()->getAxisX(), value, isAnalog);
|
||||
break;
|
||||
case AndroidControllerCode::THUMBSTICK_RIGHT_Y:
|
||||
thiz->sendEventAxis(gamepad->getRightThumbstick()->getAxisY(), value, isAnalog);
|
||||
break;
|
||||
default:
|
||||
CCASSERT(false, "Invalid controller axis code!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Controller* _controller;
|
||||
int _controllerID;
|
||||
};
|
||||
|
||||
|
||||
std::vector<Controller*> Controller::_controllers;
|
||||
|
||||
const std::vector<Controller*>& Controller::getControllers()
|
||||
{
|
||||
return _controllers;
|
||||
}
|
||||
|
||||
void Controller::startDiscoveryController()
|
||||
{
|
||||
// Empty implementation on Android
|
||||
}
|
||||
|
||||
void Controller::stopDiscoveryController()
|
||||
{
|
||||
// Empty implementation on Android
|
||||
}
|
||||
|
||||
const std::string& Controller::getVendorName()
|
||||
{
|
||||
return _vendorName;
|
||||
}
|
||||
|
||||
bool Controller::isConnected() const
|
||||
{
|
||||
// If there is a controller instance, it means that the controller is connected.
|
||||
// If a controller is disconnected, the instance will be destroyed.
|
||||
// So always returns true for this method.
|
||||
return true;
|
||||
}
|
||||
|
||||
int Controller::getPlayerIndex() const
|
||||
{
|
||||
return _playerIndex;
|
||||
}
|
||||
|
||||
void Controller::setPlayerIndex(int playerIndex)
|
||||
{
|
||||
_playerIndex = playerIndex;
|
||||
}
|
||||
|
||||
Gamepad* Controller::getGamepad() const
|
||||
{
|
||||
return _gamepad;
|
||||
}
|
||||
|
||||
Controller::Controller()
|
||||
: _playerIndex(PLAYER_INDEX_UNSET)
|
||||
, _gamepad(new Gamepad)
|
||||
, _impl(new ControllerImpl(this))
|
||||
{
|
||||
_gamepad->_controller = this;
|
||||
}
|
||||
|
||||
Controller::~Controller()
|
||||
{
|
||||
CC_SAFE_DELETE(_impl);
|
||||
CC_SAFE_DELETE(_gamepad);
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerConnected(JNIEnv* env, jobject thiz, jstring vendorName, jint controllerID)
|
||||
{
|
||||
CCLOG("controller id: %d connected!", controllerID);
|
||||
cocos2d::ControllerImpl::onConnected(cocos2d::JniHelper::jstring2string(vendorName), controllerID);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerDisconnected(JNIEnv* env, jobject thiz, jstring vendorName, jint controllerID)
|
||||
{
|
||||
CCLOG("controller id: %d disconnected!", controllerID);
|
||||
cocos2d::ControllerImpl::onDisconnected(cocos2d::JniHelper::jstring2string(vendorName), controllerID);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerButtonEvent(JNIEnv* env, jobject thiz, jstring vendorName, jint controllerID, jint button, jboolean isPressed, jfloat value, jboolean isAnalog)
|
||||
{
|
||||
CCLOG("controller id: %d, btn code: %d, isPressed: %d, value: %f, isAnalog:%d", controllerID, button, (int)isPressed, value, (int)isAnalog);
|
||||
cocos2d::ControllerImpl::onButtonEvent(cocos2d::JniHelper::jstring2string(vendorName), controllerID, static_cast<cocos2d::AndroidControllerCode>(button), isPressed, value, isAnalog);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerAxisEvent(JNIEnv* env, jobject thiz, jstring vendorName, jint controllerID, jint axis, jfloat value, jboolean isAnalog)
|
||||
{
|
||||
// CCLOG("controller id: %d, axis code: %d, value: %f, isAnalog:%d", controllerID, axis, value, (int)isAnalog);
|
||||
cocos2d::ControllerImpl::onAxisEvent(cocos2d::JniHelper::jstring2string(vendorName), controllerID, static_cast<cocos2d::AndroidControllerCode>(axis), value, isAnalog);
|
||||
}
|
||||
|
||||
} // extern "C" {
|
||||
|
||||
|
||||
#endif // #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>libcontrollerdelegate</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.cocos2dx.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="10"/>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,17 @@
|
|||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked into Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="androidcontrollerdelegate" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
|
@ -0,0 +1,20 @@
|
|||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -0,0 +1,55 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public interface GameControllerDelegate {
|
||||
|
||||
public static final int THUMBSTICK_LEFT_X = 100;
|
||||
public static final int THUMBSTICK_LEFT_Y = 101;
|
||||
public static final int THUMBSTICK_RIGHT_X = 102;
|
||||
public static final int THUMBSTICK_RIGHT_Y = 103;
|
||||
|
||||
public static final int BUTTON_A = 110;
|
||||
public static final int BUTTON_B = 111;
|
||||
public static final int BUTTON_C = 112;
|
||||
public static final int BUTTON_X = 113;
|
||||
public static final int BUTTON_Y = 114;
|
||||
public static final int BUTTON_Z = 115;
|
||||
|
||||
public static final int BUTTON_LEFT_SHOULDER = 120;
|
||||
public static final int BUTTON_RIGHT_SHOULDER = 121;
|
||||
public static final int BUTTON_LEFT_TRIGGER = 122;
|
||||
public static final int BUTTON_RIGHT_TRIGGER = 123;
|
||||
|
||||
public static final int BUTTON_DPAD_UP = 130;
|
||||
public static final int BUTTON_DPAD_DOWN = 131;
|
||||
public static final int BUTTON_DPAD_LEFT = 132;
|
||||
public static final int BUTTON_DPAD_RIGHT = 133;
|
||||
public static final int BUTTON_DPAD_CENTER = 134;
|
||||
|
||||
public static final int BUTTON_LEFT_THUMBSTICK = 140;
|
||||
public static final int BUTTON_RIGHT_THUMBSTICK = 141;
|
||||
|
||||
public static final int BUTTON_START = 150;
|
||||
public static final int BUTTON_SELECT = 151;
|
||||
|
||||
void onCreate(Context context);
|
||||
void onPause();
|
||||
void onResume();
|
||||
void onDestroy();
|
||||
|
||||
boolean dispatchKeyEvent(KeyEvent event);
|
||||
boolean dispatchGenericMotionEvent(MotionEvent event);
|
||||
|
||||
void setControllerEventListener(ControllerEventListener listener);
|
||||
|
||||
public interface ControllerEventListener {
|
||||
void onButtonEvent(String vendorName, int controller, int button, boolean isPressed, float value, boolean isAnalog);
|
||||
void onAxisEvent(String vendorName, int controller, int axisID, float value, boolean isAnalog);
|
||||
|
||||
void onConnected(String vendorName, int controller);
|
||||
void onDisconnected(String vendorName, int controller);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>libcontrollermoga</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.cocos2dx.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="10"/>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,17 @@
|
|||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked into Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="androidcontrollermoga" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
Binary file not shown.
|
@ -0,0 +1,23 @@
|
|||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
-libraryjars com.bda.controller.jar
|
||||
-dontwarn com.bda.controller.*
|
||||
-keep class org.cocos2dx.lib.*{*;}
|
|
@ -0,0 +1,191 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import org.cocos2dx.lib.GameControllerDelegate;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.bda.controller.Controller;
|
||||
import com.bda.controller.ControllerListener;
|
||||
import com.bda.controller.KeyEvent;
|
||||
import com.bda.controller.MotionEvent;
|
||||
import com.bda.controller.StateEvent;
|
||||
|
||||
public class GameControllerMoga implements ControllerListener, GameControllerDelegate {
|
||||
|
||||
private static final String mVendorName = "Moga";
|
||||
|
||||
private float mOldLeftThumbstickX = 0.0f;
|
||||
private float mOldLeftThumbstickY = 0.0f;
|
||||
private float mOldRightThumbstickX = 0.0f;
|
||||
private float mOldRightThumbstickY = 0.0f;
|
||||
|
||||
private SparseIntArray mKeyMap = null;
|
||||
|
||||
public GameControllerMoga() {
|
||||
mKeyMap = new SparseIntArray(20);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_A, GameControllerDelegate.BUTTON_A);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_B, GameControllerDelegate.BUTTON_B);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_X, GameControllerDelegate.BUTTON_X);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_Y, GameControllerDelegate.BUTTON_Y);
|
||||
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_L1,
|
||||
GameControllerDelegate.BUTTON_LEFT_SHOULDER);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_R1,
|
||||
GameControllerDelegate.BUTTON_RIGHT_SHOULDER);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_L2,
|
||||
GameControllerDelegate.BUTTON_LEFT_TRIGGER);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_R2,
|
||||
GameControllerDelegate.BUTTON_RIGHT_TRIGGER);
|
||||
|
||||
mKeyMap.put(KeyEvent.KEYCODE_DPAD_UP,
|
||||
GameControllerDelegate.BUTTON_DPAD_UP);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_DPAD_DOWN,
|
||||
GameControllerDelegate.BUTTON_DPAD_DOWN);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_DPAD_LEFT,
|
||||
GameControllerDelegate.BUTTON_DPAD_LEFT);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_DPAD_RIGHT,
|
||||
GameControllerDelegate.BUTTON_DPAD_RIGHT);
|
||||
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_START,
|
||||
GameControllerDelegate.BUTTON_START);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_SELECT,
|
||||
GameControllerDelegate.BUTTON_SELECT);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_START,
|
||||
GameControllerDelegate.BUTTON_START);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_THUMBL,
|
||||
GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
|
||||
mKeyMap.put(KeyEvent.KEYCODE_BUTTON_THUMBR,
|
||||
GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
|
||||
}
|
||||
|
||||
public void onKeyEvent(KeyEvent event) {
|
||||
boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN;
|
||||
int keycode = event.getKeyCode();
|
||||
boolean isAnalog = false;
|
||||
|
||||
if (keycode == KeyEvent.KEYCODE_BUTTON_THUMBL
|
||||
|| keycode == KeyEvent.KEYCODE_BUTTON_THUMBR) {
|
||||
isAnalog = true;
|
||||
}
|
||||
|
||||
if (mKeyMap.get(keycode, Integer.MIN_VALUE) != Integer.MIN_VALUE && mControllerEventListener != null) {
|
||||
mControllerEventListener.onButtonEvent(mVendorName,
|
||||
event.getControllerId(), mKeyMap.get(keycode), isPressed,
|
||||
isPressed ? 1.0f : 0.0f, isAnalog);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionEvent(MotionEvent event) {
|
||||
if (mControllerEventListener == null) {
|
||||
return;
|
||||
}
|
||||
float newLeftThumbstickX = event.getAxisValue(MotionEvent.AXIS_X);
|
||||
if (newLeftThumbstickX != mOldLeftThumbstickX) {
|
||||
mControllerEventListener.onAxisEvent(mVendorName,
|
||||
event.getControllerId(),
|
||||
GameControllerDelegate.THUMBSTICK_LEFT_X,
|
||||
newLeftThumbstickX, true);
|
||||
mOldLeftThumbstickX = newLeftThumbstickX;
|
||||
}
|
||||
|
||||
float newLeftThumbstickY = event.getAxisValue(MotionEvent.AXIS_Y);
|
||||
if (newLeftThumbstickY != mOldLeftThumbstickY) {
|
||||
mControllerEventListener.onAxisEvent(mVendorName,
|
||||
event.getControllerId(),
|
||||
GameControllerDelegate.THUMBSTICK_LEFT_Y,
|
||||
newLeftThumbstickY, true);
|
||||
mOldLeftThumbstickY = newLeftThumbstickY;
|
||||
}
|
||||
|
||||
float newRightThumbstickX = event.getAxisValue(MotionEvent.AXIS_Z);
|
||||
if (newRightThumbstickX != mOldRightThumbstickX) {
|
||||
mControllerEventListener.onAxisEvent(mVendorName,
|
||||
event.getControllerId(),
|
||||
GameControllerDelegate.THUMBSTICK_RIGHT_X,
|
||||
newRightThumbstickX, true);
|
||||
mOldRightThumbstickX = newRightThumbstickX;
|
||||
}
|
||||
|
||||
float newRightThumbstickY = event.getAxisValue(MotionEvent.AXIS_RZ);
|
||||
if (newRightThumbstickY != mOldRightThumbstickY) {
|
||||
mControllerEventListener.onAxisEvent(mVendorName,
|
||||
event.getControllerId(),
|
||||
GameControllerDelegate.THUMBSTICK_RIGHT_Y,
|
||||
newRightThumbstickY, true);
|
||||
mOldRightThumbstickY = newRightThumbstickY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateEvent(StateEvent event) {
|
||||
if (mControllerEventListener != null) {
|
||||
switch (event.getState()) {
|
||||
case StateEvent.STATE_CONNECTION:
|
||||
switch (event.getAction()) {
|
||||
case StateEvent.ACTION_DISCONNECTED:
|
||||
// disconnected from controller
|
||||
mControllerEventListener.onDisconnected(mVendorName,
|
||||
event.getControllerId());
|
||||
break;
|
||||
case StateEvent.ACTION_CONNECTED:
|
||||
// connected to controller
|
||||
mControllerEventListener.onConnected(mVendorName,
|
||||
event.getControllerId());
|
||||
break;
|
||||
case StateEvent.ACTION_CONNECTING:
|
||||
// attempting to connect to controller
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case StateEvent.STATE_POWER_LOW:
|
||||
if (event.getAction() == StateEvent.ACTION_TRUE) {
|
||||
// controller has entered low power state
|
||||
} else {
|
||||
// controller has entered normal power state
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Controller mController = null;
|
||||
|
||||
public void onCreate(Context context) {
|
||||
mController = Controller.getInstance(context);
|
||||
|
||||
mController.init();
|
||||
mController.setListener(this, new Handler());
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
mController.onPause();
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
mController.onResume();
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
mController.exit();
|
||||
}
|
||||
|
||||
private ControllerEventListener mControllerEventListener;
|
||||
@Override
|
||||
public void setControllerEventListener(ControllerEventListener listener) {
|
||||
mControllerEventListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(android.view.KeyEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(android.view.MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>libcontrollernibiru</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.cocos2dx.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="10"/>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,17 @@
|
|||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked into Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="androidcontrollernibiru" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
Binary file not shown.
|
@ -0,0 +1,20 @@
|
|||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -0,0 +1,209 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import org.cocos2dx.lib.GameControllerDelegate;
|
||||
|
||||
import com.nibiru.lib.controller.AccEvent;
|
||||
import com.nibiru.lib.controller.Controller;
|
||||
import com.nibiru.lib.controller.ControllerDevice;
|
||||
import com.nibiru.lib.controller.ControllerKeyEvent;
|
||||
import com.nibiru.lib.controller.ControllerService;
|
||||
import com.nibiru.lib.controller.ControllerService.OnControllerSeviceListener;
|
||||
import com.nibiru.lib.controller.ControllerServiceException;
|
||||
import com.nibiru.lib.controller.GyroEvent;
|
||||
import com.nibiru.lib.controller.OnAccListener;
|
||||
import com.nibiru.lib.controller.OnGyroListener;
|
||||
import com.nibiru.lib.controller.OnKeyListener;
|
||||
import com.nibiru.lib.controller.OnSimpleStickListener;
|
||||
import com.nibiru.lib.controller.OnStateListener;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class GameControllerNibiru implements OnControllerSeviceListener, OnKeyListener,
|
||||
OnSimpleStickListener, OnAccListener, OnGyroListener, OnStateListener, GameControllerDelegate {
|
||||
|
||||
private static final String TAG = "NibiruTag";
|
||||
private static final String mVendorName = "Nibiru";
|
||||
|
||||
private Context mContext;
|
||||
private SparseIntArray mKeyMap;
|
||||
private ControllerEventListener mControllerEventListener = null;
|
||||
private ControllerService mControllerService = null;
|
||||
|
||||
public GameControllerNibiru() {
|
||||
mKeyMap = new SparseIntArray(20);
|
||||
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_A , GameControllerDelegate.BUTTON_A);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_B , GameControllerDelegate.BUTTON_B);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_X , GameControllerDelegate.BUTTON_X);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_Y , GameControllerDelegate.BUTTON_Y);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_L1 , GameControllerDelegate.BUTTON_LEFT_SHOULDER);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_R1 , GameControllerDelegate.BUTTON_RIGHT_SHOULDER);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_L2, GameControllerDelegate.BUTTON_LEFT_TRIGGER);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_R2, GameControllerDelegate.BUTTON_RIGHT_TRIGGER);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_UP , GameControllerDelegate.BUTTON_DPAD_UP);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_DOWN , GameControllerDelegate.BUTTON_DPAD_DOWN);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_LEFT , GameControllerDelegate.BUTTON_DPAD_LEFT);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_RIGHT , GameControllerDelegate.BUTTON_DPAD_RIGHT);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_START , GameControllerDelegate.BUTTON_START);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_SELECT , GameControllerDelegate.BUTTON_SELECT);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_THUMBL , GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
|
||||
mKeyMap.put(ControllerKeyEvent.KEYCODE_BUTTON_THUMBR , GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControllerEventListener(ControllerEventListener listener) {
|
||||
mControllerEventListener = listener;
|
||||
}
|
||||
|
||||
public void onCreate(Context context) {
|
||||
mContext = context;
|
||||
|
||||
mControllerService = Controller.getControllerService();
|
||||
if (mControllerService != null) {
|
||||
mControllerService.setControllerServiceListener(this);
|
||||
mControllerService.setStateListener(this);
|
||||
mControllerService.setKeyListener(this);
|
||||
mControllerService.setSimpleStickListener(this);
|
||||
//mControllerService.setAccListener(this);
|
||||
//mControllerService.setGyroListener(this);
|
||||
mControllerService.setEnableLR2(true);
|
||||
mControllerService.setAutoKeyUpMode(false);
|
||||
|
||||
mControllerService.checkNibiruInstall(mContext, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
if (mControllerService != null) {
|
||||
mControllerService.setEnable(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
if (mControllerService != null) {
|
||||
if (mControllerService.isServiceEnable()) {
|
||||
//onControllerServiceReady(true);
|
||||
} else {
|
||||
if (mControllerService.checkNibiruInstall(mContext, false)) {
|
||||
try {
|
||||
mControllerService.register(mContext);
|
||||
} catch (ControllerServiceException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mControllerService.setEnable(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
if( mControllerService != null ){
|
||||
mControllerService.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControllerServiceReady(boolean isSucc) {
|
||||
if( isSucc )
|
||||
{
|
||||
if( !mControllerService.hasDeviceConnected() ){
|
||||
Bundle bun = new Bundle();
|
||||
bun.putBoolean(ControllerService.FLAG_IS_SHOW_GAMEPAD_TIP, true);
|
||||
try {
|
||||
mControllerService.showDeviceManagerUI(mContext, bun);
|
||||
} catch (ControllerServiceException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControllerKeyDown(int playerOrder, int keyCode, ControllerKeyEvent event) {
|
||||
if (mKeyMap.get(keyCode) == 0) {
|
||||
Log.e(TAG, "Didn't map the key: " + keyCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mControllerEventListener != null) {
|
||||
mControllerEventListener.onButtonEvent(mVendorName, playerOrder, mKeyMap.get(keyCode), true, 1.0f, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControllerKeyUp(int playerOrder, int keyCode, ControllerKeyEvent event) {
|
||||
if (mKeyMap.get(keyCode) == 0) {
|
||||
Log.e(TAG, "Didn't map the key: " + keyCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mControllerEventListener != null) {
|
||||
mControllerEventListener.onButtonEvent(mVendorName, playerOrder,
|
||||
mKeyMap.get(keyCode), false, 0.0f, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeftStickChanged(int playerOrder, float x, float y) {
|
||||
if (mControllerEventListener != null) {
|
||||
mControllerEventListener.onAxisEvent(mVendorName, playerOrder,
|
||||
GameControllerDelegate.THUMBSTICK_LEFT_X, x, true);
|
||||
mControllerEventListener.onAxisEvent(mVendorName, playerOrder,
|
||||
GameControllerDelegate.THUMBSTICK_LEFT_Y, y, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRightStickChanged(int playerOrder, float x, float y) {
|
||||
if (mControllerEventListener != null) {
|
||||
mControllerEventListener.onAxisEvent(mVendorName, playerOrder,
|
||||
GameControllerDelegate.THUMBSTICK_RIGHT_X, x, true);
|
||||
mControllerEventListener.onAxisEvent(mVendorName, playerOrder,
|
||||
GameControllerDelegate.THUMBSTICK_RIGHT_Y, y, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControllerStateChanged(int playerOrder, int state, ControllerDevice device) {
|
||||
if (mControllerEventListener != null) {
|
||||
if (state == ControllerDevice.STATE_CONN)
|
||||
{
|
||||
mControllerEventListener.onConnected(mVendorName, playerOrder);
|
||||
}
|
||||
else if (state == ControllerDevice.STATE_DISCONN)
|
||||
{
|
||||
mControllerEventListener.onDisconnected(mVendorName, playerOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event){
|
||||
return mControllerService.handleExternalInput(event);
|
||||
}
|
||||
|
||||
public boolean dispatchKeyEvent(KeyEvent event){
|
||||
return mControllerService.handleExternalInput(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControllerAccEvent(int playerOrder, AccEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControllerGyroEvent(int playerOrder, GyroEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int state) {
|
||||
Log.d(TAG, "onBluetoothStateChanged:"+state);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>libcontrollerouya</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.cocos2dx.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="10"/>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,17 @@
|
|||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked into Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="androidcontrollerouya" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
Binary file not shown.
|
@ -0,0 +1,20 @@
|
|||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -0,0 +1,182 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
|
||||
import org.cocos2dx.lib.GameControllerDelegate;
|
||||
|
||||
import tv.ouya.console.api.OuyaController;
|
||||
import android.content.Context;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class GameControllerOuya implements GameControllerDelegate{
|
||||
|
||||
public static final String sVendorName = "Ouya";
|
||||
|
||||
private SparseIntArray mKeyMap;
|
||||
|
||||
public GameControllerOuya(){
|
||||
mKeyMap = new SparseIntArray(20);
|
||||
mKeyMap.put(OuyaController.BUTTON_A, GameControllerDelegate.BUTTON_B);
|
||||
mKeyMap.put(OuyaController.BUTTON_O, GameControllerDelegate.BUTTON_A);
|
||||
mKeyMap.put(OuyaController.BUTTON_U, GameControllerDelegate.BUTTON_X);
|
||||
mKeyMap.put(OuyaController.BUTTON_Y, GameControllerDelegate.BUTTON_Y);
|
||||
mKeyMap.put(OuyaController.BUTTON_DPAD_DOWN, GameControllerDelegate.BUTTON_DPAD_DOWN);
|
||||
mKeyMap.put(OuyaController.BUTTON_DPAD_LEFT, GameControllerDelegate.BUTTON_DPAD_LEFT);
|
||||
mKeyMap.put(OuyaController.BUTTON_DPAD_RIGHT, GameControllerDelegate.BUTTON_DPAD_RIGHT);
|
||||
mKeyMap.put(OuyaController.BUTTON_DPAD_UP, GameControllerDelegate.BUTTON_DPAD_UP);
|
||||
mKeyMap.put(OuyaController.BUTTON_L1, GameControllerDelegate.BUTTON_LEFT_SHOULDER);
|
||||
mKeyMap.put(OuyaController.BUTTON_R1, GameControllerDelegate.BUTTON_RIGHT_SHOULDER);
|
||||
mKeyMap.put(OuyaController.AXIS_L2, GameControllerDelegate.BUTTON_LEFT_TRIGGER);
|
||||
mKeyMap.put(OuyaController.AXIS_R2, GameControllerDelegate.BUTTON_RIGHT_TRIGGER);
|
||||
|
||||
mKeyMap.put(OuyaController.AXIS_LS_X, GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
|
||||
mKeyMap.put(OuyaController.AXIS_LS_Y, GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
|
||||
mKeyMap.put(OuyaController.AXIS_RS_X, GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
|
||||
mKeyMap.put(OuyaController.AXIS_RS_Y, GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
|
||||
}
|
||||
|
||||
public void onCreate(Context context) {
|
||||
OuyaController.init(context);
|
||||
/*GameControllerAdapter.addRunnableToFrameStartList(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
OuyaController.startOfFrame();
|
||||
}
|
||||
|
||||
});*/
|
||||
}
|
||||
|
||||
private float mOldLeftThumbstickX = 0.0f;
|
||||
private float mOldLeftThumbstickY = 0.0f;
|
||||
private float mOldRightThumbstickX = 0.0f;
|
||||
private float mOldRightThumbstickY = 0.0f;
|
||||
|
||||
private float mOldLeftTrigger = 0.0f;
|
||||
private float mOldRightTrigger = 0.0f;
|
||||
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event) {
|
||||
boolean handled = OuyaController.onGenericMotionEvent(event);
|
||||
|
||||
if (handled && mControllerEventListener != null)
|
||||
{
|
||||
OuyaController c = OuyaController.getControllerByDeviceId(event.getDeviceId());
|
||||
int controllerID = OuyaController.getPlayerNumByDeviceId(event.getDeviceId());
|
||||
|
||||
float newLeftTrigger = c.getAxisValue(OuyaController.AXIS_L2);
|
||||
if (Float.compare(newLeftTrigger, mOldLeftTrigger) != 0) {
|
||||
if (Float.compare(newLeftTrigger, 0.0f) == 0) {
|
||||
mControllerEventListener.onButtonEvent(sVendorName, controllerID, GameControllerDelegate.BUTTON_LEFT_TRIGGER, false, 0.0f, true);
|
||||
}else {
|
||||
mControllerEventListener.onButtonEvent(sVendorName, controllerID, GameControllerDelegate.BUTTON_LEFT_TRIGGER, true, newLeftTrigger, true);
|
||||
}
|
||||
mOldLeftTrigger = newLeftTrigger;
|
||||
}
|
||||
|
||||
float newRightTrigger = c.getAxisValue(OuyaController.AXIS_R2);
|
||||
if (Float.compare(newRightTrigger, mOldRightTrigger) != 0) {
|
||||
if (Float.compare(newRightTrigger, 0.0f) == 0) {
|
||||
mControllerEventListener.onButtonEvent(sVendorName, controllerID, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, false, 0.0f, true);
|
||||
}else {
|
||||
mControllerEventListener.onButtonEvent(sVendorName, controllerID, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, true, newRightTrigger, true);
|
||||
}
|
||||
mOldRightTrigger = newRightTrigger;
|
||||
}
|
||||
|
||||
float newLeftThumbstickX = c.getAxisValue(OuyaController.AXIS_LS_X);
|
||||
if (Float.compare(newLeftThumbstickX, mOldLeftThumbstickX) != 0) {
|
||||
if (Float.compare(newLeftThumbstickX, 0.0f) == 0) {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_LEFT_X, 0.0f, true);
|
||||
}else {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_LEFT_X, newLeftThumbstickX, true);
|
||||
}
|
||||
mOldLeftThumbstickX = newLeftThumbstickX;
|
||||
}
|
||||
|
||||
float newLeftThumbstickY = c.getAxisValue(OuyaController.AXIS_LS_Y);
|
||||
if (Float.compare(newLeftThumbstickY, mOldLeftThumbstickY) != 0) {
|
||||
if (Float.compare(newLeftThumbstickY, 0.0f) == 0) {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_LEFT_Y, 0.0f, true);
|
||||
}else {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_LEFT_Y, newLeftThumbstickY, true);
|
||||
}
|
||||
mOldLeftThumbstickY = newLeftThumbstickY;
|
||||
}
|
||||
|
||||
float newRightThumbstickX = c.getAxisValue(OuyaController.AXIS_RS_X);
|
||||
if (Float.compare(newRightThumbstickX, mOldRightThumbstickX) != 0) {
|
||||
if (Float.compare(newRightThumbstickX, 0.0f) == 0) {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_RIGHT_X, 0.0f, true);
|
||||
}else {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_RIGHT_X, newRightThumbstickX, true);
|
||||
}
|
||||
mOldRightThumbstickX = newRightThumbstickX;
|
||||
}
|
||||
|
||||
float newRightThumbstickY = c.getAxisValue(OuyaController.AXIS_RS_Y);
|
||||
if (Float.compare(newRightThumbstickY, mOldRightThumbstickY) != 0) {
|
||||
if (Float.compare(newRightThumbstickY, 0.0f) == 0) {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_RIGHT_Y, 0.0f, true);
|
||||
}else {
|
||||
mControllerEventListener.onAxisEvent(sVendorName, controllerID, GameControllerDelegate.THUMBSTICK_RIGHT_Y, newRightThumbstickY, true);
|
||||
}
|
||||
mOldRightThumbstickY = newRightThumbstickY;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
boolean handled = false;
|
||||
int action = event.getAction();
|
||||
int keyCode = event.getKeyCode();
|
||||
|
||||
if (action == KeyEvent.ACTION_DOWN) {
|
||||
handled = OuyaController.onKeyDown(keyCode, event);
|
||||
}
|
||||
else if (action == KeyEvent.ACTION_UP) {
|
||||
handled = OuyaController.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
if (handled && mControllerEventListener != null) {
|
||||
boolean isAnalog = false;
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BUTTON_THUMBL || keyCode == KeyEvent.KEYCODE_BUTTON_THUMBR){
|
||||
isAnalog = true;
|
||||
}
|
||||
|
||||
int controllerID = OuyaController.getPlayerNumByDeviceId(event.getDeviceId());
|
||||
if (action == KeyEvent.ACTION_DOWN) {
|
||||
mControllerEventListener.onButtonEvent(sVendorName, controllerID, mKeyMap.get(keyCode), true, 1.0f, isAnalog);
|
||||
}else {
|
||||
mControllerEventListener.onButtonEvent(sVendorName, controllerID, mKeyMap.get(keyCode), false, 0.0f, isAnalog);
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
// show the mouse cursor
|
||||
OuyaController.showCursor(true);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
// hide the mouse cursor
|
||||
OuyaController.showCursor(false);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
|
||||
private ControllerEventListener mControllerEventListener;
|
||||
|
||||
@Override
|
||||
public void setControllerEventListener(ControllerEventListener listener) {
|
||||
mControllerEventListener = listener;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
<issue id="InlinedApi">
|
||||
<ignore path="src/org/cocos2dx/lib/GameControllerHelper.java" />
|
||||
</issue>
|
||||
<issue id="NewApi">
|
||||
<ignore path="src/org/cocos2dx/lib/Cocos2dxActivity.java" />
|
||||
<ignore path="src/org/cocos2dx/lib/GameControllerHelper.java" />
|
||||
</issue>
|
||||
</lint>
|
|
@ -0,0 +1,77 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GameControllerAdapter {
|
||||
private static ArrayList<Runnable> sRunnableFrameStartList = null;
|
||||
|
||||
public static void addRunnableToFrameStartList(Runnable runnable) {
|
||||
if (sRunnableFrameStartList == null)
|
||||
sRunnableFrameStartList = new ArrayList<Runnable>();
|
||||
sRunnableFrameStartList.add(runnable);
|
||||
}
|
||||
|
||||
public static void removeRunnableFromFrameStartList(Runnable runnable) {
|
||||
if (sRunnableFrameStartList != null)
|
||||
sRunnableFrameStartList.remove(runnable);
|
||||
}
|
||||
|
||||
public static void onDrawFrameStart() {
|
||||
if (sRunnableFrameStartList != null)
|
||||
{
|
||||
int size = sRunnableFrameStartList.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
sRunnableFrameStartList.get(i).run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void onConnected(final String vendorName, final int controller)
|
||||
{
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
nativeControllerConnected(vendorName, controller);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void onDisconnected(final String vendorName, final int controller)
|
||||
{
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
nativeControllerDisconnected(vendorName, controller);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void onButtonEvent(final String vendorName, final int controller, final int button, final boolean isPressed, final float value, final boolean isAnalog)
|
||||
{
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
nativeControllerButtonEvent(vendorName, controller, button, isPressed, value, isAnalog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void onAxisEvent(final String vendorName, final int controller, final int axisID, final float value, final boolean isAnalog)
|
||||
{
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
nativeControllerAxisEvent(vendorName, controller, axisID, value, isAnalog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static native void nativeControllerConnected(final String vendorName, final int controller);
|
||||
private static native void nativeControllerDisconnected(final String vendorName, final int controller);
|
||||
private static native void nativeControllerButtonEvent(final String vendorName, final int controller, final int button, final boolean isPressed, final float value, final boolean isAnalog);
|
||||
private static native void nativeControllerAxisEvent(final String vendorName, final int controller, final int axisID, final float value, final boolean isAnalog);
|
||||
}
|
|
@ -0,0 +1,870 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.apache.http.Header;
|
||||
|
||||
import com.loopj.android.http.AsyncHttpClient;
|
||||
import com.loopj.android.http.FileAsyncHttpResponseHandler;
|
||||
import com.loopj.android.http.JsonHttpResponseHandler;
|
||||
|
||||
import dalvik.system.DexClassLoader;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class GameControllerHelper {
|
||||
|
||||
private final static String TAG = GameControllerHelper.class.getSimpleName();
|
||||
|
||||
public static final String StandardControllerName = "Standard";
|
||||
public static final String[] DRIVERS_NAME = {"nibiru","moga","ouya",StandardControllerName};
|
||||
|
||||
public static final int DRIVERTYPE_NIBIRU = 0;
|
||||
public static final int DRIVERTYPE_MOGA = 1;
|
||||
public static final int DRIVERTYPE_OUYA = 2;
|
||||
public static final int DRIVERTYPE_STANDARD = 3;
|
||||
public static final int DRIVERTYPE_UNKNOWN = 4;
|
||||
|
||||
public static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
|
||||
|
||||
SparseIntArray ControllerKeyMap;
|
||||
|
||||
private static final String COCOS_CONTROLLER_URL = "http://115.28.134.83:9000/download/cocoscontroller/";
|
||||
private static final String COCOS_CONTROLLER_CONFIG = "controller.json";
|
||||
|
||||
private static final String NIBIRU_DEP_PACKAGE = "com.nibiru";
|
||||
private static final String MOGA__DEP_PACKAGE = "com.bda.pivot.mogapgp";
|
||||
|
||||
private static Cocos2dxActivity sCocos2dxActivity;
|
||||
private static GameControllerHelper sControllerHelper;
|
||||
|
||||
private List<String> mNibiruSupportedDrives;
|
||||
private String mNibiruDepFileName;
|
||||
private String mNibiruLibFileName;
|
||||
private int mNibiruLibFileSize;
|
||||
private int mNibiruDepFileSize;
|
||||
|
||||
private List<String> mMogaSupportedDrives;
|
||||
private String mMogaDepFileName;
|
||||
private String mMogaLibFileName;
|
||||
private int mMogaLibFileSize;
|
||||
private int mMogaDepFileSize;
|
||||
|
||||
private List<String> mOuyaSupportedDrives;
|
||||
private String mOuyaLibFileName;
|
||||
private int mOuyaLibFileSize;
|
||||
|
||||
private AsyncHttpClient mDownDepsHttpClient = null;
|
||||
|
||||
private BluetoothAdapter mBluetoothAdapter = null;
|
||||
private ArrayList<BluetoothDevice> mBluetoothDevices = null;
|
||||
private SparseIntArray mDevicesDriver;
|
||||
private int mClearDevices = 0;
|
||||
|
||||
private String mConfigFilePath;
|
||||
private String mLocalSavePath = null;
|
||||
|
||||
private boolean mLazyInit = true;
|
||||
private boolean mLazyConfigInit = true;
|
||||
private static ControllerListener mControllerListener = null;
|
||||
|
||||
public static interface ControllerListener{
|
||||
void onDownloadConfigStarted();
|
||||
void onDownloadConfigFinished(boolean isSuccess);
|
||||
|
||||
void onControllerDiscoveryStarted();
|
||||
//
|
||||
void onControllerDiscoveryFinish(ArrayList<BluetoothDevice> devices);
|
||||
|
||||
void onDownloadDepsStarted();
|
||||
void onDownloadDepsProgress(int bytesWritten, int totalSize);
|
||||
void onDownloadDepsFinished(boolean isSuccess);
|
||||
|
||||
void onInstallDriver(String filePath);
|
||||
void onConnectController();
|
||||
}
|
||||
|
||||
public void setControllerListener(ControllerListener listener){
|
||||
mControllerListener = listener;
|
||||
}
|
||||
|
||||
public GameControllerHelper(Cocos2dxActivity activity){
|
||||
sCocos2dxActivity = activity;
|
||||
sControllerHelper = this;
|
||||
|
||||
ControllerKeyMap = new SparseIntArray(25);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_A, GameControllerDelegate.BUTTON_A);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_B, GameControllerDelegate.BUTTON_B);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_C, GameControllerDelegate.BUTTON_C);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_X, GameControllerDelegate.BUTTON_X);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_Y, GameControllerDelegate.BUTTON_Y);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_Z, GameControllerDelegate.BUTTON_Z);
|
||||
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_DPAD_UP, GameControllerDelegate.BUTTON_DPAD_UP);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_DPAD_DOWN, GameControllerDelegate.BUTTON_DPAD_DOWN);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_DPAD_LEFT, GameControllerDelegate.BUTTON_DPAD_LEFT);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_DPAD_RIGHT, GameControllerDelegate.BUTTON_DPAD_RIGHT);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_DPAD_CENTER, GameControllerDelegate.BUTTON_DPAD_CENTER);
|
||||
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_THUMBL, GameControllerDelegate.BUTTON_LEFT_THUMBSTICK);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_THUMBR, GameControllerDelegate.BUTTON_RIGHT_THUMBSTICK);
|
||||
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_L1, GameControllerDelegate.BUTTON_LEFT_SHOULDER);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_R1, GameControllerDelegate.BUTTON_RIGHT_SHOULDER);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_L2, GameControllerDelegate.BUTTON_LEFT_TRIGGER);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_R2, GameControllerDelegate.BUTTON_RIGHT_TRIGGER);
|
||||
|
||||
ControllerKeyMap.put(MotionEvent.AXIS_X, GameControllerDelegate.THUMBSTICK_LEFT_X);
|
||||
ControllerKeyMap.put(MotionEvent.AXIS_Y, GameControllerDelegate.THUMBSTICK_LEFT_Y);
|
||||
ControllerKeyMap.put(MotionEvent.AXIS_Z, GameControllerDelegate.THUMBSTICK_RIGHT_X);
|
||||
ControllerKeyMap.put(MotionEvent.AXIS_RZ, GameControllerDelegate.THUMBSTICK_RIGHT_Y);
|
||||
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_START, GameControllerDelegate.BUTTON_START);
|
||||
ControllerKeyMap.put(KeyEvent.KEYCODE_BUTTON_SELECT, GameControllerDelegate.BUTTON_SELECT);
|
||||
//KEYCODE_BUTTON_MODE
|
||||
}
|
||||
|
||||
public void connectController(){
|
||||
if (mLazyInit) {
|
||||
mLazyInit = false;
|
||||
mNibiruSupportedDrives = new ArrayList<String>(30);
|
||||
mMogaSupportedDrives = new ArrayList<String>(5);
|
||||
mOuyaSupportedDrives = new ArrayList<String>(5);
|
||||
|
||||
mLocalSavePath = Environment.getExternalStorageDirectory() + File.separator + "CocosGameController" + File.separator;
|
||||
mConfigFilePath = sCocos2dxActivity.getFilesDir().getAbsolutePath() + File.separator + COCOS_CONTROLLER_CONFIG;
|
||||
mDownDepsHttpClient = new AsyncHttpClient();
|
||||
mDownDepsHttpClient.setTimeout(360 * 1000);
|
||||
}
|
||||
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadConfigStarted();
|
||||
}
|
||||
if (mLazyConfigInit) {
|
||||
if (mDownDepsHttpClient != null) {
|
||||
mDownDepsHttpClient.cancelRequests(sCocos2dxActivity, true);
|
||||
}
|
||||
requestControllerConfig();
|
||||
}
|
||||
else {
|
||||
scanBluetoothDrive();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<BluetoothDevice> getBondedDevices(){
|
||||
if (mBluetoothAdapter == null) {
|
||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (mBluetoothAdapter == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return mBluetoothAdapter.getBondedDevices();
|
||||
}
|
||||
|
||||
public void destrory(){
|
||||
if (mDownDepsHttpClient != null) {
|
||||
mDownDepsHttpClient.cancelRequests(sCocos2dxActivity, true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean scanBluetoothDrive(){
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadConfigFinished(true);
|
||||
}
|
||||
|
||||
if (mBluetoothAdapter == null) {
|
||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (mBluetoothAdapter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mBluetoothDevices == null) {
|
||||
mBluetoothDevices = new ArrayList<BluetoothDevice>(5);
|
||||
mDevicesDriver = new SparseIntArray();
|
||||
}
|
||||
|
||||
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
|
||||
//filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
|
||||
//filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
|
||||
//filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
|
||||
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
|
||||
sCocos2dxActivity.registerReceiver(mBluetoothReceiver, filter);
|
||||
|
||||
IntentFilter appFilter = new IntentFilter();
|
||||
appFilter.addAction("android.intent.action.PACKAGE_ADDED");
|
||||
appFilter.addDataScheme("package");
|
||||
sCocos2dxActivity.registerReceiver(mAppReceiver, appFilter);
|
||||
}
|
||||
|
||||
if (!mBluetoothAdapter.isEnabled()) {
|
||||
mBluetoothAdapter.enable();
|
||||
}
|
||||
|
||||
if (mBluetoothAdapter.isDiscovering()) {
|
||||
mBluetoothAdapter.cancelDiscovery();
|
||||
}
|
||||
|
||||
mBluetoothAdapter.startDiscovery();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int checkDriverType(BluetoothDevice device){
|
||||
String deviceName = device.getName();
|
||||
|
||||
if (mNibiruSupportedDrives.contains(deviceName)) {
|
||||
return DRIVERTYPE_NIBIRU;
|
||||
}
|
||||
else if (mMogaSupportedDrives.contains(deviceName)) {
|
||||
return DRIVERTYPE_MOGA;
|
||||
}
|
||||
else if (mOuyaSupportedDrives.contains(deviceName)) {
|
||||
return DRIVERTYPE_OUYA;
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
return DRIVERTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public static void installApplication(String filePath){
|
||||
if (sCocos2dxActivity != null) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
sCocos2dxActivity.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkApplication(String packName){
|
||||
try {
|
||||
ApplicationInfo applicationInfo = sCocos2dxActivity.getPackageManager().getApplicationInfo(packName, PackageManager.GET_UNINSTALLED_PACKAGES);
|
||||
Log.d(TAG, applicationInfo.toString());
|
||||
return true;
|
||||
} catch (NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
if (mBluetoothDevices.contains(device)) {
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Remote device discovered :" + device.getName());
|
||||
//We can't ensure non-controller can be filtered out.Some game controller marked with computer class.
|
||||
/*String deviceName = device.getName();
|
||||
|
||||
if(device.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.COMPUTER
|
||||
|| device.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.PHONE)
|
||||
{
|
||||
Log.w(TAG, "Remote device discovered :" + deviceName + " is computer or phone." + device.getBluetoothClass().getMajorDeviceClass());
|
||||
return;
|
||||
}*/
|
||||
|
||||
mBluetoothDevices.add(device);
|
||||
int type = checkDriverType(device);
|
||||
if (type != DRIVERTYPE_UNKNOWN) {
|
||||
mTargetDriverType = type;
|
||||
mClearDevices += 1;
|
||||
}
|
||||
mDevicesDriver.append(mBluetoothDevices.size() - 1, type);
|
||||
}
|
||||
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
|
||||
Log.d(TAG, "The local Bluetooth adapter has finished the device discovery process.");
|
||||
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onControllerDiscoveryFinish(mBluetoothDevices);
|
||||
}
|
||||
else {
|
||||
if (mBluetoothDevices.size() == 0) {
|
||||
if (checkApplication(NIBIRU_DEP_PACKAGE)) {
|
||||
downControllerDeps(DRIVERTYPE_NIBIRU);
|
||||
}
|
||||
Log.w(TAG, "Not found any supported bluetooth game controller!");
|
||||
}else {
|
||||
if (mClearDevices == 1 ) {
|
||||
downControllerDeps(mTargetDriverType);
|
||||
}
|
||||
else {
|
||||
Log.i(TAG, "More than one device");
|
||||
//todo:show sel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
|
||||
Log.d(TAG, "The local Bluetooth adapter has started the remote device discovery process.");
|
||||
if(mControllerListener != null){
|
||||
mControllerListener.onControllerDiscoveryStarted();
|
||||
}
|
||||
|
||||
mBluetoothDevices.clear();
|
||||
mDevicesDriver.clear();
|
||||
mClearDevices = 0;
|
||||
mTargetDriverType = DRIVERTYPE_UNKNOWN;
|
||||
|
||||
//check moga controller
|
||||
Iterator<BluetoothDevice> it = mBluetoothAdapter.getBondedDevices().iterator();
|
||||
while (it.hasNext()) {
|
||||
BluetoothDevice device = it.next();
|
||||
//if(device.getBluetoothClass().getMajorDeviceClass() != BluetoothClass.Device.Major.COMPUTER
|
||||
// && device.getBluetoothClass().getMajorDeviceClass() != BluetoothClass.Device.Major.PHONE)
|
||||
{
|
||||
if (!mBluetoothDevices.contains(device)) {
|
||||
mBluetoothDevices.add(device);
|
||||
int type = checkDriverType(device);
|
||||
Log.d(TAG, "BluetoothDevice objects that are bonded (paired) to the local adapter :" + device.getName());
|
||||
if (type != DRIVERTYPE_UNKNOWN) {
|
||||
mClearDevices += 1;
|
||||
mTargetDriverType = type;
|
||||
}
|
||||
mDevicesDriver.append(mBluetoothDevices.size() - 1, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static int depsCount = 0;
|
||||
private static int mTargetDriverType = DRIVERTYPE_UNKNOWN;
|
||||
|
||||
private static int mDownloadTotalSize;
|
||||
private static int mDownloadLibSize;
|
||||
private static int mLibDownloadCompletedSize;
|
||||
private static int mDepDownloadCompletedSize;
|
||||
|
||||
public void downControllerDeps(int driverType){
|
||||
if (driverType == DRIVERTYPE_STANDARD || driverType == DRIVERTYPE_UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadDepsStarted();
|
||||
}
|
||||
|
||||
mDownloadTotalSize = 0;
|
||||
mLibDownloadCompletedSize = 0;
|
||||
mDepDownloadCompletedSize = 0;
|
||||
|
||||
mTargetDriverType = driverType;
|
||||
depsCount = 1;
|
||||
|
||||
GameControllerUtils.ensureDirectoryExist(mLocalSavePath);
|
||||
|
||||
String remoteDir = COCOS_CONTROLLER_URL + DRIVERS_NAME[driverType] + File.separator;
|
||||
|
||||
if (driverType == DRIVERTYPE_NIBIRU) {
|
||||
mDownloadLibSize = mNibiruLibFileSize;
|
||||
mDownloadTotalSize += mNibiruLibFileSize;
|
||||
if (!checkApplication(NIBIRU_DEP_PACKAGE)) {
|
||||
depsCount += 1;
|
||||
mDownloadTotalSize += mNibiruDepFileSize;
|
||||
mDownDepsHttpClient.get(remoteDir + mNibiruDepFileName, new MyDepsAsyncHandler(
|
||||
new File(mLocalSavePath + mNibiruDepFileName), MyDepsAsyncHandler.FILETYPE_DEP_APK));
|
||||
}
|
||||
|
||||
File libFile = new File(mLocalSavePath + mNibiruLibFileName);
|
||||
if (libFile.exists() && libFile.length() == mNibiruLibFileSize) {
|
||||
depsCount -= 1;
|
||||
if (depsCount == 0) {
|
||||
onDepsReady();
|
||||
}
|
||||
}
|
||||
else {
|
||||
mDownDepsHttpClient.get(remoteDir + mNibiruLibFileName, new MyDepsAsyncHandler(
|
||||
libFile, MyDepsAsyncHandler.FILETYPE_JAR));
|
||||
}
|
||||
|
||||
}
|
||||
else if (driverType == DRIVERTYPE_MOGA) {
|
||||
mDownloadLibSize = mMogaLibFileSize;
|
||||
mDownloadTotalSize += mMogaLibFileSize;
|
||||
if (!checkApplication(MOGA__DEP_PACKAGE)) {
|
||||
mDownloadTotalSize += mMogaDepFileSize;
|
||||
depsCount += 1;
|
||||
mDownDepsHttpClient.get(remoteDir + mMogaDepFileName, new MyDepsAsyncHandler(
|
||||
new File(mLocalSavePath + mMogaDepFileName), MyDepsAsyncHandler.FILETYPE_DEP_APK));
|
||||
}
|
||||
|
||||
File libFile = new File(mLocalSavePath + mMogaLibFileName);
|
||||
if (libFile.exists() && libFile.length() == mMogaLibFileSize) {
|
||||
depsCount -= 1;
|
||||
if (depsCount == 0) {
|
||||
onDepsReady();
|
||||
}
|
||||
}else {
|
||||
mDownDepsHttpClient.get(remoteDir + mMogaLibFileName, new MyDepsAsyncHandler(
|
||||
libFile, MyDepsAsyncHandler.FILETYPE_JAR));
|
||||
}
|
||||
}
|
||||
else if(driverType == DRIVERTYPE_OUYA){
|
||||
mDownloadLibSize = mOuyaLibFileSize;
|
||||
mDownloadTotalSize += mOuyaLibFileSize;
|
||||
|
||||
File libFile = new File(mLocalSavePath + mOuyaLibFileName);
|
||||
if (libFile.exists() && libFile.length() == mOuyaLibFileSize) {
|
||||
depsCount -= 1;
|
||||
if (depsCount == 0) {
|
||||
onDepsReady();
|
||||
}
|
||||
}else {
|
||||
mDownDepsHttpClient.get(remoteDir + mOuyaLibFileName, new MyDepsAsyncHandler(
|
||||
new File(mLocalSavePath + mOuyaLibFileName), MyDepsAsyncHandler.FILETYPE_JAR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MyDepsAsyncHandler extends FileAsyncHttpResponseHandler{
|
||||
|
||||
public static final int FILETYPE_DEP_APK = 0;
|
||||
public static final int FILETYPE_JAR = 1;
|
||||
|
||||
private int mFileType = FILETYPE_DEP_APK;
|
||||
|
||||
public MyDepsAsyncHandler(File file, int fileType) {
|
||||
super(file);
|
||||
mFileType = fileType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int statusCode, Header[] headers,
|
||||
Throwable e, File file) {
|
||||
if (mFileType == FILETYPE_JAR) {
|
||||
if (file.exists() && file.length() == mDownloadLibSize) {
|
||||
depsCount -= 1;
|
||||
if (depsCount == 0) {
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadDepsFinished(true);
|
||||
}
|
||||
sControllerHelper.onDepsReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mFileType == FILETYPE_DEP_APK) {
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadDepsFinished(false);
|
||||
}
|
||||
}
|
||||
|
||||
Log.e(TAG,"Failed to download:" + file.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(File file) {
|
||||
Log.d(TAG, "Down file success:" + file.getName());
|
||||
|
||||
depsCount -= 1;
|
||||
if (depsCount == 0) {
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadDepsFinished(true);
|
||||
}
|
||||
sControllerHelper.onDepsReady();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(int bytesWritten, int totalSize) {
|
||||
if (mFileType == FILETYPE_JAR) {
|
||||
mLibDownloadCompletedSize = bytesWritten;
|
||||
} else {
|
||||
mDepDownloadCompletedSize = bytesWritten;
|
||||
}
|
||||
if (mControllerListener != null) {
|
||||
|
||||
mControllerListener.onDownloadDepsProgress(mLibDownloadCompletedSize + mDepDownloadCompletedSize, mDownloadTotalSize);
|
||||
}
|
||||
Log.d(TAG, "totalSize:" + totalSize + ", bytesWritten:" + bytesWritten);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDepsReady(){
|
||||
Log.d(TAG, "onDepsReady:" + mTargetDriverType);
|
||||
|
||||
if (mTargetDriverType == DRIVERTYPE_NIBIRU) {
|
||||
if (checkApplication(NIBIRU_DEP_PACKAGE)) {
|
||||
createControllerInstance(mLocalSavePath + mNibiruLibFileName, mTargetDriverType);
|
||||
}
|
||||
else {
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onInstallDriver(mLocalSavePath + mMogaDepFileName);
|
||||
}
|
||||
installApplication(mLocalSavePath + mNibiruDepFileName);
|
||||
}
|
||||
}
|
||||
else if (mTargetDriverType == DRIVERTYPE_MOGA) {
|
||||
if (checkApplication(MOGA__DEP_PACKAGE)) {
|
||||
createControllerInstance(mLocalSavePath + mMogaLibFileName, mTargetDriverType);
|
||||
}
|
||||
else {
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onInstallDriver(mLocalSavePath + mMogaDepFileName);
|
||||
}
|
||||
installApplication(mLocalSavePath + mMogaDepFileName);
|
||||
}
|
||||
}
|
||||
else if (mTargetDriverType == DRIVERTYPE_OUYA) {
|
||||
/*if (checkApplication(OUYA_FRAMEWORK_PACKAGE)) {
|
||||
if (checkApplication(OUYA_LAUNCHER_PACKAGE)) {
|
||||
createControllerInstance(mLocalSavePath + mOuyaLibFileName, mTargetSDK);
|
||||
}
|
||||
else {
|
||||
installApplication(mLocalSavePath + mOuyaLauncherFileName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
installApplication(mLocalSavePath + mOuyaFrameworkFileName);
|
||||
}*/
|
||||
createControllerInstance(mLocalSavePath + mOuyaLibFileName, mTargetDriverType);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CONFIGKEY_DRIVES = "drives";
|
||||
private static final String CONFIGKEY_LIB_FILENAME = "lib";
|
||||
private static final String CONFIGKEY_LIB_FILESIZE = "lib-size";
|
||||
private static final String CONFIGKEY_DEP_FILENAME = "dep-apk";
|
||||
private static final String CONFIGKEY_DEP_FILESIZE = "dep-size";
|
||||
|
||||
private boolean parseConfig(String jsonString){
|
||||
mMogaSupportedDrives.clear();
|
||||
mNibiruSupportedDrives.clear();
|
||||
mOuyaSupportedDrives.clear();
|
||||
|
||||
try {
|
||||
JSONObject configObject = new JSONObject(jsonString);
|
||||
|
||||
JSONObject nibiruObject = configObject.getJSONObject("nibiru");
|
||||
JSONArray drives = nibiruObject.getJSONArray(CONFIGKEY_DRIVES);
|
||||
int count = drives.length();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mNibiruSupportedDrives.add(drives.getString(i));
|
||||
}
|
||||
mNibiruDepFileName = nibiruObject.getString(CONFIGKEY_DEP_FILENAME);
|
||||
mNibiruDepFileSize = nibiruObject.getInt(CONFIGKEY_DEP_FILESIZE);
|
||||
mNibiruLibFileName = nibiruObject.getString(CONFIGKEY_LIB_FILENAME);
|
||||
mNibiruLibFileSize = nibiruObject.getInt(CONFIGKEY_LIB_FILESIZE);
|
||||
|
||||
JSONObject mogaObject = configObject.getJSONObject("moga");
|
||||
drives = mogaObject.getJSONArray(CONFIGKEY_DRIVES);
|
||||
count = drives.length();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mMogaSupportedDrives.add(drives.getString(i));
|
||||
}
|
||||
mMogaDepFileName = mogaObject.getString(CONFIGKEY_DEP_FILENAME);
|
||||
mMogaDepFileSize = mogaObject.getInt(CONFIGKEY_DEP_FILESIZE);
|
||||
mMogaLibFileName = mogaObject.getString(CONFIGKEY_LIB_FILENAME);
|
||||
mMogaLibFileSize = mogaObject.getInt(CONFIGKEY_LIB_FILESIZE);
|
||||
|
||||
JSONObject ouyaObject = configObject.getJSONObject("ouya");
|
||||
drives = ouyaObject.getJSONArray(CONFIGKEY_DRIVES);
|
||||
count = drives.length();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mOuyaSupportedDrives.add(drives.getString(i));
|
||||
}
|
||||
mOuyaLibFileName = ouyaObject.getString(CONFIGKEY_LIB_FILENAME);
|
||||
mOuyaLibFileSize = ouyaObject.getInt(CONFIGKEY_LIB_FILESIZE);
|
||||
//mOuyaFrameworkFileName = ouyaObject.getString("dep-framework");
|
||||
//mOuyaLauncherFileName = ouyaObject.getString("dep-launcher");
|
||||
mLazyConfigInit = false;
|
||||
return true;
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void requestControllerConfig() {
|
||||
|
||||
final JsonHttpResponseHandler configResponseHandler = new JsonHttpResponseHandler() {
|
||||
|
||||
@Override
|
||||
public void onFailure(int statusCode, Header[] headers,
|
||||
String responseBody, Throwable e) {
|
||||
|
||||
Log.e(TAG, "Failed to download game controller config!");
|
||||
|
||||
String configJSON = GameControllerUtils.readJsonFile(mConfigFilePath);
|
||||
if (configJSON != null) {
|
||||
if (parseConfig(configJSON)) {
|
||||
scanBluetoothDrive();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadConfigFinished(false);
|
||||
}
|
||||
/*new AlertDialog.Builder(sCocos2dxActivity)
|
||||
.setTitle("Loading controller config failed!")
|
||||
.setMessage(
|
||||
"Please make sure internet connection works ok!")
|
||||
.setPositiveButton("Retry",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
dialog.dismiss();
|
||||
requestControllerConfig();
|
||||
}
|
||||
}).setCancelable(false).show();*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers,
|
||||
String responseBody) {
|
||||
|
||||
String jsonString = responseBody.trim();
|
||||
|
||||
try {
|
||||
if (parseConfig(jsonString)) {
|
||||
scanBluetoothDrive();
|
||||
showToast("Get controller config succeed!");
|
||||
|
||||
File configFile = new File(mConfigFilePath);
|
||||
FileOutputStream outputStream = new FileOutputStream(configFile);
|
||||
byte[] contentString = jsonString.getBytes();
|
||||
outputStream.write(contentString, 0, contentString.length);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
String jsonStr = GameControllerUtils.readJsonFile(mConfigFilePath);
|
||||
if (jsonStr != null) {
|
||||
if (parseConfig(jsonStr)) {
|
||||
scanBluetoothDrive();
|
||||
showToast("Get controller config succeed!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onDownloadConfigFinished(false);
|
||||
}
|
||||
Log.e(TAG, "Failed to download controller config!");
|
||||
}
|
||||
};
|
||||
|
||||
mDownDepsHttpClient.get(COCOS_CONTROLLER_URL + COCOS_CONTROLLER_CONFIG, configResponseHandler);
|
||||
}
|
||||
|
||||
private static void showToast(String message){
|
||||
Toast.makeText(sCocos2dxActivity, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private static void createControllerInstance(String libFilePath,int sdkType) {
|
||||
File libFile = new File(libFilePath);
|
||||
if (! libFile.exists()) {
|
||||
Log.w(TAG, libFile.toString() + "not exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
DexClassLoader classLoader = null;
|
||||
|
||||
try {
|
||||
File dexOutputDir = sCocos2dxActivity.getDir("dex", Context.MODE_PRIVATE);
|
||||
|
||||
classLoader = new DexClassLoader(libFile.getCanonicalPath(), dexOutputDir.getCanonicalPath(),
|
||||
null, sCocos2dxActivity.getClassLoader());
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> controllerDelegate = null;
|
||||
if (sdkType == DRIVERTYPE_MOGA) {
|
||||
controllerDelegate = classLoader.loadClass("org.cocos2dx.lib.GameControllerMoga");
|
||||
} else if (sdkType == DRIVERTYPE_NIBIRU) {
|
||||
controllerDelegate = classLoader.loadClass("org.cocos2dx.lib.GameControllerNibiru");
|
||||
} else if (sdkType == DRIVERTYPE_OUYA) {
|
||||
controllerDelegate = classLoader.loadClass("org.cocos2dx.lib.GameControllerOuya");
|
||||
}
|
||||
|
||||
GameControllerDelegate instance = (GameControllerDelegate)controllerDelegate.newInstance();
|
||||
|
||||
if (mControllerListener != null) {
|
||||
mControllerListener.onConnectController();
|
||||
}
|
||||
sCocos2dxActivity.setGameControllerInstance(instance);
|
||||
if (sdkType == DRIVERTYPE_NIBIRU) {
|
||||
Method method = controllerDelegate.getDeclaredMethod("onResume");
|
||||
method.invoke(instance);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver mAppReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String packageName = intent.getDataString();
|
||||
Log.d(TAG, "mAppReceiver:" + intent);
|
||||
if (packageName.contains(NIBIRU_DEP_PACKAGE)) {
|
||||
createControllerInstance(mLocalSavePath + mNibiruLibFileName, DRIVERTYPE_NIBIRU);
|
||||
}
|
||||
else if (packageName.contains(MOGA__DEP_PACKAGE)) {
|
||||
createControllerInstance(mLocalSavePath + mMogaLibFileName, DRIVERTYPE_MOGA);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private float mOldLeftThumbstickX = 0.0f;
|
||||
private float mOldLeftThumbstickY = 0.0f;
|
||||
private float mOldRightThumbstickX = 0.0f;
|
||||
private float mOldRightThumbstickY = 0.0f;
|
||||
|
||||
private float mOldLeftTrigger = 0.0f;
|
||||
private float mOldRightTrigger = 0.0f;
|
||||
private float mOldThrottle = 0.0f;
|
||||
private float mOldBrake = 0.0f;
|
||||
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event) {
|
||||
boolean handled = false;
|
||||
|
||||
int eventSource = event.getSource();
|
||||
|
||||
if ( ((eventSource & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|
||||
|| ((eventSource & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK) )
|
||||
{
|
||||
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
int devicedId = event.getDeviceId();
|
||||
|
||||
float newAXIS_LX = event.getAxisValue(MotionEvent.AXIS_X);
|
||||
if (Float.compare(newAXIS_LX , mOldLeftThumbstickX) != 0) {
|
||||
GameControllerAdapter.onAxisEvent(StandardControllerName, devicedId, GameControllerDelegate.THUMBSTICK_LEFT_X, newAXIS_LX, true);
|
||||
mOldLeftThumbstickX = newAXIS_LX;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_LY = event.getAxisValue(MotionEvent.AXIS_Y);
|
||||
if (Float.compare(newAXIS_LY , mOldLeftThumbstickY) != 0) {
|
||||
GameControllerAdapter.onAxisEvent(StandardControllerName, devicedId, GameControllerDelegate.THUMBSTICK_LEFT_Y, newAXIS_LY, true);
|
||||
mOldLeftThumbstickY = newAXIS_LY;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_RX = event.getAxisValue(MotionEvent.AXIS_Z);
|
||||
if (Float.compare(newAXIS_RX , mOldRightThumbstickX) != 0) {
|
||||
GameControllerAdapter.onAxisEvent(StandardControllerName, devicedId, GameControllerDelegate.THUMBSTICK_RIGHT_X, newAXIS_RX, true);
|
||||
mOldRightThumbstickX = newAXIS_RX;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_RY = event.getAxisValue(MotionEvent.AXIS_RZ);
|
||||
if (Float.compare(newAXIS_RY , mOldRightThumbstickY) != 0) {
|
||||
GameControllerAdapter.onAxisEvent(StandardControllerName, devicedId, GameControllerDelegate.THUMBSTICK_RIGHT_Y, newAXIS_RY, true);
|
||||
mOldRightThumbstickY = newAXIS_RY;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_LTRIGGER = event.getAxisValue(MotionEvent.AXIS_LTRIGGER);
|
||||
if (Float.compare(newAXIS_LTRIGGER , mOldLeftTrigger) != 0) {
|
||||
if (Float.compare(newAXIS_LTRIGGER, 0.0f) == 0) {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_LEFT_TRIGGER, false, 0.0f, true);
|
||||
}else {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_LEFT_TRIGGER, true, newAXIS_LTRIGGER, true);
|
||||
}
|
||||
mOldLeftTrigger = newAXIS_LTRIGGER;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_RTRIGGER = event.getAxisValue(MotionEvent.AXIS_RTRIGGER);
|
||||
if (Float.compare(newAXIS_RTRIGGER , mOldRightTrigger) != 0) {
|
||||
if (Float.compare(newAXIS_RTRIGGER, 0.0f) == 0) {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, false, 0.0f, true);
|
||||
}else {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, true, newAXIS_RTRIGGER, true);
|
||||
}
|
||||
mOldRightTrigger = newAXIS_RTRIGGER;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_BRAKE = event.getAxisValue(MotionEvent.AXIS_BRAKE);
|
||||
if (Float.compare(newAXIS_BRAKE , mOldBrake) != 0) {
|
||||
if (Float.compare(newAXIS_BRAKE, 0.0f) == 0) {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_LEFT_TRIGGER, false, 0.0f, true);
|
||||
}else {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_LEFT_TRIGGER, true, newAXIS_BRAKE, true);
|
||||
}
|
||||
mOldBrake = newAXIS_BRAKE;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
float newAXIS_THROTTLE = event.getAxisValue(MotionEvent.AXIS_THROTTLE);
|
||||
if (Float.compare(newAXIS_THROTTLE , mOldThrottle) != 0) {
|
||||
if (Float.compare(newAXIS_THROTTLE, 0.0f) == 0) {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, false, 0.0f, true);
|
||||
}else {
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName, devicedId, GameControllerDelegate.BUTTON_RIGHT_TRIGGER, true, newAXIS_THROTTLE, true);
|
||||
}
|
||||
mOldThrottle = newAXIS_THROTTLE;
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
boolean handled = false;
|
||||
|
||||
int eventSource = event.getSource();
|
||||
int controllerKey = ControllerKeyMap.get(event.getKeyCode());
|
||||
|
||||
if (controllerKey != 0 && (((eventSource & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|
||||
|| ((eventSource & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)
|
||||
|| ((eventSource & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD)))
|
||||
{
|
||||
int action = event.getAction();
|
||||
if (action == KeyEvent.ACTION_DOWN) {
|
||||
handled = true;
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName,event.getDeviceId(), controllerKey,true, 1.0f, false);
|
||||
}else if (action == KeyEvent.ACTION_UP) {
|
||||
handled = true;
|
||||
GameControllerAdapter.onButtonEvent(StandardControllerName,event.getDeviceId(), controllerKey,false, 0.0f, false);
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
public class GameControllerUtils {
|
||||
|
||||
public static void ensureDirectoryExist(String path){
|
||||
|
||||
File sdkDir = new File(path);
|
||||
if(!sdkDir.exists()){
|
||||
sdkDir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static String readJsonFile(String filePath) {
|
||||
|
||||
File file = new File(filePath);
|
||||
|
||||
if (!file.exists()){
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
FileInputStream is = new FileInputStream(file);;
|
||||
|
||||
int size = is.available();
|
||||
byte[] buffer = new byte[size];
|
||||
|
||||
is.read(buffer);
|
||||
is.close();
|
||||
|
||||
String jsonstr = new String(buffer, "UTF-8");
|
||||
|
||||
return jsonstr;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cocos2dx.lib.inputmanagercompat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public interface InputManagerCompat {
|
||||
/**
|
||||
* Gets information about the input device with the specified id.
|
||||
*
|
||||
* @param id The device id
|
||||
* @return The input device or null if not found
|
||||
*/
|
||||
public InputDevice getInputDevice(int id);
|
||||
|
||||
/**
|
||||
* Gets the ids of all input devices in the system.
|
||||
*
|
||||
* @return The input device ids.
|
||||
*/
|
||||
public int[] getInputDeviceIds();
|
||||
|
||||
/**
|
||||
* Registers an input device listener to receive notifications about when
|
||||
* input devices are added, removed or changed.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
* @param handler The handler on which the listener should be invoked, or
|
||||
* null if the listener should be invoked on the calling thread's
|
||||
* looper.
|
||||
*/
|
||||
public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
|
||||
Handler handler);
|
||||
|
||||
/**
|
||||
* Unregisters an input device listener.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
|
||||
|
||||
/*
|
||||
* The following three calls are to simulate V16 behavior on pre-Jellybean
|
||||
* devices. If you don't call them, your callback will never be called
|
||||
* pre-API 16.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pass the motion events to the InputManagerCompat. This is used to
|
||||
* optimize for polling for controllers. If you do not pass these events in,
|
||||
* polling will cause regular object creation.
|
||||
*
|
||||
* @param event the motion event from the app
|
||||
*/
|
||||
public void onGenericMotionEvent(MotionEvent event);
|
||||
|
||||
/**
|
||||
* Tell the V9 input manager that it should stop polling for disconnected
|
||||
* devices. You can call this during onPause in your activity, although you
|
||||
* might want to call it whenever your game is not active (or whenever you
|
||||
* don't care about being notified of new input devices)
|
||||
*/
|
||||
public void onPause();
|
||||
|
||||
/**
|
||||
* Tell the V9 input manager that it should start polling for disconnected
|
||||
* devices. You can call this during onResume in your activity, although you
|
||||
* might want to call it less often (only when the gameplay is actually
|
||||
* active)
|
||||
*/
|
||||
public void onResume();
|
||||
|
||||
public interface InputDeviceListener {
|
||||
/**
|
||||
* Called whenever the input manager detects that a device has been
|
||||
* added. This will only be called in the V9 version when a motion event
|
||||
* is detected.
|
||||
*
|
||||
* @param deviceId The id of the input device that was added.
|
||||
*/
|
||||
void onInputDeviceAdded(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the properties of an input device have changed since
|
||||
* they were last queried. This will not be called for the V9 version of
|
||||
* the API.
|
||||
*
|
||||
* @param deviceId The id of the input device that changed.
|
||||
*/
|
||||
void onInputDeviceChanged(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the input manager detects that a device has been
|
||||
* removed. For the V9 version, this can take some time depending on the
|
||||
* poll rate.
|
||||
*
|
||||
* @param deviceId The id of the input device that was removed.
|
||||
*/
|
||||
void onInputDeviceRemoved(int deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to construct a compatible InputManager.
|
||||
*/
|
||||
public static class Factory {
|
||||
|
||||
/**
|
||||
* Constructs and returns a compatible InputManger
|
||||
*
|
||||
* @param context the Context that will be used to get the system
|
||||
* service from
|
||||
* @return a compatible implementation of InputManager
|
||||
*/
|
||||
public static InputManagerCompat getInputManager(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
return new InputManagerV16(context);
|
||||
} else {
|
||||
return new InputManagerV9();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cocos2dx.lib.inputmanagercompat;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public class InputManagerV16 implements InputManagerCompat {
|
||||
|
||||
private final InputManager mInputManager;
|
||||
private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
|
||||
|
||||
public InputManagerV16(Context context) {
|
||||
mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
|
||||
mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputDevice getInputDevice(int id) {
|
||||
return mInputManager.getInputDevice(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInputDeviceIds() {
|
||||
return mInputManager.getInputDeviceIds();
|
||||
}
|
||||
|
||||
static class V16InputDeviceListener implements InputManager.InputDeviceListener {
|
||||
final InputManagerCompat.InputDeviceListener mIDL;
|
||||
|
||||
public V16InputDeviceListener(InputDeviceListener idl) {
|
||||
mIDL = idl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
mIDL.onInputDeviceAdded(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
mIDL.onInputDeviceChanged(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
mIDL.onInputDeviceRemoved(deviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||
V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
|
||||
mInputManager.registerInputDeviceListener(v16Listener, handler);
|
||||
mListeners.put(listener, v16Listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||
V16InputDeviceListener curListener = mListeners.remove(listener);
|
||||
if (null != curListener)
|
||||
{
|
||||
mInputManager.unregisterInputDeviceListener(curListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericMotionEvent(MotionEvent event) {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cocos2dx.lib.inputmanagercompat;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
public class InputManagerV9 implements InputManagerCompat {
|
||||
private static final String LOG_TAG = "InputManagerV9";
|
||||
private static final int MESSAGE_TEST_FOR_DISCONNECT = 101;
|
||||
private static final long CHECK_ELAPSED_TIME = 3000L;
|
||||
|
||||
private static final int ON_DEVICE_ADDED = 0;
|
||||
private static final int ON_DEVICE_CHANGED = 1;
|
||||
private static final int ON_DEVICE_REMOVED = 2;
|
||||
|
||||
private final SparseArray<long[]> mDevices;
|
||||
private final Map<InputDeviceListener, Handler> mListeners;
|
||||
private final Handler mDefaultHandler;
|
||||
|
||||
private static class PollingMessageHandler extends Handler {
|
||||
private final WeakReference<InputManagerV9> mInputManager;
|
||||
|
||||
PollingMessageHandler(InputManagerV9 im) {
|
||||
mInputManager = new WeakReference<InputManagerV9>(im);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
switch (msg.what) {
|
||||
case MESSAGE_TEST_FOR_DISCONNECT:
|
||||
InputManagerV9 imv = mInputManager.get();
|
||||
if (null != imv) {
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
int size = imv.mDevices.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
long[] lastContact = imv.mDevices.valueAt(i);
|
||||
if (null != lastContact) {
|
||||
if (time - lastContact[0] > CHECK_ELAPSED_TIME) {
|
||||
// check to see if the device has been
|
||||
// disconnected
|
||||
int id = imv.mDevices.keyAt(i);
|
||||
if (null == InputDevice.getDevice(id)) {
|
||||
// disconnected!
|
||||
imv.notifyListeners(ON_DEVICE_REMOVED, id);
|
||||
imv.mDevices.remove(id);
|
||||
} else {
|
||||
lastContact[0] = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT,
|
||||
CHECK_ELAPSED_TIME);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public InputManagerV9() {
|
||||
mDevices = new SparseArray<long[]>();
|
||||
mListeners = new HashMap<InputDeviceListener, Handler>();
|
||||
mDefaultHandler = new PollingMessageHandler(this);
|
||||
// as a side-effect, populates our collection of watched
|
||||
// input devices
|
||||
getInputDeviceIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputDevice getInputDevice(int id) {
|
||||
return InputDevice.getDevice(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInputDeviceIds() {
|
||||
// add any hitherto unknown devices to our
|
||||
// collection of watched input devices
|
||||
int[] activeDevices = InputDevice.getDeviceIds();
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
for ( int id : activeDevices ) {
|
||||
long[] lastContact = mDevices.get(id);
|
||||
if ( null == lastContact ) {
|
||||
// we have a new device
|
||||
mDevices.put(id, new long[] { time });
|
||||
}
|
||||
}
|
||||
return activeDevices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||
mListeners.remove(listener);
|
||||
if (handler == null) {
|
||||
handler = mDefaultHandler;
|
||||
}
|
||||
mListeners.put(listener, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners(int why, int deviceId) {
|
||||
// the state of some device has changed
|
||||
if (!mListeners.isEmpty()) {
|
||||
// yes... this will cause an object to get created... hopefully
|
||||
// it won't happen very often
|
||||
for (InputDeviceListener listener : mListeners.keySet()) {
|
||||
Handler handler = mListeners.get(listener);
|
||||
DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener);
|
||||
handler.post(odc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeviceEvent implements Runnable {
|
||||
private int mMessageType;
|
||||
private int mId;
|
||||
private InputDeviceListener mListener;
|
||||
private static Queue<DeviceEvent> sEventQueue = new ArrayDeque<DeviceEvent>();
|
||||
|
||||
private DeviceEvent() {
|
||||
}
|
||||
|
||||
static DeviceEvent getDeviceEvent(int messageType, int id,
|
||||
InputDeviceListener listener) {
|
||||
DeviceEvent curChanged = sEventQueue.poll();
|
||||
if (null == curChanged) {
|
||||
curChanged = new DeviceEvent();
|
||||
}
|
||||
curChanged.mMessageType = messageType;
|
||||
curChanged.mId = id;
|
||||
curChanged.mListener = listener;
|
||||
return curChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
switch (mMessageType) {
|
||||
case ON_DEVICE_ADDED:
|
||||
mListener.onInputDeviceAdded(mId);
|
||||
break;
|
||||
case ON_DEVICE_CHANGED:
|
||||
mListener.onInputDeviceChanged(mId);
|
||||
break;
|
||||
case ON_DEVICE_REMOVED:
|
||||
mListener.onInputDeviceRemoved(mId);
|
||||
break;
|
||||
default:
|
||||
Log.e(LOG_TAG, "Unknown Message Type");
|
||||
break;
|
||||
}
|
||||
// dump this runnable back in the queue
|
||||
sEventQueue.offer(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericMotionEvent(MotionEvent event) {
|
||||
// detect new devices
|
||||
int id = event.getDeviceId();
|
||||
long[] timeArray = mDevices.get(id);
|
||||
if (null == timeArray) {
|
||||
notifyListeners(ON_DEVICE_ADDED, id);
|
||||
timeArray = new long[1];
|
||||
mDevices.put(id, timeArray);
|
||||
}
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
timeArray[0] = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mDefaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mDefaultHandler.sendEmptyMessage(MESSAGE_TEST_FOR_DISCONNECT);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue