Thing/Sources/EVEViewController.mm
2026-05-25 18:06:58 +01:00

148 lines
4.7 KiB
Text

#import "EVEViewController.h"
#import <CoreMotion/CoreMotion.h>
#import <QuartzCore/QuartzCore.h>
#import "EVEGLView.h"
@interface EVEViewController ()
@property(nonatomic, strong) EVEGLView *glView;
@property(nonatomic, strong) UILabel *overlayLabel;
@property(nonatomic, strong) CADisplayLink *displayLink;
@property(nonatomic, strong) CMMotionManager *motionManager;
@property(nonatomic, assign) NSTimeInterval previousTimestamp;
@property(nonatomic, assign) double filteredFPS;
@property(nonatomic, assign) NSUInteger touchCount;
@end
@implementation EVEViewController
- (void)loadView {
UIView *root = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds];
root.backgroundColor = UIColor.blackColor;
root.multipleTouchEnabled = YES;
self.glView = [[EVEGLView alloc] initWithFrame:root.bounds];
self.glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[root addSubview:self.glView];
self.overlayLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.overlayLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.overlayLabel.numberOfLines = 0;
self.overlayLabel.textColor = UIColor.whiteColor;
self.overlayLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.45];
self.overlayLabel.font = [UIFont monospacedSystemFontOfSize:13.0 weight:UIFontWeightRegular];
self.overlayLabel.layer.cornerRadius = 6.0;
self.overlayLabel.layer.masksToBounds = YES;
[root addSubview:self.overlayLabel];
UILayoutGuide *safe = root.safeAreaLayoutGuide;
[NSLayoutConstraint activateConstraints:@[
[self.overlayLabel.leadingAnchor constraintEqualToAnchor:safe.leadingAnchor constant:12.0],
[self.overlayLabel.topAnchor constraintEqualToAnchor:safe.topAnchor constant:12.0],
[self.overlayLabel.widthAnchor constraintLessThanOrEqualToAnchor:safe.widthAnchor multiplier:0.92],
]];
self.view = root;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.accelerometerUpdateInterval = 1.0 / 30.0;
self.motionManager.gyroUpdateInterval = 1.0 / 30.0;
if (self.motionManager.accelerometerAvailable) {
[self.motionManager startAccelerometerUpdates];
}
if (self.motionManager.gyroAvailable) {
[self.motionManager startGyroUpdates];
}
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(frameTick:)];
[self.displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
}
- (void)dealloc {
[self.displayLink invalidate];
[self.motionManager stopAccelerometerUpdates];
[self.motionManager stopGyroUpdates];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
return UIRectEdgeAll;
}
- (BOOL)prefersHomeIndicatorAutoHidden {
return YES;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.glView resizeDrawableIfNeeded];
}
- (void)frameTick:(CADisplayLink *)link {
if (self.previousTimestamp > 0) {
NSTimeInterval delta = link.timestamp - self.previousTimestamp;
if (delta > 0) {
double instantFPS = 1.0 / delta;
self.filteredFPS = self.filteredFPS == 0 ? instantFPS : (self.filteredFPS * 0.9 + instantFPS * 0.1);
}
}
self.previousTimestamp = link.timestamp;
[self.glView renderAtTime:link.timestamp];
[self updateOverlay];
}
- (void)updateOverlay {
UIScreen *screen = UIScreen.mainScreen;
CGSize points = screen.bounds.size;
CGFloat scale = screen.scale;
CGSize pixels = CGSizeMake(points.width * scale, points.height * scale);
CMAcceleration acceleration = self.motionManager.accelerometerData.acceleration;
CMRotationRate rotation = self.motionManager.gyroData.rotationRate;
self.overlayLabel.text = [NSString stringWithFormat:
@"EVE Canvas\n"
"native shell + UIKit text\n"
"points %.0fx%.0f pixels %.0fx%.0f @ %.1fx\n"
"fps %.1f touches %lu\n"
"accel %+0.2f %+0.2f %+0.2f\n"
"gyro %+0.2f %+0.2f %+0.2f",
points.width, points.height, pixels.width, pixels.height, scale,
self.filteredFPS, (unsigned long)self.touchCount,
acceleration.x, acceleration.y, acceleration.z,
rotation.x, rotation.y, rotation.z];
[self.overlayLabel sizeToFit];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
(void)touches;
self.touchCount = event.allTouches.count;
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
(void)touches;
self.touchCount = event.allTouches.count;
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
(void)touches;
self.touchCount = event.allTouches.count;
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
(void)touches;
self.touchCount = event.allTouches.count;
}
@end