| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| package org.dolphinemu.dolphinemu; | ||
|
|
||
| import android.app.Activity; | ||
| import android.app.ListActivity; | ||
| import android.content.Intent; | ||
| import android.os.Bundle; | ||
| import android.util.Log; | ||
| import android.view.InputDevice; | ||
| import android.view.KeyEvent; | ||
| import android.view.MotionEvent; | ||
| import android.view.View; | ||
| import android.widget.ListView; | ||
| import android.widget.Toast; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Copyright 2013 Dolphin Emulator Project | ||
| * Licensed under GPLv2 | ||
| * Refer to the license.txt file included. | ||
| */ | ||
| public class InputConfigActivity extends ListActivity { | ||
| private InputConfigAdapter adapter; | ||
| private int configPosition = 0; | ||
| boolean Configuring = false; | ||
| boolean firstEvent = true; | ||
|
|
||
| @Override | ||
| public void onCreate(Bundle savedInstanceState) | ||
| { | ||
| super.onCreate(savedInstanceState); | ||
| List<InputConfigItem> Input = new ArrayList<InputConfigItem>(); | ||
| int a = 0; | ||
|
|
||
| Input.add(a++, new InputConfigItem("Draw on-screen controls", "Android-ScreenControls", "True")); | ||
| Input.add(a++, new InputConfigItem("Button A", "Android-InputA")); | ||
| Input.add(a++, new InputConfigItem("Button B", "Android-InputB")); | ||
| Input.add(a++, new InputConfigItem("Button Start", "Android-InputStart")); | ||
| Input.add(a++, new InputConfigItem("Button X", "Android-InputX")); | ||
| Input.add(a++, new InputConfigItem("Button Y", "Android-InputY")); | ||
| Input.add(a++, new InputConfigItem("Button Z", "Android-InputZ")); | ||
| Input.add(a++, new InputConfigItem("D-Pad Up", "Android-DPadUp")); | ||
| Input.add(a++, new InputConfigItem("D-Pad Down", "Android-DPadDown")); | ||
| Input.add(a++, new InputConfigItem("D-Pad Left", "Android-DPadLeft")); | ||
| Input.add(a++, new InputConfigItem("D-Pad Right", "Android-DPadRight")); | ||
| Input.add(a++, new InputConfigItem("Main Stick Up", "Android-MainUp")); | ||
| Input.add(a++, new InputConfigItem("Main Stick Down", "Android-MainDown")); | ||
| Input.add(a++, new InputConfigItem("Main Stick Left", "Android-MainLeft")); | ||
| Input.add(a++, new InputConfigItem("Main Stick Right", "Android-MainRight")); | ||
| Input.add(a++, new InputConfigItem("C Stick Up", "Android-CStickUp")); | ||
| Input.add(a++, new InputConfigItem("C Stick Down", "Android-CStickDown")); | ||
| Input.add(a++, new InputConfigItem("C Stick Left", "Android-CStickLeft")); | ||
| Input.add(a++, new InputConfigItem("C Stick Right", "Android-CStickRight")); | ||
| Input.add(a++, new InputConfigItem("Trigger L", "Android-InputL")); | ||
| Input.add(a++, new InputConfigItem("Trigger R", "Android-InputR")); | ||
|
|
||
| adapter = new InputConfigAdapter(this,R.layout.folderbrowser, Input); | ||
| this.setListAdapter(adapter); | ||
| } | ||
| @Override | ||
| protected void onListItemClick(ListView l, View v, int position, long id) { | ||
| super.onListItemClick(l, v, position, id); | ||
| InputConfigItem o = adapter.getItem(position); | ||
| switch(position) | ||
| { | ||
| case 0: // On screen controls | ||
| String newBind; | ||
| if (o.getBind() == "True") | ||
| { | ||
| Toast.makeText(this, "Not Drawing on screen controls", Toast.LENGTH_SHORT).show(); | ||
| newBind = "False"; | ||
| } | ||
| else | ||
| { | ||
| Toast.makeText(this, "Drawing on screen controls", Toast.LENGTH_SHORT).show(); | ||
| newBind = "True"; | ||
| } | ||
| adapter.remove(o); | ||
| o.setBind(newBind); | ||
| adapter.insert(o, position); | ||
| break; | ||
| default: // gamepad controls | ||
| Toast.makeText(this, "Press button to configure " + o.getName(), Toast.LENGTH_SHORT).show(); | ||
| configPosition = position; | ||
| Configuring = true; | ||
| firstEvent = true; | ||
| break; | ||
| } | ||
|
|
||
| } | ||
| static ArrayList<Float> m_values = new ArrayList<Float>(); | ||
| // Gets move(triggers, joystick) events | ||
| void AssignBind(String bind) | ||
| { | ||
| InputConfigItem o = adapter.getItem(configPosition); | ||
| adapter.remove(o); | ||
| o.setBind(bind); | ||
| adapter.insert(o, configPosition); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean dispatchGenericMotionEvent(MotionEvent event) { | ||
| if (((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)) { | ||
| return super.dispatchGenericMotionEvent(event); | ||
| } | ||
| InputDevice input = event.getDevice(); | ||
| List<InputDevice.MotionRange> motions = input.getMotionRanges(); | ||
| if (Configuring) | ||
| { | ||
| if (firstEvent) | ||
| { | ||
| m_values.clear(); | ||
| for (int a = 0; a < motions.size(); ++a) | ||
| { | ||
| InputDevice.MotionRange range = motions.get(a); | ||
| m_values.add(event.getAxisValue(range.getAxis())); | ||
| } | ||
| firstEvent = false; | ||
| } | ||
| else | ||
| { | ||
| for (int a = 0; a < motions.size(); ++a) | ||
| { | ||
| InputDevice.MotionRange range; | ||
| range = motions.get(a); | ||
| if (m_values.get(a) > (event.getAxisValue(range.getAxis()) + 0.5f)) | ||
| { | ||
| AssignBind("Device '" + input.getDescriptor() + "'-Axis " + range.getAxis() + "-"); | ||
| Configuring = false; | ||
| } | ||
| else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f)) | ||
| { | ||
| AssignBind("Device '" + input.getDescriptor() + "'-Axis " + range.getAxis() + "+"); | ||
| Configuring = false; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| // Gets button presses | ||
| @Override | ||
| public boolean dispatchKeyEvent(KeyEvent event) { | ||
| Log.w("Dolphinemu", "Got Event " + event.getAction()); | ||
| switch (event.getAction()) { | ||
| case KeyEvent.ACTION_DOWN: | ||
| case KeyEvent.ACTION_UP: | ||
| if (Configuring) | ||
| { | ||
| InputDevice input = event.getDevice(); | ||
| AssignBind("Device '" + input.getDescriptor() + "'-Button " + event.getKeyCode()); | ||
| Configuring = false; | ||
| return true; | ||
| } | ||
| default: | ||
| break; | ||
| } | ||
|
|
||
| return super.dispatchKeyEvent(event); | ||
| } | ||
|
|
||
| @Override | ||
| public void onBackPressed() { | ||
| for (int a = 0; a < adapter.getCount(); ++a) | ||
| { | ||
| InputConfigItem o = adapter.getItem(a); | ||
| String config = o.getConfig(); | ||
| String bind = o.getBind(); | ||
| String ConfigValues[] = config.split("-"); | ||
| String Key = ConfigValues[0]; | ||
| String Value = ConfigValues[1]; | ||
| NativeLibrary.SetConfig("Dolphin.ini", Key, Value, bind); | ||
| } | ||
| Intent intent = new Intent(); | ||
| setResult(Activity.RESULT_OK, intent); | ||
| this.finish(); | ||
| super.onBackPressed(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package org.dolphinemu.dolphinemu; | ||
|
|
||
| import android.content.Context; | ||
| import android.view.LayoutInflater; | ||
| import android.view.View; | ||
| import android.view.ViewGroup; | ||
| import android.widget.ArrayAdapter; | ||
| import android.widget.TextView; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Copyright 2013 Dolphin Emulator Project | ||
| * Licensed under GPLv2 | ||
| * Refer to the license.txt file included. | ||
| */ | ||
| public class InputConfigAdapter extends ArrayAdapter<InputConfigItem> { | ||
| private Context c; | ||
| private int id; | ||
| private List<InputConfigItem> items; | ||
|
|
||
| public InputConfigAdapter(Context context, int textViewResourceId, | ||
| List<InputConfigItem> objects) { | ||
| super(context, textViewResourceId, objects); | ||
| c = context; | ||
| id = textViewResourceId; | ||
| items = objects; | ||
| } | ||
|
|
||
| public InputConfigItem getItem(int i) | ||
| { | ||
| return items.get(i); | ||
| } | ||
| @Override | ||
| public View getView(int position, View convertView, ViewGroup parent) { | ||
| View v = convertView; | ||
| if (v == null) { | ||
| LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); | ||
| v = vi.inflate(id, null); | ||
| } | ||
| final InputConfigItem o = items.get(position); | ||
| if (o != null) { | ||
| TextView t1 = (TextView) v.findViewById(R.id.TextView01); | ||
| TextView t2 = (TextView) v.findViewById(R.id.TextView02); | ||
|
|
||
| if(t1!=null) | ||
| t1.setText(o.getName()); | ||
| if(t2!=null) | ||
| t2.setText(o.getBind()); | ||
| } | ||
| return v; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package org.dolphinemu.dolphinemu; | ||
|
|
||
| /** | ||
| * Copyright 2013 Dolphin Emulator Project | ||
| * Licensed under GPLv2 | ||
| * Refer to the license.txt file included. | ||
| */ | ||
| public class InputConfigItem implements Comparable<InputConfigItem>{ | ||
| private String m_name; | ||
| private String m_Config; | ||
| private String m_bind; | ||
|
|
||
| private void Init(String n, String c, String d) | ||
| { | ||
| m_name = n; | ||
| m_Config = c; | ||
| String ConfigValues[] = m_Config.split("-"); | ||
| String Key = ConfigValues[0]; | ||
| String Value = ConfigValues[1]; | ||
| m_bind = NativeLibrary.GetConfig("Dolphin.ini", Key, Value, d); | ||
| } | ||
|
|
||
| public InputConfigItem(String n, String c, String d) | ||
| { | ||
| Init(n, c, d); | ||
| } | ||
|
|
||
| public InputConfigItem(String n, String c) | ||
| { | ||
| Init(n, c, "None"); | ||
| } | ||
| public String getName() | ||
| { | ||
| return m_name; | ||
| } | ||
| public String getConfig() | ||
| { | ||
| return m_Config; | ||
| } | ||
| public String getBind() | ||
| { | ||
| return m_bind; | ||
| } | ||
| public void setBind(String b) | ||
| { | ||
| m_bind = b; | ||
| } | ||
|
|
||
| public int compareTo(InputConfigItem o) | ||
| { | ||
| if(this.m_name != null) | ||
| return this.m_name.toLowerCase().compareTo(o.getName().toLowerCase()); | ||
| else | ||
| throw new IllegalArgumentException(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package org.dolphinemu.dolphinemu; | ||
|
|
||
| import android.util.Log; | ||
| import android.view.Surface; | ||
|
|
||
| /** | ||
| * Copyright 2013 Dolphin Emulator Project | ||
| * Licensed under GPLv2 | ||
| * Refer to the license.txt file included. | ||
| */ | ||
| public class NativeLibrary { | ||
| public static native void onTouchEvent(int Action, float X, float Y); | ||
| public static native void onGamePadEvent(String Device, int Button, int Action); | ||
| public static native void onGamePadMoveEvent(String Device, int Axis, float Value); | ||
| public static native String GetConfig(String configFile, String Key, String Value, String Default); | ||
| public static native void SetConfig(String configFile, String Key, String Value, String Default); | ||
| public static native int[] GetBanner(String filename); | ||
| public static native String GetTitle(String filename); | ||
|
|
||
| public static native void Run(String File, Surface surf, int width, int height); | ||
| public static native void UnPauseEmulation(); | ||
| public static native void PauseEmulation(); | ||
| public static native void StopEmulation(); | ||
|
|
||
| static | ||
| { | ||
| try | ||
| { | ||
| System.loadLibrary("dolphin-emu-nogui"); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Log.w("me", ex.toString()); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,223 @@ | ||
| // Copyright (C) 2003 Dolphin Project. | ||
|
|
||
| // This program is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, version 2.0. | ||
|
|
||
| // This program is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License 2.0 for more details. | ||
|
|
||
| // A copy of the GPL 2.0 should have been included with the program. | ||
| // If not, see http://www.gnu.org/licenses/ | ||
|
|
||
| // Official SVN repository and contact information can be found at | ||
| // http://code.google.com/p/dolphin-emu/ | ||
|
|
||
| #include <vector> | ||
| #include "GLInterface.h" | ||
| #include "Android/TextureLoader.h" | ||
| #include "Android/ButtonManager.h" | ||
|
|
||
| extern void DrawButton(GLuint tex, float *coords); | ||
|
|
||
| namespace ButtonManager | ||
| { | ||
| std::vector<Button*> m_buttons; | ||
| std::map<std::string, InputDevice*> m_controllers; | ||
| // XXX: This needs to not be here so we can load the locations from file | ||
| // This will allow customizable button locations in the future | ||
| // These are the OpenGL on screen coordinates | ||
| float m_coords[][8] = { // X, Y, X, EY, EX, EY, EX, Y | ||
| {0.75f, -1.0f, 0.75f, -0.75f, 1.0f, -0.75f, 1.0f, -1.0f}, // A | ||
| {0.50f, -1.0f, 0.50f, -0.75f, 0.75f, -0.75f, 0.75f, -1.0f}, // B | ||
| {-0.10f, -1.0f, -0.10f, -0.80f, 0.10f, -0.80f, 0.10f, -1.0f}, // Start | ||
| }; | ||
| const char *configStrings[] = { "InputA", | ||
| "InputB", | ||
| "InputStart", | ||
| "InputX", | ||
| "InputY", | ||
| "InputZ", | ||
| "DPadUp", | ||
| "DPadDown", | ||
| "DPadLeft", | ||
| "DPadRight", | ||
| "MainUp", | ||
| "MainDown", | ||
| "MainLeft", | ||
| "MainRight", | ||
| "CStickUp", | ||
| "CStickDown", | ||
| "CStickLeft", | ||
| "CStickRight", | ||
| "InputL", | ||
| "InputR" }; | ||
| const int configStringNum = 20; | ||
|
|
||
| void AddBind(std::string dev, sBind *bind) | ||
| { | ||
| auto it = m_controllers.find(dev); | ||
| if (it != m_controllers.end()) | ||
| { | ||
| it->second->AddBind(bind); | ||
| return; | ||
| } | ||
| m_controllers[dev] = new InputDevice(dev); | ||
| m_controllers[dev]->AddBind(bind); | ||
| } | ||
|
|
||
| void Init() | ||
| { | ||
| // Initialize our touchscreen buttons | ||
| m_buttons.push_back(new Button("ButtonA.png", BUTTON_A, m_coords[0])); | ||
| m_buttons.push_back(new Button("ButtonB.png", BUTTON_B, m_coords[1])); | ||
| m_buttons.push_back(new Button("ButtonStart.png", BUTTON_START, m_coords[2])); | ||
|
|
||
| // Init our controller bindings | ||
| IniFile ini; | ||
| ini.Load(File::GetUserPath(D_CONFIG_IDX) + std::string("Dolphin.ini")); | ||
| for (int a = 0; a < configStringNum; ++a) | ||
| { | ||
| BindType type; | ||
| int bindnum; | ||
| char dev[128]; | ||
| bool hasbind = false; | ||
| char modifier = 0; | ||
| std::string value; | ||
| ini.Get("Android", configStrings[a], &value, "None"); | ||
| if (value == "None") | ||
| continue; | ||
| if (std::string::npos != value.find("Axis")) | ||
| { | ||
| hasbind = true; | ||
| type = BIND_AXIS; | ||
| sscanf(value.c_str(), "Device '%[^\']'-Axis %d%c", dev, &bindnum, &modifier); | ||
| } | ||
| else if (std::string::npos != value.find("Button")) | ||
| { | ||
| hasbind = true; | ||
| type = BIND_BUTTON; | ||
| sscanf(value.c_str(), "Device '%[^\']'-Button %d", dev, &bindnum); | ||
| } | ||
| if (hasbind) | ||
| AddBind(std::string(dev), new sBind((ButtonType)a, type, bindnum, modifier == '-' ? -1.0f : 1.0f)); | ||
| } | ||
|
|
||
| } | ||
| bool GetButtonPressed(ButtonType button) | ||
| { | ||
| bool pressed = false; | ||
| for (auto it = m_buttons.begin(); it != m_buttons.end(); ++it) | ||
| if ((*it)->GetButtonType() == button) | ||
| pressed = (*it)->Pressed(); | ||
|
|
||
| for (auto it = m_controllers.begin(); it != m_controllers.end(); ++it) | ||
| pressed |= it->second->ButtonValue(button); | ||
|
|
||
| return pressed; | ||
| } | ||
| float GetAxisValue(ButtonType axis) | ||
| { | ||
| auto it = m_controllers.begin(); | ||
| if (it == m_controllers.end()) | ||
| return 0.0f; | ||
| return it->second->AxisValue(axis); | ||
| } | ||
| void TouchEvent(int action, float x, float y) | ||
| { | ||
| // Actions | ||
| // 0 is press | ||
| // 1 is let go | ||
| // 2 is move | ||
| for (auto it = m_buttons.begin(); it != m_buttons.end(); ++it) | ||
| { | ||
| float *coords = (*it)->GetCoords(); | ||
| if ( x >= coords[0] && | ||
| x <= coords[4] && | ||
| y >= coords[1] && | ||
| y <= coords[3]) | ||
| { | ||
| if (action == 0) | ||
| (*it)->SetState(BUTTON_PRESSED); | ||
| if (action == 1) | ||
| (*it)->SetState(BUTTON_RELEASED); | ||
| if (action == 2) | ||
| ; // XXX: Be used later for analog stick | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void GamepadEvent(std::string dev, int button, int action) | ||
| { | ||
| auto it = m_controllers.find(dev); | ||
| if (it != m_controllers.end()) | ||
| { | ||
| it->second->PressEvent(button, action); | ||
| return; | ||
| } | ||
| m_controllers[dev] = new InputDevice(dev); | ||
| m_controllers[dev]->PressEvent(button, action); | ||
| } | ||
| void GamepadAxisEvent(std::string dev, int axis, float value) | ||
| { | ||
| auto it = m_controllers.find(dev); | ||
| if (it != m_controllers.end()) | ||
| { | ||
| it->second->AxisEvent(axis, value); | ||
| return; | ||
| } | ||
| m_controllers[dev] = new InputDevice(dev); | ||
| m_controllers[dev]->AxisEvent(axis, value); | ||
| } | ||
| void Shutdown() | ||
| { | ||
| for(auto it = m_buttons.begin(); it != m_buttons.end(); ++it) | ||
| delete *it; | ||
| for (auto it = m_controllers.begin(); it != m_controllers.end(); ++it) | ||
| delete it->second; | ||
| } | ||
|
|
||
| void DrawButtons() | ||
| { | ||
| glEnable(GL_BLEND); | ||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
|
|
||
| for(auto it = m_buttons.begin(); it != m_buttons.end(); ++it) | ||
| DrawButton((*it)->GetTexture(), (*it)->GetCoords()); | ||
|
|
||
| glDisable(GL_BLEND); | ||
| } | ||
|
|
||
| // InputDevice | ||
| void InputDevice::PressEvent(int button, int action) | ||
| { | ||
| m_buttons[button] = action == 0 ? true : false; | ||
| } | ||
| void InputDevice::AxisEvent(int axis, float value) | ||
| { | ||
| m_axises[axis] = value; | ||
| } | ||
| bool InputDevice::ButtonValue(ButtonType button) | ||
| { | ||
| auto it = m_binds.find(button); | ||
| if (it == m_binds.end()) | ||
| return false; | ||
| if (it->second->m_bindtype == BIND_BUTTON) | ||
| return m_buttons[it->second->m_bind]; | ||
| else | ||
| return AxisValue(button); | ||
| } | ||
| float InputDevice::AxisValue(ButtonType axis) | ||
| { | ||
| auto it = m_binds.find(axis); | ||
| if (it == m_binds.end()) | ||
| return 0.0f; | ||
| if (it->second->m_bindtype == BIND_BUTTON) | ||
| return ButtonValue(axis); | ||
| else | ||
| return m_axises[it->second->m_bind] * it->second->m_neg; | ||
| } | ||
|
|
||
| } |