/* Copyright (C) 2013 Victor Olausson, Patrik Wållgren 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, either version 3 of the License, or (at your option) any later version. 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 for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/ */ package bgsep.virtualgamepad; import java.util.ArrayList; import java.util.Observable; import java.util.Observer; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.hardware.SensorManager; import android.os.Bundle; import android.os.Vibrator; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; import bgsep.communication.Communication; import bgsep.communication.CommunicationNotifier; import bgsep.model.Button; import bgsep.model.Gyro; import bgsep.model.JoystickHandler; /** * The activity for the PS controller * @author Victor Olausson * @author Patrik Wållgren * */ public class PsActivity extends Activity implements Observer { private ImageView imageX, imageCircle, imageSquare, imageTriangle, imageUp, imageDown, imageRight, imageLeft, imageR1, imageR2, imageL1, imageL2, imageStart, imageSelect, imageLeftStick, imageLeftBoundary, imageRightStick, imageRightBoundary; private Button buttonX, buttonCircle, buttonSquare, buttonTriangle, buttonUp, buttonDown, buttonRight, buttonLeft, buttonR1, buttonR2, buttonL1, buttonL2, buttonStart, buttonSelect; private ArrayList<Button> buttons; private JoystickHandler leftJoystick, rightJoystick; private Gyro gyro; private boolean isInitialized; private boolean hapticFeedback; private boolean useAccelerometer; private Communication comm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ps); // Keep screen on getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON); //Dim soft menu keys if present if (!ViewConfiguration.get(this).hasPermanentMenuKey()) getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); Intent i = getIntent(); hapticFeedback = i.getBooleanExtra("hapticFeedback", false); useAccelerometer = i.getBooleanExtra("useAccelerometer", false); comm = Communication.getInstance(); if(useAccelerometer) initGyro(); isInitialized = false; } @Override public void onWindowFocusChanged(boolean hasFocus) { // Initialization of the joystick must happen when all the views has been drawn. // Therefore initialize it when the window has focus and not in onCreate. if(!isInitialized) { initImages(); initButtons(); initJoysticks(); isInitialized = true; } super.onWindowFocusChanged(hasFocus); } private void initImages() { imageX = (ImageView) findViewById(R.id.ps_x); imageCircle = (ImageView) findViewById(R.id.ps_o); imageSquare = (ImageView) findViewById(R.id.ps_sq); imageTriangle = (ImageView) findViewById(R.id.ps_tr); imageUp = (ImageView) findViewById(R.id.ps_arrow_up); imageDown = (ImageView) findViewById(R.id.ps_arrow_down); imageLeft = (ImageView) findViewById(R.id.ps_arrow_left); imageRight = (ImageView) findViewById(R.id.ps_arrow_right); imageR1 = (ImageView) findViewById(R.id.ps_r1); imageR2 = (ImageView) findViewById(R.id.ps_r2); imageL1 = (ImageView) findViewById(R.id.ps_l1); imageL2 = (ImageView) findViewById(R.id.ps_l2); imageStart = (ImageView) findViewById(R.id.ps_start); imageSelect = (ImageView) findViewById(R.id.ps_select); imageLeftBoundary = (ImageView) findViewById(R.id.ps_joy_bg_left); imageRightBoundary = (ImageView) findViewById(R.id.ps_joy_bg_right); imageLeftStick = (ImageView) findViewById(R.id.ps_joy_left); imageRightStick = (ImageView) findViewById(R.id.ps_joy_right); } private void initButtons() { Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); buttonLeft = new Button(imageLeft, R.drawable.ps_arrow_left, R.drawable.ps_arrow_left_pr, 0, this, vibrator, hapticFeedback); buttonRight = new Button(imageRight, R.drawable.ps_arrow_right, R.drawable.ps_arrow_right_pr, 1, this, vibrator, hapticFeedback); buttonUp = new Button(imageUp, R.drawable.ps_arrow_up, R.drawable.ps_arrow_up_pr, 2, this, vibrator, hapticFeedback); buttonDown = new Button(imageDown, R.drawable.ps_arrow_down, R.drawable.ps_arrow_down_pr, 3, this, vibrator, hapticFeedback); buttonX = new Button(imageX, R.drawable.ps_x, R.drawable.ps_x_pr, 4, this, vibrator, hapticFeedback); buttonCircle = new Button(imageCircle, R.drawable.ps_o, R.drawable.ps_o_pr, 5, this, vibrator, hapticFeedback); buttonTriangle = new Button(imageTriangle, R.drawable.ps_tr, R.drawable.ps_tr_pr, 6, this, vibrator, hapticFeedback); buttonSquare = new Button(imageSquare, R.drawable.ps_sq, R.drawable.ps_sq_pr, 7, this, vibrator, hapticFeedback); buttonR1 = new Button(imageR1, R.drawable.ps_r1, R.drawable.ps_r1_pr, 8, this, vibrator, hapticFeedback); buttonR2 = new Button(imageR2, R.drawable.ps_r2, R.drawable.ps_r2_pr, 9, this, vibrator, hapticFeedback); buttonL1 = new Button(imageL1, R.drawable.ps_l1, R.drawable.ps_l1_pr, 10, this, vibrator, hapticFeedback); buttonL2 = new Button(imageL2, R.drawable.ps_l2, R.drawable.ps_l2_pr, 11, this, vibrator, hapticFeedback); buttonSelect = new Button(imageSelect, R.drawable.ps_select, R.drawable.ps_select_pr, 12, this, vibrator, hapticFeedback); buttonStart = new Button(imageStart, R.drawable.ps_start, R.drawable.ps_start_pr, 13, this, vibrator, hapticFeedback); buttons = new ArrayList<Button>(); buttons.add(buttonCircle); buttons.add(buttonDown); buttons.add(buttonL1); buttons.add(buttonL2); buttons.add(buttonLeft); buttons.add(buttonR1); buttons.add(buttonR2); buttons.add(buttonRight); buttons.add(buttonSelect); buttons.add(buttonSquare); buttons.add(buttonStart); buttons.add(buttonTriangle); buttons.add(buttonUp); buttons.add(buttonX); for(Button b : buttons) b.addObserver(comm); } private void initJoysticks() { leftJoystick = new JoystickHandler(imageLeftBoundary, imageLeftStick); rightJoystick = new JoystickHandler(imageRightBoundary, imageRightStick); leftJoystick.setLeftRightJoystickID(14, 15); leftJoystick.setUpDownJoystickID(16, 17); rightJoystick.setLeftRightJoystickID(18, 19); rightJoystick.setUpDownJoystickID(20, 21); leftJoystick.addObserver(this); leftJoystick.addObserver(comm); rightJoystick.addObserver(this); rightJoystick.addObserver(comm); } @Override public void update(Observable o, Object data) { // Joystick and Button movement handling if(o instanceof JoystickHandler && !(data instanceof CommunicationNotifier)) { JoystickHandler joystick = (JoystickHandler)o; ImageView stick = joystick.getStick(); ImageView boundary = joystick.getBoundary(); stick.setX((joystick.getX() * boundary.getWidth()/2) + boundary.getLeft() + boundary.getWidth()/2-stick.getWidth()/2); stick.setY((joystick.getY() * boundary.getHeight()/2 * -1) + boundary.getTop() + boundary.getHeight()/2-stick.getHeight()/2); } else if(o instanceof Button) { Button button = (Button)o; if(button.isPressed()) button.getButtonView().setImageResource(button.getPressedDrawableID()); else button.getButtonView().setImageResource(button.getUnPressedDrawableID()); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.ps, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection Intent i; switch (item.getItemId()) { case R.id.action_nes: i = new Intent(this, NesActivity.class); i.putExtra("hapticFeedback", hapticFeedback); i.putExtra("useAccelerometer", useAccelerometer); startActivity(i); finish(); return true; case R.id.action_gc: i = new Intent(this, GcActivity.class); i.putExtra("hapticFeedback", hapticFeedback); i.putExtra("useAccelerometer", useAccelerometer); startActivity(i); finish(); return true; default: return super.onOptionsItemSelected(item); } } private void initGyro() { SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); gyro = new Gyro(sensorManager); gyro.setLeftRightGyroID(22, 23); gyro.setEnabled(useAccelerometer); gyro.registerListener(); gyro.addObserver(comm); } @Override public void onDestroy() { super.onDestroy(); releaseAliciaKeys(); } @Override public void onPause() { super.onPause(); releaseAliciaKeys(); } @Override public void onResume() { super.onResume(); if(useAccelerometer) gyro.registerListener(); } private void releaseAliciaKeys() { if(useAccelerometer) gyro.unregisterListener(); unPressAllButtons(); leftJoystick.releaseJoystick(); rightJoystick.releaseJoystick(); } private void unPressAllButtons() { for(Button b : buttons) b.setPressed(false); } }