├── Preview.PNG ├── espff.plist ├── control ├── Vector3.h ├── KittyMemory ├── KittyUtils.hpp ├── MemoryBackup.hpp ├── writeData.cpp ├── writeData.hpp ├── MemoryPatch.hpp ├── MemoryBackup.cpp ├── KittyUtils.cpp ├── MemoryPatch.cpp ├── KittyMemory.hpp └── KittyMemory.cpp ├── SCLAlertView ├── SCLTextView.h ├── SCLAlertViewResponder.h ├── SCLSwitchView.h ├── SCLAlertViewResponder.m ├── SCLTimerDisplay.h ├── SCLTextView.m ├── SCLMacros.h ├── SCLAlertViewStyleKit.h ├── SCLButton.h ├── SCLSwitchView.m ├── SCLTimerDisplay.m ├── SCLButton.m ├── UIImage+ImageEffects.h ├── UIImage+ImageEffects.m ├── SCLAlertViewStyleKit.m └── SCLAlertView.h ├── esp.h ├── README.md ├── LICENSE ├── Makefile ├── Macros.h ├── Menu.h ├── esp.mm ├── Obfuscate.h ├── Vector3.hpp ├── Quaternion.hpp └── Menu.mm /Preview.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/34306/ESP_FreeFire/HEAD/Preview.PNG -------------------------------------------------------------------------------- /espff.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.dts.freefireth" 5 | ); 6 | }; 7 | } -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.34306.espff 2 | Name: ESP Free Fire Mod Menu 3 | Depends: mobilesubstrate 4 | Version: 1.93.1 5 | Architecture: iphoneos-arm 6 | Description: Free Fire Mod Menu by 34306! 7 | Maintainer: Little 34306 8 | Author: 34306 9 | Section: Tweaks 10 | 11 | -------------------------------------------------------------------------------- /Vector3.h: -------------------------------------------------------------------------------- 1 | struct Vector3{ 2 | float x; 3 | float y; 4 | float z; 5 | 6 | Vector3(); 7 | Vector3(float x, float y, float z); 8 | ~Vector3(); 9 | }; 10 | 11 | Vector3::Vector3() {} 12 | Vector3::Vector3(float x, float y, float z) : x(x), y(y), z(z) {} 13 | Vector3::~Vector3() {} -------------------------------------------------------------------------------- /KittyMemory/KittyUtils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace KittyUtils { 7 | 8 | bool validateHexString(std::string &xstr); 9 | void toHex(void *const data, const size_t dataLength, std::string &dest); 10 | void fromHex(const std::string &in, void *const data); 11 | 12 | } -------------------------------------------------------------------------------- /SCLAlertView/SCLTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTextView.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | 15 | @interface SCLTextView : UITextField 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /esp.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | struct player_t { 4 | CGRect rect; 5 | CGRect healthbar; 6 | CGPoint topofbox; 7 | CGPoint bottomofbox; 8 | float health; 9 | bool enemy; 10 | float distance; 11 | }; 12 | @interface esp : UIView 13 | @property bool espboxes; 14 | @property bool esplines; 15 | @property bool healthbarr; 16 | @property bool distanceesp; 17 | @property std::vector *players; 18 | - (void)callupdate; 19 | - (void)drawRect:(CGRect)rect; 20 | - (id)initWithFrame:(UIWindow*)main; 21 | @end 22 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewResponder.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewResponder.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import Foundation; 11 | #else 12 | #import 13 | #endif 14 | #import "SCLAlertView.h" 15 | 16 | @interface SCLAlertViewResponder : NSObject 17 | 18 | /** TODO 19 | * 20 | * TODO 21 | */ 22 | - (instancetype)init:(SCLAlertView *)alertview; 23 | 24 | /** TODO 25 | * 26 | * TODO 27 | */ 28 | - (void)close; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SCLAlertView/SCLSwitchView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLSwitchView.h 3 | // SCLAlertView 4 | // 5 | // Created by André Felipe Santos on 27/01/16. 6 | // Copyright (c) 2016-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | 15 | @interface SCLSwitchView : UIView 16 | 17 | @property (strong, nonatomic) UIColor *tintColor UI_APPEARANCE_SELECTOR; 18 | @property (strong, nonatomic) UIColor *labelColor UI_APPEARANCE_SELECTOR; 19 | @property (strong, nonatomic) UIFont *labelFont UI_APPEARANCE_SELECTOR; 20 | @property (strong, nonatomic) NSString *labelText UI_APPEARANCE_SELECTOR; 21 | @property (nonatomic, getter=isSelected) BOOL selected; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP FreeFire 2 | 3 |
4 | ESP source code for Free Fire (iOS jailbreak, Free Fire version: 1.93.1).

5 | 6 | 7 |
8 | 9 | ___ 10 |
11 | 12 | ### This source is for learning purpose only, please do not use it for commercial purpose! 13 | - Known issue: Maybe it's laggy when play on Survival Mode, you can fix it yourself by limit the distance that draw the ESP. 14 | ### Many thanks to 15 | - [Kitty Memory](https://github.com/MJx0/KittyMemory) by [MJx0](https://github.com/MJx0) 16 | - [Ted 2 Template menu](https://github.com/joeyjurjens/iOS-Mod-Menu-Template-for-Theos) by [joeyjurjens](https://github.com/joeyjurjens) 17 | - And Zeus from [iOSGods](https://iosgods.com) 18 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewResponder.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewResponder.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLAlertViewResponder.h" 10 | 11 | @interface SCLAlertViewResponder () 12 | 13 | @property SCLAlertView *alertview; 14 | 15 | @end 16 | 17 | @implementation SCLAlertViewResponder 18 | 19 | // 20 | //// Allow alerts to be closed/renamed in a chainable manner 21 | //// Example: SCLAlertView().showSuccess(self, title: "Test", subTitle: "Value").close() 22 | 23 | // Initialisation and Title/Subtitle/Close functions 24 | - (instancetype)init:(SCLAlertView *)alertview 25 | { 26 | self.alertview = alertview; 27 | return self; 28 | } 29 | 30 | - (void)setTitletitle:(NSString *)title 31 | { 32 | self.alertview.labelTitle.text = title; 33 | } 34 | 35 | - (void)setSubTitle:(NSString *)subTitle 36 | { 37 | self.alertview.viewText.text = subTitle; 38 | } 39 | 40 | - (void)close 41 | { 42 | [self.alertview hideView]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Huy Nguyen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SCLAlertView/SCLTimerDisplay.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTimerDisplay.h 3 | // SCLAlertView 4 | // 5 | // Created by Taylor Ryan on 8/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | // Taken from https://stackoverflow.com/questions/11783439/uibutton-with-timer 9 | 10 | #if defined(__has_feature) && __has_feature(modules) 11 | @import UIKit; 12 | #else 13 | #import 14 | #endif 15 | #import "SCLButton.h" 16 | 17 | @interface SCLTimerDisplay : UIView { 18 | CGFloat currentAngle; 19 | CGFloat currentTime; 20 | CGFloat timerLimit; 21 | CGFloat radius; 22 | CGFloat lineWidth; 23 | NSTimer *timer; 24 | SCLActionBlock completedBlock; 25 | } 26 | 27 | @property CGFloat currentAngle; 28 | @property NSInteger buttonIndex; 29 | @property (strong, nonatomic) UIColor *color; 30 | @property (assign, nonatomic) BOOL reverse; 31 | 32 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r; 33 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r lineWidth:(CGFloat)width; 34 | - (void)updateFrame:(CGSize)size; 35 | - (void)cancelTimer; 36 | - (void)stopTimer; 37 | - (void)startTimerWithTimeLimit:(int)tl completed:(SCLActionBlock)completed; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /KittyMemory/MemoryBackup.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryBackup.hpp 3 | // 4 | // Created by MJ (Ruit) on 4/19/20. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include "KittyMemory.hpp" 12 | 13 | class MemoryBackup { 14 | private: 15 | void *_address; 16 | size_t _size; 17 | 18 | std::vector _orig_code; 19 | 20 | std::string _hexString; 21 | 22 | public: 23 | MemoryBackup(); 24 | 25 | /* 26 | * expects library name and relative address 27 | */ 28 | MemoryBackup(const char *fileName, uint64_t address, size_t backup_size); 29 | 30 | /* 31 | * expects absolute address 32 | */ 33 | MemoryBackup(uint64_t absolute_address, size_t backup_size); 34 | 35 | 36 | ~MemoryBackup(); 37 | 38 | 39 | /* 40 | * Validate patch 41 | */ 42 | bool isValid() const; 43 | 44 | 45 | size_t get_BackupSize() const; 46 | 47 | /* 48 | * Returns pointer to the target address 49 | */ 50 | void *get_TargetAddress() const; 51 | 52 | 53 | /* 54 | * Restores backup code 55 | */ 56 | bool Restore(); 57 | 58 | 59 | /* 60 | * Returns current target address bytes as hex string 61 | */ 62 | std::string get_CurrBytes(); 63 | }; 64 | -------------------------------------------------------------------------------- /SCLAlertView/SCLTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTextView.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLTextView.h" 10 | 11 | #define MIN_HEIGHT 30.0f 12 | 13 | @implementation SCLTextView 14 | 15 | - (instancetype)init 16 | { 17 | self = [super init]; 18 | if (self) 19 | { 20 | [self setup]; 21 | } 22 | return self; 23 | } 24 | 25 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 26 | { 27 | self = [super initWithCoder:aDecoder]; 28 | if(self) 29 | { 30 | [self setup]; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithFrame:(CGRect)frame 36 | { 37 | self = [super initWithFrame:frame]; 38 | if (self) 39 | { 40 | [self setup]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void)setup 46 | { 47 | self.frame = CGRectMake(0.0f, 0.0f, 0.0f, MIN_HEIGHT); 48 | self.returnKeyType = UIReturnKeyDone; 49 | self.borderStyle = UITextBorderStyleRoundedRect; 50 | self.autocapitalizationType = UITextAutocapitalizationTypeSentences; 51 | self.clearButtonMode = UITextFieldViewModeWhileEditing; 52 | self.layer.masksToBounds = YES; 53 | self.layer.borderWidth = 1.0f; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SCLAlertView/SCLMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLMacros.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 10/03/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #ifndef SCL_MACROS_H 10 | #define SCL_MACROS_H 11 | 12 | #define UIColorFromHEX(rgbValue) [UIColor \ 13 | colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ 14 | green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \ 15 | blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 16 | 17 | #define DEGREES_TO_RADIANS(degrees) ((M_PI * degrees)/ 180) 18 | #define TIMER_STEP .01 19 | #define START_DEGREE_OFFSET -90 20 | 21 | #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) 22 | #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) 23 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 24 | #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 25 | #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /KittyMemory/writeData.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // writeData.cpp 3 | // 4 | // 5 | // Created by MJ (Ruit) on 4/13/19. 6 | // 7 | 8 | 9 | /* 10 | This is an alternative for the old writeData that was made by HackJack & Razzile 11 | */ 12 | 13 | #include "writeData.hpp" 14 | 15 | 16 | 17 | bool writeData8(uint64_t offset, uint8_t data) 18 | { 19 | const size_t sz = sizeof(uint8_t); 20 | 21 | // pass NULL as fileName for base executable 22 | return MemoryPatch(NULL, /* relative address */ offset, /* patch bytes */ &data, /* patch bytes length */ sz).Modify(); 23 | } 24 | 25 | bool writeData16(uint64_t offset, uint16_t data) 26 | { 27 | const size_t sz = sizeof(uint16_t); 28 | SwapData(data); 29 | 30 | // pass NULL as fileName for base executable 31 | return MemoryPatch(NULL, /* relative address */ offset, /* patch bytes */ &data, /* patch bytes length */ sz).Modify(); 32 | } 33 | 34 | bool writeData32(uint64_t offset, uint32_t data) 35 | { 36 | const size_t sz = sizeof(uint32_t); 37 | SwapData(data); 38 | 39 | // pass NULL as fileName for base executable 40 | return MemoryPatch(NULL, /* relative address */ offset, /* patch bytes */ &data, /* patch bytes length */ sz).Modify(); 41 | } 42 | 43 | 44 | bool writeData64(uint64_t offset, uint64_t data) 45 | { 46 | const size_t sz = sizeof(uint64_t); 47 | SwapData(data); 48 | 49 | // pass NULL as fileName for base executable 50 | return MemoryPatch(NULL, /* relative address */ offset, /* patch bytes */ &data, /* patch bytes length */ sz).Modify(); 51 | } 52 | -------------------------------------------------------------------------------- /KittyMemory/writeData.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // writeData.h 3 | // 4 | // 5 | // Created by MJ (Ruit) on 4/13/19. 6 | // 7 | 8 | 9 | /* 10 | This is an alternative for the old writeData that was made by HackJack & Razzile 11 | */ 12 | 13 | 14 | #ifndef writeData_h 15 | #define writeData_h 16 | 17 | #include 18 | #include "MemoryPatch.hpp" 19 | 20 | 21 | #define BITS_IN_BYTE 8 22 | 23 | 24 | // https://www.exploringbinary.com/number-of-bits-in-a-decimal-integer/ 25 | // returns bits size of an integer 26 | inline int findBits(uint64_t n) 27 | { 28 | if(n > 0) 29 | { 30 | return floor(log(n)/log(2))+1; 31 | } 32 | return 0; 33 | } 34 | 35 | 36 | // returns bytes size of an integer 37 | inline size_t findBytes(uint64_t data) 38 | { 39 | int bits = findBits(data); 40 | if(bits > 0) 41 | { 42 | return (size_t)(bits / BITS_IN_BYTE); 43 | } 44 | return 0; 45 | } 46 | 47 | 48 | template 49 | void SwapData(T& data) 50 | { 51 | const size_t sz = sizeof(T); 52 | switch (sz) 53 | { 54 | case sizeof(int16_t): 55 | data = _OSSwapInt16(data); 56 | break; 57 | case sizeof(int32_t): 58 | data = _OSSwapInt32(data); 59 | break; 60 | case sizeof(int64_t): 61 | data = _OSSwapInt64(data); 62 | break; 63 | default: 64 | break; 65 | } 66 | } 67 | 68 | bool writeData8 (uint64_t offset, uint8_t data); 69 | bool writeData16(uint64_t offset, uint16_t data); 70 | bool writeData32(uint64_t offset, uint32_t data); 71 | bool writeData64(uint64_t offset, uint64_t data); 72 | 73 | #endif /* writeData.h */ -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewStyleKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewStyleKit.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import Foundation; 11 | @import UIKit; 12 | #else 13 | #import 14 | #import 15 | #endif 16 | #import "SCLButton.h" 17 | 18 | @interface SCLAlertViewStyleKit : NSObject 19 | 20 | // Images 21 | /** TODO 22 | * 23 | * TODO 24 | */ 25 | + (UIImage *)imageOfCheckmark; 26 | 27 | /** TODO 28 | * 29 | * TODO 30 | */ 31 | + (UIImage *)imageOfCross; 32 | 33 | /** TODO 34 | * 35 | * TODO 36 | */ 37 | + (UIImage *)imageOfNotice; 38 | 39 | /** TODO 40 | * 41 | * TODO 42 | */ 43 | + (UIImage *)imageOfWarning; 44 | 45 | /** TODO 46 | * 47 | * TODO 48 | */ 49 | + (UIImage *)imageOfInfo; 50 | 51 | /** TODO 52 | * 53 | * TODO 54 | */ 55 | + (UIImage *)imageOfEdit; 56 | 57 | /** TODO 58 | * 59 | * TODO 60 | */ 61 | + (UIImage *)imageOfQuestion; 62 | 63 | /** TODO 64 | * 65 | * TODO 66 | */ 67 | + (void)drawCheckmark; 68 | 69 | /** TODO 70 | * 71 | * TODO 72 | */ 73 | + (void)drawCross; 74 | 75 | /** TODO 76 | * 77 | * TODO 78 | */ 79 | + (void)drawNotice; 80 | 81 | /** TODO 82 | * 83 | * TODO 84 | */ 85 | + (void)drawWarning; 86 | 87 | /** TODO 88 | * 89 | * TODO 90 | */ 91 | + (void)drawInfo; 92 | 93 | /** TODO 94 | * 95 | * TODO 96 | */ 97 | + (void)drawEdit; 98 | 99 | /** TODO 100 | * 101 | * TODO 102 | */ 103 | + (void)drawQuestion; 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /KittyMemory/MemoryPatch.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryPatch.h 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include "KittyMemory.hpp" 12 | #include "KittyUtils.hpp" 13 | 14 | 15 | class MemoryPatch { 16 | private: 17 | void *_address; 18 | size_t _size; 19 | 20 | std::vector _orig_code; 21 | std::vector _patch_code; 22 | 23 | std::string _hexString; 24 | 25 | public: 26 | MemoryPatch(); 27 | 28 | /* 29 | * expects an already calculated address 30 | */ 31 | MemoryPatch(uint64_t absolute_address, 32 | const void *patch_code, size_t patch_size); 33 | 34 | /* 35 | * expects file name and relative address, you can pass NULL as filename for base executable 36 | */ 37 | MemoryPatch(const char *fileName, uint64_t address, 38 | const void *patch_code, size_t patch_size); 39 | 40 | 41 | ~MemoryPatch(); 42 | 43 | /* 44 | * compatible hex format (0xffff & ffff & ff ff) 45 | */ 46 | static MemoryPatch createWithHex(const char *fileName, uint64_t address, std::string hex); 47 | static MemoryPatch createWithHex(uint64_t absolute_address, std::string hex); 48 | 49 | /* 50 | * Validate patch 51 | */ 52 | bool isValid() const; 53 | 54 | 55 | size_t get_PatchSize() const; 56 | 57 | /* 58 | * Returns pointer to the target address 59 | */ 60 | void *get_TargetAddress() const; 61 | 62 | 63 | /* 64 | * Restores patch to original value 65 | */ 66 | bool Restore(); 67 | 68 | 69 | /* 70 | * Applies patch modifications to target address 71 | */ 72 | bool Modify(); 73 | 74 | 75 | /* 76 | * Returns current patch target address bytes as hex string 77 | */ 78 | std::string get_CurrBytes(); 79 | }; -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # THEOS_DEVICE_IP = 127.0.0.1 -p 2222 # install to device from pc 2 | ARCHS = arm64 3 | DEBUG = 0 4 | FINALPACKAGE = 1 5 | FOR_RELEASE = 1 6 | 7 | # 0 to treat warnings as errors, 1 otherwise. 8 | IGNORE_WARNINGS=1 9 | 10 | # only set this to 1 if you are on mobile theos 11 | # assuming you have an sdk at your theos sdks directory 12 | # this will include c++ headers and other needed headers for your project so you don't need to manually include them or something like that 13 | # if some c++ headers are still missing in your sdk like "initializer_list" then manually copy them to your c++ headers directory and not your project folder 14 | # for example in my case c++ headers directory is located at /private/var/theos/sdks/iPhoneOS11.2.sdk/usr/include/c++/4.2.1/ 15 | # please note, do not include c++ headers in your theos includes to enable c++ which is a ghetto solution and use this approach instead 16 | MOBILE_THEOS=1 17 | ifeq ($(MOBILE_THEOS),1) 18 | # path to your sdk 19 | SDK_PATH = $(THEOS)/sdks/iPhoneOS11.2.sdk/ 20 | $(info ===> Setting SYSROOT to $(SDK_PATH)...) 21 | SYSROOT = $(SDK_PATH) 22 | else 23 | TARGET = iphone:clang:latest:8.0 24 | endif 25 | 26 | 27 | ## Common frameworks ## 28 | PROJ_COMMON_FRAMEWORKS = UIKit Foundation Security QuartzCore CoreGraphics CoreText 29 | 30 | ## source files ## 31 | KITTYMEMORY_SRC = $(wildcard KittyMemory/*.cpp) 32 | SCLALERTVIEW_SRC = $(wildcard SCLAlertView/*.m) 33 | MENU_SRC = Menu.mm 34 | 35 | include $(THEOS)/makefiles/common.mk 36 | 37 | TWEAK_NAME = espff 38 | 39 | $(TWEAK_NAME)_CFLAGS = -fobjc-arc 40 | $(TWEAK_NAME)_CCFLAGS = -std=c++11 -fno-rtti -fno-exceptions -DNDEBUG 41 | 42 | ifeq ($(IGNORE_WARNINGS),1) 43 | $(TWEAK_NAME)_CFLAGS += -w 44 | $(TWEAK_NAME)_CCFLAGS += -w 45 | endif 46 | 47 | 48 | $(TWEAK_NAME)_FILES = Tweak.xm $(MENU_SRC) $(KITTYMEMORY_SRC) $(SCLALERTVIEW_SRC) esp.mm 49 | 50 | $(TWEAK_NAME)_LIBRARIES += substrate 51 | 52 | $(TWEAK_NAME)_FRAMEWORKS = $(PROJ_COMMON_FRAMEWORKS) 53 | # GO_EASY_ON_ME = 1 54 | 55 | include $(THEOS_MAKE_PATH)/tweak.mk 56 | 57 | internal-package-check:: 58 | 59 | after-install:: 60 | install.exec "killall -9 || :" 61 | -------------------------------------------------------------------------------- /KittyMemory/MemoryBackup.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryBackup.cpp 3 | // 4 | // Created by MJ (Ruit) on 4/19/20. 5 | // 6 | 7 | #include "MemoryBackup.hpp" 8 | 9 | 10 | MemoryBackup::MemoryBackup() { 11 | _address = 0; 12 | _size = 0; 13 | _orig_code.clear(); 14 | } 15 | 16 | MemoryBackup::MemoryBackup(const char *fileName, uint64_t address, size_t backup_size) { 17 | MemoryBackup(); 18 | 19 | if (address == 0 || backup_size < 1) 20 | return; 21 | 22 | _address = reinterpret_cast(KittyMemory::getAbsoluteAddress(fileName, address)); 23 | if(_address == NULL) return; 24 | 25 | _size = backup_size; 26 | 27 | _orig_code.resize(backup_size); 28 | 29 | // backup current content 30 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), backup_size); 31 | } 32 | 33 | 34 | MemoryBackup::MemoryBackup(uint64_t absolute_address, size_t backup_size) { 35 | MemoryBackup(); 36 | 37 | if (absolute_address == 0 || backup_size < 1) 38 | return; 39 | 40 | _address = reinterpret_cast(absolute_address); 41 | 42 | _size = backup_size; 43 | 44 | _orig_code.resize(backup_size); 45 | 46 | // backup current content 47 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), backup_size); 48 | } 49 | 50 | MemoryBackup::~MemoryBackup() { 51 | // clean up 52 | _orig_code.clear(); 53 | } 54 | 55 | 56 | bool MemoryBackup::isValid() const { 57 | return (_address != 0 && _size > 0 58 | && _orig_code.size() == _size); 59 | } 60 | 61 | size_t MemoryBackup::get_BackupSize() const{ 62 | return _size; 63 | } 64 | 65 | void *MemoryBackup::get_TargetAddress() const{ 66 | return _address; 67 | } 68 | 69 | bool MemoryBackup::Restore() { 70 | if (!isValid()) return false; 71 | return KittyMemory::memWrite(reinterpret_cast(_address), &_orig_code[0], _size) == KittyMemory::SUCCESS; 72 | } 73 | 74 | std::string MemoryBackup::get_CurrBytes() { 75 | if (!isValid()) 76 | _hexString = std::string("0xInvalid"); 77 | else 78 | _hexString = KittyMemory::read2HexStr(reinterpret_cast(_address), _size); 79 | 80 | return _hexString; 81 | } 82 | -------------------------------------------------------------------------------- /Macros.h: -------------------------------------------------------------------------------- 1 | // 2 | // Macros.h 3 | // ModMenu 4 | // 5 | // Created by Joey on 4/2/19. 6 | // Copyright © 2019 Joey. All rights reserved. 7 | // 8 | 9 | #include "Menu.h" 10 | #import "KittyMemory/writeData.hpp" 11 | 12 | #include 13 | #include 14 | 15 | // definition at Menu.h 16 | extern Menu *menu; 17 | extern Switches *switches; 18 | 19 | // thanks to shmoo for the usefull stuff under this comment. 20 | #define timer(sec) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, sec * NSEC_PER_SEC), dispatch_get_main_queue(), ^ 21 | #define HOOK(offset, ptr, orig) MSHookFunction((void *)getRealOffset(offset), (void *)ptr, (void **)&orig) 22 | #define HOOK_NO_ORIG(offset, ptr) MSHookFunction((void *)getRealOffset(offset), (void *)ptr, NULL) 23 | 24 | // Note to not prepend an underscore to the symbol. See Notes on the Apple manpage (https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html) 25 | #define HOOKSYM(sym, ptr, org) MSHookFunction((void*)dlsym((void *)RTLD_DEFAULT, sym), (void *)ptr, (void **)&org) 26 | #define HOOKSYM_NO_ORIG(sym, ptr) MSHookFunction((void*)dlsym((void *)RTLD_DEFAULT, sym), (void *)ptr, NULL) 27 | #define getSym(symName) dlsym((void *)RTLD_DEFAULT, symName) 28 | 29 | // Convert hex color to UIColor, usage: For the color #BD0000 you'd use: UIColorFromHex(0xBD0000) 30 | #define UIColorFromHex(hexColor) [UIColor colorWithRed:((float)((hexColor & 0xFF0000) >> 16))/255.0 green:((float)((hexColor & 0xFF00) >> 8))/255.0 blue:((float)(hexColor & 0xFF))/255.0 alpha:1.0] 31 | 32 | uint64_t getRealOffset(uint64_t offset){ 33 | return KittyMemory::getAbsoluteAddress([menu getFrameworkName], offset); 34 | } 35 | 36 | // Patching a offset without switch. 37 | void patchOffset(uint64_t offset, std::string hexBytes) { 38 | MemoryPatch patch = MemoryPatch::createWithHex([menu getFrameworkName], offset, hexBytes); 39 | if(!patch.isValid()){ 40 | [menu showPopup:@"Invalid patch" description:[NSString stringWithFormat:@"Failing offset: 0x%llx, please re-check the hex you entered.", offset]]; 41 | return; 42 | } 43 | if(!patch.Modify()) { 44 | [menu showPopup:@"Something went wrong!" description:[NSString stringWithFormat:@"Something went wrong while patching this offset: %llu", offset]]; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /KittyMemory/KittyUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "KittyUtils.hpp" 2 | 3 | static void xtrim(std::string &hex){ 4 | if(hex.compare(0, 2, "0x") == 0){ 5 | hex.erase(0, 2); 6 | } 7 | 8 | // https://www.techiedelight.com/remove-whitespaces-string-cpp/ 9 | hex.erase(std::remove_if(hex.begin(), hex.end(), [](char c){ 10 | return (c == ' ' || c == '\n' || c == '\r' || 11 | c == '\t' || c == '\v' || c == '\f'); 12 | }), 13 | hex.end()); 14 | } 15 | 16 | 17 | bool KittyUtils::validateHexString(std::string &xstr){ 18 | if(xstr.length() < 2) return false; 19 | xtrim(xstr); // first remove spaces 20 | if(xstr.length() % 2 != 0) return false; 21 | for(size_t i = 0; i < xstr.length(); i++){ 22 | if(!std::isxdigit((unsigned char)xstr[i])){ 23 | return false; 24 | } 25 | } 26 | return true; 27 | } 28 | 29 | 30 | // https://tweex.net/post/c-anything-tofrom-a-hex-string/ 31 | #include 32 | #include 33 | 34 | 35 | // ------------------------------------------------------------------ 36 | /*! 37 | Convert a block of data to a hex string 38 | */ 39 | void KittyUtils::toHex( 40 | void *const data, //!< Data to convert 41 | const size_t dataLength, //!< Length of the data to convert 42 | std::string &dest //!< Destination string 43 | ) 44 | { 45 | unsigned char *byteData = reinterpret_cast(data); 46 | std::stringstream hexStringStream; 47 | 48 | hexStringStream << std::hex << std::setfill('0'); 49 | for(size_t index = 0; index < dataLength; ++index) 50 | hexStringStream << std::setw(2) << static_cast(byteData[index]); 51 | dest = hexStringStream.str(); 52 | } 53 | 54 | 55 | // ------------------------------------------------------------------ 56 | /*! 57 | Convert a hex string to a block of data 58 | */ 59 | void KittyUtils::fromHex( 60 | const std::string &in, //!< Input hex string 61 | void *const data //!< Data store 62 | ) 63 | { 64 | size_t length = in.length(); 65 | unsigned char *byteData = reinterpret_cast(data); 66 | 67 | std::stringstream hexStringStream; hexStringStream >> std::hex; 68 | for(size_t strIndex = 0, dataIndex = 0; strIndex < length; ++dataIndex) 69 | { 70 | // Read out and convert the string two characters at a time 71 | const char tmpStr[3] = { in[strIndex++], in[strIndex++], 0 }; 72 | 73 | // Reset and fill the string stream 74 | hexStringStream.clear(); 75 | hexStringStream.str(tmpStr); 76 | 77 | // Do the conversion 78 | int tmpValue = 0; 79 | hexStringStream >> tmpValue; 80 | byteData[dataIndex] = static_cast(tmpValue); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Menu.h: -------------------------------------------------------------------------------- 1 | // 2 | // Menu.h 3 | // ModMenu 4 | // 5 | // Created by Joey on 3/14/19. 6 | // Copyright © 2019 Joey. All rights reserved. 7 | // 8 | 9 | #import "UIKit/UIKit.h" 10 | #import "KittyMemory/MemoryPatch.hpp" 11 | #import "SCLAlertView/SCLAlertView.h" 12 | 13 | #import 14 | #import 15 | 16 | @class OffsetSwitch; 17 | @class TextFieldSwitch; 18 | @class SliderSwitch; 19 | @class Switches; 20 | 21 | @interface Menu : UIView 22 | 23 | -(id)initWithTitle:(NSString *)title_ titleColor:(UIColor *)titleColor_ titleFont:(NSString *)titleFont_ credits:(NSString *)credits_ headerColor:(UIColor *)headerColor_ switchOffColor:(UIColor *)switchOffColor_ switchOnColor:(UIColor *)switchOnColor_ switchTitleFont:(NSString *)switchTitleFont_ switchTitleColor:(UIColor *)switchTitleColor_ infoButtonColor:(UIColor *)infoButtonColor_ maxVisibleSwitches:(int)maxVisibleSwitches_ menuWidth:(CGFloat )menuWidth_ menuIcon:(NSString *)menuIconBase64_ menuButton:(NSString *)menuButtonBase64_; 24 | -(void)setFrameworkName:(const char *)name_; 25 | -(const char *)getFrameworkName; 26 | 27 | 28 | -(void)showMenuButton; 29 | -(void)addSwitchToMenu:(id)switch_; 30 | -(void)showPopup:(NSString *)title_ description:(NSString *)description_; 31 | 32 | @end 33 | 34 | @interface OffsetSwitch : UIButton { 35 | NSString *preferencesKey; 36 | NSString *description; 37 | UILabel *switchLabel; 38 | } 39 | 40 | - (id)initHackNamed:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::vector)offsets_ bytes:(std::vector)bytes_; 41 | -(void)showInfo:(UIGestureRecognizer *)gestureRec; 42 | 43 | -(NSString *)getPreferencesKey; 44 | -(NSString *)getDescription; 45 | - (std::vector)getMemoryPatches; 46 | 47 | 48 | @end 49 | 50 | @interface TextFieldSwitch : OffsetSwitch { 51 | NSString *switchValueKey; 52 | } 53 | 54 | - (id)initTextfieldNamed:(NSString *)hackName_ description:(NSString *)description_ inputBorderColor:(UIColor *)inputBorderColor_; 55 | 56 | -(NSString *)getSwitchValueKey; 57 | 58 | @end 59 | 60 | @interface SliderSwitch : TextFieldSwitch 61 | 62 | - (id)initSliderNamed:(NSString *)hackName_ description:(NSString *)description_ minimumValue:(float)minimumValue_ maximumValue:(float)maximumValue_ sliderColor:(UIColor *)sliderColor_; 63 | 64 | @end 65 | 66 | 67 | @interface Switches : UIButton 68 | 69 | -(void)addSwitch:(NSString *)hackName_ description:(NSString *)description_; 70 | 71 | - (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::initializer_list)offsets_ bytes:(std::initializer_list)bytes_; 72 | 73 | - (void)addTextfieldSwitch:(NSString *)hackName_ description:(NSString *)description_ inputBorderColor:(UIColor *)inputBorderColor_; 74 | 75 | - (void)addSliderSwitch:(NSString *)hackName_ description:(NSString *)description_ minimumValue:(float)minimumValue_ maximumValue:(float)maximumValue_ sliderColor:(UIColor *)sliderColor_; 76 | 77 | - (NSString *)getValueFromSwitch:(NSString *)name; 78 | -(bool)isSwitchOn:(NSString *)switchName; 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /SCLAlertView/SCLButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLButton.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | 15 | @class SCLTimerDisplay; 16 | 17 | @interface SCLButton : UIButton 18 | 19 | typedef void (^SCLActionBlock)(void); 20 | typedef BOOL (^SCLValidationBlock)(void); 21 | typedef NSDictionary* (^CompleteButtonFormatBlock)(void); 22 | typedef NSDictionary* (^ButtonFormatBlock)(void); 23 | 24 | // Action Types 25 | typedef NS_ENUM(NSInteger, SCLActionType) 26 | { 27 | SCLNone, 28 | SCLSelector, 29 | SCLBlock 30 | }; 31 | 32 | /** Set button action type. 33 | * 34 | * Holds the button action type. 35 | */ 36 | @property SCLActionType actionType; 37 | 38 | /** Set action button block. 39 | * 40 | * TODO 41 | */ 42 | @property (copy, nonatomic) SCLActionBlock actionBlock; 43 | 44 | /** Set Validation button block. 45 | * 46 | * Set one kind of validation and keeps the alert visible until the validation is successful 47 | */ 48 | @property (copy, nonatomic) SCLValidationBlock validationBlock; 49 | 50 | /** Set Complete button format block. 51 | * 52 | * Holds the complete button format block. 53 | * Support keys : backgroundColor, borderWidth, borderColor, textColor 54 | */ 55 | @property (copy, nonatomic) CompleteButtonFormatBlock completeButtonFormatBlock; 56 | 57 | /** Set button format block. 58 | * 59 | * Holds the button format block. 60 | * Support keys : backgroundColor, borderWidth, borderColor, textColor 61 | */ 62 | @property (copy, nonatomic) ButtonFormatBlock buttonFormatBlock; 63 | 64 | /** Set SCLButton color. 65 | * 66 | * Set SCLButton color. 67 | */ 68 | @property (strong, nonatomic) UIColor *defaultBackgroundColor UI_APPEARANCE_SELECTOR; 69 | 70 | /** Set Target object. 71 | * 72 | * Target is an object that holds the information necessary to send a message to another object when an event occurs. 73 | */ 74 | @property id target; 75 | 76 | /** Set selector id. 77 | * 78 | * A selector is the name used to select a method to execute for an object, 79 | * or the unique identifier that replaces the name when the source code is compiled. 80 | */ 81 | @property SEL selector; 82 | 83 | /** Parse button configuration 84 | * 85 | * Parse ButtonFormatBlock and CompleteButtonFormatBlock setting custom configuration. 86 | * Set keys : backgroundColor, borderWidth, borderColor, textColor 87 | */ 88 | - (void)parseConfig:(NSDictionary *)buttonConfig; 89 | 90 | /** Set button timer. 91 | * 92 | * Holds the button timer, if present. 93 | */ 94 | @property (strong, nonatomic) SCLTimerDisplay *timer; 95 | 96 | /** Init method 97 | * 98 | */ 99 | - (instancetype)initWithWindowWidth:(CGFloat)windowWidth; 100 | 101 | /** Adjust width of the button according to the width of the alert and 102 | * the number of buttons. Only used when buttons are horizontally aligned. 103 | * 104 | * @param windowWidth The width of the alert. 105 | * @param numberOfButtons The number of buttons in the alert. 106 | */ 107 | - (void)adjustWidthWithWindowWidth:(CGFloat)windowWidth numberOfButtons:(NSUInteger)numberOfButtons; 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /SCLAlertView/SCLSwitchView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLSwitchView.m 3 | // SCLAlertView 4 | // 5 | // Created by André Felipe Santos on 27/01/16. 6 | // Copyright (c) 2016-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLSwitchView.h" 10 | #import "SCLMacros.h" 11 | 12 | @interface SCLSwitchView () 13 | 14 | @property (strong, nonatomic) UISwitch *switchKnob; 15 | @property (strong, nonatomic) UILabel *switchLabel; 16 | 17 | @end 18 | 19 | #pragma mark 20 | 21 | @implementation SCLSwitchView 22 | 23 | #pragma mark - Constructors 24 | 25 | - (instancetype)init 26 | { 27 | self = [super init]; 28 | if (self) 29 | { 30 | [self setup]; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 36 | { 37 | self = [super initWithCoder:aDecoder]; 38 | if(self) 39 | { 40 | [self setup]; 41 | } 42 | return self; 43 | } 44 | 45 | - (instancetype)initWithFrame:(CGRect)frame 46 | { 47 | self = [super initWithFrame:frame]; 48 | if (self) 49 | { 50 | [self setup]; 51 | } 52 | return self; 53 | } 54 | 55 | #pragma mark - Initialization 56 | 57 | - (void)setup 58 | { 59 | // Add switch knob 60 | self.switchKnob = [[UISwitch alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.f)]; 61 | [self addSubview:self.switchKnob]; 62 | 63 | // Add switch label 64 | CGFloat x, width, height; 65 | x = self.switchKnob.frame.size.width + 8.0f; 66 | width = self.frame.size.width - self.switchKnob.frame.size.width - 8.0f; 67 | height = self.switchKnob.frame.size.height; 68 | 69 | self.switchLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, 0.0f, width, height)]; 70 | 71 | NSString *switchFontFamily = @"HelveticaNeue-Bold"; 72 | CGFloat switchFontSize = 12.0f; 73 | 74 | self.switchLabel.numberOfLines = 1; 75 | self.switchLabel.textAlignment = NSTextAlignmentLeft; 76 | self.switchLabel.lineBreakMode = NSLineBreakByTruncatingTail; 77 | self.switchLabel.adjustsFontSizeToFitWidth = YES; 78 | self.switchLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; 79 | self.switchLabel.minimumScaleFactor = 0.5f; 80 | self.switchLabel.font = [UIFont fontWithName:switchFontFamily size:switchFontSize]; 81 | self.switchLabel.textColor = UIColorFromHEX(0x4D4D4D); 82 | 83 | [self addSubview:self.switchLabel]; 84 | } 85 | 86 | #pragma mark - Getters 87 | 88 | - (UIColor *)tintColor 89 | { 90 | return self.switchKnob.tintColor; 91 | } 92 | 93 | - (UIColor *)labelColor 94 | { 95 | return self.switchLabel.textColor; 96 | } 97 | 98 | - (UIFont *)labelFont 99 | { 100 | return self.switchLabel.font; 101 | } 102 | 103 | - (NSString *)labelText 104 | { 105 | return self.switchLabel.text; 106 | } 107 | 108 | - (BOOL)isSelected 109 | { 110 | return self.switchKnob.isOn; 111 | } 112 | 113 | #pragma mark - Setters 114 | 115 | - (void)setTintColor:(UIColor *)tintColor 116 | { 117 | self.switchKnob.onTintColor = tintColor; 118 | } 119 | 120 | - (void)setLabelColor:(UIColor *)labelColor 121 | { 122 | self.switchLabel.textColor = labelColor; 123 | } 124 | 125 | - (void)setLabelFont:(UIFont *)labelFont 126 | { 127 | self.switchLabel.font = labelFont; 128 | } 129 | 130 | - (void)setLabelText:(NSString *)labelText 131 | { 132 | self.switchLabel.text = labelText; 133 | } 134 | 135 | - (void)setSelected:(BOOL)selected 136 | { 137 | self.switchKnob.on = selected; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /esp.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import "esp.h" 3 | #import 4 | 5 | @implementation esp : UIView 6 | @synthesize players; 7 | @synthesize espboxes; 8 | @synthesize esplines; 9 | @synthesize healthbarr; 10 | @synthesize distanceesp; 11 | 12 | - (id)initWithFrame:(UIWindow*)main 13 | { 14 | self = [super initWithFrame:main.frame]; 15 | self.userInteractionEnabled = false; 16 | self.hidden = false; 17 | self.backgroundColor = [UIColor clearColor]; 18 | if(!players){ 19 | players = new std::vector(); 20 | } 21 | [main addSubview:self]; 22 | CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)]; 23 | [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 24 | return self; 25 | } 26 | 27 | - (void)callupdate { 28 | [NSTimer scheduledTimerWithTimeInterval:0.01 29 | target:self 30 | selector:@selector(update) 31 | userInfo:nil 32 | repeats:YES]; 33 | } 34 | 35 | - (void)drawRect:(CGRect)rect { 36 | CGContextRef contextRef = UIGraphicsGetCurrentContext(); 37 | CGContextClearRect(contextRef,self.bounds); 38 | CGContextSetLineWidth(contextRef, 0.5); 39 | CGColor *colour; 40 | UIColor *Ucolour; 41 | for(int i = 0; i < players->size(); i++) { 42 | if((*players)[i]->enemy){ 43 | colour = [UIColor redColor].CGColor; 44 | Ucolour = [UIColor redColor]; 45 | }else{ 46 | colour = [UIColor blueColor].CGColor; 47 | Ucolour = [UIColor blueColor]; 48 | } 49 | if((*players)[i]->enemy){ 50 | CGFloat floatx = (*players)[i]->rect.origin.x + (*players)[i]->rect.size.width/2; 51 | CGFloat floaty = (*players)[i]->rect.origin.y; 52 | CGContextSetStrokeColorWithColor(contextRef, colour); 53 | 54 | if(espboxes){ 55 | CGContextStrokeRect(contextRef, (*players)[i]->rect); 56 | } 57 | if(esplines){ 58 | if((*players)[i]->enemy){ 59 | CGContextMoveToPoint(contextRef,self.frame.size.width/2, 0.0f); 60 | CGContextAddLineToPoint(contextRef, (*players)[i]->topofbox.x, (*players)[i]->topofbox.y); 61 | }else{ 62 | CGContextMoveToPoint(contextRef,self.frame.size.width/2, self.frame.size.height); 63 | CGContextAddLineToPoint(contextRef, (*players)[i]->bottomofbox.x, (*players)[i]->bottomofbox.y); 64 | } 65 | CGContextStrokePath(contextRef); 66 | } 67 | if(healthbarr){ 68 | [[UIColor redColor] setFill]; 69 | CGContextFillRect(contextRef, (*players)[i]->healthbar); 70 | [[UIColor greenColor] setFill]; 71 | float cc = (*players)[i]->health/100; 72 | CGRect healthbar = CGRectMake((*players)[i]->healthbar.origin.x, (*players)[i]->healthbar.origin.y, (*players)[i]->healthbar.size.width, (*players)[i]->healthbar.size.height*cc); 73 | CGContextFillRect(contextRef, healthbar); 74 | } 75 | if(distanceesp){ 76 | NSString *text = [NSString stringWithFormat:@"%.0f", (*players)[i]->distance]; 77 | float xd = 30 / ((*players)[i]->distance/10); 78 | if(xd>25){ 79 | xd = 25.0f; 80 | } 81 | xd = (*players)[i]->rect.size.width/2; 82 | NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:xd], NSForegroundColorAttributeName:Ucolour}; 83 | [text drawAtPoint:CGPointMake(((*players)[i]->rect.origin.x), ((*players)[i]->bottomofbox.y)) withAttributes:attributes]; 84 | } 85 | 86 | } 87 | } 88 | 89 | } 90 | - (void)update { 91 | if(esplines || espboxes || healthbarr || distanceesp ){ 92 | [self setNeedsDisplay]; 93 | } 94 | } 95 | 96 | @end -------------------------------------------------------------------------------- /SCLAlertView/SCLTimerDisplay.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLTimerDisplay.m 3 | // SCLAlertView 4 | // 5 | // Created by Taylor Ryan on 8/18/15. 6 | // Copyright (c) 2015-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLTimerDisplay.h" 10 | #import "SCLMacros.h" 11 | 12 | @interface SCLTimerDisplay () 13 | 14 | @property (strong, nonatomic) UILabel *countLabel; 15 | 16 | @end 17 | 18 | @implementation SCLTimerDisplay 19 | 20 | @synthesize currentAngle; 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) 26 | { 27 | self.backgroundColor = [UIColor clearColor]; 28 | currentAngle = 0.0f; 29 | } 30 | return self; 31 | } 32 | 33 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r 34 | { 35 | return [self initWithOrigin:(CGPoint)origin radius:r lineWidth:5.0f]; 36 | } 37 | 38 | - (instancetype)initWithOrigin:(CGPoint)origin radius:(CGFloat)r lineWidth:(CGFloat)width 39 | { 40 | self = [super initWithFrame:CGRectMake(origin.x, origin.y, r*2, r*2)]; 41 | if (self) { 42 | self.backgroundColor = [UIColor clearColor]; 43 | currentAngle = START_DEGREE_OFFSET; 44 | radius = r-(width/2); 45 | lineWidth = width; 46 | self.color = [UIColor whiteColor]; 47 | self.userInteractionEnabled = NO; 48 | 49 | // Add count label 50 | _countLabel = [[UILabel alloc] init]; 51 | _countLabel.textColor = [UIColor whiteColor]; 52 | _countLabel.backgroundColor = [UIColor clearColor]; 53 | _countLabel.font = [UIFont fontWithName: @"HelveticaNeue-Bold" size:12.0f]; 54 | _countLabel.textAlignment = NSTextAlignmentCenter; 55 | _countLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 56 | [self addSubview:_countLabel]; 57 | } 58 | return self; 59 | } 60 | 61 | - (void)updateFrame:(CGSize)size 62 | { 63 | CGFloat r = radius+(lineWidth/2); 64 | 65 | CGFloat originX = size.width - (2*r) - 5; 66 | CGFloat originY = (size.height - (2*r))/2; 67 | 68 | self.frame = CGRectMake(originX, originY, r*2, r*2); 69 | self.countLabel.frame = CGRectMake(0, 0, r*2, r*2); 70 | } 71 | 72 | - (void)drawRect:(CGRect)rect 73 | { 74 | UIBezierPath* aPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius+(lineWidth/2), radius+(lineWidth/2)) 75 | radius:radius 76 | startAngle:DEGREES_TO_RADIANS(START_DEGREE_OFFSET) 77 | endAngle:DEGREES_TO_RADIANS(currentAngle) 78 | clockwise:YES]; 79 | [self.color setStroke]; 80 | aPath.lineWidth = lineWidth; 81 | [aPath stroke]; 82 | 83 | _countLabel.text = [NSString stringWithFormat:@"%d", (int)currentTime]; 84 | } 85 | 86 | - (void)startTimerWithTimeLimit:(int)tl completed:(SCLActionBlock)completed 87 | { 88 | if (_reverse) 89 | { 90 | currentTime = tl; 91 | } 92 | timerLimit = tl; 93 | timer = [NSTimer scheduledTimerWithTimeInterval:TIMER_STEP target:self selector:@selector(updateTimerButton:) userInfo:nil repeats:YES]; 94 | completedBlock = completed; 95 | _countLabel.textColor = _color; 96 | } 97 | 98 | - (void)cancelTimer 99 | { 100 | [timer invalidate]; 101 | } 102 | 103 | - (void)stopTimer 104 | { 105 | [timer invalidate]; 106 | if (completedBlock != nil) { 107 | completedBlock(); 108 | } 109 | } 110 | 111 | - (void)updateTimerButton:(NSTimer *)timer 112 | { 113 | if (_reverse) 114 | { 115 | currentTime -= TIMER_STEP; 116 | currentAngle = (currentTime/timerLimit) * 360 + START_DEGREE_OFFSET; 117 | 118 | if(currentTime <= 0) { 119 | [self stopTimer]; 120 | } 121 | } 122 | else { 123 | currentTime += TIMER_STEP; 124 | currentAngle = (currentTime/timerLimit) * 360 + START_DEGREE_OFFSET; 125 | 126 | if(currentAngle >= (360 + START_DEGREE_OFFSET)) { 127 | [self stopTimer]; 128 | } 129 | } 130 | [self setNeedsDisplay]; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /KittyMemory/MemoryPatch.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MemoryPatch.cpp 3 | // 4 | // Created by MJ (Ruit) on 1/1/19. 5 | // 6 | 7 | #include "MemoryPatch.hpp" 8 | 9 | 10 | MemoryPatch::MemoryPatch() { 11 | _address = 0; 12 | _size = 0; 13 | _orig_code.clear(); 14 | _patch_code.clear(); 15 | } 16 | 17 | MemoryPatch::MemoryPatch(uint64_t absolute_address, 18 | const void *patch_code, size_t patch_size) { 19 | MemoryPatch(); 20 | 21 | if (absolute_address == 0 || patch_code == NULL || patch_size < 1) 22 | return; 23 | 24 | _address = reinterpret_cast(absolute_address); 25 | _size = patch_size; 26 | 27 | _orig_code.resize(patch_size); 28 | _patch_code.resize(patch_size); 29 | 30 | // initialize patch & backup current content 31 | KittyMemory::memRead(&_patch_code[0], patch_code, patch_size); 32 | KittyMemory::memRead(&_orig_code[0], static_cast(_address), patch_size); 33 | } 34 | 35 | MemoryPatch::MemoryPatch(const char *fileName, uint64_t address, 36 | const void *patch_code, size_t patch_size) { 37 | MemoryPatch(); 38 | 39 | if (address == 0 || patch_code == NULL || patch_size < 1) 40 | return; 41 | 42 | _address = reinterpret_cast(KittyMemory::getAbsoluteAddress(fileName, address)); 43 | if(_address == NULL) return; 44 | 45 | _size = patch_size; 46 | 47 | _orig_code.resize(patch_size); 48 | _patch_code.resize(patch_size); 49 | 50 | // initialize patch & backup current content 51 | KittyMemory::memRead(&_patch_code[0], patch_code, patch_size); 52 | KittyMemory::memRead(&_orig_code[0], reinterpret_cast(_address), patch_size); 53 | } 54 | 55 | MemoryPatch::~MemoryPatch() { 56 | // clean up 57 | _orig_code.clear(); 58 | _patch_code.clear(); 59 | } 60 | 61 | 62 | MemoryPatch MemoryPatch::createWithHex(const char *fileName, uint64_t address, std::string hex) { 63 | MemoryPatch patch; 64 | 65 | if (address == 0 || !KittyUtils::validateHexString(hex)) 66 | return patch; 67 | 68 | patch._address = reinterpret_cast(KittyMemory::getAbsoluteAddress(fileName, address)); 69 | if(patch._address == NULL) return patch; 70 | 71 | patch._size = hex.length() / 2; 72 | 73 | patch._orig_code.resize(patch._size); 74 | patch._patch_code.resize(patch._size); 75 | 76 | // initialize patch 77 | KittyUtils::fromHex(hex, &patch._patch_code[0]); 78 | 79 | // backup current content 80 | KittyMemory::memRead(&patch._orig_code[0], reinterpret_cast(patch._address), patch._size); 81 | return patch; 82 | } 83 | 84 | MemoryPatch MemoryPatch::createWithHex(uint64_t absolute_address, std::string hex) { 85 | MemoryPatch patch; 86 | 87 | if (absolute_address == 0 || !KittyUtils::validateHexString(hex)) 88 | return patch; 89 | 90 | patch._address = reinterpret_cast(absolute_address); 91 | patch._size = hex.length() / 2; 92 | 93 | patch._orig_code.resize(patch._size); 94 | patch._patch_code.resize(patch._size); 95 | 96 | // initialize patch 97 | KittyUtils::fromHex(hex, &patch._patch_code[0]); 98 | 99 | // backup current content 100 | KittyMemory::memRead(&patch._orig_code[0], reinterpret_cast(patch._address), patch._size); 101 | return patch; 102 | } 103 | 104 | bool MemoryPatch::isValid() const { 105 | return (_address != NULL && _size > 0 106 | && _orig_code.size() == _size && _patch_code.size() == _size); 107 | } 108 | 109 | size_t MemoryPatch::get_PatchSize() const{ 110 | return _size; 111 | } 112 | 113 | void *MemoryPatch::get_TargetAddress() const{ 114 | return _address; 115 | } 116 | 117 | bool MemoryPatch::Restore() { 118 | if (!isValid()) return false; 119 | return KittyMemory::memWrite(_address, &_orig_code[0], _size) == KittyMemory::SUCCESS; 120 | } 121 | 122 | bool MemoryPatch::Modify() { 123 | if (!isValid()) return false; 124 | return (KittyMemory::memWrite(_address, &_patch_code[0], _size) == KittyMemory::SUCCESS); 125 | } 126 | 127 | std::string MemoryPatch::get_CurrBytes() { 128 | if (!isValid()) 129 | _hexString = std::string("0xInvalid"); 130 | else 131 | _hexString = KittyMemory::read2HexStr(reinterpret_cast(_address), _size); 132 | 133 | return _hexString; 134 | } 135 | -------------------------------------------------------------------------------- /SCLAlertView/SCLButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLButton.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLButton.h" 10 | #import "SCLTimerDisplay.h" 11 | 12 | #define MARGIN_BUTTON 12.0f 13 | #define DEFAULT_WINDOW_WIDTH 240 14 | #define MIN_HEIGHT 35.0f 15 | 16 | @implementation SCLButton 17 | 18 | - (instancetype)init 19 | { 20 | self = [super init]; 21 | if (self) 22 | { 23 | [self setupWithWindowWidth:DEFAULT_WINDOW_WIDTH]; 24 | } 25 | return self; 26 | } 27 | 28 | - (instancetype)initWithWindowWidth:(CGFloat)windowWidth 29 | { 30 | self = [super init]; 31 | if (self) 32 | { 33 | [self setupWithWindowWidth:windowWidth]; 34 | } 35 | return self; 36 | } 37 | 38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 39 | { 40 | self = [super initWithCoder:aDecoder]; 41 | if(self) 42 | { 43 | [self setupWithWindowWidth:DEFAULT_WINDOW_WIDTH]; 44 | } 45 | return self; 46 | } 47 | 48 | - (instancetype)initWithFrame:(CGRect)frame 49 | { 50 | self = [super initWithFrame:frame]; 51 | if (self) 52 | { 53 | [self setupWithWindowWidth:DEFAULT_WINDOW_WIDTH]; 54 | } 55 | return self; 56 | } 57 | 58 | - (void)setupWithWindowWidth:(CGFloat)windowWidth 59 | { 60 | self.frame = CGRectMake(0.0f, 0.0f, windowWidth - (MARGIN_BUTTON * 2), MIN_HEIGHT); 61 | self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; 62 | self.titleLabel.textAlignment = NSTextAlignmentCenter; 63 | self.layer.cornerRadius = 3.0f; 64 | } 65 | 66 | - (void)adjustWidthWithWindowWidth:(CGFloat)windowWidth numberOfButtons:(NSUInteger)numberOfButtons 67 | { 68 | CGFloat allButtonsWidth = windowWidth - (MARGIN_BUTTON * 2); 69 | CGFloat buttonWidth = (allButtonsWidth - ((numberOfButtons - 1) * 10)) / numberOfButtons; 70 | 71 | self.frame = CGRectMake(0.0f, 0.0f, buttonWidth, MIN_HEIGHT); 72 | } 73 | 74 | - (void)setTitle:(NSString *)title forState:(UIControlState)state 75 | { 76 | [super setTitle:title forState:state]; 77 | self.titleLabel.numberOfLines = 0; 78 | 79 | // Update title frame. 80 | [self.titleLabel sizeToFit]; 81 | 82 | // Update button frame 83 | [self layoutIfNeeded]; 84 | 85 | // Get height needed to display title label completely 86 | CGFloat buttonHeight = MAX(self.titleLabel.frame.size.height, MIN_HEIGHT); 87 | 88 | // Update button frame 89 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, buttonHeight); 90 | } 91 | 92 | - (void)setHighlighted:(BOOL)highlighted 93 | { 94 | self.backgroundColor = (highlighted) ? [self darkerColorForColor:_defaultBackgroundColor] : _defaultBackgroundColor; 95 | [super setHighlighted:highlighted]; 96 | } 97 | 98 | - (void)setDefaultBackgroundColor:(UIColor *)defaultBackgroundColor 99 | { 100 | self.backgroundColor = _defaultBackgroundColor = defaultBackgroundColor; 101 | } 102 | 103 | - (void)setTimer:(SCLTimerDisplay *)timer 104 | { 105 | _timer = timer; 106 | [self addSubview:timer]; 107 | [timer updateFrame:self.frame.size]; 108 | timer.color = self.titleLabel.textColor; 109 | } 110 | 111 | #pragma mark - Button Apperance 112 | 113 | - (void)parseConfig:(NSDictionary *)buttonConfig 114 | { 115 | if (buttonConfig[@"backgroundColor"]) 116 | { 117 | self.defaultBackgroundColor = buttonConfig[@"backgroundColor"]; 118 | } 119 | if (buttonConfig[@"textColor"]) 120 | { 121 | [self setTitleColor:buttonConfig[@"textColor"] forState:UIControlStateNormal]; 122 | } 123 | if (buttonConfig[@"cornerRadius"]) 124 | { 125 | self.layer.cornerRadius = [buttonConfig[@"cornerRadius"] floatValue]; 126 | } 127 | if ((buttonConfig[@"borderColor"]) && (buttonConfig[@"borderWidth"])) 128 | { 129 | self.layer.borderColor = ((UIColor*)buttonConfig[@"borderColor"]).CGColor; 130 | self.layer.borderWidth = [buttonConfig[@"borderWidth"] floatValue]; 131 | } 132 | else if (buttonConfig[@"borderWidth"]) 133 | { 134 | self.layer.borderWidth = [buttonConfig[@"borderWidth"] floatValue]; 135 | } 136 | 137 | // Add Button custom font with buttonConfig parameters 138 | if (buttonConfig[@"font"]) { 139 | self.titleLabel.font = buttonConfig[@"font"]; 140 | } 141 | } 142 | 143 | #pragma mark - Helpers 144 | 145 | - (UIColor *)darkerColorForColor:(UIColor *)color 146 | { 147 | CGFloat r, g, b, a; 148 | if ([color getRed:&r green:&g blue:&b alpha:&a]) 149 | return [UIColor colorWithRed:MAX(r - 0.2f, 0.0f) 150 | green:MAX(g - 0.2f, 0.0f) 151 | blue:MAX(b - 0.2f, 0.0f) 152 | alpha:a]; 153 | return nil; 154 | } 155 | 156 | - (UIColor *)lighterColorForColor:(UIColor *)color 157 | { 158 | CGFloat r, g, b, a; 159 | if ([color getRed:&r green:&g blue:&b alpha:&a]) 160 | return [UIColor colorWithRed:MIN(r + 0.2f, 1.0f) 161 | green:MIN(g + 0.2f, 1.0f) 162 | blue:MIN(b + 0.2f, 1.0f) 163 | alpha:a]; 164 | return nil; 165 | } 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /Obfuscate.h: -------------------------------------------------------------------------------- 1 | // http://www.rohitab.com/discuss/topic/39611-malware-related-compile-time-hacks-with-c11/ 2 | // https://github.com/Rednick16/cpp11-compile-time-string-obfuscation 3 | 4 | #include 5 | #include 6 | 7 | //-------------------------------------------------------------// 8 | // "Malware related compile-time hacks with C++11" by LeFF // 9 | // You can use this code however you like, I just don't really // 10 | // give a shit, but if you feel some respect for me, please // 11 | // don't cut off this comment when copy-pasting... ;-) // 12 | //-------------------------------------------------------------// 13 | 14 | #if defined(_MSC_VER) 15 | #define ALWAYS_INLINE __forceinline 16 | #else 17 | #define ALWAYS_INLINE __attribute__((always_inline)) 18 | #endif 19 | 20 | // Usage examples: 21 | void setup() __attribute__((noinline)); 22 | void startAuthentication() __attribute__((noinline)); 23 | 24 | #ifndef seed 25 | // I use current (compile time) as a seed 26 | // Convert time string (hh:mm:ss) into a number 27 | constexpr int seedToInt(char c) { return c - '0'; } 28 | const int seed = seedToInt(__TIME__[7]) + 29 | seedToInt(__TIME__[6]) * 10 + 30 | seedToInt(__TIME__[4]) * 60 + 31 | seedToInt(__TIME__[3]) * 600 + 32 | seedToInt(__TIME__[1]) * 3600 + 33 | seedToInt(__TIME__[0]) * 36000; 34 | #endif 35 | 36 | // The constantify template is used to make sure that the result of constexpr 37 | // function will be computed at compile-time instead of run-time 38 | template struct 39 | vxCplConstantify { enum { Value = Const }; }; 40 | 41 | // Compile-time mod of a linear congruential pseudorandom number generator, 42 | // the actual algorithm was taken from "Numerical Recipes" book 43 | constexpr uintptr_t vxCplRandom(uintptr_t Id) 44 | { return (1013904223 + 1664525 * ((Id > 0) ? (vxCplRandom(Id - 1)) : (/*vxCPLSEED*/seed))) & 0xFFFFFFFF; } 45 | 46 | // Compile-time random macros, can be used to randomize execution 47 | // path for separate builds, or compile-time trash code generation 48 | #define vxRANDOM(Min, Max) (Min + (vxRAND() % (Max - Min + 1))) 49 | #define vxRAND() (vxCplConstantify::Value) 50 | 51 | // Compile-time recursive mod of string hashing algorithm, 52 | // the actual algorithm was taken from Qt library (this 53 | // function isn't case sensitive due to vxCplTolower) 54 | constexpr char vxCplTolower(char Ch) { return (Ch >= 'A' && Ch <= 'Z') ? (Ch - 'A' + 'a') : (Ch); } 55 | constexpr uintptr_t vxCplHashPart3(char Ch, uintptr_t Hash) { return ((Hash << 4) + vxCplTolower(Ch)); } 56 | constexpr uintptr_t vxCplHashPart2(char Ch, uintptr_t Hash) { return (vxCplHashPart3(Ch, Hash) ^ ((vxCplHashPart3(Ch, Hash) & 0xF0000000) >> 23)); } 57 | constexpr uintptr_t vxCplHashPart1(char Ch, uintptr_t Hash) { return (vxCplHashPart2(Ch, Hash) & 0x0FFFFFFF); } 58 | constexpr uintptr_t vxCplHash(const char* Str) { return (*Str) ? (vxCplHashPart1(*Str, vxCplHash(Str + 1))) : (0); } 59 | 60 | // Compile-time hashing macro, hash values changes using the first pseudorandom number in sequence 61 | #define HASH(Str) (uintptr_t)(vxCplConstantify::Value ^ vxCplConstantify::Value) 62 | 63 | // Compile-time generator for list of indexes (0, 1, 2, ...) 64 | template struct vxCplIndexList {}; 65 | template struct vxCplAppend; 66 | template struct vxCplAppend, Right> { typedef vxCplIndexList Result; }; 67 | template struct vxCplIndexes { typedef typename vxCplAppend::Result, N - 1>::Result Result; }; 68 | template <> struct vxCplIndexes<0> { typedef vxCplIndexList<> Result; }; 69 | 70 | // Compile-time string encryption of a single character 71 | const char vxCplEncryptCharKey = (const char)vxRANDOM(0, 0xFF); 72 | constexpr char ALWAYS_INLINE vxCplEncryptChar(const char Ch, uintptr_t Idx) { return Ch ^ (vxCplEncryptCharKey + Idx); } 73 | 74 | // Compile-time string encryption class 75 | template struct vxCplEncryptedString; 76 | template struct vxCplEncryptedString > 77 | { 78 | char Value[sizeof...(Idx) + 1]; // Buffer for a string 79 | 80 | // Compile-time constructor 81 | constexpr ALWAYS_INLINE vxCplEncryptedString(const char* const Str) 82 | : Value{ vxCplEncryptChar(Str[Idx], Idx)... } {} 83 | 84 | // Run-time decryption 85 | inline const char* decrypt() 86 | { 87 | for(uintptr_t t = 0; t < sizeof...(Idx); t++) 88 | { this->Value[t] = this->Value[t] ^ (vxCplEncryptCharKey + t); } 89 | this->Value[sizeof...(Idx)] = '\0'; return this->Value; 90 | } 91 | }; 92 | 93 | // Compile-time string encryption macro 94 | #define ENCRYPT(Str) (vxCplEncryptedString::Result>(Str).decrypt()) 95 | 96 | #ifdef __APPLE__ 97 | // Compile-time Objective-c string encryption macro 98 | #define NSSENCRYPT(Str) @(ENCRYPT(Str)) 99 | #endif 100 | 101 | // Compile-time offset string encryption macro, converts back to uint64_t. 102 | #define ENCRYPTOFFSET(Str) strtoull(ENCRYPT(Str), NULL, 0) 103 | 104 | // Compile-time hex string encryption macro, does same as ENCRYPT, but the naming is just more clear. 105 | #define ENCRYPTHEX(Str) ENCRYPT(Str) 106 | -------------------------------------------------------------------------------- /KittyMemory/KittyMemory.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // KittyMemory.hpp 3 | // 4 | // 5 | // Created by MJ (Ruit) on 1/1/19. 6 | // 7 | // 8 | 9 | #pragma once 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define BAD_KERN_CALL(call) call != KERN_SUCCESS 22 | 23 | #define _SYS_PAGE_SIZE_ (sysconf(_SC_PAGE_SIZE)) 24 | 25 | #define _PAGE_START_OF_(x) ((uintptr_t)x & ~(uintptr_t)(_SYS_PAGE_SIZE_ - 1)) 26 | #define _PAGE_END_OF_(x, len) (_PAGE_START_OF_((uintptr_t)x + len - 1)) 27 | #define _PAGE_LEN_OF_(x, len) (_PAGE_END_OF_(x, len) - _PAGE_START_OF_(x) + _SYS_PAGE_SIZE_) 28 | #define _PAGE_OFFSET_OF_(x) ((uintptr_t)x - _PAGE_START_OF_(x)) 29 | 30 | #define _PROT_RWX_ (PROT_READ | PROT_WRITE | PROT_EXEC) 31 | #define _PROT_RX_ (PROT_READ | PROT_EXEC) 32 | #define _PROT_RW_ (PROT_READ | PROT_WRITE) 33 | 34 | 35 | #define EMPTY_VEC_OFFSET std::vector() 36 | 37 | 38 | namespace KittyMemory { 39 | 40 | typedef enum { 41 | FAILED = 0, 42 | SUCCESS = 1, 43 | INV_ADDR = 2, 44 | INV_LEN = 3, 45 | INV_BUF = 4, 46 | INV_PROT = 5, 47 | INV_KERN_CALL = 6, 48 | INV_MAP = 7 49 | } Memory_Status; 50 | 51 | 52 | typedef struct { 53 | int index; 54 | const mach_header *header; 55 | const char *name; 56 | intptr_t address; 57 | } memory_file_info; 58 | 59 | 60 | /* 61 | * Changes protection of an address with given length 62 | */ 63 | bool ProtectAddr(void *address, size_t length, int protection, bool aligned); 64 | 65 | /* 66 | * Writes buffer content to an address 67 | */ 68 | Memory_Status memWrite(void *address, const void *buffer, size_t len); 69 | 70 | /* 71 | * Reads an address content into a buffer 72 | */ 73 | Memory_Status memRead(void *buffer, const void *addr, size_t len); 74 | 75 | /* 76 | * Wrapper to dereference & get value of a multi level pointer 77 | * Make sure to use the correct data type! 78 | */ 79 | template 80 | Type readMultiPtr(void *ptr, std::vector offsets) { 81 | Type defaultVal = {}; 82 | if (ptr == NULL) 83 | return defaultVal; 84 | 85 | uintptr_t finalPtr = reinterpret_cast(ptr); 86 | int offsetsSize = offsets.size(); 87 | if (offsetsSize > 0) { 88 | for (int i = 0; finalPtr != 0 && i < offsetsSize; i++) { 89 | if (i == (offsetsSize - 1)) 90 | return *reinterpret_cast(finalPtr + offsets[i]); 91 | 92 | finalPtr = *reinterpret_cast(finalPtr + offsets[i]); 93 | } 94 | } 95 | 96 | if (finalPtr == 0) 97 | return defaultVal; 98 | 99 | return *reinterpret_cast(finalPtr); 100 | } 101 | 102 | 103 | /* 104 | * Wrapper to dereference & set value of a multi level pointer 105 | * Make sure to use the correct data type!, const objects won't work 106 | */ 107 | template 108 | bool writeMultiPtr(void *ptr, std::vector offsets, Type val) { 109 | if (ptr == NULL) 110 | return false; 111 | 112 | uintptr_t finalPtr = reinterpret_cast(ptr); 113 | int offsetsSize = offsets.size(); 114 | if (offsetsSize > 0) { 115 | for (int i = 0; finalPtr != 0 && i < offsetsSize; i++) { 116 | if (i == (offsetsSize - 1)) { 117 | *reinterpret_cast(finalPtr + offsets[i]) = val; 118 | return true; 119 | } 120 | 121 | finalPtr = *reinterpret_cast(finalPtr + offsets[i]); 122 | } 123 | } 124 | 125 | if (finalPtr == 0) 126 | return false; 127 | 128 | *reinterpret_cast(finalPtr) = val; 129 | return true; 130 | } 131 | 132 | 133 | /* 134 | * Wrapper to dereference & get value of a pointer 135 | * Make sure to use the correct data type! 136 | */ 137 | template 138 | Type readPtr(void *ptr) { 139 | Type defaultVal = {}; 140 | if (ptr == NULL) 141 | return defaultVal; 142 | 143 | return *reinterpret_cast(ptr); 144 | } 145 | 146 | 147 | /* 148 | * Wrapper to dereference & set value of a pointer 149 | * Make sure to use the correct data type!, const objects won't work 150 | */ 151 | template 152 | bool writePtr(void *ptr, Type val) { 153 | if (ptr == NULL) 154 | return false; 155 | 156 | *reinterpret_cast(ptr) = val; 157 | return true; 158 | } 159 | 160 | 161 | /* 162 | * Reads an address content and returns hex string 163 | */ 164 | std::string read2HexStr(const void *address, size_t len); 165 | 166 | 167 | kern_return_t getPageInfo(void *page_start, vm_region_submap_short_info_64 *outInfo); 168 | 169 | /* 170 | * returns base executable info 171 | */ 172 | memory_file_info getBaseInfo(); 173 | 174 | /* 175 | * find in memory file info 176 | */ 177 | memory_file_info getMemoryFileInfo(const char *fileName); 178 | 179 | /* 180 | * returns relative address of file in memory, NULL as fileName will return base executable 181 | */ 182 | uint64_t getAbsoluteAddress(const char *fileName, uint64_t address); 183 | 184 | }; -------------------------------------------------------------------------------- /SCLAlertView/UIImage+ImageEffects.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: UIImage+ImageEffects.h 3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur. 4 | Version: 1.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2013 Apple Inc. All Rights Reserved. 45 | 46 | 47 | Copyright © 2013 Apple Inc. All rights reserved. 48 | WWDC 2013 License 49 | 50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013 51 | Session. Please refer to the applicable WWDC 2013 Session for further 52 | information. 53 | 54 | IMPORTANT: This Apple software is supplied to you by Apple Inc. 55 | ("Apple") in consideration of your agreement to the following terms, and 56 | your use, installation, modification or redistribution of this Apple 57 | software constitutes acceptance of these terms. If you do not agree with 58 | these terms, please do not use, install, modify or redistribute this 59 | Apple software. 60 | 61 | In consideration of your agreement to abide by the following terms, and 62 | subject to these terms, Apple grants you a non-exclusive license, under 63 | Apple's copyrights in this original Apple software (the "Apple 64 | Software"), to use, reproduce, modify and redistribute the Apple 65 | Software, with or without modifications, in source and/or binary forms; 66 | provided that if you redistribute the Apple Software in its entirety and 67 | without modifications, you must retain this notice and the following 68 | text and disclaimers in all such redistributions of the Apple Software. 69 | Neither the name, trademarks, service marks or logos of Apple Inc. may 70 | be used to endorse or promote products derived from the Apple Software 71 | without specific prior written permission from Apple. Except as 72 | expressly stated in this notice, no other rights or licenses, express or 73 | implied, are granted by Apple herein, including but not limited to any 74 | patent rights that may be infringed by your derivative works or by other 75 | works in which the Apple Software may be incorporated. 76 | 77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES 78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR 80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 82 | 83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 90 | POSSIBILITY OF SUCH DAMAGE. 91 | 92 | EA1002 93 | 5/3/2013 94 | */ 95 | 96 | #if defined(__has_feature) && __has_feature(modules) 97 | @import UIKit; 98 | #else 99 | #import 100 | #endif 101 | 102 | @interface UIImage (ImageEffects) 103 | 104 | - (UIImage *)applyLightEffect; 105 | - (UIImage *)applyExtraLightEffect; 106 | - (UIImage *)applyDarkEffect; 107 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; 108 | 109 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; 110 | 111 | + (UIImage *)imageWithColor:(UIColor *)color; 112 | + (UIImage *)convertViewToImage; 113 | + (UIImage *)convertViewToImage:(UIView *)view; 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /KittyMemory/KittyMemory.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // KittyMemory.cpp 3 | // 4 | // 5 | // Created by MJ (Ruit) on 1/1/19. 6 | // 7 | // 8 | 9 | #include "KittyMemory.hpp" 10 | #include 11 | 12 | 13 | using KittyMemory::Memory_Status; 14 | 15 | 16 | // may not be accurate 17 | static bool cydiaExist(){ 18 | bool ret = false; 19 | FILE *f = NULL; 20 | if(( f = fopen( "/Applications/Cydia.app" , "r" ) ) 21 | || ( f = fopen( "/Library/MobileSubstrate/MobileSubstrate.dylib" , "r" ) )){ 22 | ret = true; 23 | } 24 | if(f != NULL){ 25 | fclose(f); 26 | } 27 | return ret; 28 | } 29 | 30 | typedef void (*MSHookMemory_t)(void *, const void *, size_t); 31 | inline bool findMSHookMemory(void *dst, const void *src, size_t len){ 32 | static void *ret = MSFindSymbol(NULL, "_MSHookMemory"); 33 | if(ret != NULL){ 34 | reinterpret_cast(ret)(dst, src, len); 35 | return true; 36 | } 37 | return false; 38 | } 39 | 40 | 41 | extern "C" kern_return_t mach_vm_remap(vm_map_t, mach_vm_address_t *, mach_vm_size_t, 42 | mach_vm_offset_t, int, vm_map_t, mach_vm_address_t, 43 | boolean_t, vm_prot_t *, vm_prot_t *, vm_inherit_t); 44 | 45 | 46 | bool KittyMemory::ProtectAddr(void *address, size_t length, int protection, bool aligned) { 47 | if(aligned) 48 | return mprotect(address, length, protection) != -1; 49 | 50 | uintptr_t pageStart = _PAGE_START_OF_(address); 51 | uintptr_t pageLen = _PAGE_LEN_OF_(address, length); 52 | return mprotect(reinterpret_cast(pageStart), pageLen, protection) != -1; 53 | } 54 | 55 | 56 | kern_return_t KittyMemory::getPageInfo(void *page_start, vm_region_submap_short_info_64 *outInfo) { 57 | vm_address_t region = reinterpret_cast(page_start); 58 | vm_size_t region_len = 0; 59 | mach_msg_type_number_t info_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 60 | unsigned int depth = 0; 61 | return vm_region_recurse_64(mach_task_self(), ®ion, ®ion_len, 62 | &depth, 63 | (vm_region_recurse_info_t) outInfo, 64 | &info_count); 65 | } 66 | 67 | 68 | /* 69 | refs to 70 | - https://github.com/asLody/whale/blob/master/whale/src/platform/memory.cc 71 | - CydiaSubstrate 72 | */ 73 | Memory_Status KittyMemory::memWrite(void *address, const void *buffer, size_t len) { 74 | if (address == NULL) 75 | return INV_ADDR; 76 | 77 | if (buffer == NULL) 78 | return INV_BUF; 79 | 80 | if (len < 1 || len > INT_MAX) 81 | return INV_LEN; 82 | 83 | // check for MSHookMemory that was added recently, but check for cydia existance first. 84 | if(cydiaExist() && findMSHookMemory(address, buffer, len)){ 85 | return SUCCESS; 86 | } 87 | 88 | void * page_start = reinterpret_cast(_PAGE_START_OF_(address)); 89 | void * page_offset = reinterpret_cast(_PAGE_OFFSET_OF_(address)); 90 | size_t page_len = _PAGE_LEN_OF_(address, len); 91 | 92 | vm_region_submap_short_info_64 page_info; 93 | if(BAD_KERN_CALL(getPageInfo(page_start, &page_info))) 94 | return INV_KERN_CALL; 95 | 96 | if(page_info.protection & VM_PROT_WRITE){ 97 | if(memcpy(address, buffer, len) != NULL){ 98 | return SUCCESS; 99 | } else { 100 | return FAILED; 101 | } 102 | } 103 | 104 | void *new_map = mmap(NULL, page_len, _PROT_RW_, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 105 | if(new_map == NULL) 106 | return INV_MAP; 107 | 108 | task_t self_task = mach_task_self(); 109 | 110 | 111 | if(BAD_KERN_CALL(vm_copy(self_task, 112 | reinterpret_cast(page_start), page_len, reinterpret_cast(new_map)))) 113 | return INV_KERN_CALL; 114 | 115 | 116 | void *dst = reinterpret_cast(reinterpret_cast(new_map) + reinterpret_cast(page_offset)); 117 | if(memcpy(dst, buffer, len) == NULL || !ProtectAddr(new_map, page_len, _PROT_RX_, true)) 118 | return FAILED; 119 | 120 | vm_prot_t cur_protection, max_protection; 121 | mach_vm_address_t mach_vm_page_start = reinterpret_cast(page_start); 122 | if(BAD_KERN_CALL(mach_vm_remap(self_task, &mach_vm_page_start, page_len, 0, VM_FLAGS_OVERWRITE, 123 | self_task, reinterpret_cast(new_map), TRUE, &cur_protection, &max_protection, 124 | page_info.inheritance))) 125 | return INV_KERN_CALL; 126 | 127 | return SUCCESS; 128 | } 129 | 130 | 131 | Memory_Status KittyMemory::memRead(void *buffer, const void *addr, size_t len) { 132 | if (addr == NULL) 133 | return INV_ADDR; 134 | 135 | if (buffer == NULL) 136 | return INV_BUF; 137 | 138 | if (len < 1 || len > INT_MAX) 139 | return INV_LEN; 140 | 141 | if (memcpy(buffer, addr, len) != NULL) 142 | return SUCCESS; 143 | 144 | return FAILED; 145 | } 146 | 147 | 148 | std::string KittyMemory::read2HexStr(const void *addr, size_t len) { 149 | char temp[len]; 150 | memset(temp, 0, len); 151 | 152 | const size_t bufferLen = len * 2 + 1; 153 | char buffer[bufferLen]; 154 | memset(buffer, 0, bufferLen); 155 | 156 | std::string ret; 157 | 158 | if (memRead(temp, addr, len) != SUCCESS) 159 | return ret; 160 | 161 | for (int i = 0; i < len; i++) { 162 | sprintf(&buffer[i * 2], "%02X", (unsigned char) temp[i]); 163 | } 164 | 165 | ret += buffer; 166 | return ret; 167 | } 168 | 169 | 170 | KittyMemory::memory_file_info KittyMemory::getBaseInfo(){ 171 | memory_file_info _info = { 172 | 0, 173 | _dyld_get_image_header(0), 174 | _dyld_get_image_name(0), 175 | _dyld_get_image_vmaddr_slide(0) 176 | }; 177 | return _info; 178 | } 179 | 180 | 181 | 182 | KittyMemory::memory_file_info KittyMemory::getMemoryFileInfo(const char *fileName){ 183 | memory_file_info _info; 184 | 185 | int imageCount = _dyld_image_count(); 186 | 187 | for(int i = 0; i < imageCount; i++) { 188 | const char *name = _dyld_get_image_name(i); 189 | const mach_header *header = _dyld_get_image_header(i); 190 | if(!strstr(name, fileName)) continue; 191 | 192 | memory_file_info new_info = { 193 | i, header, name, _dyld_get_image_vmaddr_slide(i) 194 | }; 195 | 196 | _info = new_info; 197 | } 198 | return _info; 199 | } 200 | 201 | 202 | uint64_t KittyMemory::getAbsoluteAddress(const char *fileName, uint64_t address){ 203 | memory_file_info info; 204 | if(fileName != NULL){ 205 | info = getMemoryFileInfo(fileName); 206 | } else { 207 | info = getBaseInfo(); 208 | } 209 | if(info.address == 0) 210 | return 0; 211 | return info.address + address; 212 | } 213 | -------------------------------------------------------------------------------- /SCLAlertView/UIImage+ImageEffects.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: UIImage+ImageEffects.m 3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur. 4 | Version: 1.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2013 Apple Inc. All Rights Reserved. 45 | 46 | 47 | Copyright © 2013 Apple Inc. All rights reserved. 48 | WWDC 2013 License 49 | 50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013 51 | Session. Please refer to the applicable WWDC 2013 Session for further 52 | information. 53 | 54 | IMPORTANT: This Apple software is supplied to you by Apple Inc. 55 | ("Apple") in consideration of your agreement to the following terms, and 56 | your use, installation, modification or redistribution of this Apple 57 | software constitutes acceptance of these terms. If you do not agree with 58 | these terms, please do not use, install, modify or redistribute this 59 | Apple software. 60 | 61 | In consideration of your agreement to abide by the following terms, and 62 | subject to these terms, Apple grants you a non-exclusive license, under 63 | Apple's copyrights in this original Apple software (the "Apple 64 | Software"), to use, reproduce, modify and redistribute the Apple 65 | Software, with or without modifications, in source and/or binary forms; 66 | provided that if you redistribute the Apple Software in its entirety and 67 | without modifications, you must retain this notice and the following 68 | text and disclaimers in all such redistributions of the Apple Software. 69 | Neither the name, trademarks, service marks or logos of Apple Inc. may 70 | be used to endorse or promote products derived from the Apple Software 71 | without specific prior written permission from Apple. Except as 72 | expressly stated in this notice, no other rights or licenses, express or 73 | implied, are granted by Apple herein, including but not limited to any 74 | patent rights that may be infringed by your derivative works or by other 75 | works in which the Apple Software may be incorporated. 76 | 77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES 78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE 79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR 80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 82 | 83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 90 | POSSIBILITY OF SUCH DAMAGE. 91 | 92 | EA1002 93 | 5/3/2013 94 | */ 95 | 96 | #import "UIImage+ImageEffects.h" 97 | #import "SCLMacros.h" 98 | 99 | #if defined(__has_feature) && __has_feature(modules) 100 | @import Accelerate; 101 | #else 102 | #import 103 | #endif 104 | #import 105 | 106 | 107 | @implementation UIImage (ImageEffects) 108 | 109 | 110 | - (UIImage *)applyLightEffect 111 | { 112 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3]; 113 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 114 | } 115 | 116 | 117 | - (UIImage *)applyExtraLightEffect 118 | { 119 | UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82]; 120 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 121 | } 122 | 123 | 124 | - (UIImage *)applyDarkEffect 125 | { 126 | UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73]; 127 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 128 | } 129 | 130 | 131 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor 132 | { 133 | const CGFloat EffectColorAlpha = 0.6; 134 | UIColor *effectColor = tintColor; 135 | NSUInteger componentCount = CGColorGetNumberOfComponents(tintColor.CGColor); 136 | if (componentCount == 2) { 137 | CGFloat b; 138 | if ([tintColor getWhite:&b alpha:NULL]) { 139 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha]; 140 | } 141 | } 142 | else { 143 | CGFloat r, g, b; 144 | if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) { 145 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha]; 146 | } 147 | } 148 | return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil]; 149 | } 150 | 151 | 152 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage 153 | { 154 | // Check pre-conditions. 155 | if (self.size.width < 1 || self.size.height < 1) { 156 | NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self); 157 | return nil; 158 | } 159 | if (!self.CGImage) { 160 | NSLog (@"*** error: image must be backed by a CGImage: %@", self); 161 | return nil; 162 | } 163 | if (maskImage && !maskImage.CGImage) { 164 | NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage); 165 | return nil; 166 | } 167 | 168 | CGRect imageRect = { CGPointZero, self.size }; 169 | UIImage *effectImage = self; 170 | 171 | BOOL hasBlur = blurRadius > __FLT_EPSILON__; 172 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__; 173 | if (hasBlur || hasSaturationChange) { 174 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 175 | CGContextRef effectInContext = UIGraphicsGetCurrentContext(); 176 | CGContextScaleCTM(effectInContext, 1.0, -1.0); 177 | CGContextTranslateCTM(effectInContext, 0, -self.size.height); 178 | CGContextDrawImage(effectInContext, imageRect, self.CGImage); 179 | 180 | vImage_Buffer effectInBuffer; 181 | effectInBuffer.data = CGBitmapContextGetData(effectInContext); 182 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext); 183 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext); 184 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext); 185 | 186 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 187 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext(); 188 | vImage_Buffer effectOutBuffer; 189 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext); 190 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext); 191 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext); 192 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext); 193 | 194 | if (hasBlur) { 195 | // A description of how to compute the box kernel width from the Gaussian 196 | // radius (aka standard deviation) appears in the SVG spec: 197 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement 198 | // 199 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three 200 | // successive box-blurs build a piece-wise quadratic convolution kernel, which 201 | // approximates the Gaussian kernel to within roughly 3%. 202 | // 203 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) 204 | // 205 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. 206 | // 207 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale]; 208 | uint32_t radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5); 209 | if (radius % 2 != 1) { 210 | radius += 1; // force radius to be odd so that the three box-blur methodology works. 211 | } 212 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); 213 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); 214 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend); 215 | } 216 | BOOL effectImageBuffersAreSwapped = NO; 217 | if (hasSaturationChange) { 218 | CGFloat s = saturationDeltaFactor; 219 | CGFloat floatingPointSaturationMatrix[] = { 220 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0, 221 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0, 222 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0, 223 | 0, 0, 0, 1, 224 | }; 225 | const int32_t divisor = 256; 226 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]); 227 | int16_t saturationMatrix[matrixSize]; 228 | for (NSUInteger i = 0; i < matrixSize; ++i) { 229 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor); 230 | } 231 | if (hasBlur) { 232 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); 233 | effectImageBuffersAreSwapped = YES; 234 | } 235 | else { 236 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); 237 | } 238 | } 239 | if (!effectImageBuffersAreSwapped) 240 | effectImage = UIGraphicsGetImageFromCurrentImageContext(); 241 | UIGraphicsEndImageContext(); 242 | 243 | if (effectImageBuffersAreSwapped) 244 | effectImage = UIGraphicsGetImageFromCurrentImageContext(); 245 | UIGraphicsEndImageContext(); 246 | } 247 | 248 | // Set up output context. 249 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 250 | CGContextRef outputContext = UIGraphicsGetCurrentContext(); 251 | CGContextScaleCTM(outputContext, 1.0, -1.0); 252 | CGContextTranslateCTM(outputContext, 0, -self.size.height); 253 | 254 | // Draw base image. 255 | CGContextDrawImage(outputContext, imageRect, self.CGImage); 256 | 257 | // Draw effect image. 258 | if (hasBlur) { 259 | CGContextSaveGState(outputContext); 260 | if (maskImage) { 261 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage); 262 | } 263 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage); 264 | CGContextRestoreGState(outputContext); 265 | } 266 | 267 | // Add in color tint. 268 | if (tintColor) { 269 | CGContextSaveGState(outputContext); 270 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor); 271 | CGContextFillRect(outputContext, imageRect); 272 | CGContextRestoreGState(outputContext); 273 | } 274 | 275 | // Output image is ready. 276 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 277 | UIGraphicsEndImageContext(); 278 | 279 | return outputImage; 280 | } 281 | 282 | + (UIImage *)imageWithColor:(UIColor *)color 283 | { 284 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 285 | UIGraphicsBeginImageContext(rect.size); 286 | CGContextRef context = UIGraphicsGetCurrentContext(); 287 | 288 | CGContextSetFillColorWithColor(context, [color CGColor]); 289 | CGContextFillRect(context, rect); 290 | 291 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 292 | UIGraphicsEndImageContext(); 293 | 294 | return image; 295 | } 296 | 297 | + (UIImage *)convertViewToImage 298 | { 299 | UIWindow *keyWindow = [[UIApplication sharedApplication]keyWindow]; 300 | CGRect rect = [keyWindow bounds]; 301 | UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f); 302 | CGContextRef context = UIGraphicsGetCurrentContext(); 303 | [keyWindow.layer renderInContext:context]; 304 | UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext(); 305 | UIGraphicsEndImageContext(); 306 | 307 | return capturedScreen; 308 | } 309 | 310 | + (UIImage *)convertViewToImage:(UIView *)view 311 | { 312 | CGFloat scale = [UIScreen mainScreen].scale; 313 | UIImage *capturedScreen; 314 | 315 | //Optimized/fast method for rendering a UIView as image on iOS 7 and later versions. 316 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, scale); 317 | [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; 318 | capturedScreen = UIGraphicsGetImageFromCurrentImageContext(); 319 | UIGraphicsEndImageContext(); 320 | 321 | return capturedScreen; 322 | } 323 | 324 | @end 325 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertViewStyleKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertViewStyleKit.m 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #import "SCLAlertViewStyleKit.h" 10 | 11 | // ------------------------------------ 12 | // Icon drawing 13 | // Code generated by PaintCode 14 | // ------------------------------------ 15 | @implementation SCLAlertViewStyleKit 16 | 17 | #pragma mark - Cache 18 | 19 | static UIImage *imageOfCheckmark = nil; 20 | static UIImage *imageOfCross = nil; 21 | static UIImage *imageOfNotice = nil; 22 | static UIImage *imageOfWarning = nil; 23 | static UIImage *imageOfInfo = nil; 24 | static UIImage *imageOfEdit = nil; 25 | static UIImage *imageOfQuestion = nil; 26 | 27 | #pragma mark - Initialization 28 | 29 | + (void)initialize 30 | { 31 | // Do something 32 | } 33 | 34 | #pragma mark - Drawing Methods 35 | 36 | + (void)drawCheckmark 37 | { 38 | // Checkmark Shape Drawing 39 | UIBezierPath *checkmarkShapePath = [[UIBezierPath alloc] init]; 40 | [checkmarkShapePath moveToPoint:CGPointMake(73.25, 14.05)]; 41 | [checkmarkShapePath addCurveToPoint:CGPointMake(64.51, 13.86) controlPoint1: CGPointMake(70.98, 11.44) controlPoint2: CGPointMake(66.78, 11.26)]; 42 | [checkmarkShapePath addLineToPoint:CGPointMake(27.46, 52)]; 43 | [checkmarkShapePath addLineToPoint:CGPointMake(15.75, 39.54)]; 44 | [checkmarkShapePath addCurveToPoint:CGPointMake(6.84, 39.54) controlPoint1: CGPointMake(13.48, 36.93) controlPoint2: CGPointMake(9.28, 36.93)]; 45 | [checkmarkShapePath addCurveToPoint:CGPointMake(6.84, 49.02) controlPoint1: CGPointMake(4.39, 42.14) controlPoint2: CGPointMake(4.39, 46.42)]; 46 | [checkmarkShapePath addLineToPoint:CGPointMake(22.91, 66.14)]; 47 | [checkmarkShapePath addCurveToPoint:CGPointMake(27.28, 68) controlPoint1: CGPointMake(24.14, 67.44) controlPoint2: CGPointMake(25.71, 68)]; 48 | [checkmarkShapePath addCurveToPoint:CGPointMake(31.65, 66.14) controlPoint1: CGPointMake(28.86, 68) controlPoint2: CGPointMake(30.43, 67.26)]; 49 | [checkmarkShapePath addLineToPoint:CGPointMake(73.08, 23.35)]; 50 | [checkmarkShapePath addCurveToPoint:CGPointMake(73.25, 14.05) controlPoint1: CGPointMake(75.52, 20.75) controlPoint2: CGPointMake(75.7, 16.65)]; 51 | [checkmarkShapePath closePath]; 52 | checkmarkShapePath.miterLimit = 4; 53 | 54 | [[UIColor whiteColor] setFill]; 55 | [checkmarkShapePath fill]; 56 | } 57 | 58 | + (void)drawCross 59 | { 60 | // Cross Shape Drawing 61 | UIBezierPath *crossShapePath = [[UIBezierPath alloc] init]; 62 | [crossShapePath moveToPoint:CGPointMake(10, 70)]; 63 | [crossShapePath addLineToPoint:CGPointMake(70, 10)]; 64 | [crossShapePath moveToPoint:CGPointMake(10, 10)]; 65 | [crossShapePath addLineToPoint:CGPointMake(70, 70)]; 66 | 67 | crossShapePath.lineCapStyle = kCGLineCapRound; 68 | crossShapePath.lineJoinStyle = kCGLineJoinRound; 69 | 70 | [[UIColor whiteColor] setStroke]; 71 | crossShapePath.lineWidth = 14; 72 | [crossShapePath stroke]; 73 | } 74 | 75 | + (void)drawNotice 76 | { 77 | // Notice Shape Drawing 78 | UIBezierPath *noticeShapePath = [[UIBezierPath alloc] init]; 79 | [noticeShapePath moveToPoint:CGPointMake(72, 48.54)]; 80 | [noticeShapePath addLineToPoint:CGPointMake(72, 39.9)]; 81 | [noticeShapePath addCurveToPoint:CGPointMake(66.38, 34.01) controlPoint1: CGPointMake(72, 36.76) controlPoint2: CGPointMake(69.48, 34.01)]; 82 | [noticeShapePath addCurveToPoint:CGPointMake(61.53, 35.97) controlPoint1: CGPointMake(64.82, 34.01) controlPoint2: CGPointMake(62.69, 34.8)]; 83 | [noticeShapePath addCurveToPoint:CGPointMake(60.36, 35.78) controlPoint1: CGPointMake(61.33, 35.97) controlPoint2: CGPointMake(62.3, 35.78)]; 84 | [noticeShapePath addLineToPoint:CGPointMake(60.36, 33.22)]; 85 | [noticeShapePath addCurveToPoint:CGPointMake(54.16, 26.16) controlPoint1: CGPointMake(60.36, 29.3) controlPoint2: CGPointMake(57.65, 26.16)]; 86 | [noticeShapePath addCurveToPoint:CGPointMake(48.73, 29.89) controlPoint1: CGPointMake(51.64, 26.16) controlPoint2: CGPointMake(50.67, 27.73)]; 87 | [noticeShapePath addLineToPoint:CGPointMake(48.73, 28.71)]; 88 | [noticeShapePath addCurveToPoint:CGPointMake(43.49, 21.64) controlPoint1: CGPointMake(48.73, 24.78) controlPoint2: CGPointMake(46.98, 21.64)]; 89 | [noticeShapePath addCurveToPoint:CGPointMake(39.03, 25.37) controlPoint1: CGPointMake(40.97, 21.64) controlPoint2: CGPointMake(39.03, 23.01)]; 90 | [noticeShapePath addLineToPoint:CGPointMake(39.03, 9.07)]; 91 | [noticeShapePath addCurveToPoint:CGPointMake(32.24, 2) controlPoint1: CGPointMake(39.03, 5.14) controlPoint2: CGPointMake(35.73, 2)]; 92 | [noticeShapePath addCurveToPoint:CGPointMake(25.45, 9.07) controlPoint1: CGPointMake(28.56, 2) controlPoint2: CGPointMake(25.45, 5.14)]; 93 | [noticeShapePath addLineToPoint:CGPointMake(25.45, 41.47)]; 94 | [noticeShapePath addCurveToPoint:CGPointMake(24.29, 43.44) controlPoint1: CGPointMake(25.45, 42.45) controlPoint2: CGPointMake(24.68, 43.04)]; 95 | [noticeShapePath addCurveToPoint:CGPointMake(9.55, 43.04) controlPoint1: CGPointMake(16.73, 40.88) controlPoint2: CGPointMake(11.88, 40.69)]; 96 | [noticeShapePath addCurveToPoint:CGPointMake(8, 46.58) controlPoint1: CGPointMake(8.58, 43.83) controlPoint2: CGPointMake(8, 45.2)]; 97 | [noticeShapePath addCurveToPoint:CGPointMake(14.4, 55.81) controlPoint1: CGPointMake(8.19, 50.31) controlPoint2: CGPointMake(12.07, 53.84)]; 98 | [noticeShapePath addLineToPoint:CGPointMake(27.2, 69.56)]; 99 | [noticeShapePath addCurveToPoint:CGPointMake(42.91, 77.8) controlPoint1: CGPointMake(30.5, 74.47) controlPoint2: CGPointMake(35.73, 77.21)]; 100 | [noticeShapePath addCurveToPoint:CGPointMake(43.88, 77.8) controlPoint1: CGPointMake(43.3, 77.8) controlPoint2: CGPointMake(43.68, 77.8)]; 101 | [noticeShapePath addCurveToPoint:CGPointMake(47.18, 78) controlPoint1: CGPointMake(45.04, 77.8) controlPoint2: CGPointMake(46.01, 78)]; 102 | [noticeShapePath addLineToPoint:CGPointMake(48.34, 78)]; 103 | [noticeShapePath addLineToPoint:CGPointMake(48.34, 78)]; 104 | [noticeShapePath addCurveToPoint:CGPointMake(71.61, 52.08) controlPoint1: CGPointMake(56.48, 78) controlPoint2: CGPointMake(69.87, 75.05)]; 105 | [noticeShapePath addCurveToPoint:CGPointMake(72, 48.54) controlPoint1: CGPointMake(71.81, 51.29) controlPoint2: CGPointMake(72, 49.72)]; 106 | [noticeShapePath closePath]; 107 | noticeShapePath.miterLimit = 4; 108 | 109 | [[UIColor whiteColor] setFill]; 110 | [noticeShapePath fill]; 111 | } 112 | 113 | + (void)drawWarning 114 | { 115 | // Color Declarations 116 | UIColor *greyColor = [UIColor colorWithRed:0.236 green:0.236 blue:0.236 alpha:1.000]; 117 | 118 | // Warning Group 119 | // Warning Circle Drawing 120 | UIBezierPath *warningCirclePath = [[UIBezierPath alloc] init]; 121 | [warningCirclePath moveToPoint:CGPointMake(40.94, 63.39)]; 122 | [warningCirclePath addCurveToPoint:CGPointMake(36.03, 65.55) controlPoint1: CGPointMake(39.06, 63.39) controlPoint2: CGPointMake(37.36, 64.18)]; 123 | [warningCirclePath addCurveToPoint:CGPointMake(34.14, 70.45) controlPoint1: CGPointMake(34.9, 66.92) controlPoint2: CGPointMake(34.14, 68.49)]; 124 | [warningCirclePath addCurveToPoint:CGPointMake(36.22, 75.54) controlPoint1: CGPointMake(34.14, 72.41) controlPoint2: CGPointMake(34.9, 74.17)]; 125 | [warningCirclePath addCurveToPoint:CGPointMake(40.94, 77.5) controlPoint1: CGPointMake(37.54, 76.91) controlPoint2: CGPointMake(39.06, 77.5)]; 126 | [warningCirclePath addCurveToPoint:CGPointMake(45.86, 75.35) controlPoint1: CGPointMake(42.83, 77.5) controlPoint2: CGPointMake(44.53, 76.72)]; 127 | [warningCirclePath addCurveToPoint:CGPointMake(47.93, 70.45) controlPoint1: CGPointMake(47.18, 74.17) controlPoint2: CGPointMake(47.93, 72.41)]; 128 | [warningCirclePath addCurveToPoint:CGPointMake(45.86, 65.35) controlPoint1: CGPointMake(47.93, 68.49) controlPoint2: CGPointMake(47.18, 66.72)]; 129 | [warningCirclePath addCurveToPoint:CGPointMake(40.94, 63.39) controlPoint1: CGPointMake(44.53, 64.18) controlPoint2: CGPointMake(42.83, 63.39)]; 130 | [warningCirclePath closePath]; 131 | warningCirclePath.miterLimit = 4; 132 | 133 | [greyColor setFill]; 134 | [warningCirclePath fill]; 135 | 136 | 137 | //// Warning Shape Drawing 138 | UIBezierPath *warningShapePath = [[UIBezierPath alloc] init]; 139 | [warningShapePath moveToPoint:CGPointMake(46.23, 4.26)]; 140 | [warningShapePath addCurveToPoint:CGPointMake(40.94, 2.5) controlPoint1: CGPointMake(44.91, 3.09) controlPoint2: CGPointMake(43.02, 2.5)]; 141 | [warningShapePath addCurveToPoint:CGPointMake(34.71, 4.26) controlPoint1: CGPointMake(38.68, 2.5) controlPoint2: CGPointMake(36.03, 3.09)]; 142 | [warningShapePath addCurveToPoint:CGPointMake(31.5, 8.77) controlPoint1: CGPointMake(33.01, 5.44) controlPoint2: CGPointMake(31.5, 7.01)]; 143 | [warningShapePath addLineToPoint:CGPointMake(31.5, 19.36)]; 144 | [warningShapePath addLineToPoint:CGPointMake(34.71, 54.44)]; 145 | [warningShapePath addCurveToPoint:CGPointMake(40.38, 58.16) controlPoint1: CGPointMake(34.9, 56.2) controlPoint2: CGPointMake(36.41, 58.16)]; 146 | [warningShapePath addCurveToPoint:CGPointMake(45.67, 54.44) controlPoint1: CGPointMake(44.34, 58.16) controlPoint2: CGPointMake(45.67, 56.01)]; 147 | [warningShapePath addLineToPoint:CGPointMake(48.5, 19.36)]; 148 | [warningShapePath addLineToPoint:CGPointMake(48.5, 8.77)]; 149 | [warningShapePath addCurveToPoint:CGPointMake(46.23, 4.26) controlPoint1: CGPointMake(48.5, 7.01) controlPoint2: CGPointMake(47.74, 5.44)]; 150 | [warningShapePath closePath]; 151 | warningShapePath.miterLimit = 4; 152 | 153 | [greyColor setFill]; 154 | [warningShapePath fill]; 155 | } 156 | 157 | + (void)drawInfo 158 | { 159 | // Color Declarations 160 | UIColor *color0 = [UIColor colorWithRed:1.000 green:1.000 blue:1.000 alpha:1.000]; 161 | 162 | // Info Shape Drawing 163 | UIBezierPath *infoShapePath = [[UIBezierPath alloc] init]; 164 | [infoShapePath moveToPoint:CGPointMake(45.66, 15.96)]; 165 | [infoShapePath addCurveToPoint:CGPointMake(45.66, 5.22) controlPoint1: CGPointMake(48.78, 12.99) controlPoint2: CGPointMake(48.78, 8.19)]; 166 | [infoShapePath addCurveToPoint:CGPointMake(34.34, 5.22) controlPoint1: CGPointMake(42.53, 2.26) controlPoint2: CGPointMake(37.47, 2.26)]; 167 | [infoShapePath addCurveToPoint:CGPointMake(34.34, 15.96) controlPoint1: CGPointMake(31.22, 8.19) controlPoint2: CGPointMake(31.22, 12.99)]; 168 | [infoShapePath addCurveToPoint:CGPointMake(45.66, 15.96) controlPoint1: CGPointMake(37.47, 18.92) controlPoint2: CGPointMake(42.53, 18.92)]; 169 | [infoShapePath closePath]; 170 | 171 | [infoShapePath moveToPoint:CGPointMake(48, 69.41)]; 172 | [infoShapePath addCurveToPoint:CGPointMake(40, 77) controlPoint1: CGPointMake(48, 73.58) controlPoint2: CGPointMake(44.4, 77)]; 173 | [infoShapePath addLineToPoint:CGPointMake(40, 77)]; 174 | [infoShapePath addCurveToPoint:CGPointMake(32, 69.41) controlPoint1: CGPointMake(35.6, 77) controlPoint2: CGPointMake(32, 73.58)]; 175 | [infoShapePath addLineToPoint:CGPointMake(32, 35.26)]; 176 | [infoShapePath addCurveToPoint:CGPointMake(40, 27.67) controlPoint1: CGPointMake(32, 31.08) controlPoint2: CGPointMake(35.6, 27.67)]; 177 | [infoShapePath addLineToPoint:CGPointMake(40, 27.67)]; 178 | [infoShapePath addCurveToPoint:CGPointMake(48, 35.26) controlPoint1: CGPointMake(44.4, 27.67) controlPoint2: CGPointMake(48, 31.08)]; 179 | [infoShapePath addLineToPoint:CGPointMake(48, 69.41)]; 180 | [infoShapePath closePath]; 181 | 182 | [color0 setFill]; 183 | [infoShapePath fill]; 184 | } 185 | 186 | + (void)drawEdit 187 | { 188 | // Color Declarations 189 | UIColor *color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; 190 | 191 | // Edit shape Drawing 192 | UIBezierPath *editPathPath = [[UIBezierPath alloc] init]; 193 | [editPathPath moveToPoint:CGPointMake(71, 2.7)]; 194 | [editPathPath addCurveToPoint:CGPointMake(71.9, 15.2) controlPoint1:CGPointMake(74.7, 5.9) controlPoint2:CGPointMake(75.1, 11.6)]; 195 | [editPathPath addLineToPoint:CGPointMake(64.5, 23.7)]; 196 | [editPathPath addLineToPoint:CGPointMake(49.9, 11.1)]; 197 | [editPathPath addLineToPoint:CGPointMake(57.3, 2.6)]; 198 | [editPathPath addCurveToPoint:CGPointMake(69.7, 1.7) controlPoint1:CGPointMake(60.4, -1.1) controlPoint2:CGPointMake(66.1, -1.5)]; 199 | [editPathPath addLineToPoint:CGPointMake(71, 2.7)]; 200 | [editPathPath addLineToPoint:CGPointMake(71, 2.7)]; 201 | [editPathPath closePath]; 202 | 203 | [editPathPath moveToPoint:CGPointMake(47.8, 13.5)]; 204 | [editPathPath addLineToPoint:CGPointMake(13.4, 53.1)]; 205 | [editPathPath addLineToPoint:CGPointMake(15.7, 55.1)]; 206 | [editPathPath addLineToPoint:CGPointMake(50.1, 15.5)]; 207 | [editPathPath addLineToPoint:CGPointMake(47.8, 13.5)]; 208 | [editPathPath addLineToPoint:CGPointMake(47.8, 13.5)]; 209 | [editPathPath closePath]; 210 | 211 | [editPathPath moveToPoint:CGPointMake(17.7, 56.7)]; 212 | [editPathPath addLineToPoint:CGPointMake(23.8, 62.2)]; 213 | [editPathPath addLineToPoint:CGPointMake(58.2, 22.6)]; 214 | [editPathPath addLineToPoint:CGPointMake(52, 17.1)]; 215 | [editPathPath addLineToPoint:CGPointMake(17.7, 56.7)]; 216 | [editPathPath addLineToPoint:CGPointMake(17.7, 56.7)]; 217 | [editPathPath closePath]; 218 | 219 | [editPathPath moveToPoint:CGPointMake(25.8, 63.8)]; 220 | [editPathPath addLineToPoint:CGPointMake(60.1, 24.2)]; 221 | [editPathPath addLineToPoint:CGPointMake(62.3, 26.1)]; 222 | [editPathPath addLineToPoint:CGPointMake(28.1, 65.7)]; 223 | [editPathPath addLineToPoint:CGPointMake(25.8, 63.8)]; 224 | [editPathPath addLineToPoint:CGPointMake(25.8, 63.8)]; 225 | [editPathPath closePath]; 226 | 227 | [editPathPath moveToPoint:CGPointMake(25.9, 68.1)]; 228 | [editPathPath addLineToPoint:CGPointMake(4.2, 79.5)]; 229 | [editPathPath addLineToPoint:CGPointMake(11.3, 55.5)]; 230 | [editPathPath addLineToPoint:CGPointMake(25.9, 68.1)]; 231 | [editPathPath closePath]; 232 | 233 | editPathPath.miterLimit = 4; 234 | editPathPath.usesEvenOddFillRule = YES; 235 | [color setFill]; 236 | [editPathPath fill]; 237 | } 238 | 239 | + (void)drawQuestion 240 | { 241 | // Color Declarations 242 | UIColor *color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; 243 | 244 | // Questionmark Shape Drawing 245 | UIBezierPath *questionShapePath = [[UIBezierPath alloc] init]; 246 | [questionShapePath moveToPoint: CGPointMake(33.75, 54.1)]; 247 | [questionShapePath addLineToPoint: CGPointMake(44.15, 54.1)]; 248 | [questionShapePath addLineToPoint: CGPointMake(44.15, 47.5)]; 249 | [questionShapePath addCurveToPoint: CGPointMake(51.85, 37.2) controlPoint1: CGPointMake(44.15, 42.9) controlPoint2: CGPointMake(46.75, 41.2)]; 250 | [questionShapePath addCurveToPoint: CGPointMake(61.95, 19.9) controlPoint1: CGPointMake(59.05, 31.6) controlPoint2: CGPointMake(61.95, 28.5)]; 251 | [questionShapePath addCurveToPoint: CGPointMake(41.45, 2.8) controlPoint1: CGPointMake(61.95, 7.6) controlPoint2: CGPointMake(52.85, 2.8)]; 252 | [questionShapePath addCurveToPoint: CGPointMake(25.05, 5.8) controlPoint1: CGPointMake(34.75, 2.8) controlPoint2: CGPointMake(29.65, 3.8)]; 253 | [questionShapePath addLineToPoint: CGPointMake(25.05, 14.4)]; 254 | [questionShapePath addCurveToPoint: CGPointMake(38.15, 12.3) controlPoint1: CGPointMake(29.15, 13.2) controlPoint2: CGPointMake(32.35, 12.3)]; 255 | [questionShapePath addCurveToPoint: CGPointMake(49.65, 20.8) controlPoint1: CGPointMake(45.65, 12.3) controlPoint2: CGPointMake(49.65, 14.4)]; 256 | [questionShapePath addCurveToPoint: CGPointMake(43.65, 31.7) controlPoint1: CGPointMake(49.65, 26) controlPoint2: CGPointMake(47.95, 28.4)]; 257 | [questionShapePath addCurveToPoint: CGPointMake(33.75, 46.6) controlPoint1: CGPointMake(37.15, 36.9) controlPoint2: CGPointMake(33.75, 39.7)]; 258 | [questionShapePath addLineToPoint: CGPointMake(33.75, 54.1)]; 259 | [questionShapePath closePath]; 260 | 261 | [questionShapePath moveToPoint: CGPointMake(33.15, 75.4)]; 262 | [questionShapePath addLineToPoint: CGPointMake(45.35, 75.4)]; 263 | [questionShapePath addLineToPoint: CGPointMake(45.35, 63.7)]; 264 | [questionShapePath addLineToPoint: CGPointMake(33.15, 63.7)]; 265 | [questionShapePath addLineToPoint: CGPointMake(33.15, 75.4)]; 266 | [questionShapePath closePath]; 267 | 268 | [color setFill]; 269 | [questionShapePath fill]; 270 | } 271 | 272 | #pragma mark - Images 273 | 274 | + (UIImage*)imageOfCheckmark 275 | { 276 | if (imageOfCheckmark != nil) 277 | { 278 | return imageOfCheckmark; 279 | } 280 | 281 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 282 | [SCLAlertViewStyleKit drawCheckmark]; 283 | imageOfCheckmark = UIGraphicsGetImageFromCurrentImageContext(); 284 | UIGraphicsEndImageContext(); 285 | 286 | return imageOfCheckmark; 287 | } 288 | 289 | 290 | + (UIImage*)imageOfCross 291 | { 292 | if (imageOfCross != nil) 293 | { 294 | return imageOfCross; 295 | } 296 | 297 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 298 | [SCLAlertViewStyleKit drawCross]; 299 | imageOfCross = UIGraphicsGetImageFromCurrentImageContext(); 300 | UIGraphicsEndImageContext(); 301 | 302 | return imageOfCross; 303 | } 304 | 305 | + (UIImage*)imageOfNotice 306 | { 307 | if (imageOfNotice != nil) 308 | { 309 | return imageOfNotice; 310 | } 311 | 312 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 313 | [SCLAlertViewStyleKit drawNotice]; 314 | imageOfNotice = UIGraphicsGetImageFromCurrentImageContext(); 315 | UIGraphicsEndImageContext(); 316 | 317 | return imageOfNotice; 318 | } 319 | 320 | + (UIImage*)imageOfWarning 321 | { 322 | if (imageOfWarning != nil) 323 | { 324 | return imageOfWarning; 325 | } 326 | 327 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 328 | [SCLAlertViewStyleKit drawWarning]; 329 | imageOfWarning = UIGraphicsGetImageFromCurrentImageContext(); 330 | UIGraphicsEndImageContext(); 331 | 332 | return imageOfWarning; 333 | } 334 | 335 | + (UIImage*)imageOfInfo 336 | { 337 | if (imageOfInfo != nil) 338 | { 339 | return imageOfInfo; 340 | } 341 | 342 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 343 | [SCLAlertViewStyleKit drawInfo]; 344 | imageOfInfo = UIGraphicsGetImageFromCurrentImageContext(); 345 | UIGraphicsEndImageContext(); 346 | 347 | return imageOfInfo; 348 | } 349 | 350 | + (UIImage*)imageOfEdit 351 | { 352 | if (imageOfEdit != nil) 353 | { 354 | return imageOfEdit; 355 | } 356 | 357 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 358 | [SCLAlertViewStyleKit drawEdit]; 359 | imageOfEdit = UIGraphicsGetImageFromCurrentImageContext(); 360 | UIGraphicsEndImageContext(); 361 | 362 | return imageOfEdit; 363 | } 364 | 365 | + (UIImage*)imageOfQuestion 366 | { 367 | if (imageOfQuestion != nil) 368 | { 369 | return imageOfQuestion; 370 | } 371 | 372 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 80), NO, 0); 373 | [SCLAlertViewStyleKit drawQuestion]; 374 | imageOfQuestion = UIGraphicsGetImageFromCurrentImageContext(); 375 | UIGraphicsEndImageContext(); 376 | 377 | return imageOfQuestion; 378 | } 379 | 380 | @end 381 | -------------------------------------------------------------------------------- /Vector3.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | 6 | 7 | struct Vector3 8 | { 9 | union 10 | { 11 | struct 12 | { 13 | float X; 14 | float Y; 15 | float Z; 16 | }; 17 | float data[3]; 18 | }; 19 | 20 | 21 | /** 22 | * Constructors. 23 | */ 24 | inline Vector3(); 25 | inline Vector3(float data[]); 26 | inline Vector3(float value); 27 | inline Vector3(float x, float y); 28 | inline Vector3(float x, float y, float z); 29 | 30 | 31 | /** 32 | * Constants for common vectors. 33 | */ 34 | static inline Vector3 Zero(); 35 | static inline Vector3 One(); 36 | static inline Vector3 Right(); 37 | static inline Vector3 Left(); 38 | static inline Vector3 Up(); 39 | static inline Vector3 Down(); 40 | static inline Vector3 Forward(); 41 | static inline Vector3 Backward(); 42 | 43 | 44 | /** 45 | * Returns the angle between two vectors in radians. 46 | * @param a: The first vector. 47 | * @param b: The second vector. 48 | * @return: A scalar value. 49 | */ 50 | static inline float Angle(Vector3 a, Vector3 b); 51 | 52 | /** 53 | * Returns a vector with its magnitude clamped to maxLength. 54 | * @param vector: The target vector. 55 | * @param maxLength: The maximum length of the return vector. 56 | * @return: A new vector. 57 | */ 58 | static inline Vector3 ClampMagnitude(Vector3 vector, float maxLength); 59 | 60 | /** 61 | * Returns the component of a in the direction of b (scalar projection). 62 | * @param a: The target vector. 63 | * @param b: The vector being compared against. 64 | * @return: A scalar value. 65 | */ 66 | static inline float Component(Vector3 a, Vector3 b); 67 | 68 | /** 69 | * Returns the cross product of two vectors. 70 | * @param lhs: The left side of the multiplication. 71 | * @param rhs: The right side of the multiplication. 72 | * @return: A new vector. 73 | */ 74 | static inline Vector3 Cross(Vector3 lhs, Vector3 rhs); 75 | 76 | /** 77 | * Returns the distance between a and b. 78 | * @param a: The first point. 79 | * @param b: The second point. 80 | * @return: A scalar value. 81 | */ 82 | static inline float Distance(Vector3 a, Vector3 b); 83 | 84 | static inline char ToChar(Vector3 a); 85 | 86 | /** 87 | * Returns the dot product of two vectors. 88 | * @param lhs: The left side of the multiplication. 89 | * @param rhs: The right side of the multiplication. 90 | * @return: A scalar value. 91 | */ 92 | static inline float Dot(Vector3 lhs, Vector3 rhs); 93 | 94 | /** 95 | * Converts a spherical representation of a vector into cartesian 96 | * coordinates. 97 | * This uses the ISO convention (radius r, inclination theta, azimuth phi). 98 | * @param rad: The magnitude of the vector. 99 | * @param theta: The angle in the XY plane from the X axis. 100 | * @param phi: The angle from the positive Z axis to the vector. 101 | * @return: A new vector. 102 | */ 103 | static inline Vector3 FromSpherical(float rad, float theta, float phi); 104 | 105 | /** 106 | * Returns a vector linearly interpolated between a and b, moving along 107 | * a straight line. The vector is clamped to never go beyond the end points. 108 | * @param a: The starting point. 109 | * @param b: The ending point. 110 | * @param t: The interpolation value [0-1]. 111 | * @return: A new vector. 112 | */ 113 | static inline Vector3 Lerp(Vector3 a, Vector3 b, float t); 114 | 115 | /** 116 | * Returns a vector linearly interpolated between a and b, moving along 117 | * a straight line. 118 | * @param a: The starting point. 119 | * @param b: The ending point. 120 | * @param t: The interpolation value [0-1] (no actual bounds). 121 | * @return: A new vector. 122 | */ 123 | static inline Vector3 LerpUnclamped(Vector3 a, Vector3 b, float t); 124 | 125 | /** 126 | * Returns the magnitude of a vector. 127 | * @param v: The vector in question. 128 | * @return: A scalar value. 129 | */ 130 | static inline float Magnitude(Vector3 v); 131 | 132 | /** 133 | * Returns a vector made from the largest components of two other vectors. 134 | * @param a: The first vector. 135 | * @param b: The second vector. 136 | * @return: A new vector. 137 | */ 138 | static inline Vector3 Max(Vector3 a, Vector3 b); 139 | 140 | /** 141 | * Returns a vector made from the smallest components of two other vectors. 142 | * @param a: The first vector. 143 | * @param b: The second vector. 144 | * @return: A new vector. 145 | */ 146 | static inline Vector3 Min(Vector3 a, Vector3 b); 147 | 148 | /** 149 | * Returns a vector "maxDistanceDelta" units closer to the target. This 150 | * interpolation is in a straight line, and will not overshoot. 151 | * @param current: The current position. 152 | * @param target: The destination position. 153 | * @param maxDistanceDelta: The maximum distance to move. 154 | * @return: A new vector. 155 | */ 156 | static inline Vector3 MoveTowards(Vector3 current, Vector3 target, 157 | float maxDistanceDelta); 158 | 159 | /** 160 | * Returns a new vector with magnitude of one. 161 | * @param v: The vector in question. 162 | * @return: A new vector. 163 | */ 164 | static inline Vector3 Normalized(Vector3 v); 165 | 166 | /** 167 | * Returns an arbitrary vector orthogonal to the input. 168 | * This vector is not normalized. 169 | * @param v: The input vector. 170 | * @return: A new vector. 171 | */ 172 | static inline Vector3 Orthogonal(Vector3 v); 173 | 174 | /** 175 | * Creates a new coordinate system out of the three vectors. 176 | * Normalizes "normal", normalizes "tangent" and makes it orthogonal to 177 | * "normal" and normalizes "binormal" and makes it orthogonal to both 178 | * "normal" and "tangent". 179 | * @param normal: A reference to the first axis vector. 180 | * @param tangent: A reference to the second axis vector. 181 | * @param binormal: A reference to the third axis vector. 182 | */ 183 | static inline void OrthoNormalize(Vector3 &normal, Vector3 &tangent, 184 | Vector3 &binormal); 185 | 186 | /** 187 | * Returns the vector projection of a onto b. 188 | * @param a: The target vector. 189 | * @param b: The vector being projected onto. 190 | * @return: A new vector. 191 | */ 192 | static inline Vector3 Project(Vector3 a, Vector3 b); 193 | 194 | /** 195 | * Returns a vector projected onto a plane orthogonal to "planeNormal". 196 | * This can be visualized as the shadow of the vector onto the plane, if 197 | * the light source were in the direction of the plane normal. 198 | * @param vector: The vector to project. 199 | * @param planeNormal: The normal of the plane onto which to project. 200 | * @param: A new vector. 201 | */ 202 | static inline Vector3 ProjectOnPlane(Vector3 vector, Vector3 planeNormal); 203 | 204 | /** 205 | * Returns a vector reflected off the plane orthogonal to the normal. 206 | * The input vector is pointed inward, at the plane, and the return vector 207 | * is pointed outward from the plane, like a beam of light hitting and then 208 | * reflecting off a mirror. 209 | * @param vector: The vector traveling inward at the plane. 210 | * @param planeNormal: The normal of the plane off of which to reflect. 211 | * @return: A new vector pointing outward from the plane. 212 | */ 213 | static inline Vector3 Reflect(Vector3 vector, Vector3 planeNormal); 214 | 215 | /** 216 | * Returns the vector rejection of a on b. 217 | * @param a: The target vector. 218 | * @param b: The vector being projected onto. 219 | * @return: A new vector. 220 | */ 221 | static inline Vector3 Reject(Vector3 a, Vector3 b); 222 | 223 | /** 224 | * Rotates vector "current" towards vector "target" by "maxRadiansDelta". 225 | * This treats the vectors as directions and will linearly interpolate 226 | * between their magnitudes by "maxMagnitudeDelta". This function does not 227 | * overshoot. If a negative delta is supplied, it will rotate away from 228 | * "target" until it is pointing the opposite direction, but will not 229 | * overshoot that either. 230 | * @param current: The starting direction. 231 | * @param target: The destination direction. 232 | * @param maxRadiansDelta: The maximum number of radians to rotate. 233 | * @param maxMagnitudeDelta: The maximum delta for magnitude interpolation. 234 | * @return: A new vector. 235 | */ 236 | static inline Vector3 RotateTowards(Vector3 current, Vector3 target, 237 | float maxRadiansDelta, 238 | float maxMagnitudeDelta); 239 | 240 | /** 241 | * Multiplies two vectors element-wise. 242 | * @param a: The lhs of the multiplication. 243 | * @param b: The rhs of the multiplication. 244 | * @return: A new vector. 245 | */ 246 | static inline Vector3 Scale(Vector3 a, Vector3 b); 247 | 248 | /** 249 | * Returns a vector rotated towards b from a by the percent t. 250 | * Since interpolation is done spherically, the vector moves at a constant 251 | * angular velocity. This rotation is clamped to 0 <= t <= 1. 252 | * @param a: The starting direction. 253 | * @param b: The ending direction. 254 | * @param t: The interpolation value [0-1]. 255 | */ 256 | static inline Vector3 Slerp(Vector3 a, Vector3 b, float t); 257 | 258 | /** 259 | * Returns a vector rotated towards b from a by the percent t. 260 | * Since interpolation is done spherically, the vector moves at a constant 261 | * angular velocity. This rotation is unclamped. 262 | * @param a: The starting direction. 263 | * @param b: The ending direction. 264 | * @param t: The interpolation value [0-1]. 265 | */ 266 | static inline Vector3 SlerpUnclamped(Vector3 a, Vector3 b, float t); 267 | 268 | /** 269 | * Returns the squared magnitude of a vector. 270 | * This is useful when comparing relative lengths, where the exact length 271 | * is not important, and much time can be saved by not calculating the 272 | * square root. 273 | * @param v: The vector in question. 274 | * @return: A scalar value. 275 | */ 276 | static inline float SqrMagnitude(Vector3 v); 277 | 278 | /** 279 | * Calculates the spherical coordinate space representation of a vector. 280 | * This uses the ISO convention (radius r, inclination theta, azimuth phi). 281 | * @param vector: The vector to convert. 282 | * @param rad: The magnitude of the vector. 283 | * @param theta: The angle in the XY plane from the X axis. 284 | * @param phi: The angle from the positive Z axis to the vector. 285 | */ 286 | static inline void ToSpherical(Vector3 vector, float &rad, float &theta, 287 | float &phi); 288 | 289 | 290 | /** 291 | * Operator overloading. 292 | */ 293 | inline struct Vector3& operator+=(const float rhs); 294 | inline struct Vector3& operator-=(const float rhs); 295 | inline struct Vector3& operator*=(const float rhs); 296 | inline struct Vector3& operator/=(const float rhs); 297 | inline struct Vector3& operator+=(const Vector3 rhs); 298 | inline struct Vector3& operator-=(const Vector3 rhs); 299 | }; 300 | 301 | inline Vector3 operator-(Vector3 rhs); 302 | inline Vector3 operator+(Vector3 lhs, const float rhs); 303 | inline Vector3 operator-(Vector3 lhs, const float rhs); 304 | inline Vector3 operator*(Vector3 lhs, const float rhs); 305 | inline Vector3 operator/(Vector3 lhs, const float rhs); 306 | inline Vector3 operator+(const float lhs, Vector3 rhs); 307 | inline Vector3 operator-(const float lhs, Vector3 rhs); 308 | inline Vector3 operator*(const float lhs, Vector3 rhs); 309 | inline Vector3 operator/(const float lhs, Vector3 rhs); 310 | inline Vector3 operator+(Vector3 lhs, const Vector3 rhs); 311 | inline Vector3 operator-(Vector3 lhs, const Vector3 rhs); 312 | inline bool operator==(const Vector3 lhs, const Vector3 rhs); 313 | inline bool operator!=(const Vector3 lhs, const Vector3 rhs); 314 | 315 | 316 | 317 | /******************************************************************************* 318 | * Implementation 319 | */ 320 | 321 | Vector3::Vector3() : X(0), Y(0), Z(0) {} 322 | Vector3::Vector3(float data[]) : X(data[0]), Y(data[1]), Z(data[2]) {} 323 | Vector3::Vector3(float value) : X(value), Y(value), Z(value) {} 324 | Vector3::Vector3(float x, float y) : X(x), Y(y), Z(0) {} 325 | Vector3::Vector3(float x, float y, float z) : X(x), Y(y), Z(z) {} 326 | 327 | 328 | Vector3 Vector3::Zero() { return Vector3(0, 0, 0); } 329 | Vector3 Vector3::One() { return Vector3(1, 1, 1); } 330 | Vector3 Vector3::Right() { return Vector3(1, 0, 0); } 331 | Vector3 Vector3::Left() { return Vector3(-1, 0, 0); } 332 | Vector3 Vector3::Up() { return Vector3(0, 1, 0); } 333 | Vector3 Vector3::Down() { return Vector3(0, -1, 0); } 334 | Vector3 Vector3::Forward() { return Vector3(0, 0, 1); } 335 | Vector3 Vector3::Backward() { return Vector3(0, 0, -1); } 336 | 337 | 338 | float Vector3::Angle(Vector3 a, Vector3 b) 339 | { 340 | float v = Dot(a, b) / (Magnitude(a) * Magnitude(b)); 341 | v = fmax(v, -1.0); 342 | v = fmin(v, 1.0); 343 | return acos(v); 344 | } 345 | 346 | Vector3 Vector3::ClampMagnitude(Vector3 vector, float maxLength) 347 | { 348 | float length = Magnitude(vector); 349 | if (length > maxLength) 350 | vector *= maxLength / length; 351 | return vector; 352 | } 353 | 354 | float Vector3::Component(Vector3 a, Vector3 b) 355 | { 356 | return Dot(a, b) / Magnitude(b); 357 | } 358 | 359 | Vector3 Vector3::Cross(Vector3 lhs, Vector3 rhs) 360 | { 361 | float x = lhs.Y * rhs.Z - lhs.Z * rhs.Y; 362 | float y = lhs.Z * rhs.X - lhs.X * rhs.Z; 363 | float z = lhs.X * rhs.Y - lhs.Y * rhs.X; 364 | return Vector3(x, y, z); 365 | } 366 | 367 | float Vector3::Distance(Vector3 a, Vector3 b) 368 | { 369 | return Vector3::Magnitude(a - b); 370 | } 371 | 372 | float Vector3::Dot(Vector3 lhs, Vector3 rhs) 373 | { 374 | return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z; 375 | } 376 | 377 | Vector3 Vector3::FromSpherical(float rad, float theta, float phi) 378 | { 379 | Vector3 v; 380 | v.X = rad * sin(theta) * cos(phi); 381 | v.Y = rad * sin(theta) * sin(phi); 382 | v.Z = rad * cos(theta); 383 | return v; 384 | } 385 | 386 | Vector3 Vector3::Lerp(Vector3 a, Vector3 b, float t) 387 | { 388 | if (t < 0) return a; 389 | else if (t > 1) return b; 390 | return LerpUnclamped(a, b, t); 391 | } 392 | 393 | Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, float t) 394 | { 395 | return (b - a) * t + a; 396 | } 397 | 398 | float Vector3::Magnitude(Vector3 v) 399 | { 400 | return sqrt(SqrMagnitude(v)); 401 | } 402 | 403 | Vector3 Vector3::Max(Vector3 a, Vector3 b) 404 | { 405 | float x = a.X > b.X ? a.X : b.X; 406 | float y = a.Y > b.Y ? a.Y : b.Y; 407 | float z = a.Z > b.Z ? a.Z : b.Z; 408 | return Vector3(x, y, z); 409 | } 410 | 411 | Vector3 Vector3::Min(Vector3 a, Vector3 b) 412 | { 413 | float x = a.X > b.X ? b.X : a.X; 414 | float y = a.Y > b.Y ? b.Y : a.Y; 415 | float z = a.Z > b.Z ? b.Z : a.Z; 416 | return Vector3(x, y, z); 417 | } 418 | 419 | Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, 420 | float maxDistanceDelta) 421 | { 422 | Vector3 d = target - current; 423 | float m = Magnitude(d); 424 | if (m < maxDistanceDelta || m == 0) 425 | return target; 426 | return current + (d * maxDistanceDelta / m); 427 | } 428 | 429 | Vector3 Vector3::Normalized(Vector3 v) 430 | { 431 | float mag = Magnitude(v); 432 | if (mag == 0) 433 | return Vector3::Zero(); 434 | return v / mag; 435 | } 436 | 437 | Vector3 Vector3::Orthogonal(Vector3 v) 438 | { 439 | return v.Z < v.X ? Vector3(v.Y, -v.X, 0) : Vector3(0, -v.Z, v.Y); 440 | } 441 | 442 | void Vector3::OrthoNormalize(Vector3 &normal, Vector3 &tangent, 443 | Vector3 &binormal) 444 | { 445 | normal = Normalized(normal); 446 | tangent = ProjectOnPlane(tangent, normal); 447 | tangent = Normalized(tangent); 448 | binormal = ProjectOnPlane(binormal, tangent); 449 | binormal = ProjectOnPlane(binormal, normal); 450 | binormal = Normalized(binormal); 451 | } 452 | 453 | Vector3 Vector3::Project(Vector3 a, Vector3 b) 454 | { 455 | float m = Magnitude(b); 456 | return Dot(a, b) / (m * m) * b; 457 | } 458 | 459 | Vector3 Vector3::ProjectOnPlane(Vector3 vector, Vector3 planeNormal) 460 | { 461 | return Reject(vector, planeNormal); 462 | } 463 | 464 | Vector3 Vector3::Reflect(Vector3 vector, Vector3 planeNormal) 465 | { 466 | return vector - 2 * Project(vector, planeNormal); 467 | } 468 | 469 | Vector3 Vector3::Reject(Vector3 a, Vector3 b) 470 | { 471 | return a - Project(a, b); 472 | } 473 | 474 | Vector3 Vector3::RotateTowards(Vector3 current, Vector3 target, 475 | float maxRadiansDelta, 476 | float maxMagnitudeDelta) 477 | { 478 | float magCur = Magnitude(current); 479 | float magTar = Magnitude(target); 480 | float newMag = magCur + maxMagnitudeDelta * 481 | ((magTar > magCur) - (magCur > magTar)); 482 | newMag = fmin(newMag, fmax(magCur, magTar)); 483 | newMag = fmax(newMag, fmin(magCur, magTar)); 484 | 485 | float totalAngle = Angle(current, target) - maxRadiansDelta; 486 | if (totalAngle <= 0) 487 | return Normalized(target) * newMag; 488 | else if (totalAngle >= M_PI) 489 | return Normalized(-target) * newMag; 490 | 491 | Vector3 axis = Cross(current, target); 492 | float magAxis = Magnitude(axis); 493 | if (magAxis == 0) 494 | axis = Normalized(Cross(current, current + Vector3(3.95, 5.32, -4.24))); 495 | else 496 | axis /= magAxis; 497 | current = Normalized(current); 498 | Vector3 newVector = current * cos(maxRadiansDelta) + 499 | Cross(axis, current) * sin(maxRadiansDelta); 500 | return newVector * newMag; 501 | } 502 | 503 | Vector3 Vector3::Scale(Vector3 a, Vector3 b) 504 | { 505 | return Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); 506 | } 507 | 508 | Vector3 Vector3::Slerp(Vector3 a, Vector3 b, float t) 509 | { 510 | if (t < 0) return a; 511 | else if (t > 1) return b; 512 | return SlerpUnclamped(a, b, t); 513 | } 514 | 515 | Vector3 Vector3::SlerpUnclamped(Vector3 a, Vector3 b, float t) 516 | { 517 | float magA = Magnitude(a); 518 | float magB = Magnitude(b); 519 | a /= magA; 520 | b /= magB; 521 | float dot = Dot(a, b); 522 | dot = fmax(dot, -1.0); 523 | dot = fmin(dot, 1.0); 524 | float theta = acos(dot) * t; 525 | Vector3 relativeVec = Normalized(b - a * dot); 526 | Vector3 newVec = a * cos(theta) + relativeVec * sin(theta); 527 | return newVec * (magA + (magB - magA) * t); 528 | } 529 | 530 | float Vector3::SqrMagnitude(Vector3 v) 531 | { 532 | return v.X * v.X + v.Y * v.Y + v.Z * v.Z; 533 | } 534 | 535 | void Vector3::ToSpherical(Vector3 vector, float &rad, float &theta, 536 | float &phi) 537 | { 538 | rad = Magnitude(vector); 539 | float v = vector.Z / rad; 540 | v = fmax(v, -1.0); 541 | v = fmin(v, 1.0); 542 | theta = acos(v); 543 | phi = atan2(vector.Y, vector.X); 544 | } 545 | 546 | 547 | struct Vector3& Vector3::operator+=(const float rhs) 548 | { 549 | X += rhs; 550 | Y += rhs; 551 | Z += rhs; 552 | return *this; 553 | } 554 | 555 | struct Vector3& Vector3::operator-=(const float rhs) 556 | { 557 | X -= rhs; 558 | Y -= rhs; 559 | Z -= rhs; 560 | return *this; 561 | } 562 | 563 | struct Vector3& Vector3::operator*=(const float rhs) 564 | { 565 | X *= rhs; 566 | Y *= rhs; 567 | Z *= rhs; 568 | return *this; 569 | } 570 | 571 | struct Vector3& Vector3::operator/=(const float rhs) 572 | { 573 | X /= rhs; 574 | Y /= rhs; 575 | Z /= rhs; 576 | return *this; 577 | } 578 | 579 | struct Vector3& Vector3::operator+=(const Vector3 rhs) 580 | { 581 | X += rhs.X; 582 | Y += rhs.Y; 583 | Z += rhs.Z; 584 | return *this; 585 | } 586 | 587 | struct Vector3& Vector3::operator-=(const Vector3 rhs) 588 | { 589 | X -= rhs.X; 590 | Y -= rhs.Y; 591 | Z -= rhs.Z; 592 | return *this; 593 | } 594 | 595 | Vector3 operator-(Vector3 rhs) { return rhs * -1; } 596 | Vector3 operator+(Vector3 lhs, const float rhs) { return lhs += rhs; } 597 | Vector3 operator-(Vector3 lhs, const float rhs) { return lhs -= rhs; } 598 | Vector3 operator*(Vector3 lhs, const float rhs) { return lhs *= rhs; } 599 | Vector3 operator/(Vector3 lhs, const float rhs) { return lhs /= rhs; } 600 | Vector3 operator+(const float lhs, Vector3 rhs) { return rhs += lhs; } 601 | Vector3 operator-(const float lhs, Vector3 rhs) { return rhs -= lhs; } 602 | Vector3 operator*(const float lhs, Vector3 rhs) { return rhs *= lhs; } 603 | Vector3 operator/(const float lhs, Vector3 rhs) { return rhs /= lhs; } 604 | Vector3 operator+(Vector3 lhs, const Vector3 rhs) { return lhs += rhs; } 605 | Vector3 operator-(Vector3 lhs, const Vector3 rhs) { return lhs -= rhs; } 606 | 607 | bool operator==(const Vector3 lhs, const Vector3 rhs) 608 | { 609 | return lhs.X == rhs.X && lhs.Y == rhs.Y && lhs.Z == rhs.Z; 610 | } 611 | 612 | bool operator!=(const Vector3 lhs, const Vector3 rhs) 613 | { 614 | return !(lhs == rhs); 615 | } -------------------------------------------------------------------------------- /Quaternion.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | #define SMALL_float 0.0000000001 8 | 9 | 10 | /** 11 | * Attempt to include a header file if the file exists. 12 | * If the file does not exist, create a dummy data structure for that type. 13 | * If it cannot be determined if it exists, just attempt to include it. 14 | */ 15 | #include "Vector3.hpp" 16 | 17 | 18 | 19 | struct Quaternion 20 | { 21 | union 22 | { 23 | struct 24 | { 25 | float X; 26 | float Y; 27 | float Z; 28 | float W; 29 | }; 30 | float data[4]; 31 | }; 32 | 33 | 34 | /** 35 | * Constructors. 36 | */ 37 | inline Quaternion(); 38 | inline Quaternion(float data[]); 39 | inline Quaternion(Vector3 vector, float scalar); 40 | inline Quaternion(float x, float y, float z, float w); 41 | 42 | 43 | /** 44 | * Constants for common quaternions. 45 | */ 46 | static inline Quaternion Identity(); 47 | 48 | 49 | /** 50 | * Returns the angle between two quaternions. 51 | * The quaternions must be normalized. 52 | * @param a: The first quaternion. 53 | * @param b: The second quaternion. 54 | * @return: A scalar value. 55 | */ 56 | static inline float Angle(Quaternion a, Quaternion b); 57 | 58 | /** 59 | * Returns the conjugate of a quaternion. 60 | * @param rotation: The quaternion in question. 61 | * @return: A new quaternion. 62 | */ 63 | static inline Quaternion Conjugate(Quaternion rotation); 64 | 65 | /** 66 | * Returns the dot product of two quaternions. 67 | * @param lhs: The left side of the multiplication. 68 | * @param rhs: The right side of the multiplication. 69 | * @return: A scalar value. 70 | */ 71 | static inline float Dot(Quaternion lhs, Quaternion rhs); 72 | 73 | /** 74 | * Creates a new quaternion from the angle-axis representation of 75 | * a rotation. 76 | * @param angle: The rotation angle in radians. 77 | * @param axis: The vector about which the rotation occurs. 78 | * @return: A new quaternion. 79 | */ 80 | static inline Quaternion FromAngleAxis(float angle, Vector3 axis); 81 | 82 | /** 83 | * Create a new quaternion from the euler angle representation of 84 | * a rotation. The z, x and y values represent rotations about those 85 | * axis in that respective order. 86 | * @param rotation: The x, y and z rotations. 87 | * @return: A new quaternion. 88 | */ 89 | static inline Quaternion FromEuler(Vector3 rotation); 90 | 91 | /** 92 | * Create a new quaternion from the euler angle representation of 93 | * a rotation. The z, x and y values represent rotations about those 94 | * axis in that respective order. 95 | * @param x: The rotation about the x-axis in radians. 96 | * @param y: The rotation about the y-axis in radians. 97 | * @param z: The rotation about the z-axis in radians. 98 | * @return: A new quaternion. 99 | */ 100 | static inline Quaternion FromEuler(float x, float y, float z); 101 | 102 | /** 103 | * Create a quaternion rotation which rotates "fromVector" to "toVector". 104 | * @param fromVector: The vector from which to start the rotation. 105 | * @param toVector: The vector at which to end the rotation. 106 | * @return: A new quaternion. 107 | */ 108 | static inline Quaternion FromToRotation(Vector3 fromVector, 109 | Vector3 toVector); 110 | 111 | /** 112 | * Returns the inverse of a rotation. 113 | * @param rotation: The quaternion in question. 114 | * @return: A new quaternion. 115 | */ 116 | static inline Quaternion Inverse(Quaternion rotation); 117 | 118 | /** 119 | * Interpolates between a and b by t, which is clamped to the range [0-1]. 120 | * The result is normalized before being returned. 121 | * @param a: The starting rotation. 122 | * @param b: The ending rotation. 123 | * @return: A new quaternion. 124 | */ 125 | static inline Quaternion Lerp(Quaternion a, Quaternion b, float t); 126 | 127 | /** 128 | * Interpolates between a and b by t. This normalizes the result when 129 | * complete. 130 | * @param a: The starting rotation. 131 | * @param b: The ending rotation. 132 | * @param t: The interpolation value. 133 | * @return: A new quaternion. 134 | */ 135 | static inline Quaternion LerpUnclamped(Quaternion a, Quaternion b, 136 | float t); 137 | 138 | /** 139 | * Creates a rotation with the specified forward direction. This is the 140 | * same as calling LookRotation with (0, 1, 0) as the upwards vector. 141 | * The output is undefined for parallel vectors. 142 | * @param forward: The forward direction to look toward. 143 | * @return: A new quaternion. 144 | */ 145 | static inline Quaternion LookRotation(Vector3 forward); 146 | 147 | /** 148 | * Creates a rotation with the specified forward and upwards directions. 149 | * The output is undefined for parallel vectors. 150 | * @param forward: The forward direction to look toward. 151 | * @param upwards: The direction to treat as up. 152 | * @return: A new quaternion. 153 | */ 154 | static inline Quaternion LookRotation(Vector3 forward, Vector3 upwards); 155 | 156 | /** 157 | * Returns the norm of a quaternion. 158 | * @param rotation: The quaternion in question. 159 | * @return: A scalar value. 160 | */ 161 | static inline float Norm(Quaternion rotation); 162 | 163 | /** 164 | * Returns a quaternion with identical rotation and a norm of one. 165 | * @param rotation: The quaternion in question. 166 | * @return: A new quaternion. 167 | */ 168 | static inline Quaternion Normalized(Quaternion rotation); 169 | 170 | /** 171 | * Returns a new Quaternion created by rotating "from" towards "to" by 172 | * "maxRadiansDelta". This will not overshoot, and if a negative delta is 173 | * applied, it will rotate till completely opposite "to" and then stop. 174 | * @param from: The rotation at which to start. 175 | * @param to: The rotation at which to end. 176 | # @param maxRadiansDelta: The maximum number of radians to rotate. 177 | * @return: A new Quaternion. 178 | */ 179 | static inline Quaternion RotateTowards(Quaternion from, Quaternion to, 180 | float maxRadiansDelta); 181 | 182 | /** 183 | * Returns a new quaternion interpolated between a and b, using spherical 184 | * linear interpolation. The variable t is clamped to the range [0-1]. The 185 | * resulting quaternion will be normalized. 186 | * @param a: The starting rotation. 187 | * @param b: The ending rotation. 188 | * @param t: The interpolation value. 189 | * @return: A new quaternion. 190 | */ 191 | static inline Quaternion Slerp(Quaternion a, Quaternion b, float t); 192 | 193 | /** 194 | * Returns a new quaternion interpolated between a and b, using spherical 195 | * linear interpolation. The resulting quaternion will be normalized. 196 | * @param a: The starting rotation. 197 | * @param b: The ending rotation. 198 | * @param t: The interpolation value. 199 | * @return: A new quaternion. 200 | */ 201 | static inline Quaternion SlerpUnclamped(Quaternion a, Quaternion b, 202 | float t); 203 | 204 | /** 205 | * Outputs the angle axis representation of the provided quaternion. 206 | * @param rotation: The input quaternion. 207 | * @param angle: The output angle. 208 | * @param axis: The output axis. 209 | */ 210 | static inline void ToAngleAxis(Quaternion rotation, float &angle, 211 | Vector3 &axis); 212 | 213 | /** 214 | * Returns the Euler angle representation of a rotation. The resulting 215 | * vector contains the rotations about the z, x and y axis, in that order. 216 | * @param rotation: The quaternion to convert. 217 | * @return: A new vector. 218 | */ 219 | static inline Vector3 ToEuler(Quaternion rotation); 220 | 221 | /** 222 | * Operator overloading. 223 | */ 224 | inline struct Quaternion& operator+=(const float rhs); 225 | inline struct Quaternion& operator-=(const float rhs); 226 | inline struct Quaternion& operator*=(const float rhs); 227 | inline struct Quaternion& operator/=(const float rhs); 228 | inline struct Quaternion& operator+=(const Quaternion rhs); 229 | inline struct Quaternion& operator-=(const Quaternion rhs); 230 | inline struct Quaternion& operator*=(const Quaternion rhs); 231 | }; 232 | 233 | inline Quaternion operator-(Quaternion rhs); 234 | inline Quaternion operator+(Quaternion lhs, const float rhs); 235 | inline Quaternion operator-(Quaternion lhs, const float rhs); 236 | inline Quaternion operator*(Quaternion lhs, const float rhs); 237 | inline Quaternion operator/(Quaternion lhs, const float rhs); 238 | inline Quaternion operator+(const float lhs, Quaternion rhs); 239 | inline Quaternion operator-(const float lhs, Quaternion rhs); 240 | inline Quaternion operator*(const float lhs, Quaternion rhs); 241 | inline Quaternion operator/(const float lhs, Quaternion rhs); 242 | inline Quaternion operator+(Quaternion lhs, const Quaternion rhs); 243 | inline Quaternion operator-(Quaternion lhs, const Quaternion rhs); 244 | inline Quaternion operator*(Quaternion lhs, const Quaternion rhs); 245 | inline Vector3 operator*(Quaternion lhs, const Vector3 rhs); 246 | inline bool operator==(const Quaternion lhs, const Quaternion rhs); 247 | inline bool operator!=(const Quaternion lhs, const Quaternion rhs); 248 | 249 | 250 | 251 | /******************************************************************************* 252 | * Implementation 253 | */ 254 | 255 | Quaternion::Quaternion() : X(0), Y(0), Z(0), W(1) {} 256 | Quaternion::Quaternion(float data[]) : X(data[0]), Y(data[1]), Z(data[2]), 257 | W(data[3]) {} 258 | Quaternion::Quaternion(Vector3 vector, float scalar) : X(vector.X), 259 | Y(vector.Y), Z(vector.Z), W(scalar) {} 260 | Quaternion::Quaternion(float x, float y, float z, float w) : X(x), Y(y), 261 | Z(z), W(w) {} 262 | 263 | 264 | Quaternion Quaternion::Identity() { return Quaternion(0, 0, 0, 1); } 265 | 266 | 267 | float Quaternion::Angle(Quaternion a, Quaternion b) 268 | { 269 | float dot = Dot(a, b); 270 | return acos(fmin(fabs(dot), 1)) * 2; 271 | } 272 | 273 | Quaternion Quaternion::Conjugate(Quaternion rotation) 274 | { 275 | return Quaternion(-rotation.X, -rotation.Y, -rotation.Z, rotation.W); 276 | } 277 | 278 | float Quaternion::Dot(Quaternion lhs, Quaternion rhs) 279 | { 280 | return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z + lhs.W * rhs.W; 281 | } 282 | 283 | Quaternion Quaternion::FromAngleAxis(float angle, Vector3 axis) 284 | { 285 | Quaternion q; 286 | float m = sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); 287 | float s = sin(angle / 2) / m; 288 | q.X = axis.X * s; 289 | q.Y = axis.Y * s; 290 | q.Z = axis.Z * s; 291 | q.W = cos(angle / 2); 292 | return q; 293 | } 294 | 295 | Quaternion Quaternion::FromEuler(Vector3 rotation) 296 | { 297 | return FromEuler(rotation.X, rotation.Y, rotation.Z); 298 | } 299 | 300 | Quaternion Quaternion::FromEuler(float x, float y, float z) 301 | { 302 | float cx = cos(x * 0.5); 303 | float cy = cos(y * 0.5); 304 | float cz = cos(z * 0.5); 305 | float sx = sin(x * 0.5); 306 | float sy = sin(y * 0.5); 307 | float sz = sin(z * 0.5); 308 | Quaternion q; 309 | q.X = cx * sy * sz + cy * cz * sx; 310 | q.Y = cx * cz * sy - cy * sx * sz; 311 | q.Z = cx * cy * sz - cz * sx * sy; 312 | q.W = sx * sy * sz + cx * cy * cz; 313 | return q; 314 | } 315 | 316 | Quaternion Quaternion::FromToRotation(Vector3 fromVector, Vector3 toVector) 317 | { 318 | float dot = Vector3::Dot(fromVector, toVector); 319 | float k = sqrt(Vector3::SqrMagnitude(fromVector) * 320 | Vector3::SqrMagnitude(toVector)); 321 | if (fabs(dot / k + 1) < 0.00001) 322 | { 323 | Vector3 ortho = Vector3::Orthogonal(fromVector); 324 | return Quaternion(Vector3::Normalized(ortho), 0); 325 | } 326 | Vector3 cross = Vector3::Cross(fromVector, toVector); 327 | return Normalized(Quaternion(cross, dot + k)); 328 | } 329 | 330 | Quaternion Quaternion::Inverse(Quaternion rotation) 331 | { 332 | float n = Norm(rotation); 333 | return Conjugate(rotation) / (n * n); 334 | } 335 | 336 | Quaternion Quaternion::Lerp(Quaternion a, Quaternion b, float t) 337 | { 338 | if (t < 0) return Normalized(a); 339 | else if (t > 1) return Normalized(b); 340 | return LerpUnclamped(a, b, t); 341 | } 342 | 343 | Quaternion Quaternion::LerpUnclamped(Quaternion a, Quaternion b, float t) 344 | { 345 | Quaternion quaternion; 346 | if (Dot(a, b) >= 0) 347 | quaternion = a * (1 - t) + b * t; 348 | else 349 | quaternion = a * (1 - t) - b * t; 350 | return Normalized(quaternion); 351 | } 352 | 353 | Quaternion Quaternion::LookRotation(Vector3 forward) 354 | { 355 | return LookRotation(forward, Vector3(0, 1, 0)); 356 | } 357 | 358 | Quaternion Quaternion::LookRotation(Vector3 forward, Vector3 upwards) 359 | { 360 | // Normalize inputs 361 | forward = Vector3::Normalized(forward); 362 | upwards = Vector3::Normalized(upwards); 363 | // Don't allow zero vectors 364 | if (Vector3::SqrMagnitude(forward) < SMALL_float || Vector3::SqrMagnitude(upwards) < SMALL_float) 365 | return Quaternion::Identity(); 366 | // Handle alignment with up direction 367 | if (1 - fabs(Vector3::Dot(forward, upwards)) < SMALL_float) 368 | return FromToRotation(Vector3::Forward(), forward); 369 | // Get orthogonal vectors 370 | Vector3 right = Vector3::Normalized(Vector3::Cross(upwards, forward)); 371 | upwards = Vector3::Cross(forward, right); 372 | // Calculate rotation 373 | Quaternion quaternion; 374 | float radicand = right.X + upwards.Y + forward.Z; 375 | if (radicand > 0) 376 | { 377 | quaternion.W = sqrt(1.0 + radicand) * 0.5; 378 | float recip = 1.0 / (4.0 * quaternion.W); 379 | quaternion.X = (upwards.Z - forward.Y) * recip; 380 | quaternion.Y = (forward.X - right.Z) * recip; 381 | quaternion.Z = (right.Y - upwards.X) * recip; 382 | } 383 | else if (right.X >= upwards.Y && right.X >= forward.Z) 384 | { 385 | quaternion.X = sqrt(1.0 + right.X - upwards.Y - forward.Z) * 0.5; 386 | float recip = 1.0 / (4.0 * quaternion.X); 387 | quaternion.W = (upwards.Z - forward.Y) * recip; 388 | quaternion.Z = (forward.X + right.Z) * recip; 389 | quaternion.Y = (right.Y + upwards.X) * recip; 390 | } 391 | else if (upwards.Y > forward.Z) 392 | { 393 | quaternion.Y = sqrt(1.0 - right.X + upwards.Y - forward.Z) * 0.5; 394 | float recip = 1.0 / (4.0 * quaternion.Y); 395 | quaternion.Z = (upwards.Z + forward.Y) * recip; 396 | quaternion.W = (forward.X - right.Z) * recip; 397 | quaternion.X = (right.Y + upwards.X) * recip; 398 | } 399 | else 400 | { 401 | quaternion.Z = sqrt(1.0 - right.X - upwards.Y + forward.Z) * 0.5; 402 | float recip = 1.0 / (4.0 * quaternion.Z); 403 | quaternion.Y = (upwards.Z + forward.Y) * recip; 404 | quaternion.X = (forward.X + right.Z) * recip; 405 | quaternion.W = (right.Y - upwards.X) * recip; 406 | } 407 | return quaternion; 408 | } 409 | 410 | float Quaternion::Norm(Quaternion rotation) 411 | { 412 | return sqrt(rotation.X * rotation.X + 413 | rotation.Y * rotation.Y + 414 | rotation.Z * rotation.Z + 415 | rotation.W * rotation.W); 416 | } 417 | 418 | Quaternion Quaternion::Normalized(Quaternion rotation) 419 | { 420 | return rotation / Norm(rotation); 421 | } 422 | 423 | Quaternion Quaternion::RotateTowards(Quaternion from, Quaternion to, 424 | float maxRadiansDelta) 425 | { 426 | float angle = Quaternion::Angle(from, to); 427 | if (angle == 0) 428 | return to; 429 | maxRadiansDelta = fmax(maxRadiansDelta, angle - M_PI); 430 | float t = fmin(1, maxRadiansDelta / angle); 431 | return Quaternion::SlerpUnclamped(from, to, t); 432 | } 433 | 434 | Quaternion Quaternion::Slerp(Quaternion a, Quaternion b, float t) 435 | { 436 | if (t < 0) return Normalized(a); 437 | else if (t > 1) return Normalized(b); 438 | return SlerpUnclamped(a, b, t); 439 | } 440 | 441 | Quaternion Quaternion::SlerpUnclamped(Quaternion a, Quaternion b, float t) 442 | { 443 | float n1; 444 | float n2; 445 | float n3 = Dot(a, b); 446 | bool flag = false; 447 | if (n3 < 0) 448 | { 449 | flag = true; 450 | n3 = -n3; 451 | } 452 | if (n3 > 0.999999) 453 | { 454 | n2 = 1 - t; 455 | n1 = flag ? -t : t; 456 | } 457 | else 458 | { 459 | float n4 = acos(n3); 460 | float n5 = 1 / sin(n4); 461 | n2 = sin((1 - t) * n4) * n5; 462 | n1 = flag ? -sin(t * n4) * n5 : sin(t * n4) * n5; 463 | } 464 | Quaternion quaternion; 465 | quaternion.X = (n2 * a.X) + (n1 * b.X); 466 | quaternion.Y = (n2 * a.Y) + (n1 * b.Y); 467 | quaternion.Z = (n2 * a.Z) + (n1 * b.Z); 468 | quaternion.W = (n2 * a.W) + (n1 * b.W); 469 | return Normalized(quaternion); 470 | } 471 | 472 | void Quaternion::ToAngleAxis(Quaternion rotation, float &angle, Vector3 &axis) 473 | { 474 | if (rotation.W > 1) 475 | rotation = Normalized(rotation); 476 | angle = 2 * acos(rotation.W); 477 | float s = sqrt(1 - rotation.W * rotation.W); 478 | if (s < 0.00001) { 479 | axis.X = 1; 480 | axis.Y = 0; 481 | axis.Z = 0; 482 | } else { 483 | axis.X = rotation.X / s; 484 | axis.Y = rotation.Y / s; 485 | axis.Z = rotation.Z / s; 486 | } 487 | } 488 | 489 | Vector3 Quaternion::ToEuler(Quaternion rotation) 490 | { 491 | float sqw = rotation.W * rotation.W; 492 | float sqx = rotation.X * rotation.X; 493 | float sqy = rotation.Y * rotation.Y; 494 | float sqz = rotation.Z * rotation.Z; 495 | // If normalized is one, otherwise is correction factor 496 | float unit = sqx + sqy + sqz + sqw; 497 | float test = rotation.X * rotation.W - rotation.Y * rotation.Z; 498 | Vector3 v; 499 | // Singularity at north pole 500 | if (test > 0.4995f * unit) 501 | { 502 | v.Y = 2 * atan2(rotation.Y, rotation.X); 503 | v.X = M_PI_2; 504 | v.Z = 0; 505 | return v; 506 | } 507 | // Singularity at south pole 508 | if (test < -0.4995f * unit) 509 | { 510 | v.Y = -2 * atan2(rotation.Y, rotation.X); 511 | v.X = -M_PI_2; 512 | v.Z = 0; 513 | return v; 514 | } 515 | // Yaw 516 | v.Y = atan2(2 * rotation.W * rotation.Y + 2 * rotation.Z * rotation.X, 517 | 1 - 2 * (rotation.X * rotation.X + rotation.Y * rotation.Y)); 518 | // Pitch 519 | v.X = asin(2 * (rotation.W * rotation.X - rotation.Y * rotation.Z)); 520 | // Roll 521 | v.Z = atan2(2 * rotation.W * rotation.Z + 2 * rotation.X * rotation.Y, 522 | 1 - 2 * (rotation.Z * rotation.Z + rotation.X * rotation.X)); 523 | return v; 524 | } 525 | 526 | struct Quaternion& Quaternion::operator+=(const float rhs) 527 | { 528 | X += rhs; 529 | Y += rhs; 530 | Z += rhs; 531 | W += rhs; 532 | return *this; 533 | } 534 | 535 | struct Quaternion& Quaternion::operator-=(const float rhs) 536 | { 537 | X -= rhs; 538 | Y -= rhs; 539 | Z -= rhs; 540 | W -= rhs; 541 | return *this; 542 | } 543 | 544 | struct Quaternion& Quaternion::operator*=(const float rhs) 545 | { 546 | X *= rhs; 547 | Y *= rhs; 548 | Z *= rhs; 549 | W *= rhs; 550 | return *this; 551 | } 552 | 553 | struct Quaternion& Quaternion::operator/=(const float rhs) 554 | { 555 | X /= rhs; 556 | Y /= rhs; 557 | Z /= rhs; 558 | W /= rhs; 559 | return *this; 560 | } 561 | 562 | struct Quaternion& Quaternion::operator+=(const Quaternion rhs) 563 | { 564 | X += rhs.X; 565 | Y += rhs.Y; 566 | Z += rhs.Z; 567 | W += rhs.W; 568 | return *this; 569 | } 570 | 571 | struct Quaternion& Quaternion::operator-=(const Quaternion rhs) 572 | { 573 | X -= rhs.X; 574 | Y -= rhs.Y; 575 | Z -= rhs.Z; 576 | W -= rhs.W; 577 | return *this; 578 | } 579 | 580 | struct Quaternion& Quaternion::operator*=(const Quaternion rhs) 581 | { 582 | Quaternion q; 583 | q.W = W * rhs.W - X * rhs.X - Y * rhs.Y - Z * rhs.Z; 584 | q.X = X * rhs.W + W * rhs.X + Y * rhs.Z - Z * rhs.Y; 585 | q.Y = W * rhs.Y - X * rhs.Z + Y * rhs.W + Z * rhs.X; 586 | q.Z = W * rhs.Z + X * rhs.Y - Y * rhs.X + Z * rhs.W; 587 | *this = q; 588 | return *this; 589 | } 590 | 591 | Quaternion operator-(Quaternion rhs) { return rhs * -1; } 592 | Quaternion operator+(Quaternion lhs, const float rhs) { return lhs += rhs; } 593 | Quaternion operator-(Quaternion lhs, const float rhs) { return lhs -= rhs; } 594 | Quaternion operator*(Quaternion lhs, const float rhs) { return lhs *= rhs; } 595 | Quaternion operator/(Quaternion lhs, const float rhs) { return lhs /= rhs; } 596 | Quaternion operator+(const float lhs, Quaternion rhs) { return rhs += lhs; } 597 | Quaternion operator-(const float lhs, Quaternion rhs) { return rhs -= lhs; } 598 | Quaternion operator*(const float lhs, Quaternion rhs) { return rhs *= lhs; } 599 | Quaternion operator/(const float lhs, Quaternion rhs) { return rhs /= lhs; } 600 | Quaternion operator+(Quaternion lhs, const Quaternion rhs) 601 | { 602 | return lhs += rhs; 603 | } 604 | Quaternion operator-(Quaternion lhs, const Quaternion rhs) 605 | { 606 | return lhs -= rhs; 607 | } 608 | Quaternion operator*(Quaternion lhs, const Quaternion rhs) 609 | { 610 | return lhs *= rhs; 611 | } 612 | 613 | Vector3 operator*(Quaternion lhs, const Vector3 rhs) 614 | { 615 | Vector3 u = Vector3(lhs.X, lhs.Y, lhs.Z); 616 | float s = lhs.W; 617 | return u * (Vector3::Dot(u, rhs) * 2) 618 | + rhs * (s * s - Vector3::Dot(u, u)) 619 | + Vector3::Cross(u, rhs) * (2.0 * s); 620 | } 621 | 622 | bool operator==(const Quaternion lhs, const Quaternion rhs) 623 | { 624 | return lhs.X == rhs.X && 625 | lhs.Y == rhs.Y && 626 | lhs.Z == rhs.Z && 627 | lhs.W == rhs.W; 628 | } 629 | 630 | bool operator!=(const Quaternion lhs, const Quaternion rhs) 631 | { 632 | return !(lhs == rhs); 633 | } -------------------------------------------------------------------------------- /Menu.mm: -------------------------------------------------------------------------------- 1 | // 2 | // Menu.m 3 | // ModMenu 4 | // 5 | // Created by Joey on 3/14/19. 6 | // Copyright © 2019 Joey. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Menu.h" 11 | 12 | @interface Menu () 13 | 14 | @property (assign, nonatomic) CGPoint lastMenuLocation; 15 | @property (strong, nonatomic) UILabel *menuTitle; 16 | @property (strong, nonatomic) UIView *header; 17 | @property (strong, nonatomic) UIView *footer; 18 | 19 | @end 20 | 21 | 22 | @implementation Menu 23 | 24 | NSUserDefaults *defaults; 25 | 26 | UIScrollView *scrollView; 27 | CGFloat menuWidth; 28 | CGFloat scrollViewX; 29 | NSString *credits; 30 | UIColor *switchOnColor; 31 | NSString *switchTitleFont; 32 | UIColor *switchTitleColor; 33 | UIColor *infoButtonColor; 34 | NSString *menuIconBase64; 35 | NSString *menuButtonBase64; 36 | float scrollViewHeight = 0; 37 | BOOL hasRestoredLastSession = false; 38 | UIButton *menuButton; 39 | 40 | const char *frameworkName = NULL; 41 | 42 | UIWindow *mainWindow; 43 | 44 | 45 | // init the menu 46 | // global variabls, extern in Macros.h 47 | Menu *menu = [[Menu alloc]init]; 48 | Switches *switches = [[Switches alloc]init]; 49 | 50 | 51 | -(id)initWithTitle:(NSString *)title_ titleColor:(UIColor *)titleColor_ titleFont:(NSString *)titleFont_ credits:(NSString *)credits_ headerColor:(UIColor *)headerColor_ switchOffColor:(UIColor *)switchOffColor_ switchOnColor:(UIColor *)switchOnColor_ switchTitleFont:(NSString *)switchTitleFont_ switchTitleColor:(UIColor *)switchTitleColor_ infoButtonColor:(UIColor *)infoButtonColor_ maxVisibleSwitches:(int)maxVisibleSwitches_ menuWidth:(CGFloat )menuWidth_ menuIcon:(NSString *)menuIconBase64_ menuButton:(NSString *)menuButtonBase64_ { 52 | mainWindow = [UIApplication sharedApplication].keyWindow; 53 | defaults = [NSUserDefaults standardUserDefaults]; 54 | 55 | menuWidth = menuWidth_; 56 | switchOnColor = switchOnColor_; 57 | credits = credits_; 58 | switchTitleFont = switchTitleFont_; 59 | switchTitleColor = switchTitleColor_; 60 | infoButtonColor = infoButtonColor_; 61 | menuButtonBase64 = menuButtonBase64_; 62 | 63 | // Base of the Menu UI. 64 | self = [super initWithFrame:CGRectMake(0,0,menuWidth_, maxVisibleSwitches_ * 50 + 50)]; 65 | self.center = mainWindow.center; 66 | self.layer.opacity = 0.0f; 67 | 68 | self.header = [[UIView alloc]initWithFrame:CGRectMake(0, 1, menuWidth_, 50)]; 69 | self.header.backgroundColor = headerColor_; 70 | CAShapeLayer *headerLayer = [CAShapeLayer layer]; 71 | headerLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.header.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.0}].CGPath; 72 | self.header.layer.mask = headerLayer; 73 | [self addSubview:self.header]; 74 | 75 | NSData* data = [[NSData alloc] initWithBase64EncodedString:menuIconBase64_ options:0]; 76 | UIImage* menuIconImage = [UIImage imageWithData:data]; 77 | 78 | UIButton *menuIcon = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 79 | menuIcon.frame = CGRectMake(5, 1, 35, 35); 80 | menuIcon.backgroundColor = [UIColor clearColor]; 81 | [menuIcon setBackgroundImage:menuIconImage forState:UIControlStateNormal]; 82 | 83 | [menuIcon addTarget:self action:@selector(menuIconTapped) forControlEvents:UIControlEventTouchDown]; 84 | [self.header addSubview:menuIcon]; 85 | 86 | scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, CGRectGetHeight(self.header.bounds), menuWidth_, CGRectGetHeight(self.bounds) - CGRectGetHeight(self.header.bounds))]; 87 | scrollView.backgroundColor = switchOffColor_; 88 | [self addSubview:scrollView]; 89 | 90 | // we need this for the switches, do not remove. 91 | scrollViewX = CGRectGetMinX(scrollView.self.bounds); 92 | 93 | self.menuTitle = [[UILabel alloc]initWithFrame:CGRectMake(55, -2, menuWidth_ - 60, 50)]; 94 | self.menuTitle.text = title_; 95 | self.menuTitle.textColor = titleColor_; 96 | self.menuTitle.font = [UIFont fontWithName:titleFont_ size:30.0f]; 97 | self.menuTitle.adjustsFontSizeToFitWidth = true; 98 | self.menuTitle.textAlignment = NSTextAlignmentCenter; 99 | [self.header addSubview: self.menuTitle]; 100 | 101 | self.footer = [[UIView alloc]initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds) - 1, menuWidth_, 20)]; 102 | self.footer.backgroundColor = headerColor_; 103 | CAShapeLayer *footerLayer = [CAShapeLayer layer]; 104 | footerLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.footer.bounds byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii: (CGSize){10.0, 10.0}].CGPath; 105 | self.footer.layer.mask = footerLayer; 106 | [self addSubview:self.footer]; 107 | 108 | UIPanGestureRecognizer *dragMenuRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(menuDragged:)]; 109 | [self.header addGestureRecognizer:dragMenuRecognizer]; 110 | 111 | UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(hideMenu:)]; 112 | tapGestureRecognizer.numberOfTapsRequired = 1; 113 | [self.header addGestureRecognizer:tapGestureRecognizer]; 114 | 115 | [mainWindow addSubview:self]; 116 | [self showMenuButton]; 117 | 118 | return self; 119 | } 120 | 121 | // Detects whether the menu is being touched and sets a lastMenuLocation. 122 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 123 | self.lastMenuLocation = CGPointMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame)); 124 | [super touchesBegan:touches withEvent:event]; 125 | } 126 | 127 | // Update the menu's location when it's being dragged 128 | - (void)menuDragged:(UIPanGestureRecognizer *)pan { 129 | CGPoint newLocation = [pan translationInView:self.superview]; 130 | self.frame = CGRectMake(self.lastMenuLocation.x + newLocation.x, self.lastMenuLocation.y + newLocation.y, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)); 131 | } 132 | 133 | - (void)hideMenu:(UITapGestureRecognizer *)tap { 134 | if(tap.state == UIGestureRecognizerStateEnded) { 135 | [UIView animateWithDuration:0.5 animations:^ { 136 | self.alpha = 0.0f; 137 | menuButton.alpha = 1.0f; 138 | }]; 139 | } 140 | } 141 | 142 | -(void)showMenu:(UITapGestureRecognizer *)tapGestureRecognizer { 143 | if(tapGestureRecognizer.state == UIGestureRecognizerStateEnded) { 144 | menuButton.alpha = 0.0f; 145 | [UIView animateWithDuration:0.5 animations:^ { 146 | self.alpha = 1.0f; 147 | }]; 148 | } 149 | // We should only have to do this once (first launch) 150 | if(!hasRestoredLastSession) { 151 | restoreLastSession(); 152 | hasRestoredLastSession = true; 153 | } 154 | } 155 | 156 | /********************************************************************************************** 157 | This function will be called when the menu has been opened for the first time on launch. 158 | It'll handle the correct background color and patches the switches do. 159 | ***********************************************************************************************/ 160 | void restoreLastSession() { 161 | UIColor *clearColor = [UIColor clearColor]; 162 | BOOL isOn = false; 163 | 164 | for(id switch_ in scrollView.subviews) { 165 | if([switch_ isKindOfClass:[OffsetSwitch class]]) { 166 | isOn = [defaults boolForKey:[switch_ getPreferencesKey]]; 167 | std::vector memoryPatches = [switch_ getMemoryPatches]; 168 | for(int i = 0; i < memoryPatches.size(); i++) { 169 | if(isOn){ 170 | memoryPatches[i].Modify(); 171 | } else { 172 | memoryPatches[i].Restore(); 173 | } 174 | } 175 | ((OffsetSwitch*)switch_).backgroundColor = isOn ? switchOnColor : clearColor; 176 | } 177 | 178 | if([switch_ isKindOfClass:[TextFieldSwitch class]]) { 179 | isOn = [defaults boolForKey:[switch_ getPreferencesKey]]; 180 | ((TextFieldSwitch*)switch_).backgroundColor = isOn ? switchOnColor : clearColor; 181 | } 182 | 183 | if([switch_ isKindOfClass:[SliderSwitch class]]) { 184 | isOn = [defaults boolForKey:[switch_ getPreferencesKey]]; 185 | ((SliderSwitch*)switch_).backgroundColor = isOn ? switchOnColor : clearColor; 186 | } 187 | } 188 | } 189 | 190 | -(void)showMenuButton { 191 | NSData* data = [[NSData alloc] initWithBase64EncodedString:menuButtonBase64 options:0]; 192 | UIImage* menuButtonImage = [UIImage imageWithData:data]; 193 | 194 | menuButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 195 | menuButton.frame = CGRectMake((mainWindow.frame.size.width/2), (mainWindow.frame.size.height/2), 35, 35); 196 | menuButton.backgroundColor = [UIColor clearColor]; 197 | [menuButton setBackgroundImage:menuButtonImage forState:UIControlStateNormal]; 198 | 199 | UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(showMenu:)]; 200 | [menuButton addGestureRecognizer:tapGestureRecognizer]; 201 | 202 | [menuButton addTarget:self action:@selector(buttonDragged:withEvent:) 203 | forControlEvents:UIControlEventTouchDragInside]; 204 | [mainWindow addSubview:menuButton]; 205 | } 206 | 207 | // handler for when the user is draggin the menu. 208 | - (void)buttonDragged:(UIButton *)button withEvent:(UIEvent *)event { 209 | UITouch *touch = [[event touchesForView:button] anyObject]; 210 | 211 | CGPoint previousLocation = [touch previousLocationInView:button]; 212 | CGPoint location = [touch locationInView:button]; 213 | CGFloat delta_x = location.x - previousLocation.x; 214 | CGFloat delta_y = location.y - previousLocation.y; 215 | 216 | button.center = CGPointMake(button.center.x + delta_x, button.center.y + delta_y); 217 | } 218 | 219 | // When the menu icon(on the header) has been tapped, we want to show proper credits! 220 | -(void)menuIconTapped { 221 | [self showPopup:self.menuTitle.text description:credits]; 222 | self.layer.opacity = 0.0f; 223 | } 224 | 225 | -(void)showPopup:(NSString *)title_ description:(NSString *)description_ { 226 | SCLAlertView *alert = [[SCLAlertView alloc] initWithNewWindow]; 227 | 228 | alert.shouldDismissOnTapOutside = NO; 229 | alert.customViewColor = [UIColor purpleColor]; 230 | alert.showAnimationType = SCLAlertViewShowAnimationFadeIn; 231 | 232 | [alert addButton: @"Ok!" actionBlock: ^(void) { 233 | self.layer.opacity = 1.0f; 234 | }]; 235 | 236 | [alert showInfo:title_ subTitle:description_ closeButtonTitle:nil duration:9999999.0f]; 237 | } 238 | 239 | /******************************************************************* 240 | This method adds the given switch to the menu's scrollview. 241 | it also add's an action for when the switch is being clicked. 242 | ********************************************************************/ 243 | - (void)addSwitchToMenu:(id)switch_ { 244 | [switch_ addTarget:self action:@selector(switchClicked:) forControlEvents:UIControlEventTouchDown]; 245 | scrollViewHeight += 50; 246 | scrollView.contentSize = CGSizeMake(menuWidth, scrollViewHeight); 247 | [scrollView addSubview:switch_]; 248 | } 249 | 250 | - (void)changeSwitchBackground:(id)switch_ isSwitchOn:(BOOL)isSwitchOn_ { 251 | UIColor *clearColor = [UIColor clearColor]; 252 | 253 | [UIView animateWithDuration:0.3 animations:^ { 254 | if([switch_ isKindOfClass:[TextFieldSwitch class]]) { 255 | ((TextFieldSwitch*)switch_).backgroundColor = isSwitchOn_ ? clearColor : switchOnColor; 256 | } 257 | if([switch_ isKindOfClass:[SliderSwitch class]]) { 258 | ((SliderSwitch*)switch_).backgroundColor = isSwitchOn_ ? clearColor : switchOnColor; 259 | } 260 | if([switch_ isKindOfClass:[OffsetSwitch class]]) { 261 | ((OffsetSwitch*)switch_).backgroundColor = isSwitchOn_ ? clearColor : switchOnColor; 262 | } 263 | }]; 264 | 265 | [defaults setBool:!isSwitchOn_ forKey:[switch_ getPreferencesKey]]; 266 | } 267 | 268 | /********************************************************************************************* 269 | This method does the following handles the behaviour when a switch has been clicked 270 | TextfieldSwitch and SliderSwitch only change from color based on whether it's on or not. 271 | A OffsetSwitch does too, but it also applies offset patches 272 | ***********************************************************************************************/ 273 | -(void)switchClicked:(id)switch_ { 274 | BOOL isOn = [defaults boolForKey:[switch_ getPreferencesKey]]; 275 | 276 | if([switch_ isKindOfClass:[OffsetSwitch class]]) { 277 | std::vector memoryPatches = [switch_ getMemoryPatches]; 278 | for(int i = 0; i < memoryPatches.size(); i++) { 279 | if(!isOn){ 280 | memoryPatches[i].Modify(); 281 | } else { 282 | memoryPatches[i].Restore(); 283 | } 284 | } 285 | } 286 | 287 | // Update switch background color and pref value. 288 | [self changeSwitchBackground:switch_ isSwitchOn:isOn]; 289 | } 290 | 291 | -(void)setFrameworkName:(const char *)name_ { 292 | frameworkName = name_; 293 | } 294 | 295 | -(const char *)getFrameworkName { 296 | return frameworkName; 297 | } 298 | @end // End of menu class! 299 | 300 | 301 | /******************************** 302 | OFFSET SWITCH STARTS HERE! 303 | *********************************/ 304 | 305 | @implementation OffsetSwitch { 306 | std::vector memoryPatches; 307 | } 308 | 309 | - (id)initHackNamed:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::vector)offsets_ bytes:(std::vector)bytes_ { 310 | description = description_; 311 | preferencesKey = hackName_; 312 | 313 | if(offsets_.size() != bytes_.size()){ 314 | [menu showPopup:@"Invalid input count" description:[NSString stringWithFormat:@"Offsets array input count (%d) is not equal to the bytes array input count (%d)", (int)offsets_.size(), (int)bytes_.size()]]; 315 | } else { 316 | // For each offset, we create a MemoryPatch. 317 | for(int i = 0; i < offsets_.size(); i++) { 318 | MemoryPatch patch = MemoryPatch::createWithHex([menu getFrameworkName], offsets_[i], bytes_[i]); 319 | if(patch.isValid()) { 320 | memoryPatches.push_back(patch); 321 | } else { 322 | [menu showPopup:@"Invalid patch" description:[NSString stringWithFormat:@"Failing offset: 0x%llx, please re-check the hex you entered.", offsets_[i]]]; 323 | } 324 | } 325 | } 326 | 327 | self = [super initWithFrame:CGRectMake(-1, scrollViewX + scrollViewHeight - 1, menuWidth + 2, 50)]; 328 | self.backgroundColor = [UIColor clearColor]; 329 | self.layer.borderWidth = 0.5f; 330 | self.layer.borderColor = [UIColor whiteColor].CGColor; 331 | 332 | switchLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 0, menuWidth - 60, 50)]; 333 | switchLabel.text = hackName_; 334 | switchLabel.textColor = switchTitleColor; 335 | switchLabel.font = [UIFont fontWithName:switchTitleFont size:18]; 336 | switchLabel.adjustsFontSizeToFitWidth = true; 337 | switchLabel.textAlignment = NSTextAlignmentCenter; 338 | [self addSubview:switchLabel]; 339 | 340 | UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark]; 341 | infoButton.frame = CGRectMake(menuWidth - 30, 15, 20, 20); 342 | infoButton.tintColor = infoButtonColor; 343 | 344 | UITapGestureRecognizer *infoTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showInfo:)]; 345 | [infoButton addGestureRecognizer:infoTap]; 346 | [self addSubview:infoButton]; 347 | 348 | return self; 349 | } 350 | 351 | -(void)showInfo:(UIGestureRecognizer *)gestureRec { 352 | if(gestureRec.state == UIGestureRecognizerStateEnded) { 353 | [menu showPopup:[self getPreferencesKey] description:[self getDescription]]; 354 | menu.layer.opacity = 0.0f; 355 | } 356 | } 357 | 358 | -(NSString *)getPreferencesKey { 359 | return preferencesKey; 360 | } 361 | 362 | -(NSString *)getDescription { 363 | return description; 364 | } 365 | 366 | - (std::vector)getMemoryPatches { 367 | return memoryPatches; 368 | } 369 | 370 | @end //end of OffsetSwitch class 371 | 372 | 373 | /************************************** 374 | TEXTFIELD SWITCH STARTS HERE! 375 | - Note that this extends from OffsetSwitch. 376 | ***************************************/ 377 | 378 | @implementation TextFieldSwitch { 379 | UITextField *textfieldValue; 380 | } 381 | 382 | - (id)initTextfieldNamed:(NSString *)hackName_ description:(NSString *)description_ inputBorderColor:(UIColor *)inputBorderColor_ { 383 | preferencesKey = hackName_; 384 | switchValueKey = [hackName_ stringByApplyingTransform:NSStringTransformLatinToCyrillic reverse:false]; 385 | description = description_; 386 | 387 | self = [super initWithFrame:CGRectMake(-1, scrollViewX + scrollViewHeight -1, menuWidth + 2, 50)]; 388 | self.backgroundColor = [UIColor clearColor]; 389 | self.layer.borderWidth = 0.5f; 390 | self.layer.borderColor = [UIColor whiteColor].CGColor; 391 | 392 | switchLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 0, menuWidth - 60, 30)]; 393 | switchLabel.text = hackName_; 394 | switchLabel.textColor = switchTitleColor; 395 | switchLabel.font = [UIFont fontWithName:switchTitleFont size:18]; 396 | switchLabel.adjustsFontSizeToFitWidth = true; 397 | switchLabel.textAlignment = NSTextAlignmentCenter; 398 | [self addSubview:switchLabel]; 399 | 400 | textfieldValue = [[UITextField alloc]initWithFrame:CGRectMake(menuWidth / 4 - 10, switchLabel.self.bounds.origin.x - 5 + switchLabel.self.bounds.size.height, menuWidth / 2, 20)]; 401 | textfieldValue.layer.borderWidth = 2.0f; 402 | textfieldValue.layer.borderColor = inputBorderColor_.CGColor; 403 | textfieldValue.layer.cornerRadius = 10.0f; 404 | textfieldValue.textColor = switchTitleColor; 405 | textfieldValue.textAlignment = NSTextAlignmentCenter; 406 | textfieldValue.delegate = self; 407 | textfieldValue.backgroundColor = [UIColor clearColor]; 408 | 409 | // get value from the plist & show it (if it's not empty). 410 | if([[NSUserDefaults standardUserDefaults] objectForKey:switchValueKey] != nil) { 411 | textfieldValue.text = [[NSUserDefaults standardUserDefaults] objectForKey:switchValueKey]; 412 | } 413 | 414 | UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark]; 415 | infoButton.frame = CGRectMake(menuWidth - 30, 15, 20, 20); 416 | infoButton.tintColor = infoButtonColor; 417 | 418 | UITapGestureRecognizer *infoTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showInfo:)]; 419 | [infoButton addGestureRecognizer:infoTap]; 420 | [self addSubview:infoButton]; 421 | 422 | [self addSubview:textfieldValue]; 423 | 424 | return self; 425 | } 426 | 427 | // so when click "return" the keyboard goes way, got it from internet. Common thing apparantly 428 | -(BOOL)textFieldShouldReturn:(UITextField*)textfieldValue_ { 429 | switchValueKey = [[self getPreferencesKey] stringByApplyingTransform:NSStringTransformLatinToCyrillic reverse:false]; 430 | [defaults setObject:textfieldValue_.text forKey:[self getSwitchValueKey]]; 431 | [textfieldValue_ resignFirstResponder]; 432 | 433 | return true; 434 | } 435 | 436 | -(NSString *)getSwitchValueKey { 437 | return switchValueKey; 438 | } 439 | 440 | @end // end of TextFieldSwitch Class 441 | 442 | 443 | /******************************* 444 | SLIDER SWITCH STARTS HERE! 445 | - Note that this extends from TextFieldSwitch 446 | *******************************/ 447 | 448 | @implementation SliderSwitch { 449 | UISlider *sliderValue; 450 | float valueOfSlider; 451 | } 452 | 453 | - (id)initSliderNamed:(NSString *)hackName_ description:(NSString *)description_ minimumValue:(float)minimumValue_ maximumValue:(float)maximumValue_ sliderColor:(UIColor *)sliderColor_{ 454 | preferencesKey = hackName_; 455 | switchValueKey = [hackName_ stringByApplyingTransform:NSStringTransformLatinToCyrillic reverse:false]; 456 | description = description_; 457 | 458 | self = [super initWithFrame:CGRectMake(-1, scrollViewX + scrollViewHeight -1, menuWidth + 2, 50)]; 459 | self.backgroundColor = [UIColor clearColor]; 460 | self.layer.borderWidth = 0.5f; 461 | self.layer.borderColor = [UIColor whiteColor].CGColor; 462 | 463 | switchLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 0, menuWidth - 60, 30)]; 464 | switchLabel.text = [NSString stringWithFormat:@"%@ %.2f", hackName_, sliderValue.value]; 465 | switchLabel.textColor = switchTitleColor; 466 | switchLabel.font = [UIFont fontWithName:switchTitleFont size:18]; 467 | switchLabel.adjustsFontSizeToFitWidth = true; 468 | switchLabel.textAlignment = NSTextAlignmentCenter; 469 | [self addSubview:switchLabel]; 470 | 471 | sliderValue = [[UISlider alloc]initWithFrame:CGRectMake(menuWidth / 4 - 20, switchLabel.self.bounds.origin.x - 4 + switchLabel.self.bounds.size.height, menuWidth / 2 + 20, 20)]; 472 | sliderValue.thumbTintColor = sliderColor_; 473 | sliderValue.minimumTrackTintColor = switchTitleColor; 474 | sliderValue.maximumTrackTintColor = switchTitleColor; 475 | sliderValue.minimumValue = minimumValue_; 476 | sliderValue.maximumValue = maximumValue_; 477 | sliderValue.continuous = true; 478 | [sliderValue addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged]; 479 | valueOfSlider = sliderValue.value; 480 | 481 | // get value from the plist & show it (if it's not empty). 482 | if([[NSUserDefaults standardUserDefaults] objectForKey:switchValueKey] != nil) { 483 | sliderValue.value = [[NSUserDefaults standardUserDefaults] floatForKey:switchValueKey]; 484 | switchLabel.text = [NSString stringWithFormat:@"%@ %.2f", hackName_, sliderValue.value]; 485 | } 486 | 487 | UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight]; 488 | infoButton.frame = CGRectMake(menuWidth - 30, 15, 20, 20); 489 | infoButton.tintColor = infoButtonColor; 490 | 491 | UITapGestureRecognizer *infoTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showInfo:)]; 492 | [infoButton addGestureRecognizer:infoTap]; 493 | [self addSubview:infoButton]; 494 | 495 | [self addSubview:sliderValue]; 496 | 497 | return self; 498 | } 499 | 500 | -(void)sliderValueChanged:(UISlider *)slider_ { 501 | switchValueKey = [[self getPreferencesKey] stringByApplyingTransform:NSStringTransformLatinToCyrillic reverse:false]; 502 | switchLabel.text = [NSString stringWithFormat:@"%@ %.2f", [self getPreferencesKey], slider_.value]; 503 | [defaults setFloat:slider_.value forKey:[self getSwitchValueKey]]; 504 | } 505 | 506 | @end // end of SliderSwitch class 507 | 508 | 509 | 510 | 511 | 512 | @implementation Switches 513 | 514 | 515 | -(void)addSwitch:(NSString *)hackName_ description:(NSString *)description_ { 516 | OffsetSwitch *offsetPatch = [[OffsetSwitch alloc]initHackNamed:hackName_ description:description_ offsets:std::vector{} bytes:std::vector{}]; 517 | [menu addSwitchToMenu:offsetPatch]; 518 | 519 | } 520 | 521 | - (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::initializer_list)offsets_ bytes:(std::initializer_list)bytes_ { 522 | std::vector offsetVector; 523 | std::vector bytesVector; 524 | 525 | offsetVector.insert(offsetVector.begin(), offsets_.begin(), offsets_.end()); 526 | bytesVector.insert(bytesVector.begin(), bytes_.begin(), bytes_.end()); 527 | 528 | OffsetSwitch *offsetPatch = [[OffsetSwitch alloc]initHackNamed:hackName_ description:description_ offsets:offsetVector bytes:bytesVector]; 529 | [menu addSwitchToMenu:offsetPatch]; 530 | } 531 | 532 | - (void)addTextfieldSwitch:(NSString *)hackName_ description:(NSString *)description_ inputBorderColor:(UIColor *)inputBorderColor_ { 533 | TextFieldSwitch *textfieldSwitch = [[TextFieldSwitch alloc]initTextfieldNamed:hackName_ description:description_ inputBorderColor:inputBorderColor_]; 534 | [menu addSwitchToMenu:textfieldSwitch]; 535 | } 536 | 537 | - (void)addSliderSwitch:(NSString *)hackName_ description:(NSString *)description_ minimumValue:(float)minimumValue_ maximumValue:(float)maximumValue_ sliderColor:(UIColor *)sliderColor_ { 538 | SliderSwitch *sliderSwitch = [[SliderSwitch alloc] initSliderNamed:hackName_ description:description_ minimumValue:minimumValue_ maximumValue:maximumValue_ sliderColor:sliderColor_]; 539 | [menu addSwitchToMenu:sliderSwitch]; 540 | } 541 | 542 | - (NSString *)getValueFromSwitch:(NSString *)name { 543 | 544 | //getting the correct key for the saved input. 545 | NSString *correctKey = [name stringByApplyingTransform:NSStringTransformLatinToCyrillic reverse:false]; 546 | 547 | if([[NSUserDefaults standardUserDefaults] objectForKey:correctKey]) { 548 | return [[NSUserDefaults standardUserDefaults] objectForKey:correctKey]; 549 | } 550 | else if([[NSUserDefaults standardUserDefaults] floatForKey:correctKey]) { 551 | NSString *sliderValue = [NSString stringWithFormat:@"%f", [[NSUserDefaults standardUserDefaults] floatForKey:correctKey]]; 552 | return sliderValue; 553 | } 554 | 555 | return 0; 556 | } 557 | 558 | -(bool)isSwitchOn:(NSString *)switchName { 559 | return [[NSUserDefaults standardUserDefaults] boolForKey:switchName]; 560 | } 561 | 562 | @end 563 | -------------------------------------------------------------------------------- /SCLAlertView/SCLAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCLAlertView.h 3 | // SCLAlertView 4 | // 5 | // Created by Diogo Autilio on 9/26/14. 6 | // Copyright (c) 2014-2017 AnyKey Entertainment. All rights reserved. 7 | // 8 | 9 | #if defined(__has_feature) && __has_feature(modules) 10 | @import UIKit; 11 | #else 12 | #import 13 | #endif 14 | #import "SCLButton.h" 15 | #import "SCLTextView.h" 16 | #import "SCLSwitchView.h" 17 | 18 | typedef NSAttributedString* (^SCLAttributedFormatBlock)(NSString *value); 19 | typedef void (^SCLDismissBlock)(void); 20 | typedef void (^SCLDismissAnimationCompletionBlock)(void); 21 | typedef void (^SCLShowAnimationCompletionBlock)(void); 22 | typedef void (^SCLForceHideBlock)(void); 23 | 24 | @interface SCLAlertView : UIViewController 25 | 26 | /** Alert Styles 27 | * 28 | * Set SCLAlertView Style 29 | */ 30 | typedef NS_ENUM(NSInteger, SCLAlertViewStyle) 31 | { 32 | SCLAlertViewStyleSuccess, 33 | SCLAlertViewStyleError, 34 | SCLAlertViewStyleNotice, 35 | SCLAlertViewStyleWarning, 36 | SCLAlertViewStyleInfo, 37 | SCLAlertViewStyleEdit, 38 | SCLAlertViewStyleWaiting, 39 | SCLAlertViewStyleQuestion, 40 | SCLAlertViewStyleCustom 41 | }; 42 | 43 | /** Alert hide animation styles 44 | * 45 | * Set SCLAlertView hide animation type. 46 | */ 47 | typedef NS_ENUM(NSInteger, SCLAlertViewHideAnimation) 48 | { 49 | SCLAlertViewHideAnimationFadeOut, 50 | SCLAlertViewHideAnimationSlideOutToBottom, 51 | SCLAlertViewHideAnimationSlideOutToTop, 52 | SCLAlertViewHideAnimationSlideOutToLeft, 53 | SCLAlertViewHideAnimationSlideOutToRight, 54 | SCLAlertViewHideAnimationSlideOutToCenter, 55 | SCLAlertViewHideAnimationSlideOutFromCenter, 56 | SCLAlertViewHideAnimationSimplyDisappear 57 | }; 58 | 59 | /** Alert show animation styles 60 | * 61 | * Set SCLAlertView show animation type. 62 | */ 63 | typedef NS_ENUM(NSInteger, SCLAlertViewShowAnimation) 64 | { 65 | SCLAlertViewShowAnimationFadeIn, 66 | SCLAlertViewShowAnimationSlideInFromBottom, 67 | SCLAlertViewShowAnimationSlideInFromTop, 68 | SCLAlertViewShowAnimationSlideInFromLeft, 69 | SCLAlertViewShowAnimationSlideInFromRight, 70 | SCLAlertViewShowAnimationSlideInFromCenter, 71 | SCLAlertViewShowAnimationSlideInToCenter, 72 | SCLAlertViewShowAnimationSimplyAppear 73 | }; 74 | 75 | /** Alert background styles 76 | * 77 | * Set SCLAlertView background type. 78 | */ 79 | typedef NS_ENUM(NSInteger, SCLAlertViewBackground) 80 | { 81 | SCLAlertViewBackgroundShadow, 82 | SCLAlertViewBackgroundBlur, 83 | SCLAlertViewBackgroundTransparent 84 | }; 85 | 86 | /** Content view corner radius 87 | * 88 | * A float value that replaces the standard content viuew corner radius. 89 | */ 90 | @property CGFloat cornerRadius; 91 | 92 | /** Tint top circle 93 | * 94 | * A boolean value that determines whether to tint the SCLAlertView top circle. 95 | * (Default: YES) 96 | */ 97 | @property (assign, nonatomic) BOOL tintTopCircle; 98 | 99 | /** Use larger icon 100 | * 101 | * A boolean value that determines whether to make the SCLAlertView top circle icon larger. 102 | * (Default: NO) 103 | */ 104 | @property (assign, nonatomic) BOOL useLargerIcon; 105 | 106 | /** Title Label 107 | * 108 | * The text displayed as title. 109 | */ 110 | @property (strong, nonatomic) UILabel *labelTitle; 111 | 112 | /** Text view with the body message 113 | * 114 | * Holds the textview. 115 | */ 116 | @property (strong, nonatomic) UITextView *viewText; 117 | 118 | /** Activity Indicator 119 | * 120 | * Holds the activityIndicator. 121 | */ 122 | @property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView; 123 | 124 | /** Dismiss on tap outside 125 | * 126 | * A boolean value that determines whether to dismiss when tapping outside the SCLAlertView. 127 | * (Default: NO) 128 | */ 129 | @property (assign, nonatomic) BOOL shouldDismissOnTapOutside; 130 | 131 | /** Sound URL 132 | * 133 | * Holds the sound NSURL path. 134 | */ 135 | @property (strong, nonatomic) NSURL *soundURL; 136 | 137 | /** Set text attributed format block 138 | * 139 | * Holds the attributed string. 140 | */ 141 | @property (copy, nonatomic) SCLAttributedFormatBlock attributedFormatBlock; 142 | 143 | /** Set Complete button format block. 144 | * 145 | * Holds the button format block. 146 | * Support keys : backgroundColor, borderWidth, borderColor, textColor 147 | */ 148 | @property (copy, nonatomic) CompleteButtonFormatBlock completeButtonFormatBlock; 149 | 150 | /** Set button format block. 151 | * 152 | * Holds the button format block. 153 | * Support keys : backgroundColor, borderWidth, borderColor, textColor 154 | */ 155 | @property (copy, nonatomic) ButtonFormatBlock buttonFormatBlock; 156 | 157 | /** Set force hide block. 158 | * 159 | * When set force hideview method invocation. 160 | */ 161 | @property (copy, nonatomic) SCLForceHideBlock forceHideBlock; 162 | 163 | /** Hide animation type 164 | * 165 | * Holds the hide animation type. 166 | * (Default: FadeOut) 167 | */ 168 | @property (nonatomic) SCLAlertViewHideAnimation hideAnimationType; 169 | 170 | /** Show animation type 171 | * 172 | * Holds the show animation type. 173 | * (Default: SlideInFromTop) 174 | */ 175 | @property (nonatomic) SCLAlertViewShowAnimation showAnimationType; 176 | 177 | /** Set SCLAlertView background type. 178 | * 179 | * SCLAlertView background type. 180 | * (Default: Shadow) 181 | */ 182 | @property (nonatomic) SCLAlertViewBackground backgroundType; 183 | 184 | /** Set custom color to SCLAlertView. 185 | * 186 | * SCLAlertView custom color. 187 | * (Buttons, top circle and borders) 188 | */ 189 | @property (strong, nonatomic) UIColor *customViewColor; 190 | 191 | /** Set custom color to SCLAlertView background. 192 | * 193 | * SCLAlertView background custom color. 194 | */ 195 | @property (strong, nonatomic) UIColor *backgroundViewColor; 196 | 197 | /** Set custom tint color for icon image. 198 | * 199 | * SCLAlertView icon tint color 200 | */ 201 | @property (strong, nonatomic) UIColor *iconTintColor; 202 | 203 | /** Set custom circle icon height. 204 | * 205 | * Circle icon height 206 | */ 207 | @property (nonatomic) CGFloat circleIconHeight; 208 | 209 | /** Set SCLAlertView extension bounds. 210 | * 211 | * Set new bounds (EXTENSION ONLY) 212 | */ 213 | @property (nonatomic) CGRect extensionBounds; 214 | 215 | /** Set status bar hidden. 216 | * 217 | * Status bar hidden 218 | */ 219 | @property (nonatomic) BOOL statusBarHidden; 220 | 221 | /** Set status bar style. 222 | * 223 | * Status bar style 224 | */ 225 | @property (nonatomic) UIStatusBarStyle statusBarStyle; 226 | 227 | /** Set horizontal alignment for buttons 228 | * 229 | * Horizontal aligment instead of vertically if YES 230 | */ 231 | @property (nonatomic) BOOL horizontalButtons; 232 | 233 | /** Initialize SCLAlertView using a new window. 234 | * 235 | * Init with new window 236 | */ 237 | - (instancetype)initWithNewWindow; 238 | 239 | /** Initialize SCLAlertView using a new window. 240 | * 241 | * Init with new window with custom width 242 | */ 243 | - (instancetype)initWithNewWindowWidth:(CGFloat)windowWidth; 244 | 245 | /** Warns that alerts is gone 246 | * 247 | * Warns that alerts is gone using block 248 | */ 249 | - (void)alertIsDismissed:(SCLDismissBlock)dismissBlock; 250 | 251 | /** Warns that alerts dismiss animation is completed 252 | * 253 | * Warns that alerts dismiss animation is completed 254 | */ 255 | - (void)alertDismissAnimationIsCompleted:(SCLDismissAnimationCompletionBlock)dismissAnimationCompletionBlock; 256 | 257 | /** Warns that alerts show animation is completed 258 | * 259 | * Warns that alerts show animation is completed 260 | */ 261 | - (void)alertShowAnimationIsCompleted:(SCLShowAnimationCompletionBlock)showAnimationCompletionBlock; 262 | 263 | /** Hide SCLAlertView 264 | * 265 | * Hide SCLAlertView using animation and removing from super view. 266 | */ 267 | 268 | - (void)hideView; 269 | 270 | /** SCLAlertView visibility 271 | * 272 | * Returns if the alert is visible or not. 273 | */ 274 | - (BOOL)isVisible; 275 | 276 | /** Remove Top Circle 277 | * 278 | * Remove top circle from SCLAlertView. 279 | */ 280 | - (void)removeTopCircle; 281 | 282 | /** Add a custom UIView 283 | * 284 | * @param customView UIView object to be added above the first SCLButton. 285 | */ 286 | - (UIView *)addCustomView:(UIView *)customView; 287 | 288 | /** Add Text Field 289 | * 290 | * @param title The text displayed on the textfield. 291 | */ 292 | - (SCLTextView *)addTextField:(NSString *)title; 293 | 294 | /** Add a custom Text Field 295 | * 296 | * @param textField The custom textfield provided by the programmer. 297 | */ 298 | - (void)addCustomTextField:(UITextField *)textField; 299 | 300 | /** Add a switch view 301 | * 302 | * @param label The label displayed for the switch. 303 | */ 304 | - (SCLSwitchView *)addSwitchViewWithLabel:(NSString *)label; 305 | 306 | /** Add Timer Display 307 | * 308 | * @param buttonIndex The index of the button to add the timer display to. 309 | * @param reverse Convert timer to countdown. 310 | */ 311 | - (void)addTimerToButtonIndex:(NSInteger)buttonIndex reverse:(BOOL)reverse; 312 | 313 | /** Set Title font family and size 314 | * 315 | * @param titleFontFamily The family name used to displayed the title. 316 | * @param size Font size. 317 | */ 318 | - (void)setTitleFontFamily:(NSString *)titleFontFamily withSize:(CGFloat)size; 319 | 320 | /** Set Text field font family and size 321 | * 322 | * @param bodyTextFontFamily The family name used to displayed the text field. 323 | * @param size Font size. 324 | */ 325 | - (void)setBodyTextFontFamily:(NSString *)bodyTextFontFamily withSize:(CGFloat)size; 326 | 327 | /** Set Buttons font family and size 328 | * 329 | * @param buttonsFontFamily The family name used to displayed the buttons. 330 | * @param size Font size. 331 | */ 332 | - (void)setButtonsTextFontFamily:(NSString *)buttonsFontFamily withSize:(CGFloat)size; 333 | 334 | /** Add a Button with a title and a block to handle when the button is pressed. 335 | * 336 | * @param title The text displayed on the button. 337 | * @param action A block of code to be executed when the button is pressed. 338 | */ 339 | - (SCLButton *)addButton:(NSString *)title actionBlock:(SCLActionBlock)action; 340 | 341 | /** Add a Button with a title, a block to handle validation, and a block to handle when the button is pressed and validation succeeds. 342 | * 343 | * @param title The text displayed on the button. 344 | * @param validationBlock A block of code that will allow you to validate fields or do any other logic you may want to do to determine if the alert should be dismissed or not. Inside of this block, return a BOOL indicating whether or not the action block should be called and the alert dismissed. 345 | * @param action A block of code to be executed when the button is pressed and validation passes. 346 | */ 347 | - (SCLButton *)addButton:(NSString *)title validationBlock:(SCLValidationBlock)validationBlock actionBlock:(SCLActionBlock)action; 348 | 349 | /** Add a Button with a title, a target and a selector to handle when the button is pressed. 350 | * 351 | * @param title The text displayed on the button. 352 | * @param target Add target for particular event. 353 | * @param selector A method to be executed when the button is pressed. 354 | */ 355 | - (SCLButton *)addButton:(NSString *)title target:(id)target selector:(SEL)selector; 356 | 357 | /** Show Success SCLAlertView 358 | * 359 | * @param vc The view controller the alert view will be displayed in. 360 | * @param title The text displayed on the button. 361 | * @param subTitle The subtitle text of the alert view. 362 | * @param closeButtonTitle The text for the close button. 363 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 364 | */ 365 | - (void)showSuccess:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 366 | - (void)showSuccess:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 367 | 368 | /** Show Error SCLAlertView 369 | * 370 | * @param vc The view controller the alert view will be displayed in. 371 | * @param title The text displayed on the button. 372 | * @param subTitle The subtitle text of the alert view. 373 | * @param closeButtonTitle The text for the close button. 374 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 375 | */ 376 | - (void)showError:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 377 | - (void)showError:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 378 | 379 | /** Show Notice SCLAlertView 380 | * 381 | * @param vc The view controller the alert view will be displayed in. 382 | * @param title The text displayed on the button. 383 | * @param subTitle The subtitle text of the alert view. 384 | * @param closeButtonTitle The text for the close button. 385 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 386 | */ 387 | - (void)showNotice:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 388 | - (void)showNotice:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 389 | 390 | /** Show Warning SCLAlertView 391 | * 392 | * @param vc The view controller the alert view will be displayed in. 393 | * @param title The text displayed on the button. 394 | * @param subTitle The subtitle text of the alert view. 395 | * @param closeButtonTitle The text for the close button. 396 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 397 | */ 398 | - (void)showWarning:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 399 | - (void)showWarning:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 400 | 401 | /** Show Info SCLAlertView 402 | * 403 | * @param vc The view controller the alert view will be displayed in. 404 | * @param title The text displayed on the button. 405 | * @param subTitle The subtitle text of the alert view. 406 | * @param closeButtonTitle The text for the close button. 407 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 408 | */ 409 | - (void)showInfo:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 410 | - (void)showInfo:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 411 | 412 | /** Show Edit SCLAlertView 413 | * 414 | * @param vc The view controller the alert view will be displayed in. 415 | * @param title The text displayed on the button. 416 | * @param subTitle The subtitle text of the alert view. 417 | * @param closeButtonTitle The text for the close button. 418 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 419 | */ 420 | - (void)showEdit:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 421 | - (void)showEdit:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 422 | 423 | /** Show Title SCLAlertView using a predefined type 424 | * 425 | * @param vc The view controller the alert view will be displayed in. 426 | * @param title The text displayed on the button. 427 | * @param subTitle The subtitle text of the alert view. 428 | * @param style One of predefined SCLAlertView styles. 429 | * @param closeButtonTitle The text for the close button. 430 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 431 | */ 432 | - (void)showTitle:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle style:(SCLAlertViewStyle)style closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 433 | - (void)showTitle:(NSString *)title subTitle:(NSString *)subTitle style:(SCLAlertViewStyle)style closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 434 | 435 | /** Shows a custom SCLAlertView without using a predefined type, allowing for a custom image and color to be specified. 436 | * 437 | * @param vc The view controller the alert view will be displayed in. 438 | * @param image A UIImage object to be used as the icon for the alert view. 439 | * @param color A UIColor object to be used to tint the background of the icon circle and the buttons. 440 | * @param title The title text of the alert view. 441 | * @param subTitle The subtitle text of the alert view. 442 | * @param closeButtonTitle The text for the close button. 443 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 444 | */ 445 | - (void)showCustom:(UIViewController *)vc image:(UIImage *)image color:(UIColor *)color title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 446 | - (void)showCustom:(UIImage *)image color:(UIColor *)color title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 447 | 448 | /** Show Waiting SCLAlertView with UIActityIndicator. 449 | * 450 | * @param vc The view controller the alert view will be displayed in. 451 | * @param title The text displayed on the button. 452 | * @param subTitle The subtitle text of the alert view. 453 | * @param closeButtonTitle The text for the close button. 454 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 455 | */ 456 | - (void)showWaiting:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 457 | - (void)showWaiting:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 458 | 459 | /** Show Question SCLAlertView 460 | * 461 | * @param vc The view controller the alert view will be displayed in. 462 | * @param title The text displayed on the button. 463 | * @param subTitle The subtitle text of the alert view. 464 | * @param closeButtonTitle The text for the close button. 465 | * @param duration The amount of time the alert will remain on screen until it is automatically dismissed. If automatic dismissal is not desired, set to 0. 466 | */ 467 | - (void)showQuestion:(UIViewController *)vc title:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 468 | - (void)showQuestion:(NSString *)title subTitle:(NSString *)subTitle closeButtonTitle:(NSString *)closeButtonTitle duration:(NSTimeInterval)duration; 469 | 470 | @end 471 | 472 | @protocol SCLItemsBuilder__Protocol__Fluent 473 | - (void)setupFluent; 474 | @end 475 | 476 | @interface SCLAlertViewBuilder__WithFluent: NSObject @end 477 | 478 | @interface SCLAlertViewShowBuilder : SCLAlertViewBuilder__WithFluent 479 | 480 | @property(weak, nonatomic, readonly) UIViewController *parameterViewController; 481 | @property(copy, nonatomic, readonly) UIImage *parameterImage; 482 | @property(copy, nonatomic, readonly) UIColor *parameterColor; 483 | @property(copy, nonatomic, readonly) NSString *parameterTitle; 484 | @property(copy, nonatomic, readonly) NSString *parameterSubTitle; 485 | @property(copy, nonatomic, readonly) NSString *parameterCompleteText; 486 | @property(copy, nonatomic, readonly) NSString *parameterCloseButtonTitle; 487 | @property(assign, nonatomic, readonly) SCLAlertViewStyle parameterStyle; 488 | @property(assign, nonatomic, readonly) NSTimeInterval parameterDuration; 489 | 490 | #pragma mark - Setters 491 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^viewController)(UIViewController *viewController); 492 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^image)(UIImage *image); 493 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^color)(UIColor *color); 494 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^title)(NSString *title); 495 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^subTitle)(NSString *subTitle); 496 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^completeText)(NSString *completeText); 497 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^style)(SCLAlertViewStyle style); 498 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^closeButtonTitle)(NSString *closeButtonTitle); 499 | @property(copy, nonatomic, readonly) SCLAlertViewShowBuilder *(^duration)(NSTimeInterval duration); 500 | 501 | - (void)showAlertView:(SCLAlertView *)alertView; 502 | - (void)showAlertView:(SCLAlertView *)alertView onViewController:(UIViewController *)controller; 503 | @property(copy, nonatomic, readonly) void (^show)(SCLAlertView *view, UIViewController *controller); 504 | @end 505 | 506 | @interface SCLALertViewTextFieldBuilder : SCLAlertViewBuilder__WithFluent 507 | 508 | #pragma mark - Available later after adding 509 | @property(weak, nonatomic, readonly) SCLTextView *textField; 510 | 511 | #pragma mark - Setters 512 | @property(copy, nonatomic, readonly) SCLALertViewTextFieldBuilder *(^title) (NSString *title); 513 | 514 | @end 515 | 516 | @interface SCLALertViewButtonBuilder : SCLAlertViewBuilder__WithFluent 517 | 518 | #pragma mark - Available later after adding 519 | @property(weak, nonatomic, readonly) SCLButton *button; 520 | 521 | #pragma mark - Setters 522 | @property(copy, nonatomic, readonly) SCLALertViewButtonBuilder *(^title) (NSString *title); 523 | @property(copy, nonatomic, readonly) SCLALertViewButtonBuilder *(^target) (id target); 524 | @property(copy, nonatomic, readonly) SCLALertViewButtonBuilder *(^selector) (SEL selector); 525 | @property(copy, nonatomic, readonly) SCLALertViewButtonBuilder *(^actionBlock) (void(^actionBlock)(void)); 526 | @property(copy, nonatomic, readonly) SCLALertViewButtonBuilder *(^validationBlock) (BOOL(^validationBlock)(void)); 527 | 528 | @end 529 | 530 | @interface SCLAlertViewBuilder : SCLAlertViewBuilder__WithFluent 531 | 532 | #pragma mark - Parameters 533 | @property (strong, nonatomic, readonly) SCLAlertView *alertView; 534 | 535 | #pragma mark - Init 536 | - (instancetype)init; 537 | - (instancetype)initWithNewWindow; 538 | - (instancetype)initWithNewWindowWidth:(CGFloat)width; 539 | 540 | #pragma mark - Properties 541 | @property(copy, nonatomic) SCLAlertViewBuilder *(^cornerRadius) (CGFloat cornerRadius); 542 | @property(copy, nonatomic) SCLAlertViewBuilder *(^tintTopCircle) (BOOL tintTopCircle); 543 | @property(copy, nonatomic) SCLAlertViewBuilder *(^useLargerIcon) (BOOL useLargerIcon); 544 | @property(copy, nonatomic) SCLAlertViewBuilder *(^labelTitle) (UILabel *labelTitle); 545 | @property(copy, nonatomic) SCLAlertViewBuilder *(^viewText) (UITextView *viewText); 546 | @property(copy, nonatomic) SCLAlertViewBuilder *(^activityIndicatorView) (UIActivityIndicatorView *activityIndicatorView); 547 | @property(copy, nonatomic) SCLAlertViewBuilder *(^shouldDismissOnTapOutside) (BOOL shouldDismissOnTapOutside); 548 | @property(copy, nonatomic) SCLAlertViewBuilder *(^soundURL) (NSURL *soundURL); 549 | @property(copy, nonatomic) SCLAlertViewBuilder *(^attributedFormatBlock) (SCLAttributedFormatBlock attributedFormatBlock); 550 | @property(copy, nonatomic) SCLAlertViewBuilder *(^completeButtonFormatBlock) (CompleteButtonFormatBlock completeButtonFormatBlock); 551 | @property(copy, nonatomic) SCLAlertViewBuilder *(^buttonFormatBlock) (ButtonFormatBlock buttonFormatBlock); 552 | @property(copy, nonatomic) SCLAlertViewBuilder *(^forceHideBlock) (SCLForceHideBlock forceHideBlock); 553 | @property(copy, nonatomic) SCLAlertViewBuilder *(^hideAnimationType) (SCLAlertViewHideAnimation hideAnimationType); 554 | @property(copy, nonatomic) SCLAlertViewBuilder *(^showAnimationType) (SCLAlertViewShowAnimation showAnimationType); 555 | @property(copy, nonatomic) SCLAlertViewBuilder *(^backgroundType) (SCLAlertViewBackground backgroundType); 556 | @property(copy, nonatomic) SCLAlertViewBuilder *(^customViewColor) (UIColor *customViewColor); 557 | @property(copy, nonatomic) SCLAlertViewBuilder *(^backgroundViewColor) (UIColor *backgroundViewColor); 558 | @property(copy, nonatomic) SCLAlertViewBuilder *(^iconTintColor) (UIColor *iconTintColor); 559 | @property(copy, nonatomic) SCLAlertViewBuilder *(^circleIconHeight) (CGFloat circleIconHeight); 560 | @property(copy, nonatomic) SCLAlertViewBuilder *(^extensionBounds) (CGRect extensionBounds); 561 | @property(copy, nonatomic) SCLAlertViewBuilder *(^statusBarHidden) (BOOL statusBarHidden); 562 | @property(copy, nonatomic) SCLAlertViewBuilder *(^statusBarStyle) (UIStatusBarStyle statusBarStyle); 563 | 564 | #pragma mark - Custom Setters 565 | @property(copy, nonatomic) SCLAlertViewBuilder *(^alertIsDismissed) (SCLDismissBlock dismissBlock); 566 | @property(copy, nonatomic) SCLAlertViewBuilder *(^alertDismissAnimationIsCompleted) (SCLDismissAnimationCompletionBlock dismissAnimationCompletionBlock); 567 | @property(copy, nonatomic) SCLAlertViewBuilder *(^alertShowAnimationIsCompleted) (SCLShowAnimationCompletionBlock showAnimationCompletionBlock); 568 | @property(copy, nonatomic) SCLAlertViewBuilder *(^removeTopCircle)(void); 569 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addCustomView)(UIView *view); 570 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addTextField)(NSString *title); 571 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addCustomTextField)(UITextField *textField); 572 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addSwitchViewWithLabelTitle)(NSString *title); 573 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addTimerToButtonIndex)(NSInteger buttonIndex, BOOL reverse); 574 | @property(copy, nonatomic) SCLAlertViewBuilder *(^setTitleFontFamily)(NSString *titleFontFamily, CGFloat size); 575 | @property(copy, nonatomic) SCLAlertViewBuilder *(^setBodyTextFontFamily)(NSString *bodyTextFontFamily, CGFloat size); 576 | @property(copy, nonatomic) SCLAlertViewBuilder *(^setButtonsTextFontFamily)(NSString *buttonsFontFamily, CGFloat size); 577 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addButtonWithActionBlock)(NSString *title, SCLActionBlock action); 578 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addButtonWithValidationBlock)(NSString *title, SCLValidationBlock validationBlock, SCLActionBlock action); 579 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addButtonWithTarget)(NSString *title, id target, SEL selector); 580 | 581 | #pragma mark - Builders 582 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addButtonWithBuilder)(SCLALertViewButtonBuilder *builder); 583 | @property(copy, nonatomic) SCLAlertViewBuilder *(^addTextFieldWithBuilder)(SCLALertViewTextFieldBuilder *builder); 584 | 585 | @end 586 | --------------------------------------------------------------------------------