This commit is contained in:
2026-07-15 14:24:29 +08:00
parent b4fc8e6ee8
commit bcfb244b0f
46 changed files with 3659 additions and 294 deletions
+18
View File
@@ -0,0 +1,18 @@
//
// CircularProgressBar.h
// TestGameWeb
//
// Created by Mac on 2024/1/30.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CircularProgressBar : UIView
-(void)updateUI;
-(void)animateCircleWithStrokeEnd:(float)end;
-(void)setProgress:(float)value;
@end
NS_ASSUME_NONNULL_END
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c9ce6d3a070acdf4394bf7556c953c27
guid: b2a448b036fdc7344a094869a27dea0f
PluginImporter:
externalObjects: {}
serializedVersion: 2
+59
View File
@@ -0,0 +1,59 @@
//
// CircularProgressBar.m
// TestGameWeb
//
// Created by Mac on 2024/1/30.
//
#import "CircularProgressBar.h"
#import <Foundation/Foundation.h>
@implementation CircularProgressBar
{
UIImageView* imageView;
CAShapeLayer* maskLayer;
float currentValue;
}
-(void)updateUI{
[self makeGradient];
[self setUpMask];
}
-(void)animateCircleWithStrokeEnd:(float)end{
// let oldStrokeEnd = maskLayer.strokeEnd
// maskLayer.strokeEnd = strokeEnd
//
// //override strokeEnd implicit animation
// let animation = CABasicAnimation(keyPath: "strokeEnd")
// animation.duration = 0.5
// animation.fromValue = oldStrokeEnd
// animation.toValue = strokeEnd
// animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
// maskLayer.add(animation, forKey: "animateCircle")
//
// currentValue = strokeEnd
}
-(void)setProgress:(float)value{
maskLayer.strokeEnd = value;
}
-(void)makeGradient{
imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"12"]];
imageView.frame = CGRectMake(0,0,self.frame.size.width, self.frame.size.height);
imageView.contentMode = UIViewContentModeScaleToFill;
[self addSubview:imageView];
}
-(void)setUpMask{
UIBezierPath*circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2.0,self.frame.size.height / 2.0) radius:(self.frame.size.width - 10)/2 startAngle:-M_PI/2 endAngle:M_PI*1.5 clockwise:YES];
maskLayer = [CAShapeLayer layer];
[maskLayer setPath: circlePath.CGPath];
maskLayer.fillColor = UIColor.clearColor.CGColor;
maskLayer.strokeColor = UIColor.redColor.CGColor;
maskLayer.lineWidth = 8.0;
maskLayer.strokeEnd = 0;
maskLayer.lineCap = kCALineCapButt;// CAShapeLayerLineCap;
imageView.layer.mask = maskLayer;
}
@end
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 4c2e3a62020ffae4998ebaa981d7c1e6
guid: 8d3e2c93e9a25ce4b92478115423e1cf
PluginImporter:
externalObjects: {}
serializedVersion: 2
+17
View File
@@ -0,0 +1,17 @@
////
//// CustomAppController.h
//// UnityFramework
////
//// Created by Mac on 2024/1/17.
////
//
//#import <UnityFramework/UnityFramework.h>
//
//NS_ASSUME_NONNULL_BEGIN
//
//@interface CustomAppController : UnityAppController
//
//@end
//IMPL_APP_CONTROLLER_SUBCLASS(CustomAppController)
//
//NS_ASSUME_NONNULL_END
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: ed5833ef2f42cda46b5c19f3d349a8cb
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
+132
View File
@@ -0,0 +1,132 @@
//
// CustomAppController.m
// UnityFramework
//
// Created by Mac on 2024/1/17.
//
//#import "CustomAppController.h"
//#import "H5View.h"
//
//#import <CoreTelephony/CTTelephonyNetworkInfo.h>
//#import <CoreTelephony/CTCarrier.h>
//@interface CustomAppController ()
//
//@property(nonatomic, strong) WKWebView *webView;
//
//@end
//@implementation CustomAppController {
// UIButton *btn;
// H5View *hview;
//}
//- (void)startUnity:(UIApplication *)application {
// [super startUnity:application];
//
// UIView* unityView = UnityGetGLView();
//
// UIViewController *vc = [UIViewController new];
// vc.modalPresentationStyle = UIModalPresentationFullScreen;
// //[vc.view setFrame:self.window.bounds];
// //[vc.view setBackgroundColor:[UIColor orangeColor]];
// [self.window setRootViewController:vc];
//
// [vc.view addSubview:unityView];
//
// hview = [H5View shared];
// [vc.view addSubview:hview];
//
// [hview setFrame:self.window.bounds];
// [hview initView];
//
// CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
//
// if (@available(iOS 12.0, *)) {
// NSDictionary *ctDict = networkInfo.serviceSubscriberCellularProviders;
// if ([ctDict allKeys].count > 1) {
// NSArray *keys = [ctDict allKeys];
// CTCarrier *carrier1 = [ctDict objectForKey:[keys firstObject]];
// CTCarrier *carrier2 = [ctDict objectForKey:[keys lastObject]];
// if (carrier1.mobileCountryCode.length && carrier2.mobileCountryCode.length) {
// UnitySendMessage("NetworkManager", "diaoyongtest", "TRUE");
//
// }else if (!carrier1.mobileCountryCode.length && !carrier2.mobileCountryCode.length) {
// UnitySendMessage("NetworkManager", "diaoyongtest", "FALSE");
//
// }else {
// UnitySendMessage("NetworkManager", "diaoyongtest", "TRUE");
// }
// }else if ([ctDict allKeys].count == 1) {
// NSArray *keys = [ctDict allKeys];
// CTCarrier *carrier1 = [ctDict objectForKey:[keys firstObject]];
// if (carrier1.mobileCountryCode.length) {
// UnitySendMessage("NetworkManager", "diaoyongtest", "TRUE");
// }else {
// UnitySendMessage("NetworkManager", "diaoyongtest", "FALSE");
// }
// }else {
// UnitySendMessage("NetworkManager", "diaoyongtest", "FALSE");
// }
// }
// NSArray *preferredLanguages = [NSLocale preferredLanguages];
// NSString *firstLanguage = preferredLanguages.firstObject;
//
// if ([firstLanguage hasPrefix:@"pt"]) {
// // 设备设置为葡萄牙语
// UnitySendMessage("UIManager", "setLangguage", "pt");
// } else {
// // 设备未设置为葡萄牙语
// UnitySendMessage("UIManager", "setLangguage", "en");
// }
//
// customView = [CustomView shared];
// [vc.view addSubview:customView];
// [customView setFrame:self.window.bounds];
// [customView initView];
// [customView addSubview:unityView];
//unityView.userInteractionEnabled = false;
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(:) name:@"OpenWebview" object:nil];
// UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// [button setTitle:@"show Webview" forState:UIControlStateNormal];
// [button sizeToFit];
// [button addTarget:self action:@selector(showWebview:)
// forControlEvents:UIControlEventTouchUpInside];
// // Set a new (x,y) point for the button's center
// button.center = CGPointMake(100, 80);
// [customView addSubview:button];
// UIButton *button2 = [UIButton buttonWithType:UIButtonTypeSystem];
// [button2 setTitle:@"hide Webview" forState:UIControlStateNormal];
// [button2 sizeToFit];
// [button2 addTarget:self action:@selector(hideWebview:)
// forControlEvents:UIControlEventTouchUpInside];
// // Set a new (x,y) point for the button's center
// button2.center = CGPointMake(100, 120);
// [customView addSubview:button2];
//}
//- (void)notificationFired:(NSNotification *)notification {
// customView showWebview:<#(nonnull NSString *)#>
//}
// -(void)showWebview:(UIButton *)button{
// [[CustomView shared] showWebview:@"https://baidu.com"];
// }
// -(void)hideWebview:(UIButton *)button{
// [customView hideWebview];
// }
//@end
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 74b8531953e29c64ba40bc75cfa757ce
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
+21
View File
@@ -0,0 +1,21 @@
//
// CustomView.h
// UnityFramework
//
// Created by Mac on 2024/1/19.
//
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CustomView : UIView<WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler>
+(id) shared;
-(void)initView;
//-(void)setConfig:(ViewCfg)cfg;
-(void)userContentController:(WKUserContentController*) userContentController didReceiveScriptMessage:(WKScriptMessage*)message;
@end
NS_ASSUME_NONNULL_END
+33
View File
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 8e95116484f503a41b9738e3a4219aea
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
+162
View File
@@ -0,0 +1,162 @@
//
// CustomView.m
// UnityFramework
//
// Created by Mac on 2024/1/19.
//
#import "CustomView.h"
#import "H5View.h"
@implementation CustomView
{
// WKWebView *webview;
// UIView* unityView;
// //ViewCfg config;
// CGPoint hitTestLocation;
// BOOL isTouchWebView;
// BOOL isWebviewOpen;
// BOOL canCT;
int test;
}
+(id) shared{
static CustomView *view = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{view = [[self alloc] init];});
return view;
}
-(void)initView{
// Initialize a WKWebViewConfiguration object.
// UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
// [unityView addGestureRecognizer:gest];
// [gest setDelegate:self];
// CustomGestureDelegate *deleg = [[CustomGestureDelegate alloc] init];
// [gest setDelegate:deleg];
// gest.cancelsTouchesInView = false; // to recieve touchesBegan callback even if gesture is recognized
// gest.delaysTouchesBegan = false; // to not delay touchesBegan callback
// gest.delaysTouchesEnded = false; // to not delay touchesEnded callback
// CustomGestureDelegate *deleg = [[CustomGestureDelegate alloc] init];
// [gest setDelegate:deleg];
// NSTimeInterval delayInSeconds = 7;
// dispatch_time_t popTime2 = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
// dispatch_after(popTime2, dispatch_get_main_queue(), ^(void){
//
// [self loop];
// });
// [self setWebviewPadding:CGRectMake(0, 120, 0, 180)];
}
//-(void)setConfig:(ViewCfg)cfg{
// config = cfg;
//
// webview.frame = config.rect;
// // webview.frame = CGRectMake(0, 100, self.bounds.size.width, 500);
// //canCT = YES;
//}
// -(void)handleTap:(UITapGestureRecognizer*) gest{
// CGPoint pt = [gest locationInView:webview];
// // NSLog(@"GestureRecognizer x:%f, y:%f", pt.x, pt.y);
// // if (gest.state == UIGestureRecognizerStateBegan){
// // NSLog(@"Begin x:%f, y:%f", pt.x, pt.y);
// // }
// if (gest.state == UIGestureRecognizerStateEnded){
// NSLog(@"GestureRecognizer End x:%f, y:%f", pt.x, pt.y);
// }
// }
// //- (void) touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event{
// // UITouch *touch = [[event allTouches] anyObject];
// //
// // CGPoint location = [touch locationInView:self];
// // beginTouches = touches;
// // beginEvent = event;
// // NSLog(@"Touch Began CustomView");
// //}
// //
// //- (void) touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event{
// // UITouch *touch = [[event allTouches] anyObject];
// //
// // CGPoint location = [touch locationInView:self];
// // beginTouches = touches;
// // beginEvent = event;
// // NSLog(@"Touch Ended CustomView");
// //}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//UIView* touchedView = [super hitTest:point withEvent:event];
// if([[H5View shared] isDarkThough]){
// NSLog(@"Point coordinates: x = %f, y = %f", point.x, point.y);
// NSLog(@"Point coordinates: max = %f,",self.bounds.size.width);
UIView* testview = [ [H5View shared]hitTest:point withEvent:event];
return testview;
// }
// else
// return touchedView;
}
// -(void)showWebview:(NSString*)url{
// // NSLog(@"Native showWebview: %@", url);
// NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
// [webview loadRequest:request];
// if (webview.superview == nil)
// [self insertSubview:webview atIndex:0];
// isWebviewOpen = YES;
// }
// -(void)hideWebview{
// // NSLog(@"Native hideWebview");
// [webview removeFromSuperview];
// isWebviewOpen = NO;
// }
// -(void)scrollWebview:(CGPoint)offset{
// CGPoint pt = [webview.scrollView contentOffset];
// if (offset.y < 0 && pt.y <= 0) return;
// float val = pt.y + offset.y*0.5;
// if (val<0) val = 0;
// [webview.scrollView setContentOffset:CGPointMake(0, val)];
// }
// -(void)setTouchWebview:(BOOL)flag forceCT:(BOOL)force{
// if (!isWebviewOpen) return;
// isTouchWebView = flag;
// //unityView.userInteractionEnabled = !flag;
// if (canCT || force){
// if (!CGRectContainsPoint(webview.bounds, hitTestLocation))
// return;
// [self doCT];
// }
// }
// -(void)tapWithPoint:(CGPoint)zspoint{
// [Helpers helpAt:1 AtPoint:zspoint withTouchPhase:UITouchPhaseBegan];
// [Helpers helpAt:1 AtPoint:zspoint withTouchPhase:UITouchPhaseEnded];
// }
// -(void)enableCT:(BOOL)flag{
// // NSLog(@"Native enableCT: %d",flag);
// canCT = flag;
// }
// -(void)doCT{
// NSTimeInterval delayInSeconds = 0.1;
// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// // NSLog(@"CT x:%f, y:%f", self->hitTestLocation.x, self->hitTestLocation.y);
// self->unityView.userInteractionEnabled = false;
// [self tapWithPoint:self->hitTestLocation];
// self->unityView.userInteractionEnabled = true;
// });
// }
@end
+33
View File
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 4103d2c7c9134ec41a226f6b8b794354
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
+20 -66
View File
@@ -2,80 +2,34 @@ fileFormatVersion: 2
guid: 1c0d8a6c9b36440eaa4c01518670217f
labels:
- gvh
- gvh_version-10.6.0
- gvhp_exportpath-Plugins/iOS/GADUAdNetworkExtras.h
timeCreated: 1480838400
PluginImporter:
serializedVersion: 1
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Android:
enabled: 0
settings:
CPU: AnyCPU
Any:
- first:
Any:
second:
enabled: 0
settings: {}
Editor:
enabled: 1
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
- first:
iPhone: iOS
second:
enabled: 1
settings:
CPU: x86
Linux64:
enabled: 1
settings:
CPU: x86_64
LinuxUniversal:
enabled: 1
settings:
CPU: AnyCPU
OSXIntel:
enabled: 1
settings:
CPU: x86
OSXIntel64:
enabled: 1
settings:
CPU: x86_64
OSXUniversal:
enabled: 1
settings:
CPU: AnyCPU
Web:
enabled: 0
settings: {}
WebStreamed:
enabled: 0
settings: {}
Win:
enabled: 1
settings:
CPU: x86
Win64:
enabled: 1
settings:
CPU: x86_64
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
iOS:
enabled: 1
settings:
CompileFlags:
FrameworkDependencies:
tvOS:
enabled: 0
settings:
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
+32
View File
@@ -0,0 +1,32 @@
//
// H5View.h
// TestGameWeb
//
// Created by Mac on 2024/1/30.
//
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface H5View : UIView<WKUIDelegate, WKNavigationDelegate,WKScriptMessageHandler>
+(id) shared;
-(void)initView;
-(void)showWebview:(NSString*)url;
-(void)showDarkWebview:(int)type;
-(void)showView:(BOOL)show;
-(void)setIconProgress:(float)value;
-(void)setViewPadding:(CGRect)rect;
-(void)SetDarkThough:(BOOL)though;
-(void)setViewBtn:(CGRect)rect;
-(void)addH5Field:(int)field1 field2:(int)field2 field3:(int)field3 field4:(int)field4 field5:(int)field5 field6:(char* )field6 field7:(char* )field7 dark_url:(char*)dark_url light_url:(char*)light_url field8:(BOOL)field8 web_through_probability:(char*)web_through_probability click_add_time:(char*)click_add_time ;
-(void)showFlyBtn:(BOOL)flag;
-(void)setInH5View:(BOOL)flag;
-(void)upDataH5times:(char*)weblink times:(int)times is_dark:(BOOL)is_dark;
-(void)setFlyBtnTag:(BOOL)isShow;
-(void)setRewardBtnTag:(BOOL)isShow;
-(void)OpenWv;
@end
@interface H5View (WKNavigationDelegate) <WKNavigationDelegate>
@end
NS_ASSUME_NONNULL_END
+33
View File
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 803bcb50fbbc55041bdeb0bce53cadad
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 0d6ea760436ab504bb83f2ac764687d2
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
// HapticFeedbackManager.h
#import <Foundation/Foundation.h>
@interface HapticFeedbackManager : NSObject
+ (void)TriggerCustomHaptic:(float)intensity sharpness:(float)sharpness duration:(float)duration;
@end
@@ -1,95 +0,0 @@
// HapticFeedbackManager.m
#import "HapticFeedbackManager.h"
#import <CoreHaptics/CoreHaptics.h>
#import <AudioToolbox/AudioToolbox.h>
#import <UIKit/UIKit.h>
@implementation HapticFeedbackManager
static CHHapticEngine *hapticEngine;
+ (void)initializeHapticEngine {
if (!hapticEngine) {
NSError *error = nil;
hapticEngine = [[CHHapticEngine alloc] initAndReturnError:&error];
if (error) {
NSLog(@"Failed to create haptic engine: %@", error.localizedDescription);
} else {
[hapticEngine startWithCompletionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"Failed to start haptic engine: %@", error.localizedDescription);
}
}];
}
}
}
+ (void)TriggerCustomHaptic:(float)intensity sharpness:(float)sharpness duration:(float)duration {
if (@available(iOS 13.0, *)) {
if (![CHHapticEngine capabilitiesForHardware].supportsHaptics) {
NSLog(@"Haptic feedback is not supported on this device.");
[self triggerFallbackHaptic];
return;
}
[self initializeHapticEngine];
NSError *error = nil;
CHHapticEventParameter *intensityParameter = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:intensity];
CHHapticEventParameter *sharpnessParameter = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticSharpness value:sharpness];
CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:@[intensityParameter, sharpnessParameter] relativeTime:0 duration:duration];
CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:@[event] parameters:@[] error:&error];
if (error) {
NSLog(@"Failed to create haptic pattern: %@", error.localizedDescription);
return;
}
id<CHHapticPatternPlayer> player = [hapticEngine createPlayerWithPattern:pattern error:&error];
if (error) {
NSLog(@"Failed to create haptic player: %@", error.localizedDescription);
return;
}
[player startAtTime:CHHapticTimeImmediate error:&error];
if (error) {
NSLog(@"Failed to start haptic player: %@", error.localizedDescription);
}
} else {
NSLog(@"Core Haptics is not available on this version of iOS.");
}
}
+ (void)triggerFallbackHaptic {
// 使用轻微震动作为替代
// UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc]
// initWithStyle:UIImpactFeedbackStyleLight];
// [generator prepare];
// [generator impactOccurred];
// UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc]
// initWithStyle:UIImpactFeedbackStyleHeavy];
// [generator prepare];
// [generator impactOccurred];
// 使用 UINotificationFeedbackGenerator 触发通知风格的震动
// UINotificationFeedbackGenerator *generator = [[UINotificationFeedbackGenerator alloc] init];
// [generator prepare];
// [generator notificationOccurred:UINotificationFeedbackTypeSuccess];
// 使用系统震动
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
#ifdef __cplusplus
extern "C" {
#endif
void TriggerCustomHaptic(float intensity, float sharpness, float duration) { [HapticFeedbackManager TriggerCustomHaptic:intensity sharpness:sharpness duration:duration];
}
#ifdef __cplusplus
}
#endif
@end
@@ -0,0 +1,200 @@
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import <QuartzCore/QuartzCore.h>
extern UIView *UnityGetGLView(void);
@interface UIApplication (UnityTouchHook)
- (void)ut_sendEvent:(UIEvent *)event;
@end
@implementation UIApplication (UnityTouchHook)
// ==========================================
// 【实装优化】:将 Ivar、Class 提取为静态全局变量,在 +load 中一次性缓存
static CFTimeInterval g_lastMovedTime = 0;
static Class g_touchClass = Nil;
static Ivar g_ivarView = NULL;
static Ivar g_ivarLocation = NULL;
static Ivar g_ivarPrevLocation = NULL;
// ==========================================
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = [UIApplication class];
Method original = class_getInstanceMethod(cls, @selector(sendEvent:));
Method swizzled = class_getInstanceMethod(cls, @selector(ut_sendEvent:));
if (original && swizzled) {
method_exchangeImplementations(original, swizzled);
}
// ==========================================
// 【实装优化】:在 +load 时集中初始化,彻底消灭每帧的 Runtime 检索开销
g_touchClass = [UITouch class];
g_ivarView = class_getInstanceVariable(g_touchClass, "_view");
g_ivarLocation = class_getInstanceVariable(g_touchClass, "_locationInWindow");
g_ivarPrevLocation = class_getInstanceVariable(g_touchClass, "_previousLocationInWindow");
// ==========================================
});
}
- (void)ut_sendEvent:(UIEvent *)event
{
// 1. 让系统和 WebView 先走正常响应
[self ut_sendEvent:event];
if (event.type != UIEventTypeTouches)
return;
UIView *unityView = UnityGetGLView();
if (!unityView)
return;
NSSet *touches = event.allTouches;
UITouch *touch = [touches anyObject];
if (!touch)
return;
// 2. 拦截所有来自 WebView 或非 UnityView 的点击
if (touch.view != unityView && ![touch.view isDescendantOfView:unityView]) {
UITouchPhase phase = touch.phase;
if (phase == UITouchPhaseMoved) {
CFTimeInterval currentTime = CACurrentMediaTime();
if (currentTime - g_lastMovedTime < 0.016) {
return;
}
g_lastMovedTime = currentTime;
}
// 【优化成果】:直接使用 self 获取 keyWindow
UIWindow *window = self.keyWindow;
if (!window && unityView.window) {
window = unityView.window;
}
// ==========================================
// 【实装优化】:window == nil 时提前返回,防止后续无意义计算与 KVC 崩溃风险
if (!window) {
return;
}
// ==========================================
// 【优化成果】:提取 locationInView 只计算一次
CGPoint pointInWindow = [touch locationInView:window];
CGPoint pointPrevWindow = [touch previousLocationInView:window];
CGPoint originalLocationStruct = pointInWindow;
CGPoint originalPrevLocationStruct = pointPrevWindow;
// 【优化成果】:砍掉 convertPoint:fromView: 的矩阵计算
CGPoint pointInUnity = pointInWindow;
CGRect unityFrame = unityView.frame;
if (unityFrame.origin.x != 0 || unityFrame.origin.y != 0) {
pointInUnity.x -= unityFrame.origin.x;
pointInUnity.y -= unityFrame.origin.y;
}
// 【优化安全加固】:保留最后一道防线,防御极端情况下的 NaN / Inf
if (isnan(pointInUnity.x) || isinf(pointInUnity.x)) pointInUnity.x = 0;
if (isnan(pointInUnity.y) || isinf(pointInUnity.y)) pointInUnity.y = 0;
// 【优化成果】:在栈上缓存一次 bounds 结构体
CGRect bounds = unityView.bounds;
CGFloat viewWidth = bounds.size.width <= 0 ? 375 : bounds.size.width;
CGFloat viewHeight = bounds.size.height <= 0 ? 812 : bounds.size.height;
// 【优化成果】:改用利于 CPU 分支预测的 if-else 约束范围
if (pointInUnity.x < 0) {
pointInUnity.x = 0;
} else if (pointInUnity.x > viewWidth) {
pointInUnity.x = viewWidth;
}
if (pointInUnity.y < 0) {
pointInUnity.y = 0;
} else if (pointInUnity.y > viewHeight) {
pointInUnity.y = viewHeight;
}
CGPoint finalInjectPoint = pointInUnity;
// 3. 备份原始值(后续无需重复获取 Ivar,直接使用静态全局变量)
UIView *originalView = touch.view;
NSValue *originalLocation = nil;
NSValue *originalPrevLocation = nil;
if (g_ivarLocation) {
originalLocation = [touch valueForKey:@"locationInWindow"];
}
if (g_ivarPrevLocation) {
originalPrevLocation = [touch valueForKey:@"previousLocationInWindow"];
}
// 4. 【强制临时修改】重写原生 touch
if (g_ivarView) {
object_setIvar(touch, g_ivarView, unityView);
} else {
[touch setValue:unityView forKey:@"view"];
}
if (g_ivarLocation) object_setIvar(touch, g_ivarLocation, [NSValue valueWithCGPoint:finalInjectPoint]);
// 计算 Moved 阶段的伪造历史坐标
if (phase == UITouchPhaseMoved && originalLocation && originalPrevLocation) {
CGPoint offset = CGPointMake(originalLocationStruct.x - originalPrevLocationStruct.x, originalLocationStruct.y - originalPrevLocationStruct.y);
CGPoint fakePrevPoint = CGPointMake(finalInjectPoint.x - offset.x, finalInjectPoint.y - offset.y);
if (isnan(fakePrevPoint.x) || isinf(fakePrevPoint.x)) fakePrevPoint.x = finalInjectPoint.x;
if (isnan(fakePrevPoint.y) || isinf(fakePrevPoint.y)) fakePrevPoint.y = finalInjectPoint.y;
if (fakePrevPoint.x < 0) {
fakePrevPoint.x = 0;
} else if (fakePrevPoint.x > viewWidth) {
fakePrevPoint.x = viewWidth;
}
if (fakePrevPoint.y < 0) {
fakePrevPoint.y = 0;
} else if (fakePrevPoint.y > viewHeight) {
fakePrevPoint.y = viewHeight;
}
if (g_ivarPrevLocation) object_setIvar(touch, g_ivarPrevLocation, [NSValue valueWithCGPoint:fakePrevPoint]);
} else {
if (g_ivarPrevLocation) object_setIvar(touch, g_ivarPrevLocation, [NSValue valueWithCGPoint:finalInjectPoint]);
}
[touch setValue:[NSValue valueWithCGPoint:finalInjectPoint] forKey:@"locationInWindow"];
// 5. 将清洗干净的事件丢给 UnityView 通道
switch (phase) {
case UITouchPhaseBegan: [unityView touchesBegan:touches withEvent:event]; break;
case UITouchPhaseMoved: [unityView touchesMoved:touches withEvent:event]; break;
case UITouchPhaseEnded: [unityView touchesEnded:touches withEvent:event]; break;
case UITouchPhaseCancelled: [unityView touchesCancelled:touches withEvent:event]; break;
default: break;
}
// 6. 立刻恢复现场
if (g_ivarView) {
object_setIvar(touch, g_ivarView, originalView);
} else {
[touch setValue:originalView forKey:@"view"];
}
if (g_ivarLocation && originalLocation) {
object_setIvar(touch, g_ivarLocation, originalLocation);
[touch setValue:originalLocation forKey:@"locationInWindow"];
}
if (g_ivarPrevLocation && originalPrevLocation) {
object_setIvar(touch, g_ivarPrevLocation, originalPrevLocation);
}
}
}
@end
@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 4b4b8d72a37ba3f40aef9216b44dbe37
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:
+7
View File
@@ -42,6 +42,13 @@ extern "C"
// 调用trackProduct方法并传递两个参数
[[EventMark sharedEventMark] trackProduct:eventNameString dictionaryJson:jsonString];
}
void copyText(const char* text)
{
NSLog(@"copyText----: %s", text);
// 将C风格的字符串转换为NSString,并调用openURL方法
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = [NSString stringWithUTF8String:text];
}
}
- (void)initDataEyeSDK
{
+32 -10
View File
@@ -1,20 +1,42 @@
#import <UnityFramework/UnityFramework-Swift.h>
extern "C" {
#import "UnityAppController.h"
#include "H5View.h"
NSString *stringFromChar(const char *input) {
return [NSString stringWithUTF8String: input];
}
void ShowH5View(bool flag){//显示明或暗网页
[[H5View shared] showView:flag];
}
void addH5Field(int field1 ,int field2,int field3,int field4,int field5 ,char* field6 ,char* field7 ,char* dark_url,char* light_url, bool field8 , char* web_through_probability, char* click_add_time){
[[H5View shared] addH5Field:field1 field2:field2 field3:field3 field4:field4 field5:field5 field6:field6 field7:field7 dark_url:dark_url light_url:light_url field8:field8 web_through_probability:web_through_probability click_add_time:click_add_time];
}
void SetPadding(float left, float top, float right, float bottom){
[[H5View shared] setViewPadding:CGRectMake(left, top, right, bottom)];
}
void SetDarkThough(bool though){
[[H5View shared] SetDarkThough:though];
}
void openWebview(bool though){
}
void showGameA(bool flag){//显示游戏a
[NativeUIManager showMainMenu];
}
void SetBtn(int left, int top, int right, int bottom){
[[H5View shared] setViewBtn:CGRectMake(left, top, right, bottom)];
}
void SetIconProgress(float val){
[[H5View shared] setIconProgress:val];
}
void ShowFlyBtn(bool show){
[[H5View shared] showFlyBtn:show];
}
void setFlyBtnTag (bool show) {
[[H5View shared] setFlyBtnTag: show];
}
void setRewardBtnTag (bool show) {
[[H5View shared] setRewardBtnTag: show];
}
void OpenWv (bool show) {
[[H5View shared] OpenWv];
}
}
+20 -66
View File
@@ -2,80 +2,34 @@ fileFormatVersion: 2
guid: 52c76a20e90b4b26b396c50aea983ab5
labels:
- gvh
- gvh_version-10.6.0
- gvhp_exportpath-Plugins/iOS/unity-plugin-library.a
timeCreated: 1480838400
PluginImporter:
serializedVersion: 1
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Android:
enabled: 0
settings:
CPU: AnyCPU
Any:
- first:
Any:
second:
enabled: 0
settings: {}
Editor:
enabled: 1
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux:
- first:
iPhone: iOS
second:
enabled: 1
settings:
CPU: x86
Linux64:
enabled: 1
settings:
CPU: x86_64
LinuxUniversal:
enabled: 1
settings:
CPU: AnyCPU
OSXIntel:
enabled: 1
settings:
CPU: x86
OSXIntel64:
enabled: 1
settings:
CPU: x86_64
OSXUniversal:
enabled: 1
settings:
CPU: AnyCPU
Web:
enabled: 0
settings: {}
WebStreamed:
enabled: 0
settings: {}
Win:
enabled: 1
settings:
CPU: x86
Win64:
enabled: 1
settings:
CPU: x86_64
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
iOS:
enabled: 1
settings:
CompileFlags:
FrameworkDependencies:
tvOS:
enabled: 0
settings:
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:
AddToEmbeddedBinaries: true
userData:
assetBundleName:
assetBundleVariant: