diff --git a/MobileApp/.gitignore b/MobileApp/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/MobileApp/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/MobileApp/app/.gitignore b/MobileApp/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/MobileApp/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/MobileApp/app/build.gradle b/MobileApp/app/build.gradle new file mode 100644 index 0000000..8238090 --- /dev/null +++ b/MobileApp/app/build.gradle @@ -0,0 +1,45 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdk 32 + + defaultConfig { + applicationId "com.example.lfrmobileapp" + minSdk 22 + targetSdk 32 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding true + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'com.google.android.material:material:1.7.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' + implementation 'androidx.navigation:navigation-fragment:2.5.3' + implementation 'androidx.navigation:navigation-ui:2.5.3' + implementation project(path: ':virtualjoystick') + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' +} \ No newline at end of file diff --git a/MobileApp/app/proguard-rules.pro b/MobileApp/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/MobileApp/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/MobileApp/app/src/androidTest/java/com/example/lfrmobileapp/ExampleInstrumentedTest.java b/MobileApp/app/src/androidTest/java/com/example/lfrmobileapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..b2959df --- /dev/null +++ b/MobileApp/app/src/androidTest/java/com/example/lfrmobileapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.lfrmobileapp; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.example.lfrmobileapp", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/MobileApp/app/src/main/AndroidManifest.xml b/MobileApp/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ea737bf --- /dev/null +++ b/MobileApp/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java new file mode 100644 index 0000000..34ac80a --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java @@ -0,0 +1,37 @@ +package com.example.lfrmobileapp; + +import android.os.Bundle; + +import com.google.android.material.bottomnavigation.BottomNavigationView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.navigation.NavController; +import androidx.navigation.Navigation; +import androidx.navigation.ui.AppBarConfiguration; +import androidx.navigation.ui.NavigationUI; + +import com.example.lfrmobileapp.databinding.ActivityMainBinding; + +public class MainActivity extends AppCompatActivity { + + private ActivityMainBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + BottomNavigationView navView = findViewById(R.id.nav_view); + // Passing each menu ID as a set of Ids because each + // menu should be considered as top level destinations. + AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( + R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications) + .build(); + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main); + NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); + NavigationUI.setupWithNavController(binding.navView, navController); + } + +} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java new file mode 100644 index 0000000..330b508 --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java @@ -0,0 +1,37 @@ +package com.example.lfrmobileapp.ui.dashboard; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.example.lfrmobileapp.databinding.FragmentAutomatikBinding; + +public class DashboardFragment extends Fragment { + + private FragmentAutomatikBinding binding; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + DashboardViewModel dashboardViewModel = + new ViewModelProvider(this).get(DashboardViewModel.class); + + binding = FragmentAutomatikBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + final TextView textView = binding.textDashboard; + dashboardViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardViewModel.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardViewModel.java new file mode 100644 index 0000000..d7c1b93 --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardViewModel.java @@ -0,0 +1,19 @@ +package com.example.lfrmobileapp.ui.dashboard; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class DashboardViewModel extends ViewModel { + + private final MutableLiveData mText; + + public DashboardViewModel() { + mText = new MutableLiveData<>(); + mText.setValue(""); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java new file mode 100644 index 0000000..a19e9c3 --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java @@ -0,0 +1,53 @@ +package com.example.lfrmobileapp.ui.home; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.example.lfrmobileapp.databinding.FragmentManuellBinding; + +import io.github.controlwear.virtual.joystick.android.JoystickView; + +public class HomeFragment extends Fragment { + + private FragmentManuellBinding binding; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + HomeViewModel homeViewModel = + new ViewModelProvider(this).get(HomeViewModel.class); + + binding = FragmentManuellBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + final TextView textView = binding.textHome; + homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); + + JoystickView joystick = (JoystickView) binding.joystick; + joystick.setOnMoveListener(new JoystickView.OnMoveListener() { + @Override + public void onMove(int angle, int strength) { + homeViewModel.setText(Integer.toString(angle), Integer.toString(strength)); + } + }); + + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + + +} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeViewModel.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeViewModel.java new file mode 100644 index 0000000..9f05bcd --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeViewModel.java @@ -0,0 +1,24 @@ +package com.example.lfrmobileapp.ui.home; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class HomeViewModel extends ViewModel { + + private final MutableLiveData mText; + + public HomeViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("Bewege den Punkt zum steuern des Roboters"); + } + + public LiveDatasetText(String angle, String strength){ + mText.setValue("Winkel: "+ angle + " Verstärkung: " + strength); + return mText; + }; + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java new file mode 100644 index 0000000..eaaf556 --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java @@ -0,0 +1,37 @@ +package com.example.lfrmobileapp.ui.notifications; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.example.lfrmobileapp.databinding.FragmentEinstellungenBinding; + +public class NotificationsFragment extends Fragment { + + private FragmentEinstellungenBinding binding; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + NotificationsViewModel notificationsViewModel = + new ViewModelProvider(this).get(NotificationsViewModel.class); + + binding = FragmentEinstellungenBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + final TextView textView = binding.textNotifications; + notificationsViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsViewModel.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsViewModel.java new file mode 100644 index 0000000..b1eb19d --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsViewModel.java @@ -0,0 +1,19 @@ +package com.example.lfrmobileapp.ui.notifications; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class NotificationsViewModel extends ViewModel { + + private final MutableLiveData mText; + + public NotificationsViewModel() { + mText = new MutableLiveData<>(); + mText.setValue(""); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/MobileApp/app/src/main/res/drawable-anydpi/automatik.xml b/MobileApp/app/src/main/res/drawable-anydpi/automatik.xml new file mode 100644 index 0000000..fed05fb --- /dev/null +++ b/MobileApp/app/src/main/res/drawable-anydpi/automatik.xml @@ -0,0 +1,11 @@ + + + diff --git a/MobileApp/app/src/main/res/drawable-anydpi/einstellungen.xml b/MobileApp/app/src/main/res/drawable-anydpi/einstellungen.xml new file mode 100644 index 0000000..0a4ca26 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable-anydpi/einstellungen.xml @@ -0,0 +1,11 @@ + + + diff --git a/MobileApp/app/src/main/res/drawable-anydpi/manuell.xml b/MobileApp/app/src/main/res/drawable-anydpi/manuell.xml new file mode 100644 index 0000000..9afc8f8 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable-anydpi/manuell.xml @@ -0,0 +1,14 @@ + + + + diff --git a/MobileApp/app/src/main/res/drawable-hdpi/automatik.png b/MobileApp/app/src/main/res/drawable-hdpi/automatik.png new file mode 100644 index 0000000..c3b6893 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-hdpi/automatik.png differ diff --git a/MobileApp/app/src/main/res/drawable-hdpi/einstellungen.png b/MobileApp/app/src/main/res/drawable-hdpi/einstellungen.png new file mode 100644 index 0000000..54a6240 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-hdpi/einstellungen.png differ diff --git a/MobileApp/app/src/main/res/drawable-hdpi/manuell.png b/MobileApp/app/src/main/res/drawable-hdpi/manuell.png new file mode 100644 index 0000000..a2b006b Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-hdpi/manuell.png differ diff --git a/MobileApp/app/src/main/res/drawable-mdpi/automatik.png b/MobileApp/app/src/main/res/drawable-mdpi/automatik.png new file mode 100644 index 0000000..0a372f3 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-mdpi/automatik.png differ diff --git a/MobileApp/app/src/main/res/drawable-mdpi/einstellungen.png b/MobileApp/app/src/main/res/drawable-mdpi/einstellungen.png new file mode 100644 index 0000000..c83213f Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-mdpi/einstellungen.png differ diff --git a/MobileApp/app/src/main/res/drawable-mdpi/manuell.png b/MobileApp/app/src/main/res/drawable-mdpi/manuell.png new file mode 100644 index 0000000..54ddeec Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-mdpi/manuell.png differ diff --git a/MobileApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/MobileApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/drawable-xhdpi/automatik.png b/MobileApp/app/src/main/res/drawable-xhdpi/automatik.png new file mode 100644 index 0000000..523a007 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-xhdpi/automatik.png differ diff --git a/MobileApp/app/src/main/res/drawable-xhdpi/einstellungen.png b/MobileApp/app/src/main/res/drawable-xhdpi/einstellungen.png new file mode 100644 index 0000000..cc82440 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-xhdpi/einstellungen.png differ diff --git a/MobileApp/app/src/main/res/drawable-xhdpi/manuell.png b/MobileApp/app/src/main/res/drawable-xhdpi/manuell.png new file mode 100644 index 0000000..3ce9075 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-xhdpi/manuell.png differ diff --git a/MobileApp/app/src/main/res/drawable-xxhdpi/automatik.png b/MobileApp/app/src/main/res/drawable-xxhdpi/automatik.png new file mode 100644 index 0000000..a988772 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-xxhdpi/automatik.png differ diff --git a/MobileApp/app/src/main/res/drawable-xxhdpi/einstellungen.png b/MobileApp/app/src/main/res/drawable-xxhdpi/einstellungen.png new file mode 100644 index 0000000..95c8482 Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-xxhdpi/einstellungen.png differ diff --git a/MobileApp/app/src/main/res/drawable-xxhdpi/manuell.png b/MobileApp/app/src/main/res/drawable-xxhdpi/manuell.png new file mode 100644 index 0000000..efd1cab Binary files /dev/null and b/MobileApp/app/src/main/res/drawable-xxhdpi/manuell.png differ diff --git a/MobileApp/app/src/main/res/drawable/ic_baseline_rotate_left_24.xml b/MobileApp/app/src/main/res/drawable/ic_baseline_rotate_left_24.xml new file mode 100644 index 0000000..f6b24b7 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable/ic_baseline_rotate_left_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/MobileApp/app/src/main/res/drawable/ic_baseline_rotate_right_24.xml b/MobileApp/app/src/main/res/drawable/ic_baseline_rotate_right_24.xml new file mode 100644 index 0000000..9436d5b --- /dev/null +++ b/MobileApp/app/src/main/res/drawable/ic_baseline_rotate_right_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/MobileApp/app/src/main/res/drawable/ic_dashboard_black_24dp.xml b/MobileApp/app/src/main/res/drawable/ic_dashboard_black_24dp.xml new file mode 100644 index 0000000..46fc8de --- /dev/null +++ b/MobileApp/app/src/main/res/drawable/ic_dashboard_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/MobileApp/app/src/main/res/drawable/ic_home_black_24dp.xml b/MobileApp/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 0000000..f8bb0b5 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/MobileApp/app/src/main/res/drawable/ic_launcher_background.xml b/MobileApp/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MobileApp/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/MobileApp/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..78b75c3 --- /dev/null +++ b/MobileApp/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/MobileApp/app/src/main/res/layout/activity_main.xml b/MobileApp/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..54f4a65 --- /dev/null +++ b/MobileApp/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/layout/fragment_automatik.xml b/MobileApp/app/src/main/res/layout/fragment_automatik.xml new file mode 100644 index 0000000..42dc441 --- /dev/null +++ b/MobileApp/app/src/main/res/layout/fragment_automatik.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/layout/fragment_einstellungen.xml b/MobileApp/app/src/main/res/layout/fragment_einstellungen.xml new file mode 100644 index 0000000..d417935 --- /dev/null +++ b/MobileApp/app/src/main/res/layout/fragment_einstellungen.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/layout/fragment_manuell.xml b/MobileApp/app/src/main/res/layout/fragment_manuell.xml new file mode 100644 index 0000000..cd3b54d --- /dev/null +++ b/MobileApp/app/src/main/res/layout/fragment_manuell.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/menu/bottom_nav_menu.xml b/MobileApp/app/src/main/res/menu/bottom_nav_menu.xml new file mode 100644 index 0000000..20c7f08 --- /dev/null +++ b/MobileApp/app/src/main/res/menu/bottom_nav_menu.xml @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/MobileApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/MobileApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/MobileApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/MobileApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/MobileApp/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/MobileApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/MobileApp/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/MobileApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/MobileApp/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/MobileApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/MobileApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/MobileApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/MobileApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/MobileApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/MobileApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/MobileApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/MobileApp/app/src/main/res/navigation/mobile_navigation.xml b/MobileApp/app/src/main/res/navigation/mobile_navigation.xml new file mode 100644 index 0000000..74d858f --- /dev/null +++ b/MobileApp/app/src/main/res/navigation/mobile_navigation.xml @@ -0,0 +1,25 @@ + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/values-night/themes.xml b/MobileApp/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..4314902 --- /dev/null +++ b/MobileApp/app/src/main/res/values-night/themes.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/values/colors.xml b/MobileApp/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..0e9e9ca --- /dev/null +++ b/MobileApp/app/src/main/res/values/colors.xml @@ -0,0 +1,13 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + #0046A0 + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/values/dimens.xml b/MobileApp/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..e00c2dd --- /dev/null +++ b/MobileApp/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 16dp + 16dp + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/values/strings.xml b/MobileApp/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..6698051 --- /dev/null +++ b/MobileApp/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + Line-Following-Robot 2.0 + Manuell + Automatik + Einstellungen + Kreuzungstyp + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/values/themes.xml b/MobileApp/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..3d76da0 --- /dev/null +++ b/MobileApp/app/src/main/res/values/themes.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/xml/backup_rules.xml b/MobileApp/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..fa0f996 --- /dev/null +++ b/MobileApp/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/MobileApp/app/src/main/res/xml/data_extraction_rules.xml b/MobileApp/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..9ee9997 --- /dev/null +++ b/MobileApp/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/MobileApp/app/src/test/java/com/example/lfrmobileapp/ExampleUnitTest.java b/MobileApp/app/src/test/java/com/example/lfrmobileapp/ExampleUnitTest.java new file mode 100644 index 0000000..56456b1 --- /dev/null +++ b/MobileApp/app/src/test/java/com/example/lfrmobileapp/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.example.lfrmobileapp; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/MobileApp/build.gradle b/MobileApp/build.gradle new file mode 100644 index 0000000..948fe78 --- /dev/null +++ b/MobileApp/build.gradle @@ -0,0 +1,9 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id 'com.android.application' version '7.2.0' apply false + id 'com.android.library' version '7.2.0' apply false +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/MobileApp/gradle.properties b/MobileApp/gradle.properties new file mode 100644 index 0000000..dab7c28 --- /dev/null +++ b/MobileApp/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/MobileApp/gradle/wrapper/gradle-wrapper.jar b/MobileApp/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/MobileApp/gradle/wrapper/gradle-wrapper.jar differ diff --git a/MobileApp/gradle/wrapper/gradle-wrapper.properties b/MobileApp/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..da34a91 --- /dev/null +++ b/MobileApp/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Jan 07 18:41:59 CET 2023 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/MobileApp/gradlew b/MobileApp/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/MobileApp/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/MobileApp/gradlew.bat b/MobileApp/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/MobileApp/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/MobileApp/settings.gradle b/MobileApp/settings.gradle new file mode 100644 index 0000000..347725b --- /dev/null +++ b/MobileApp/settings.gradle @@ -0,0 +1,22 @@ +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + } +} +rootProject.name = "LFRMobileApp" +include ':app' + + +include ':virtualjoystick' +project(':virtualjoystick').projectDir = new File(rootDir, 'virtual-joystick-android-master/virtualjoystick/') +include ':virtualjoystick' diff --git a/MobileApp/virtual-joystick-android-master/.gitignore b/MobileApp/virtual-joystick-android-master/.gitignore new file mode 100644 index 0000000..c88a4b6 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/.gitignore @@ -0,0 +1,7 @@ +*.iml +.gradle +/local.properties +.idea +.DS_Store +/build +/captures diff --git a/MobileApp/virtual-joystick-android-master/LICENSE b/MobileApp/virtual-joystick-android-master/LICENSE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/MobileApp/virtual-joystick-android-master/README.md b/MobileApp/virtual-joystick-android-master/README.md new file mode 100644 index 0000000..e5a16c4 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/README.md @@ -0,0 +1,187 @@ +# virtual-joystick-android + +**v1.10.1** _(New version - [support custom images](#image), button & background size, limited direction, normalized coordinate, alpha border)_ + +_I created this very simple library as a learning process and I have been inspired by this project [JoystickView](https://github.com/zerokol/JoystickView) (the author is a genius!)_ + +This library provides a very simple and **ready-to-use** custom view which emulates a joystick for Android. + +![Alt text](/misc/virtual-joystick-android.png?raw=true "Double Joystick with custom size and colors") + +### Gist +Here is a very simple snippets to use it. Just set the `onMoveListener` to retrieve its angle and strength. + +```java +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + ... + + JoystickView joystick = (JoystickView) findViewById(R.id.joystickView); + joystick.setOnMoveListener(new JoystickView.OnMoveListener() { + @Override + public void onMove(int angle, int strength) { + // do whatever you want + } + }); +} +``` +The **angle** follow the rules of a simple **counter-clock** protractor. The **strength is percentage** of how far the button is **from the center to the border**. + +![Alt text](/misc/virtual-joystick.png?raw=true "Explanation") + +By default the **refresh rate** to get the data is **20/sec (every 50ms)**. If you want more or less just set the listener with one more parameters to set the refresh rate in milliseconds. +```java +joystick.setOnMoveListener(new JoystickView.OnMoveListener() { ... }, 17); // around 60/sec +``` + +### Attributes + +You can customize the joystick according to these attributes `JV_buttonImage`, `JV_buttonColor`, `JV_buttonSizeRatio`, `JV_borderColor`, `JV_borderAlpha`, `JV_borderWidth`, `JV_backgroundColor`, `JV_backgroundSizeRatio`, `JV_fixedCenter`, `JV_autoReCenterButton`, `JV_buttonStickToBorder`, `JV_enabled` and `JV_buttonDirection` + +If you specified `JV_buttonImage` you don't need `JV_buttonColor` + +Here is an example for your layout resources: +```xml + +``` +#### Image +If you want a more customized joystick, you can use `JV_buttonImage` and the regular `background` attributes to specify drawables. The images will be automatically resized. + +```xml + +``` + +![Alt text](/misc/android-virtual-joystick-custom-image.png?raw=true "Left joystick with custom image") + +#### SizeRatio +We can change the default size of the button and background. +The size is calculated as a percentage of the total width/height. + +By default, the button is 25% (0.25) and the background 75% (0.25), as the first screenshot above. + +If the total (background + button) is above 1.0, the button will probably be a bit cut when on the border. + +```xml +<... + custom:JV_buttonSizeRatio="50%" + custom:JV_backgroundSizeRatio="10%"/> + +``` + +```java +joystick.setBackgroundSizeRatio(0.5); +joystick.setButtonSizeRatio(0.1); +``` + +_The background size is not working for a custom picture._ + +#### FixedCenter or Not? (and auto re-center) +If you don’t set up this parameter, it will be FixedCenter by default, which is the regular behavior. + +However, sometimes, it is convenient to have an auto-defined center which will be defined each time you touch down the screen with your finger (center position will be limited inside the JoystickView’s width/height). +As every parameter you can set it up in xml (as above) or in Java: +```java +joystick.setFixedCenter(false); // set up auto-define center +``` + +UnfixedCenter (set to false) is particularly convenient when the user can’t (or doesn’t want to) see the screen (e.g. a drone's controller). + +We can also remove the automatically re-centered button, just set it to false. +```java +joystick.setAutoReCenterButton(false); +``` +_(The behavior is a bit weird if we set remove both the FixedCenter and the AutoReCenter.)_ + +#### Enabled +By default the joystick is enabled (set to True), but you can disable it either in xml or Java. Then, the button will stop moving and `onMove()` won’t be called anymore. +```java +joystick.setEnabled(false); // disabled the joystick +joystick.isEnabled(); // return enabled state +``` + +#### ButtonDirection +By default the button can move in both direction X,Y (regular behavior), but we can limit the movement through one axe horizontal or vertical. +```xml +<... + custom:JV_buttonDirection="horizontal"/> +``` +In the layout file (xml), this option can be set to `horizontal`, `vertical` or `both`. + +We can also set this option in the Java file by setting an integer value: +- any negative value (e.g. -1) for the horizontal axe +- any positive value (e.g. 1) for the vertical axe +- zero (0) for both (which is the default option) + +```java +joystick.setButtonDirection(1); // vertical +``` + +### Wearable +If you use this library in Wearable app, you will probably disable the Swipe-To-Dismiss Gesture and implement the Long Press to Dismiss Pattern, which could be a problem for a Joystick Pattern (because we usually let the user touch the joystick as long as she/he wants), in that case you can set another convenient listener: `OnMultipleLongPressListener` which will be invoked only with multiple pointers (at least two fingers) instead of one. +```java +joystick.setOnMultiLongPressListener(new JoystickView.OnMultipleLongPressListener() { + @Override + public void onMultipleLongPress() { + ... // eg. mDismissOverlay.show(); + } +}); +``` +Or better, if you just want a simple Joystick (and few other cool stuff) as a controller for your mobile app you can use the following related project ;) + +## Demo +For those who want more than just a snippet, here is the demo : +- [Basic two joysticks ](https://github.com/controlwear/virtual-joystick-demo) (similar to screenshot) + +If you want to add your project here, go ahead :) + +## Required +Minimum API level is 16 (Android 4.1.x - Jelly Bean) which cover 99.5% of the Android platforms as of October 2018 according to the distribution dashboard. + +## Download +### Gradle +```java +compile 'io.github.controlwear:virtualjoystick:1.10.1' +``` + +## Contributing +If you would like to contribute code, you can do so through GitHub by forking the repository and sending a pull request. +When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. + +## License +``` +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. +``` + +## Authors + +**virtual-joystick-android** is an open source project created by @makowildcat (mostly spare time) and partially funded by [Black Artick](http://blackartick.com/) and [NSERC](http://www.nserc-crsng.gc.ca/index_eng.asp). + +Also, thanks to Bernix01, teancake, Spettacolo83, djjaysmith, jaybkim1, sikrinick, AlexandrDavydov, indrek-koue, QitmentX7, esplemea, FenixGit, AlexanderShniperson +and GijsGoudzwaard for contributing. diff --git a/MobileApp/virtual-joystick-android-master/build.gradle b/MobileApp/virtual-joystick-android-master/build.gradle new file mode 100644 index 0000000..8bbeaab --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/build.gradle @@ -0,0 +1,28 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + google() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/MobileApp/virtual-joystick-android-master/gradle.properties b/MobileApp/virtual-joystick-android-master/gradle.properties new file mode 100644 index 0000000..1d3591c --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true \ No newline at end of file diff --git a/MobileApp/virtual-joystick-android-master/gradle/wrapper/gradle-wrapper.jar b/MobileApp/virtual-joystick-android-master/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..05ef575 Binary files /dev/null and b/MobileApp/virtual-joystick-android-master/gradle/wrapper/gradle-wrapper.jar differ diff --git a/MobileApp/virtual-joystick-android-master/gradle/wrapper/gradle-wrapper.properties b/MobileApp/virtual-joystick-android-master/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9f723b0 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Nov 20 17:17:49 EST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/MobileApp/virtual-joystick-android-master/gradlew b/MobileApp/virtual-joystick-android-master/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/MobileApp/virtual-joystick-android-master/gradlew.bat b/MobileApp/virtual-joystick-android-master/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/MobileApp/virtual-joystick-android-master/misc/android-virtual-joystick-custom-image.png b/MobileApp/virtual-joystick-android-master/misc/android-virtual-joystick-custom-image.png new file mode 100644 index 0000000..213d59e Binary files /dev/null and b/MobileApp/virtual-joystick-android-master/misc/android-virtual-joystick-custom-image.png differ diff --git a/MobileApp/virtual-joystick-android-master/misc/virtual-joystick-android.png b/MobileApp/virtual-joystick-android-master/misc/virtual-joystick-android.png new file mode 100644 index 0000000..f33d019 Binary files /dev/null and b/MobileApp/virtual-joystick-android-master/misc/virtual-joystick-android.png differ diff --git a/MobileApp/virtual-joystick-android-master/misc/virtual-joystick.png b/MobileApp/virtual-joystick-android-master/misc/virtual-joystick.png new file mode 100644 index 0000000..71dbfe3 Binary files /dev/null and b/MobileApp/virtual-joystick-android-master/misc/virtual-joystick.png differ diff --git a/MobileApp/virtual-joystick-android-master/settings.gradle b/MobileApp/virtual-joystick-android-master/settings.gradle new file mode 100644 index 0000000..0175e54 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/settings.gradle @@ -0,0 +1 @@ +include ':virtualjoystick' diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/.gitignore b/MobileApp/virtual-joystick-android-master/virtualjoystick/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/.gitignore @@ -0,0 +1 @@ +/build diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/build.gradle b/MobileApp/virtual-joystick-android-master/virtualjoystick/build.gradle new file mode 100644 index 0000000..1695c6f --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/build.gradle @@ -0,0 +1,47 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 32 + versionCode 20 + versionName "1.10.1" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation 'junit:junit:4.12' +} + +ext { + // Where you will see your artifact in Bintray's web interface + // The "bintrayName" should match the name of the Bintray repro. + bintrayRepo = 'maven' + bintrayName = 'virtual-joystick-android' + + // Maven metadata + publishedGroupId = 'io.github.controlwear' + libraryName = 'virtual-joystick-android' + // Save yourself a head ache, and set this equal to the name of the Android Studio library + // module. The artifact name needs to match the name of the library. + artifact = 'virtualjoystick' + + libraryDescription = 'This library provides a very simple and ready-to-use custom view which emulates a joystick for Android.' + libraryVersion = '1.10.1' + + developerId = 'makowildcat' + developerName = 'Damien Brun' + developerEmail = 'makowildcat@gmail.com' +} + +//apply from: 'https://raw.githubusercontent.com/attwellbrian/JCenter/master/installv1.gradle' +//apply from: 'https://raw.githubusercontent.com/attwellbrian/JCenter/master/bintrayv1.gradle' diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/proguard-rules.pro b/MobileApp/virtual-joystick-android-master/virtualjoystick/proguard-rules.pro new file mode 100644 index 0000000..c202a9e --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/damienbrun/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# 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 *; +#} diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/AndroidManifest.xml b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a80144e --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java new file mode 100644 index 0000000..bcf400d --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/java/io/github/controlwear/virtual/joystick/android/JoystickView.java @@ -0,0 +1,871 @@ +package io.github.controlwear.virtual.joystick.android; + + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +public class JoystickView extends View + implements + Runnable { + + + /* + INTERFACES + */ + + + /** + * Interface definition for a callback to be invoked when a + * JoystickView's button is moved + */ + public interface OnMoveListener { + + /** + * Called when a JoystickView's button has been moved + * @param angle current angle + * @param strength current strength + */ + void onMove(int angle, int strength); + } + + + /** + * Interface definition for a callback to be invoked when a JoystickView + * is touched and held by multiple pointers. + */ + public interface OnMultipleLongPressListener { + /** + * Called when a JoystickView has been touch and held enough time by multiple pointers. + */ + void onMultipleLongPress(); + } + + + /* + CONSTANTS + */ + + /** + * Default refresh rate as a time in milliseconds to send move values through callback + */ + private static final int DEFAULT_LOOP_INTERVAL = 50; // in milliseconds + + /** + * Used to allow a slight move without cancelling MultipleLongPress + */ + private static final int MOVE_TOLERANCE = 10; + + /** + * Default color for button + */ + private static final int DEFAULT_COLOR_BUTTON = Color.BLACK; + + /** + * Default color for border + */ + private static final int DEFAULT_COLOR_BORDER = Color.TRANSPARENT; + + /** + * Default alpha for border + */ + private static final int DEFAULT_ALPHA_BORDER = 255; + + /** + * Default background color + */ + private static final int DEFAULT_BACKGROUND_COLOR = Color.TRANSPARENT; + + /** + * Default View's size + */ + private static final int DEFAULT_SIZE = 200; + + /** + * Default border's width + */ + private static final int DEFAULT_WIDTH_BORDER = 3; + + /** + * Default behavior to fixed center (not auto-defined) + */ + private static final boolean DEFAULT_FIXED_CENTER = true; + + + /** + * Default behavior to auto re-center button (automatically recenter the button) + */ + private static final boolean DEFAULT_AUTO_RECENTER_BUTTON = true; + + + /** + * Default behavior to button stickToBorder (button stay on the border) + */ + private static final boolean DEFAULT_BUTTON_STICK_TO_BORDER = false; + + + // DRAWING + private Paint mPaintCircleButton; + private Paint mPaintCircleBorder; + private Paint mPaintBackground; + + private Paint mPaintBitmapButton; + private Bitmap mButtonBitmap; + + + /** + * Ratio use to define the size of the button + */ + private float mButtonSizeRatio; + + + /** + * Ratio use to define the size of the background + * + */ + private float mBackgroundSizeRatio; + + + // COORDINATE + private int mPosX = 0; + private int mPosY = 0; + private int mCenterX = 0; + private int mCenterY = 0; + + private int mFixedCenterX = 0; + private int mFixedCenterY = 0; + + /** + * Used to adapt behavior whether it is auto-defined center (false) or fixed center (true) + */ + private boolean mFixedCenter; + + + /** + * Used to adapt behavior whether the button is automatically re-centered (true) + * when released or not (false) + */ + private boolean mAutoReCenterButton; + + + /** + * Used to adapt behavior whether the button is stick to border (true) or + * could be anywhere (when false - similar to regular behavior) + */ + private boolean mButtonStickToBorder; + + + /** + * Used to enabled/disabled the Joystick. When disabled (enabled to false) the joystick button + * can't move and onMove is not called. + */ + private boolean mEnabled; + + + // SIZE + private int mButtonRadius; + private int mBorderRadius; + + + /** + * Alpha of the border (to use when changing color dynamically) + */ + private int mBorderAlpha; + + + /** + * Based on mBorderRadius but a bit smaller (minus half the stroke size of the border) + */ + private float mBackgroundRadius; + + + /** + * Listener used to dispatch OnMove event + */ + private OnMoveListener mCallback; + + private long mLoopInterval = DEFAULT_LOOP_INTERVAL; + private Thread mThread = new Thread(this); + + + /** + * Listener used to dispatch MultipleLongPress event + */ + private OnMultipleLongPressListener mOnMultipleLongPressListener; + + private final Handler mHandlerMultipleLongPress = new Handler(); + private Runnable mRunnableMultipleLongPress; + private int mMoveTolerance; + + + /** + * Default value. + * Both direction correspond to horizontal and vertical movement + */ + public static int BUTTON_DIRECTION_BOTH = 0; + + /** + * The allowed direction of the button is define by the value of this parameter: + * - a negative value for horizontal axe + * - a positive value for vertical axe + * - zero for both axes + */ + private int mButtonDirection = 0; + + + /* + CONSTRUCTORS + */ + + + /** + * Simple constructor to use when creating a JoystickView from code. + * Call another constructor passing null to Attribute. + * @param context The Context the JoystickView is running in, through which it can + * access the current theme, resources, etc. + */ + public JoystickView(Context context) { + this(context, null); + } + + + public JoystickView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs); + } + + + /** + * Constructor that is called when inflating a JoystickView from XML. This is called + * when a JoystickView is being constructed from an XML file, supplying attributes + * that were specified in the XML file. + * @param context The Context the JoystickView is running in, through which it can + * access the current theme, resources, etc. + * @param attrs The attributes of the XML tag that is inflating the JoystickView. + */ + public JoystickView(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray styledAttributes = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.JoystickView, + 0, 0 + ); + + int buttonColor; + int borderColor; + int backgroundColor; + int borderWidth; + Drawable buttonDrawable; + try { + buttonColor = styledAttributes.getColor(R.styleable.JoystickView_JV_buttonColor, DEFAULT_COLOR_BUTTON); + borderColor = styledAttributes.getColor(R.styleable.JoystickView_JV_borderColor, DEFAULT_COLOR_BORDER); + mBorderAlpha = styledAttributes.getInt(R.styleable.JoystickView_JV_borderAlpha, DEFAULT_ALPHA_BORDER); + backgroundColor = styledAttributes.getColor(R.styleable.JoystickView_JV_backgroundColor, DEFAULT_BACKGROUND_COLOR); + borderWidth = styledAttributes.getDimensionPixelSize(R.styleable.JoystickView_JV_borderWidth, DEFAULT_WIDTH_BORDER); + mFixedCenter = styledAttributes.getBoolean(R.styleable.JoystickView_JV_fixedCenter, DEFAULT_FIXED_CENTER); + mAutoReCenterButton = styledAttributes.getBoolean(R.styleable.JoystickView_JV_autoReCenterButton, DEFAULT_AUTO_RECENTER_BUTTON); + mButtonStickToBorder = styledAttributes.getBoolean(R.styleable.JoystickView_JV_buttonStickToBorder, DEFAULT_BUTTON_STICK_TO_BORDER); + buttonDrawable = styledAttributes.getDrawable(R.styleable.JoystickView_JV_buttonImage); + mEnabled = styledAttributes.getBoolean(R.styleable.JoystickView_JV_enabled, true); + mButtonSizeRatio = styledAttributes.getFraction(R.styleable.JoystickView_JV_buttonSizeRatio, 1, 1, 0.25f); + mBackgroundSizeRatio = styledAttributes.getFraction(R.styleable.JoystickView_JV_backgroundSizeRatio, 1, 1, 0.75f); + mButtonDirection = styledAttributes.getInteger(R.styleable.JoystickView_JV_buttonDirection, BUTTON_DIRECTION_BOTH); + } finally { + styledAttributes.recycle(); + } + + // Initialize the drawing according to attributes + + mPaintCircleButton = new Paint(); + mPaintCircleButton.setAntiAlias(true); + mPaintCircleButton.setColor(buttonColor); + mPaintCircleButton.setStyle(Paint.Style.FILL); + + if (buttonDrawable != null) { + if (buttonDrawable instanceof BitmapDrawable) { + mButtonBitmap = ((BitmapDrawable) buttonDrawable).getBitmap(); + mPaintBitmapButton = new Paint(); + } + } + + mPaintCircleBorder = new Paint(); + mPaintCircleBorder.setAntiAlias(true); + mPaintCircleBorder.setColor(borderColor); + mPaintCircleBorder.setStyle(Paint.Style.STROKE); + mPaintCircleBorder.setStrokeWidth(borderWidth); + + if (borderColor != Color.TRANSPARENT) { + mPaintCircleBorder.setAlpha(mBorderAlpha); + } + + mPaintBackground = new Paint(); + mPaintBackground.setAntiAlias(true); + mPaintBackground.setColor(backgroundColor); + mPaintBackground.setStyle(Paint.Style.FILL); + + + // Init Runnable for MultiLongPress + + mRunnableMultipleLongPress = new Runnable() { + @Override + public void run() { + if (mOnMultipleLongPressListener != null) + mOnMultipleLongPressListener.onMultipleLongPress(); + } + }; + } + + + private void initPosition() { + // get the center of view to position circle + mFixedCenterX = mCenterX = mPosX = getWidth() / 2; + mFixedCenterY = mCenterY = mPosY = getWidth() / 2; + } + + + /** + * Draw the background, the border and the button + * @param canvas the canvas on which the shapes will be drawn + */ + @Override + protected void onDraw(Canvas canvas) { + // Draw the background + canvas.drawCircle(mFixedCenterX, mFixedCenterY, mBackgroundRadius, mPaintBackground); + + // Draw the circle border + canvas.drawCircle(mFixedCenterX, mFixedCenterY, mBorderRadius, mPaintCircleBorder); + + // Draw the button from image + if (mButtonBitmap != null) { + canvas.drawBitmap( + mButtonBitmap, + mPosX + mFixedCenterX - mCenterX - mButtonRadius, + mPosY + mFixedCenterY - mCenterY - mButtonRadius, + mPaintBitmapButton + ); + } + // Draw the button as simple circle + else { + canvas.drawCircle( + mPosX + mFixedCenterX - mCenterX, + mPosY + mFixedCenterY - mCenterY, + mButtonRadius, + mPaintCircleButton + ); + } + } + + + /** + * This is called during layout when the size of this view has changed. + * Here we get the center of the view and the radius to draw all the shapes. + * + * @param w Current width of this view. + * @param h Current height of this view. + * @param oldW Old width of this view. + * @param oldH Old height of this view. + */ + @Override + protected void onSizeChanged(int w, int h, int oldW, int oldH) { + super.onSizeChanged(w, h, oldW, oldH); + + initPosition(); + + // radius based on smallest size : height OR width + int d = Math.min(w, h); + mButtonRadius = (int) (d / 2 * mButtonSizeRatio); + mBorderRadius = (int) (d / 2 * mBackgroundSizeRatio); + mBackgroundRadius = mBorderRadius - (mPaintCircleBorder.getStrokeWidth() / 2); + + if (mButtonBitmap != null) + mButtonBitmap = Bitmap.createScaledBitmap(mButtonBitmap, mButtonRadius * 2, mButtonRadius * 2, true); + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // setting the measured values to resize the view to a certain width and height + int d = Math.min(measure(widthMeasureSpec), measure(heightMeasureSpec)); + setMeasuredDimension(d, d); + } + + + private int measure(int measureSpec) { + if (MeasureSpec.getMode(measureSpec) == MeasureSpec.UNSPECIFIED) { + // if no bounds are specified return a default size (200) + return DEFAULT_SIZE; + } else { + // As you want to fill the available space + // always return the full available bounds. + return MeasureSpec.getSize(measureSpec); + } + } + + + /* + USER EVENT + */ + + + /** + * Handle touch screen motion event. Move the button according to the + * finger coordinate and detect longPress by multiple pointers only. + * + * @param event The motion event. + * @return True if the event was handled, false otherwise. + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + // if disabled we don't move the + if (!mEnabled) { + return true; + } + + + // to move the button according to the finger coordinate + // (or limited to one axe according to direction option + mPosY = mButtonDirection < 0 ? mCenterY : (int) event.getY(); // direction negative is horizontal axe + mPosX = mButtonDirection > 0 ? mCenterX : (int) event.getX(); // direction positive is vertical axe + + if (event.getAction() == MotionEvent.ACTION_UP) { + + // stop listener because the finger left the touch screen + mThread.interrupt(); + + // re-center the button or not (depending on settings) + if (mAutoReCenterButton) { + resetButtonPosition(); + + // update now the last strength and angle which should be zero after resetButton + if (mCallback != null) + mCallback.onMove(getAngle(), getStrength()); + } + + // if mAutoReCenterButton is false we will send the last strength and angle a bit + // later only after processing new position X and Y otherwise it could be above the border limit + } + + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mThread != null && mThread.isAlive()) { + mThread.interrupt(); + } + + mThread = new Thread(this); + mThread.start(); + + if (mCallback != null) + mCallback.onMove(getAngle(), getStrength()); + } + + // handle first touch and long press with multiple touch only + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // when the first touch occurs we update the center (if set to auto-defined center) + if (!mFixedCenter) { + mCenterX = mPosX; + mCenterY = mPosY; + } + break; + + case MotionEvent.ACTION_POINTER_DOWN: { + // when the second finger touch + if (event.getPointerCount() == 2) { + mHandlerMultipleLongPress.postDelayed(mRunnableMultipleLongPress, ViewConfiguration.getLongPressTimeout()*2); + mMoveTolerance = MOVE_TOLERANCE; + } + break; + } + + case MotionEvent.ACTION_MOVE: + mMoveTolerance--; + if (mMoveTolerance == 0) { + mHandlerMultipleLongPress.removeCallbacks(mRunnableMultipleLongPress); + } + break; + + case MotionEvent.ACTION_POINTER_UP: { + // when the last multiple touch is released + if (event.getPointerCount() == 2) { + mHandlerMultipleLongPress.removeCallbacks(mRunnableMultipleLongPress); + } + break; + } + } + + double abs = Math.sqrt((mPosX - mCenterX) * (mPosX - mCenterX) + + (mPosY - mCenterY) * (mPosY - mCenterY)); + + // (abs > mBorderRadius) means button is too far therefore we limit to border + // (buttonStickBorder && abs != 0) means wherever is the button we stick it to the border except when abs == 0 + if (abs > mBorderRadius || (mButtonStickToBorder && abs != 0)) { + mPosX = (int) ((mPosX - mCenterX) * mBorderRadius / abs + mCenterX); + mPosY = (int) ((mPosY - mCenterY) * mBorderRadius / abs + mCenterY); + } + + if (!mAutoReCenterButton) { + // Now update the last strength and angle if not reset to center + if (mCallback != null) + mCallback.onMove(getAngle(), getStrength()); + } + + + // to force a new draw + invalidate(); + + return true; + } + + + /* + GETTERS + */ + + + /** + * Process the angle following the 360° counter-clock protractor rules. + * @return the angle of the button + */ + private int getAngle() { + int angle = (int) Math.toDegrees(Math.atan2(mCenterY - mPosY, mPosX - mCenterX)); + return angle < 0 ? angle + 360 : angle; // make it as a regular counter-clock protractor + } + + + /** + * Process the strength as a percentage of the distance between the center and the border. + * @return the strength of the button + */ + private int getStrength() { + return (int) (100 * Math.sqrt((mPosX - mCenterX) + * (mPosX - mCenterX) + (mPosY - mCenterY) + * (mPosY - mCenterY)) / mBorderRadius); + } + + + /** + * Reset the button position to the center. + */ + public void resetButtonPosition() { + mPosX = mCenterX; + mPosY = mCenterY; + } + + + /** + * Return the current direction allowed for the button to move + * @return Actually return an integer corresponding to the direction: + * - A negative value is horizontal axe, + * - A positive value is vertical axe, + * - Zero means both axes + */ + public int getButtonDirection() { + return mButtonDirection; + } + + + /** + * Return the state of the joystick. False when the button don't move. + * @return the state of the joystick + */ + public boolean isEnabled() { + return mEnabled; + } + + + /** + * Return the size of the button (as a ratio of the total width/height) + * Default is 0.25 (25%). + * @return button size (value between 0.0 and 1.0) + */ + public float getButtonSizeRatio() { + return mButtonSizeRatio; + } + + + /** + * Return the size of the background (as a ratio of the total width/height) + * Default is 0.75 (75%). + * @return background size (value between 0.0 and 1.0) + */ + public float getmBackgroundSizeRatio() { + return mBackgroundSizeRatio; + } + + + /** + * Return the current behavior of the auto re-center button + * @return True if automatically re-centered or False if not + */ + public boolean isAutoReCenterButton() { + return mAutoReCenterButton; + } + + + /** + * Return the current behavior of the button stick to border + * @return True if the button stick to the border otherwise False + */ + public boolean isButtonStickToBorder() { + return mButtonStickToBorder; + } + + + /** + * Return the relative X coordinate of button center related + * to top-left virtual corner of the border + * @return coordinate of X (normalized between 0 and 100) + */ + public int getNormalizedX() { + if (getWidth() == 0) { + return 50; + } + return Math.round((mPosX-mButtonRadius)*100.0f/(getWidth()-mButtonRadius*2)); + } + + + /** + * Return the relative Y coordinate of the button center related + * to top-left virtual corner of the border + * @return coordinate of Y (normalized between 0 and 100) + */ + public int getNormalizedY() { + if (getHeight() == 0) { + return 50; + } + return Math.round((mPosY-mButtonRadius)*100.0f/(getHeight()-mButtonRadius*2)); + } + + + /** + * Return the alpha of the border + * @return it should be an integer between 0 and 255 previously set + */ + public int getBorderAlpha() { + return mBorderAlpha; + } + + /* + SETTERS + */ + + + /** + * Set an image to the button with a drawable + * @param d drawable to pick the image + */ + public void setButtonDrawable(Drawable d) { + if (d != null) { + if (d instanceof BitmapDrawable) { + mButtonBitmap = ((BitmapDrawable) d).getBitmap(); + + if (mButtonRadius != 0) { + mButtonBitmap = Bitmap.createScaledBitmap( + mButtonBitmap, + mButtonRadius * 2, + mButtonRadius * 2, + true); + } + + if (mPaintBitmapButton != null) + mPaintBitmapButton = new Paint(); + } + } + } + + + /** + * Set the button color for this JoystickView. + * @param color the color of the button + */ + public void setButtonColor(int color) { + mPaintCircleButton.setColor(color); + invalidate(); + } + + + /** + * Set the border color for this JoystickView. + * @param color the color of the border + */ + public void setBorderColor(int color) { + mPaintCircleBorder.setColor(color); + if (color != Color.TRANSPARENT) { + mPaintCircleBorder.setAlpha(mBorderAlpha); + } + invalidate(); + } + + + /** + * Set the border alpha for this JoystickView. + * @param alpha the transparency of the border between 0 and 255 + */ + public void setBorderAlpha(int alpha) { + mBorderAlpha = alpha; + mPaintCircleBorder.setAlpha(alpha); + invalidate(); + } + + + /** + * Set the background color for this JoystickView. + * @param color the color of the background + */ + @Override + public void setBackgroundColor(int color) { + mPaintBackground.setColor(color); + invalidate(); + } + + + /** + * Set the border width for this JoystickView. + * @param width the width of the border + */ + public void setBorderWidth(int width) { + mPaintCircleBorder.setStrokeWidth(width); + mBackgroundRadius = mBorderRadius - (width / 2.0f); + invalidate(); + } + + + /** + * Register a callback to be invoked when this JoystickView's button is moved + * @param l The callback that will run + */ + public void setOnMoveListener(OnMoveListener l) { + setOnMoveListener(l, DEFAULT_LOOP_INTERVAL); + } + + + /** + * Register a callback to be invoked when this JoystickView's button is moved + * @param l The callback that will run + * @param loopInterval Refresh rate to be invoked in milliseconds + */ + public void setOnMoveListener(OnMoveListener l, int loopInterval) { + mCallback = l; + mLoopInterval = loopInterval; + } + + + /** + * Register a callback to be invoked when this JoystickView is touch and held by multiple pointers + * @param l The callback that will run + */ + public void setOnMultiLongPressListener(OnMultipleLongPressListener l) { + mOnMultipleLongPressListener = l; + } + + + /** + * Set the joystick center's behavior (fixed or auto-defined) + * @param fixedCenter True for fixed center, False for auto-defined center based on touch down + */ + public void setFixedCenter(boolean fixedCenter) { + // if we set to "fixed" we make sure to re-init position related to the width of the joystick + if (fixedCenter) { + initPosition(); + } + mFixedCenter = fixedCenter; + invalidate(); + } + + + /** + * Enable or disable the joystick + * @param enabled False mean the button won't move and onMove won't be called + */ + public void setEnabled(boolean enabled) { + mEnabled = enabled; + } + + + /** + * Set the joystick button size (as a fraction of the real width/height) + * By default it is 25% (0.25). + * @param newRatio between 0.0 and 1.0 + */ + public void setButtonSizeRatio(float newRatio) { + if (newRatio > 0.0f & newRatio <= 1.0f) { + mButtonSizeRatio = newRatio; + } + } + + + /** + * Set the joystick button size (as a fraction of the real width/height) + * By default it is 75% (0.75). + * Not working if the background is an image. + * @param newRatio between 0.0 and 1.0 + */ + public void setBackgroundSizeRatio(float newRatio) { + if (newRatio > 0.0f & newRatio <= 1.0f) { + mBackgroundSizeRatio = newRatio; + } + } + + + /** + * Set the current behavior of the auto re-center button + * @param b True if automatically re-centered or False if not + */ + public void setAutoReCenterButton(boolean b) { + mAutoReCenterButton = b; + } + + + /** + * Set the current behavior of the button stick to border + * @param b True if the button stick to the border or False (default) if not + */ + public void setButtonStickToBorder(boolean b) { + mButtonStickToBorder = b; + } + + + /** + * Set the current authorized direction for the button to move + * @param direction the value will define the authorized direction: + * - any negative value (such as -1) for horizontal axe + * - any positive value (such as 1) for vertical axe + * - zero (0) for the full direction (both axes) + */ + public void setButtonDirection(int direction) { + mButtonDirection = direction; + } + + + /* + IMPLEMENTS + */ + + + @Override // Runnable + public void run() { + while (!Thread.interrupted()) { + post(new Runnable() { + public void run() { + if (mCallback != null) + mCallback.onMove(getAngle(), getStrength()); + } + }); + + try { + Thread.sleep(mLoopInterval); + } catch (InterruptedException e) { + break; + } + } + } +} \ No newline at end of file diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/res/values/attrs.xml b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/res/values/attrs.xml new file mode 100644 index 0000000..c3bf1dc --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/main/res/values/attrs.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MobileApp/virtual-joystick-android-master/virtualjoystick/src/test/java/io/github/controlwear/virtual/joystick/android/ExampleUnitTest.java b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/test/java/io/github/controlwear/virtual/joystick/android/ExampleUnitTest.java new file mode 100644 index 0000000..fd72f39 --- /dev/null +++ b/MobileApp/virtual-joystick-android-master/virtualjoystick/src/test/java/io/github/controlwear/virtual/joystick/android/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package io.github.controlwear.virtual.joystick.android; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file