Merge commit '7621e2f8dec938cf48181c8b10afc9b01f444e68' into beta

This commit is contained in:
Ilya Laktyushin
2025-12-06 02:17:48 +04:00
commit 8344b97e03
28070 changed files with 7995182 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
load("//build-system/bazel-utils:unique_directories.bzl", "unique_directories")
private_headers = glob([
"Sources/**/*.h",
])
objc_library(
name = "RMIntro",
enable_modules = True,
module_name = "RMIntro",
srcs = glob([
"Sources/**/*.m",
"Sources/**/*.c",
]) + private_headers,
hdrs = glob([
"PublicHeaders/**/*.h",
]),
includes = [
"PublicHeaders",
],
copts = [
"-I{}/{}".format(package_name(), directory) for directory in unique_directories(private_headers)
] + [
"-Werror",
"-I{}/PublicHeaders/RMIntro".format(package_name()),
],
deps = [
"//submodules/LegacyComponents:LegacyComponents",
],
sdk_frameworks = [
"Foundation",
"UIKit",
"GLKit",
],
visibility = [
"//visibility:public",
],
)
@@ -0,0 +1,4 @@
#import <UIKit/UIKit.h>
#import <RMIntro/RMIntroViewController.h>
@@ -0,0 +1,84 @@
//
// RMIntroViewController.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 19/01/14.
//
//
#import <UIKit/UIKit.h>
#define GLES_SILENCE_DEPRECATION
#import <GLKit/GLKit.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@class SSignal;
@interface TGAvailableLocalization : NSObject <NSCoding>
@property (nonatomic, strong, readonly) NSString *title;
@property (nonatomic, strong, readonly) NSString *localizedTitle;
@property (nonatomic, strong, readonly) NSString *code;
- (instancetype)initWithTitle:(NSString *)title localizedTitle:(NSString *)localizedTitle code:(NSString *)code;
@end
@interface TGSuggestedLocalization : NSObject
@property (nonatomic, strong, readonly) TGAvailableLocalization *info;
@property (nonatomic, strong, readonly) NSString *continueWithLanguageString;
@property (nonatomic, strong, readonly) NSString *chooseLanguageString;
@property (nonatomic, strong, readonly) NSString *chooseLanguageOtherString;
@property (nonatomic, strong, readonly) NSString *englishLanguageNameString;
- (instancetype)initWithInfo:(TGAvailableLocalization *)info continueWithLanguageString:(NSString *)continueWithLanguageString chooseLanguageString:(NSString *)chooseLanguageString chooseLanguageOtherString:(NSString *)chooseLanguageOtherString englishLanguageNameString:(NSString *)englishLanguageNameString;
@end
@interface RMIntroViewController : UIViewController<UIScrollViewDelegate, GLKViewDelegate>
{
EAGLContext *_context;
GLKView *_glkView;
NSArray *_headlines;
NSArray *_descriptions;
NSMutableArray *_pageViews;
NSInteger _currentPage;
UIScrollView *_pageScrollView;
UIPageControl *_pageControl;
NSTimer *_updateAndRenderTimer;
BOOL _isOpenGLLoaded;
}
@property (nonatomic) CGRect defaultFrame;
- (instancetype)initWithBackgroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor buttonColor:(UIColor *)buttonColor accentColor:(UIColor *)accentColor regularDotColor:(UIColor *)regularDotColor highlightedDotColor:(UIColor *)highlightedDotColor suggestedLocalizationSignal:(SSignal *)suggestedLocalizationSignal;
@property (nonatomic, copy) void (^startMessaging)(void);
@property (nonatomic, copy) void (^startMessagingInAlternativeLanguage)(NSString *);
@property (nonatomic, copy) UIView *(^createStartButton)(CGFloat);
- (UIView *)createAnimationSnapshot;
- (UIView *)createTextSnapshot;
- (void)animateIn;
@property (nonatomic) bool isEnabled;
- (void)startTimer;
- (void)stopTimer;
@end
#pragma clang diagnostic pop
+4
View File
@@ -0,0 +1,4 @@
libglm/
libpng/*
!libpng/Android.mk
zlib/
+529
View File
@@ -0,0 +1,529 @@
#ifndef LINMATH_H
#define LINMATH_H
#include <math.h>
typedef float vec2[2];
typedef float vec3[3];
static inline void vec3_add(vec3 r, vec3 a, vec3 b)
{
int i;
for(i=0; i<3; ++i)
r[i] = a[i] + b[i];
}
static inline void vec3_sub(vec3 r, vec3 a, vec3 b)
{
int i;
for(i=0; i<3; ++i)
r[i] = a[i] - b[i];
}
static inline void vec3_scale(vec3 r, vec3 v, float s)
{
int i;
for(i=0; i<3; ++i)
r[i] = v[i] * s;
}
static inline float vec3_mul_inner(vec3 a, vec3 b)
{
float p = 0.f;
int i;
for(i=0; i<3; ++i)
p += b[i]*a[i];
return p;
}
static inline void vec3_mul_cross(vec3 r, vec3 a, vec3 b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
}
static inline float vec3_len(vec3 v)
{
return sqrtf(vec3_mul_inner(v, v));
}
static inline void vec3_norm(vec3 r, vec3 v)
{
float k = 1.f / vec3_len(v);
vec3_scale(r, v, k);
}
/////
static inline void vec2_add(vec2 r, vec2 a, vec2 b)
{
int i;
for(i=0; i<2; ++i)
r[i] = a[i] + b[i];
}
static inline float vec2_mul_inner(vec2 a, vec2 b)
{
float p = 0.f;
int i;
for(i=0; i<2; ++i)
p += b[i]*a[i];
return p;
}
static inline float vec2_len(vec2 v)
{
return sqrtf(vec2_mul_inner(v, v));
}
static inline void vec2_scale(vec2 r, vec2 v, float s)
{
int i;
for(i=0; i<2; ++i)
r[i] = v[i] * s;
}
static inline void vec2_norm(vec2 r, vec2 v)
{
float k = 1.f / vec2_len(v);
vec2_scale(r, v, k);
}
////
static inline void vec3_reflect(vec3 r, vec3 v, vec3 n)
{
float p = 2.f*vec3_mul_inner(v, n);
int i;
for(i=0;i<3;++i)
r[i] = v[i] - p*n[i];
}
typedef float vec4[4];
static inline void vec4_add(vec4 r, vec4 a, vec4 b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] + b[i];
}
static inline void vec4_sub(vec4 r, vec4 a, vec4 b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] - b[i];
}
static inline void vec4_scale(vec4 r, vec4 v, float s)
{
int i;
for(i=0; i<4; ++i)
r[i] = v[i] * s;
}
static inline float vec4_mul_inner(vec4 a, vec4 b)
{
float p = 0.f;
int i;
for(i=0; i<4; ++i)
p += b[i]*a[i];
return p;
}
static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
r[3] = 1.f;
}
static inline float vec4_len(vec4 v)
{
return sqrtf(vec4_mul_inner(v, v));
}
static inline void vec4_norm(vec4 r, vec4 v)
{
float k = 1.f / vec4_len(v);
vec4_scale(r, v, k);
}
static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
{
float p = 2.f*vec4_mul_inner(v, n);
int i;
for(i=0;i<4;++i)
r[i] = v[i] - p*n[i];
}
typedef vec4 mat4x4[4];
static inline void mat4x4_identity(mat4x4 M)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = i==j ? 1.f : 0.f;
}
static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = N[i][j];
}
static inline void mat4x4_row(vec4 r, mat4x4 M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[k][i];
}
static inline void mat4x4_col(vec4 r, mat4x4 M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[i][k];
}
static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
{
int i, j;
for(j=0; j<4; ++j)
for(i=0; i<4; ++i)
M[i][j] = N[j][i];
}
static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
{
int i;
for(i=0; i<4; ++i)
vec4_add(M[i], a[i], b[i]);
}
static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
{
int i;
for(i=0; i<4; ++i)
vec4_sub(M[i], a[i], b[i]);
}
static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
{
int i;
for(i=0; i<4; ++i)
vec4_scale(M[i], a[i], k);
}
static inline void mat4x4_scale_XYZ(mat4x4 M, float x, float y, float z)
{
mat4x4 a;
mat4x4_dup(a, M);
vec4_scale(M[0], a[0], x);
vec4_scale(M[1], a[1], y);
vec4_scale(M[2], a[2], z);
}
static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
{
vec4_scale(M[0], a[0], x);
vec4_scale(M[1], a[1], y);
vec4_scale(M[2], a[2], z);
}
static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
{
int k, r, c;
for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
M[c][r] = 0.f;
for(k=0; k<4; ++k)
M[c][r] += a[k][r] * b[c][k];
}
}
static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
{
int i, j;
for(j=0; j<4; ++j) {
r[j] = 0.f;
for(i=0; i<4; ++i)
r[j] += M[i][j] * v[i];
}
}
static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
{
mat4x4_identity(T);
T[3][0] = x;
T[3][1] = y;
T[3][2] = z;
}
static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
{
int i, j;
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
}
static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
vec3 u = {x, y, z};
vec3_norm(u, u);
{
mat4x4 T;
mat4x4_from_vec3_mul_outer(T, u, u);
mat4x4 S = {
{ 0.f, u[2], -u[1], 0.f},
{-u[2], 0.f, u[0], 0.f},
{ u[1], -u[0], 0.f, 0.f},
{ 0.f, 0.f, 0.f, 0.f}
};
mat4x4_scale(S, S, s);
mat4x4 C;
mat4x4_identity(C);
mat4x4_sub(C, C, T);
mat4x4_scale(C, C, c);
mat4x4_add(T, T, C);
mat4x4_add(T, T, S);
T[3][3] = 1.f;
mat4x4_mul(R, M, T);
}
}
static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{1.f, 0.f, 0.f, 0.f},
{0.f, c, s, 0.f},
{0.f, -s, c, 0.f},
{0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, 0.f, s, 0.f},
{ 0.f, 1.f, 0.f, 0.f},
{ -s, 0.f, c, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Z2(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, s, 0.f, 0.f},
{ -s, c, 0.f, 0.f},
{ 0.f, 0.f, 1.f, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Z(mat4x4 Q, float angle)
{
mat4x4 temp;
mat4x4_dup(temp, Q);
mat4x4_rotate_Z2(Q, temp, angle);
}
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
{
float s[6];
float c[6];
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
/* Assumes it is invertible */
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
}
static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.0f*n/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][0] = (r+l)/(r-l);
M[2][1] = (t+b)/(t-b);
M[2][2] = -(f+n)/(f-n);
M[2][3] = -1.f;
M[3][2] = -2.f*(f*n)/(f-n);
M[3][0] = M[3][1] = M[3][3] = 0.f;
}
static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][2] = -2.f/(f-n);
M[2][0] = M[2][1] = M[2][3] = 0.f;
M[3][0] = -(r+l)/(r-l);
M[3][1] = -(t+b)/(t-b);
M[3][2] = -(f+n)/(f-n);
M[3][3] = 1.f;
}
typedef float quat[4];
static inline void quat_identity(quat q)
{
q[0] = q[1] = q[2] = 0.f;
q[3] = 1.f;
}
static inline void quat_add(quat r, quat a, quat b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] + b[i];
}
static inline void quat_sub(quat r, quat a, quat b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] - b[i];
}
static inline void quat_mul(quat r, quat p, quat q)
{
vec3 w;
vec3_mul_cross(r, p, q);
vec3_scale(w, p, q[3]);
vec3_add(r, r, w);
vec3_scale(w, q, p[3]);
vec3_add(r, r, w);
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
}
static inline void quat_scale(quat r, quat v, float s)
{
int i;
for(i=0; i<4; ++i)
r[i] = v[i] * s;
}
static inline float quat_inner_product(quat a, quat b)
{
float p = 0.f;
int i;
for(i=0; i<4; ++i)
p += b[i]*a[i];
return p;
}
static inline void quat_conj(quat r, quat q)
{
int i;
for(i=0; i<3; ++i)
r[i] = -q[i];
r[3] = q[3];
}
#define quat_norm vec4_norm
static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
{
quat v_ = {v[0], v[1], v[2], 0.f};
quat_conj(r, q);
quat_norm(r, r);
quat_mul(r, v_, r);
quat_mul(r, q, r);
}
static inline void mat4x4_from_quat(mat4x4 M, quat q)
{
float a = q[3];
float b = q[0];
float c = q[1];
float d = q[2];
float a2 = a*a;
float b2 = b*b;
float c2 = c*c;
float d2 = d*d;
M[0][0] = a2 + b2 - c2 - d2;
M[0][1] = 2.f*(b*c + a*d);
M[0][2] = 2.f*(b*d - a*c);
M[0][3] = 0.f;
M[1][0] = 2*(b*c - a*d);
M[1][1] = a2 - b2 + c2 - d2;
M[1][2] = 2.f*(c*d + a*b);
M[1][3] = 0.f;
M[2][0] = 2.f*(b*d + a*c);
M[2][1] = 2.f*(c*d - a*b);
M[2][2] = a2 - b2 - c2 + d2;
M[2][3] = 0.f;
M[3][0] = M[3][1] = M[3][2] = 0.f;
M[3][3] = 1.f;
}
static inline void mat4x4_mul_quat(mat4x4 R, mat4x4 M, quat q)
{
quat_mul_vec3(R[0], M[0], q);
quat_mul_vec3(R[1], M[1], q);
quat_mul_vec3(R[2], M[2], q);
R[3][0] = R[3][1] = R[3][2] = 0.f;
R[3][3] = 1.f;
}
static inline void quat_from_mat4x4(quat q, mat4x4 M)
{
float r=0.f;
int i;
int perm[] = { 0, 1, 2, 0, 1 };
int *p = perm;
for(i = 0; i<3; i++) {
float m = M[i][i];
if( m < r )
continue;
m = r;
p = &perm[i];
}
r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
if(r < 1e-6) {
q[0] = 1.f;
q[1] = q[2] = q[3] = 0.f;
return;
}
q[0] = r/2.f;
q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
}
#endif
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
//
// animations.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 29/03/14.
// Copyright (c) 2014 IntroOpenGL. All rights reserved.
//
void on_surface_created();
void on_surface_changed(int a_width_px, int a_height_px, float a_scale_factor, int a1, int a2, int a3, int a4, int a5);
void on_draw_frame();
void set_touch_x(int a);
void set_date(double a);
void set_date0(double a);
void set_page(int page);
void set_pages_textures(int a1, int a2, int a3, int a4, int a5, int a6);
void set_ic_textures(int a_ic_bubble_dot, int a_ic_bubble, int a_ic_cam_lens, int a_ic_cam, int a_ic_pencil, int a_ic_pin, int a_ic_smile_eye, int a_ic_smile, int a_ic_videocam);
void set_telegram_textures(int a_telegram_sphere, int a_telegram_plane);
void set_fast_textures(int a_fast_body, int a_fast_spiral, int a_fast_arrow, int a_fast_arrow_shadow);
void set_free_textures(int a_knot_up, int a_knot_down);
void set_powerful_textures(int a_powerful_mask, int a_powerful_star, int a_powerful_infinity, int a_powerful_infinity_white);
void set_private_textures(int a_private_door, int a_private_screw);
void set_y_offset(float a);
void set_scroll_offset(float a_offset);
void inc_stars_rendered();
void set_elements_top_margins(int a_icon_y, int a_text_y, int a_button_y);
void set_intro_background_color(float r, float g, float b);
+19
View File
@@ -0,0 +1,19 @@
#include "buffer.h"
#include "platform_gl.h"
#include <assert.h>
#include <stdlib.h>
GLuint create_vbo(const GLsizeiptr size, const GLvoid* data, const GLenum usage) {
assert(data != NULL);
GLuint vbo_object;
glGenBuffers(1, &vbo_object);
assert(vbo_object != 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo_object);
//glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
glBufferData(GL_ARRAY_BUFFER, size, data, usage);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return vbo_object;
}
+6
View File
@@ -0,0 +1,6 @@
#include "platform_gl.h"
#define BUFFER_OFFSET(i) ((void*)(i))
GLuint create_vbo(const GLsizeiptr size, const GLvoid* data, const GLenum usage);
GLuint create_vbo2(const GLsizeiptr vertex_data_size, const GLvoid* vertex_data, const GLsizeiptr color_data_size, const GLvoid* color_data, const GLenum usage);
+1
View File
@@ -0,0 +1 @@
#define UNUSED(x) (void)(x)
+13
View File
@@ -0,0 +1,13 @@
#include <math.h>
static inline float deg_to_radf(float deg) {
return deg * (float)M_PI / 180.0f;
}
static inline double MAXf(float a, float b) {
return a > b ? a : b;
}
static inline double MINf(float a, float b) {
return a < b ? a : b;
}
+100
View File
@@ -0,0 +1,100 @@
#include "linmath.h"
#include <math.h>
#include <string.h>
/* Adapted from Android's OpenGL Matrix.java. */
static inline void mat4x4_perspective(mat4x4 m, float y_fov_in_degrees, float aspect, float n, float f)
{
const float angle_in_radians = (float) (y_fov_in_degrees * M_PI / 180.0);
const float a = (float) (1.0 / tan(angle_in_radians / 2.0));
m[0][0] = a / aspect;
m[1][0] = 0.0f;
m[2][0] = 0.0f;
m[3][0] = 0.0f;
m[1][0] = 0.0f;
m[1][1] = a;
m[1][2] = 0.0f;
m[1][3] = 0.0f;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = -((f + n) / (f - n));
m[2][3] = -1.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = -((2.0f * f * n) / (f - n));
m[3][3] = 0.0f;
}
static inline void mat4x4_translate_in_place(mat4x4 m, float x, float y, float z)
{
int i;
for (i = 0; i < 4; ++i) {
m[3][i] += m[0][i] * x
+ m[1][i] * y
+ m[2][i] * z;
}
}
static inline void mat4x4_look_at(mat4x4 m,
float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ,
float upX, float upY, float upZ)
{
// See the OpenGL GLUT documentation for gluLookAt for a description
// of the algorithm. We implement it in a straightforward way:
float fx = centerX - eyeX;
float fy = centerY - eyeY;
float fz = centerZ - eyeZ;
// Normalize f
vec3 f_vec = {fx, fy, fz};
float rlf = 1.0f / vec3_len(f_vec);
fx *= rlf;
fy *= rlf;
fz *= rlf;
// compute s = f x up (x means "cross product")
float sx = fy * upZ - fz * upY;
float sy = fz * upX - fx * upZ;
float sz = fx * upY - fy * upX;
// and normalize s
vec3 s_vec = {sx, sy, sz};
float rls = 1.0f / vec3_len(s_vec);
sx *= rls;
sy *= rls;
sz *= rls;
// compute u = s x f
float ux = sy * fz - sz * fy;
float uy = sz * fx - sx * fz;
float uz = sx * fy - sy * fx;
m[0][0] = sx;
m[0][1] = ux;
m[0][2] = -fx;
m[0][3] = 0.0f;
m[1][0] = sy;
m[1][1] = uy;
m[1][2] = -fy;
m[1][3] = 0.0f;
m[2][0] = sz;
m[2][1] = uz;
m[2][2] = -fz;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
mat4x4_translate_in_place(m, -eyeX, -eyeY, -eyeZ);
}
File diff suppressed because it is too large Load Diff
+177
View File
@@ -0,0 +1,177 @@
//
// objects.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 29/03/14.
// Copyright (c) 2014 IntroOpenGL. All rights reserved.
//
#include "platform_gl.h"
#include "program.h"
#include "linmath.h"
extern float scale_factor;
extern int width, height;
extern int y_offset_absolute;
typedef enum {NORMAL, NORMAL_ONE, RED, BLUE, LIGHT_RED, LIGHT_BLUE, DARK, LIGHT, DARK_BLUE} texture_program_type;
typedef struct {
float x;
float y;
} CPoint;
typedef struct {
float width;
float height;
} CSize;
typedef struct {
float r;
float g;
float b;
float a;
} CColor;
CPoint CPointMake(float x, float y);
CSize CSizeMake(float width, float height);
float D2R(float a);
float R2D(float a);
typedef struct {
float x;
float y;
float z;
} xyz;
xyz xyzMake(float x, float y, float z);
typedef struct {
float side_length;
float start_angle;
float end_angle;
float angle;
CSize size;
float radius;
float width;
} VarParams;
typedef struct {
int datasize;
int round_count;
GLenum triangle_mode;
int is_star;
} ConstParams;
typedef struct {
xyz anchor;
xyz position;
float rotation;
xyz scale;
} LayerParams;
typedef struct {
xyz anchor;
xyz position;
float rotation;
xyz scale;
float alpha;
VarParams var_params;
ConstParams const_params;
LayerParams *layer_params;
} Params;
typedef struct {
vec4 color;
CPoint *data;
GLuint buffer;
int num_points;
Params params;
} Shape;
typedef struct {
GLuint texture;
CPoint *data;
GLuint buffer;
int num_points;
Params params;
} TexturedShape;
Params default_params();
LayerParams default_layer_params();
void mat4x4_translate_independed(mat4x4 m, float x, float y, float z);
void set_y_offset_objects(float a);
void setup_shaders();
void draw_shape(const Shape* shape, mat4x4 view_projection_matrix);
void draw_colored_shape(const Shape* shape, mat4x4 view_projection_matrix, vec4 color);
void draw_textured_shape(const TexturedShape* shape, mat4x4 view_projection_matrix, texture_program_type program_type);
TexturedShape create_segmented_square(float side_length, float start_angle, float end_angle, GLuint texture);
void change_segmented_square(TexturedShape* shape, float side_length, float start_angle, float end_angle);
Shape create_rounded_rectangle(CSize size, float radius, int round_count, const vec4 color);
void change_rounded_rectangle(Shape* shape, CSize size, float radius);
Shape create_rectangle(CSize size, const vec4 color);
Shape create_circle(float radius, int vertex_count, const vec4 color);
void change_circle(Shape* shape, float radius);
void draw_colored_rectangle(const Shape* shape, mat4x4 view_projection_matrix);
TexturedShape create_textured_rectangle(CSize size, GLuint texture);
void change_textured_rectangle(TexturedShape* shape, CSize size);
Shape create_ribbon(float length, const vec4 color);
void change_ribbon(Shape* shape, float length);
Shape create_segmented_circle(float radius, int vertex_count, float start_angle, float angle, const vec4 color);
void change_segmented_circle(Shape* shape, float radius, float start_angle, float angle);
Shape create_infinity(float width, float angle, int segment_count, const vec4 color);
void change_infinity(Shape* shape, float angle);
void draw_infinity(const Shape* shape, mat4x4 view_projection_matrix);
Shape create_rounded_rectangle_stroked(CSize size, float radius, float stroke_width, int round_count, const vec4 color);
void change_rounded_rectangle_stroked(Shape* shape, CSize size, float radius, float stroke_width);
Shape create_rounded_rectangle(CSize size, float radius, int round_count, const vec4 color);
void change_rounded_rectangle(Shape* shape, CSize size, float radius);
void mat4x4_log(mat4x4 M);
+38
View File
@@ -0,0 +1,38 @@
#include "program.h"
#include "platform_gl.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TextureProgram get_texture_program(GLuint program)
{
return (TextureProgram) {
program,
glGetAttribLocation(program, "a_Position"),
glGetAttribLocation(program, "a_TextureCoordinates"),
glGetUniformLocation(program, "u_MvpMatrix"),
glGetUniformLocation(program, "u_TextureUnit"),
glGetUniformLocation(program, "u_Alpha")};
}
ColorProgram get_color_program(GLuint program)
{
return (ColorProgram) {
program,
glGetAttribLocation(program, "a_Position"),
glGetUniformLocation(program, "u_MvpMatrix"),
glGetUniformLocation(program, "u_Color"),
glGetUniformLocation(program, "u_Alpha")};
}
GradientProgram get_gradient_program(GLuint program)
{
return (GradientProgram) {
program,
glGetAttribLocation(program, "a_Position"),
glGetUniformLocation(program, "u_MvpMatrix"),
glGetAttribLocation(program, "a_Color"),
glGetUniformLocation(program, "u_Alpha")};
}
#pragma clang diagnostic pop
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "platform_gl.h"
typedef struct {
GLuint program;
GLint a_position_location;
GLint a_texture_coordinates_location;
GLint u_mvp_matrix_location;
GLint u_texture_unit_location;
GLint u_alpha_loaction;
} TextureProgram;
typedef struct {
GLuint program;
GLint a_position_location;
GLint u_mvp_matrix_location;
GLint u_color_location;
GLint u_alpha_loaction;
} ColorProgram;
typedef struct {
GLuint program;
GLint a_position_location;
GLint u_mvp_matrix_location;
GLint a_color_location;
GLint u_alpha_loaction;
} GradientProgram;
TextureProgram get_texture_program(GLuint program);
ColorProgram get_color_program(GLuint program);
GradientProgram get_gradient_program(GLuint program);
+19
View File
@@ -0,0 +1,19 @@
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "rngs.h"
float frand(float from, float to)
{
return (float)(((double)random()/RAND_MAX)*(to-from)+from);
}
int irand(int from, int to)
{
return (int)(((double)random()/RAND_MAX)*(to-from+1)+from);
}
int signrand()
{
return irand(0, 1)*2-1;
}
+7
View File
@@ -0,0 +1,7 @@
int irand(int from, int to);
float frand(float from, float to);
int signrand();
+119
View File
@@ -0,0 +1,119 @@
#include "shader.h"
#include "platform_gl.h"
#include "platform_log.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define TAG "shaders"
#ifndef LOGGING_ON
#define LOGGING_ON 0
#endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
static void log_v_fixed_length(const GLchar* source, const GLint length) {
if (LOGGING_ON) {
char log_buffer[length + 1];
memcpy(log_buffer, source, length);
log_buffer[length] = '\0';
DEBUG_LOG_WRITE_V(TAG, log_buffer);
}
}
static void log_shader_info_log(GLuint shader_object_id) {
if (LOGGING_ON) {
GLint log_length;
glGetShaderiv(shader_object_id, GL_INFO_LOG_LENGTH, &log_length);
GLchar log_buffer[log_length];
glGetShaderInfoLog(shader_object_id, log_length, NULL, log_buffer);
DEBUG_LOG_WRITE_V(TAG, log_buffer);
}
}
static void log_program_info_log(GLuint program_object_id) {
if (LOGGING_ON) {
GLint log_length;
glGetProgramiv(program_object_id, GL_INFO_LOG_LENGTH, &log_length);
GLchar log_buffer[log_length];
glGetProgramInfoLog(program_object_id, log_length, NULL, log_buffer);
DEBUG_LOG_WRITE_V(TAG, log_buffer);
}
}
GLuint compile_shader(const GLenum type, const GLchar* source, const GLint length) {
assert(source != NULL);
GLuint shader_object_id = glCreateShader(type);
GLint compile_status;
assert(shader_object_id != 0);
glShaderSource(shader_object_id, 1, (const GLchar **)&source, &length);
glCompileShader(shader_object_id);
glGetShaderiv(shader_object_id, GL_COMPILE_STATUS, &compile_status);
if (LOGGING_ON) {
DEBUG_LOG_WRITE_D(TAG, "Results of compiling shader source:");
log_v_fixed_length(source, length);
log_shader_info_log(shader_object_id);
}
assert(compile_status != 0);
return shader_object_id;
}
GLuint link_program(const GLuint vertex_shader, const GLuint fragment_shader) {
GLuint program_object_id = glCreateProgram();
GLint link_status;
assert(program_object_id != 0);
glAttachShader(program_object_id, vertex_shader);
glAttachShader(program_object_id, fragment_shader);
glLinkProgram(program_object_id);
glGetProgramiv(program_object_id, GL_LINK_STATUS, &link_status);
if (LOGGING_ON) {
DEBUG_LOG_WRITE_D(TAG, "Results of linking program:");
log_program_info_log(program_object_id);
}
assert(link_status != 0);
return program_object_id;
}
GLuint build_program(
const GLchar * vertex_shader_source, const GLint vertex_shader_source_length,
const GLchar * fragment_shader_source, const GLint fragment_shader_source_length) {
assert(vertex_shader_source != NULL);
assert(fragment_shader_source != NULL);
GLuint vertex_shader = compile_shader(
GL_VERTEX_SHADER, vertex_shader_source, vertex_shader_source_length);
GLuint fragment_shader = compile_shader(
GL_FRAGMENT_SHADER, fragment_shader_source, fragment_shader_source_length);
return link_program(vertex_shader, fragment_shader);
}
GLint validate_program(const GLuint program) {
if (LOGGING_ON) {
int validate_status;
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &validate_status);
DEBUG_LOG_PRINT_D(TAG, "Results of validating program: %d", validate_status);
log_program_info_log(program);
return validate_status;
}
return 0;
}
#pragma clang diagnostic pop
+10
View File
@@ -0,0 +1,10 @@
#include "platform_gl.h"
GLuint compile_shader(const GLenum type, const GLchar* source, const GLint length);
GLuint link_program(const GLuint vertex_shader, const GLuint fragment_shader);
GLuint build_program(
const GLchar * vertex_shader_source, const GLint vertex_shader_source_length,
const GLchar * fragment_shader_source, const GLint fragment_shader_source_length);
/* Should be called just before using a program to draw, if validation is needed. */
GLint validate_program(const GLuint program);
+130
View File
@@ -0,0 +1,130 @@
#include "timing.h"
static inline float evaluateAtParameterWithCoefficients(float t, float coefficients[])
{
return coefficients[0] + t*coefficients[1] + t*t*coefficients[2] + t*t*t*coefficients[3];
}
static inline float evaluateDerivationAtParameterWithCoefficients(float t, float coefficients[])
{
return coefficients[1] + 2*t*coefficients[2] + 3*t*t*coefficients[3];
}
static inline float calcParameterViaNewtonRaphsonUsingXAndCoefficientsForX(float x, float coefficientsX[])
{
// see http://en.wikipedia.org/wiki/Newton's_method
// start with X being the correct value
float t = x;
// iterate several times
//const float epsilon = 0.00001;
int i;
for(i = 0; i < 10; i++)
{
float x2 = evaluateAtParameterWithCoefficients(t, coefficientsX) - x;
float d = evaluateDerivationAtParameterWithCoefficients(t, coefficientsX);
float dt = x2/d;
t = t - dt;
}
return t;
}
static inline float calcParameterUsingXAndCoefficientsForX (float x, float coefficientsX[])
{
// for the time being, we'll guess Newton-Raphson always
// returns the correct value.
// if we find it doesn't find the solution often enough,
// we can add additional calculation methods.
float t = calcParameterViaNewtonRaphsonUsingXAndCoefficientsForX(x, coefficientsX);
return t;
}
static int is_initialized=0;
static float _coefficientsX[TIMING_NUM][4], _coefficientsY[TIMING_NUM][4];
static const float _c0x = 0.0;
static const float _c0y = 0.0;
static const float _c3x = 1.0;
static const float _c3y = 1.0;
float timing(float x, timing_type type)
{
if (is_initialized==0) {
is_initialized=1;
float c[TIMING_NUM][4];
c[Default][0]=0.25f;
c[Default][1]=0.1f;
c[Default][2]=0.25f;
c[Default][3]=1.0f;
c[EaseInEaseOut][0]=0.42f;
c[EaseInEaseOut][1]=0.0f;
c[EaseInEaseOut][2]=0.58f;
c[EaseInEaseOut][3]=1.0f;
c[EaseIn][0]=0.42f;
c[EaseIn][1]=0.0f;
c[EaseIn][2]=1.0f;
c[EaseIn][3]=1.0f;
c[EaseOut][0]=0.0f;
c[EaseOut][1]=0.0f;
c[EaseOut][2]=0.58f;
c[EaseOut][3]=1.0f;
c[EaseOutBounce][0]=0.0;
c[EaseOutBounce][1]=0.0;
c[EaseOutBounce][2]=0.;
c[EaseOutBounce][3]=1.25;
c[Linear][0]=0.0;
c[Linear][1]=0.0;
c[Linear][2]=1.0;
c[Linear][3]=1.0;
int i;
for (i=0; i<TIMING_NUM; i++) {
float _c1x = c[i][0];
float _c1y = c[i][1];
float _c2x = c[i][2];
float _c2y = c[i][3];
_coefficientsX[i][0] = _c0x; // t^0
_coefficientsX[i][1] = -3.0f*_c0x + 3.0f*_c1x; // t^1
_coefficientsX[i][2] = 3.0f*_c0x - 6.0f*_c1x + 3.0f*_c2x; // t^2
_coefficientsX[i][3] = -_c0x + 3.0f*_c1x - 3.0f*_c2x + _c3x; // t^3
_coefficientsY[i][0] = _c0y; // t^0
_coefficientsY[i][1] = -3.0f*_c0y + 3.0f*_c1y; // t^1
_coefficientsY[i][2] = 3.0f*_c0y - 6.0f*_c1y + 3.0f*_c2y; // t^2
_coefficientsY[i][3] = -_c0y + 3.0f*_c1y - 3.0f*_c2y + _c3y; // t^3
}
}
if (x==0.0 || x==1.0) {
return x;
}
float t = calcParameterUsingXAndCoefficientsForX(x, _coefficientsX[type]);
float y = evaluateAtParameterWithCoefficients(t, _coefficientsY[type]);
return y;
}
+22
View File
@@ -0,0 +1,22 @@
//
// timing.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 03/05/14.
// Copyright (c) 2014 IntroOpenGL. All rights reserved.
//
typedef enum
{
Default=0,
EaseIn=1,
EaseOut=2,
EaseInEaseOut=3,
Linear=4,
Sin=5,
EaseOutBounce,
TIMING_NUM
} timing_type;
float timing(float x, timing_type type);
+27
View File
@@ -0,0 +1,27 @@
#include "platform_log.h"
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#define LOG_VPRINTF(priority) printf("(" priority ") %s: ", tag); \
va_list arg_ptr; \
va_start(arg_ptr, fmt); \
vprintf(fmt, arg_ptr); \
va_end(arg_ptr); \
printf("\n");
void _debug_log_v(const char *tag, const char *fmt, ...) {
LOG_VPRINTF("VERBOSE");
}
void _debug_log_d(const char *tag, const char *fmt, ...) {
LOG_VPRINTF("DEBUG");
}
void _debug_log_w(const char *tag, const char *fmt, ...) {
LOG_VPRINTF("WARN");
}
void _debug_log_e(const char *tag, const char *fmt, ...) {
LOG_VPRINTF("ERROR");
}
+22
View File
@@ -0,0 +1,22 @@
#include "platform_macros.h"
#ifndef LOGGING_ON
#define LOGGING_ON 0
#endif
void _debug_log_v(const char* tag, const char* text, ...) PRINTF_ATTRIBUTE(2, 3);
void _debug_log_d(const char* tag, const char* text, ...) PRINTF_ATTRIBUTE(2, 3);
void _debug_log_w(const char* tag, const char* text, ...) PRINTF_ATTRIBUTE(2, 3);
void _debug_log_e(const char* tag, const char* text, ...) PRINTF_ATTRIBUTE(2, 3);
#define DEBUG_LOG_PRINT_V(tag, fmt, ...) do { if (LOGGING_ON) _debug_log_v(tag, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
#define DEBUG_LOG_PRINT_D(tag, fmt, ...) do { if (LOGGING_ON) _debug_log_d(tag, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
#define DEBUG_LOG_PRINT_W(tag, fmt, ...) do { if (LOGGING_ON) _debug_log_w(tag, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
#define DEBUG_LOG_PRINT_E(tag, fmt, ...) do { if (LOGGING_ON) _debug_log_e(tag, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
#define DEBUG_LOG_WRITE_V(tag, text) DEBUG_LOG_PRINT_V(tag, "%s", text)
#define DEBUG_LOG_WRITE_D(tag, text) DEBUG_LOG_PRINT_D(tag, "%s", text)
#define DEBUG_LOG_WRITE_W(tag, text) DEBUG_LOG_PRINT_W(tag, "%s", text)
#define DEBUG_LOG_WRITE_E(tag, text) DEBUG_LOG_PRINT_E(tag, "%s", text)
#define CRASH(e) DEBUG_LOG_WRITE_E("Assert", #e); __builtin_trap()
@@ -0,0 +1,5 @@
#if defined(__GNUC__)
#define PRINTF_ATTRIBUTE(format_pos, arg_pos) __attribute__((format(printf, format_pos, arg_pos)))
#else
#define PRINTF_ATTRIBUTE(format_pos, arg_pos)
#endif
@@ -0,0 +1,181 @@
//
// RMGeometry.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 11/19/10.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
//const float extern Pi=3.14;
//const float extern Pi2=6.28;
static inline CGFloat DtoR(CGFloat a)
{
return (CGFloat)(a*M_PI/180.0);
}
static inline CGFloat rnd(CGFloat a, CGFloat b)
{
//return rand()%10000/10000.0*(b-a)+a;
return (CGFloat)(arc4random()%10000/10000.0*(b-a)+a);
}
static inline NSInteger intRnd(NSInteger a, NSInteger b)
{
//return rand()%(b-a+1)+a;
return arc4random()%(b-a+1)+a;
}
static inline NSInteger signRnd()
{
return intRnd(0, 1)*2-1;
}
static inline NSInteger sign(CGFloat a)
{
return a >= 0 ? 1 : -1;
}
static inline CGPoint CGRectCenter(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
}
static inline CGRect CGRectCentralize(CGRect rect, CGPoint center) {
CGPoint oldCenter = CGRectCenter(rect);
CGPoint offset = CGPointMake(center.x - oldCenter.x, center.y - oldCenter.y);
return CGRectOffset(rect, offset.x, offset.y);
}
static inline CGRect CGRectRoundComponents(CGRect rect) {
return CGRectMake((NSInteger) (rect.origin.x + 0.5), (NSInteger) (rect.origin.y + 0.5), (NSInteger) (rect.size.width + 0.5), (NSInteger) (rect.size.height + 0.5));
}
static inline CGRect CGRectScaledToWidth (CGRect rect, CGFloat width) {
const CGFloat ratio = width / rect.size.width;
return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height * ratio);
}
static inline CGRect CGRectScaledToHeight(CGRect rect, CGFloat height) {
const CGFloat ratio = height / rect.size.height;
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width * ratio, height);
}
static inline CGRect CGRectScaledToWidthI (CGRect rect, CGFloat width) {
const CGFloat ratio = width / rect.size.width;
return CGRectMake((NSInteger) rect.origin.x, (NSInteger) rect.origin.y, (NSInteger) width, (NSInteger) (rect.size.height * ratio));
}
static inline CGRect CGRectScaledToHeightI(CGRect rect, CGFloat height) {
const CGFloat ratio = height / rect.size.height;
return CGRectMake((NSInteger) rect.origin.x, (NSInteger) rect.origin.y, (NSInteger) (rect.size.width * ratio), (NSInteger) height);
}
static inline CGRect CGRectScaledToFitRect(CGRect innerRect, CGRect boundingRect, BOOL centralize) {
const CGFloat innerRectWHRatio = innerRect.size.width / innerRect.size.height;
const CGFloat boundingRectWHRatio = boundingRect.size.width / boundingRect.size.height;
CGRect result;
if (innerRectWHRatio >= boundingRectWHRatio) {
result = CGRectScaledToWidth(innerRect, boundingRect.size.width);
} else {
result = CGRectScaledToHeight(innerRect, boundingRect.size.height);
}
if (centralize) {
result = CGRectCentralize(result, CGRectCenter(boundingRect));
}
result = CGRectRoundComponents(result);
return result;
}
static inline CGRect CGRectScaledToFitRectSmall(CGRect innerRect, CGRect boundingRect, BOOL centralize) {
const CGFloat innerRectWHRatio = innerRect.size.width / innerRect.size.height;
const CGFloat boundingRectWHRatio = boundingRect.size.width / boundingRect.size.height;
CGRect result;
if (innerRect.size.width<boundingRect.size.width && innerRect.size.height<boundingRect.size.height) {
result=CGRectCentralize(innerRect, CGRectCenter(boundingRect));
}
else
{
if (innerRectWHRatio >= boundingRectWHRatio) {
result = CGRectScaledToWidth(innerRect, boundingRect.size.width);
} else {
result = CGRectScaledToHeight(innerRect, boundingRect.size.height);
}
if (centralize) {
result = CGRectCentralize(result, CGRectCenter(boundingRect));
}
}
result = CGRectRoundComponents(result);
return result;
}
static inline CGRect CGRectScaledToFitRectI(CGRect innerRect, CGRect boundingRect, BOOL centralize) {
return CGRectRoundComponents(CGRectScaledToFitRect(innerRect, boundingRect, centralize));
}
static inline CGRect CGRectMakeOrigAndSize(CGPoint orig, CGSize size) {
return CGRectMake(orig.x, orig.y, size.width, size.height);
}
static inline CGRect CGRectChangedWidth(CGRect rect, CGFloat width) {
return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height);
}
static inline CGRect CGRectChangedHeight(CGRect rect, CGFloat height) {
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height);
}
static inline CGRect CGRectChangedSize(CGRect rect, CGSize size) {
return CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height);
}
static inline CGRect CGRectChangedOrigin(CGRect rect, CGPoint origin) {
return CGRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
}
static inline CGRect CGRectChangedOriginX(CGRect rect, CGFloat originX) {
return CGRectMake(originX, rect.origin.y, rect.size.width, rect.size.height);
}
static inline CGRect CGRectChangedOriginY(CGRect rect, CGFloat originY) {
return CGRectMake(rect.origin.x, originY, rect.size.width, rect.size.height);
}
static inline CGRect CGRectChangedCenterY(CGRect rect, CGFloat centerY) {
return CGRectMake(rect.origin.x, centerY - rect.size.height / 2.0f, rect.size.width, rect.size.height);
}
static inline CGRect CGRectChangedCenterX(CGRect rect, CGFloat centerX) {
return CGRectMake(centerX - rect.size.width / 2.0f, rect.origin.y, rect.size.width, rect.size.height);
}
static inline CGRect CGRectWithIndent(CGRect rect, NSInteger indent) {
return CGRectMake(rect.origin.x-indent, rect.origin.y-indent, rect.size.width+indent*2,rect.size.height+indent*2);
}
#define VK_ROUND_RECT(rect) rect = CGRectRoundComponents(rect)
@@ -0,0 +1,9 @@
//
// RMGeometry.m
// IntroOpenGL
//
// Created by Ilya Rimchikov on 11/19/10.
//
#import "RMGeometry.h"
@@ -0,0 +1,22 @@
//
// RMIntroPageView.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 05.12.13.
// Copyright (c) 2013 Ilya Rimchikov. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RMIntroPageView : UIView
{
NSString *_headline;
NSMutableAttributedString *_description;
}
@property (nonatomic, readonly) UILabel *headerLabel;
@property (nonatomic, readonly) UILabel *descriptionLabel;
- (id)initWithFrame:(CGRect)frame headline:(NSString*)headline description:(NSString*)description color:(UIColor *)color;
@end
@@ -0,0 +1,98 @@
//
// RMIntroPageView.m
// IntroOpenGL
//
// Created by Ilya Rimchikov on 05.12.13.
// Copyright (c) 2013 Ilya Rimchikov. All rights reserved.
//
#import "RMIntroPageView.h"
@implementation RMIntroPageView
#define IPAD ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
- (id)initWithFrame:(CGRect)frame headline:(NSString*)headline description:(NSString*)description color:(UIColor *)color
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//self.backgroundColor=[UIColor redColor];
self.opaque=YES;
_headline=headline;
UILabel *headlineLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, 64+8)];
headlineLabel.font = [UIFont boldSystemFontOfSize:35.0]; //[UIFont fontWithName:@"HelveticaNeue-Light" size:IPAD ? 96/2 : 36];
headlineLabel.text = _headline;
headlineLabel.textColor = color;
headlineLabel.textAlignment = NSTextAlignmentCenter;
headlineLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
_headerLabel = headlineLabel;
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = IPAD ? 4 : 3;
style.lineBreakMode = NSLineBreakByWordWrapping;
style.alignment = NSTextAlignmentCenter;
NSMutableArray *boldRanges = [[NSMutableArray alloc] init];
NSMutableString *cleanText = [[NSMutableString alloc] initWithString:description];
while (true)
{
NSRange startRange = [cleanText rangeOfString:@"**"];
if (startRange.location == NSNotFound)
break;
[cleanText deleteCharactersInRange:startRange];
NSRange endRange = [cleanText rangeOfString:@"**"];
if (endRange.location == NSNotFound)
break;
[cleanText deleteCharactersInRange:endRange];
[boldRanges addObject:[NSValue valueWithRange:NSMakeRange(startRange.location, endRange.location - startRange.location)]];
}
_description = [[NSMutableAttributedString alloc]initWithString:cleanText];
NSDictionary *boldAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont boldSystemFontOfSize:IPAD ? 22 : 17.0], NSFontAttributeName, nil];
for (NSValue *nRange in boldRanges)
{
[_description addAttributes:boldAttributes range:[nRange rangeValue]];
}
[_description addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, _description.length)];
[_description addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, _description.length)];
UILabel *descriptionLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 25 + (IPAD ? 22 : 0), frame.size.width, 120+8+5)];
descriptionLabel.font = [UIFont systemFontOfSize:IPAD ? 22 : 17.0];
descriptionLabel.attributedText = _description;
descriptionLabel.numberOfLines=0;
descriptionLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
[self addSubview:descriptionLabel];
_descriptionLabel = descriptionLabel;
[self addSubview:headlineLabel];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
@@ -0,0 +1,773 @@
//
// RMIntroViewController.m
// IntroOpenGL
//
// Created by Ilya Rimchikov on 19/01/14.
//
//
#import "RMGeometry.h"
#import "RMIntroViewController.h"
#import "RMIntroPageView.h"
#include "animations.h"
#include "objects.h"
#include "texture_helper.h"
#import <SSignalKit/SSignalKit.h>
#import <LegacyComponents/LegacyComponents.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
typedef enum {
Inch35 = 0,
Inch4 = 1,
Inch47 = 2,
Inch55 = 3,
Inch65 = 4,
iPad = 5,
iPadPro = 6
} DeviceScreen;
@interface UIScrollView (CurrentPage)
- (int)currentPage;
- (void)setPage:(NSInteger)page;
- (int)currentPageMin;
- (int)currentPageMax;
@end
@implementation UIScrollView (CurrentPage)
- (int)currentPage
{
CGFloat pageWidth = self.frame.size.width;
return (int)floor((self.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
}
- (int)currentPageMin
{
CGFloat pageWidth = self.frame.size.width;
return (int)floor((self.contentOffset.x - pageWidth / 2 - pageWidth / 2) / pageWidth) + 1;
}
- (int)currentPageMax
{
CGFloat pageWidth = self.frame.size.width;
return (int)floor((self.contentOffset.x - pageWidth / 2 + pageWidth / 2 ) / pageWidth) + 1;
}
- (void)setPage:(NSInteger)page
{
self.contentOffset = CGPointMake(self.frame.size.width*page, 0);
}
@end
@interface RMIntroView : UIView
@property (nonatomic, copy) void (^onLayout)();
@end
@implementation RMIntroView
- (void)layoutSubviews {
[super layoutSubviews];
if (_onLayout) {
_onLayout();
}
}
@end
@interface RMIntroViewController () <UIGestureRecognizerDelegate>
{
id _didEnterBackgroundObserver;
id _willEnterBackgroundObserver;
UIColor *_backgroundColor;
UIColor *_primaryColor;
UIColor *_buttonColor;
UIColor *_accentColor;
UIColor *_regularDotColor;
UIColor *_highlightedDotColor;
TGModernButton *_alternativeLanguageButton;
SMetaDisposable *_localizationsDisposable;
TGSuggestedLocalization *_alternativeLocalizationInfo;
SVariable *_alternativeLocalization;
NSDictionary<NSString *, NSString *> *_englishStrings;
UIView *_wrapperView;
UIView *_startButton;
bool _loadedView;
}
@end
@implementation RMIntroViewController
- (instancetype)initWithBackgroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor buttonColor:(UIColor *)buttonColor accentColor:(UIColor *)accentColor regularDotColor:(UIColor *)regularDotColor highlightedDotColor:(UIColor *)highlightedDotColor suggestedLocalizationSignal:(SSignal *)suggestedLocalizationSignal
{
self = [super init];
if (self != nil)
{
_isEnabled = true;
_backgroundColor = backgroundColor;
_primaryColor = primaryColor;
_buttonColor = buttonColor;
_accentColor = accentColor;
_regularDotColor = regularDotColor;
_highlightedDotColor = highlightedDotColor;
NSArray<NSString *> *stringKeys = @[
@"Tour.Title1",
@"Tour.Title2",
@"Tour.Title3",
@"Tour.Title4",
@"Tour.Title5",
@"Tour.Title6",
@"Tour.Text1",
@"Tour.Text2",
@"Tour.Text3",
@"Tour.Text4",
@"Tour.Text5",
@"Tour.Text6",
@"Tour.StartButton"
];
NSMutableDictionary *englishStrings = [[NSMutableDictionary alloc] init];
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"]];
for (NSString *key in stringKeys) {
if (bundle != nil) {
NSString *value = [bundle localizedStringForKey:key value:key table:nil];
if (value != nil) {
englishStrings[key] = value;
} else {
englishStrings[key] = key;
}
} else {
englishStrings[key] = key;
}
}
_englishStrings = englishStrings;
_headlines = @[ _englishStrings[@"Tour.Title1"], _englishStrings[@"Tour.Title2"], _englishStrings[@"Tour.Title6"], _englishStrings[@"Tour.Title3"], _englishStrings[@"Tour.Title4"], _englishStrings[@"Tour.Title5"]];
_descriptions = @[_englishStrings[@"Tour.Text1"], _englishStrings[@"Tour.Text2"], _englishStrings[@"Tour.Text6"], _englishStrings[@"Tour.Text3"], _englishStrings[@"Tour.Text4"], _englishStrings[@"Tour.Text5"]];
__weak RMIntroViewController *weakSelf = self;
_didEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:nil usingBlock:^(__unused NSNotification *notification)
{
__strong RMIntroViewController *strongSelf = weakSelf;
[strongSelf stopTimer];
}];
_willEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:nil usingBlock:^(__unused NSNotification *notification)
{
__strong RMIntroViewController *strongSelf = weakSelf;
[strongSelf loadGL];
[strongSelf startTimer];
}];
_alternativeLanguageButton = [[TGModernButton alloc] init];
_alternativeLanguageButton.modernHighlight = true;
[_alternativeLanguageButton setTitleColor:accentColor];
_alternativeLanguageButton.titleLabel.font = [UIFont systemFontOfSize:18.0];
_alternativeLanguageButton.hidden = true;
[_alternativeLanguageButton addTarget:self action:@selector(alternativeLanguageButtonPressed) forControlEvents:UIControlEventTouchUpInside];
_alternativeLocalization = [[SVariable alloc] init];
_localizationsDisposable = [[suggestedLocalizationSignal deliverOn:[SQueue mainQueue]] startStrictWithNext:^(TGSuggestedLocalization *next) {
__strong RMIntroViewController *strongSelf = weakSelf;
if (strongSelf != nil && next != nil) {
if (strongSelf->_alternativeLocalizationInfo == nil) {
strongSelf->_alternativeLocalizationInfo = next;
[strongSelf->_alternativeLanguageButton setTitle:next.continueWithLanguageString forState:UIControlStateNormal];
strongSelf->_alternativeLanguageButton.hidden = false;
[strongSelf->_alternativeLanguageButton sizeToFit];
if ([strongSelf isViewLoaded]) {
strongSelf->_alternativeLanguageButton.alpha = 0.0;
[UIView animateWithDuration:0.3 animations:^{
strongSelf->_alternativeLanguageButton.alpha = strongSelf->_isEnabled ? 1.0 : 0.6;
[strongSelf viewWillLayoutSubviews];
}];
}
}
}
} file:__FILE_NAME__ line:__LINE__];
}
return self;
}
- (void)startTimer
{
if (_updateAndRenderTimer == nil)
{
_updateAndRenderTimer = [NSTimer timerWithTimeInterval:1.0f / 60.0f target:self selector:@selector(updateAndRender) userInfo:nil repeats:true];
[[NSRunLoop mainRunLoop] addTimer:_updateAndRenderTimer forMode:NSRunLoopCommonModes];
}
}
- (void)stopTimer
{
if (_updateAndRenderTimer != nil)
{
[_updateAndRenderTimer invalidate];
_updateAndRenderTimer = nil;
}
}
- (void)animateIn {
CGPoint logoTargetPosition = _glkView.center;
_glkView.center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0);
RMIntroPageView *firstPage = (RMIntroPageView *)[_pageViews firstObject];
CGPoint headerTargetPosition = firstPage.headerLabel.center;
firstPage.headerLabel.center = CGPointMake(headerTargetPosition.x, headerTargetPosition.y + 140.0);
CGPoint descriptionTargetPosition = firstPage.descriptionLabel.center;
firstPage.descriptionLabel.center = CGPointMake(descriptionTargetPosition.x, descriptionTargetPosition.y + 160.0);
CGPoint pageControlTargetPosition = _pageControl.center;
_pageControl.center = CGPointMake(pageControlTargetPosition.x, pageControlTargetPosition.y + 200.0);
CGPoint buttonTargetPosition = _startButton.center;
_startButton.center = CGPointMake(buttonTargetPosition.x, buttonTargetPosition.y + 220.0);
_glkView.transform = CGAffineTransformMakeScale(0.66, 0.66);
[UIView animateWithDuration:0.65 delay:0.15 usingSpringWithDamping:1.2f initialSpringVelocity:0.0 options:kNilOptions animations:^{
_glkView.center = logoTargetPosition;
firstPage.headerLabel.center = headerTargetPosition;
firstPage.descriptionLabel.center = descriptionTargetPosition;
_pageControl.center = pageControlTargetPosition;
_startButton.center = buttonTargetPosition;
_glkView.transform = CGAffineTransformIdentity;
} completion:nil];
_glkView.alpha = 0.0;
_pageScrollView.alpha = 0.0;
_pageControl.alpha = 0.0;
_startButton.alpha = 0.0;
[UIView animateWithDuration:0.3 delay:0.15 options:kNilOptions animations:^{
_glkView.alpha = 1.0;
_pageScrollView.alpha = 1.0;
_pageControl.alpha = 1.0;
_startButton.alpha = 1.0;
} completion:nil];
}
- (void)loadGL
{
#if TARGET_OS_SIMULATOR && defined(__aarch64__)
return;
#endif
if (/*[[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground*/true && !_isOpenGLLoaded)
{
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!_context)
NSLog(@"Failed to create ES context");
bool isIpad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
CGFloat size = 200;
if (isIpad)
size *= 1.2;
int height = 50;
if (isIpad)
height += 138 / 2;
_glkView = [[GLKView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width / 2 - size / 2, height, size, size) context:_context];
_glkView.backgroundColor = _backgroundColor;
_glkView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
_glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
_glkView.drawableMultisample = GLKViewDrawableMultisample4X;
_glkView.enableSetNeedsDisplay = false;
_glkView.userInteractionEnabled = false;
_glkView.delegate = self;
[self setupGL];
[self.view addSubview:_glkView];
[self startTimer];
_isOpenGLLoaded = true;
}
}
- (void)freeGL
{
if (!_isOpenGLLoaded)
return;
[self stopTimer];
if ([EAGLContext currentContext] == _glkView.context)
[EAGLContext setCurrentContext:nil];
_context = nil;
[_glkView removeFromSuperview];
_glkView = nil;
_isOpenGLLoaded = false;
}
- (void)loadView {
self.view = [[RMIntroView alloc] initWithFrame:self.defaultFrame];
__weak RMIntroViewController *weakSelf = self;
((RMIntroView *)self.view).onLayout = ^{
__strong RMIntroViewController *strongSelf = weakSelf;
if (strongSelf != nil) {
[strongSelf updateLayout];
}
};
[self viewDidLoad];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (_loadedView) {
return;
}
_loadedView = true;
self.view.backgroundColor = _backgroundColor;
[self loadGL];
_wrapperView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_wrapperView];
_pageScrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
_pageScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
_pageScrollView.clipsToBounds = true;
_pageScrollView.opaque = true;
_pageScrollView.clearsContextBeforeDrawing = false;
[_pageScrollView setShowsHorizontalScrollIndicator:false];
[_pageScrollView setShowsVerticalScrollIndicator:false];
_pageScrollView.pagingEnabled = true;
_pageScrollView.contentSize = CGSizeMake(_headlines.count * self.view.bounds.size.width, self.view.bounds.size.height);
_pageScrollView.delegate = self;
[_wrapperView addSubview:_pageScrollView];
_pageViews = [NSMutableArray array];
for (NSUInteger i = 0; i < _headlines.count; i++)
{
RMIntroPageView *p = [[RMIntroPageView alloc]initWithFrame:CGRectMake(i * self.view.bounds.size.width, 0, self.view.bounds.size.width, 0) headline:[_headlines objectAtIndex:i] description:[_descriptions objectAtIndex:i] color:_primaryColor];
p.opaque = true;
p.clearsContextBeforeDrawing = false;
[_pageViews addObject:p];
[_pageScrollView addSubview:p];
}
[_pageScrollView setPage:0];
[self.view addSubview:_alternativeLanguageButton];
_pageControl = [[UIPageControl alloc] init];
_pageControl.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin;
_pageControl.userInteractionEnabled = false;
[_pageControl setNumberOfPages:6];
_pageControl.pageIndicatorTintColor = _regularDotColor;
_pageControl.currentPageIndicatorTintColor = _highlightedDotColor;
[_wrapperView addSubview:_pageControl];
}
- (UIView *)createAnimationSnapshot {
UIImage *image = _glkView.snapshot;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:_glkView.frame];
imageView.image = image;
return imageView;
}
- (UIView *)createTextSnapshot {
UIView *snapshotView = [_wrapperView snapshotViewAfterScreenUpdates:false];
snapshotView.frame = _wrapperView.frame;
return snapshotView;
}
- (BOOL)shouldAutorotate
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
return true;
return false;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
return UIInterfaceOrientationMaskAll;
return UIInterfaceOrientationMaskPortrait;
}
- (DeviceScreen)deviceScreen
{
CGSize viewSize = self.view.frame.size;
int max = (int)MAX(viewSize.width, viewSize.height);
DeviceScreen deviceScreen = Inch55;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
switch (max)
{
case 1366:
deviceScreen = iPadPro;
break;
default:
deviceScreen = iPad;
break;
}
}
else
{
switch (max)
{
case 480:
deviceScreen = Inch35;
break;
case 568:
deviceScreen = Inch4;
break;
case 667:
deviceScreen = Inch47;
break;
case 896:
deviceScreen = Inch65;
break;
default:
deviceScreen = Inch55;
break;
}
}
return deviceScreen;
}
- (void)updateLayout
{
UIInterfaceOrientation isVertical = (self.view.bounds.size.height / self.view.bounds.size.width > 1.0f);
CGFloat statusBarHeight = 0;
CGFloat pageControlY = 0;
CGFloat glViewY = 0;
CGFloat startButtonY = 0;
CGFloat pageY = 0;
CGFloat languageButtonSpread = 60.0f;
CGFloat languageButtonOffset = 26.0f;
DeviceScreen deviceScreen = [self deviceScreen];
switch (deviceScreen)
{
case iPad:
glViewY = isVertical ? 121 + 90 : 121;
startButtonY = 120;
pageY = isVertical ? 485 : 335;
pageControlY = pageY + 200.0f;
break;
case iPadPro:
glViewY = isVertical ? 221 + 110 : 221;
startButtonY = 120;
pageY = isVertical ? 605 : 435;
pageControlY = pageY + 200.0f;
break;
case Inch35:
pageControlY = 162 / 2;
glViewY = 62 - 20;
startButtonY = 75;
pageY = 215;
pageControlY = pageY + 160.0f;
if (!_alternativeLanguageButton.isHidden) {
glViewY -= 40.0f;
pageY -= 40.0f;
pageControlY -= 40.0f;
startButtonY -= 30.0f;
}
languageButtonSpread = 65.0f;
languageButtonOffset = 15.0f;
break;
case Inch4:
glViewY = 62;
startButtonY = 75;
pageY = 245;
pageControlY = pageY + 160.0f;
languageButtonSpread = 50.0f;
languageButtonOffset = 20.0f;
break;
case Inch47:
pageControlY = 162 / 2 + 10;
glViewY = 62 + 25;
startButtonY = 75 + 5;
pageY = 245 + 50;
pageControlY = pageY + 160.0f;
break;
case Inch55:
glViewY = 62 + 45;
startButtonY = 75 + 20;
pageY = 245 + 85;
pageControlY = pageY + 160.0f;
break;
case Inch65:
glViewY = 62 + 85;
startButtonY = 75 + 30;
pageY = 245 + 125;
pageControlY = pageY + 160.0f;
break;
default:
break;
}
if (!_alternativeLanguageButton.isHidden) {
startButtonY += languageButtonSpread;
}
_pageControl.frame = CGRectMake(0, pageControlY, self.view.bounds.size.width, 7);
_glkView.frame = CGRectChangedOriginY(_glkView.frame, glViewY - statusBarHeight);
CGFloat startButtonWidth = MIN(430.0 - 48.0, self.view.bounds.size.width - 48.0f);
UIView *startButton = self.createStartButton(startButtonWidth);
if (startButton.superview == nil) {
_startButton = startButton;
[self.view addSubview:startButton];
}
startButton.frame = CGRectMake(floor((self.view.bounds.size.width - startButtonWidth) / 2.0f), self.view.bounds.size.height - startButtonY - statusBarHeight, startButtonWidth, 50.0f);
_alternativeLanguageButton.frame = CGRectMake(floor((self.view.bounds.size.width - _alternativeLanguageButton.frame.size.width) / 2.0f), CGRectGetMaxY(startButton.frame) + languageButtonOffset, _alternativeLanguageButton.frame.size.width, _alternativeLanguageButton.frame.size.height);
_wrapperView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
_pageScrollView.frame=CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20);
_pageScrollView.contentSize=CGSizeMake(_headlines.count * self.view.bounds.size.width, 150);
_pageScrollView.contentOffset = CGPointMake(_currentPage * self.view.bounds.size.width, 0);
[_pageViews enumerateObjectsUsingBlock:^(UIView *pageView, NSUInteger index, __unused BOOL *stop) {
pageView.frame = CGRectMake(index * self.view.bounds.size.width, (pageY - statusBarHeight), self.view.bounds.size.width, 150);
}];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self loadGL];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[self freeGL];
}
- (void)startButtonPress
{
if (_startMessaging) {
_startMessaging();
}
}
- (void)updateAndRender
{
[_glkView display];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:_didEnterBackgroundObserver];
[[NSNotificationCenter defaultCenter] removeObserver:_willEnterBackgroundObserver];
[_localizationsDisposable dispose];
[self freeGL];
}
- (void)setupGL
{
[EAGLContext setCurrentContext:_glkView.context];
UIColor *color = _backgroundColor;
CGFloat red = 0.0f;
CGFloat green = 0.0f;
CGFloat blue = 0.0f;
if ([color getRed:&red green:&green blue:&blue alpha:NULL]) {
} else if ([color getWhite:&red alpha:NULL]) {
green = red;
blue = red;
}
set_intro_background_color(red, green, blue);
set_telegram_textures(setup_texture(@"telegram_sphere.png", color), setup_texture(@"telegram_plane1.png", color));
set_ic_textures(setup_texture(@"ic_bubble_dot.png", color), setup_texture(@"ic_bubble.png", color), setup_texture(@"ic_cam_lens.png", color), setup_texture(@"ic_cam.png", color), setup_texture(@"ic_pencil.png", color), setup_texture(@"ic_pin.png", color), setup_texture(@"ic_smile_eye.png", color), setup_texture(@"ic_smile.png", color), setup_texture(@"ic_videocam.png", color));
set_fast_textures(setup_texture(@"fast_body.png", color), setup_texture(@"fast_spiral.png", color), setup_texture(@"fast_arrow.png", color), setup_texture(@"fast_arrow_shadow.png", color));
set_free_textures(setup_texture(@"knot_up1.png", color), setup_texture(@"knot_down.png", color));
set_powerful_textures(setup_texture(@"powerful_mask.png", color), setup_texture(@"powerful_star.png", color), setup_texture(@"powerful_infinity.png", color), setup_texture(@"powerful_infinity_white.png", color));
set_private_textures(setup_texture(@"private_door.png", color), setup_texture(@"private_screw.png", color));
on_surface_created();
on_surface_changed(200, 200, 1, 0,0,0,0,0);
}
#pragma mark - GLKView delegate methods
- (void)glkView:(GLKView *)__unused view drawInRect:(CGRect)__unused rect
{
double time = CFAbsoluteTimeGetCurrent();
set_page((int)_currentPage);
set_date(time);
on_draw_frame();
}
static CGFloat x;
static bool justEndDragging;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)__unused decelerate
{
x = scrollView.contentOffset.x;
justEndDragging = true;
}
NSInteger _current_page_end;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offset = (scrollView.contentOffset.x - _currentPage * scrollView.frame.size.width) / self.view.frame.size.width;
set_scroll_offset((float)offset);
if (justEndDragging)
{
justEndDragging = false;
CGFloat page = scrollView.contentOffset.x / scrollView.frame.size.width;
CGFloat sign = scrollView.contentOffset.x - x;
if (sign > 0)
{
if (page > _currentPage)
_currentPage++;
}
if (sign < 0)
{
if (page < _currentPage)
_currentPage--;
}
_currentPage = MAX(0, MIN(5, _currentPage));
_current_page_end = _currentPage;
}
else
{
if (_pageScrollView.contentOffset.x > _current_page_end*_pageScrollView.frame.size.width)
{
if (_pageScrollView.currentPageMin > _current_page_end) {
_currentPage = [_pageScrollView currentPage];
_current_page_end = _currentPage;
}
}
else
{
if (_pageScrollView.currentPageMax < _current_page_end)
{
_currentPage = [_pageScrollView currentPage];
_current_page_end = _currentPage;
}
}
}
[_pageControl setCurrentPage:_currentPage];
}
- (void)alternativeLanguageButtonPressed {
if (_startMessagingInAlternativeLanguage && _alternativeLocalizationInfo.info.code.length != 0) {
_startMessagingInAlternativeLanguage(_alternativeLocalizationInfo.info.code);
}
}
- (void)setIsEnabled:(bool)isEnabled {
if (_isEnabled != isEnabled) {
_isEnabled = isEnabled;
_alternativeLanguageButton.alpha = _isEnabled ? 1.0 : 0.6;
}
}
@end
@implementation TGAvailableLocalization
- (instancetype)initWithTitle:(NSString *)title localizedTitle:(NSString *)localizedTitle code:(NSString *)code {
self = [super init];
if (self != nil) {
_title = title;
_localizedTitle = localizedTitle;
_code = code;
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
return [self initWithTitle:[aDecoder decodeObjectForKey:@"title"] localizedTitle:[aDecoder decodeObjectForKey:@"localizedTitle"] code:[aDecoder decodeObjectForKey:@"code"]];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_title forKey:@"title"];
[aCoder encodeObject:_localizedTitle forKey:@"localizedTitle"];
[aCoder encodeObject:_code forKey:@"code"];
}
@end
@implementation TGSuggestedLocalization
- (instancetype)initWithInfo:(TGAvailableLocalization *)info continueWithLanguageString:(NSString *)continueWithLanguageString chooseLanguageString:(NSString *)chooseLanguageString chooseLanguageOtherString:(NSString *)chooseLanguageOtherString englishLanguageNameString:(NSString *)englishLanguageNameString {
self = [super init];
if (self != nil) {
_info = info;
_continueWithLanguageString = continueWithLanguageString;
_chooseLanguageString = chooseLanguageString;
_chooseLanguageOtherString = chooseLanguageOtherString;
_englishLanguageNameString = englishLanguageNameString;
}
return self;
}
@end
#pragma clang diagnostic pop
Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

+2
View File
@@ -0,0 +1,2 @@
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
@@ -0,0 +1,14 @@
//
// texture_helper.h
// IntroOpenGL
//
// Created by Ilya Rimchikov on 11/03/14.
// Copyright (c) 2014 IntroOpenGL. All rights reserved.
//
#include "platform_gl.h"
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
GLuint setup_texture(NSString *fileName, UIColor *color);
@@ -0,0 +1,61 @@
//
// texture_helper.m
// IntroOpenGL
//
// Created by Ilya Rimchikov on 11/03/14.
// Copyright (c) 2014 Learn OpenGL ES. All rights reserved.
//
#include "texture_helper.h"
#import <UIKit/UIKit.h>
GLuint setup_texture(NSString *fileName, UIColor *color)
{
CGImageRef spriteImage = [[UIImage imageNamed:fileName] CGImage];
if (!spriteImage) {
NSLog(@"Failed to load image %@", fileName);
return -1;
}
// 2
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);
GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
// 3
if ([fileName isEqualToString:@"telegram_sphere.png"]) {
CGContextSetFillColorWithColor(spriteContext, color.CGColor);
CGContextFillRect(spriteContext, CGRectMake(0, 0, width, height));
}
CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
CGContextRelease(spriteContext);
// 4
GLuint texName;
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
// use linear filetring
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// clamp to edge
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
free(spriteData);
return texName;
}