Skip to content

Commit 571b1b0

Browse files
authored
ofxiOSCoreHaptics (#7343)
#changelog #ios
1 parent c767ea4 commit 571b1b0

File tree

7 files changed

+259
-1
lines changed

7 files changed

+259
-1
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// created by artificiel 2023-02-15
2+
//
3+
// features to add:
4+
//
5+
// - detect if haptics are supported on specific device to fail gracefully
6+
// - recover from going in BG (haptics are only for front app)
7+
//
8+
9+
#pragma once
10+
#import <CoreHaptics/CoreHaptics.h>
11+
12+
class ofxiOSCoreHaptics {
13+
public:
14+
bool sendParameters(float intensity, float sharpness);
15+
void setup(); // will be lazy-called; usefull in ofApp::setup() to prevent small engine hiccup
16+
17+
private:
18+
bool prepare_engine();
19+
bool is_vibrating() ;
20+
bool is_vibrating_ {false};
21+
CHHapticEngine * engine_;
22+
id<CHHapticAdvancedPatternPlayer> player_;
23+
};
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// created by artificiel 2023-02-15
2+
3+
#include "ofxiOSCoreHaptics.h"
4+
5+
bool ofxiOSCoreHaptics::prepare_engine() {
6+
7+
// this starts the engine and primes it with an instance of CHHapticAdvancedPatternPlayer
8+
// that will later be modulated by CHHapticDynamicParameters
9+
10+
NSError * error;
11+
12+
NSLog(@"Preparing Haptics Engine");
13+
auto init_intensity = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
14+
auto init_sharpness = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticSharpness value:0.0f];
15+
auto event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:@[init_intensity, init_sharpness] relativeTime:CHHapticTimeImmediate duration:10000];
16+
auto pattern = [[CHHapticPattern alloc] initWithEvents:@[event] parameters:@[] error:&error];
17+
18+
engine_ = [[CHHapticEngine alloc] initAndReturnError:&error];
19+
if (error != nil) {
20+
NSLog(@"ofxiOSCoreHaptics::prepare_engine [engine_ initAndReturnError:] %@", error);
21+
return false;
22+
}
23+
[engine_ setStoppedHandler:^(CHHapticEngineStoppedReason reason){
24+
switch (reason) {
25+
case CHHapticEngineStoppedReasonAudioSessionInterrupt:
26+
NSLog(@"ofxiOSCoreHaptics::stoppedHandler() engine stopped: CHHapticEngineStoppedReasonAudioSessionInterrupt");
27+
break;
28+
case CHHapticEngineStoppedReasonApplicationSuspended:
29+
NSLog(@"ofxiOSCoreHaptics::stoppedHandler() engine stopped: CHHapticEngineStoppedReasonApplicationSuspended");
30+
break;
31+
case CHHapticEngineStoppedReasonIdleTimeout:
32+
NSLog(@"ofxiOSCoreHaptics::stoppedHandler() engine stopped: CHHapticEngineStoppedReasonIdleTimeout");
33+
break;
34+
case CHHapticEngineStoppedReasonSystemError:
35+
NSLog(@"ofxiOSCoreHaptics::stoppedHandler() engine stopped: CHHapticEngineStoppedReasonSystemError");
36+
break;
37+
}
38+
}];
39+
40+
player_ = [engine_ createAdvancedPlayerWithPattern:pattern error:&error];
41+
if (error != nil) {
42+
NSLog(@"ofxiOSCoreHaptics::prepare_engine() %@ [engine_ createAdvancedPlayerWithPattern:]", error);
43+
return false;
44+
}
45+
46+
[engine_ startAndReturnError:&error];
47+
if (error != nil) {
48+
NSLog(@"ofxiOSCoreHaptics::prepare_engine [engine_ startAndReturnError:] %@", error);
49+
return false;
50+
}
51+
52+
[player_ startAtTime:CHHapticTimeImmediate error:&error];
53+
if (error != nil) {
54+
NSLog(@"ofxiOSCoreHaptics::prepare_engine [player_ startAtTime:] %@", error);
55+
return false;
56+
}
57+
[player_ setLoopEnabled:TRUE];
58+
return true;
59+
}
60+
61+
void ofxiOSCoreHaptics::setup() {
62+
is_vibrating_ = prepare_engine();
63+
if (!is_vibrating_) NSLog(@"ofxiOSCoreHaptics::setup() failed");
64+
}
65+
66+
bool ofxiOSCoreHaptics::is_vibrating() {
67+
if (!is_vibrating_) setup();
68+
return is_vibrating_;
69+
}
70+
71+
bool ofxiOSCoreHaptics::sendParameters(float i, float s) {
72+
73+
if (is_vibrating()) {
74+
75+
NSError * error;
76+
auto intensity = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:i relativeTime:CHHapticTimeImmediate];
77+
auto sharpness = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticSharpnessControl value:s relativeTime:CHHapticTimeImmediate];
78+
79+
[player_ sendParameters:@[intensity, sharpness] atTime:CHHapticTimeImmediate error:&error];
80+
81+
if (error != nil) {
82+
NSLog(@"ofxiOSCoreHaptics::sendParameters %@", error);
83+
return false;
84+
} else {
85+
return true;
86+
}
87+
}
88+
return false;
89+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "ofApp.h"
2+
3+
int main() {
4+
5+
// here are the most commonly used iOS window settings.
6+
//------------------------------------------------------
7+
ofiOSWindowSettings settings;
8+
settings.enableRetina = true; // enables retina resolution if the device supports it.
9+
settings.enableDepth = false; // enables depth buffer for 3d drawing.
10+
settings.enableAntiAliasing = false; // enables anti-aliasing which smooths out graphics on the screen.
11+
settings.numOfAntiAliasingSamples = 0; // number of samples used for anti-aliasing.
12+
settings.enableHardwareOrientation = false; // enables native view orientation.
13+
settings.enableHardwareOrientationAnimation = false; // enables native orientation changes to be animated.
14+
settings.glesVersion = OFXIOS_RENDERER_ES2; // type of renderer to use, ES1, ES2, ES3
15+
settings.windowControllerType = ofxiOSWindowControllerType::GL_KIT; // Window Controller Type
16+
settings.colorType = ofxiOSRendererColorFormat::RGBA8888; // color format used default RGBA8888
17+
settings.depthType = ofxiOSRendererDepthFormat::DEPTH_NONE; // depth format (16/24) if depth enabled
18+
settings.stencilType = ofxiOSRendererStencilFormat::STENCIL_NONE; // stencil mode
19+
settings.windowMode = OF_FULLSCREEN;
20+
settings.enableMultiTouch = false; // enables multitouch support and updates touch.id etc.
21+
ofCreateWindow(settings);
22+
23+
return ofRunApp(new ofApp);
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include "ofxiOS.h"
4+
#include "ofxiOSCoreHaptics.h"
5+
6+
class ofApp : public ofxiOSApp {
7+
8+
ofxiOSCoreHaptics haptics_;
9+
10+
void setup() override;
11+
void update() override;
12+
void draw() override;
13+
void exit() override;
14+
15+
void touchDown(ofTouchEventArgs & touch) override;
16+
void touchMoved(ofTouchEventArgs & touch) override;
17+
void touchUp(ofTouchEventArgs & touch) override;
18+
void touchDoubleTap(ofTouchEventArgs & touch) override;
19+
void touchCancelled(ofTouchEventArgs & touch) override;
20+
21+
void lostFocus() override;
22+
void gotFocus() override;
23+
void gotMemoryWarning() override;
24+
void deviceOrientationChanged(int newOrientation) override;
25+
void launchedWithURL(std::string url) override;
26+
27+
};
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include "ofApp.h"
2+
3+
//--------------------------------------------------------------
4+
void ofApp::setup(){
5+
6+
}
7+
8+
//--------------------------------------------------------------
9+
void ofApp::update(){
10+
haptics_.sendParameters(fmod(ofGetElapsedTimef()*2.0f,1),ofMap(sin(ofGetElapsedTimef()*PI/3.0f), -1, 1, 0, 1));
11+
}
12+
13+
//--------------------------------------------------------------
14+
void ofApp::draw(){
15+
16+
}
17+
18+
//--------------------------------------------------------------
19+
void ofApp::exit(){
20+
21+
}
22+
23+
//--------------------------------------------------------------
24+
void ofApp::touchDown(ofTouchEventArgs & touch){
25+
26+
}
27+
28+
//--------------------------------------------------------------
29+
void ofApp::touchMoved(ofTouchEventArgs & touch){
30+
31+
}
32+
33+
//--------------------------------------------------------------
34+
void ofApp::touchUp(ofTouchEventArgs & touch){
35+
36+
}
37+
38+
//--------------------------------------------------------------
39+
void ofApp::touchDoubleTap(ofTouchEventArgs & touch){
40+
41+
}
42+
43+
//--------------------------------------------------------------
44+
void ofApp::touchCancelled(ofTouchEventArgs & touch){
45+
46+
}
47+
48+
//--------------------------------------------------------------
49+
void ofApp::lostFocus(){
50+
51+
}
52+
53+
//--------------------------------------------------------------
54+
void ofApp::gotFocus(){
55+
56+
}
57+
58+
//--------------------------------------------------------------
59+
void ofApp::gotMemoryWarning(){
60+
61+
}
62+
63+
//--------------------------------------------------------------
64+
void ofApp::deviceOrientationChanged(int newOrientation){
65+
66+
}
67+
68+
//--------------------------------------------------------------
69+
void ofApp::launchedWithURL(std::string url){
70+
71+
}

libs/openFrameworksCompiled/project/ios/CoreOF.xcconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ OF_CORE_LIBS = $(MISC_FLAGS) $(LIB_BOOST) $(LIB_FREEIMAGE) $(LIB_FREETYPE) $(LIB
3636

3737
OF_CORE_HEADERS = $(HEADER_OF) $(HEADER_OFXIOS) $(HEADER_OFXACCELEROMETER) $(HEADER_BOOST) $(HEADER_UTF8) $(HEADER_FREETYPE) $(HEADER_FREETYPE2) $(HEADER_FMOD) $(HEADER_GLEW) $(HEADER_FREEIMAGE) $(HEADER_TESS2) $(HEADER_RTAUDIO) $(HEADER_JSON) $(HEADER_GLM) $(HEADER_CURL) $(HEADER_URIPARSER) $(HEADER_PUGIXML)
3838

39-
OF_CORE_FRAMEWORKS = -framework AudioToolbox -framework Accelerate -framework AVFoundation -framework CoreAudio -framework CoreGraphics -framework CoreLocation -framework CoreMotion -framework CoreMedia -framework CoreVideo -framework Foundation -framework GameController -framework GLKit -framework MapKit -framework OpenAL -framework OpenGLES -framework UIKit -framework Security -framework QuartzCore
39+
OF_CORE_FRAMEWORKS = -framework AudioToolbox -framework Accelerate -framework AVFoundation -framework CoreAudio -framework CoreGraphics -framework CoreLocation -framework CoreMotion -framework CoreMedia -framework CoreVideo -framework Foundation -framework GameController -framework GLKit -framework MapKit -framework OpenAL -framework OpenGLES -framework UIKit -framework Security -framework QuartzCore -framework CoreHaptics
4040

4141
// once all libraries are compiled for libc++ / all architectures
4242
CLANG_CXX_LIBRARY = libc++

libs/openFrameworksCompiled/project/ios/iOS+OFLib.xcodeproj/project.pbxproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@
230230
E4F76EB6176CB27200798745 /* ofVideoGrabber.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F76E16176CB27200798745 /* ofVideoGrabber.h */; };
231231
E4F76EB7176CB27200798745 /* ofVideoPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F76E17176CB27200798745 /* ofVideoPlayer.cpp */; };
232232
E4F76EB8176CB27200798745 /* ofVideoPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F76E18176CB27200798745 /* ofVideoPlayer.h */; };
233+
E999E70E299D53FC00649F18 /* ofxiOSCoreHaptics.h in Headers */ = {isa = PBXBuildFile; fileRef = E999E70C299D53FC00649F18 /* ofxiOSCoreHaptics.h */; };
234+
E999E70F299D53FC00649F18 /* ofxiOSCoreHaptics.mm in Sources */ = {isa = PBXBuildFile; fileRef = E999E70D299D53FC00649F18 /* ofxiOSCoreHaptics.mm */; };
235+
E9F39183299E892200280B58 /* CoreHaptics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9F39182299E892200280B58 /* CoreHaptics.framework */; };
233236
/* End PBXBuildFile section */
234237

235238
/* Begin PBXFileReference section */
@@ -465,13 +468,17 @@
465468
E4F76E16176CB27200798745 /* ofVideoGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofVideoGrabber.h; sourceTree = "<group>"; };
466469
E4F76E17176CB27200798745 /* ofVideoPlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ofVideoPlayer.cpp; sourceTree = "<group>"; };
467470
E4F76E18176CB27200798745 /* ofVideoPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofVideoPlayer.h; sourceTree = "<group>"; };
471+
E999E70C299D53FC00649F18 /* ofxiOSCoreHaptics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ofxiOSCoreHaptics.h; sourceTree = "<group>"; };
472+
E999E70D299D53FC00649F18 /* ofxiOSCoreHaptics.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ofxiOSCoreHaptics.mm; sourceTree = "<group>"; };
473+
E9F39182299E892200280B58 /* CoreHaptics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreHaptics.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/System/Library/Frameworks/CoreHaptics.framework; sourceTree = DEVELOPER_DIR; };
468474
/* End PBXFileReference section */
469475

470476
/* Begin PBXFrameworksBuildPhase section */
471477
BB24DEC910DA7A3F00E9C588 /* Frameworks */ = {
472478
isa = PBXFrameworksBuildPhase;
473479
buildActionMask = 2147483647;
474480
files = (
481+
E9F39183299E892200280B58 /* CoreHaptics.framework in Frameworks */,
475482
99752D331BF21EEE0026316A /* GameController.framework in Frameworks */,
476483
67D48ED01C10399900F719BC /* CoreMotion.framework in Frameworks */,
477484
BB24DECA10DA7A3F00E9C588 /* AudioToolbox.framework in Frameworks */,
@@ -558,6 +565,8 @@
558565
15594F0215C55A5700727FF2 /* utils */ = {
559566
isa = PBXGroup;
560567
children = (
568+
E999E70C299D53FC00649F18 /* ofxiOSCoreHaptics.h */,
569+
E999E70D299D53FC00649F18 /* ofxiOSCoreHaptics.mm */,
561570
15594FB615C56D1E00727FF2 /* ofxiOSCoreLocation.h */,
562571
15594FAF15C56D1E00727FF2 /* ofxiOSCoreLocation.mm */,
563572
67D48ED11C103BAE00F719BC /* ofxiOSCoreMotion.h */,
@@ -632,6 +641,7 @@
632641
E4F76D69176CB27200798745 /* openFrameworks */,
633642
BB16E9930F2B1E5900518274 /* libs */,
634643
19C28FACFE9D520D11CA2CBB /* Products */,
644+
E9F39181299E892200280B58 /* Frameworks */,
635645
);
636646
indentWidth = 4;
637647
name = CustomTemplate;
@@ -946,6 +956,14 @@
946956
path = video;
947957
sourceTree = "<group>";
948958
};
959+
E9F39181299E892200280B58 /* Frameworks */ = {
960+
isa = PBXGroup;
961+
children = (
962+
E9F39182299E892200280B58 /* CoreHaptics.framework */,
963+
);
964+
name = Frameworks;
965+
sourceTree = "<group>";
966+
};
949967
/* End PBXGroup section */
950968

951969
/* Begin PBXHeadersBuildPhase section */
@@ -956,6 +974,7 @@
956974
2E49891B292C98000096EC56 /* ofCubeMap.h in Headers */,
957975
E4F76E1A176CB27200798745 /* of3dPrimitives.h in Headers */,
958976
E4F76E1C176CB27200798745 /* of3dUtils.h in Headers */,
977+
E999E70E299D53FC00649F18 /* ofxiOSCoreHaptics.h in Headers */,
959978
E4F76E1E176CB27200798745 /* ofCamera.h in Headers */,
960979
E4F76E20176CB27200798745 /* ofEasyCam.h in Headers */,
961980
E4F76E22176CB27200798745 /* ofMesh.h in Headers */,
@@ -1138,6 +1157,7 @@
11381157
E4F76E43176CB27200798745 /* ofMaterial.cpp in Sources */,
11391158
E4F76E45176CB27200798745 /* ofShader.cpp in Sources */,
11401159
E4F76E49176CB27200798745 /* ofTexture.cpp in Sources */,
1160+
E999E70F299D53FC00649F18 /* ofxiOSCoreHaptics.mm in Sources */,
11411161
E4F76E4B176CB27200798745 /* ofVbo.cpp in Sources */,
11421162
90080014204EDA1300DC786A /* ofxiOSGLKViewController.mm in Sources */,
11431163
E4F76E4D176CB27200798745 /* ofVboMesh.cpp in Sources */,
@@ -1238,6 +1258,7 @@
12381258
"\"$(SRCROOT)/../../../tess2/lib/ios\"",
12391259
"\"$(SRCROOT)/../../../poco/lib/ios\"",
12401260
);
1261+
OF_CORE_FRAMEWORKS = "-framework AudioToolbox -framework Accelerate -framework AVFoundation -framework CoreAudio -framework CoreGraphics -framework CoreLocation -framework CoreMotion -framework CoreMedia -framework CoreVideo -framework Foundation -framework GameController -framework GLKit -framework MapKit -framework OpenAL -framework OpenGLES -framework UIKit -framework Security -framework QuartzCore -framework CoreHaptics";
12411262
PRODUCT_NAME = "ofxiOS_${PLATFORM_NAME}_Debug";
12421263
SDKROOT = iphoneos;
12431264
SKIP_INSTALL = YES;
@@ -1263,6 +1284,7 @@
12631284
"\"$(SRCROOT)/../../../tess2/lib/ios\"",
12641285
"\"$(SRCROOT)/../../../poco/lib/ios\"",
12651286
);
1287+
OF_CORE_FRAMEWORKS = "-framework AudioToolbox -framework Accelerate -framework AVFoundation -framework CoreAudio -framework CoreGraphics -framework CoreLocation -framework CoreMotion -framework CoreMedia -framework CoreVideo -framework Foundation -framework GameController -framework GLKit -framework MapKit -framework OpenAL -framework OpenGLES -framework UIKit -framework Security -framework QuartzCore -framework CoreHaptics";
12661288
PRODUCT_NAME = "ofxiOS_${PLATFORM_NAME}_Release";
12671289
SDKROOT = iphoneos;
12681290
SKIP_INSTALL = YES;
@@ -1300,6 +1322,7 @@
13001322
GCC_WARN_UNDECLARED_SELECTOR = YES;
13011323
GCC_WARN_UNUSED_FUNCTION = YES;
13021324
OBJROOT = "$(SRCROOT)/../../lib/ios/build/debug";
1325+
OF_CORE_FRAMEWORKS = "-framework AudioToolbox -framework Accelerate -framework AVFoundation -framework CoreAudio -framework CoreGraphics -framework CoreLocation -framework CoreMotion -framework CoreMedia -framework CoreVideo -framework Foundation -framework GameController -framework GLKit -framework MapKit -framework OpenAL -framework OpenGLES -framework UIKit -framework Security -framework QuartzCore -framework CoreHaptics";
13031326
ONLY_ACTIVE_ARCH = YES;
13041327
SDKROOT = iphoneos;
13051328
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
@@ -1341,6 +1364,7 @@
13411364
GCC_WARN_UNDECLARED_SELECTOR = YES;
13421365
GCC_WARN_UNUSED_FUNCTION = YES;
13431366
OBJROOT = "$(SRCROOT)/../../lib/ios/build/release";
1367+
OF_CORE_FRAMEWORKS = "-framework AudioToolbox -framework Accelerate -framework AVFoundation -framework CoreAudio -framework CoreGraphics -framework CoreLocation -framework CoreMotion -framework CoreMedia -framework CoreVideo -framework Foundation -framework GameController -framework GLKit -framework MapKit -framework OpenAL -framework OpenGLES -framework UIKit -framework Security -framework QuartzCore -framework CoreHaptics";
13441368
ONLY_ACTIVE_ARCH = NO;
13451369
SDKROOT = iphoneos;
13461370
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";

0 commit comments

Comments
 (0)