Showing preview only (851K chars total). Download the full file or copy to clipboard to get everything.
Repository: Ciechan/Revolved
Branch: master
Commit: c817c1533519
Files: 288
Total size: 777.4 KB
Directory structure:
gitextract_ger1ifyu/
├── .gitignore
├── LICENSE
├── README.md
├── Revolved/
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── AxisVertex.h
│ ├── BCShader.h
│ ├── BCShader.m
│ ├── BCShader_SubclassHooks.h
│ ├── Camera.h
│ ├── Camera.m
│ ├── CameraController.h
│ ├── CameraController.m
│ ├── Color.h
│ ├── Constants.h
│ ├── DrawGestureRecognizer.h
│ ├── DrawGestureRecognizer.m
│ ├── Geometry.h
│ ├── Images.xcassets/
│ │ ├── AddFull.imageset/
│ │ │ └── Contents.json
│ │ ├── AddPlus.imageset/
│ │ │ └── Contents.json
│ │ ├── AddSemiCircle.imageset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── BackButton.imageset/
│ │ │ └── Contents.json
│ │ ├── Camera.imageset/
│ │ │ └── Contents.json
│ │ ├── CloneButton.imageset/
│ │ │ └── Contents.json
│ │ ├── ConfirmButton.imageset/
│ │ │ └── Contents.json
│ │ ├── CreditsButton.imageset/
│ │ │ └── Contents.json
│ │ ├── CreditsText.imageset/
│ │ │ └── Contents.json
│ │ ├── DeclineButton.imageset/
│ │ │ └── Contents.json
│ │ ├── Dots.imageset/
│ │ │ └── Contents.json
│ │ ├── DotsSelected.imageset/
│ │ │ └── Contents.json
│ │ ├── Empty.imageset/
│ │ │ └── Contents.json
│ │ ├── Facebook.imageset/
│ │ │ └── Contents.json
│ │ ├── Gear.imageset/
│ │ │ └── Contents.json
│ │ ├── LaunchImage.launchimage/
│ │ │ └── Contents.json
│ │ ├── Logo.imageset/
│ │ │ └── Contents.json
│ │ ├── MailButton.imageset/
│ │ │ └── Contents.json
│ │ ├── ObjFileIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── RateButton.imageset/
│ │ │ └── Contents.json
│ │ ├── ReviewBegger.imageset/
│ │ │ └── Contents.json
│ │ ├── RvlvdFileIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── Save.imageset/
│ │ │ └── Contents.json
│ │ ├── SegmentLimit.imageset/
│ │ │ └── Contents.json
│ │ ├── ShareButton.imageset/
│ │ │ └── Contents.json
│ │ ├── Stem.imageset/
│ │ │ └── Contents.json
│ │ ├── StlFileIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── TrashButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TrashCan.imageset/
│ │ │ └── Contents.json
│ │ ├── TrashLid.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialAxis.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialAxis3D.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialCloseButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialControlPoint.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialEndPoint.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialFinishButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialGetToKnow.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialHaveFun.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLine.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend1.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend3.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend5.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend7.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend9.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineLong.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialRevolvedBack.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialRevolvedFront.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialSegment1.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialSegment2.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialSegment3.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialWheel.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialiPadCamera.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialiPadHomeBlack.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialiPadHomeWhite.imageset/
│ │ │ └── Contents.json
│ │ └── Twitter.imageset/
│ │ └── Contents.json
│ ├── LineVertex.h
│ ├── MFMailComposeViewController+SendIfPossible.h
│ ├── MFMailComposeViewController+SendIfPossible.m
│ ├── NSArray+Functional.h
│ ├── NSArray+Functional.m
│ ├── NSError+RevolvedErrors.h
│ ├── NSError+RevolvedErrors.m
│ ├── NSMapTable+BlockEnumeration.h
│ ├── NSMapTable+BlockEnumeration.m
│ ├── NSMutableArray+MoveObject.h
│ ├── NSMutableArray+MoveObject.m
│ ├── NSMutableOrderedSet+MoveObject.h
│ ├── NSMutableOrderedSet+MoveObject.m
│ ├── PointVertex.h
│ ├── RVAddProgressView.h
│ ├── RVAddProgressView.m
│ ├── RVAnchorPoint.h
│ ├── RVAnchorPoint.m
│ ├── RVAnimation.h
│ ├── RVAnimation.m
│ ├── RVAnimation_Private.h
│ ├── RVAnimator.h
│ ├── RVAnimator.m
│ ├── RVAxisMeshController.h
│ ├── RVAxisMeshController.m
│ ├── RVAxisShader.fsh
│ ├── RVAxisShader.h
│ ├── RVAxisShader.m
│ ├── RVAxisShader.vsh
│ ├── RVAxisSprite.h
│ ├── RVAxisSprite.m
│ ├── RVBendTutorialPage.h
│ ├── RVBendTutorialPage.m
│ ├── RVBendTutorialPage.xib
│ ├── RVColorPicker.h
│ ├── RVColorPicker.m
│ ├── RVColorPickerButton.h
│ ├── RVColorPickerButton.m
│ ├── RVColorProvider.h
│ ├── RVColorProvider.m
│ ├── RVControlPoint.h
│ ├── RVControlPoint.m
│ ├── RVCreditsViewController.h
│ ├── RVCreditsViewController.m
│ ├── RVCreditsViewController.xib
│ ├── RVDeleteView.h
│ ├── RVDeleteView.m
│ ├── RVDrawController.h
│ ├── RVDrawController.m
│ ├── RVDrawViewController.h
│ ├── RVDrawViewController.m
│ ├── RVDrawViewController.xib
│ ├── RVDrawingTutorialPage.h
│ ├── RVDrawingTutorialPage.m
│ ├── RVDrawingTutorialPage.xib
│ ├── RVEndPoint.h
│ ├── RVEndPoint.m
│ ├── RVExportViewController.h
│ ├── RVExportViewController.m
│ ├── RVExportViewController.xib
│ ├── RVExporter.h
│ ├── RVExporter.m
│ ├── RVFinishTutorialPage.h
│ ├── RVFinishTutorialPage.m
│ ├── RVFinishTutorialPage.xib
│ ├── RVFloatAnimation.h
│ ├── RVFloatAnimation.m
│ ├── RVGuideline.h
│ ├── RVGuideline.m
│ ├── RVGuidelineDotSprite.h
│ ├── RVGuidelineDotSprite.m
│ ├── RVGuidlineDotMeshController.h
│ ├── RVGuidlineDotMeshController.m
│ ├── RVLineMeshController.h
│ ├── RVLineMeshController.m
│ ├── RVLineShader.fsh
│ ├── RVLineShader.h
│ ├── RVLineShader.m
│ ├── RVLineShader.vsh
│ ├── RVLineSprite.h
│ ├── RVLineSprite.m
│ ├── RVMeshController.h
│ ├── RVMeshController.m
│ ├── RVMeshController_Private.h
│ ├── RVModel.h
│ ├── RVModel.m
│ ├── RVModelButtonsView.h
│ ├── RVModelButtonsView.m
│ ├── RVModelButtonsView.xib
│ ├── RVModelCell.h
│ ├── RVModelCell.m
│ ├── RVModelManager.h
│ ├── RVModelManager.m
│ ├── RVModelMeshController.h
│ ├── RVModelMeshController.m
│ ├── RVModelMetadata.h
│ ├── RVModelMetadata.m
│ ├── RVModelSerializer.h
│ ├── RVModelSerializer.m
│ ├── RVModelShader.fsh
│ ├── RVModelShader.h
│ ├── RVModelShader.m
│ ├── RVModelShader.vsh
│ ├── RVModelSprite.h
│ ├── RVModelSprite.m
│ ├── RVModelViewController.h
│ ├── RVModelViewController.m
│ ├── RVModelViewController.xib
│ ├── RVModelsViewController.h
│ ├── RVModelsViewController.m
│ ├── RVModelsViewController.xib
│ ├── RVOBJExporter.h
│ ├── RVOBJExporter.m
│ ├── RVOpenGLView.h
│ ├── RVOpenGLView.m
│ ├── RVPassForwardView.h
│ ├── RVPassForwardView.m
│ ├── RVPictureViewController.h
│ ├── RVPictureViewController.m
│ ├── RVPictureViewController.xib
│ ├── RVPoint.h
│ ├── RVPoint.m
│ ├── RVPointMeshController.h
│ ├── RVPointMeshController.m
│ ├── RVPointShader.fsh
│ ├── RVPointShader.h
│ ├── RVPointShader.m
│ ├── RVPointShader.vsh
│ ├── RVPointSprite.h
│ ├── RVPointSprite.m
│ ├── RVPreviewViewController.h
│ ├── RVPreviewViewController.m
│ ├── RVPreviewViewController.xib
│ ├── RVQuaternionAnimation.h
│ ├── RVQuaternionAnimation.m
│ ├── RVRenderingController.h
│ ├── RVRenderingController.m
│ ├── RVRevolvedTutorialPage.h
│ ├── RVRevolvedTutorialPage.m
│ ├── RVRevolvedTutorialPage.xib
│ ├── RVRevolvedTutorialPageSolid.xib
│ ├── RVRootViewController.h
│ ├── RVRootViewController.m
│ ├── RVRootViewController.xib
│ ├── RVSTLExporter.h
│ ├── RVSTLExporter.m
│ ├── RVSegment.h
│ ├── RVSegment.m
│ ├── RVSegmentConnection.h
│ ├── RVSegmentConnection.m
│ ├── RVSegmentsTutorialPage.h
│ ├── RVSegmentsTutorialPage.m
│ ├── RVSegmentsTutorialPage.xib
│ ├── RVSelectTutorialPage.h
│ ├── RVSelectTutorialPage.m
│ ├── RVSelectTutorialPage.xib
│ ├── RVSettingsButtonsView.h
│ ├── RVSettingsButtonsView.m
│ ├── RVSettingsButtonsView.xib
│ ├── RVSpaceConverter.h
│ ├── RVSpaceConverter.m
│ ├── RVSprite.h
│ ├── RVSprite.m
│ ├── RVStartTutorialPage.h
│ ├── RVStartTutorialPage.m
│ ├── RVStartTutorialPage.xib
│ ├── RVTutorialLineImageView.h
│ ├── RVTutorialLineImageView.m
│ ├── RVTutorialPage.h
│ ├── RVTutorialPage.m
│ ├── RVTutorialScrollView.h
│ ├── RVTutorialScrollView.m
│ ├── RVTutorialViewController.h
│ ├── RVTutorialViewController.m
│ ├── RVTutorialViewController.xib
│ ├── RVUserDefaults.h
│ ├── RVUserDefaults.m
│ ├── RVVectorAnimation.h
│ ├── RVVectorAnimation.m
│ ├── Renderer.h
│ ├── Renderer.m
│ ├── Revolved-Info.plist
│ ├── Revolved-Prefix.pch
│ ├── SSZipArchive.h
│ ├── SSZipArchive.m
│ ├── SegmentEnd.h
│ ├── UIColor+RevolvedColors.h
│ ├── UIColor+RevolvedColors.m
│ ├── UIView+RotationAnimation.h
│ ├── UIView+RotationAnimation.m
│ ├── Vertex.h
│ ├── en.lproj/
│ │ └── InfoPlist.strings
│ ├── mail.txt
│ ├── main.m
│ ├── minizip/
│ │ ├── crypt.h
│ │ ├── ioapi.c
│ │ ├── ioapi.h
│ │ ├── mztools.c
│ │ ├── mztools.h
│ │ ├── unzip.c
│ │ ├── unzip.h
│ │ ├── zip.c
│ │ └── zip.h
│ ├── model1.rvlvd
│ ├── model2.rvlvd
│ └── model3.rvlvd
├── Revolved Tests/
│ ├── RVConnectionTests.m
│ ├── RVSerializerTests.m
│ ├── Revolved Tests-Info.plist
│ ├── Revolved Tests-Prefix.pch
│ └── en.lproj/
│ └── InfoPlist.strings
└── Revolved.xcodeproj/
├── project.pbxproj
└── project.xcworkspace/
└── contents.xcworkspacedata
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/
.DS_Store
================================================
FILE: LICENSE
================================================
Copyright (c) 2014, Bartosz Ciechanowski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.md
================================================
Revolved
========
This is the complete source code of [Revolved](http://revolvedapp.com) – the 3D modelling app for the iPad that I've developed last summer.

## Why?
There were many reasons for making Revolved open-sourced – [some internal](https://twitter.com/BCiechanowski/status/488649036250238977), [some external](https://twitter.com/BCiechanowski/status/487272741171908608), but it nonetheless feels like the perfect time to share the source code with the rest of the world. I strongly believe in giving back, as I've personally learned so much [from others](https://github.com/lemnar/Molecules).
Revolved is *no longer under development*, but I'd be more than happy if its source helped making your app better.
## Features
- OpenGL ES 2.0 based rendering integrated with UIKit
- custom animation engine
- a bit of private API hackery
The line drawing system has been [explained in details on my blog](http://ciechanowski.me/blog/2014/02/18/drawing-bezier-curves/).
## License
Revolved source code is released under the [BSD 3-Clause License](https://github.com/Ciechan/Revolved/blob/master/LICENSE). You're free to use/copy/rewrite whatever pieces of code you desire. However, this license **does not cover the image assets** – you can't reuse them in your app. While I don't care that much for the PNGs, this is intended to prevent blatant resubmission of Revolved to the AppStore without a slightest alteration.
## Contact
[Bartosz Ciechanowski](http://ciechanowski.me)
[@BCiechanowski](https://twitter.com/BCiechanowski)
================================================
FILE: Revolved/AppDelegate.h
================================================
//
// AppDelegate.h
// Revolved
//
// Created by Bartosz Ciechanowski on 03.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@class RVRootViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) RVRootViewController *viewController;
@end
================================================
FILE: Revolved/AppDelegate.m
================================================
//
// AppDelegate.m
// Revolved
//
// Created by Bartosz Ciechanowski on 03.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "AppDelegate.h"
#import "UIColor+RevolvedColors.h"
#import "RVModelViewController.h"
#import "RVRootViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[RVRootViewController alloc] init];
self.window.rootViewController = self.viewController;
self.window.backgroundColor = [UIColor rv_backgroundColor];
self.window.tintColor = [UIColor rv_tintColor];
[self.window makeKeyAndVisible];
NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
if (url != nil && [url isFileURL]) {
[self.viewController handleOpeningURL:url];
}
return YES;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if (url != nil && [url isFileURL]) {
[self.viewController handleOpeningURL:url];
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults] synchronize];
}
@end
================================================
FILE: Revolved/AxisVertex.h
================================================
//
// AxisVertex.h
// Revolved
//
// Created by Bartosz Ciechanowski on 02.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#ifndef Revolved_AxisVertex_h
#define Revolved_AxisVertex_h
typedef struct AxisVertex {
GLKVector3 p;
GLKVector4 color;
} AxisVertex;
#endif
================================================
FILE: Revolved/BCShader.h
================================================
//
// BCShader.h
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
typedef enum {
VertexAttribPosition,
VertexAttribNormal,
VertexAttribColor,
VertexAttribTexCoord,
VertexAttribAlpha,
} VertexAttrib;
#import <Foundation/Foundation.h>
@interface BCShader : NSObject
@property (nonatomic, readonly) GLuint program;
- (BOOL)loadProgram;
@end
================================================
FILE: Revolved/BCShader.m
================================================
//
// BCShader.m
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "BCShader.h"
@implementation BCShader
#pragma mark - OpenGL ES 2 shader compilation
- (BOOL)loadProgram
{
GLuint vertShader, fragShader;
NSString *vertShaderPathname, *fragShaderPathname;
_program = glCreateProgram();
vertShaderPathname = [[NSBundle mainBundle] pathForResource:[self shaderName] ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"Failed to compile vertex shader - %@", [self shaderName]);
return NO;
}
fragShaderPathname = [[NSBundle mainBundle] pathForResource:[self shaderName] ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
NSLog(@"Failed to compile fragment shader - %@", [self shaderName]);
return NO;
}
glAttachShader(_program, vertShader);
glAttachShader(_program, fragShader);
[self bindAttributeLocations];
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program %d for shader %@", _program, [self shaderName]);
if (vertShader) {
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
[self getUniformLocations];
if (vertShader) {
glDetachShader(_program, vertShader);
glDeleteShader(vertShader);
}
if (fragShader) {
glDetachShader(_program, fragShader);
glDeleteShader(fragShader);
}
return YES;
}
- (void)dealloc
{
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
}
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
GLint status;
const GLchar *source;
source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
if (!source) {
NSLog(@"Failed to load vertex shader");
return NO;
}
*shader = glCreateShader(type);
glShaderSource(*shader, 1, &source, NULL);
glCompileShader(*shader);
#if defined(DEBUG)
GLint logLength;
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status == 0) {
glDeleteShader(*shader);
return NO;
}
return YES;
}
- (BOOL)linkProgram:(GLuint)prog
{
GLint status;
glLinkProgram(prog);
#if defined(DEBUG)
GLint logLength;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program link log:\n%s", log);
free(log);
}
#endif
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == 0) {
return NO;
}
return YES;
}
- (BOOL)validateProgram:(GLuint)prog
{
GLint logLength, status;
glValidateProgram(prog);
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
if (status == 0) {
return NO;
}
return YES;
}
#pragma mark - Abstract
- (void)bindAttributeLocations
{
NSAssert(0, @"Abstract method, implement in subclass");
}
- (void)getUniformLocations
{
NSAssert(0, @"Abstract method, implement in subclass");
}
- (NSString *)shaderName
{
NSAssert(0, @"Abstract method, implement in subclass");
return nil;
}
@end
================================================
FILE: Revolved/BCShader_SubclassHooks.h
================================================
//
// BCShader_SubclassHooks.h
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
@interface BCShader ()
- (void)bindAttributeLocations;
- (void)getUniformLocations;
- (NSString *)shaderName;
@end
================================================
FILE: Revolved/Camera.h
================================================
//
// BCCamera.h
// Patterns
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <GLKit/GLKit.h>
@interface Camera : NSObject
//@property (nonatomic) GLKQuaternion rotation;
@property (nonatomic) float distance;
@property (nonatomic) float aspect;
@property (nonatomic) GLKVector3 sceneTranslation;
@property (nonatomic, readonly) GLKMatrix4 viewMatrix;
@property (nonatomic, readonly) GLKMatrix4 viewProjectionMatrix;
//@property (nonatomic, readonly) GLKMatrix4 rotationMatrix;
@property (nonatomic, readonly) GLKMatrix4 projectionMatrix;
- (void)updateMatrices;
@end
================================================
FILE: Revolved/Camera.m
================================================
//
// Camera.m
// Patterns
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "Camera.h"
@implementation Camera
- (id)init
{
self = [super init];
if (self) {
_distance = 2.0;
_aspect = 1.0;
}
return self;
}
- (void)updateMatrices
{
GLKMatrix4 distanceTranslation = GLKMatrix4MakeTranslation(0, 0, -_distance);
GLKMatrix4 sceneTranslation = GLKMatrix4MakeTranslation(_sceneTranslation.x, _sceneTranslation.y, _sceneTranslation.z);
_viewMatrix = GLKMatrix4Multiply(sceneTranslation, distanceTranslation);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(M_PI/7.0, _aspect, 11.15, 18.05);
_projectionMatrix = projectionMatrix;
_viewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, _viewMatrix);
}
@end
================================================
FILE: Revolved/CameraController.h
================================================
//
// CameraController.h
// Patterns
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@class Camera;
@interface CameraController : NSObject
@property (nonatomic) CGSize renderSurfaceSize;
@property (nonatomic, readonly) GLKQuaternion quaternion;
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *panRecognizer;
@property (nonatomic, strong, readonly) UIRotationGestureRecognizer *rotationRecognizer;
- (void)resetPosition;
- (void)stop;
- (void)displayTick;
- (void)animateToStartPositionWithDuration:(NSTimeInterval)duration;
@end
================================================
FILE: Revolved/CameraController.m
================================================
//
// CameraController.m
// Patterns
//
// Created by Bartosz Ciechanowski on 23.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "CameraController.h"
#import "Camera.h"
#import "RVQuaternionAnimation.h"
#import "RVAnimator.h"
static const float DeaccelerationFactor = 0.96;
static const float ThresholdScreenPanVelocity = 100.0f;
static const float ThresholdScreenRotationVelocity = 1.0f;
static const float RotationVelocityToAngularScale = 0.01f;
static const float PanVelocityToAngularScale = 0.00007f;
static const GLKQuaternion IdentityQuaternion = {0.0f, 0.0f, 0.0f, 1.0f};
typedef NS_ENUM(NSInteger, CameraControllerState) {
CameraControllerStatePassive,
CameraControllerStatePanning,
CameraControllerStateRotating,
CameraControllerStateInertia
};
@interface CameraController() <UIGestureRecognizerDelegate>
@property (nonatomic) CameraControllerState state;
@property (nonatomic) GLKQuaternion startQuaternion;
@property (nonatomic) GLKQuaternion panQuaternion;
@property (nonatomic) GLKQuaternion rotationQuaternion;
@property (nonatomic) GLKVector3 panStartPoint;
@property (nonatomic) NSUInteger previousNumberOfPanTouches;
@property (nonatomic) float currentRotation;
@property (nonatomic) float previousRotation;
@property (nonatomic) GLKVector3 inertiaAxis;
@property (nonatomic) float inertiaVelocity;
@property (nonatomic) float inertiaAngle;
@property (nonatomic) float extraSlowdownFactor;
@property (nonatomic) float panInertiaVelocity;
@property (nonatomic) GLKVector3 panInertiaAxis;
@property (nonatomic) float rotationInertiaVelocity;
@property (nonatomic) GLKVector3 rotationInertiaAxis;
@end
@implementation CameraController
- (id)init
{
self = [super init];
if (self)
{
_panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
_panRecognizer.delegate = self;
_panRecognizer.cancelsTouchesInView = NO;
_rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotate:)];
_rotationRecognizer.delegate = self;
_rotationRecognizer.cancelsTouchesInView = NO;
[self resetPosition];
[self displayTick];
}
return self;
}
- (void)setState:(CameraControllerState)state
{
if (state == _state) {
return;
}
_state = state;
if (state != CameraControllerStatePanning) {
[self resetPanQuaternion];
}
if (state != CameraControllerStateRotating) {
[self resetRotationQuaternion];
}
}
- (void)resetPanQuaternion
{
_startQuaternion = GLKQuaternionMultiply(_panQuaternion, _startQuaternion);
_panQuaternion = GLKQuaternionIdentity;
}
- (void)resetRotationQuaternion
{
_startQuaternion = GLKQuaternionMultiply(_rotationQuaternion, _startQuaternion);
_rotationQuaternion = IdentityQuaternion;
_previousRotation = _currentRotation;
}
#pragma mark - Gesture Recognizers
- (void)pan:(UIPanGestureRecognizer *)sender
{
CGPoint viewPoint = [sender locationInView:sender.view];
CGPoint viewVelocity = [sender velocityInView:sender.view];
switch (sender.state) {
case UIGestureRecognizerStateBegan:
[self beginPanAtPoint:[self pointToSphere:viewPoint]];
_previousNumberOfPanTouches = 1;
break;
case UIGestureRecognizerStateChanged:
[self continuePanAtPoint:[self pointToSphere:viewPoint] withNumberOfTouches:sender.numberOfTouches];
_previousNumberOfPanTouches = sender.numberOfTouches;
break;
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded:
[self endPanWithVelocity:[self angularVelocityForScreenVelocty:viewVelocity atScreenPoint:viewPoint]];
break;
default:
break;
}
}
- (void)rotate:(UIRotationGestureRecognizer *)sender
{
CGFloat rotation = sender.rotation;
CGFloat velocity = sender.velocity;
switch (sender.state) {
case UIGestureRecognizerStateBegan:
[self beginRotation:rotation];
break;
case UIGestureRecognizerStateChanged:
[self continueRotation:rotation withNumberOfTouches:sender.numberOfTouches];
break;
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded:
[self endRotation:rotation withVelocity:velocity];
break;
default:
break;
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return touch.view == gestureRecognizer.view;
}
#pragma mark - Pan
- (void)beginPanAtPoint:(GLKVector3)point
{
[self resetInertia];
_panStartPoint = point;
_panQuaternion = IdentityQuaternion;
if (_state != CameraControllerStateRotating) {
_state = CameraControllerStatePanning;
}
}
- (void)continuePanAtPoint:(GLKVector3)point withNumberOfTouches:(NSUInteger)numberOfTouches
{
if (numberOfTouches > 1 && _previousNumberOfPanTouches == 1) {
[self resetRotationQuaternion];
}
if (numberOfTouches > 1) {
return;
}
if (numberOfTouches == 1 && _previousNumberOfPanTouches > 1) {
self.panStartPoint = point;
}
if (_state == CameraControllerStateRotating) {
self.state = CameraControllerStatePanning;
self.panStartPoint = point;
}
GLKVector3 panEndPoint = point;
_panQuaternion = [self quaternionFromStartPoint:_panStartPoint toEndPoint:panEndPoint];
}
- (void)endPanWithVelocity:(GLKVector3)velocity
{
float length = GLKVector3Length(velocity);
_panInertiaAxis = GLKVector3MultiplyScalar(velocity, 1.0/length);
_panInertiaVelocity = length;
[self resolveInertia];
}
#pragma mark - Rotation
- (void)beginRotation:(CGFloat)rotation
{
[self resetInertia];
_previousRotation = 0.0f;
if (_state == CameraControllerStatePassive) {
self.state = CameraControllerStateRotating;
}
}
- (void)continueRotation:(CGFloat)rotation withNumberOfTouches:(NSUInteger)touches
{
if (touches == 2) {
if (_state == CameraControllerStatePanning) {
self.state = CameraControllerStateRotating;
}
_currentRotation = rotation;
_rotationQuaternion = GLKQuaternionMakeWithAngleAndAxis(rotation - _previousRotation, 0, 0, -1);
} else {
if (_state == CameraControllerStateRotating) {
self.state = CameraControllerStatePanning;
}
}
}
- (void)endRotation:(CGFloat)rotation withVelocity:(CGFloat)velocity
{
float absVelocity = fabsf(velocity);
_rotationInertiaAxis = GLKVector3Make(0.0f, 0.0f, -1.0f);
_rotationInertiaVelocity = (absVelocity > ThresholdScreenRotationVelocity ? velocity : 0.0) * RotationVelocityToAngularScale;
[self resolveInertia];
}
- (void)resolveInertia
{
if (_rotationInertiaVelocity != 0.0f) {
_inertiaAxis = _rotationInertiaAxis;
_inertiaVelocity = _rotationInertiaVelocity;
} else if (_panInertiaVelocity > 0.0f) {
_inertiaAxis = _panInertiaAxis;
_inertiaVelocity = _panInertiaVelocity;
}
self.state = CameraControllerStatePassive;
}
- (void)displayTick
{
_inertiaVelocity *= DeaccelerationFactor * _extraSlowdownFactor;
_inertiaAngle += _inertiaVelocity;
GLKQuaternion intertiaQuaternion = GLKQuaternionMakeWithAngleAndVector3Axis(_inertiaAngle, _inertiaAxis);
GLKQuaternion q = GLKQuaternionMultiply(GLKQuaternionMultiply(intertiaQuaternion, _rotationQuaternion),
GLKQuaternionMultiply(_panQuaternion, _startQuaternion));
_quaternion = q;
}
- (void)resetInertia
{
GLKQuaternion intertiaQuaternion = GLKQuaternionMakeWithAngleAndVector3Axis(_inertiaAngle, _inertiaAxis);
_startQuaternion = GLKQuaternionMultiply(intertiaQuaternion, _startQuaternion);
_inertiaAxis = GLKVector3Make(1.0f, 0.0f, 0.0f);
_inertiaAngle = 0.0f;
_inertiaVelocity = 0.0f;
_extraSlowdownFactor = 1.0f;
_panInertiaVelocity = 0.0f;
_rotationInertiaVelocity = 0.0f;
if (_state == CameraControllerStateInertia) {
self.state = CameraControllerStatePassive;
}
}
- (void)stop
{
_extraSlowdownFactor = 0.65;
}
- (void)resetPosition
{
_startQuaternion = BaseQuaternion;
_panQuaternion = GLKQuaternionIdentity;
_rotationQuaternion = GLKQuaternionIdentity;;
_inertiaAngle = 0.0f;
[self resetInertia];
[self displayTick];
}
- (GLKQuaternion)quaternionFromStartPoint:(GLKVector3)start toEndPoint:(GLKVector3)end
{
const float epsilon = 0.00001;
GLKVector3 cross = GLKVector3CrossProduct(start, end);
float length = GLKVector3Length(cross);
if (length < epsilon) {
return GLKQuaternionIdentity;
} else {
GLKVector3 axis = GLKVector3MultiplyScalar(cross, 1.0/length);
float angle = 2.0 * acosf(GLKVector3DotProduct(start, end));
return GLKQuaternionMakeWithAngleAndVector3Axis(angle, axis);
}
}
#pragma mark - Trackball
- (GLKVector3)normalizedScreenVectorFromPoint:(CGPoint)point
{
CGSize surfaceSize = self.renderSurfaceSize;
GLKVector3 vector = GLKVector3Make(point.x - surfaceSize.width/2.0, surfaceSize.height/2.0 - point.y, 0.0f);
return GLKVector3MultiplyScalar(vector, 2.0f/(MAX(surfaceSize.width, surfaceSize.height)));
}
- (GLKVector3)pointToSphere:(CGPoint)pointOnScreen
{
GLKVector3 point = [self normalizedScreenVectorFromPoint:pointOnScreen];
CGFloat length = point.x*point.x + point.y*point.y;
CGFloat radius = 1.0f;
if (length > radius * radius / 2.0f) {
point.z = (radius * radius / 2.0) / sqrtf(length);
} else {
point.z = sqrtf(radius * radius - length);
}
return GLKVector3Normalize(point);
}
- (GLKVector3)angularVelocityForScreenVelocty:(CGPoint)screenVelocity atScreenPoint:(CGPoint)screenPoint
{
CGFloat length = sqrtf(screenVelocity.x * screenVelocity.x + screenVelocity.y * screenVelocity.y);
if (length < ThresholdScreenPanVelocity) {
return GLKVector3Make(0.0f, 0.0f, 0.0f);
}
CGPoint endPoint = CGPointMake(screenPoint.x + screenVelocity.x/length, screenPoint.y + screenVelocity.y/length);
GLKVector3 start = [self pointToSphere:screenPoint];
GLKVector3 end = [self pointToSphere:endPoint];
GLKVector3 axis = GLKVector3Normalize(GLKVector3CrossProduct(start, end));
return GLKVector3MultiplyScalar(axis, length * PanVelocityToAngularScale);
}
#pragma mark - Animation
- (void)animateToStartPositionWithDuration:(NSTimeInterval)duration
{
self.state = CameraControllerStatePassive;
[self resetInertia];
RVQuaternionAnimation *animation = [RVQuaternionAnimation quaternionAnimationFromValue:self.startQuaternion toValue:BaseQuaternion withDuration:duration];
[[RVAnimator sharedAnimator] addAnimation:animation forKey:@"startQuaternion" toTarget:self];
}
@end
================================================
FILE: Revolved/Color.h
================================================
//
// Color.h
// Revolved
//
// Created by Bartosz Ciechanowski on 03.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#ifndef Revolved_Color_h
#define Revolved_Color_h
typedef struct Color {
unsigned char r, g, b;
} Color;
static inline GLKVector3 colorToGLKVector3(Color color)
{
return GLKVector3Make(color.r / 255.0, color.g / 255.0, color.b / 255.0);
}
static inline Color colorWithRGB(char red, char green, char blue)
{
return (Color){red, green, blue};
}
static inline Color colorWithHexColor(NSUInteger hexColor)
{
return colorWithRGB((hexColor & 0xFF0000) >> 16,
(hexColor & 0x00FF00) >> 8,
(hexColor & 0x0000FF) >> 0);
}
#endif
================================================
FILE: Revolved/Constants.h
================================================
//
// Constants.h
// Revolved
//
// Created by Bartosz Ciechanowski on 05.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#ifndef Revolved_Constants_h
#define Revolved_Constants_h
static const NSUInteger Spans = 14;
static const NSUInteger StripesPerSpan = 4;
static const NSUInteger SegmentLimit = 60;
#endif
================================================
FILE: Revolved/DrawGestureRecognizer.h
================================================
//
// DrawGestureRecognizer.h
// Revolved
//
// Created by Bartosz Ciechanowski on 07.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface DrawGestureRecognizer : UIPanGestureRecognizer
- (CGPoint)firstTouchLocationInView:(UIView *)view;
@end
================================================
FILE: Revolved/DrawGestureRecognizer.m
================================================
//
// DrawGestureRecognizer.m
// Revolved
//
// Created by Bartosz Ciechanowski on 07.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIGestureRecognizerSubclass.h>
#import "DrawGestureRecognizer.h"
@interface DrawGestureRecognizer()
@property (nonatomic, strong) UITouch *firstTouch;
@property (nonatomic) CGPoint firstTouchLocation;
@end
@implementation DrawGestureRecognizer
- (CGPoint)firstTouchLocationInView:(UIView *)view
{
return [self.view convertPoint:self.firstTouchLocation toView:view];
}
- (void)reset
{
[super reset];
self.firstTouch = nil;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (self.numberOfTouches > 0) {
return;
}
if (touches.count > 1) {
touches = [NSSet setWithObject:[touches anyObject]];
}
[super touchesBegan:touches withEvent:event];
self.firstTouch = [touches anyObject];
self.firstTouchLocation = [self.firstTouch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (![touches containsObject:self.firstTouch]) {
return;
}
touches = [NSSet setWithObject:self.firstTouch];
[super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (![touches containsObject:self.firstTouch]) {
return;
}
touches = [NSSet setWithObject:self.firstTouch];
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
if (![touches containsObject:self.firstTouch]) {
return;
}
touches = [NSSet setWithObject:self.firstTouch];
[super touchesCancelled:touches withEvent:event];
}
@end
================================================
FILE: Revolved/Geometry.h
================================================
//
// Geometry.h
// Revolved
//
// Created by Bartosz Ciechanowski on 10.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#ifndef Revolved_Geometry_h
#define Revolved_Geometry_h
static inline float GLKVector2DistanceSq(GLKVector2 vectorStart, GLKVector2 vectorEnd)
{
GLKVector2 diff = GLKVector2Subtract(vectorEnd, vectorStart);
return GLKVector2DotProduct(diff, diff);
}
static inline float SquareDistancePointSegment(GLKVector2 a, GLKVector2 b, GLKVector2 c)
{
GLKVector2 ab = GLKVector2Subtract(b, a);
GLKVector2 ac = GLKVector2Subtract(c, a);
float e = GLKVector2DotProduct(ac, ab);
if (e <= 0.0f) {
return GLKVector2DotProduct(ac, ac);
}
GLKVector2 bc = GLKVector2Subtract(c, b);
float f = GLKVector2DotProduct(ab, ab);
if (e >= f) {
return GLKVector2DotProduct(bc, bc);
}
return GLKVector2DotProduct(ac, ac) - e * e / f;
}
// given segment ab and point c, computes closest point d on ab
// returns UNCLAMPPED value of t
static inline GLKVector2 ClosestPointOnSegmentForPoint(GLKVector2 a, GLKVector2 b, GLKVector2 c, float *t)
{
GLKVector2 ab = GLKVector2Subtract(b, a);
GLKVector2 ac = GLKVector2Subtract(c, a);
float realT = GLKVector2DotProduct(ac, ab) / GLKVector2DotProduct(ab, ab);
*t = realT;
return GLKVector2Add(a, GLKVector2MultiplyScalar(ab, realT));
}
#endif
================================================
FILE: Revolved/Images.xcassets/AddFull.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "AddFull.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "AddFull@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/AddPlus.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "AddPlus.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "AddPlus@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/AddSemiCircle.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "AddSemiCircle.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "AddSemiCircle@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "50x50",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "50x50",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "72x72",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "72x72",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/BackButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "BackButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "BackButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Camera.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Camera.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Camera@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/CloneButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "CloneButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "CloneButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/ConfirmButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "ConfirmButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "ConfirmButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/CreditsButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "CreditsButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "CreditsButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/CreditsText.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "CreditsText.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "CreditsText@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/DeclineButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "DeclineButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "DeclineButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Dots.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Dots.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Dots@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/DotsSelected.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "DotsSelected.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "DotsSelected@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Empty.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Empty.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Empty@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Facebook.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Facebook.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Facebook@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Gear.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Gear.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Gear@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/LaunchImage.launchimage/Contents.json
================================================
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"filename" : "Default.png",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"filename" : "Default@2x.png",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "to-status-bar",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "to-status-bar",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "to-status-bar",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "to-status-bar",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Logo.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Logo.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Logo@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/MailButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "MailButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "MailButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/ObjFileIcon.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "ObjFileIcon.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "ObjFileIcon@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/RateButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "RateButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "RateButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/ReviewBegger.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "ReviewBegger.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "ReviewBegger@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/RvlvdFileIcon.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "RvlvdFileIcon.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "RvlvdFileIcon@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Save.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Save.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Save@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/SegmentLimit.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "SegmentLimit.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "SegmentLimit@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/ShareButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "ShareButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "ShareButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Stem.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Stem.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Stem@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/StlFileIcon.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "StlFileIcon.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "StlFileIcon@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TrashButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TrashButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TrashButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TrashCan.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TrashCan.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TrashCan@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TrashLid.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TrashLid.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TrashLid@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialAxis.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialAxis.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialAxis3D.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialAxis3D.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TutorialButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialCloseButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialCloseButtong.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TutorialCloseButtong@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialControlPoint.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialControlPoint.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialEndPoint.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialEndPoint.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialFinishButton.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialFinishButton.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TutorialFinishButton@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialGetToKnow.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialGetToKnow.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TutorialGetToKnow@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialHaveFun.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialHaveFun.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "TutorialHaveFun@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLine.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLine.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLineBend1.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLineBend1.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLineBend3.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLineBend3.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLineBend5.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLineBend5.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLineBend7.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLineBend7.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLineBend9.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLineBend9.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialLineLong.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialLineLong.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialRevolvedBack.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialRevolvedBack.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialRevolvedFront.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialRevolvedFront.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialSegment1.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialSegment1.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialSegment2.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialSegment2.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialSegment3.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialSegment3.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialWheel.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialWheel.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialiPadCamera.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialiPadCamera.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialiPadHomeBlack.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialiPadHomeBlack.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/TutorialiPadHomeWhite.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "TutorialiPadHomeWhite.png"
},
{
"idiom" : "universal",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/Images.xcassets/Twitter.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Twitter.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Twitter@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Revolved/LineVertex.h
================================================
//
// LineVertex.h
// Revolved
//
// Created by Bartosz Ciechanowski on 07.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#ifndef Revolved_LineVertex_h
#define Revolved_LineVertex_h
typedef struct LineVertex {
GLKVector2 p;
GLKVector3 color;
} LineVertex;
#endif
================================================
FILE: Revolved/MFMailComposeViewController+SendIfPossible.h
================================================
//
// MFMailComposeViewController+SendIfPossible.h
// Revolved
//
// Created by Bartosz Ciechanowski on 24.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <MessageUI/MessageUI.h>
@interface MFMailComposeViewController (SendIfPossible)
+ (BOOL)rv_canSendEmailIfNotShowAlert;
+ (void)rv_showDefaultFailAlertWithError:(NSError *)error;
@end
================================================
FILE: Revolved/MFMailComposeViewController+SendIfPossible.m
================================================
//
// MFMailComposeViewController+SendIfPossible.m
// Revolved
//
// Created by Bartosz Ciechanowski on 24.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "MFMailComposeViewController+SendIfPossible.h"
@implementation MFMailComposeViewController (SendIfPossible)
+ (BOOL)rv_canSendEmailIfNotShowAlert
{
if ([self canSendMail]) {
return YES;
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error sending e-mail"
message:@"Your iPad doesn't have an e-mail account setup"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
return NO;
}
+ (void)rv_showDefaultFailAlertWithError:(NSError *)error
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error sending e-mail"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
@end
================================================
FILE: Revolved/NSArray+Functional.h
================================================
//
// NSArray+Functional.h
// Ico
//
// Created by Bartosz Ciechanowski on 21.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSArray (Functional)
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block;
- (NSArray *)filterObjectsUsingBlock:(BOOL (^)(id obj, NSUInteger idx))block;
@end
================================================
FILE: Revolved/NSArray+Functional.m
================================================
//
// NSArray+Functional.m
// Ico
//
// Created by Bartosz Ciechanowski on 21.07.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "NSArray+Functional.h"
@implementation NSArray (Functional)
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[result addObject:block(obj, idx)];
}];
return [result copy];
}
- (NSArray *)filterObjectsUsingBlock:(BOOL (^)(id obj, NSUInteger idx))block
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (block(obj, idx)) {
[result addObject:obj];
}
}];
return [result copy];
}
@end
================================================
FILE: Revolved/NSError+RevolvedErrors.h
================================================
//
// NSError+RevolvedErrors.h
// Revolved
//
// Created by Bartosz Ciechanowski on 01.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSError (RevolvedErrors)
+ (NSError *)malformedFileError;
+ (NSError *)obsoleteAppVersionError;
@end
================================================
FILE: Revolved/NSError+RevolvedErrors.m
================================================
//
// NSError+RevolvedErrors.m
// Revolved
//
// Created by Bartosz Ciechanowski on 01.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "NSError+RevolvedErrors.h"
static NSString * const ErrorDomain = @"com.bartoszciechanowski.revolved";
@implementation NSError (RevolvedErrors)
+ (NSError *)malformedFileError
{
return [NSError errorWithDomain:ErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"The model you're trying to import seems to be malformed"}];
}
+ (NSError *)obsoleteAppVersionError
{
return [NSError errorWithDomain:ErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"You need to update Revolved in the AppStore to import this model"}];
}
@end
================================================
FILE: Revolved/NSMapTable+BlockEnumeration.h
================================================
//
// NSMapTable+BlockEnumeration.h
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMapTable (BlockEnumeration)
- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block;
@end
================================================
FILE: Revolved/NSMapTable+BlockEnumeration.m
================================================
//
// NSMapTable+BlockEnumeration.m
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "NSMapTable+BlockEnumeration.h"
@implementation NSMapTable (BlockEnumeration)
- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block
{
BOOL stop = NO;
for (id key in self) {
block(key, [self objectForKey:key], &stop);
if (stop) {
return;
}
}
}
@end
================================================
FILE: Revolved/NSMutableArray+MoveObject.h
================================================
//
// NSMutableArray+MoveObject.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMutableArray (MoveObject)
- (void)moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex;
@end
================================================
FILE: Revolved/NSMutableArray+MoveObject.m
================================================
//
// NSMutableArray+MoveObject.m
// Revolved
//
// Created by Bartosz Ciechanowski on 15.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "NSMutableArray+MoveObject.h"
@implementation NSMutableArray (MoveObject)
- (void)moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
{
id object = [self objectAtIndex:fromIndex];
[self removeObjectAtIndex:fromIndex];
[self insertObject:object atIndex:toIndex];
}
@end
================================================
FILE: Revolved/NSMutableOrderedSet+MoveObject.h
================================================
//
// NSMutableOrderedSet+MoveObject.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMutableOrderedSet (MoveObject)
- (void)moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex;
@end
================================================
FILE: Revolved/NSMutableOrderedSet+MoveObject.m
================================================
//
// NSMutableOrderedSet+MoveObject.m
// Revolved
//
// Created by Bartosz Ciechanowski on 15.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "NSMutableOrderedSet+MoveObject.h"
@implementation NSMutableOrderedSet (MoveObject)
- (void)moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
{
id object = [self objectAtIndex:fromIndex];
[self removeObjectAtIndex:fromIndex];
[self insertObject:object atIndex:toIndex];
}
@end
================================================
FILE: Revolved/PointVertex.h
================================================
//
// PointVertex.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#ifndef Revolved_PointVertex_h
#define Revolved_PointVertex_h
typedef struct PointVertex {
GLKVector2 p;
GLKVector2 uv;
float alpha;
} PointVertex;
#endif
================================================
FILE: Revolved/RVAddProgressView.h
================================================
//
// RVAddProgressView.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RVAddProgressView : UIView
@property (nonatomic, strong, readonly) UIButton *plus;
@property (nonatomic) float progress;
- (void)setProgress:(float)progress allowingFull:(BOOL)allowFull;
@end
================================================
FILE: Revolved/RVAddProgressView.m
================================================
//
// RVAddProgressView.m
// Revolved
//
// Created by Bartosz Ciechanowski on 15.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAddProgressView.h"
#import <QuartzCore/QuartzCore.h>
@interface RVAddProgressView()
@property (nonatomic, strong) UIView *firstContainer;
@property (nonatomic, strong) UIView *secondContainer;
@property (nonatomic, strong) UIImageView *firstSemiCircle;
@property (nonatomic, strong) UIImageView *secondSemiCircle;
@property (nonatomic, strong, readwrite) UIButton *plus;
@property (nonatomic, strong) UIImageView *plusFull;
@end
@implementation RVAddProgressView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit
{
self.backgroundColor = [UIColor clearColor];
_firstContainer = [[UIView alloc] init];
_firstContainer.clipsToBounds = YES;
_firstContainer.backgroundColor = [UIColor clearColor];
_firstContainer.userInteractionEnabled = NO;
_secondContainer = [[UIView alloc] init];
_secondContainer.clipsToBounds = YES;
_secondContainer.backgroundColor = [UIColor clearColor];
_secondContainer.userInteractionEnabled = NO;
_firstSemiCircle = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"AddSemiCircle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
_firstSemiCircle.layer.anchorPoint = CGPointMake(0.0f, 0.5f);
_secondSemiCircle = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"AddSemiCircle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
_secondSemiCircle.layer.anchorPoint = CGPointMake(0.0f, 0.5f);
_plus = [UIButton buttonWithType:UIButtonTypeSystem];
_plus.bounds = CGRectMake(0, 0, 44.0f, 44.0f);
_plus.exclusiveTouch = YES;
[_plus setImage:[UIImage imageNamed:@"AddPlus"] forState:UIControlStateNormal];
_plusFull = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"AddFull"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
_plusFull.alpha = 0.0f;
[self addSubview:_firstContainer];
[self addSubview:_secondContainer];
[self addSubview:_plus];
[self addSubview:_plusFull];
[_firstContainer addSubview:_firstSemiCircle];
[_secondContainer addSubview:_secondSemiCircle];
[self setProgress:0.0f];
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect bounds = self.bounds;
CGRect leftFrame, rightFrame;
CGRectDivide(bounds, &rightFrame, &leftFrame, bounds.size.width/2.0f, CGRectMaxXEdge);
_firstContainer.frame = rightFrame;
_secondContainer.frame = leftFrame;
_firstSemiCircle.center = CGPointMake(0.0, rightFrame.size.height/2.0);
_secondSemiCircle.center = CGPointMake(leftFrame.size.width, leftFrame.size.height/2.0);
_plus.center = CGPointMake(bounds.size.width/2.0, bounds.size.height/2.0);
_plusFull.center = CGPointMake(bounds.size.width/2.0, bounds.size.height/2.0);
}
- (void)setProgress:(float)progress
{
[self setProgress:progress allowingFull:NO];
}
- (void)setProgress:(float)progress allowingFull:(BOOL)allowFull
{
progress = MIN(MAX(0.0f, progress), 1.0f);
_firstSemiCircle.transform = CGAffineTransformMakeRotation(M_PI + 2.0f * M_PI * MIN(progress, 0.5f));
_secondSemiCircle.transform = CGAffineTransformMakeRotation(M_PI * 2.0f * MAX(progress - 0.5f, 0.0f));
if (progress == 1.0f && _progress < 1.0f && allowFull) {
[UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
_plus.alpha = 0.0f;
_firstContainer.alpha = 0.0f;
_secondContainer.alpha = 0.0f;
_plusFull.alpha = 1.0f;
} completion:NULL];
} else if (_progress == 1.0f && progress < 1.0f) {
[UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
_plus.alpha = 1.0f;
_firstContainer.alpha = 1.0f;
_secondContainer.alpha = 1.0f;
_plusFull.alpha = 0.0f;
} completion:NULL];
}
_progress = progress;
}
@end
================================================
FILE: Revolved/RVAnchorPoint.h
================================================
//
// RVAnchorPoint.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVPoint.h"
@interface RVAnchorPoint : RVPoint
@property (nonatomic) BOOL hasControlPoint;
@end
================================================
FILE: Revolved/RVAnchorPoint.m
================================================
//
// RVAnchorPoint.m
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAnchorPoint.h"
@implementation RVAnchorPoint
- (PointType)type
{
return PointTypeAnchor;
}
@end
================================================
FILE: Revolved/RVAnimation.h
================================================
//
// RVAnimation.h
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^CompletionBlock)(void);
typedef NS_ENUM(NSInteger, RVAnimationCurve) {
RVAnimationCurveEaseInOut,
RVAnimationCurveEaseIn,
RVAnimationCurveEaseOut,
RVAnimationCurveQuartEaseOut,
RVAnimationCurveQuinticEaseInOut,
RVAnimationCurveElasticEaseOut,
RVAnimationCurveJumpEaseIn,
RVAnimationCurveJumpEaseOut,
RVAnimationCurveJelly,
RVAnimationCurveLinear
};
@interface RVAnimation : NSObject
@property (nonatomic) NSTimeInterval duration;
@property (nonatomic) NSTimeInterval delay;
@property (nonatomic) NSTimeInterval time; // don't touch unless you know what you're doing
@property (nonatomic) RVAnimationCurve animationCurve;
@property (nonatomic, copy) CompletionBlock completionBlock;
@end
================================================
FILE: Revolved/RVAnimation.m
================================================
//
// RVAnimation.m
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAnimation.h"
#import "RVAnimation_Private.h"
@implementation RVAnimation
@end
================================================
FILE: Revolved/RVAnimation_Private.h
================================================
//
// RVAnimation_Private.h
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAnimation.h"
@class RVSprite;
@interface RVAnimation ()
@property (nonatomic, strong) NSString *key;
@property (nonatomic, weak) id target;
@end
================================================
FILE: Revolved/RVAnimator.h
================================================
//
// RVAnimator.h
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@class RVAnimation;
@interface RVAnimator : NSObject
+ (instancetype)sharedAnimator;
- (void)addAnimation:(RVAnimation *)animation forKey:(NSString *)key toTarget:(id)target;
- (RVAnimation *)animationforKey:(NSString *)key forTarget:(id)target;
- (void)removeAnimationForKey:(NSString *)key fromTarget:(id)target;
- (void)tick:(NSTimeInterval)dt;
@end
================================================
FILE: Revolved/RVAnimator.m
================================================
//
// RVAnimator.m
// Revolved
//
// Created by Bartosz Ciechanowski on 25.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAnimator.h"
#import "RVAnimation_Private.h"
#import "RVAnimation.h"
#import "RVFloatAnimation.h"
#import "RVVectorAnimation.h"
#import "RVQuaternionAnimation.h"
#import "RVLineSprite.h"
#import "RVPointSprite.h"
#import "RVModelSprite.h"
#import "UIView+RotationAnimation.h"
typedef float (^Executor)(RVAnimation *animation, float p);
typedef float (*Curve)(float time);
static NSDictionary *keyExecutorMap;
@interface RVAnimator()
@property (nonatomic, strong) NSMapTable *targetToAnimationsDictionaryMap;
@property (nonatomic, strong) NSHashTable *allAnimations;
@end
@implementation RVAnimator
+ (instancetype)sharedAnimator
{
static RVAnimator *sharedInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedInstance = [[RVAnimator alloc] init];
});
return sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
self.targetToAnimationsDictionaryMap = [NSMapTable weakToStrongObjectsMapTable];
self.allAnimations = [NSHashTable weakObjectsHashTable];
}
return self;
}
- (NSMutableDictionary *)animationDictionaryForTarget:(id)target
{
NSMutableDictionary *dictionary = [self.targetToAnimationsDictionaryMap objectForKey:target];
if (!dictionary) {
dictionary = [NSMutableDictionary dictionary];
[self.targetToAnimationsDictionaryMap setObject:dictionary forKey:target];
}
return dictionary;
}
- (void)addAnimation:(RVAnimation *)animation forKey:(NSString *)key toTarget:(id)target
{
animation.target = target;
animation.key = key;
animation.time = -animation.delay;
[self animationDictionaryForTarget:target][key] = animation;
[self.allAnimations addObject:animation];
}
- (RVAnimation *)animationforKey:(NSString *)key forTarget:(id)target
{
return [self.targetToAnimationsDictionaryMap objectForKey:target][key];
}
- (void)removeAnimationForKey:(NSString *)key fromTarget:(id)target
{
NSMutableDictionary *dict = [self animationDictionaryForTarget:target];
RVAnimation *animation = [dict objectForKey:key];
if (animation) {
[self.allAnimations removeObject:animation];
}
[dict removeObjectForKey:key];
if (dict.count == 0) {
[self.targetToAnimationsDictionaryMap removeObjectForKey:target];
}
}
- (void)tick:(NSTimeInterval)dt
{
NSMutableArray *completionBlocks = [NSMutableArray array];
for (RVAnimation *animation in self.allAnimations.allObjects) {
animation.time += dt;
Executor executor = keyExecutorMap[animation.key];
NSAssert(executor, @"Animating non animatable property %@", animation.key);
float time = animation.time/animation.duration;
time = MIN(MAX(0.0f, time), 1.0f);
float progress = curves[animation.animationCurve](time);
executor(animation, progress);
if (time >= 1.0f) {
[self removeAnimationForKey:animation.key fromTarget:animation.target];
if (animation.completionBlock) {
[completionBlocks addObject:animation.completionBlock];
}
}
}
for (CompletionBlock block in completionBlocks) {
block();
}
}
- (void)setStartQuaternion:(GLKQuaternion)quaternion {}
+ (void)initialize
{
keyExecutorMap = @{
@"color" : ^(RVVectorAnimation *animation, float p){
[(RVLineSprite *)animation.target setColor:[animation valueForProgress:p]];
},
@"burnout" : ^(RVFloatAnimation *animation, float p){
[(RVLineSprite *)animation.target setBurnout:[animation valueForProgress:p]];
},
@"rotation" : ^(RVFloatAnimation *animation, float p){
[(UIView *)animation.target rv_setRotation:[animation valueForProgress:p]];
},
@"alpha" : ^(RVFloatAnimation *animation, float p){
[(RVPointSprite *)animation.target setAlpha:[animation valueForProgress:p]];
},
@"axisAlpha" : ^(RVFloatAnimation *animation, float p){
[(RVModelSprite *)animation.target setAxisAlpha:[animation valueForProgress:p]];
},
@"scale" : ^(RVFloatAnimation *animation, float p){
[(RVPointSprite *)animation.target setScale:[animation valueForProgress:p]];
},
@"extraTranslationVector" : ^(RVVectorAnimation *animation, float p){
[(RVModelSprite *)animation.target setExtraTranslationVector:[animation valueForProgress:p]];
},
@"scaleVector" : ^(RVVectorAnimation *animation, float p){
[(RVModelSprite *)animation.target setScaleVector:[animation valueForProgress:p]];
},
@"modelScaleVector" : ^(RVVectorAnimation *animation, float p){
[(RVModelSprite *)animation.target setModelScaleVector:[animation valueForProgress:p]];
},
@"widthMultiplier" : ^(RVFloatAnimation *animation, float p){
[(RVLineSprite *)animation.target setWidthMultiplier:[animation valueForProgress:p]];
},
@"startQuaternion" : ^(RVQuaternionAnimation *animation, float p){
[(RVAnimator *)animation.target setStartQuaternion:[animation valueForProgress:p]];
},
@"quaternion" : ^(RVQuaternionAnimation *animation, float p){
[(RVModelSprite *)animation.target setQuaternion:[animation valueForProgress:p]];
},
@"wait" : ^(RVFloatAnimation *animation, float p){
},
};
}
#pragma mark - Animation curves
float easeOut(float time)
{
return - time * (time - 2.0f);
}
float easeIn(float time)
{
return time * time;
}
float linear(float time)
{
return time;
}
float easeInOut(float time)
{
return time * time * (3.0f - 2.0f * time);
}
float easeOutQuart(float time)
{
float nt = 1.0f - time;
return 1.0f - nt*nt*nt*nt;
}
float elasticEaseOut(float t)
{
return 0.7*sinf(M_PI*t*4.0f)*expf(-5.0f*t) + 1.0f - expf(-14.0f*t);
}
float jumpEaseIn(float t)
{
return t*(t - 0.2f)/0.8f;
}
float jumpEaseOut(float t)
{
return t*t*(5.0f - 3.75f*t - 2.5*t*t + 2.25*t*t*t);
}
float quinticEaseInOut(float t)
{
return t*t*t*(10.0f - 15.0f*t + 6.0f*t*t);
}
float jelly(float t)
{
return (sinf(6.0f * t * (float)M_PI) * (t - 1.0f) * (t - 1.0f)) * 0.5f + 0.5f;
}
static Curve curves[] = {
[RVAnimationCurveEaseInOut] = easeInOut,
[RVAnimationCurveEaseIn] = easeIn,
[RVAnimationCurveEaseOut] = easeOut,
[RVAnimationCurveLinear] = linear,
[RVAnimationCurveQuartEaseOut] = easeOutQuart,
[RVAnimationCurveElasticEaseOut] = elasticEaseOut,
[RVAnimationCurveJumpEaseIn] = jumpEaseIn,
[RVAnimationCurveJumpEaseOut] = jumpEaseOut,
[RVAnimationCurveQuinticEaseInOut] = quinticEaseInOut,
[RVAnimationCurveJelly] = jelly,
};
@end
================================================
FILE: Revolved/RVAxisMeshController.h
================================================
//
// RVAxisMeshController.h
// Revolved
//
// Created by Bartosz Ciechanowski on 02.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVMeshController.h"
@interface RVAxisMeshController : RVMeshController
- (void)updateBuffersWithLineSprites:(NSArray *)lineSprites;
@end
================================================
FILE: Revolved/RVAxisMeshController.m
================================================
//
// RVAxisMeshController.m
// Revolved
//
// Created by Bartosz Ciechanowski on 02.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAxisMeshController.h"
#import "RVMeshController_Private.h"
#import "RVLineSprite.h"
#import "AxisVertex.h"
#import "BCShader.h"
static const NSUInteger VertexLimit = 512;
static const NSUInteger IndexLimit = VertexLimit * 4;
static const NSUInteger VerticesInSegment = 1;
static const NSUInteger IndiciesInSegment = 2;
@implementation RVAxisMeshController
- (void)setupVAO
{
glGenVertexArraysOES(1, &_VAO);
glBindVertexArrayOES(_VAO);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, VertexLimit * sizeof(AxisVertex), NULL, GL_DYNAMIC_DRAW);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, IndexLimit * sizeof(GLushort), NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VertexAttribPosition);
glVertexAttribPointer(VertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(AxisVertex), (void *)offsetof(AxisVertex, p));
glEnableVertexAttribArray(VertexAttribColor);
glVertexAttribPointer(VertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(AxisVertex), (void *)offsetof(AxisVertex, color));
glBindVertexArrayOES(0);
}
- (void)updateBuffersWithLineSprites:(NSArray *)lineSprites
{
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
AxisVertex *vertexData = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
GLushort *indexData = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
GLuint totalIndicies = 0;
GLuint totalVertices = 0;
for (RVLineSprite *sprite in lineSprites) {
NSUInteger verticesCount;
NSUInteger indiciesCount;
if (![self tessellateSprite:sprite vertexData:vertexData indexData:indexData startVertexIndex:totalVertices verticesCount:&verticesCount indiciesCount:&indiciesCount]) {
break;
}
sprite.indiciesCount = (GLuint)indiciesCount;
sprite.indiciesOffset = totalIndicies;
totalIndicies += indiciesCount;
totalVertices += verticesCount;
vertexData += verticesCount;
indexData += indiciesCount;
}
_indiciesCount = totalIndicies;
glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER);
glUnmapBufferOES(GL_ARRAY_BUFFER);
}
- (BOOL)tessellateSprite:(RVLineSprite *)sprite
vertexData:(AxisVertex *)vertexData
indexData:(GLushort *)indexData
startVertexIndex:(NSUInteger)startVertex
verticesCount:(out NSUInteger *)verticesCount
indiciesCount:(out NSUInteger *)indiciesCount
{
AxisVertex v[VerticesInSegment];
GLushort i[IndiciesInSegment];
NSUInteger totalIndicies = 0;
NSUInteger totalVertices = 0;
GLKVector3 color = sprite.color;
v[0].color = GLKVector4Make(0.0, 0.0, 0.0, MIN(1.0f, 1.1f - color.r));
NSUInteger tesselationSegments = sprite.tesselationSegments;
SegmentTesselator tessalator = sprite.tesselator;
if (startVertex + (tesselationSegments + 1) * VerticesInSegment > VertexLimit) {
return NO;
}
for (int seg = 0; seg < tesselationSegments + 1; seg++) {
SegmentTesselation tess = tessalator((double)seg/(double)tesselationSegments);
v[0].p = GLKVector3Make(tess.p.x, tess.p.y, 0.0f);
memcpy(vertexData, v, sizeof(v));
vertexData += VerticesInSegment;
totalVertices += VerticesInSegment;
}
for (int seg = 0; seg < tesselationSegments; seg++) {
i[0] = startVertex + 0;
i[1] = startVertex + 1;
memcpy(indexData, i, sizeof(i));
indexData += IndiciesInSegment;
totalIndicies += IndiciesInSegment;
startVertex += VerticesInSegment;
}
*verticesCount = totalVertices;
*indiciesCount = totalIndicies;
return YES;
}
@end
================================================
FILE: Revolved/RVAxisShader.fsh
================================================
varying lowp vec4 colorVarying;
void main()
{
gl_FragColor = colorVarying;
}
================================================
FILE: Revolved/RVAxisShader.h
================================================
//
// RVAxisShader.h
// Revolved
//
// Created by Bartosz Ciechanowski on 02.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "BCShader.h"
@interface RVAxisShader : BCShader
@property (nonatomic) GLint alphaUniform;
@property (nonatomic) GLint viewProjectionModelMatrixUniform;
@end
================================================
FILE: Revolved/RVAxisShader.m
================================================
//
// RVAxisShader.m
// Revolved
//
// Created by Bartosz Ciechanowski on 02.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAxisShader.h"
@implementation RVAxisShader
- (void)bindAttributeLocations
{
glBindAttribLocation(self.program, VertexAttribPosition, "position");
glBindAttribLocation(self.program, VertexAttribColor, "color");
}
- (void)getUniformLocations
{
self.alphaUniform = glGetUniformLocation(self.program, "axisAlpha");
self.viewProjectionModelMatrixUniform = glGetUniformLocation(self.program, "viewProjectionModelMatrix");
}
- (NSString *)shaderName
{
return @"RVAxisShader";
}
@end
================================================
FILE: Revolved/RVAxisShader.vsh
================================================
attribute vec4 position;
attribute vec4 color;
varying vec4 colorVarying;
uniform mat4 viewProjectionModelMatrix;
uniform float axisAlpha;
void main()
{
colorVarying = color;
colorVarying.a *= axisAlpha;
gl_Position = viewProjectionModelMatrix * position;
}
================================================
FILE: Revolved/RVAxisSprite.h
================================================
//
// RVAxisSprite.h
// Revolved
//
// Created by Bartosz Ciechanowski on 03.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVSprite.h"
@interface RVAxisSprite : RVSprite
@property (nonatomic) float alpha;
@property (nonatomic) GLKQuaternion quaternion;
@end
================================================
FILE: Revolved/RVAxisSprite.m
================================================
//
// RVAxisSprite.m
// Revolved
//
// Created by Bartosz Ciechanowski on 03.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVAxisSprite.h"
@implementation RVAxisSprite
@end
================================================
FILE: Revolved/RVBendTutorialPage.h
================================================
//
// RVBendTutorialPage.h
// Revolved
//
// Created by Bartosz Ciechanowski on 02.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVTutorialPage.h"
@interface RVBendTutorialPage : RVTutorialPage
@end
================================================
FILE: Revolved/RVBendTutorialPage.m
================================================
//
// RVBendTutorialPage.m
// Revolved
//
// Created by Bartosz Ciechanowski on 02.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVBendTutorialPage.h"
@interface RVBendTutorialPage()
@property (weak, nonatomic) IBOutlet UIImageView *lineBend1;
@property (weak, nonatomic) IBOutlet UIImageView *lineBend2;
@property (weak, nonatomic) IBOutlet UIImageView *lineBend3;
@property (weak, nonatomic) IBOutlet UIImageView *lineBend4;
@property (weak, nonatomic) IBOutlet UIImageView *lineBend5;
@property (nonatomic, strong) NSArray *lines;
@end
@implementation RVBendTutorialPage
- (void)awakeFromNib
{
[super awakeFromNib];
self.lines = @[self.lineBend1,
self.lineBend2,
self.lineBend3,
self.lineBend4,
self.lineBend5];
}
- (NSString *)descriptionString
{
return @"...drag handles to change its shape";
}
- (void)setDisplayPercent:(float)displayPercent
{
[super setDisplayPercent:displayPercent];
displayPercent -= 0.4;
displayPercent /= 0.6;
NSUInteger count = self.lines.count;
[self.lines enumerateObjectsUsingBlock:^(UIView *line, NSUInteger idx, BOOL *stop) {
float probingOffset = (count - (NSInteger)idx - 1)/(float)(count - 1);
float probe = displayPercent + probingOffset - 1.0f;
if (idx == 0) {
probe = MAX(probe, 0.0);
} else if (idx == count - 1) {
probe = MIN(probe, 0.0);
}
float progress = [self progressForPercent:probe];
line.alpha = progress;
}];
}
- (float)progressForPercent:(float)percent
{
float value = (-fabsf(percent) + 1.0f);
return MIN(MAX(0.0f, value), 1.0);
}
@end
================================================
FILE: Revolved/RVBendTutorialPage.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="4510" systemVersion="12E55" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1" customClass="RVBendTutorialPage">
<rect key="frame" x="0.0" y="0.0" width="700" height="576"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialLineBend1" id="cvr-zH-myr">
<rect key="frame" x="193" y="133" width="221" height="309"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialLineBend3" id="BXN-JN-EDY">
<rect key="frame" x="193" y="133" width="221" height="309"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialLineBend5" id="IVK-5L-SCV">
<rect key="frame" x="193" y="133" width="237" height="309"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialLineBend7" id="Je0-4w-84x">
<rect key="frame" x="193" y="133" width="275" height="309"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialLineBend9" id="ozd-SN-kbK">
<rect key="frame" x="193" y="133" width="314" height="309"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="lineBend1" destination="cvr-zH-myr" id="6BT-qh-ruB"/>
<outlet property="lineBend2" destination="BXN-JN-EDY" id="kfD-1F-J0g"/>
<outlet property="lineBend3" destination="IVK-5L-SCV" id="ImH-GP-7EJ"/>
<outlet property="lineBend4" destination="Je0-4w-84x" id="mxl-1t-rA3"/>
<outlet property="lineBend5" destination="ozd-SN-kbK" id="JI9-TL-akF"/>
</connections>
</view>
</objects>
<resources>
<image name="TutorialLineBend1" width="442" height="618"/>
<image name="TutorialLineBend3" width="442" height="618"/>
<image name="TutorialLineBend5" width="474" height="618"/>
<image name="TutorialLineBend7" width="550" height="618"/>
<image name="TutorialLineBend9" width="628" height="618"/>
</resources>
</document>
================================================
FILE: Revolved/RVColorPicker.h
================================================
//
// RVColorPicker.h
// Revolved
//
// Created by Bartosz Ciechanowski on 14.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "Color.h"
@interface RVColorPicker : UIControl
@property (nonatomic, readonly) BOOL expanded;
@property (nonatomic) NSUInteger selectedColorIndex;
- (void)setSelectedColorIndex:(NSUInteger)selectedColorIndex animated:(BOOL)animated;
- (void)expandAnimated:(BOOL)animated;
- (void)collapseAnimated:(BOOL)animated;
@end
================================================
FILE: Revolved/RVColorPicker.m
================================================
//
// RVColorPicker.m
// Revolved
//
// Created by Bartosz Ciechanowski on 14.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVColorPicker.h"
#import "RVColorProvider.h"
#import "RVColorPickerButton.h"
#import <QuartzCore/QuartzCore.h>
static const CGFloat FlowerRadius = 22.0f;
static const CGFloat CenterPieceRadius = 30.0f;
static const CGFloat ExpandedRadius = 94.0f;
static const CGFloat TotalRadius = ExpandedRadius + FlowerRadius;
static const CGFloat CollapsedTopOffset = 40.0f;
static const CGFloat ExpandedTopOffset = 160.0f;
@interface RVColorPicker()
@property (nonatomic, strong) UIView *rootContainer;
@property (nonatomic, strong) UIButton *centerPiece;
@property (nonatomic, strong) UIView *centerPieceColorView;
@property (nonatomic, strong) NSArray *lollipops;
@property (nonatomic, strong) NSArray *stems;
@property (nonatomic, strong) NSArray *flowers;
@end
@implementation RVColorPicker
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit
{
self.backgroundColor = [UIColor clearColor];
//self.layer.speed = 0.1;
[self addTarget:self action:@selector(touchedUp) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(touchedUp) forControlEvents:UIControlEventTouchUpOutside];
self.rootContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2.0 * TotalRadius, 2.0 * TotalRadius)];
self.rootContainer.center = CGPointMake(self.bounds.size.width/2.0, CollapsedTopOffset);
self.rootContainer.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self addSubview:self.rootContainer];
NSMutableArray *lollipops = [NSMutableArray array];
NSMutableArray *stems = [NSMutableArray array];
NSMutableArray *flowers = [NSMutableArray array];
for (int i = 0; i < ColorCount; i++) {
UIView *lollipop = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2.0 * FlowerRadius, TotalRadius)];
lollipop.layer.anchorPoint = CGPointMake(0.5, 1.0);
lollipop.backgroundColor = [UIColor clearColor];
lollipop.center = CGPointMake(TotalRadius, TotalRadius);
lollipop.transform = CGAffineTransformMakeRotation(i * 2.0 * M_PI/ColorCount);
[lollipops addObject:lollipop];
UIImageView *stem = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Stem"]];
stem.layer.anchorPoint = CGPointMake(0.5, 1.0);
stem.center = CGPointMake(FlowerRadius, TotalRadius);
[stems addObject:stem];
UIButton *flower = [[RVColorPickerButton alloc] initWithFrame:CGRectMake(0, 0, 2.0 * FlowerRadius, 2.0 * FlowerRadius)];
flower.backgroundColor = [RVColorProvider colorForColorIndex:i];
flower.layer.cornerRadius = FlowerRadius;
flower.center = CGPointMake(FlowerRadius, TotalRadius);
flower.tag = i;
[flower addTarget:self action:@selector(masterColorTouchUp:) forControlEvents:UIControlEventTouchUpInside];
[flowers addObject:flower];
[self.rootContainer addSubview:lollipop];
[lollipop addSubview:stem];
[lollipop addSubview:flower];
}
self.centerPiece = [[RVColorPickerButton alloc] initWithFrame:CGRectMake(0, 0, 2.0 * CenterPieceRadius, 2.0 * CenterPieceRadius)];
self.centerPiece.center = CGPointMake(TotalRadius, TotalRadius);
self.centerPiece.layer.cornerRadius = CenterPieceRadius;
self.centerPiece.backgroundColor = [UIColor redColor];
[self.centerPiece addTarget:self action:@selector(centerPieceTap:) forControlEvents:UIControlEventTouchUpInside];
[self.rootContainer addSubview:self.centerPiece];
self.centerPieceColorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2.0 * CenterPieceRadius, 2.0 * CenterPieceRadius)];
self.centerPieceColorView.layer.cornerRadius = CenterPieceRadius;
self.centerPieceColorView.backgroundColor = [UIColor clearColor];
self.centerPieceColorView.userInteractionEnabled = NO;
[self.centerPiece addSubview:self.centerPieceColorView];
self.lollipops = lollipops;
self.stems = stems;
self.flowers = flowers;
_selectedColorIndex = NSNotFound; //forcing refresh on setter
self.selectedColorIndex = 0;
[self collapseAnimated:NO];
}
- (void)layoutSubviews
{
if (self.expanded) {
[self expandAnimated:NO];
} else {
[self collapseAnimated:NO];
}
}
- (void)centerPieceTap:(UIButton *)sender
{
if (self.expanded) {
[self collapseAnimated:YES];
} else {
[self expandAnimated:YES];
}
}
- (void)setSelectedColorIndex:(NSUInteger)selectedColorIndex
{
[self setSelectedColorIndex:selectedColorIndex animated:NO];
}
- (void)setSelectedColorIndex:(NSUInteger)selectedColorIndex animated:(BOOL)animated
{
selectedColorIndex = MIN(ColorCount - 1, selectedColorIndex);
if (_selectedColorIndex == selectedColorIndex) {
return;
}
_selectedColorIndex = selectedColorIndex;
self.centerPieceColorView.transform = CGAffineTransformMakeScale(0.01, 0.01);
self.centerPieceColorView.backgroundColor = [RVColorProvider colorForColorIndex:selectedColorIndex];
self.centerPieceColorView.alpha = 0.4f;
[UIView animateWithDuration:animated ? 0.2 : 0.0 animations:^{
self.centerPieceColorView.transform = CGAffineTransformIdentity;
self.centerPieceColorView.alpha = 1.0f;
} completion:^(BOOL finished) {
self.centerPiece.backgroundColor = [RVColorProvider colorForColorIndex:selectedColorIndex];
self.centerPieceColorView.alpha = 0.0f;
}];
}
- (void)touchedUp
{
[self collapseAnimated:YES];
}
- (void)masterColorTouchUp:(UIView *)sender
{
if (self.expanded) {
[self setSelectedColorIndex:sender.tag animated:YES];
[self sendActionsForControlEvents:UIControlEventValueChanged];
[self collapseAnimated:YES];
} else {
[self expandAnimated:YES];
}
}
- (void)collapseAnimated:(BOOL)animated
{
const CGFloat CollapsedScale = 0.3;
const NSTimeInterval FirstStepDelayVariaton = 0.15;
const NSTimeInterval WitherDuration = 0.3;
const NSTimeInterval WitherDamping = 1.0;
const NSTimeInterval WitherVelocity = -2.0;
const NSTimeInterval ShrinkDuration = 0.15;
const NSTimeInterval ShrinkDamping = 1.0;
const NSTimeInterval ShrinkVelocity = 0.0;
const NSTimeInterval HopDuration = 0.45;
const NSTimeInterval HopDelay = 0.1;
const NSTimeInterval HopDamping = 1.0;
const NSTimeInterval HopVelocity = -5.0;
_expanded = NO;
[UIView animateWithDuration:animated ? HopDuration : 0.0
delay:animated ? HopDelay: 0.0
usingSpringWithDamping:HopDamping
initialSpringVelocity:HopVelocity
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.centerPiece.transform = CGAffineTransformMakeScale(FlowerRadius/CenterPieceRadius, FlowerRadius/CenterPieceRadius);
self.rootContainer.transform = CGAffineTransformIdentity;
}
completion:NULL];
for (int i = 0; i < ColorCount; i++) {
const NSTimeInterval delay = drand48() * FirstStepDelayVariaton;
UIView *stem = self.stems[i];
UIView *flower = self.flowers[i];
[UIView animateWithDuration:animated ? WitherDuration : 0.0
delay:animated ? delay : 0.0
usingSpringWithDamping:WitherDamping
initialSpringVelocity:WitherVelocity
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
stem.transform = CGAffineTransformIdentity;
flower.center = CGPointMake(FlowerRadius, TotalRadius);
} completion:NULL];
[UIView animateWithDuration:animated ? ShrinkDuration : 0.0
delay:animated ? delay : 0.0
usingSpringWithDamping:ShrinkDamping
initialSpringVelocity:ShrinkVelocity
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
flower.transform = CGAffineTransformMakeScale(0.8f * CollapsedScale, CollapsedScale);
} completion:NULL];
}
}
- (void)expandAnimated:(BOOL)animated
{
const NSTimeInterval DropDuration = 0.45;
const NSTimeInterval DropDamping = 0.78;
const NSTimeInterval DropVelocity = 12.0;
const NSTimeInterval SecondStepDelayVariaton = 0.2;
const NSTimeInterval ExpandDelay = 0.06;
const NSTimeInterval ExpandDuration = 0.4;
const NSTimeInterval ExpandDamping = 0.65;
const NSTimeInterval ExpandVelocity = 10.0;
const NSTimeInterval BlossomDelay = 0.13;
const NSTimeInterval BlossomDuration = 0.3;
const NSTimeInterval BlossomDamping = 0.9;
const NSTimeInterval BlossomVelocity = 35.0;
_expanded = YES;
[UIView animateWithDuration:animated ? DropDuration : 0.0
delay:0.0
usingSpringWithDamping:DropDamping
initialSpringVelocity:DropVelocity
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.centerPiece.transform = CGAffineTransformIdentity;
self.rootContainer.transform = CGAffineTransformMakeTranslation(0.0, ExpandedTopOffset - CollapsedTopOffset);
}
completion:NULL];
for (int i = 0; i < ColorCount; i++) {
const NSTimeInterval surplusDelay = drand48() * SecondStepDelayVariaton;
UIView *stem = self.stems[i];
UIView *flower = self.flowers[i];
[UIView animateWithDuration:animated ? ExpandDuration : 0.0
delay:animated ? (ExpandDelay + surplusDelay) : 0.0
usingSpringWithDamping:ExpandDamping
initialSpringVelocity:ExpandVelocity
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
stem.transform = CGAffineTransformMakeScale(1.0, ExpandedRadius);
flower.center = CGPointMake(FlowerRadius, FlowerRadius);
} completion:NULL];
[UIView animateWithDuration:animated ? BlossomDuration : 0.0
delay:animated ? (BlossomDelay + surplusDelay) : 0.0
usingSpringWithDamping:BlossomDamping
initialSpringVelocity:BlossomVelocity
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
flower.transform = CGAffineTransformIdentity;
} completion:NULL];
}
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self && !_expanded) {
return nil;
}
return hitView;
}
@end
================================================
FILE: Revolved/RVColorPickerButton.h
================================================
//
// RVColorPickerButton.h
// Revolved
//
// Created by Bartosz Ciechanowski on 06.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RVColorPickerButton : UIButton
@end
================================================
FILE: Revolved/RVColorPickerButton.m
================================================
//
// RVColorPickerButton.m
// Revolved
//
// Created by Bartosz Ciechanowski on 06.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVColorPickerButton.h"
@implementation RVColorPickerButton
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
const CGFloat Surplus = 7.0f;
CGSize size = self.bounds.size;
CGFloat radius = MIN(size.width, size.height)/2.0f;
point.x -= radius;
point.y -= radius;
CGFloat r = radius + Surplus;
return point.x*point.x + point.y*point.y <= r * r;
}
@end
================================================
FILE: Revolved/RVColorProvider.h
================================================
//
// RVColorProvider.h
// Revolved
//
// Created by Bartosz Ciechanowski on 18.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
extern const NSUInteger ColorCount;
@interface RVColorProvider : NSObject
+ (UIColor *)colorForColorIndex:(NSUInteger)colorIndex;
+ (GLKVector3)vectorForColorIndex:(NSUInteger)colorIndex;
+ (GLKVector3)vectorForDesaturatedColorIndex:(NSUInteger)colorIndex;
+ (GLKVector3)vectorForBackgroundColor;
+ (GLKVector3)vectorForAxisColor;
+ (NSString *)mtlString;
@end
================================================
FILE: Revolved/RVColorProvider.m
================================================
//
// RVColorProvider.m
// Revolved
//
// Created by Bartosz Ciechanowski on 18.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVColorProvider.h"
const NSUInteger ColorCount = 12;
static const NSUInteger ColorValues[ColorCount] = {
0xed4c54,
0xf58c58,
0xfebe4d,
0xf1d948,
0x98cc3d,
0x47b24f,
0x35b299,
0x368ab4,
0x345fa3,
0x8045ba,
0xb440b1,
0xb53678,
};
static UIColor *colors[ColorCount];
static GLKVector3 vectors[ColorCount];
static GLKVector3 desaturatedVectors[ColorCount];
@implementation RVColorProvider
+ (void)initialize
{
for (int i = 0; i < ColorCount; i++) {
colors[i] = [self colorFromHex:ColorValues[i]];
vectors[i] = [self vectorFromHex:ColorValues[i]];
desaturatedVectors[i] = [self vectorForColor:[self desaturatedColor:colors[i]]];
}
}
+ (UIColor *)colorFromHex:(NSUInteger)hex
{
return [UIColor colorWithRed:((float)((hex & 0xFF0000) >> 16))/255.0
green:((float)((hex & 0x00FF00) >> 8))/255.0
blue:((float)((hex & 0x0000FF) >> 0))/255.0 alpha:1.0];
}
+ (UIColor *)desaturatedColor:(UIColor *)color
{
CGFloat hue, saturation, brightness, alpha;
[color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];
return [UIColor colorWithHue:hue saturation:saturation * 0.1 brightness:brightness * 0.8 alpha:alpha];
}
+ (GLKVector3)vectorForColor:(UIColor *)color
{
CGFloat red, green, blue, alpha;
[color getRed:&red green:&green blue:&blue alpha:&alpha];
return GLKVector3Make(red, green, blue);
}
+ (GLKVector3)vectorFromHex:(NSUInteger)hex
{
return GLKVector3Make((float)((hex & 0xFF0000) >> 16)/255.0,
(float)((hex & 0x00FF00) >> 8)/255.0,
(float)((hex & 0x0000FF) >> 0)/255.0);
}
+ (UIColor *)colorForColorIndex:(NSUInteger)colorIndex
{
return colors[colorIndex];
}
+ (GLKVector3)vectorForColorIndex:(NSUInteger)colorIndex
{
return vectors[colorIndex];
}
+ (GLKVector3)vectorForDesaturatedColorIndex:(NSUInteger)colorIndex
{
return desaturatedVectors[colorIndex];
}
+ (GLKVector3)vectorForBackgroundColor
{
const float shade = 0.93f;
return GLKVector3Make(shade, shade, shade);
}
+ (GLKVector3)vectorForAxisColor
{
const float shade = 0.72f;
return GLKVector3Make(shade, shade, shade);
}
+ (NSString *)mtlString
{
NSMutableString *string = [NSMutableString string];
for (int i = 0; i < ColorCount; i++) {
[string appendFormat:@"newmtl mat%d\n", i];
GLKVector3 c = [self vectorForColorIndex:i];
GLKVector3 Ka = c;
GLKVector3 Kd = c;
[string appendFormat:@"Ka %g %g %g\n", Ka.x, Ka.y, Ka.z];
[string appendFormat:@"Kd %g %g %g\n", Kd.x, Kd.y, Kd.z];
[string appendFormat:@"Ks %g %g %g\n", 0.0f, 0.0f, 0.0f];
[string appendString:@"d 1\nillum 2\n\n"];
}
return string;
}
@end
================================================
FILE: Revolved/RVControlPoint.h
================================================
//
// RVControlPoint.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVPoint.h"
@interface RVControlPoint : RVPoint
@end
================================================
FILE: Revolved/RVControlPoint.m
================================================
//
// RVControlPoint.m
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVControlPoint.h"
@implementation RVControlPoint
- (PointType)type
{
return PointTypeControl;
}
@end
================================================
FILE: Revolved/RVCreditsViewController.h
================================================
//
// RVCreditsViewController.h
// Revolved
//
// Created by Bartosz Ciechanowski on 23.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RVCreditsViewController : UIViewController
- (void)present;
@end
================================================
FILE: Revolved/RVCreditsViewController.m
================================================
//
// RVCreditsViewController.m
// Revolved
//
// Created by Bartosz Ciechanowski on 23.09.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVCreditsViewController.h"
#import <MessageUI/MessageUI.h>
#import "MFMailComposeViewController+SendIfPossible.h"
typedef NS_ENUM(NSInteger, TwitterClient) {
TwitterClientTwitterrific,
TwitterClientTweetbot,
TwitterClientTwitter,
};
static NSString * const TwitterNames[] = {
[TwitterClientTwitterrific] = @"Twitterrific",
[TwitterClientTweetbot] = @"Tweetbot",
[TwitterClientTwitter] = @"Twitter",
};
@interface RVCreditsViewController () <MFMailComposeViewControllerDelegate>
@property (nonatomic, strong) NSArray *displayedTwitterClients;
@property (weak, nonatomic) IBOutlet UIControl *backgroundView;
@property (weak, nonatomic) IBOutlet UIView *containerView;
@property (weak, nonatomic) IBOutlet UIButton *twitterButton;
@property (weak, nonatomic) IBOutlet UIButton *emailButton;
@end
@implementation RVCreditsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.twitterButton.exclusiveTouch = YES;
self.emailButton.exclusiveTouch = YES;
self.view.hidden = YES;
self.containerView.backgroundColor = [UIColor rv_backgroundColor];
self.backgroundView.backgroundColor = [UIColor rv_dimColor];
}
- (void)present
{
const NSTimeInterval BackgroundDuration = 0.2;
const NSTimeInterval SlideDelay = 0.1;
const NSTimeInterval SlideDuration = 0.5;
self.view.hidden = NO;
self.backgroundView.alpha = 0.0f;
self.containerView.transform = CGAffineTransformMakeTranslation(0.0, -self.view.bounds.size.height);
[UIView animateWithDuration:BackgroundDuration animations:^{
self.backgroundView.alpha = 1.0f;
}];
[UIView animateWithDuration:SlideDuration delay:SlideDelay usingSpringWithDamping:0.85 initialSpringVelocity:0.0 options:0 animations:^{
self.containerView.transform = CGAffineTransformIdentity;
} completion:NULL];
}
- (void)dismiss
{
const NSTimeInterval BackgroundDuration = 0.2;
const NSTimeInterval BackgroundDelay = 0.3;
const NSTimeInterval SlideDuration = 0.5;
[UIView animateWithDuration:BackgroundDuration delay:BackgroundDelay options:0 animations:^{
self.backgroundView.alpha = 0.0f;
} completion:^(BOOL finished) {
self.view.hidden = YES;
}];
[UIView animateWithDuration:SlideDuration delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:-5.0 options:0 animations:^{
self.containerView.transform = CGAffineTransformMakeTranslation(0.0, -self.view.bounds.size.height);
} completion:NULL];
}
- (IBAction)backgroundTouched:(UIControl *)sender
{
[self dismiss];
}
- (IBAction)emailButtonTapped:(UIButton *)sender
{
if ([MFMailComposeViewController rv_canSendEmailIfNotShowAlert]) {
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:@"Hello!"];
[mailer setToRecipients:@[@"bartosz@ciechanowski.me"]];
[self presentViewController:mailer animated:YES completion:NULL];
}
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
if (result == MFMailComposeResultFailed) {
[MFMailComposeViewController rv_showDefaultFailAlertWithError:error];
} else {
[self dismissViewControllerAnimated:YES completion:NULL];
}
}
- (IBAction)twitterButtonTapped:(UIButton *)sender
{
NSArray *clients = [self twitterClients];
if (clients.count == 0) {
[[UIApplication sharedApplication] openURL:[self safariAppURL]];
return;
}
if (clients.count == 1) {
[[UIApplication sharedApplication] openURL:[self urlForClient:[[clients firstObject] integerValue]]];
return;
}
self.displayedTwitterClients = clients;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Multiple Twitter Clients" message:@"Which one would you like to use?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
for (NSNumber *clientNumber in clients) {
[alert addButtonWithTitle:TwitterNames[[clientNumber integerValue]]];
}
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == alertView.cancelButtonIndex) {
return;
}
TwitterClient client = [self.displayedTwitterClients[buttonIndex - 1] integerValue];
[[UIApplication sharedApplication] openURL:[self urlForClient:client]];
}
- (NSArray *)twitterClients
{
NSMutableArray *clients = [NSMutableArray array];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"twitterrific://"]]) {
[clients addObject:@(TwitterClientTwitterrific)];
}
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tweetbot://"]]) {
[clients addObject:@(TwitterClientTweetbot)];
}
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"twitter://"]]) {
[clients addObject:@(TwitterClientTwitter)];
}
return clients;
}
- (NSURL *)urlForClient:(TwitterClient)client
{
switch (client) {
case TwitterClientTweetbot:
return [NSURL URLWithString:@"tweetbot:///user_profile/BCiechanowski"];
case TwitterClientTwitter:
return [NSURL URLWithString:@"twitter://user?screen_name=BCiechanowski"];
case TwitterClientTwitterrific:
return [NSURL URLWithString:@"twitterrific:///profile?screen_name=BCiechanowski"];
default:
break;
}
return nil;
}
- (NSURL *)safariAppURL
{
return [NSURL URLWithString:@"https://twitter.com/BCiechanowski"];
}
@end
================================================
FILE: Revolved/RVCreditsViewController.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="5023" systemVersion="12F45" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RVCreditsViewController">
<connections>
<outlet property="backgroundView" destination="KYd-qv-ZHl" id="TwK-kl-0NA"/>
<outlet property="containerView" destination="NcQ-qU-YGN" id="5Pd-RU-Cei"/>
<outlet property="emailButton" destination="4q5-1w-r6n" id="VSH-J9-SyT"/>
<outlet property="twitterButton" destination="IKA-rK-Nwx" id="19k-50-q3m"/>
<outlet property="view" destination="2" id="3"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="2">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" id="KYd-qv-ZHl" userLabel="Background" customClass="UIControl">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" id="NcQ-qU-YGN" userLabel="Container">
<rect key="frame" x="362" y="209" width="300" height="350"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="IKA-rK-Nwx">
<rect key="frame" x="80" y="275" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" size="button"/>
<state key="normal" image="Twitter"/>
<connections>
<action selector="twitterButtonTapped:" destination="-1" eventType="touchUpInside" id="4b9-Vp-0uV"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="4q5-1w-r6n">
<rect key="frame" x="170" y="275" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" size="button"/>
<state key="normal" image="MailButton"/>
<connections>
<action selector="emailButtonTapped:" destination="-1" eventType="touchUpInside" id="d5B-6J-KLc"/>
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="CreditsText" id="Nth-ab-68h">
<rect key="frame" x="38" y="56" width="224" height="158"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="0.9379276916" alpha="1" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="0.14999999999999999" alpha="0.80000000000000004" colorSpace="calibratedWhite"/>
<connections>
<action selector="backgroundTouched:" destination="-1" eventType="touchUpInside" id="V2H-BY-9Ib"/>
<action selector="backgroundTouched:" destination="-1" eventType="touchUpOutside" id="ciu-0Z-HNl"/>
</connections>
</view>
</subviews>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
</view>
</objects>
<resources>
<image name="CreditsText" width="224" height="158"/>
<image name="MailButton" width="34" height="24"/>
<image name="Twitter" width="38" height="32"/>
</resources>
</document>
================================================
FILE: Revolved/RVDeleteView.h
================================================
//
// RVDeleteView.h
// Revolved
//
// Created by Bartosz Ciechanowski on 16.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RVDeleteView : UIView
@property (nonatomic) float percentOpen;
- (void)appear;
- (void)disappearWithDeleteAnimation:(BOOL)shouldAnimateDelete;
@end
================================================
FILE: Revolved/RVDeleteView.m
================================================
//
// RVDeleteView.m
// Revolved
//
// Created by Bartosz Ciechanowski on 16.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVDeleteView.h"
@interface RVDeleteView()
@property (nonatomic, strong) UIView *container;
@property (nonatomic, strong) UIImageView *canImageView;
@property (nonatomic, strong) UIImageView *lidImageView;
@end
@implementation RVDeleteView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.container = [[UIView alloc] initWithFrame:CGRectZero];
self.container.clipsToBounds = NO;
self.container.backgroundColor = [UIColor clearColor];
[self addSubview:self.container];
self.canImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TrashCan"]];
[self.container addSubview:self.canImageView];
self.lidImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TrashCanLid"]];
[self.container addSubview:self.lidImageView];
}
return self;
}
- (void)layoutSubviews
{
const CGPoint LidCoverOffset = CGPointMake(-1, 2);
CGRect bounds = self.bounds;
self.container.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
self.canImageView.center = CGPointZero;
CGPoint canOrigin = self.canImageView.frame.origin;
CGPoint lidCenter = CGPointMake(canOrigin.x + LidCoverOffset.x, canOrigin.y + LidCoverOffset.y);
self.lidImageView.center = lidCenter;
}
- (UIColor *)onColor
{
return [UIColor colorWithHue:0.0 saturation:0.82 brightness:0.89 alpha:0.85];
}
- (UIColor *)offColor
{
return [UIColor colorWithWhite:0.75 alpha:0.85];
}
- (void)setPercentOpen:(float)percentOpen
{
percentOpen = MIN(MAX(0.0, percentOpen), 1.0);
if (percentOpen == 1.0) {
[UIView animateWithDuration:0.2 animations:^{
self.backgroundColor = [self onColor];
}];
} else {
[UIView animateWithDuration:0.2 animations:^{
self.backgroundColor = [self offColor];
}];
}
_percentOpen = percentOpen;
self.lidImageView.transform = CGAffineTransformMakeRotation(-M_PI * _percentOpen);
}
- (void)appear
{
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 1.0f;
}];
}
- (void)disappearWithDeleteAnimation:(BOOL)shouldAnimateDelete
{
const float Scale = 1.2f;
if (shouldAnimateDelete) {
[UIView animateWithDuration:0.2 animations:^{
self.container.transform = CGAffineTransformMakeScale(Scale, Scale);
self.container.alpha = 0.5;
self.alpha = 0.0f;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.2 animations:^{
self.container.transform = CGAffineTransformIdentity;
self.container.alpha = 1.0;
self.backgroundColor = [self offColor];
}];
}];
} else {
[UIView animateWithDuration:_percentOpen * 0.2 animations:^{
self.lidImageView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 0.0f;
}];
}
}];
}
}
@end
================================================
FILE: Revolved/RVDrawController.h
================================================
//
// DrawController.h
// Revolved
//
// Created by Bartosz Ciechanowski on 10.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Color.h"
@class RVSegment, RVPoint, RVGuideline, RVControlPoint;
@protocol DrawControllerDelegate;
typedef NS_ENUM(NSInteger, DrawControllerState) {
DrawControllerStateIdle,
DrawControllerStateDrawing,
DrawControllerStateSelection,
DrawControllerStateDraggingPoint
};
@interface RVDrawController : NSObject
@property (nonatomic, weak) id<DrawControllerDelegate> delegate;
@property (nonatomic) DrawControllerState state;
@property (nonatomic, strong) NSMutableOrderedSet *segments;
@property (nonatomic, strong, readonly) RVSegment *selectedSegment;
@property (nonatomic) float rightEdge;
@property (nonatomic) float topEdge;
@property (nonatomic) float bottomEdge;
@property (nonatomic) float evadeSquareRadius;
@property (nonatomic) GLKVector2 topEvadeCenter;
@property (nonatomic) GLKVector2 bottomEvadeCenter;
@property (nonatomic) float snapDistanceSquared;
@property (nonatomic) float tapDistanceSquared;
- (void)handlePanBeginAtPosition:(GLKVector2)position firstTouchPosition:(GLKVector2)firstTouchPosition;
- (void)handlePanContinueAtPosition:(GLKVector2)position;
- (void)handlePanEndAtPosition:(GLKVector2)position;
- (void)handleTapAtPosition:(GLKVector2)position;
- (void)handleColorSelection:(NSUInteger)selectedColorIndex;
- (void)deleteSegment:(RVSegment *)segment;
- (void)clear;
@end
@protocol DrawControllerDelegate <NSObject>
- (void)drawControllerDidSelectSegment:(RVSegment *)segment;
- (void)drawControllerDidSelectEndPoint:(RVPoint *)endPoint;
- (void)drawControllerDidTryAddButReachedSegmentLimit;
- (void)drawControllerDidAddSegment:(RVSegment *)segment;
- (void)drawControllerDidModifySegment:(RVSegment *)segment;
- (void)drawControllerDidRecolorSegment:(RVSegment *)segment;
- (void)drawControllerDidRemoveSegment:(RVSegment *)segment;
- (void)drawControllerDidAddGuideLine:(RVGuideline *)guideline;
- (void)drawControllerDidRemoveGuideLine:(RVGuideline *)guideline;
- (void)drawControllerDidStartDraggingPoint:(RVPoint *)point;
- (void)drawControllerDidDragPoint:(RVPoint *)point;
- (void)drawControllerDidEndDraggingPoint:(RVPoint *)point;
- (void)drawControllerDidSelectColorIndex:(NSUInteger)colorIndex;
@end
================================================
FILE: Revolved/RVDrawController.m
================================================
//
// DrawController.m
// Revolved
//
// Created by Bartosz Ciechanowski on 10.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVDrawController.h"
#import "RVSegment.h"
#import "RVSegmentConnection.h"
#import "RVGuideline.h"
#import "Geometry.h"
#import "RVEndPoint.h"
#import "RVAnchorPoint.h"
#import "RVControlPoint.h"
#import "Constants.h"
@interface RVDrawController()
@property (nonatomic) NSUInteger drawingColorIndex;
@property (nonatomic, strong) RVSegment *drawnSegment;
@property (nonatomic, strong, readwrite) RVSegment *selectedSegment;
@property (nonatomic, strong) RVPoint *draggedPoint;
@property (nonatomic) GLKVector2 draggedPointOffset;
@property (nonatomic, strong) RVGuideline *currentGuideLine;
@end
@implementation RVDrawController
- (void)setSelectedSegment:(RVSegment *)selectedSegment
{
if (_selectedSegment == selectedSegment) {
return;
}
if (selectedSegment) {
NSUInteger segmentIndex = [self.segments indexOfObject:selectedSegment];
NSUInteger lastIndex = self.segments.count - 1;
NSAssert(segmentIndex != NSNotFound, @"SelectedSegment not in allSegments");
NSAssert(self.segments.count > 0, @"allSegments empty");
[self.segments moveObjectsAtIndexes:[NSIndexSet indexSetWithIndex:segmentIndex] toIndex:lastIndex];
}
_selectedSegment = selectedSegment;
[self.delegate drawControllerDidSelectSegment:selectedSegment];
[self.delegate drawControllerDidSelectColorIndex:selectedSegment ? selectedSegment.colorIndex : self.drawingColorIndex];
}
- (void)deleteSegment:(RVSegment *)segment
{
[RVSegmentConnection disconnectSegment:segment atSegmentEnd:SegmentEndFirst];
[RVSegmentConnection disconnectSegment:segment atSegmentEnd:SegmentEndSecond];
[self.segments removeObject:segment];
if (segment == self.selectedSegment) {
self.selectedSegment = nil;
self.state = DrawControllerStateIdle;
}
[self.delegate drawControllerDidRemoveSegment:segment];
}
- (void)clear
{
self.segments = nil;
self.state = DrawControllerStateIdle;
self.drawnSegment = nil;
self.draggedPoint = nil;
self.selectedSegment = nil;
}
- (RVGuideline *)guideLineForControlPoint:(RVControlPoint *)controlPoint
{
RVSegment *segment = controlPoint.segment;
RVSegmentConnection *connection = [segment connectionAtSegmentEnd:controlPoint.segmentEnd];
if (!connection) {
return nil;
}
SegmentEnd otherEnd;
RVSegment *otherSegment = [connection otherSegment:segment otherEnd:&otherEnd];
RVPoint *otherControlPoint = [otherSegment controlPointAtSegmentEnd:otherEnd];
RVPoint *otherPoint = [otherSegment endPointAtSegmentEnd:otherEnd];
GLKVector2 start = otherPoint.position;
GLKVector2 direction = GLKVector2Normalize(GLKVector2Subtract(start, otherControlPoint.position));
float t = INFINITY;
float newT = -1.0f;
newT = (self.topEdge - start.y)/direction.y;
if (newT >= 0.0f && newT < t) {
t = newT;
}
newT = (self.bottomEdge - start.y)/direction.y;
if (newT >= 0.0f && newT < t) {
t = newT;
}
newT = (-start.x)/direction.x;
if (newT >= 0.0f && newT < t) {
t = newT;
}
newT = (self.rightEdge - start.x)/direction.x;
if (newT >= 0.0f && newT < t) {
t = newT;
}
if (start.x <= 0.0f || start.y >= _rightEdge || start.y <= _bottomEdge || start.y >= _topEdge) {
t = 0.0f;
}
GLKVector2 scaledDirection = GLKVector2MultiplyScalar(direction, t);
RVGuideline *guideline = [RVGuideline new];
guideline.start = start;
guideline.end = GLKVector2Add(start, scaledDirection);
guideline.direction = direction;
guideline.length = GLKVector2Length(scaledDirection);
return guideline;
}
#pragma mark - Segment connection
- (void)snapSegment:(RVSegment *)segment bySegmentEnd:(SegmentEnd)segmentEnd nearPosition:(GLKVector2)position
{
position = [self clampedPosition:position];
NSMutableSet *staticSegments = [NSMutableSet setWithSet:self.segments.set];
[staticSegments removeObject:segment];
RVEndPoint *sourcePoint = [segment endPointAtSegmentEnd:segmentEnd];
RVEndPoint *snapPoint = [self nearestEndPointForPosition:position amongSegments:staticSegments withDistanceSq:_snapDistanceSquared];
if (snapPoint) {
RVSegmentConnection *snapPointConnection = [snapPoint.segment connectionAtSegmentEnd:snapPoint.segmentEnd];
if (snapPointConnection) {
if ([snapPointConnection hasEndPoint:sourcePoint]) {
[sourcePoint setPosition:snapPoint.position];
} else {
[sourcePoint setPosition:position];
}
} else {
[RVSegmentConnection disconnectSegment:segment atSegmentEnd:segmentEnd];
[RVSegmentConnection connectSegment:segment bySegmentEnd:segmentEnd toSegment:snapPoint.segment atSegmentEnd:snapPoint.segmentEnd];
[sourcePoint setPosition:snapPoint.position];
}
} else {
[RVSegmentConnection disconnectSegment:segment atSegmentEnd:segmentEnd];
[sourcePoint setPosition:position];
}
[segment adjustAnchorPoints];
}
#pragma mark - Event handling
- (void)handlePanBeginAtPosition:(GLKVector2)position firstTouchPosition:(GLKVector2)firstTouchPosition
{
if (self.state == DrawControllerStateIdle) {
if (self.segments.count > SegmentLimit) {
[self.delegate drawControllerDidTryAddButReachedSegmentLimit];
return;
}
self.state = DrawControllerStateDrawing;
self.drawnSegment = [[RVSegment alloc] init];
[self snapSegment:self.drawnSegment bySegmentEnd:SegmentEndFirst nearPosition:firstTouchPosition];
RVPoint *a = [self.drawnSegment endPointAtSegmentEnd:SegmentEndFirst];
RVPoint *b = [self.drawnSegment endPointAtSegmentEnd:SegmentEndSecond];
b.position = a.position;
self.drawnSegment.colorIndex = self.drawingColorIndex;
[self.segments addObject:self.drawnSegment];
[self.delegate drawControllerDidAddSegment:self.drawnSegment];
return;
}
if (self.state == DrawControllerStateSelection) {
RVPoint *bestPoint = [self closestPointInSet:[self.selectedSegment draggablePoints]
toPosition:firstTouchPosition
graceSquared:_tapDistanceSquared];
if (bestPoint) {
self.draggedPoint = bestPoint;
self.draggedPointOffset = GLKVector2Subtract(position, bestPoint.position);
self.state = DrawControllerStateDraggingPoint;
if (bestPoint.type == PointTypeControl) {
RVGuideline *guideline = [self guideLineForControlPoint:(RVControlPoint *)bestPoint];
if (guideline) {
self.currentGuideLine = guideline;
[self.delegate drawControllerDidAddGuideLine:guideline];
}
}
[self.delegate drawControllerDidStartDraggingPoint:bestPoint];
}
return;
}
}
- (void)handlePanContinueAtPosition:(GLKVector2)position
{
if (self.state == DrawControllerStateDrawing) {
[self snapSegment:self.drawnSegment bySegmentEnd:SegmentEndSecond nearPosition:position];
[self.drawnSegment adjustAnchorPoints];
[self.delegate drawControllerDidModifySegment:self.drawnSegment];
return;
}
if (self.state == DrawControllerStateDraggingPoint) {
position = GLKVector2Subtract(position, self.draggedPointOffset);
if (self.draggedPoint.type == PointTypeControl) {
self.draggedPoint.position = [self snapPositionForControlPoint:(RVControlPoint *)self.draggedPoint nearPosition:position withDistanceSq:_snapDistanceSquared];
} else if (self.draggedPoint.type == PointTypeEnd) {
[self snapSegment:self.draggedPoint.segment bySegmentEnd:self.draggedPoint.segmentEnd nearPosition:position];
}
[self.delegate drawControllerDidDragPoint:self.draggedPoint];
[self.delegate drawControllerDidModifySegment:self.draggedPoint.segment];
return;
}
}
- (void)handlePanEndAtPosition:(GLKVector2)position;
{
if (self.state == DrawControllerStateDrawing) {
self.state = DrawControllerStateIdle;
self.drawnSegment = nil;
return;
}
if (self.state == DrawControllerStateDraggingPoint) {
self.state = DrawControllerStateSelection;
[self.delegate drawControllerDidEndDraggingPoint:self.draggedPoint];
self.draggedPoint = nil;
if (self.currentGuideLine) {
[self.delegate drawControllerDidRemoveGuideLine:self.currentGuideLine];
self.currentGuideLine = nil;
}
return;
}
}
- (void)handleTapAtPosition:(GLKVector2)position
{
if (self.state == DrawControllerStateSelection) {
RVPoint *hitPoint = [self closestPointInSet:[self.selectedSegment draggablePoints]
toPosition:position
graceSquared:_tapDistanceSquared];
if (hitPoint) {
[self.delegate drawControllerDidSelectEndPoint:hitPoint];
return;
}
}
float bestDist = INFINITY;
float dist;
RVSegment *bestSegment = nil;
for (RVSegment *segment in self.segments) {
if ((dist = [segment hitSquareDistance:position]) < bestDist) {
bestDist = dist;
bestSegment = segment;
}
}
if (bestDist < _tapDistanceSquared) {
if (self.state == DrawControllerStateSelection && bestSegment == self.selectedSegment) {
self.state = DrawControllerStateIdle;
self.selectedSegment = nil;
} else {
self.state = DrawControllerStateSelection;
self.selectedSegment = bestSegment;
}
} else {
self.state = DrawControllerStateIdle;
self.selectedSegment = nil;
}
}
- (void)handleColorSelection:(NSUInteger)selectedColorIndex
{
if (self.state == DrawControllerStateSelection || self.state == DrawControllerStateDraggingPoint) {
self.selectedSegment.colorIndex = selectedColorIndex;
[self.delegate drawControllerDidRecolorSegment:self.selectedSegment];
} else if (self.state == DrawControllerStateIdle) {
self.drawingColorIndex = selectedColorIndex;
} else if (self.state == DrawControllerStateDrawing) {
self.drawnSegment.colorIndex = selectedColorIndex;
self.drawingColorIndex = selectedColorIndex;
[self.delegate drawControllerDidRecolorSegment:self.drawnSegment];
}
}
#pragma mark - Helpers
- (GLKVector2)clampedPosition:(GLKVector2)position
{
position.x = MIN(MAX(0.0, position.x), _rightEdge);
position.y = MIN(MAX(_bottomEdge, position.y), _topEdge);
GLKVector2 bottomDiff = GLKVector2Subtract(position, _bottomEvadeCenter);
GLKVector2 topDiff = GLKVector2Subtract(position, _topEvadeCenter);
if (GLKVector2DotProduct(bottomDiff, bottomDiff) <= _evadeSquareRadius) {
position.y = _bottomEvadeCenter.y + sqrtf(_evadeSquareRadius - bottomDiff.x * bottomDiff.x);
} else if (GLKVector2DotProduct(topDiff, topDiff) <= _evadeSquareRadius) {
position.y = _topEvadeCenter.y - sqrtf(_evadeSquareRadius - topDiff.x * topDiff.x);
}
return position;
}
- (RVPoint *)closestPointInSet:(NSSet *)points toPosition:(GLKVector2)position graceSquared:(float)graceSquared
{
float bestDist = INFINITY;
float dist;
RVPoint *bestPoint = nil;
for (RVPoint *point in points) {
if ((dist = [point hitSquareDistance:position]) < bestDist) {
bestDist = dist;
bestPoint = point;
}
}
if (bestDist < graceSquared) {
return bestPoint;
}
return nil;
}
- (GLKVector2)snapPositionForControlPoint:(RVControlPoint *)controlPoint nearPosition:(GLKVector2)position withDistanceSq:(float)distanceSq
{
assert([controlPoint isKindOfClass:[RVControlPoint class]]);
RVSegment *segment = controlPoint.segment;
RVAnchorPoint *anchorPoint = [segment anchorPointAtSegmentEnd:controlPoint.segmentEnd];
if (GLKVector2DistanceSq(position, anchorPoint.position) < _snapDistanceSquared) {
anchorPoint.hasControlPoint = YES;
return anchorPoint.position;
}
anchorPoint.hasControlPoint = NO;
if (self.currentGuideLine) {
float t;
GLKVector2 tangentPoint = ClosestPointOnSegmentForPoint(self.currentGuideLine.start, self.currentGuideLine.end, position, &t);
if (t <= 1.0 && t >= 0.0 && GLKVector2DistanceSq(position, tangentPoint) < _snapDistanceSquared) {
return [self clampedPosition:tangentPoint];
}
}
return [self clampedPosition:position];
}
- (RVEndPoint *)nearestEndPointForPosition:(GLKVector2)position amongSegments:(NSSet *)segments withDistanceSq:(float)distanceSq
{
NSMutableSet *allEndPoints = [NSMutableSet setWithCapacity:segments.count * 2];
for (RVSegment *segment in segments) {
for (SegmentEnd end = SegmentEndFirst; end <= SegmentEndSecond; end++) {
[allEndPoints addObject:[segment endPointAtSegmentEnd:end]];
}
}
return (RVEndPoint *)[self closestPointInSet:allEndPoints toPosition:position graceSquared:distanceSq];
}
@end
================================================
FILE: Revolved/RVDrawViewController.h
================================================
//
// DrawViewController.h
// Revolved
//
// Created by Bartosz Ciechanowski on 07.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@class RVDrawController, RVLineMeshController, RVSpaceConverter, RVPointMeshController, RVGuidlineDotMeshController, RVColorPicker, RVSegment, RVGuideline;
@interface RVDrawViewController : UIViewController
@property (nonatomic, strong) RVDrawController *drawController;
@property (nonatomic, strong) RVSpaceConverter *converter;
@property (nonatomic, strong, readonly) NSArray *axisSprites;
@property (nonatomic, strong, readonly) NSArray *lineSprites;
@property (nonatomic, strong, readonly) NSArray *guidelineSprites;
@property (nonatomic, strong, readonly) NSArray *pointSprites;
- (void)addIntitialLineSpritesForSegments:(NSSet *)segments;
- (void)addLineSpriteForSegment:(RVSegment *)segment;
- (void)modifyLineSpriteForSegment:(RVSegment *)segment;
- (void)removeLineSpriteForSegment:(RVSegment *)segment;
- (void)addSpritesForGuideLine:(RVGuideline *)guideline;
- (void)removeSpritesForGuideLine:(RVGuideline *)guideline;
- (void)addPointSpritesForPoints:(NSSet *)points;
- (void)modifyPointSpritesForPoints:(NSSet *)points;
- (void)dropPointSpritesForPoints:(NSSet *)points;
- (void)removeAllPointSprites;
- (void)setSelectedColorIndex:(NSUInteger)colorIndex;
- (void)selectLineSpriteForSegment:(RVSegment *)segment;
- (void)clearAllSprites;
- (void)animateInWithDuration:(NSTimeInterval)duration;
- (void)animateOutWithDuration:(NSTimeInterval)duration;
@end
================================================
FILE: Revolved/RVDrawViewController.m
================================================
//
// DrawViewController.m
// Revolved
//
// Created by Bartosz Ciechanowski on 07.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVDrawViewController.h"
#import "RVDrawController.h"
#import "RVSpaceConverter.h"
#import "RVModelMeshController.h"
#import "RVLineMeshController.h"
#import "RVGuidlineDotMeshController.h"
#import "RVPointMeshController.h"
#import "RVColorPicker.h"
#import "RVColorProvider.h"
#import "DrawGestureRecognizer.h"
#import "Geometry.h"
#import "RVPoint.h"
#import "RVSegment.h"
#import "RVGuideline.h"
#import "RVLineSprite.h"
#import "RVPointSprite.h"
#import "RVGuidelineDotSprite.h"
#import "RVVectorAnimation.h"
#import "RVFloatAnimation.h"
#import "NSMapTable+BlockEnumeration.h"
static const float SnapDistance = 17.0f;
static const float TapDistance = 26.0f;
@interface RVDrawViewController () <UIGestureRecognizerDelegate>
@property (nonatomic, strong) DrawGestureRecognizer *drawRecgonizer;
@property (nonatomic, strong) UITapGestureRecognizer *tapRecognizer;
@property (weak, nonatomic) IBOutlet UIButton *deleteButton;
@property (weak, nonatomic) IBOutlet RVColorPicker *colorPicker;
@property (nonatomic, strong) NSArray *axisLineSprites;
@property (nonatomic, strong) NSMapTable *segmentToLineSpriteMap;
@property (nonatomic, strong) NSMapTable *guidelineToLineSpriteArrayMap;
@property (nonatomic, strong) NSMapTable *pointToPointSpriteMap;
@end
@implementation RVDrawViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_segmentToLineSpriteMap = [NSMapTable strongToStrongObjectsMapTable];
_guidelineToLineSpriteArrayMap = [NSMapTable strongToStrongObjectsMapTable];
_pointToPointSpriteMap = [NSMapTable strongToStrongObjectsMapTable];
[self createAxisLineSprites];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.drawRecgonizer = [[DrawGestureRecognizer alloc] initWithTarget:self action:@selector(draw:)];
self.drawRecgonizer.cancelsTouchesInView = NO;
self.drawRecgonizer.delegate = self;
[self.view addGestureRecognizer:self.drawRecgonizer];
self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
self.tapRecognizer.cancelsTouchesInView = NO;
self.tapRecognizer.delegate = self;
[self.view addGestureRecognizer:self.tapRecognizer];
}
- (void)setConverter:(RVSpaceConverter *)converter {
const CGFloat DraggerRadius = 26.0f;
_converter = converter;
self.drawController.snapDistanceSquared = [converter modelSquareDistanceForViewDistance:SnapDistance];
self.drawController.tapDistanceSquared = [converter modelSquareDistanceForViewDistance:TapDistance];
CGSize size = self.view.bounds.size;
self.drawController.topEdge = [converter modelPointForViewPoint:CGPointMake(0.0, DraggerRadius)].y;
self.drawController.rightEdge = [converter modelPointForViewPoint:CGPointMake(size.width - DraggerRadius, 0.0)].x;
self.drawController.bottomEdge = [converter modelPointForViewPoint:CGPointMake(0.0, size.height - DraggerRadius)].y;
CGFloat xCenter = self.deleteButton.center.x;
self.drawController.evadeSquareRadius = [converter modelSquareDistanceForViewDistance:90.0f];
self.drawController.bottomEvadeCenter = [converter modelPointForViewPoint:CGPointMake(xCenter, size.height)];
self.drawController.topEvadeCenter = [converter modelPointForViewPoint:CGPointMake(xCenter, 0.0f)];
[self resizeAxisLineSprites];
}
- (NSArray *)lineSprites
{
NSMutableArray *allSprites = [NSMutableArray array];
[allSprites addObjectsFromArray:self.axisLineSprites];
NSMutableArray *validLineSprites = [NSMutableArray array];
NSMutableSet *allLineSprite = [NSMutableSet setWithArray:self.segmentToLineSpriteMap.objectEnumerator.allObjects];
for (RVSegment *segment in self.drawController.segments) {
RVLineSprite *sprite = [self.segmentToLineSpriteMap objectForKey:segment];
[validLineSprites addObject:sprite];
[allLineSprite removeObject:sprite];
}
[allSprites addObjectsFromArray:allLineSprite.allObjects];
[allSprites addObjectsFromArray:validLineSprites];
return allSprites;
}
- (NSArray *)guidelineSprites
{
NSMutableArray *allSprites = [NSMutableArray array];
for (NSArray *guidelineArray in self.guidelineToLineSpriteArrayMap.objectEnumerator.allObjects) {
[allSprites addObjectsFromArray:guidelineArray];
}
return allSprites;
}
- (NSArray *)axisSprites
{
return self.axisLineSprites;
}
#pragma mark - UI Events
- (void)draw:(DrawGestureRecognizer *)sender
{
GLKVector2 position = [self.converter modelPointForViewPoint:[sender locationInView:sender.view]];
switch (sender.state) {
case UIGestureRecognizerStateBegan:
[self.drawController handlePanBeginAtPosition:position
firstTouchPosition:[self.converter modelPointForViewPoint:[sender firstTouchLocationInView:sender.view]]];
/* FALL THROUGH */
case UIGestureRecognizerStateChanged:
[self.drawController handlePanContinueAtPosition:position];
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
[self.drawController handlePanEndAtPosition:position];
break;
default:
break;
}
}
- (void)setSelectedColorIndex:(NSUInteger)colorIndex
{
[self.colorPicker setSelectedColorIndex:colorIndex animated:YES];
}
- (IBAction)tap:(UITapGestureRecognizer *)sender
{
GLKVector2 point = [self.converter modelPointForViewPoint:[sender locationInView:sender.view]];
[self.drawController handleTapAtPosition:point];
}
- (IBAction)deleteButtonTapped:(UIButton *)sender
{
[self.drawController deleteSegment:self.drawController.selectedSegment];
}
- (IBAction)colorPickerChangedColor:(RVColorPicker *)sender
{
[self.drawController handleColorSelection:sender.selectedColorIndex];
}
#pragma mark - In/Out animation
- (void)animateInWithDuration:(NSTimeInterval)duration
{
self.deleteButton.alpha = 0.0f;
self.colorPicker.alpha = 0.0f;
[UIView animateWithDuration:duration animations:^{
self.deleteButton.alpha = 1.0f;
self.colorPicker.alpha = 1.0f;
}];
[self.segmentToLineSpriteMap enumerateKeysAndObjectsUsingBlock:^(RVSegment *segment, RVLineSprite *lineSprite, BOOL *stop) {
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:lineSprite.color toValue:[RVColorProvider vectorForColorIndex:segment.colorIndex] withDuration:duration];
RVFloatAnimation *widthAnimation = [RVFloatAnimation floatAnimationFromValue:lineSprite.widthMultiplier toValue:1.0 withDuration:duration];
[lineSprite addAnimation:colorAnimation forKey:@"color"];
[lineSprite addAnimation:widthAnimation forKey:@"widthMultiplier"];
}];
NSUInteger axisSegmentsCount = self.axisLineSprites.count;
GLKVector3 backgroundColor = [RVColorProvider vectorForBackgroundColor];
GLKVector3 axisColor = [RVColorProvider vectorForAxisColor];
[self.axisLineSprites enumerateObjectsUsingBlock:^(RVLineSprite *axisSprite, NSUInteger i, BOOL *stop) {
float t = i / (axisSegmentsCount - 1.0f);
float value = MIN(1.0f, 30.0 * sinf(t*M_PI) * sinf(t*M_PI) + 0.05);
GLKVector3 finalColor = GLKVector3Add(GLKVector3MultiplyScalar(axisColor, value),
GLKVector3MultiplyScalar(backgroundColor, 1.0 - value));
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:backgroundColor toValue:finalColor withDuration:duration];
[axisSprite addAnimation:colorAnimation forKey:@"color"];
}];
}
- (void)animateOutWithDuration:(NSTimeInterval)duration
{
[UIView animateWithDuration:duration animations:^{
self.deleteButton.alpha = 0.0f;
self.colorPicker.alpha = 0.0f;
} completion:^(BOOL finished) {
[self.colorPicker collapseAnimated:NO];
}];
for (RVLineSprite *lineSprite in self.segmentToLineSpriteMap.objectEnumerator.allObjects) {
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:lineSprite.color toValue:[RVColorProvider vectorForBackgroundColor] withDuration:duration];
RVFloatAnimation *widthAnimation = [RVFloatAnimation floatAnimationFromValue:lineSprite.widthMultiplier toValue:0.0 withDuration:duration];
[lineSprite addAnimation:colorAnimation forKey:@"color"];
[lineSprite addAnimation:widthAnimation forKey:@"widthMultiplier"];
}
GLKVector3 backgroundColor = [RVColorProvider vectorForBackgroundColor];
for (RVLineSprite *axisSprite in self.axisLineSprites) {
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:axisSprite.color toValue:backgroundColor withDuration:duration];
[axisSprite addAnimation:colorAnimation forKey:@"color"];
}
for (RVPointSprite *pointSprite in self.pointToPointSpriteMap.objectEnumerator.allObjects) {
RVFloatAnimation *alphaAnimation = [RVFloatAnimation floatAnimationFromValue:pointSprite.alpha toValue:0.0f withDuration:duration];
[pointSprite addAnimation:alphaAnimation forKey:@"alpha"];
}
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (self.colorPicker.expanded) {
return NO;
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if (gestureRecognizer == self.tapRecognizer && [touch.view isKindOfClass:[UIButton class]]) {
return NO;
}
return YES;
}
#pragma mark - Line Sprites
- (void)mapNewTesselationDataToSprite:(RVLineSprite *)lineSprite withSegment:(RVSegment *)segment
{
lineSprite.tesselator = segment.tesselator;
lineSprite.tesselationSegments = segment.lineTesselationSegments;
}
- (void)addIntitialLineSpritesForSegments:(NSSet *)segments
{
for (RVSegment *segment in segments) {
RVLineSprite *lineSprite = [[RVLineSprite alloc] init];
lineSprite.color = [RVColorProvider vectorForBackgroundColor];
lineSprite.widthMultiplier = 0.0f;
[self.segmentToLineSpriteMap setObject:lineSprite forKey:segment];
[self mapNewTesselationDataToSprite:lineSprite withSegment:segment];
}
}
- (void)addLineSpriteForSegment:(RVSegment *)segment
{
RVLineSprite *lineSprite = [[RVLineSprite alloc] init];
lineSprite.color = [RVColorProvider vectorForColorIndex:segment.colorIndex];
lineSprite.widthMultiplier = 1.0f;
[self.segmentToLineSpriteMap setObject:lineSprite forKey:segment];
[self mapNewTesselationDataToSprite:lineSprite withSegment:segment];
}
- (void)modifyLineSpriteForSegment:(RVSegment *)segment
{
RVLineSprite *lineSprite = [self.segmentToLineSpriteMap objectForKey:segment];
lineSprite.color = [RVColorProvider vectorForColorIndex:segment.colorIndex];
[self mapNewTesselationDataToSprite:lineSprite withSegment:segment];
}
- (void)removeLineSpriteForSegment:(RVSegment *)segment
{
RVLineSprite *lineSprite = [self.segmentToLineSpriteMap objectForKey:segment];
RVFloatAnimation *burnoutAnimation = [RVFloatAnimation new];
burnoutAnimation.from = 0.0f;
burnoutAnimation.to = 1.0f;
burnoutAnimation.duration = 0.3f;
//burnoutAnimation.animationCurve = RVAnimationCurveEaseIn;
burnoutAnimation.completionBlock = ^{[self.segmentToLineSpriteMap removeObjectForKey:segment];};
//RVFloatAnimation *lineAnimation = [self lineWidthAnimationFromWidth:1.0 toWidth:0.7];
[lineSprite addAnimation:burnoutAnimation forKey:@"burnout"];
//[lineSprite addAnimation:lineAnimation forKey:@"widthMultiplier"];
}
- (void)selectLineSpriteForSegment:(RVSegment *)segment
{
const NSTimeInterval Duration = 0.16;
if (segment) {
self.deleteButton.enabled = YES;
[self.segmentToLineSpriteMap enumerateKeysAndObjectsUsingBlock:^(RVSegment *segment, RVLineSprite *lineSprite, BOOL *stop) {
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:lineSprite.color toValue:[RVColorProvider vectorForDesaturatedColorIndex:segment.colorIndex] withDuration:Duration];
RVFloatAnimation *widthAnimation = [RVFloatAnimation floatAnimationFromValue:lineSprite.widthMultiplier toValue:0.8 withDuration:Duration];
[lineSprite addAnimation:colorAnimation forKey:@"color"];
[lineSprite addAnimation:widthAnimation forKey:@"widthMultiplier"];
}];
RVLineSprite *selectedLineSprite = [self.segmentToLineSpriteMap objectForKey:segment];
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:selectedLineSprite.color toValue:[RVColorProvider vectorForColorIndex:segment.colorIndex] withDuration:Duration];
RVFloatAnimation *widthAnimation = [RVFloatAnimation floatAnimationFromValue:selectedLineSprite.widthMultiplier toValue:1.1 withDuration:Duration];
[selectedLineSprite addAnimation:colorAnimation forKey:@"color"];
[selectedLineSprite addAnimation:widthAnimation forKey:@"widthMultiplier"];
} else {
self.deleteButton.enabled = NO;
[self.segmentToLineSpriteMap enumerateKeysAndObjectsUsingBlock:^(RVSegment *segment, RVLineSprite *lineSprite, BOOL *stop) {
RVVectorAnimation *colorAnimation = [RVVectorAnimation vectorAnimationFromValue:lineSprite.color toValue:[RVColorProvider vectorForColorIndex:segment.colorIndex] withDuration:Duration];
RVFloatAnimation *widthAnimation = [RVFloatAnimation floatAnimationFromValue:lineSprite.widthMultiplier toValue:1.0 withDuration:Duration];
[lineSprite addAnimation:colorAnimation forKey:@"color"];
[lineSprite addAnimation:widthAnimation forKey:@"widthMultiplier"];
}];
}
}
- (void)clearAllSprites
{
[self.segmentToLineSpriteMap removeAllObjects];
[self.pointToPointSpriteMap removeAllObjects];
}
#pragma mark - Guideline Sprites
- (void)addSpritesForGuideLine:(RVGuideline *)guideline
{
const NSTimeInterval AppearDuration = 0.15;
const NSTimeInterval AppearStepMaxDelay = 0.01;
const NSTimeInterval AppearStepMaxDiff = 0.006;
float dotDistance = sqrtf(self.drawController.snapDistanceSquared/4.0);
NSInteger dotCount = guideline.length/dotDistance;
if (dotCount == 0) {
return;
}
GLKVector2 start = guideline.start;
GLKVector2 direction = guideline.direction;
NSMutableArray *dots = [NSMutableArray arrayWithCapacity:dotCount];
float p = 1.0f/(dotCount - 1);
NSTimeInterval delay = 0.0;
for (int i = 0; i < dotCount; i++) {
RVGuidelineDotSprite *sprite = [RVGuidelineDotSprite new];
sprite.position = GLKVector2Add(start, GLKVector2MultiplyScalar(direction, i * dotDistance));
sprite.alpha = 1.0f;
RVFloatAnimation *scaleAnimation = [RVFloatAnimation floatAnimationFromValue:0.0f toValue:1.0f withDuration:AppearDuration];
scaleAnimation.delay = delay;
scaleAnimation.animationCurve = RVAnimationCurveEaseOut;
[sprite addAnimation:scaleAnimation forKey:@"scale"];
[dots addObject:sprite];
delay += AppearStepMaxDelay - (i * p) * (i * p) * AppearStepMaxDiff;
}
if (dotCount == 2) {
[(RVPointSprite *)[dots lastObject] setAlpha:0.5f];
} else if (dotCount > 2) {
[(RVPointSprite *)dots[dotCount - 1] setAlpha:0.33f];
[(RVPointSprite *)dots[dotCount - 2] setAlpha:0.66f];
}
[self.guidelineToLineSpriteArrayMap setObject:dots forKey:guideline];
}
- (void)removeSpritesForGuideLine:(RVGuideline *)guideline
{
const NSTimeInterval DisappearDuration = 0.15;
NSArray *dots = [self.guidelineToLineSpriteArrayMap objectForKey:guideline];
NSUInteger count = dots.count;
[dots enumerateObjectsUsingBlock:^(RVGuidelineDotSprite *dot, NSUInteger idx, BOOL *stop) {
RVFloatAnimation *alphaAnimation = [RVFloatAnimation floatAnimationFromValue:dot.alpha toValue:0.0f withDuration:DisappearDuration];
alphaAnimation.animationCurve = RVAnimationCurveEaseOut;
[dot addAnimation:alphaAnimation forKey:@"alpha"];
if (idx == count - 1) {
alphaAnimation.completionBlock = ^{[self.guidelineToLineSpriteArrayMap removeObjectForKey:guideline];};
}
}];
}
#pragma mark - Point Sprites
- (void)mapNewPointPositionDataToSprite:(RVPointSprite *)pointSprite withPoint:(RVPoint *)point
{
pointSprite.position = point.position;
}
- (NSArray *)pointSprites
{
return self.pointToPointSpriteMap.objectEnumerator.allObjects;
}
- (void)addPointSpritesForPoints:(NSSet *)points
{
for (RVPoint *point in points) {
RVPointSprite *pointSprite = [RVPointSprite new];
pointSprite.segmentEnd = point.segmentEnd;
pointSprite.type = point.type;
[self.pointToPointSpriteMap setObject:pointSprite forKey:point];
[self mapNewPointPositionDataToSprite:pointSprite withPoint:point];
RVFloatAnimation *alphaAnimation = [RVFloatAnimation floatAnimationFromValue:0.3 toValue:1.0 withDuration:0.18];
alphaAnimation.animationCurve = RVAnimationCurveQuartEaseOut;
RVFloatAnimation *scaleAnimation = [RVFloatAnimation floatAnimationFromValue:0.0 toValue:1.0 withDuration:0.18];
scaleAnimation.animationCurve = RVAnimationCurveQuartEaseOut;
[pointSprite addAnimation:alphaAnimation forKey:@"alpha"];
[pointSprite addAnimation:scaleAnimation forKey:@"scale"];
}
}
- (void)modifyPointSpritesForPoints:(NSSet *)points
{
for (RVPoint *point in points) {
RVPointSprite *pointSprite = [self.pointToPointSpriteMap objectForKey:point];
[self mapNewPointPositionDataToSprite:pointSprite withPoint:point];
}
}
- (void)dropPointSpritesForPoints:(NSSet *)points
{
const NSTimeInterval Duration = 0.6;
const NSTimeInterval DelayVariation = 0.12;
for (RVPoint *point in points) {
RVPointSprite *pointSprite = [self.pointToPointSpriteMap objectForKey:point];
[pointSprite removeAnimationForKey:@"scale"];
RVFloatAnimation *alphaAnimation = (RVFloatAnimation *)[pointSprite animationForKey:@"alpha"];
alphaAnimation.duration = Duration + DelayVariation;
alphaAnimation.to = 0.8f;
GLKVector3 startTranslation = pointSprite.extraTranslationVector;
GLKVector3 endTranslation = startTranslation;
endTranslation.y -= 4.0f;
RVVectorAnimation *translationAnimation = [RVVectorAnimation vectorAnimationFromValue:startTranslation
toValue:endTranslation
withDuration:Duration];
translationAnimation.animationCurve = RVAnimationCurveJumpEaseIn;
translationAnimation.delay = drand48() * DelayVariation;
[pointSprite addAnimation:translationAnimation forKey:@"extraTranslationVector"];
}
}
- (void)removeAllPointSprites
{
for (RVPoint *point in self.pointToPointSpriteMap.keyEnumerator.allObjects) {
RVPointSprite *pointSprite = [self.pointToPointSpriteMap objectForKey:point];
RVFloatAnimation *alphaAnimation = [RVFloatAnimation floatAnimationFromValue:1.0 toValue:0.3 withDuration:0.12];
alphaAnimation.animationCurve = RVAnimationCurveEaseOut;
alphaAnimation.completionBlock = ^{[self.pointToPointSpriteMap removeObjectForKey:point];};
RVFloatAnimation *scaleAnimation = [RVFloatAnimation floatAnimationFromValue:1.0 toValue:0.0 withDuration:0.12];
scaleAnimation.animationCurve = RVAnimationCurveEaseOut;
[pointSprite addAnimation:alphaAnimation forKey:@"alpha"];
[pointSprite addAnimation:scaleAnimation forKey:@"scale"];
}
}
#pragma mark - Axis Line Sprites
- (void)createAxisLineSprites
{
const NSUInteger AxisSegmentsCount = 50;
GLKVector3 backgroundColor = [RVColorProvider vectorForBackgroundColor];
NSMutableArray *axisSprites = [NSMutableArray array];
for (int i = 0; i <AxisSegmentsCount; i++) {
RVLineSprite *sprite = [RVLineSprite new];
sprite.widthMultiplier = 0.5f;
sprite.tesselationSegments = 1;
sprite.color = backgroundColor;
[axisSprites addObject:sprite];
}
self.axisLineSprites = axisSprites;
}
- (void)resizeAxisLineSprites
{
const float SegmentToSpaceRatio = 1.0;
NSUInteger count = self.axisLineSprites.count;
float bottomEdge = self.drawController.bottomEdge;
float totalSpan = self.drawController.topEdge - self.drawController.bottomEdge;
float spaceSpan = totalSpan/(SegmentToSpaceRatio * count + count - 1);
float segmentSpan = spaceSpan * SegmentToSpaceRatio;
float midSegmentSpan = spaceSpan + segmentSpan;
[self.axisLineSprites enumerateObjectsUsingBlock:^(RVLineSprite *lineSprite, NSUInteger idx, BOOL *stop) {
GLKVector2 a = GLKVector2Make(0.0f, midSegmentSpan * idx + bottomEdge);
GLKVector2 b = GLKVector2Make(0.0f, midSegmentSpan * idx + segmentSpan + bottomEdge);
lineSprite.tesselator = ^(float t){
float nt = 1.0f - t;
SegmentTesselation tess;
tess.p = GLKVector2Make(a.x * nt + b.x * t, a.y * nt + b.y * t);
tess.n = GLKVector2Normalize(GLKVector2Make(a.y - b.y, -a.x + b.x));
return tess;
};
}];
}
@end
================================================
FILE: Revolved/RVDrawViewController.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="5023" systemVersion="12F45" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RVDrawViewController">
<connections>
<outlet property="colorPicker" destination="osE-yB-IGM" id="fu5-JF-s5p"/>
<outlet property="deleteButton" destination="vgS-Eu-lYR" id="ty3-XM-jMK"/>
<outlet property="view" destination="1" id="3gc-T8-Bmg"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1">
<rect key="frame" x="0.0" y="0.0" width="478" height="768"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" id="osE-yB-IGM" customClass="RVColorPicker">
<rect key="frame" x="30" y="0.0" width="448" height="768"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<color key="tintColor" red="0.99915167297979801" green="0.97816481265497124" blue="0.920235698522745" alpha="1" colorSpace="calibratedRGB"/>
<connections>
<action selector="colorPickerChangedColor:" destination="-1" eventType="valueChanged" id="NaP-2Y-PSj"/>
</connections>
</view>
<button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="vgS-Eu-lYR">
<rect key="frame" x="224" y="705" width="60" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<state key="normal" image="TrashButton">
<color key="titleColor" red="0.23652541035353536" green="0.16935382770018501" blue="0.14376399760714612" alpha="1" colorSpace="calibratedRGB"/>
</state>
<connections>
<action selector="deleteButtonTapped:" destination="-1" eventType="touchUpInside" id="SZA-xJ-k7M"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<gestureRecognizers/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="blackOpaque"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
<resources>
<image name="TrashButton" width="24" height="32"/>
</resources>
</document>
================================================
FILE: Revolved/RVDrawingTutorialPage.h
================================================
//
// RVDrawingTutorialPage.h
// Revolved
//
// Created by Bartosz Ciechanowski on 01.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVTutorialPage.h"
@interface RVDrawingTutorialPage : RVTutorialPage
@end
================================================
FILE: Revolved/RVDrawingTutorialPage.m
================================================
//
// RVDrawingTutorialPage.m
// Revolved
//
// Created by Bartosz Ciechanowski on 01.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVDrawingTutorialPage.h"
#import "RVTutorialLineImageView.h"
@interface RVDrawingTutorialPage()
@property (weak, nonatomic) IBOutlet UIView *iPadBorderView;
@property (weak, nonatomic) IBOutlet UIImageView *iPadCameraImageView;
@property (weak, nonatomic) IBOutlet UIImageView *iPadHomeButtonImageView;
@property (weak, nonatomic) IBOutlet RVTutorialLineImageView *line;
@end
@implementation RVDrawingTutorialPage
/*
I detect the device color by a private API call. Then it's just a matter of
adjusting the iPad color on screen.
*/
+ (NSString *)deviceColor
{
static NSString * color = @"white";
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *deviceColor;
NSString *argument = [@"hDhehvihcehCohlhhorh" stringByReplacingOccurrencesOfString:@"h" withString:@""];
NSString *selectorString = [@"_zdzzezvzizczzezIznzfzoFzozrzKezyz:" stringByReplacingOccurrencesOfString:@"z" withString:@""];
SEL selector = NSSelectorFromString(selectorString);
if ([[UIDevice currentDevice] respondsToSelector:selector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setArgument:&argument atIndex:2];
[invocation setTarget:[UIDevice currentDevice]];
[invocation invoke];
[invocation getReturnValue:&deviceColor];
}
if ([deviceColor isKindOfClass:[NSString class]] && (
[deviceColor isEqualToString:@"black"] ||
[deviceColor isEqualToString:@"#3b3b3c"] )) {
color = @"black";
}
});
return color;
}
- (void)awakeFromNib
{
[super awakeFromNib];
if ([[RVDrawingTutorialPage deviceColor] isEqualToString:@"black"]) {
self.iPadHomeButtonImageView.image = [UIImage imageNamed:@"TutorialiPadHomeBlack"];
self.iPadBorderView.backgroundColor = [UIColor colorWithWhite:0.09 alpha:1.0f];
}
}
- (NSString *)descriptionString
{
return @"You draw them on the right side of the screen";
}
/*
Making sure the iPad on screen looks the same as the one held in user's hands
*/
- (void)setupInterfaceOrientation:(UIInterfaceOrientation)orientation
{
self.iPadCameraImageView.alpha = orientation == UIInterfaceOrientationLandscapeLeft ? 1.0f : 0.0f;
self.iPadHomeButtonImageView.alpha = orientation == UIInterfaceOrientationLandscapeLeft ? 0.0f : 1.0f;
}
- (void)setDisplayPercent:(float)displayPercent
{
[super setDisplayPercent:displayPercent];
const CGPoint Start = {188, 125};
const CGPoint End = {364, 392};
float progress = [self progressForPercent:displayPercent];
CGFloat dx = End.x - Start.x;
CGFloat dy = End.y - Start.y;
CGPoint end = CGPointMake(Start.x + progress * dx, Start.y + progress * dy);
if (progress == 0.0f) {
[self.line positionWithRotation:atan2f(dy, dx) atPoint:Start];
} else {
[self.line positionFromPoint:Start toPoint:end];
}
}
- (float)progressForPercent:(float)percent
{
percent = MIN(MAX(0.0f, percent), 1.0f);
return percent;
}
@end
================================================
FILE: Revolved/RVDrawingTutorialPage.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="4510" systemVersion="12E55" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1" customClass="RVDrawingTutorialPage">
<rect key="frame" x="0.0" y="0.0" width="700" height="576"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" id="nzv-1f-LlC">
<rect key="frame" x="594" y="0.0" width="106" height="576"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialiPadCamera" id="VpZ-vB-Rf4">
<rect key="frame" x="45" y="280" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialiPadHomeWhite" id="CsE-Pd-o06">
<rect key="frame" x="26" y="261" width="54" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="0.98905109489051091" alpha="1" colorSpace="calibratedWhite"/>
</view>
<view contentMode="scaleToFill" id="Pzm-3u-Vzt">
<rect key="frame" x="590" y="0.0" width="4" height="576"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialAxis" id="TpJ-bo-LNe">
<rect key="frame" x="128" y="0.0" width="2" height="576"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TutorialLine" id="jhz-Oa-li2" customClass="RVTutorialLineImageView">
<rect key="frame" x="364" y="392" width="6" height="6"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="iPadBorderView" destination="nzv-1f-LlC" id="Nfp-CN-Eyc"/>
<outlet property="iPadCameraImageView" destination="VpZ-vB-Rf4" id="LrH-z2-6VQ"/>
<outlet property="iPadHomeButtonImageView" destination="CsE-Pd-o06" id="fcX-jf-pE6"/>
<outlet property="line" destination="jhz-Oa-li2" id="0mA-RI-RH6"/>
</connections>
</view>
</objects>
<resources>
<image name="TutorialAxis" width="4" height="1052"/>
<image name="TutorialLine" width="6" height="6"/>
<image name="TutorialiPadCamera" width="32" height="32"/>
<image name="TutorialiPadHomeWhite" width="108" height="108"/>
</resources>
</document>
================================================
FILE: Revolved/RVEndPoint.h
================================================
//
// RVEndPoint.h
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVPoint.h"
@interface RVEndPoint : RVPoint
@end
================================================
FILE: Revolved/RVEndPoint.m
================================================
//
// RVEndPoint.m
// Revolved
//
// Created by Bartosz Ciechanowski on 15.08.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVEndPoint.h"
@implementation RVEndPoint
- (PointType)type
{
return PointTypeEnd;
}
@end
================================================
FILE: Revolved/RVExportViewController.h
================================================
//
// RVExportViewController.h
// Revolved
//
// Created by Bartosz Ciechanowski on 27.12.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <UIKit/UIKit.h>
@class RVModel;
@interface RVExportViewController : UIViewController
@property (nonatomic, strong) RVModel *model;
- (void)present;
- (void)dismiss;
@end
================================================
FILE: Revolved/RVExportViewController.m
================================================
//
// RVExportViewController.m
// Revolved
//
// Created by Bartosz Ciechanowski on 27.12.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVExportViewController.h"
#import "RVColorProvider.h"
#import "RVModelManager.h"
#import "RVSTLExporter.h"
#import "RVOBJExporter.h"
#import "SSZipArchive.h"
@interface RVExportViewController () <UIDocumentInteractionControllerDelegate>
@property (weak, nonatomic) IBOutlet UIControl *backgroundView;
@property (weak, nonatomic) IBOutlet UIView *containerView;
@property (weak, nonatomic) IBOutlet UIButton *stlButton;
@property (weak, nonatomic) IBOutlet UIButton *objButton;
@property (weak, nonatomic) IBOutlet UIButton *rvlvdButton;
@property (nonatomic, strong) NSString *filePath;
@property (nonatomic, strong) UIDocumentInteractionController *documentInteractionController;
@end
@implementation RVExportViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.stlButton.exclusiveTouch = YES;
self.objButton.exclusiveTouch = YES;
self.rvlvdButton.exclusiveTouch = YES;
self.view.hidden = YES;
self.containerView.backgroundColor = [UIColor rv_backgroundColor];
self.backgroundView.backgroundColor = [UIColor rv_dimColor];
}
- (void)present
{
const NSTimeInterval BackgroundDuration = 0.2;
const NSTimeInterval SlideDelay = 0.1;
const NSTimeInterval SlideDuration = 0.5;
self.view.hidden = NO;
self.backgroundView.alpha = 0.0f;
self.containerView.transform = CGAffineTransformMakeTranslation(0.0, -self.view.bounds.size.height);
[UIView animateWithDuration:BackgroundDuration animations:^{
self.backgroundView.alpha = 1.0f;
}];
[UIView animateWithDuration:SlideDuration delay:SlideDelay usingSpringWithDamping:0.85 initialSpringVelocity:0.0 options:0 animations:^{
self.containerView.transform = CGAffineTransformIdentity;
} completion:NULL];
}
- (void)dismiss
{
const NSTimeInterval BackgroundDuration = 0.2;
const NSTimeInterval BackgroundDelay = 0.3;
const NSTimeInterval SlideDuration = 0.5;
[UIView animateWithDuration:BackgroundDuration delay:BackgroundDelay options:0 animations:^{
self.backgroundView.alpha = 0.0f;
} completion:^(BOOL finished) {
self.view.hidden = YES;
}];
[UIView animateWithDuration:SlideDuration delay:0.0 usingSpringWithDamping:1.0 initialSpringVelocity:-5.0 options:0 animations:^{
self.containerView.transform = CGAffineTransformMakeTranslation(0.0, -self.view.bounds.size.height);
} completion:NULL];
}
- (NSString *)documentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return documentsDirectory;
}
#pragma mark - Button Actions
- (IBAction)stlButtonTapped:(UIButton *)sender
{
NSString *filePath = [[self documentsDirectory] stringByAppendingPathComponent:@"RevolvedModel.stl"];
RVSTLExporter *exporter = [[RVSTLExporter alloc] init];
[exporter exportModel:self.model toFileAtPath:filePath];
self.filePath = filePath;
[self showDocumentInteractionControllerFromRect:sender.frame];
}
- (IBAction)objButtonTapped:(UIButton *)sender
{
NSString *objFilePath = [[self documentsDirectory] stringByAppendingPathComponent:@"RevolvedModel.obj"];
RVOBJExporter *exporter = [[RVOBJExporter alloc] init];
[exporter exportModel:self.model toFileAtPath:objFilePath];
NSString *mtlFilePath = [[self documentsDirectory] stringByAppendingPathComponent:@"RevolvedMaterials.mtl"];
[[RVColorProvider mtlString] writeToFile:mtlFilePath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
NSString *zipFilePath = [[self documentsDirectory] stringByAppendingPathComponent:@"RevolvedModel.zip"];
[SSZipArchive createZipFileAtPath:zipFilePath withFilesAtPaths:@[objFilePath, mtlFilePath]];
self.filePath = zipFilePath;
[[NSFileManager defaultManager] removeItemAtPath:objFilePath error:NULL];
[[NSFileManager defaultManager] removeItemAtPath:mtlFilePath error:NULL];
[self showDocumentInteractionControllerFromRect:sender.frame];
}
- (IBAction)rvlvdButtonTapped:(UIButton *)sender
{
NSString *rvlvdFilePath = [[self documentsDirectory] stringByAppendingPathComponent:@"RevolvedModel.rvlvd"];
NSData *payload = [RVModelManager exportDataForModel:self.model];
[payload writeToFile:rvlvdFilePath atomically:YES];
self.filePath = rvlvdFilePath;
[self showDocumentInteractionControllerFromRect:sender.frame];
}
- (IBAction)backgroundTouched:(UIControl *)sender
{
[self dismiss];
}
#pragma mark - Document Interaction Controlle
- (void)showDocumentInteractionControllerFromRect:(CGRect)rect
{
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:self.filePath]];
self.documentInteractionController.delegate = self;
[self.documentInteractionController presentOptionsMenuFromRect:rect inView:self.containerView animated:YES];
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
{
}
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller
{
[[NSFileManager defaultManager] removeItemAtPath:self.filePath error:nil];
}
@end
================================================
FILE: Revolved/RVExportViewController.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="5023" systemVersion="12F45" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RVExportViewController">
<connections>
<outlet property="backgroundView" destination="rvg-Rx-BLP" id="tMF-eN-oIw"/>
<outlet property="containerView" destination="Qs6-gU-tIB" id="c0X-xZ-wOV"/>
<outlet property="objButton" destination="NNT-FX-4aj" id="Ys7-ls-AUb"/>
<outlet property="rvlvdButton" destination="GdO-MW-X6e" id="mcx-O3-gPD"/>
<outlet property="stlButton" destination="uex-r9-09A" id="Xn1-Wt-Vhe"/>
<outlet property="view" destination="1" id="2"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="1">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" id="rvg-Rx-BLP" userLabel="Background" customClass="UIControl">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" id="Qs6-gU-tIB" userLabel="Container">
<rect key="frame" x="309" y="294" width="406" height="179"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="uex-r9-09A">
<rect key="frame" x="35" y="35" width="86" height="109"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" size="button"/>
<state key="normal" image="StlFileIcon"/>
<connections>
<action selector="stlButtonTapped:" destination="-1" eventType="touchUpInside" id="UFB-q4-NY6"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="NNT-FX-4aj">
<rect key="frame" x="160" y="35" width="86" height="109"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" size="button"/>
<state key="normal" image="ObjFileIcon"/>
<connections>
<action selector="objButtonTapped:" destination="-1" eventType="touchUpInside" id="C17-Ub-bN0"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="GdO-MW-X6e">
<rect key="frame" x="285" y="35" width="86" height="109"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" size="button"/>
<state key="normal" image="RvlvdFileIcon"/>
<connections>
<action selector="rvlvdButtonTapped:" destination="-1" eventType="touchUpInside" id="QAp-mM-dOt"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.9379276916" alpha="1" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="0.14999999999999999" alpha="0.80000000000000004" colorSpace="calibratedWhite"/>
<connections>
<action selector="backgroundTouched:" destination="-1" eventType="touchUpOutside" id="tub-r9-bo6"/>
<action selector="backgroundTouched:" destination="-1" eventType="touchUpInside" id="vwt-hK-D6h"/>
</connections>
</view>
</subviews>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
</view>
</objects>
<resources>
<image name="ObjFileIcon" width="86" height="109"/>
<image name="RvlvdFileIcon" width="86" height="109"/>
<image name="StlFileIcon" width="86" height="109"/>
</resources>
</document>
================================================
FILE: Revolved/RVExporter.h
================================================
//
// RVExporter.h
// Revolved
//
// Created by Bartosz Ciechanowski on 10.11.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import <Foundation/Foundation.h>
@class RVModel;
@interface RVExporter : NSObject
- (void)exportModel:(RVModel *)model toFileAtPath:(NSString *)path;
- (void)appendModel:(RVModel *)model toHandle:(NSFileHandle *)handle;
@end
================================================
FILE: Revolved/RVExporter.m
================================================
//
// RVExporter.m
// Revolved
//
// Created by Bartosz Ciechanowski on 10.11.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVExporter.h"
#import "RVModel.h"
@implementation RVExporter
- (void)exportModel:(RVModel *)model toFileAtPath:(NSString *)path
{
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:path];
[self appendModel:model toHandle:handle];
[handle closeFile];
}
- (void)appendModel:(RVModel *)model toHandle:(NSFileHandle *)handle
{
}
@end
================================================
FILE: Revolved/RVFinishTutorialPage.h
================================================
//
// RVFinishTutorialPage.h
// Revolved
//
// Created by Bartosz Ciechanowski on 03.10.2013.
// Copyright (c) 2013 Bartosz Ciechanowski. All rights reserved.
//
#import "RVTutorialPage.h"
@interface RVFinishTutorialPage : RVTutorialPage
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
================================================
FILE: Revolved/RVFinishTutorialPage.m
================================================
//
// RVFinishTutorialPage.m
// Revolved
//
// Created by Bartosz Ciechanowski on 03.10.2013.
// C
gitextract_ger1ifyu/
├── .gitignore
├── LICENSE
├── README.md
├── Revolved/
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── AxisVertex.h
│ ├── BCShader.h
│ ├── BCShader.m
│ ├── BCShader_SubclassHooks.h
│ ├── Camera.h
│ ├── Camera.m
│ ├── CameraController.h
│ ├── CameraController.m
│ ├── Color.h
│ ├── Constants.h
│ ├── DrawGestureRecognizer.h
│ ├── DrawGestureRecognizer.m
│ ├── Geometry.h
│ ├── Images.xcassets/
│ │ ├── AddFull.imageset/
│ │ │ └── Contents.json
│ │ ├── AddPlus.imageset/
│ │ │ └── Contents.json
│ │ ├── AddSemiCircle.imageset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── BackButton.imageset/
│ │ │ └── Contents.json
│ │ ├── Camera.imageset/
│ │ │ └── Contents.json
│ │ ├── CloneButton.imageset/
│ │ │ └── Contents.json
│ │ ├── ConfirmButton.imageset/
│ │ │ └── Contents.json
│ │ ├── CreditsButton.imageset/
│ │ │ └── Contents.json
│ │ ├── CreditsText.imageset/
│ │ │ └── Contents.json
│ │ ├── DeclineButton.imageset/
│ │ │ └── Contents.json
│ │ ├── Dots.imageset/
│ │ │ └── Contents.json
│ │ ├── DotsSelected.imageset/
│ │ │ └── Contents.json
│ │ ├── Empty.imageset/
│ │ │ └── Contents.json
│ │ ├── Facebook.imageset/
│ │ │ └── Contents.json
│ │ ├── Gear.imageset/
│ │ │ └── Contents.json
│ │ ├── LaunchImage.launchimage/
│ │ │ └── Contents.json
│ │ ├── Logo.imageset/
│ │ │ └── Contents.json
│ │ ├── MailButton.imageset/
│ │ │ └── Contents.json
│ │ ├── ObjFileIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── RateButton.imageset/
│ │ │ └── Contents.json
│ │ ├── ReviewBegger.imageset/
│ │ │ └── Contents.json
│ │ ├── RvlvdFileIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── Save.imageset/
│ │ │ └── Contents.json
│ │ ├── SegmentLimit.imageset/
│ │ │ └── Contents.json
│ │ ├── ShareButton.imageset/
│ │ │ └── Contents.json
│ │ ├── Stem.imageset/
│ │ │ └── Contents.json
│ │ ├── StlFileIcon.imageset/
│ │ │ └── Contents.json
│ │ ├── TrashButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TrashCan.imageset/
│ │ │ └── Contents.json
│ │ ├── TrashLid.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialAxis.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialAxis3D.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialCloseButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialControlPoint.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialEndPoint.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialFinishButton.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialGetToKnow.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialHaveFun.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLine.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend1.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend3.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend5.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend7.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineBend9.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialLineLong.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialRevolvedBack.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialRevolvedFront.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialSegment1.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialSegment2.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialSegment3.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialWheel.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialiPadCamera.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialiPadHomeBlack.imageset/
│ │ │ └── Contents.json
│ │ ├── TutorialiPadHomeWhite.imageset/
│ │ │ └── Contents.json
│ │ └── Twitter.imageset/
│ │ └── Contents.json
│ ├── LineVertex.h
│ ├── MFMailComposeViewController+SendIfPossible.h
│ ├── MFMailComposeViewController+SendIfPossible.m
│ ├── NSArray+Functional.h
│ ├── NSArray+Functional.m
│ ├── NSError+RevolvedErrors.h
│ ├── NSError+RevolvedErrors.m
│ ├── NSMapTable+BlockEnumeration.h
│ ├── NSMapTable+BlockEnumeration.m
│ ├── NSMutableArray+MoveObject.h
│ ├── NSMutableArray+MoveObject.m
│ ├── NSMutableOrderedSet+MoveObject.h
│ ├── NSMutableOrderedSet+MoveObject.m
│ ├── PointVertex.h
│ ├── RVAddProgressView.h
│ ├── RVAddProgressView.m
│ ├── RVAnchorPoint.h
│ ├── RVAnchorPoint.m
│ ├── RVAnimation.h
│ ├── RVAnimation.m
│ ├── RVAnimation_Private.h
│ ├── RVAnimator.h
│ ├── RVAnimator.m
│ ├── RVAxisMeshController.h
│ ├── RVAxisMeshController.m
│ ├── RVAxisShader.fsh
│ ├── RVAxisShader.h
│ ├── RVAxisShader.m
│ ├── RVAxisShader.vsh
│ ├── RVAxisSprite.h
│ ├── RVAxisSprite.m
│ ├── RVBendTutorialPage.h
│ ├── RVBendTutorialPage.m
│ ├── RVBendTutorialPage.xib
│ ├── RVColorPicker.h
│ ├── RVColorPicker.m
│ ├── RVColorPickerButton.h
│ ├── RVColorPickerButton.m
│ ├── RVColorProvider.h
│ ├── RVColorProvider.m
│ ├── RVControlPoint.h
│ ├── RVControlPoint.m
│ ├── RVCreditsViewController.h
│ ├── RVCreditsViewController.m
│ ├── RVCreditsViewController.xib
│ ├── RVDeleteView.h
│ ├── RVDeleteView.m
│ ├── RVDrawController.h
│ ├── RVDrawController.m
│ ├── RVDrawViewController.h
│ ├── RVDrawViewController.m
│ ├── RVDrawViewController.xib
│ ├── RVDrawingTutorialPage.h
│ ├── RVDrawingTutorialPage.m
│ ├── RVDrawingTutorialPage.xib
│ ├── RVEndPoint.h
│ ├── RVEndPoint.m
│ ├── RVExportViewController.h
│ ├── RVExportViewController.m
│ ├── RVExportViewController.xib
│ ├── RVExporter.h
│ ├── RVExporter.m
│ ├── RVFinishTutorialPage.h
│ ├── RVFinishTutorialPage.m
│ ├── RVFinishTutorialPage.xib
│ ├── RVFloatAnimation.h
│ ├── RVFloatAnimation.m
│ ├── RVGuideline.h
│ ├── RVGuideline.m
│ ├── RVGuidelineDotSprite.h
│ ├── RVGuidelineDotSprite.m
│ ├── RVGuidlineDotMeshController.h
│ ├── RVGuidlineDotMeshController.m
│ ├── RVLineMeshController.h
│ ├── RVLineMeshController.m
│ ├── RVLineShader.fsh
│ ├── RVLineShader.h
│ ├── RVLineShader.m
│ ├── RVLineShader.vsh
│ ├── RVLineSprite.h
│ ├── RVLineSprite.m
│ ├── RVMeshController.h
│ ├── RVMeshController.m
│ ├── RVMeshController_Private.h
│ ├── RVModel.h
│ ├── RVModel.m
│ ├── RVModelButtonsView.h
│ ├── RVModelButtonsView.m
│ ├── RVModelButtonsView.xib
│ ├── RVModelCell.h
│ ├── RVModelCell.m
│ ├── RVModelManager.h
│ ├── RVModelManager.m
│ ├── RVModelMeshController.h
│ ├── RVModelMeshController.m
│ ├── RVModelMetadata.h
│ ├── RVModelMetadata.m
│ ├── RVModelSerializer.h
│ ├── RVModelSerializer.m
│ ├── RVModelShader.fsh
│ ├── RVModelShader.h
│ ├── RVModelShader.m
│ ├── RVModelShader.vsh
│ ├── RVModelSprite.h
│ ├── RVModelSprite.m
│ ├── RVModelViewController.h
│ ├── RVModelViewController.m
│ ├── RVModelViewController.xib
│ ├── RVModelsViewController.h
│ ├── RVModelsViewController.m
│ ├── RVModelsViewController.xib
│ ├── RVOBJExporter.h
│ ├── RVOBJExporter.m
│ ├── RVOpenGLView.h
│ ├── RVOpenGLView.m
│ ├── RVPassForwardView.h
│ ├── RVPassForwardView.m
│ ├── RVPictureViewController.h
│ ├── RVPictureViewController.m
│ ├── RVPictureViewController.xib
│ ├── RVPoint.h
│ ├── RVPoint.m
│ ├── RVPointMeshController.h
│ ├── RVPointMeshController.m
│ ├── RVPointShader.fsh
│ ├── RVPointShader.h
│ ├── RVPointShader.m
│ ├── RVPointShader.vsh
│ ├── RVPointSprite.h
│ ├── RVPointSprite.m
│ ├── RVPreviewViewController.h
│ ├── RVPreviewViewController.m
│ ├── RVPreviewViewController.xib
│ ├── RVQuaternionAnimation.h
│ ├── RVQuaternionAnimation.m
│ ├── RVRenderingController.h
│ ├── RVRenderingController.m
│ ├── RVRevolvedTutorialPage.h
│ ├── RVRevolvedTutorialPage.m
│ ├── RVRevolvedTutorialPage.xib
│ ├── RVRevolvedTutorialPageSolid.xib
│ ├── RVRootViewController.h
│ ├── RVRootViewController.m
│ ├── RVRootViewController.xib
│ ├── RVSTLExporter.h
│ ├── RVSTLExporter.m
│ ├── RVSegment.h
│ ├── RVSegment.m
│ ├── RVSegmentConnection.h
│ ├── RVSegmentConnection.m
│ ├── RVSegmentsTutorialPage.h
│ ├── RVSegmentsTutorialPage.m
│ ├── RVSegmentsTutorialPage.xib
│ ├── RVSelectTutorialPage.h
│ ├── RVSelectTutorialPage.m
│ ├── RVSelectTutorialPage.xib
│ ├── RVSettingsButtonsView.h
│ ├── RVSettingsButtonsView.m
│ ├── RVSettingsButtonsView.xib
│ ├── RVSpaceConverter.h
│ ├── RVSpaceConverter.m
│ ├── RVSprite.h
│ ├── RVSprite.m
│ ├── RVStartTutorialPage.h
│ ├── RVStartTutorialPage.m
│ ├── RVStartTutorialPage.xib
│ ├── RVTutorialLineImageView.h
│ ├── RVTutorialLineImageView.m
│ ├── RVTutorialPage.h
│ ├── RVTutorialPage.m
│ ├── RVTutorialScrollView.h
│ ├── RVTutorialScrollView.m
│ ├── RVTutorialViewController.h
│ ├── RVTutorialViewController.m
│ ├── RVTutorialViewController.xib
│ ├── RVUserDefaults.h
│ ├── RVUserDefaults.m
│ ├── RVVectorAnimation.h
│ ├── RVVectorAnimation.m
│ ├── Renderer.h
│ ├── Renderer.m
│ ├── Revolved-Info.plist
│ ├── Revolved-Prefix.pch
│ ├── SSZipArchive.h
│ ├── SSZipArchive.m
│ ├── SegmentEnd.h
│ ├── UIColor+RevolvedColors.h
│ ├── UIColor+RevolvedColors.m
│ ├── UIView+RotationAnimation.h
│ ├── UIView+RotationAnimation.m
│ ├── Vertex.h
│ ├── en.lproj/
│ │ └── InfoPlist.strings
│ ├── mail.txt
│ ├── main.m
│ ├── minizip/
│ │ ├── crypt.h
│ │ ├── ioapi.c
│ │ ├── ioapi.h
│ │ ├── mztools.c
│ │ ├── mztools.h
│ │ ├── unzip.c
│ │ ├── unzip.h
│ │ ├── zip.c
│ │ └── zip.h
│ ├── model1.rvlvd
│ ├── model2.rvlvd
│ └── model3.rvlvd
├── Revolved Tests/
│ ├── RVConnectionTests.m
│ ├── RVSerializerTests.m
│ ├── Revolved Tests-Info.plist
│ ├── Revolved Tests-Prefix.pch
│ └── en.lproj/
│ └── InfoPlist.strings
└── Revolved.xcodeproj/
├── project.pbxproj
└── project.xcworkspace/
└── contents.xcworkspacedata
SYMBOL INDEX (150 symbols across 20 files)
FILE: Revolved/AxisVertex.h
type AxisVertex (line 12) | typedef struct AxisVertex {
FILE: Revolved/BCShader.h
type VertexAttrib (line 8) | typedef enum {
FILE: Revolved/Color.h
type Color (line 12) | typedef struct Color {
function GLKVector3 (line 16) | static inline GLKVector3 colorToGLKVector3(Color color)
function Color (line 21) | static inline Color colorWithRGB(char red, char green, char blue)
function Color (line 26) | static inline Color colorWithHexColor(NSUInteger hexColor)
FILE: Revolved/Geometry.h
function GLKVector2DistanceSq (line 13) | static inline float GLKVector2DistanceSq(GLKVector2 vectorStart, GLKVect...
function SquareDistancePointSegment (line 21) | static inline float SquareDistancePointSegment(GLKVector2 a, GLKVector2 ...
function GLKVector2 (line 44) | static inline GLKVector2 ClosestPointOnSegmentForPoint(GLKVector2 a, GLK...
FILE: Revolved/LineVertex.h
type LineVertex (line 12) | typedef struct LineVertex {
FILE: Revolved/PointVertex.h
type PointVertex (line 12) | typedef struct PointVertex {
FILE: Revolved/RVAnimation.h
type RVAnimationCurveEaseInOut (line 13) | typedef NS_ENUM(NSInteger, RVAnimationCurve) {
FILE: Revolved/RVDrawController.h
type DrawControllerStateIdle (line 15) | typedef NS_ENUM(NSInteger, DrawControllerState) {
FILE: Revolved/RVMeshController_Private.h
function interface (line 11) | interface RVMeshController ()
FILE: Revolved/RVSegment.h
type SegmentTesselation (line 15) | typedef struct SegmentTesselation {
FILE: Revolved/SegmentEnd.h
type SegmentEndFirst (line 12) | typedef NS_ENUM(NSInteger, SegmentEnd) {
FILE: Revolved/Vertex.h
type Vertex (line 12) | typedef struct Vertex {
FILE: Revolved/minizip/crypt.h
function decrypt_byte (line 35) | static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_...
function update_keys (line 48) | static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32...
function init_keys (line 65) | static void init_keys(const char* passwd,unsigned long* pkeys,const unsi...
function crypthead (line 90) | static int crypthead(const char* passwd, /* password string */
FILE: Revolved/minizip/ioapi.c
function voidpf (line 19) | voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*...
function call_zseek64 (line 29) | long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filest...
function ZPOS64_T (line 43) | ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf fi...
function fill_zlib_filefunc64_32_def_from_filefunc32 (line 57) | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def*...
function voidpf (line 87) | static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* file...
function voidpf (line 105) | static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* fi...
function uLong (line 124) | static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, vo...
function uLong (line 131) | static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, c...
function ftell_file_func (line 138) | static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
function ZPOS64_T (line 146) | static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
function fseek_file_func (line 153) | static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uL...
function fseek64_file_func (line 176) | static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ...
function fclose_file_func (line 202) | static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
function ferror_file_func (line 209) | static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
function fill_fopen_filefunc (line 216) | void fill_fopen_filefunc (pzlib_filefunc_def)
function fill_fopen64_filefunc (line 229) | void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
FILE: Revolved/minizip/ioapi.h
type IT_INT_CUSTOM_TYPE (line 82) | typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
type ZPOS64_T (line 86) | typedef uint64_t ZPOS64_T;
type ZPOS64_T (line 91) | typedef unsigned __int64 ZPOS64_T;
type ZPOS64_T (line 93) | typedef unsigned long long int ZPOS64_T;
type zlib_filefunc_def (line 139) | typedef struct zlib_filefunc_def_s
type zlib_filefunc64_def (line 155) | typedef struct zlib_filefunc64_def_s
type zlib_filefunc64_32_def (line 171) | typedef struct zlib_filefunc64_32_def_s
FILE: Revolved/minizip/mztools.c
function unzRepair (line 31) | extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, byte...
FILE: Revolved/minizip/unzip.c
type unz_file_info64_internal (line 126) | typedef struct unz_file_info64_internal_s
type file_in_zip64_read_info_s (line 134) | typedef struct
type unz64_s (line 165) | typedef struct
function local (line 212) | local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefun...
function local (line 239) | local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filef...
function local (line 266) | local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefu...
function local (line 302) | local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_file...
function local (line 349) | local int strcmpcasenosensitive_internal (const char* fileName1, const c...
function unzStringFileNameCompare (line 390) | extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
function local (line 413) | local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def*...
function local (line 478) | local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_de...
function local (line 584) | local unzFile unzOpenInternal (const void *path,
function unzFile (line 765) | extern unzFile ZEXPORT unzOpen2 (const char *path,
function unzFile (line 778) | extern unzFile ZEXPORT unzOpen2_64 (const void *path,
function unzFile (line 793) | extern unzFile ZEXPORT unzOpen (const char *path)
function unzFile (line 798) | extern unzFile ZEXPORT unzOpen64 (const void *path)
function unzClose (line 808) | extern int ZEXPORT unzClose (unzFile file)
function unzGetGlobalInfo64 (line 828) | extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* ...
function unzGetGlobalInfo (line 838) | extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglo...
function local (line 852) | local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
function local (line 879) | local int unz64local_GetCurrentFileInfoInternal (unzFile file,
function unzGetCurrentFileInfo64 (line 1132) | extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
function unzGetCurrentFileInfo (line 1144) | extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
function unzGoToFirstFile (line 1186) | extern int ZEXPORT unzGoToFirstFile (unzFile file)
function unzGoToNextFile (line 1207) | extern int ZEXPORT unzGoToNextFile (unzFile file)
function unzLocateFile (line 1240) | extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, ...
function unzGetFilePos64 (line 1316) | extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos)
function unzGetFilePos (line 1332) | extern int ZEXPORT unzGetFilePos(
function unzGoToFilePos64 (line 1346) | extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* ...
function unzGoToFilePos (line 1368) | extern int ZEXPORT unzGoToFilePos(
function local (line 1393) | local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* ...
function unzOpenCurrentFile3 (line 1480) | extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
function unzOpenCurrentFile (line 1654) | extern int ZEXPORT unzOpenCurrentFile (unzFile file)
function unzOpenCurrentFilePassword (line 1659) | extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*...
function unzOpenCurrentFile2 (line 1664) | extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* ...
function ZPOS64_T (line 1671) | extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
function unzReadCurrentFile (line 1697) | extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigne...
function z_off_t (line 1916) | extern z_off_t ZEXPORT unztell (unzFile file)
function ZPOS64_T (line 1931) | extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
function ZEXPORT (line 1951) | extern int ZEXPORT unzeof (unzFile file)
function unzGetLocalExtrafield (line 1983) | extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsig...
function unzCloseCurrentFile (line 2031) | extern int ZEXPORT unzCloseCurrentFile (unzFile file)
function unzGetGlobalComment (line 2078) | extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, ...
function ZPOS64_T (line 2106) | extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
function uLong (line 2121) | extern uLong ZEXPORT unzGetOffset (unzFile file)
function unzSetOffset64 (line 2131) | extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
function unzSetOffset (line 2149) | extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
FILE: Revolved/minizip/unzip.h
type unzFile__ (line 67) | typedef struct TagunzFile__ { int unused; } unzFile__;
type unzFile__ (line 68) | typedef unzFile__ *unzFile;
type voidp (line 70) | typedef voidp unzFile;
type tm_unz (line 84) | typedef struct tm_unz_s
type unz_global_info64 (line 96) | typedef struct unz_global_info64_s
type unz_global_info (line 103) | typedef struct unz_global_info_s
type unz_file_info64 (line 111) | typedef struct unz_file_info64_s
type unz_file_info (line 132) | typedef struct unz_file_info_s
type unz_file_pos (line 258) | typedef struct unz_file_pos_s
type unz64_file_pos (line 272) | typedef struct unz64_file_pos_s
FILE: Revolved/minizip/zip.c
type linkedlist_datablock_internal (line 114) | typedef struct linkedlist_datablock_internal_s
type linkedlist_data (line 123) | typedef struct linkedlist_data_s
type curfile64_info (line 130) | typedef struct
type zip64_internal (line 165) | typedef struct
function local (line 189) | local linkedlist_datablock_internal* allocate_new_datablock()
function local (line 203) | local void free_datablock(linkedlist_datablock_internal* ldi)
function local (line 213) | local void init_linkedlist(linkedlist_data* ll)
function local (line 218) | local void free_linkedlist(linkedlist_data* ll)
function local (line 225) | local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uL...
function local (line 287) | local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filef...
function local (line 311) | local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbB...
function local (line 332) | local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)
function local (line 349) | local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefun...
function local (line 373) | local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filef...
function local (line 395) | local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefu...
function local (line 426) | local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_file...
function local (line 480) | local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def*...
function local (line 542) | local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_de...
function LoadCentralDirectoryRecord (line 641) | int LoadCentralDirectoryRecord(zip64_internal* pziinit)
function zipFile (line 851) | extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipch...
function zipFile (line 922) | extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipch...
function zipFile (line 934) | extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zi...
function zipFile (line 950) | extern zipFile ZEXPORT zipOpen (const char* pathname, int append)
function zipFile (line 955) | extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append)
function Write_LocalFileHeader (line 961) | int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt...
function zipOpenNewFileInZip4 (line 1269) | extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filen...
function zipOpenNewFileInZip3 (line 1285) | extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filen...
function zipOpenNewFileInZip3_64 (line 1300) | extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* fil...
function zipOpenNewFileInZip2 (line 1315) | extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filena...
function zipOpenNewFileInZip2_64 (line 1328) | extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* fil...
function zipOpenNewFileInZip64 (line 1341) | extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* file...
function zipOpenNewFileInZip (line 1354) | extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filena...
function local (line 1367) | local int zip64FlushWriteBuffer(zip64_internal* zi)
function zipWriteInFileInZip (line 1406) | extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,uns...
function zipCloseFileInZipRaw (line 1513) | extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompresse...
function zipCloseFileInZipRaw64 (line 1518) | extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncomp...
function zipCloseFileInZip (line 1760) | extern int ZEXPORT zipCloseFileInZip (zipFile file)
function Write_Zip64EndOfCentralDirectoryLocator (line 1766) | int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T...
function Write_Zip64EndOfCentralDirectoryRecord (line 1789) | int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong siz...
function Write_EndOfCentralDirectoryRecord (line 1830) | int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_cen...
function Write_GlobalComment (line 1879) | int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
function zipClose (line 1897) | extern int ZEXPORT zipClose (zipFile file, const char* global_comment)
function zipRemoveExtraInfoBlock (line 1966) | extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, s...
FILE: Revolved/minizip/zip.h
type zipFile__ (line 66) | typedef struct TagzipFile__ { int unused; } zipFile__;
type zipFile__ (line 67) | typedef zipFile__ *zipFile;
type voidp (line 69) | typedef voidp zipFile;
type tm_zip (line 89) | typedef struct tm_zip_s
type zip_fileinfo (line 99) | typedef struct
Condensed preview — 288 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (852K chars).
[
{
"path": ".gitignore",
"chars": 506,
"preview": "# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!defau"
},
{
"path": "LICENSE",
"chars": 1496,
"preview": "Copyright (c) 2014, Bartosz Ciechanowski\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with o"
},
{
"path": "README.md",
"chars": 1631,
"preview": "Revolved\n========\n\nThis is the complete source code of [Revolved](http://revolvedapp.com) – the 3D modelling app for the"
},
{
"path": "Revolved/AppDelegate.h",
"chars": 396,
"preview": "//\n// AppDelegate.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/AppDelegate.m",
"chars": 1412,
"preview": "//\n// AppDelegate.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/AxisVertex.h",
"chars": 308,
"preview": "//\n// AxisVertex.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.09.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/BCShader.h",
"chars": 438,
"preview": "//\n// BCShader.h\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bartosz Ciechanowski. All"
},
{
"path": "Revolved/BCShader.m",
"chars": 4296,
"preview": "//\n// BCShader.m\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bartosz Ciechanowski. All"
},
{
"path": "Revolved/BCShader_SubclassHooks.h",
"chars": 274,
"preview": "//\n// BCShader_SubclassHooks.h\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bartosz Cie"
},
{
"path": "Revolved/Camera.h",
"chars": 693,
"preview": "//\n// BCCamera.h\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bartosz Ciec"
},
{
"path": "Revolved/Camera.m",
"chars": 870,
"preview": "//\n// Camera.m\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bartosz Ciecha"
},
{
"path": "Revolved/CameraController.h",
"chars": 665,
"preview": "//\n// CameraController.h\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bart"
},
{
"path": "Revolved/CameraController.m",
"chars": 11376,
"preview": "//\n// CameraController.m\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 23.07.2013.\n// Copyright (c) 2013 Bart"
},
{
"path": "Revolved/Color.h",
"chars": 742,
"preview": "//\n// Color.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.08.2013.\n// Copyright (c) 2013 Bartosz Ciechan"
},
{
"path": "Revolved/Constants.h",
"chars": 347,
"preview": "//\n// Constants.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 05.08.2013.\n// Copyright (c) 2013 Bartosz Cie"
},
{
"path": "Revolved/DrawGestureRecognizer.h",
"chars": 310,
"preview": "//\n// DrawGestureRecognizer.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/DrawGestureRecognizer.m",
"chars": 1819,
"preview": "//\n// DrawGestureRecognizer.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/Geometry.h",
"chars": 1428,
"preview": "//\n// Geometry.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bartosz Ciec"
},
{
"path": "Revolved/Images.xcassets/AddFull.imageset/Contents.json",
"chars": 278,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"AddFull.png\"\n },\n {\n"
},
{
"path": "Revolved/Images.xcassets/AddPlus.imageset/Contents.json",
"chars": 278,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"AddPlus.png\"\n },\n {\n"
},
{
"path": "Revolved/Images.xcassets/AddSemiCircle.imageset/Contents.json",
"chars": 290,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"AddSemiCircle.png\"\n },\n"
},
{
"path": "Revolved/Images.xcassets/AppIcon.appiconset/Contents.json",
"chars": 966,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"ipad\",\n \"size\" : \"29x29\",\n \"scale\" : \"1x\"\n },\n {\n \"idiom\" :"
},
{
"path": "Revolved/Images.xcassets/BackButton.imageset/Contents.json",
"chars": 284,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"BackButton.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/Camera.imageset/Contents.json",
"chars": 276,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Camera.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/CloneButton.imageset/Contents.json",
"chars": 286,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"CloneButton.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/ConfirmButton.imageset/Contents.json",
"chars": 290,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"ConfirmButton.png\"\n },\n"
},
{
"path": "Revolved/Images.xcassets/CreditsButton.imageset/Contents.json",
"chars": 290,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"CreditsButton.png\"\n },\n"
},
{
"path": "Revolved/Images.xcassets/CreditsText.imageset/Contents.json",
"chars": 286,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"CreditsText.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/DeclineButton.imageset/Contents.json",
"chars": 290,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"DeclineButton.png\"\n },\n"
},
{
"path": "Revolved/Images.xcassets/Dots.imageset/Contents.json",
"chars": 272,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Dots.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/DotsSelected.imageset/Contents.json",
"chars": 288,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"DotsSelected.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/Empty.imageset/Contents.json",
"chars": 274,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Empty.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/Facebook.imageset/Contents.json",
"chars": 280,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Facebook.png\"\n },\n {"
},
{
"path": "Revolved/Images.xcassets/Gear.imageset/Contents.json",
"chars": 272,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Gear.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/LaunchImage.launchimage/Contents.json",
"chars": 1316,
"preview": "{\n \"images\" : [\n {\n \"orientation\" : \"portrait\",\n \"idiom\" : \"ipad\",\n \"extent\" : \"full-screen\",\n \""
},
{
"path": "Revolved/Images.xcassets/Logo.imageset/Contents.json",
"chars": 272,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Logo.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/MailButton.imageset/Contents.json",
"chars": 284,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"MailButton.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/ObjFileIcon.imageset/Contents.json",
"chars": 286,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"ObjFileIcon.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/RateButton.imageset/Contents.json",
"chars": 284,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"RateButton.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/ReviewBegger.imageset/Contents.json",
"chars": 288,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"ReviewBegger.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/RvlvdFileIcon.imageset/Contents.json",
"chars": 290,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"RvlvdFileIcon.png\"\n },\n"
},
{
"path": "Revolved/Images.xcassets/Save.imageset/Contents.json",
"chars": 272,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Save.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/SegmentLimit.imageset/Contents.json",
"chars": 288,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"SegmentLimit.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/ShareButton.imageset/Contents.json",
"chars": 286,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"ShareButton.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/Stem.imageset/Contents.json",
"chars": 272,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Stem.png\"\n },\n {\n "
},
{
"path": "Revolved/Images.xcassets/StlFileIcon.imageset/Contents.json",
"chars": 286,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"StlFileIcon.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/TrashButton.imageset/Contents.json",
"chars": 286,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TrashButton.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/TrashCan.imageset/Contents.json",
"chars": 280,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TrashCan.png\"\n },\n {"
},
{
"path": "Revolved/Images.xcassets/TrashLid.imageset/Contents.json",
"chars": 280,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TrashLid.png\"\n },\n {"
},
{
"path": "Revolved/Images.xcassets/TutorialAxis.imageset/Contents.json",
"chars": 246,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialAxis.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/TutorialAxis3D.imageset/Contents.json",
"chars": 248,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialAxis3D.png\"\n },"
},
{
"path": "Revolved/Images.xcassets/TutorialButton.imageset/Contents.json",
"chars": 292,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialButton.png\"\n },"
},
{
"path": "Revolved/Images.xcassets/TutorialCloseButton.imageset/Contents.json",
"chars": 304,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialCloseButtong.png\"\n"
},
{
"path": "Revolved/Images.xcassets/TutorialControlPoint.imageset/Contents.json",
"chars": 254,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialControlPoint.png\"\n"
},
{
"path": "Revolved/Images.xcassets/TutorialEndPoint.imageset/Contents.json",
"chars": 250,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialEndPoint.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialFinishButton.imageset/Contents.json",
"chars": 304,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialFinishButton.png\"\n"
},
{
"path": "Revolved/Images.xcassets/TutorialGetToKnow.imageset/Contents.json",
"chars": 298,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialGetToKnow.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialHaveFun.imageset/Contents.json",
"chars": 294,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialHaveFun.png\"\n }"
},
{
"path": "Revolved/Images.xcassets/TutorialLine.imageset/Contents.json",
"chars": 246,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLine.png\"\n },\n "
},
{
"path": "Revolved/Images.xcassets/TutorialLineBend1.imageset/Contents.json",
"chars": 251,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLineBend1.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialLineBend3.imageset/Contents.json",
"chars": 251,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLineBend3.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialLineBend5.imageset/Contents.json",
"chars": 251,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLineBend5.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialLineBend7.imageset/Contents.json",
"chars": 251,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLineBend7.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialLineBend9.imageset/Contents.json",
"chars": 251,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLineBend9.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialLineLong.imageset/Contents.json",
"chars": 250,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialLineLong.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialRevolvedBack.imageset/Contents.json",
"chars": 254,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialRevolvedBack.png\"\n"
},
{
"path": "Revolved/Images.xcassets/TutorialRevolvedFront.imageset/Contents.json",
"chars": 255,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialRevolvedFront.png\""
},
{
"path": "Revolved/Images.xcassets/TutorialSegment1.imageset/Contents.json",
"chars": 250,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialSegment1.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialSegment2.imageset/Contents.json",
"chars": 250,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialSegment2.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialSegment3.imageset/Contents.json",
"chars": 250,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialSegment3.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialWheel.imageset/Contents.json",
"chars": 247,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialWheel.png\"\n },\n"
},
{
"path": "Revolved/Images.xcassets/TutorialiPadCamera.imageset/Contents.json",
"chars": 252,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialiPadCamera.png\"\n "
},
{
"path": "Revolved/Images.xcassets/TutorialiPadHomeBlack.imageset/Contents.json",
"chars": 255,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialiPadHomeBlack.png\""
},
{
"path": "Revolved/Images.xcassets/TutorialiPadHomeWhite.imageset/Contents.json",
"chars": 255,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"TutorialiPadHomeWhite.png\""
},
{
"path": "Revolved/Images.xcassets/Twitter.imageset/Contents.json",
"chars": 278,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\",\n \"filename\" : \"Twitter.png\"\n },\n {\n"
},
{
"path": "Revolved/LineVertex.h",
"chars": 309,
"preview": "//\n// LineVertex.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/MFMailComposeViewController+SendIfPossible.h",
"chars": 383,
"preview": "//\n// MFMailComposeViewController+SendIfPossible.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 24.09.2013.\n/"
},
{
"path": "Revolved/MFMailComposeViewController+SendIfPossible.m",
"chars": 1294,
"preview": "//\n// MFMailComposeViewController+SendIfPossible.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 24.09.2013.\n/"
},
{
"path": "Revolved/NSArray+Functional.h",
"chars": 385,
"preview": "//\n// NSArray+Functional.h\n// Ico\n//\n// Created by Bartosz Ciechanowski on 21.07.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/NSArray+Functional.m",
"chars": 894,
"preview": "//\n// NSArray+Functional.m\n// Ico\n//\n// Created by Bartosz Ciechanowski on 21.07.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/NSError+RevolvedErrors.h",
"chars": 318,
"preview": "//\n// NSError+RevolvedErrors.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 01.09.2013.\n// Copyright (c) 201"
},
{
"path": "Revolved/NSError+RevolvedErrors.m",
"chars": 726,
"preview": "//\n// NSError+RevolvedErrors.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 01.09.2013.\n// Copyright (c) 201"
},
{
"path": "Revolved/NSMapTable+BlockEnumeration.h",
"chars": 344,
"preview": "//\n// NSMapTable+BlockEnumeration.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c"
},
{
"path": "Revolved/NSMapTable+BlockEnumeration.m",
"chars": 513,
"preview": "//\n// NSMapTable+BlockEnumeration.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c"
},
{
"path": "Revolved/NSMutableArray+MoveObject.h",
"chars": 330,
"preview": "//\n// NSMutableArray+MoveObject.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.09.2013.\n// Copyright (c) "
},
{
"path": "Revolved/NSMutableArray+MoveObject.m",
"chars": 480,
"preview": "//\n// NSMutableArray+MoveObject.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.09.2013.\n// Copyright (c) "
},
{
"path": "Revolved/NSMutableOrderedSet+MoveObject.h",
"chars": 340,
"preview": "//\n// NSMutableOrderedSet+MoveObject.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.09.2013.\n// Copyright"
},
{
"path": "Revolved/NSMutableOrderedSet+MoveObject.m",
"chars": 495,
"preview": "//\n// NSMutableOrderedSet+MoveObject.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.09.2013.\n// Copyright"
},
{
"path": "Revolved/PointVertex.h",
"chars": 332,
"preview": "//\n// PointVertex.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVAddProgressView.h",
"chars": 395,
"preview": "//\n// RVAddProgressView.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.09.2013.\n// Copyright (c) 2013 Bar"
},
{
"path": "Revolved/RVAddProgressView.m",
"chars": 4435,
"preview": "//\n// RVAddProgressView.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.09.2013.\n// Copyright (c) 2013 Bar"
},
{
"path": "Revolved/RVAnchorPoint.h",
"chars": 267,
"preview": "//\n// RVAnchorPoint.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVAnchorPoint.m",
"chars": 274,
"preview": "//\n// RVAnchorPoint.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVAnimation.h",
"chars": 943,
"preview": "//\n// RVAnimation.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVAnimation.m",
"chars": 249,
"preview": "//\n// RVAnimation.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVAnimation_Private.h",
"chars": 325,
"preview": "//\n// RVAnimation_Private.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 B"
},
{
"path": "Revolved/RVAnimator.h",
"chars": 549,
"preview": "//\n// RVAnimator.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVAnimator.m",
"chars": 7588,
"preview": "//\n// RVAnimator.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVAxisMeshController.h",
"chars": 316,
"preview": "//\n// RVAxisMeshController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.09.2013.\n// Copyright (c) 2013 "
},
{
"path": "Revolved/RVAxisMeshController.m",
"chars": 4202,
"preview": "//\n// RVAxisMeshController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.09.2013.\n// Copyright (c) 2013 "
},
{
"path": "Revolved/RVAxisShader.fsh",
"chars": 84,
"preview": "\nvarying lowp vec4 colorVarying;\n\nvoid main()\n{\n gl_FragColor = colorVarying;\n}\n\n"
},
{
"path": "Revolved/RVAxisShader.h",
"chars": 327,
"preview": "//\n// RVAxisShader.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.09.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVAxisShader.m",
"chars": 671,
"preview": "//\n// RVAxisShader.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.09.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVAxisShader.vsh",
"chars": 280,
"preview": "\nattribute vec4 position;\nattribute vec4 color;\n\nvarying vec4 colorVarying;\n\nuniform mat4 viewProjectionModelMatrix;\nuni"
},
{
"path": "Revolved/RVAxisSprite.h",
"chars": 306,
"preview": "//\n// RVAxisSprite.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.09.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVAxisSprite.m",
"chars": 222,
"preview": "//\n// RVAxisSprite.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.09.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVBendTutorialPage.h",
"chars": 246,
"preview": "//\n// RVBendTutorialPage.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.10.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVBendTutorialPage.m",
"chars": 1789,
"preview": "//\n// RVBendTutorialPage.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.10.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVBendTutorialPage.xib",
"chars": 3957,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVColorPicker.h",
"chars": 516,
"preview": "//\n// RVColorPicker.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 14.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVColorPicker.m",
"chars": 11674,
"preview": "//\n// RVColorPicker.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 14.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVColorPickerButton.h",
"chars": 239,
"preview": "//\n// RVColorPickerButton.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 06.10.2013.\n// Copyright (c) 2013 B"
},
{
"path": "Revolved/RVColorPickerButton.m",
"chars": 589,
"preview": "//\n// RVColorPickerButton.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 06.10.2013.\n// Copyright (c) 2013 B"
},
{
"path": "Revolved/RVColorProvider.h",
"chars": 563,
"preview": "//\n// RVColorProvider.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 18.08.2013.\n// Copyright (c) 2013 Barto"
},
{
"path": "Revolved/RVColorProvider.m",
"chars": 3047,
"preview": "//\n// RVColorProvider.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 18.08.2013.\n// Copyright (c) 2013 Barto"
},
{
"path": "Revolved/RVControlPoint.h",
"chars": 224,
"preview": "//\n// RVControlPoint.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVControlPoint.m",
"chars": 278,
"preview": "//\n// RVControlPoint.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVCreditsViewController.h",
"chars": 273,
"preview": "//\n// RVCreditsViewController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.09.2013.\n// Copyright (c) 20"
},
{
"path": "Revolved/RVCreditsViewController.m",
"chars": 5958,
"preview": "//\n// RVCreditsViewController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.09.2013.\n// Copyright (c) 20"
},
{
"path": "Revolved/RVCreditsViewController.xib",
"chars": 5595,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVDeleteView.h",
"chars": 346,
"preview": "//\n// RVDeleteView.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 16.08.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVDeleteView.m",
"chars": 3377,
"preview": "//\n// RVDeleteView.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 16.08.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVDrawController.h",
"chars": 2385,
"preview": "//\n// DrawController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVDrawController.m",
"chars": 13885,
"preview": "//\n// DrawController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVDrawViewController.h",
"chars": 1573,
"preview": "//\n// DrawViewController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVDrawViewController.m",
"chars": 22371,
"preview": "//\n// DrawViewController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVDrawViewController.xib",
"chars": 3362,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVDrawingTutorialPage.h",
"chars": 252,
"preview": "//\n// RVDrawingTutorialPage.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 01.10.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/RVDrawingTutorialPage.m",
"chars": 3471,
"preview": "//\n// RVDrawingTutorialPage.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 01.10.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/RVDrawingTutorialPage.xib",
"chars": 4437,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVEndPoint.h",
"chars": 216,
"preview": "//\n// RVEndPoint.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVEndPoint.m",
"chars": 262,
"preview": "//\n// RVEndPoint.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 15.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVExportViewController.h",
"chars": 351,
"preview": "//\n// RVExportViewController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 27.12.2013.\n// Copyright (c) 201"
},
{
"path": "Revolved/RVExportViewController.m",
"chars": 5765,
"preview": "//\n// RVExportViewController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 27.12.2013.\n// Copyright (c) 201"
},
{
"path": "Revolved/RVExportViewController.xib",
"chars": 6171,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVExporter.h",
"chars": 387,
"preview": "//\n// RVExporter.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.11.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVExporter.m",
"chars": 629,
"preview": "//\n// RVExporter.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.11.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVFinishTutorialPage.h",
"chars": 306,
"preview": "//\n// RVFinishTutorialPage.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.10.2013.\n// Copyright (c) 2013 "
},
{
"path": "Revolved/RVFinishTutorialPage.m",
"chars": 920,
"preview": "//\n// RVFinishTutorialPage.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.10.2013.\n// Copyright (c) 2013 "
},
{
"path": "Revolved/RVFinishTutorialPage.xib",
"chars": 2424,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVFloatAnimation.h",
"chars": 472,
"preview": "//\n// RVFloatAnimation.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 Bart"
},
{
"path": "Revolved/RVFloatAnimation.m",
"chars": 660,
"preview": "//\n// RVFloatAnimation.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 25.08.2013.\n// Copyright (c) 2013 Bart"
},
{
"path": "Revolved/RVGuideline.h",
"chars": 430,
"preview": "//\n// RVGuideline.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 11.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVGuideline.m",
"chars": 217,
"preview": "//\n// RVGuideline.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 11.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVGuidelineDotSprite.h",
"chars": 353,
"preview": "//\n// RVGuidelineDotSprite.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 04.09.2013.\n// Copyright (c) 2013 "
},
{
"path": "Revolved/RVGuidelineDotSprite.m",
"chars": 244,
"preview": "//\n// RVGuidelineDotSprite.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 04.09.2013.\n// Copyright (c) 2013 "
},
{
"path": "Revolved/RVGuidlineDotMeshController.h",
"chars": 376,
"preview": "//\n// RVGuidlineDotMeshController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 04.09.2013.\n// Copyright (c"
},
{
"path": "Revolved/RVGuidlineDotMeshController.m",
"chars": 3617,
"preview": "//\n// RVGuidlineDotMeshController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 04.09.2013.\n// Copyright (c"
},
{
"path": "Revolved/RVLineMeshController.h",
"chars": 349,
"preview": "//\n// LineController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVLineMeshController.m",
"chars": 4728,
"preview": "//\n// LineController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVLineShader.fsh",
"chars": 84,
"preview": "\nvarying lowp vec4 colorVarying;\n\nvoid main()\n{\n gl_FragColor = colorVarying;\n}\n\n"
},
{
"path": "Revolved/RVLineShader.h",
"chars": 278,
"preview": "//\n// LineShader.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVLineShader.m",
"chars": 587,
"preview": "//\n// LineShader.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 07.08.2013.\n// Copyright (c) 2013 Bartosz Ci"
},
{
"path": "Revolved/RVLineShader.vsh",
"chars": 212,
"preview": "\nattribute vec4 position;\nattribute vec4 color;\n\nvarying vec4 colorVarying;\n\nuniform mat4 viewProjectionMatrix;\n\nvoid ma"
},
{
"path": "Revolved/RVLineSprite.h",
"chars": 482,
"preview": "//\n// RVLineSprite.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 19.08.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVLineSprite.m",
"chars": 220,
"preview": "//\n// RVLineSprite.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 19.08.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVMeshController.h",
"chars": 364,
"preview": "//\n// RVMeshController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bart"
},
{
"path": "Revolved/RVMeshController.m",
"chars": 372,
"preview": "//\n// RVMeshController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bart"
},
{
"path": "Revolved/RVMeshController_Private.h",
"chars": 377,
"preview": "//\n// RVMeshController_Private.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2"
},
{
"path": "Revolved/RVModel.h",
"chars": 287,
"preview": "//\n// RVModel.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bartosz Ciech"
},
{
"path": "Revolved/RVModel.m",
"chars": 336,
"preview": "//\n// RVModel.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bartosz Ciech"
},
{
"path": "Revolved/RVModelButtonsView.h",
"chars": 493,
"preview": "//\n// RVModelButtonsView.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 17.09.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVModelButtonsView.m",
"chars": 4213,
"preview": "//\n// RVModelButtonsView.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 17.09.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVModelButtonsView.xib",
"chars": 8013,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVModelCell.h",
"chars": 402,
"preview": "//\n// RVModelCell.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVModelCell.m",
"chars": 1794,
"preview": "//\n// RVModelCell.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bartosz C"
},
{
"path": "Revolved/RVModelManager.h",
"chars": 721,
"preview": "//\n// RVModelManager.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVModelManager.m",
"chars": 8959,
"preview": "//\n// RVFileManager.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVModelMeshController.h",
"chars": 372,
"preview": "//\n// MeshController.h\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 24.07.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVModelMeshController.m",
"chars": 6642,
"preview": "//\n// MeshController.m\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 24.07.2013.\n// Copyright (c) 2013 Bartos"
},
{
"path": "Revolved/RVModelMetadata.h",
"chars": 421,
"preview": "//\n// RVModelMetadata.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 01.09.2013.\n// Copyright (c) 2013 Barto"
},
{
"path": "Revolved/RVModelMetadata.m",
"chars": 705,
"preview": "//\n// RVModelMetadata.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 01.09.2013.\n// Copyright (c) 2013 Barto"
},
{
"path": "Revolved/RVModelSerializer.h",
"chars": 410,
"preview": "//\n// RVModelSerializer.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bar"
},
{
"path": "Revolved/RVModelSerializer.m",
"chars": 8174,
"preview": "//\n// RVModelSerializer.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 23.08.2013.\n// Copyright (c) 2013 Bar"
},
{
"path": "Revolved/RVModelShader.fsh",
"chars": 226,
"preview": "\nvarying lowp vec4 colorVarying;\nvarying lowp vec2 texCoordVarying;\n\nuniform lowp sampler2D texSampler;\n\nvoid main()\n{\n "
},
{
"path": "Revolved/RVModelShader.h",
"chars": 437,
"preview": "//\n// PatternShader.h\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 25.07.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVModelShader.m",
"chars": 994,
"preview": "//\n// PatternShader.m\n// Patterns\n//\n// Created by Bartosz Ciechanowski on 25.07.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVModelShader.vsh",
"chars": 916,
"preview": "#extension GL_EXT_draw_instanced : require\n\nattribute vec4 position;\nattribute vec3 normal;\nattribute vec4 color;\nattrib"
},
{
"path": "Revolved/RVModelSprite.h",
"chars": 657,
"preview": "//\n// RVModelSprite.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 24.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVModelSprite.m",
"chars": 494,
"preview": "//\n// RVModelSprite.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 24.08.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVModelViewController.h",
"chars": 1308,
"preview": "//\n// RVModelViewController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.08.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/RVModelViewController.m",
"chars": 9100,
"preview": "//\n// RootViewController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 03.08.2013.\n// Copyright (c) 2013 Ba"
},
{
"path": "Revolved/RVModelViewController.xib",
"chars": 1460,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVModelsViewController.h",
"chars": 2199,
"preview": "//\n// RVModelsViewController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 20.08.2013.\n// Copyright (c) 201"
},
{
"path": "Revolved/RVModelsViewController.m",
"chars": 44483,
"preview": "//\n// RVModelsViewController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 20.08.2013.\n// Copyright (c) 201"
},
{
"path": "Revolved/RVModelsViewController.xib",
"chars": 5564,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVOBJExporter.h",
"chars": 228,
"preview": "//\n// RVOBJExporter.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 16.11.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVOBJExporter.m",
"chars": 3270,
"preview": "//\n// RVOBJExporter.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 16.11.2013.\n// Copyright (c) 2013 Bartosz"
},
{
"path": "Revolved/RVOpenGLView.h",
"chars": 643,
"preview": "//\n// RVOpenGLView.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 21.08.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVOpenGLView.m",
"chars": 9284,
"preview": "//\n// RVOpenGLView.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 21.08.2013.\n// Copyright (c) 2013 Bartosz "
},
{
"path": "Revolved/RVPassForwardView.h",
"chars": 283,
"preview": "//\n// RVPassForwardView.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.10.2013.\n// Copyright (c) 2013 Bar"
},
{
"path": "Revolved/RVPassForwardView.m",
"chars": 456,
"preview": "//\n// RVPassForwardView.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 02.10.2013.\n// Copyright (c) 2013 Bar"
},
{
"path": "Revolved/RVPictureViewController.h",
"chars": 320,
"preview": "//\n// RVPictureViewController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 20.08.2013.\n// Copyright (c) 20"
},
{
"path": "Revolved/RVPictureViewController.m",
"chars": 5690,
"preview": "//\n// RVPictureViewController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 20.08.2013.\n// Copyright (c) 20"
},
{
"path": "Revolved/RVPictureViewController.xib",
"chars": 8578,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB\" "
},
{
"path": "Revolved/RVPoint.h",
"chars": 711,
"preview": "//\n// RVPoint.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bartosz Ciech"
},
{
"path": "Revolved/RVPoint.m",
"chars": 600,
"preview": "//\n// RVPoint.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013 Bartosz Ciech"
},
{
"path": "Revolved/RVPointMeshController.h",
"chars": 360,
"preview": "//\n// RVPointMeshController.h\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/RVPointMeshController.m",
"chars": 4344,
"preview": "//\n// RVPointMeshController.m\n// Revolved\n//\n// Created by Bartosz Ciechanowski on 10.08.2013.\n// Copyright (c) 2013"
},
{
"path": "Revolved/RVPointShader.fsh",
"chars": 245,
"preview": "\nvarying lowp vec2 texCoordVarying;\nvarying lowp float alphaVarying;\n\nuniform lowp sampler2D texSampler;\n\nvoid main()\n{\n"
}
]
// ... and 88 more files (download for full content)
About this extraction
This page contains the full source code of the Ciechan/Revolved GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 288 files (777.4 KB), approximately 223.3k tokens, and a symbol index with 150 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.