| @@ -0,0 +1,18 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" | |||
| package="com.juce.jucedemo"> | |||
| <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/> | |||
| <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="11"/> | |||
| <uses-permission android:name="android.permission.RECORD_AUDIO"/> | |||
| <uses-permission android:name="android.permission.INTERNET"/> | |||
| <uses-feature android:glEsVersion="0x00020000" android:required="true"/> | |||
| <application android:label="@string/app_name" android:icon="@drawable/icon"> | |||
| <activity android:name="JuceDemo" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation"> | |||
| <intent-filter> | |||
| <action android:name="android.intent.action.MAIN"/> | |||
| <category android:name="android.intent.category.LAUNCHER"/> | |||
| </intent-filter> | |||
| </activity> | |||
| </application> | |||
| </manifest> | |||
| @@ -0,0 +1,31 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project name="JuceDemo" default="debug"> | |||
| <loadproperties srcFile="local.properties"/> | |||
| <loadproperties srcFile="project.properties"/> | |||
| <target name="clean"> | |||
| <exec executable="${ndk.dir}/ndk-build" dir="${basedir}" failonerror="true"> | |||
| <arg value="clean"/> | |||
| </exec> | |||
| </target> | |||
| <target name="-pre-build"> | |||
| <condition property="makefileConfig" value="Debug" else="Release"> | |||
| <equals arg1="${ant.project.invoked-targets}" arg2="debug"/> | |||
| </condition> | |||
| <condition property="ndkDebugValue" value="NDK_DEBUG=1" else="NDK_DEBUG=0"> | |||
| <equals arg1="${ant.project.invoked-targets}" arg2="debug"/> | |||
| </condition> | |||
| <condition property="app_abis" value="armeabi armeabi-v7a" else="armeabi armeabi-v7a"> | |||
| <equals arg1="${ant.project.invoked-targets}" arg2="debug"/> | |||
| </condition> | |||
| <exec executable="${ndk.dir}/ndk-build" dir="${basedir}" failonerror="true"> | |||
| <arg value="--jobs=2"/> | |||
| <arg value="CONFIG=${makefileConfig}"/> | |||
| <arg value="${ndkDebugValue}"/> | |||
| <arg value="APP_ABI=${app_abis}"/> | |||
| </exec> | |||
| <delete file="${out.final.file}"/> | |||
| <delete file="${out.packaged.file}"/> | |||
| </target> | |||
| <import file="${sdk.dir}/tools/ant/build.xml"/> | |||
| </project> | |||
| @@ -0,0 +1,76 @@ | |||
| # Automatically generated makefile, created by the Introjucer | |||
| # Don't edit this file! Your changes will be overwritten when you re-save the Introjucer project! | |||
| LOCAL_PATH := $(call my-dir) | |||
| include $(CLEAR_VARS) | |||
| LOCAL_ARM_MODE := arm | |||
| LOCAL_MODULE := juce_jni | |||
| LOCAL_SRC_FILES := \ | |||
| ../../../Source/Main.cpp\ | |||
| ../../../Source/MainWindow.cpp\ | |||
| ../../../Source/IntroScreen.cpp\ | |||
| ../../../Source/Demos/AnimationDemo.cpp\ | |||
| ../../../Source/Demos/AudioLatencyDemo.cpp\ | |||
| ../../../Source/Demos/AudioPlaybackDemo.cpp\ | |||
| ../../../Source/Demos/AudioRecordingDemo.cpp\ | |||
| ../../../Source/Demos/AudioSettingsDemo.cpp\ | |||
| ../../../Source/Demos/AudioSynthesiserDemo.cpp\ | |||
| ../../../Source/Demos/Box2DDemo.cpp\ | |||
| ../../../Source/Demos/CameraDemo.cpp\ | |||
| ../../../Source/Demos/CodeEditorDemo.cpp\ | |||
| ../../../Source/Demos/ComponentTransformsDemo.cpp\ | |||
| ../../../Source/Demos/CryptographyDemo.cpp\ | |||
| ../../../Source/Demos/DialogsDemo.cpp\ | |||
| ../../../Source/Demos/FontsDemo.cpp\ | |||
| ../../../Source/Demos/GraphicsDemo.cpp\ | |||
| ../../../Source/Demos/ImagesDemo.cpp\ | |||
| ../../../Source/Demos/JavaScript.cpp\ | |||
| ../../../Source/Demos/KeyMappingsDemo.cpp\ | |||
| ../../../Source/Demos/MDIDemo.cpp\ | |||
| ../../../Source/Demos/MidiDemo.cpp\ | |||
| ../../../Source/Demos/MultithreadingDemo.cpp\ | |||
| ../../../Source/Demos/MultiTouch.cpp\ | |||
| ../../../Source/Demos/NetworkingDemo.cpp\ | |||
| ../../../Source/Demos/OpenGLDemo.cpp\ | |||
| ../../../Source/Demos/PropertiesDemo.cpp\ | |||
| ../../../Source/Demos/SystemInfoDemo.cpp\ | |||
| ../../../Source/Demos/TimersAndEventsDemo.cpp\ | |||
| ../../../Source/Demos/UnitTestsDemo.cpp\ | |||
| ../../../Source/Demos/ValueTreesDemo.cpp\ | |||
| ../../../Source/Demos/VideoDemo.cpp\ | |||
| ../../../Source/Demos/WebBrowserDemo.cpp\ | |||
| ../../../Source/Demos/WidgetsDemo.cpp\ | |||
| ../../../Source/Demos/WindowsDemo.cpp\ | |||
| ../../../Source/Demos/XMLandJSONDemo.cpp\ | |||
| ../../../JuceLibraryCode/BinaryData.cpp\ | |||
| ../../../../../modules/juce_audio_basics/juce_audio_basics.cpp\ | |||
| ../../../../../modules/juce_audio_devices/juce_audio_devices.cpp\ | |||
| ../../../../../modules/juce_audio_formats/juce_audio_formats.cpp\ | |||
| ../../../../../modules/juce_audio_processors/juce_audio_processors.cpp\ | |||
| ../../../../../modules/juce_audio_utils/juce_audio_utils.cpp\ | |||
| ../../../../../modules/juce_box2d/juce_box2d.cpp\ | |||
| ../../../../../modules/juce_core/juce_core.cpp\ | |||
| ../../../../../modules/juce_cryptography/juce_cryptography.cpp\ | |||
| ../../../../../modules/juce_data_structures/juce_data_structures.cpp\ | |||
| ../../../../../modules/juce_events/juce_events.cpp\ | |||
| ../../../../../modules/juce_graphics/juce_graphics.cpp\ | |||
| ../../../../../modules/juce_gui_basics/juce_gui_basics.cpp\ | |||
| ../../../../../modules/juce_gui_extra/juce_gui_extra.cpp\ | |||
| ../../../../../modules/juce_opengl/juce_opengl.cpp\ | |||
| ../../../../../modules/juce_video/juce_video.cpp\ | |||
| ifeq ($(CONFIG),Debug) | |||
| LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -I "../../../../modules" -O0 -std=c++0x -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=9" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||
| LOCAL_LDLIBS := -llog -lGLESv2 | |||
| LOCAL_CFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -I "../../../../modules" -O0 -std=c++0x -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=9" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||
| LOCAL_LDLIBS := -llog -lGLESv2 | |||
| else | |||
| LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -I "../../../../modules" -O3 -std=c++0x -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=9" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||
| LOCAL_LDLIBS := -llog -lGLESv2 | |||
| LOCAL_CFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -I "../../../../modules" -O3 -std=c++0x -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=9" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||
| LOCAL_LDLIBS := -llog -lGLESv2 | |||
| endif | |||
| include $(BUILD_SHARED_LIBRARY) | |||
| @@ -0,0 +1,6 @@ | |||
| # Automatically generated makefile, created by the Introjucer | |||
| # Don't edit this file! Your changes will be overwritten when you re-save the Introjucer project! | |||
| APP_STL := gnustl_static | |||
| APP_CPPFLAGS += -fsigned-char -fexceptions -frtti -Wno-psabi | |||
| APP_PLATFORM := android-10 | |||
| @@ -0,0 +1,10 @@ | |||
| # This file is used to override default values used by the Ant build system. | |||
| # It is automatically generated by the Introjucer - DO NOT EDIT IT or your changes will be lost!. | |||
| sdk.dir=${user.home}/SDKs/android-sdk | |||
| ndk.dir=${user.home}/SDKs/android-ndk | |||
| key.store=${user.home}/.android/debug.keystore | |||
| key.alias=androiddebugkey | |||
| key.store.password=android | |||
| key.alias.password=android | |||
| @@ -0,0 +1,5 @@ | |||
| # This file is used to override default values used by the Ant build system. | |||
| # It is automatically generated - DO NOT EDIT IT or your changes will be lost!. | |||
| target=android-10 | |||
| @@ -0,0 +1,5 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <resources> | |||
| <string name="app_name">JuceDemo</string> | |||
| </resources> | |||
| @@ -0,0 +1,717 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||
| Permission is granted to use this software under the terms of either: | |||
| a) the GPL v2 (or any later version) | |||
| b) the Affero GPL v3 | |||
| Details of these licenses can be found at: www.gnu.org/licenses | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| package com.juce.jucedemo; | |||
| import android.app.Activity; | |||
| import android.app.AlertDialog; | |||
| import android.content.DialogInterface; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import android.content.res.Configuration; | |||
| import android.net.Uri; | |||
| import android.os.Bundle; | |||
| import android.view.*; | |||
| import android.view.inputmethod.BaseInputConnection; | |||
| import android.view.inputmethod.EditorInfo; | |||
| import android.view.inputmethod.InputConnection; | |||
| import android.view.inputmethod.InputMethodManager; | |||
| import android.graphics.*; | |||
| import android.opengl.*; | |||
| import android.text.ClipboardManager; | |||
| import android.text.InputType; | |||
| import android.util.DisplayMetrics; | |||
| import java.io.BufferedInputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.net.URL; | |||
| import java.net.HttpURLConnection; | |||
| import javax.microedition.khronos.egl.EGLConfig; | |||
| import javax.microedition.khronos.opengles.GL10; | |||
| import android.media.AudioManager; | |||
| import android.media.MediaScannerConnection; | |||
| import android.media.MediaScannerConnection.MediaScannerConnectionClient; | |||
| //============================================================================== | |||
| public final class JuceDemo extends Activity | |||
| { | |||
| //============================================================================== | |||
| static | |||
| { | |||
| System.loadLibrary ("juce_jni"); | |||
| } | |||
| @Override | |||
| public final void onCreate (Bundle savedInstanceState) | |||
| { | |||
| super.onCreate (savedInstanceState); | |||
| viewHolder = new ViewHolder (this); | |||
| setContentView (viewHolder); | |||
| setVolumeControlStream (AudioManager.STREAM_MUSIC); | |||
| } | |||
| @Override | |||
| protected final void onDestroy() | |||
| { | |||
| quitApp(); | |||
| super.onDestroy(); | |||
| } | |||
| @Override | |||
| protected final void onPause() | |||
| { | |||
| if (viewHolder != null) | |||
| viewHolder.onPause(); | |||
| suspendApp(); | |||
| super.onPause(); | |||
| } | |||
| @Override | |||
| protected final void onResume() | |||
| { | |||
| super.onResume(); | |||
| if (viewHolder != null) | |||
| viewHolder.onResume(); | |||
| resumeApp(); | |||
| } | |||
| @Override | |||
| public void onConfigurationChanged (Configuration cfg) | |||
| { | |||
| super.onConfigurationChanged (cfg); | |||
| setContentView (viewHolder); | |||
| } | |||
| private void callAppLauncher() | |||
| { | |||
| launchApp (getApplicationInfo().publicSourceDir, | |||
| getApplicationInfo().dataDir); | |||
| } | |||
| //============================================================================== | |||
| private native void launchApp (String appFile, String appDataDir); | |||
| private native void quitApp(); | |||
| private native void suspendApp(); | |||
| private native void resumeApp(); | |||
| private native void setScreenSize (int screenWidth, int screenHeight, int dpi); | |||
| //============================================================================== | |||
| public native void deliverMessage (long value); | |||
| private android.os.Handler messageHandler = new android.os.Handler(); | |||
| public final void postMessage (long value) | |||
| { | |||
| messageHandler.post (new MessageCallback (value)); | |||
| } | |||
| private final class MessageCallback implements Runnable | |||
| { | |||
| public MessageCallback (long value_) { value = value_; } | |||
| public final void run() { deliverMessage (value); } | |||
| private long value; | |||
| } | |||
| //============================================================================== | |||
| private ViewHolder viewHolder; | |||
| public final ComponentPeerView createNewView (boolean opaque, long host) | |||
| { | |||
| ComponentPeerView v = new ComponentPeerView (this, opaque, host); | |||
| viewHolder.addView (v); | |||
| return v; | |||
| } | |||
| public final void deleteView (ComponentPeerView view) | |||
| { | |||
| ViewGroup group = (ViewGroup) (view.getParent()); | |||
| if (group != null) | |||
| group.removeView (view); | |||
| } | |||
| final class ViewHolder extends ViewGroup | |||
| { | |||
| public ViewHolder (Context context) | |||
| { | |||
| super (context); | |||
| setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS); | |||
| setFocusable (false); | |||
| } | |||
| protected final void onLayout (boolean changed, int left, int top, int right, int bottom) | |||
| { | |||
| setScreenSize (getWidth(), getHeight(), getDPI()); | |||
| if (isFirstResize) | |||
| { | |||
| isFirstResize = false; | |||
| callAppLauncher(); | |||
| } | |||
| } | |||
| public final void onPause() | |||
| { | |||
| for (int i = getChildCount(); --i >= 0;) | |||
| { | |||
| View v = getChildAt (i); | |||
| if (v instanceof ComponentPeerView) | |||
| ((ComponentPeerView) v).onPause(); | |||
| } | |||
| } | |||
| public final void onResume() | |||
| { | |||
| for (int i = getChildCount(); --i >= 0;) | |||
| { | |||
| View v = getChildAt (i); | |||
| if (v instanceof ComponentPeerView) | |||
| ((ComponentPeerView) v).onResume(); | |||
| } | |||
| } | |||
| private final int getDPI() | |||
| { | |||
| DisplayMetrics metrics = new DisplayMetrics(); | |||
| getWindowManager().getDefaultDisplay().getMetrics (metrics); | |||
| return metrics.densityDpi; | |||
| } | |||
| private boolean isFirstResize = true; | |||
| } | |||
| public final void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom) | |||
| { | |||
| canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE); | |||
| } | |||
| //============================================================================== | |||
| public final String getClipboardContent() | |||
| { | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| return clipboard.getText().toString(); | |||
| } | |||
| public final void setClipboardContent (String newText) | |||
| { | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| clipboard.setText (newText); | |||
| } | |||
| //============================================================================== | |||
| public final void showMessageBox (String title, String message, final long callback) | |||
| { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder (this); | |||
| builder.setTitle (title) | |||
| .setMessage (message) | |||
| .setCancelable (true) | |||
| .setPositiveButton ("OK", new DialogInterface.OnClickListener() | |||
| { | |||
| public void onClick (DialogInterface dialog, int id) | |||
| { | |||
| dialog.cancel(); | |||
| JuceDemo.this.alertDismissed (callback, 0); | |||
| } | |||
| }); | |||
| builder.create().show(); | |||
| } | |||
| public final void showOkCancelBox (String title, String message, final long callback) | |||
| { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder (this); | |||
| builder.setTitle (title) | |||
| .setMessage (message) | |||
| .setCancelable (true) | |||
| .setPositiveButton ("OK", new DialogInterface.OnClickListener() | |||
| { | |||
| public void onClick (DialogInterface dialog, int id) | |||
| { | |||
| dialog.cancel(); | |||
| JuceDemo.this.alertDismissed (callback, 1); | |||
| } | |||
| }) | |||
| .setNegativeButton ("Cancel", new DialogInterface.OnClickListener() | |||
| { | |||
| public void onClick (DialogInterface dialog, int id) | |||
| { | |||
| dialog.cancel(); | |||
| JuceDemo.this.alertDismissed (callback, 0); | |||
| } | |||
| }); | |||
| builder.create().show(); | |||
| } | |||
| public final void showYesNoCancelBox (String title, String message, final long callback) | |||
| { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder (this); | |||
| builder.setTitle (title) | |||
| .setMessage (message) | |||
| .setCancelable (true) | |||
| .setPositiveButton ("Yes", new DialogInterface.OnClickListener() | |||
| { | |||
| public void onClick (DialogInterface dialog, int id) | |||
| { | |||
| dialog.cancel(); | |||
| JuceDemo.this.alertDismissed (callback, 1); | |||
| } | |||
| }) | |||
| .setNegativeButton ("No", new DialogInterface.OnClickListener() | |||
| { | |||
| public void onClick (DialogInterface dialog, int id) | |||
| { | |||
| dialog.cancel(); | |||
| JuceDemo.this.alertDismissed (callback, 2); | |||
| } | |||
| }) | |||
| .setNeutralButton ("Cancel", new DialogInterface.OnClickListener() | |||
| { | |||
| public void onClick (DialogInterface dialog, int id) | |||
| { | |||
| dialog.cancel(); | |||
| JuceDemo.this.alertDismissed (callback, 0); | |||
| } | |||
| }); | |||
| builder.create().show(); | |||
| } | |||
| public native void alertDismissed (long callback, int id); | |||
| //============================================================================== | |||
| public final class ComponentPeerView extends ViewGroup | |||
| implements View.OnFocusChangeListener | |||
| { | |||
| public ComponentPeerView (Context context, boolean opaque_, long host) | |||
| { | |||
| super (context); | |||
| this.host = host; | |||
| setWillNotDraw (false); | |||
| opaque = opaque_; | |||
| setFocusable (true); | |||
| setFocusableInTouchMode (true); | |||
| setOnFocusChangeListener (this); | |||
| requestFocus(); | |||
| } | |||
| //============================================================================== | |||
| private native void handlePaint (long host, Canvas canvas); | |||
| @Override | |||
| public void onDraw (Canvas canvas) | |||
| { | |||
| handlePaint (host, canvas); | |||
| } | |||
| @Override | |||
| public boolean isOpaque() | |||
| { | |||
| return opaque; | |||
| } | |||
| private boolean opaque; | |||
| private long host; | |||
| //============================================================================== | |||
| private native void handleMouseDown (long host, int index, float x, float y, long time); | |||
| private native void handleMouseDrag (long host, int index, float x, float y, long time); | |||
| private native void handleMouseUp (long host, int index, float x, float y, long time); | |||
| @Override | |||
| public boolean onTouchEvent (MotionEvent event) | |||
| { | |||
| int action = event.getAction(); | |||
| long time = event.getEventTime(); | |||
| switch (action & MotionEvent.ACTION_MASK) | |||
| { | |||
| case MotionEvent.ACTION_DOWN: | |||
| handleMouseDown (host, event.getPointerId(0), event.getX(), event.getY(), time); | |||
| return true; | |||
| case MotionEvent.ACTION_CANCEL: | |||
| case MotionEvent.ACTION_UP: | |||
| handleMouseUp (host, event.getPointerId(0), event.getX(), event.getY(), time); | |||
| return true; | |||
| case MotionEvent.ACTION_MOVE: | |||
| { | |||
| int n = event.getPointerCount(); | |||
| for (int i = 0; i < n; ++i) | |||
| handleMouseDrag (host, event.getPointerId(i), event.getX(i), event.getY(i), time); | |||
| return true; | |||
| } | |||
| case MotionEvent.ACTION_POINTER_UP: | |||
| { | |||
| int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; | |||
| handleMouseUp (host, event.getPointerId(i), event.getX(i), event.getY(i), time); | |||
| return true; | |||
| } | |||
| case MotionEvent.ACTION_POINTER_DOWN: | |||
| { | |||
| int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; | |||
| handleMouseDown (host, event.getPointerId(i), event.getX(i), event.getY(i), time); | |||
| return true; | |||
| } | |||
| default: | |||
| break; | |||
| } | |||
| return false; | |||
| } | |||
| //============================================================================== | |||
| private native void handleKeyDown (long host, int keycode, int textchar); | |||
| private native void handleKeyUp (long host, int keycode, int textchar); | |||
| public void showKeyboard (boolean shouldShow) | |||
| { | |||
| InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE); | |||
| if (imm != null) | |||
| { | |||
| if (shouldShow) | |||
| imm.showSoftInput (this, InputMethodManager.SHOW_FORCED); | |||
| else | |||
| imm.hideSoftInputFromWindow (getWindowToken(), 0); | |||
| } | |||
| } | |||
| @Override | |||
| public boolean onKeyDown (int keyCode, KeyEvent event) | |||
| { | |||
| switch (keyCode) | |||
| { | |||
| case KeyEvent.KEYCODE_VOLUME_UP: | |||
| case KeyEvent.KEYCODE_VOLUME_DOWN: | |||
| return super.onKeyDown (keyCode, event); | |||
| default: break; | |||
| } | |||
| handleKeyDown (host, keyCode, event.getUnicodeChar()); | |||
| return true; | |||
| } | |||
| @Override | |||
| public boolean onKeyUp (int keyCode, KeyEvent event) | |||
| { | |||
| handleKeyUp (host, keyCode, event.getUnicodeChar()); | |||
| return true; | |||
| } | |||
| // this is here to make keyboard entry work on a Galaxy Tab2 10.1 | |||
| @Override | |||
| public InputConnection onCreateInputConnection (EditorInfo outAttrs) | |||
| { | |||
| outAttrs.actionLabel = ""; | |||
| outAttrs.hintText = ""; | |||
| outAttrs.initialCapsMode = 0; | |||
| outAttrs.initialSelEnd = outAttrs.initialSelStart = -1; | |||
| outAttrs.label = ""; | |||
| outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI; | |||
| outAttrs.inputType = InputType.TYPE_NULL; | |||
| return new BaseInputConnection (this, false); | |||
| } | |||
| //============================================================================== | |||
| @Override | |||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||
| { | |||
| super.onSizeChanged (w, h, oldw, oldh); | |||
| viewSizeChanged (host); | |||
| } | |||
| @Override | |||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||
| { | |||
| for (int i = getChildCount(); --i >= 0;) | |||
| requestTransparentRegion (getChildAt (i)); | |||
| } | |||
| private native void viewSizeChanged (long host); | |||
| @Override | |||
| public void onFocusChange (View v, boolean hasFocus) | |||
| { | |||
| if (v == this) | |||
| focusChanged (host, hasFocus); | |||
| } | |||
| private native void focusChanged (long host, boolean hasFocus); | |||
| public void setViewName (String newName) {} | |||
| public boolean isVisible() { return getVisibility() == VISIBLE; } | |||
| public void setVisible (boolean b) { setVisibility (b ? VISIBLE : INVISIBLE); } | |||
| public boolean containsPoint (int x, int y) | |||
| { | |||
| return true; //xxx needs to check overlapping views | |||
| } | |||
| public final void onPause() | |||
| { | |||
| for (int i = getChildCount(); --i >= 0;) | |||
| { | |||
| View v = getChildAt (i); | |||
| if (v instanceof OpenGLView) | |||
| ((OpenGLView) v).onPause(); | |||
| } | |||
| } | |||
| public final void onResume() | |||
| { | |||
| for (int i = getChildCount(); --i >= 0;) | |||
| { | |||
| View v = getChildAt (i); | |||
| if (v instanceof OpenGLView) | |||
| ((OpenGLView) v).onResume(); | |||
| } | |||
| } | |||
| public OpenGLView createGLView() | |||
| { | |||
| OpenGLView glView = new OpenGLView (getContext()); | |||
| addView (glView); | |||
| return glView; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| public final class OpenGLView extends GLSurfaceView | |||
| implements GLSurfaceView.Renderer | |||
| { | |||
| OpenGLView (Context context) | |||
| { | |||
| super (context); | |||
| setEGLContextClientVersion (2); | |||
| setRenderer (this); | |||
| setRenderMode (RENDERMODE_WHEN_DIRTY); | |||
| } | |||
| @Override | |||
| public void onSurfaceCreated (GL10 unused, EGLConfig config) | |||
| { | |||
| contextCreated(); | |||
| } | |||
| @Override | |||
| public void onSurfaceChanged (GL10 unused, int width, int height) | |||
| { | |||
| contextChangedSize(); | |||
| } | |||
| @Override | |||
| public void onDrawFrame (GL10 unused) | |||
| { | |||
| render(); | |||
| } | |||
| private native void contextCreated(); | |||
| private native void contextChangedSize(); | |||
| private native void render(); | |||
| } | |||
| //============================================================================== | |||
| public final int[] renderGlyph (char glyph, Paint paint, android.graphics.Matrix matrix, Rect bounds) | |||
| { | |||
| Path p = new Path(); | |||
| paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p); | |||
| RectF boundsF = new RectF(); | |||
| p.computeBounds (boundsF, true); | |||
| matrix.mapRect (boundsF); | |||
| boundsF.roundOut (bounds); | |||
| bounds.left--; | |||
| bounds.right++; | |||
| final int w = bounds.width(); | |||
| final int h = Math.max (1, bounds.height()); | |||
| Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888); | |||
| Canvas c = new Canvas (bm); | |||
| matrix.postTranslate (-bounds.left, -bounds.top); | |||
| c.setMatrix (matrix); | |||
| c.drawPath (p, paint); | |||
| final int sizeNeeded = w * h; | |||
| if (cachedRenderArray.length < sizeNeeded) | |||
| cachedRenderArray = new int [sizeNeeded]; | |||
| bm.getPixels (cachedRenderArray, 0, w, 0, 0, w, h); | |||
| bm.recycle(); | |||
| return cachedRenderArray; | |||
| } | |||
| private int[] cachedRenderArray = new int [256]; | |||
| //============================================================================== | |||
| public static class HTTPStream | |||
| { | |||
| public HTTPStream (HttpURLConnection connection_) throws IOException | |||
| { | |||
| connection = connection_; | |||
| inputStream = new BufferedInputStream (connection.getInputStream()); | |||
| } | |||
| public final void release() | |||
| { | |||
| try | |||
| { | |||
| inputStream.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| connection.disconnect(); | |||
| } | |||
| public final int read (byte[] buffer, int numBytes) | |||
| { | |||
| int num = 0; | |||
| try | |||
| { | |||
| num = inputStream.read (buffer, 0, numBytes); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| if (num > 0) | |||
| position += num; | |||
| return num; | |||
| } | |||
| public final long getPosition() { return position; } | |||
| public final long getTotalLength() { return -1; } | |||
| public final boolean isExhausted() { return false; } | |||
| public final boolean setPosition (long newPos) { return false; } | |||
| private HttpURLConnection connection; | |||
| private InputStream inputStream; | |||
| private long position; | |||
| } | |||
| public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData, | |||
| String headers, int timeOutMs, | |||
| java.lang.StringBuffer responseHeaders) | |||
| { | |||
| try | |||
| { | |||
| HttpURLConnection connection = (HttpURLConnection) (new URL (address).openConnection()); | |||
| if (connection != null) | |||
| { | |||
| try | |||
| { | |||
| if (isPost) | |||
| { | |||
| connection.setConnectTimeout (timeOutMs); | |||
| connection.setDoOutput (true); | |||
| connection.setChunkedStreamingMode (0); | |||
| OutputStream out = connection.getOutputStream(); | |||
| out.write (postData); | |||
| out.flush(); | |||
| } | |||
| return new HTTPStream (connection); | |||
| } | |||
| catch (Throwable e) | |||
| { | |||
| connection.disconnect(); | |||
| } | |||
| } | |||
| } | |||
| catch (Throwable e) | |||
| {} | |||
| return null; | |||
| } | |||
| public final void launchURL (String url) | |||
| { | |||
| startActivity (new Intent (Intent.ACTION_VIEW, Uri.parse (url))); | |||
| } | |||
| public static final String getLocaleValue (boolean isRegion) | |||
| { | |||
| java.util.Locale locale = java.util.Locale.getDefault(); | |||
| return isRegion ? locale.getDisplayCountry (java.util.Locale.US) | |||
| : locale.getDisplayLanguage (java.util.Locale.US); | |||
| } | |||
| //============================================================================== | |||
| private final class SingleMediaScanner implements MediaScannerConnectionClient | |||
| { | |||
| public SingleMediaScanner (Context context, String filename) | |||
| { | |||
| file = filename; | |||
| msc = new MediaScannerConnection (context, this); | |||
| msc.connect(); | |||
| } | |||
| @Override | |||
| public void onMediaScannerConnected() | |||
| { | |||
| msc.scanFile (file, null); | |||
| } | |||
| @Override | |||
| public void onScanCompleted (String path, Uri uri) | |||
| { | |||
| msc.disconnect(); | |||
| } | |||
| private MediaScannerConnection msc; | |||
| private String file; | |||
| } | |||
| public final void scanFile (String filename) | |||
| { | |||
| new SingleMediaScanner (this, filename); | |||
| } | |||
| } | |||
| @@ -0,0 +1,384 @@ | |||
| # Automatically generated makefile, created by the Introjucer | |||
| # Don't edit this file! Your changes will be overwritten when you re-save the Introjucer project! | |||
| # (this disables dependency generation if multiple architectures are set) | |||
| DEPFLAGS := $(if $(word 2, $(TARGET_ARCH)), , -MMD) | |||
| ifndef CONFIG | |||
| CONFIG=Debug | |||
| endif | |||
| ifeq ($(CONFIG),Debug) | |||
| BINDIR := build | |||
| LIBDIR := build | |||
| OBJDIR := build/intermediate/Debug | |||
| OUTDIR := build | |||
| ifeq ($(TARGET_ARCH),) | |||
| TARGET_ARCH := -march=native | |||
| endif | |||
| CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../../modules | |||
| CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 | |||
| CXXFLAGS += $(CFLAGS) | |||
| LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt | |||
| LDDEPS := | |||
| RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../../modules | |||
| TARGET := JuceDemo | |||
| BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) | |||
| endif | |||
| ifeq ($(CONFIG),Release) | |||
| BINDIR := build | |||
| LIBDIR := build | |||
| OBJDIR := build/intermediate/Release | |||
| OUTDIR := build | |||
| ifeq ($(TARGET_ARCH),) | |||
| TARGET_ARCH := -march=native | |||
| endif | |||
| CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../../modules | |||
| CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 | |||
| CXXFLAGS += $(CFLAGS) | |||
| LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -fvisibility=hidden -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt | |||
| LDDEPS := | |||
| RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../../modules | |||
| TARGET := JuceDemo | |||
| BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) | |||
| endif | |||
| OBJECTS := \ | |||
| $(OBJDIR)/Main_90ebc5c2.o \ | |||
| $(OBJDIR)/MainWindow_499ac812.o \ | |||
| $(OBJDIR)/IntroScreen_73347059.o \ | |||
| $(OBJDIR)/AnimationDemo_9fc7e4e9.o \ | |||
| $(OBJDIR)/AudioLatencyDemo_78d49233.o \ | |||
| $(OBJDIR)/AudioPlaybackDemo_ea12adf6.o \ | |||
| $(OBJDIR)/AudioRecordingDemo_435914e6.o \ | |||
| $(OBJDIR)/AudioSettingsDemo_6d710bfe.o \ | |||
| $(OBJDIR)/AudioSynthesiserDemo_1b3666f6.o \ | |||
| $(OBJDIR)/Box2DDemo_51053c42.o \ | |||
| $(OBJDIR)/CameraDemo_a10f7e50.o \ | |||
| $(OBJDIR)/CodeEditorDemo_d5c17a65.o \ | |||
| $(OBJDIR)/ComponentTransformsDemo_377f7889.o \ | |||
| $(OBJDIR)/CryptographyDemo_232d46d7.o \ | |||
| $(OBJDIR)/DialogsDemo_19d585d0.o \ | |||
| $(OBJDIR)/FontsDemo_6da1e5e9.o \ | |||
| $(OBJDIR)/GraphicsDemo_85142ef6.o \ | |||
| $(OBJDIR)/ImagesDemo_ecf13aa3.o \ | |||
| $(OBJDIR)/JavaScript_d6e42eb5.o \ | |||
| $(OBJDIR)/KeyMappingsDemo_cf05c709.o \ | |||
| $(OBJDIR)/MDIDemo_c476c2d7.o \ | |||
| $(OBJDIR)/MidiDemo_75ebc30c.o \ | |||
| $(OBJDIR)/MultithreadingDemo_ff566eaa.o \ | |||
| $(OBJDIR)/MultiTouch_595f3a2e.o \ | |||
| $(OBJDIR)/NetworkingDemo_fbd1b19f.o \ | |||
| $(OBJDIR)/OpenGLDemo_fdac55da.o \ | |||
| $(OBJDIR)/PropertiesDemo_8ff1a8de.o \ | |||
| $(OBJDIR)/SystemInfoDemo_984acd28.o \ | |||
| $(OBJDIR)/TimersAndEventsDemo_f2656547.o \ | |||
| $(OBJDIR)/UnitTestsDemo_5c21762.o \ | |||
| $(OBJDIR)/ValueTreesDemo_9657d84f.o \ | |||
| $(OBJDIR)/VideoDemo_b55a1560.o \ | |||
| $(OBJDIR)/WebBrowserDemo_3df2dbdf.o \ | |||
| $(OBJDIR)/WidgetsDemo_fb0454.o \ | |||
| $(OBJDIR)/WindowsDemo_e8cfa428.o \ | |||
| $(OBJDIR)/XMLandJSONDemo_5bc88df3.o \ | |||
| $(OBJDIR)/BinaryData_ce4232d4.o \ | |||
| $(OBJDIR)/juce_audio_basics_399a455e.o \ | |||
| $(OBJDIR)/juce_audio_devices_c1c9ba9c.o \ | |||
| $(OBJDIR)/juce_audio_formats_f04b043c.o \ | |||
| $(OBJDIR)/juce_audio_processors_eb9ae116.o \ | |||
| $(OBJDIR)/juce_audio_utils_cf18005c.o \ | |||
| $(OBJDIR)/juce_box2d_7c8de7fc.o \ | |||
| $(OBJDIR)/juce_core_1ee54a40.o \ | |||
| $(OBJDIR)/juce_cryptography_3b1f489a.o \ | |||
| $(OBJDIR)/juce_data_structures_84790dfc.o \ | |||
| $(OBJDIR)/juce_events_584896b4.o \ | |||
| $(OBJDIR)/juce_graphics_f9afc18.o \ | |||
| $(OBJDIR)/juce_gui_basics_90929794.o \ | |||
| $(OBJDIR)/juce_gui_extra_b81d9e1c.o \ | |||
| $(OBJDIR)/juce_opengl_1890bee0.o \ | |||
| $(OBJDIR)/juce_video_86a19d3c.o \ | |||
| .PHONY: clean | |||
| $(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES) | |||
| @echo Linking JuceDemo | |||
| -@mkdir -p $(BINDIR) | |||
| -@mkdir -p $(LIBDIR) | |||
| -@mkdir -p $(OUTDIR) | |||
| @$(BLDCMD) | |||
| clean: | |||
| @echo Cleaning JuceDemo | |||
| -@rm -f $(OUTDIR)/$(TARGET) | |||
| -@rm -rf $(OBJDIR)/* | |||
| -@rm -rf $(OBJDIR) | |||
| strip: | |||
| @echo Stripping JuceDemo | |||
| -@strip --strip-unneeded $(OUTDIR)/$(TARGET) | |||
| $(OBJDIR)/Main_90ebc5c2.o: ../../Source/Main.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling Main.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/MainWindow_499ac812.o: ../../Source/MainWindow.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling MainWindow.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/IntroScreen_73347059.o: ../../Source/IntroScreen.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling IntroScreen.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/AnimationDemo_9fc7e4e9.o: ../../Source/Demos/AnimationDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling AnimationDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/AudioLatencyDemo_78d49233.o: ../../Source/Demos/AudioLatencyDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling AudioLatencyDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/AudioPlaybackDemo_ea12adf6.o: ../../Source/Demos/AudioPlaybackDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling AudioPlaybackDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/AudioRecordingDemo_435914e6.o: ../../Source/Demos/AudioRecordingDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling AudioRecordingDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/AudioSettingsDemo_6d710bfe.o: ../../Source/Demos/AudioSettingsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling AudioSettingsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/AudioSynthesiserDemo_1b3666f6.o: ../../Source/Demos/AudioSynthesiserDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling AudioSynthesiserDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/Box2DDemo_51053c42.o: ../../Source/Demos/Box2DDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling Box2DDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/CameraDemo_a10f7e50.o: ../../Source/Demos/CameraDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling CameraDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/CodeEditorDemo_d5c17a65.o: ../../Source/Demos/CodeEditorDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling CodeEditorDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/ComponentTransformsDemo_377f7889.o: ../../Source/Demos/ComponentTransformsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling ComponentTransformsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/CryptographyDemo_232d46d7.o: ../../Source/Demos/CryptographyDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling CryptographyDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/DialogsDemo_19d585d0.o: ../../Source/Demos/DialogsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling DialogsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/FontsDemo_6da1e5e9.o: ../../Source/Demos/FontsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling FontsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/GraphicsDemo_85142ef6.o: ../../Source/Demos/GraphicsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling GraphicsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/ImagesDemo_ecf13aa3.o: ../../Source/Demos/ImagesDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling ImagesDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/JavaScript_d6e42eb5.o: ../../Source/Demos/JavaScript.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling JavaScript.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/KeyMappingsDemo_cf05c709.o: ../../Source/Demos/KeyMappingsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling KeyMappingsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/MDIDemo_c476c2d7.o: ../../Source/Demos/MDIDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling MDIDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/MidiDemo_75ebc30c.o: ../../Source/Demos/MidiDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling MidiDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/MultithreadingDemo_ff566eaa.o: ../../Source/Demos/MultithreadingDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling MultithreadingDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/MultiTouch_595f3a2e.o: ../../Source/Demos/MultiTouch.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling MultiTouch.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/NetworkingDemo_fbd1b19f.o: ../../Source/Demos/NetworkingDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling NetworkingDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/OpenGLDemo_fdac55da.o: ../../Source/Demos/OpenGLDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling OpenGLDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/PropertiesDemo_8ff1a8de.o: ../../Source/Demos/PropertiesDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling PropertiesDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/SystemInfoDemo_984acd28.o: ../../Source/Demos/SystemInfoDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling SystemInfoDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/TimersAndEventsDemo_f2656547.o: ../../Source/Demos/TimersAndEventsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling TimersAndEventsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/UnitTestsDemo_5c21762.o: ../../Source/Demos/UnitTestsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling UnitTestsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/ValueTreesDemo_9657d84f.o: ../../Source/Demos/ValueTreesDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling ValueTreesDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/VideoDemo_b55a1560.o: ../../Source/Demos/VideoDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling VideoDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/WebBrowserDemo_3df2dbdf.o: ../../Source/Demos/WebBrowserDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling WebBrowserDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/WidgetsDemo_fb0454.o: ../../Source/Demos/WidgetsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling WidgetsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/WindowsDemo_e8cfa428.o: ../../Source/Demos/WindowsDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling WindowsDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/XMLandJSONDemo_5bc88df3.o: ../../Source/Demos/XMLandJSONDemo.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling XMLandJSONDemo.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/BinaryData_ce4232d4.o: ../../JuceLibraryCode/BinaryData.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling BinaryData.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_audio_basics_399a455e.o: ../../../../modules/juce_audio_basics/juce_audio_basics.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_audio_basics.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_audio_devices_c1c9ba9c.o: ../../../../modules/juce_audio_devices/juce_audio_devices.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_audio_devices.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_audio_formats_f04b043c.o: ../../../../modules/juce_audio_formats/juce_audio_formats.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_audio_formats.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_audio_processors_eb9ae116.o: ../../../../modules/juce_audio_processors/juce_audio_processors.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_audio_processors.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_audio_utils_cf18005c.o: ../../../../modules/juce_audio_utils/juce_audio_utils.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_audio_utils.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_box2d_7c8de7fc.o: ../../../../modules/juce_box2d/juce_box2d.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_box2d.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_core_1ee54a40.o: ../../../../modules/juce_core/juce_core.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_core.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_cryptography_3b1f489a.o: ../../../../modules/juce_cryptography/juce_cryptography.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_cryptography.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_data_structures_84790dfc.o: ../../../../modules/juce_data_structures/juce_data_structures.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_data_structures.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_events_584896b4.o: ../../../../modules/juce_events/juce_events.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_events.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_graphics_f9afc18.o: ../../../../modules/juce_graphics/juce_graphics.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_graphics.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_gui_basics_90929794.o: ../../../../modules/juce_gui_basics/juce_gui_basics.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_gui_basics.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_gui_extra_b81d9e1c.o: ../../../../modules/juce_gui_extra/juce_gui_extra.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_gui_extra.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_opengl_1890bee0.o: ../../../../modules/juce_opengl/juce_opengl.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_opengl.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| $(OBJDIR)/juce_video_86a19d3c.o: ../../../../modules/juce_video/juce_video.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling juce_video.cpp" | |||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||
| -include $(OBJECTS:%.o=%.d) | |||
| @@ -0,0 +1,27 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist> | |||
| <dict> | |||
| <key>CFBundleExecutable</key> | |||
| <string>${EXECUTABLE_NAME}</string> | |||
| <key>CFBundleIconFile</key> | |||
| <string>Icon.icns</string> | |||
| <key>CFBundleIdentifier</key> | |||
| <string>com.yourcompany.JuceDemo</string> | |||
| <key>CFBundleName</key> | |||
| <string>JuceDemo</string> | |||
| <key>CFBundlePackageType</key> | |||
| <string>APPL</string> | |||
| <key>CFBundleSignature</key> | |||
| <string>????</string> | |||
| <key>CFBundleShortVersionString</key> | |||
| <string>1.0.0</string> | |||
| <key>CFBundleVersion</key> | |||
| <string>1.0.0</string> | |||
| <key>NSHumanReadableCopyright</key> | |||
| <string></string> | |||
| <key>NSHighResolutionCapable</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @@ -0,0 +1,19 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| # Visual Studio 2010 | |||
| Project("{91BB874D-440B-A2C5-C57C-5104BA5F5EDC}") = "JuceDemo", "JuceDemo.vcxproj", "{9C58F305-06EC-8076-ACCD-88CCC530EFB5}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Win32 = Debug|Win32 | |||
| Release|Win32 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Debug|Win32.ActiveCfg = Debug|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Debug|Win32.Build.0 = Debug|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Release|Win32.ActiveCfg = Release|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Release|Win32.Build.0 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| EndGlobalSection | |||
| EndGlobal | |||
| @@ -0,0 +1,32 @@ | |||
| #ifdef JUCE_USER_DEFINED_RC_FILE | |||
| #include JUCE_USER_DEFINED_RC_FILE | |||
| #else | |||
| #undef WIN32_LEAN_AND_MEAN | |||
| #define WIN32_LEAN_AND_MEAN | |||
| #include <windows.h> | |||
| VS_VERSION_INFO VERSIONINFO | |||
| FILEVERSION 1,0,0,0 | |||
| BEGIN | |||
| BLOCK "StringFileInfo" | |||
| BEGIN | |||
| BLOCK "040904E4" | |||
| BEGIN | |||
| VALUE "FileDescription", "JuceDemo\0" | |||
| VALUE "FileVersion", "1.0.0\0" | |||
| VALUE "ProductName", "JuceDemo\0" | |||
| VALUE "ProductVersion", "1.0.0\0" | |||
| END | |||
| END | |||
| BLOCK "VarFileInfo" | |||
| BEGIN | |||
| VALUE "Translation", 0x409, 65001 | |||
| END | |||
| END | |||
| #endif | |||
| IDI_ICON1 ICON DISCARDABLE "icon.ico" | |||
| IDI_ICON2 ICON DISCARDABLE "icon.ico" | |||
| @@ -0,0 +1,19 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| # Visual Studio 2012 | |||
| Project("{91BB874D-440B-A2C5-C57C-5104BA5F5EDC}") = "JuceDemo", "JuceDemo.vcxproj", "{9C58F305-06EC-8076-ACCD-88CCC530EFB5}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Win32 = Debug|Win32 | |||
| Release|Win32 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Debug|Win32.ActiveCfg = Debug|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Debug|Win32.Build.0 = Debug|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Release|Win32.ActiveCfg = Release|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Release|Win32.Build.0 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| EndGlobalSection | |||
| EndGlobal | |||
| @@ -0,0 +1,32 @@ | |||
| #ifdef JUCE_USER_DEFINED_RC_FILE | |||
| #include JUCE_USER_DEFINED_RC_FILE | |||
| #else | |||
| #undef WIN32_LEAN_AND_MEAN | |||
| #define WIN32_LEAN_AND_MEAN | |||
| #include <windows.h> | |||
| VS_VERSION_INFO VERSIONINFO | |||
| FILEVERSION 1,0,0,0 | |||
| BEGIN | |||
| BLOCK "StringFileInfo" | |||
| BEGIN | |||
| BLOCK "040904E4" | |||
| BEGIN | |||
| VALUE "FileDescription", "JuceDemo\0" | |||
| VALUE "FileVersion", "1.0.0\0" | |||
| VALUE "ProductName", "JuceDemo\0" | |||
| VALUE "ProductVersion", "1.0.0\0" | |||
| END | |||
| END | |||
| BLOCK "VarFileInfo" | |||
| BEGIN | |||
| VALUE "Translation", 0x409, 65001 | |||
| END | |||
| END | |||
| #endif | |||
| IDI_ICON1 ICON DISCARDABLE "icon.ico" | |||
| IDI_ICON2 ICON DISCARDABLE "icon.ico" | |||
| @@ -0,0 +1,19 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| # Visual Studio 2013 | |||
| Project("{91BB874D-440B-A2C5-C57C-5104BA5F5EDC}") = "JuceDemo", "JuceDemo.vcxproj", "{9C58F305-06EC-8076-ACCD-88CCC530EFB5}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Win32 = Debug|Win32 | |||
| Release|Win32 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Debug|Win32.ActiveCfg = Debug|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Debug|Win32.Build.0 = Debug|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Release|Win32.ActiveCfg = Release|Win32 | |||
| {9C58F305-06EC-8076-ACCD-88CCC530EFB5}.Release|Win32.Build.0 = Release|Win32 | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| EndGlobalSection | |||
| EndGlobal | |||
| @@ -0,0 +1,32 @@ | |||
| #ifdef JUCE_USER_DEFINED_RC_FILE | |||
| #include JUCE_USER_DEFINED_RC_FILE | |||
| #else | |||
| #undef WIN32_LEAN_AND_MEAN | |||
| #define WIN32_LEAN_AND_MEAN | |||
| #include <windows.h> | |||
| VS_VERSION_INFO VERSIONINFO | |||
| FILEVERSION 1,0,0,0 | |||
| BEGIN | |||
| BLOCK "StringFileInfo" | |||
| BEGIN | |||
| BLOCK "040904E4" | |||
| BEGIN | |||
| VALUE "FileDescription", "JuceDemo\0" | |||
| VALUE "FileVersion", "1.0.0\0" | |||
| VALUE "ProductName", "JuceDemo\0" | |||
| VALUE "ProductVersion", "1.0.0\0" | |||
| END | |||
| END | |||
| BLOCK "VarFileInfo" | |||
| BEGIN | |||
| VALUE "Translation", 0x409, 65001 | |||
| END | |||
| END | |||
| #endif | |||
| IDI_ICON1 ICON DISCARDABLE "icon.ico" | |||
| IDI_ICON2 ICON DISCARDABLE "icon.ico" | |||
| @@ -0,0 +1,29 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist> | |||
| <dict> | |||
| <key>LSRequiresIPhoneOS</key> | |||
| <true/> | |||
| <key>CFBundleExecutable</key> | |||
| <string>${EXECUTABLE_NAME}</string> | |||
| <key>CFBundleIconFile</key> | |||
| <string>Icon.icns</string> | |||
| <key>CFBundleIdentifier</key> | |||
| <string>com.yourcompany.JuceDemo</string> | |||
| <key>CFBundleName</key> | |||
| <string>JuceDemo</string> | |||
| <key>CFBundlePackageType</key> | |||
| <string>APPL</string> | |||
| <key>CFBundleSignature</key> | |||
| <string>????</string> | |||
| <key>CFBundleShortVersionString</key> | |||
| <string>1.0.0</string> | |||
| <key>CFBundleVersion</key> | |||
| <string>1.0.0</string> | |||
| <key>NSHumanReadableCopyright</key> | |||
| <string></string> | |||
| <key>NSHighResolutionCapable</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @@ -0,0 +1,303 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <JUCERPROJECT id="sBBIzr" name="JuceDemo" projectType="guiapp" version="1.0.0" | |||
| juceLinkage="amalg_multi" buildVST="1" buildRTAS="0" buildAU="1" | |||
| pluginName="Juce Project" pluginDesc="Juce Project" pluginManufacturer="yourcompany" | |||
| pluginManufacturerCode="Manu" pluginCode="Plug" pluginChannelConfigs="{1, 1}, {2, 2}" | |||
| pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0" | |||
| pluginSilenceInIsSilenceOut="0" pluginTailLength="0" pluginEditorRequiresKeys="0" | |||
| pluginAUExportPrefix="JuceProjectAU" pluginAUViewClass="JuceProjectAU_V1" | |||
| pluginRTASCategory="" bundleIdentifier="com.yourcompany.JuceDemo" | |||
| jucerVersion="3.1.0" defines="JUCE_UNIT_TESTS=1" includeBinaryInAppConfig="1"> | |||
| <EXPORTFORMATS> | |||
| <XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK" | |||
| objCExtraSuffix="hZh0GG" bigIcon="BvyE0d" extraCompilerFlags="-Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo" | |||
| osxSDK="default" osxCompatibility="default" osxArchitecture="Native" | |||
| defines=""/> | |||
| <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="JuceDemo" | |||
| osxSDK="default" osxCompatibility="10.6 SDK" osxArchitecture="Native" | |||
| defines=""/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </XCODE_MAC> | |||
| <XCODE_IPHONE targetFolder="Builds/iOS" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK" | |||
| objCExtraSuffix="Lpywnl" bigIcon="BvyE0d"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo" | |||
| osxSDK="default" osxCompatibility="default" osxArchitecture="default" | |||
| defines="" iosCompatibility="default"/> | |||
| <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="JuceDemo" | |||
| osxSDK="default" osxCompatibility="default" osxArchitecture="default" | |||
| defines="" iosCompatibility="default"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </XCODE_IPHONE> | |||
| <VS2010 targetFolder="Builds/VisualStudio2010" vstFolder="c:\SDKs\vstsdk2.4" | |||
| rtasFolder="c:\SDKs\PT_80_SDK" libraryType="1" bigIcon="BvyE0d"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo" | |||
| defines="" winWarningLevel="4" winArchitecture="32-bit" generateManifest="1"/> | |||
| <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="JuceDemo" | |||
| defines="" winWarningLevel="4" winArchitecture="32-bit" generateManifest="1"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </VS2010> | |||
| <VS2012 targetFolder="Builds/VisualStudio2012" bigIcon="BvyE0d"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" | |||
| isDebug="1" optimisation="1" targetName="JuceDemo"/> | |||
| <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" | |||
| isDebug="0" optimisation="3" targetName="JuceDemo"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </VS2012> | |||
| <VS2013 targetFolder="Builds/VisualStudio2013" bigIcon="BvyE0d"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" | |||
| isDebug="1" optimisation="1" targetName="JuceDemo"/> | |||
| <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit" | |||
| isDebug="0" optimisation="3" targetName="JuceDemo"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </VS2013> | |||
| <ANDROID targetFolder="Builds/Android" androidActivityClass="com.juce.jucedemo.JuceDemo" | |||
| androidSDKPath="${user.home}/SDKs/android-sdk" androidNDKPath="${user.home}/SDKs/android-ndk" | |||
| androidMinimumSDK="9" androidInternetNeeded="1" androidKeyStore="${user.home}/.android/debug.keystore" | |||
| androidKeyStorePass="android" androidKeyAlias="androiddebugkey" | |||
| androidKeyAliasPass="android" androidMicNeeded="1" bigIcon="xycKOk" | |||
| androidCpp11="1"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" androidArchitectures="armeabi armeabi-v7a" isDebug="1" | |||
| optimisation="1" targetName="JuceDemo"/> | |||
| <CONFIGURATION name="Release" androidArchitectures="armeabi armeabi-v7a" isDebug="0" | |||
| optimisation="3" targetName="JuceDemo"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </ANDROID> | |||
| <LINUX_MAKE targetFolder="Builds/Linux"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" libraryPath="/usr/X11R6/lib/" isDebug="1" optimisation="1" | |||
| targetName="JuceDemo"/> | |||
| <CONFIGURATION name="Release" libraryPath="/usr/X11R6/lib/" isDebug="0" optimisation="3" | |||
| targetName="JuceDemo"/> | |||
| </CONFIGURATIONS> | |||
| <MODULEPATHS> | |||
| <MODULEPATH id="juce_video" path="../../modules"/> | |||
| <MODULEPATH id="juce_opengl" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_extra" path="../../modules"/> | |||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||
| <MODULEPATH id="juce_cryptography" path="../../modules"/> | |||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||
| <MODULEPATH id="juce_box2d" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_processors" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | |||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | |||
| </MODULEPATHS> | |||
| </LINUX_MAKE> | |||
| </EXPORTFORMATS> | |||
| <MAINGROUP id="giMP9w" name="JuceDemo"> | |||
| <GROUP id="YqGr3h" name="Source"> | |||
| <FILE id="SMaweI" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/> | |||
| <FILE id="Qsaulq" name="MainWindow.cpp" compile="1" resource="0" file="Source/MainWindow.cpp"/> | |||
| <FILE id="lU9OYz" name="MainWindow.h" compile="0" resource="0" file="Source/MainWindow.h"/> | |||
| <FILE id="Xx8GpS" name="DemoUtilities.h" compile="0" resource="0" file="Source/DemoUtilities.h"/> | |||
| <FILE id="wlp1ru" name="IntroScreen.cpp" compile="1" resource="0" file="Source/IntroScreen.cpp"/> | |||
| <FILE id="UaODxY" name="JuceDemoHeader.h" compile="0" resource="0" | |||
| file="Source/JuceDemoHeader.h"/> | |||
| <GROUP id="qHa6FB" name="Demos"> | |||
| <FILE id="J7O1be" name="AnimationDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/AnimationDemo.cpp"/> | |||
| <FILE id="zfNu7M" name="AudioLatencyDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/AudioLatencyDemo.cpp"/> | |||
| <FILE id="DYnsqa" name="AudioLiveScrollingDisplay.h" compile="0" resource="0" | |||
| file="Source/Demos/AudioLiveScrollingDisplay.h"/> | |||
| <FILE id="gsfrsQ" name="AudioPlaybackDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/AudioPlaybackDemo.cpp"/> | |||
| <FILE id="Fffkfc" name="AudioRecordingDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/AudioRecordingDemo.cpp"/> | |||
| <FILE id="snAgpi" name="AudioSettingsDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/AudioSettingsDemo.cpp"/> | |||
| <FILE id="gY4iMY" name="AudioSynthesiserDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/AudioSynthesiserDemo.cpp"/> | |||
| <FILE id="nWMZgj" name="Box2DDemo.cpp" compile="1" resource="0" file="Source/Demos/Box2DDemo.cpp"/> | |||
| <FILE id="mytllf" name="CameraDemo.cpp" compile="1" resource="0" file="Source/Demos/CameraDemo.cpp"/> | |||
| <FILE id="E1AN07" name="CodeEditorDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/CodeEditorDemo.cpp"/> | |||
| <FILE id="RDS9At" name="ComponentTransformsDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/ComponentTransformsDemo.cpp"/> | |||
| <FILE id="F4wkwd" name="CryptographyDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/CryptographyDemo.cpp"/> | |||
| <FILE id="E17XEZ" name="DialogsDemo.cpp" compile="1" resource="0" file="Source/Demos/DialogsDemo.cpp"/> | |||
| <FILE id="oM20ll" name="FontsDemo.cpp" compile="1" resource="0" file="Source/Demos/FontsDemo.cpp"/> | |||
| <FILE id="emYkSr" name="GraphicsDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/GraphicsDemo.cpp"/> | |||
| <FILE id="nNKKBo" name="ImagesDemo.cpp" compile="1" resource="0" file="Source/Demos/ImagesDemo.cpp"/> | |||
| <FILE id="L2SbwO" name="JavaScript.cpp" compile="1" resource="0" file="Source/Demos/JavaScript.cpp"/> | |||
| <FILE id="b6ICYv" name="KeyMappingsDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/KeyMappingsDemo.cpp"/> | |||
| <FILE id="zL6QF2" name="MDIDemo.cpp" compile="1" resource="0" file="Source/Demos/MDIDemo.cpp"/> | |||
| <FILE id="apxMrA" name="MidiDemo.cpp" compile="1" resource="0" file="Source/Demos/MidiDemo.cpp"/> | |||
| <FILE id="aqmz1c" name="MultithreadingDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/MultithreadingDemo.cpp"/> | |||
| <FILE id="JIA5Oo" name="MultiTouch.cpp" compile="1" resource="0" file="Source/Demos/MultiTouch.cpp"/> | |||
| <FILE id="iii6RP" name="NetworkingDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/NetworkingDemo.cpp"/> | |||
| <FILE id="r2PxPF" name="OpenGLDemo.cpp" compile="1" resource="0" file="Source/Demos/OpenGLDemo.cpp"/> | |||
| <FILE id="b2eKRP" name="PropertiesDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/PropertiesDemo.cpp"/> | |||
| <FILE id="cmVbyh" name="SystemInfoDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/SystemInfoDemo.cpp"/> | |||
| <FILE id="vRzDXp" name="TimersAndEventsDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/TimersAndEventsDemo.cpp"/> | |||
| <FILE id="fy39l" name="UnitTestsDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/UnitTestsDemo.cpp"/> | |||
| <FILE id="Cjidk8" name="ValueTreesDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/ValueTreesDemo.cpp"/> | |||
| <FILE id="iYJSd9" name="VideoDemo.cpp" compile="1" resource="0" file="Source/Demos/VideoDemo.cpp"/> | |||
| <FILE id="jbppAk" name="WavefrontObjParser.h" compile="0" resource="0" | |||
| file="Source/Demos/WavefrontObjParser.h"/> | |||
| <FILE id="ZpKDLq" name="WebBrowserDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/WebBrowserDemo.cpp"/> | |||
| <FILE id="AC58u7" name="WidgetsDemo.cpp" compile="1" resource="0" file="Source/Demos/WidgetsDemo.cpp"/> | |||
| <FILE id="BiiSqw" name="WindowsDemo.cpp" compile="1" resource="0" file="Source/Demos/WindowsDemo.cpp"/> | |||
| <FILE id="hNiiNX" name="XMLandJSONDemo.cpp" compile="1" resource="0" | |||
| file="Source/Demos/XMLandJSONDemo.cpp"/> | |||
| </GROUP> | |||
| <GROUP id="rsbEqp" name="Resources"> | |||
| <FILE id="fiPhJS" name="brushed_aluminium.png" compile="0" resource="1" | |||
| file="Resources/brushed_aluminium.png"/> | |||
| <FILE id="OmjAzt" name="cello.wav" compile="0" resource="1" file="Resources/cello.wav"/> | |||
| <FILE id="L1n4sU" name="demo table data.xml" compile="0" resource="1" | |||
| file="Resources/demo table data.xml"/> | |||
| <FILE id="e8N9Bc" name="icons.zip" compile="0" resource="1" file="Resources/icons.zip"/> | |||
| <FILE id="BvyE0d" name="juce_icon.png" compile="0" resource="1" file="Resources/juce_icon.png"/> | |||
| <FILE id="Sh53Yd" name="juce_module_info" compile="0" resource="1" | |||
| file="Resources/juce_module_info"/> | |||
| <FILE id="eqRA5C" name="portmeirion.jpg" compile="0" resource="1" file="Resources/portmeirion.jpg"/> | |||
| <FILE id="lppWLa" name="teapot.obj" compile="0" resource="1" file="Resources/teapot.obj"/> | |||
| <FILE id="Lf30im" name="treedemo.xml" compile="0" resource="1" file="Resources/treedemo.xml"/> | |||
| </GROUP> | |||
| </GROUP> | |||
| </MAINGROUP> | |||
| <JUCEOPTIONS/> | |||
| <MODULES> | |||
| <MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULES id="juce_box2d" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_core" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_events" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0"/> | |||
| <MODULE id="juce_video" showAllCode="1" useLocalCopy="0"/> | |||
| </MODULES> | |||
| </JUCERPROJECT> | |||
| @@ -0,0 +1,190 @@ | |||
| /* | |||
| IMPORTANT! This file is auto-generated each time you save your | |||
| project - if you alter its contents, your changes may be overwritten! | |||
| There's a section below where you can add your own custom code safely, and the | |||
| Introjucer will preserve the contents of that block, but the best way to change | |||
| any of these definitions is by using the Introjucer's project settings. | |||
| Any commented-out settings will assume their default values. | |||
| */ | |||
| #ifndef __JUCE_APPCONFIG_SBBIZR__ | |||
| #define __JUCE_APPCONFIG_SBBIZR__ | |||
| //============================================================================== | |||
| // [BEGIN_USER_CODE_SECTION] | |||
| // (You can add your own code in this section, and the Introjucer will not overwrite it) | |||
| // [END_USER_CODE_SECTION] | |||
| //============================================================================== | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_basics 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_devices 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_formats 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_processors 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_audio_utils 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_box2d 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_core 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_cryptography 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_data_structures 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_events 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_graphics 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_gui_basics 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_gui_extra 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_opengl 1 | |||
| #define JUCE_MODULE_AVAILABLE_juce_video 1 | |||
| //============================================================================== | |||
| // juce_audio_devices flags: | |||
| #ifndef JUCE_ASIO | |||
| //#define JUCE_ASIO | |||
| #endif | |||
| #ifndef JUCE_WASAPI | |||
| //#define JUCE_WASAPI | |||
| #endif | |||
| #ifndef JUCE_DIRECTSOUND | |||
| //#define JUCE_DIRECTSOUND | |||
| #endif | |||
| #ifndef JUCE_ALSA | |||
| //#define JUCE_ALSA | |||
| #endif | |||
| #ifndef JUCE_JACK | |||
| //#define JUCE_JACK | |||
| #endif | |||
| #ifndef JUCE_USE_ANDROID_OPENSLES | |||
| //#define JUCE_USE_ANDROID_OPENSLES | |||
| #endif | |||
| #ifndef JUCE_USE_CDREADER | |||
| //#define JUCE_USE_CDREADER | |||
| #endif | |||
| #ifndef JUCE_USE_CDBURNER | |||
| //#define JUCE_USE_CDBURNER | |||
| #endif | |||
| //============================================================================== | |||
| // juce_audio_formats flags: | |||
| #ifndef JUCE_USE_FLAC | |||
| //#define JUCE_USE_FLAC | |||
| #endif | |||
| #ifndef JUCE_USE_OGGVORBIS | |||
| //#define JUCE_USE_OGGVORBIS | |||
| #endif | |||
| #ifndef JUCE_USE_MP3AUDIOFORMAT | |||
| //#define JUCE_USE_MP3AUDIOFORMAT | |||
| #endif | |||
| #ifndef JUCE_USE_LAME_AUDIO_FORMAT | |||
| //#define JUCE_USE_LAME_AUDIO_FORMAT | |||
| #endif | |||
| #ifndef JUCE_USE_WINDOWS_MEDIA_FORMAT | |||
| //#define JUCE_USE_WINDOWS_MEDIA_FORMAT | |||
| #endif | |||
| //============================================================================== | |||
| // juce_audio_processors flags: | |||
| #ifndef JUCE_PLUGINHOST_VST | |||
| //#define JUCE_PLUGINHOST_VST | |||
| #endif | |||
| #ifndef JUCE_PLUGINHOST_AU | |||
| //#define JUCE_PLUGINHOST_AU | |||
| #endif | |||
| //============================================================================== | |||
| // juce_core flags: | |||
| #ifndef JUCE_FORCE_DEBUG | |||
| //#define JUCE_FORCE_DEBUG | |||
| #endif | |||
| #ifndef JUCE_LOG_ASSERTIONS | |||
| //#define JUCE_LOG_ASSERTIONS | |||
| #endif | |||
| #ifndef JUCE_CHECK_MEMORY_LEAKS | |||
| //#define JUCE_CHECK_MEMORY_LEAKS | |||
| #endif | |||
| #ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
| //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||
| #endif | |||
| #ifndef JUCE_INCLUDE_ZLIB_CODE | |||
| //#define JUCE_INCLUDE_ZLIB_CODE | |||
| #endif | |||
| //============================================================================== | |||
| // juce_graphics flags: | |||
| #ifndef JUCE_USE_COREIMAGE_LOADER | |||
| //#define JUCE_USE_COREIMAGE_LOADER | |||
| #endif | |||
| #ifndef JUCE_USE_DIRECTWRITE | |||
| //#define JUCE_USE_DIRECTWRITE | |||
| #endif | |||
| //============================================================================== | |||
| // juce_gui_basics flags: | |||
| #ifndef JUCE_ENABLE_REPAINT_DEBUGGING | |||
| //#define JUCE_ENABLE_REPAINT_DEBUGGING | |||
| #endif | |||
| #ifndef JUCE_USE_XSHM | |||
| //#define JUCE_USE_XSHM | |||
| #endif | |||
| #ifndef JUCE_USE_XRENDER | |||
| //#define JUCE_USE_XRENDER | |||
| #endif | |||
| #ifndef JUCE_USE_XCURSOR | |||
| //#define JUCE_USE_XCURSOR | |||
| #endif | |||
| //============================================================================== | |||
| // juce_gui_extra flags: | |||
| #ifndef JUCE_WEB_BROWSER | |||
| //#define JUCE_WEB_BROWSER | |||
| #endif | |||
| //============================================================================== | |||
| // juce_video flags: | |||
| #ifndef JUCE_DIRECTSHOW | |||
| //#define JUCE_DIRECTSHOW | |||
| #endif | |||
| #ifndef JUCE_MEDIAFOUNDATION | |||
| //#define JUCE_MEDIAFOUNDATION | |||
| #endif | |||
| #ifndef JUCE_QUICKTIME | |||
| //#define JUCE_QUICKTIME | |||
| #endif | |||
| #ifndef JUCE_USE_CAMERA | |||
| //#define JUCE_USE_CAMERA | |||
| #endif | |||
| #endif // __JUCE_APPCONFIG_SBBIZR__ | |||
| @@ -0,0 +1,45 @@ | |||
| /* ========================================================================================= | |||
| This is an auto-generated file: Any edits you make may be overwritten! | |||
| */ | |||
| namespace BinaryData | |||
| { | |||
| extern const char* brushed_aluminium_png; | |||
| const int brushed_aluminium_pngSize = 14724; | |||
| extern const char* cello_wav; | |||
| const int cello_wavSize = 46348; | |||
| extern const char* demo_table_data_xml; | |||
| const int demo_table_data_xmlSize = 5239; | |||
| extern const char* icons_zip; | |||
| const int icons_zipSize = 83876; | |||
| extern const char* juce_icon_png; | |||
| const int juce_icon_pngSize = 19826; | |||
| extern const char* juce_module_info; | |||
| const int juce_module_infoSize = 1404; | |||
| extern const char* portmeirion_jpg; | |||
| const int portmeirion_jpgSize = 145904; | |||
| extern const char* teapot_obj; | |||
| const int teapot_objSize = 95000; | |||
| extern const char* treedemo_xml; | |||
| const int treedemo_xmlSize = 1126; | |||
| // Points to the start of a list of resource names. | |||
| extern const char* namedResourceList[]; | |||
| // Number of elements in the namedResourceList array. | |||
| extern const int namedResourceListSize; | |||
| // If you provide the name of one of the binary resource variables above, this function will | |||
| // return the corresponding data and its size (or a null pointer if the name isn't found). | |||
| const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes) throw(); | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /* | |||
| IMPORTANT! This file is auto-generated each time you save your | |||
| project - if you alter its contents, your changes may be overwritten! | |||
| This is the header file that your files should include in order to get all the | |||
| JUCE library headers. You should avoid including the JUCE headers directly in | |||
| your own source files, because that wouldn't pick up the correct configuration | |||
| options for your app. | |||
| */ | |||
| #ifndef __APPHEADERFILE_SBBIZR__ | |||
| #define __APPHEADERFILE_SBBIZR__ | |||
| #include "AppConfig.h" | |||
| #include "modules/juce_audio_basics/juce_audio_basics.h" | |||
| #include "modules/juce_audio_devices/juce_audio_devices.h" | |||
| #include "modules/juce_audio_formats/juce_audio_formats.h" | |||
| #include "modules/juce_audio_processors/juce_audio_processors.h" | |||
| #include "modules/juce_audio_utils/juce_audio_utils.h" | |||
| #include "modules/juce_box2d/juce_box2d.h" | |||
| #include "modules/juce_core/juce_core.h" | |||
| #include "modules/juce_cryptography/juce_cryptography.h" | |||
| #include "modules/juce_data_structures/juce_data_structures.h" | |||
| #include "modules/juce_events/juce_events.h" | |||
| #include "modules/juce_graphics/juce_graphics.h" | |||
| #include "modules/juce_gui_basics/juce_gui_basics.h" | |||
| #include "modules/juce_gui_extra/juce_gui_extra.h" | |||
| #include "modules/juce_opengl/juce_opengl.h" | |||
| #include "modules/juce_video/juce_video.h" | |||
| #include "BinaryData.h" | |||
| #if ! DONT_SET_USING_JUCE_NAMESPACE | |||
| // If your code uses a lot of JUCE classes, then this will obviously save you | |||
| // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. | |||
| using namespace juce; | |||
| #endif | |||
| namespace ProjectInfo | |||
| { | |||
| const char* const projectName = "JuceDemo"; | |||
| const char* const versionString = "1.0.0"; | |||
| const int versionNumber = 0x10000; | |||
| } | |||
| #endif // __APPHEADERFILE_SBBIZR__ | |||
| @@ -0,0 +1,12 @@ | |||
| Important Note!! | |||
| ================ | |||
| The purpose of this folder is to contain files that are auto-generated by the Introjucer, | |||
| and ALL files in this folder will be mercilessly DELETED and completely re-written whenever | |||
| the Introjucer saves your project. | |||
| Therefore, it's a bad idea to make any manual changes to the files in here, or to | |||
| put any of your own files in here if you don't want to lose them. (Of course you may choose | |||
| to add the folder's contents to your version-control system so that you can re-merge your own | |||
| modifications after the Introjucer has saved its changes). | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_basics/juce_audio_basics.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_devices/juce_audio_devices.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_formats/juce_audio_formats.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_processors/juce_audio_processors.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_audio_utils/juce_audio_utils.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_box2d/juce_box2d.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_core/juce_core.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_cryptography/juce_cryptography.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_data_structures/juce_data_structures.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_events/juce_events.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_graphics/juce_graphics.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_gui_basics/juce_gui_basics.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_gui_extra/juce_gui_extra.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_opengl/juce_opengl.h" | |||
| @@ -0,0 +1,5 @@ | |||
| // This is an auto-generated file to redirect any included | |||
| // module headers to the correct external folder. | |||
| #include "../../../../../modules/juce_video/juce_video.h" | |||
| @@ -0,0 +1,49 @@ | |||
| <DEMO_TABLE_DATA> | |||
| <COLUMNS> | |||
| <COLUMN columnId="1" name="ID" width="50"/> | |||
| <COLUMN columnId="2" name="Artist" width="150"/> | |||
| <COLUMN columnId="3" name="Song" width="200"/> | |||
| <COLUMN columnId="4" name="Album" width="100"/> | |||
| <COLUMN columnId="5" name="Rating" width="120"/> | |||
| <COLUMN columnId="6" name="Genre" width="80"/> | |||
| <COLUMN columnId="7" name="Length" width="80"/> | |||
| </COLUMNS> | |||
| <DATA> | |||
| <ITEM ID="01" Artist="The Beatles" Album="Revolver" Song="Taxman" Genre="Rock" Length="2:39" Rating="1"/> | |||
| <ITEM ID="02" Artist="The Beatles" Album="Revolver" Song="Eleanor Rigby" Genre="Rock" Length="2:07" Rating="2"/> | |||
| <ITEM ID="03" Artist="The Beatles" Album="Revolver" Song="I'm only Sleeping" Genre="Rock" Length="3:01" Rating="3"/> | |||
| <ITEM ID="04" Artist="The Beatles" Album="Revolver" Song="Yellow Submarine" Genre="Rock" Length="2:40" Rating="4"/> | |||
| <ITEM ID="05" Artist="The Beatles" Album="Rubber Soul" Song="Drive My Car" Genre="Rock" Length="2:30" Rating="1"/> | |||
| <ITEM ID="06" Artist="The Beatles" Album="Rubber Soul" Song="Norwegian Wood" Genre="Rock" Length="2:05" Rating="1"/> | |||
| <ITEM ID="07" Artist="The Beatles" Album="Rubber Soul" Song="Nowhere Man" Genre="Rock" Length="2:44" Rating="5"/> | |||
| <ITEM ID="08" Artist="The Beatles" Album="Rubber Soul" Song="The Word" Genre="Rock" Length="2:43" Rating="2"/> | |||
| <ITEM ID="09" Artist="The Beatles" Album="Rubber Soul" Song="What Goes On" Genre="Rock" Length="2:50" Rating="3"/> | |||
| <ITEM ID="10" Artist="The Beatles" Album="Rubber Soul" Song="In My Life" Genre="Rock" Length="2:27" Rating="1"/> | |||
| <ITEM ID="11" Artist="Cocteau Twins" Album="Victorialand" Song="Lazy Calm" Genre="Etherial" Length="6:36" Rating="6"/> | |||
| <ITEM ID="12" Artist="Cocteau Twins" Album="Victorialand" Song="Fluffy Tufts" Genre="Etherial" Length="3:05" Rating="1"/> | |||
| <ITEM ID="13" Artist="Cocteau Twins" Album="Victorialand" Song="Oomingmak" Genre="Etherial" Length="2:42" Rating="3"/> | |||
| <ITEM ID="14" Artist="Cocteau Twins" Album="Victorialand" Song="Feet-Like Fins" Genre="Etherial" Length="3:26" Rating="1"/> | |||
| <ITEM ID="15" Artist="Cocteau Twins" Album="Four Calendar Cafe" Song="Know Who You Are At Every Age" Genre="Etherial" Length="3:42" Rating="1"/> | |||
| <ITEM ID="16" Artist="Cocteau Twins" Album="Four Calendar Cafe" Song="Evangeline" Genre="Etherial" Length="4:31" Rating="5"/> | |||
| <ITEM ID="17" Artist="Cocteau Twins" Album="Four Calendar Cafe" Song="Bluebeard" Genre="Etherial" Length="3:56" Rating="1"/> | |||
| <ITEM ID="18" Artist="Cocteau Twins" Album="Four Calendar Cafe" Song="Squeeze-Wax" Genre="Etherial" Length="3:49" Rating="1"/> | |||
| <ITEM ID="19" Artist="Cocteau Twins" Album="Heaven Or Las Vegas" Song="Cherry-Coloured Funk" Genre="Etherial" Length="3:13" Rating="1"/> | |||
| <ITEM ID="20" Artist="Cocteau Twins" Album="Heaven Or Las Vegas" Song="Iceblink Luck" Genre="Etherial" Length="3:18" Rating="7"/> | |||
| <ITEM ID="21" Artist="Cocteau Twins" Album="Heaven Or Las Vegas" Song="Fifty-Fifty Clown" Genre="Etherial" Length="3:15" Rating="2"/> | |||
| <ITEM ID="22" Artist="Cocteau Twins" Album="Heaven Or Las Vegas" Song="Fotzepolitic" Genre="Etherial" Length="3:30" Rating="1"/> | |||
| <ITEM ID="23" Artist="Robyn Hitchcock" Album="I Often Dream of Trains" Song="Nocturne" Genre="Rock" Length="1:42" Rating="1"/> | |||
| <ITEM ID="24" Artist="Robyn Hitchcock" Album="I Often Dream of Trains" Song="Uncorrected Personality Traits" Genre="Rock" Length="1:45" Rating="5"/> | |||
| <ITEM ID="25" Artist="Robyn Hitchcock" Album="I Often Dream of Trains" Song="My Favourite Buildings" Genre="Rock" Length="2:49" Rating="1"/> | |||
| <ITEM ID="26" Artist="Robyn Hitchcock" Album="I Often Dream of Trains" Song="Heartful of Leaves" Genre="Rock" Length="2:30" Rating="7"/> | |||
| <ITEM ID="27" Artist="Robyn Hitchcock" Album="Luxor" Song="Penelope's Angles" Genre="Rock" Length="3:18" Rating="1"/> | |||
| <ITEM ID="28" Artist="Robyn Hitchcock" Album="Luxor" Song="You Remind Me Of You" Genre="Rock" Length="4:15" Rating="4"/> | |||
| <ITEM ID="29" Artist="Robyn Hitchcock" Album="Luxor" Song="The Wolf House" Genre="Rock" Length="3:23" Rating="1"/> | |||
| <ITEM ID="30" Artist="Robyn Hitchcock" Album="Jewels For Sophia" Song="Mexican God" Genre="Rock" Length="2:57" Rating="3"/> | |||
| <ITEM ID="31" Artist="Robyn Hitchcock" Album="Jewels For Sophia" Song="The Cheese Alarm" Genre="Rock" Length="4:03" Rating="1"/> | |||
| <ITEM ID="32" Artist="Robyn Hitchcock" Album="Jewels For Sophia" Song="No, I Don't Remember Guildford" Genre="Rock" Length="4:45" Rating="6"/> | |||
| <ITEM ID="33" Artist="Syd Barrett" Album="Barrett" Song="Baby Lemonade" Genre="Rock" Length="4:10" Rating="2"/> | |||
| <ITEM ID="34" Artist="Syd Barrett" Album="Barrett" Song="Dominoes" Genre="Rock" Length="4:08" Rating="3"/> | |||
| <ITEM ID="35" Artist="Syd Barrett" Album="Barrett" Song="Gigolo Aunt" Genre="Rock" Length="5:46" Rating="4"/> | |||
| <ITEM ID="36" Artist="Syd Barrett" Album="Barrett" Song="Effervescing Elephant" Genre="Rock" Length="1:52" Rating="5"/> | |||
| </DATA> | |||
| </DEMO_TABLE_DATA> | |||
| @@ -0,0 +1,38 @@ | |||
| { | |||
| "id": "juce_core", | |||
| "name": "JUCE core classes", | |||
| "version": "2.1.5", | |||
| "description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.", | |||
| "website": "http://www.juce.com/juce", | |||
| "license": "ISC Permissive", | |||
| "dependencies": [], | |||
| "include": "juce_core.h", | |||
| "compile": [ { "file": "juce_core.cpp", "target": "! xcode" }, | |||
| { "file": "juce_core.mm", "target": "xcode" } ], | |||
| "browse": [ "text/*", | |||
| "maths/*", | |||
| "memory/*", | |||
| "containers/*", | |||
| "threads/*", | |||
| "time/*", | |||
| "files/*", | |||
| "network/*", | |||
| "streams/*", | |||
| "logging/*", | |||
| "system/*", | |||
| "xml/*", | |||
| "json/*", | |||
| "zip/*", | |||
| "unit_tests/*", | |||
| "misc/*", | |||
| "native/*" ], | |||
| "OSXFrameworks": "Cocoa IOKit", | |||
| "iOSFrameworks": "Foundation", | |||
| "LinuxLibs": "rt dl pthread", | |||
| "mingwLibs": "uuid wsock32 wininet version ole32 ws2_32 oleaut32 imm32 comdlg32 shlwapi rpcrt4 winmm" | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| <tree> | |||
| <item1> | |||
| <subnode colour="ffff0000" width="800" /> | |||
| <subnode colour="ff33bb00" width="50" /> | |||
| <subnode colour="33000000" /> | |||
| <subnode width="100" /> | |||
| <subnode colour="ff8866ee" /> | |||
| <subnode/> | |||
| <subnode colour="33000000" /> | |||
| <subnode/> | |||
| <subnode/> | |||
| </item1> | |||
| <item2 colour="ff777777"> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode width="800"/> | |||
| <subnode width="800"/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <item3> | |||
| <subnode> | |||
| <subnode width="50"/> | |||
| </subnode> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| </item3> | |||
| </item2> | |||
| <item4> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| <subnode/> | |||
| </item4> | |||
| </tree> | |||
| @@ -0,0 +1,82 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-11 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef DEMOUTILITIES_H_INCLUDED | |||
| #define DEMOUTILITIES_H_INCLUDED | |||
| //============================================================================== | |||
| /* | |||
| This file contains a bunch of miscellaneous utilities that are | |||
| used by the various demos. | |||
| */ | |||
| //============================================================================== | |||
| inline Colour getRandomColour (float brightness) | |||
| { | |||
| return Colour::fromHSV (Random::getSystemRandom().nextFloat(), 0.5f, brightness, 1.0f); | |||
| } | |||
| inline Colour getRandomBrightColour() { return getRandomColour (0.8f); } | |||
| inline Colour getRandomDarkColour() { return getRandomColour (0.3f); } | |||
| inline void fillBrushedAluminiumBackground (Graphics& g) | |||
| { | |||
| g.setFillType (FillType (ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, | |||
| BinaryData::brushed_aluminium_pngSize), | |||
| AffineTransform::identity)); | |||
| g.fillAll(); | |||
| } | |||
| //============================================================================== | |||
| // This is basically a sawtooth wave generator - maps a value that bounces between | |||
| // 0.0 and 1.0 at a random speed | |||
| struct BouncingNumber | |||
| { | |||
| BouncingNumber() | |||
| : speed (0.0004 + 0.0007 * Random::getSystemRandom().nextDouble()), | |||
| phase (Random::getSystemRandom().nextDouble()) | |||
| { | |||
| } | |||
| float getValue() const | |||
| { | |||
| double v = fmod (phase + speed * Time::getMillisecondCounterHiRes(), 2.0); | |||
| return (float) (v >= 1.0 ? (2.0 - v) : v); | |||
| } | |||
| protected: | |||
| double speed, phase; | |||
| }; | |||
| struct SlowerBouncingNumber : public BouncingNumber | |||
| { | |||
| SlowerBouncingNumber() | |||
| { | |||
| speed *= 0.3; | |||
| } | |||
| }; | |||
| #endif // DEMOUTILITIES_H_INCLUDED | |||
| @@ -0,0 +1,265 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| //============================================================================== | |||
| /** This will be the source of our balls and can be dragged around. */ | |||
| class BallGeneratorComponent : public Component | |||
| { | |||
| public: | |||
| BallGeneratorComponent() | |||
| { | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| Rectangle<float> area (getLocalBounds().toFloat().reduced (2.0f)); | |||
| g.setColour (Colours::orange.withAlpha (0.6f)); | |||
| g.fillRoundedRectangle (area, 10.0f); | |||
| g.setColour (Colours::darkgrey); | |||
| g.drawRoundedRectangle (area, 10.0f, 2.0f); | |||
| AttributedString s; | |||
| s.setJustification (Justification::centred); | |||
| s.setWordWrap (AttributedString::none); | |||
| s.append ("Balls!\n" | |||
| "(Drag Me)"); | |||
| s.setColour (Colours::black); | |||
| s.draw (g, area); | |||
| } | |||
| void resized() override | |||
| { | |||
| // Just set the limits of our constrainer so that we don't drag ourselves off the screen | |||
| constrainer.setMinimumOnscreenAmounts (getHeight(), getWidth(), getHeight(), getWidth()); | |||
| } | |||
| void mouseDown (const MouseEvent& e) override | |||
| { | |||
| // Prepares our dragger to drag this Component | |||
| dragger.startDraggingComponent (this, e); | |||
| } | |||
| void mouseDrag (const MouseEvent& e) override | |||
| { | |||
| // Moves this Component according to the mouse drag event and applies our constraints to it | |||
| dragger.dragComponent (this, e, &constrainer); | |||
| } | |||
| private: | |||
| ComponentBoundsConstrainer constrainer; | |||
| ComponentDragger dragger; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BallGeneratorComponent) | |||
| }; | |||
| //============================================================================== | |||
| struct BallComponent : public Component | |||
| { | |||
| BallComponent (const Point<float>& pos) | |||
| : position (pos), | |||
| speed (Random::getSystemRandom().nextFloat() * 4.0f - 2.0f, | |||
| Random::getSystemRandom().nextFloat() * -6.0f - 2.0f), | |||
| colour (getRandomBrightColour().withAlpha (0.4f)) | |||
| { | |||
| setSize (20, 20); | |||
| step(); | |||
| } | |||
| bool step() | |||
| { | |||
| position += speed; | |||
| speed.y += 0.05f; | |||
| setCentrePosition ((int) position.x, | |||
| (int) position.y); | |||
| if (Component* parent = getParentComponent()) | |||
| return isPositiveAndBelow (position.x, (float) parent->getWidth()) | |||
| && position.y < (float) parent->getHeight(); | |||
| return position.y < 400.0f && position.x >= -10.0f; | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.setColour (colour); | |||
| g.fillEllipse (2.0f, 2.0f, getWidth() - 4.0f, getHeight() - 4.0f); | |||
| g.setColour (Colours::darkgrey); | |||
| g.drawEllipse (2.0f, 2.0f, getWidth() - 4.0f, getHeight() - 4.0f, 1.0f); | |||
| } | |||
| Point<float> position, speed; | |||
| Colour colour; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BallComponent) | |||
| }; | |||
| //============================================================================== | |||
| class AnimationDemo : public Component, | |||
| private Button::Listener, | |||
| private Timer | |||
| { | |||
| public: | |||
| AnimationDemo() | |||
| { | |||
| setOpaque (true); | |||
| for (int i = 11; --i >= 0;) | |||
| { | |||
| Button* b = createRandomButton(); | |||
| componentsToAnimate.add (b); | |||
| addAndMakeVisible (b); | |||
| b->addListener (this); | |||
| } | |||
| ballGenerator = new BallGeneratorComponent(); | |||
| componentsToAnimate.add (ballGenerator); | |||
| addAndMakeVisible (ballGenerator); | |||
| ballGenerator->setBounds (200, 500, 70, 50); | |||
| int w = 160, h = 80; | |||
| for (int i = 0; i < componentsToAnimate.size(); ++i) | |||
| { | |||
| Rectangle<int> r (w * (i % 3), h * (i / 3), w, h); | |||
| componentsToAnimate.getUnchecked(i)->setBounds (r.reduced (10)); | |||
| } | |||
| startTimer (1000 / 60); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| private: | |||
| OwnedArray<Component> componentsToAnimate; | |||
| OwnedArray<BallComponent> balls; | |||
| BallGeneratorComponent* ballGenerator; | |||
| ComponentAnimator animator; | |||
| Button* createRandomButton() | |||
| { | |||
| DrawablePath normal, over; | |||
| Path star1; | |||
| star1.addStar (Point<float>(), 5, 20.0f, 50.0f, 0.2f); | |||
| normal.setPath (star1); | |||
| normal.setFill (Colours::red); | |||
| Path star2; | |||
| star2.addStar (Point<float>(), 7, 30.0f, 50.0f, 0.0f); | |||
| over.setPath (star2); | |||
| over.setFill (Colours::pink); | |||
| over.setStrokeFill (Colours::black); | |||
| over.setStrokeThickness (5.0f); | |||
| DrawableImage down; | |||
| down.setImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize)); | |||
| down.setOverlayColour (Colours::black.withAlpha (0.3f)); | |||
| if (Random::getSystemRandom().nextInt (10) > 2) | |||
| { | |||
| int type = Random::getSystemRandom().nextInt (3); | |||
| DrawableButton* d = new DrawableButton ("Button", | |||
| type == 0 ? DrawableButton::ImageOnButtonBackground | |||
| : (type == 1 ? DrawableButton::ImageFitted | |||
| : DrawableButton::ImageAboveTextLabel)); | |||
| d->setImages (&normal, | |||
| Random::getSystemRandom().nextBool() ? &over : nullptr, | |||
| Random::getSystemRandom().nextBool() ? &down : nullptr); | |||
| if (Random::getSystemRandom().nextBool()) | |||
| { | |||
| d->setColour (DrawableButton::backgroundColourId, getRandomBrightColour()); | |||
| d->setColour (DrawableButton::backgroundOnColourId, getRandomBrightColour()); | |||
| } | |||
| d->setClickingTogglesState (Random::getSystemRandom().nextBool()); | |||
| return d; | |||
| } | |||
| ImageButton* b = new ImageButton ("ImageButton"); | |||
| Image image = ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize); | |||
| b->setImages (true, true, true, | |||
| image, 0.7f, Colours::transparentBlack, | |||
| image, 1.0f, getRandomDarkColour().withAlpha (0.2f), | |||
| image, 1.0f, getRandomBrightColour().withAlpha (0.8f), | |||
| 0.5f); | |||
| return b; | |||
| } | |||
| void buttonClicked (Button*) override | |||
| { | |||
| for (int i = 0; i < componentsToAnimate.size(); ++i) | |||
| componentsToAnimate.swap (i, Random::getSystemRandom().nextInt (componentsToAnimate.size())); | |||
| int w = 160, h = 80; | |||
| for (int i = 0; i < componentsToAnimate.size(); ++i) | |||
| { | |||
| Rectangle<int> r (w * (i % 3), h * (i / 3), w, h); | |||
| animator.animateComponent (componentsToAnimate.getUnchecked(i), | |||
| r.reduced (10), | |||
| Random::getSystemRandom().nextBool() ? 1.0f : 0.4f, | |||
| 500 + Random::getSystemRandom().nextInt (2000), | |||
| false, | |||
| Random::getSystemRandom().nextDouble(), | |||
| Random::getSystemRandom().nextDouble()); | |||
| } | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| // Go through each of our balls and update their position | |||
| for (int i = balls.size(); --i >= 0;) | |||
| if (! balls.getUnchecked(i)->step()) | |||
| balls.remove (i); | |||
| // Randomly generate new balls | |||
| if (Random::getSystemRandom().nextInt (200) < 4) | |||
| { | |||
| BallComponent* ball = new BallComponent (ballGenerator->getBounds().getCentre().toFloat()); | |||
| balls.add (ball); | |||
| addAndMakeVisible (ball); | |||
| } | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimationDemo) | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<AnimationDemo> demo ("10 Components: Animation"); | |||
| @@ -0,0 +1,375 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| #include "AudioLiveScrollingDisplay.h" | |||
| class LatencyTester : public AudioIODeviceCallback, | |||
| private Timer | |||
| { | |||
| public: | |||
| LatencyTester (TextEditor& resultsBox_) | |||
| : testSound (1, 1), | |||
| recordedSound (1, 1), | |||
| playingSampleNum (0), | |||
| recordedSampleNum (-1), | |||
| sampleRate (0), | |||
| testIsRunning (false), | |||
| resultsBox (resultsBox_) | |||
| { | |||
| MainAppWindow::getSharedAudioDeviceManager().addAudioCallback (this); | |||
| } | |||
| ~LatencyTester() | |||
| { | |||
| MainAppWindow::getSharedAudioDeviceManager().removeAudioCallback (this); | |||
| } | |||
| //============================================================================== | |||
| void beginTest() | |||
| { | |||
| resultsBox.moveCaretToEnd(); | |||
| resultsBox.insertTextAtCaret (newLine + newLine + "Starting test..." + newLine); | |||
| resultsBox.moveCaretToEnd(); | |||
| startTimer (50); | |||
| const ScopedLock sl (lock); | |||
| createTestSound(); | |||
| recordedSound.clear(); | |||
| playingSampleNum = recordedSampleNum = 0; | |||
| testIsRunning = true; | |||
| } | |||
| void timerCallback() | |||
| { | |||
| if (testIsRunning && recordedSampleNum >= recordedSound.getNumSamples()) | |||
| { | |||
| testIsRunning = false; | |||
| stopTimer(); | |||
| // Test has finished, so calculate the result.. | |||
| const int latencySamples = calculateLatencySamples(); | |||
| resultsBox.moveCaretToEnd(); | |||
| resultsBox.insertTextAtCaret (getMessageDescribingResult (latencySamples)); | |||
| resultsBox.moveCaretToEnd(); | |||
| } | |||
| } | |||
| String getMessageDescribingResult (int latencySamples) | |||
| { | |||
| String message; | |||
| if (latencySamples >= 0) | |||
| { | |||
| message << newLine | |||
| << "Results:" << newLine | |||
| << latencySamples << " samples (" << String (latencySamples * 1000.0 / sampleRate, 1) | |||
| << " milliseconds)" << newLine | |||
| << "The audio device reports an input latency of " | |||
| << deviceInputLatency << " samples, output latency of " | |||
| << deviceOutputLatency << " samples." << newLine | |||
| << "So the corrected latency = " | |||
| << (latencySamples - deviceInputLatency - deviceOutputLatency) | |||
| << " samples (" << String ((latencySamples - deviceInputLatency - deviceOutputLatency) * 1000.0 / sampleRate, 2) | |||
| << " milliseconds)"; | |||
| } | |||
| else | |||
| { | |||
| message << newLine | |||
| << "Couldn't detect the test signal!!" << newLine | |||
| << "Make sure there's no background noise that might be confusing it.."; | |||
| } | |||
| return message; | |||
| } | |||
| //============================================================================== | |||
| void audioDeviceAboutToStart (AudioIODevice* device) | |||
| { | |||
| testIsRunning = false; | |||
| playingSampleNum = recordedSampleNum = 0; | |||
| sampleRate = device->getCurrentSampleRate(); | |||
| deviceInputLatency = device->getInputLatencyInSamples(); | |||
| deviceOutputLatency = device->getOutputLatencyInSamples(); | |||
| recordedSound.setSize (1, (int) (0.9 * sampleRate)); | |||
| recordedSound.clear(); | |||
| } | |||
| void audioDeviceStopped() | |||
| { | |||
| // (nothing to do here) | |||
| } | |||
| void audioDeviceIOCallback (const float** inputChannelData, | |||
| int numInputChannels, | |||
| float** outputChannelData, | |||
| int numOutputChannels, | |||
| int numSamples) | |||
| { | |||
| const ScopedLock sl (lock); | |||
| if (testIsRunning) | |||
| { | |||
| float* const recordingBuffer = recordedSound.getSampleData (0, 0); | |||
| const float* const playBuffer = testSound.getSampleData (0, 0); | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| if (recordedSampleNum < recordedSound.getNumSamples()) | |||
| { | |||
| float inputSamp = 0; | |||
| for (int j = numInputChannels; --j >= 0;) | |||
| if (inputChannelData[j] != 0) | |||
| inputSamp += inputChannelData[j][i]; | |||
| recordingBuffer [recordedSampleNum] = inputSamp; | |||
| } | |||
| ++recordedSampleNum; | |||
| float outputSamp = (playingSampleNum < testSound.getNumSamples()) ? playBuffer [playingSampleNum] : 0; | |||
| for (int j = numOutputChannels; --j >= 0;) | |||
| if (outputChannelData[j] != 0) | |||
| outputChannelData[j][i] = outputSamp; | |||
| ++playingSampleNum; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // We need to clear the output buffers, in case they're full of junk.. | |||
| for (int i = 0; i < numOutputChannels; ++i) | |||
| if (outputChannelData[i] != 0) | |||
| zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples); | |||
| } | |||
| } | |||
| private: | |||
| AudioSampleBuffer testSound, recordedSound; | |||
| Array <int> spikePositions; | |||
| int playingSampleNum, recordedSampleNum; | |||
| CriticalSection lock; | |||
| double sampleRate; | |||
| bool testIsRunning; | |||
| TextEditor& resultsBox; | |||
| int deviceInputLatency, deviceOutputLatency; | |||
| // create a test sound which consists of a series of randomly-spaced audio spikes.. | |||
| void createTestSound() | |||
| { | |||
| const int length = ((int) sampleRate) / 4; | |||
| testSound.setSize (1, length); | |||
| testSound.clear(); | |||
| float* s = testSound.getSampleData (0, 0); | |||
| Random rand (0); | |||
| rand.setSeedRandomly(); | |||
| for (int i = 0; i < length; ++i) | |||
| s[i] = (rand.nextFloat() - rand.nextFloat() + rand.nextFloat() - rand.nextFloat()) * 0.06f; | |||
| spikePositions.clear(); | |||
| int spikePos = 0; | |||
| int spikeDelta = 50; | |||
| while (spikePos < length - 1) | |||
| { | |||
| spikePositions.add (spikePos); | |||
| s[spikePos] = 0.99f; | |||
| s[spikePos + 1] = -0.99f; | |||
| spikePos += spikeDelta; | |||
| spikeDelta += spikeDelta / 6 + rand.nextInt (5); | |||
| } | |||
| } | |||
| // Searches a buffer for a set of spikes that matches those in the test sound | |||
| int findOffsetOfSpikes (const AudioSampleBuffer& buffer) const | |||
| { | |||
| const float minSpikeLevel = 5.0f; | |||
| const double smooth = 0.975; | |||
| const float* s = buffer.getSampleData (0, 0); | |||
| const int spikeDriftAllowed = 5; | |||
| Array <int> spikesFound; | |||
| spikesFound.ensureStorageAllocated (100); | |||
| double runningAverage = 0; | |||
| int lastSpike = 0; | |||
| for (int i = 0; i < buffer.getNumSamples() - 10; ++i) | |||
| { | |||
| const float samp = fabsf (s[i]); | |||
| if (samp > runningAverage * minSpikeLevel && i > lastSpike + 20) | |||
| { | |||
| lastSpike = i; | |||
| spikesFound.add (i); | |||
| } | |||
| runningAverage = runningAverage * smooth + (1.0 - smooth) * samp; | |||
| } | |||
| int bestMatch = -1; | |||
| int bestNumMatches = spikePositions.size() / 3; // the minimum number of matches required | |||
| if (spikesFound.size() < bestNumMatches) | |||
| return -1; | |||
| for (int offsetToTest = 0; offsetToTest < buffer.getNumSamples() - 2048; ++offsetToTest) | |||
| { | |||
| int numMatchesHere = 0; | |||
| int foundIndex = 0; | |||
| for (int refIndex = 0; refIndex < spikePositions.size(); ++refIndex) | |||
| { | |||
| const int referenceSpike = spikePositions.getUnchecked (refIndex) + offsetToTest; | |||
| int spike = 0; | |||
| while ((spike = spikesFound.getUnchecked (foundIndex)) < referenceSpike - spikeDriftAllowed | |||
| && foundIndex < spikesFound.size() - 1) | |||
| ++foundIndex; | |||
| if (spike >= referenceSpike - spikeDriftAllowed && spike <= referenceSpike + spikeDriftAllowed) | |||
| ++numMatchesHere; | |||
| } | |||
| if (numMatchesHere > bestNumMatches) | |||
| { | |||
| bestNumMatches = numMatchesHere; | |||
| bestMatch = offsetToTest; | |||
| if (numMatchesHere == spikePositions.size()) | |||
| break; | |||
| } | |||
| } | |||
| return bestMatch; | |||
| } | |||
| int calculateLatencySamples() const | |||
| { | |||
| // Detect the sound in both our test sound and the recording of it, and measure the difference | |||
| // in their start times.. | |||
| const int referenceStart = findOffsetOfSpikes (testSound); | |||
| jassert (referenceStart >= 0); | |||
| const int recordedStart = findOffsetOfSpikes (recordedSound); | |||
| return (recordedStart < 0) ? -1 | |||
| : (recordedStart - referenceStart); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LatencyTester); | |||
| }; | |||
| //============================================================================== | |||
| class AudioLatencyDemo : public Component, | |||
| private Button::Listener | |||
| { | |||
| public: | |||
| AudioLatencyDemo() | |||
| { | |||
| setOpaque (true); | |||
| addAndMakeVisible (liveAudioScroller = new LiveScrollingAudioDisplay()); | |||
| addAndMakeVisible (&resultsBox); | |||
| resultsBox.setMultiLine (true); | |||
| resultsBox.setReturnKeyStartsNewLine (true); | |||
| resultsBox.setReadOnly (true); | |||
| resultsBox.setScrollbarsShown (true); | |||
| resultsBox.setCaretVisible (false); | |||
| resultsBox.setPopupMenuEnabled (true); | |||
| resultsBox.setColour (TextEditor::backgroundColourId, Colour (0x32ffffff)); | |||
| resultsBox.setColour (TextEditor::outlineColourId, Colour (0x1c000000)); | |||
| resultsBox.setColour (TextEditor::shadowColourId, Colour (0x16000000)); | |||
| resultsBox.setText ("Running this test measures the round-trip latency between the audio output and input " | |||
| "devices you\'ve got selected.\n\n" | |||
| "It\'ll play a sound, then try to measure the time at which the sound arrives " | |||
| "back at the audio input. Obviously for this to work you need to have your " | |||
| "microphone somewhere near your speakers..."); | |||
| addAndMakeVisible (&startTestButton); | |||
| startTestButton.addListener (this); | |||
| startTestButton.setButtonText ("Test Latency"); | |||
| MainAppWindow::getSharedAudioDeviceManager().addAudioCallback (liveAudioScroller); | |||
| } | |||
| ~AudioLatencyDemo() | |||
| { | |||
| MainAppWindow::getSharedAudioDeviceManager().removeAudioCallback (liveAudioScroller); | |||
| startTestButton.removeListener (this); | |||
| latencyTester = nullptr; | |||
| liveAudioScroller = nullptr; | |||
| } | |||
| void startTest() | |||
| { | |||
| if (latencyTester == nullptr) | |||
| latencyTester = new LatencyTester (resultsBox); | |||
| latencyTester->beginTest(); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| void resized() override | |||
| { | |||
| liveAudioScroller->setBounds (8, 8, getWidth() - 16, 64); | |||
| startTestButton.setBounds (8, getHeight() - 41, 168, 32); | |||
| resultsBox.setBounds (8, 88, getWidth() - 16, getHeight() - 137); | |||
| } | |||
| private: | |||
| ScopedPointer<LatencyTester> latencyTester; | |||
| ScopedPointer<LiveScrollingAudioDisplay> liveAudioScroller; | |||
| TextButton startTestButton; | |||
| TextEditor resultsBox; | |||
| void buttonClicked (Button* buttonThatWasClicked) override | |||
| { | |||
| if (buttonThatWasClicked == &startTestButton) | |||
| startTest(); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioLatencyDemo) | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<AudioLatencyDemo> demo ("31 Audio: Latency Detector"); | |||
| @@ -0,0 +1,141 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-11 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __AUDIOLIVESCROLLINGDISPLAY_H_4C3BD3A7__ | |||
| #define __AUDIOLIVESCROLLINGDISPLAY_H_4C3BD3A7__ | |||
| #include "../JuceDemoHeader.h" | |||
| //============================================================================== | |||
| /* This component scrolls a continuous waveform showing the audio that's | |||
| coming into whatever audio inputs this object is connected to. | |||
| */ | |||
| class LiveScrollingAudioDisplay : public Component, | |||
| public AudioIODeviceCallback, | |||
| private Timer | |||
| { | |||
| public: | |||
| LiveScrollingAudioDisplay() | |||
| : nextSample (0), subSample (0), accumulator (0) | |||
| { | |||
| setOpaque (true); | |||
| clear(); | |||
| startTimer (1000 / 75); // use a timer to keep repainting this component | |||
| } | |||
| //============================================================================== | |||
| void audioDeviceAboutToStart (AudioIODevice*) override | |||
| { | |||
| clear(); | |||
| } | |||
| void audioDeviceStopped() override | |||
| { | |||
| clear(); | |||
| } | |||
| void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels, | |||
| float** outputChannelData, int numOutputChannels, | |||
| int numSamples) override | |||
| { | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| float inputSample = 0; | |||
| for (int chan = 0; chan < numInputChannels; ++chan) | |||
| if (inputChannelData[chan] != nullptr) | |||
| inputSample += fabsf (inputChannelData[chan][i]); // find the sum of all the channels | |||
| pushSample (10.0f * inputSample); // boost the level to make it more easily visible. | |||
| } | |||
| // We need to clear the output buffers before returning, in case they're full of junk.. | |||
| for (int j = 0; j < numOutputChannels; ++j) | |||
| if (outputChannelData[j] != nullptr) | |||
| zeromem (outputChannelData[j], sizeof (float) * (size_t) numSamples); | |||
| } | |||
| private: | |||
| float samples[1024]; | |||
| int nextSample, subSample; | |||
| float accumulator; | |||
| void clear() | |||
| { | |||
| zeromem (samples, sizeof (samples)); | |||
| accumulator = 0; | |||
| subSample = 0; | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (Colours::black); | |||
| const float midY = getHeight() * 0.5f; | |||
| int samplesAgo = (nextSample + numElementsInArray (samples) - 1); | |||
| RectangleList<float> waveform; | |||
| for (int x = jmin (getWidth(), (int) numElementsInArray (samples)); --x >= 0;) | |||
| { | |||
| const float sampleSize = midY * samples [samplesAgo-- % numElementsInArray (samples)]; | |||
| waveform.addWithoutMerging (Rectangle<float> ((float) x, midY - sampleSize, 1.0f, sampleSize * 2.0f)); | |||
| } | |||
| g.setColour (Colours::lightgreen); | |||
| g.fillRectList (waveform); | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| repaint(); | |||
| } | |||
| void pushSample (const float newSample) | |||
| { | |||
| accumulator += newSample; | |||
| if (subSample == 0) | |||
| { | |||
| const int inputSamplesPerPixel = 200; | |||
| samples[nextSample] = accumulator / inputSamplesPerPixel; | |||
| nextSample = (nextSample + 1) % numElementsInArray (samples); | |||
| subSample = inputSamplesPerPixel; | |||
| accumulator = 0; | |||
| } | |||
| else | |||
| { | |||
| --subSample; | |||
| } | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LiveScrollingAudioDisplay); | |||
| }; | |||
| #endif // __AUDIOLIVESCROLLINGDISPLAY_H_4C3BD3A7__ | |||
| @@ -0,0 +1,424 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| //============================================================================== | |||
| class DemoThumbnailComp : public Component, | |||
| public ChangeListener, | |||
| public FileDragAndDropTarget, | |||
| public ChangeBroadcaster, | |||
| private ScrollBar::Listener, | |||
| private Timer | |||
| { | |||
| public: | |||
| DemoThumbnailComp (AudioFormatManager& formatManager, | |||
| AudioTransportSource& transportSource_, | |||
| Slider& slider) | |||
| : transportSource (transportSource_), | |||
| zoomSlider (slider), | |||
| scrollbar (false), | |||
| thumbnailCache (5), | |||
| thumbnail (512, formatManager, thumbnailCache), | |||
| isFollowingTransport (false) | |||
| { | |||
| thumbnail.addChangeListener (this); | |||
| addAndMakeVisible (&scrollbar); | |||
| scrollbar.setRangeLimits (visibleRange); | |||
| scrollbar.setAutoHide (false); | |||
| scrollbar.addListener (this); | |||
| currentPositionMarker.setFill (Colours::white.withAlpha (0.85f)); | |||
| addAndMakeVisible (¤tPositionMarker); | |||
| } | |||
| ~DemoThumbnailComp() | |||
| { | |||
| scrollbar.removeListener (this); | |||
| thumbnail.removeChangeListener (this); | |||
| } | |||
| void setFile (const File& file) | |||
| { | |||
| if (! file.isDirectory()) | |||
| { | |||
| thumbnail.setSource (new FileInputSource (file)); | |||
| const Range<double> newRange (0.0, thumbnail.getTotalLength()); | |||
| scrollbar.setRangeLimits (newRange); | |||
| setRange (newRange); | |||
| startTimer (1000 / 40); | |||
| } | |||
| } | |||
| File getLastDroppedFile() const noexcept { return lastFileDropped; } | |||
| void setZoomFactor (double amount) | |||
| { | |||
| if (thumbnail.getTotalLength() > 0) | |||
| { | |||
| const double newScale = jmax (0.001, thumbnail.getTotalLength() * (1.0 - jlimit (0.0, 0.99, amount))); | |||
| const double timeAtCentre = xToTime (getWidth() / 2.0f); | |||
| setRange (Range<double> (timeAtCentre - newScale * 0.5, timeAtCentre + newScale * 0.5)); | |||
| } | |||
| } | |||
| void setRange (Range<double> newRange) | |||
| { | |||
| visibleRange = newRange; | |||
| scrollbar.setCurrentRange (visibleRange); | |||
| updateCursorPosition(); | |||
| repaint(); | |||
| } | |||
| void setFollowsTransport (bool shouldFollow) | |||
| { | |||
| isFollowingTransport = shouldFollow; | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (Colours::darkgrey); | |||
| g.setColour (Colours::lightblue); | |||
| if (thumbnail.getTotalLength() > 0.0) | |||
| { | |||
| Rectangle<int> thumbArea (getLocalBounds()); | |||
| thumbArea.removeFromBottom (scrollbar.getHeight() + 4); | |||
| thumbnail.drawChannels (g, thumbArea.reduced (2), | |||
| visibleRange.getStart(), visibleRange.getEnd(), 1.0f); | |||
| } | |||
| else | |||
| { | |||
| g.setFont (14.0f); | |||
| g.drawFittedText ("(No audio file selected)", getLocalBounds(), Justification::centred, 2); | |||
| } | |||
| } | |||
| void resized() override | |||
| { | |||
| scrollbar.setBounds (getLocalBounds().removeFromBottom (14).reduced (2)); | |||
| } | |||
| void changeListenerCallback (ChangeBroadcaster*) override | |||
| { | |||
| // this method is called by the thumbnail when it has changed, so we should repaint it.. | |||
| repaint(); | |||
| } | |||
| bool isInterestedInFileDrag (const StringArray& /*files*/) override | |||
| { | |||
| return true; | |||
| } | |||
| void filesDropped (const StringArray& files, int /*x*/, int /*y*/) override | |||
| { | |||
| lastFileDropped = File (files[0]); | |||
| sendChangeMessage(); | |||
| } | |||
| void mouseDown (const MouseEvent& e) override | |||
| { | |||
| mouseDrag (e); | |||
| } | |||
| void mouseDrag (const MouseEvent& e) override | |||
| { | |||
| if (canMoveTransport()) | |||
| transportSource.setPosition (jmax (0.0, xToTime ((float) e.x))); | |||
| } | |||
| void mouseUp (const MouseEvent&) override | |||
| { | |||
| transportSource.start(); | |||
| } | |||
| void mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel) override | |||
| { | |||
| if (thumbnail.getTotalLength() > 0.0) | |||
| { | |||
| double newStart = visibleRange.getStart() - wheel.deltaX * (visibleRange.getLength()) / 10.0; | |||
| newStart = jlimit (0.0, jmax (0.0, thumbnail.getTotalLength() - (visibleRange.getLength())), newStart); | |||
| if (canMoveTransport()) | |||
| setRange (Range<double> (newStart, newStart + visibleRange.getLength())); | |||
| if (wheel.deltaY != 0.0f) | |||
| zoomSlider.setValue (zoomSlider.getValue() - wheel.deltaY); | |||
| repaint(); | |||
| } | |||
| } | |||
| private: | |||
| AudioTransportSource& transportSource; | |||
| Slider& zoomSlider; | |||
| ScrollBar scrollbar; | |||
| AudioThumbnailCache thumbnailCache; | |||
| AudioThumbnail thumbnail; | |||
| Range<double> visibleRange; | |||
| bool isFollowingTransport; | |||
| File lastFileDropped; | |||
| DrawableRectangle currentPositionMarker; | |||
| float timeToX (const double time) const | |||
| { | |||
| return getWidth() * (float) ((time - visibleRange.getStart()) / (visibleRange.getLength())); | |||
| } | |||
| double xToTime (const float x) const | |||
| { | |||
| return (x / getWidth()) * (visibleRange.getLength()) + visibleRange.getStart(); | |||
| } | |||
| bool canMoveTransport() const noexcept | |||
| { | |||
| return ! (isFollowingTransport && transportSource.isPlaying()); | |||
| } | |||
| void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart) override | |||
| { | |||
| if (scrollBarThatHasMoved == &scrollbar) | |||
| if (! (isFollowingTransport && transportSource.isPlaying())) | |||
| setRange (visibleRange.movedToStartAt (newRangeStart)); | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| if (canMoveTransport()) | |||
| updateCursorPosition(); | |||
| else | |||
| setRange (visibleRange.movedToStartAt (transportSource.getCurrentPosition() - (visibleRange.getLength() / 2.0))); | |||
| } | |||
| void updateCursorPosition() | |||
| { | |||
| currentPositionMarker.setVisible (transportSource.isPlaying() || isMouseButtonDown()); | |||
| currentPositionMarker.setRectangle (Rectangle<float> (timeToX (transportSource.getCurrentPosition()) - 0.75f, 0, | |||
| 1.5f, (float) (getHeight() - scrollbar.getHeight()))); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class AudioPlaybackDemo : public Component, | |||
| private FileBrowserListener, | |||
| private Button::Listener, | |||
| private Slider::Listener, | |||
| private ChangeListener | |||
| { | |||
| public: | |||
| AudioPlaybackDemo() | |||
| : deviceManager (MainAppWindow::getSharedAudioDeviceManager()), | |||
| thread ("audio file preview"), | |||
| directoryList (nullptr, thread), | |||
| fileTreeComp (directoryList) | |||
| { | |||
| addAndMakeVisible (&zoomLabel); | |||
| zoomLabel.setText ("zoom:", dontSendNotification); | |||
| zoomLabel.setFont (Font (15.00f, Font::plain)); | |||
| zoomLabel.setJustificationType (Justification::centredRight); | |||
| zoomLabel.setEditable (false, false, false); | |||
| zoomLabel.setColour (TextEditor::textColourId, Colours::black); | |||
| zoomLabel.setColour (TextEditor::backgroundColourId, Colour (0x00000000)); | |||
| addAndMakeVisible (&followTransportButton); | |||
| followTransportButton.setButtonText ("Follow Transport"); | |||
| followTransportButton.addListener (this); | |||
| addAndMakeVisible (&explanation); | |||
| explanation.setText ("Select an audio file in the treeview above, and this page will display its waveform, and let you play it..", dontSendNotification); | |||
| explanation.setFont (Font (14.00f, Font::plain)); | |||
| explanation.setJustificationType (Justification::bottomRight); | |||
| explanation.setEditable (false, false, false); | |||
| explanation.setColour (TextEditor::textColourId, Colours::black); | |||
| explanation.setColour (TextEditor::backgroundColourId, Colour (0x00000000)); | |||
| addAndMakeVisible (&zoomSlider); | |||
| zoomSlider.setRange (0, 1, 0); | |||
| zoomSlider.setSliderStyle (Slider::LinearHorizontal); | |||
| zoomSlider.setTextBoxStyle (Slider::NoTextBox, false, 80, 20); | |||
| zoomSlider.addListener (this); | |||
| zoomSlider.setSkewFactor (2); | |||
| addAndMakeVisible (thumbnail = new DemoThumbnailComp (formatManager, transportSource, zoomSlider)); | |||
| thumbnail->addChangeListener (this); | |||
| addAndMakeVisible (&startStopButton); | |||
| startStopButton.setButtonText ("Play/Stop"); | |||
| startStopButton.addListener (this); | |||
| startStopButton.setColour (TextButton::buttonColourId, Colour (0xff79ed7f)); | |||
| addAndMakeVisible (&fileTreeComp); | |||
| // audio setup | |||
| formatManager.registerBasicFormats(); | |||
| directoryList.setDirectory (File::getSpecialLocation (File::userHomeDirectory), true, true); | |||
| thread.startThread (3); | |||
| fileTreeComp.setColour (FileTreeComponent::backgroundColourId, Colours::lightgrey.withAlpha (0.6f)); | |||
| fileTreeComp.addListener (this); | |||
| deviceManager.addAudioCallback (&audioSourcePlayer); | |||
| audioSourcePlayer.setSource (&transportSource); | |||
| setOpaque (true); | |||
| } | |||
| ~AudioPlaybackDemo() | |||
| { | |||
| transportSource.setSource (nullptr); | |||
| audioSourcePlayer.setSource (nullptr); | |||
| deviceManager.removeAudioCallback (&audioSourcePlayer); | |||
| fileTreeComp.removeListener (this); | |||
| thumbnail->removeChangeListener (this); | |||
| followTransportButton.removeListener (this); | |||
| zoomSlider.removeListener (this); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| void resized() override | |||
| { | |||
| Rectangle<int> r (getLocalBounds().reduced (4)); | |||
| Rectangle<int> controls (r.removeFromBottom (90)); | |||
| explanation.setBounds (controls.removeFromRight (controls.getWidth() / 3)); | |||
| Rectangle<int> zoom (controls.removeFromTop (25)); | |||
| zoomLabel.setBounds (zoom.removeFromLeft (50)); | |||
| zoomSlider.setBounds (zoom); | |||
| followTransportButton.setBounds (controls.removeFromTop (25)); | |||
| startStopButton.setBounds (controls); | |||
| r.removeFromBottom (6); | |||
| thumbnail->setBounds (r.removeFromBottom (140)); | |||
| r.removeFromBottom (6); | |||
| fileTreeComp.setBounds (r); | |||
| } | |||
| private: | |||
| AudioDeviceManager& deviceManager; | |||
| AudioFormatManager formatManager; | |||
| TimeSliceThread thread; | |||
| DirectoryContentsList directoryList; | |||
| AudioSourcePlayer audioSourcePlayer; | |||
| AudioTransportSource transportSource; | |||
| ScopedPointer<AudioFormatReaderSource> currentAudioFileSource; | |||
| ScopedPointer<DemoThumbnailComp> thumbnail; | |||
| Label zoomLabel, explanation; | |||
| Slider zoomSlider; | |||
| ToggleButton followTransportButton; | |||
| TextButton startStopButton; | |||
| FileTreeComponent fileTreeComp; | |||
| //============================================================================== | |||
| void showFile (const File& file) | |||
| { | |||
| loadFileIntoTransport (file); | |||
| zoomSlider.setValue (0, dontSendNotification); | |||
| thumbnail->setFile (file); | |||
| } | |||
| void loadFileIntoTransport (const File& audioFile) | |||
| { | |||
| // unload the previous file source and delete it.. | |||
| transportSource.stop(); | |||
| transportSource.setSource (nullptr); | |||
| currentAudioFileSource = nullptr; | |||
| AudioFormatReader* reader = formatManager.createReaderFor (audioFile); | |||
| if (reader != nullptr) | |||
| { | |||
| currentAudioFileSource = new AudioFormatReaderSource (reader, true); | |||
| // ..and plug it into our transport source | |||
| transportSource.setSource (currentAudioFileSource, | |||
| 32768, // tells it to buffer this many samples ahead | |||
| &thread, // this is the background thread to use for reading-ahead | |||
| reader->sampleRate); // allows for sample rate correction | |||
| } | |||
| } | |||
| void selectionChanged() override | |||
| { | |||
| showFile (fileTreeComp.getSelectedFile()); | |||
| } | |||
| void fileClicked (const File&, const MouseEvent&) override {} | |||
| void fileDoubleClicked (const File&) override {} | |||
| void browserRootChanged (const File&) override {} | |||
| void sliderValueChanged (Slider* sliderThatWasMoved) override | |||
| { | |||
| if (sliderThatWasMoved == &zoomSlider) | |||
| thumbnail->setZoomFactor (zoomSlider.getValue()); | |||
| } | |||
| void buttonClicked (Button* buttonThatWasClicked) override | |||
| { | |||
| if (buttonThatWasClicked == &startStopButton) | |||
| { | |||
| if (transportSource.isPlaying()) | |||
| { | |||
| transportSource.stop(); | |||
| } | |||
| else | |||
| { | |||
| transportSource.setPosition (0); | |||
| transportSource.start(); | |||
| } | |||
| } | |||
| else if (buttonThatWasClicked == &followTransportButton) | |||
| { | |||
| thumbnail->setFollowsTransport (followTransportButton.getToggleState()); | |||
| } | |||
| } | |||
| void changeListenerCallback (ChangeBroadcaster* source) override | |||
| { | |||
| if (source == thumbnail) | |||
| showFile (thumbnail->getLastDroppedFile()); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPlaybackDemo); | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<AudioPlaybackDemo> demo ("31 Audio: File Playback"); | |||
| @@ -0,0 +1,304 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| #include "AudioLiveScrollingDisplay.h" | |||
| //============================================================================== | |||
| /** A simple class that acts as an AudioIODeviceCallback and writes the | |||
| incoming audio data to a WAV file. | |||
| */ | |||
| class AudioRecorder : public AudioIODeviceCallback | |||
| { | |||
| public: | |||
| AudioRecorder (AudioThumbnail& thumbnailToUpdate) | |||
| : thumbnail (thumbnailToUpdate), | |||
| backgroundThread ("Audio Recorder Thread"), | |||
| sampleRate (0), nextSampleNum (0), activeWriter (nullptr) | |||
| { | |||
| backgroundThread.startThread(); | |||
| } | |||
| ~AudioRecorder() | |||
| { | |||
| stop(); | |||
| } | |||
| //============================================================================== | |||
| void startRecording (const File& file) | |||
| { | |||
| stop(); | |||
| if (sampleRate > 0) | |||
| { | |||
| // Create an OutputStream to write to our destination file... | |||
| file.deleteFile(); | |||
| ScopedPointer<FileOutputStream> fileStream (file.createOutputStream()); | |||
| if (fileStream != nullptr) | |||
| { | |||
| // Now create a WAV writer object that writes to our output stream... | |||
| WavAudioFormat wavFormat; | |||
| AudioFormatWriter* writer = wavFormat.createWriterFor (fileStream, sampleRate, 1, 16, StringPairArray(), 0); | |||
| if (writer != nullptr) | |||
| { | |||
| fileStream.release(); // (passes responsibility for deleting the stream to the writer object that is now using it) | |||
| // Now we'll create one of these helper objects which will act as a FIFO buffer, and will | |||
| // write the data to disk on our background thread. | |||
| threadedWriter = new AudioFormatWriter::ThreadedWriter (writer, backgroundThread, 32768); | |||
| // Reset our recording thumbnail | |||
| thumbnail.reset (writer->getNumChannels(), writer->getSampleRate()); | |||
| nextSampleNum = 0; | |||
| // And now, swap over our active writer pointer so that the audio callback will start using it.. | |||
| const ScopedLock sl (writerLock); | |||
| activeWriter = threadedWriter; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void stop() | |||
| { | |||
| // First, clear this pointer to stop the audio callback from using our writer object.. | |||
| { | |||
| const ScopedLock sl (writerLock); | |||
| activeWriter = nullptr; | |||
| } | |||
| // Now we can delete the writer object. It's done in this order because the deletion could | |||
| // take a little time while remaining data gets flushed to disk, so it's best to avoid blocking | |||
| // the audio callback while this happens. | |||
| threadedWriter = nullptr; | |||
| } | |||
| bool isRecording() const | |||
| { | |||
| return activeWriter != nullptr; | |||
| } | |||
| //============================================================================== | |||
| void audioDeviceAboutToStart (AudioIODevice* device) override | |||
| { | |||
| sampleRate = device->getCurrentSampleRate(); | |||
| } | |||
| void audioDeviceStopped() override | |||
| { | |||
| sampleRate = 0; | |||
| } | |||
| void audioDeviceIOCallback (const float** inputChannelData, int /*numInputChannels*/, | |||
| float** outputChannelData, int numOutputChannels, | |||
| int numSamples) override | |||
| { | |||
| const ScopedLock sl (writerLock); | |||
| if (activeWriter != nullptr) | |||
| { | |||
| activeWriter->write (inputChannelData, numSamples); | |||
| // Create an AudioSampleBuffer to wrap our incomming data, note that this does no allocations or copies, it simply references our input data | |||
| const AudioSampleBuffer buffer (const_cast<float**> (inputChannelData), thumbnail.getNumChannels(), numSamples); | |||
| thumbnail.addBlock (nextSampleNum, buffer, 0, numSamples); | |||
| nextSampleNum += numSamples; | |||
| } | |||
| // We need to clear the output buffers, in case they're full of junk.. | |||
| for (int i = 0; i < numOutputChannels; ++i) | |||
| if (outputChannelData[i] != nullptr) | |||
| FloatVectorOperations::clear (outputChannelData[i], numSamples); | |||
| } | |||
| private: | |||
| AudioThumbnail& thumbnail; | |||
| TimeSliceThread backgroundThread; // the thread that will write our audio data to disk | |||
| ScopedPointer<AudioFormatWriter::ThreadedWriter> threadedWriter; // the FIFO used to buffer the incoming data | |||
| double sampleRate; | |||
| int64 nextSampleNum; | |||
| CriticalSection writerLock; | |||
| AudioFormatWriter::ThreadedWriter* volatile activeWriter; | |||
| }; | |||
| //============================================================================== | |||
| class RecordingThumbnail : public Component, | |||
| private ChangeListener | |||
| { | |||
| public: | |||
| RecordingThumbnail() | |||
| : thumbnailCache (10), | |||
| thumbnail (512, formatManager, thumbnailCache), | |||
| displayFullThumb (false) | |||
| { | |||
| formatManager.registerBasicFormats(); | |||
| thumbnail.addChangeListener (this); | |||
| } | |||
| ~RecordingThumbnail() | |||
| { | |||
| thumbnail.removeChangeListener (this); | |||
| } | |||
| AudioThumbnail& getAudioThumbnail() { return thumbnail; } | |||
| void setDisplayFullThumbnail (bool displayFull) | |||
| { | |||
| displayFullThumb = displayFull; | |||
| repaint(); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (Colours::darkgrey); | |||
| g.setColour (Colours::lightgrey); | |||
| if (thumbnail.getTotalLength() > 0.0) | |||
| { | |||
| const double endTime = displayFullThumb ? thumbnail.getTotalLength() | |||
| : jmax (30.0, thumbnail.getTotalLength()); | |||
| Rectangle<int> thumbArea (getLocalBounds()); | |||
| thumbnail.drawChannels (g, thumbArea.reduced (2), 0.0, endTime, 1.0f); | |||
| } | |||
| else | |||
| { | |||
| g.setFont (14.0f); | |||
| g.drawFittedText ("(No file recorded)", getLocalBounds(), Justification::centred, 2); | |||
| } | |||
| } | |||
| private: | |||
| AudioFormatManager formatManager; | |||
| AudioThumbnailCache thumbnailCache; | |||
| AudioThumbnail thumbnail; | |||
| bool displayFullThumb; | |||
| void changeListenerCallback (ChangeBroadcaster* source) override | |||
| { | |||
| if (source == &thumbnail) | |||
| repaint(); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RecordingThumbnail) | |||
| }; | |||
| //============================================================================== | |||
| class AudioRecordingDemo : public Component, | |||
| private Button::Listener | |||
| { | |||
| public: | |||
| AudioRecordingDemo() | |||
| : deviceManager (MainAppWindow::getSharedAudioDeviceManager()), | |||
| recorder (recordingThumbnail.getAudioThumbnail()) | |||
| { | |||
| setOpaque (true); | |||
| addAndMakeVisible (&liveAudioScroller); | |||
| addAndMakeVisible (&explanationLabel); | |||
| explanationLabel.setText ("This page demonstrates how to record a wave file from the live audio input..\n\nPressing record will start recording a file in your \"Documents\" folder.", dontSendNotification); | |||
| explanationLabel.setFont (Font (15.00f, Font::plain)); | |||
| explanationLabel.setJustificationType (Justification::topLeft); | |||
| explanationLabel.setEditable (false, false, false); | |||
| explanationLabel.setColour (TextEditor::textColourId, Colours::black); | |||
| explanationLabel.setColour (TextEditor::backgroundColourId, Colour (0x00000000)); | |||
| addAndMakeVisible (&recordButton); | |||
| recordButton.setButtonText ("Record"); | |||
| recordButton.addListener (this); | |||
| recordButton.setColour (TextButton::buttonColourId, Colour (0xffff5c5c)); | |||
| recordButton.setColour (TextButton::textColourOnId, Colours::black); | |||
| addAndMakeVisible (&recordingThumbnail); | |||
| deviceManager.addAudioCallback (&liveAudioScroller); | |||
| deviceManager.addAudioCallback (&recorder); | |||
| } | |||
| ~AudioRecordingDemo() | |||
| { | |||
| deviceManager.removeAudioCallback (&recorder); | |||
| deviceManager.removeAudioCallback (&liveAudioScroller); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| void resized() override | |||
| { | |||
| Rectangle<int> area (getLocalBounds()); | |||
| liveAudioScroller.setBounds (area.removeFromTop (80).reduced (8)); | |||
| recordingThumbnail.setBounds (area.removeFromTop (80).reduced (8)); | |||
| recordButton.setBounds (area.removeFromLeft (140).removeFromTop (36).reduced (8)); | |||
| explanationLabel.setBounds (area.reduced (8)); | |||
| } | |||
| private: | |||
| AudioDeviceManager& deviceManager; | |||
| LiveScrollingAudioDisplay liveAudioScroller; | |||
| RecordingThumbnail recordingThumbnail; | |||
| AudioRecorder recorder; | |||
| Label explanationLabel; | |||
| TextButton recordButton; | |||
| void startRecording() | |||
| { | |||
| const File file (File::getSpecialLocation (File::userDocumentsDirectory) | |||
| .getNonexistentChildFile ("Juce Demo Audio Recording", ".wav")); | |||
| recorder.startRecording (file); | |||
| recordButton.setButtonText ("Stop"); | |||
| recordingThumbnail.setDisplayFullThumbnail (false); | |||
| } | |||
| void stopRecording() | |||
| { | |||
| recorder.stop(); | |||
| recordButton.setButtonText ("Record"); | |||
| recordingThumbnail.setDisplayFullThumbnail (true); | |||
| } | |||
| void buttonClicked (Button* button) override | |||
| { | |||
| if (button == &recordButton) | |||
| { | |||
| if (recorder.isRecording()) | |||
| stopRecording(); | |||
| else | |||
| startRecording(); | |||
| } | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioRecordingDemo) | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<AudioRecordingDemo> demo ("31 Audio: Recording"); | |||
| @@ -0,0 +1,132 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| //============================================================================== | |||
| class AudioSettingsDemo : public Component, | |||
| public ChangeListener | |||
| { | |||
| public: | |||
| AudioSettingsDemo() | |||
| { | |||
| setOpaque (true); | |||
| addAndMakeVisible (audioSetupComp | |||
| = new AudioDeviceSelectorComponent (MainAppWindow::getSharedAudioDeviceManager(), | |||
| 0, 256, 0, 256, true, true, true, false)); | |||
| addAndMakeVisible (&diagnosticsBox); | |||
| diagnosticsBox.setMultiLine (true); | |||
| diagnosticsBox.setReturnKeyStartsNewLine (true); | |||
| diagnosticsBox.setReadOnly (true); | |||
| diagnosticsBox.setScrollbarsShown (true); | |||
| diagnosticsBox.setCaretVisible (false); | |||
| diagnosticsBox.setPopupMenuEnabled (true); | |||
| diagnosticsBox.setColour (TextEditor::backgroundColourId, Colour (0x32ffffff)); | |||
| diagnosticsBox.setColour (TextEditor::outlineColourId, Colour (0x1c000000)); | |||
| diagnosticsBox.setColour (TextEditor::shadowColourId, Colour (0x16000000)); | |||
| MainAppWindow::getSharedAudioDeviceManager().addChangeListener (this); | |||
| logMessage ("Audio device diagnostics:\n"); | |||
| dumpDeviceInfo(); | |||
| } | |||
| ~AudioSettingsDemo() | |||
| { | |||
| MainAppWindow::getSharedAudioDeviceManager().removeChangeListener (this); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| void resized() override | |||
| { | |||
| Rectangle<int> r (getLocalBounds().reduced (4)); | |||
| audioSetupComp->setBounds (r.removeFromTop (proportionOfHeight (0.65f))); | |||
| diagnosticsBox.setBounds (r); | |||
| } | |||
| void dumpDeviceInfo() | |||
| { | |||
| AudioDeviceManager& dm = MainAppWindow::getSharedAudioDeviceManager(); | |||
| logMessage ("--------------------------------------"); | |||
| logMessage ("Current audio device type: " + (dm.getCurrentDeviceTypeObject() != nullptr | |||
| ? dm.getCurrentDeviceTypeObject()->getTypeName() | |||
| : "<none>")); | |||
| if (AudioIODevice* device = dm.getCurrentAudioDevice()) | |||
| { | |||
| logMessage ("Current audio device: " + device->getName().quoted()); | |||
| logMessage ("Sample rate: " + String (device->getCurrentSampleRate()) + " Hz"); | |||
| logMessage ("Block size: " + String (device->getCurrentBufferSizeSamples()) + " samples"); | |||
| logMessage ("Bit depth: " + String (device->getCurrentBitDepth())); | |||
| logMessage ("Input channel names: " + device->getInputChannelNames().joinIntoString (", ")); | |||
| logMessage ("Active input channels: " + getListOfActiveBits (device->getActiveInputChannels())); | |||
| logMessage ("Output channel names: " + device->getOutputChannelNames().joinIntoString (", ")); | |||
| logMessage ("Active output channels: " + getListOfActiveBits (device->getActiveOutputChannels())); | |||
| } | |||
| else | |||
| { | |||
| logMessage ("No audio device open"); | |||
| } | |||
| } | |||
| void logMessage (const String& m) | |||
| { | |||
| diagnosticsBox.moveCaretToEnd(); | |||
| diagnosticsBox.insertTextAtCaret (m + newLine); | |||
| } | |||
| private: | |||
| ScopedPointer<AudioDeviceSelectorComponent> audioSetupComp; | |||
| TextEditor diagnosticsBox; | |||
| void changeListenerCallback (ChangeBroadcaster*) override | |||
| { | |||
| dumpDeviceInfo(); | |||
| } | |||
| static String getListOfActiveBits (const BitArray& b) | |||
| { | |||
| StringArray bits; | |||
| for (int i = 0; i <= b.getHighestBit(); ++i) | |||
| if (b[i]) | |||
| bits.add (String (i)); | |||
| return bits.joinIntoString (", "); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSettingsDemo); | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<AudioSettingsDemo> demo ("30 Audio: Settings"); | |||
| @@ -0,0 +1,316 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| #include "AudioLiveScrollingDisplay.h" | |||
| //============================================================================== | |||
| /** Our demo synth sound is just a basic sine wave.. */ | |||
| struct SineWaveSound : public SynthesiserSound | |||
| { | |||
| SineWaveSound() {} | |||
| bool appliesToNote (const int /*midiNoteNumber*/) { return true; } | |||
| bool appliesToChannel (const int /*midiChannel*/) { return true; } | |||
| }; | |||
| //============================================================================== | |||
| /** Our demo synth voice just plays a sine wave.. */ | |||
| struct SineWaveVoice : public SynthesiserVoice | |||
| { | |||
| SineWaveVoice() : currentAngle (0), angleDelta (0), level (0), tailOff (0) | |||
| { | |||
| } | |||
| bool canPlaySound (SynthesiserSound* sound) override | |||
| { | |||
| return dynamic_cast<SineWaveSound*> (sound) != nullptr; | |||
| } | |||
| void startNote (int midiNoteNumber, float velocity, | |||
| SynthesiserSound*, int /*currentPitchWheelPosition*/) override | |||
| { | |||
| currentAngle = 0.0; | |||
| level = velocity * 0.15; | |||
| tailOff = 0.0; | |||
| double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber); | |||
| double cyclesPerSample = cyclesPerSecond / getSampleRate(); | |||
| angleDelta = cyclesPerSample * 2.0 * double_Pi; | |||
| } | |||
| void stopNote (bool allowTailOff) override | |||
| { | |||
| if (allowTailOff) | |||
| { | |||
| // start a tail-off by setting this flag. The render callback will pick up on | |||
| // this and do a fade out, calling clearCurrentNote() when it's finished. | |||
| if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the | |||
| // stopNote method could be called more than once. | |||
| tailOff = 1.0; | |||
| } | |||
| else | |||
| { | |||
| // we're being told to stop playing immediately, so reset everything.. | |||
| clearCurrentNote(); | |||
| angleDelta = 0.0; | |||
| } | |||
| } | |||
| void pitchWheelMoved (int /*newValue*/) override | |||
| { | |||
| // can't be bothered implementing this for the demo! | |||
| } | |||
| void controllerMoved (int /*controllerNumber*/, int /*newValue*/) override | |||
| { | |||
| // not interested in controllers in this case. | |||
| } | |||
| void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override | |||
| { | |||
| if (angleDelta != 0.0) | |||
| { | |||
| if (tailOff > 0) | |||
| { | |||
| while (--numSamples >= 0) | |||
| { | |||
| const float currentSample = (float) (sin (currentAngle) * level * tailOff); | |||
| for (int i = outputBuffer.getNumChannels(); --i >= 0;) | |||
| *outputBuffer.getSampleData (i, startSample) += currentSample; | |||
| currentAngle += angleDelta; | |||
| ++startSample; | |||
| tailOff *= 0.99; | |||
| if (tailOff <= 0.005) | |||
| { | |||
| clearCurrentNote(); | |||
| angleDelta = 0.0; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| while (--numSamples >= 0) | |||
| { | |||
| const float currentSample = (float) (sin (currentAngle) * level); | |||
| for (int i = outputBuffer.getNumChannels(); --i >= 0;) | |||
| *outputBuffer.getSampleData (i, startSample) += currentSample; | |||
| currentAngle += angleDelta; | |||
| ++startSample; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private: | |||
| double currentAngle, angleDelta, level, tailOff; | |||
| }; | |||
| //============================================================================== | |||
| // This is an audio source that streams the output of our demo synth. | |||
| struct SynthAudioSource : public AudioSource | |||
| { | |||
| SynthAudioSource (MidiKeyboardState& keyState) : keyboardState (keyState) | |||
| { | |||
| // Add some voices to our synth, to play the sounds.. | |||
| for (int i = 4; --i >= 0;) | |||
| { | |||
| synth.addVoice (new SineWaveVoice()); // These voices will play our custom sine-wave sounds.. | |||
| synth.addVoice (new SamplerVoice()); // and these ones play the sampled sounds | |||
| } | |||
| // ..and add a sound for them to play... | |||
| setUsingSineWaveSound(); | |||
| } | |||
| void setUsingSineWaveSound() | |||
| { | |||
| synth.clearSounds(); | |||
| synth.addSound (new SineWaveSound()); | |||
| } | |||
| void setUsingSampledSound() | |||
| { | |||
| WavAudioFormat wavFormat; | |||
| ScopedPointer<AudioFormatReader> audioReader (wavFormat.createReaderFor (new MemoryInputStream (BinaryData::cello_wav, | |||
| BinaryData::cello_wavSize, | |||
| false), | |||
| true)); | |||
| BigInteger allNotes; | |||
| allNotes.setRange (0, 128, true); | |||
| synth.clearSounds(); | |||
| synth.addSound (new SamplerSound ("demo sound", | |||
| *audioReader, | |||
| allNotes, | |||
| 74, // root midi note | |||
| 0.1, // attack time | |||
| 0.1, // release time | |||
| 10.0 // maximum sample length | |||
| )); | |||
| } | |||
| void prepareToPlay (int /*samplesPerBlockExpected*/, double sampleRate) override | |||
| { | |||
| midiCollector.reset (sampleRate); | |||
| synth.setCurrentPlaybackSampleRate (sampleRate); | |||
| } | |||
| void releaseResources() override | |||
| { | |||
| } | |||
| void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override | |||
| { | |||
| // the synth always adds its output to the audio buffer, so we have to clear it | |||
| // first.. | |||
| bufferToFill.clearActiveBufferRegion(); | |||
| // fill a midi buffer with incoming messages from the midi input. | |||
| MidiBuffer incomingMidi; | |||
| midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples); | |||
| // pass these messages to the keyboard state so that it can update the component | |||
| // to show on-screen which keys are being pressed on the physical midi keyboard. | |||
| // This call will also add midi messages to the buffer which were generated by | |||
| // the mouse-clicking on the on-screen keyboard. | |||
| keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true); | |||
| // and now get the synth to process the midi events and generate its output. | |||
| synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples); | |||
| } | |||
| //============================================================================== | |||
| // this collects real-time midi messages from the midi input device, and | |||
| // turns them into blocks that we can process in our audio callback | |||
| MidiMessageCollector midiCollector; | |||
| // this represents the state of which keys on our on-screen keyboard are held | |||
| // down. When the mouse is clicked on the keyboard component, this object also | |||
| // generates midi messages for this, which we can pass on to our synth. | |||
| MidiKeyboardState& keyboardState; | |||
| // the synth itself! | |||
| Synthesiser synth; | |||
| }; | |||
| //============================================================================== | |||
| class AudioSynthesiserDemo : public Component, | |||
| private Button::Listener | |||
| { | |||
| public: | |||
| AudioSynthesiserDemo() | |||
| : deviceManager (MainAppWindow::getSharedAudioDeviceManager()), | |||
| synthAudioSource (keyboardState), | |||
| keyboardComponent (keyboardState, MidiKeyboardComponent::horizontalKeyboard) | |||
| { | |||
| addAndMakeVisible (&keyboardComponent); | |||
| addAndMakeVisible (&sineButton); | |||
| sineButton.setButtonText ("Use sine wave"); | |||
| sineButton.setRadioGroupId (321); | |||
| sineButton.addListener (this); | |||
| sineButton.setToggleState (true, dontSendNotification); | |||
| addAndMakeVisible (&sampledButton); | |||
| sampledButton.setButtonText ("Use sampled sound"); | |||
| sampledButton.setRadioGroupId (321); | |||
| sampledButton.addListener (this); | |||
| addAndMakeVisible (&liveAudioDisplayComp); | |||
| deviceManager.addAudioCallback (&liveAudioDisplayComp); | |||
| audioSourcePlayer.setSource (&synthAudioSource); | |||
| deviceManager.addAudioCallback (&audioSourcePlayer); | |||
| deviceManager.addMidiInputCallback (String::empty, &(synthAudioSource.midiCollector)); | |||
| setOpaque (true); | |||
| setSize (640, 480); | |||
| } | |||
| ~AudioSynthesiserDemo() | |||
| { | |||
| audioSourcePlayer.setSource (nullptr); | |||
| deviceManager.removeMidiInputCallback (String::empty, &(synthAudioSource.midiCollector)); | |||
| deviceManager.removeAudioCallback (&audioSourcePlayer); | |||
| deviceManager.removeAudioCallback (&liveAudioDisplayComp); | |||
| } | |||
| //============================================================================== | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| void resized() override | |||
| { | |||
| keyboardComponent.setBounds (8, 96, getWidth() - 16, 64); | |||
| sineButton.setBounds (16, 176, 150, 24); | |||
| sampledButton.setBounds (16, 200, 150, 24); | |||
| liveAudioDisplayComp.setBounds (8, 8, getWidth() - 16, 64); | |||
| } | |||
| private: | |||
| AudioDeviceManager& deviceManager; | |||
| MidiKeyboardState keyboardState; | |||
| AudioSourcePlayer audioSourcePlayer; | |||
| SynthAudioSource synthAudioSource; | |||
| MidiKeyboardComponent keyboardComponent; | |||
| ToggleButton sineButton; | |||
| ToggleButton sampledButton; | |||
| LiveScrollingAudioDisplay liveAudioDisplayComp; | |||
| //============================================================================== | |||
| void buttonClicked (Button* buttonThatWasClicked) override | |||
| { | |||
| if (buttonThatWasClicked == &sineButton) | |||
| synthAudioSource.setUsingSineWaveSound(); | |||
| else if (buttonThatWasClicked == &sampledButton) | |||
| synthAudioSource.setUsingSampledSound(); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSynthesiserDemo) | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<AudioSynthesiserDemo> demo ("31 Audio: Synthesisers"); | |||
| @@ -0,0 +1,338 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-12 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../JuceDemoHeader.h" | |||
| // (These classes and random functions are used inside the 3rd-party Box2D demo code) | |||
| inline float32 RandomFloat() { return Random::getSystemRandom().nextFloat() * 2.0f - 1.0f; } | |||
| inline float32 RandomFloat (float32 lo, float32 hi) { return Random::getSystemRandom().nextFloat() * (hi - lo) + lo; } | |||
| struct Settings | |||
| { | |||
| Settings() | |||
| : viewCenter (0.0f, 20.0f), | |||
| hz (60.0f), | |||
| velocityIterations (8), | |||
| positionIterations (3), | |||
| drawShapes (1), | |||
| drawJoints (1), | |||
| drawAABBs (0), | |||
| drawPairs (0), | |||
| drawContactPoints (0), | |||
| drawContactNormals (0), | |||
| drawContactForces (0), | |||
| drawFrictionForces (0), | |||
| drawCOMs (0), | |||
| drawStats (0), | |||
| drawProfile (0), | |||
| enableWarmStarting (1), | |||
| enableContinuous (1), | |||
| enableSubStepping (0), | |||
| pause (0), | |||
| singleStep (0) | |||
| {} | |||
| b2Vec2 viewCenter; | |||
| float32 hz; | |||
| int velocityIterations; | |||
| int positionIterations; | |||
| int drawShapes; | |||
| int drawJoints; | |||
| int drawAABBs; | |||
| int drawPairs; | |||
| int drawContactPoints; | |||
| int drawContactNormals; | |||
| int drawContactForces; | |||
| int drawFrictionForces; | |||
| int drawCOMs; | |||
| int drawStats; | |||
| int drawProfile; | |||
| int enableWarmStarting; | |||
| int enableContinuous; | |||
| int enableSubStepping; | |||
| int pause; | |||
| int singleStep; | |||
| }; | |||
| struct Test | |||
| { | |||
| Test() : m_world (new b2World (b2Vec2 (0.0f, -10.0f))) {} | |||
| virtual ~Test() {} | |||
| virtual void Keyboard (unsigned char /*key*/) {} | |||
| virtual void KeyboardUp (unsigned char /*key*/) {} | |||
| ScopedPointer<b2World> m_world; | |||
| }; | |||
| #include "Box2DTests/AddPair.h" | |||
| #include "Box2DTests/ApplyForce.h" | |||
| #include "Box2DTests/Dominos.h" | |||
| #include "Box2DTests/Chain.h" | |||
| //============================================================================== | |||
| /** This list box just displays a StringArray and broadcasts a change message when the | |||
| selected row changes. | |||
| */ | |||
| class Box2DTestList : public ListBoxModel, | |||
| public ChangeBroadcaster | |||
| { | |||
| public: | |||
| Box2DTestList (const StringArray& testList) : tests (testList) | |||
| { | |||
| } | |||
| int getNumRows() override { return tests.size(); } | |||
| void paintListBoxItem (int row, Graphics& g, int w, int h, bool rowIsSelected) override | |||
| { | |||
| if (rowIsSelected) | |||
| g.fillAll (LookAndFeel::getDefaultLookAndFeel().findColour (TextEditor::highlightColourId)); | |||
| const Font f (h * 0.7f); | |||
| g.setColour (Colours::black); | |||
| g.setFont (f); | |||
| g.drawText (tests[row], Rectangle<int> (0, 0, w, h).reduced (2), | |||
| Justification::centredLeft, true); | |||
| } | |||
| void selectedRowsChanged (int /*lastRowSelected*/) override | |||
| { | |||
| sendChangeMessage(); | |||
| } | |||
| private: | |||
| StringArray tests; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Box2DTestList) | |||
| }; | |||
| //============================================================================== | |||
| struct Box2DRenderComponent : public Component | |||
| { | |||
| Box2DRenderComponent() | |||
| { | |||
| setOpaque (true); | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.fillAll (Colours::white); | |||
| if (currentTest != nullptr) | |||
| { | |||
| Box2DRenderer renderer; | |||
| renderer.render (g, *currentTest->m_world, | |||
| -16.0f, 30.0f, 16.0f, -1.0f, | |||
| getLocalBounds().toFloat().reduced (8.0f)); | |||
| } | |||
| } | |||
| ScopedPointer<Test> currentTest; | |||
| }; | |||
| //============================================================================== | |||
| class Box2DDemo : public Component, | |||
| private Timer, | |||
| private ChangeListener | |||
| { | |||
| public: | |||
| enum Demos | |||
| { | |||
| addPair = 0, | |||
| applyForce, | |||
| dominoes, | |||
| chain, | |||
| numTests | |||
| }; | |||
| Box2DDemo() | |||
| : testsList (getTestsList()), | |||
| testsListModel (testsList) | |||
| { | |||
| setOpaque (true); | |||
| setWantsKeyboardFocus (true); | |||
| testsListModel.addChangeListener (this); | |||
| addAndMakeVisible (&renderComponent); | |||
| addAndMakeVisible (&testsListBox); | |||
| testsListBox.setModel (&testsListModel); | |||
| testsListBox.selectRow (dominoes); | |||
| testsListBox.setColour (ListBox::backgroundColourId, Colours::lightgrey); | |||
| addAndMakeVisible (&instructions); | |||
| instructions.setMultiLine (true); | |||
| instructions.setReadOnly (true); | |||
| instructions.setColour (TextEditor::backgroundColourId, Colours::lightgrey); | |||
| startTimer (1000 / 60); | |||
| } | |||
| ~Box2DDemo() | |||
| { | |||
| testsListModel.removeChangeListener (this); | |||
| } | |||
| void paint (Graphics& g) override | |||
| { | |||
| fillBrushedAluminiumBackground (g); | |||
| } | |||
| void resized() override | |||
| { | |||
| Rectangle<int> r (getLocalBounds().reduced (4)); | |||
| Rectangle<int> area (r.removeFromBottom (150)); | |||
| testsListBox.setBounds (area.removeFromLeft (150)); | |||
| area.removeFromLeft (4); | |||
| instructions.setBounds (area); | |||
| r.removeFromBottom (6); | |||
| renderComponent.setBounds (r); | |||
| } | |||
| bool keyPressed (const KeyPress& key) override | |||
| { | |||
| if (renderComponent.currentTest != nullptr) | |||
| { | |||
| // We override this to avoid the system beeping for an unused keypress | |||
| switch (key.getTextCharacter()) | |||
| { | |||
| case 'a': | |||
| case 'w': | |||
| case 'd': | |||
| return true; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| private: | |||
| StringArray testsList; | |||
| Box2DTestList testsListModel; | |||
| Box2DRenderComponent renderComponent; | |||
| ListBox testsListBox; | |||
| TextEditor instructions; | |||
| static Test* createTest (int index) | |||
| { | |||
| switch (index) | |||
| { | |||
| case addPair: return new AddPair(); | |||
| case applyForce: return new ApplyForce(); | |||
| case dominoes: return new Dominos(); | |||
| case chain: return new Chain(); | |||
| default: break; | |||
| } | |||
| return nullptr; | |||
| } | |||
| static String getInstructions (int index) | |||
| { | |||
| switch (index) | |||
| { | |||
| case applyForce: | |||
| { | |||
| String s; | |||
| s << "Keys:" << newLine << newLine << "Left: \'a\'" << newLine << "Right: \'d\'" << newLine << "Forward: \'w\'"; | |||
| return s; | |||
| } | |||
| default: | |||
| break; | |||
| } | |||
| return String::empty; | |||
| } | |||
| void checkKeys() | |||
| { | |||
| if (renderComponent.currentTest == nullptr) | |||
| return; | |||
| checkKeyCode ('a'); | |||
| checkKeyCode ('w'); | |||
| checkKeyCode ('d'); | |||
| } | |||
| void checkKeyCode (const int keyCode) | |||
| { | |||
| if (KeyPress::isKeyCurrentlyDown (keyCode)) | |||
| renderComponent.currentTest->Keyboard ((unsigned char) keyCode); | |||
| } | |||
| void timerCallback() override | |||
| { | |||
| if (renderComponent.currentTest == nullptr) | |||
| return; | |||
| grabKeyboardFocus(); | |||
| checkKeys(); | |||
| renderComponent.currentTest->m_world->Step (1.0f / 60.0f, 6, 2); | |||
| repaint(); | |||
| } | |||
| void changeListenerCallback (ChangeBroadcaster* source) override | |||
| { | |||
| if (source == &testsListModel) | |||
| { | |||
| const int index = testsListBox.getSelectedRow(); | |||
| renderComponent.currentTest = createTest (index); | |||
| instructions.setText (getInstructions (index)); | |||
| repaint(); | |||
| } | |||
| } | |||
| static StringArray getTestsList() | |||
| { | |||
| const char* tests[] = | |||
| { | |||
| "Add Pair Stress Test", | |||
| "Apply Force", | |||
| "Dominoes", | |||
| "Chain" | |||
| }; | |||
| jassert (numElementsInArray (tests) == numTests); | |||
| return StringArray (tests, numElementsInArray (tests)); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Box2DDemo) | |||
| }; | |||
| // This static object will register this demo type in a global list of demos.. | |||
| static JuceDemoType<Box2DDemo> demo ("29 Graphics: Box 2D"); | |||
| @@ -0,0 +1,180 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef APPLY_FORCE_H | |||
| #define APPLY_FORCE_H | |||
| class ApplyForce : public Test | |||
| { | |||
| public: | |||
| ApplyForce() | |||
| { | |||
| m_world->SetGravity(b2Vec2(0.0f, 0.0f)); | |||
| const float32 k_restitution = 0.4f; | |||
| b2Body* ground; | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(0.0f, 20.0f); | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| b2FixtureDef sd; | |||
| sd.shape = &shape; | |||
| sd.density = 0.0f; | |||
| sd.restitution = k_restitution; | |||
| // Left vertical | |||
| shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(-20.0f, 20.0f)); | |||
| ground->CreateFixture(&sd); | |||
| // Right vertical | |||
| shape.Set(b2Vec2(20.0f, -20.0f), b2Vec2(20.0f, 20.0f)); | |||
| ground->CreateFixture(&sd); | |||
| // Top horizontal | |||
| shape.Set(b2Vec2(-20.0f, 20.0f), b2Vec2(20.0f, 20.0f)); | |||
| ground->CreateFixture(&sd); | |||
| // Bottom horizontal | |||
| shape.Set(b2Vec2(-20.0f, -20.0f), b2Vec2(20.0f, -20.0f)); | |||
| ground->CreateFixture(&sd); | |||
| } | |||
| { | |||
| b2Transform xf1; | |||
| xf1.q.Set(0.3524f * b2_pi); | |||
| xf1.p = xf1.q.GetXAxis(); | |||
| b2Vec2 vertices[3]; | |||
| vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); | |||
| vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); | |||
| vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); | |||
| b2PolygonShape poly1; | |||
| poly1.Set(vertices, 3); | |||
| b2FixtureDef sd1; | |||
| sd1.shape = &poly1; | |||
| sd1.density = 4.0f; | |||
| b2Transform xf2; | |||
| xf2.q.Set(-0.3524f * b2_pi); | |||
| xf2.p = -xf2.q.GetXAxis(); | |||
| vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); | |||
| vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); | |||
| vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); | |||
| b2PolygonShape poly2; | |||
| poly2.Set(vertices, 3); | |||
| b2FixtureDef sd2; | |||
| sd2.shape = &poly2; | |||
| sd2.density = 2.0f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.angularDamping = 5.0f; | |||
| bd.linearDamping = 0.1f; | |||
| bd.position.Set(0.0f, 2.0f); | |||
| bd.angle = b2_pi; | |||
| bd.allowSleep = false; | |||
| m_body = m_world->CreateBody(&bd); | |||
| m_body->CreateFixture(&sd1); | |||
| m_body->CreateFixture(&sd2); | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.5f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.3f; | |||
| for (int i = 0; i < 10; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 5.0f + 1.54f * i); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| float32 gravity = 10.0f; | |||
| float32 I = body->GetInertia(); | |||
| float32 mass = body->GetMass(); | |||
| // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m) | |||
| float32 radius = b2Sqrt(2.0f * I / mass); | |||
| b2FrictionJointDef jd; | |||
| jd.localAnchorA.SetZero(); | |||
| jd.localAnchorB.SetZero(); | |||
| jd.bodyA = ground; | |||
| jd.bodyB = body; | |||
| jd.collideConnected = true; | |||
| jd.maxForce = mass * gravity; | |||
| jd.maxTorque = mass * radius * gravity; | |||
| m_world->CreateJoint(&jd); | |||
| } | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'w': | |||
| { | |||
| b2Vec2 f = m_body->GetWorldVector(b2Vec2(0.0f, -200.0f)); | |||
| b2Vec2 p = m_body->GetWorldPoint(b2Vec2(0.0f, 2.0f)); | |||
| m_body->ApplyForce(f, p); | |||
| } | |||
| break; | |||
| case 'a': | |||
| { | |||
| m_body->ApplyTorque(50.0f); | |||
| } | |||
| break; | |||
| case 'd': | |||
| { | |||
| m_body->ApplyTorque(-50.0f); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new ApplyForce; | |||
| } | |||
| b2Body* m_body; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,159 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef BODY_TYPES_H | |||
| #define BODY_TYPES_H | |||
| class BodyTypes : public Test | |||
| { | |||
| public: | |||
| BodyTypes() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| ground->CreateFixture(&fd); | |||
| } | |||
| // Define attachment | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 3.0f); | |||
| m_attachment = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 2.0f); | |||
| m_attachment->CreateFixture(&shape, 2.0f); | |||
| } | |||
| // Define platform | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-4.0f, 5.0f); | |||
| m_platform = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 4.0f, b2Vec2(4.0f, 0.0f), 0.5f * b2_pi); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.friction = 0.6f; | |||
| fd.density = 2.0f; | |||
| m_platform->CreateFixture(&fd); | |||
| b2RevoluteJointDef rjd; | |||
| rjd.Initialize(m_attachment, m_platform, b2Vec2(0.0f, 5.0f)); | |||
| rjd.maxMotorTorque = 50.0f; | |||
| rjd.enableMotor = true; | |||
| m_world->CreateJoint(&rjd); | |||
| b2PrismaticJointDef pjd; | |||
| pjd.Initialize(ground, m_platform, b2Vec2(0.0f, 5.0f), b2Vec2(1.0f, 0.0f)); | |||
| pjd.maxMotorForce = 1000.0f; | |||
| pjd.enableMotor = true; | |||
| pjd.lowerTranslation = -10.0f; | |||
| pjd.upperTranslation = 10.0f; | |||
| pjd.enableLimit = true; | |||
| m_world->CreateJoint(&pjd); | |||
| m_speed = 3.0f; | |||
| } | |||
| // Create a payload | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 8.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.75f, 0.75f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.friction = 0.6f; | |||
| fd.density = 2.0f; | |||
| body->CreateFixture(&fd); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'd': | |||
| m_platform->SetType(b2_dynamicBody); | |||
| break; | |||
| case 's': | |||
| m_platform->SetType(b2_staticBody); | |||
| break; | |||
| case 'k': | |||
| m_platform->SetType(b2_kinematicBody); | |||
| m_platform->SetLinearVelocity(b2Vec2(-m_speed, 0.0f)); | |||
| m_platform->SetAngularVelocity(0.0f); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| // Drive the kinematic body. | |||
| if (m_platform->GetType() == b2_kinematicBody) | |||
| { | |||
| b2Vec2 p = m_platform->GetTransform().p; | |||
| b2Vec2 v = m_platform->GetLinearVelocity(); | |||
| if ((p.x < -10.0f && v.x < 0.0f) || | |||
| (p.x > 10.0f && v.x > 0.0f)) | |||
| { | |||
| v.x = -v.x; | |||
| m_platform->SetLinearVelocity(v); | |||
| } | |||
| } | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Keys: (d) dynamic, (s) static, (k) kinematic"); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new BodyTypes; | |||
| } | |||
| b2Body* m_attachment; | |||
| b2Body* m_platform; | |||
| float32 m_speed; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,155 @@ | |||
| /* | |||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef BREAKABLE_TEST_H | |||
| #define BREAKABLE_TEST_H | |||
| // This is used to test sensor shapes. | |||
| class Breakable : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_count = 7 | |||
| }; | |||
| Breakable() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Breakable dynamic body | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 40.0f); | |||
| bd.angle = 0.25f * b2_pi; | |||
| m_body1 = m_world->CreateBody(&bd); | |||
| m_shape1.SetAsBox(0.5f, 0.5f, b2Vec2(-0.5f, 0.0f), 0.0f); | |||
| m_piece1 = m_body1->CreateFixture(&m_shape1, 1.0f); | |||
| m_shape2.SetAsBox(0.5f, 0.5f, b2Vec2(0.5f, 0.0f), 0.0f); | |||
| m_piece2 = m_body1->CreateFixture(&m_shape2, 1.0f); | |||
| } | |||
| m_break = false; | |||
| m_broke = false; | |||
| } | |||
| void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) | |||
| { | |||
| if (m_broke) | |||
| { | |||
| // The body already broke. | |||
| return; | |||
| } | |||
| // Should the body break? | |||
| int32 count = contact->GetManifold()->pointCount; | |||
| float32 maxImpulse = 0.0f; | |||
| for (int32 i = 0; i < count; ++i) | |||
| { | |||
| maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]); | |||
| } | |||
| if (maxImpulse > 40.0f) | |||
| { | |||
| // Flag the body for breaking. | |||
| m_break = true; | |||
| } | |||
| } | |||
| void Break() | |||
| { | |||
| // Create two bodies from one. | |||
| b2Body* body1 = m_piece1->GetBody(); | |||
| b2Vec2 center = body1->GetWorldCenter(); | |||
| body1->DestroyFixture(m_piece2); | |||
| m_piece2 = NULL; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position = body1->GetPosition(); | |||
| bd.angle = body1->GetAngle(); | |||
| b2Body* body2 = m_world->CreateBody(&bd); | |||
| m_piece2 = body2->CreateFixture(&m_shape2, 1.0f); | |||
| // Compute consistent velocities for new bodies based on | |||
| // cached velocity. | |||
| b2Vec2 center1 = body1->GetWorldCenter(); | |||
| b2Vec2 center2 = body2->GetWorldCenter(); | |||
| b2Vec2 velocity1 = m_velocity + b2Cross(m_angularVelocity, center1 - center); | |||
| b2Vec2 velocity2 = m_velocity + b2Cross(m_angularVelocity, center2 - center); | |||
| body1->SetAngularVelocity(m_angularVelocity); | |||
| body1->SetLinearVelocity(velocity1); | |||
| body2->SetAngularVelocity(m_angularVelocity); | |||
| body2->SetLinearVelocity(velocity2); | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| if (m_break) | |||
| { | |||
| Break(); | |||
| m_broke = true; | |||
| m_break = false; | |||
| } | |||
| // Cache velocities to improve movement on breakage. | |||
| if (m_broke == false) | |||
| { | |||
| m_velocity = m_body1->GetLinearVelocity(); | |||
| m_angularVelocity = m_body1->GetAngularVelocity(); | |||
| } | |||
| Test::Step(settings); | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Breakable; | |||
| } | |||
| b2Body* m_body1; | |||
| b2Vec2 m_velocity; | |||
| float32 m_angularVelocity; | |||
| b2PolygonShape m_shape1; | |||
| b2PolygonShape m_shape2; | |||
| b2Fixture* m_piece1; | |||
| b2Fixture* m_piece2; | |||
| bool m_broke; | |||
| bool m_break; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,125 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef BRIDGE_H | |||
| #define BRIDGE_H | |||
| class Bridge : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_count = 30 | |||
| }; | |||
| Bridge() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| fd.friction = 0.2f; | |||
| b2RevoluteJointDef jd; | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-14.5f + 1.0f * i, 5.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| if (i == (e_count >> 1)) | |||
| { | |||
| m_middle = body; | |||
| } | |||
| prevBody = body; | |||
| } | |||
| b2Vec2 anchor(-15.0f + 1.0f * e_count, 5.0f); | |||
| jd.Initialize(prevBody, ground, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| } | |||
| for (int32 i = 0; i < 2; ++i) | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.5f, 0.0f); | |||
| vertices[1].Set(0.5f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| b2PolygonShape shape; | |||
| shape.Set(vertices, 3); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-8.0f + 8.0f * i, 12.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| } | |||
| for (int32 i = 0; i < 3; ++i) | |||
| { | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.5f; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-6.0f + 6.0f * i, 10.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Bridge; | |||
| } | |||
| b2Body* m_middle; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,136 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef BULLET_TEST_H | |||
| #define BULLET_TEST_H | |||
| class BulletTest : public Test | |||
| { | |||
| public: | |||
| BulletTest() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(0.0f, 0.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2EdgeShape edge; | |||
| edge.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | |||
| body->CreateFixture(&edge, 0.0f); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); | |||
| body->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 4.0f); | |||
| b2PolygonShape box; | |||
| box.SetAsBox(2.0f, 0.1f); | |||
| m_body = m_world->CreateBody(&bd); | |||
| m_body->CreateFixture(&box, 1.0f); | |||
| box.SetAsBox(0.25f, 0.25f); | |||
| //m_x = RandomFloat(-1.0f, 1.0f); | |||
| m_x = 0.20352793f; | |||
| bd.position.Set(m_x, 10.0f); | |||
| bd.bullet = true; | |||
| m_bullet = m_world->CreateBody(&bd); | |||
| m_bullet->CreateFixture(&box, 100.0f); | |||
| m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | |||
| } | |||
| } | |||
| void Launch() | |||
| { | |||
| m_body->SetTransform(b2Vec2(0.0f, 4.0f), 0.0f); | |||
| m_body->SetLinearVelocity(b2Vec2_zero); | |||
| m_body->SetAngularVelocity(0.0f); | |||
| m_x = RandomFloat(-1.0f, 1.0f); | |||
| m_bullet->SetTransform(b2Vec2(m_x, 10.0f), 0.0f); | |||
| m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | |||
| m_bullet->SetAngularVelocity(0.0f); | |||
| extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | |||
| extern int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; | |||
| extern int32 b2_toiRootIters, b2_toiMaxRootIters; | |||
| b2_gjkCalls = 0; | |||
| b2_gjkIters = 0; | |||
| b2_gjkMaxIters = 0; | |||
| b2_toiCalls = 0; | |||
| b2_toiIters = 0; | |||
| b2_toiMaxIters = 0; | |||
| b2_toiRootIters = 0; | |||
| b2_toiMaxRootIters = 0; | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | |||
| extern int32 b2_toiCalls, b2_toiIters; | |||
| extern int32 b2_toiRootIters, b2_toiMaxRootIters; | |||
| if (b2_gjkCalls > 0) | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", | |||
| b2_gjkCalls, b2_gjkIters / float32(b2_gjkCalls), b2_gjkMaxIters); | |||
| m_textLine += 15; | |||
| } | |||
| if (b2_toiCalls > 0) | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", | |||
| b2_toiCalls, b2_toiIters / float32(b2_toiCalls), b2_toiMaxRootIters); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", | |||
| b2_toiRootIters / float32(b2_toiCalls), b2_toiMaxRootIters); | |||
| m_textLine += 15; | |||
| } | |||
| if (m_stepCount % 60 == 0) | |||
| { | |||
| Launch(); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new BulletTest; | |||
| } | |||
| b2Body* m_body; | |||
| b2Body* m_bullet; | |||
| float32 m_x; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,211 @@ | |||
| /* | |||
| * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef CANTILEVER_H | |||
| #define CANTILEVER_H | |||
| // It is difficult to make a cantilever made of links completely rigid with weld joints. | |||
| // You will have to use a high number of iterations to make them stiff. | |||
| // So why not go ahead and use soft weld joints? They behave like a revolute | |||
| // joint with a rotational spring. | |||
| class Cantilever : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_count = 8 | |||
| }; | |||
| Cantilever() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| b2WeldJointDef jd; | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-14.5f + 1.0f * i, 5.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| prevBody = body; | |||
| } | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(1.0f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| b2WeldJointDef jd; | |||
| jd.frequencyHz = 5.0f; | |||
| jd.dampingRatio = 0.7f; | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < 3; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-14.0f + 2.0f * i, 15.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| b2Vec2 anchor(-15.0f + 2.0f * i, 15.0f); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| prevBody = body; | |||
| } | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| b2WeldJointDef jd; | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-4.5f + 1.0f * i, 5.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| if (i > 0) | |||
| { | |||
| b2Vec2 anchor(-5.0f + 1.0f * i, 5.0f); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| } | |||
| prevBody = body; | |||
| } | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| b2WeldJointDef jd; | |||
| jd.frequencyHz = 8.0f; | |||
| jd.dampingRatio = 0.7f; | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(5.5f + 1.0f * i, 10.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| if (i > 0) | |||
| { | |||
| b2Vec2 anchor(5.0f + 1.0f * i, 10.0f); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| } | |||
| prevBody = body; | |||
| } | |||
| } | |||
| for (int32 i = 0; i < 2; ++i) | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.5f, 0.0f); | |||
| vertices[1].Set(0.5f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| b2PolygonShape shape; | |||
| shape.Set(vertices, 3); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-8.0f + 8.0f * i, 12.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| } | |||
| for (int32 i = 0; i < 2; ++i) | |||
| { | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.5f; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-6.0f + 6.0f * i, 10.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Cantilever; | |||
| } | |||
| b2Body* m_middle; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,286 @@ | |||
| /* | |||
| * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef CAR_H | |||
| #define CAR_H | |||
| // This is a fun demo that shows off the wheel joint | |||
| class Car : public Test | |||
| { | |||
| public: | |||
| Car() | |||
| { | |||
| m_hz = 4.0f; | |||
| m_zeta = 0.7f; | |||
| m_speed = 50.0f; | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 0.0f; | |||
| fd.friction = 0.6f; | |||
| shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | |||
| ground->CreateFixture(&fd); | |||
| float32 hs[10] = {0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f}; | |||
| float32 x = 20.0f, y1 = 0.0f, dx = 5.0f; | |||
| for (int32 i = 0; i < 10; ++i) | |||
| { | |||
| float32 y2 = hs[i]; | |||
| shape.Set(b2Vec2(x, y1), b2Vec2(x + dx, y2)); | |||
| ground->CreateFixture(&fd); | |||
| y1 = y2; | |||
| x += dx; | |||
| } | |||
| for (int32 i = 0; i < 10; ++i) | |||
| { | |||
| float32 y2 = hs[i]; | |||
| shape.Set(b2Vec2(x, y1), b2Vec2(x + dx, y2)); | |||
| ground->CreateFixture(&fd); | |||
| y1 = y2; | |||
| x += dx; | |||
| } | |||
| shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | |||
| ground->CreateFixture(&fd); | |||
| x += 80.0f; | |||
| shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | |||
| ground->CreateFixture(&fd); | |||
| x += 40.0f; | |||
| shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 10.0f, 5.0f)); | |||
| ground->CreateFixture(&fd); | |||
| x += 20.0f; | |||
| shape.Set(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); | |||
| ground->CreateFixture(&fd); | |||
| x += 40.0f; | |||
| shape.Set(b2Vec2(x, 0.0f), b2Vec2(x, 20.0f)); | |||
| ground->CreateFixture(&fd); | |||
| } | |||
| // Teeter | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(140.0f, 1.0f); | |||
| bd.type = b2_dynamicBody; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape box; | |||
| box.SetAsBox(10.0f, 0.25f); | |||
| body->CreateFixture(&box, 1.0f); | |||
| b2RevoluteJointDef jd; | |||
| jd.Initialize(ground, body, body->GetPosition()); | |||
| jd.lowerAngle = -8.0f * b2_pi / 180.0f; | |||
| jd.upperAngle = 8.0f * b2_pi / 180.0f; | |||
| jd.enableLimit = true; | |||
| m_world->CreateJoint(&jd); | |||
| body->ApplyAngularImpulse(100.0f); | |||
| } | |||
| // Bridge | |||
| { | |||
| int32 N = 20; | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(1.0f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.6f; | |||
| b2RevoluteJointDef jd; | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < N; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(161.0f + 2.0f * i, -0.125f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| b2Vec2 anchor(160.0f + 2.0f * i, -0.125f); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| prevBody = body; | |||
| } | |||
| b2Vec2 anchor(160.0f + 2.0f * N, -0.125f); | |||
| jd.Initialize(prevBody, ground, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| } | |||
| // Boxes | |||
| { | |||
| b2PolygonShape box; | |||
| box.SetAsBox(0.5f, 0.5f); | |||
| b2Body* body = NULL; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(230.0f, 0.5f); | |||
| body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&box, 0.5f); | |||
| bd.position.Set(230.0f, 1.5f); | |||
| body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&box, 0.5f); | |||
| bd.position.Set(230.0f, 2.5f); | |||
| body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&box, 0.5f); | |||
| bd.position.Set(230.0f, 3.5f); | |||
| body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&box, 0.5f); | |||
| bd.position.Set(230.0f, 4.5f); | |||
| body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&box, 0.5f); | |||
| } | |||
| // Car | |||
| { | |||
| b2PolygonShape chassis; | |||
| b2Vec2 vertices[8]; | |||
| vertices[0].Set(-1.5f, -0.5f); | |||
| vertices[1].Set(1.5f, -0.5f); | |||
| vertices[2].Set(1.5f, 0.0f); | |||
| vertices[3].Set(0.0f, 0.9f); | |||
| vertices[4].Set(-1.15f, 0.9f); | |||
| vertices[5].Set(-1.5f, 0.2f); | |||
| chassis.Set(vertices, 6); | |||
| b2CircleShape circle; | |||
| circle.m_radius = 0.4f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 1.0f); | |||
| m_car = m_world->CreateBody(&bd); | |||
| m_car->CreateFixture(&chassis, 1.0f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &circle; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.9f; | |||
| bd.position.Set(-1.0f, 0.35f); | |||
| m_wheel1 = m_world->CreateBody(&bd); | |||
| m_wheel1->CreateFixture(&fd); | |||
| bd.position.Set(1.0f, 0.4f); | |||
| m_wheel2 = m_world->CreateBody(&bd); | |||
| m_wheel2->CreateFixture(&fd); | |||
| b2WheelJointDef jd; | |||
| b2Vec2 axis(0.0f, 1.0f); | |||
| jd.Initialize(m_car, m_wheel1, m_wheel1->GetPosition(), axis); | |||
| jd.motorSpeed = 0.0f; | |||
| jd.maxMotorTorque = 20.0f; | |||
| jd.enableMotor = true; | |||
| jd.frequencyHz = m_hz; | |||
| jd.dampingRatio = m_zeta; | |||
| m_spring1 = (b2WheelJoint*)m_world->CreateJoint(&jd); | |||
| jd.Initialize(m_car, m_wheel2, m_wheel2->GetPosition(), axis); | |||
| jd.motorSpeed = 0.0f; | |||
| jd.maxMotorTorque = 10.0f; | |||
| jd.enableMotor = false; | |||
| jd.frequencyHz = m_hz; | |||
| jd.dampingRatio = m_zeta; | |||
| m_spring2 = (b2WheelJoint*)m_world->CreateJoint(&jd); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'a': | |||
| m_spring1->SetMotorSpeed(m_speed); | |||
| break; | |||
| case 's': | |||
| m_spring1->SetMotorSpeed(0.0f); | |||
| break; | |||
| case 'd': | |||
| m_spring1->SetMotorSpeed(-m_speed); | |||
| break; | |||
| case 'q': | |||
| m_hz = b2Max(0.0f, m_hz - 1.0f); | |||
| m_spring1->SetSpringFrequencyHz(m_hz); | |||
| m_spring2->SetSpringFrequencyHz(m_hz); | |||
| break; | |||
| case 'e': | |||
| m_hz += 1.0f; | |||
| m_spring1->SetSpringFrequencyHz(m_hz); | |||
| m_spring2->SetSpringFrequencyHz(m_hz); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, hz down = q, hz up = e"); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "frequency = %g hz, damping ratio = %g", m_hz, m_zeta); | |||
| m_textLine += 15; | |||
| settings->viewCenter.x = m_car->GetPosition().x; | |||
| Test::Step(settings); | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Car; | |||
| } | |||
| b2Body* m_car; | |||
| b2Body* m_wheel1; | |||
| b2Body* m_wheel2; | |||
| float32 m_hz; | |||
| float32 m_zeta; | |||
| float32 m_speed; | |||
| b2WheelJoint* m_spring1; | |||
| b2WheelJoint* m_spring2; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,253 @@ | |||
| /* | |||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef CHARACTER_COLLISION_H | |||
| #define CHARACTER_COLLISION_H | |||
| /// This is a test of typical character collision scenarios. This does not | |||
| /// show how you should implement a character in your application. | |||
| /// Instead this is used to test smooth collision on edge chains. | |||
| class CharacterCollision : public Test | |||
| { | |||
| public: | |||
| CharacterCollision() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Collinear edges with no adjacency information. | |||
| // This shows the problematic case where a box shape can hit | |||
| // an internal vertex. | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-8.0f, 1.0f), b2Vec2(-6.0f, 1.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(b2Vec2(-6.0f, 1.0f), b2Vec2(-4.0f, 1.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(b2Vec2(-4.0f, 1.0f), b2Vec2(-2.0f, 1.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Chain shape | |||
| { | |||
| b2BodyDef bd; | |||
| bd.angle = 0.25f * b2_pi; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2Vec2 vs[4]; | |||
| vs[0].Set(5.0f, 7.0f); | |||
| vs[1].Set(6.0f, 8.0f); | |||
| vs[2].Set(7.0f, 8.0f); | |||
| vs[3].Set(8.0f, 7.0f); | |||
| b2ChainShape shape; | |||
| shape.CreateChain(vs, 4); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Square tiles. This shows that adjacency shapes may | |||
| // have non-smooth collision. There is no solution | |||
| // to this problem. | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(1.0f, 1.0f, b2Vec2(4.0f, 3.0f), 0.0f); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.SetAsBox(1.0f, 1.0f, b2Vec2(6.0f, 3.0f), 0.0f); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.SetAsBox(1.0f, 1.0f, b2Vec2(8.0f, 3.0f), 0.0f); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Square made from an edge loop. Collision should be smooth. | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2Vec2 vs[4]; | |||
| vs[0].Set(-1.0f, 3.0f); | |||
| vs[1].Set(1.0f, 3.0f); | |||
| vs[2].Set(1.0f, 5.0f); | |||
| vs[3].Set(-1.0f, 5.0f); | |||
| b2ChainShape shape; | |||
| shape.CreateLoop(vs, 4); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Edge loop. Collision should be smooth. | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(-10.0f, 4.0f); | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2Vec2 vs[10]; | |||
| vs[0].Set(0.0f, 0.0f); | |||
| vs[1].Set(6.0f, 0.0f); | |||
| vs[2].Set(6.0f, 2.0f); | |||
| vs[3].Set(4.0f, 1.0f); | |||
| vs[4].Set(2.0f, 2.0f); | |||
| vs[5].Set(0.0f, 2.0f); | |||
| vs[6].Set(-2.0f, 2.0f); | |||
| vs[7].Set(-4.0f, 3.0f); | |||
| vs[8].Set(-6.0f, 2.0f); | |||
| vs[9].Set(-6.0f, 0.0f); | |||
| b2ChainShape shape; | |||
| shape.CreateLoop(vs, 10); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Square character 1 | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(-3.0f, 8.0f); | |||
| bd.type = b2_dynamicBody; | |||
| bd.fixedRotation = true; | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.5f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| body->CreateFixture(&fd); | |||
| } | |||
| // Square character 2 | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(-5.0f, 5.0f); | |||
| bd.type = b2_dynamicBody; | |||
| bd.fixedRotation = true; | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.25f, 0.25f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| body->CreateFixture(&fd); | |||
| } | |||
| // Hexagon character | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(-5.0f, 8.0f); | |||
| bd.type = b2_dynamicBody; | |||
| bd.fixedRotation = true; | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| float32 angle = 0.0f; | |||
| float32 delta = b2_pi / 3.0f; | |||
| b2Vec2 vertices[6]; | |||
| for (int32 i = 0; i < 6; ++i) | |||
| { | |||
| vertices[i].Set(0.5f * cosf(angle), 0.5f * sinf(angle)); | |||
| angle += delta; | |||
| } | |||
| b2PolygonShape shape; | |||
| shape.Set(vertices, 6); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| body->CreateFixture(&fd); | |||
| } | |||
| // Circle character | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(3.0f, 5.0f); | |||
| bd.type = b2_dynamicBody; | |||
| bd.fixedRotation = true; | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.5f; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| body->CreateFixture(&fd); | |||
| } | |||
| // Circle character | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(-7.0f, 6.0f); | |||
| bd.type = b2_dynamicBody; | |||
| bd.allowSleep = false; | |||
| m_character = m_world->CreateBody(&bd); | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.25f; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| fd.friction = 1.0f; | |||
| m_character->CreateFixture(&fd); | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| b2Vec2 v = m_character->GetLinearVelocity(); | |||
| v.x = -5.0f; | |||
| m_character->SetLinearVelocity(v); | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "This tests various character collision shapes."); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "Limitation: square and hexagon can snag on aligned boxes."); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "Feature: edge chains have smooth collision inside and out."); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new CharacterCollision; | |||
| } | |||
| b2Body* m_character; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,176 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef COLLISION_FILTERING_H | |||
| #define COLLISION_FILTERING_H | |||
| // This is a test of collision filtering. | |||
| // There is a triangle, a box, and a circle. | |||
| // There are 6 shapes. 3 large and 3 small. | |||
| // The 3 small ones always collide. | |||
| // The 3 large ones never collide. | |||
| // The boxes don't collide with triangles (except if both are small). | |||
| const int16 k_smallGroup = 1; | |||
| const int16 k_largeGroup = -1; | |||
| const uint16 k_defaultCategory = 0x0001; | |||
| const uint16 k_triangleCategory = 0x0002; | |||
| const uint16 k_boxCategory = 0x0004; | |||
| const uint16 k_circleCategory = 0x0008; | |||
| const uint16 k_triangleMask = 0xFFFF; | |||
| const uint16 k_boxMask = 0xFFFF ^ k_triangleCategory; | |||
| const uint16 k_circleMask = 0xFFFF; | |||
| class CollisionFiltering : public Test | |||
| { | |||
| public: | |||
| CollisionFiltering() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| b2FixtureDef sd; | |||
| sd.shape = &shape; | |||
| sd.friction = 0.3f; | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| ground->CreateFixture(&sd); | |||
| } | |||
| // Small triangle | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-1.0f, 0.0f); | |||
| vertices[1].Set(1.0f, 0.0f); | |||
| vertices[2].Set(0.0f, 2.0f); | |||
| b2PolygonShape polygon; | |||
| polygon.Set(vertices, 3); | |||
| b2FixtureDef triangleShapeDef; | |||
| triangleShapeDef.shape = &polygon; | |||
| triangleShapeDef.density = 1.0f; | |||
| triangleShapeDef.filter.groupIndex = k_smallGroup; | |||
| triangleShapeDef.filter.categoryBits = k_triangleCategory; | |||
| triangleShapeDef.filter.maskBits = k_triangleMask; | |||
| b2BodyDef triangleBodyDef; | |||
| triangleBodyDef.type = b2_dynamicBody; | |||
| triangleBodyDef.position.Set(-5.0f, 2.0f); | |||
| b2Body* body1 = m_world->CreateBody(&triangleBodyDef); | |||
| body1->CreateFixture(&triangleShapeDef); | |||
| // Large triangle (recycle definitions) | |||
| vertices[0] *= 2.0f; | |||
| vertices[1] *= 2.0f; | |||
| vertices[2] *= 2.0f; | |||
| polygon.Set(vertices, 3); | |||
| triangleShapeDef.filter.groupIndex = k_largeGroup; | |||
| triangleBodyDef.position.Set(-5.0f, 6.0f); | |||
| triangleBodyDef.fixedRotation = true; // look at me! | |||
| b2Body* body2 = m_world->CreateBody(&triangleBodyDef); | |||
| body2->CreateFixture(&triangleShapeDef); | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-5.0f, 10.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape p; | |||
| p.SetAsBox(0.5f, 1.0f); | |||
| body->CreateFixture(&p, 1.0f); | |||
| b2PrismaticJointDef jd; | |||
| jd.bodyA = body2; | |||
| jd.bodyB = body; | |||
| jd.enableLimit = true; | |||
| jd.localAnchorA.Set(0.0f, 4.0f); | |||
| jd.localAnchorB.SetZero(); | |||
| jd.localAxisA.Set(0.0f, 1.0f); | |||
| jd.lowerTranslation = -1.0f; | |||
| jd.upperTranslation = 1.0f; | |||
| m_world->CreateJoint(&jd); | |||
| } | |||
| // Small box | |||
| polygon.SetAsBox(1.0f, 0.5f); | |||
| b2FixtureDef boxShapeDef; | |||
| boxShapeDef.shape = &polygon; | |||
| boxShapeDef.density = 1.0f; | |||
| boxShapeDef.restitution = 0.1f; | |||
| boxShapeDef.filter.groupIndex = k_smallGroup; | |||
| boxShapeDef.filter.categoryBits = k_boxCategory; | |||
| boxShapeDef.filter.maskBits = k_boxMask; | |||
| b2BodyDef boxBodyDef; | |||
| boxBodyDef.type = b2_dynamicBody; | |||
| boxBodyDef.position.Set(0.0f, 2.0f); | |||
| b2Body* body3 = m_world->CreateBody(&boxBodyDef); | |||
| body3->CreateFixture(&boxShapeDef); | |||
| // Large box (recycle definitions) | |||
| polygon.SetAsBox(2.0f, 1.0f); | |||
| boxShapeDef.filter.groupIndex = k_largeGroup; | |||
| boxBodyDef.position.Set(0.0f, 6.0f); | |||
| b2Body* body4 = m_world->CreateBody(&boxBodyDef); | |||
| body4->CreateFixture(&boxShapeDef); | |||
| // Small circle | |||
| b2CircleShape circle; | |||
| circle.m_radius = 1.0f; | |||
| b2FixtureDef circleShapeDef; | |||
| circleShapeDef.shape = &circle; | |||
| circleShapeDef.density = 1.0f; | |||
| circleShapeDef.filter.groupIndex = k_smallGroup; | |||
| circleShapeDef.filter.categoryBits = k_circleCategory; | |||
| circleShapeDef.filter.maskBits = k_circleMask; | |||
| b2BodyDef circleBodyDef; | |||
| circleBodyDef.type = b2_dynamicBody; | |||
| circleBodyDef.position.Set(5.0f, 2.0f); | |||
| b2Body* body5 = m_world->CreateBody(&circleBodyDef); | |||
| body5->CreateFixture(&circleShapeDef); | |||
| // Large circle | |||
| circle.m_radius *= 2.0f; | |||
| circleShapeDef.filter.groupIndex = k_largeGroup; | |||
| circleBodyDef.position.Set(5.0f, 6.0f); | |||
| b2Body* body6 = m_world->CreateBody(&circleBodyDef); | |||
| body6->CreateFixture(&circleShapeDef); | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new CollisionFiltering; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,188 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef COLLISION_PROCESSING_H | |||
| #define COLLISION_PROCESSING_H | |||
| #include <algorithm> | |||
| // This test shows collision processing and tests | |||
| // deferred body destruction. | |||
| class CollisionProcessing : public Test | |||
| { | |||
| public: | |||
| CollisionProcessing() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); | |||
| b2FixtureDef sd; | |||
| sd.shape = &shape;; | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| ground->CreateFixture(&sd); | |||
| } | |||
| float32 xLo = -5.0f, xHi = 5.0f; | |||
| float32 yLo = 2.0f, yHi = 35.0f; | |||
| // Small triangle | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-1.0f, 0.0f); | |||
| vertices[1].Set(1.0f, 0.0f); | |||
| vertices[2].Set(0.0f, 2.0f); | |||
| b2PolygonShape polygon; | |||
| polygon.Set(vertices, 3); | |||
| b2FixtureDef triangleShapeDef; | |||
| triangleShapeDef.shape = &polygon; | |||
| triangleShapeDef.density = 1.0f; | |||
| b2BodyDef triangleBodyDef; | |||
| triangleBodyDef.type = b2_dynamicBody; | |||
| triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | |||
| b2Body* body1 = m_world->CreateBody(&triangleBodyDef); | |||
| body1->CreateFixture(&triangleShapeDef); | |||
| // Large triangle (recycle definitions) | |||
| vertices[0] *= 2.0f; | |||
| vertices[1] *= 2.0f; | |||
| vertices[2] *= 2.0f; | |||
| polygon.Set(vertices, 3); | |||
| triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | |||
| b2Body* body2 = m_world->CreateBody(&triangleBodyDef); | |||
| body2->CreateFixture(&triangleShapeDef); | |||
| // Small box | |||
| polygon.SetAsBox(1.0f, 0.5f); | |||
| b2FixtureDef boxShapeDef; | |||
| boxShapeDef.shape = &polygon; | |||
| boxShapeDef.density = 1.0f; | |||
| b2BodyDef boxBodyDef; | |||
| boxBodyDef.type = b2_dynamicBody; | |||
| boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | |||
| b2Body* body3 = m_world->CreateBody(&boxBodyDef); | |||
| body3->CreateFixture(&boxShapeDef); | |||
| // Large box (recycle definitions) | |||
| polygon.SetAsBox(2.0f, 1.0f); | |||
| boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | |||
| b2Body* body4 = m_world->CreateBody(&boxBodyDef); | |||
| body4->CreateFixture(&boxShapeDef); | |||
| // Small circle | |||
| b2CircleShape circle; | |||
| circle.m_radius = 1.0f; | |||
| b2FixtureDef circleShapeDef; | |||
| circleShapeDef.shape = &circle; | |||
| circleShapeDef.density = 1.0f; | |||
| b2BodyDef circleBodyDef; | |||
| circleBodyDef.type = b2_dynamicBody; | |||
| circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | |||
| b2Body* body5 = m_world->CreateBody(&circleBodyDef); | |||
| body5->CreateFixture(&circleShapeDef); | |||
| // Large circle | |||
| circle.m_radius *= 2.0f; | |||
| circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); | |||
| b2Body* body6 = m_world->CreateBody(&circleBodyDef); | |||
| body6->CreateFixture(&circleShapeDef); | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| // We are going to destroy some bodies according to contact | |||
| // points. We must buffer the bodies that should be destroyed | |||
| // because they may belong to multiple contact points. | |||
| const int32 k_maxNuke = 6; | |||
| b2Body* nuke[k_maxNuke]; | |||
| int32 nukeCount = 0; | |||
| // Traverse the contact results. Destroy bodies that | |||
| // are touching heavier bodies. | |||
| for (int32 i = 0; i < m_pointCount; ++i) | |||
| { | |||
| ContactPoint* point = m_points + i; | |||
| b2Body* body1 = point->fixtureA->GetBody(); | |||
| b2Body* body2 = point->fixtureB->GetBody(); | |||
| float32 mass1 = body1->GetMass(); | |||
| float32 mass2 = body2->GetMass(); | |||
| if (mass1 > 0.0f && mass2 > 0.0f) | |||
| { | |||
| if (mass2 > mass1) | |||
| { | |||
| nuke[nukeCount++] = body1; | |||
| } | |||
| else | |||
| { | |||
| nuke[nukeCount++] = body2; | |||
| } | |||
| if (nukeCount == k_maxNuke) | |||
| { | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| // Sort the nuke array to group duplicates. | |||
| std::sort(nuke, nuke + nukeCount); | |||
| // Destroy the bodies, skipping duplicates. | |||
| int32 i = 0; | |||
| while (i < nukeCount) | |||
| { | |||
| b2Body* b = nuke[i++]; | |||
| while (i < nukeCount && nuke[i] == b) | |||
| { | |||
| ++i; | |||
| } | |||
| if (b != m_bomb) | |||
| { | |||
| m_world->DestroyBody(b); | |||
| } | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new CollisionProcessing; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,143 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef COMPOUND_SHAPES_H | |||
| #define COMPOUND_SHAPES_H | |||
| // TODO_ERIN test joints on compounds. | |||
| class CompoundShapes : public Test | |||
| { | |||
| public: | |||
| CompoundShapes() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(0.0f, 0.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); | |||
| body->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2CircleShape circle1; | |||
| circle1.m_radius = 0.5f; | |||
| circle1.m_p.Set(-0.5f, 0.5f); | |||
| b2CircleShape circle2; | |||
| circle2.m_radius = 0.5f; | |||
| circle2.m_p.Set(0.5f, 0.5f); | |||
| for (int i = 0; i < 10; ++i) | |||
| { | |||
| float32 x = RandomFloat(-0.1f, 0.1f); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(x + 5.0f, 1.05f + 2.5f * i); | |||
| bd.angle = RandomFloat(-b2_pi, b2_pi); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&circle1, 2.0f); | |||
| body->CreateFixture(&circle2, 0.0f); | |||
| } | |||
| } | |||
| { | |||
| b2PolygonShape polygon1; | |||
| polygon1.SetAsBox(0.25f, 0.5f); | |||
| b2PolygonShape polygon2; | |||
| polygon2.SetAsBox(0.25f, 0.5f, b2Vec2(0.0f, -0.5f), 0.5f * b2_pi); | |||
| for (int i = 0; i < 10; ++i) | |||
| { | |||
| float32 x = RandomFloat(-0.1f, 0.1f); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(x - 5.0f, 1.05f + 2.5f * i); | |||
| bd.angle = RandomFloat(-b2_pi, b2_pi); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&polygon1, 2.0f); | |||
| body->CreateFixture(&polygon2, 2.0f); | |||
| } | |||
| } | |||
| { | |||
| b2Transform xf1; | |||
| xf1.q.Set(0.3524f * b2_pi); | |||
| xf1.p = xf1.q.GetXAxis(); | |||
| b2Vec2 vertices[3]; | |||
| b2PolygonShape triangle1; | |||
| vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); | |||
| vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); | |||
| vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); | |||
| triangle1.Set(vertices, 3); | |||
| b2Transform xf2; | |||
| xf2.q.Set(-0.3524f * b2_pi); | |||
| xf2.p = -xf2.q.GetXAxis(); | |||
| b2PolygonShape triangle2; | |||
| vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); | |||
| vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); | |||
| vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); | |||
| triangle2.Set(vertices, 3); | |||
| for (int32 i = 0; i < 10; ++i) | |||
| { | |||
| float32 x = RandomFloat(-0.1f, 0.1f); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(x, 2.05f + 2.5f * i); | |||
| bd.angle = 0.0f; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&triangle1, 2.0f); | |||
| body->CreateFixture(&triangle2, 2.0f); | |||
| } | |||
| } | |||
| { | |||
| b2PolygonShape bottom; | |||
| bottom.SetAsBox( 1.5f, 0.15f ); | |||
| b2PolygonShape left; | |||
| left.SetAsBox(0.15f, 2.7f, b2Vec2(-1.45f, 2.35f), 0.2f); | |||
| b2PolygonShape right; | |||
| right.SetAsBox(0.15f, 2.7f, b2Vec2(1.45f, 2.35f), -0.2f); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set( 0.0f, 2.0f ); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&bottom, 4.0f); | |||
| body->CreateFixture(&left, 4.0f); | |||
| body->CreateFixture(&right, 4.0f); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new CompoundShapes; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,167 @@ | |||
| /* | |||
| * Copyright (c) 2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef CONFINED_H | |||
| #define CONFINED_H | |||
| class Confined : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_columnCount = 0, | |||
| e_rowCount = 0 | |||
| }; | |||
| Confined() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| // Floor | |||
| shape.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| // Left wall | |||
| shape.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(-10.0f, 20.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| // Right wall | |||
| shape.Set(b2Vec2(10.0f, 0.0f), b2Vec2(10.0f, 20.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| // Roof | |||
| shape.Set(b2Vec2(-10.0f, 20.0f), b2Vec2(10.0f, 20.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| float32 radius = 0.5f; | |||
| b2CircleShape shape; | |||
| shape.m_p.SetZero(); | |||
| shape.m_radius = radius; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.1f; | |||
| for (int32 j = 0; j < e_columnCount; ++j) | |||
| { | |||
| for (int i = 0; i < e_rowCount; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-10.0f + (2.1f * j + 1.0f + 0.01f * i) * radius, (2.0f * i + 1.0f) * radius); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| } | |||
| } | |||
| m_world->SetGravity(b2Vec2(0.0f, 0.0f)); | |||
| } | |||
| void CreateCircle() | |||
| { | |||
| float32 radius = 2.0f; | |||
| b2CircleShape shape; | |||
| shape.m_p.SetZero(); | |||
| shape.m_radius = radius; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.0f; | |||
| b2Vec2 p(RandomFloat(), 3.0f + RandomFloat()); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position = p; | |||
| //bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'c': | |||
| CreateCircle(); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| bool sleeping = true; | |||
| for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) | |||
| { | |||
| if (b->GetType() != b2_dynamicBody) | |||
| { | |||
| continue; | |||
| } | |||
| if (b->IsAwake()) | |||
| { | |||
| sleeping = false; | |||
| } | |||
| } | |||
| if (m_stepCount == 180) | |||
| { | |||
| m_stepCount += 0; | |||
| } | |||
| //if (sleeping) | |||
| //{ | |||
| // CreateCircle(); | |||
| //} | |||
| Test::Step(settings); | |||
| for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) | |||
| { | |||
| if (b->GetType() != b2_dynamicBody) | |||
| { | |||
| continue; | |||
| } | |||
| b2Vec2 p = b->GetPosition(); | |||
| if (p.x <= -10.0f || 10.0f <= p.x || p.y <= 0.0f || 20.0f <= p.y) | |||
| { | |||
| p.x += 0.0; | |||
| } | |||
| } | |||
| m_debugDraw.DrawString(5, m_textLine, "Press 'c' to create a circle."); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Confined; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,137 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef CONTINUOUS_TEST_H | |||
| #define CONTINUOUS_TEST_H | |||
| class ContinuousTest : public Test | |||
| { | |||
| public: | |||
| ContinuousTest() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(0.0f, 0.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2EdgeShape edge; | |||
| edge.Set(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); | |||
| body->CreateFixture(&edge, 0.0f); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); | |||
| body->CreateFixture(&shape, 0.0f); | |||
| } | |||
| #if 1 | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 20.0f); | |||
| //bd.angle = 0.1f; | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(2.0f, 0.1f); | |||
| m_body = m_world->CreateBody(&bd); | |||
| m_body->CreateFixture(&shape, 1.0f); | |||
| m_angularVelocity = RandomFloat(-50.0f, 50.0f); | |||
| //m_angularVelocity = 46.661274f; | |||
| m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | |||
| m_body->SetAngularVelocity(m_angularVelocity); | |||
| } | |||
| #else | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 2.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2CircleShape shape; | |||
| shape.m_p.SetZero(); | |||
| shape.m_radius = 0.5f; | |||
| body->CreateFixture(&shape, 1.0f); | |||
| bd.bullet = true; | |||
| bd.position.Set(0.0f, 10.0f); | |||
| body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&shape, 1.0f); | |||
| body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | |||
| } | |||
| #endif | |||
| } | |||
| void Launch() | |||
| { | |||
| m_body->SetTransform(b2Vec2(0.0f, 20.0f), 0.0f); | |||
| m_angularVelocity = RandomFloat(-50.0f, 50.0f); | |||
| m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); | |||
| m_body->SetAngularVelocity(m_angularVelocity); | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| if (m_stepCount == 12) | |||
| { | |||
| m_stepCount += 0; | |||
| } | |||
| Test::Step(settings); | |||
| extern int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; | |||
| if (b2_gjkCalls > 0) | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", | |||
| b2_gjkCalls, b2_gjkIters / float32(b2_gjkCalls), b2_gjkMaxIters); | |||
| m_textLine += 15; | |||
| } | |||
| extern int32 b2_toiCalls, b2_toiIters; | |||
| extern int32 b2_toiRootIters, b2_toiMaxRootIters; | |||
| if (b2_toiCalls > 0) | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", | |||
| b2_toiCalls, b2_toiIters / float32(b2_toiCalls), b2_toiMaxRootIters); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", | |||
| b2_toiRootIters / float32(b2_toiCalls), b2_toiMaxRootIters); | |||
| m_textLine += 15; | |||
| } | |||
| if (m_stepCount % 60 == 0) | |||
| { | |||
| //Launch(); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new ContinuousTest; | |||
| } | |||
| b2Body* m_body; | |||
| float32 m_angularVelocity; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,135 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef DISTANCE_TEST_H | |||
| #define DISTANCE_TEST_H | |||
| class DistanceTest : public Test | |||
| { | |||
| public: | |||
| DistanceTest() | |||
| { | |||
| { | |||
| m_transformA.SetIdentity(); | |||
| m_transformA.p.Set(0.0f, -0.2f); | |||
| m_polygonA.SetAsBox(10.0f, 0.2f); | |||
| } | |||
| { | |||
| m_positionB.Set(12.017401f, 0.13678508f); | |||
| m_angleB = -0.0109265f; | |||
| m_transformB.Set(m_positionB, m_angleB); | |||
| m_polygonB.SetAsBox(2.0f, 0.1f); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new DistanceTest; | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| b2DistanceInput input; | |||
| input.proxyA.Set(&m_polygonA, 0); | |||
| input.proxyB.Set(&m_polygonB, 0); | |||
| input.transformA = m_transformA; | |||
| input.transformB = m_transformB; | |||
| input.useRadii = true; | |||
| b2SimplexCache cache; | |||
| cache.count = 0; | |||
| b2DistanceOutput output; | |||
| b2Distance(&output, &cache, &input); | |||
| m_debugDraw.DrawString(5, m_textLine, "distance = %g", output.distance); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "iterations = %d", output.iterations); | |||
| m_textLine += 15; | |||
| { | |||
| b2Color color(0.9f, 0.9f, 0.9f); | |||
| b2Vec2 v[b2_maxPolygonVertices]; | |||
| for (int32 i = 0; i < m_polygonA.m_vertexCount; ++i) | |||
| { | |||
| v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); | |||
| } | |||
| m_debugDraw.DrawPolygon(v, m_polygonA.m_vertexCount, color); | |||
| for (int32 i = 0; i < m_polygonB.m_vertexCount; ++i) | |||
| { | |||
| v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); | |||
| } | |||
| m_debugDraw.DrawPolygon(v, m_polygonB.m_vertexCount, color); | |||
| } | |||
| b2Vec2 x1 = output.pointA; | |||
| b2Vec2 x2 = output.pointB; | |||
| b2Color c1(1.0f, 0.0f, 0.0f); | |||
| m_debugDraw.DrawPoint(x1, 4.0f, c1); | |||
| b2Color c2(1.0f, 1.0f, 0.0f); | |||
| m_debugDraw.DrawPoint(x2, 4.0f, c2); | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'a': | |||
| m_positionB.x -= 0.1f; | |||
| break; | |||
| case 'd': | |||
| m_positionB.x += 0.1f; | |||
| break; | |||
| case 's': | |||
| m_positionB.y -= 0.1f; | |||
| break; | |||
| case 'w': | |||
| m_positionB.y += 0.1f; | |||
| break; | |||
| case 'q': | |||
| m_angleB += 0.1f * b2_pi; | |||
| break; | |||
| case 'e': | |||
| m_angleB -= 0.1f * b2_pi; | |||
| break; | |||
| } | |||
| m_transformB.Set(m_positionB, m_angleB); | |||
| } | |||
| b2Vec2 m_positionB; | |||
| float32 m_angleB; | |||
| b2Transform m_transformA; | |||
| b2Transform m_transformB; | |||
| b2PolygonShape m_polygonA; | |||
| b2PolygonShape m_polygonB; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,267 @@ | |||
| /* | |||
| * Copyright (c) 2011 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef DUMP_SHELL_H | |||
| #define DUMP_SHELL_H | |||
| // This test holds worlds dumped using b2World::Dump. | |||
| class DumpShell : public Test | |||
| { | |||
| public: | |||
| DumpShell() | |||
| { | |||
| b2Vec2 g(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| m_world->SetGravity(g); | |||
| b2Body** bodies = (b2Body**)b2Alloc(3 * sizeof(b2Body*)); | |||
| b2Joint** joints = (b2Joint**)b2Alloc(2 * sizeof(b2Joint*)); | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2BodyType(2); | |||
| bd.position.Set(1.304347801208496e+01f, 2.500000000000000e+00f); | |||
| bd.angle = 0.000000000000000e+00f; | |||
| bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| bd.angularVelocity = 0.000000000000000e+00f; | |||
| bd.linearDamping = 5.000000000000000e-01f; | |||
| bd.angularDamping = 5.000000000000000e-01f; | |||
| bd.allowSleep = bool(4); | |||
| bd.awake = bool(2); | |||
| bd.fixedRotation = bool(0); | |||
| bd.bullet = bool(0); | |||
| bd.active = bool(32); | |||
| bd.gravityScale = 1.000000000000000e+00f; | |||
| bodies[0] = m_world->CreateBody(&bd); | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.friction = 1.000000000000000e+00f; | |||
| fd.restitution = 5.000000000000000e-01f; | |||
| fd.density = 1.000000000000000e+01f; | |||
| fd.isSensor = bool(0); | |||
| fd.filter.categoryBits = uint16(1); | |||
| fd.filter.maskBits = uint16(65535); | |||
| fd.filter.groupIndex = int16(0); | |||
| b2PolygonShape shape; | |||
| b2Vec2 vs[8]; | |||
| vs[0].Set(-6.900000095367432e+00f, -3.000000119209290e-01f); | |||
| vs[1].Set(2.000000029802322e-01f, -3.000000119209290e-01f); | |||
| vs[2].Set(2.000000029802322e-01f, 2.000000029802322e-01f); | |||
| vs[3].Set(-6.900000095367432e+00f, 2.000000029802322e-01f); | |||
| shape.Set(vs, 4); | |||
| fd.shape = &shape; | |||
| bodies[0]->CreateFixture(&fd); | |||
| } | |||
| } | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2BodyType(2); | |||
| bd.position.Set(8.478260636329651e-01f, 2.500000000000000e+00f); | |||
| bd.angle = 0.000000000000000e+00f; | |||
| bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| bd.angularVelocity = 0.000000000000000e+00f; | |||
| bd.linearDamping = 5.000000000000000e-01f; | |||
| bd.angularDamping = 5.000000000000000e-01f; | |||
| bd.allowSleep = bool(4); | |||
| bd.awake = bool(2); | |||
| bd.fixedRotation = bool(0); | |||
| bd.bullet = bool(0); | |||
| bd.active = bool(32); | |||
| bd.gravityScale = 1.000000000000000e+00f; | |||
| bodies[1] = m_world->CreateBody(&bd); | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.friction = 1.000000000000000e+00f; | |||
| fd.restitution = 5.000000000000000e-01f; | |||
| fd.density = 1.000000000000000e+01f; | |||
| fd.isSensor = bool(0); | |||
| fd.filter.categoryBits = uint16(1); | |||
| fd.filter.maskBits = uint16(65535); | |||
| fd.filter.groupIndex = int16(0); | |||
| b2PolygonShape shape; | |||
| b2Vec2 vs[8]; | |||
| vs[0].Set(-3.228000104427338e-01f, -2.957000136375427e-01f); | |||
| vs[1].Set(6.885900020599365e+00f, -3.641000092029572e-01f); | |||
| vs[2].Set(6.907599925994873e+00f, 3.271999955177307e-01f); | |||
| vs[3].Set(-3.228000104427338e-01f, 2.825999855995178e-01f); | |||
| shape.Set(vs, 4); | |||
| fd.shape = &shape; | |||
| bodies[1]->CreateFixture(&fd); | |||
| } | |||
| } | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2BodyType(0); | |||
| bd.position.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| bd.angle = 0.000000000000000e+00f; | |||
| bd.linearVelocity.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| bd.angularVelocity = 0.000000000000000e+00f; | |||
| bd.linearDamping = 0.000000000000000e+00f; | |||
| bd.angularDamping = 0.000000000000000e+00f; | |||
| bd.allowSleep = bool(4); | |||
| bd.awake = bool(2); | |||
| bd.fixedRotation = bool(0); | |||
| bd.bullet = bool(0); | |||
| bd.active = bool(32); | |||
| bd.gravityScale = 1.000000000000000e+00f; | |||
| bodies[2] = m_world->CreateBody(&bd); | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.friction = 1.000000000000000e+01f; | |||
| fd.restitution = 0.000000000000000e+00f; | |||
| fd.density = 0.000000000000000e+00f; | |||
| fd.isSensor = bool(0); | |||
| fd.filter.categoryBits = uint16(1); | |||
| fd.filter.maskBits = uint16(65535); | |||
| fd.filter.groupIndex = int16(0); | |||
| b2EdgeShape shape; | |||
| shape.m_radius = 9.999999776482582e-03f; | |||
| shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_vertex1.Set(4.452173995971680e+01f, 1.669565200805664e+01f); | |||
| shape.m_vertex2.Set(4.452173995971680e+01f, 0.000000000000000e+00f); | |||
| shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_hasVertex0 = bool(0); | |||
| shape.m_hasVertex3 = bool(0); | |||
| fd.shape = &shape; | |||
| bodies[2]->CreateFixture(&fd); | |||
| } | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.friction = 1.000000000000000e+01f; | |||
| fd.restitution = 0.000000000000000e+00f; | |||
| fd.density = 0.000000000000000e+00f; | |||
| fd.isSensor = bool(0); | |||
| fd.filter.categoryBits = uint16(1); | |||
| fd.filter.maskBits = uint16(65535); | |||
| fd.filter.groupIndex = int16(0); | |||
| b2EdgeShape shape; | |||
| shape.m_radius = 9.999999776482582e-03f; | |||
| shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_vertex1.Set(0.000000000000000e+00f, 1.669565200805664e+01f); | |||
| shape.m_vertex2.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_hasVertex0 = bool(0); | |||
| shape.m_hasVertex3 = bool(0); | |||
| fd.shape = &shape; | |||
| bodies[2]->CreateFixture(&fd); | |||
| } | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.friction = 1.000000000000000e+01f; | |||
| fd.restitution = 0.000000000000000e+00f; | |||
| fd.density = 0.000000000000000e+00f; | |||
| fd.isSensor = bool(0); | |||
| fd.filter.categoryBits = uint16(1); | |||
| fd.filter.maskBits = uint16(65535); | |||
| fd.filter.groupIndex = int16(0); | |||
| b2EdgeShape shape; | |||
| shape.m_radius = 9.999999776482582e-03f; | |||
| shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_vertex1.Set(0.000000000000000e+00f, 1.669565200805664e+01f); | |||
| shape.m_vertex2.Set(4.452173995971680e+01f, 1.669565200805664e+01f); | |||
| shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_hasVertex0 = bool(0); | |||
| shape.m_hasVertex3 = bool(0); | |||
| fd.shape = &shape; | |||
| bodies[2]->CreateFixture(&fd); | |||
| } | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.friction = 1.000000000000000e+01f; | |||
| fd.restitution = 0.000000000000000e+00f; | |||
| fd.density = 0.000000000000000e+00f; | |||
| fd.isSensor = bool(0); | |||
| fd.filter.categoryBits = uint16(1); | |||
| fd.filter.maskBits = uint16(65535); | |||
| fd.filter.groupIndex = int16(0); | |||
| b2EdgeShape shape; | |||
| shape.m_radius = 9.999999776482582e-03f; | |||
| shape.m_vertex0.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_vertex1.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_vertex2.Set(4.452173995971680e+01f, 0.000000000000000e+00f); | |||
| shape.m_vertex3.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| shape.m_hasVertex0 = bool(0); | |||
| shape.m_hasVertex3 = bool(0); | |||
| fd.shape = &shape; | |||
| bodies[2]->CreateFixture(&fd); | |||
| } | |||
| } | |||
| { | |||
| b2PrismaticJointDef jd; | |||
| jd.bodyA = bodies[1]; | |||
| jd.bodyB = bodies[0]; | |||
| jd.collideConnected = bool(0); | |||
| jd.localAnchorA.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| jd.localAnchorB.Set(-1.219565200805664e+01f, 0.000000000000000e+00f); | |||
| jd.localAxisA.Set(-1.219565200805664e+01f, 0.000000000000000e+00f); | |||
| jd.referenceAngle = 0.000000000000000e+00f; | |||
| jd.enableLimit = bool(1); | |||
| jd.lowerTranslation = -2.000000000000000e+01f; | |||
| jd.upperTranslation = 0.000000000000000e+00f; | |||
| jd.enableMotor = bool(1); | |||
| jd.motorSpeed = 0.000000000000000e+00f; | |||
| jd.maxMotorForce = 1.000000000000000e+01f; | |||
| joints[0] = m_world->CreateJoint(&jd); | |||
| } | |||
| { | |||
| b2RevoluteJointDef jd; | |||
| jd.bodyA = bodies[1]; | |||
| jd.bodyB = bodies[2]; | |||
| jd.collideConnected = bool(0); | |||
| jd.localAnchorA.Set(0.000000000000000e+00f, 0.000000000000000e+00f); | |||
| jd.localAnchorB.Set(8.478260636329651e-01f, 2.500000000000000e+00f); | |||
| jd.referenceAngle = 0.000000000000000e+00f; | |||
| jd.enableLimit = bool(0); | |||
| jd.lowerAngle = 0.000000000000000e+00f; | |||
| jd.upperAngle = 0.000000000000000e+00f; | |||
| jd.enableMotor = bool(0); | |||
| jd.motorSpeed = 0.000000000000000e+00f; | |||
| jd.maxMotorTorque = 0.000000000000000e+00f; | |||
| joints[1] = m_world->CreateJoint(&jd); | |||
| } | |||
| b2Free(joints); | |||
| b2Free(bodies); | |||
| joints = NULL; | |||
| bodies = NULL; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new DumpShell; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,357 @@ | |||
| /* | |||
| * Copyright (c) 2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef DYNAMIC_TREE_TEST_H | |||
| #define DYNAMIC_TREE_TEST_H | |||
| class DynamicTreeTest : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_actorCount = 128 | |||
| }; | |||
| DynamicTreeTest() | |||
| { | |||
| m_worldExtent = 15.0f; | |||
| m_proxyExtent = 0.5f; | |||
| srand(888); | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| Actor* actor = m_actors + i; | |||
| GetRandomAABB(&actor->aabb); | |||
| actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); | |||
| } | |||
| m_stepCount = 0; | |||
| float32 h = m_worldExtent; | |||
| m_queryAABB.lowerBound.Set(-3.0f, -4.0f + h); | |||
| m_queryAABB.upperBound.Set(5.0f, 6.0f + h); | |||
| m_rayCastInput.p1.Set(-5.0, 5.0f + h); | |||
| m_rayCastInput.p2.Set(7.0f, -4.0f + h); | |||
| //m_rayCastInput.p1.Set(0.0f, 2.0f + h); | |||
| //m_rayCastInput.p2.Set(0.0f, -2.0f + h); | |||
| m_rayCastInput.maxFraction = 1.0f; | |||
| m_automated = false; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new DynamicTreeTest; | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| B2_NOT_USED(settings); | |||
| m_rayActor = NULL; | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| m_actors[i].fraction = 1.0f; | |||
| m_actors[i].overlap = false; | |||
| } | |||
| if (m_automated == true) | |||
| { | |||
| int32 actionCount = b2Max(1, e_actorCount >> 2); | |||
| for (int32 i = 0; i < actionCount; ++i) | |||
| { | |||
| Action(); | |||
| } | |||
| } | |||
| Query(); | |||
| RayCast(); | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| Actor* actor = m_actors + i; | |||
| if (actor->proxyId == b2_nullNode) | |||
| continue; | |||
| b2Color c(0.9f, 0.9f, 0.9f); | |||
| if (actor == m_rayActor && actor->overlap) | |||
| { | |||
| c.Set(0.9f, 0.6f, 0.6f); | |||
| } | |||
| else if (actor == m_rayActor) | |||
| { | |||
| c.Set(0.6f, 0.9f, 0.6f); | |||
| } | |||
| else if (actor->overlap) | |||
| { | |||
| c.Set(0.6f, 0.6f, 0.9f); | |||
| } | |||
| m_debugDraw.DrawAABB(&actor->aabb, c); | |||
| } | |||
| b2Color c(0.7f, 0.7f, 0.7f); | |||
| m_debugDraw.DrawAABB(&m_queryAABB, c); | |||
| m_debugDraw.DrawSegment(m_rayCastInput.p1, m_rayCastInput.p2, c); | |||
| b2Color c1(0.2f, 0.9f, 0.2f); | |||
| b2Color c2(0.9f, 0.2f, 0.2f); | |||
| m_debugDraw.DrawPoint(m_rayCastInput.p1, 6.0f, c1); | |||
| m_debugDraw.DrawPoint(m_rayCastInput.p2, 6.0f, c2); | |||
| if (m_rayActor) | |||
| { | |||
| b2Color cr(0.2f, 0.2f, 0.9f); | |||
| b2Vec2 p = m_rayCastInput.p1 + m_rayActor->fraction * (m_rayCastInput.p2 - m_rayCastInput.p1); | |||
| m_debugDraw.DrawPoint(p, 6.0f, cr); | |||
| } | |||
| { | |||
| int32 height = m_tree.GetHeight(); | |||
| m_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d", height); | |||
| m_textLine += 15; | |||
| } | |||
| ++m_stepCount; | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'a': | |||
| m_automated = !m_automated; | |||
| break; | |||
| case 'c': | |||
| CreateProxy(); | |||
| break; | |||
| case 'd': | |||
| DestroyProxy(); | |||
| break; | |||
| case 'm': | |||
| MoveProxy(); | |||
| break; | |||
| } | |||
| } | |||
| bool QueryCallback(int32 proxyId) | |||
| { | |||
| Actor* actor = (Actor*)m_tree.GetUserData(proxyId); | |||
| actor->overlap = b2TestOverlap(m_queryAABB, actor->aabb); | |||
| return true; | |||
| } | |||
| float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId) | |||
| { | |||
| Actor* actor = (Actor*)m_tree.GetUserData(proxyId); | |||
| b2RayCastOutput output; | |||
| bool hit = actor->aabb.RayCast(&output, input); | |||
| if (hit) | |||
| { | |||
| m_rayCastOutput = output; | |||
| m_rayActor = actor; | |||
| m_rayActor->fraction = output.fraction; | |||
| return output.fraction; | |||
| } | |||
| return input.maxFraction; | |||
| } | |||
| private: | |||
| struct Actor | |||
| { | |||
| b2AABB aabb; | |||
| float32 fraction; | |||
| bool overlap; | |||
| int32 proxyId; | |||
| }; | |||
| void GetRandomAABB(b2AABB* aabb) | |||
| { | |||
| b2Vec2 w; w.Set(2.0f * m_proxyExtent, 2.0f * m_proxyExtent); | |||
| //aabb->lowerBound.x = -m_proxyExtent; | |||
| //aabb->lowerBound.y = -m_proxyExtent + m_worldExtent; | |||
| aabb->lowerBound.x = RandomFloat(-m_worldExtent, m_worldExtent); | |||
| aabb->lowerBound.y = RandomFloat(0.0f, 2.0f * m_worldExtent); | |||
| aabb->upperBound = aabb->lowerBound + w; | |||
| } | |||
| void MoveAABB(b2AABB* aabb) | |||
| { | |||
| b2Vec2 d; | |||
| d.x = RandomFloat(-0.5f, 0.5f); | |||
| d.y = RandomFloat(-0.5f, 0.5f); | |||
| //d.x = 2.0f; | |||
| //d.y = 0.0f; | |||
| aabb->lowerBound += d; | |||
| aabb->upperBound += d; | |||
| b2Vec2 c0 = 0.5f * (aabb->lowerBound + aabb->upperBound); | |||
| b2Vec2 min; min.Set(-m_worldExtent, 0.0f); | |||
| b2Vec2 max; max.Set(m_worldExtent, 2.0f * m_worldExtent); | |||
| b2Vec2 c = b2Clamp(c0, min, max); | |||
| aabb->lowerBound += c - c0; | |||
| aabb->upperBound += c - c0; | |||
| } | |||
| void CreateProxy() | |||
| { | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| int32 j = rand() % e_actorCount; | |||
| Actor* actor = m_actors + j; | |||
| if (actor->proxyId == b2_nullNode) | |||
| { | |||
| GetRandomAABB(&actor->aabb); | |||
| actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| void DestroyProxy() | |||
| { | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| int32 j = rand() % e_actorCount; | |||
| Actor* actor = m_actors + j; | |||
| if (actor->proxyId != b2_nullNode) | |||
| { | |||
| m_tree.DestroyProxy(actor->proxyId); | |||
| actor->proxyId = b2_nullNode; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| void MoveProxy() | |||
| { | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| int32 j = rand() % e_actorCount; | |||
| Actor* actor = m_actors + j; | |||
| if (actor->proxyId == b2_nullNode) | |||
| { | |||
| continue; | |||
| } | |||
| b2AABB aabb0 = actor->aabb; | |||
| MoveAABB(&actor->aabb); | |||
| b2Vec2 displacement = actor->aabb.GetCenter() - aabb0.GetCenter(); | |||
| m_tree.MoveProxy(actor->proxyId, actor->aabb, displacement); | |||
| return; | |||
| } | |||
| } | |||
| void Action() | |||
| { | |||
| int32 choice = rand() % 20; | |||
| switch (choice) | |||
| { | |||
| case 0: | |||
| CreateProxy(); | |||
| break; | |||
| case 1: | |||
| DestroyProxy(); | |||
| break; | |||
| default: | |||
| MoveProxy(); | |||
| } | |||
| } | |||
| void Query() | |||
| { | |||
| m_tree.Query(this, m_queryAABB); | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| if (m_actors[i].proxyId == b2_nullNode) | |||
| { | |||
| continue; | |||
| } | |||
| bool overlap = b2TestOverlap(m_queryAABB, m_actors[i].aabb); | |||
| B2_NOT_USED(overlap); | |||
| b2Assert(overlap == m_actors[i].overlap); | |||
| } | |||
| } | |||
| void RayCast() | |||
| { | |||
| m_rayActor = NULL; | |||
| b2RayCastInput input = m_rayCastInput; | |||
| // Ray cast against the dynamic tree. | |||
| m_tree.RayCast(this, input); | |||
| // Brute force ray cast. | |||
| Actor* bruteActor = NULL; | |||
| b2RayCastOutput bruteOutput; | |||
| for (int32 i = 0; i < e_actorCount; ++i) | |||
| { | |||
| if (m_actors[i].proxyId == b2_nullNode) | |||
| { | |||
| continue; | |||
| } | |||
| b2RayCastOutput output; | |||
| bool hit = m_actors[i].aabb.RayCast(&output, input); | |||
| if (hit) | |||
| { | |||
| bruteActor = m_actors + i; | |||
| bruteOutput = output; | |||
| input.maxFraction = output.fraction; | |||
| } | |||
| } | |||
| if (bruteActor != NULL) | |||
| { | |||
| b2Assert(bruteOutput.fraction == m_rayCastOutput.fraction); | |||
| } | |||
| } | |||
| float32 m_worldExtent; | |||
| float32 m_proxyExtent; | |||
| b2DynamicTree m_tree; | |||
| b2AABB m_queryAABB; | |||
| b2RayCastInput m_rayCastInput; | |||
| b2RayCastOutput m_rayCastOutput; | |||
| Actor* m_rayActor; | |||
| Actor m_actors[e_actorCount]; | |||
| int32 m_stepCount; | |||
| bool m_automated; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,249 @@ | |||
| /* | |||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef EDGE_SHAPES_H | |||
| #define EDGE_SHAPES_H | |||
| class EdgeShapesCallback : public b2RayCastCallback | |||
| { | |||
| public: | |||
| EdgeShapesCallback() | |||
| { | |||
| m_fixture = NULL; | |||
| } | |||
| float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point, | |||
| const b2Vec2& normal, float32 fraction) | |||
| { | |||
| m_fixture = fixture; | |||
| m_point = point; | |||
| m_normal = normal; | |||
| return fraction; | |||
| } | |||
| b2Fixture* m_fixture; | |||
| b2Vec2 m_point; | |||
| b2Vec2 m_normal; | |||
| }; | |||
| class EdgeShapes : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_maxBodies = 256 | |||
| }; | |||
| EdgeShapes() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| float32 x1 = -20.0f; | |||
| float32 y1 = 2.0f * cosf(x1 / 10.0f * b2_pi); | |||
| for (int32 i = 0; i < 80; ++i) | |||
| { | |||
| float32 x2 = x1 + 0.5f; | |||
| float32 y2 = 2.0f * cosf(x2 / 10.0f * b2_pi); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(x1, y1), b2Vec2(x2, y2)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| x1 = x2; | |||
| y1 = y2; | |||
| } | |||
| } | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.5f, 0.0f); | |||
| vertices[1].Set(0.5f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| m_polygons[0].Set(vertices, 3); | |||
| } | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.1f, 0.0f); | |||
| vertices[1].Set(0.1f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| m_polygons[1].Set(vertices, 3); | |||
| } | |||
| { | |||
| float32 w = 1.0f; | |||
| float32 b = w / (2.0f + b2Sqrt(2.0f)); | |||
| float32 s = b2Sqrt(2.0f) * b; | |||
| b2Vec2 vertices[8]; | |||
| vertices[0].Set(0.5f * s, 0.0f); | |||
| vertices[1].Set(0.5f * w, b); | |||
| vertices[2].Set(0.5f * w, b + s); | |||
| vertices[3].Set(0.5f * s, w); | |||
| vertices[4].Set(-0.5f * s, w); | |||
| vertices[5].Set(-0.5f * w, b + s); | |||
| vertices[6].Set(-0.5f * w, b); | |||
| vertices[7].Set(-0.5f * s, 0.0f); | |||
| m_polygons[2].Set(vertices, 8); | |||
| } | |||
| { | |||
| m_polygons[3].SetAsBox(0.5f, 0.5f); | |||
| } | |||
| { | |||
| m_circle.m_radius = 0.5f; | |||
| } | |||
| m_bodyIndex = 0; | |||
| memset(m_bodies, 0, sizeof(m_bodies)); | |||
| m_angle = 0.0f; | |||
| } | |||
| void Create(int32 index) | |||
| { | |||
| if (m_bodies[m_bodyIndex] != NULL) | |||
| { | |||
| m_world->DestroyBody(m_bodies[m_bodyIndex]); | |||
| m_bodies[m_bodyIndex] = NULL; | |||
| } | |||
| b2BodyDef bd; | |||
| float32 x = RandomFloat(-10.0f, 10.0f); | |||
| float32 y = RandomFloat(10.0f, 20.0f); | |||
| bd.position.Set(x, y); | |||
| bd.angle = RandomFloat(-b2_pi, b2_pi); | |||
| bd.type = b2_dynamicBody; | |||
| if (index == 4) | |||
| { | |||
| bd.angularDamping = 0.02f; | |||
| } | |||
| m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | |||
| if (index < 4) | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.shape = m_polygons + index; | |||
| fd.friction = 0.3f; | |||
| fd.density = 20.0f; | |||
| m_bodies[m_bodyIndex]->CreateFixture(&fd); | |||
| } | |||
| else | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.shape = &m_circle; | |||
| fd.friction = 0.3f; | |||
| fd.density = 20.0f; | |||
| m_bodies[m_bodyIndex]->CreateFixture(&fd); | |||
| } | |||
| m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; | |||
| } | |||
| void DestroyBody() | |||
| { | |||
| for (int32 i = 0; i < e_maxBodies; ++i) | |||
| { | |||
| if (m_bodies[i] != NULL) | |||
| { | |||
| m_world->DestroyBody(m_bodies[i]); | |||
| m_bodies[i] = NULL; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case '1': | |||
| case '2': | |||
| case '3': | |||
| case '4': | |||
| case '5': | |||
| Create(key - '1'); | |||
| break; | |||
| case 'd': | |||
| DestroyBody(); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| bool advanceRay = settings->pause == 0 || settings->singleStep; | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff"); | |||
| m_textLine += 15; | |||
| float32 L = 25.0f; | |||
| b2Vec2 point1(0.0f, 10.0f); | |||
| b2Vec2 d(L * cosf(m_angle), -L * b2Abs(sinf(m_angle))); | |||
| b2Vec2 point2 = point1 + d; | |||
| EdgeShapesCallback callback; | |||
| m_world->RayCast(&callback, point1, point2); | |||
| if (callback.m_fixture) | |||
| { | |||
| m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | |||
| m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | |||
| b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | |||
| m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | |||
| } | |||
| else | |||
| { | |||
| m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | |||
| } | |||
| if (advanceRay) | |||
| { | |||
| m_angle += 0.25f * b2_pi / 180.0f; | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new EdgeShapes; | |||
| } | |||
| int32 m_bodyIndex; | |||
| b2Body* m_bodies[e_maxBodies]; | |||
| b2PolygonShape m_polygons[4]; | |||
| b2CircleShape m_circle; | |||
| float32 m_angle; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,109 @@ | |||
| /* | |||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef EDGE_TEST_H | |||
| #define EDGE_TEST_H | |||
| class EdgeTest : public Test | |||
| { | |||
| public: | |||
| EdgeTest() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2Vec2 v1(-10.0f, 0.0f), v2(-7.0f, -2.0f), v3(-4.0f, 0.0f); | |||
| b2Vec2 v4(0.0f, 0.0f), v5(4.0f, 0.0f), v6(7.0f, 2.0f), v7(10.0f, 0.0f); | |||
| b2EdgeShape shape; | |||
| shape.Set(v1, v2); | |||
| shape.m_hasVertex3 = true; | |||
| shape.m_vertex3 = v3; | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(v2, v3); | |||
| shape.m_hasVertex0 = true; | |||
| shape.m_hasVertex3 = true; | |||
| shape.m_vertex0 = v1; | |||
| shape.m_vertex3 = v4; | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(v3, v4); | |||
| shape.m_hasVertex0 = true; | |||
| shape.m_hasVertex3 = true; | |||
| shape.m_vertex0 = v2; | |||
| shape.m_vertex3 = v5; | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(v4, v5); | |||
| shape.m_hasVertex0 = true; | |||
| shape.m_hasVertex3 = true; | |||
| shape.m_vertex0 = v3; | |||
| shape.m_vertex3 = v6; | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(v5, v6); | |||
| shape.m_hasVertex0 = true; | |||
| shape.m_hasVertex3 = true; | |||
| shape.m_vertex0 = v4; | |||
| shape.m_vertex3 = v7; | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| shape.Set(v6, v7); | |||
| shape.m_hasVertex0 = true; | |||
| shape.m_vertex0 = v5; | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-0.5f, 0.6f); | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.5f; | |||
| body->CreateFixture(&shape, 1.0f); | |||
| } | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(1.0f, 0.6f); | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.5f); | |||
| body->CreateFixture(&shape, 1.0f); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new EdgeTest; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,187 @@ | |||
| /* | |||
| * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef GEARS_H | |||
| #define GEARS_H | |||
| class Gears : public Test | |||
| { | |||
| public: | |||
| Gears() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Gears co | |||
| { | |||
| b2CircleShape circle1; | |||
| circle1.m_radius = 1.0f; | |||
| b2PolygonShape box; | |||
| box.SetAsBox(0.5f, 5.0f); | |||
| b2CircleShape circle2; | |||
| circle2.m_radius = 2.0f; | |||
| b2BodyDef bd1; | |||
| bd1.type = b2_staticBody; | |||
| bd1.position.Set(10.0f, 9.0f); | |||
| b2Body* body1 = m_world->CreateBody(&bd1); | |||
| body1->CreateFixture(&circle1, 0.0f); | |||
| b2BodyDef bd2; | |||
| bd2.type = b2_dynamicBody; | |||
| bd2.position.Set(10.0f, 8.0f); | |||
| b2Body* body2 = m_world->CreateBody(&bd2); | |||
| body2->CreateFixture(&box, 5.0f); | |||
| b2BodyDef bd3; | |||
| bd3.type = b2_dynamicBody; | |||
| bd3.position.Set(10.0f, 6.0f); | |||
| b2Body* body3 = m_world->CreateBody(&bd3); | |||
| body3->CreateFixture(&circle2, 5.0f); | |||
| b2RevoluteJointDef jd1; | |||
| jd1.Initialize(body2, body1, bd1.position); | |||
| b2Joint* joint1 = m_world->CreateJoint(&jd1); | |||
| b2RevoluteJointDef jd2; | |||
| jd2.Initialize(body2, body3, bd3.position); | |||
| b2Joint* joint2 = m_world->CreateJoint(&jd2); | |||
| b2GearJointDef jd4; | |||
| jd4.bodyA = body1; | |||
| jd4.bodyB = body3; | |||
| jd4.joint1 = joint1; | |||
| jd4.joint2 = joint2; | |||
| jd4.ratio = circle2.m_radius / circle1.m_radius; | |||
| m_world->CreateJoint(&jd4); | |||
| } | |||
| { | |||
| b2CircleShape circle1; | |||
| circle1.m_radius = 1.0f; | |||
| b2CircleShape circle2; | |||
| circle2.m_radius = 2.0f; | |||
| b2PolygonShape box; | |||
| box.SetAsBox(0.5f, 5.0f); | |||
| b2BodyDef bd1; | |||
| bd1.type = b2_dynamicBody; | |||
| bd1.position.Set(-3.0f, 12.0f); | |||
| b2Body* body1 = m_world->CreateBody(&bd1); | |||
| body1->CreateFixture(&circle1, 5.0f); | |||
| b2RevoluteJointDef jd1; | |||
| jd1.bodyA = ground; | |||
| jd1.bodyB = body1; | |||
| jd1.localAnchorA = ground->GetLocalPoint(bd1.position); | |||
| jd1.localAnchorB = body1->GetLocalPoint(bd1.position); | |||
| jd1.referenceAngle = body1->GetAngle() - ground->GetAngle(); | |||
| m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd1); | |||
| b2BodyDef bd2; | |||
| bd2.type = b2_dynamicBody; | |||
| bd2.position.Set(0.0f, 12.0f); | |||
| b2Body* body2 = m_world->CreateBody(&bd2); | |||
| body2->CreateFixture(&circle2, 5.0f); | |||
| b2RevoluteJointDef jd2; | |||
| jd2.Initialize(ground, body2, bd2.position); | |||
| m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd2); | |||
| b2BodyDef bd3; | |||
| bd3.type = b2_dynamicBody; | |||
| bd3.position.Set(2.5f, 12.0f); | |||
| b2Body* body3 = m_world->CreateBody(&bd3); | |||
| body3->CreateFixture(&box, 5.0f); | |||
| b2PrismaticJointDef jd3; | |||
| jd3.Initialize(ground, body3, bd3.position, b2Vec2(0.0f, 1.0f)); | |||
| jd3.lowerTranslation = -5.0f; | |||
| jd3.upperTranslation = 5.0f; | |||
| jd3.enableLimit = true; | |||
| m_joint3 = (b2PrismaticJoint*)m_world->CreateJoint(&jd3); | |||
| b2GearJointDef jd4; | |||
| jd4.bodyA = body1; | |||
| jd4.bodyB = body2; | |||
| jd4.joint1 = m_joint1; | |||
| jd4.joint2 = m_joint2; | |||
| jd4.ratio = circle2.m_radius / circle1.m_radius; | |||
| m_joint4 = (b2GearJoint*)m_world->CreateJoint(&jd4); | |||
| b2GearJointDef jd5; | |||
| jd5.bodyA = body2; | |||
| jd5.bodyB = body3; | |||
| jd5.joint1 = m_joint2; | |||
| jd5.joint2 = m_joint3; | |||
| jd5.ratio = -1.0f / circle2.m_radius; | |||
| m_joint5 = (b2GearJoint*)m_world->CreateJoint(&jd5); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 0: | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| float32 ratio, value; | |||
| ratio = m_joint4->GetRatio(); | |||
| value = m_joint1->GetJointAngle() + ratio * m_joint2->GetJointAngle(); | |||
| m_debugDraw.DrawString(5, m_textLine, "theta1 + %4.2f * theta2 = %4.2f", (float) ratio, (float) value); | |||
| m_textLine += 15; | |||
| ratio = m_joint5->GetRatio(); | |||
| value = m_joint2->GetJointAngle() + ratio * m_joint3->GetJointTranslation(); | |||
| m_debugDraw.DrawString(5, m_textLine, "theta2 + %4.2f * delta = %4.2f", (float) ratio, (float) value); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Gears; | |||
| } | |||
| b2RevoluteJoint* m_joint1; | |||
| b2RevoluteJoint* m_joint2; | |||
| b2PrismaticJoint* m_joint3; | |||
| b2GearJoint* m_joint4; | |||
| b2GearJoint* m_joint5; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,120 @@ | |||
| /* | |||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef ONE_SIDED_PLATFORM_H | |||
| #define ONE_SIDED_PLATFORM_H | |||
| class OneSidedPlatform : public Test | |||
| { | |||
| public: | |||
| enum State | |||
| { | |||
| e_unknown, | |||
| e_above, | |||
| e_below | |||
| }; | |||
| OneSidedPlatform() | |||
| { | |||
| // Ground | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| // Platform | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(0.0f, 10.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(3.0f, 0.5f); | |||
| m_platform = body->CreateFixture(&shape, 0.0f); | |||
| m_bottom = 10.0f - 0.5f; | |||
| m_top = 10.0f + 0.5f; | |||
| } | |||
| // Actor | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.0f, 12.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| m_radius = 0.5f; | |||
| b2CircleShape shape; | |||
| shape.m_radius = m_radius; | |||
| m_character = body->CreateFixture(&shape, 20.0f); | |||
| body->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); | |||
| m_state = e_unknown; | |||
| } | |||
| } | |||
| void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) | |||
| { | |||
| Test::PreSolve(contact, oldManifold); | |||
| b2Fixture* fixtureA = contact->GetFixtureA(); | |||
| b2Fixture* fixtureB = contact->GetFixtureB(); | |||
| if (fixtureA != m_platform && fixtureA != m_character) | |||
| { | |||
| return; | |||
| } | |||
| if (fixtureB != m_platform && fixtureB != m_character) | |||
| { | |||
| return; | |||
| } | |||
| b2Vec2 position = m_character->GetBody()->GetPosition(); | |||
| if (position.y < m_top + m_radius - 3.0f * b2_linearSlop) | |||
| { | |||
| contact->SetEnabled(false); | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape."); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new OneSidedPlatform; | |||
| } | |||
| float32 m_radius, m_top, m_bottom; | |||
| State m_state; | |||
| b2Fixture* m_platform; | |||
| b2Fixture* m_character; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,169 @@ | |||
| /* | |||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef PINBALL_H | |||
| #define PINBALL_H | |||
| /// This tests bullet collision and provides an example of a gameplay scenario. | |||
| /// This also uses a loop shape. | |||
| class Pinball : public Test | |||
| { | |||
| public: | |||
| Pinball() | |||
| { | |||
| // Ground body | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2Vec2 vs[5]; | |||
| vs[0].Set(0.0f, -2.0f); | |||
| vs[1].Set(8.0f, 6.0f); | |||
| vs[2].Set(8.0f, 20.0f); | |||
| vs[3].Set(-8.0f, 20.0f); | |||
| vs[4].Set(-8.0f, 6.0f); | |||
| b2ChainShape loop; | |||
| loop.CreateLoop(vs, 5); | |||
| b2FixtureDef fd; | |||
| fd.shape = &loop; | |||
| fd.density = 0.0f; | |||
| ground->CreateFixture(&fd); | |||
| } | |||
| // Flippers | |||
| { | |||
| b2Vec2 p1(-2.0f, 0.0f), p2(2.0f, 0.0f); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position = p1; | |||
| b2Body* leftFlipper = m_world->CreateBody(&bd); | |||
| bd.position = p2; | |||
| b2Body* rightFlipper = m_world->CreateBody(&bd); | |||
| b2PolygonShape box; | |||
| box.SetAsBox(1.75f, 0.1f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &box; | |||
| fd.density = 1.0f; | |||
| leftFlipper->CreateFixture(&fd); | |||
| rightFlipper->CreateFixture(&fd); | |||
| b2RevoluteJointDef jd; | |||
| jd.bodyA = ground; | |||
| jd.localAnchorB.SetZero(); | |||
| jd.enableMotor = true; | |||
| jd.maxMotorTorque = 1000.0f; | |||
| jd.enableLimit = true; | |||
| jd.motorSpeed = 0.0f; | |||
| jd.localAnchorA = p1; | |||
| jd.bodyB = leftFlipper; | |||
| jd.lowerAngle = -30.0f * b2_pi / 180.0f; | |||
| jd.upperAngle = 5.0f * b2_pi / 180.0f; | |||
| m_leftJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | |||
| jd.motorSpeed = 0.0f; | |||
| jd.localAnchorA = p2; | |||
| jd.bodyB = rightFlipper; | |||
| jd.lowerAngle = -5.0f * b2_pi / 180.0f; | |||
| jd.upperAngle = 30.0f * b2_pi / 180.0f; | |||
| m_rightJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); | |||
| } | |||
| // Circle character | |||
| { | |||
| b2BodyDef bd; | |||
| bd.position.Set(1.0f, 15.0f); | |||
| bd.type = b2_dynamicBody; | |||
| bd.bullet = true; | |||
| m_ball = m_world->CreateBody(&bd); | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.2f; | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 1.0f; | |||
| m_ball->CreateFixture(&fd); | |||
| } | |||
| m_button = false; | |||
| } | |||
| void Step() | |||
| { | |||
| if (m_button) | |||
| { | |||
| m_leftJoint->SetMotorSpeed(20.0f); | |||
| m_rightJoint->SetMotorSpeed(-20.0f); | |||
| } | |||
| else | |||
| { | |||
| m_leftJoint->SetMotorSpeed(-10.0f); | |||
| m_rightJoint->SetMotorSpeed(10.0f); | |||
| } | |||
| // Test::Step(settings); | |||
| // | |||
| // m_debugDraw.DrawString(5, m_textLine, "Press 'a' to control the flippers"); | |||
| // m_textLine += 15; | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'a': | |||
| case 'A': | |||
| m_button = true; | |||
| break; | |||
| } | |||
| } | |||
| void KeyboardUp(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'a': | |||
| case 'A': | |||
| m_button = false; | |||
| break; | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Pinball; | |||
| } | |||
| b2RevoluteJoint* m_leftJoint; | |||
| b2RevoluteJoint* m_rightJoint; | |||
| b2Body* m_ball; | |||
| bool m_button; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,122 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef POLYCOLLISION_H | |||
| #define POLYCOLLISION_H | |||
| class PolyCollision : public Test | |||
| { | |||
| public: | |||
| PolyCollision() | |||
| { | |||
| { | |||
| m_polygonA.SetAsBox(0.2f, 0.4f); | |||
| m_transformA.Set(b2Vec2(0.0f, 0.0f), 0.0f); | |||
| } | |||
| { | |||
| m_polygonB.SetAsBox(0.5f, 0.5f); | |||
| m_positionB.Set(19.345284f, 1.5632932f); | |||
| m_angleB = 1.9160721f; | |||
| m_transformB.Set(m_positionB, m_angleB); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new PolyCollision; | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| B2_NOT_USED(settings); | |||
| b2Manifold manifold; | |||
| b2CollidePolygons(&manifold, &m_polygonA, m_transformA, &m_polygonB, m_transformB); | |||
| b2WorldManifold worldManifold; | |||
| worldManifold.Initialize(&manifold, m_transformA, m_polygonA.m_radius, m_transformB, m_polygonB.m_radius); | |||
| m_debugDraw.DrawString(5, m_textLine, "point count = %d", manifold.pointCount); | |||
| m_textLine += 15; | |||
| { | |||
| b2Color color(0.9f, 0.9f, 0.9f); | |||
| b2Vec2 v[b2_maxPolygonVertices]; | |||
| for (int32 i = 0; i < m_polygonA.m_vertexCount; ++i) | |||
| { | |||
| v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); | |||
| } | |||
| m_debugDraw.DrawPolygon(v, m_polygonA.m_vertexCount, color); | |||
| for (int32 i = 0; i < m_polygonB.m_vertexCount; ++i) | |||
| { | |||
| v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); | |||
| } | |||
| m_debugDraw.DrawPolygon(v, m_polygonB.m_vertexCount, color); | |||
| } | |||
| for (int32 i = 0; i < manifold.pointCount; ++i) | |||
| { | |||
| m_debugDraw.DrawPoint(worldManifold.points[i], 4.0f, b2Color(0.9f, 0.3f, 0.3f)); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'a': | |||
| m_positionB.x -= 0.1f; | |||
| break; | |||
| case 'd': | |||
| m_positionB.x += 0.1f; | |||
| break; | |||
| case 's': | |||
| m_positionB.y -= 0.1f; | |||
| break; | |||
| case 'w': | |||
| m_positionB.y += 0.1f; | |||
| break; | |||
| case 'q': | |||
| m_angleB += 0.1f * b2_pi; | |||
| break; | |||
| case 'e': | |||
| m_angleB -= 0.1f * b2_pi; | |||
| break; | |||
| } | |||
| m_transformB.Set(m_positionB, m_angleB); | |||
| } | |||
| b2PolygonShape m_polygonA; | |||
| b2PolygonShape m_polygonB; | |||
| b2Transform m_transformA; | |||
| b2Transform m_transformB; | |||
| b2Vec2 m_positionB; | |||
| float32 m_angleB; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,295 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef POLY_SHAPES_H | |||
| #define POLY_SHAPES_H | |||
| /// This tests stacking. It also shows how to use b2World::Query | |||
| /// and b2TestOverlap. | |||
| const int32 k_maxBodies = 256; | |||
| /// This callback is called by b2World::QueryAABB. We find all the fixtures | |||
| /// that overlap an AABB. Of those, we use b2TestOverlap to determine which fixtures | |||
| /// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border. | |||
| class PolyShapesCallback : public b2QueryCallback | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_maxCount = 4 | |||
| }; | |||
| PolyShapesCallback() | |||
| { | |||
| m_count = 0; | |||
| } | |||
| void DrawFixture(b2Fixture* fixture) | |||
| { | |||
| b2Color color(0.95f, 0.95f, 0.6f); | |||
| const b2Transform& xf = fixture->GetBody()->GetTransform(); | |||
| switch (fixture->GetType()) | |||
| { | |||
| case b2Shape::e_circle: | |||
| { | |||
| b2CircleShape* circle = (b2CircleShape*)fixture->GetShape(); | |||
| b2Vec2 center = b2Mul(xf, circle->m_p); | |||
| float32 radius = circle->m_radius; | |||
| m_debugDraw->DrawCircle(center, radius, color); | |||
| } | |||
| break; | |||
| case b2Shape::e_polygon: | |||
| { | |||
| b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape(); | |||
| int32 vertexCount = poly->m_vertexCount; | |||
| b2Assert(vertexCount <= b2_maxPolygonVertices); | |||
| b2Vec2 vertices[b2_maxPolygonVertices]; | |||
| for (int32 i = 0; i < vertexCount; ++i) | |||
| { | |||
| vertices[i] = b2Mul(xf, poly->m_vertices[i]); | |||
| } | |||
| m_debugDraw->DrawPolygon(vertices, vertexCount, color); | |||
| } | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| /// Called for each fixture found in the query AABB. | |||
| /// @return false to terminate the query. | |||
| bool ReportFixture(b2Fixture* fixture) | |||
| { | |||
| if (m_count == e_maxCount) | |||
| { | |||
| return false; | |||
| } | |||
| b2Body* body = fixture->GetBody(); | |||
| b2Shape* shape = fixture->GetShape(); | |||
| bool overlap = b2TestOverlap(shape, 0, &m_circle, 0, body->GetTransform(), m_transform); | |||
| if (overlap) | |||
| { | |||
| DrawFixture(fixture); | |||
| ++m_count; | |||
| } | |||
| return true; | |||
| } | |||
| b2CircleShape m_circle; | |||
| b2Transform m_transform; | |||
| b2Draw* m_debugDraw; | |||
| int32 m_count; | |||
| }; | |||
| class PolyShapes : public Test | |||
| { | |||
| public: | |||
| PolyShapes() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.5f, 0.0f); | |||
| vertices[1].Set(0.5f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| m_polygons[0].Set(vertices, 3); | |||
| } | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.1f, 0.0f); | |||
| vertices[1].Set(0.1f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| m_polygons[1].Set(vertices, 3); | |||
| } | |||
| { | |||
| float32 w = 1.0f; | |||
| float32 b = w / (2.0f + b2Sqrt(2.0f)); | |||
| float32 s = b2Sqrt(2.0f) * b; | |||
| b2Vec2 vertices[8]; | |||
| vertices[0].Set(0.5f * s, 0.0f); | |||
| vertices[1].Set(0.5f * w, b); | |||
| vertices[2].Set(0.5f * w, b + s); | |||
| vertices[3].Set(0.5f * s, w); | |||
| vertices[4].Set(-0.5f * s, w); | |||
| vertices[5].Set(-0.5f * w, b + s); | |||
| vertices[6].Set(-0.5f * w, b); | |||
| vertices[7].Set(-0.5f * s, 0.0f); | |||
| m_polygons[2].Set(vertices, 8); | |||
| } | |||
| { | |||
| m_polygons[3].SetAsBox(0.5f, 0.5f); | |||
| } | |||
| { | |||
| m_circle.m_radius = 0.5f; | |||
| } | |||
| m_bodyIndex = 0; | |||
| memset(m_bodies, 0, sizeof(m_bodies)); | |||
| } | |||
| void Create(int32 index) | |||
| { | |||
| if (m_bodies[m_bodyIndex] != NULL) | |||
| { | |||
| m_world->DestroyBody(m_bodies[m_bodyIndex]); | |||
| m_bodies[m_bodyIndex] = NULL; | |||
| } | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| float32 x = RandomFloat(-2.0f, 2.0f); | |||
| bd.position.Set(x, 10.0f); | |||
| bd.angle = RandomFloat(-b2_pi, b2_pi); | |||
| if (index == 4) | |||
| { | |||
| bd.angularDamping = 0.02f; | |||
| } | |||
| m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | |||
| if (index < 4) | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.shape = m_polygons + index; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.3f; | |||
| m_bodies[m_bodyIndex]->CreateFixture(&fd); | |||
| } | |||
| else | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.shape = &m_circle; | |||
| fd.density = 1.0f; | |||
| fd.friction = 0.3f; | |||
| m_bodies[m_bodyIndex]->CreateFixture(&fd); | |||
| } | |||
| m_bodyIndex = (m_bodyIndex + 1) % k_maxBodies; | |||
| } | |||
| void DestroyBody() | |||
| { | |||
| for (int32 i = 0; i < k_maxBodies; ++i) | |||
| { | |||
| if (m_bodies[i] != NULL) | |||
| { | |||
| m_world->DestroyBody(m_bodies[i]); | |||
| m_bodies[i] = NULL; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case '1': | |||
| case '2': | |||
| case '3': | |||
| case '4': | |||
| case '5': | |||
| Create(key - '1'); | |||
| break; | |||
| case 'a': | |||
| for (int32 i = 0; i < k_maxBodies; i += 2) | |||
| { | |||
| if (m_bodies[i]) | |||
| { | |||
| bool active = m_bodies[i]->IsActive(); | |||
| m_bodies[i]->SetActive(!active); | |||
| } | |||
| } | |||
| break; | |||
| case 'd': | |||
| DestroyBody(); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| PolyShapesCallback callback; | |||
| callback.m_circle.m_radius = 2.0f; | |||
| callback.m_circle.m_p.Set(0.0f, 1.1f); | |||
| callback.m_transform.SetIdentity(); | |||
| callback.m_debugDraw = &m_debugDraw; | |||
| b2AABB aabb; | |||
| callback.m_circle.ComputeAABB(&aabb, callback.m_transform, 0); | |||
| m_world->QueryAABB(&callback, aabb); | |||
| b2Color color(0.4f, 0.7f, 0.8f); | |||
| m_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color); | |||
| m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff"); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "Press 'a' to (de)activate some bodies"); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "Press 'd' to destroy a body"); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new PolyShapes; | |||
| } | |||
| int32 m_bodyIndex; | |||
| b2Body* m_bodies[k_maxBodies]; | |||
| b2PolygonShape m_polygons[4]; | |||
| b2CircleShape m_circle; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,107 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef PRISMATIC_H | |||
| #define PRISMATIC_H | |||
| // The motor in this test gets smoother with higher velocity iterations. | |||
| class Prismatic : public Test | |||
| { | |||
| public: | |||
| Prismatic() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(2.0f, 0.5f); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-10.0f, 10.0f); | |||
| bd.angle = 0.5f * b2_pi; | |||
| bd.allowSleep = false; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&shape, 5.0f); | |||
| b2PrismaticJointDef pjd; | |||
| // Bouncy limit | |||
| b2Vec2 axis(2.0f, 1.0f); | |||
| axis.Normalize(); | |||
| pjd.Initialize(ground, body, b2Vec2(0.0f, 0.0f), axis); | |||
| // Non-bouncy limit | |||
| //pjd.Initialize(ground, body, b2Vec2(-10.0f, 10.0f), b2Vec2(1.0f, 0.0f)); | |||
| pjd.motorSpeed = 10.0f; | |||
| pjd.maxMotorForce = 10000.0f; | |||
| pjd.enableMotor = true; | |||
| pjd.lowerTranslation = 0.0f; | |||
| pjd.upperTranslation = 20.0f; | |||
| pjd.enableLimit = true; | |||
| m_joint = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'l': | |||
| m_joint->EnableLimit(!m_joint->IsLimitEnabled()); | |||
| break; | |||
| case 'm': | |||
| m_joint->EnableMotor(!m_joint->IsMotorEnabled()); | |||
| break; | |||
| case 's': | |||
| m_joint->SetMotorSpeed(-m_joint->GetMotorSpeed()); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motors, (s) speed"); | |||
| m_textLine += 15; | |||
| float32 force = m_joint->GetMotorForce(settings->hz); | |||
| m_debugDraw.DrawString(5, m_textLine, "Motor Force = %4.0f", (float) force); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Prismatic; | |||
| } | |||
| b2PrismaticJoint* m_joint; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,106 @@ | |||
| /* | |||
| * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef PULLEYS_H | |||
| #define PULLEYS_H | |||
| class Pulleys : public Test | |||
| { | |||
| public: | |||
| Pulleys() | |||
| { | |||
| float32 y = 16.0f; | |||
| float32 L = 12.0f; | |||
| float32 a = 1.0f; | |||
| float32 b = 2.0f; | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape edge; | |||
| edge.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| //ground->CreateFixture(&shape, 0.0f); | |||
| b2CircleShape circle; | |||
| circle.m_radius = 2.0f; | |||
| circle.m_p.Set(-10.0f, y + b + L); | |||
| ground->CreateFixture(&circle, 0.0f); | |||
| circle.m_p.Set(10.0f, y + b + L); | |||
| ground->CreateFixture(&circle, 0.0f); | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(a, b); | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| //bd.fixedRotation = true; | |||
| bd.position.Set(-10.0f, y); | |||
| b2Body* body1 = m_world->CreateBody(&bd); | |||
| body1->CreateFixture(&shape, 5.0f); | |||
| bd.position.Set(10.0f, y); | |||
| b2Body* body2 = m_world->CreateBody(&bd); | |||
| body2->CreateFixture(&shape, 5.0f); | |||
| b2PulleyJointDef pulleyDef; | |||
| b2Vec2 anchor1(-10.0f, y + b); | |||
| b2Vec2 anchor2(10.0f, y + b); | |||
| b2Vec2 groundAnchor1(-10.0f, y + b + L); | |||
| b2Vec2 groundAnchor2(10.0f, y + b + L); | |||
| pulleyDef.Initialize(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, 1.5f); | |||
| m_joint1 = (b2PulleyJoint*)m_world->CreateJoint(&pulleyDef); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 0: | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| float32 ratio = m_joint1->GetRatio(); | |||
| float32 L = m_joint1->GetLengthA() + ratio * m_joint1->GetLengthB(); | |||
| m_debugDraw.DrawString(5, m_textLine, "L1 + %4.2f * L2 = %4.2f", (float) ratio, (float) L); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Pulleys; | |||
| } | |||
| b2PulleyJoint* m_joint1; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,89 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef PYRAMID_H | |||
| #define PYRAMID_H | |||
| class Pyramid : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_count = 20 | |||
| }; | |||
| Pyramid() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| float32 a = 0.5f; | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(a, a); | |||
| b2Vec2 x(-7.0f, 0.75f); | |||
| b2Vec2 y; | |||
| b2Vec2 deltaX(0.5625f, 1.25f); | |||
| b2Vec2 deltaY(1.125f, 0.0f); | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| y = x; | |||
| for (int32 j = i; j < e_count; ++j) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position = y; | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&shape, 5.0f); | |||
| y += deltaY; | |||
| } | |||
| x += deltaX; | |||
| } | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; | |||
| //if (m_stepCount == 400) | |||
| //{ | |||
| // tree->RebuildBottomUp(); | |||
| //} | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Pyramid; | |||
| } | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,440 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef RAY_CAST_H | |||
| #define RAY_CAST_H | |||
| // This test demonstrates how to use the world ray-cast feature. | |||
| // NOTE: we are intentionally filtering one of the polygons, therefore | |||
| // the ray will always miss one type of polygon. | |||
| // This callback finds the closest hit. Polygon 0 is filtered. | |||
| class RayCastClosestCallback : public b2RayCastCallback | |||
| { | |||
| public: | |||
| RayCastClosestCallback() | |||
| { | |||
| m_hit = false; | |||
| } | |||
| float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point, | |||
| const b2Vec2& normal, float32 fraction) | |||
| { | |||
| b2Body* body = fixture->GetBody(); | |||
| void* userData = body->GetUserData(); | |||
| if (userData) | |||
| { | |||
| int32 index = *(int32*)userData; | |||
| if (index == 0) | |||
| { | |||
| // filter | |||
| return -1.0f; | |||
| } | |||
| } | |||
| m_hit = true; | |||
| m_point = point; | |||
| m_normal = normal; | |||
| return fraction; | |||
| } | |||
| bool m_hit; | |||
| b2Vec2 m_point; | |||
| b2Vec2 m_normal; | |||
| }; | |||
| // This callback finds any hit. Polygon 0 is filtered. | |||
| class RayCastAnyCallback : public b2RayCastCallback | |||
| { | |||
| public: | |||
| RayCastAnyCallback() | |||
| { | |||
| m_hit = false; | |||
| } | |||
| float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point, | |||
| const b2Vec2& normal, float32 fraction) | |||
| { | |||
| b2Body* body = fixture->GetBody(); | |||
| void* userData = body->GetUserData(); | |||
| if (userData) | |||
| { | |||
| int32 index = *(int32*)userData; | |||
| if (index == 0) | |||
| { | |||
| // filter | |||
| return -1.0f; | |||
| } | |||
| } | |||
| m_hit = true; | |||
| m_point = point; | |||
| m_normal = normal; | |||
| return 0.0f; | |||
| } | |||
| bool m_hit; | |||
| b2Vec2 m_point; | |||
| b2Vec2 m_normal; | |||
| }; | |||
| // This ray cast collects multiple hits along the ray. Polygon 0 is filtered. | |||
| class RayCastMultipleCallback : public b2RayCastCallback | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_maxCount = 3 | |||
| }; | |||
| RayCastMultipleCallback() | |||
| { | |||
| m_count = 0; | |||
| } | |||
| float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point, | |||
| const b2Vec2& normal, float32 fraction) | |||
| { | |||
| b2Body* body = fixture->GetBody(); | |||
| void* userData = body->GetUserData(); | |||
| if (userData) | |||
| { | |||
| int32 index = *(int32*)userData; | |||
| if (index == 0) | |||
| { | |||
| // filter | |||
| return -1.0f; | |||
| } | |||
| } | |||
| b2Assert(m_count < e_maxCount); | |||
| m_points[m_count] = point; | |||
| m_normals[m_count] = normal; | |||
| ++m_count; | |||
| if (m_count == e_maxCount) | |||
| { | |||
| return 0.0f; | |||
| } | |||
| return 1.0f; | |||
| } | |||
| b2Vec2 m_points[e_maxCount]; | |||
| b2Vec2 m_normals[e_maxCount]; | |||
| int32 m_count; | |||
| }; | |||
| class RayCast : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_maxBodies = 256 | |||
| }; | |||
| enum Mode | |||
| { | |||
| e_closest, | |||
| e_any, | |||
| e_multiple | |||
| }; | |||
| RayCast() | |||
| { | |||
| // Ground body | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.5f, 0.0f); | |||
| vertices[1].Set(0.5f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| m_polygons[0].Set(vertices, 3); | |||
| } | |||
| { | |||
| b2Vec2 vertices[3]; | |||
| vertices[0].Set(-0.1f, 0.0f); | |||
| vertices[1].Set(0.1f, 0.0f); | |||
| vertices[2].Set(0.0f, 1.5f); | |||
| m_polygons[1].Set(vertices, 3); | |||
| } | |||
| { | |||
| float32 w = 1.0f; | |||
| float32 b = w / (2.0f + b2Sqrt(2.0f)); | |||
| float32 s = b2Sqrt(2.0f) * b; | |||
| b2Vec2 vertices[8]; | |||
| vertices[0].Set(0.5f * s, 0.0f); | |||
| vertices[1].Set(0.5f * w, b); | |||
| vertices[2].Set(0.5f * w, b + s); | |||
| vertices[3].Set(0.5f * s, w); | |||
| vertices[4].Set(-0.5f * s, w); | |||
| vertices[5].Set(-0.5f * w, b + s); | |||
| vertices[6].Set(-0.5f * w, b); | |||
| vertices[7].Set(-0.5f * s, 0.0f); | |||
| m_polygons[2].Set(vertices, 8); | |||
| } | |||
| { | |||
| m_polygons[3].SetAsBox(0.5f, 0.5f); | |||
| } | |||
| { | |||
| m_circle.m_radius = 0.5f; | |||
| } | |||
| m_bodyIndex = 0; | |||
| memset(m_bodies, 0, sizeof(m_bodies)); | |||
| m_angle = 0.0f; | |||
| m_mode = e_closest; | |||
| } | |||
| void Create(int32 index) | |||
| { | |||
| if (m_bodies[m_bodyIndex] != NULL) | |||
| { | |||
| m_world->DestroyBody(m_bodies[m_bodyIndex]); | |||
| m_bodies[m_bodyIndex] = NULL; | |||
| } | |||
| b2BodyDef bd; | |||
| float32 x = RandomFloat(-10.0f, 10.0f); | |||
| float32 y = RandomFloat(0.0f, 20.0f); | |||
| bd.position.Set(x, y); | |||
| bd.angle = RandomFloat(-b2_pi, b2_pi); | |||
| m_userData[m_bodyIndex] = index; | |||
| bd.userData = m_userData + m_bodyIndex; | |||
| if (index == 4) | |||
| { | |||
| bd.angularDamping = 0.02f; | |||
| } | |||
| m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); | |||
| if (index < 4) | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.shape = m_polygons + index; | |||
| fd.friction = 0.3f; | |||
| m_bodies[m_bodyIndex]->CreateFixture(&fd); | |||
| } | |||
| else | |||
| { | |||
| b2FixtureDef fd; | |||
| fd.shape = &m_circle; | |||
| fd.friction = 0.3f; | |||
| m_bodies[m_bodyIndex]->CreateFixture(&fd); | |||
| } | |||
| m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; | |||
| } | |||
| void DestroyBody() | |||
| { | |||
| for (int32 i = 0; i < e_maxBodies; ++i) | |||
| { | |||
| if (m_bodies[i] != NULL) | |||
| { | |||
| m_world->DestroyBody(m_bodies[i]); | |||
| m_bodies[i] = NULL; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case '1': | |||
| case '2': | |||
| case '3': | |||
| case '4': | |||
| case '5': | |||
| Create(key - '1'); | |||
| break; | |||
| case 'd': | |||
| DestroyBody(); | |||
| break; | |||
| case 'm': | |||
| if (m_mode == e_closest) | |||
| { | |||
| m_mode = e_any; | |||
| } | |||
| else if (m_mode == e_any) | |||
| { | |||
| m_mode = e_multiple; | |||
| } | |||
| else if (m_mode == e_multiple) | |||
| { | |||
| m_mode = e_closest; | |||
| } | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| bool advanceRay = settings->pause == 0 || settings->singleStep; | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff, m to change the mode"); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "Mode = %d", m_mode); | |||
| m_textLine += 15; | |||
| float32 L = 11.0f; | |||
| b2Vec2 point1(0.0f, 10.0f); | |||
| b2Vec2 d(L * cosf(m_angle), L * sinf(m_angle)); | |||
| b2Vec2 point2 = point1 + d; | |||
| if (m_mode == e_closest) | |||
| { | |||
| RayCastClosestCallback callback; | |||
| m_world->RayCast(&callback, point1, point2); | |||
| if (callback.m_hit) | |||
| { | |||
| m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | |||
| m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | |||
| b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | |||
| m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | |||
| } | |||
| else | |||
| { | |||
| m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | |||
| } | |||
| } | |||
| else if (m_mode == e_any) | |||
| { | |||
| RayCastAnyCallback callback; | |||
| m_world->RayCast(&callback, point1, point2); | |||
| if (callback.m_hit) | |||
| { | |||
| m_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | |||
| m_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); | |||
| b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; | |||
| m_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); | |||
| } | |||
| else | |||
| { | |||
| m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | |||
| } | |||
| } | |||
| else if (m_mode == e_multiple) | |||
| { | |||
| RayCastMultipleCallback callback; | |||
| m_world->RayCast(&callback, point1, point2); | |||
| m_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); | |||
| for (int32 i = 0; i < callback.m_count; ++i) | |||
| { | |||
| b2Vec2 p = callback.m_points[i]; | |||
| b2Vec2 n = callback.m_normals[i]; | |||
| m_debugDraw.DrawPoint(p, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); | |||
| m_debugDraw.DrawSegment(point1, p, b2Color(0.8f, 0.8f, 0.8f)); | |||
| b2Vec2 head = p + 0.5f * n; | |||
| m_debugDraw.DrawSegment(p, head, b2Color(0.9f, 0.9f, 0.4f)); | |||
| } | |||
| } | |||
| if (advanceRay) | |||
| { | |||
| m_angle += 0.25f * b2_pi / 180.0f; | |||
| } | |||
| #if 0 | |||
| // This case was failing. | |||
| { | |||
| b2Vec2 vertices[4]; | |||
| //vertices[0].Set(-22.875f, -3.0f); | |||
| //vertices[1].Set(22.875f, -3.0f); | |||
| //vertices[2].Set(22.875f, 3.0f); | |||
| //vertices[3].Set(-22.875f, 3.0f); | |||
| b2PolygonShape shape; | |||
| //shape.Set(vertices, 4); | |||
| shape.SetAsBox(22.875f, 3.0f); | |||
| b2RayCastInput input; | |||
| input.p1.Set(10.2725f,1.71372f); | |||
| input.p2.Set(10.2353f,2.21807f); | |||
| //input.maxFraction = 0.567623f; | |||
| input.maxFraction = 0.56762173f; | |||
| b2Transform xf; | |||
| xf.SetIdentity(); | |||
| xf.position.Set(23.0f, 5.0f); | |||
| b2RayCastOutput output; | |||
| bool hit; | |||
| hit = shape.RayCast(&output, input, xf); | |||
| hit = false; | |||
| b2Color color(1.0f, 1.0f, 1.0f); | |||
| b2Vec2 vs[4]; | |||
| for (int32 i = 0; i < 4; ++i) | |||
| { | |||
| vs[i] = b2Mul(xf, shape.m_vertices[i]); | |||
| } | |||
| m_debugDraw.DrawPolygon(vs, 4, color); | |||
| m_debugDraw.DrawSegment(input.p1, input.p2, color); | |||
| } | |||
| #endif | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new RayCast; | |||
| } | |||
| int32 m_bodyIndex; | |||
| b2Body* m_bodies[e_maxBodies]; | |||
| int32 m_userData[e_maxBodies]; | |||
| b2PolygonShape m_polygons[4]; | |||
| b2CircleShape m_circle; | |||
| float32 m_angle; | |||
| Mode m_mode; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,166 @@ | |||
| /* | |||
| * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef REVOLUTE_H | |||
| #define REVOLUTE_H | |||
| class Revolute : public Test | |||
| { | |||
| public: | |||
| Revolute() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| //fd.filter.categoryBits = 2; | |||
| ground->CreateFixture(&fd); | |||
| } | |||
| { | |||
| b2CircleShape shape; | |||
| shape.m_radius = 0.5f; | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| b2RevoluteJointDef rjd; | |||
| bd.position.Set(-10.0f, 20.0f); | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&shape, 5.0f); | |||
| float32 w = 100.0f; | |||
| body->SetAngularVelocity(w); | |||
| body->SetLinearVelocity(b2Vec2(-8.0f * w, 0.0f)); | |||
| rjd.Initialize(ground, body, b2Vec2(-10.0f, 12.0f)); | |||
| rjd.motorSpeed = 1.0f * b2_pi; | |||
| rjd.maxMotorTorque = 10000.0f; | |||
| rjd.enableMotor = false; | |||
| rjd.lowerAngle = -0.25f * b2_pi; | |||
| rjd.upperAngle = 0.5f * b2_pi; | |||
| rjd.enableLimit = true; | |||
| rjd.collideConnected = true; | |||
| m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&rjd); | |||
| } | |||
| { | |||
| b2CircleShape circle_shape; | |||
| circle_shape.m_radius = 3.0f; | |||
| b2BodyDef circle_bd; | |||
| circle_bd.type = b2_dynamicBody; | |||
| circle_bd.position.Set(5.0f, 30.0f); | |||
| b2FixtureDef fd; | |||
| fd.density = 5.0f; | |||
| fd.filter.maskBits = 1; | |||
| fd.shape = &circle_shape; | |||
| m_ball = m_world->CreateBody(&circle_bd); | |||
| m_ball->CreateFixture(&fd); | |||
| b2PolygonShape polygon_shape; | |||
| polygon_shape.SetAsBox(10.0f, 0.2f, b2Vec2 (-10.0f, 0.0f), 0.0f); | |||
| b2BodyDef polygon_bd; | |||
| polygon_bd.position.Set(20.0f, 10.0f); | |||
| polygon_bd.type = b2_dynamicBody; | |||
| polygon_bd.bullet = true; | |||
| b2Body* polygon_body = m_world->CreateBody(&polygon_bd); | |||
| polygon_body->CreateFixture(&polygon_shape, 2.0f); | |||
| b2RevoluteJointDef rjd; | |||
| rjd.Initialize(ground, polygon_body, b2Vec2(20.0f, 10.0f)); | |||
| rjd.lowerAngle = -0.25f * b2_pi; | |||
| rjd.upperAngle = 0.0f * b2_pi; | |||
| rjd.enableLimit = true; | |||
| m_world->CreateJoint(&rjd); | |||
| } | |||
| // Tests mass computation of a small object far from the origin | |||
| { | |||
| b2BodyDef bodyDef; | |||
| bodyDef.type = b2_dynamicBody; | |||
| b2Body* body = m_world->CreateBody(&bodyDef); | |||
| b2PolygonShape polyShape; | |||
| b2Vec2 verts[3]; | |||
| verts[0].Set( 17.63f, 36.31f ); | |||
| verts[1].Set( 17.52f, 36.69f ); | |||
| verts[2].Set( 17.19f, 36.36f ); | |||
| polyShape.Set(verts, 3); | |||
| b2FixtureDef polyFixtureDef; | |||
| polyFixtureDef.shape = &polyShape; | |||
| polyFixtureDef.density = 1; | |||
| body->CreateFixture(&polyFixtureDef); //assertion hits inside here | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'l': | |||
| m_joint->EnableLimit(!m_joint->IsLimitEnabled()); | |||
| break; | |||
| case 'm': | |||
| m_joint->EnableMotor(!m_joint->IsMotorEnabled()); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Keys: (l) limits, (m) motor"); | |||
| m_textLine += 15; | |||
| //if (m_stepCount == 360) | |||
| //{ | |||
| // m_ball->SetTransform(b2Vec2(0.0f, 0.5f), 0.0f); | |||
| //} | |||
| //float32 torque1 = m_joint1->GetMotorTorque(); | |||
| //m_debugDraw.DrawString(5, m_textLine, "Motor Torque = %4.0f, %4.0f : Motor Force = %4.0f", (float) torque1, (float) torque2, (float) force3); | |||
| //m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Revolute; | |||
| } | |||
| b2Body* m_ball; | |||
| b2RevoluteJoint* m_joint; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,101 @@ | |||
| /* | |||
| * Copyright (c) 2011 Erin Catto http://box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef ROPE_H | |||
| #define ROPE_H | |||
| /// | |||
| class Rope : public Test | |||
| { | |||
| public: | |||
| Rope() | |||
| { | |||
| const int32 N = 40; | |||
| b2Vec2 vertices[N]; | |||
| float32 masses[N]; | |||
| for (int32 i = 0; i < N; ++i) | |||
| { | |||
| vertices[i].Set(0.0f, 20.0f - 0.25f * i); | |||
| masses[i] = 1.0f; | |||
| } | |||
| masses[0] = 0.0f; | |||
| masses[1] = 0.0f; | |||
| b2RopeDef def; | |||
| def.vertices = vertices; | |||
| def.count = N; | |||
| def.gravity.Set(0.0f, -10.0f); | |||
| def.masses = masses; | |||
| def.damping = 0.1f; | |||
| def.k2 = 1.0f; | |||
| def.k3 = 0.5f; | |||
| m_rope.Initialize(&def); | |||
| m_angle = 0.0f; | |||
| m_rope.SetAngle(m_angle); | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'q': | |||
| m_angle = b2Max(-b2_pi, m_angle - 0.05f * b2_pi); | |||
| m_rope.SetAngle(m_angle); | |||
| break; | |||
| case 'e': | |||
| m_angle = b2Min(b2_pi, m_angle + 0.05f * b2_pi); | |||
| m_rope.SetAngle(m_angle); | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| float32 dt = settings->hz > 0.0f ? 1.0f / settings->hz : 0.0f; | |||
| if (settings->pause == 1 && settings->singleStep == 0) | |||
| { | |||
| dt = 0.0f; | |||
| } | |||
| m_rope.Step(dt, 1); | |||
| Test::Step(settings); | |||
| m_rope.Draw(&m_debugDraw); | |||
| m_debugDraw.DrawString(5, m_textLine, "Press (q,e) to adjust target angle"); | |||
| m_textLine += 15; | |||
| m_debugDraw.DrawString(5, m_textLine, "Target angle = %g degrees", m_angle * 180.0f / b2_pi); | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new Rope; | |||
| } | |||
| b2Rope m_rope; | |||
| float32 m_angle; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,145 @@ | |||
| /* | |||
| * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef ROPE_JOINT_H | |||
| #define ROPE_JOINT_H | |||
| /// This test shows how a rope joint can be used to stabilize a chain of | |||
| /// bodies with a heavy payload. Notice that the rope joint just prevents | |||
| /// excessive stretching and has no other effect. | |||
| /// By disabling the rope joint you can see that the Box2D solver has trouble | |||
| /// supporting heavy bodies with light bodies. Try playing around with the | |||
| /// densities, time step, and iterations to see how they affect stability. | |||
| /// This test also shows how to use contact filtering. Filtering is configured | |||
| /// so that the payload does not collide with the chain. | |||
| class RopeJoint : public Test | |||
| { | |||
| public: | |||
| RopeJoint() | |||
| { | |||
| b2Body* ground = NULL; | |||
| { | |||
| b2BodyDef bd; | |||
| ground = m_world->CreateBody(&bd); | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| { | |||
| b2PolygonShape shape; | |||
| shape.SetAsBox(0.5f, 0.125f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.density = 20.0f; | |||
| fd.friction = 0.2f; | |||
| fd.filter.categoryBits = 0x0001; | |||
| fd.filter.maskBits = 0xFFFF & ~0x0002; | |||
| b2RevoluteJointDef jd; | |||
| jd.collideConnected = false; | |||
| const int32 N = 10; | |||
| const float32 y = 15.0f; | |||
| m_ropeDef.localAnchorA.Set(0.0f, y); | |||
| b2Body* prevBody = ground; | |||
| for (int32 i = 0; i < N; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(0.5f + 1.0f * i, y); | |||
| if (i == N - 1) | |||
| { | |||
| shape.SetAsBox(1.5f, 1.5f); | |||
| fd.density = 100.0f; | |||
| fd.filter.categoryBits = 0x0002; | |||
| bd.position.Set(1.0f * i, y); | |||
| bd.angularDamping = 0.4f; | |||
| } | |||
| b2Body* body = m_world->CreateBody(&bd); | |||
| body->CreateFixture(&fd); | |||
| b2Vec2 anchor(float32(i), y); | |||
| jd.Initialize(prevBody, body, anchor); | |||
| m_world->CreateJoint(&jd); | |||
| prevBody = body; | |||
| } | |||
| m_ropeDef.localAnchorB.SetZero(); | |||
| float32 extraLength = 0.01f; | |||
| m_ropeDef.maxLength = N - 1.0f + extraLength; | |||
| m_ropeDef.bodyB = prevBody; | |||
| } | |||
| { | |||
| m_ropeDef.bodyA = ground; | |||
| m_rope = m_world->CreateJoint(&m_ropeDef); | |||
| } | |||
| } | |||
| void Keyboard(unsigned char key) | |||
| { | |||
| switch (key) | |||
| { | |||
| case 'j': | |||
| if (m_rope) | |||
| { | |||
| m_world->DestroyJoint(m_rope); | |||
| m_rope = NULL; | |||
| } | |||
| else | |||
| { | |||
| m_rope = m_world->CreateJoint(&m_ropeDef); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| m_debugDraw.DrawString(5, m_textLine, "Press (j) to toggle the rope joint."); | |||
| m_textLine += 15; | |||
| if (m_rope) | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "Rope ON"); | |||
| } | |||
| else | |||
| { | |||
| m_debugDraw.DrawString(5, m_textLine, "Rope OFF"); | |||
| } | |||
| m_textLine += 15; | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new RopeJoint; | |||
| } | |||
| b2RopeJointDef m_ropeDef; | |||
| b2Joint* m_rope; | |||
| }; | |||
| #endif | |||
| @@ -0,0 +1,181 @@ | |||
| /* | |||
| * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org | |||
| * | |||
| * This software is provided 'as-is', without any express or implied | |||
| * warranty. In no event will the authors be held liable for any damages | |||
| * arising from the use of this software. | |||
| * Permission is granted to anyone to use this software for any purpose, | |||
| * including commercial applications, and to alter it and redistribute it | |||
| * freely, subject to the following restrictions: | |||
| * 1. The origin of this software must not be misrepresented; you must not | |||
| * claim that you wrote the original software. If you use this software | |||
| * in a product, an acknowledgment in the product documentation would be | |||
| * appreciated but is not required. | |||
| * 2. Altered source versions must be plainly marked as such, and must not be | |||
| * misrepresented as being the original software. | |||
| * 3. This notice may not be removed or altered from any source distribution. | |||
| */ | |||
| #ifndef SENSOR_TEST_H | |||
| #define SENSOR_TEST_H | |||
| // This is used to test sensor shapes. | |||
| class SensorTest : public Test | |||
| { | |||
| public: | |||
| enum | |||
| { | |||
| e_count = 7 | |||
| }; | |||
| SensorTest() | |||
| { | |||
| { | |||
| b2BodyDef bd; | |||
| b2Body* ground = m_world->CreateBody(&bd); | |||
| { | |||
| b2EdgeShape shape; | |||
| shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); | |||
| ground->CreateFixture(&shape, 0.0f); | |||
| } | |||
| #if 0 | |||
| { | |||
| b2FixtureDef sd; | |||
| sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f); | |||
| sd.isSensor = true; | |||
| m_sensor = ground->CreateFixture(&sd); | |||
| } | |||
| #else | |||
| { | |||
| b2CircleShape shape; | |||
| shape.m_radius = 5.0f; | |||
| shape.m_p.Set(0.0f, 10.0f); | |||
| b2FixtureDef fd; | |||
| fd.shape = &shape; | |||
| fd.isSensor = true; | |||
| m_sensor = ground->CreateFixture(&fd); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| b2CircleShape shape; | |||
| shape.m_radius = 1.0f; | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| b2BodyDef bd; | |||
| bd.type = b2_dynamicBody; | |||
| bd.position.Set(-10.0f + 3.0f * i, 20.0f); | |||
| bd.userData = m_touching + i; | |||
| m_touching[i] = false; | |||
| m_bodies[i] = m_world->CreateBody(&bd); | |||
| m_bodies[i]->CreateFixture(&shape, 1.0f); | |||
| } | |||
| } | |||
| } | |||
| // Implement contact listener. | |||
| void BeginContact(b2Contact* contact) | |||
| { | |||
| b2Fixture* fixtureA = contact->GetFixtureA(); | |||
| b2Fixture* fixtureB = contact->GetFixtureB(); | |||
| if (fixtureA == m_sensor) | |||
| { | |||
| void* userData = fixtureB->GetBody()->GetUserData(); | |||
| if (userData) | |||
| { | |||
| bool* touching = (bool*)userData; | |||
| *touching = true; | |||
| } | |||
| } | |||
| if (fixtureB == m_sensor) | |||
| { | |||
| void* userData = fixtureA->GetBody()->GetUserData(); | |||
| if (userData) | |||
| { | |||
| bool* touching = (bool*)userData; | |||
| *touching = true; | |||
| } | |||
| } | |||
| } | |||
| // Implement contact listener. | |||
| void EndContact(b2Contact* contact) | |||
| { | |||
| b2Fixture* fixtureA = contact->GetFixtureA(); | |||
| b2Fixture* fixtureB = contact->GetFixtureB(); | |||
| if (fixtureA == m_sensor) | |||
| { | |||
| void* userData = fixtureB->GetBody()->GetUserData(); | |||
| if (userData) | |||
| { | |||
| bool* touching = (bool*)userData; | |||
| *touching = false; | |||
| } | |||
| } | |||
| if (fixtureB == m_sensor) | |||
| { | |||
| void* userData = fixtureA->GetBody()->GetUserData(); | |||
| if (userData) | |||
| { | |||
| bool* touching = (bool*)userData; | |||
| *touching = false; | |||
| } | |||
| } | |||
| } | |||
| void Step(Settings* settings) | |||
| { | |||
| Test::Step(settings); | |||
| // Traverse the contact results. Apply a force on shapes | |||
| // that overlap the sensor. | |||
| for (int32 i = 0; i < e_count; ++i) | |||
| { | |||
| if (m_touching[i] == false) | |||
| { | |||
| continue; | |||
| } | |||
| b2Body* body = m_bodies[i]; | |||
| b2Body* ground = m_sensor->GetBody(); | |||
| b2CircleShape* circle = (b2CircleShape*)m_sensor->GetShape(); | |||
| b2Vec2 center = ground->GetWorldPoint(circle->m_p); | |||
| b2Vec2 position = body->GetPosition(); | |||
| b2Vec2 d = center - position; | |||
| if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON) | |||
| { | |||
| continue; | |||
| } | |||
| d.Normalize(); | |||
| b2Vec2 F = 100.0f * d; | |||
| body->ApplyForce(F, position); | |||
| } | |||
| } | |||
| static Test* Create() | |||
| { | |||
| return new SensorTest; | |||
| } | |||
| b2Fixture* m_sensor; | |||
| b2Body* m_bodies[e_count]; | |||
| bool m_touching[e_count]; | |||
| }; | |||
| #endif | |||