├── .gitignore ├── README.md ├── addon_config.mk ├── example ├── Makefile ├── Project.xcconfig ├── addons.make ├── bin │ └── data │ │ └── .gitkeep ├── config.make ├── example.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── example Debug.xcscheme │ │ └── example Release.xcscheme ├── openFrameworks-Info.plist └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── ofxaddons_thumbnail.png ├── screenshot.png ├── src ├── Drawing │ ├── Areas │ │ ├── Canvas.cpp │ │ ├── Canvas.h │ │ ├── MaskFrame.cpp │ │ ├── MaskFrame.h │ │ ├── TextArea.cpp │ │ └── TextArea.h │ ├── Collections │ │ ├── CanvasContents.cpp │ │ ├── CanvasContents.h │ │ ├── SafeDeque.cpp │ │ └── SafeDeque.h │ ├── Homography.cpp │ ├── Homography.h │ ├── Mouse.cpp │ ├── Mouse.h │ └── Points │ │ ├── DragHandle.cpp │ │ ├── DragHandle.h │ │ ├── MaskPoint.cpp │ │ ├── MaskPoint.h │ │ ├── PointObject.cpp │ │ └── PointObject.h ├── Presets.cpp ├── Presets.h ├── Storage │ ├── Xml.cpp │ └── Xml.h ├── ofExtensions.cpp ├── ofExtensions.h ├── ofxProjectionMask.cpp └── ofxProjectionMask.h └── vimeo.png /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # ofApp 3 | ######################### 4 | */bin/data/ProjectionMasks/development/*-* 5 | */bin/data/ProjectionMasks/production/*-* 6 | 7 | ######################### 8 | # openFrameworks patterns 9 | ######################### 10 | 11 | # build files 12 | openFrameworks.a 13 | openFrameworksDebug.a 14 | openFrameworksUniversal.a 15 | libs/openFrameworksCompiled/lib/*/* 16 | !libs/openFrameworksCompiled/lib/*/.gitkeep 17 | 18 | # apothecary 19 | scripts/apothecary/build 20 | 21 | # rule to avoid non-official addons going into git 22 | # see addons/.gitignore 23 | addons/* 24 | 25 | # rule to avoid non-official apps going into git 26 | # see apps/.gitignore 27 | apps/* 28 | 29 | # also, see examples/.gitignore 30 | 31 | ######################### 32 | # general 33 | ######################### 34 | 35 | [Bb]uild/ 36 | [Oo]bj/ 37 | *.o 38 | [Dd]ebug*/ 39 | [Rr]elease*/ 40 | *.mode* 41 | *.app/ 42 | *.pyc 43 | .svn/ 44 | *.log 45 | *.cpp.eep 46 | *.cpp.elf 47 | *.cpp.hex 48 | 49 | ######################### 50 | # IDE 51 | ######################### 52 | 53 | # XCode 54 | *.pbxuser 55 | *.perspective 56 | *.perspectivev3 57 | *.mode1v3 58 | *.mode2v3 59 | # XCode 4 60 | xcuserdata 61 | *.xcworkspace 62 | 63 | # Code::Blocks 64 | *.depend 65 | *.layout 66 | 67 | # Visual Studio 68 | *.sdf 69 | *.opensdf 70 | *.suo 71 | *.pdb 72 | *.ilk 73 | *.aps 74 | *.exp 75 | *.exe 76 | *.lib 77 | *.dll 78 | ipch/ 79 | 80 | # Eclipse 81 | .metadata 82 | local.properties 83 | .externalToolBuilders 84 | 85 | ######################### 86 | # operating system 87 | ######################### 88 | 89 | # Linux 90 | *~ 91 | # KDE 92 | .directory 93 | .AppleDouble 94 | 95 | # OSX 96 | .DS_Store 97 | *.swp 98 | *~.nib 99 | # Thumbnails 100 | ._* 101 | 102 | # Windows 103 | # Windows image file caches 104 | Thumbs.db 105 | # Folder config file 106 | Desktop.ini 107 | 108 | # Android 109 | .csettings 110 | /libs/openFrameworksCompiled/project/android/paths.make 111 | 112 | ######################### 113 | # miscellaneous 114 | ######################### 115 | 116 | .mailmap 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ofxProjectionMask 2 | ================= 3 | ofxProjectionMask is an addon allowing you to mask projected light over real-world objects, from anything you draw in [openFrameworks](http://openframeworks.cc/). 4 | 5 | ![A screenshot of the mask designer UI](screenshot.png) 6 | 7 | Unlike projection mapping, this is not about creating the illusion that a light surface is 'mapped onto' a physical object; instead this addon simply prevents the light from 'bleeding' outside of the mask. 8 | 9 | In other words, this addon separates out the [masking from the mapping](http://jahya.net/blog/projection-masking-not-projection), and focuses on the former rather than the latter. 10 | 11 | Why? 12 | ---- 13 | Sometimes you [don't want to map, you just want to mask](http://jahya.net/blog/?2014-10-projection-masking-not-projection). Sometimes you want the light to 'drape' over an object at it's original rendered resolution. Sometimes you want to transform the media in a way unrelated to it's masking. This addon is for those occasions. 14 | 15 | [![See a demo of the addon over rocks](/vimeo.png)](https://vimeo.com/109387735) 16 | 17 | Also, there is a difference in emphasis here. This isn't about 'creating an illusion', this is about experimenting with projected media in the form of light. From this perspective, things don't have to match up in the way we expect them to in the real world - in fact it's better if they don't. 18 | 19 | However, you do a have a set of options for how you would like the light to be shaped over the object, including homography and stretch. These options are explained below. 20 | 21 | How does it work? 22 | ----------------- 23 | Use the design UI (illustrated above) to carve out shapes at runtime. The UI will be fed by patterns you draw patterns into the addon like this: 24 | 25 | ```cpp 26 | ofxProjectionMask designer; 27 | ofxLayerMask *pattern1, *pattern2; 28 | 29 | void ofApp::setup(){ 30 | designer.setup(); 31 | pattern1 = designer.newPattern(640, 480); //Each pattern can have 32 | pattern2 = designer.newPattern(1024, 1024); //unique dimensions 33 | } 34 | 35 | void ofApp::update(){ 36 | pattern1->begin(); 37 | { 38 | //Draw a pattern here 39 | } 40 | pattern1->end(); 41 | 42 | pattern2->begin(); 43 | { 44 | //Draw another pattern 45 | } 46 | pattern2->end(); 47 | } 48 | 49 | void ofApp::draw(){ 50 | designer.draw(); 51 | } 52 | ``` 53 | 54 | You can choose from three drawing modes, which apply to the live canvas and change how your pattern is rendered. 55 | 56 | ```cpp 57 | void ofApp::setup(){ 58 | designer.setup(DO_NOT_STRETCH); 59 | //or 60 | designer.setup(STRETCH_TO_MASKFRAME); 61 | //or 62 | designer.setup(HOMOGRAPHY); 63 | } 64 | ``` 65 | 66 | The drawing modes can only be set on `setup()` and apply to all patterns in the `ofxProjectionMask` instance. Each option affects how patterns are rendered: 67 | 68 | - ### DO_NOT_STRETCH 69 | Draw the pattern exactly as specified, pixel-perfect to how it was drawn into the pattern buffer 70 | 71 | - ### STRETCH_TO_MASKFRAME 72 | Stretch the given pattern so that it matches the boundaries of the 'mask frame' which contains it - you will learn about mask frames when you launch the UI 73 | 74 | - ### HOMOGRAPHY 75 | Stretch the pattern so that it matches four arbitrary points within a mask frame. This is the closest we get to projection *mapping*, this essentially allows you to 'pre-warp' your pattern to match a rectangular target surface 76 | 77 | Note: HOMOGRAPHY mode only works when you have exactly 4 mask points inside your mask frame. If you have more than 4 then it falls back to DO_NOT_STRETCH 78 | 79 | Check out the `ofApp.cpp` file for a full set of instructions and examples. 80 | 81 | Can I run this fullscreen and with a projector? 82 | ----------------------------------------------- 83 | Of course! That's what this is all about. Check out `ofApp.cpp` for full instructions. 84 | 85 | Versions 86 | -------- 87 | - 0.3.1 88 | - Removes dependency on ofxSecondWindow 89 | - Bumps OF support to OF v0.10.0 90 | - Simplifies usage via OF listeners 91 | - 0.3.0 92 | - Switches rendering from ofxTriangle to ofxLayerMask 93 | - Adds support for homography and stretching to mask frames 94 | - Simplifies API for drawing patterns 95 | - Moves example patterns to `ofApp.cpp` to demonstrate 96 | - 0.2.0 97 | - New screen management with ofxSecondWindow 98 | - Splits XML storage locations based on preset mode 99 | - Drops support for cycling between 'development' and 'production' mode presets at runtime. Now you have to select one mode or another before compiling, as described in `ofApp.cpp` 100 | - 0.1.0 Initial release 101 | 102 | Project dependencies 103 | -------------------- 104 | - [ofxLayerMask](https://github.com/microcosm/ofxLayerMask) to mask patterns based on the points you select 105 | - [ofxXmlSettings](http://www.openframeworks.cc/documentation/ofxXmlSettings/ofxXmlSettings.html) to store masks as you draw them - it's part of the openFrameworks core 106 | - Tested against [openFrameworks 0.10.0](http://openframeworks.cc/download/) 107 | 108 | With thanks 109 | ----------- 110 | This codebase was created with support from [I-Park Foundation](http://www.i-park.org/) and the [Contemporary Artist Center](http://www.cactroy.org/). -------------------------------------------------------------------------------- /addon_config.mk: -------------------------------------------------------------------------------- 1 | meta: 2 | ADDON_NAME = ofxProjectionMask 3 | ADDON_DESCRIPTION = Projection mapping without the mapping 4 | ADDON_AUTHOR = Andrew McWilliams 5 | ADDON_TAGS = mask projection-mask projection-map projection-mapping 6 | ADDON_URL = http://github.com/microcosm/ofxProjectionMask 7 | 8 | common: 9 | ADDON_DEPENDENCIES = ofxXmlSettings ofxTriangle -------------------------------------------------------------------------------- /example/Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=$(realpath ../../..) 10 | endif 11 | 12 | # call the project makefile! 13 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 14 | -------------------------------------------------------------------------------- /example/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_CFLAGS = $(OF_CORE_CFLAGS) 17 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 18 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 19 | -------------------------------------------------------------------------------- /example/addons.make: -------------------------------------------------------------------------------- 1 | ofxLayerMask 2 | ofxProjectionMask 3 | ofxXmlSettings 4 | -------------------------------------------------------------------------------- /example/bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microcosm/ofxProjectionMask/300750e49d425d91964e1b61602d9b2f071aaba5/example/bin/data/.gitkeep -------------------------------------------------------------------------------- /example/config.make: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # CONFIGURE PROJECT MAKEFILE (optional) 3 | # This file is where we make project specific configurations. 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # OF ROOT 8 | # The location of your root openFrameworks installation 9 | # (default) OF_ROOT = ../../.. 10 | ################################################################################ 11 | # OF_ROOT = ../../.. 12 | 13 | ################################################################################ 14 | # PROJECT ROOT 15 | # The location of the project - a starting place for searching for files 16 | # (default) PROJECT_ROOT = . (this directory) 17 | # 18 | ################################################################################ 19 | # PROJECT_ROOT = . 20 | 21 | ################################################################################ 22 | # PROJECT SPECIFIC CHECKS 23 | # This is a project defined section to create internal makefile flags to 24 | # conditionally enable or disable the addition of various features within 25 | # this makefile. For instance, if you want to make changes based on whether 26 | # GTK is installed, one might test that here and create a variable to check. 27 | ################################################################################ 28 | # None 29 | 30 | ################################################################################ 31 | # PROJECT EXTERNAL SOURCE PATHS 32 | # These are fully qualified paths that are not within the PROJECT_ROOT folder. 33 | # Like source folders in the PROJECT_ROOT, these paths are subject to 34 | # exlclusion via the PROJECT_EXLCUSIONS list. 35 | # 36 | # (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) 37 | # 38 | # Note: Leave a leading space when adding list items with the += operator 39 | ################################################################################ 40 | # PROJECT_EXTERNAL_SOURCE_PATHS = 41 | 42 | ################################################################################ 43 | # PROJECT EXCLUSIONS 44 | # These makefiles assume that all folders in your current project directory 45 | # and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations 46 | # to look for source code. The any folders or files that match any of the 47 | # items in the PROJECT_EXCLUSIONS list below will be ignored. 48 | # 49 | # Each item in the PROJECT_EXCLUSIONS list will be treated as a complete 50 | # string unless teh user adds a wildcard (%) operator to match subdirectories. 51 | # GNU make only allows one wildcard for matching. The second wildcard (%) is 52 | # treated literally. 53 | # 54 | # (default) PROJECT_EXCLUSIONS = (blank) 55 | # 56 | # Will automatically exclude the following: 57 | # 58 | # $(PROJECT_ROOT)/bin% 59 | # $(PROJECT_ROOT)/obj% 60 | # $(PROJECT_ROOT)/%.xcodeproj 61 | # 62 | # Note: Leave a leading space when adding list items with the += operator 63 | ################################################################################ 64 | # PROJECT_EXCLUSIONS = 65 | 66 | ################################################################################ 67 | # PROJECT LINKER FLAGS 68 | # These flags will be sent to the linker when compiling the executable. 69 | # 70 | # (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs 71 | # 72 | # Note: Leave a leading space when adding list items with the += operator 73 | ################################################################################ 74 | 75 | # Currently, shared libraries that are needed are copied to the 76 | # $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to 77 | # add a runtime path to search for those shared libraries, since they aren't 78 | # incorporated directly into the final executable application binary. 79 | # TODO: should this be a default setting? 80 | # PROJECT_LDFLAGS=-Wl,-rpath=./libs 81 | 82 | ################################################################################ 83 | # PROJECT DEFINES 84 | # Create a space-delimited list of DEFINES. The list will be converted into 85 | # CFLAGS with the "-D" flag later in the makefile. 86 | # 87 | # (default) PROJECT_DEFINES = (blank) 88 | # 89 | # Note: Leave a leading space when adding list items with the += operator 90 | ################################################################################ 91 | # PROJECT_DEFINES = 92 | 93 | ################################################################################ 94 | # PROJECT CFLAGS 95 | # This is a list of fully qualified CFLAGS required when compiling for this 96 | # project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS 97 | # defined in your platform specific core configuration files. These flags are 98 | # presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. 99 | # 100 | # (default) PROJECT_CFLAGS = (blank) 101 | # 102 | # Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in 103 | # your platform specific configuration file will be applied by default and 104 | # further flags here may not be needed. 105 | # 106 | # Note: Leave a leading space when adding list items with the += operator 107 | ################################################################################ 108 | # PROJECT_CFLAGS = 109 | 110 | ################################################################################ 111 | # PROJECT OPTIMIZATION CFLAGS 112 | # These are lists of CFLAGS that are target-specific. While any flags could 113 | # be conditionally added, they are usually limited to optimization flags. 114 | # These flags are added BEFORE the PROJECT_CFLAGS. 115 | # 116 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. 117 | # 118 | # (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) 119 | # 120 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. 121 | # 122 | # (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) 123 | # 124 | # Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the 125 | # PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration 126 | # file will be applied by default and further optimization flags here may not 127 | # be needed. 128 | # 129 | # Note: Leave a leading space when adding list items with the += operator 130 | ################################################################################ 131 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE = 132 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG = 133 | 134 | ################################################################################ 135 | # PROJECT COMPILERS 136 | # Custom compilers can be set for CC and CXX 137 | # (default) PROJECT_CXX = (blank) 138 | # (default) PROJECT_CC = (blank) 139 | # Note: Leave a leading space when adding list items with the += operator 140 | ################################################################################ 141 | # PROJECT_CXX = 142 | # PROJECT_CC = 143 | -------------------------------------------------------------------------------- /example/example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | archiveVersion 5 | 1 6 | classes 7 | 8 | objectVersion 9 | 46 10 | objects 11 | 12 | 933A2227713C720CEFF80FD9 13 | 14 | fileRef 15 | 2B40EDA85BEB63E46785BC29 16 | isa 17 | PBXBuildFile 18 | 19 | 2B40EDA85BEB63E46785BC29 20 | 21 | explicitFileType 22 | sourcecode.cpp.cpp 23 | fileEncoding 24 | 4 25 | isa 26 | PBXFileReference 27 | name 28 | tinyxml.cpp 29 | path 30 | ../../../addons/ofxXmlSettings/libs/tinyxml.cpp 31 | sourceTree 32 | SOURCE_ROOT 33 | 34 | 9D44DC88EF9E7991B4A09951 35 | 36 | fileRef 37 | 832BDC407620CDBA568B713D 38 | isa 39 | PBXBuildFile 40 | 41 | 832BDC407620CDBA568B713D 42 | 43 | explicitFileType 44 | sourcecode.cpp.cpp 45 | fileEncoding 46 | 4 47 | isa 48 | PBXFileReference 49 | name 50 | tinyxmlerror.cpp 51 | path 52 | ../../../addons/ofxXmlSettings/libs/tinyxmlerror.cpp 53 | sourceTree 54 | SOURCE_ROOT 55 | 56 | 5A4349E9754D6FA14C0F2A3A 57 | 58 | fileRef 59 | FC5DA1C87211D4F6377DA719 60 | isa 61 | PBXBuildFile 62 | 63 | FC5DA1C87211D4F6377DA719 64 | 65 | explicitFileType 66 | sourcecode.cpp.cpp 67 | fileEncoding 68 | 4 69 | isa 70 | PBXFileReference 71 | name 72 | tinyxmlparser.cpp 73 | path 74 | ../../../addons/ofxXmlSettings/libs/tinyxmlparser.cpp 75 | sourceTree 76 | SOURCE_ROOT 77 | 78 | 6E54289412D2D94F45A05113 79 | 80 | children 81 | 82 | B21E7E5F548EEA92F368040B 83 | FC5DA1C87211D4F6377DA719 84 | 832BDC407620CDBA568B713D 85 | 2B40EDA85BEB63E46785BC29 86 | 87 | isa 88 | PBXGroup 89 | name 90 | libs 91 | sourceTree 92 | <group> 93 | 94 | B21E7E5F548EEA92F368040B 95 | 96 | explicitFileType 97 | sourcecode.c.h 98 | fileEncoding 99 | 4 100 | isa 101 | PBXFileReference 102 | name 103 | tinyxml.h 104 | path 105 | ../../../addons/ofxXmlSettings/libs/tinyxml.h 106 | sourceTree 107 | SOURCE_ROOT 108 | 109 | 01DCC0911400F9ACF5B65578 110 | 111 | explicitFileType 112 | sourcecode.c.h 113 | fileEncoding 114 | 4 115 | isa 116 | PBXFileReference 117 | name 118 | ofxXmlSettings.h 119 | path 120 | ../../../addons/ofxXmlSettings/src/ofxXmlSettings.h 121 | sourceTree 122 | SOURCE_ROOT 123 | 124 | 6ECEF0D76BC33727823EADFF 125 | 126 | children 127 | 128 | 50DF87D612C5AAE17AAFA6C0 129 | 01DCC0911400F9ACF5B65578 130 | 131 | isa 132 | PBXGroup 133 | name 134 | src 135 | sourceTree 136 | <group> 137 | 138 | 1F4FB5C423662B96ADFDCC0B 139 | 140 | children 141 | 142 | 6ECEF0D76BC33727823EADFF 143 | 6E54289412D2D94F45A05113 144 | 145 | isa 146 | PBXGroup 147 | name 148 | ofxXmlSettings 149 | sourceTree 150 | <group> 151 | 152 | 63B57AC5BF4EF088491E0317 153 | 154 | fileRef 155 | 50DF87D612C5AAE17AAFA6C0 156 | isa 157 | PBXBuildFile 158 | 159 | 50DF87D612C5AAE17AAFA6C0 160 | 161 | explicitFileType 162 | sourcecode.cpp.cpp 163 | fileEncoding 164 | 4 165 | isa 166 | PBXFileReference 167 | name 168 | ofxXmlSettings.cpp 169 | path 170 | ../../../addons/ofxXmlSettings/src/ofxXmlSettings.cpp 171 | sourceTree 172 | SOURCE_ROOT 173 | 174 | 729840592B90C492EBB4EBDE 175 | 176 | fileRef 177 | 3270FA6535936663D879D198 178 | isa 179 | PBXBuildFile 180 | 181 | 3270FA6535936663D879D198 182 | 183 | explicitFileType 184 | sourcecode.cpp.cpp 185 | fileEncoding 186 | 4 187 | isa 188 | PBXFileReference 189 | name 190 | ofxProjectionMask.cpp 191 | path 192 | ../../../addons/ofxProjectionMask/src/ofxProjectionMask.cpp 193 | sourceTree 194 | SOURCE_ROOT 195 | 196 | 0DB54D1D7240859E40204C01 197 | 198 | fileRef 199 | 2B39DEF5C59E58FEFFC856B6 200 | isa 201 | PBXBuildFile 202 | 203 | 2B39DEF5C59E58FEFFC856B6 204 | 205 | explicitFileType 206 | sourcecode.cpp.cpp 207 | fileEncoding 208 | 4 209 | isa 210 | PBXFileReference 211 | name 212 | Xml.cpp 213 | path 214 | ../../../addons/ofxProjectionMask/src/Storage/Xml.cpp 215 | sourceTree 216 | SOURCE_ROOT 217 | 218 | 1F158FF081BDEBEC64CE78C5 219 | 220 | children 221 | 222 | F9004F0176BA58CF8044C484 223 | 2B39DEF5C59E58FEFFC856B6 224 | 225 | isa 226 | PBXGroup 227 | name 228 | Storage 229 | sourceTree 230 | <group> 231 | 232 | F9004F0176BA58CF8044C484 233 | 234 | explicitFileType 235 | sourcecode.c.h 236 | fileEncoding 237 | 4 238 | isa 239 | PBXFileReference 240 | name 241 | Xml.h 242 | path 243 | ../../../addons/ofxProjectionMask/src/Storage/Xml.h 244 | sourceTree 245 | SOURCE_ROOT 246 | 247 | 4C6FF3EB83F5CF320E2F44C0 248 | 249 | fileRef 250 | 046F82E0626C8EECEB03BA31 251 | isa 252 | PBXBuildFile 253 | 254 | 046F82E0626C8EECEB03BA31 255 | 256 | explicitFileType 257 | sourcecode.cpp.cpp 258 | fileEncoding 259 | 4 260 | isa 261 | PBXFileReference 262 | name 263 | Presets.cpp 264 | path 265 | ../../../addons/ofxProjectionMask/src/Presets.cpp 266 | sourceTree 267 | SOURCE_ROOT 268 | 269 | B64E87CE73C6EBBF8FFA7BEC 270 | 271 | explicitFileType 272 | sourcecode.c.h 273 | fileEncoding 274 | 4 275 | isa 276 | PBXFileReference 277 | name 278 | Presets.h 279 | path 280 | ../../../addons/ofxProjectionMask/src/Presets.h 281 | sourceTree 282 | SOURCE_ROOT 283 | 284 | C331C50B8B721DB309247421 285 | 286 | fileRef 287 | E40A5F0E03635F574CB851B0 288 | isa 289 | PBXBuildFile 290 | 291 | E40A5F0E03635F574CB851B0 292 | 293 | explicitFileType 294 | sourcecode.cpp.cpp 295 | fileEncoding 296 | 4 297 | isa 298 | PBXFileReference 299 | name 300 | ofExtensions.cpp 301 | path 302 | ../../../addons/ofxProjectionMask/src/ofExtensions.cpp 303 | sourceTree 304 | SOURCE_ROOT 305 | 306 | F552D018A402690FB077A090 307 | 308 | explicitFileType 309 | sourcecode.c.h 310 | fileEncoding 311 | 4 312 | isa 313 | PBXFileReference 314 | name 315 | ofxProjectionMask.h 316 | path 317 | ../../../addons/ofxProjectionMask/src/ofxProjectionMask.h 318 | sourceTree 319 | SOURCE_ROOT 320 | 321 | 03459BA2996723AFF8C5D4AE 322 | 323 | explicitFileType 324 | sourcecode.c.h 325 | fileEncoding 326 | 4 327 | isa 328 | PBXFileReference 329 | name 330 | CanvasContents.h 331 | path 332 | ../../../addons/ofxProjectionMask/src/Drawing/Collections/CanvasContents.h 333 | sourceTree 334 | SOURCE_ROOT 335 | 336 | F5CCFD748FE1DD6C1A740FA4 337 | 338 | explicitFileType 339 | sourcecode.c.h 340 | fileEncoding 341 | 4 342 | isa 343 | PBXFileReference 344 | name 345 | SafeDeque.h 346 | path 347 | ../../../addons/ofxProjectionMask/src/Drawing/Collections/SafeDeque.h 348 | sourceTree 349 | SOURCE_ROOT 350 | 351 | B26EE6708293A09D2B2E316A 352 | 353 | fileRef 354 | 046F07F04BE391B539FF7E98 355 | isa 356 | PBXBuildFile 357 | 358 | 046F07F04BE391B539FF7E98 359 | 360 | explicitFileType 361 | sourcecode.cpp.cpp 362 | fileEncoding 363 | 4 364 | isa 365 | PBXFileReference 366 | name 367 | SafeDeque.cpp 368 | path 369 | ../../../addons/ofxProjectionMask/src/Drawing/Collections/SafeDeque.cpp 370 | sourceTree 371 | SOURCE_ROOT 372 | 373 | 9AC2EDD3E37C434314776335 374 | 375 | children 376 | 377 | 610664C60D4DABBAF7644D37 378 | 046F07F04BE391B539FF7E98 379 | F5CCFD748FE1DD6C1A740FA4 380 | 03459BA2996723AFF8C5D4AE 381 | 382 | isa 383 | PBXGroup 384 | name 385 | Collections 386 | sourceTree 387 | <group> 388 | 389 | 09647D14A621C73DE9931223 390 | 391 | fileRef 392 | 610664C60D4DABBAF7644D37 393 | isa 394 | PBXBuildFile 395 | 396 | 610664C60D4DABBAF7644D37 397 | 398 | explicitFileType 399 | sourcecode.cpp.cpp 400 | fileEncoding 401 | 4 402 | isa 403 | PBXFileReference 404 | name 405 | CanvasContents.cpp 406 | path 407 | ../../../addons/ofxProjectionMask/src/Drawing/Collections/CanvasContents.cpp 408 | sourceTree 409 | SOURCE_ROOT 410 | 411 | 6571D6A30BABD8EA6C708E9B 412 | 413 | fileRef 414 | 628184A9BF426DA066FE888A 415 | isa 416 | PBXBuildFile 417 | 418 | 628184A9BF426DA066FE888A 419 | 420 | explicitFileType 421 | sourcecode.cpp.cpp 422 | fileEncoding 423 | 4 424 | isa 425 | PBXFileReference 426 | name 427 | Homography.cpp 428 | path 429 | ../../../addons/ofxProjectionMask/src/Drawing/Homography.cpp 430 | sourceTree 431 | SOURCE_ROOT 432 | 433 | BE473D6D6F903843A397DAEA 434 | 435 | explicitFileType 436 | sourcecode.c.h 437 | fileEncoding 438 | 4 439 | isa 440 | PBXFileReference 441 | name 442 | MaskPoint.h 443 | path 444 | ../../../addons/ofxProjectionMask/src/Drawing/Points/MaskPoint.h 445 | sourceTree 446 | SOURCE_ROOT 447 | 448 | D9F409CE2113AB08F0B59CED 449 | 450 | explicitFileType 451 | sourcecode.c.h 452 | fileEncoding 453 | 4 454 | isa 455 | PBXFileReference 456 | name 457 | DragHandle.h 458 | path 459 | ../../../addons/ofxProjectionMask/src/Drawing/Points/DragHandle.h 460 | sourceTree 461 | SOURCE_ROOT 462 | 463 | 9FCABFF231B041B5F4B145E3 464 | 465 | fileRef 466 | C207CD5E09DA359FDD8F0BFA 467 | isa 468 | PBXBuildFile 469 | 470 | C207CD5E09DA359FDD8F0BFA 471 | 472 | explicitFileType 473 | sourcecode.cpp.cpp 474 | fileEncoding 475 | 4 476 | isa 477 | PBXFileReference 478 | name 479 | MaskPoint.cpp 480 | path 481 | ../../../addons/ofxProjectionMask/src/Drawing/Points/MaskPoint.cpp 482 | sourceTree 483 | SOURCE_ROOT 484 | 485 | 3B96DE095864B8DB0144EDE4 486 | 487 | fileRef 488 | 8FB23526782349FEF09EF80D 489 | isa 490 | PBXBuildFile 491 | 492 | 8FB23526782349FEF09EF80D 493 | 494 | explicitFileType 495 | sourcecode.cpp.cpp 496 | fileEncoding 497 | 4 498 | isa 499 | PBXFileReference 500 | name 501 | DragHandle.cpp 502 | path 503 | ../../../addons/ofxProjectionMask/src/Drawing/Points/DragHandle.cpp 504 | sourceTree 505 | SOURCE_ROOT 506 | 507 | BBB68A8265F6404CF134058B 508 | 509 | fileRef 510 | EE0A37942F9AE36EFB55C224 511 | isa 512 | PBXBuildFile 513 | 514 | EE0A37942F9AE36EFB55C224 515 | 516 | explicitFileType 517 | sourcecode.cpp.cpp 518 | fileEncoding 519 | 4 520 | isa 521 | PBXFileReference 522 | name 523 | PointObject.cpp 524 | path 525 | ../../../addons/ofxProjectionMask/src/Drawing/Points/PointObject.cpp 526 | sourceTree 527 | SOURCE_ROOT 528 | 529 | B8C656E224502D36AD440ED3 530 | 531 | children 532 | 533 | 687FDC6F308E919DD5FC4C5C 534 | EE0A37942F9AE36EFB55C224 535 | 8FB23526782349FEF09EF80D 536 | C207CD5E09DA359FDD8F0BFA 537 | D9F409CE2113AB08F0B59CED 538 | BE473D6D6F903843A397DAEA 539 | 540 | isa 541 | PBXGroup 542 | name 543 | Points 544 | sourceTree 545 | <group> 546 | 547 | 687FDC6F308E919DD5FC4C5C 548 | 549 | explicitFileType 550 | sourcecode.c.h 551 | fileEncoding 552 | 4 553 | isa 554 | PBXFileReference 555 | name 556 | PointObject.h 557 | path 558 | ../../../addons/ofxProjectionMask/src/Drawing/Points/PointObject.h 559 | sourceTree 560 | SOURCE_ROOT 561 | 562 | A506CEE81D6CFA75C1CB4DA2 563 | 564 | explicitFileType 565 | sourcecode.c.h 566 | fileEncoding 567 | 4 568 | isa 569 | PBXFileReference 570 | name 571 | Mouse.h 572 | path 573 | ../../../addons/ofxProjectionMask/src/Drawing/Mouse.h 574 | sourceTree 575 | SOURCE_ROOT 576 | 577 | 244900C88898E50686F09114 578 | 579 | fileRef 580 | B96C481D7B4DF3DB53BEDE75 581 | isa 582 | PBXBuildFile 583 | 584 | B96C481D7B4DF3DB53BEDE75 585 | 586 | explicitFileType 587 | sourcecode.cpp.cpp 588 | fileEncoding 589 | 4 590 | isa 591 | PBXFileReference 592 | name 593 | Mouse.cpp 594 | path 595 | ../../../addons/ofxProjectionMask/src/Drawing/Mouse.cpp 596 | sourceTree 597 | SOURCE_ROOT 598 | 599 | B3C9BBA09800AAFF4752835D 600 | 601 | explicitFileType 602 | sourcecode.c.h 603 | fileEncoding 604 | 4 605 | isa 606 | PBXFileReference 607 | name 608 | Homography.h 609 | path 610 | ../../../addons/ofxProjectionMask/src/Drawing/Homography.h 611 | sourceTree 612 | SOURCE_ROOT 613 | 614 | CE3F473B577FE2766469EE0D 615 | 616 | explicitFileType 617 | sourcecode.c.h 618 | fileEncoding 619 | 4 620 | isa 621 | PBXFileReference 622 | name 623 | TextArea.h 624 | path 625 | ../../../addons/ofxProjectionMask/src/Drawing/Areas/TextArea.h 626 | sourceTree 627 | SOURCE_ROOT 628 | 629 | 423EF5CBEC8650CAC82B97F7 630 | 631 | explicitFileType 632 | sourcecode.c.h 633 | fileEncoding 634 | 4 635 | isa 636 | PBXFileReference 637 | name 638 | Canvas.h 639 | path 640 | ../../../addons/ofxProjectionMask/src/Drawing/Areas/Canvas.h 641 | sourceTree 642 | SOURCE_ROOT 643 | 644 | 161C42E81468A0FCD634E19A 645 | 646 | explicitFileType 647 | sourcecode.c.h 648 | fileEncoding 649 | 4 650 | isa 651 | PBXFileReference 652 | name 653 | MaskFrame.h 654 | path 655 | ../../../addons/ofxProjectionMask/src/Drawing/Areas/MaskFrame.h 656 | sourceTree 657 | SOURCE_ROOT 658 | 659 | B6A612F76CCE330A56118A28 660 | 661 | fileRef 662 | A3C5D360A115AF05D2BA2AEC 663 | isa 664 | PBXBuildFile 665 | 666 | A3C5D360A115AF05D2BA2AEC 667 | 668 | explicitFileType 669 | sourcecode.cpp.cpp 670 | fileEncoding 671 | 4 672 | isa 673 | PBXFileReference 674 | name 675 | Canvas.cpp 676 | path 677 | ../../../addons/ofxProjectionMask/src/Drawing/Areas/Canvas.cpp 678 | sourceTree 679 | SOURCE_ROOT 680 | 681 | F7A71601C83BF7AFD88C7B89 682 | 683 | fileRef 684 | 1E0871A58D8655794E9662B9 685 | isa 686 | PBXBuildFile 687 | 688 | 1E0871A58D8655794E9662B9 689 | 690 | explicitFileType 691 | sourcecode.cpp.cpp 692 | fileEncoding 693 | 4 694 | isa 695 | PBXFileReference 696 | name 697 | TextArea.cpp 698 | path 699 | ../../../addons/ofxProjectionMask/src/Drawing/Areas/TextArea.cpp 700 | sourceTree 701 | SOURCE_ROOT 702 | 703 | D22193753FEB293A2401E522 704 | 705 | children 706 | 707 | 3AD622672ACA353E2A83E7D0 708 | 1E0871A58D8655794E9662B9 709 | A3C5D360A115AF05D2BA2AEC 710 | 161C42E81468A0FCD634E19A 711 | 423EF5CBEC8650CAC82B97F7 712 | CE3F473B577FE2766469EE0D 713 | 714 | isa 715 | PBXGroup 716 | name 717 | Areas 718 | sourceTree 719 | <group> 720 | 721 | BD0CF07A973138F65BF0D12F 722 | 723 | children 724 | 725 | D22193753FEB293A2401E522 726 | B3C9BBA09800AAFF4752835D 727 | B96C481D7B4DF3DB53BEDE75 728 | A506CEE81D6CFA75C1CB4DA2 729 | B8C656E224502D36AD440ED3 730 | 628184A9BF426DA066FE888A 731 | 9AC2EDD3E37C434314776335 732 | 733 | isa 734 | PBXGroup 735 | name 736 | Drawing 737 | sourceTree 738 | <group> 739 | 740 | BA93CE2308F26A4FFC7A7B61 741 | 742 | fileRef 743 | 3AD622672ACA353E2A83E7D0 744 | isa 745 | PBXBuildFile 746 | 747 | 3AD622672ACA353E2A83E7D0 748 | 749 | explicitFileType 750 | sourcecode.cpp.cpp 751 | fileEncoding 752 | 4 753 | isa 754 | PBXFileReference 755 | name 756 | MaskFrame.cpp 757 | path 758 | ../../../addons/ofxProjectionMask/src/Drawing/Areas/MaskFrame.cpp 759 | sourceTree 760 | SOURCE_ROOT 761 | 762 | EA120572967FA8C94E460F49 763 | 764 | children 765 | 766 | CDF121A03AD00F0B4313C629 767 | BD0CF07A973138F65BF0D12F 768 | F552D018A402690FB077A090 769 | E40A5F0E03635F574CB851B0 770 | B64E87CE73C6EBBF8FFA7BEC 771 | 046F82E0626C8EECEB03BA31 772 | 1F158FF081BDEBEC64CE78C5 773 | 3270FA6535936663D879D198 774 | 775 | isa 776 | PBXGroup 777 | name 778 | src 779 | sourceTree 780 | <group> 781 | 782 | 3E01AADAE5C886DC8AEB011F 783 | 784 | children 785 | 786 | EA120572967FA8C94E460F49 787 | 788 | isa 789 | PBXGroup 790 | name 791 | ofxProjectionMask 792 | sourceTree 793 | <group> 794 | 795 | CDF121A03AD00F0B4313C629 796 | 797 | explicitFileType 798 | sourcecode.c.h 799 | fileEncoding 800 | 4 801 | isa 802 | PBXFileReference 803 | name 804 | ofExtensions.h 805 | path 806 | ../../../addons/ofxProjectionMask/src/ofExtensions.h 807 | sourceTree 808 | SOURCE_ROOT 809 | 810 | D57D6AE7066A76AF5E633AC8 811 | 812 | fileRef 813 | C48B1EA263E7E4D4C4D70C16 814 | isa 815 | PBXBuildFile 816 | 817 | C48B1EA263E7E4D4C4D70C16 818 | 819 | explicitFileType 820 | file 821 | fileEncoding 822 | 4 823 | isa 824 | PBXFileReference 825 | name 826 | alphaMask_ES2.vert 827 | path 828 | ../../../addons/ofxLayerMask/src/shader/alphaMask_ES2.vert 829 | sourceTree 830 | SOURCE_ROOT 831 | 832 | CFC55146A17C49881A095458 833 | 834 | fileRef 835 | 6B1EE0E710D517C3317B38A7 836 | isa 837 | PBXBuildFile 838 | 839 | 6B1EE0E710D517C3317B38A7 840 | 841 | explicitFileType 842 | file 843 | fileEncoding 844 | 4 845 | isa 846 | PBXFileReference 847 | name 848 | alphaMask_GL2.vert 849 | path 850 | ../../../addons/ofxLayerMask/src/shader/alphaMask_GL2.vert 851 | sourceTree 852 | SOURCE_ROOT 853 | 854 | 7EFF2709948EE75A4BA3BF80 855 | 856 | fileRef 857 | 95F5452C58F13212B5099E64 858 | isa 859 | PBXBuildFile 860 | 861 | 95F5452C58F13212B5099E64 862 | 863 | explicitFileType 864 | file 865 | fileEncoding 866 | 4 867 | isa 868 | PBXFileReference 869 | name 870 | alphaMask_GL3.vert 871 | path 872 | ../../../addons/ofxLayerMask/src/shader/alphaMask_GL3.vert 873 | sourceTree 874 | SOURCE_ROOT 875 | 876 | 7109C5297DF12D28548F1E82 877 | 878 | fileRef 879 | 94CC084F31DBD2C66E3DBEB9 880 | isa 881 | PBXBuildFile 882 | 883 | 94CC084F31DBD2C66E3DBEB9 884 | 885 | explicitFileType 886 | file 887 | fileEncoding 888 | 4 889 | isa 890 | PBXFileReference 891 | name 892 | alphaMask_GL3.frag 893 | path 894 | ../../../addons/ofxLayerMask/src/shader/alphaMask_GL3.frag 895 | sourceTree 896 | SOURCE_ROOT 897 | 898 | 0F72FC16F5D8C70F532317E3 899 | 900 | fileRef 901 | E3D0D0CBB99F266909832764 902 | isa 903 | PBXBuildFile 904 | 905 | E3D0D0CBB99F266909832764 906 | 907 | explicitFileType 908 | file 909 | fileEncoding 910 | 4 911 | isa 912 | PBXFileReference 913 | name 914 | alphaMask_GL2.frag 915 | path 916 | ../../../addons/ofxLayerMask/src/shader/alphaMask_GL2.frag 917 | sourceTree 918 | SOURCE_ROOT 919 | 920 | E74DC01A078204FA75FD4D0D 921 | 922 | children 923 | 924 | 2E0493A3C19C349A27FC7D25 925 | E3D0D0CBB99F266909832764 926 | 94CC084F31DBD2C66E3DBEB9 927 | 95F5452C58F13212B5099E64 928 | 6B1EE0E710D517C3317B38A7 929 | C48B1EA263E7E4D4C4D70C16 930 | 931 | isa 932 | PBXGroup 933 | name 934 | shader 935 | sourceTree 936 | <group> 937 | 938 | F9BB26B7E6520AF05BBFAA14 939 | 940 | fileRef 941 | 2E0493A3C19C349A27FC7D25 942 | isa 943 | PBXBuildFile 944 | 945 | 2E0493A3C19C349A27FC7D25 946 | 947 | explicitFileType 948 | file 949 | fileEncoding 950 | 4 951 | isa 952 | PBXFileReference 953 | name 954 | alphaMask_ES2.frag 955 | path 956 | ../../../addons/ofxLayerMask/src/shader/alphaMask_ES2.frag 957 | sourceTree 958 | SOURCE_ROOT 959 | 960 | 853F053FBB0E1A5C69AE0829 961 | 962 | fileRef 963 | A9E4628DEE13794A92581E42 964 | isa 965 | PBXBuildFile 966 | 967 | A9E4628DEE13794A92581E42 968 | 969 | explicitFileType 970 | sourcecode.cpp.cpp 971 | fileEncoding 972 | 4 973 | isa 974 | PBXFileReference 975 | name 976 | ofxLayerMask.cpp 977 | path 978 | ../../../addons/ofxLayerMask/src/ofxLayerMask.cpp 979 | sourceTree 980 | SOURCE_ROOT 981 | 982 | F996C14C51CDE505FA9BD196 983 | 984 | children 985 | 986 | 458AE5917CB33942884049CC 987 | A9E4628DEE13794A92581E42 988 | E74DC01A078204FA75FD4D0D 989 | 990 | isa 991 | PBXGroup 992 | name 993 | src 994 | sourceTree 995 | <group> 996 | 997 | DB48ECEB4A5AD24AB25E3141 998 | 999 | children 1000 | 1001 | F996C14C51CDE505FA9BD196 1002 | 1003 | isa 1004 | PBXGroup 1005 | name 1006 | ofxLayerMask 1007 | sourceTree 1008 | <group> 1009 | 1010 | 458AE5917CB33942884049CC 1011 | 1012 | explicitFileType 1013 | sourcecode.c.h 1014 | fileEncoding 1015 | 4 1016 | isa 1017 | PBXFileReference 1018 | name 1019 | ofxLayerMask.h 1020 | path 1021 | ../../../addons/ofxLayerMask/src/ofxLayerMask.h 1022 | sourceTree 1023 | SOURCE_ROOT 1024 | 1025 | 6948EE371B920CB800B5AC1A 1026 | 1027 | children 1028 | 1029 | isa 1030 | PBXGroup 1031 | name 1032 | local_addons 1033 | sourceTree 1034 | <group> 1035 | 1036 | 8466F1851C04CA0E00918B1C 1037 | 1038 | buildActionMask 1039 | 12 1040 | files 1041 | 1042 | inputPaths 1043 | 1044 | isa 1045 | PBXShellScriptBuildPhase 1046 | outputPaths 1047 | 1048 | runOnlyForDeploymentPostprocessing 1049 | 0 1050 | shellPath 1051 | /bin/sh 1052 | shellScript 1053 | echo "$GCC_PREPROCESSOR_DEFINITIONS"; 1054 | APPSTORE=`expr "$GCC_PREPROCESSOR_DEFINITIONS" : ".*APPSTORE=\([0-9]*\)"` 1055 | if [ -z "$APPSTORE" ] ; then 1056 | echo "Note: Not copying bin/data to App Package or doing App Code signing. Use AppStore target for AppStore distribution"; 1057 | else 1058 | # Copy bin/data into App/Resources 1059 | rsync -avz --exclude='.DS_Store' "${SRCROOT}/bin/data/" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/data/" 1060 | 1061 | # ---- Code Sign App Package ---- 1062 | 1063 | # WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY! 1064 | 1065 | # Verify that $CODE_SIGN_IDENTITY is set 1066 | if [ -z "${CODE_SIGN_IDENTITY}" ] ; then 1067 | echo "CODE_SIGN_IDENTITY needs to be set for framework code-signing" 1068 | exit 0 1069 | fi 1070 | 1071 | if [ -z "${CODE_SIGN_ENTITLEMENTS}" ] ; then 1072 | echo "CODE_SIGN_ENTITLEMENTS needs to be set for framework code-signing!" 1073 | 1074 | if [ "${CONFIGURATION}" = "Release" ] ; then 1075 | exit 1 1076 | else 1077 | # Code-signing is optional for non-release builds. 1078 | exit 0 1079 | fi 1080 | fi 1081 | 1082 | ITEMS="" 1083 | 1084 | FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 1085 | echo "$FRAMEWORKS_DIR" 1086 | if [ -d "$FRAMEWORKS_DIR" ] ; then 1087 | FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle" | sed -e "s/\(.*framework\)/\1\/Versions\/A\//") 1088 | RESULT=$? 1089 | if [[ $RESULT != 0 ]] ; then 1090 | exit 1 1091 | fi 1092 | 1093 | ITEMS="${FRAMEWORKS}" 1094 | fi 1095 | 1096 | LOGINITEMS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Library/LoginItems/" 1097 | if [ -d "$LOGINITEMS_DIR" ] ; then 1098 | LOGINITEMS=$(find "${LOGINITEMS_DIR}" -depth -type d -name "*.app") 1099 | RESULT=$? 1100 | if [[ $RESULT != 0 ]] ; then 1101 | exit 1 1102 | fi 1103 | 1104 | ITEMS="${ITEMS}"$'\n'"${LOGINITEMS}" 1105 | fi 1106 | 1107 | # Prefer the expanded name, if available. 1108 | CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 1109 | if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then 1110 | # Fall back to old behavior. 1111 | CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}" 1112 | fi 1113 | 1114 | echo "Identity:" 1115 | echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}" 1116 | 1117 | echo "Entitlements:" 1118 | echo "${CODE_SIGN_ENTITLEMENTS}" 1119 | 1120 | echo "Found:" 1121 | echo "${ITEMS}" 1122 | 1123 | # Change the Internal Field Separator (IFS) so that spaces in paths will not cause problems below. 1124 | SAVED_IFS=$IFS 1125 | IFS=$(echo -en "\n\b") 1126 | 1127 | # Loop through all items. 1128 | for ITEM in $ITEMS; 1129 | do 1130 | echo "Signing '${ITEM}'" 1131 | codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" --entitlements "${CODE_SIGN_ENTITLEMENTS}" "${ITEM}" 1132 | RESULT=$? 1133 | if [[ $RESULT != 0 ]] ; then 1134 | echo "Failed to sign '${ITEM}'." 1135 | IFS=$SAVED_IFS 1136 | exit 1 1137 | fi 1138 | done 1139 | 1140 | # Restore $IFS. 1141 | IFS=$SAVED_IFS 1142 | 1143 | fi 1144 | 1145 | 1146 | 99FA3DBB1C7456C400CFA0EE 1147 | 1148 | baseConfigurationReference 1149 | E4EB6923138AFD0F00A09F29 1150 | buildSettings 1151 | 1152 | HEADER_SEARCH_PATHS 1153 | 1154 | $(OF_CORE_HEADERS) 1155 | src 1156 | ../../../addons/ofxLayerMask/src 1157 | ../../../addons/ofxLayerMask/src/shader 1158 | ../../../addons/ofxProjectionMask/src 1159 | ../../../addons/ofxProjectionMask/src/Drawing 1160 | ../../../addons/ofxProjectionMask/src/Drawing/Areas 1161 | ../../../addons/ofxProjectionMask/src/Drawing/Collections 1162 | ../../../addons/ofxProjectionMask/src/Drawing/Points 1163 | ../../../addons/ofxProjectionMask/src/Storage 1164 | ../../../addons/ofxXmlSettings/libs 1165 | ../../../addons/ofxXmlSettings/src 1166 | 1167 | CONFIGURATION_BUILD_DIR 1168 | $(SRCROOT)/bin/ 1169 | COPY_PHASE_STRIP 1170 | YES 1171 | DEAD_CODE_STRIPPING 1172 | YES 1173 | GCC_AUTO_VECTORIZATION 1174 | YES 1175 | GCC_ENABLE_SSE3_EXTENSIONS 1176 | YES 1177 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS 1178 | YES 1179 | GCC_INLINES_ARE_PRIVATE_EXTERN 1180 | NO 1181 | GCC_OPTIMIZATION_LEVEL 1182 | 3 1183 | GCC_PREPROCESSOR_DEFINITIONS[arch=*] 1184 | DISTRIBUTION=1 1185 | GCC_SYMBOLS_PRIVATE_EXTERN 1186 | NO 1187 | GCC_UNROLL_LOOPS 1188 | YES 1189 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS 1190 | YES 1191 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO 1192 | NO 1193 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL 1194 | NO 1195 | GCC_WARN_UNINITIALIZED_AUTOS 1196 | NO 1197 | GCC_WARN_UNUSED_VALUE 1198 | NO 1199 | GCC_WARN_UNUSED_VARIABLE 1200 | NO 1201 | MACOSX_DEPLOYMENT_TARGET 1202 | 10.9 1203 | OTHER_CPLUSPLUSFLAGS 1204 | 1205 | -D__MACOSX_CORE__ 1206 | -mtune=native 1207 | 1208 | SDKROOT 1209 | macosx 1210 | 1211 | isa 1212 | XCBuildConfiguration 1213 | name 1214 | AppStore 1215 | 1216 | 99FA3DBC1C7456C400CFA0EE 1217 | 1218 | baseConfigurationReference 1219 | E4EB6923138AFD0F00A09F29 1220 | buildSettings 1221 | 1222 | HEADER_SEARCH_PATHS 1223 | 1224 | $(OF_CORE_HEADERS) 1225 | src 1226 | ../../../addons/ofxLayerMask/src 1227 | ../../../addons/ofxLayerMask/src/shader 1228 | ../../../addons/ofxProjectionMask/src 1229 | ../../../addons/ofxProjectionMask/src/Drawing 1230 | ../../../addons/ofxProjectionMask/src/Drawing/Areas 1231 | ../../../addons/ofxProjectionMask/src/Drawing/Collections 1232 | ../../../addons/ofxProjectionMask/src/Drawing/Points 1233 | ../../../addons/ofxProjectionMask/src/Storage 1234 | ../../../addons/ofxXmlSettings/libs 1235 | ../../../addons/ofxXmlSettings/src 1236 | 1237 | COMBINE_HIDPI_IMAGES 1238 | YES 1239 | COPY_PHASE_STRIP 1240 | YES 1241 | FRAMEWORK_SEARCH_PATHS 1242 | 1243 | $(inherited) 1244 | 1245 | GCC_GENERATE_DEBUGGING_SYMBOLS 1246 | YES 1247 | GCC_MODEL_TUNING 1248 | NONE 1249 | GCC_PREPROCESSOR_DEFINITIONS[arch=*] 1250 | APPSTORE=1 1251 | ICON 1252 | $(ICON_NAME_RELEASE) 1253 | ICON_FILE 1254 | $(ICON_FILE_PATH)$(ICON) 1255 | INFOPLIST_FILE 1256 | openFrameworks-Info.plist 1257 | INSTALL_PATH 1258 | /Applications 1259 | LIBRARY_SEARCH_PATHS 1260 | $(inherited) 1261 | PRODUCT_NAME 1262 | $(TARGET_NAME) 1263 | WRAPPER_EXTENSION 1264 | app 1265 | baseConfigurationReference 1266 | E4EB6923138AFD0F00A09F29 1267 | 1268 | isa 1269 | XCBuildConfiguration 1270 | name 1271 | AppStore 1272 | 1273 | BB4B014C10F69532006C3DED 1274 | 1275 | children 1276 | 1277 | DB48ECEB4A5AD24AB25E3141 1278 | 3E01AADAE5C886DC8AEB011F 1279 | 1F4FB5C423662B96ADFDCC0B 1280 | 1281 | isa 1282 | PBXGroup 1283 | name 1284 | addons 1285 | sourceTree 1286 | <group> 1287 | 1288 | E4328143138ABC890047C5CB 1289 | 1290 | isa 1291 | PBXFileReference 1292 | lastKnownFileType 1293 | wrapper.pb-project 1294 | name 1295 | openFrameworksLib.xcodeproj 1296 | path 1297 | ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj 1298 | sourceTree 1299 | SOURCE_ROOT 1300 | 1301 | E4328144138ABC890047C5CB 1302 | 1303 | children 1304 | 1305 | E4328148138ABC890047C5CB 1306 | 1307 | isa 1308 | PBXGroup 1309 | name 1310 | Products 1311 | sourceTree 1312 | <group> 1313 | 1314 | E4328147138ABC890047C5CB 1315 | 1316 | containerPortal 1317 | E4328143138ABC890047C5CB 1318 | isa 1319 | PBXContainerItemProxy 1320 | proxyType 1321 | 2 1322 | remoteGlobalIDString 1323 | E4B27C1510CBEB8E00536013 1324 | remoteInfo 1325 | openFrameworks 1326 | 1327 | E4328148138ABC890047C5CB 1328 | 1329 | fileType 1330 | archive.ar 1331 | isa 1332 | PBXReferenceProxy 1333 | path 1334 | openFrameworksDebug.a 1335 | remoteRef 1336 | E4328147138ABC890047C5CB 1337 | sourceTree 1338 | BUILT_PRODUCTS_DIR 1339 | 1340 | E4328149138ABC9F0047C5CB 1341 | 1342 | fileRef 1343 | E4328148138ABC890047C5CB 1344 | isa 1345 | PBXBuildFile 1346 | 1347 | E4B69B4A0A3A1720003C02F2 1348 | 1349 | children 1350 | 1351 | E4B6FCAD0C3E899E008CF71C 1352 | E4EB6923138AFD0F00A09F29 1353 | E4B69E1C0A3A1BDC003C02F2 1354 | E4EEC9E9138DF44700A80321 1355 | BB4B014C10F69532006C3DED 1356 | 6948EE371B920CB800B5AC1A 1357 | E4B69B5B0A3A1756003C02F2 1358 | 1359 | isa 1360 | PBXGroup 1361 | sourceTree 1362 | <group> 1363 | 1364 | E4B69B4C0A3A1720003C02F2 1365 | 1366 | attributes 1367 | 1368 | LastUpgradeCheck 1369 | 0600 1370 | 1371 | buildConfigurationList 1372 | E4B69B4D0A3A1720003C02F2 1373 | compatibilityVersion 1374 | Xcode 3.2 1375 | developmentRegion 1376 | English 1377 | hasScannedForEncodings 1378 | 0 1379 | isa 1380 | PBXProject 1381 | knownRegions 1382 | 1383 | English 1384 | Japanese 1385 | French 1386 | German 1387 | 1388 | mainGroup 1389 | E4B69B4A0A3A1720003C02F2 1390 | productRefGroup 1391 | E4B69B4A0A3A1720003C02F2 1392 | projectDirPath 1393 | 1394 | projectReferences 1395 | 1396 | 1397 | ProductGroup 1398 | E4328144138ABC890047C5CB 1399 | ProjectRef 1400 | E4328143138ABC890047C5CB 1401 | 1402 | 1403 | projectRoot 1404 | 1405 | targets 1406 | 1407 | E4B69B5A0A3A1756003C02F2 1408 | 1409 | 1410 | E4B69B4D0A3A1720003C02F2 1411 | 1412 | buildConfigurations 1413 | 1414 | E4B69B4E0A3A1720003C02F2 1415 | E4B69B4F0A3A1720003C02F2 1416 | 99FA3DBB1C7456C400CFA0EE 1417 | 1418 | defaultConfigurationIsVisible 1419 | 0 1420 | defaultConfigurationName 1421 | Release 1422 | isa 1423 | XCConfigurationList 1424 | 1425 | E4B69B4E0A3A1720003C02F2 1426 | 1427 | baseConfigurationReference 1428 | E4EB6923138AFD0F00A09F29 1429 | buildSettings 1430 | 1431 | HEADER_SEARCH_PATHS 1432 | 1433 | $(OF_CORE_HEADERS) 1434 | src 1435 | ../../../addons/ofxLayerMask/src 1436 | ../../../addons/ofxLayerMask/src/shader 1437 | ../../../addons/ofxProjectionMask/src 1438 | ../../../addons/ofxProjectionMask/src/Drawing 1439 | ../../../addons/ofxProjectionMask/src/Drawing/Areas 1440 | ../../../addons/ofxProjectionMask/src/Drawing/Collections 1441 | ../../../addons/ofxProjectionMask/src/Drawing/Points 1442 | ../../../addons/ofxProjectionMask/src/Storage 1443 | ../../../addons/ofxXmlSettings/libs 1444 | ../../../addons/ofxXmlSettings/src 1445 | 1446 | CONFIGURATION_BUILD_DIR 1447 | $(SRCROOT)/bin/ 1448 | COPY_PHASE_STRIP 1449 | NO 1450 | DEAD_CODE_STRIPPING 1451 | YES 1452 | GCC_AUTO_VECTORIZATION 1453 | YES 1454 | GCC_ENABLE_SSE3_EXTENSIONS 1455 | YES 1456 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS 1457 | YES 1458 | GCC_INLINES_ARE_PRIVATE_EXTERN 1459 | NO 1460 | GCC_OPTIMIZATION_LEVEL 1461 | 0 1462 | GCC_SYMBOLS_PRIVATE_EXTERN 1463 | NO 1464 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS 1465 | YES 1466 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO 1467 | NO 1468 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL 1469 | NO 1470 | GCC_WARN_UNINITIALIZED_AUTOS 1471 | NO 1472 | GCC_WARN_UNUSED_VALUE 1473 | NO 1474 | GCC_WARN_UNUSED_VARIABLE 1475 | NO 1476 | MACOSX_DEPLOYMENT_TARGET 1477 | 10.9 1478 | ONLY_ACTIVE_ARCH 1479 | YES 1480 | OTHER_CPLUSPLUSFLAGS 1481 | 1482 | -D__MACOSX_CORE__ 1483 | -mtune=native 1484 | 1485 | SDKROOT 1486 | macosx 1487 | 1488 | isa 1489 | XCBuildConfiguration 1490 | name 1491 | Debug 1492 | 1493 | E4B69B4F0A3A1720003C02F2 1494 | 1495 | baseConfigurationReference 1496 | E4EB6923138AFD0F00A09F29 1497 | buildSettings 1498 | 1499 | HEADER_SEARCH_PATHS 1500 | 1501 | $(OF_CORE_HEADERS) 1502 | src 1503 | ../../../addons/ofxLayerMask/src 1504 | ../../../addons/ofxLayerMask/src/shader 1505 | ../../../addons/ofxProjectionMask/src 1506 | ../../../addons/ofxProjectionMask/src/Drawing 1507 | ../../../addons/ofxProjectionMask/src/Drawing/Areas 1508 | ../../../addons/ofxProjectionMask/src/Drawing/Collections 1509 | ../../../addons/ofxProjectionMask/src/Drawing/Points 1510 | ../../../addons/ofxProjectionMask/src/Storage 1511 | ../../../addons/ofxXmlSettings/libs 1512 | ../../../addons/ofxXmlSettings/src 1513 | 1514 | CONFIGURATION_BUILD_DIR 1515 | $(SRCROOT)/bin/ 1516 | COPY_PHASE_STRIP 1517 | YES 1518 | DEAD_CODE_STRIPPING 1519 | YES 1520 | GCC_AUTO_VECTORIZATION 1521 | YES 1522 | GCC_ENABLE_SSE3_EXTENSIONS 1523 | YES 1524 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS 1525 | YES 1526 | GCC_INLINES_ARE_PRIVATE_EXTERN 1527 | NO 1528 | GCC_OPTIMIZATION_LEVEL 1529 | 3 1530 | GCC_SYMBOLS_PRIVATE_EXTERN 1531 | NO 1532 | GCC_UNROLL_LOOPS 1533 | YES 1534 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS 1535 | YES 1536 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO 1537 | NO 1538 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL 1539 | NO 1540 | GCC_WARN_UNINITIALIZED_AUTOS 1541 | NO 1542 | GCC_WARN_UNUSED_VALUE 1543 | NO 1544 | GCC_WARN_UNUSED_VARIABLE 1545 | NO 1546 | MACOSX_DEPLOYMENT_TARGET 1547 | 10.9 1548 | OTHER_CPLUSPLUSFLAGS 1549 | 1550 | -D__MACOSX_CORE__ 1551 | -mtune=native 1552 | 1553 | SDKROOT 1554 | macosx 1555 | 1556 | isa 1557 | XCBuildConfiguration 1558 | name 1559 | Release 1560 | 1561 | E4B69B580A3A1756003C02F2 1562 | 1563 | buildActionMask 1564 | 2147483647 1565 | files 1566 | 1567 | E4B69E200A3A1BDC003C02F2 1568 | E4B69E210A3A1BDC003C02F2 1569 | 853F053FBB0E1A5C69AE0829 1570 | F9BB26B7E6520AF05BBFAA14 1571 | 0F72FC16F5D8C70F532317E3 1572 | 7109C5297DF12D28548F1E82 1573 | 7EFF2709948EE75A4BA3BF80 1574 | CFC55146A17C49881A095458 1575 | D57D6AE7066A76AF5E633AC8 1576 | BA93CE2308F26A4FFC7A7B61 1577 | F7A71601C83BF7AFD88C7B89 1578 | B6A612F76CCE330A56118A28 1579 | 244900C88898E50686F09114 1580 | BBB68A8265F6404CF134058B 1581 | 3B96DE095864B8DB0144EDE4 1582 | 9FCABFF231B041B5F4B145E3 1583 | 6571D6A30BABD8EA6C708E9B 1584 | 09647D14A621C73DE9931223 1585 | B26EE6708293A09D2B2E316A 1586 | C331C50B8B721DB309247421 1587 | 4C6FF3EB83F5CF320E2F44C0 1588 | 0DB54D1D7240859E40204C01 1589 | 729840592B90C492EBB4EBDE 1590 | 63B57AC5BF4EF088491E0317 1591 | 5A4349E9754D6FA14C0F2A3A 1592 | 9D44DC88EF9E7991B4A09951 1593 | 933A2227713C720CEFF80FD9 1594 | 1595 | isa 1596 | PBXSourcesBuildPhase 1597 | runOnlyForDeploymentPostprocessing 1598 | 0 1599 | 1600 | E4B69B590A3A1756003C02F2 1601 | 1602 | buildActionMask 1603 | 2147483647 1604 | files 1605 | 1606 | E4328149138ABC9F0047C5CB 1607 | 1608 | isa 1609 | PBXFrameworksBuildPhase 1610 | runOnlyForDeploymentPostprocessing 1611 | 0 1612 | 1613 | E4B69B5A0A3A1756003C02F2 1614 | 1615 | buildConfigurationList 1616 | E4B69B5F0A3A1757003C02F2 1617 | buildPhases 1618 | 1619 | E4B69B580A3A1756003C02F2 1620 | E4B69B590A3A1756003C02F2 1621 | E4B6FFFD0C3F9AB9008CF71C 1622 | E4C2427710CC5ABF004149E2 1623 | 8466F1851C04CA0E00918B1C 1624 | 1625 | buildRules 1626 | 1627 | dependencies 1628 | 1629 | E4EEB9AC138B136A00A80321 1630 | 1631 | isa 1632 | PBXNativeTarget 1633 | name 1634 | example 1635 | productName 1636 | myOFApp 1637 | productReference 1638 | E4B69B5B0A3A1756003C02F2 1639 | productType 1640 | com.apple.product-type.application 1641 | 1642 | E4B69B5B0A3A1756003C02F2 1643 | 1644 | explicitFileType 1645 | wrapper.application 1646 | includeInIndex 1647 | 0 1648 | isa 1649 | PBXFileReference 1650 | path 1651 | exampleDebug.app 1652 | sourceTree 1653 | BUILT_PRODUCTS_DIR 1654 | 1655 | E4B69B5F0A3A1757003C02F2 1656 | 1657 | buildConfigurations 1658 | 1659 | E4B69B600A3A1757003C02F2 1660 | E4B69B610A3A1757003C02F2 1661 | 99FA3DBC1C7456C400CFA0EE 1662 | 1663 | defaultConfigurationIsVisible 1664 | 0 1665 | defaultConfigurationName 1666 | Release 1667 | isa 1668 | XCConfigurationList 1669 | 1670 | E4B69B600A3A1757003C02F2 1671 | 1672 | baseConfigurationReference 1673 | E4EB6923138AFD0F00A09F29 1674 | buildSettings 1675 | 1676 | HEADER_SEARCH_PATHS 1677 | 1678 | $(OF_CORE_HEADERS) 1679 | src 1680 | ../../../addons/ofxLayerMask/src 1681 | ../../../addons/ofxLayerMask/src/shader 1682 | ../../../addons/ofxProjectionMask/src 1683 | ../../../addons/ofxProjectionMask/src/Drawing 1684 | ../../../addons/ofxProjectionMask/src/Drawing/Areas 1685 | ../../../addons/ofxProjectionMask/src/Drawing/Collections 1686 | ../../../addons/ofxProjectionMask/src/Drawing/Points 1687 | ../../../addons/ofxProjectionMask/src/Storage 1688 | ../../../addons/ofxXmlSettings/libs 1689 | ../../../addons/ofxXmlSettings/src 1690 | 1691 | COMBINE_HIDPI_IMAGES 1692 | YES 1693 | COPY_PHASE_STRIP 1694 | NO 1695 | FRAMEWORK_SEARCH_PATHS 1696 | 1697 | $(inherited) 1698 | 1699 | GCC_DYNAMIC_NO_PIC 1700 | NO 1701 | GCC_GENERATE_DEBUGGING_SYMBOLS 1702 | YES 1703 | GCC_MODEL_TUNING 1704 | NONE 1705 | ICON 1706 | $(ICON_NAME_DEBUG) 1707 | ICON_FILE 1708 | $(ICON_FILE_PATH)$(ICON) 1709 | INFOPLIST_FILE 1710 | openFrameworks-Info.plist 1711 | INSTALL_PATH 1712 | /Applications 1713 | LIBRARY_SEARCH_PATHS 1714 | $(inherited) 1715 | PRODUCT_NAME 1716 | $(TARGET_NAME)Debug 1717 | WRAPPER_EXTENSION 1718 | app 1719 | 1720 | isa 1721 | XCBuildConfiguration 1722 | name 1723 | Debug 1724 | 1725 | E4B69B610A3A1757003C02F2 1726 | 1727 | baseConfigurationReference 1728 | E4EB6923138AFD0F00A09F29 1729 | buildSettings 1730 | 1731 | HEADER_SEARCH_PATHS 1732 | 1733 | $(OF_CORE_HEADERS) 1734 | src 1735 | ../../../addons/ofxLayerMask/src 1736 | ../../../addons/ofxLayerMask/src/shader 1737 | ../../../addons/ofxProjectionMask/src 1738 | ../../../addons/ofxProjectionMask/src/Drawing 1739 | ../../../addons/ofxProjectionMask/src/Drawing/Areas 1740 | ../../../addons/ofxProjectionMask/src/Drawing/Collections 1741 | ../../../addons/ofxProjectionMask/src/Drawing/Points 1742 | ../../../addons/ofxProjectionMask/src/Storage 1743 | ../../../addons/ofxXmlSettings/libs 1744 | ../../../addons/ofxXmlSettings/src 1745 | 1746 | COMBINE_HIDPI_IMAGES 1747 | YES 1748 | COPY_PHASE_STRIP 1749 | YES 1750 | FRAMEWORK_SEARCH_PATHS 1751 | 1752 | $(inherited) 1753 | 1754 | GCC_GENERATE_DEBUGGING_SYMBOLS 1755 | YES 1756 | GCC_MODEL_TUNING 1757 | NONE 1758 | ICON 1759 | $(ICON_NAME_RELEASE) 1760 | ICON_FILE 1761 | $(ICON_FILE_PATH)$(ICON) 1762 | INFOPLIST_FILE 1763 | openFrameworks-Info.plist 1764 | INSTALL_PATH 1765 | /Applications 1766 | LIBRARY_SEARCH_PATHS 1767 | $(inherited) 1768 | PRODUCT_NAME 1769 | $(TARGET_NAME) 1770 | WRAPPER_EXTENSION 1771 | app 1772 | baseConfigurationReference 1773 | E4EB6923138AFD0F00A09F29 1774 | 1775 | isa 1776 | XCBuildConfiguration 1777 | name 1778 | Release 1779 | 1780 | E4B69E1C0A3A1BDC003C02F2 1781 | 1782 | children 1783 | 1784 | E4B69E1D0A3A1BDC003C02F2 1785 | E4B69E1E0A3A1BDC003C02F2 1786 | E4B69E1F0A3A1BDC003C02F2 1787 | 1788 | isa 1789 | PBXGroup 1790 | path 1791 | src 1792 | sourceTree 1793 | SOURCE_ROOT 1794 | 1795 | E4B69E1D0A3A1BDC003C02F2 1796 | 1797 | fileEncoding 1798 | 4 1799 | isa 1800 | PBXFileReference 1801 | lastKnownFileType 1802 | sourcecode.cpp.cpp 1803 | name 1804 | main.cpp 1805 | path 1806 | src/main.cpp 1807 | sourceTree 1808 | SOURCE_ROOT 1809 | 1810 | E4B69E1E0A3A1BDC003C02F2 1811 | 1812 | explicitFileType 1813 | sourcecode.cpp.cpp 1814 | fileEncoding 1815 | 4 1816 | isa 1817 | PBXFileReference 1818 | name 1819 | ofApp.cpp 1820 | path 1821 | src/ofApp.cpp 1822 | sourceTree 1823 | SOURCE_ROOT 1824 | 1825 | E4B69E1F0A3A1BDC003C02F2 1826 | 1827 | fileEncoding 1828 | 4 1829 | isa 1830 | PBXFileReference 1831 | lastKnownFileType 1832 | sourcecode.c.h 1833 | name 1834 | ofApp.h 1835 | path 1836 | src/ofApp.h 1837 | sourceTree 1838 | SOURCE_ROOT 1839 | 1840 | E4B69E200A3A1BDC003C02F2 1841 | 1842 | fileRef 1843 | E4B69E1D0A3A1BDC003C02F2 1844 | isa 1845 | PBXBuildFile 1846 | 1847 | E4B69E210A3A1BDC003C02F2 1848 | 1849 | fileRef 1850 | E4B69E1E0A3A1BDC003C02F2 1851 | isa 1852 | PBXBuildFile 1853 | 1854 | E4B6FCAD0C3E899E008CF71C 1855 | 1856 | fileEncoding 1857 | 4 1858 | isa 1859 | PBXFileReference 1860 | lastKnownFileType 1861 | text.plist.xml 1862 | path 1863 | openFrameworks-Info.plist 1864 | sourceTree 1865 | <group> 1866 | 1867 | E4B6FFFD0C3F9AB9008CF71C 1868 | 1869 | buildActionMask 1870 | 2147483647 1871 | files 1872 | 1873 | inputPaths 1874 | 1875 | isa 1876 | PBXShellScriptBuildPhase 1877 | outputPaths 1878 | 1879 | runOnlyForDeploymentPostprocessing 1880 | 0 1881 | shellPath 1882 | /bin/sh 1883 | shellScript 1884 | mkdir -p "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" 1885 | # Copy default icon file into App/Resources 1886 | rsync -aved "$ICON_FILE" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" 1887 | # Copy libfmod and change install directory for fmod to run 1888 | rsync -aved "$OF_PATH/libs/fmodex/lib/osx/libfmodex.dylib" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/"; 1889 | install_name_tool -change @executable_path/libfmodex.dylib @executable_path/../Frameworks/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"; 1890 | 1891 | echo "$GCC_PREPROCESSOR_DEFINITIONS"; 1892 | 1893 | 1894 | E4C2427710CC5ABF004149E2 1895 | 1896 | buildActionMask 1897 | 2147483647 1898 | dstPath 1899 | 1900 | dstSubfolderSpec 1901 | 10 1902 | files 1903 | 1904 | isa 1905 | PBXCopyFilesBuildPhase 1906 | runOnlyForDeploymentPostprocessing 1907 | 0 1908 | 1909 | E4EB691F138AFCF100A09F29 1910 | 1911 | fileEncoding 1912 | 4 1913 | isa 1914 | PBXFileReference 1915 | lastKnownFileType 1916 | text.xcconfig 1917 | name 1918 | CoreOF.xcconfig 1919 | path 1920 | ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig 1921 | sourceTree 1922 | SOURCE_ROOT 1923 | 1924 | E4EB6923138AFD0F00A09F29 1925 | 1926 | fileEncoding 1927 | 4 1928 | isa 1929 | PBXFileReference 1930 | lastKnownFileType 1931 | text.xcconfig 1932 | path 1933 | Project.xcconfig 1934 | sourceTree 1935 | <group> 1936 | 1937 | E4EEB9AB138B136A00A80321 1938 | 1939 | containerPortal 1940 | E4328143138ABC890047C5CB 1941 | isa 1942 | PBXContainerItemProxy 1943 | proxyType 1944 | 1 1945 | remoteGlobalIDString 1946 | E4B27C1410CBEB8E00536013 1947 | remoteInfo 1948 | openFrameworks 1949 | 1950 | E4EEB9AC138B136A00A80321 1951 | 1952 | isa 1953 | PBXTargetDependency 1954 | name 1955 | openFrameworks 1956 | targetProxy 1957 | E4EEB9AB138B136A00A80321 1958 | 1959 | E4EEC9E9138DF44700A80321 1960 | 1961 | children 1962 | 1963 | E4EB691F138AFCF100A09F29 1964 | E4328143138ABC890047C5CB 1965 | 1966 | isa 1967 | PBXGroup 1968 | name 1969 | openFrameworks 1970 | sourceTree 1971 | <group> 1972 | 1973 | 1974 | rootObject 1975 | E4B69B4C0A3A1720003C02F2 1976 | 1977 | 1978 | -------------------------------------------------------------------------------- /example/example.xcodeproj/xcshareddata/xcschemes/example Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /example/example.xcodeproj/xcshareddata/xcschemes/example Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /example/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /example/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | #include "ofAppGLFWWindow.h" 4 | 5 | int getNumScreens(){ 6 | CGDisplayCount displayCount; 7 | CGDirectDisplayID displays[32]; 8 | CGGetActiveDisplayList(32, displays, &displayCount); 9 | return displayCount; 10 | } 11 | 12 | int main(){ 13 | int numScreens = getNumScreens(); 14 | 15 | ofGLFWWindowSettings settings; 16 | //settings.windowMode = OF_FULLSCREEN; 17 | settings.monitor = 0; 18 | shared_ptr mainWindow = ofCreateWindow(settings); 19 | 20 | settings.shareContextWith = mainWindow; 21 | settings.monitor = numScreens > 1 ? 1 : settings.monitor; 22 | shared_ptr secondWindow = ofCreateWindow(settings); 23 | secondWindow->setVerticalSync(false); 24 | 25 | shared_ptr mainApp(new ofApp); 26 | ofAddListener(secondWindow->events().draw, mainApp.get(), &ofApp::drawSecondWindow); 27 | 28 | ofRunApp(mainWindow, mainApp); 29 | ofRunMainLoop(); 30 | } 31 | -------------------------------------------------------------------------------- /example/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | /* 3 | ofxProjectionMask 4 | ================= 5 | ofxProjectionMask is an addon which allows you to mask out 6 | areas of the real world onto which to project any light 7 | pattern you like. 8 | 9 | Unlike projection mapping, this addon is not specifically 10 | about creating the 'illusion' that a light surface is 11 | 'mapped onto' some target physical object; instead this 12 | addon simply masks - prevents the light patterns you specify 13 | from showing up anywhere outside of the mask boundaries. 14 | 15 | You can choose from three drawing modes: 16 | 17 | 1. DO_NOT_STRETCH Draw the pattern exactly as specified, 18 | pixel-perfect to how it was drawn 19 | 20 | 2. STRETCH_TO_MASKFRAME Stretch the given pattern so that it 21 | matches the boundaries of the mask 22 | frame which contains it - you will 23 | learn about mask frames when you 24 | launch the UI 25 | 26 | 3. HOMOGRAPHY Stretch the pattern so that it matches 27 | four arbitrary points within a mask 28 | frame. This is the closest we get to 29 | projection *mapping*, this essentially 30 | allows you to 'pre-warp' your pattern 31 | to match a rectangular target surface 32 | 33 | Note: HOMOGRAPHY mode only works when 34 | you have exactly 4 mask points inside 35 | your mask frame. If you have more than 36 | 4 then it falls back to DO_NOT_STRETCH 37 | 38 | The idea of this addon is it separates out the masking from 39 | the mapping, and focuses more on the former than the latter. 40 | This is useful for situations in which you are more interested 41 | in exploring certain properties of light, computer graphics 42 | and physical space, than in creating an optical illusion. 43 | 44 | How to get started? 45 | ------------------- 46 | Just launch the app! Instructions are there for how to 47 | use the UI. When you've had enough, scroll through this file 48 | to see how to program your own patterns. 49 | */ 50 | 51 | void ofApp::setup(){ 52 | //First, set up the ofxProjectionMask designer 53 | designer.setup(); //Default is STRETCH_TO_MASKFRAME 54 | //designer.setup(DO_NOT_STRETCH); //Otherwise, explicitly state which mode you want 55 | //designer.setup(STRETCH_TO_MASKFRAME); //These are explained above 56 | //designer.setup(HOMOGRAPHY); 57 | 58 | //When you are ready to use this addon fullscreen with a 59 | //projector you will need to uncomment this line below, and 60 | //comment out the setup() call with no arguments above. 61 | //designer.setup(DO_NOT_STRETCH, PRESETS_PRODUCTION); 62 | //NOTE: If you enable PRESETS_PRODUCTION, you MUST also 63 | //go and uncomment this line in main.cpp 64 | //main.cpp : settings.windowMode = OF_FULLSCREEN; 65 | 66 | //Now lets set up two patterns of different sizes 67 | pattern1 = designer.newPattern(200, 200); 68 | pattern2 = designer.newPattern(800, 800); 69 | 70 | //And lets init the variables our patterns are going to use 71 | currentHue = 0; 72 | ofSetVerticalSync(true); 73 | ofSetFrameRate(60); 74 | ofEnableSmoothing(); 75 | } 76 | 77 | void ofApp::update(){ 78 | //Tell the designer where your mouse is 79 | designer.update(mouseX, mouseY); 80 | 81 | //Let's draw a hue-cycle in our first pattern 82 | pattern1->begin(); 83 | { 84 | currentHue += 0.2; 85 | if(currentHue >= 256){ 86 | currentHue = 0; 87 | } 88 | 89 | ofBackground(ofColor::fromHsb(currentHue, 255, 255)); 90 | for(int i = 5; i < pattern1->getWidth(); i += 40){ 91 | for(int j = 15; j < pattern1->getHeight(); j += 40){ 92 | ofSetColor(ofColor::black); 93 | ofDrawBitmapString(ofToString((int)currentHue), i, j); 94 | } 95 | } 96 | } 97 | pattern1->end(); 98 | 99 | //Let's draw a grid in the second pattern 100 | pattern2->begin(); 101 | { 102 | ofBackground(ofColor::black); 103 | for(int i = 40; i < pattern2->getWidth(); i += 80){ 104 | for(int j = 40; j < pattern2->getHeight(); j += 80){ 105 | ofSetColor(ofColor::white); 106 | ofDrawRectangle(0, i, pattern2->getWidth(), 20); 107 | ofDrawRectangle(j, 0, 20, pattern2->getHeight()); 108 | } 109 | } 110 | } 111 | pattern2->end(); 112 | } 113 | 114 | void ofApp::draw(){ 115 | designer.drawFirstWindow(); 116 | } 117 | 118 | void ofApp::drawSecondWindow(ofEventArgs &args){ 119 | designer.drawSecondWindow(); 120 | } 121 | -------------------------------------------------------------------------------- /example/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "ofxProjectionMask.h" 5 | #include "ofxLayerMask.h" 6 | 7 | class ofApp : public ofBaseApp{ 8 | 9 | public: 10 | void setup(); 11 | void update(); 12 | void draw(); 13 | void drawSecondWindow(ofEventArgs &args); 14 | 15 | ofxProjectionMask designer; 16 | ofxLayerMask *pattern1, *pattern2; 17 | 18 | float currentHue; 19 | }; 20 | -------------------------------------------------------------------------------- /ofxaddons_thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microcosm/ofxProjectionMask/300750e49d425d91964e1b61602d9b2f071aaba5/ofxaddons_thumbnail.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microcosm/ofxProjectionMask/300750e49d425d91964e1b61602d9b2f071aaba5/screenshot.png -------------------------------------------------------------------------------- /src/Drawing/Areas/Canvas.cpp: -------------------------------------------------------------------------------- 1 | #include "Canvas.h" 2 | 3 | const ofColor outlineColor = ofColor(255, 255, 255, 255); 4 | const ofColor interiorColor = ofColor(255, 255, 255, 100); 5 | const int nameTextOffset = 8; 6 | 7 | int Canvas::getWidth(){ 8 | return this->width; 9 | } 10 | 11 | int Canvas::getHeight(){ 12 | return this->height; 13 | } 14 | 15 | int Canvas::getX(){ 16 | return this->x; 17 | } 18 | 19 | int Canvas::getY(){ 20 | return this->y; 21 | } 22 | 23 | void Canvas::setName(string name){ 24 | this->name = name; 25 | } 26 | 27 | void Canvas::setPosition(int x, int y){ 28 | this->x = x; 29 | this->y = y; 30 | } 31 | 32 | void Canvas::setSize(int width, int height){ 33 | this->width = width; 34 | this->height = height; 35 | this->calculateGridLineDistances(); 36 | } 37 | 38 | void Canvas::setNumGridLines(int numGridLinesX, int numGridLinesY){ 39 | this->numGridLinesX = numGridLinesX; 40 | this->numGridLinesY = numGridLinesY; 41 | this->calculateGridLineDistances(); 42 | } 43 | 44 | void Canvas::calculateGridLineDistances(){ 45 | if(this->width > 0 && this->numGridLinesX > 0){ 46 | this->gridLineDistanceX = ceil((float)this->width / this->numGridLinesX); 47 | } 48 | if(this->height > 0 && this->numGridLinesY > 0){ 49 | this->gridLineDistanceY = ceil((float)this->height / this->numGridLinesY); 50 | } 51 | } 52 | 53 | void Canvas::draw(){ 54 | ofNoFill(); 55 | ofSetColor(outlineColor); 56 | ofDrawRectangle(0, 0, width, height); 57 | ofSetColor(interiorColor); 58 | for (int i = 0; i < width; i += this->gridLineDistanceX){ 59 | ofDrawLine(i, 0, i, height); 60 | } 61 | for (int i = 0; i < height; i += this->gridLineDistanceY){ 62 | ofDrawLine(0, i, width, i); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Drawing/Areas/Canvas.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | 4 | class Canvas{ 5 | public: 6 | int getWidth(); 7 | int getHeight(); 8 | int getX(); 9 | int getY(); 10 | void setName(string name); 11 | void setPosition(int x, int y); 12 | void setSize(int width, int height); 13 | void setNumGridLines(int numGridLinesX, int numGridLinesY); 14 | void draw(); 15 | 16 | protected: 17 | string name; 18 | int width; 19 | int height; 20 | int x; 21 | int y; 22 | int numGridLinesX; 23 | int numGridLinesY; 24 | int gridLineDistanceX; 25 | int gridLineDistanceY; 26 | void calculateGridLineDistances(); 27 | }; -------------------------------------------------------------------------------- /src/Drawing/Areas/MaskFrame.cpp: -------------------------------------------------------------------------------- 1 | #include "MaskFrame.h" 2 | 3 | const ofColor notHighlightedColor = ofColor(255, 255, 255, 128); 4 | const ofColor highlightedColor = ofColor(0, 255, 255, 255); 5 | const ofColor maskLineColor = ofColor(255, 255, 255, 128); 6 | const int minimumFrameSize = 6; 7 | const int frameMargin = 2; 8 | const int cursorMargin = 6; 9 | 10 | //Public 11 | int MaskFrame::getId(){ 12 | return frameId; 13 | } 14 | 15 | void MaskFrame::setId(int newId){ 16 | frameId = newId; 17 | } 18 | 19 | void MaskFrame::assignCanvases(Canvas& designCanvas, Canvas& liveCanvas){ 20 | this->designCanvas = &designCanvas; 21 | this->liveCanvas = &liveCanvas; 22 | } 23 | 24 | void MaskFrame::setPattern(ofxLayerMask *pattern){ 25 | this->pattern = pattern; 26 | } 27 | 28 | void MaskFrame::highlightIfCloseTo(int absoluteX, int absoluteY){ 29 | this->highlightDragHandlesIfCloseTo(absoluteX, absoluteY); 30 | if(this->hasHighlightedDragHandle()){ 31 | this->highlighted = false; 32 | this->unhighlightAllMaskPoints(); 33 | }else{ 34 | this->highlighted = true; 35 | this->highlightRectIfCloseTo(absoluteX, absoluteY); 36 | this->highlightMaskPointsIfCloseTo(absoluteX, absoluteY); 37 | 38 | if(this->hasHighlightedMaskPoint()){ 39 | this->hasAGhostPoint = false; 40 | }else{ 41 | this->findGhostPointIfCloseTo(absoluteX, absoluteY); 42 | } 43 | } 44 | } 45 | 46 | void MaskFrame::setHighlighted(bool isHighlighted){ 47 | this->highlighted = isHighlighted; 48 | } 49 | 50 | bool MaskFrame::isHighlighted(){ 51 | return this->highlighted; 52 | } 53 | 54 | bool MaskFrame::hasHighlightedDragHandle(){ 55 | for(int i = 0; i < dragHandles.size(); i++){ 56 | if(dragHandles[i]->isHighlighted()){ 57 | return true; 58 | break; 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | bool MaskFrame::hasHighlightedMaskPoint(){ 65 | for(int i = 0; i < maskPoints.size(); i++){ 66 | if(maskPoints[i]->isHighlighted()){ 67 | return true; 68 | break; 69 | } 70 | } 71 | return false; 72 | } 73 | 74 | MaskPoint* MaskFrame::getHighlightedMaskPoint(){ 75 | for(int i = 0; i < maskPoints.size(); i++){ 76 | if(maskPoints[i]->isHighlighted()){ 77 | return maskPoints[i]; 78 | break; 79 | } 80 | } 81 | return 0; 82 | } 83 | 84 | DragHandle* MaskFrame::getHighlightedDragHandle(){ 85 | for(int i = 0; i < dragHandles.size(); i++){ 86 | if(dragHandles[i]->isHighlighted()){ 87 | return dragHandles[i]; 88 | break; 89 | } 90 | } 91 | return 0; 92 | } 93 | 94 | bool MaskFrame::hasGhostPoint(){ 95 | return this->hasAGhostPoint; 96 | } 97 | 98 | bool MaskFrame::canDrawLive(){ 99 | if(maskPoints.size() > 3){ 100 | return true; 101 | }else if(maskPoints.size() == 3){ 102 | for(int i = 0; i < 3; i++){ 103 | for(int j = 0; j < 3; j++){ 104 | if(!maskPoints[i]->equals(maskPoints[j])){ 105 | return true; 106 | } 107 | } 108 | } 109 | } 110 | return false; 111 | } 112 | 113 | int MaskFrame::getSelectedMaskPointX(){ 114 | return selectedMaskPoint->getX(); 115 | } 116 | 117 | int MaskFrame::getSelectedMaskPointY(){ 118 | return selectedMaskPoint->getY(); 119 | } 120 | 121 | SafeDeque *MaskFrame::getMaskPoints(){ 122 | return &maskPoints; 123 | } 124 | 125 | TransformState MaskFrame::getTransformState(){ 126 | return this->transformState; 127 | } 128 | 129 | void MaskFrame::setTransformState(TransformState transformState){ 130 | this->transformState = transformState; 131 | this->respondToStateChange(); 132 | } 133 | 134 | void MaskFrame::drawDesign(){ 135 | ofPushMatrix(); 136 | ofTranslate(this->designPosition.x, this->designPosition.y); 137 | 138 | bool hasHighlightedDragHandle = this->hasHighlightedDragHandle(); 139 | bool hasHighlightedMaskPoint = this->hasHighlightedMaskPoint(); 140 | 141 | if((highlighted || hasHighlightedDragHandle || getTransformState() == Scaling) && !hasHighlightedMaskPoint){ 142 | ofSetColor(highlightedColor); 143 | }else{ 144 | ofSetColor(notHighlightedColor); 145 | } 146 | ofDrawRectangle(0, 0, this->designWidth, this->designHeight); 147 | 148 | if((highlighted || hasHighlightedDragHandle) && !hasHighlightedMaskPoint){ 149 | for(int i = 0; i < dragHandles.size(); i++){ 150 | dragHandles[i]->drawDesign(); 151 | } 152 | } 153 | 154 | if(maskPoints.size() > 1){ 155 | ofSetColor(maskLineColor); 156 | for(int i = 0; i < maskPoints.size(); i++){ 157 | int nextIndex = getNextIndex(i, maskPoints.size()); 158 | ofDrawLine(maskPoints[i]->getX(), maskPoints[i]->getY(), maskPoints[nextIndex]->getX(), maskPoints[nextIndex]->getY()); 159 | } 160 | } 161 | 162 | if(this->hasAGhostPoint){ 163 | ghostPoint.drawDesign(); 164 | } 165 | 166 | for(int i = 0; i < maskPoints.size(); i++){ 167 | maskPoints[i]->drawDesign(); 168 | } 169 | 170 | ofPopMatrix(); 171 | } 172 | 173 | void MaskFrame::drawLive(DisplayMode mode, StretchMode stretchMode){ 174 | ofPushMatrix(); 175 | ofTranslate(this->livePosition.x, this->livePosition.y); 176 | 177 | if(this->canDrawLive()){ 178 | homographyMode = stretchMode == HOMOGRAPHY && maskPoints.size() == 4; 179 | ofSetColor(ofColor::white); 180 | 181 | if(homographyMode) { 182 | prepareHomography(); 183 | homography.begin(input, output); 184 | pattern->drawLayer(0, false); 185 | homography.end(); 186 | } else { 187 | pattern->beginMask(); 188 | ofPushStyle(); 189 | { 190 | ofFill(); 191 | ofBackground(ofColor::black); 192 | ofBeginShape(); 193 | for(int i = 0; i < maskPoints.size(); i++){ 194 | if(stretchMode == STRETCH_TO_MASKFRAME) { 195 | x = ofMap(maskPoints[i]->getLiveX(), 0, getLiveWidth(), 0, pattern->getWidth()); 196 | y = ofMap(maskPoints[i]->getLiveY(), 0, getLiveHeight(), 0, pattern->getHeight()); 197 | } else { 198 | x = maskPoints[i]->getLiveX(); 199 | y = maskPoints[i]->getLiveY(); 200 | } 201 | ofVertex(x, y); 202 | } 203 | ofEndShape(); 204 | } 205 | ofPopStyle(); 206 | pattern->endMask(); 207 | 208 | if(stretchMode == STRETCH_TO_MASKFRAME) { 209 | pattern->draw(0, 0, getLiveWidth(), getLiveHeight()); 210 | } else { 211 | pattern->draw(); 212 | } 213 | } 214 | } 215 | 216 | if(mode != Live){ 217 | 218 | bool hasHighlightedDragHandle = this->hasHighlightedDragHandle(); 219 | bool hasHighlightedMaskPoint = this->hasHighlightedMaskPoint(); 220 | 221 | ofPushStyle(); 222 | { 223 | if((highlighted || hasHighlightedDragHandle || getTransformState() == Scaling) && !hasHighlightedMaskPoint){ 224 | ofSetColor(highlightedColor); 225 | }else{ 226 | ofSetColor(notHighlightedColor); 227 | } 228 | ofDrawRectangle(0, 0, this->liveWidth, this->liveHeight); 229 | 230 | if((highlighted || hasHighlightedDragHandle) && !hasHighlightedMaskPoint){ 231 | for(int i = 0; i < dragHandles.size(); i++){ 232 | dragHandles[i]->drawLive(); 233 | } 234 | } 235 | } 236 | ofPopStyle(); 237 | } 238 | 239 | if(mode == Design){ 240 | if(maskPoints.size() > 2){ 241 | ofSetColor(maskLineColor); 242 | for(int i = 0; i < maskPoints.size(); i++){ 243 | int nextIndex = getNextIndex(i, maskPoints.size()); 244 | ofDrawLine(maskPoints[i]->getLiveX(), maskPoints[i]->getLiveY(), maskPoints[nextIndex]->getLiveX(), maskPoints[nextIndex]->getLiveY()); 245 | } 246 | } 247 | } 248 | 249 | if(mode != Live){ 250 | 251 | if(this->hasAGhostPoint){ 252 | ghostPoint.drawLive(); 253 | } 254 | 255 | for(int i = 0; i < maskPoints.size(); i++){ 256 | maskPoints[i]->drawLive(); 257 | } 258 | } 259 | ofPopMatrix(); 260 | } 261 | 262 | void MaskFrame::setSize(int width, int height){ 263 | this->designWidth = width; 264 | this->designHeight = height; 265 | setDragHandlePositions(); 266 | transposeToLiveCanvas(); 267 | } 268 | 269 | void MaskFrame::setSize(int width, int height, Corner movingCorner){ 270 | this->setPositionsToMatchScaleChange(width, height, movingCorner); 271 | this->setSize(width, height); 272 | } 273 | 274 | void MaskFrame::setLiveSize(int width, int height){ 275 | this->liveWidth = width; 276 | this->liveHeight = height; 277 | transposeToDesignCanvas(); 278 | setDragHandlePositions(); 279 | } 280 | 281 | void MaskFrame::setLiveSize(int width, int height, Corner movingCorner){ 282 | this->setLivePositionsToMatchScaleChange(width, height, movingCorner); 283 | this->setLiveSize(width, height); 284 | } 285 | 286 | void MaskFrame::setPosition(int absoluteX, int absoluteY){ 287 | setRectPosition(absoluteX, absoluteY); 288 | setDragHandlePositions(); 289 | transposeToLiveCanvas(); 290 | } 291 | 292 | void MaskFrame::setLivePosition(int absoluteX, int absoluteY){ 293 | setLiveRectPosition(absoluteX, absoluteY); 294 | transposeToDesignCanvas(); 295 | setDragHandlePositions(); 296 | } 297 | 298 | void MaskFrame::setLiveRelativePosition(int absoluteX, int absoluteY){ 299 | setLiveRectPosition(this->liveCanvas->getX() + absoluteX, this->liveCanvas->getY() + absoluteY); 300 | transposeToDesignCanvas(); 301 | setDragHandlePositions(); 302 | } 303 | 304 | void MaskFrame::setSelectedMaskPointPosition(int x, int y){ 305 | int clampedX = clampInt(x, frameMargin, this->getWidth() - frameMargin); 306 | int clampedY = clampInt(y, frameMargin, this->getHeight() - frameMargin); 307 | selectedMaskPoint->setPosition(clampedX, clampedY); 308 | transposeToLiveCanvas(); 309 | } 310 | 311 | void MaskFrame::setX(int absoluteX){ 312 | this->setRectX(absoluteX); 313 | setDragHandlePositions(); 314 | transposeToLiveCanvas(); 315 | } 316 | 317 | void MaskFrame::setY(int absoluteY){ 318 | this->setRectY(absoluteY); 319 | setDragHandlePositions(); 320 | transposeToLiveCanvas(); 321 | } 322 | 323 | int MaskFrame::getX(){ 324 | return designCanvas->getX() + designPosition.x; 325 | } 326 | 327 | int MaskFrame::getY(){ 328 | return designCanvas->getY() + designPosition.y; 329 | } 330 | 331 | int MaskFrame::getRelativeX(){ 332 | return designPosition.x; 333 | } 334 | 335 | int MaskFrame::getRelativeY(){ 336 | return designPosition.y; 337 | } 338 | 339 | int MaskFrame::getWidth(){ 340 | return designWidth; 341 | } 342 | 343 | int MaskFrame::getHeight(){ 344 | return designHeight; 345 | } 346 | 347 | int MaskFrame::getLiveX(){ 348 | return liveCanvas->getX() + livePosition.x; 349 | } 350 | 351 | int MaskFrame::getLiveY(){ 352 | return liveCanvas->getY() + livePosition.y; 353 | } 354 | 355 | int MaskFrame::getLiveRelativeX(){ 356 | return livePosition.x; 357 | } 358 | 359 | int MaskFrame::getLiveRelativeY(){ 360 | return livePosition.y; 361 | } 362 | 363 | int MaskFrame::getLiveWidth(){ 364 | return liveWidth; 365 | } 366 | 367 | int MaskFrame::getLiveHeight(){ 368 | return liveHeight; 369 | } 370 | 371 | int MaskFrame::getSmallestLegalWidth(Corner cornerBeingAdjusted){ 372 | int result; 373 | if(cornerBeingAdjusted == TopRight || cornerBeingAdjusted == BottomRight){ 374 | result = getWidestPointLeftToRight(); 375 | }else if(cornerBeingAdjusted == TopLeft || cornerBeingAdjusted == BottomLeft){ 376 | result = getWidestPointRightToLeft(); 377 | } 378 | 379 | result += frameMargin; 380 | if(result < minimumFrameSize){ 381 | return minimumFrameSize; 382 | } 383 | return result; 384 | } 385 | 386 | int MaskFrame::getSmallestLegalHeight(Corner cornerBeingAdjusted){ 387 | int result; 388 | if(cornerBeingAdjusted == BottomLeft || cornerBeingAdjusted == BottomRight){ 389 | result = getTallestPointTopToBottom(); 390 | }else if(cornerBeingAdjusted == TopLeft || cornerBeingAdjusted == TopRight){ 391 | result = getTallestPointBottomToTop(); 392 | } 393 | 394 | result += frameMargin; 395 | if(result < minimumFrameSize){ 396 | return minimumFrameSize; 397 | } 398 | return result; 399 | } 400 | 401 | void MaskFrame::addMaskPoint(int absoluteX, int absoluteY){ 402 | if(maskPoints.size() < 3){ 403 | int x = absoluteX - this->designCanvas->getX() - this->designPosition.x; 404 | int y = absoluteY - this->designCanvas->getY() - this->designPosition.y; 405 | MaskPoint maskPoint; 406 | maskPoint.setType(Real); 407 | maskPoint.setPosition(x, y); 408 | this->insert(&maskPoint); 409 | }else if(this->hasAGhostPoint){ 410 | this->makeGhostPointReal(); 411 | } 412 | transposeToLiveCanvas(); 413 | } 414 | 415 | void MaskFrame::makeGhostPointReal(){ 416 | MaskPoint maskPoint; 417 | maskPoint.setType(Real); 418 | maskPoint.setPosition(this->ghostPoint.getX(), this->ghostPoint.getY()); 419 | maskPoint.setHighlighted(true); 420 | this->insert(&maskPoint); 421 | this->hasAGhostPoint = false; 422 | transposeToLiveCanvas(); 423 | } 424 | 425 | void MaskFrame::deleteSelectedMaskPoint(){ 426 | for(int i = 0; i < maskPoints.size(); i++){ 427 | if(maskPoints[i]->isHighlighted()){ 428 | maskPoints.deleteItem(i); 429 | break; 430 | } 431 | } 432 | transposeToLiveCanvas(); 433 | } 434 | 435 | void MaskFrame::nudge(Direction direction){ 436 | 437 | int newX, newY; 438 | newX = this->livePosition.x; 439 | newY = this->livePosition.y; 440 | 441 | if(direction == Left){ 442 | newX--; 443 | }else if(direction == Up){ 444 | newY--; 445 | }else if(direction == Right){ 446 | newX++; 447 | }else if(direction == Down){ 448 | newY++; 449 | } 450 | 451 | int innerBoundaryX = 0; 452 | int outerBoundaryX = this->liveCanvas->getWidth() - this->liveWidth; 453 | this->livePosition.x = clampInt(newX, innerBoundaryX, outerBoundaryX); 454 | 455 | int innerBoundaryY = 0; 456 | int outerBoundaryY = this->liveCanvas->getHeight() - this->liveHeight; 457 | this->livePosition.y = clampInt(newY, innerBoundaryY, outerBoundaryY); 458 | 459 | transposeToDesignCanvas(); 460 | } 461 | 462 | void MaskFrame::nudgeDragHandle(Direction direction){ 463 | 464 | int newWidth, newHeight; 465 | newWidth = this->liveWidth; 466 | newHeight = this->liveHeight; 467 | 468 | DragHandle *highlightedDragHandle = this->getHighlightedDragHandle(); 469 | Corner corner = highlightedDragHandle->getCorner(); 470 | 471 | if(corner == TopLeft){ 472 | if(direction == Left){ 473 | newWidth++; 474 | }else if(direction == Up){ 475 | newHeight++; 476 | }else if(direction == Right){ 477 | newWidth--; 478 | }else if(direction == Down){ 479 | newHeight--; 480 | } 481 | }else if(corner == TopRight){ 482 | if(direction == Left){ 483 | newWidth--; 484 | }else if(direction == Up){ 485 | newHeight++; 486 | }else if(direction == Right){ 487 | newWidth++; 488 | }else if(direction == Down){ 489 | newHeight--; 490 | } 491 | }else if(corner == BottomRight){ 492 | if(direction == Left){ 493 | newWidth--; 494 | }else if(direction == Up){ 495 | newHeight--; 496 | }else if(direction == Right){ 497 | newWidth++; 498 | }else if(direction == Down){ 499 | newHeight++; 500 | } 501 | }else if(corner == BottomLeft){ 502 | if(direction == Left){ 503 | newWidth++; 504 | }else if(direction == Up){ 505 | newHeight--; 506 | }else if(direction == Right){ 507 | newWidth--; 508 | }else if(direction == Down){ 509 | newHeight++; 510 | } 511 | } 512 | 513 | int smallestLegalWidth = this->getSmallestLegalLiveWidth(corner); 514 | int smallestLegalHeight = this->getSmallestLegalLiveHeight(corner); 515 | int newWidthClamped = clampInt(newWidth, smallestLegalWidth); 516 | int newHeightClamped = clampInt(newHeight, smallestLegalHeight); 517 | this->setLiveSize(newWidthClamped, newHeightClamped, corner); 518 | } 519 | 520 | void MaskFrame::nudgeMaskPoint(Direction direction){ 521 | MaskPoint* highlightedMaskPoint = getHighlightedMaskPoint(); 522 | if(highlightedMaskPoint != 0){ 523 | 524 | int newX, newY; 525 | newX = highlightedMaskPoint->getLiveX(); 526 | newY = highlightedMaskPoint->getLiveY(); 527 | 528 | if(direction == Left){ 529 | newX--; 530 | }else if(direction == Up){ 531 | newY--; 532 | }else if(direction == Right){ 533 | newX++; 534 | }else if(direction == Down){ 535 | newY++; 536 | } 537 | 538 | newX = clampInt(newX, frameMargin, this->liveWidth - frameMargin); 539 | newY = clampInt(newY, frameMargin, this->liveHeight - frameMargin); 540 | 541 | highlightedMaskPoint->setLiveX(newX); 542 | highlightedMaskPoint->setLiveY(newY); 543 | transposeToDesignCanvas(); 544 | } 545 | } 546 | 547 | Corner MaskFrame::highlightedCorner(){ 548 | for(int i = 0; i < dragHandles.size(); i++){ 549 | if(dragHandles[i]->isHighlighted()){ 550 | return dragHandles[i]->getCorner(); 551 | } 552 | } 553 | throw "Highlighted corner not found"; 554 | } 555 | 556 | void MaskFrame::transposeToLiveCanvas(){ 557 | int designCanvasWidth = this->designCanvas->getWidth(); 558 | int designCanvasHeight = this->designCanvas->getHeight(); 559 | int liveCanvasWidth = this->liveCanvas->getWidth(); 560 | int liveCanvasHeight = this->liveCanvas->getHeight(); 561 | 562 | this->livePosition.x = ceil(ofMap(this->designPosition.x, 0, designCanvasWidth, 0, liveCanvasWidth)); 563 | this->livePosition.y = ceil(ofMap(this->designPosition.y, 0, designCanvasHeight, 0, liveCanvasHeight)); 564 | 565 | this->liveWidth = ceil(ofMap(this->designWidth, 0, designCanvasWidth, 0, liveCanvasWidth)); 566 | this->liveHeight = ceil(ofMap(this->designHeight, 0, designCanvasHeight, 0, liveCanvasHeight)); 567 | 568 | for(int i = 0; i < maskPoints.size(); i++){ 569 | int liveX = ceil(ofMap(maskPoints[i]->getX(), 0, designCanvasWidth, 0, liveCanvasWidth)); 570 | int liveY = ceil(ofMap(maskPoints[i]->getY(), 0, designCanvasHeight, 0, liveCanvasHeight)); 571 | maskPoints[i]->setLiveX(liveX); 572 | maskPoints[i]->setLiveY(liveY); 573 | } 574 | 575 | if(this->hasGhostPoint()){ 576 | int liveX = ceil(ofMap(ghostPoint.getX(), 0, designCanvasWidth, 0, liveCanvasWidth)); 577 | int liveY = ceil(ofMap(ghostPoint.getY(), 0, designCanvasHeight, 0, liveCanvasHeight)); 578 | ghostPoint.setLiveX(liveX); 579 | ghostPoint.setLiveY(liveY); 580 | } 581 | } 582 | 583 | void MaskFrame::transposeToDesignCanvas(){ 584 | int designCanvasWidth = this->designCanvas->getWidth(); 585 | int designCanvasHeight = this->designCanvas->getHeight(); 586 | int liveCanvasWidth = this->liveCanvas->getWidth(); 587 | int liveCanvasHeight = this->liveCanvas->getHeight(); 588 | 589 | this->designPosition.x = floor(ofMap(this->livePosition.x, 0, liveCanvasWidth, 0, designCanvasWidth)); 590 | this->designPosition.y = floor(ofMap(this->livePosition.y, 0, liveCanvasHeight, 0, designCanvasHeight)); 591 | 592 | this->designWidth = floor(ofMap(this->liveWidth, 0, liveCanvasWidth, 0, designCanvasWidth)); 593 | this->designHeight = floor(ofMap(this->liveHeight, 0, liveCanvasHeight, 0, designCanvasHeight)); 594 | 595 | for(int i = 0; i < maskPoints.size(); i++){ 596 | int designX = floor(ofMap(maskPoints[i]->getLiveX(), 0, liveCanvasWidth, 0, designCanvasWidth)); 597 | int designY = floor(ofMap(maskPoints[i]->getLiveY(), 0, liveCanvasHeight, 0, designCanvasHeight)); 598 | maskPoints[i]->setPosition(designX, designY); 599 | } 600 | } 601 | 602 | //Protected 603 | void MaskFrame::prepareHomography() { 604 | input[0] = ofPoint(0, 0); 605 | input[1] = ofPoint(pattern->getWidth(), 0); 606 | input[2] = ofPoint(pattern->getWidth(), pattern->getHeight()); 607 | input[3] = ofPoint(0, pattern->getHeight()); 608 | for(int i = 0; i < 4; i++) { 609 | x = maskPoints[i]->getLiveX(); 610 | y = maskPoints[i]->getLiveY(); 611 | output[i] = ofPoint(x, y); 612 | } 613 | } 614 | 615 | void MaskFrame::findGhostPointIfCloseTo(int absoluteX, int absoluteY){ 616 | int maskFrameX = absoluteX - this->getX(); 617 | int maskFrameY = absoluteY - this->getY(); 618 | this->hasAGhostPoint = false; 619 | for(int i = 0; i < maskPoints.size(); i++){ 620 | int nextIndex = getNextIndex(i, maskPoints.size()); 621 | this->hasAGhostPoint = getIntersection(maskFrameX, maskFrameY, maskPoints[i], maskPoints[nextIndex], &ghostPoint); 622 | if(this->hasAGhostPoint){ 623 | ghostPointIndex = nextIndex; 624 | transposeToLiveCanvas(); 625 | break; 626 | } 627 | } 628 | } 629 | 630 | void MaskFrame::highlightRectIfCloseTo(int absoluteX, int absoluteY){ 631 | int canvasX = absoluteX - this->designCanvas->getX(); 632 | int canvasY = absoluteY - this->designCanvas->getY(); 633 | bool containsPosition = containsPositionInRect(canvasX, canvasY) || containsPositionInDragHandles(canvasX, canvasY); 634 | this->setHighlighted(containsPosition); 635 | } 636 | 637 | void MaskFrame::highlightDragHandlesIfCloseTo(int absoluteX, int absoluteY){ 638 | int canvasX = absoluteX - this->designCanvas->getX(); 639 | int canvasY = absoluteY - this->designCanvas->getY(); 640 | for(int i = 0; i < dragHandles.size(); i++){ 641 | bool isHighlighted = containsPosition(canvasX, canvasY, dragHandles[i]); 642 | dragHandles[i]->setHighlighted(isHighlighted); 643 | } 644 | } 645 | 646 | void MaskFrame::highlightMaskPointsIfCloseTo(int absoluteX, int absoluteY){ 647 | int canvasX = absoluteX - this->designCanvas->getX(); 648 | int canvasY = absoluteY - this->designCanvas->getY(); 649 | for(int i = 0; i < maskPoints.size(); i++){ 650 | bool isHighlighted = containsPosition(canvasX, canvasY, maskPoints[i]); 651 | maskPoints[i]->setHighlighted(isHighlighted); 652 | } 653 | } 654 | 655 | void MaskFrame::unhighlightAllDragHandles(){ 656 | for(int i = 0; i < dragHandles.size(); i++){ 657 | dragHandles[i]->setHighlighted(false); 658 | } 659 | } 660 | 661 | void MaskFrame::unhighlightAllMaskPoints(){ 662 | for(int i = 0; i < maskPoints.size(); i++){ 663 | maskPoints[i]->setHighlighted(false); 664 | } 665 | } 666 | 667 | void MaskFrame::selectHighlightedMaskPoint(){ 668 | for(int i = 0; i < maskPoints.size(); i++){ 669 | if(maskPoints[i]->isHighlighted()){ 670 | selectedMaskPoint = maskPoints[i]; 671 | return; 672 | } 673 | } 674 | throw "No highlighted mask point found to select"; 675 | } 676 | 677 | void MaskFrame::deselectMaskPoint(){ 678 | selectedMaskPoint = 0; 679 | } 680 | 681 | void MaskFrame::insert(MaskPoint *maskPoint){ 682 | if(maskPoints.size() < 3){ 683 | maskPoints.push_back(*maskPoint); 684 | }else if(this->hasAGhostPoint){ 685 | maskPoints.insert(ghostPointIndex, *maskPoint); 686 | } 687 | } 688 | 689 | bool MaskFrame::getIntersection(int maskFrameX, int maskFrameY, MaskPoint* maskPoint1, MaskPoint* maskPoint2, MaskPoint* intersection){ 690 | 691 | ofPoint maskPointLineStart, maskPointLineEnd; 692 | maskPointLineStart.x = maskPoint1->getX(); 693 | maskPointLineStart.y = maskPoint1->getY(); 694 | maskPointLineEnd.x = maskPoint2->getX(); 695 | maskPointLineEnd.y = maskPoint2->getY(); 696 | 697 | ofPoint mouseCursorWithXMarginStart, mouseCursorWithXMarginEnd, xIntersection; 698 | mouseCursorWithXMarginStart.x = maskFrameX - round(cursorMargin / 2); 699 | mouseCursorWithXMarginStart.y = maskFrameY; 700 | mouseCursorWithXMarginEnd.x = mouseCursorWithXMarginStart.x + cursorMargin; 701 | mouseCursorWithXMarginEnd.y = maskFrameY; 702 | 703 | ofPoint mouseCursorWithYMarginStart, mouseCursorWithYMarginEnd, yIntersection; 704 | mouseCursorWithYMarginStart.x = maskFrameX; 705 | mouseCursorWithYMarginStart.y = maskFrameY - round(cursorMargin / 2); 706 | mouseCursorWithYMarginEnd.x = maskFrameX; 707 | mouseCursorWithYMarginEnd.y = mouseCursorWithYMarginStart.y + cursorMargin; 708 | 709 | bool xIntersects = ofLineSegmentIntersection(mouseCursorWithXMarginStart, mouseCursorWithXMarginEnd, maskPointLineStart, maskPointLineEnd, xIntersection); 710 | bool yIntersects = ofLineSegmentIntersection(mouseCursorWithYMarginStart, mouseCursorWithYMarginEnd, maskPointLineStart, maskPointLineEnd, yIntersection); 711 | 712 | if(xIntersects){ 713 | intersection->setPosition(xIntersection.x, xIntersection.y); 714 | }else if(yIntersects){ 715 | intersection->setPosition(yIntersection.x, yIntersection.y); 716 | } 717 | return xIntersects || yIntersects; 718 | } 719 | 720 | void MaskFrame::initialiseDragHandles(){ 721 | DragHandle topLeft, topRight, bottomRight, bottomLeft; 722 | 723 | topLeft.setCorner(TopLeft); 724 | topRight.setCorner(TopRight); 725 | bottomRight.setCorner(BottomRight); 726 | bottomLeft.setCorner(BottomLeft); 727 | 728 | dragHandles.push_back(topLeft); 729 | dragHandles.push_back(topRight); 730 | dragHandles.push_back(bottomRight); 731 | dragHandles.push_back(bottomLeft); 732 | } 733 | 734 | void MaskFrame::respondToStateChange(){ 735 | if(transformState == Masking){ 736 | this->selectHighlightedMaskPoint(); 737 | }else{ 738 | this->deselectMaskPoint(); 739 | } 740 | if(transformState == NoTransform){ 741 | this->highlighted = false; 742 | this->unhighlightAllDragHandles(); 743 | } 744 | } 745 | 746 | bool MaskFrame::containsPositionInRect(int canvasX, int canvasY){ 747 | return( 748 | canvasX > this->designPosition.x && 749 | canvasY > this->designPosition.y && 750 | canvasX < (this->designPosition.x + this->designWidth) && 751 | canvasY < (this->designPosition.y + this->designHeight)); 752 | } 753 | 754 | bool MaskFrame::containsPositionInDragHandles(int canvasX, int canvasY){ 755 | for(int i = 0; i < dragHandles.size(); i++){ 756 | if(containsPosition(canvasX, canvasY, dragHandles[i])){ 757 | return true; 758 | } 759 | } 760 | return false; 761 | } 762 | 763 | bool MaskFrame::containsPosition(int canvasX, int canvasY, PointObject* pointObject){ 764 | int maskFrameX = canvasX - this->designPosition.x; 765 | int maskFrameY = canvasY - this->designPosition.y; 766 | int pointObjectX = pointObject->getX(); 767 | int pointObjectY = pointObject->getY(); 768 | int pointObjectRadius = pointObject->getRadius(); 769 | 770 | if(abs(ofDist(maskFrameX, maskFrameY, pointObjectX, pointObjectY)) < pointObjectRadius){ 771 | return true; 772 | } 773 | return false; 774 | } 775 | 776 | void MaskFrame::setRectPosition(int absoluteX, int absoluteY){ 777 | setRectX(absoluteX); 778 | setRectY(absoluteY); 779 | } 780 | 781 | void MaskFrame::setLiveRectPosition(int absoluteX, int absoluteY){ 782 | setLiveRectX(absoluteX); 783 | setLiveRectY(absoluteY); 784 | } 785 | 786 | void MaskFrame::setRectX(int absoluteX){ 787 | int canvasX = absoluteX - this->designCanvas->getX(); 788 | int innerBoundaryX = 0; 789 | int outerBoundaryX = this->designCanvas->getWidth() - this->designWidth; 790 | this->designPosition.x = clampInt(canvasX, innerBoundaryX, outerBoundaryX); 791 | } 792 | 793 | void MaskFrame::setRectY(int absoluteY){ 794 | int canvasY = absoluteY - this->designCanvas->getY(); 795 | int innerBoundaryY = 0; 796 | int outerBoundaryY = this->designCanvas->getHeight() - this->designHeight; 797 | this->designPosition.y = clampInt(canvasY, innerBoundaryY, outerBoundaryY); 798 | } 799 | 800 | void MaskFrame::setLiveRectX(int absoluteX){ 801 | int canvasX = absoluteX - this->liveCanvas->getX(); 802 | int innerBoundaryX = 0; 803 | int outerBoundaryX = this->liveCanvas->getWidth() - this->liveWidth; 804 | this->livePosition.x = clampInt(canvasX, innerBoundaryX, outerBoundaryX); 805 | } 806 | 807 | void MaskFrame::setLiveRectY(int absoluteY){ 808 | int canvasY = absoluteY - this->liveCanvas->getY(); 809 | int innerBoundaryY = 0; 810 | int outerBoundaryY = this->liveCanvas->getHeight() - this->liveHeight; 811 | this->livePosition.y = clampInt(canvasY, innerBoundaryY, outerBoundaryY); 812 | } 813 | 814 | void MaskFrame::setDragHandlePositions(){ 815 | for(int i = 0; i < dragHandles.size(); i++){ 816 | Corner corner = dragHandles[i]->getCorner(); 817 | if(corner == TopLeft){ 818 | dragHandles[i]->setPosition(0, 0); 819 | dragHandles[i]->setLivePosition(0, 0); 820 | }else if(corner == TopRight){ 821 | dragHandles[i]->setPosition(this->designWidth, 0); 822 | dragHandles[i]->setLivePosition(this->liveWidth, 0); 823 | }else if(corner == BottomRight){ 824 | dragHandles[i]->setPosition(this->designWidth, this->designHeight); 825 | dragHandles[i]->setLivePosition(this->liveWidth, this->liveHeight); 826 | }else if(corner == BottomLeft){ 827 | dragHandles[i]->setPosition(0, this->designHeight); 828 | dragHandles[i]->setLivePosition(0, this->liveHeight); 829 | } 830 | } 831 | } 832 | 833 | /* Design */ 834 | void MaskFrame::setPositionsToMatchScaleChange(int width, int height, Corner movingCorner){ 835 | if(movingCorner == BottomLeft){ 836 | this->setXPositionsToMatchScaleChange(width); 837 | 838 | }else if(movingCorner == TopLeft){ 839 | this->setXPositionsToMatchScaleChange(width); 840 | this->setYPositionsToMatchScaleChange(height); 841 | 842 | }else if(movingCorner == TopRight){ 843 | this->setYPositionsToMatchScaleChange(height); 844 | } 845 | } 846 | 847 | void MaskFrame::setXPositionsToMatchScaleChange(int width){ 848 | int oldX = this->getX(); 849 | int oldWidth = this->getWidth(); 850 | int difference = width - oldWidth; 851 | this->setX(oldX - difference); 852 | this->translateMaskPointsX(difference); 853 | } 854 | 855 | void MaskFrame::setYPositionsToMatchScaleChange(int height){ 856 | int oldY = this->getY(); 857 | int oldHeight = this->getHeight(); 858 | int difference = height - oldHeight; 859 | this->setY(oldY - difference); 860 | this->translateMaskPointsY(difference); 861 | } 862 | 863 | void MaskFrame::translateMaskPointsX(int amount){ 864 | for(int i = 0; i < maskPoints.size(); i++){ 865 | int liveAmount = ofMap(amount, 0, this->designCanvas->getWidth(), 0, this->liveCanvas->getWidth()); 866 | int newX = maskPoints[i]->getX() + amount; 867 | int newLiveX = maskPoints[i]->getLiveX() + liveAmount; 868 | maskPoints[i]->setX(newX); 869 | maskPoints[i]->setLiveX(newLiveX); 870 | } 871 | } 872 | 873 | void MaskFrame::translateMaskPointsY(int amount){ 874 | for(int i = 0; i < maskPoints.size(); i++){ 875 | int liveAmount = ofMap(amount, 0, this->designCanvas->getHeight(), 0, this->liveCanvas->getHeight()); 876 | int newY = maskPoints[i]->getY() + amount; 877 | int newLiveY = maskPoints[i]->getLiveY() + liveAmount; 878 | maskPoints[i]->setY(newY); 879 | maskPoints[i]->setLiveY(newLiveY); 880 | } 881 | } 882 | 883 | int MaskFrame::getWidestPointLeftToRight(){ 884 | int widestPointFound = 0; 885 | for(int i = 0; i < maskPoints.size(); i++){ 886 | if(maskPoints[i]->getX() > widestPointFound){ 887 | widestPointFound = maskPoints[i]->getX(); 888 | } 889 | } 890 | return widestPointFound; 891 | } 892 | 893 | int MaskFrame::getWidestPointRightToLeft(){ 894 | int widestPointFound = this->getWidth(); 895 | for(int i = 0; i < maskPoints.size(); i++){ 896 | if(maskPoints[i]->getX() < widestPointFound){ 897 | widestPointFound = maskPoints[i]->getX(); 898 | } 899 | } 900 | return this->getWidth() - widestPointFound; 901 | } 902 | 903 | int MaskFrame::getTallestPointTopToBottom(){ 904 | int tallestPointFound = 0; 905 | for(int i = 0; i < maskPoints.size(); i++){ 906 | if(maskPoints[i]->getY() > tallestPointFound){ 907 | tallestPointFound = maskPoints[i]->getY(); 908 | } 909 | } 910 | return tallestPointFound; 911 | } 912 | 913 | int MaskFrame::getTallestPointBottomToTop(){ 914 | int tallestPointFound = this->getHeight(); 915 | for(int i = 0; i < maskPoints.size(); i++){ 916 | if(maskPoints[i]->getY() < tallestPointFound){ 917 | tallestPointFound = maskPoints[i]->getY(); 918 | } 919 | } 920 | return this->getHeight() - tallestPointFound; 921 | } 922 | 923 | /* Live */ 924 | void MaskFrame::setLivePositionsToMatchScaleChange(int width, int height, Corner movingCorner){ 925 | if(movingCorner == BottomLeft){ 926 | this->setLiveXPositionsToMatchScaleChange(width); 927 | 928 | }else if(movingCorner == TopLeft){ 929 | this->setLiveXPositionsToMatchScaleChange(width); 930 | this->setLiveYPositionsToMatchScaleChange(height); 931 | 932 | }else if(movingCorner == TopRight){ 933 | this->setLiveYPositionsToMatchScaleChange(height); 934 | } 935 | } 936 | 937 | void MaskFrame::setLiveXPositionsToMatchScaleChange(int width){ 938 | int oldX = this->livePosition.x; 939 | int oldWidth = this->liveWidth; 940 | int difference = width - oldWidth; 941 | this->livePosition.x = oldX - difference; 942 | this->translateMaskPointsLiveX(difference); 943 | } 944 | 945 | void MaskFrame::setLiveYPositionsToMatchScaleChange(int height){ 946 | int oldY = this->livePosition.y; 947 | int oldHeight = this->liveHeight; 948 | int difference = height - oldHeight; 949 | this->livePosition.y = oldY - difference; 950 | this->translateMaskPointsLiveY(difference); 951 | } 952 | 953 | void MaskFrame::translateMaskPointsLiveX(int amount){ 954 | for(int i = 0; i < maskPoints.size(); i++){ 955 | int designAmount = ofMap(amount, 0, this->liveCanvas->getWidth(), 0, this->designCanvas->getWidth()); 956 | int newX = maskPoints[i]->getLiveX() + amount; 957 | int newDesignX = maskPoints[i]->getX() + designAmount; 958 | maskPoints[i]->setLiveX(newX); 959 | maskPoints[i]->setX(newDesignX); 960 | } 961 | } 962 | 963 | void MaskFrame::translateMaskPointsLiveY(int amount){ 964 | for(int i = 0; i < maskPoints.size(); i++){ 965 | int designAmount = ofMap(amount, 0, this->liveCanvas->getHeight(), 0, this->designCanvas->getHeight()); 966 | int newY = maskPoints[i]->getLiveY() + amount; 967 | int newDesignY = maskPoints[i]->getY() + designAmount; 968 | maskPoints[i]->setLiveY(newY); 969 | maskPoints[i]->setY(newDesignY); 970 | } 971 | } 972 | 973 | int MaskFrame::getSmallestLegalLiveWidth(Corner cornerBeingAdjusted){ 974 | int result; 975 | if(cornerBeingAdjusted == TopRight || cornerBeingAdjusted == BottomRight){ 976 | result = getWidestLivePointLeftToRight(); 977 | }else if(cornerBeingAdjusted == TopLeft || cornerBeingAdjusted == BottomLeft){ 978 | result = getWidestLivePointRightToLeft(); 979 | } 980 | 981 | result += frameMargin; 982 | if(result < minimumFrameSize){ 983 | return minimumFrameSize; 984 | } 985 | return result; 986 | } 987 | 988 | int MaskFrame::getSmallestLegalLiveHeight(Corner cornerBeingAdjusted){ 989 | int result; 990 | if(cornerBeingAdjusted == BottomLeft || cornerBeingAdjusted == BottomRight){ 991 | result = getTallestLivePointTopToBottom(); 992 | }else if(cornerBeingAdjusted == TopLeft || cornerBeingAdjusted == TopRight){ 993 | result = getTallestLivePointBottomToTop(); 994 | } 995 | 996 | result += frameMargin; 997 | if(result < minimumFrameSize){ 998 | return minimumFrameSize; 999 | } 1000 | return result; 1001 | } 1002 | 1003 | int MaskFrame::getWidestLivePointLeftToRight(){ 1004 | int widestPointFound = 0; 1005 | for(int i = 0; i < maskPoints.size(); i++){ 1006 | if(maskPoints[i]->getLiveX() > widestPointFound){ 1007 | widestPointFound = maskPoints[i]->getLiveX(); 1008 | } 1009 | } 1010 | return widestPointFound; 1011 | } 1012 | 1013 | int MaskFrame::getWidestLivePointRightToLeft(){ 1014 | int widestPointFound = this->liveWidth; 1015 | for(int i = 0; i < maskPoints.size(); i++){ 1016 | if(maskPoints[i]->getLiveX() < widestPointFound){ 1017 | widestPointFound = maskPoints[i]->getLiveX(); 1018 | } 1019 | } 1020 | return this->liveWidth - widestPointFound; 1021 | } 1022 | 1023 | int MaskFrame::getTallestLivePointTopToBottom(){ 1024 | int tallestPointFound = 0; 1025 | for(int i = 0; i < maskPoints.size(); i++){ 1026 | if(maskPoints[i]->getLiveY() > tallestPointFound){ 1027 | tallestPointFound = maskPoints[i]->getLiveY(); 1028 | } 1029 | } 1030 | return tallestPointFound; 1031 | } 1032 | 1033 | int MaskFrame::getTallestLivePointBottomToTop(){ 1034 | int tallestPointFound = this->liveHeight; 1035 | for(int i = 0; i < maskPoints.size(); i++){ 1036 | if(maskPoints[i]->getLiveY() < tallestPointFound){ 1037 | tallestPointFound = maskPoints[i]->getLiveY(); 1038 | } 1039 | } 1040 | return this->liveHeight - tallestPointFound; 1041 | } 1042 | -------------------------------------------------------------------------------- /src/Drawing/Areas/MaskFrame.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "Canvas.h" 4 | #include "DragHandle.h" 5 | #include "MaskPoint.h" 6 | #include "PointObject.h" 7 | #include "ofExtensions.h" 8 | #include "SafeDeque.h" 9 | #include "Homography.h" 10 | #include "ofxLayerMask.h" 11 | 12 | enum DisplayMode { Design, HalfLive, Live }; 13 | enum StretchMode { 14 | DO_NOT_STRETCH, 15 | STRETCH_TO_MASKFRAME, 16 | HOMOGRAPHY 17 | }; 18 | 19 | class MaskFrame{ 20 | public: 21 | MaskFrame(){ 22 | highlighted = false; 23 | transformState = NoTransform; 24 | selectedMaskPoint = 0; 25 | ghostPoint.setType(Ghost); 26 | ghostPointIndex = 0; 27 | initialiseDragHandles(); 28 | } 29 | 30 | int getId(); 31 | void setId(int newId); 32 | void assignCanvases(Canvas& designCanvas, Canvas& liveCanvas); 33 | void setPattern(ofxLayerMask *pattern); 34 | 35 | void highlightIfCloseTo(int absoluteX, int absoluteY); 36 | void setHighlighted(bool isHighlighted); 37 | bool isHighlighted(); 38 | bool hasHighlightedDragHandle(); 39 | bool hasHighlightedMaskPoint(); 40 | bool hasGhostPoint(); 41 | bool canDrawLive(); 42 | MaskPoint* getHighlightedMaskPoint(); 43 | DragHandle* getHighlightedDragHandle(); 44 | int getSelectedMaskPointX(); 45 | int getSelectedMaskPointY(); 46 | SafeDeque *getMaskPoints(); 47 | 48 | TransformState getTransformState(); 49 | void setTransformState(TransformState transformState); 50 | 51 | void drawDesign(); 52 | void drawLive(DisplayMode mode, StretchMode stretchMode); 53 | 54 | void setSize(int width, int height); 55 | void setSize(int width, int height, Corner movingCorner); 56 | void setLiveSize(int width, int height); 57 | void setLiveSize(int width, int height, Corner movingCorner); 58 | void setPosition(int absoluteX, int absoluteY); 59 | void setLivePosition(int absoluteX, int absoluteY); 60 | void setLiveRelativePosition(int absoluteX, int absoluteY); 61 | void setSelectedMaskPointPosition(int x, int y); 62 | void setX(int absoluteX); 63 | void setY(int absoluteY); 64 | int getX(); 65 | int getY(); 66 | int getRelativeX(); 67 | int getRelativeY(); 68 | int getWidth(); 69 | int getHeight(); 70 | int getLiveX(); 71 | int getLiveY(); 72 | int getLiveRelativeX(); 73 | int getLiveRelativeY(); 74 | int getLiveWidth(); 75 | int getLiveHeight(); 76 | int getSmallestLegalWidth(); 77 | int getSmallestLegalHeight(); 78 | int getSmallestLegalWidth(Corner cornerBeingAdjusted); 79 | int getSmallestLegalHeight(Corner cornerBeingAdjusted); 80 | 81 | void addMaskPoint(int absoluteX, int absoluteY); 82 | void makeGhostPointReal(); 83 | void deleteSelectedMaskPoint(); 84 | 85 | void nudge(Direction direction); 86 | void nudgeMaskPoint(Direction direction); 87 | void nudgeDragHandle(Direction direction); 88 | 89 | void transposeToLiveCanvas(); 90 | void transposeToDesignCanvas(); 91 | 92 | Corner highlightedCorner(); 93 | 94 | protected: 95 | int frameId; 96 | bool highlighted; 97 | bool hasAGhostPoint; 98 | bool homographyMode; 99 | int ghostPointIndex; 100 | TransformState transformState; 101 | MaskPoint* selectedMaskPoint; 102 | MaskPoint ghostPoint; 103 | ofxLayerMask *pattern; 104 | Homography homography; 105 | 106 | int designWidth; 107 | int designHeight; 108 | int liveWidth; 109 | int liveHeight; 110 | ofVec2f designPosition; 111 | ofVec2f livePosition; 112 | Canvas* designCanvas; 113 | Canvas* liveCanvas; 114 | float x, y; 115 | ofPoint input[4]; 116 | ofPoint output[4]; 117 | 118 | SafeDeque dragHandles; 119 | SafeDeque maskPoints; 120 | 121 | void prepareHomography(); 122 | void findGhostPointIfCloseTo(int absoluteX, int absoluteY); 123 | void highlightRectIfCloseTo(int absoluteX, int absoluteY); 124 | void highlightDragHandlesIfCloseTo(int absoluteX, int absoluteY); 125 | void highlightMaskPointsIfCloseTo(int absoluteX, int absoluteY); 126 | void unhighlightAllDragHandles(); 127 | void unhighlightAllMaskPoints(); 128 | void selectHighlightedMaskPoint(); 129 | void deselectMaskPoint(); 130 | 131 | void insert(MaskPoint* maskPoint); 132 | int getInsertionIndex(MaskPoint* maskPoint); 133 | bool getIntersection(int x, int y, MaskPoint* maskPoint1, MaskPoint* maskPoint2, MaskPoint* intersection); 134 | 135 | void initialiseDragHandles(); 136 | void respondToStateChange(); 137 | 138 | bool containsPositionInRect(int canvasX, int canvasY); 139 | bool containsPositionInDragHandles(int canvasX, int canvasY); 140 | bool containsPosition(int canvasX, int canvasY, PointObject* pointObject); 141 | 142 | void setRectPosition(int absoluteX, int absoluteY); 143 | void setLiveRectPosition(int absoluteX, int absoluteY); 144 | void setRectX(int absoluteX); 145 | void setRectY(int absoluteY); 146 | void setLiveRectX(int absoluteX); 147 | void setLiveRectY(int absoluteY); 148 | void setDragHandlePositions(); 149 | 150 | /* Design */ 151 | void setPositionsToMatchScaleChange(int width, int height, Corner movingCorner); 152 | void setXPositionsToMatchScaleChange(int width); 153 | void setYPositionsToMatchScaleChange(int height); 154 | 155 | void translateMaskPointsX(int amount); 156 | void translateMaskPointsY(int amount); 157 | 158 | int getWidestPointLeftToRight(); 159 | int getWidestPointRightToLeft(); 160 | int getTallestPointTopToBottom(); 161 | int getTallestPointBottomToTop(); 162 | 163 | /* Live */ 164 | void setLivePositionsToMatchScaleChange(int width, int height, Corner movingCorner); 165 | void setLiveXPositionsToMatchScaleChange(int width); 166 | void setLiveYPositionsToMatchScaleChange(int height); 167 | void translateMaskPointsLiveX(int amount); 168 | void translateMaskPointsLiveY(int amount); 169 | int getSmallestLegalLiveWidth(Corner cornerBeingAdjusted); 170 | int getSmallestLegalLiveHeight(Corner cornerBeingAdjusted); 171 | int getWidestLivePointLeftToRight(); 172 | int getWidestLivePointRightToLeft(); 173 | int getTallestLivePointTopToBottom(); 174 | int getTallestLivePointBottomToTop(); 175 | }; -------------------------------------------------------------------------------- /src/Drawing/Areas/TextArea.cpp: -------------------------------------------------------------------------------- 1 | #include "TextArea.h" 2 | 3 | const ofColor textColor = ofColor(255, 255, 255, 255); 4 | 5 | const string designModeText = "Design"; 6 | const string designLiveModeText = "Design / Live"; 7 | const string liveModeText = "Live"; 8 | 9 | const string developmentModeText = "Development"; 10 | const string productionModeText = "Production"; 11 | 12 | const string stringOne = " RENDER\n ------\nRender mode: "; 13 | const string stringTwo = "\nPreset mode: "; 14 | const string stringThree = "\n Framerate: "; 15 | const string stringFour = "\nFrame nudge: "; 16 | const string stringFive = "\n\n KEYS\n ----\n F : new mask frame\n P : new point inside frame\narrow keys : nudge\n del : delete\n M : cycle render mode\n N : enable frame nudge\n U : undo (keep pressing)\n R : redo (keep pressing)\n S : save\n L : load\n space : toggle fullscreen\n\n INSTRUCTIONS\n ------------\n 1. Position your mouse over the design\n canvas. Notice there is a corresponding\n crosshair on the live canvas.\n\n 2. Press 'f' to create a new mask frame. You\n can click, drag, and re-size the frame\n with the mouse.\n\n 3. Position the mouse inside the mask frame,\n and press 'p' in 3 different locations\n to create your first triangle.\n\n 4. Hover your mouse over the edges of the\n triangle. You can now click and drag to\n create more points.\n\n 5. Click 'u' for 'undo' a few times, and\n then 'r' for 'redo'.\n\n 6. Hover over one of the points on your\n shape, and use the arrow keys. Each press\n nudges the point on the live canvas by 1\n pixel.\n\n 7. Press 'm' to cycle through render modes.\n\n 8. Check out the bin/data folder. Every\n time you make a change, a backup is saved\n in there. If you ever want to get back to\n a previous state, just overwrite\n 'saved.xml' and press 'l' for 'load'."; 17 | 18 | const string playbackVolumeTag = "Vol: "; 19 | const string nonPlaybackVolumeTag = "Non-Playback"; 20 | 21 | const string frameNudgeEnabledText = "Enabled"; 22 | const string frameNudgeDisabledText = "Disabled"; 23 | 24 | void TextArea::setInstructionsPosition(int x, int y){ 25 | this->instructionsX = x; 26 | this->instructionsY = y; 27 | } 28 | 29 | void TextArea::setPlaybackVolumePosition(int x, int y){ 30 | this->playbackVolumeX = x; 31 | this->playbackVolumeY = y; 32 | } 33 | 34 | void TextArea::setNonPlaybackVolumesPosition(int x, int y){ 35 | this->nonPlaybackVolumeX = x; 36 | this->nonPlaybackVolumeY = y; 37 | } 38 | 39 | void TextArea::setNumberBoxSize(int width, int height){ 40 | this->numberBoxWidth = width; 41 | this->numberBoxHeight = height; 42 | } 43 | 44 | void TextArea::setMargins(int numberTagMargin, int numberBoxMargin){ 45 | this->numberTagMargin = numberTagMargin; 46 | this->numberBoxMargin = numberBoxMargin; 47 | } 48 | 49 | void TextArea::setOffsets(int numberTagOffsetX, int numberTagOffsetY){ 50 | this->numberTagOffsetX = numberTagOffsetX; 51 | this->numberTagOffsetY = numberTagOffsetY; 52 | } 53 | 54 | void TextArea::setDisplayMode(DisplayMode displayMode){ 55 | if(displayMode == Design){ 56 | renderModeText = designModeText; 57 | }else if(displayMode == HalfLive){ 58 | renderModeText = designLiveModeText; 59 | }else if(displayMode == Live){ 60 | renderModeText = liveModeText; 61 | } 62 | } 63 | 64 | void TextArea::setPresetMode(PresetMode presetMode){ 65 | if(presetMode == PRESETS_DEVELOPMENT){ 66 | presetModeText = developmentModeText; 67 | }else if(presetMode == PRESETS_PRODUCTION){ 68 | presetModeText = productionModeText; 69 | } 70 | } 71 | 72 | void TextArea::setFrameNudgeEnabled(bool enabled){ 73 | if(enabled){ 74 | frameNudgeStatus = frameNudgeEnabledText; 75 | }else{ 76 | frameNudgeStatus = frameNudgeDisabledText; 77 | } 78 | } 79 | 80 | void TextArea::setVolumes(float *playbackVolume, vector *nonPlaybackVolumes){ 81 | this->playbackVolume = playbackVolume; 82 | this->nonPlaybackVolumes = nonPlaybackVolumes; 83 | } 84 | 85 | void TextArea::draw(){ 86 | ofSetColor(textColor); 87 | drawInstructionsText(); 88 | //drawPlaybackVolume(); 89 | //drawNonPlaybackVolumes(); 90 | } 91 | 92 | void TextArea::drawInstructionsText(){ 93 | ofSetColor(textColor); 94 | string textToDisplay = getTextToDisplay(); 95 | ofDrawBitmapString(textToDisplay, instructionsX, instructionsY); 96 | } 97 | 98 | void TextArea::drawPlaybackVolume(){ 99 | ofNoFill(); 100 | string volumeText = playbackVolumeTag + ofToString(*playbackVolume, 2); 101 | ofDrawBitmapString(volumeText, playbackVolumeX, playbackVolumeY + numberBoxHeight + numberTagMargin); 102 | ofDrawRectangle(playbackVolumeX, playbackVolumeY, numberBoxWidth, numberBoxHeight); 103 | ofFill(); 104 | ofDrawRectangle(playbackVolumeX, playbackVolumeY, *playbackVolume * numberBoxWidth, numberBoxHeight); 105 | } 106 | 107 | void TextArea::drawNonPlaybackVolumes(){ 108 | int rectX = nonPlaybackVolumeX - numberBoxWidth; 109 | int tagX = rectX + numberTagOffsetX; 110 | int rectY, tagY; 111 | float volume; 112 | int numVolumes = nonPlaybackVolumes->size(); 113 | int volumeIndex; 114 | 115 | for(int i = 0; i < numVolumes; i++){ 116 | volumeIndex = numVolumes - i; 117 | rectY = nonPlaybackVolumeY - numberBoxHeight - ((numberBoxHeight + numberBoxMargin) * i); 118 | tagY = nonPlaybackVolumeY - round(numberBoxHeight * 0.5); 119 | ofNoFill(); 120 | ofDrawRectangle(rectX, rectY, numberBoxWidth, numberBoxHeight); 121 | ofFill(); 122 | ofDrawRectangle(rectX, rectY, (*nonPlaybackVolumes)[volumeIndex - 1] * numberBoxWidth, numberBoxHeight); 123 | ofDrawBitmapString(ofToString(volumeIndex), tagX, rectY + numberTagOffsetY); 124 | } 125 | 126 | ofDrawBitmapString(nonPlaybackVolumeTag, nonPlaybackVolumeX - numberBoxWidth, nonPlaybackVolumeY + numberTagMargin); 127 | } 128 | 129 | string TextArea::getTextToDisplay(){ 130 | return stringOne + renderModeText + stringTwo + presetModeText + stringThree + ofToString(ofGetFrameRate()) + stringFour + frameNudgeStatus + stringFive; 131 | } 132 | -------------------------------------------------------------------------------- /src/Drawing/Areas/TextArea.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "ofTrueTypeFont.h" 4 | #include "MaskFrame.h" 5 | #include "Presets.h" 6 | 7 | class TextArea{ 8 | public: 9 | TextArea(){ 10 | playbackVolume = 0; 11 | setFrameNudgeEnabled(false); 12 | } 13 | void setInstructionsPosition(int x, int y); 14 | void setPlaybackVolumePosition(int x, int y); 15 | void setNonPlaybackVolumesPosition(int x, int y); 16 | 17 | void setNumberBoxSize(int width, int height); 18 | void setMargins(int numberTagMargin, int numberBoxMargin); 19 | void setOffsets(int numberTagOffsetX, int numberTagOffsetY); 20 | 21 | void setDisplayMode(DisplayMode mode); 22 | void setPresetMode(PresetMode mode); 23 | void setFrameNudgeEnabled(bool enabled); 24 | void setVolumes(float *playbackVolume, vector *nonPlaybackVolumes); 25 | 26 | void draw(); 27 | protected: 28 | int instructionsX, instructionsY; 29 | int playbackVolumeX, playbackVolumeY; 30 | int nonPlaybackVolumeX, nonPlaybackVolumeY; 31 | int numberBoxWidth, numberBoxHeight; 32 | 33 | int numberTagMargin, numberBoxMargin; 34 | int numberTagOffsetX, numberTagOffsetY; 35 | 36 | string renderModeText, presetModeText; 37 | string frameNudgeStatus; 38 | string textToDisplay; 39 | float *playbackVolume; 40 | vector *nonPlaybackVolumes; 41 | 42 | void drawInstructionsText(); 43 | void drawPlaybackVolume(); 44 | void drawNonPlaybackVolumes(); 45 | string getTextToDisplay(); 46 | }; -------------------------------------------------------------------------------- /src/Drawing/Collections/CanvasContents.cpp: -------------------------------------------------------------------------------- 1 | #include "CanvasContents.h" 2 | 3 | //Public 4 | void CanvasContents::add(MaskFrame *maskFrame){ 5 | maskFrames.backup(); 6 | maskFrames.push_back(*maskFrame); 7 | assignMaskFrameIds(); 8 | } 9 | 10 | void CanvasContents::nudge(Direction direction){ 11 | if(this->hasHighlightedMaskFrame()){ 12 | maskFrames.backup(); 13 | MaskFrame* maskFrame = this->getHighlightedMaskFrame(); 14 | 15 | if(maskFrame->hasHighlightedMaskPoint()){ 16 | maskFrame->nudgeMaskPoint(direction); 17 | }else if(frameNudge){ 18 | maskFrame->nudge(direction); 19 | } 20 | }else{ 21 | for(int i = 0; i < maskFrames.size(); i++){ 22 | if(maskFrames[i]->hasHighlightedDragHandle()){ 23 | maskFrames[i]->nudgeDragHandle(direction); 24 | break; 25 | } 26 | } 27 | } 28 | } 29 | 30 | void CanvasContents::eraseHighlighted(){ 31 | int i = getHighlightedMaskFrameIndex(); 32 | if(i > -1){ 33 | if(maskFrames[i]->hasHighlightedMaskPoint()){ 34 | maskFrames.backup(); 35 | maskFrames[i]->deleteSelectedMaskPoint(); 36 | }else{ 37 | maskFrames.backup(); 38 | maskFrames.deleteItem(i); 39 | } 40 | } 41 | } 42 | 43 | void CanvasContents::eraseAll(){ 44 | maskFrames.deleteAll(); 45 | } 46 | 47 | void CanvasContents::createMaskPointAt(int x, int y){ 48 | MaskFrame* highlightedMaskFrame = this->getHighlightedMaskFrame(); 49 | if(highlightedMaskFrame != 0){ 50 | maskFrames.backup(); 51 | highlightedMaskFrame->addMaskPoint(x, y); 52 | } 53 | } 54 | 55 | void CanvasContents::updateHighlights(int x, int y){ 56 | this->unhighlightAllMaskFrames(); 57 | 58 | for (int i = 0; i < maskFrames.size(); i++){ 59 | maskFrames[i]->highlightIfCloseTo(x, y); 60 | 61 | if(maskFrames[i]->isHighlighted() || maskFrames[i]->hasHighlightedDragHandle()){ 62 | lastHighlightedMaskFrame = maskFrames[i]; 63 | break; 64 | } 65 | } 66 | } 67 | 68 | void CanvasContents::toggleFrameNudge(){ 69 | frameNudge = !frameNudge; 70 | } 71 | 72 | MaskFrame* CanvasContents::beginTransform(){ 73 | for(int i = 0; i < maskFrames.size(); i++){ 74 | if(maskFrames[i]->hasHighlightedDragHandle()){ 75 | maskFrames[i]->setTransformState(Scaling); 76 | maskFrames.backup(); 77 | return maskFrames.getPointer(i); 78 | } 79 | if(maskFrames[i]->isHighlighted()){ 80 | if(maskFrames[i]->hasGhostPoint()){ 81 | maskFrames[i]->makeGhostPointReal(); 82 | maskFrames[i]->setTransformState(Masking); 83 | }else if(maskFrames[i]->hasHighlightedMaskPoint()){ 84 | maskFrames[i]->setTransformState(Masking); 85 | }else{ 86 | maskFrames[i]->setTransformState(Translating); 87 | } 88 | maskFrames.backup(); 89 | return maskFrames.getPointer(i); 90 | } 91 | } 92 | return 0; 93 | } 94 | 95 | void CanvasContents::endTransform(){ 96 | for(int i = 0; i < maskFrames.size(); i++){ 97 | maskFrames[i]->setTransformState(NoTransform); 98 | } 99 | } 100 | 101 | void CanvasContents::undo(){ 102 | maskFrames.undo(); 103 | } 104 | 105 | void CanvasContents::redo(){ 106 | maskFrames.redo(); 107 | } 108 | 109 | bool CanvasContents::getFrameNudgeEnabled(){ 110 | return frameNudge; 111 | } 112 | 113 | void CanvasContents::drawDesign(){ 114 | for (int i = 0; i < maskFrames.size(); i++){ 115 | maskFrames[i]->drawDesign(); 116 | } 117 | } 118 | 119 | void CanvasContents::drawLive(DisplayMode displayMode, StretchMode stretchMode){ 120 | for (int i = 0; i < maskFrames.size(); i++){ 121 | maskFrames[i]->drawLive(displayMode, stretchMode); 122 | } 123 | } 124 | 125 | SafeDeque *CanvasContents::getMaskFrames(){ 126 | return &this->maskFrames; 127 | } 128 | 129 | //Protected 130 | void CanvasContents::unhighlightAllMaskFrames(){ 131 | for(int i = 0; i < maskFrames.size(); i++){ 132 | maskFrames[i]->setHighlighted(false); 133 | } 134 | } 135 | 136 | int CanvasContents::getHighlightedMaskFrameIndex(){ 137 | for(int i = 0; i < maskFrames.size(); i++){ 138 | if(maskFrames[i]->isHighlighted()){ 139 | return i; 140 | } 141 | } 142 | return -1; 143 | } 144 | 145 | MaskFrame* CanvasContents::getHighlightedMaskFrame(){ 146 | int i = getHighlightedMaskFrameIndex(); 147 | if(i > -1){ 148 | return maskFrames[i]; 149 | } 150 | return 0; 151 | } 152 | 153 | bool CanvasContents::hasHighlightedMaskFrame(){ 154 | int i = getHighlightedMaskFrameIndex(); 155 | return i > -1; 156 | } 157 | 158 | int CanvasContents::assignMaskFrameIds(){ 159 | for(int i = 0; i < maskFrames.size(); i++){ 160 | maskFrames[i]->setId(i); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Drawing/Collections/CanvasContents.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "SafeDeque.h" 4 | #include "MaskFrame.h" 5 | 6 | class CanvasContents{ 7 | public: 8 | CanvasContents(){ 9 | frameNudge = false; 10 | } 11 | void add(MaskFrame *maskFrame); 12 | void nudge(Direction direction); 13 | void eraseHighlighted(); 14 | void eraseAll(); 15 | 16 | void createMaskPointAt(int x, int y); 17 | void updateHighlights(int x, int y); 18 | void toggleFrameNudge(); 19 | 20 | MaskFrame* beginTransform(); 21 | void endTransform(); 22 | void undo(); 23 | void redo(); 24 | bool getFrameNudgeEnabled(); 25 | 26 | void drawDesign(); 27 | void drawLive(DisplayMode displayMode, StretchMode stretchMode); 28 | 29 | SafeDeque *getMaskFrames(); 30 | 31 | protected: 32 | MaskFrame *lastHighlightedMaskFrame; 33 | SafeDeque maskFrames; 34 | bool frameNudge; 35 | 36 | void unhighlightAllMaskFrames(); 37 | int getHighlightedMaskFrameIndex(); 38 | MaskFrame* getHighlightedMaskFrame(); 39 | bool hasHighlightedMaskFrame(); 40 | int assignMaskFrameIds(); 41 | }; 42 | -------------------------------------------------------------------------------- /src/Drawing/Collections/SafeDeque.cpp: -------------------------------------------------------------------------------- 1 | #include "SafeDeque.h" 2 | -------------------------------------------------------------------------------- /src/Drawing/Collections/SafeDeque.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template class SafeDeque{ 5 | public: 6 | SafeDeque(){ 7 | cursor = 0; 8 | hasUndoList = false; 9 | } 10 | T* operator[](const int i); 11 | void push_back(T item); 12 | void deleteItem(int i); 13 | void deleteAll(); 14 | T* getPointer(int i); 15 | void insert(int i, T &item); 16 | int size(); 17 | void undo(); 18 | void redo(); 19 | void backup(); 20 | protected: 21 | std::deque items; 22 | std::deque < std::deque > undoList; 23 | int cursor; 24 | bool hasUndoList; 25 | void backupTopItem(); 26 | }; 27 | 28 | template T* SafeDeque::operator[] (const int i){ 29 | return &items[i]; 30 | } 31 | 32 | template void SafeDeque::push_back(T item){ 33 | items.push_back(item); 34 | } 35 | 36 | template void SafeDeque::deleteItem(int i){ 37 | items.erase(items.begin() + i); 38 | } 39 | 40 | template void SafeDeque::deleteAll(){ 41 | items.clear(); 42 | } 43 | 44 | template T* SafeDeque::getPointer(int i){ 45 | return &items[i]; 46 | } 47 | 48 | template void SafeDeque::insert(int i, T &item){ 49 | items.insert(items.begin() + i, item); 50 | } 51 | 52 | template int SafeDeque::size(){ 53 | return items.size(); 54 | } 55 | 56 | template void SafeDeque::undo(){ 57 | if(cursor > 0){ 58 | backupTopItem(); 59 | cursor--; 60 | items = undoList[cursor]; 61 | } 62 | } 63 | 64 | template void SafeDeque::redo(){ 65 | if(hasUndoList && cursor < undoList.size() - 1){ 66 | cursor++; 67 | items = undoList[cursor]; 68 | } 69 | } 70 | 71 | template void SafeDeque::backup(){ 72 | undoList.erase(undoList.begin() + cursor, undoList.end()); 73 | undoList.push_back(items); 74 | cursor = undoList.size(); 75 | hasUndoList = true; 76 | } 77 | 78 | template void SafeDeque::backupTopItem(){ 79 | if(cursor == undoList.size()){ 80 | undoList.push_back(items); 81 | hasUndoList = true; 82 | } 83 | } -------------------------------------------------------------------------------- /src/Drawing/Homography.cpp: -------------------------------------------------------------------------------- 1 | #include "Homography.h" 2 | 3 | void Homography::begin(ofPoint src[4], ofPoint dst[4]) { 4 | 5 | findHomography(src, dst, transformMatrix); 6 | glPushMatrix(); 7 | glMultMatrixf(transformMatrix); 8 | glPushMatrix(); 9 | } 10 | 11 | void Homography::end() { 12 | glPopMatrix(); 13 | glPopMatrix(); 14 | } -------------------------------------------------------------------------------- /src/Drawing/Homography.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "MaskPoint.h" 4 | 5 | class Homography { 6 | public: 7 | void begin(ofPoint src[4], ofPoint dst[4]); 8 | void end(); 9 | 10 | private: 11 | //Adapted from Arturo castro 12 | //http://forum.openframeworks.cc/t/quad-warping-homography-without-opencv/3121 13 | 14 | float transformMatrix[16]; 15 | 16 | void gaussian_elimination(float *input, int n){ 17 | // ported to c from pseudocode in 18 | // http://en.wikipedia.org/wiki/Gaussian_elimination 19 | 20 | float * A = input; 21 | int i = 0; 22 | int j = 0; 23 | int m = n-1; 24 | while (i < m && j < n){ 25 | // Find pivot in column j, starting in row i: 26 | int maxi = i; 27 | for(int k = i+1; k fabs(A[maxi*n+j])){ 29 | maxi = k; 30 | } 31 | } 32 | if (A[maxi*n+j] != 0){ 33 | //swap rows i and maxi, but do not change the value of i 34 | if(i!=maxi) 35 | for(int k=0;k=0;i--){ 63 | for(int j=i+1;jgetX() + offsetX, canvas->getX() + canvas->getWidth() + offsetX); 19 | int newWidth; 20 | 21 | if(selectedCorner == TopLeft){ 22 | 23 | newWidth = (selectedMaskFrame->getX() + selectedMaskFrame->getWidth() + offsetX) - mouseXConstrained; 24 | 25 | }else if(selectedCorner == TopRight){ 26 | 27 | newWidth = mouseXConstrained - (selectedMaskFrame->getX() + offsetX); 28 | 29 | }else if(selectedCorner == BottomRight){ 30 | 31 | newWidth = mouseXConstrained - (selectedMaskFrame->getX() + offsetX); 32 | 33 | }else if(selectedCorner == BottomLeft){ 34 | 35 | newWidth = (selectedMaskFrame->getX() + selectedMaskFrame->getWidth() + offsetX) - mouseXConstrained; 36 | } 37 | 38 | int smallestLegalWidth = selectedMaskFrame->getSmallestLegalWidth(selectedCorner); 39 | int newWidthClamped = clampInt(newWidth, smallestLegalWidth); 40 | return newWidthClamped; 41 | } 42 | 43 | int Mouse::newSelectionHeight(){ 44 | int mouseYConstrained = clampInt(y, canvas->getY() + offsetY, canvas->getY() + canvas->getHeight() + offsetY); 45 | int newHeight; 46 | 47 | if(selectedCorner == TopLeft){ 48 | 49 | newHeight = (selectedMaskFrame->getY() + selectedMaskFrame->getHeight() + offsetY) - mouseYConstrained; 50 | 51 | }else if(selectedCorner == TopRight){ 52 | 53 | newHeight = (selectedMaskFrame->getY() + selectedMaskFrame->getHeight() + offsetY) - mouseYConstrained; 54 | 55 | }else if(selectedCorner == BottomRight){ 56 | 57 | newHeight = mouseYConstrained - (selectedMaskFrame->getY() + offsetY); 58 | 59 | }else if(selectedCorner == BottomLeft){ 60 | 61 | newHeight = mouseYConstrained - (selectedMaskFrame->getY() + offsetY); 62 | } 63 | 64 | int smallestLegalHeight = selectedMaskFrame->getSmallestLegalHeight(selectedCorner); 65 | int newHeightClamped = clampInt(newHeight, smallestLegalHeight); 66 | return newHeightClamped; 67 | } 68 | 69 | float Mouse::newSelectionX() { 70 | return x - offsetX; 71 | } 72 | 73 | float Mouse::newSelectionY() { 74 | return y - offsetY; 75 | } 76 | 77 | void Mouse::setMouseOffsetFromSelectedMaskFrame(){ 78 | TransformState transformState = selectedMaskFrame->getTransformState(); 79 | if(transformState == Translating){ 80 | setMouseOffsetFromTopLeftCorner(); 81 | }else if(transformState == Scaling){ 82 | setMouseOffsetFromSelectedCorner(); 83 | }else if(transformState == Masking){ 84 | setMouseOffsetFromSelectedMaskPoint(); 85 | } 86 | } 87 | 88 | void Mouse::setMouseOffsetFromSelectedMaskPoint(){ 89 | offsetX = x - selectedMaskFrame->getSelectedMaskPointX(); 90 | offsetY = y - selectedMaskFrame->getSelectedMaskPointY(); 91 | } 92 | 93 | void Mouse::setMouseOffsetFromSelectedCorner(){ 94 | selectedCorner = selectedMaskFrame->highlightedCorner(); 95 | if(selectedCorner == TopLeft){ 96 | setMouseOffsetFromTopLeftCorner(); 97 | }else if(selectedCorner == TopRight){ 98 | setMouseOffsetFromTopRightCorner(); 99 | }else if(selectedCorner == BottomRight){ 100 | setMouseOffsetFromBottomRightCorner(); 101 | }else if(selectedCorner == BottomLeft){ 102 | setMouseOffsetFromBottomLeftCorner(); 103 | } 104 | } 105 | 106 | void Mouse::setMouseOffsetFromTopLeftCorner(){ 107 | offsetX = x - selectedMaskFrame->getX(); 108 | offsetY = y - selectedMaskFrame->getY(); 109 | } 110 | 111 | void Mouse::setMouseOffsetFromTopRightCorner(){ 112 | offsetX = x - selectedMaskFrame->getX() - selectedMaskFrame->getWidth(); 113 | offsetY = y - selectedMaskFrame->getY(); 114 | } 115 | 116 | void Mouse::setMouseOffsetFromBottomRightCorner(){ 117 | offsetX = x - selectedMaskFrame->getX() - selectedMaskFrame->getWidth(); 118 | offsetY = y - selectedMaskFrame->getY() - selectedMaskFrame->getHeight(); 119 | } 120 | 121 | void Mouse::setMouseOffsetFromBottomLeftCorner(){ 122 | offsetX = x - selectedMaskFrame->getX(); 123 | offsetY = y - selectedMaskFrame->getY() - selectedMaskFrame->getHeight(); 124 | } -------------------------------------------------------------------------------- /src/Drawing/Mouse.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "MaskFrame.h" 4 | #include "DragHandle.h" 5 | #include "Canvas.h" 6 | 7 | class Mouse{ 8 | public: 9 | Mouse() { 10 | adjustment.x = -1; 11 | adjustment.y = -2; 12 | } 13 | float x, y; 14 | void setup(Canvas* _canvas); 15 | void set(int _x, int _y); 16 | 17 | void setSelection(MaskFrame* maskFrame); 18 | int newSelectionWidth(); 19 | int newSelectionHeight(); 20 | float newSelectionX(); 21 | float newSelectionY(); 22 | 23 | protected: 24 | ofVec2f adjustment; 25 | Canvas* canvas; 26 | MaskFrame* selectedMaskFrame; 27 | float offsetX, offsetY; 28 | Corner selectedCorner; 29 | 30 | void setMouseOffsetFromSelectedMaskFrame(); 31 | void setMouseOffsetFromSelectedMaskPoint(); 32 | void setMouseOffsetFromSelectedCorner(); 33 | 34 | void setMouseOffsetFromTopLeftCorner(); 35 | void setMouseOffsetFromTopRightCorner(); 36 | void setMouseOffsetFromBottomRightCorner(); 37 | void setMouseOffsetFromBottomLeftCorner(); 38 | }; -------------------------------------------------------------------------------- /src/Drawing/Points/DragHandle.cpp: -------------------------------------------------------------------------------- 1 | #include "DragHandle.h" 2 | 3 | const ofColor notHighlightedColor = ofColor(255, 255, 255, 128); 4 | const ofColor highlightedColor = ofColor(0, 255, 255, 128); 5 | 6 | Corner DragHandle::getCorner(){ 7 | return corner; 8 | } 9 | 10 | void DragHandle::setCorner(Corner corner){ 11 | this->corner = corner; 12 | } 13 | 14 | void DragHandle::drawDesign(){ 15 | if(this->highlighted){ 16 | ofCircleNoStroke(this->position.x, this->position.y, this->getRadius(), highlightedColor); 17 | }else{ 18 | ofCircleNoStroke(this->position.x, this->position.y, this->getRadius(), notHighlightedColor); 19 | } 20 | } 21 | 22 | void DragHandle::drawLive(){ 23 | if(this->highlighted){ 24 | ofCircleNoStroke(this->livePosition.x, this->livePosition.y, this->getRadius(), highlightedColor); 25 | }else{ 26 | ofCircleNoStroke(this->livePosition.x, this->livePosition.y, this->getRadius(), notHighlightedColor); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Drawing/Points/DragHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "PointObject.h" 4 | #include "ofExtensions.h" 5 | 6 | enum Corner { TopLeft, TopRight, BottomLeft, BottomRight }; 7 | 8 | class DragHandle : public PointObject{ 9 | public: 10 | Corner getCorner(); 11 | void setCorner(Corner corner); 12 | 13 | void drawDesign(); 14 | void drawLive(); 15 | 16 | protected: 17 | Corner corner; 18 | }; -------------------------------------------------------------------------------- /src/Drawing/Points/MaskPoint.cpp: -------------------------------------------------------------------------------- 1 | #include "MaskPoint.h" 2 | 3 | const ofColor maskPointColor = ofColor(255, 255, 255, 128); 4 | const ofColor highlightColor = ofColor(0, 255, 255, 255); 5 | const ofColor nonHighlightColor = ofColor(0, 128, 128, 255); 6 | const ofColor ghostColor = ofColor(0, 255, 255, 128); 7 | 8 | void MaskPoint::setType(MaskPointType type){ 9 | this->type = type; 10 | } 11 | 12 | MaskPointType MaskPoint::getType(){ 13 | return this->type; 14 | } 15 | 16 | void MaskPoint::drawDesign(){ 17 | if(this->type == Real){ 18 | ofSetColor(maskPointColor); 19 | ofDrawRectangle(this->getX(), this->getY(), 1, 1); 20 | if(this->isHighlighted()){ 21 | ofNoFill(); 22 | ofSetColor(highlightColor); 23 | ofDrawCircle(this->getX(), this->getY(), this->getRadius()); 24 | } 25 | } 26 | if(this->type == Ghost){ 27 | ofSetColor(maskPointColor); 28 | ofDrawRectangle(this->getX(), this->getY(), 1, 1); 29 | ofNoFill(); 30 | ofSetColor(ghostColor); 31 | ofDrawCircle(this->getX(), this->getY(), this->getRadius()); 32 | } 33 | } 34 | 35 | void MaskPoint::drawLive(){ 36 | if(this->type == Real){ 37 | ofSetColor(maskPointColor); 38 | ofDrawRectangle(this->getLiveX(), this->getLiveY(), 1, 1); 39 | if(this->isHighlighted()){ 40 | ofSetColor(highlightColor); 41 | }else{ 42 | ofSetColor(nonHighlightColor); 43 | } 44 | ofNoFill(); 45 | ofDrawCircle(this->getLiveX(), this->getLiveY(), this->getRadius()); 46 | } 47 | if(this->type == Ghost){ 48 | ofSetColor(maskPointColor); 49 | ofDrawRectangle(this->getLiveX(), this->getLiveY(), 1, 1); 50 | ofNoFill(); 51 | ofSetColor(ghostColor); 52 | ofDrawCircle(this->getLiveX(), this->getLiveY(), this->getRadius()); 53 | } 54 | } 55 | 56 | bool MaskPoint::equals(MaskPoint* otherPoint){ 57 | return position.x == otherPoint->getX() && position.y == otherPoint->getY(); 58 | } 59 | -------------------------------------------------------------------------------- /src/Drawing/Points/MaskPoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "PointObject.h" 4 | #include "ofExtensions.h" 5 | 6 | enum MaskPointType { Real, Ghost }; 7 | enum Direction { Left, Right, Up, Down }; 8 | 9 | class MaskPoint : public PointObject{ 10 | public: 11 | void setType(MaskPointType type); 12 | MaskPointType getType(); 13 | 14 | void drawDesign(); 15 | void drawLive(); 16 | 17 | bool equals(MaskPoint* otherPoint); 18 | 19 | protected: 20 | MaskPointType type; 21 | }; -------------------------------------------------------------------------------- /src/Drawing/Points/PointObject.cpp: -------------------------------------------------------------------------------- 1 | #include "PointObject.h" 2 | 3 | const int radius = 4; 4 | 5 | int PointObject::getX(){ 6 | return position.x; 7 | } 8 | 9 | int PointObject::getY(){ 10 | return position.y; 11 | } 12 | 13 | int PointObject::getLiveX(){ 14 | return livePosition.x; 15 | } 16 | 17 | int PointObject::getLiveY(){ 18 | return livePosition.y; 19 | } 20 | 21 | void PointObject::setPosition(int x, int y){ 22 | this->position.x = x; 23 | this->position.y = y; 24 | } 25 | 26 | void PointObject::setX(int x){ 27 | this->position.x = x; 28 | } 29 | 30 | void PointObject::setY(int y){ 31 | this->position.y = y; 32 | } 33 | 34 | void PointObject::setLivePosition(int x, int y){ 35 | this->livePosition.x = x; 36 | this->livePosition.y = y; 37 | } 38 | 39 | void PointObject::setLiveX(int x){ 40 | this->livePosition.x = x; 41 | } 42 | 43 | void PointObject::setLiveY(int y){ 44 | this->livePosition.y = y; 45 | } 46 | 47 | void PointObject::drawDesign(){ 48 | 49 | } 50 | 51 | void PointObject::drawLive(){ 52 | 53 | } 54 | 55 | int PointObject::getRadius(){ 56 | return radius; 57 | } 58 | 59 | bool PointObject::isHighlighted(){ 60 | return this->highlighted; 61 | } 62 | 63 | void PointObject::setHighlighted(bool isHighlighted){ 64 | this->highlighted = isHighlighted; 65 | } -------------------------------------------------------------------------------- /src/Drawing/Points/PointObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "ofExtensions.h" 4 | 5 | class PointObject{ 6 | public: 7 | PointObject(){ 8 | highlighted = false; 9 | } 10 | int getX(); 11 | int getY(); 12 | int getLiveX(); 13 | int getLiveY(); 14 | 15 | void setPosition(int x, int y); 16 | void setX(int x); 17 | void setY(int y); 18 | 19 | void setLivePosition(int x, int y); 20 | void setLiveX(int x); 21 | void setLiveY(int y); 22 | 23 | void drawDesign(); 24 | void drawLive(); 25 | 26 | int getRadius(); 27 | bool isHighlighted(); 28 | void setHighlighted(bool isHighlighted); 29 | 30 | protected: 31 | bool highlighted; 32 | ofVec2f position; 33 | ofVec2f livePosition; 34 | }; -------------------------------------------------------------------------------- /src/Presets.cpp: -------------------------------------------------------------------------------- 1 | #include "Presets.h" 2 | 3 | /* 4 | Edit your presets here 5 | ====================== 6 | This file is full of presets to help you easily switch between when 7 | you are developing your patterns and when you want to display live 8 | on a projector. 9 | */ 10 | const int developmentFirstWindowWidth = 800; 11 | const int developmentFirstWindowHeight = 800; 12 | const int developmentFirstWindowX = 816; 13 | const int developmentFirstWindowY = 0; 14 | 15 | const int developmentSecondWindowWidth = 616; 16 | const int developmentSecondWindowHeight = 416; 17 | const int developmentSecondWindowX = 0; 18 | const int developmentSecondWindowY = 0; 19 | 20 | const int developmentNumGridLinesX = 14; 21 | const int developmentNumGridLinesY = 10; 22 | 23 | const int developmentDesignCanvasX = 402; 24 | const int developmentDesignCanvasY = 8; 25 | const int developmentDesignCanvasWidth = 240; 26 | const int developmentDesignCanvasHeight = 180; 27 | const int developmentDesignCanvasLabelX = 402; 28 | const int developmentDesignCanvasLabelY = 204; 29 | 30 | const int developmentLiveCanvasX = 8; 31 | const int developmentLiveCanvasY = 8; 32 | const int developmentLiveCanvasWidth = 600; 33 | const int developmentLiveCanvasHeight = 400; 34 | 35 | const int developmentBufferPreviewX = 402; 36 | const int developmentBufferPreviewY = 224; 37 | const int developmentBufferPreviewWidth = 80; 38 | const int developmentBufferPreviewHeight = 80; 39 | const int developmentBufferMargin = 16; 40 | 41 | const int developmentNumberBoxWidth = 100; 42 | const int developmentNumberBoxHeight = 20; 43 | 44 | const int developmentInstructionsX = 8; 45 | const int developmentInstructionsY = 18; 46 | const int developmentPlaybackVolumeX = 9; 47 | const int developmentPlaybackVolumeY = 726; 48 | const int developmentNonPlaybackVolumeX = 320; 49 | const int developmentNonPlaybackVolumeY = 746; 50 | 51 | const int developmentNumberTagMargin = 20; 52 | const int developmentNumberBoxMargin = 6; 53 | const int developmentNumberTagOffsetX = -20; 54 | const int developmentNumberTagOffsetY = 14; 55 | 56 | const int developmentNewMaskFrameWidth = 70; 57 | const int developmentNewMaskFrameHeight = 100; 58 | 59 | const bool developmentStartFullscreen = false; 60 | const char* developmentStorageDirectory = "development"; 61 | 62 | /* 63 | Production mode presets 64 | ======================= 65 | */ 66 | 67 | const int productionNumGridLinesX = 60; 68 | const int productionNumGridLinesY = 46; 69 | 70 | const int productionDesignCanvasX = 10; 71 | const int productionDesignCanvasY = 10; 72 | const int productionDesignCanvasWidth = 1004; 73 | const int productionDesignCanvasHeight = 710; 74 | const int productionDesignCanvasLabelX = -1000; 75 | const int productionDesignCanvasLabelY = -1000; 76 | 77 | const int productionBufferPreviewX = 10; 78 | const int productionBufferPreviewY = 730; 79 | const int productionBufferPreviewWidth = 150; 80 | const int productionBufferPreviewHeight = 150; 81 | const int productionBufferMargin = 16; 82 | 83 | const int productionNumberBoxWidth = 290; 84 | const int productionNumberBoxHeight = 48; 85 | 86 | const int productionInstructionsX = 1028; 87 | const int productionInstructionsY = 26; 88 | const int productionPlaybackVolumeX = 1028; 89 | const int productionPlaybackVolumeY = 688; 90 | const int productionNonPlaybackVolumeX = 1651; 91 | const int productionNonPlaybackVolumeY = 736; 92 | 93 | const int productionNumberTagMargin = 20; 94 | const int productionNumberBoxMargin = 12; 95 | const int productionNumberTagOffsetX = -18; 96 | const int productionNumberTagOffsetY = 28; 97 | 98 | const int productionNewMaskFrameWidth = 200; 99 | const int productionNewMaskFrameHeight = 300; 100 | 101 | const bool productionStartFullscreen = true; 102 | const char* productionStorageDirectory = "production"; 103 | 104 | void Presets::setMode(PresetMode _mode){ 105 | mode = _mode; 106 | load(); 107 | } 108 | 109 | PresetMode Presets::getMode(){ 110 | return mode; 111 | } 112 | 113 | void Presets::cycleMode(){ 114 | if(mode == PRESETS_DEVELOPMENT){ 115 | setMode(PRESETS_PRODUCTION); 116 | }else if(mode == PRESETS_PRODUCTION){ 117 | setMode(PRESETS_DEVELOPMENT); 118 | } 119 | } 120 | 121 | bool Presets::isDevelopmentMode(){ 122 | return mode == PRESETS_DEVELOPMENT; 123 | } 124 | 125 | bool Presets::isProductionMode(){ 126 | return mode == PRESETS_PRODUCTION; 127 | } 128 | 129 | void Presets::load() { 130 | if(mode == PRESETS_DEVELOPMENT) { 131 | loadDevelopmentValues(); 132 | } else if(mode == PRESETS_PRODUCTION) { 133 | loadProductionValues(); 134 | } 135 | } 136 | 137 | void Presets::loadDevelopmentValues() { 138 | firstWindowWidth = developmentFirstWindowWidth; 139 | firstWindowHeight = developmentFirstWindowHeight; 140 | firstWindowX = developmentFirstWindowX; 141 | firstWindowY = developmentFirstWindowY; 142 | 143 | secondWindowWidth = developmentSecondWindowWidth; 144 | secondWindowHeight = developmentSecondWindowHeight; 145 | secondWindowX = developmentSecondWindowX; 146 | secondWindowY = developmentSecondWindowY; 147 | 148 | numGridLinesX = developmentNumGridLinesX; 149 | numGridLinesY = developmentNumGridLinesY; 150 | 151 | designCanvasX = developmentDesignCanvasX; 152 | designCanvasY = developmentDesignCanvasY; 153 | designCanvasWidth = developmentDesignCanvasWidth; 154 | designCanvasHeight = developmentDesignCanvasHeight; 155 | designCanvasLabelX = developmentDesignCanvasLabelX; 156 | designCanvasLabelY = developmentDesignCanvasLabelY; 157 | 158 | liveCanvasX = developmentLiveCanvasX; 159 | liveCanvasY = developmentLiveCanvasY; 160 | liveCanvasWidth = developmentLiveCanvasWidth; 161 | liveCanvasHeight = developmentLiveCanvasHeight; 162 | 163 | bufferPreviewX = developmentBufferPreviewX; 164 | bufferPreviewY = developmentBufferPreviewY; 165 | bufferPreviewWidth = developmentBufferPreviewWidth; 166 | bufferPreviewHeight = developmentBufferPreviewHeight; 167 | bufferMargin = developmentBufferMargin; 168 | 169 | numberBoxWidth = developmentNumberBoxWidth; 170 | numberBoxHeight = developmentNumberBoxHeight; 171 | 172 | instructionsX = developmentInstructionsX; 173 | instructionsY = developmentInstructionsY; 174 | playbackVolumeX = developmentPlaybackVolumeX; 175 | playbackVolumeY = developmentPlaybackVolumeY; 176 | nonPlaybackVolumeX = developmentNonPlaybackVolumeX; 177 | nonPlaybackVolumeY = developmentNonPlaybackVolumeY; 178 | 179 | numberTagMargin = developmentNumberTagMargin; 180 | numberBoxMargin = developmentNumberBoxMargin; 181 | numberTagOffsetX = developmentNumberTagOffsetX; 182 | numberTagOffsetY = developmentNumberTagOffsetY; 183 | 184 | newMaskFrameWidth = developmentNewMaskFrameWidth; 185 | newMaskFrameHeight = developmentNewMaskFrameHeight; 186 | 187 | storageDirectory = developmentStorageDirectory; 188 | } 189 | 190 | void Presets::loadProductionValues() { 191 | numGridLinesX = productionNumGridLinesX; 192 | numGridLinesY = productionNumGridLinesY; 193 | 194 | designCanvasX = productionDesignCanvasX; 195 | designCanvasY = productionDesignCanvasY; 196 | designCanvasWidth = productionDesignCanvasWidth; 197 | designCanvasHeight = productionDesignCanvasHeight; 198 | designCanvasLabelX = productionDesignCanvasLabelX; 199 | designCanvasLabelY = productionDesignCanvasLabelY; 200 | 201 | bufferPreviewX = productionBufferPreviewX; 202 | bufferPreviewY = productionBufferPreviewY; 203 | bufferPreviewWidth = productionBufferPreviewWidth; 204 | bufferPreviewHeight = productionBufferPreviewHeight; 205 | bufferMargin = productionBufferMargin; 206 | 207 | numberBoxWidth = productionNumberBoxWidth; 208 | numberBoxHeight = productionNumberBoxHeight; 209 | 210 | instructionsX = productionInstructionsX; 211 | instructionsY = productionInstructionsY; 212 | playbackVolumeX = productionPlaybackVolumeX; 213 | playbackVolumeY = productionPlaybackVolumeY; 214 | nonPlaybackVolumeX = productionNonPlaybackVolumeX; 215 | nonPlaybackVolumeY = productionNonPlaybackVolumeY; 216 | 217 | numberTagMargin = productionNumberTagMargin; 218 | numberBoxMargin = productionNumberBoxMargin; 219 | numberTagOffsetX = productionNumberTagOffsetX; 220 | numberTagOffsetY = productionNumberTagOffsetY; 221 | 222 | newMaskFrameWidth = productionNewMaskFrameWidth; 223 | newMaskFrameHeight = productionNewMaskFrameHeight; 224 | 225 | storageDirectory = productionStorageDirectory; 226 | } 227 | -------------------------------------------------------------------------------- /src/Presets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum PresetMode { PRESETS_DEVELOPMENT, PRESETS_PRODUCTION }; 4 | 5 | class Presets{ 6 | public: 7 | Presets(){ 8 | setMode(PRESETS_DEVELOPMENT); 9 | } 10 | 11 | void setMode(PresetMode _mode); 12 | void cycleMode(); 13 | 14 | PresetMode getMode(); 15 | bool isDevelopmentMode(); 16 | bool isProductionMode(); 17 | 18 | int firstWindowX, firstWindowY, firstWindowWidth, firstWindowHeight; 19 | 20 | int secondWindowX, secondWindowY, secondWindowWidth, secondWindowHeight; 21 | 22 | int numGridLinesX, numGridLinesY; 23 | 24 | int designCanvasX, designCanvasY; 25 | int designCanvasWidth, designCanvasHeight; 26 | int designCanvasLabelX, designCanvasLabelY; 27 | 28 | int liveCanvasX, liveCanvasY; 29 | int liveCanvasWidth, liveCanvasHeight; 30 | 31 | int bufferPreviewX, bufferPreviewY; 32 | int bufferPreviewWidth, bufferPreviewHeight; 33 | int bufferMargin; 34 | 35 | int numberBoxWidth, numberBoxHeight; 36 | 37 | int instructionsX, instructionsY; 38 | int playbackVolumeX, playbackVolumeY; 39 | int nonPlaybackVolumeX, nonPlaybackVolumeY; 40 | 41 | int numberTagMargin, numberBoxMargin; 42 | int numberTagOffsetX, numberTagOffsetY; 43 | 44 | int newMaskFrameWidth, newMaskFrameHeight; 45 | 46 | const char* storageDirectory; 47 | 48 | protected: 49 | void load(); 50 | void loadDevelopmentValues(); 51 | void loadProductionValues(); 52 | 53 | PresetMode mode; 54 | }; 55 | -------------------------------------------------------------------------------- /src/Storage/Xml.cpp: -------------------------------------------------------------------------------- 1 | #include "Xml.h" 2 | 3 | const string sessionTag = "session"; 4 | const string typeTag = "type"; 5 | const string timestampTag = "timestamp"; 6 | const string designCanvasTag = "designCanvas"; 7 | const string liveCanvasTag = "liveCanvas"; 8 | const string maskFramesTag = "maskFrames"; 9 | const string maskFrameTag = "maskFrame"; 10 | const string maskPointsTag = "maskPoints"; 11 | const string maskPointTag = "maskPoint"; 12 | 13 | const string idTag = "id"; 14 | const string widthTag = "width"; 15 | const string heightTag = "height"; 16 | const string xTag = "x"; 17 | const string yTag = "y"; 18 | 19 | const string designWidthTag = "designWidth"; 20 | const string designHeightTag = "designHeight"; 21 | const string designXTag = "designX"; 22 | const string designYTag = "designY"; 23 | 24 | const string liveWidthTag = "liveWidth"; 25 | const string liveHeightTag = "liveHeight"; 26 | const string liveXTag = "liveX"; 27 | const string liveYTag = "liveY"; 28 | 29 | const string levelDivider = ":"; 30 | 31 | const string designCanvasName = "design"; 32 | const string liveCanvasName = "live"; 33 | 34 | const string typeAuto = "auto"; 35 | const string typeManual = "manual"; 36 | 37 | const string defaultTimestamp = "no-timestamp-found"; 38 | 39 | const string defaultFileName = "saved"; 40 | const string fileExtension = ".xml"; 41 | const string directoryDivider = "/"; 42 | const string projectionMaskPath = "ProjectionMasks"; 43 | 44 | void Xml::setup(Canvas *designCanvas, Canvas *liveCanvas, CanvasContents *canvasContents, vector *patterns, string directory){ 45 | fileName = defaultFileName; 46 | this->designCanvas = designCanvas; 47 | this->liveCanvas = liveCanvas; 48 | this->canvasContents = canvasContents; 49 | this->patterns = patterns; 50 | this->xmlSubPath = projectionMaskPath + directoryDivider + directory; 51 | } 52 | 53 | void Xml::setFileName(string _fileName){ 54 | fileName = _fileName; 55 | canvasContents->eraseAll(); 56 | load(); 57 | } 58 | 59 | void Xml::save(){ 60 | save(false); 61 | } 62 | 63 | void Xml::autoSave(){ 64 | save(true); 65 | } 66 | 67 | void Xml::load(){ 68 | 69 | ofxXmlSettings xml; 70 | 71 | if(xml.loadFile(xmlSubPath + directoryDivider + fileName + fileExtension)){ 72 | xml.pushTag(sessionTag); 73 | 74 | loadSourceCanvasDimensions(&xml); 75 | loadMaskFrames(&xml); 76 | 77 | xml.popTag(); 78 | } 79 | } 80 | 81 | void Xml::save(bool autoSave){ 82 | 83 | ensureDirectory(); 84 | backupExistingFile(); 85 | 86 | ofxXmlSettings xml; 87 | 88 | xml.addTag(sessionTag); 89 | xml.pushTag(sessionTag); 90 | 91 | addType(&xml, autoSave); 92 | addTimestamp(&xml); 93 | addCanvas(&xml, designCanvas, designCanvasTag); 94 | addCanvas(&xml, liveCanvas, liveCanvasTag); 95 | addMaskFrames(&xml, canvasContents); 96 | 97 | xml.popTag(); 98 | 99 | xml.saveFile(xmlSubPath + directoryDivider + fileName + fileExtension); 100 | } 101 | 102 | void Xml::backupExistingFile(){ 103 | 104 | ofxXmlSettings xml; 105 | 106 | if(xml.loadFile(xmlSubPath + directoryDivider + fileName + fileExtension)){ 107 | xml.pushTag(sessionTag); 108 | string timestamp = xml.getValue(timestampTag, defaultTimestamp); 109 | xml.saveFile(xmlSubPath + directoryDivider + fileName + "-" + timestamp + fileExtension); 110 | } 111 | } 112 | 113 | void Xml::ensureDirectory(){ 114 | 115 | ofDirectory directory; 116 | 117 | string dataDirectory = ofToDataPath(""); 118 | if(!directory.doesDirectoryExist(dataDirectory)){ 119 | directory.createDirectory(dataDirectory); 120 | } 121 | 122 | string projectionMaskDirectory = ofToDataPath(projectionMaskPath); 123 | if(!directory.doesDirectoryExist(projectionMaskDirectory)){ 124 | directory.createDirectory(projectionMaskDirectory); 125 | } 126 | 127 | string xmlSubDirectory = ofToDataPath(xmlSubPath); 128 | if(!directory.doesDirectoryExist(xmlSubDirectory)){ 129 | directory.createDirectory(xmlSubDirectory); 130 | } 131 | } 132 | 133 | void Xml::addTimestamp(ofxXmlSettings *xml){ 134 | xml->addTag(timestampTag); 135 | xml->setValue(timestampTag, ofGetTimestampString()); 136 | } 137 | 138 | void Xml::addType(ofxXmlSettings *xml, bool autoSave){ 139 | xml->addTag(typeTag); 140 | if(autoSave){ 141 | xml->setValue(typeTag, typeAuto); 142 | }else{ 143 | xml->setValue(typeTag, typeManual); 144 | } 145 | } 146 | 147 | void Xml::addCanvas(ofxXmlSettings *xml, Canvas *canvas, string tagName){ 148 | 149 | xml->addTag(tagName); 150 | xml->pushTag(tagName); 151 | 152 | xml->addTag(widthTag); 153 | xml->addTag(heightTag); 154 | xml->addTag(xTag); 155 | xml->addTag(yTag); 156 | 157 | xml->setValue(widthTag, canvas->getWidth()); 158 | xml->setValue(heightTag, canvas->getHeight()); 159 | xml->setValue(xTag, canvas->getX()); 160 | xml->setValue(yTag, canvas->getY()); 161 | 162 | xml->popTag(); 163 | } 164 | 165 | void Xml::addMaskFrames(ofxXmlSettings *xml, CanvasContents *canvasContents){ 166 | 167 | xml->addTag(maskFramesTag); 168 | xml->pushTag(maskFramesTag); 169 | 170 | SafeDeque *maskFrames = canvasContents->getMaskFrames(); 171 | 172 | for(int i = 0; i < maskFrames->size(); i++){ 173 | addMaskFrame(xml, maskFrames->getPointer(i), i); 174 | } 175 | 176 | xml->popTag(); 177 | } 178 | 179 | void Xml::addMaskFrame(ofxXmlSettings *xml, MaskFrame *maskFrame, int i){ 180 | 181 | xml->addTag(maskFrameTag); 182 | xml->setValue(maskFrameTag + levelDivider + idTag, maskFrame->getId(), i); 183 | 184 | xml->setValue(maskFrameTag + levelDivider + designWidthTag, maskFrame->getWidth(), i); 185 | xml->setValue(maskFrameTag + levelDivider + designHeightTag, maskFrame->getHeight(), i); 186 | xml->setValue(maskFrameTag + levelDivider + designXTag, maskFrame->getRelativeX(), i); 187 | xml->setValue(maskFrameTag + levelDivider + designYTag, maskFrame->getRelativeY(), i); 188 | 189 | xml->setValue(maskFrameTag + levelDivider + liveWidthTag, maskFrame->getLiveWidth(), i); 190 | xml->setValue(maskFrameTag + levelDivider + liveHeightTag, maskFrame->getLiveHeight(), i); 191 | xml->setValue(maskFrameTag + levelDivider + liveXTag, maskFrame->getLiveRelativeX(), i); 192 | xml->setValue(maskFrameTag + levelDivider + liveYTag, maskFrame->getLiveRelativeY(), i); 193 | 194 | xml->pushTag(maskFrameTag, i); 195 | addMaskPoints(xml, maskFrame); 196 | xml->popTag(); 197 | } 198 | 199 | void Xml::addMaskPoints(ofxXmlSettings *xml, MaskFrame *maskFrame){ 200 | 201 | xml->addTag(maskPointsTag); 202 | xml->pushTag(maskPointsTag); 203 | 204 | SafeDeque *maskPoints = maskFrame->getMaskPoints(); 205 | 206 | for(int i = 0; i < maskPoints->size(); i++){ 207 | addMaskPoint(xml, maskPoints->getPointer(i), i); 208 | } 209 | 210 | xml->popTag(); 211 | } 212 | 213 | void Xml::addMaskPoint(ofxXmlSettings *xml, MaskPoint *maskPoint, int i){ 214 | 215 | xml->addTag(maskPointTag); 216 | 217 | xml->setValue(maskPointTag + levelDivider + designXTag, maskPoint->getX(), i); 218 | xml->setValue(maskPointTag + levelDivider + designYTag, maskPoint->getY(), i); 219 | xml->setValue(maskPointTag + levelDivider + liveXTag, maskPoint->getLiveX(), i); 220 | xml->setValue(maskPointTag + levelDivider + liveYTag, maskPoint->getLiveY(), i); 221 | } 222 | 223 | void Xml::loadSourceCanvasDimensions(ofxXmlSettings *xml){ 224 | xml->pushTag(designCanvasTag); 225 | sourceDesignCanvasWidth = xml->getValue(widthTag, 0); 226 | sourceDesignCanvasHeight = xml->getValue(heightTag, 0); 227 | xml->popTag(); 228 | 229 | xml->pushTag(liveCanvasTag); 230 | sourceLiveCanvasWidth = xml->getValue(widthTag, 0); 231 | sourceLiveCanvasHeight = xml->getValue(heightTag, 0); 232 | xml->popTag(); 233 | } 234 | 235 | void Xml::loadMaskFrames(ofxXmlSettings *xml){ 236 | 237 | xml->pushTag(maskFramesTag); 238 | 239 | SafeDeque *maskFrames = canvasContents->getMaskFrames(); 240 | maskFrames->deleteAll(); 241 | 242 | int numFrames = xml->getNumTags(maskFrameTag); 243 | 244 | for(int i = 0; i < numFrames; i++){ 245 | loadMaskFrame(xml, maskFrames, i); 246 | } 247 | 248 | xml->popTag(); 249 | } 250 | 251 | void Xml::loadMaskFrame(ofxXmlSettings *xml, SafeDeque *maskFrames, int i){ 252 | 253 | xml->pushTag(maskFrameTag, i); 254 | 255 | MaskFrame maskFrame; 256 | maskFrame.setId(getMaskFrameId(xml)); 257 | 258 | maskFrame.assignCanvases(*designCanvas, *liveCanvas); 259 | maskFrame.setPattern(nextPattern()); 260 | 261 | int liveWidth = getMaskFrameLiveWidth(xml); 262 | int liveHeight = getMaskFrameLiveHeight(xml); 263 | maskFrame.setLiveSize(liveWidth, liveHeight); 264 | 265 | int liveX = getMaskFrameLiveX(xml); 266 | int liveY = getMaskFrameLiveY(xml); 267 | maskFrame.setLiveRelativePosition(liveX, liveY); 268 | 269 | loadMaskPoints(xml, &maskFrame); 270 | maskFrame.transposeToDesignCanvas(); 271 | maskFrames->push_back(maskFrame); 272 | 273 | xml->popTag(); 274 | } 275 | 276 | void Xml::loadMaskPoints(ofxXmlSettings *xml, MaskFrame *maskFrame){ 277 | 278 | xml->pushTag(maskPointsTag, 0); 279 | 280 | SafeDeque *maskPoints = maskFrame->getMaskPoints(); 281 | 282 | int numPoints = xml->getNumTags(maskPointTag); 283 | 284 | for(int i = 0; i < numPoints; i++){ 285 | loadMaskPoint(xml, maskPoints, maskFrame, i); 286 | } 287 | 288 | xml->popTag(); 289 | } 290 | 291 | void Xml::loadMaskPoint(ofxXmlSettings *xml, SafeDeque *maskPoints, MaskFrame *maskFrame, int i){ 292 | 293 | xml->pushTag(maskPointTag, i); 294 | 295 | MaskPoint maskPoint; 296 | maskPoint.setType(Real); 297 | maskPoint.setLiveX(xml->getValue(liveXTag, 0)); 298 | maskPoint.setLiveY(xml->getValue(liveYTag, 0)); 299 | 300 | maskPoints->push_back(maskPoint); 301 | xml->popTag(); 302 | } 303 | 304 | int Xml::getMaskFrameId(ofxXmlSettings *xml){ 305 | return xml->getValue(idTag, 0); 306 | } 307 | 308 | int Xml::getMaskFrameLiveWidth(ofxXmlSettings *xml){ 309 | sourceMaskFrameWidth = xml->getValue(liveWidthTag, 0); 310 | return ofMap(sourceMaskFrameWidth, 0, sourceLiveCanvasWidth, 0, liveCanvas->getWidth()); 311 | } 312 | 313 | int Xml::getMaskFrameLiveHeight(ofxXmlSettings *xml){ 314 | sourceMaskFrameHeight = xml->getValue(liveHeightTag, 0); 315 | return ofMap(sourceMaskFrameHeight, 0, sourceLiveCanvasHeight, 0, liveCanvas->getHeight()); 316 | } 317 | 318 | int Xml::getMaskFrameLiveX(ofxXmlSettings *xml){ 319 | int maskFrameLiveX = xml->getValue(liveXTag, 0); 320 | return ofMap(maskFrameLiveX, 0, sourceLiveCanvasWidth, 0, liveCanvas->getWidth()); 321 | } 322 | 323 | int Xml::getMaskFrameLiveY(ofxXmlSettings *xml){ 324 | int maskFrameLiveY = xml->getValue(liveYTag, 0); 325 | return ofMap(maskFrameLiveY, 0, sourceLiveCanvasHeight, 0, liveCanvas->getHeight()); 326 | } 327 | 328 | int Xml::getMaskPointLiveX(ofxXmlSettings *xml, MaskFrame *maskFrame){ 329 | int maskPointLiveX = xml->getValue(liveXTag, 0); 330 | return ofMap(maskPointLiveX, 0, sourceMaskFrameWidth, 0, maskFrame->getWidth()); 331 | } 332 | 333 | int Xml::getMaskPointLiveY(ofxXmlSettings *xml, MaskFrame *maskFrame){ 334 | int maskPointLiveY = xml->getValue(liveYTag, 0); 335 | return ofMap(maskPointLiveY, 0, sourceMaskFrameHeight, 0, maskFrame->getHeight()); 336 | } 337 | 338 | ofxLayerMask* Xml::nextPattern() { 339 | int patternId = (canvasContents->getMaskFrames()->size()) % patterns->size(); 340 | return patterns->at(patternId); 341 | } 342 | -------------------------------------------------------------------------------- /src/Storage/Xml.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofxXmlSettings.h" 3 | #include "Canvas.h" 4 | #include "CanvasContents.h" 5 | #include "ofxLayerMask.h" 6 | 7 | class Xml{ 8 | public: 9 | void setup(Canvas *designCanvas, Canvas *liveCanvas, CanvasContents *canvasContents, vector *patterns, string directory); 10 | void setFileName(string _fileName); 11 | void save(); 12 | void autoSave(); 13 | void load(); 14 | protected: 15 | Canvas *designCanvas, *liveCanvas; 16 | int sourceDesignCanvasWidth, sourceDesignCanvasHeight; 17 | int sourceLiveCanvasWidth, sourceLiveCanvasHeight; 18 | int sourceMaskFrameWidth, sourceMaskFrameHeight; 19 | CanvasContents *canvasContents; 20 | vector *patterns; 21 | string xmlSubPath; 22 | 23 | string fileName; 24 | 25 | void save(bool autoSave); 26 | void backupExistingFile(); 27 | void ensureDirectory(); 28 | 29 | void addTimestamp(ofxXmlSettings *xml); 30 | void addType(ofxXmlSettings *xml, bool autoSave); 31 | void addCanvas(ofxXmlSettings *xml, Canvas *canvas, string tagName); 32 | void addMaskFrames(ofxXmlSettings *xml, CanvasContents *canvasContents); 33 | void addMaskFrame(ofxXmlSettings *xml, MaskFrame *maskFrame, int i); 34 | void addMaskPoints(ofxXmlSettings *xml, MaskFrame *maskFrame); 35 | void addMaskPoint(ofxXmlSettings *xml, MaskPoint *maskPoint, int i); 36 | 37 | void loadSourceCanvasDimensions(ofxXmlSettings *xml); 38 | void loadMaskFrames(ofxXmlSettings *xml); 39 | void loadMaskFrame(ofxXmlSettings *xml, SafeDeque *maskFrames, int i); 40 | void loadMaskPoints(ofxXmlSettings *xml, MaskFrame *maskFrame); 41 | void loadMaskPoint(ofxXmlSettings *xml, SafeDeque *maskPoints, MaskFrame *maskFrame, int i); 42 | 43 | int getMaskFrameId(ofxXmlSettings *xml); 44 | int getMaskFrameLiveWidth(ofxXmlSettings *xml); 45 | int getMaskFrameLiveHeight(ofxXmlSettings *xml); 46 | int getMaskFrameLiveX(ofxXmlSettings *xml); 47 | int getMaskFrameLiveY(ofxXmlSettings *xml); 48 | int getMaskPointLiveX(ofxXmlSettings *xml, MaskFrame *maskFrame); 49 | int getMaskPointLiveY(ofxXmlSettings *xml, MaskFrame *maskFrame); 50 | 51 | ofxLayerMask* nextPattern(); 52 | }; 53 | -------------------------------------------------------------------------------- /src/ofExtensions.cpp: -------------------------------------------------------------------------------- 1 | #include "ofExtensions.h" 2 | 3 | void ofCircleStroke(int x, int y, int radius, int stroke, ofColor fillColor, ofColor strokeColor){ 4 | 5 | /* 6 | Making an ofCircle with a stroke 7 | ================================ 8 | - Only the stroke (outer line) of a circle is smoothed 9 | - To create a stroke you have to call ofCircle twice, once with ofFill and once without 10 | - But ofCircle is limited by what openGL can do and so the line segments don't look good 11 | when you ofSetLineWidth > 1 12 | - Therefore to create the illusion you have to create 2 x ofCircle, each with it's own 13 | 1px stroke the same color as the fill 14 | - Then you still have to choose between tiny gaps vs. a properly smooth edge 15 | (adjust ofSetLineWidth(0..1) to see this) 16 | - It has been reported on github: 17 | http://forum.openframeworks.cc/index.php?topic=7278.0 18 | */ 19 | 20 | int strokeRadius = radius + stroke; 21 | ofSetLineWidth(1); 22 | 23 | ofSetColor(strokeColor); 24 | ofFill(); 25 | ofDrawCircle(x, y, strokeRadius); 26 | ofSetColor(strokeColor); 27 | ofNoFill(); 28 | ofDrawCircle(x, y, strokeRadius); 29 | 30 | ofSetColor(fillColor); 31 | ofFill(); 32 | ofDrawCircle(x, y, radius); 33 | ofSetColor(fillColor); 34 | ofNoFill(); 35 | ofDrawCircle(x, y, radius); 36 | } 37 | 38 | void ofCircleNoStroke(int x, int y, int radius, ofColor color){ 39 | 40 | ofSetLineWidth(1); 41 | 42 | ofSetColor(color); 43 | ofFill(); 44 | ofDrawCircle(x, y, radius); 45 | ofSetColor(color); 46 | ofNoFill(); 47 | ofDrawCircle(x, y, radius); 48 | } 49 | 50 | float clampFloat(float value, float lowerBoundary, float upperBoundary){ 51 | if(value < lowerBoundary){ 52 | return lowerBoundary; 53 | }else if(value > upperBoundary){ 54 | return upperBoundary; 55 | }else{ 56 | return value; 57 | } 58 | } 59 | 60 | int clampInt(int value, int lowerBoundary, int upperBoundary){ 61 | if(value < lowerBoundary){ 62 | return lowerBoundary; 63 | }else if(value > upperBoundary){ 64 | return upperBoundary; 65 | }else{ 66 | return value; 67 | } 68 | } 69 | 70 | int clampInt(int value, int lowerBoundary){ 71 | if(value < lowerBoundary){ 72 | return lowerBoundary; 73 | } 74 | return value; 75 | } 76 | 77 | int getNextIndex(int currentIndex, int size){ 78 | if(currentIndex + 1 == size){ 79 | return 0; 80 | } 81 | return currentIndex + 1; 82 | } 83 | 84 | //http://stackoverflow.com/questions/236129/splitting-a-string-in-c 85 | vector &split(const string &s, char delim, vector &elems) { 86 | stringstream ss(s); 87 | string item; 88 | while(getline(ss, item, delim)) { 89 | elems.push_back(item); 90 | } 91 | return elems; 92 | } 93 | 94 | 95 | vector split(const string &s, char delim) { 96 | vector elems; 97 | return split(s, delim, elems); 98 | } 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/ofExtensions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | 4 | enum TransformState { Translating, Scaling, Masking, NoTransform }; 5 | 6 | void ofCircleStroke(int x, int y, int radius, int stroke, ofColor fillColor, ofColor strokeColor); 7 | void ofCircleNoStroke(int x, int y, int radius, ofColor color); 8 | 9 | float clampFloat(float value, float lowerBoundary, float upperBoundary); 10 | int clampInt(int value, int lowerBoundary, int upperBoundary); 11 | int clampInt(int value, int lowerBoundary); 12 | int getNextIndex(int currentIndex, int size); 13 | 14 | vector &split(const string &s, char delim, vector &elems); 15 | vector split(const string &s, char delim); 16 | 17 | -------------------------------------------------------------------------------- /src/ofxProjectionMask.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxProjectionMask.h" 2 | 3 | //Public 4 | void ofxProjectionMask::setup(StretchMode _stretchMode, PresetMode presetMode){ 5 | presets.setMode(presetMode); 6 | displayMode = Design; 7 | 8 | setupCommon(presets.firstWindowX, presets.firstWindowY, presets.firstWindowWidth, presets.firstWindowHeight); 9 | layoutFirstWindow(); 10 | 11 | selectedMaskFrame = 0; 12 | stretchMode = _stretchMode; 13 | 14 | xml.setup(&designCanvas, &liveCanvas, &canvasContents, &patterns, presets.storageDirectory); 15 | 16 | if(patterns.size() > 0) { 17 | xml.load(); 18 | } 19 | mouse.setup(&designCanvas); 20 | 21 | background.setup(presets.liveCanvasWidth, presets.liveCanvasHeight, 1); 22 | 23 | ofAddListener(ofEvents().keyReleased, this, &ofxProjectionMask::keyReleased); 24 | ofAddListener(ofEvents().mouseDragged, this, &ofxProjectionMask::mouseDragged); 25 | ofAddListener(ofEvents().mousePressed, this, &ofxProjectionMask::mousePressed); 26 | ofAddListener(ofEvents().mouseReleased, this, &ofxProjectionMask::mouseReleased); 27 | } 28 | 29 | void ofxProjectionMask::setupSecondWindow(){ 30 | setupCommon(presets.secondWindowX, presets.secondWindowY, presets.secondWindowWidth, presets.secondWindowHeight); 31 | layoutSecondWindow(); 32 | secondWindowSetup = true; 33 | } 34 | 35 | void ofxProjectionMask::setupCommon(int x, int y, int width, int height){ 36 | ofSetHexColor(0xFFFFFF); 37 | ofBackground(0, 0, 0); 38 | ofEnableAlphaBlending(); 39 | 40 | if(presets.isProductionMode()){ 41 | ofSetFullscreen(true); 42 | } else { 43 | ofSetWindowPosition(x, y); 44 | ofSetWindowShape(width, height); 45 | } 46 | } 47 | 48 | void ofxProjectionMask::setStorageFileName(string fileName){ 49 | xml.setFileName(fileName); 50 | } 51 | 52 | ofxLayerMask* ofxProjectionMask::newPattern(int width, int height){ 53 | patterns.push_back(new ofxLayerMask); 54 | patterns.back()->setup(width, height, 1); 55 | xml.load(); 56 | return patterns.back(); 57 | } 58 | 59 | void ofxProjectionMask::layoutFirstWindow() { 60 | if(presets.isProductionMode()){ 61 | presets.firstWindowWidth = ofGetWindowWidth(); 62 | presets.firstWindowHeight = ofGetWindowHeight(); 63 | } 64 | 65 | designCanvas.setPosition(presets.designCanvasX, presets.designCanvasY); 66 | designCanvas.setSize(presets.designCanvasWidth, presets.designCanvasHeight); 67 | designCanvas.setNumGridLines(presets.numGridLinesX, presets.numGridLinesY); 68 | 69 | textArea.setInstructionsPosition(presets.instructionsX, presets.instructionsY); 70 | textArea.setPlaybackVolumePosition(presets.playbackVolumeX, presets.playbackVolumeY); 71 | textArea.setNonPlaybackVolumesPosition(presets.nonPlaybackVolumeX, presets.nonPlaybackVolumeY); 72 | textArea.setNumberBoxSize(presets.numberBoxWidth, presets.numberBoxHeight); 73 | textArea.setOffsets(presets.numberTagOffsetX, presets.numberTagOffsetY); 74 | textArea.setMargins(presets.numberTagMargin, presets.numberBoxMargin); 75 | } 76 | 77 | void ofxProjectionMask::layoutSecondWindow() { 78 | if(presets.isProductionMode()){ 79 | presets.secondWindowWidth = ofGetWindowWidth(); 80 | presets.secondWindowHeight = ofGetWindowHeight(); 81 | presets.secondWindowX = 0; 82 | presets.secondWindowY = 0; 83 | } 84 | 85 | liveCanvas.setPosition(presets.secondWindowX, presets.secondWindowY); 86 | liveCanvas.setSize(presets.secondWindowWidth, presets.secondWindowHeight); 87 | liveCanvas.setNumGridLines(presets.numGridLinesX, presets.numGridLinesY); 88 | } 89 | 90 | void ofxProjectionMask::update(int mouseX, int mouseY){ 91 | mouse.set(mouseX, mouseY); 92 | 93 | if(!isTransforming()){ 94 | canvasContents.updateHighlights(mouseX, mouseY); 95 | } 96 | 97 | textArea.setDisplayMode(displayMode); 98 | textArea.setPresetMode(presets.getMode()); 99 | } 100 | 101 | void ofxProjectionMask::drawFirstWindow(){ 102 | ofPushStyle(); 103 | { 104 | ofSetLineWidth(1); 105 | ofBackground(ofColor::black); 106 | drawBufferPreviews(); 107 | 108 | ofPushMatrix(); 109 | ofTranslate(designCanvas.getX(), designCanvas.getY()); 110 | drawBackground(designCanvas.getWidth(), designCanvas.getHeight(), 150); 111 | designCanvas.draw(); 112 | canvasContents.drawDesign(); 113 | ofPopMatrix(); 114 | 115 | ofPushMatrix(); 116 | ofTranslate(presets.designCanvasLabelX, presets.designCanvasLabelY); 117 | ofSetColor(ofColor::white); 118 | ofDrawBitmapString("Design Canvas", ofPoint(0, 0)); 119 | ofPopMatrix(); 120 | 121 | textArea.draw(); 122 | } 123 | ofPopStyle(); 124 | } 125 | 126 | void ofxProjectionMask::drawSecondWindow(){ 127 | if(!secondWindowSetup){ 128 | setupSecondWindow(); 129 | } 130 | ofPushMatrix(); 131 | ofTranslate(0, 0); 132 | drawBackground(liveCanvas.getWidth(), liveCanvas.getHeight(), 255); 133 | if(displayMode == Design){ 134 | liveCanvas.draw(); 135 | } 136 | canvasContents.drawLive(displayMode, stretchMode); 137 | ofPopMatrix(); 138 | drawLiveCursor(); 139 | } 140 | 141 | void ofxProjectionMask::drawBackground(int width, int height, int alpha){ 142 | if(background.numLayers() > 0){ 143 | background.draw(0, 0, width, height); 144 | ofSetColor(ofColor::black, 255 - alpha); 145 | ofFill(); 146 | ofDrawRectangle(0, 0, width, height); 147 | ofSetColor(ofColor::white); 148 | ofNoFill(); 149 | } 150 | } 151 | 152 | void ofxProjectionMask::keyReleased(ofKeyEventArgs& args){ 153 | if(args.key == 'f' || args.key == 'F'){ 154 | createNewMaskFrame(); 155 | xml.autoSave(); 156 | }else if(args.key == 'p' || args.key == 'P'){ 157 | createNewMaskPoint(); 158 | xml.autoSave(); 159 | }else if (args.key == ' '){ 160 | ofToggleFullscreen(); 161 | }else if(args.key == 'u' || args.key == 'U'){ 162 | undo(); 163 | }else if(args.key == 'r' || args.key == 'R'){ 164 | redo(); 165 | }else if(args.key == 127 || args.key == 8){ 166 | deleteHighlightedItem(); 167 | xml.autoSave(); 168 | xml.load(); 169 | }else if(args.key == OF_KEY_LEFT){ 170 | nudge(Left); 171 | xml.autoSave(); 172 | }else if(args.key == OF_KEY_UP){ 173 | nudge(Up); 174 | xml.autoSave(); 175 | }else if(args.key == OF_KEY_RIGHT){ 176 | nudge(Right); 177 | xml.autoSave(); 178 | }else if(args.key == OF_KEY_DOWN){ 179 | nudge(Down); 180 | xml.autoSave(); 181 | }else if(args.key == 's' || args.key == 'S'){ 182 | xml.save(); 183 | }else if(args.key == 'l' || args.key == 'L'){ 184 | xml.load(); 185 | }else if(args.key == 'm' || args.key == 'M'){ 186 | cycleMode(); 187 | }else if(args.key == 'n' || args.key == 'N'){ 188 | toggleFrameNudge(); 189 | } 190 | } 191 | 192 | void ofxProjectionMask::mouseDragged(ofMouseEventArgs &args){ 193 | if(selectedMaskFrame != 0){ 194 | TransformState state = selectedMaskFrame->getTransformState(); 195 | 196 | if(state == Translating){ 197 | float x = mouse.newSelectionX(); 198 | float y = mouse.newSelectionY(); 199 | selectedMaskFrame->setPosition(x, y); 200 | 201 | }else if(state == Scaling){ 202 | int width = mouse.newSelectionWidth(); 203 | int height = mouse.newSelectionHeight(); 204 | Corner corner = selectedMaskFrame->highlightedCorner(); 205 | selectedMaskFrame->setSize(width, height, corner); 206 | 207 | }else if(state == Masking){ 208 | float x = mouse.newSelectionX(); 209 | float y = mouse.newSelectionY(); 210 | selectedMaskFrame->setSelectedMaskPointPosition(x, y); 211 | } 212 | } 213 | } 214 | 215 | void ofxProjectionMask::mousePressed(ofMouseEventArgs &args){ 216 | selectedMaskFrame = canvasContents.beginTransform(); 217 | if(selectedMaskFrame != 0){ 218 | mouse.setSelection(selectedMaskFrame); 219 | } 220 | } 221 | 222 | void ofxProjectionMask::mouseReleased(ofMouseEventArgs &args){ 223 | selectedMaskFrame = 0; 224 | canvasContents.endTransform(); 225 | xml.autoSave(); 226 | } 227 | 228 | void ofxProjectionMask::setVolumes(float *playbackVolume, vector *nonPlaybackVolumes){ 229 | textArea.setVolumes(playbackVolume, nonPlaybackVolumes); 230 | } 231 | 232 | ofxLayerMask* ofxProjectionMask::nextPattern() { 233 | int patternId = (canvasContents.getMaskFrames()->size()) % patterns.size(); 234 | return patterns.at(patternId); 235 | } 236 | 237 | ofxLayerMask* ofxProjectionMask::getBackground() { 238 | return &background; 239 | } 240 | 241 | //Protected 242 | void ofxProjectionMask::undo(){ 243 | canvasContents.undo(); 244 | } 245 | 246 | void ofxProjectionMask::redo(){ 247 | canvasContents.redo(); 248 | } 249 | 250 | void ofxProjectionMask::nudge(Direction direction){ 251 | canvasContents.nudge(direction); 252 | } 253 | 254 | void ofxProjectionMask::toggleFrameNudge(){ 255 | canvasContents.toggleFrameNudge(); 256 | textArea.setFrameNudgeEnabled(canvasContents.getFrameNudgeEnabled()); 257 | } 258 | 259 | void ofxProjectionMask::createNewMaskFrame(){ 260 | MaskFrame maskFrame; 261 | maskFrame.assignCanvases(designCanvas, liveCanvas); 262 | maskFrame.setPattern(nextPattern()); 263 | maskFrame.setSize(presets.newMaskFrameWidth, presets.newMaskFrameHeight); 264 | maskFrame.setPosition(mouse.x, mouse.y); 265 | canvasContents.add(&maskFrame); 266 | } 267 | 268 | void ofxProjectionMask::createNewMaskPoint(){ 269 | canvasContents.createMaskPointAt(mouse.x, mouse.y); 270 | } 271 | 272 | void ofxProjectionMask::deleteHighlightedItem(){ 273 | canvasContents.eraseHighlighted(); 274 | } 275 | 276 | void ofxProjectionMask::cycleMode(){ 277 | if(displayMode == Design){ 278 | displayMode = HalfLive; 279 | }else if(displayMode == HalfLive){ 280 | displayMode = Live; 281 | }else if(displayMode == Live){ 282 | displayMode = Design; 283 | } 284 | } 285 | 286 | bool ofxProjectionMask::mouseIsOverDesignCanvas(){ 287 | return mouse.x > this->designCanvas.getX() && mouse.x < (this->designCanvas.getX() + this->designCanvas.getWidth()) 288 | && mouse.y > this->designCanvas.getY() && mouse.y < (this->designCanvas.getY() + this->designCanvas.getHeight()); 289 | } 290 | 291 | void ofxProjectionMask::drawLiveCursor(){ 292 | if(mouseIsOverDesignCanvas() && displayMode != Live){ 293 | int liveMouseX = ofMap(mouse.x, designCanvas.getX(), designCanvas.getX() + designCanvas.getWidth(), liveCanvas.getX(), liveCanvas.getX() + liveCanvas.getWidth()); 294 | int liveMouseY = ofMap(mouse.y, designCanvas.getY(), designCanvas.getY() + designCanvas.getHeight(), liveCanvas.getY(), liveCanvas.getY() + liveCanvas.getHeight()); 295 | 296 | ofDrawLine(liveMouseX - 5, liveMouseY - 5, liveMouseX + 5, liveMouseY + 5); 297 | ofDrawLine(liveMouseX + 5, liveMouseY - 5, liveMouseX - 5, liveMouseY + 5); 298 | } 299 | } 300 | 301 | void ofxProjectionMask::drawBufferPreviews(){ 302 | ofPushMatrix(); 303 | ofTranslate(presets.bufferPreviewX, presets.bufferPreviewY); 304 | 305 | ofSetColor(255, 255, 255, 255); 306 | ofNoFill(); 307 | 308 | int x = 0, y = 0, count = 0; 309 | 310 | for(int i = 0; i < patterns.size(); i++){ 311 | ofTranslate(x, y); 312 | patterns.at(i)->drawLayer(0, 0, 0, presets.bufferPreviewWidth, presets.bufferPreviewHeight, false); 313 | ofDrawRectangle(0, 0, presets.bufferPreviewWidth, presets.bufferPreviewHeight); 314 | ofDrawBitmapString("Buffer " + ofToString(i + 1), 0, presets.bufferPreviewHeight + presets.bufferMargin); 315 | x = presets.bufferPreviewWidth + presets.bufferMargin; 316 | } 317 | 318 | ofPopMatrix(); 319 | } 320 | 321 | bool ofxProjectionMask::isTransforming(){ 322 | return selectedMaskFrame != 0 && selectedMaskFrame->getTransformState() != NoTransform; 323 | } 324 | -------------------------------------------------------------------------------- /src/ofxProjectionMask.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "ofxLayerMask.h" 4 | #include "CanvasContents.h" 5 | #include "MaskFrame.h" 6 | #include "TextArea.h" 7 | #include "Xml.h" 8 | #include "Presets.h" 9 | #include "Mouse.h" 10 | 11 | class ofxProjectionMask{ 12 | public: 13 | void setup(StretchMode _stretchMode=STRETCH_TO_MASKFRAME, PresetMode presetMode=PRESETS_DEVELOPMENT); 14 | void setupSecondWindow(); 15 | void setupCommon(int x, int y, int width, int height); 16 | 17 | void setStorageFileName(string fileName); 18 | ofxLayerMask* newPattern(int width, int height); 19 | void layoutFirstWindow(); 20 | void layoutSecondWindow(); 21 | 22 | void update(int mouseX, int mouseY); 23 | void drawFirstWindow(); 24 | void drawSecondWindow(); 25 | void drawBackground(int width, int height, int alpha); 26 | 27 | void keyReleased(ofKeyEventArgs& args); 28 | void mouseDragged(ofMouseEventArgs &args); 29 | void mousePressed(ofMouseEventArgs &args); 30 | void mouseReleased(ofMouseEventArgs &args); 31 | 32 | void setVolumes(float *volume, vector *nonPlaybackVolumes); 33 | ofxLayerMask* nextPattern(); 34 | ofxLayerMask* getBackground(); 35 | 36 | protected: 37 | Presets presets; 38 | DisplayMode displayMode; 39 | StretchMode stretchMode; 40 | 41 | Canvas designCanvas, liveCanvas; 42 | CanvasContents canvasContents; 43 | vector patterns; 44 | ofxLayerMask background; 45 | 46 | Mouse mouse; 47 | MaskFrame *selectedMaskFrame; 48 | TextArea textArea; 49 | Xml xml; 50 | bool secondWindowSetup = false; 51 | 52 | void undo(); 53 | void redo(); 54 | 55 | void nudge(Direction direction); 56 | void toggleFrameNudge(); 57 | 58 | void createNewMaskFrame(); 59 | void createNewMaskPoint(); 60 | void deleteHighlightedItem(); 61 | 62 | void cycleMode(); 63 | bool mouseIsOverDesignCanvas(); 64 | 65 | void drawLiveCursor(); 66 | void drawBufferPreviews(); 67 | 68 | bool isTransforming(); 69 | }; 70 | -------------------------------------------------------------------------------- /vimeo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microcosm/ofxProjectionMask/300750e49d425d91964e1b61602d9b2f071aaba5/vimeo.png --------------------------------------------------------------------------------