UGCKitTheme.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // Copyright (c) 2019 Tencent. All rights reserved.
  2. #import "UGCKitTheme.h"
  3. #import <objc/runtime.h>
  4. #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
  5. green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
  6. blue:((float)(rgbValue & 0xFF))/255.0 \
  7. alpha:1.0]
  8. #define RGB(r,g,b) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:1]
  9. @interface UGCKitTheme ()
  10. {
  11. NSMutableDictionary<NSString *, UIImage *> *_imageDict;
  12. NSMutableDictionary<NSString *, UIImage *> *_filterIconDictionary;
  13. NSBundle *_resourceBundle;
  14. NSBundle *_beautyPanelResourceBundle;
  15. }
  16. @property (strong, nonatomic) NSBundle *beautyPanelResourceBundle;
  17. @end
  18. @implementation UGCKitTheme
  19. @dynamic closeIcon, progressTrackImage, rightArrowIcon;
  20. @dynamic transitionLeftRightIcon;
  21. @dynamic transitionUpDownIcon;
  22. @dynamic transitionZoomInIcon;
  23. @dynamic transitionZoomOutIcon;
  24. @dynamic transitionRotateIcon;
  25. @dynamic transitionFadeInOutIcon;
  26. @dynamic recordMusicDownloadIcon;
  27. @dynamic nextIcon,backIcon,recordAspect43Icon,recordAspect34Icon,recordAspect11Icon,recordAspect169Icon,recordAspect916Icon,\
  28. recordMusicIcon,recordBeautyIcon,recordAudioEffectIcon,recordCountDownIcon,recordTorchOnIcon,recordTorchOnHighlightedIcon,recordTorchOffIcon;
  29. @dynamic recordTorchOffHighlightedIcon, recordTorchDisabledIcon,recordButtonTapModeIcon,recordButtonPhotoModeIcon,recordButtonPhotoModeBackgroundImage,\
  30. recordButtonPauseInnerIcon,recordButtonPauseBackgroundImage,recordSwitchCameraIcon, \
  31. recordDeleteHighlightedIcon, recordDeleteIcon, recordButtonModeSwitchIndicatorIcon;
  32. @dynamic recordSpeedCenterIcon;
  33. @dynamic recordSpeedLeftIcon;
  34. @dynamic recordSpeedRightIcon;
  35. @dynamic recordMusicSampleImage;
  36. @dynamic recordMusicSwitchIcon;
  37. @dynamic recordMusicDeleteIcon;
  38. @dynamic editPanelAddPasterIcon,editPanelCloseIcon,editPanelConfirmIcon,\
  39. editPanelMusicIcon,editPanelEffectIcon,editPanelSpeedIcon,editPanelFilterIcon,editPanelPasterIcon,editPanelSubtitleIcon,editPanelMusicHighlightedIcon,\
  40. editPanelEffectHighlightedIcon,editPanelSpeedHighlightedIcon,editPanelFilterHighlightedIcon,editPanelPasterHighlightedIcon,editPanelSubtitleHighlightedIcon,\
  41. editPanelDeleteIcon,editPanelDeleteHighlightedIcon,editPlayIcon,editPlayHighlightedIcon,editPauseIcon,editPauseHighlightedIcon,editChooseVideoIcon,confirmIcon,\
  42. confirmHighlightedIcon,editTimelineIndicatorIcon;
  43. @dynamic editTimeEffectIndicatorIcon;
  44. @dynamic editCutSliderLeftIcon;
  45. @dynamic editCutSliderRightIcon;
  46. @dynamic editCutSliderCenterIcon;
  47. @dynamic editMusicSliderRightIcon;
  48. @dynamic editMusicSliderLeftIcon;
  49. @dynamic editPasterDeleteIcon;
  50. @dynamic editTextPasterRotateIcon;
  51. @dynamic editTextPasterEditIcon;
  52. @dynamic editTextPasterConfirmIcon;
  53. @dynamic editFilterSelectionIcon;
  54. @dynamic beautyPanelSmoothBeautyStyleIcon;
  55. @dynamic beautyPanelEyeScaleIcon;
  56. @dynamic beautyPanelPTuBeautyStyleIcon;
  57. @dynamic beautyPanelNatureBeautyStyleIcon;
  58. @dynamic beautyPanelRuddyIcon;
  59. @dynamic beautyPanelBgRemovalIcon;
  60. @dynamic beautyPanelWhitnessIcon;
  61. @dynamic beautyPanelFaceSlimIcon;
  62. @dynamic beautyPanelGoodLuckIcon;
  63. @dynamic beautyPanelChinIcon;
  64. @dynamic beautyPanelFaceVIcon;
  65. @dynamic beautyPanelFaceScaleIcon;
  66. @dynamic beautyPanelNoseSlimIcon;
  67. @dynamic beautyPanelToothWhitenIcon;
  68. @dynamic beautyPanelEyeDistanceIcon;
  69. @dynamic beautyPanelForeheadIcon;
  70. @dynamic beautyPanelFaceBeautyIcon;
  71. @dynamic beautyPanelEyeAngleIcon;
  72. @dynamic beautyPanelNoseWingIcon;
  73. @dynamic beautyPanelLipsThicknessIcon;
  74. @dynamic beautyPanelWrinkleRemoveIcon;
  75. @dynamic beautyPanelMouthShapeIcon;
  76. @dynamic beautyPanelPounchRemoveIcon;
  77. @dynamic beautyPanelSmileLinesRemoveIcon;
  78. @dynamic beautyPanelEyeLightenIcon;
  79. @dynamic beautyPanelNosePositionIcon;
  80. @dynamic beautyPanelMenuSelectionBackgroundImage;
  81. @dynamic menuDisableIcon;
  82. @dynamic sliderThumbImage;
  83. @dynamic audioEffectReverbKTVIcon;
  84. @dynamic audioEffectVoiceChangerHeavyMachineryIcon;
  85. @dynamic audioEffectVoiceChangerHeavyMetalIcon;
  86. @dynamic audioEffectVoiceChangerForeignerIcon;
  87. @dynamic audioEffectVoiceChangerFattyIcon;
  88. @dynamic audioEffectVoiceChangerUncleIcon;
  89. @dynamic audioEffectVoiceChangerLoliIcon;
  90. @dynamic audioEffectVoiceChangerBadBoyIcon;
  91. @dynamic audioEffectVoiceChangerElectricIcon;
  92. @dynamic audioEffectVoiceChangerBeastIcon;
  93. @dynamic audioEffectVoiceChangerEtherealIcon;
  94. @dynamic audioEffectReverbHallIcon;
  95. @dynamic audioEffectReverbRoomIcon;
  96. @dynamic audioEffectReverbMetalIcon;
  97. @dynamic audioEffectReverbLowIcon;
  98. @dynamic audioEffectReverbMagneticIcon;
  99. @dynamic audioEffectReverbSonorousIcon;
  100. static BOOL isBeuatyPanelThemeMethod(SEL selector) {
  101. static NSMutableDictionary<NSString*, NSNumber*> *cache = nil;
  102. if (nil == cache) {
  103. cache = [NSMutableDictionary dictionary];
  104. }
  105. NSString *name = NSStringFromSelector(selector);
  106. NSNumber *val = cache[name];
  107. if (val) {
  108. return val.boolValue;
  109. }
  110. unsigned int outCount = 0;
  111. struct objc_method_description *descriptions
  112. = protocol_copyMethodDescriptionList(@protocol(TCBeautyPanelThemeProtocol),
  113. YES,
  114. YES,
  115. &outCount);
  116. for (unsigned int i = 0; i < outCount; ++i) {
  117. if (descriptions[i].name == selector) {
  118. free(descriptions);
  119. cache[name] = @(YES);
  120. return YES;
  121. }
  122. }
  123. free(descriptions);
  124. cache[name] = @(NO);
  125. return NO;
  126. }
  127. static UIImage *getImageByName(UGCKitTheme *self, SEL selector) {
  128. NSString *selName = NSStringFromSelector(selector);
  129. NSString *key = [[[selName substringToIndex:1] lowercaseString] stringByAppendingString:[selName substringFromIndex:1]];
  130. UIImage *image = [self imageForKey:key];
  131. if (nil == image) {
  132. NSBundle *bundle = self.resourceBundle;
  133. if (isBeuatyPanelThemeMethod(selector)) {
  134. bundle = self.beautyPanelResourceBundle;
  135. }
  136. image = [UIImage imageNamed:NSStringFromSelector(selector) inBundle:bundle compatibleWithTraitCollection:nil];
  137. }
  138. if (nil == image) {
  139. NSLog(@"%@ %@ image not found", NSStringFromClass([self class]), key);
  140. }
  141. return image;
  142. }
  143. static void setImageForKey(id self, SEL selector, UIImage *image) {
  144. NSString *selName = NSStringFromSelector(selector);
  145. NSString *attrName = [[selName substringFromIndex:3] stringByTrimmingCharactersInSet:
  146. [NSCharacterSet characterSetWithCharactersInString:@":"]];
  147. NSString *key = [[[attrName substringToIndex:1] lowercaseString] stringByAppendingString:[attrName substringFromIndex:1]];
  148. [self setImage:image forKey:key];
  149. }
  150. + (BOOL)resolveInstanceMethod:(SEL)sel
  151. {
  152. NSString *selName = NSStringFromSelector(sel);
  153. if ([selName hasPrefix:@"set"]) {
  154. if ([selName hasSuffix:@"Icon:"] || [selName hasSuffix:@"Image:"]) {
  155. class_addMethod([self class], sel, (IMP)setImageForKey, "@@:@");
  156. return YES;
  157. }
  158. } else if ([selName hasSuffix:@"Icon"] || [selName hasSuffix:@"Image"]) {
  159. class_addMethod([self class], sel, (IMP)getImageByName, "@@:");
  160. return YES;
  161. }
  162. return [super resolveInstanceMethod:sel];
  163. }
  164. + (instancetype)sharedTheme {
  165. static UGCKitTheme *theme = nil;
  166. static dispatch_once_t onceToken;
  167. dispatch_once(&onceToken, ^{
  168. theme = [[UGCKitTheme alloc] init];
  169. });
  170. return theme;
  171. }
  172. - (instancetype)init {
  173. if (self = [super init]) {
  174. NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"UGCKitResources"
  175. ofType:@"bundle"];
  176. NSBundle *bundle = [NSBundle bundleWithPath:resourcePath];
  177. _resourceBundle = bundle ?: [NSBundle mainBundle];
  178. NSString *beautyPanelResPath = [bundle pathForResource:@"TCBeautyPanelResources"
  179. ofType:@"bundle"];
  180. _beautyPanelResourceBundle = [NSBundle bundleWithPath:beautyPanelResPath];
  181. _backgroundColor = [UIColor colorWithRed:0.12 green:0.15 blue:0.19 alpha:1];
  182. _editPanelBackgroundColor = [UIColor blackColor];
  183. _editPanelTextColor = [UIColor whiteColor];
  184. _titleColor = [UIColor whiteColor];
  185. _recordTimelineColor = UIColorFromRGB(0xFF584C);
  186. _recordTimelineSelectionColor = UIColorFromRGB(0xA8002D);
  187. _recordTimelineSeperatorColor = UIColorFromRGB(0xA8002D);
  188. _beautyPanelTitleColor = [UIColor whiteColor];
  189. _beautyPanelSelectionColor = [UIColor colorWithRed:0xff/255.0 green:0x58/255.0 blue:0x4c/255.0 alpha:1];
  190. _sliderMinColor = RGB(238, 100, 85);// RGB(166, 166, 165);
  191. _sliderValueColor = [UIColor colorWithRed:1.0 green:0x58/255.0 blue:0x4c/255.0 alpha:1];
  192. _progressColor = RGB(238, 100, 85);
  193. _pickerSelectionBorderColor = RGB(255, 88, 76);
  194. _editPasterBorderColor = [UIColor whiteColor];
  195. _imageDict = [NSMutableDictionary dictionary];
  196. _editCutSliderBorderColor = RGB(239, 100, 85);
  197. _editMusicSliderBorderColor = _editCutSliderBorderColor;
  198. }
  199. return self;
  200. }
  201. - (UIImage *)imageForKey:(NSString *)key
  202. {
  203. return _imageDict[key];
  204. }
  205. - (void)setImage:(UIImage *)image forKey:(NSString *)key
  206. {
  207. _imageDict[key] = image;
  208. }
  209. - (UIImage *)iconForFilter:(NSString *)filter;
  210. {
  211. UIImage *image = _filterIconDictionary[filter];
  212. if (image) {
  213. return image;
  214. }
  215. NSString *imageName = filter;
  216. if (nil == filter) {
  217. imageName = @"original";
  218. } else if ([filter isEqualToString:@"white"]) {
  219. imageName = @"fwhite";
  220. }
  221. return [UIImage imageNamed:imageName
  222. inBundle:_beautyPanelResourceBundle
  223. compatibleWithTraitCollection:nil];
  224. }
  225. - (UIImage *)imageNamed:(NSString *)name {
  226. UIImage *image = [UIImage imageNamed:name
  227. inBundle:_beautyPanelResourceBundle
  228. compatibleWithTraitCollection:nil];
  229. if (nil == image) {
  230. image = [UIImage imageNamed:name
  231. inBundle:_resourceBundle
  232. compatibleWithTraitCollection:nil];
  233. }
  234. return image;
  235. }
  236. - (void)setIcon:(UIImage *)icon forFilter:(TCFilterIdentifier)identifier
  237. {
  238. if (_filterIconDictionary == nil) {
  239. _filterIconDictionary = [NSMutableDictionary dictionaryWithObject:icon forKey:identifier];
  240. } else {
  241. _filterIconDictionary[identifier] = icon;
  242. }
  243. }
  244. //- (UIColor*)_autoContentColor {
  245. // if (@available(iOS 13, *)) {
  246. // return [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
  247. // if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
  248. // return [UIColor whiteColor];
  249. // } else {
  250. // return [UIColor blackColor];
  251. // }
  252. // }];
  253. // } else {
  254. // return [UIColor whiteColor];
  255. // }
  256. //}
  257. //- (UIColor*)_autoBackgroundColor {
  258. // if (@available(iOS 13, *)) {
  259. // return [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
  260. // if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight) {
  261. // return [UIColor whiteColor];
  262. // } else {
  263. // return [UIColor blackColor];
  264. // }
  265. // }];
  266. // } else {
  267. // return [UIColor whiteColor];
  268. // }
  269. //}
  270. - (NSString *)localizedString:(NSString *)key {
  271. return [_resourceBundle localizedStringForKey:key value:@"" table:nil];
  272. }
  273. - (UIImage *)effectIconWithName:(NSString *)name {
  274. NSString *path = [@"VideoEffects" stringByAppendingPathComponent:name];
  275. return [self effectIconWithPath:path frameDuration:1.0/20];
  276. }
  277. - (NSArray *)imagesWithPath:(NSString *)path {
  278. NSString *rootPath = _resourceBundle ? _resourceBundle.bundlePath : [NSBundle mainBundle].bundlePath;
  279. NSString *dir = [rootPath stringByAppendingPathComponent:path];
  280. NSFileManager *fm = [[NSFileManager alloc] init];
  281. NSMutableArray *files = [[NSMutableArray alloc] init];
  282. for (NSString *item in [fm enumeratorAtPath:dir]) {
  283. [files addObject:item];
  284. }
  285. [files sortUsingSelector:@selector(compare:)];
  286. NSMutableArray *images = [NSMutableArray arrayWithCapacity:files.count];
  287. for (NSString *path in files) {
  288. UIImage *image = [UIImage imageWithContentsOfFile:[dir stringByAppendingPathComponent:path]];
  289. [images addObject:image];
  290. }
  291. return images;
  292. }
  293. - (UIImage *)effectIconWithPath:(NSString *)path frameDuration:(float)frameDuration {
  294. NSArray *images = [self imagesWithPath:path];
  295. return [UIImage animatedImageWithImages:images duration:frameDuration * images.count];
  296. }
  297. - (UIImage *)editTimeEffectNormalIcon {
  298. NSString *key = NSStringFromSelector(@selector(editTimeEffectNormalIcon));
  299. if (_imageDict[key]) {
  300. return _imageDict[key];
  301. }
  302. return [self effectIconWithPath:@"jump" frameDuration: 1.0 / 20];
  303. }
  304. - (UIImage *)editTimeEffectReveseIcon {
  305. NSString *key = NSStringFromSelector(@selector(editTimeEffectReveseIcon));
  306. if (_imageDict[key]) {
  307. return _imageDict[key];
  308. }
  309. NSArray *images = [self imagesWithPath:@"jump"];
  310. NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:images.count];
  311. for (UIImage *image in [images reverseObjectEnumerator]) {
  312. [imageArray addObject:image];
  313. }
  314. return [UIImage animatedImageWithImages:imageArray duration:1.0/20*images.count];
  315. }
  316. - (UIImage *)editTimeEffectRepeatIcon {
  317. NSString *key = NSStringFromSelector(@selector(editTimeEffectRepeatIcon));
  318. if (_imageDict[key]) {
  319. return _imageDict[key];
  320. }
  321. NSMutableArray *imageArray = [[self imagesWithPath:@"jump"] mutableCopy];
  322. NSArray *toRepeat = [imageArray subarrayWithRange:NSMakeRange(5, 10)];
  323. [imageArray insertObjects:toRepeat atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(10, 10)]];
  324. [imageArray insertObjects:toRepeat atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(20, 10)]];
  325. return [UIImage animatedImageWithImages:imageArray duration:1.0/20 * imageArray.count];
  326. }
  327. - (UIImage *)editTimeEffectSlowMotionIcon {
  328. NSString *key = NSStringFromSelector(@selector(editTimeEffectSlowMotionIcon));
  329. if (_imageDict[key]) {
  330. return _imageDict[key];
  331. }
  332. return [self effectIconWithPath:@"jump" frameDuration: 1.0 / 10];
  333. }
  334. - (NSString *)goodLuckVideoFilePath {
  335. return [_beautyPanelResourceBundle pathForResource:@"goodluck" ofType:@"mp4"];
  336. }
  337. @end