267 changed files with 20945 additions and 20856 deletions
@ -1,5 +1,5 @@ |
|||
# These are supported funding model platforms |
|||
|
|||
github: [kr15h] |
|||
patreon: kriwkrow |
|||
custom: ['https://paypal.me/kriwkrow'] |
|||
# These are supported funding model platforms |
|||
|
|||
github: [kr15h] |
|||
patreon: kriwkrow |
|||
custom: ['https://paypal.me/kriwkrow'] |
|||
|
@ -1,57 +1,57 @@ |
|||
name: linux |
|||
on: |
|||
push: |
|||
branches: |
|||
- master |
|||
jobs: |
|||
compile: |
|||
runs-on: ubuntu-latest |
|||
env: |
|||
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_linux64gcc6_release.tar.gz |
|||
steps: |
|||
- name: Fetch ofxPiMapper |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 1 |
|||
- name: Download openFrameworks and add ofxPiMapper to addons |
|||
run: | |
|||
mkdir .ofxPiMapper |
|||
mv ./* .ofxPiMapper/ |
|||
wget ${OF_URL} --tries=10 --quiet |
|||
echo "Unarchive openFrameworks" |
|||
OF_ARCHIVE_NAME=$(basename -- "$OF_URL") |
|||
tar -xf ${OF_ARCHIVE_NAME} |
|||
rm ${OF_ARCHIVE_NAME} |
|||
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .tar.gz) |
|||
mv ${OF_EXTRACT_NAME} openFrameworks |
|||
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper |
|||
- name: Install openFrameworks Dependencies |
|||
working-directory: ./openFrameworks/scripts/linux/ubuntu |
|||
run: sudo ./install_dependencies.sh -y |
|||
- name: Compile openFrameworks |
|||
working-directory: ./openFrameworks/scripts/linux |
|||
run: ./compileOF.sh |
|||
- name: Compile example_basic |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_camera |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_fbo-sources |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_pocketvj |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Install ofxJSON dependency |
|||
working-directory: ./openFrameworks/addons/ |
|||
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1 |
|||
- name: Compile example_remote-client |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_remote-server |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_simpler |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler |
|||
run: mv addons.make.norpi addons.make && make |
|||
name: linux |
|||
on: |
|||
push: |
|||
branches: |
|||
- master |
|||
jobs: |
|||
compile: |
|||
runs-on: ubuntu-latest |
|||
env: |
|||
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_linux64gcc6_release.tar.gz |
|||
steps: |
|||
- name: Fetch ofxPiMapper |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 1 |
|||
- name: Download openFrameworks and add ofxPiMapper to addons |
|||
run: | |
|||
mkdir .ofxPiMapper |
|||
mv ./* .ofxPiMapper/ |
|||
wget ${OF_URL} --tries=10 --quiet |
|||
echo "Unarchive openFrameworks" |
|||
OF_ARCHIVE_NAME=$(basename -- "$OF_URL") |
|||
tar -xf ${OF_ARCHIVE_NAME} |
|||
rm ${OF_ARCHIVE_NAME} |
|||
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .tar.gz) |
|||
mv ${OF_EXTRACT_NAME} openFrameworks |
|||
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper |
|||
- name: Install openFrameworks Dependencies |
|||
working-directory: ./openFrameworks/scripts/linux/ubuntu |
|||
run: sudo ./install_dependencies.sh -y |
|||
- name: Compile openFrameworks |
|||
working-directory: ./openFrameworks/scripts/linux |
|||
run: ./compileOF.sh |
|||
- name: Compile example_basic |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_camera |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_fbo-sources |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_pocketvj |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Install ofxJSON dependency |
|||
working-directory: ./openFrameworks/addons/ |
|||
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1 |
|||
- name: Compile example_remote-client |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_remote-server |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_simpler |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler |
|||
run: mv addons.make.norpi addons.make && make |
|||
|
@ -1,60 +1,60 @@ |
|||
name: osx |
|||
on: |
|||
push: |
|||
branches: |
|||
- master |
|||
jobs: |
|||
compile: |
|||
runs-on: macos-latest |
|||
env: |
|||
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_osx_release.zip |
|||
steps: |
|||
- name: Fetch ofxPiMapper |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 1 |
|||
- name: Download openFrameworks and add ofxPiMapper to addons |
|||
run: | |
|||
mkdir .ofxPiMapper |
|||
mv ./* .ofxPiMapper/ |
|||
wget ${OF_URL} --tries=10 --quiet |
|||
echo "Unarchive openFrameworks" |
|||
OF_ARCHIVE_NAME=$(basename -- "$OF_URL") |
|||
unzip ${OF_ARCHIVE_NAME} |
|||
rm ${OF_ARCHIVE_NAME} |
|||
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip) |
|||
mv ${OF_EXTRACT_NAME} openFrameworks |
|||
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper |
|||
- name: Install Dependencies |
|||
run: | |
|||
set -ev |
|||
brew update |
|||
brew install gdb |
|||
brew install coreutils |
|||
- name: Compile openFrameworks |
|||
working-directory: ./openFrameworks/scripts/templates/osx |
|||
run: make |
|||
- name: Compile example_basic |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_camera |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_fbo-sources |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_pocketvj |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Install ofxJSON dependency |
|||
working-directory: ./openFrameworks/addons/ |
|||
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1 |
|||
- name: Compile example_remote-client |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_remote-server |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_simpler |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler |
|||
run: mv addons.make.norpi addons.make && make |
|||
name: osx |
|||
on: |
|||
push: |
|||
branches: |
|||
- master |
|||
jobs: |
|||
compile: |
|||
runs-on: macos-latest |
|||
env: |
|||
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_osx_release.zip |
|||
steps: |
|||
- name: Fetch ofxPiMapper |
|||
uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 1 |
|||
- name: Download openFrameworks and add ofxPiMapper to addons |
|||
run: | |
|||
mkdir .ofxPiMapper |
|||
mv ./* .ofxPiMapper/ |
|||
wget ${OF_URL} --tries=10 --quiet |
|||
echo "Unarchive openFrameworks" |
|||
OF_ARCHIVE_NAME=$(basename -- "$OF_URL") |
|||
unzip ${OF_ARCHIVE_NAME} |
|||
rm ${OF_ARCHIVE_NAME} |
|||
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip) |
|||
mv ${OF_EXTRACT_NAME} openFrameworks |
|||
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper |
|||
- name: Install Dependencies |
|||
run: | |
|||
set -ev |
|||
brew update |
|||
brew install gdb |
|||
brew install coreutils |
|||
- name: Compile openFrameworks |
|||
working-directory: ./openFrameworks/scripts/templates/osx |
|||
run: make |
|||
- name: Compile example_basic |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_camera |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_fbo-sources |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_pocketvj |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Install ofxJSON dependency |
|||
working-directory: ./openFrameworks/addons/ |
|||
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1 |
|||
- name: Compile example_remote-client |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_remote-server |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_simpler |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler |
|||
run: mv addons.make.norpi addons.make && make |
|||
|
@ -1,67 +1,67 @@ |
|||
name: windows |
|||
on: |
|||
push: |
|||
branches: |
|||
- master |
|||
jobs: |
|||
compile: |
|||
runs-on: windows-latest |
|||
env: |
|||
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_msys2_mingw64_release.zip |
|||
defaults: |
|||
run: |
|||
shell: msys2 {0} |
|||
steps: |
|||
- uses: msys2/setup-msys2@v2 |
|||
with: |
|||
update: true |
|||
install: unzip git |
|||
msystem: MINGW64 |
|||
- uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 1 |
|||
- name: Download openFrameworks and add ofxPiMapper to addons |
|||
run: | |
|||
mkdir .ofxPiMapper |
|||
mv ./* .ofxPiMapper/ |
|||
wget ${OF_URL} --tries=10 --quiet |
|||
echo "Unarchive openFrameworks" |
|||
OF_ARCHIVE_NAME=$(basename -- "$OF_URL") |
|||
unzip ${OF_ARCHIVE_NAME} |
|||
rm ${OF_ARCHIVE_NAME} |
|||
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip) |
|||
mv ${OF_EXTRACT_NAME} openFrameworks |
|||
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper |
|||
- name: Install openFrameworks Dependencies |
|||
working-directory: ./openFrameworks/scripts/msys2 |
|||
run: ./install_dependencies.sh --noconfirm |
|||
- name: Apply patches |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/patches/msys2 |
|||
run: ./patch.sh |
|||
- name: Compile openFrameworks |
|||
working-directory: ./openFrameworks/scripts/msys2 |
|||
run: ./compileOF.sh |
|||
- name: Compile example_basic |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_camera |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_fbo-sources |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_pocketvj |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Install ofxJSON dependency |
|||
working-directory: ./openFrameworks/addons/ |
|||
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1 |
|||
- name: Compile example_remote-client |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_remote-server |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_simpler |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler |
|||
run: mv addons.make.norpi addons.make && make |
|||
name: windows |
|||
on: |
|||
push: |
|||
branches: |
|||
- master |
|||
jobs: |
|||
compile: |
|||
runs-on: windows-latest |
|||
env: |
|||
OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.11.2/of_v0.11.2_msys2_mingw64_release.zip |
|||
defaults: |
|||
run: |
|||
shell: msys2 {0} |
|||
steps: |
|||
- uses: msys2/setup-msys2@v2 |
|||
with: |
|||
update: true |
|||
install: unzip git |
|||
msystem: MINGW64 |
|||
- uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 1 |
|||
- name: Download openFrameworks and add ofxPiMapper to addons |
|||
run: | |
|||
mkdir .ofxPiMapper |
|||
mv ./* .ofxPiMapper/ |
|||
wget ${OF_URL} --tries=10 --quiet |
|||
echo "Unarchive openFrameworks" |
|||
OF_ARCHIVE_NAME=$(basename -- "$OF_URL") |
|||
unzip ${OF_ARCHIVE_NAME} |
|||
rm ${OF_ARCHIVE_NAME} |
|||
OF_EXTRACT_NAME=$(basename ${OF_ARCHIVE_NAME} .zip) |
|||
mv ${OF_EXTRACT_NAME} openFrameworks |
|||
mv .ofxPiMapper openFrameworks/addons/ofxPiMapper |
|||
- name: Install openFrameworks Dependencies |
|||
working-directory: ./openFrameworks/scripts/msys2 |
|||
run: ./install_dependencies.sh --noconfirm |
|||
- name: Apply patches |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/patches/msys2 |
|||
run: ./patch.sh |
|||
- name: Compile openFrameworks |
|||
working-directory: ./openFrameworks/scripts/msys2 |
|||
run: ./compileOF.sh |
|||
- name: Compile example_basic |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_basic |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_camera |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_camera |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_fbo-sources |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_fbo-sources |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_pocketvj |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_pocketvj |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Install ofxJSON dependency |
|||
working-directory: ./openFrameworks/addons/ |
|||
run: git clone https://github.com/jeffcrouse/ofxJSON.git --depth 1 |
|||
- name: Compile example_remote-client |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-client |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_remote-server |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_remote-server |
|||
run: mv addons.make.norpi addons.make && make |
|||
- name: Compile example_simpler |
|||
working-directory: ./openFrameworks/addons/ofxPiMapper/example_simpler |
|||
run: mv addons.make.norpi addons.make && make |
|||
|
@ -1,121 +1,121 @@ |
|||
######################### |
|||
# general patterns |
|||
######################### |
|||
|
|||
docs/html |
|||
docs/tagfile.xml |
|||
|
|||
*/bin/* |
|||
!*/bin/data/ |
|||
|
|||
# for bin folder in root |
|||
/bin/* |
|||
!/bin/data/ |
|||
|
|||
[Bb]uild/ |
|||
[Oo]bj/ |
|||
*.o |
|||
[Dd]ebug*/ |
|||
[Rr]elease*/ |
|||
*.mode* |
|||
*.app/ |
|||
*.pyc |
|||
.svn/ |
|||
|
|||
######################### |
|||
# IDE |
|||
######################### |
|||
|
|||
# XCode |
|||
*.pbxuser |
|||
*.perspective |
|||
*.perspectivev3 |
|||
*.mode1v3 |
|||
*.mode2v3 |
|||
#XCode 4 |
|||
xcuserdata |
|||
*.xcworkspace |
|||
|
|||
# Code::Blocks |
|||
*.depend |
|||
*.layout |
|||
*.cbTemp |
|||
|
|||
# Visual Studio |
|||
*.sdf |
|||
*.opensdf |
|||
*.suo |
|||
*.pdb |
|||
*.ilk |
|||
*.aps |
|||
ipch/ |
|||
|
|||
# Eclipse |
|||
.metadata |
|||
local.properties |
|||
.externalToolBuilders |
|||
|
|||
# Codelite |
|||
*.session |
|||
*.tags |
|||
*.workspace.* |
|||
|
|||
######################### |
|||
# operating system |
|||
######################### |
|||
|
|||
# Linux |
|||
*~ |
|||
# KDE |
|||
.directory |
|||
.AppleDouble |
|||
|
|||
# OSX |
|||
.DS_Store |
|||
*.swp |
|||
*~.nib |
|||
# Thumbnails |
|||
._* |
|||
|
|||
# Windows |
|||
# Windows image file caches |
|||
Thumbs.db |
|||
# Folder config file |
|||
Desktop.ini |
|||
|
|||
#Android |
|||
.csettings |
|||
|
|||
######################### |
|||
# packages |
|||
######################### |
|||
|
|||
# it's better to unpack these files and commit the raw source |
|||
# git has its own built in compression methods |
|||
*.7z |
|||
*.dmg |
|||
*.gz |
|||
*.iso |
|||
*.jar |
|||
*.rar |
|||
*.tar |
|||
*.zip |
|||
|
|||
# Logs and databases |
|||
*.log |
|||
*.sql |
|||
*.sqlite |
|||
|
|||
example/cmake-build-debug/ |
|||
|
|||
example/\.idea/ |
|||
|
|||
example/cmake-build-release/ |
|||
|
|||
example/example\.xcodeproj/xcshareddata/xcschemes/ |
|||
|
|||
.idea/ |
|||
|
|||
cmake-build-debug/ |
|||
|
|||
CMakeLists\.txt |
|||
######################### |
|||
# general patterns |
|||
######################### |
|||
|
|||
docs/html |
|||
docs/tagfile.xml |
|||
|
|||
*/bin/* |
|||
!*/bin/data/ |
|||
|
|||
# for bin folder in root |
|||
/bin/* |
|||
!/bin/data/ |
|||
|
|||
[Bb]uild/ |
|||
[Oo]bj/ |
|||
*.o |
|||
[Dd]ebug*/ |
|||
[Rr]elease*/ |
|||
*.mode* |
|||
*.app/ |
|||
*.pyc |
|||
.svn/ |
|||
|
|||
######################### |
|||
# IDE |
|||
######################### |
|||
|
|||
# XCode |
|||
*.pbxuser |
|||
*.perspective |
|||
*.perspectivev3 |
|||
*.mode1v3 |
|||
*.mode2v3 |
|||
#XCode 4 |
|||
xcuserdata |
|||
*.xcworkspace |
|||
|
|||
# Code::Blocks |
|||
*.depend |
|||
*.layout |
|||
*.cbTemp |
|||
|
|||
# Visual Studio |
|||
*.sdf |
|||
*.opensdf |
|||
*.suo |
|||
*.pdb |
|||
*.ilk |
|||
*.aps |
|||
ipch/ |
|||
|
|||
# Eclipse |
|||
.metadata |
|||
local.properties |
|||
.externalToolBuilders |
|||
|
|||
# Codelite |
|||
*.session |
|||
*.tags |
|||
*.workspace.* |
|||
|
|||
######################### |
|||
# operating system |
|||
######################### |
|||
|
|||
# Linux |
|||
*~ |
|||
# KDE |
|||
.directory |
|||
.AppleDouble |
|||
|
|||
# OSX |
|||
.DS_Store |
|||
*.swp |
|||
*~.nib |
|||
# Thumbnails |
|||
._* |
|||
|
|||
# Windows |
|||
# Windows image file caches |
|||
Thumbs.db |
|||
# Folder config file |
|||
Desktop.ini |
|||
|
|||
#Android |
|||
.csettings |
|||
|
|||
######################### |
|||
# packages |
|||
######################### |
|||
|
|||
# it's better to unpack these files and commit the raw source |
|||
# git has its own built in compression methods |
|||
*.7z |
|||
*.dmg |
|||
*.gz |
|||
*.iso |
|||
*.jar |
|||
*.rar |
|||
*.tar |
|||
*.zip |
|||
|
|||
# Logs and databases |
|||
*.log |
|||
*.sql |
|||
*.sqlite |
|||
|
|||
example/cmake-build-debug/ |
|||
|
|||
example/\.idea/ |
|||
|
|||
example/cmake-build-release/ |
|||
|
|||
example/example\.xcodeproj/xcshareddata/xcschemes/ |
|||
|
|||
.idea/ |
|||
|
|||
cmake-build-debug/ |
|||
|
|||
CMakeLists\.txt |
|||
|
@ -1,9 +1,9 @@ |
|||
ofxPiMapper is distributed under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). This gives everyone the freedoms to use ofxPiMapper in any context: commercial or non-commercial, public or private, open or closed source. |
|||
|
|||
**Copyright (c) 2014–2021, Krisjanis Rijnieks and contributors** |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|||
ofxPiMapper is distributed under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). This gives everyone the freedoms to use ofxPiMapper in any context: commercial or non-commercial, public or private, open or closed source. |
|||
|
|||
**Copyright (c) 2014–2021, Krisjanis Rijnieks and contributors** |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|||
|
@ -1,248 +1,248 @@ |
|||
# ofxPiMapper |
|||
|
|||
[](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Alinux) |
|||
[](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Awindows) |
|||
[](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Aosx) |
|||
|
|||
Projection mapping addon for openFrameworks that runs on the Raspberry Pi. It has been tested against openFrameworks version (0.11.0). |
|||
|
|||
The project started as master's thesis project by [Krisjanis Rijnieks](https://rijnieks.com) at the [Aalto Media Lab](https://www.aalto.fi/en/aalto-media-lab). Currently being developed during free time. Please [donate](https://ofxpimapper.com/) to create more free time. |
|||
|
|||
Note on build status: GitHub Actions ubuntu-latest, windows-latest and osx-latest images with 64bit environments are used. To be reviewed. |
|||
|
|||
## Disk Image |
|||
|
|||
For those not using openFrameworks, there is a precompiled disk image available via [ofxPiMapper website](https://ofxpimapper.com). It works with Raspberry Pi up until version 3B+ (with the older BCM2837 chip). Given the recent growing interest in the project, some effort is being put into figuring out how to make the disk image to work on Pi 4 and Pi 5 (and Pi 3B+ with the more recent BCM2837B0 chip). Please [donate](https://ofxpimapper.com/) to increase the frequency and duration of these efforts. |
|||
|
|||
> **Warning!** It does not work on the latest generation of Raspberry Pi 3B+ with the BCM2837B0 chip. Make sure the Pi has the older BCM2837 chip when purchasing. |
|||
|
|||
## Introduction |
|||
|
|||
This repository contains the addon for [openFrameworks](https://openframeworks.cc). It is expected to be used as an extension for your custom openFrameworks project where you create a custom [FBO source](example_fbo-sources) that is being animated by an advanced process rather than a plain video. |
|||
|
|||
If you are planning to use videos and images only, consider using the precompiled Raspberry Pi image available from the [ofxPiMapper website](https://ofxpimapper.com). It is based on a recent Raspberry Pi OS disk image and contains compiled installation of openFrameworks along with all the scripts and services that make Pi Mapper start automatically. |
|||
|
|||
## Installation |
|||
|
|||
Clone or download the repository to your openFrameworks addons folder. Make sure that default openFrameworks examples compile and run before trying ofxPiMapper examples. There are a few things that you should do depending on if you are compiling on the Raspberry Pi or not. |
|||
|
|||
- Raspberry Pi |
|||
Please install the [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) addon before compiling. |
|||
- Windows MSYS2 |
|||
Go to `patches/msys2` directory and run `./patch.sh` |
|||
- Other platforms |
|||
Please rename the `addons.make.rpi` file to `addons.make`. |
|||
|
|||
To test, use Terminal to change the directory to `example_basic`, compile and run. |
|||
|
|||
``` |
|||
cd path/to/openFrameworks/addons/ofxPiMapper/example_basic |
|||
make |
|||
cd bin |
|||
./example_basic |
|||
``` |
|||
|
|||
If you plan to use `example_remote-server` and `example_remote-client`, make sure that you have added [ofxJSON](https://github.com/jeffcrouse/ofxJSON) dependency to your `openFrameworks/addons` folder prior compilation. |
|||
|
|||
## Usage |
|||
|
|||
Currently a keyboard and a mouse has to be used in order to do the mapping with ofxPiMapper. |
|||
|
|||
|
|||
### Modes |
|||
|
|||
PiMapper has 4 modes: |
|||
|
|||
1. Presentation mode |
|||
2. Texture mapping mode |
|||
3. Surface editing mode |
|||
4. Source assignment mode |
|||
|
|||
You can access these modes by pressing 1, 2, 3 or 4 respectively. |
|||
|
|||
|
|||
#### Presentation mode |
|||
|
|||
This mode is activated once the application starts up. It does not show anything else except the final projection mapping as it was saved previously. |
|||
|
|||
|
|||
#### Texture mapping mode |
|||
|
|||
In this mode you can adjust the texture coordinates of the surface you have selected in the surface editing mode. |
|||
|
|||
|
|||
#### Surface editing mode |
|||
|
|||
Here you can select, move and distort the surfaces you have created. |
|||
|
|||
|
|||
#### Source assignment mode |
|||
|
|||
After you select a surface in surface editing mode, activate this mode to be able to choose a source for the surface. Afterwards you might want to go to the texture mapping mode to adjust texture coordinates. |
|||
|
|||
|
|||
### Other shortcuts |
|||
|
|||
These other shortcuts that you can use while using the example app. |
|||
|
|||
Key | Function |
|||
:--- | :--- |
|||
1 | Presentation mode |
|||
2 | Texture editing mode |
|||
3 | Projection mapping mode, use this to select a surface first |
|||
4 | Source selection mode |
|||
i | Show info |
|||
t | Add triangle surface |
|||
q | Add quad surface |
|||
g | Add grid warp surface |
|||
c | Add circle surface |
|||
d | Duplicate selected surface |
|||
\+ | Scale surface up |
|||
\- | Scale surface down |
|||
p | Toggle perspective warping (quad surfaces only) |
|||
F | Expand selected surface to fill the screen (quad surfaces only) |
|||
] | Add columns to grid surface (grid warp surfaces only) |
|||
[ | Remove columns from grid surface (grid warp surfaces only) |
|||
} | Add rows to grid surface (grid warp surfaces only) |
|||
{ | Remove rows from grid surface (grid warp surfaces only) |
|||
. | Select next surface (projection mapping mode only) |
|||
, | Select previous surface (projection mapping mode only) |
|||
\> | Select next vertex |
|||
\< | Select previous vertex |
|||
0 | Move selected surface one layer up |
|||
9 | Move selected surface one layer down |
|||
s | Save composition |
|||
l | Hide/show layer panel |
|||
z | Undo |
|||
rbt | Reboot (Raspberry Pi only) |
|||
sdn | Shutdown (Raspberry Pi only) |
|||
new | Clear composition (remove all surfaces) |
|||
ext | Exit application and return to command line |
|||
BACKSPACE ('\' via SSH) | Delete surface. |
|||
SPACE | Toggle pause for video sources (texture and projection mapping modes) |
|||
TAB | Select next source (no need to use the source selection interface) |
|||
Arrow keys | Move selection. If no surface is selected in the projection mapping mode, all surfaces are moved. |
|||
\/ | Toggle 1px/10px steps for keyboard moves on Raspberry Pi |
|||
|
|||
## Notes on Video Encoding |
|||
|
|||
Easiest way to achieve success is to use [HandBrake](https://handbrake.fr/) with the following settings. This will produce a `.mkv` file with 16bit FLAC audio with 22.05KHz sampling rate. |
|||
|
|||
``` |
|||
Preset: Fast 720p30 |
|||
Summary / Format: MKV File |
|||
Video / Framerate: Same as source |
|||
Video / Profile: Baseline |
|||
Audio / Codec: FLAC 16-bit |
|||
Audio / Samplerate: 22.05 |
|||
``` |
|||
|
|||
If you are familiar with [ffmpeg](http://ffmpeg.org/), use the following. It will produce a `.mov` file. PCM audio codec with 22KHz sampling rate is used. |
|||
|
|||
``` |
|||
ffmpeg -i input-video.mp4 -s 1280x720 -aspect 16:9 \ |
|||
-c:v libx264 -profile:v baseline \ |
|||
-c:a pcm_s16le -ar 22000 -ac 2 \ |
|||
output-video.mov |
|||
``` |
|||
|
|||
These two settings have shown the best results so far. Audio problems and video playback at the beginning of longer video files was the main issue in most cases. Please open an issue if you have better suggestions. |
|||
|
|||
## Extended Functionality |
|||
|
|||
Examples represent extended functionality of ofxPiMapper. Enter each example separately to find out more. |
|||
|
|||
- [Basic Example](example_basic). |
|||
- [FBO Sources Example](example_fbo-sources). |
|||
- [Camera Example](example_camera). |
|||
- [Remote Control Server](example_remote-server) example. |
|||
- [Remote Control Client](example_remote-client) example. |
|||
- Readme's for the rest are cooking... |
|||
|
|||
## Problems with Audio |
|||
|
|||
If you are having problems with audio playback, here are two steps for you. Before you do these, make sure audio of your video file works. |
|||
|
|||
|
|||
### Step 1 |
|||
|
|||
Open example openFrameworks application `ofApp.cpp` file in a text editor. |
|||
|
|||
``` |
|||
cd /home/pi/openFrameworks/addons/ofxPiMapper/example |
|||
nano src/ofApp.cpp |
|||
``` |
|||
|
|||
Make sure that the following line looks as follows. |
|||
|
|||
``` |
|||
ofx::piMapper::VideoSource::enableAudio = true; |
|||
``` |
|||
|
|||
Save the file (CTRL + X, Y and ENTER). Recompile and run the example. |
|||
|
|||
``` |
|||
make && make run |
|||
``` |
|||
|
|||
### Step 2 |
|||
|
|||
If the sound still does not work, try to use `raspi-config`. |
|||
|
|||
``` |
|||
sudo raspi-config |
|||
``` |
|||
|
|||
Select "7 Advanced Options" and "A9 Audio" then "0 Auto". You can use one of the force options if you want to be 100% sure. |
|||
|
|||
Open alsamixer. |
|||
|
|||
``` |
|||
alsamixer |
|||
``` |
|||
|
|||
Set the volume to a value between 90 to 100 by using the arrow keys. ESC to exit the mixer. |
|||
|
|||
Launch ofxPiMapper example, select a surface and set a video source with audio. Should work. |
|||
|
|||
|
|||
## Development |
|||
|
|||
Keeping it simple. Developing ofxPiMapper master branch against the latest stable release version of openFrameworks. |
|||
|
|||
|
|||
## Licence |
|||
|
|||
ofxPiMapper is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). See the [LICENSE](LICENSE.md) file for further details. Just add my name somewhere along your project [Krisjanis Rijnieks](https://rijnieks.com) whenever possible. |
|||
|
|||
|
|||
## Supporters |
|||
|
|||
You can become a supporter by donating BitCoins, via PayPal or becoming a Patreon. Please check https://ofxpimapper.com for details. List of supporters below. |
|||
|
|||
- [Marc-André Gasser](https://www.magdesign.ch/) |
|||
- Manuel Meißner |
|||
|
|||
|
|||
## Dependencies |
|||
|
|||
Before moving on, make sure that you have all the dependencies installed. |
|||
|
|||
- ofxGui (available in oF by default) |
|||
- ofxXmlSettings (available in oF by default) |
|||
- [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) (needed only on Raspberry Pi) |
|||
|
|||
To install dependencies, `cd` into `openFrameworks/addons` directory and execute the following: |
|||
|
|||
```bash |
|||
git clone https://github.com/jvcleave/ofxOMXPlayer.git |
|||
``` |
|||
|
|||
The `ofxOMXPlayer` addon recommends you to use its releases. Currently the latest release is `0.9.0-compatible`. To checkout the code of the relase, go to the `ofxOMXPlayer` addon directory and checkout the relase. |
|||
|
|||
``` |
|||
cd openFrameworks/addons/ofxOMXPlayer |
|||
git checkout 0.9.0-compatible |
|||
``` |
|||
|
|||
You can check the latest releases on the [ofxOMXPlayer GitHub repository](https://github.com/jvcleave/ofxOMXPlayer/releases). |
|||
# ofxPiMapper |
|||
|
|||
[](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Alinux) |
|||
[](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Awindows) |
|||
[](https://github.com/kr15h/ofxPiMapper/actions?query=workflow%3Aosx) |
|||
|
|||
Projection mapping addon for openFrameworks that runs on the Raspberry Pi. It has been tested against openFrameworks version (0.11.0). |
|||
|
|||
The project started as master's thesis project by [Krisjanis Rijnieks](https://rijnieks.com) at the [Aalto Media Lab](https://www.aalto.fi/en/aalto-media-lab). Currently being developed during free time. Please [donate](https://ofxpimapper.com/) to create more free time. |
|||
|
|||
Note on build status: GitHub Actions ubuntu-latest, windows-latest and osx-latest images with 64bit environments are used. To be reviewed. |
|||
|
|||
## Disk Image |
|||
|
|||
For those not using openFrameworks, there is a precompiled disk image available via [ofxPiMapper website](https://ofxpimapper.com). It works with Raspberry Pi up until version 3B+ (with the older BCM2837 chip). Given the recent growing interest in the project, some effort is being put into figuring out how to make the disk image to work on Pi 4 and Pi 5 (and Pi 3B+ with the more recent BCM2837B0 chip). Please [donate](https://ofxpimapper.com/) to increase the frequency and duration of these efforts. |
|||
|
|||
> **Warning!** It does not work on the latest generation of Raspberry Pi 3B+ with the BCM2837B0 chip. Make sure the Pi has the older BCM2837 chip when purchasing. |
|||
|
|||
## Introduction |
|||
|
|||
This repository contains the addon for [openFrameworks](https://openframeworks.cc). It is expected to be used as an extension for your custom openFrameworks project where you create a custom [FBO source](example_fbo-sources) that is being animated by an advanced process rather than a plain video. |
|||
|
|||
If you are planning to use videos and images only, consider using the precompiled Raspberry Pi image available from the [ofxPiMapper website](https://ofxpimapper.com). It is based on a recent Raspberry Pi OS disk image and contains compiled installation of openFrameworks along with all the scripts and services that make Pi Mapper start automatically. |
|||
|
|||
## Installation |
|||
|
|||
Clone or download the repository to your openFrameworks addons folder. Make sure that default openFrameworks examples compile and run before trying ofxPiMapper examples. There are a few things that you should do depending on if you are compiling on the Raspberry Pi or not. |
|||
|
|||
- Raspberry Pi |
|||
Please install the [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) addon before compiling. |
|||
- Windows MSYS2 |
|||
Go to `patches/msys2` directory and run `./patch.sh` |
|||
- Other platforms |
|||
Please rename the `addons.make.rpi` file to `addons.make`. |
|||
|
|||
To test, use Terminal to change the directory to `example_basic`, compile and run. |
|||
|
|||
``` |
|||
cd path/to/openFrameworks/addons/ofxPiMapper/example_basic |
|||
make |
|||
cd bin |
|||
./example_basic |
|||
``` |
|||
|
|||
If you plan to use `example_remote-server` and `example_remote-client`, make sure that you have added [ofxJSON](https://github.com/jeffcrouse/ofxJSON) dependency to your `openFrameworks/addons` folder prior compilation. |
|||
|
|||
## Usage |
|||
|
|||
Currently a keyboard and a mouse has to be used in order to do the mapping with ofxPiMapper. |
|||
|
|||
|
|||
### Modes |
|||
|
|||
PiMapper has 4 modes: |
|||
|
|||
1. Presentation mode |
|||
2. Texture mapping mode |
|||
3. Surface editing mode |
|||
4. Source assignment mode |
|||
|
|||
You can access these modes by pressing 1, 2, 3 or 4 respectively. |
|||
|
|||
|
|||
#### Presentation mode |
|||
|
|||
This mode is activated once the application starts up. It does not show anything else except the final projection mapping as it was saved previously. |
|||
|
|||
|
|||
#### Texture mapping mode |
|||
|
|||
In this mode you can adjust the texture coordinates of the surface you have selected in the surface editing mode. |
|||
|
|||
|
|||
#### Surface editing mode |
|||
|
|||
Here you can select, move and distort the surfaces you have created. |
|||
|
|||
|
|||
#### Source assignment mode |
|||
|
|||
After you select a surface in surface editing mode, activate this mode to be able to choose a source for the surface. Afterwards you might want to go to the texture mapping mode to adjust texture coordinates. |
|||
|
|||
|
|||
### Other shortcuts |
|||
|
|||
These other shortcuts that you can use while using the example app. |
|||
|
|||
Key | Function |
|||
:--- | :--- |
|||
1 | Presentation mode |
|||
2 | Texture editing mode |
|||
3 | Projection mapping mode, use this to select a surface first |
|||
4 | Source selection mode |
|||
i | Show info |
|||
t | Add triangle surface |
|||
q | Add quad surface |
|||
g | Add grid warp surface |
|||
c | Add circle surface |
|||
d | Duplicate selected surface |
|||
\+ | Scale surface up |
|||
\- | Scale surface down |
|||
p | Toggle perspective warping (quad surfaces only) |
|||
F | Expand selected surface to fill the screen (quad surfaces only) |
|||
] | Add columns to grid surface (grid warp surfaces only) |
|||
[ | Remove columns from grid surface (grid warp surfaces only) |
|||
} | Add rows to grid surface (grid warp surfaces only) |
|||
{ | Remove rows from grid surface (grid warp surfaces only) |
|||
. | Select next surface (projection mapping mode only) |
|||
, | Select previous surface (projection mapping mode only) |
|||
\> | Select next vertex |
|||
\< | Select previous vertex |
|||
0 | Move selected surface one layer up |
|||
9 | Move selected surface one layer down |
|||
s | Save composition |
|||
l | Hide/show layer panel |
|||
z | Undo |
|||
rbt | Reboot (Raspberry Pi only) |
|||
sdn | Shutdown (Raspberry Pi only) |
|||
new | Clear composition (remove all surfaces) |
|||
ext | Exit application and return to command line |
|||
BACKSPACE ('\' via SSH) | Delete surface. |
|||
SPACE | Toggle pause for video sources (texture and projection mapping modes) |
|||
TAB | Select next source (no need to use the source selection interface) |
|||
Arrow keys | Move selection. If no surface is selected in the projection mapping mode, all surfaces are moved. |
|||
\/ | Toggle 1px/10px steps for keyboard moves on Raspberry Pi |
|||
|
|||
## Notes on Video Encoding |
|||
|
|||
Easiest way to achieve success is to use [HandBrake](https://handbrake.fr/) with the following settings. This will produce a `.mkv` file with 16bit FLAC audio with 22.05KHz sampling rate. |
|||
|
|||
``` |
|||
Preset: Fast 720p30 |
|||
Summary / Format: MKV File |
|||
Video / Framerate: Same as source |
|||
Video / Profile: Baseline |
|||
Audio / Codec: FLAC 16-bit |
|||
Audio / Samplerate: 22.05 |
|||
``` |
|||
|
|||
If you are familiar with [ffmpeg](http://ffmpeg.org/), use the following. It will produce a `.mov` file. PCM audio codec with 22KHz sampling rate is used. |
|||
|
|||
``` |
|||
ffmpeg -i input-video.mp4 -s 1280x720 -aspect 16:9 \ |
|||
-c:v libx264 -profile:v baseline \ |
|||
-c:a pcm_s16le -ar 22000 -ac 2 \ |
|||
output-video.mov |
|||
``` |
|||
|
|||
These two settings have shown the best results so far. Audio problems and video playback at the beginning of longer video files was the main issue in most cases. Please open an issue if you have better suggestions. |
|||
|
|||
## Extended Functionality |
|||
|
|||
Examples represent extended functionality of ofxPiMapper. Enter each example separately to find out more. |
|||
|
|||
- [Basic Example](example_basic). |
|||
- [FBO Sources Example](example_fbo-sources). |
|||
- [Camera Example](example_camera). |
|||
- [Remote Control Server](example_remote-server) example. |
|||
- [Remote Control Client](example_remote-client) example. |
|||
- Readme's for the rest are cooking... |
|||
|
|||
## Problems with Audio |
|||
|
|||
If you are having problems with audio playback, here are two steps for you. Before you do these, make sure audio of your video file works. |
|||
|
|||
|
|||
### Step 1 |
|||
|
|||
Open example openFrameworks application `ofApp.cpp` file in a text editor. |
|||
|
|||
``` |
|||
cd /home/pi/openFrameworks/addons/ofxPiMapper/example |
|||
nano src/ofApp.cpp |
|||
``` |
|||
|
|||
Make sure that the following line looks as follows. |
|||
|
|||
``` |
|||
ofx::piMapper::VideoSource::enableAudio = true; |
|||
``` |
|||
|
|||
Save the file (CTRL + X, Y and ENTER). Recompile and run the example. |
|||
|
|||
``` |
|||
make && make run |
|||
``` |
|||
|
|||
### Step 2 |
|||
|
|||
If the sound still does not work, try to use `raspi-config`. |
|||
|
|||
``` |
|||
sudo raspi-config |
|||
``` |
|||
|
|||
Select "7 Advanced Options" and "A9 Audio" then "0 Auto". You can use one of the force options if you want to be 100% sure. |
|||
|
|||
Open alsamixer. |
|||
|
|||
``` |
|||
alsamixer |
|||
``` |
|||
|
|||
Set the volume to a value between 90 to 100 by using the arrow keys. ESC to exit the mixer. |
|||
|
|||
Launch ofxPiMapper example, select a surface and set a video source with audio. Should work. |
|||
|
|||
|
|||
## Development |
|||
|
|||
Keeping it simple. Developing ofxPiMapper master branch against the latest stable release version of openFrameworks. |
|||
|
|||
|
|||
## Licence |
|||
|
|||
ofxPiMapper is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). See the [LICENSE](LICENSE.md) file for further details. Just add my name somewhere along your project [Krisjanis Rijnieks](https://rijnieks.com) whenever possible. |
|||
|
|||
|
|||
## Supporters |
|||
|
|||
You can become a supporter by donating BitCoins, via PayPal or becoming a Patreon. Please check https://ofxpimapper.com for details. List of supporters below. |
|||
|
|||
- [Marc-André Gasser](https://www.magdesign.ch/) |
|||
- Manuel Meißner |
|||
|
|||
|
|||
## Dependencies |
|||
|
|||
Before moving on, make sure that you have all the dependencies installed. |
|||
|
|||
- ofxGui (available in oF by default) |
|||
- ofxXmlSettings (available in oF by default) |
|||
- [ofxOMXPlayer](https://github.com/jvcleave/ofxOMXPlayer) (needed only on Raspberry Pi) |
|||
|
|||
To install dependencies, `cd` into `openFrameworks/addons` directory and execute the following: |
|||
|
|||
```bash |
|||
git clone https://github.com/jvcleave/ofxOMXPlayer.git |
|||
``` |
|||
|
|||
The `ofxOMXPlayer` addon recommends you to use its releases. Currently the latest release is `0.9.0-compatible`. To checkout the code of the relase, go to the `ofxOMXPlayer` addon directory and checkout the relase. |
|||
|
|||
``` |
|||
cd openFrameworks/addons/ofxOMXPlayer |
|||
git checkout 0.9.0-compatible |
|||
``` |
|||
|
|||
You can check the latest releases on the [ofxOMXPlayer GitHub repository](https://github.com/jvcleave/ofxOMXPlayer/releases). |
|||
|
@ -1,76 +1,76 @@ |
|||
# All variables and this file are optional, if they are not present the PG and the
|
|||
# makefiles will try to parse the correct values from the file system.
|
|||
#
|
|||
# Variables that specify exclusions can use % as a wildcard to specify that anything in
|
|||
# that position will match. A partial path can also be specified to, for example, exclude
|
|||
# a whole folder from the parsed paths from the file system
|
|||
#
|
|||
# Variables can be specified using = or +=
|
|||
# = will clear the contents of that variable both specified from the file or the ones parsed
|
|||
# from the file system
|
|||
# += will add the values to the previous ones in the file or the ones parsed from the file
|
|||
# system
|
|||
#
|
|||
# The PG can be used to detect errors in this file, just create a new project with this addon
|
|||
# and the PG will write to the console the kind of error and in which line it is
|
|||
|
|||
meta: |
|||
ADDON_NAME = ofxPiMapper |
|||
ADDON_DESCRIPTION = Projection mapping addon for openFrameworks |
|||
ADDON_AUTHOR = @kr15h |
|||
ADDON_TAGS = "addon" "rpi" "mapping" |
|||
ADDON_URL = http://github.com/kr15h/ofxPiMapper |
|||
|
|||
common: |
|||
# dependencies with other addons, a list of them separated by spaces
|
|||
# or use += in several lines
|
|||
ADDON_DEPENDENCIES = ofxXmlSettings ofxGui |
|||
|
|||
# include search paths, this will be usually parsed from the file system
|
|||
# but if the addon or addon libraries need special search paths they can be
|
|||
# specified here separated by spaces or one per line using +=
|
|||
# ADDON_INCLUDES =
|
|||
|
|||
# any special flag that should be passed to the compiler when using this
|
|||
# addon
|
|||
# ADDON_CFLAGS =
|
|||
|
|||
# any special flag that should be passed to the linker when using this
|
|||
# addon, also used for system libraries with -lname
|
|||
# ADDON_LDFLAGS =
|
|||
|
|||
# linux only, any library that should be included in the project using
|
|||
# pkg-config
|
|||
# ADDON_PKG_CONFIG_LIBRARIES =
|
|||
|
|||
# osx/iOS only, any framework that should be included in the project
|
|||
# ADDON_FRAMEWORKS =
|
|||
|
|||
# source files, these will be usually parsed from the file system looking
|
|||
# in the src folders in libs and the root of the addon. if your addon needs
|
|||
# to include files in different places or a different set of files per platform
|
|||
# they can be specified here
|
|||
# ADDON_SOURCES =
|
|||
|
|||
# some addons need resources to be copied to the bin/data folder of the project
|
|||
# specify here any files that need to be copied, you can use wildcards like * and ?
|
|||
# ADDON_DATA =
|
|||
|
|||
# when parsing the file system looking for libraries exclude this for all or
|
|||
# a specific platform
|
|||
# ADDON_LIBS_EXCLUDE =
|
|||
|
|||
linux64: |
|||
# binary libraries, these will be usually parsed from the file system but some
|
|||
# libraries need to passed to the linker in a specific order
|
|||
ADDON_LIBS = |
|||
linux: |
|||
ADDON_LIBS = |
|||
win_cb: |
|||
ADDON_LIBS = |
|||
linuxarmv6l: |
|||
ADDON_LIBS = |
|||
linuxarmv7l: |
|||
ADDON_LIBS = |
|||
android/armeabi: |
|||
ADDON_LIBS = |
|||
# All variables and this file are optional, if they are not present the PG and the
|
|||
# makefiles will try to parse the correct values from the file system.
|
|||
#
|
|||
# Variables that specify exclusions can use % as a wildcard to specify that anything in
|
|||
# that position will match. A partial path can also be specified to, for example, exclude
|
|||
# a whole folder from the parsed paths from the file system
|
|||
#
|
|||
# Variables can be specified using = or +=
|
|||
# = will clear the contents of that variable both specified from the file or the ones parsed
|
|||
# from the file system
|
|||
# += will add the values to the previous ones in the file or the ones parsed from the file
|
|||
# system
|
|||
#
|
|||
# The PG can be used to detect errors in this file, just create a new project with this addon
|
|||
# and the PG will write to the console the kind of error and in which line it is
|
|||
|
|||
meta: |
|||
ADDON_NAME = ofxPiMapper |
|||
ADDON_DESCRIPTION = Projection mapping addon for openFrameworks |
|||
ADDON_AUTHOR = @kr15h |
|||
ADDON_TAGS = "addon" "rpi" "mapping" |
|||
ADDON_URL = http://github.com/kr15h/ofxPiMapper |
|||
|
|||
common: |
|||
# dependencies with other addons, a list of them separated by spaces
|
|||
# or use += in several lines
|
|||
ADDON_DEPENDENCIES = ofxXmlSettings ofxGui |
|||
|
|||
# include search paths, this will be usually parsed from the file system
|
|||
# but if the addon or addon libraries need special search paths they can be
|
|||
# specified here separated by spaces or one per line using +=
|
|||
# ADDON_INCLUDES =
|
|||
|
|||
# any special flag that should be passed to the compiler when using this
|
|||
# addon
|
|||
# ADDON_CFLAGS =
|
|||
|
|||
# any special flag that should be passed to the linker when using this
|
|||
# addon, also used for system libraries with -lname
|
|||
# ADDON_LDFLAGS =
|
|||
|
|||
# linux only, any library that should be included in the project using
|
|||
# pkg-config
|
|||
# ADDON_PKG_CONFIG_LIBRARIES =
|
|||
|
|||
# osx/iOS only, any framework that should be included in the project
|
|||
# ADDON_FRAMEWORKS =
|
|||
|
|||
# source files, these will be usually parsed from the file system looking
|
|||
# in the src folders in libs and the root of the addon. if your addon needs
|
|||
# to include files in different places or a different set of files per platform
|
|||
# they can be specified here
|
|||
# ADDON_SOURCES =
|
|||
|
|||
# some addons need resources to be copied to the bin/data folder of the project
|
|||
# specify here any files that need to be copied, you can use wildcards like * and ?
|
|||
# ADDON_DATA =
|
|||
|
|||
# when parsing the file system looking for libraries exclude this for all or
|
|||
# a specific platform
|
|||
# ADDON_LIBS_EXCLUDE =
|
|||
|
|||
linux64: |
|||
# binary libraries, these will be usually parsed from the file system but some
|
|||
# libraries need to passed to the linker in a specific order
|
|||
ADDON_LIBS = |
|||
linux: |
|||
ADDON_LIBS = |
|||
win_cb: |
|||
ADDON_LIBS = |
|||
linuxarmv6l: |
|||
ADDON_LIBS = |
|||
linuxarmv7l: |
|||
ADDON_LIBS = |
|||
android/armeabi: |
|||
ADDON_LIBS = |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,7 +1,7 @@ |
|||
# Basic Example |
|||
|
|||
This is a very basic example. It shows how to use ofxPiMapper addon with it's integrated functionality. You can map images and videos with this. ofxPiMapper takes care of loading and saving your composition. |
|||
|
|||
For now you have to put your sources under `bin/data/sources`. There are two directories: `images` and `videos`. As you may expect, put images in the `images` folder and videos in the `videos` one. |
|||
|
|||
The addon is made so that you have to pass the keyboard and mouse events to it. It is because in this way you can gain more control over how it behaves. If you do not pass the keyboard and mouse events, ofxPiMapper reads the configuration file from `data/ofxpimapper.xml` and continues working from there. It just starts up, loads the configuration and displays the composition until the application quits. |
|||
# Basic Example |
|||
|
|||
This is a very basic example. It shows how to use ofxPiMapper addon with it's integrated functionality. You can map images and videos with this. ofxPiMapper takes care of loading and saving your composition. |
|||
|
|||
For now you have to put your sources under `bin/data/sources`. There are two directories: `images` and `videos`. As you may expect, put images in the `images` folder and videos in the `videos` one. |
|||
|
|||
The addon is made so that you have to pass the keyboard and mouse events to it. It is because in this way you can gain more control over how it behaves. If you do not pass the keyboard and mouse events, ofxPiMapper reads the configuration file from `data/ofxpimapper.xml` and continues working from there. It just starts up, loads the configuration and displays the composition until the application quits. |
|||
|
@ -1,4 +1,4 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
|
@ -1,3 +1,3 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,36 +1,203 @@ |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>512.000000000</x> |
|||
<y>50.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>974.000000000</x> |
|||
<y>718.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>50.000000000</x> |
|||
<y>718.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>video</source-type> |
|||
<source-name>gene-nsynthesis-loop-a.mp4</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>452.000000000</x> |
|||
<y>221.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1017.744750977</x> |
|||
<y>744.464965820</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>6.254730225</x> |
|||
<y>744.464965820</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>video</source-type> |
|||
<source-name>gene-nsynthesis-loop-c.mp4</source-name> |
|||
<source-loop>1</source-loop> |
|||
</source> |
|||
</surface> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>512.000000000</x> |
|||
<y>50.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>974.000000000</x> |
|||
<y>718.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>50.000000000</x> |
|||
<y>718.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>video</source-type> |
|||
<source-name>gene-nsynthesis-loop-a.mp4</source-name> |
|||
<source-loop>1</source-loop> |
|||
</source> |
|||
</surface> |
|||
<surface type="2"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>-8.000000000</x> |
|||
<y>6.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>434.000000000</x> |
|||
<y>250.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>920.000000000</x> |
|||
<y>101.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>-4.000000000</x> |
|||
<y>397.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>508.000000000</x> |
|||
<y>385.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>920.000000000</x> |
|||
<y>385.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>2.254730225</x> |
|||
<y>745.464965820</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>508.000000000</x> |
|||
<y>669.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>920.000000000</x> |
|||
<y>669.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.500000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.500000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.500000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>none</source-type> |
|||
<source-name>none</source-name> |
|||
</source> |
|||
<properties> |
|||
<gridCols>2</gridCols> |
|||
<gridRows>2</gridRows> |
|||
</properties> |
|||
</surface> |
|||
<surface type="5"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>267.996795654</x> |
|||
<y>22.747558594</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>267.996795654</x> |
|||
<y>147.252563477</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>434.003723145</x> |
|||
<y>147.252563477</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>434.003723145</x> |
|||
<y>22.747558594</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>none</source-type> |
|||
<source-name>none</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,7 +1,7 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1024,768,OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1024,768,OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
|
@ -1,38 +1,38 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
mapper.setup(); |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofSetFullscreen(true); |
|||
#endif |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
mapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
mapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
mapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
mapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
mapper.mouseDragged(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
mapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
mapper.mouseReleased(x, y, button); |
|||
} |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
mapper.setup(); |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofSetFullscreen(true); |
|||
#endif |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
mapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
mapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
mapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
mapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
mapper.mouseDragged(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
mapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
mapper.mouseReleased(x, y, button); |
|||
} |
|||
|
@ -1,25 +1,25 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
// We need to forward key and mouse events to ofxPiMapper.
|
|||
// By not doing it we have the opportunity to use ofxPiMapper
|
|||
// witout the interface.
|
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mouseDragged(int x, int y, int button); |
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
|
|||
// This is our mapper object.
|
|||
ofxPiMapper mapper; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
// We need to forward key and mouse events to ofxPiMapper.
|
|||
// By not doing it we have the opportunity to use ofxPiMapper
|
|||
// witout the interface.
|
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mouseDragged(int x, int y, int button); |
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
|
|||
// This is our mapper object.
|
|||
ofxPiMapper mapper; |
|||
}; |
|||
|
@ -1,5 +1,5 @@ |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,9 +1,9 @@ |
|||
# Camera Example |
|||
|
|||
This example demonstrates the possibility to use camera input as a texture source. Make sure you clone the [ofxRPiCameraVideoGrabber](https://github.com/jvcleave/ofxRPiCameraVideoGrabber) addon into your `openFrameworks/addons` folder before compiling on Raspberry Pi. |
|||
|
|||
``` |
|||
cd openFrameworks/addons |
|||
git clone https://github.com/jvcleave/ofxRPiCameraVideoGrabber.git |
|||
``` |
|||
|
|||
# Camera Example |
|||
|
|||
This example demonstrates the possibility to use camera input as a texture source. Make sure you clone the [ofxRPiCameraVideoGrabber](https://github.com/jvcleave/ofxRPiCameraVideoGrabber) addon into your `openFrameworks/addons` folder before compiling on Raspberry Pi. |
|||
|
|||
``` |
|||
cd openFrameworks/addons |
|||
git clone https://github.com/jvcleave/ofxRPiCameraVideoGrabber.git |
|||
``` |
|||
|
|||
|
@ -1,5 +1,5 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxRPiCameraVideoGrabber |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxRPiCameraVideoGrabber |
|||
|
@ -1,3 +1,3 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,36 +1,36 @@ |
|||
<surfaces> |
|||
<surface> |
|||
<vertices> |
|||
<vertex> |
|||
<x>415.000000000</x> |
|||
<y>51.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>581.000000000</x> |
|||
<y>388.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>183.000000000</x> |
|||
<y>357.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.556249976</x> |
|||
<y>0.108333334</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.862500012</x> |
|||
<y>0.941666663</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.118749999</x> |
|||
<y>0.862500012</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Camera Source</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface> |
|||
<vertices> |
|||
<vertex> |
|||
<x>415.000000000</x> |
|||
<y>51.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>581.000000000</x> |
|||
<y>388.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>183.000000000</x> |
|||
<y>357.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.556249976</x> |
|||
<y>0.108333334</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.862500012</x> |
|||
<y>0.941666663</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.118749999</x> |
|||
<y>0.862500012</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Camera Source</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,70 +1,70 @@ |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>437.000000000</x> |
|||
<y>82.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>991.000000000</x> |
|||
<y>75.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>750.000000000</x> |
|||
<y>485.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.351562500</x> |
|||
<y>0.072222225</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.857812524</x> |
|||
<y>0.125000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.549218774</x> |
|||
<y>0.695833325</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Camera Source</source-name> |
|||
</source> |
|||
</surface> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>437.000000000</x> |
|||
<y>82.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>750.000000000</x> |
|||
<y>485.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>112.000000000</x> |
|||
<y>476.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.341406256</x> |
|||
<y>0.073611110</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.557031274</x> |
|||
<y>0.690277755</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.064843751</x> |
|||
<y>0.558333337</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Camera Source</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>437.000000000</x> |
|||
<y>82.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>991.000000000</x> |
|||
<y>75.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>750.000000000</x> |
|||
<y>485.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.351562500</x> |
|||
<y>0.072222225</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.857812524</x> |
|||
<y>0.125000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.549218774</x> |
|||
<y>0.695833325</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Camera Source</source-name> |
|||
</source> |
|||
</surface> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>437.000000000</x> |
|||
<y>82.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>750.000000000</x> |
|||
<y>485.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>112.000000000</x> |
|||
<y>476.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.341406256</x> |
|||
<y>0.073611110</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.557031274</x> |
|||
<y>0.690277755</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.064843751</x> |
|||
<y>0.558333337</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Camera Source</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,62 +1,62 @@ |
|||
#include "CameraSource.h" |
|||
|
|||
CameraSource::CameraSource(){ |
|||
name = "Camera Source"; |
|||
|
|||
_cameraWidth = 1280; |
|||
_cameraHeight = 720; |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
_omxCameraSettings.width = _cameraWidth; |
|||
_omxCameraSettings.height = _cameraHeight; |
|||
_omxCameraSettings.framerate = 30; |
|||
_omxCameraSettings.enableTexture = true; |
|||
_omxCameraSettings.doRecording = false; |
|||
|
|||
_videoGrabber.setup(_omxCameraSettings); |
|||
#else |
|||
std::vector<ofVideoDevice> devices = _videoGrabber.listDevices(); |
|||
_cameraFound = false; |
|||
|
|||
for(int i = 0; i < devices.size(); i++){ |
|||
if(devices[i].bAvailable){ |
|||
ofLogNotice() << devices[i].id << ": " << devices[i].deviceName; |
|||
_cameraFound = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(_cameraFound){ |
|||
_videoGrabber.setDeviceID(0); |
|||
_videoGrabber.setup(_cameraWidth, _cameraHeight); |
|||
} |
|||
#endif |
|||
|
|||
allocate(_cameraWidth, _cameraHeight); |
|||
} |
|||
|
|||
void CameraSource::update(){ |
|||
#ifndef TARGET_RASPBERRY_PI |
|||
if(_videoGrabber.isInitialized()){ |
|||
_videoGrabber.update(); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
void CameraSource::draw(){ |
|||
ofClear(0); |
|||
ofSetHexColor(0xffffff); |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofDisableNormalizedTexCoords(); |
|||
_videoGrabber.draw(0, 0); |
|||
ofEnableNormalizedTexCoords(); |
|||
#else |
|||
if(_videoGrabber.isInitialized()){ |
|||
ofDisableNormalizedTexCoords(); |
|||
_videoGrabber.draw(0, 0); |
|||
ofEnableNormalizedTexCoords(); |
|||
}else{ |
|||
ofDrawBitmapString("no camera", _cameraWidth / 2.0f - 40.0f, _cameraHeight / 2.0f + 10.0f); |
|||
} |
|||
#endif |
|||
} |
|||
#include "CameraSource.h" |
|||
|
|||
CameraSource::CameraSource(){ |
|||
name = "Camera Source"; |
|||
|
|||
_cameraWidth = 1280; |
|||
_cameraHeight = 720; |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
_omxCameraSettings.width = _cameraWidth; |
|||
_omxCameraSettings.height = _cameraHeight; |
|||
_omxCameraSettings.framerate = 30; |
|||
_omxCameraSettings.enableTexture = true; |
|||
_omxCameraSettings.doRecording = false; |
|||
|
|||
_videoGrabber.setup(_omxCameraSettings); |
|||
#else |
|||
std::vector<ofVideoDevice> devices = _videoGrabber.listDevices(); |
|||
_cameraFound = false; |
|||
|
|||
for(int i = 0; i < devices.size(); i++){ |
|||
if(devices[i].bAvailable){ |
|||
ofLogNotice() << devices[i].id << ": " << devices[i].deviceName; |
|||
_cameraFound = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(_cameraFound){ |
|||
_videoGrabber.setDeviceID(0); |
|||
_videoGrabber.setup(_cameraWidth, _cameraHeight); |
|||
} |
|||
#endif |
|||
|
|||
allocate(_cameraWidth, _cameraHeight); |
|||
} |
|||
|
|||
void CameraSource::update(){ |
|||
#ifndef TARGET_RASPBERRY_PI |
|||
if(_videoGrabber.isInitialized()){ |
|||
_videoGrabber.update(); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
void CameraSource::draw(){ |
|||
ofClear(0); |
|||
ofSetHexColor(0xffffff); |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofDisableNormalizedTexCoords(); |
|||
_videoGrabber.draw(0, 0); |
|||
ofEnableNormalizedTexCoords(); |
|||
#else |
|||
if(_videoGrabber.isInitialized()){ |
|||
ofDisableNormalizedTexCoords(); |
|||
_videoGrabber.draw(0, 0); |
|||
ofEnableNormalizedTexCoords(); |
|||
}else{ |
|||
ofDrawBitmapString("no camera", _cameraWidth / 2.0f - 40.0f, _cameraHeight / 2.0f + 10.0f); |
|||
} |
|||
#endif |
|||
} |
|||
|
@ -1,34 +1,34 @@ |
|||
/*
|
|||
* CameraSource |
|||
* Camera source for ofxPiMapper |
|||
* Created by Krisjanis Rijnieks on 25/01/2016 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
#include "ofxRPiCameraVideoGrabber.h" |
|||
#endif |
|||
|
|||
class CameraSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
CameraSource(); |
|||
|
|||
void update(); |
|||
void draw(); |
|||
|
|||
private: |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
OMXCameraSettings _omxCameraSettings; |
|||
ofxRPiCameraVideoGrabber _videoGrabber; |
|||
#else |
|||
ofVideoGrabber _videoGrabber; |
|||
#endif |
|||
int _cameraWidth; |
|||
int _cameraHeight; |
|||
bool _cameraFound; |
|||
/*
|
|||
* CameraSource |
|||
* Camera source for ofxPiMapper |
|||
* Created by Krisjanis Rijnieks on 25/01/2016 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
#include "ofxRPiCameraVideoGrabber.h" |
|||
#endif |
|||
|
|||
class CameraSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
CameraSource(); |
|||
|
|||
void update(); |
|||
void draw(); |
|||
|
|||
private: |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
OMXCameraSettings _omxCameraSettings; |
|||
ofxRPiCameraVideoGrabber _videoGrabber; |
|||
#else |
|||
ofVideoGrabber _videoGrabber; |
|||
#endif |
|||
int _cameraWidth; |
|||
int _cameraHeight; |
|||
bool _cameraFound; |
|||
}; |
@ -1,24 +1,24 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
int main(int argc, char * argv[]){ |
|||
bool fullscreen = false; |
|||
|
|||
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc); |
|||
for(int i = 0; i < arguments.size(); ++i){ |
|||
if(arguments.at(i) == "-f"){ |
|||
fullscreen = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(fullscreen){ |
|||
ofSetupOpenGL(800, 450, OF_FULLSCREEN); |
|||
}else{ |
|||
ofSetupOpenGL(800, 450, OF_WINDOW); |
|||
} |
|||
|
|||
ofRunApp(new ofApp()); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
int main(int argc, char * argv[]){ |
|||
bool fullscreen = false; |
|||
|
|||
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc); |
|||
for(int i = 0; i < arguments.size(); ++i){ |
|||
if(arguments.at(i) == "-f"){ |
|||
fullscreen = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(fullscreen){ |
|||
ofSetupOpenGL(800, 450, OF_FULLSCREEN); |
|||
}else{ |
|||
ofSetupOpenGL(800, 450, OF_WINDOW); |
|||
} |
|||
|
|||
ofRunApp(new ofApp()); |
|||
} |
|||
|
@ -1,36 +1,36 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
cameraSource = new CameraSource(); |
|||
piMapper.registerFboSource(*cameraSource); |
|||
piMapper.setup(); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
piMapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
piMapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
piMapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
piMapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
piMapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
piMapper.mouseDragged(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
piMapper.mouseReleased(x, y, button); |
|||
} |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
cameraSource = new CameraSource(); |
|||
piMapper.registerFboSource(*cameraSource); |
|||
piMapper.setup(); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
piMapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
piMapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
piMapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
piMapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
piMapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
piMapper.mouseDragged(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
piMapper.mouseReleased(x, y, button); |
|||
} |
|||
|
@ -1,31 +1,31 @@ |
|||
/*
|
|||
* CameraSource example |
|||
* Can be used with the Raspberry Pi camera module or the Auvidea HDMI bridge. |
|||
* B101 HDMI to CSI-2 Bridge (15 pin FPC). |
|||
* Available at http://www.auvidea.eu/index.php/theme-styles/2014-12-30-22-32-06/b101
|
|||
* Created by Krisjanis Rijnieks on 25/01/2016 |
|||
* Last modified on 10/02/2016 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "CameraSource.h" |
|||
|
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
|
|||
ofxPiMapper piMapper; |
|||
CameraSource * cameraSource; |
|||
/*
|
|||
* CameraSource example |
|||
* Can be used with the Raspberry Pi camera module or the Auvidea HDMI bridge. |
|||
* B101 HDMI to CSI-2 Bridge (15 pin FPC). |
|||
* Available at http://www.auvidea.eu/index.php/theme-styles/2014-12-30-22-32-06/b101
|
|||
* Created by Krisjanis Rijnieks on 25/01/2016 |
|||
* Last modified on 10/02/2016 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "CameraSource.h" |
|||
|
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
|
|||
ofxPiMapper piMapper; |
|||
CameraSource * cameraSource; |
|||
}; |
@ -1,5 +1,5 @@ |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,28 +1,28 @@ |
|||
# FBO Sources Example |
|||
|
|||
This example shows how to use custom (FBO) source functionality with ofxPiMapper. Below you can see a list of custom sources and feel free to add your own via pull requests! |
|||
|
|||
- ScanlineSource |
|||
- SlideShowSource |
|||
|
|||
To build your own source, one should start by extending the `FboSource` class. When the source is ready, it should be instantiated in the `ofApp` class and passed via `mapper.registerFboSource(...source)` function before the `mapper.setup()` call. This will make the source name to appear under **FBO Sources** category in the source selection mode. |
|||
|
|||
Look at the source code of the custom sources to understand how to build one, but essentially it is extending the `FboSource` class of `ofxPiMapper` and overriding the `setup()`, `update()` and `draw()` functions. |
|||
|
|||
In the `setup()` function you should set a name for your custom source. |
|||
|
|||
``` |
|||
name = "Name Your Source"; |
|||
``` |
|||
|
|||
Then you should set the dimensions of your source by using the `allocate()` function. |
|||
|
|||
``` |
|||
allocate(500, 500); |
|||
``` |
|||
|
|||
In the `draw()` of your custom `FboSource` you should decide whether you want the previous frame to be cleared from the gfx buffer or not. If you want to draw a fresh frame, use the `ofClear()` function. |
|||
|
|||
``` |
|||
ofClear(0); // Clear with black |
|||
``` |
|||
# FBO Sources Example |
|||
|
|||
This example shows how to use custom (FBO) source functionality with ofxPiMapper. Below you can see a list of custom sources and feel free to add your own via pull requests! |
|||
|
|||
- ScanlineSource |
|||
- SlideShowSource |
|||
|
|||
To build your own source, one should start by extending the `FboSource` class. When the source is ready, it should be instantiated in the `ofApp` class and passed via `mapper.registerFboSource(...source)` function before the `mapper.setup()` call. This will make the source name to appear under **FBO Sources** category in the source selection mode. |
|||
|
|||
Look at the source code of the custom sources to understand how to build one, but essentially it is extending the `FboSource` class of `ofxPiMapper` and overriding the `setup()`, `update()` and `draw()` functions. |
|||
|
|||
In the `setup()` function you should set a name for your custom source. |
|||
|
|||
``` |
|||
name = "Name Your Source"; |
|||
``` |
|||
|
|||
Then you should set the dimensions of your source by using the `allocate()` function. |
|||
|
|||
``` |
|||
allocate(500, 500); |
|||
``` |
|||
|
|||
In the `draw()` of your custom `FboSource` you should decide whether you want the previous frame to be cleared from the gfx buffer or not. If you want to draw a fresh frame, use the `ofClear()` function. |
|||
|
|||
``` |
|||
ofClear(0); // Clear with black |
|||
``` |
|||
|
@ -1,4 +1,4 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
|
@ -1,3 +1,3 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,15 +1,15 @@ |
|||
<magSlideShow> |
|||
<Width>800</Width> |
|||
<Height>600</Height> |
|||
<SlideDuration>2</SlideDuration> <!-- Optional default duration for each slide--> |
|||
<Loop> |
|||
<Type>NORMAL</Type> <!-- NONE | NORMAL | PING-PONG --> |
|||
<Count>0</Count> <!-- 0 = forever --> |
|||
</Loop> |
|||
<Transition> |
|||
<Type>Dissolve</Type> |
|||
<Duration>3</Duration> |
|||
</Transition> |
|||
<!-- NoResize | Native | Fit | FitProportionally | FillProportionally --> |
|||
<ResizeOption>FitProportionally</ResizeOption> |
|||
</magSlideShow> |
|||
<magSlideShow> |
|||
<Width>800</Width> |
|||
<Height>600</Height> |
|||
<SlideDuration>2</SlideDuration> <!-- Optional default duration for each slide--> |
|||
<Loop> |
|||
<Type>NORMAL</Type> <!-- NONE | NORMAL | PING-PONG --> |
|||
<Count>0</Count> <!-- 0 = forever --> |
|||
</Loop> |
|||
<Transition> |
|||
<Type>Dissolve</Type> |
|||
<Duration>3</Duration> |
|||
</Transition> |
|||
<!-- NoResize | Native | Fit | FitProportionally | FillProportionally --> |
|||
<ResizeOption>FitProportionally</ResizeOption> |
|||
</magSlideShow> |
|||
|
@ -1,126 +1,126 @@ |
|||
<surfaces> |
|||
<surface type="5"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>337.195068359</x> |
|||
<y>362.146270752</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>337.195068359</x> |
|||
<y>595.853759766</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>648.804992676</x> |
|||
<y>595.853759766</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>648.804992676</x> |
|||
<y>362.146270752</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image4.jpg</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
<surface type="1"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>522.590332031</x> |
|||
<y>188.924621582</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>835.409606934</x> |
|||
<y>188.924621582</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>835.409606934</x> |
|||
<y>415.075378418</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>522.590332031</x> |
|||
<y>415.075378418</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image1.jpg</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>325.000000000</x> |
|||
<y>196.999847412</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>479.922424316</x> |
|||
<y>421.000091553</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>170.077636719</x> |
|||
<y>421.000091553</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image2.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="5"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>337.195068359</x> |
|||
<y>362.146270752</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>337.195068359</x> |
|||
<y>595.853759766</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>648.804992676</x> |
|||
<y>595.853759766</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>648.804992676</x> |
|||
<y>362.146270752</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image4.jpg</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
<surface type="1"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>522.590332031</x> |
|||
<y>188.924621582</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>835.409606934</x> |
|||
<y>188.924621582</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>835.409606934</x> |
|||
<y>415.075378418</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>522.590332031</x> |
|||
<y>415.075378418</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image1.jpg</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>325.000000000</x> |
|||
<y>196.999847412</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>479.922424316</x> |
|||
<y>421.000091553</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>170.077636719</x> |
|||
<y>421.000091553</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image2.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,52 +1,52 @@ |
|||
#include "BrickSource.h" |
|||
|
|||
void BrickSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Brick Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
ofSetFrameRate(60); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numX = 21; |
|||
int numY = 21; // change this to add more or less rects
|
|||
int motar = 4; |
|||
int brickLength = 20; |
|||
int brickWidth = 20; |
|||
int counter = 0; |
|||
for(int k = 0; k < numY;k++){ |
|||
for(int i = 0; i < numX; i++){ |
|||
|
|||
bricks.push_back(ofRectangle(i*(brickLength + motar), |
|||
k*(brickWidth + motar), |
|||
brickLength, |
|||
brickWidth)); |
|||
brickColor.push_back(ofRandom(0, 220)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void BrickSource::update(){ |
|||
if (ofGetFrameNum()%30 == 0) { |
|||
for(int i = 0; i < bricks.size(); i++){ |
|||
brickColor[i] = ofRandom(0, 220); |
|||
} |
|||
} // Move quads
|
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void BrickSource::draw(){ |
|||
// Fill FBO with our quads
|
|||
ofClear(0); |
|||
//ofBackground(0);
|
|||
ofFill(); |
|||
|
|||
for(int i = 0; i < bricks.size(); i++){ |
|||
//ofSetLineWidth(ofRandom(5));
|
|||
ofSetColor(brickColor[i]); |
|||
ofDrawRectangle(bricks[i]); |
|||
} |
|||
} |
|||
#include "BrickSource.h" |
|||
|
|||
void BrickSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Brick Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
ofSetFrameRate(60); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numX = 21; |
|||
int numY = 21; // change this to add more or less rects
|
|||
int motar = 4; |
|||
int brickLength = 20; |
|||
int brickWidth = 20; |
|||
int counter = 0; |
|||
for(int k = 0; k < numY;k++){ |
|||
for(int i = 0; i < numX; i++){ |
|||
|
|||
bricks.push_back(ofRectangle(i*(brickLength + motar), |
|||
k*(brickWidth + motar), |
|||
brickLength, |
|||
brickWidth)); |
|||
brickColor.push_back(ofRandom(0, 220)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void BrickSource::update(){ |
|||
if (ofGetFrameNum()%30 == 0) { |
|||
for(int i = 0; i < bricks.size(); i++){ |
|||
brickColor[i] = ofRandom(0, 220); |
|||
} |
|||
} // Move quads
|
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void BrickSource::draw(){ |
|||
// Fill FBO with our quads
|
|||
ofClear(0); |
|||
//ofBackground(0);
|
|||
ofFill(); |
|||
|
|||
for(int i = 0; i < bricks.size(); i++){ |
|||
//ofSetLineWidth(ofRandom(5));
|
|||
ofSetColor(brickColor[i]); |
|||
ofDrawRectangle(bricks[i]); |
|||
} |
|||
} |
|||
|
@ -1,15 +1,15 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class BrickSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> bricks; |
|||
std::vector<int> brickColor; |
|||
int counter; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class BrickSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> bricks; |
|||
std::vector<int> brickColor; |
|||
int counter; |
|||
}; |
|||
|
@ -1,43 +1,43 @@ |
|||
#include "CircleSource.h" |
|||
|
|||
bool col = true; |
|||
|
|||
void CircleSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Circle Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
ofSetCircleResolution(50); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numCircles = 10; // change this to add more or less rects
|
|||
for(int i = 0; i < numCircles; i++){ |
|||
circlesRadius.push_back(ofRandom(fbo->getHeight()/2)); |
|||
circlesSpeeds.push_back((1.0f + ofRandom(2))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void CircleSource::update(){ |
|||
// Move rects
|
|||
for(int i = 0; i < circlesRadius.size(); i++){ |
|||
circlesRadius[i] += circlesSpeeds[i]; |
|||
if(circlesRadius[i] > fbo->getHeight()/2){ |
|||
circlesRadius[i] = fbo->getHeight()/2*(-1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void CircleSource::draw(){ |
|||
// Fill FBO with our rects
|
|||
ofClear(0); |
|||
ofSetColor(255); |
|||
ofSetLineWidth(ofRandom(3)); |
|||
ofNoFill(); |
|||
for(int i = 0; i < circlesRadius.size(); i++){ |
|||
ofDrawCircle(fbo->getHeight()/2,fbo->getHeight()/2,circlesRadius[i]); |
|||
} |
|||
} |
|||
#include "CircleSource.h" |
|||
|
|||
bool col = true; |
|||
|
|||
void CircleSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Circle Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
ofSetCircleResolution(50); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numCircles = 10; // change this to add more or less rects
|
|||
for(int i = 0; i < numCircles; i++){ |
|||
circlesRadius.push_back(ofRandom(fbo->getHeight()/2)); |
|||
circlesSpeeds.push_back((1.0f + ofRandom(2))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void CircleSource::update(){ |
|||
// Move rects
|
|||
for(int i = 0; i < circlesRadius.size(); i++){ |
|||
circlesRadius[i] += circlesSpeeds[i]; |
|||
if(circlesRadius[i] > fbo->getHeight()/2){ |
|||
circlesRadius[i] = fbo->getHeight()/2*(-1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void CircleSource::draw(){ |
|||
// Fill FBO with our rects
|
|||
ofClear(0); |
|||
ofSetColor(255); |
|||
ofSetLineWidth(ofRandom(3)); |
|||
ofNoFill(); |
|||
for(int i = 0; i < circlesRadius.size(); i++){ |
|||
ofDrawCircle(fbo->getHeight()/2,fbo->getHeight()/2,circlesRadius[i]); |
|||
} |
|||
} |
|||
|
@ -1,14 +1,14 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class CircleSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<float> circlesRadius; |
|||
std::vector<float> circlesSpeeds; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class CircleSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<float> circlesRadius; |
|||
std::vector<float> circlesSpeeds; |
|||
}; |
|||
|
@ -1,62 +1,62 @@ |
|||
#include "QuadSource.h" |
|||
|
|||
void QuadSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Quad Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numQuads = 20; // change this to add more or less rects
|
|||
for(int i = 0; i < numQuads; i++){ |
|||
float qsize = ofRandom(fbo->getWidth()); |
|||
float fbosize = fbo->getWidth(); |
|||
|
|||
quads.push_back(ofRectangle(fbosize/2 - qsize/2, |
|||
fbosize/2 - qsize/2, |
|||
qsize, |
|||
qsize)); |
|||
|
|||
quadSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void QuadSource::update(){ |
|||
// Move quads
|
|||
for(int i = 0; i < quads.size(); i++){ |
|||
quads[i].x -= quadSpeeds[i]/2; |
|||
quads[i].y -= quadSpeeds[i]/2; |
|||
quads[i].width += quadSpeeds[i]; |
|||
quads[i].height += quadSpeeds[i]; |
|||
|
|||
if(quads[i].width > fbo->getHeight()){ |
|||
quads[i].x = fbo->getWidth()/2; |
|||
quads[i].y = fbo->getWidth()/2; |
|||
quads[i].width = 0.0f; |
|||
quads[i].height = 0.0f; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void QuadSource::draw(){ |
|||
// Fill FBO with our quads
|
|||
ofClear(0); |
|||
//ofBackground(0);
|
|||
ofNoFill(); |
|||
ofSetColor(255); |
|||
|
|||
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0 |
|||
for(int i = 0; i < quads.size(); i++){ |
|||
ofSetLineWidth(ofRandom(5)); |
|||
ofDrawRectangle(quads[i]); |
|||
} |
|||
#else |
|||
for(int i = 0; i < quads.size(); i++){ |
|||
ofRect(quads[i]); |
|||
} |
|||
#endif |
|||
} |
|||
#include "QuadSource.h" |
|||
|
|||
void QuadSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Quad Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numQuads = 20; // change this to add more or less rects
|
|||
for(int i = 0; i < numQuads; i++){ |
|||
float qsize = ofRandom(fbo->getWidth()); |
|||
float fbosize = fbo->getWidth(); |
|||
|
|||
quads.push_back(ofRectangle(fbosize/2 - qsize/2, |
|||
fbosize/2 - qsize/2, |
|||
qsize, |
|||
qsize)); |
|||
|
|||
quadSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void QuadSource::update(){ |
|||
// Move quads
|
|||
for(int i = 0; i < quads.size(); i++){ |
|||
quads[i].x -= quadSpeeds[i]/2; |
|||
quads[i].y -= quadSpeeds[i]/2; |
|||
quads[i].width += quadSpeeds[i]; |
|||
quads[i].height += quadSpeeds[i]; |
|||
|
|||
if(quads[i].width > fbo->getHeight()){ |
|||
quads[i].x = fbo->getWidth()/2; |
|||
quads[i].y = fbo->getWidth()/2; |
|||
quads[i].width = 0.0f; |
|||
quads[i].height = 0.0f; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void QuadSource::draw(){ |
|||
// Fill FBO with our quads
|
|||
ofClear(0); |
|||
//ofBackground(0);
|
|||
ofNoFill(); |
|||
ofSetColor(255); |
|||
|
|||
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0 |
|||
for(int i = 0; i < quads.size(); i++){ |
|||
ofSetLineWidth(ofRandom(5)); |
|||
ofDrawRectangle(quads[i]); |
|||
} |
|||
#else |
|||
for(int i = 0; i < quads.size(); i++){ |
|||
ofRect(quads[i]); |
|||
} |
|||
#endif |
|||
} |
|||
|
@ -1,14 +1,14 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class QuadSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> quads; |
|||
std::vector<float> quadSpeeds; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class QuadSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> quads; |
|||
std::vector<float> quadSpeeds; |
|||
}; |
|||
|
@ -1,48 +1,48 @@ |
|||
#include "ScanlineSource.h" |
|||
|
|||
void ScanlineSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Scanline Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numRects = 20; // change this to add more or less rects
|
|||
for(int i = 0; i < numRects; i++){ |
|||
rects.push_back(ofRectangle(0, |
|||
ofRandom(fbo->getHeight()), |
|||
fbo->getWidth(), |
|||
ofRandom(20))); |
|||
rectSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void ScanlineSource::update(){ |
|||
// Move rects
|
|||
for(int i = 0; i < rects.size(); i++){ |
|||
rects[i].y += rectSpeeds[i]; |
|||
if(rects[i].y > fbo->getHeight()){ |
|||
rects[i].y = -rects[i].getHeight(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void ScanlineSource::draw(){ |
|||
// Fill FBO with our rects
|
|||
ofClear(0); |
|||
//ofBackground(0);
|
|||
ofSetColor(255); |
|||
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0 |
|||
for(int i = 0; i < rects.size(); i++){ |
|||
ofDrawRectangle(rects[i]); |
|||
} |
|||
#else |
|||
for(int i = 0; i < rects.size(); i++){ |
|||
ofRect(rects[i]); |
|||
} |
|||
#endif |
|||
} |
|||
#include "ScanlineSource.h" |
|||
|
|||
void ScanlineSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Scanline Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numRects = 20; // change this to add more or less rects
|
|||
for(int i = 0; i < numRects; i++){ |
|||
rects.push_back(ofRectangle(0, |
|||
ofRandom(fbo->getHeight()), |
|||
fbo->getWidth(), |
|||
ofRandom(20))); |
|||
rectSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void ScanlineSource::update(){ |
|||
// Move rects
|
|||
for(int i = 0; i < rects.size(); i++){ |
|||
rects[i].y += rectSpeeds[i]; |
|||
if(rects[i].y > fbo->getHeight()){ |
|||
rects[i].y = -rects[i].getHeight(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void ScanlineSource::draw(){ |
|||
// Fill FBO with our rects
|
|||
ofClear(0); |
|||
//ofBackground(0);
|
|||
ofSetColor(255); |
|||
#if (OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 9) || OF_VERSION_MAJOR > 0 |
|||
for(int i = 0; i < rects.size(); i++){ |
|||
ofDrawRectangle(rects[i]); |
|||
} |
|||
#else |
|||
for(int i = 0; i < rects.size(); i++){ |
|||
ofRect(rects[i]); |
|||
} |
|||
#endif |
|||
} |
|||
|
@ -1,14 +1,14 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class ScanlineSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> rects; |
|||
std::vector<float> rectSpeeds; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class ScanlineSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> rects; |
|||
std::vector<float> rectSpeeds; |
|||
}; |
|||
|
@ -1,201 +1,201 @@ |
|||
//
|
|||
// magSlide.cpp
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#include "magSlide.h" |
|||
#include "magSlideTransition.h" |
|||
|
|||
#pragma mark magSlide |
|||
|
|||
int magSlide::idCount = 0; |
|||
|
|||
magSlide::magSlide(std::string type) |
|||
{ |
|||
this->type = type; |
|||
position = ofPoint(0, 0); |
|||
id = magSlide::idCount; |
|||
magSlide::idCount++; |
|||
} |
|||
|
|||
void magSlide::update(uint64_t deltaTime) |
|||
{ |
|||
transition->update(deltaTime); |
|||
runningTime += deltaTime; |
|||
|
|||
switch (slideState){ |
|||
// case SlideState::BuildIn:
|
|||
// if (runningTime >= buildInDuration)
|
|||
// {
|
|||
// setState(Normal);
|
|||
// activeTransition = nullptr;
|
|||
// }
|
|||
// break;
|
|||
|
|||
case SlideState::Normal: |
|||
if (runningTime >= buildOutStartTime){ |
|||
setState(BuildOut); |
|||
} |
|||
break; |
|||
|
|||
case SlideState::BuildOut: |
|||
if (runningTime >= endTime){ |
|||
setState(Complete); |
|||
} |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void magSlide::setSize(float w, float h) |
|||
{ |
|||
width = w; |
|||
height = h; |
|||
} |
|||
|
|||
void magSlide::setResizeOption(magSlide::ResizeOptions resizeOption) |
|||
{ |
|||
this->resizeOption = resizeOption; |
|||
} |
|||
|
|||
magSlide::ResizeOptions magSlide::getResizeOption() const |
|||
{ |
|||
return resizeOption; |
|||
} |
|||
|
|||
void magSlide::setDuration(uint64_t duration) |
|||
{ |
|||
this->duration = duration; |
|||
} |
|||
|
|||
void magSlide::setState(SlideState state) |
|||
{ |
|||
// Don't do anything if the new state is the same
|
|||
// as the current one:
|
|||
if (slideState == state) return; |
|||
|
|||
slideState = state; |
|||
ofEventArgs args; |
|||
ofNotifyEvent(slideStateChangedEvent, args, this); |
|||
|
|||
if (slideState == Complete) |
|||
{ |
|||
ofNotifyEvent(slideCompleteEvent, args, this); |
|||
} |
|||
} |
|||
|
|||
void magSlide::setTransitionDuration(uint64_t tDuration) |
|||
{ |
|||
buildOutDuration = tDuration; |
|||
} |
|||
|
|||
const std::string magSlide::getSlideStateName() |
|||
{ |
|||
switch (slideState) |
|||
{ |
|||
// case SlideState::BuildIn:
|
|||
// return "BuildIn";
|
|||
case SlideState::BuildOut: |
|||
return "BuildOut"; |
|||
case Normal: |
|||
return "Normal"; |
|||
case SlideState::Complete: |
|||
return "Complete"; |
|||
case SlideState::Off: |
|||
return "Off"; |
|||
} |
|||
|
|||
return "unknown"; |
|||
} |
|||
|
|||
void magSlide::start(uint64_t startTime) |
|||
{ |
|||
this->startTime = startTime; |
|||
runningTime = 0; |
|||
endTime = duration + (buildOutDuration*2); // *2 because we take into account transition in and out
|
|||
buildOutStartTime = duration + buildOutDuration; |
|||
slideState = magSlide::SlideState::Normal; |
|||
position.set(0, 0); |
|||
opacity = 255; |
|||
isComplete = false; |
|||
} |
|||
|
|||
void magSlide::draw() |
|||
{ |
|||
ofSetColor(255, opacity); |
|||
if(transition->isActive()) |
|||
{ |
|||
transition->draw(); |
|||
} |
|||
} |
|||
|
|||
|
|||
////////////////////////////////////////////////////////
|
|||
#pragma mark MAG_IMAGE_SLIDE |
|||
////////////////////////////////////////////////////////
|
|||
|
|||
magImageSlide::magImageSlide() : magSlide("magImageSlide") {} |
|||
|
|||
magImageSlide::~magImageSlide() {} |
|||
|
|||
void magImageSlide::setup(ofImage &image) |
|||
{ |
|||
// Make a copy of the image:
|
|||
this->image = ofImage(image); |
|||
image.setAnchorPercent(0.5, 0.5); |
|||
width = image.getWidth(); |
|||
height = image.getHeight(); |
|||
} |
|||
|
|||
void magImageSlide::draw() |
|||
{ |
|||
magSlide::draw(); |
|||
image.draw(position, width, height); |
|||
} |
|||
|
|||
////////////////////////////////////////////////////////
|
|||
#pragma mark MAG_VIDEO_SLIDE |
|||
////////////////////////////////////////////////////////
|
|||
|
|||
magVideoSlide::magVideoSlide() : magSlide("magVideoSlide") |
|||
{} |
|||
|
|||
magVideoSlide::~magVideoSlide() |
|||
{ |
|||
videoPlayer.stop(); |
|||
} |
|||
|
|||
bool magVideoSlide::setup(ofFile &file, bool useVideoDuration) |
|||
{ |
|||
|
|||
bool success = videoPlayer.load(file.getAbsolutePath()); |
|||
|
|||
if (success) |
|||
{ |
|||
videoPlayer.setAnchorPercent(0.5, 0.5); |
|||
if (useVideoDuration) |
|||
{ |
|||
useVideoForDuration(); |
|||
} |
|||
} |
|||
|
|||
return success; |
|||
} |
|||
|
|||
void magVideoSlide::update() |
|||
{ |
|||
videoPlayer.update(); |
|||
} |
|||
|
|||
void magVideoSlide::draw() |
|||
{ |
|||
magSlide::draw(); |
|||
videoPlayer.draw(position.x, position.y, width, height); |
|||
} |
|||
|
|||
void magVideoSlide::useVideoForDuration() |
|||
{ |
|||
duration = uint64_t((videoPlayer.getDuration()*1000)) - buildOutDuration; |
|||
} |
|||
//
|
|||
// magSlide.cpp
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#include "magSlide.h" |
|||
#include "magSlideTransition.h" |
|||
|
|||
#pragma mark magSlide |
|||
|
|||
int magSlide::idCount = 0; |
|||
|
|||
magSlide::magSlide(std::string type) |
|||
{ |
|||
this->type = type; |
|||
position = ofPoint(0, 0); |
|||
id = magSlide::idCount; |
|||
magSlide::idCount++; |
|||
} |
|||
|
|||
void magSlide::update(uint64_t deltaTime) |
|||
{ |
|||
transition->update(deltaTime); |
|||
runningTime += deltaTime; |
|||
|
|||
switch (slideState){ |
|||
// case SlideState::BuildIn:
|
|||
// if (runningTime >= buildInDuration)
|
|||
// {
|
|||
// setState(Normal);
|
|||
// activeTransition = nullptr;
|
|||
// }
|
|||
// break;
|
|||
|
|||
case SlideState::Normal: |
|||
if (runningTime >= buildOutStartTime){ |
|||
setState(BuildOut); |
|||
} |
|||
break; |
|||
|
|||
case SlideState::BuildOut: |
|||
if (runningTime >= endTime){ |
|||
setState(Complete); |
|||
} |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void magSlide::setSize(float w, float h) |
|||
{ |
|||
width = w; |
|||
height = h; |
|||
} |
|||
|
|||
void magSlide::setResizeOption(magSlide::ResizeOptions resizeOption) |
|||
{ |
|||
this->resizeOption = resizeOption; |
|||
} |
|||
|
|||
magSlide::ResizeOptions magSlide::getResizeOption() const |
|||
{ |
|||
return resizeOption; |
|||
} |
|||
|
|||
void magSlide::setDuration(uint64_t duration) |
|||
{ |
|||
this->duration = duration; |
|||
} |
|||
|
|||
void magSlide::setState(SlideState state) |
|||
{ |
|||
// Don't do anything if the new state is the same
|
|||
// as the current one:
|
|||
if (slideState == state) return; |
|||
|
|||
slideState = state; |
|||
ofEventArgs args; |
|||
ofNotifyEvent(slideStateChangedEvent, args, this); |
|||
|
|||
if (slideState == Complete) |
|||
{ |
|||
ofNotifyEvent(slideCompleteEvent, args, this); |
|||
} |
|||
} |
|||
|
|||
void magSlide::setTransitionDuration(uint64_t tDuration) |
|||
{ |
|||
buildOutDuration = tDuration; |
|||
} |
|||
|
|||
const std::string magSlide::getSlideStateName() |
|||
{ |
|||
switch (slideState) |
|||
{ |
|||
// case SlideState::BuildIn:
|
|||
// return "BuildIn";
|
|||
case SlideState::BuildOut: |
|||
return "BuildOut"; |
|||
case Normal: |
|||
return "Normal"; |
|||
case SlideState::Complete: |
|||
return "Complete"; |
|||
case SlideState::Off: |
|||
return "Off"; |
|||
} |
|||
|
|||
return "unknown"; |
|||
} |
|||
|
|||
void magSlide::start(uint64_t startTime) |
|||
{ |
|||
this->startTime = startTime; |
|||
runningTime = 0; |
|||
endTime = duration + (buildOutDuration*2); // *2 because we take into account transition in and out
|
|||
buildOutStartTime = duration + buildOutDuration; |
|||
slideState = magSlide::SlideState::Normal; |
|||
position.set(0, 0); |
|||
opacity = 255; |
|||
isComplete = false; |
|||
} |
|||
|
|||
void magSlide::draw() |
|||
{ |
|||
ofSetColor(255, opacity); |
|||
if(transition->isActive()) |
|||
{ |
|||
transition->draw(); |
|||
} |
|||
} |
|||
|
|||
|
|||
////////////////////////////////////////////////////////
|
|||
#pragma mark MAG_IMAGE_SLIDE |
|||
////////////////////////////////////////////////////////
|
|||
|
|||
magImageSlide::magImageSlide() : magSlide("magImageSlide") {} |
|||
|
|||
magImageSlide::~magImageSlide() {} |
|||
|
|||
void magImageSlide::setup(ofImage &image) |
|||
{ |
|||
// Make a copy of the image:
|
|||
this->image = ofImage(image); |
|||
image.setAnchorPercent(0.5, 0.5); |
|||
width = image.getWidth(); |
|||
height = image.getHeight(); |
|||
} |
|||
|
|||
void magImageSlide::draw() |
|||
{ |
|||
magSlide::draw(); |
|||
image.draw(position, width, height); |
|||
} |
|||
|
|||
////////////////////////////////////////////////////////
|
|||
#pragma mark MAG_VIDEO_SLIDE |
|||
////////////////////////////////////////////////////////
|
|||
|
|||
magVideoSlide::magVideoSlide() : magSlide("magVideoSlide") |
|||
{} |
|||
|
|||
magVideoSlide::~magVideoSlide() |
|||
{ |
|||
videoPlayer.stop(); |
|||
} |
|||
|
|||
bool magVideoSlide::setup(ofFile &file, bool useVideoDuration) |
|||
{ |
|||
|
|||
bool success = videoPlayer.load(file.getAbsolutePath()); |
|||
|
|||
if (success) |
|||
{ |
|||
videoPlayer.setAnchorPercent(0.5, 0.5); |
|||
if (useVideoDuration) |
|||
{ |
|||
useVideoForDuration(); |
|||
} |
|||
} |
|||
|
|||
return success; |
|||
} |
|||
|
|||
void magVideoSlide::update() |
|||
{ |
|||
videoPlayer.update(); |
|||
} |
|||
|
|||
void magVideoSlide::draw() |
|||
{ |
|||
magSlide::draw(); |
|||
videoPlayer.draw(position.x, position.y, width, height); |
|||
} |
|||
|
|||
void magVideoSlide::useVideoForDuration() |
|||
{ |
|||
duration = uint64_t((videoPlayer.getDuration()*1000)) - buildOutDuration; |
|||
} |
|||
|
@ -1,263 +1,263 @@ |
|||
//
|
|||
// Created by Cristobal Mendoza on 11/9/17.
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDE_H |
|||
#define MAGSLIDE_H |
|||
|
|||
#include "ofMain.h" |
|||
|
|||
class magSlideTransition; |
|||
|
|||
class magSlide |
|||
{ |
|||
public: |
|||
magSlide(std::string type); |
|||
// ~magSlide();
|
|||
virtual void update(uint64_t deltaTime); |
|||
virtual void draw(); |
|||
|
|||
/**
|
|||
* Sets the slide up for playback. This method must be |
|||
* called before displaying the slide. |
|||
* @param startTime |
|||
*/ |
|||
void start(uint64_t startTime); |
|||
|
|||
enum ResizeOptions : short |
|||
{ |
|||
/**
|
|||
* No resizing applied, displays the slide in its native pixel dimensions. |
|||
* This is the default behavior. |
|||
*/ |
|||
NoResize = 0, |
|||
/**
|
|||
* Explicitly set a slide to display in its native dimension. |
|||
* None and NoResize result in the same output, but if you specify |
|||
* a default resizing option in your slideshow and you want a particular |
|||
* slide not to resize, you must specify this option. Otherwise the |
|||
* slide show option will apply. |
|||
*/ |
|||
Native, |
|||
|
|||
/**
|
|||
* Sets width and height to match the source's. |
|||
* This will distort the slide if the aspect ratios |
|||
* don't match. |
|||
*/ |
|||
Fit, |
|||
|
|||
/**
|
|||
* Resizes the largest dimension to the source's max, |
|||
* the other dimension is resized proportionally. |
|||
*/ |
|||
FitProportionally, |
|||
|
|||
/**
|
|||
* Resizes the shortest dimensions to the source's max, |
|||
*/ |
|||
FillProportionally, |
|||
}; |
|||
|
|||
enum SlideState : short |
|||
{ |
|||
Off = 0, |
|||
// BuildIn,
|
|||
Normal, |
|||
BuildOut, |
|||
Complete |
|||
}; |
|||
|
|||
const std::string &getType() |
|||
{ return type; } |
|||
|
|||
float getWidth() |
|||
{ return width; } |
|||
|
|||
float getHeight() |
|||
{ return height; } |
|||
|
|||
float getOpacity() const |
|||
{ |
|||
return opacity; |
|||
} |
|||
|
|||
void setOpacity(float opacity) |
|||
{ |
|||
magSlide::opacity = opacity; |
|||
} |
|||
|
|||
/**
|
|||
* Change the display size of a slide. This will implicitly |
|||
* set resizeOptions to ResizeOption.NoResize. |
|||
* This method does not resize the pixel source of the slide. |
|||
* @param w The new width |
|||
* @param h The new height |
|||
*/ |
|||
virtual void setSize(float w, float h); |
|||
|
|||
uint64_t getDuration() |
|||
{ |
|||
return duration; |
|||
} |
|||
|
|||
/**
|
|||
* Sets the display time of the slide, excluding |
|||
* builds (in or out) |
|||
* @param duration in milliseconds. |
|||
*/ |
|||
void setDuration(uint64_t duration); |
|||
|
|||
/**
|
|||
* Sets the duration of the buildIn and buildOut |
|||
* transitions. Transition times are added to the |
|||
* duration of the slide. |
|||
* @param tDuration in milliseconds. |
|||
*/ |
|||
void setTransitionDuration(uint64_t tDuration); |
|||
|
|||
ResizeOptions getResizeOption() const; |
|||
void setResizeOption(ResizeOptions resizeOption); |
|||
|
|||
SlideState getSlideState() const |
|||
{ |
|||
return slideState; |
|||
} |
|||
|
|||
bool isSlideComplete() |
|||
{ return isComplete; } |
|||
|
|||
int getId() |
|||
{ return id; } |
|||
|
|||
const std::string getSlideStateName(); |
|||
|
|||
//////////////////////////////
|
|||
/// Events
|
|||
//////////////////////////////
|
|||
ofEvent<ofEventArgs> slideCompleteEvent; |
|||
ofEvent<ofEventArgs> slideStateChangedEvent; |
|||
|
|||
friend class magSlideShowSource; |
|||
|
|||
protected: |
|||
int id; |
|||
std::string type; |
|||
float width; |
|||
float height; |
|||
ofPoint position; |
|||
public: |
|||
const ofPoint &getPosition() const |
|||
{ |
|||
return position; |
|||
} |
|||
|
|||
void setPosition(const ofPoint &position) |
|||
{ |
|||
magSlide::position = position; |
|||
} |
|||
|
|||
void setPosition(float x, float y) |
|||
{ |
|||
position.set(x, y); |
|||
} |
|||
|
|||
|
|||
protected: |
|||
float opacity = 255; |
|||
ResizeOptions resizeOption = NoResize; |
|||
SlideState slideState = Off; |
|||
bool isComplete = false; |
|||
|
|||
// std::shared_ptr<magSlideTransition> buildIn = nullptr;
|
|||
// std::shared_ptr<magSlideTransition> buildOut = nullptr;
|
|||
std::shared_ptr<magSlideTransition> transition = nullptr; |
|||
public: |
|||
const shared_ptr<magSlideTransition> &getTransition() const |
|||
{ |
|||
return transition; |
|||
} |
|||
|
|||
protected: |
|||
/**
|
|||
* The duration of the slide in millis, not counting builds |
|||
*/ |
|||
uint64_t duration; |
|||
|
|||
/**
|
|||
* The start time of the slide in milliseconds, in "local time". |
|||
* In practice, this means that the start time is always 0. |
|||
*/ |
|||
uint64_t startTime; |
|||
|
|||
/**
|
|||
* The end time of the slide in milliseconds, in "local time". |
|||
* The endTime is startTime + buildInDuration + duration + buildOutDuration. |
|||
*/ |
|||
uint64_t endTime; |
|||
|
|||
/**
|
|||
* The duration of the build in transition or effect, in milliseconds. |
|||
*/ |
|||
// uint64_t buildInDuration;
|
|||
|
|||
/**
|
|||
* The duration of the build out transition or effect, in milliseconds. |
|||
*/ |
|||
uint64_t buildOutDuration; |
|||
|
|||
/**
|
|||
* The "local time" start of the build out transition. This time should also |
|||
* signal the enqueuing of the next slide, if applicable. |
|||
*/ |
|||
uint64_t buildOutStartTime; |
|||
|
|||
/**
|
|||
* The amount of time the slide has been displayed, in milliseconds. |
|||
* This constitutes the "local time" of the slide. |
|||
*/ |
|||
uint64_t runningTime; |
|||
|
|||
void setState(SlideState state); |
|||
|
|||
static int idCount; |
|||
}; |
|||
|
|||
class magImageSlide : public magSlide |
|||
{ |
|||
public: |
|||
magImageSlide(); |
|||
~ magImageSlide(); |
|||
/**
|
|||
* Sets up an image slide. |
|||
* @param image is copied into the member magImageSlide::image and is |
|||
* not modified in any way. |
|||
*/ |
|||
void setup(ofImage &image); |
|||
|
|||
void draw(); |
|||
|
|||
protected: |
|||
ofImage image; |
|||
}; |
|||
|
|||
class magVideoSlide : public magSlide |
|||
{ |
|||
public: |
|||
magVideoSlide(); |
|||
~magVideoSlide(); |
|||
bool setup(ofFile &file, bool useVideoDuration = false); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
/**
|
|||
* Sets the slide duration to the duration of the video. |
|||
* magSlide::duration will be changed by this call, so if you later |
|||
* change your mind you'll have to use magSlide::setDuration. |
|||
*/ |
|||
void useVideoForDuration(); |
|||
protected: |
|||
ofVideoPlayer videoPlayer; |
|||
}; |
|||
|
|||
#endif |
|||
//
|
|||
// Created by Cristobal Mendoza on 11/9/17.
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDE_H |
|||
#define MAGSLIDE_H |
|||
|
|||
#include "ofMain.h" |
|||
|
|||
class magSlideTransition; |
|||
|
|||
class magSlide |
|||
{ |
|||
public: |
|||
magSlide(std::string type); |
|||
// ~magSlide();
|
|||
virtual void update(uint64_t deltaTime); |
|||
virtual void draw(); |
|||
|
|||
/**
|
|||
* Sets the slide up for playback. This method must be |
|||
* called before displaying the slide. |
|||
* @param startTime |
|||
*/ |
|||
void start(uint64_t startTime); |
|||
|
|||
enum ResizeOptions : short |
|||
{ |
|||
/**
|
|||
* No resizing applied, displays the slide in its native pixel dimensions. |
|||
* This is the default behavior. |
|||
*/ |
|||
NoResize = 0, |
|||
/**
|
|||
* Explicitly set a slide to display in its native dimension. |
|||
* None and NoResize result in the same output, but if you specify |
|||
* a default resizing option in your slideshow and you want a particular |
|||
* slide not to resize, you must specify this option. Otherwise the |
|||
* slide show option will apply. |
|||
*/ |
|||
Native, |
|||
|
|||
/**
|
|||
* Sets width and height to match the source's. |
|||
* This will distort the slide if the aspect ratios |
|||
* don't match. |
|||
*/ |
|||
Fit, |
|||
|
|||
/**
|
|||
* Resizes the largest dimension to the source's max, |
|||
* the other dimension is resized proportionally. |
|||
*/ |
|||
FitProportionally, |
|||
|
|||
/**
|
|||
* Resizes the shortest dimensions to the source's max, |
|||
*/ |
|||
FillProportionally, |
|||
}; |
|||
|
|||
enum SlideState : short |
|||
{ |
|||
Off = 0, |
|||
// BuildIn,
|
|||
Normal, |
|||
BuildOut, |
|||
Complete |
|||
}; |
|||
|
|||
const std::string &getType() |
|||
{ return type; } |
|||
|
|||
float getWidth() |
|||
{ return width; } |
|||
|
|||
float getHeight() |
|||
{ return height; } |
|||
|
|||
float getOpacity() const |
|||
{ |
|||
return opacity; |
|||
} |
|||
|
|||
void setOpacity(float opacity) |
|||
{ |
|||
magSlide::opacity = opacity; |
|||
} |
|||
|
|||
/**
|
|||
* Change the display size of a slide. This will implicitly |
|||
* set resizeOptions to ResizeOption.NoResize. |
|||
* This method does not resize the pixel source of the slide. |
|||
* @param w The new width |
|||
* @param h The new height |
|||
*/ |
|||
virtual void setSize(float w, float h); |
|||
|
|||
uint64_t getDuration() |
|||
{ |
|||
return duration; |
|||
} |
|||
|
|||
/**
|
|||
* Sets the display time of the slide, excluding |
|||
* builds (in or out) |
|||
* @param duration in milliseconds. |
|||
*/ |
|||
void setDuration(uint64_t duration); |
|||
|
|||
/**
|
|||
* Sets the duration of the buildIn and buildOut |
|||
* transitions. Transition times are added to the |
|||
* duration of the slide. |
|||
* @param tDuration in milliseconds. |
|||
*/ |
|||
void setTransitionDuration(uint64_t tDuration); |
|||
|
|||
ResizeOptions getResizeOption() const; |
|||
void setResizeOption(ResizeOptions resizeOption); |
|||
|
|||
SlideState getSlideState() const |
|||
{ |
|||
return slideState; |
|||
} |
|||
|
|||
bool isSlideComplete() |
|||
{ return isComplete; } |
|||
|
|||
int getId() |
|||
{ return id; } |
|||
|
|||
const std::string getSlideStateName(); |
|||
|
|||
//////////////////////////////
|
|||
/// Events
|
|||
//////////////////////////////
|
|||
ofEvent<ofEventArgs> slideCompleteEvent; |
|||
ofEvent<ofEventArgs> slideStateChangedEvent; |
|||
|
|||
friend class magSlideShowSource; |
|||
|
|||
protected: |
|||
int id; |
|||
std::string type; |
|||
float width; |
|||
float height; |
|||
ofPoint position; |
|||
public: |
|||
const ofPoint &getPosition() const |
|||
{ |
|||
return position; |
|||
} |
|||
|
|||
void setPosition(const ofPoint &position) |
|||
{ |
|||
magSlide::position = position; |
|||
} |
|||
|
|||
void setPosition(float x, float y) |
|||
{ |
|||
position.set(x, y); |
|||
} |
|||
|
|||
|
|||
protected: |
|||
float opacity = 255; |
|||
ResizeOptions resizeOption = NoResize; |
|||
SlideState slideState = Off; |
|||
bool isComplete = false; |
|||
|
|||
// std::shared_ptr<magSlideTransition> buildIn = nullptr;
|
|||
// std::shared_ptr<magSlideTransition> buildOut = nullptr;
|
|||
std::shared_ptr<magSlideTransition> transition = nullptr; |
|||
public: |
|||
const shared_ptr<magSlideTransition> &getTransition() const |
|||
{ |
|||
return transition; |
|||
} |
|||
|
|||
protected: |
|||
/**
|
|||
* The duration of the slide in millis, not counting builds |
|||
*/ |
|||
uint64_t duration; |
|||
|
|||
/**
|
|||
* The start time of the slide in milliseconds, in "local time". |
|||
* In practice, this means that the start time is always 0. |
|||
*/ |
|||
uint64_t startTime; |
|||
|
|||
/**
|
|||
* The end time of the slide in milliseconds, in "local time". |
|||
* The endTime is startTime + buildInDuration + duration + buildOutDuration. |
|||
*/ |
|||
uint64_t endTime; |
|||
|
|||
/**
|
|||
* The duration of the build in transition or effect, in milliseconds. |
|||
*/ |
|||
// uint64_t buildInDuration;
|
|||
|
|||
/**
|
|||
* The duration of the build out transition or effect, in milliseconds. |
|||
*/ |
|||
uint64_t buildOutDuration; |
|||
|
|||
/**
|
|||
* The "local time" start of the build out transition. This time should also |
|||
* signal the enqueuing of the next slide, if applicable. |
|||
*/ |
|||
uint64_t buildOutStartTime; |
|||
|
|||
/**
|
|||
* The amount of time the slide has been displayed, in milliseconds. |
|||
* This constitutes the "local time" of the slide. |
|||
*/ |
|||
uint64_t runningTime; |
|||
|
|||
void setState(SlideState state); |
|||
|
|||
static int idCount; |
|||
}; |
|||
|
|||
class magImageSlide : public magSlide |
|||
{ |
|||
public: |
|||
magImageSlide(); |
|||
~ magImageSlide(); |
|||
/**
|
|||
* Sets up an image slide. |
|||
* @param image is copied into the member magImageSlide::image and is |
|||
* not modified in any way. |
|||
*/ |
|||
void setup(ofImage &image); |
|||
|
|||
void draw(); |
|||
|
|||
protected: |
|||
ofImage image; |
|||
}; |
|||
|
|||
class magVideoSlide : public magSlide |
|||
{ |
|||
public: |
|||
magVideoSlide(); |
|||
~magVideoSlide(); |
|||
bool setup(ofFile &file, bool useVideoDuration = false); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
/**
|
|||
* Sets the slide duration to the duration of the video. |
|||
* magSlide::duration will be changed by this call, so if you later |
|||
* change your mind you'll have to use magSlide::setDuration. |
|||
*/ |
|||
void useVideoForDuration(); |
|||
protected: |
|||
ofVideoPlayer videoPlayer; |
|||
}; |
|||
|
|||
#endif |
|||
|
File diff suppressed because it is too large
@ -1,167 +1,167 @@ |
|||
//
|
|||
// magSlideShowSource.h
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDESHOWSOURCE_H |
|||
#define MAGSLIDESHOWSOURCE_H |
|||
|
|||
#include "FboSource.h" |
|||
#include "magSlide.h" |
|||
#include "DirectoryWatcher.h" |
|||
|
|||
class magSlide; |
|||
|
|||
class magSlideShowSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
magSlideShowSource(); |
|||
|
|||
/**
|
|||
* Default settings file name. |
|||
*/ |
|||
static const std::string SettingsFileName; |
|||
struct Settings; // forward declaration
|
|||
bool initialize(magSlideShowSource::Settings settings); |
|||
void setup() override; |
|||
void update() override; |
|||
void draw() override; |
|||
|
|||
/**
|
|||
* Removes all slides and then attempts to create a new slide show |
|||
* based on the contents of the ofDirectory specified. The files may |
|||
* be images or videos, which will be transformed into the appropriate slide type. |
|||
* Any other file type in the directory is ignored (including other directories). |
|||
* The slide order is alphabetical according to filename. |
|||
* |
|||
* @param dir The ofDirectory to use as a source for a slide show. |
|||
* @return true if at least one slide was created. false is returned |
|||
* otherwise. Check the console for the specific error. |
|||
*/ |
|||
bool createFromFolderContents(std::string path); |
|||
bool loadFromXml(std::string path); |
|||
void addSlide(std::shared_ptr<magSlide> slide); |
|||
void play(); |
|||
void pause(); |
|||
void playNextSlide(); |
|||
void playPrevSlide(); |
|||
void playSlide(int slideIndex); |
|||
|
|||
enum LoopType : int { |
|||
NONE = 0, |
|||
NORMAL, |
|||
PING_PONG |
|||
}; |
|||
|
|||
struct Settings { |
|||
/**
|
|||
* The pixel width of the FBO. |
|||
*/ |
|||
float width = 1280; |
|||
|
|||
/**
|
|||
* The pixel height of the FBO. |
|||
*/ |
|||
float height = 720; |
|||
/**
|
|||
* An optional default slide duration, in seconds. |
|||
* If a slide specifies a duration this value is ignored. |
|||
*/ |
|||
float slideDuration = 5; |
|||
|
|||
/**
|
|||
* The default transition for the slide show. |
|||
*/ |
|||
std::string transitionName = "Dissolve"; |
|||
|
|||
/**
|
|||
* Default transition duration. |
|||
*/ |
|||
float transitionDuration = 1; |
|||
|
|||
/**
|
|||
* If specified, all applicable files in the folder will |
|||
* be used as slides in the slide show. They will be ordered |
|||
* alphabetically according to their file names. |
|||
* |
|||
* If path is relative, the root will likely be the Data folder. |
|||
*/ |
|||
std::string slidesFolderPath = "sources/images"; |
|||
|
|||
/**
|
|||
* If specified, |
|||
*/ |
|||
std::string slideshowFilePath; |
|||
|
|||
|
|||
/**
|
|||
* Loop type for the slide show. See @code LoopType for options. |
|||
* The default is @code LoopType:None. |
|||
*/ |
|||
LoopType loopType = LoopType::NONE; |
|||
|
|||
/**
|
|||
* The number of loops to perform, if the loopType is not NONE. |
|||
* If the value is 0 or less than 0, the slide show loops forever. |
|||
*/ |
|||
int numLoops = 0; |
|||
|
|||
/**
|
|||
* The resizing option for the slide show. The default is FitProportionally. |
|||
* If a slide already has a resizing option applied, that option will be |
|||
* respected and this resizeOption will not be used. |
|||
*/ |
|||
magSlide::ResizeOptions resizeOption = magSlide::ResizeOptions::FitProportionally; |
|||
}; |
|||
|
|||
////////////////////////////////////////////
|
|||
//// Event Listeners
|
|||
////////////////////////////////////////////
|
|||
void slideStateChanged(const void *sender, ofEventArgs &args); |
|||
void slideComplete(const void *sender, ofEventArgs &args); |
|||
virtual ~magSlideShowSource(); |
|||
|
|||
|
|||
/**
|
|||
* Fires when the slide show is done, which happens when |
|||
* the loop count is equal to Settings::numLoops, or when |
|||
* the last slide is played when @code LoopType::NONE is specified. |
|||
* Sender is this slide show. |
|||
*/ |
|||
ofEvent<ofEventArgs> slideshowCompleteEvent; |
|||
|
|||
|
|||
/**
|
|||
* Fires when the slide show reaches the last slide |
|||
* and will perform a loop in the next call. |
|||
* Sender is this slide show. |
|||
*/ |
|||
ofEvent<ofEventArgs> slideshowWillLoopEvent; |
|||
|
|||
protected: |
|||
Settings settings; |
|||
std::vector<std::shared_ptr<magSlide>> slides; |
|||
|
|||
private: |
|||
// std::shared_ptr<magSlide> currentSlide;
|
|||
std::vector<std::shared_ptr<magSlide>> activeSlides; |
|||
void enqueueSlide(std::shared_ptr<magSlide> slide, uint64_t startTime); |
|||
|
|||
uint64_t lastTime; |
|||
uint64_t deltaTime; |
|||
uint64_t runningTime; |
|||
|
|||
bool isInitialized = false; |
|||
bool isPlaying = false; |
|||
int currentSlideIndex = 0; |
|||
int direction = 1; |
|||
int loopCount = 0; |
|||
ofx::piMapper::DirectoryWatcher * directoryWatcher; |
|||
void fileAddedListener(const void * sender); |
|||
void fileRemovedListener(const void * sender); |
|||
bool doInit; |
|||
bool doPlayNextSlide = false; |
|||
}; |
|||
|
|||
|
|||
#endif |
|||
//
|
|||
// magSlideShowSource.h
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDESHOWSOURCE_H |
|||
#define MAGSLIDESHOWSOURCE_H |
|||
|
|||
#include "FboSource.h" |
|||
#include "magSlide.h" |
|||
#include "DirectoryWatcher.h" |
|||
|
|||
class magSlide; |
|||
|
|||
class magSlideShowSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
magSlideShowSource(); |
|||
|
|||
/**
|
|||
* Default settings file name. |
|||
*/ |
|||
static const std::string SettingsFileName; |
|||
struct Settings; // forward declaration
|
|||
bool initialize(magSlideShowSource::Settings settings); |
|||
void setup() override; |
|||
void update() override; |
|||
void draw() override; |
|||
|
|||
/**
|
|||
* Removes all slides and then attempts to create a new slide show |
|||
* based on the contents of the ofDirectory specified. The files may |
|||
* be images or videos, which will be transformed into the appropriate slide type. |
|||
* Any other file type in the directory is ignored (including other directories). |
|||
* The slide order is alphabetical according to filename. |
|||
* |
|||
* @param dir The ofDirectory to use as a source for a slide show. |
|||
* @return true if at least one slide was created. false is returned |
|||
* otherwise. Check the console for the specific error. |
|||
*/ |
|||
bool createFromFolderContents(std::string path); |
|||
bool loadFromXml(std::string path); |
|||
void addSlide(std::shared_ptr<magSlide> slide); |
|||
void play(); |
|||
void pause(); |
|||
void playNextSlide(); |
|||
void playPrevSlide(); |
|||
void playSlide(int slideIndex); |
|||
|
|||
enum LoopType : int { |
|||
NONE = 0, |
|||
NORMAL, |
|||
PING_PONG |
|||
}; |
|||
|
|||
struct Settings { |
|||
/**
|
|||
* The pixel width of the FBO. |
|||
*/ |
|||
float width = 1280; |
|||
|
|||
/**
|
|||
* The pixel height of the FBO. |
|||
*/ |
|||
float height = 720; |
|||
/**
|
|||
* An optional default slide duration, in seconds. |
|||
* If a slide specifies a duration this value is ignored. |
|||
*/ |
|||
float slideDuration = 5; |
|||
|
|||
/**
|
|||
* The default transition for the slide show. |
|||
*/ |
|||
std::string transitionName = "Dissolve"; |
|||
|
|||
/**
|
|||
* Default transition duration. |
|||
*/ |
|||
float transitionDuration = 1; |
|||
|
|||
/**
|
|||
* If specified, all applicable files in the folder will |
|||
* be used as slides in the slide show. They will be ordered |
|||
* alphabetically according to their file names. |
|||
* |
|||
* If path is relative, the root will likely be the Data folder. |
|||
*/ |
|||
std::string slidesFolderPath = "sources/images"; |
|||
|
|||
/**
|
|||
* If specified, |
|||
*/ |
|||
std::string slideshowFilePath; |
|||
|
|||
|
|||
/**
|
|||
* Loop type for the slide show. See @code LoopType for options. |
|||
* The default is @code LoopType:None. |
|||
*/ |
|||
LoopType loopType = LoopType::NONE; |
|||
|
|||
/**
|
|||
* The number of loops to perform, if the loopType is not NONE. |
|||
* If the value is 0 or less than 0, the slide show loops forever. |
|||
*/ |
|||
int numLoops = 0; |
|||
|
|||
/**
|
|||
* The resizing option for the slide show. The default is FitProportionally. |
|||
* If a slide already has a resizing option applied, that option will be |
|||
* respected and this resizeOption will not be used. |
|||
*/ |
|||
magSlide::ResizeOptions resizeOption = magSlide::ResizeOptions::FitProportionally; |
|||
}; |
|||
|
|||
////////////////////////////////////////////
|
|||
//// Event Listeners
|
|||
////////////////////////////////////////////
|
|||
void slideStateChanged(const void *sender, ofEventArgs &args); |
|||
void slideComplete(const void *sender, ofEventArgs &args); |
|||
virtual ~magSlideShowSource(); |
|||
|
|||
|
|||
/**
|
|||
* Fires when the slide show is done, which happens when |
|||
* the loop count is equal to Settings::numLoops, or when |
|||
* the last slide is played when @code LoopType::NONE is specified. |
|||
* Sender is this slide show. |
|||
*/ |
|||
ofEvent<ofEventArgs> slideshowCompleteEvent; |
|||
|
|||
|
|||
/**
|
|||
* Fires when the slide show reaches the last slide |
|||
* and will perform a loop in the next call. |
|||
* Sender is this slide show. |
|||
*/ |
|||
ofEvent<ofEventArgs> slideshowWillLoopEvent; |
|||
|
|||
protected: |
|||
Settings settings; |
|||
std::vector<std::shared_ptr<magSlide>> slides; |
|||
|
|||
private: |
|||
// std::shared_ptr<magSlide> currentSlide;
|
|||
std::vector<std::shared_ptr<magSlide>> activeSlides; |
|||
void enqueueSlide(std::shared_ptr<magSlide> slide, uint64_t startTime); |
|||
|
|||
uint64_t lastTime; |
|||
uint64_t deltaTime; |
|||
uint64_t runningTime; |
|||
|
|||
bool isInitialized = false; |
|||
bool isPlaying = false; |
|||
int currentSlideIndex = 0; |
|||
int direction = 1; |
|||
int loopCount = 0; |
|||
ofx::piMapper::DirectoryWatcher * directoryWatcher; |
|||
void fileAddedListener(const void * sender); |
|||
void fileRemovedListener(const void * sender); |
|||
bool doInit; |
|||
bool doPlayNextSlide = false; |
|||
}; |
|||
|
|||
|
|||
#endif |
|||
|
@ -1,60 +1,60 @@ |
|||
//
|
|||
// magSlideTransition.cpp
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#include "magSlideTransition.h" |
|||
|
|||
void magSlideTransition::start(std::shared_ptr<magSlide> nextSlide) |
|||
{ |
|||
runningTime = 0; |
|||
active = true; |
|||
this->nextSlide = nextSlide; |
|||
} |
|||
|
|||
void magSlideTransition::update(uint64_t timeDelta) |
|||
{ |
|||
if (!active) return; |
|||
|
|||
runningTime += timeDelta; |
|||
if (runningTime >= duration) |
|||
{ |
|||
ofEventArgs arghh; // arghhhh...
|
|||
nextSlide->setOpacity(255); |
|||
nextSlide->setPosition(0, 0); |
|||
end(); |
|||
transitionCompleteEvent.notify(this, arghh); |
|||
active = false; |
|||
} |
|||
|
|||
} |
|||
|
|||
uint64_t magSlideTransition::getRunningTime() |
|||
{ |
|||
return runningTime; |
|||
} |
|||
|
|||
float magSlideTransition::getNormalizedTime() |
|||
{ |
|||
return (double)runningTime / (double)duration; |
|||
} |
|||
|
|||
|
|||
void magDissolveTransition::draw() |
|||
{ |
|||
slide->setOpacity(255 - (getNormalizedTime() * 255)); |
|||
nextSlide->setOpacity(getNormalizedTime()*255); |
|||
} |
|||
|
|||
void magDissolveTransition::start(std::shared_ptr<magSlide> nextSlide) |
|||
{ |
|||
magSlideTransition::start(nextSlide); |
|||
nextSlide->setOpacity(0); |
|||
} |
|||
|
|||
void magDissolveTransition::end() |
|||
{ |
|||
nextSlide->setOpacity(255); |
|||
slide->setOpacity(0); |
|||
} |
|||
//
|
|||
// magSlideTransition.cpp
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#include "magSlideTransition.h" |
|||
|
|||
void magSlideTransition::start(std::shared_ptr<magSlide> nextSlide) |
|||
{ |
|||
runningTime = 0; |
|||
active = true; |
|||
this->nextSlide = nextSlide; |
|||
} |
|||
|
|||
void magSlideTransition::update(uint64_t timeDelta) |
|||
{ |
|||
if (!active) return; |
|||
|
|||
runningTime += timeDelta; |
|||
if (runningTime >= duration) |
|||
{ |
|||
ofEventArgs arghh; // arghhhh...
|
|||
nextSlide->setOpacity(255); |
|||
nextSlide->setPosition(0, 0); |
|||
end(); |
|||
transitionCompleteEvent.notify(this, arghh); |
|||
active = false; |
|||
} |
|||
|
|||
} |
|||
|
|||
uint64_t magSlideTransition::getRunningTime() |
|||
{ |
|||
return runningTime; |
|||
} |
|||
|
|||
float magSlideTransition::getNormalizedTime() |
|||
{ |
|||
return (double)runningTime / (double)duration; |
|||
} |
|||
|
|||
|
|||
void magDissolveTransition::draw() |
|||
{ |
|||
slide->setOpacity(255 - (getNormalizedTime() * 255)); |
|||
nextSlide->setOpacity(getNormalizedTime()*255); |
|||
} |
|||
|
|||
void magDissolveTransition::start(std::shared_ptr<magSlide> nextSlide) |
|||
{ |
|||
magSlideTransition::start(nextSlide); |
|||
nextSlide->setOpacity(0); |
|||
} |
|||
|
|||
void magDissolveTransition::end() |
|||
{ |
|||
nextSlide->setOpacity(255); |
|||
slide->setOpacity(0); |
|||
} |
|||
|
@ -1,129 +1,129 @@ |
|||
//
|
|||
// magSlideTransition.h
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDETRANSITION_H |
|||
#define MAGSLIDETRANSITION_H |
|||
|
|||
#include "magSlide.h" |
|||
|
|||
class magSlideTransitionFactory; |
|||
|
|||
class magSlideTransition |
|||
{ |
|||
public: |
|||
/**
|
|||
* Subclassing notes: Make sure to provide a value for name in your |
|||
* magSlideTransition subclass. |
|||
*/ |
|||
magSlideTransition() { name = "Void"; } |
|||
/**
|
|||
* Begins the transition. This needs to be called in order for the |
|||
* transition to do anything. |
|||
* @param nextSlide The subsequent slide in the slide show needs to be |
|||
* passed here. |
|||
* |
|||
* You can override this call to set any initial conditions to the transition, |
|||
* but make sure to call this method in your override. |
|||
*/ |
|||
virtual void start(std::shared_ptr<magSlide> nextSlide); |
|||
|
|||
/**
|
|||
* Called automatically when the transition is complete. Useful to set |
|||
* end states for the parameters of the slide and nextSlide. Default implementation |
|||
* does nothing. |
|||
*/ |
|||
virtual void end(){} |
|||
|
|||
/**
|
|||
* NOTE: The transition settings system is not yet implemented. |
|||
* Called when the transition is created. Loads settings for magSlideTransition |
|||
* subclasses. The default implementation does nothing. |
|||
* @param settings ofParameterGroup with settings for your custom magSlideTransition |
|||
* subclass. |
|||
*/ |
|||
virtual void loadSettings(ofParameterGroup &settings){} |
|||
|
|||
/**
|
|||
* Updates the transition. |
|||
* @param timeDelta The elapsed time (in ms.) between the last call to update() and |
|||
* this one (i.e. the frame time). |
|||
* |
|||
* If you need to override update, make sure to call this implementation |
|||
* in your subclass. |
|||
*/ |
|||
virtual void update(uint64_t timeDelta); |
|||
|
|||
/**
|
|||
* Draws the transition. Default implementation does nothing. |
|||
*/ |
|||
virtual void draw(){ |
|||
ofLogNotice("magSlideTransition") << "transition draw - this should be overriden " << getNormalizedTime(); |
|||
} |
|||
|
|||
/**
|
|||
* Current running time in milliseconds. |
|||
* @return uint64_t |
|||
*/ |
|||
uint64_t getRunningTime(); |
|||
|
|||
/**
|
|||
* Returns the current time in normalized form. |
|||
* 0 = start, 1 = end. |
|||
* @return Float between 0 and 1. |
|||
*/ |
|||
float getNormalizedTime(); |
|||
|
|||
std::string const &getName() const |
|||
{ |
|||
return name; |
|||
} |
|||
|
|||
const shared_ptr<magSlide> &getNextSlide() const |
|||
{ |
|||
return nextSlide; |
|||
} |
|||
|
|||
bool isActive() const |
|||
{ |
|||
return active; |
|||
} |
|||
|
|||
/**
|
|||
* Sender is a raw pointer to this magSlideTransition |
|||
*/ |
|||
ofEvent<ofEventArgs> transitionCompleteEvent; |
|||
|
|||
protected: |
|||
std::string name; |
|||
std::shared_ptr<magSlide> slide; |
|||
std::shared_ptr<magSlide> nextSlide; |
|||
|
|||
uint64_t runningTime; |
|||
uint64_t duration; |
|||
uint64_t endTime; |
|||
bool active = false; |
|||
|
|||
|
|||
protected: |
|||
|
|||
friend class magSlideTransitionFactory; |
|||
}; |
|||
|
|||
class magDissolveTransition : public magSlideTransition |
|||
{ |
|||
public: |
|||
magDissolveTransition() |
|||
{ |
|||
name = "Dissolve"; |
|||
} |
|||
|
|||
void start(std::shared_ptr<magSlide> nextSlide) override; |
|||
|
|||
void draw() override; |
|||
void end() override; |
|||
}; |
|||
|
|||
#endif |
|||
//
|
|||
// magSlideTransition.h
|
|||
// Copyright (c) 2017 Cristobal Mendoza
|
|||
// http://cuppetellimendoza.com
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDETRANSITION_H |
|||
#define MAGSLIDETRANSITION_H |
|||
|
|||
#include "magSlide.h" |
|||
|
|||
class magSlideTransitionFactory; |
|||
|
|||
class magSlideTransition |
|||
{ |
|||
public: |
|||
/**
|
|||
* Subclassing notes: Make sure to provide a value for name in your |
|||
* magSlideTransition subclass. |
|||
*/ |
|||
magSlideTransition() { name = "Void"; } |
|||
/**
|
|||
* Begins the transition. This needs to be called in order for the |
|||
* transition to do anything. |
|||
* @param nextSlide The subsequent slide in the slide show needs to be |
|||
* passed here. |
|||
* |
|||
* You can override this call to set any initial conditions to the transition, |
|||
* but make sure to call this method in your override. |
|||
*/ |
|||
virtual void start(std::shared_ptr<magSlide> nextSlide); |
|||
|
|||
/**
|
|||
* Called automatically when the transition is complete. Useful to set |
|||
* end states for the parameters of the slide and nextSlide. Default implementation |
|||
* does nothing. |
|||
*/ |
|||
virtual void end(){} |
|||
|
|||
/**
|
|||
* NOTE: The transition settings system is not yet implemented. |
|||
* Called when the transition is created. Loads settings for magSlideTransition |
|||
* subclasses. The default implementation does nothing. |
|||
* @param settings ofParameterGroup with settings for your custom magSlideTransition |
|||
* subclass. |
|||
*/ |
|||
virtual void loadSettings(ofParameterGroup &settings){} |
|||
|
|||
/**
|
|||
* Updates the transition. |
|||
* @param timeDelta The elapsed time (in ms.) between the last call to update() and |
|||
* this one (i.e. the frame time). |
|||
* |
|||
* If you need to override update, make sure to call this implementation |
|||
* in your subclass. |
|||
*/ |
|||
virtual void update(uint64_t timeDelta); |
|||
|
|||
/**
|
|||
* Draws the transition. Default implementation does nothing. |
|||
*/ |
|||
virtual void draw(){ |
|||
ofLogNotice("magSlideTransition") << "transition draw - this should be overriden " << getNormalizedTime(); |
|||
} |
|||
|
|||
/**
|
|||
* Current running time in milliseconds. |
|||
* @return uint64_t |
|||
*/ |
|||
uint64_t getRunningTime(); |
|||
|
|||
/**
|
|||
* Returns the current time in normalized form. |
|||
* 0 = start, 1 = end. |
|||
* @return Float between 0 and 1. |
|||
*/ |
|||
float getNormalizedTime(); |
|||
|
|||
std::string const &getName() const |
|||
{ |
|||
return name; |
|||
} |
|||
|
|||
const shared_ptr<magSlide> &getNextSlide() const |
|||
{ |
|||
return nextSlide; |
|||
} |
|||
|
|||
bool isActive() const |
|||
{ |
|||
return active; |
|||
} |
|||
|
|||
/**
|
|||
* Sender is a raw pointer to this magSlideTransition |
|||
*/ |
|||
ofEvent<ofEventArgs> transitionCompleteEvent; |
|||
|
|||
protected: |
|||
std::string name; |
|||
std::shared_ptr<magSlide> slide; |
|||
std::shared_ptr<magSlide> nextSlide; |
|||
|
|||
uint64_t runningTime; |
|||
uint64_t duration; |
|||
uint64_t endTime; |
|||
bool active = false; |
|||
|
|||
|
|||
protected: |
|||
|
|||
friend class magSlideTransitionFactory; |
|||
}; |
|||
|
|||
class magDissolveTransition : public magSlideTransition |
|||
{ |
|||
public: |
|||
magDissolveTransition() |
|||
{ |
|||
name = "Dissolve"; |
|||
} |
|||
|
|||
void start(std::shared_ptr<magSlide> nextSlide) override; |
|||
|
|||
void draw() override; |
|||
void end() override; |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -1,76 +1,76 @@ |
|||
//
|
|||
// Created by Cristobal Mendoza on 12/3/17.
|
|||
//
|
|||
|
|||
#include "magSlideTransitionFactory.h" |
|||
|
|||
/*
|
|||
* |
|||
* |
|||
* |
|||
class Base {}; |
|||
|
|||
class DerivedA : public Base {}; |
|||
class DerivedB : public Base {}; |
|||
class DerivedC : public Base {}; |
|||
|
|||
Base* create(const std::string& type) |
|||
{ |
|||
static std::map<std::string, std::function<Base*()>> type_creator_map = |
|||
{ |
|||
{"DerivedA", [](){return new DerivedA();}}, |
|||
{"DerivedB", [](){return new DerivedB();}}, |
|||
{"DerivedC", [](){return new DerivedC();}} |
|||
}; |
|||
|
|||
auto it = type_creator_map.find(type); |
|||
if(it != type_creator_map.end()) |
|||
{ |
|||
return it->second(); |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
*/ |
|||
|
|||
magSlideTransitionFactory* magSlideTransitionFactory::_instance = 0; |
|||
|
|||
magSlideTransitionFactory::magSlideTransitionFactory() |
|||
{ |
|||
magSlideTransition voidTransition; |
|||
magDissolveTransition dissolve; |
|||
|
|||
registerTransition<magSlideTransition>(voidTransition); |
|||
registerTransition<magDissolveTransition>(dissolve); |
|||
} |
|||
|
|||
magSlideTransitionFactory* magSlideTransitionFactory::instance() |
|||
{ |
|||
if (_instance == 0) |
|||
{ |
|||
_instance = new magSlideTransitionFactory(); |
|||
} |
|||
|
|||
return _instance; |
|||
} |
|||
|
|||
std::shared_ptr<magSlideTransition> |
|||
magSlideTransitionFactory::createTransition(std::string transitionName, std::shared_ptr<magSlide> slide, |
|||
ofParameterGroup &settings, uint64_t duration) |
|||
{ |
|||
std::shared_ptr<magSlideTransition> transition; |
|||
|
|||
if (transitionsMap.count(transitionName) > 0) |
|||
{ |
|||
transition = transitionsMap[transitionName](); |
|||
} |
|||
else |
|||
{ |
|||
transition = transitionsMap[transition->getName()](); |
|||
} |
|||
|
|||
transition->slide = slide; |
|||
transition->duration = duration; |
|||
transition->loadSettings(settings); |
|||
return transition; |
|||
} |
|||
//
|
|||
// Created by Cristobal Mendoza on 12/3/17.
|
|||
//
|
|||
|
|||
#include "magSlideTransitionFactory.h" |
|||
|
|||
/*
|
|||
* |
|||
* |
|||
* |
|||
class Base {}; |
|||
|
|||
class DerivedA : public Base {}; |
|||
class DerivedB : public Base {}; |
|||
class DerivedC : public Base {}; |
|||
|
|||
Base* create(const std::string& type) |
|||
{ |
|||
static std::map<std::string, std::function<Base*()>> type_creator_map = |
|||
{ |
|||
{"DerivedA", [](){return new DerivedA();}}, |
|||
{"DerivedB", [](){return new DerivedB();}}, |
|||
{"DerivedC", [](){return new DerivedC();}} |
|||
}; |
|||
|
|||
auto it = type_creator_map.find(type); |
|||
if(it != type_creator_map.end()) |
|||
{ |
|||
return it->second(); |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
*/ |
|||
|
|||
magSlideTransitionFactory* magSlideTransitionFactory::_instance = 0; |
|||
|
|||
magSlideTransitionFactory::magSlideTransitionFactory() |
|||
{ |
|||
magSlideTransition voidTransition; |
|||
magDissolveTransition dissolve; |
|||
|
|||
registerTransition<magSlideTransition>(voidTransition); |
|||
registerTransition<magDissolveTransition>(dissolve); |
|||
} |
|||
|
|||
magSlideTransitionFactory* magSlideTransitionFactory::instance() |
|||
{ |
|||
if (_instance == 0) |
|||
{ |
|||
_instance = new magSlideTransitionFactory(); |
|||
} |
|||
|
|||
return _instance; |
|||
} |
|||
|
|||
std::shared_ptr<magSlideTransition> |
|||
magSlideTransitionFactory::createTransition(std::string transitionName, std::shared_ptr<magSlide> slide, |
|||
ofParameterGroup &settings, uint64_t duration) |
|||
{ |
|||
std::shared_ptr<magSlideTransition> transition; |
|||
|
|||
if (transitionsMap.count(transitionName) > 0) |
|||
{ |
|||
transition = transitionsMap[transitionName](); |
|||
} |
|||
else |
|||
{ |
|||
transition = transitionsMap[transition->getName()](); |
|||
} |
|||
|
|||
transition->slide = slide; |
|||
transition->duration = duration; |
|||
transition->loadSettings(settings); |
|||
return transition; |
|||
} |
|||
|
@ -1,41 +1,41 @@ |
|||
//
|
|||
// Created by Cristobal Mendoza on 12/3/17.
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDETRANSITIONFACTORY_H |
|||
#define MAGSLIDETRANSITIONFACTORY_H |
|||
|
|||
#include "magSlide.h" |
|||
#include "magSlideTransition.h" |
|||
|
|||
/**
|
|||
* Factory class to register and instantiate transitions. |
|||
*/ |
|||
class magSlideTransitionFactory |
|||
{ |
|||
public: |
|||
static magSlideTransitionFactory* instance(); |
|||
|
|||
std::shared_ptr<magSlideTransition> createTransition(std::string transitionName, |
|||
std::shared_ptr<magSlide> slide, |
|||
ofParameterGroup &group, |
|||
uint64_t duration); |
|||
template<typename T> |
|||
void registerTransition(T transition) |
|||
{ |
|||
if (transitionsMap.count(transition.getName()) == 0) |
|||
{ |
|||
transitionsMap[transition.getName()] = [](){ |
|||
return std::make_shared<T>(); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
protected: |
|||
std::unordered_map<std::string, std::function<std::shared_ptr<magSlideTransition>()>> transitionsMap; |
|||
private: |
|||
static magSlideTransitionFactory* _instance; |
|||
magSlideTransitionFactory(); |
|||
}; |
|||
|
|||
#endif //MAGSLIDETRANSITIONFACTORY_H
|
|||
//
|
|||
// Created by Cristobal Mendoza on 12/3/17.
|
|||
//
|
|||
|
|||
#ifndef MAGSLIDETRANSITIONFACTORY_H |
|||
#define MAGSLIDETRANSITIONFACTORY_H |
|||
|
|||
#include "magSlide.h" |
|||
#include "magSlideTransition.h" |
|||
|
|||
/**
|
|||
* Factory class to register and instantiate transitions. |
|||
*/ |
|||
class magSlideTransitionFactory |
|||
{ |
|||
public: |
|||
static magSlideTransitionFactory* instance(); |
|||
|
|||
std::shared_ptr<magSlideTransition> createTransition(std::string transitionName, |
|||
std::shared_ptr<magSlide> slide, |
|||
ofParameterGroup &group, |
|||
uint64_t duration); |
|||
template<typename T> |
|||
void registerTransition(T transition) |
|||
{ |
|||
if (transitionsMap.count(transition.getName()) == 0) |
|||
{ |
|||
transitionsMap[transition.getName()] = [](){ |
|||
return std::make_shared<T>(); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
protected: |
|||
std::unordered_map<std::string, std::function<std::shared_ptr<magSlideTransition>()>> transitionsMap; |
|||
private: |
|||
static magSlideTransitionFactory* _instance; |
|||
magSlideTransitionFactory(); |
|||
}; |
|||
|
|||
#endif //MAGSLIDETRANSITIONFACTORY_H
|
|||
|
@ -1,87 +1,87 @@ |
|||
// #include "SyphonSource.h"
|
|||
//
|
|||
// void SyphonSource::setup(){
|
|||
// // Give our source a decent name
|
|||
// name = "Syphon Source";
|
|||
//
|
|||
// // Allocate our FBO source, decide how big it should be
|
|||
// allocate(500, 500);
|
|||
//
|
|||
// //setup our directory
|
|||
// dir.setup();
|
|||
// //setup our client
|
|||
// mClient.setup();
|
|||
//
|
|||
// //register for our directory's callbacks
|
|||
// ofAddListener(dir.events.serverAnnounced, this, &SyphonSource::serverAnnounced);
|
|||
// // not yet implemented
|
|||
// //ofAddListener(dir.events.serverUpdated, this, &ofApp::serverUpdated);
|
|||
// ofAddListener(dir.events.serverRetired, this, &SyphonSource::serverRetired);
|
|||
//
|
|||
// dirIdx = -1;
|
|||
// }
|
|||
//
|
|||
// //these are our directory's callbacks
|
|||
// void SyphonSource::serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg)
|
|||
// {
|
|||
// for( auto& dir : arg.servers ){
|
|||
// ofLogNotice("ofxSyphonServerDirectory Server Announced")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
|
|||
// }
|
|||
// dirIdx = 0;
|
|||
// }
|
|||
//
|
|||
// void SyphonSource::serverUpdated(ofxSyphonServerDirectoryEventArgs &arg)
|
|||
// {
|
|||
// for( auto& dir : arg.servers ){
|
|||
// ofLogNotice("ofxSyphonServerDirectory Server Updated")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
|
|||
// }
|
|||
// dirIdx = 0;
|
|||
// }
|
|||
//
|
|||
// void SyphonSource::serverRetired(ofxSyphonServerDirectoryEventArgs &arg)
|
|||
// {
|
|||
// for( auto& dir : arg.servers ){
|
|||
// ofLogNotice("ofxSyphonServerDirectory Server Retired")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
|
|||
// }
|
|||
// dirIdx = 0;
|
|||
// }
|
|||
//
|
|||
//
|
|||
// // Don't do any drawing here
|
|||
// void SyphonSource::update(){
|
|||
//
|
|||
// }
|
|||
//
|
|||
// // No need to take care of fbo.begin() and fbo.end() here.
|
|||
// // All within draw() is being rendered into fbo;
|
|||
// void SyphonSource::draw(){
|
|||
// if(dir.isValidIndex(dirIdx))
|
|||
// mClient.draw(0, 0);
|
|||
// }
|
|||
//
|
|||
// //--------------------------------------------------------------
|
|||
// void SyphonSource::keyReleased(int key){
|
|||
// //press any key to move through all available Syphon servers
|
|||
// if (dir.size() > 0)
|
|||
// {
|
|||
// dirIdx++;
|
|||
// if(dirIdx > dir.size() - 1)
|
|||
// dirIdx = 0;
|
|||
//
|
|||
// mClient.set(dir.getDescription(dirIdx));
|
|||
// string serverName = mClient.getServerName();
|
|||
// string appName = mClient.getApplicationName();
|
|||
//
|
|||
// if(serverName == ""){
|
|||
// serverName = "null";
|
|||
// }
|
|||
// if(appName == ""){
|
|||
// appName = "null";
|
|||
// }
|
|||
// ofSetWindowTitle(serverName + ":" + appName);
|
|||
// }
|
|||
// else
|
|||
// {
|
|||
// ofSetWindowTitle("No Server");
|
|||
// }
|
|||
// }
|
|||
// #include "SyphonSource.h"
|
|||
//
|
|||
// void SyphonSource::setup(){
|
|||
// // Give our source a decent name
|
|||
// name = "Syphon Source";
|
|||
//
|
|||
// // Allocate our FBO source, decide how big it should be
|
|||
// allocate(500, 500);
|
|||
//
|
|||
// //setup our directory
|
|||
// dir.setup();
|
|||
// //setup our client
|
|||
// mClient.setup();
|
|||
//
|
|||
// //register for our directory's callbacks
|
|||
// ofAddListener(dir.events.serverAnnounced, this, &SyphonSource::serverAnnounced);
|
|||
// // not yet implemented
|
|||
// //ofAddListener(dir.events.serverUpdated, this, &ofApp::serverUpdated);
|
|||
// ofAddListener(dir.events.serverRetired, this, &SyphonSource::serverRetired);
|
|||
//
|
|||
// dirIdx = -1;
|
|||
// }
|
|||
//
|
|||
// //these are our directory's callbacks
|
|||
// void SyphonSource::serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg)
|
|||
// {
|
|||
// for( auto& dir : arg.servers ){
|
|||
// ofLogNotice("ofxSyphonServerDirectory Server Announced")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
|
|||
// }
|
|||
// dirIdx = 0;
|
|||
// }
|
|||
//
|
|||
// void SyphonSource::serverUpdated(ofxSyphonServerDirectoryEventArgs &arg)
|
|||
// {
|
|||
// for( auto& dir : arg.servers ){
|
|||
// ofLogNotice("ofxSyphonServerDirectory Server Updated")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
|
|||
// }
|
|||
// dirIdx = 0;
|
|||
// }
|
|||
//
|
|||
// void SyphonSource::serverRetired(ofxSyphonServerDirectoryEventArgs &arg)
|
|||
// {
|
|||
// for( auto& dir : arg.servers ){
|
|||
// ofLogNotice("ofxSyphonServerDirectory Server Retired")<<" Server Name: "<<dir.serverName <<" | App Name: "<<dir.appName;
|
|||
// }
|
|||
// dirIdx = 0;
|
|||
// }
|
|||
//
|
|||
//
|
|||
// // Don't do any drawing here
|
|||
// void SyphonSource::update(){
|
|||
//
|
|||
// }
|
|||
//
|
|||
// // No need to take care of fbo.begin() and fbo.end() here.
|
|||
// // All within draw() is being rendered into fbo;
|
|||
// void SyphonSource::draw(){
|
|||
// if(dir.isValidIndex(dirIdx))
|
|||
// mClient.draw(0, 0);
|
|||
// }
|
|||
//
|
|||
// //--------------------------------------------------------------
|
|||
// void SyphonSource::keyReleased(int key){
|
|||
// //press any key to move through all available Syphon servers
|
|||
// if (dir.size() > 0)
|
|||
// {
|
|||
// dirIdx++;
|
|||
// if(dirIdx > dir.size() - 1)
|
|||
// dirIdx = 0;
|
|||
//
|
|||
// mClient.set(dir.getDescription(dirIdx));
|
|||
// string serverName = mClient.getServerName();
|
|||
// string appName = mClient.getApplicationName();
|
|||
//
|
|||
// if(serverName == ""){
|
|||
// serverName = "null";
|
|||
// }
|
|||
// if(appName == ""){
|
|||
// appName = "null";
|
|||
// }
|
|||
// ofSetWindowTitle(serverName + ":" + appName);
|
|||
// }
|
|||
// else
|
|||
// {
|
|||
// ofSetWindowTitle("No Server");
|
|||
// }
|
|||
// }
|
|||
|
@ -1,21 +1,21 @@ |
|||
// #pragma once
|
|||
//
|
|||
// #include "ofMain.h"
|
|||
// #include "FboSource.h"
|
|||
// #include "ofxSyphon.h"
|
|||
// class SyphonSource : public ofx::piMapper::FboSource {
|
|||
// public:
|
|||
// void setup();
|
|||
// void update();
|
|||
// void draw();
|
|||
//
|
|||
// void keyReleased(int key);
|
|||
//
|
|||
// void serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg);
|
|||
// void serverUpdated(ofxSyphonServerDirectoryEventArgs &args);
|
|||
// void serverRetired(ofxSyphonServerDirectoryEventArgs &arg);
|
|||
//
|
|||
// ofxSyphonServerDirectory dir;
|
|||
// ofxSyphonClient mClient;
|
|||
// int dirIdx;
|
|||
// };
|
|||
// #pragma once
|
|||
//
|
|||
// #include "ofMain.h"
|
|||
// #include "FboSource.h"
|
|||
// #include "ofxSyphon.h"
|
|||
// class SyphonSource : public ofx::piMapper::FboSource {
|
|||
// public:
|
|||
// void setup();
|
|||
// void update();
|
|||
// void draw();
|
|||
//
|
|||
// void keyReleased(int key);
|
|||
//
|
|||
// void serverAnnounced(ofxSyphonServerDirectoryEventArgs &arg);
|
|||
// void serverUpdated(ofxSyphonServerDirectoryEventArgs &args);
|
|||
// void serverRetired(ofxSyphonServerDirectoryEventArgs &arg);
|
|||
//
|
|||
// ofxSyphonServerDirectory dir;
|
|||
// ofxSyphonClient mClient;
|
|||
// int dirIdx;
|
|||
// };
|
|||
|
@ -1,7 +1,7 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1024, 768, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1024, 768, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
|
@ -1,57 +1,57 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
|
|||
// Enable or disable audio for video sources globally
|
|||
// Set this to false to save resources on the Raspberry Pi
|
|||
ofx::piMapper::VideoSource::enableAudio = true; |
|||
ofx::piMapper::VideoSource::useHDMIForAudio = false; |
|||
|
|||
// Register our sources.
|
|||
// This should be done before mapper.setup().
|
|||
piMapper.registerFboSource(ScanLSource); |
|||
piMapper.registerFboSource(QuadiSource); |
|||
piMapper.registerFboSource(CircLSource); |
|||
piMapper.registerFboSource(BricksSource); |
|||
//piMapper.registerFboSource(SyphonClient);
|
|||
//piMapper.registerFboSource(slideShowSource);
|
|||
piMapper.setup(); |
|||
|
|||
// This will set the app fullscreen if compiled on Raspberry Pi.
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofSetFullscreen(true); |
|||
#endif |
|||
|
|||
// Start slideshow.
|
|||
//slideShowSource.play();
|
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
piMapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
piMapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
piMapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
piMapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
|
|||
piMapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
piMapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
piMapper.mouseDragged(x, y, button); |
|||
} |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
|
|||
// Enable or disable audio for video sources globally
|
|||
// Set this to false to save resources on the Raspberry Pi
|
|||
ofx::piMapper::VideoSource::enableAudio = true; |
|||
ofx::piMapper::VideoSource::useHDMIForAudio = false; |
|||
|
|||
// Register our sources.
|
|||
// This should be done before mapper.setup().
|
|||
piMapper.registerFboSource(ScanLSource); |
|||
piMapper.registerFboSource(QuadiSource); |
|||
piMapper.registerFboSource(CircLSource); |
|||
piMapper.registerFboSource(BricksSource); |
|||
//piMapper.registerFboSource(SyphonClient);
|
|||
//piMapper.registerFboSource(slideShowSource);
|
|||
piMapper.setup(); |
|||
|
|||
// This will set the app fullscreen if compiled on Raspberry Pi.
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofSetFullscreen(true); |
|||
#endif |
|||
|
|||
// Start slideshow.
|
|||
//slideShowSource.play();
|
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
piMapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
piMapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
piMapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
piMapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
|
|||
piMapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
piMapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
piMapper.mouseDragged(x, y, button); |
|||
} |
|||
|
@ -1,37 +1,37 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "VideoSource.h" |
|||
#include "ScanlineSource.h" |
|||
#include "CircleSource.h" |
|||
#include "QuadSource.h" |
|||
#include "BrickSource.h" |
|||
//#include "SyphonSource.h"
|
|||
#include "magSlideShowSource.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper piMapper; |
|||
|
|||
// By using a custom source that is derived from FboSource
|
|||
// you will be able to see the source listed in sources editor
|
|||
ScanlineSource ScanLSource; |
|||
QuadSource QuadiSource; |
|||
CircleSource CircLSource; |
|||
BrickSource BricksSource; |
|||
//SyphonSource SyphonClient;
|
|||
magSlideShowSource slideShowSource; |
|||
|
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "VideoSource.h" |
|||
#include "ScanlineSource.h" |
|||
#include "CircleSource.h" |
|||
#include "QuadSource.h" |
|||
#include "BrickSource.h" |
|||
//#include "SyphonSource.h"
|
|||
#include "magSlideShowSource.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper piMapper; |
|||
|
|||
// By using a custom source that is derived from FboSource
|
|||
// you will be able to see the source listed in sources editor
|
|||
ScanlineSource ScanLSource; |
|||
QuadSource QuadiSource; |
|||
CircleSource CircLSource; |
|||
BrickSource BricksSource; |
|||
//SyphonSource SyphonClient;
|
|||
magSlideShowSource slideShowSource; |
|||
|
|||
}; |
|||
|
@ -1,6 +1,6 @@ |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
bin/*.app |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
bin/*.app |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,4 +1,4 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
|
@ -1,3 +1,3 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,36 +1,36 @@ |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>431.000000000</x> |
|||
<y>13.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>781.000000000</x> |
|||
<y>363.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>81.000000000</x> |
|||
<y>363.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image1.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>431.000000000</x> |
|||
<y>13.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>781.000000000</x> |
|||
<y>363.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>81.000000000</x> |
|||
<y>363.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image1.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,9 +1,9 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofGLFWWindowSettings settings; |
|||
settings.windowMode = OF_FULLSCREEN; |
|||
ofCreateWindow(settings); |
|||
ofRunApp(new ofApp); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofGLFWWindowSettings settings; |
|||
settings.windowMode = OF_FULLSCREEN; |
|||
ofCreateWindow(settings); |
|||
ofRunApp(new ofApp); |
|||
} |
|||
|
@ -1,124 +1,124 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
mapper.setup(); |
|||
|
|||
// Set different info text for PocketVJ
|
|||
std::string multilineInfoText = |
|||
"Custom ofxPiMapper shortcuts\n\n" |
|||
"Good day user.\n" |
|||
"Shortcuts have been customized.\n" |
|||
"Please make sure to provide your own documentation."; |
|||
mapper.setInfoText(multilineInfoText); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
mapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
mapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
if(key == '1'){ |
|||
mapper.setMode(ofx::piMapper::PRESENTATION_MODE); |
|||
}else if(key == '2'){ |
|||
mapper.setMode(ofx::piMapper::TEXTURE_MODE); |
|||
}else if(key == '3'){ |
|||
mapper.setMode(ofx::piMapper::MAPPING_MODE); |
|||
}else if(key == '4'){ |
|||
mapper.setMode(ofx::piMapper::SOURCE_MODE); |
|||
}else if(key == 'c'){ |
|||
mapper.toggleInfo(); |
|||
}else if(key == 't'){ |
|||
mapper.createSurface(ofx::piMapper::TRIANGLE_SURFACE); |
|||
}else if(key == 'q'){ |
|||
mapper.createSurface(ofx::piMapper::QUAD_SURFACE); |
|||
}else if(key == 'r'){ |
|||
mapper.createSurface(ofx::piMapper::CIRCLE_SURFACE); |
|||
}else if(key == 'x'){ |
|||
mapper.createSurface(ofx::piMapper::HEXAGON_SURFACE); |
|||
}else if(key == 'g'){ |
|||
mapper.createSurface(ofx::piMapper::GRID_WARP_SURFACE); |
|||
}else if(key == 'a'){ |
|||
mapper.duplicateSurface(); |
|||
}else if(key == 'o'){ |
|||
mapper.scaleUp(); |
|||
}else if(key == 'i'){ |
|||
mapper.scaleDown(); |
|||
}else if(key == 'p'){ |
|||
mapper.togglePerspective(); |
|||
}else if(key == 'v'){ |
|||
mapper.addGridColumn(); |
|||
}else if(key == 'b'){ |
|||
mapper.removeGridColumn(); |
|||
}else if(key == 'n'){ |
|||
mapper.addGridRow(); |
|||
}else if(key == 'm'){ |
|||
mapper.removeGridRow(); |
|||
}else if(key == '.'){ |
|||
mapper.selectNextSurface(); |
|||
}else if(key == ','){ |
|||
mapper.selectPrevSurface(); |
|||
}else if(key == 'k'){ |
|||
mapper.selectNextVertex(); |
|||
}else if(key == 'l'){ |
|||
mapper.selectPrevVertex(); |
|||
}else if(key == 'h'){ |
|||
mapper.moveLayerUp(); |
|||
}else if(key == 'j'){ |
|||
mapper.moveLayerDown(); |
|||
}else if(key == 's'){ |
|||
mapper.saveProject(); |
|||
}else if(key == 'y'){ |
|||
mapper.toggleLayerPanel(); |
|||
}else if(key == 'z'){ |
|||
mapper.undo(); |
|||
}else if(key == 'd'){ |
|||
mapper.eraseSurface(mapper.getSelectedSurface()); |
|||
}else if(key == 'w'){ |
|||
mapper.togglePause(); |
|||
}else if(key == '5'){ |
|||
mapper.setNextSource(); |
|||
}else if(key == '8'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, -1.0f, 0.0f)); |
|||
}else if(key == '9'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, 1.0f, 0.0f)); |
|||
}else if(key == '7'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(-1.0f, 0.0f, 0.0f)); |
|||
}else if(key == '0'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(1.0f, 0.0f, 0.0f)); |
|||
}else if(key == '/'){ |
|||
bool shiftIsDown = mapper.toggleShift(); |
|||
if(shiftIsDown){ |
|||
ofLogNotice("ofApp") << "Shift key is down"; |
|||
}else{ |
|||
ofLogNotice("ofApp") << "Shift key is up"; |
|||
} |
|||
} |
|||
|
|||
/* For these one has to figure out her own ways.
|
|||
* rbt Reboot (Raspberry Pi only) |
|||
* sdn Shutdown (Raspberry Pi only) |
|||
* new Clear composition (remove all surfaces) |
|||
* ext Exit application and return to command line |
|||
*/ |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
mapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
mapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
mapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
mapper.mouseDragged(x, y, button); |
|||
} |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
mapper.setup(); |
|||
|
|||
// Set different info text for PocketVJ
|
|||
std::string multilineInfoText = |
|||
"Custom ofxPiMapper shortcuts\n\n" |
|||
"Good day user.\n" |
|||
"Shortcuts have been customized.\n" |
|||
"Please make sure to provide your own documentation."; |
|||
mapper.setInfoText(multilineInfoText); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
mapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
mapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
if(key == '1'){ |
|||
mapper.setMode(ofx::piMapper::PRESENTATION_MODE); |
|||
}else if(key == '2'){ |
|||
mapper.setMode(ofx::piMapper::TEXTURE_MODE); |
|||
}else if(key == '3'){ |
|||
mapper.setMode(ofx::piMapper::MAPPING_MODE); |
|||
}else if(key == '4'){ |
|||
mapper.setMode(ofx::piMapper::SOURCE_MODE); |
|||
}else if(key == 'c'){ |
|||
mapper.toggleInfo(); |
|||
}else if(key == 't'){ |
|||
mapper.createSurface(ofx::piMapper::TRIANGLE_SURFACE); |
|||
}else if(key == 'q'){ |
|||
mapper.createSurface(ofx::piMapper::QUAD_SURFACE); |
|||
}else if(key == 'r'){ |
|||
mapper.createSurface(ofx::piMapper::CIRCLE_SURFACE); |
|||
}else if(key == 'x'){ |
|||
mapper.createSurface(ofx::piMapper::HEXAGON_SURFACE); |
|||
}else if(key == 'g'){ |
|||
mapper.createSurface(ofx::piMapper::GRID_WARP_SURFACE); |
|||
}else if(key == 'a'){ |
|||
mapper.duplicateSurface(); |
|||
}else if(key == 'o'){ |
|||
mapper.scaleUp(); |
|||
}else if(key == 'i'){ |
|||
mapper.scaleDown(); |
|||
}else if(key == 'p'){ |
|||
mapper.togglePerspective(); |
|||
}else if(key == 'v'){ |
|||
mapper.addGridColumn(); |
|||
}else if(key == 'b'){ |
|||
mapper.removeGridColumn(); |
|||
}else if(key == 'n'){ |
|||
mapper.addGridRow(); |
|||
}else if(key == 'm'){ |
|||
mapper.removeGridRow(); |
|||
}else if(key == '.'){ |
|||
mapper.selectNextSurface(); |
|||
}else if(key == ','){ |
|||
mapper.selectPrevSurface(); |
|||
}else if(key == 'k'){ |
|||
mapper.selectNextVertex(); |
|||
}else if(key == 'l'){ |
|||
mapper.selectPrevVertex(); |
|||
}else if(key == 'h'){ |
|||
mapper.moveLayerUp(); |
|||
}else if(key == 'j'){ |
|||
mapper.moveLayerDown(); |
|||
}else if(key == 's'){ |
|||
mapper.saveProject(); |
|||
}else if(key == 'y'){ |
|||
mapper.toggleLayerPanel(); |
|||
}else if(key == 'z'){ |
|||
mapper.undo(); |
|||
}else if(key == 'd'){ |
|||
mapper.eraseSurface(mapper.getSelectedSurface()); |
|||
}else if(key == 'w'){ |
|||
mapper.togglePause(); |
|||
}else if(key == '5'){ |
|||
mapper.setNextSource(); |
|||
}else if(key == '8'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, -1.0f, 0.0f)); |
|||
}else if(key == '9'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(0.0f, 1.0f, 0.0f)); |
|||
}else if(key == '7'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(-1.0f, 0.0f, 0.0f)); |
|||
}else if(key == '0'){ |
|||
mapper.moveSelection(ofx::piMapper::Vec3(1.0f, 0.0f, 0.0f)); |
|||
}else if(key == '/'){ |
|||
bool shiftIsDown = mapper.toggleShift(); |
|||
if(shiftIsDown){ |
|||
ofLogNotice("ofApp") << "Shift key is down"; |
|||
}else{ |
|||
ofLogNotice("ofApp") << "Shift key is up"; |
|||
} |
|||
} |
|||
|
|||
/* For these one has to figure out her own ways.
|
|||
* rbt Reboot (Raspberry Pi only) |
|||
* sdn Shutdown (Raspberry Pi only) |
|||
* new Clear composition (remove all surfaces) |
|||
* ext Exit application and return to command line |
|||
*/ |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
mapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
mapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
mapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
mapper.mouseDragged(x, y, button); |
|||
} |
|||
|
@ -1,21 +1,21 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "Vec3.h" |
|||
|
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper mapper; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "Vec3.h" |
|||
|
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper mapper; |
|||
}; |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,22 +1,22 @@ |
|||
# Remote Control Client for ofxPiMapper |
|||
|
|||
This example demonstrates a TCP **client** for ofxPiMapper remote control. The other part of this is the [Remote Control Server](../example_remote-server). What it does is the following. |
|||
|
|||
- Reads IP address and port defined in `bin/data/config.json`. |
|||
- Connects to server by using the IP address and port. |
|||
- Once connected, ofxPiMapper configuration is received. |
|||
- Instance of ofxPiMapper class is being set up. |
|||
- TCP messages are sent on every keyboard and mouse event. |
|||
|
|||
In reality this example should be used as the remote control residing on your laptop computa. Set up your Raspberry Pi, connect it to the same network as your laptop and get to know the IP address of the Raspberry Pi. Update `bin/data/config.json` with the IP address of your Raspberry Pi and launch the app! |
|||
|
|||
**Warning!** Sources are not being sent. Click once with the mouse after the application launches to see the borders of the surfaces. There should be a green rectangle visible in the top left corner of the screen if the connection is successfull. |
|||
|
|||
## Dependencies |
|||
|
|||
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code. |
|||
|
|||
``` |
|||
cd openFrameworks/addons |
|||
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON |
|||
``` |
|||
# Remote Control Client for ofxPiMapper |
|||
|
|||
This example demonstrates a TCP **client** for ofxPiMapper remote control. The other part of this is the [Remote Control Server](../example_remote-server). What it does is the following. |
|||
|
|||
- Reads IP address and port defined in `bin/data/config.json`. |
|||
- Connects to server by using the IP address and port. |
|||
- Once connected, ofxPiMapper configuration is received. |
|||
- Instance of ofxPiMapper class is being set up. |
|||
- TCP messages are sent on every keyboard and mouse event. |
|||
|
|||
In reality this example should be used as the remote control residing on your laptop computa. Set up your Raspberry Pi, connect it to the same network as your laptop and get to know the IP address of the Raspberry Pi. Update `bin/data/config.json` with the IP address of your Raspberry Pi and launch the app! |
|||
|
|||
**Warning!** Sources are not being sent. Click once with the mouse after the application launches to see the borders of the surfaces. There should be a green rectangle visible in the top left corner of the screen if the connection is successfull. |
|||
|
|||
## Dependencies |
|||
|
|||
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code. |
|||
|
|||
``` |
|||
cd openFrameworks/addons |
|||
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON |
|||
``` |
|||
|
@ -1,6 +1,6 @@ |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
|
@ -1,5 +1,5 @@ |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,4 +1,4 @@ |
|||
{ |
|||
"ip":"127.0.0.1", |
|||
"port":9999 |
|||
} |
|||
{ |
|||
"ip":"127.0.0.1", |
|||
"port":9999 |
|||
} |
|||
|
@ -1,36 +1,36 @@ |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>640.000000000</x> |
|||
<y>50.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1230.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>50.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>video</source-type> |
|||
<source-name>gene-nsynthesis-loop-b.mp4</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>640.000000000</x> |
|||
<y>50.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1230.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>50.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>video</source-type> |
|||
<source-name>gene-nsynthesis-loop-b.mp4</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,49 +1,49 @@ |
|||
#include "TCPClient.h" |
|||
|
|||
shared_ptr<TCPClient> TCPClient::_instance = 0; |
|||
|
|||
shared_ptr<TCPClient> TCPClient::instance(){ |
|||
if(_instance == 0){ |
|||
_instance = shared_ptr<TCPClient>(new TCPClient); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
TCPClient::TCPClient(){ |
|||
|
|||
} |
|||
|
|||
void TCPClient::setup(string ip, int port){ |
|||
_tcpClient.setup(ip, port); |
|||
} |
|||
|
|||
void TCPClient::update(){ |
|||
if(_tcpClient.isConnected()){ |
|||
string rx = _tcpClient.receive(); |
|||
if(rx.length() > 0){ |
|||
ofxJSONElement json; |
|||
json["event"] = "received"; |
|||
json["data"] = rx; |
|||
|
|||
ofMessage m(json.getRawString()); |
|||
ofSendMessage(m); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void TCPClient::draw(){ |
|||
if(_tcpClient.isConnected()){ |
|||
ofSetColor(0, 255, 0); |
|||
}else{ |
|||
ofSetColor(255, 0, 0); |
|||
} |
|||
|
|||
ofPushMatrix(); |
|||
ofTranslate(10, 10); |
|||
ofDrawRectangle(0, 0, 10, 10); |
|||
ofPopMatrix(); |
|||
} |
|||
|
|||
void TCPClient::send(string message){ |
|||
_tcpClient.send(message); |
|||
} |
|||
#include "TCPClient.h" |
|||
|
|||
shared_ptr<TCPClient> TCPClient::_instance = 0; |
|||
|
|||
shared_ptr<TCPClient> TCPClient::instance(){ |
|||
if(_instance == 0){ |
|||
_instance = shared_ptr<TCPClient>(new TCPClient); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
TCPClient::TCPClient(){ |
|||
|
|||
} |
|||
|
|||
void TCPClient::setup(string ip, int port){ |
|||
_tcpClient.setup(ip, port); |
|||
} |
|||
|
|||
void TCPClient::update(){ |
|||
if(_tcpClient.isConnected()){ |
|||
string rx = _tcpClient.receive(); |
|||
if(rx.length() > 0){ |
|||
ofxJSONElement json; |
|||
json["event"] = "received"; |
|||
json["data"] = rx; |
|||
|
|||
ofMessage m(json.getRawString()); |
|||
ofSendMessage(m); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void TCPClient::draw(){ |
|||
if(_tcpClient.isConnected()){ |
|||
ofSetColor(0, 255, 0); |
|||
}else{ |
|||
ofSetColor(255, 0, 0); |
|||
} |
|||
|
|||
ofPushMatrix(); |
|||
ofTranslate(10, 10); |
|||
ofDrawRectangle(0, 0, 10, 10); |
|||
ofPopMatrix(); |
|||
} |
|||
|
|||
void TCPClient::send(string message){ |
|||
_tcpClient.send(message); |
|||
} |
|||
|
@ -1,22 +1,22 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxNetwork.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class TCPClient{ |
|||
public: |
|||
static shared_ptr<TCPClient> instance(); |
|||
|
|||
void setup(string ip, int port); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void send(string message); |
|||
|
|||
private: |
|||
TCPClient(); |
|||
static shared_ptr<TCPClient> _instance; |
|||
|
|||
ofxTCPClient _tcpClient; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxNetwork.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class TCPClient{ |
|||
public: |
|||
static shared_ptr<TCPClient> instance(); |
|||
|
|||
void setup(string ip, int port); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void send(string message); |
|||
|
|||
private: |
|||
TCPClient(); |
|||
static shared_ptr<TCPClient> _instance; |
|||
|
|||
ofxTCPClient _tcpClient; |
|||
}; |
|||
|
@ -1,7 +1,7 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1280, 800, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1280, 800, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
|
@ -1,109 +1,109 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
|
|||
isMapperSetup = false; |
|||
|
|||
// Set IP address of your RasPi in data/config.json
|
|||
ofxJSONElement json; |
|||
json.open("config.json"); |
|||
TCPClient::instance()->setup(json["ip"].asString(), json["port"].asInt()); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
TCPClient::instance()->update(); |
|||
if(isMapperSetup){ |
|||
mapper.update(); |
|||
} |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
TCPClient::instance()->draw(); |
|||
if(isMapperSetup){ |
|||
mapper.draw(); |
|||
} |
|||
} |
|||
|
|||
// This is where we get configuration from the server part of this.
|
|||
void ofApp::gotMessage(ofMessage m){ |
|||
ofxJSONElement json; |
|||
bool ok = json.parse(m.message); |
|||
if(ok){ |
|||
if(json["event"] == "received"){ |
|||
std::string buffer = json["data"].asString(); |
|||
ofxXmlSettings xml; |
|||
xml.loadFromBuffer(buffer); |
|||
xml.save("ofxpimapper.xml"); |
|||
|
|||
mapper.setup(); |
|||
isMapperSetup = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
if(isMapperSetup){ |
|||
mapper.keyPressed(key); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "keyPressed"; |
|||
json["key"] = key; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
if(isMapperSetup){ |
|||
mapper.keyReleased(key); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "keyReleased"; |
|||
json["key"] = key; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
if(isMapperSetup){ |
|||
mapper.mousePressed(x, y, button); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "mousePressed"; |
|||
json["x"] = x; |
|||
json["y"] = y; |
|||
json["button"] = button; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
if(isMapperSetup){ |
|||
mapper.mouseReleased(x, y, button); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "mouseReleased"; |
|||
json["x"] = x; |
|||
json["y"] = y; |
|||
json["button"] = button; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
if(isMapperSetup){ |
|||
mapper.mouseDragged(x, y, button); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "mouseDragged"; |
|||
json["x"] = x; |
|||
json["y"] = y; |
|||
json["button"] = button; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
|
|||
isMapperSetup = false; |
|||
|
|||
// Set IP address of your RasPi in data/config.json
|
|||
ofxJSONElement json; |
|||
json.open("config.json"); |
|||
TCPClient::instance()->setup(json["ip"].asString(), json["port"].asInt()); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
TCPClient::instance()->update(); |
|||
if(isMapperSetup){ |
|||
mapper.update(); |
|||
} |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
TCPClient::instance()->draw(); |
|||
if(isMapperSetup){ |
|||
mapper.draw(); |
|||
} |
|||
} |
|||
|
|||
// This is where we get configuration from the server part of this.
|
|||
void ofApp::gotMessage(ofMessage m){ |
|||
ofxJSONElement json; |
|||
bool ok = json.parse(m.message); |
|||
if(ok){ |
|||
if(json["event"] == "received"){ |
|||
std::string buffer = json["data"].asString(); |
|||
ofxXmlSettings xml; |
|||
xml.loadFromBuffer(buffer); |
|||
xml.save("ofxpimapper.xml"); |
|||
|
|||
mapper.setup(); |
|||
isMapperSetup = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
if(isMapperSetup){ |
|||
mapper.keyPressed(key); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "keyPressed"; |
|||
json["key"] = key; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
if(isMapperSetup){ |
|||
mapper.keyReleased(key); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "keyReleased"; |
|||
json["key"] = key; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
if(isMapperSetup){ |
|||
mapper.mousePressed(x, y, button); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "mousePressed"; |
|||
json["x"] = x; |
|||
json["y"] = y; |
|||
json["button"] = button; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
if(isMapperSetup){ |
|||
mapper.mouseReleased(x, y, button); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "mouseReleased"; |
|||
json["x"] = x; |
|||
json["y"] = y; |
|||
json["button"] = button; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
if(isMapperSetup){ |
|||
mapper.mouseDragged(x, y, button); |
|||
|
|||
ofxJSONElement json; |
|||
json["event"] = "mouseDragged"; |
|||
json["x"] = x; |
|||
json["y"] = y; |
|||
json["button"] = button; |
|||
|
|||
TCPClient::instance()->send(json.getRawString()); |
|||
} |
|||
} |
|||
|
@ -1,25 +1,25 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "TCPClient.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void gotMessage(ofMessage m); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper mapper; |
|||
bool isMapperSetup; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "TCPClient.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void gotMessage(ofMessage m); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper mapper; |
|||
bool isMapperSetup; |
|||
}; |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,25 +1,25 @@ |
|||
# Remote Control Server for ofxPiMapper |
|||
|
|||
This example demonstrates a TCP server for ofxPiMapper remote control. The other part of this is the [Remote Control Client](../example_remote-client). What it does is the following. |
|||
|
|||
- It creates a `TCPServer` singleton. |
|||
- Waits for a client to connect via TCP. |
|||
- Sends ofxPiMapper configuration once client is connected. |
|||
- Accepts keyboard and mouse events from client after. |
|||
- Forwards events to ofxPiMapper instance. |
|||
|
|||
In a real-world scenario, the server should reside on the Raspberry Pi side of your installation. The Raspberry Pi should be connected to wired or wireless network. An IP address should be set. |
|||
|
|||
The client should know the following. |
|||
|
|||
- The **IP address** of the Raspberry Pi with the server. |
|||
- The port, which is **9999** in this case. |
|||
|
|||
## Dependencies |
|||
|
|||
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code. |
|||
|
|||
``` |
|||
cd openFrameworks/addons |
|||
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON |
|||
``` |
|||
# Remote Control Server for ofxPiMapper |
|||
|
|||
This example demonstrates a TCP server for ofxPiMapper remote control. The other part of this is the [Remote Control Client](../example_remote-client). What it does is the following. |
|||
|
|||
- It creates a `TCPServer` singleton. |
|||
- Waits for a client to connect via TCP. |
|||
- Sends ofxPiMapper configuration once client is connected. |
|||
- Accepts keyboard and mouse events from client after. |
|||
- Forwards events to ofxPiMapper instance. |
|||
|
|||
In a real-world scenario, the server should reside on the Raspberry Pi side of your installation. The Raspberry Pi should be connected to wired or wireless network. An IP address should be set. |
|||
|
|||
The client should know the following. |
|||
|
|||
- The **IP address** of the Raspberry Pi with the server. |
|||
- The port, which is **9999** in this case. |
|||
|
|||
## Dependencies |
|||
|
|||
JSON is used as the data format between ofxPiMapper remote control server and client, therefore additionally [ofxJSON](https://github.com/jeffcrouse/ofxJSON) addon is used. Install it by using the following lines of bash code. |
|||
|
|||
``` |
|||
cd openFrameworks/addons |
|||
git clone --depth=1 https://github.com/jeffcrouse/ofxJSON |
|||
``` |
|||
|
@ -1,6 +1,6 @@ |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
|
@ -1,5 +1,5 @@ |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxJSON |
|||
ofxNetwork |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,36 +1,36 @@ |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>640.000000000</x> |
|||
<y>50.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1230.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>50.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>gene-nsynthesis.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>640.000000000</x> |
|||
<y>50.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1230.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>50.000000000</x> |
|||
<y>750.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.500000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>gene-nsynthesis.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,95 +1,95 @@ |
|||
#include "TCPServer.h" |
|||
|
|||
shared_ptr<TCPServer> TCPServer::_instance = 0; |
|||
|
|||
shared_ptr<TCPServer> TCPServer::instance(){ |
|||
if(_instance == 0){ |
|||
_instance = shared_ptr<TCPServer>(new TCPServer); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
TCPServer::TCPServer(){ |
|||
std::cout << "TCPServer initialized" << std::endl; |
|||
} |
|||
|
|||
void TCPServer::setup(int port){ |
|||
_tcpServer.setup(port); |
|||
} |
|||
|
|||
void TCPServer::update(){ |
|||
int numClients = _tcpServer.getLastID(); |
|||
for(auto i = 0; i < numClients; ++i){ |
|||
if(_tcpServer.isClientConnected(i)){ |
|||
|
|||
// Notify application when new client connects
|
|||
if(!_tcpConnections[i]){ |
|||
ofxJSONElement json; |
|||
json["ip"] = _tcpServer.getClientIP(i); |
|||
json["port"] = _tcpServer.getClientPort(i); |
|||
json["id"] = i; |
|||
json["event"] = "connected"; |
|||
|
|||
ofMessage message(json.getRawString()); |
|||
ofSendMessage(message); |
|||
|
|||
_tcpConnections[i] = true; |
|||
} |
|||
|
|||
// Receive messages
|
|||
string rx = _tcpServer.receive(i); |
|||
if(rx.length() > 0){ |
|||
ofxJSONElement json; |
|||
bool ok = json.parse(rx); |
|||
|
|||
if(!ok){ |
|||
json["ip"] = _tcpServer.getClientIP(i); |
|||
json["port"] = _tcpServer.getClientPort(i); |
|||
json["id"] = i; |
|||
json["event"] = "received"; |
|||
json["data"] = rx; |
|||
} |
|||
|
|||
ofMessage message(json.getRawString()); |
|||
ofSendMessage(message); |
|||
} |
|||
}else{ |
|||
|
|||
// Notify application when client disconnects
|
|||
if(_tcpConnections[i]){ |
|||
ofxJSONElement json; |
|||
json["ip"] = _tcpServer.getClientIP(i); |
|||
json["port"] = _tcpServer.getClientPort(i); |
|||
json["id"] = i; |
|||
json["event"] = "disconnected"; |
|||
|
|||
ofMessage message(json.getRawString()); |
|||
ofSendMessage(message); |
|||
|
|||
_tcpConnections[i] = false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void TCPServer::draw(){ |
|||
int numClients = _tcpServer.getLastID(); |
|||
int clientsConnected = 0; |
|||
for(auto i = 0; i < numClients; ++i){ |
|||
if(_tcpServer.isClientConnected(i)){ |
|||
ofPushMatrix(); |
|||
ofTranslate(10, 10); |
|||
ofPushStyle(); |
|||
ofSetColor(0, 255, 0); |
|||
ofDrawRectangle(clientsConnected * 20, 0, 10, 10); |
|||
ofPopStyle(); |
|||
ofPopMatrix(); |
|||
clientsConnected++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void TCPServer::send(int clientID, std::string message){ |
|||
_tcpServer.send(clientID, message); |
|||
} |
|||
|
|||
#include "TCPServer.h" |
|||
|
|||
shared_ptr<TCPServer> TCPServer::_instance = 0; |
|||
|
|||
shared_ptr<TCPServer> TCPServer::instance(){ |
|||
if(_instance == 0){ |
|||
_instance = shared_ptr<TCPServer>(new TCPServer); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
TCPServer::TCPServer(){ |
|||
std::cout << "TCPServer initialized" << std::endl; |
|||
} |
|||
|
|||
void TCPServer::setup(int port){ |
|||
_tcpServer.setup(port); |
|||
} |
|||
|
|||
void TCPServer::update(){ |
|||
int numClients = _tcpServer.getLastID(); |
|||
for(auto i = 0; i < numClients; ++i){ |
|||
if(_tcpServer.isClientConnected(i)){ |
|||
|
|||
// Notify application when new client connects
|
|||
if(!_tcpConnections[i]){ |
|||
ofxJSONElement json; |
|||
json["ip"] = _tcpServer.getClientIP(i); |
|||
json["port"] = _tcpServer.getClientPort(i); |
|||
json["id"] = i; |
|||
json["event"] = "connected"; |
|||
|
|||
ofMessage message(json.getRawString()); |
|||
ofSendMessage(message); |
|||
|
|||
_tcpConnections[i] = true; |
|||
} |
|||
|
|||
// Receive messages
|
|||
string rx = _tcpServer.receive(i); |
|||
if(rx.length() > 0){ |
|||
ofxJSONElement json; |
|||
bool ok = json.parse(rx); |
|||
|
|||
if(!ok){ |
|||
json["ip"] = _tcpServer.getClientIP(i); |
|||
json["port"] = _tcpServer.getClientPort(i); |
|||
json["id"] = i; |
|||
json["event"] = "received"; |
|||
json["data"] = rx; |
|||
} |
|||
|
|||
ofMessage message(json.getRawString()); |
|||
ofSendMessage(message); |
|||
} |
|||
}else{ |
|||
|
|||
// Notify application when client disconnects
|
|||
if(_tcpConnections[i]){ |
|||
ofxJSONElement json; |
|||
json["ip"] = _tcpServer.getClientIP(i); |
|||
json["port"] = _tcpServer.getClientPort(i); |
|||
json["id"] = i; |
|||
json["event"] = "disconnected"; |
|||
|
|||
ofMessage message(json.getRawString()); |
|||
ofSendMessage(message); |
|||
|
|||
_tcpConnections[i] = false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void TCPServer::draw(){ |
|||
int numClients = _tcpServer.getLastID(); |
|||
int clientsConnected = 0; |
|||
for(auto i = 0; i < numClients; ++i){ |
|||
if(_tcpServer.isClientConnected(i)){ |
|||
ofPushMatrix(); |
|||
ofTranslate(10, 10); |
|||
ofPushStyle(); |
|||
ofSetColor(0, 255, 0); |
|||
ofDrawRectangle(clientsConnected * 20, 0, 10, 10); |
|||
ofPopStyle(); |
|||
ofPopMatrix(); |
|||
clientsConnected++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void TCPServer::send(int clientID, std::string message){ |
|||
_tcpServer.send(clientID, message); |
|||
} |
|||
|
|||
|
@ -1,23 +1,23 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxNetwork.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class TCPServer { |
|||
public: |
|||
static shared_ptr<TCPServer> instance(); |
|||
|
|||
void setup(int port); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void send(int clientID, std::string message); |
|||
|
|||
private: |
|||
TCPServer(); |
|||
static shared_ptr<TCPServer> _instance; |
|||
|
|||
ofxTCPServer _tcpServer; |
|||
std::map<int, bool> _tcpConnections; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxNetwork.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class TCPServer { |
|||
public: |
|||
static shared_ptr<TCPServer> instance(); |
|||
|
|||
void setup(int port); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void send(int clientID, std::string message); |
|||
|
|||
private: |
|||
TCPServer(); |
|||
static shared_ptr<TCPServer> _instance; |
|||
|
|||
ofxTCPServer _tcpServer; |
|||
std::map<int, bool> _tcpConnections; |
|||
}; |
|||
|
@ -1,7 +1,7 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1280, 800, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
|
|||
int main(){ |
|||
ofSetupOpenGL(1280, 800, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
|
@ -1,84 +1,84 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
mapper.setup(); |
|||
TCPServer::instance()->setup(9999); |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofSetFullscreen(true); |
|||
#endif |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
mapper.update(); |
|||
TCPServer::instance()->update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
mapper.draw(); |
|||
TCPServer::instance()->draw(); |
|||
} |
|||
|
|||
// Here is where we process messages received from TCPServer instance
|
|||
void ofApp::gotMessage(ofMessage m){ |
|||
std::cout << m.message << std::endl; |
|||
|
|||
ofxJSONElement json; |
|||
bool ok = json.parse(m.message); |
|||
if(ok){ |
|||
if(json["event"].asString() == "connected"){ |
|||
// Save Mapper composition and get config as string
|
|||
std::cout << "Sending mapper config" << std::endl; |
|||
mapper.saveProject(); |
|||
|
|||
ofFile file; |
|||
file.open(ofToDataPath("ofxpimapper.xml"), ofFile::ReadOnly, false); |
|||
ofBuffer buff = file.readToBuffer(); |
|||
string text = buff.getText(); |
|||
|
|||
TCPServer::instance()->send(json["id"].asInt(), text); |
|||
} |
|||
|
|||
if(json["event"].asString() == "keyPressed"){ |
|||
mapper.keyPressed(json["key"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "keyReleased"){ |
|||
mapper.keyReleased(json["key"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "mousePressed"){ |
|||
mapper.mousePressed(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "mouseReleased"){ |
|||
mapper.mouseReleased(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "mouseDragged"){ |
|||
mapper.mouseDragged(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
mapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
mapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
mapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
mapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
mapper.mouseDragged(x, y, button); |
|||
} |
|||
|
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
mapper.setup(); |
|||
TCPServer::instance()->setup(9999); |
|||
|
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofSetFullscreen(true); |
|||
#endif |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
mapper.update(); |
|||
TCPServer::instance()->update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
mapper.draw(); |
|||
TCPServer::instance()->draw(); |
|||
} |
|||
|
|||
// Here is where we process messages received from TCPServer instance
|
|||
void ofApp::gotMessage(ofMessage m){ |
|||
std::cout << m.message << std::endl; |
|||
|
|||
ofxJSONElement json; |
|||
bool ok = json.parse(m.message); |
|||
if(ok){ |
|||
if(json["event"].asString() == "connected"){ |
|||
// Save Mapper composition and get config as string
|
|||
std::cout << "Sending mapper config" << std::endl; |
|||
mapper.saveProject(); |
|||
|
|||
ofFile file; |
|||
file.open(ofToDataPath("ofxpimapper.xml"), ofFile::ReadOnly, false); |
|||
ofBuffer buff = file.readToBuffer(); |
|||
string text = buff.getText(); |
|||
|
|||
TCPServer::instance()->send(json["id"].asInt(), text); |
|||
} |
|||
|
|||
if(json["event"].asString() == "keyPressed"){ |
|||
mapper.keyPressed(json["key"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "keyReleased"){ |
|||
mapper.keyReleased(json["key"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "mousePressed"){ |
|||
mapper.mousePressed(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "mouseReleased"){ |
|||
mapper.mouseReleased(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); |
|||
} |
|||
|
|||
if(json["event"].asString() == "mouseDragged"){ |
|||
mapper.mouseDragged(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
mapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
mapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
mapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
mapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
mapper.mouseDragged(x, y, button); |
|||
} |
|||
|
|||
|
@ -1,23 +1,23 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "TCPServer.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void gotMessage(ofMessage m); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper mapper; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "TCPServer.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "ofxJSONElement.h" |
|||
|
|||
class ofApp : public ofBaseApp{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void gotMessage(ofMessage m); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper mapper; |
|||
}; |
|||
|
@ -1,5 +1,5 @@ |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
obj |
|||
*.xcworkspace |
|||
*.xcuserdatad |
|||
*~ |
|||
config.make |
|||
|
@ -1,13 +1,13 @@ |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
# Attempt to load a config.make file.
|
|||
# If none is found, project defaults in config.project.make will be used.
|
|||
ifneq ($(wildcard config.make),) |
|||
include config.make |
|||
endif |
|||
|
|||
# make sure the the OF_ROOT location is defined
|
|||
ifndef OF_ROOT |
|||
OF_ROOT=$(realpath ../../..) |
|||
endif |
|||
|
|||
# call the project makefile!
|
|||
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk |
|||
|
@ -1,4 +1,4 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxOMXPlayer |
|||
|
@ -1,3 +1,3 @@ |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxPiMapper |
|||
ofxXmlSettings |
|||
|
@ -1,81 +1,81 @@ |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>193.000000000</x> |
|||
<y>58.187255859</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>466.000000000</x> |
|||
<y>413.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>39.374511719</x> |
|||
<y>211.812774658</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>-0.006000000</x> |
|||
<y>-0.014000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image4.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
<surface type="1"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>758.067382812</x> |
|||
<y>360.033691406</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1125.932617188</x> |
|||
<y>360.033691406</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1129.000000000</x> |
|||
<y>719.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>759.000000000</x> |
|||
<y>721.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Custom FBO Source</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
</surfaces> |
|||
<surfaces> |
|||
<surface type="0"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>193.000000000</x> |
|||
<y>58.187255859</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>466.000000000</x> |
|||
<y>413.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>39.374511719</x> |
|||
<y>211.812774658</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>-0.006000000</x> |
|||
<y>-0.014000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>image</source-type> |
|||
<source-name>image4.jpg</source-name> |
|||
</source> |
|||
</surface> |
|||
<surface type="1"> |
|||
<vertices> |
|||
<vertex> |
|||
<x>758.067382812</x> |
|||
<y>360.033691406</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1125.932617188</x> |
|||
<y>360.033691406</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>1129.000000000</x> |
|||
<y>719.000000000</y> |
|||
</vertex> |
|||
<vertex> |
|||
<x>759.000000000</x> |
|||
<y>721.000000000</y> |
|||
</vertex> |
|||
</vertices> |
|||
<texCoords> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>0.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>1.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
<texCoord> |
|||
<x>0.000000000</x> |
|||
<y>1.000000000</y> |
|||
</texCoord> |
|||
</texCoords> |
|||
<source> |
|||
<source-type>fbo</source-type> |
|||
<source-name>Custom FBO Source</source-name> |
|||
</source> |
|||
<properties> |
|||
<perspectiveWarping>1</perspectiveWarping> |
|||
</properties> |
|||
</surface> |
|||
</surfaces> |
|||
|
@ -1,41 +1,41 @@ |
|||
#include "CustomSource.h" |
|||
|
|||
void CustomSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Custom FBO Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numRects = 20; // change this to add more or less rects
|
|||
for(int i = 0; i < numRects; i++){ |
|||
rects.push_back(ofRectangle(0, |
|||
ofRandom(fbo->getHeight()), |
|||
fbo->getWidth(), |
|||
ofRandom(20))); |
|||
rectSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void CustomSource::update(){ |
|||
// Move rects
|
|||
for(int i = 0; i < rects.size(); i++){ |
|||
rects[i].y += rectSpeeds[i]; |
|||
if(rects[i].y > fbo->getHeight()){ |
|||
rects[i].y = -rects[i].getHeight(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void CustomSource::draw(){ |
|||
// Fill FBO with our rects
|
|||
ofClear(0); |
|||
ofSetColor(255); |
|||
for(int i = 0; i < rects.size(); i++){ |
|||
ofDrawRectangle(rects[i]); |
|||
} |
|||
} |
|||
#include "CustomSource.h" |
|||
|
|||
void CustomSource::setup(){ |
|||
// Give our source a decent name
|
|||
name = "Custom FBO Source"; |
|||
|
|||
// Allocate our FBO source, decide how big it should be
|
|||
allocate(500, 500); |
|||
|
|||
// Genereate rects to be rendered into the FBO
|
|||
int numRects = 20; // change this to add more or less rects
|
|||
for(int i = 0; i < numRects; i++){ |
|||
rects.push_back(ofRectangle(0, |
|||
ofRandom(fbo->getHeight()), |
|||
fbo->getWidth(), |
|||
ofRandom(20))); |
|||
rectSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
// Don't do any drawing here
|
|||
void CustomSource::update(){ |
|||
// Move rects
|
|||
for(int i = 0; i < rects.size(); i++){ |
|||
rects[i].y += rectSpeeds[i]; |
|||
if(rects[i].y > fbo->getHeight()){ |
|||
rects[i].y = -rects[i].getHeight(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// No need to take care of fbo.begin() and fbo.end() here.
|
|||
// All within draw() is being rendered into fbo;
|
|||
void CustomSource::draw(){ |
|||
// Fill FBO with our rects
|
|||
ofClear(0); |
|||
ofSetColor(255); |
|||
for(int i = 0; i < rects.size(); i++){ |
|||
ofDrawRectangle(rects[i]); |
|||
} |
|||
} |
|||
|
@ -1,14 +1,14 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class CustomSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> rects; |
|||
std::vector<float> rectSpeeds; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "FboSource.h" |
|||
|
|||
class CustomSource : public ofx::piMapper::FboSource { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
std::vector<ofRectangle> rects; |
|||
std::vector<float> rectSpeeds; |
|||
}; |
@ -1,22 +1,22 @@ |
|||
#include "Settings.h" |
|||
|
|||
Settings * Settings::_instance = 0; |
|||
|
|||
Settings * Settings::instance(){ |
|||
if(_instance == 0){ |
|||
_instance = new Settings(); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
Settings::Settings(){ |
|||
_fullscreen = false; |
|||
} |
|||
|
|||
void Settings::setFullscreen(bool f){ |
|||
_fullscreen = f; |
|||
} |
|||
|
|||
bool Settings::getFullscreen(){ |
|||
return _fullscreen; |
|||
#include "Settings.h" |
|||
|
|||
Settings * Settings::_instance = 0; |
|||
|
|||
Settings * Settings::instance(){ |
|||
if(_instance == 0){ |
|||
_instance = new Settings(); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
Settings::Settings(){ |
|||
_fullscreen = false; |
|||
} |
|||
|
|||
void Settings::setFullscreen(bool f){ |
|||
_fullscreen = f; |
|||
} |
|||
|
|||
bool Settings::getFullscreen(){ |
|||
return _fullscreen; |
|||
} |
@ -1,18 +1,18 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
|
|||
class Settings { |
|||
public: |
|||
static Settings * instance(); |
|||
|
|||
void setFullscreen(bool f); |
|||
bool getFullscreen(); |
|||
|
|||
private: |
|||
static Settings * _instance; |
|||
|
|||
Settings(); |
|||
|
|||
bool _fullscreen; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
|
|||
class Settings { |
|||
public: |
|||
static Settings * instance(); |
|||
|
|||
void setFullscreen(bool f); |
|||
bool getFullscreen(); |
|||
|
|||
private: |
|||
static Settings * _instance; |
|||
|
|||
Settings(); |
|||
|
|||
bool _fullscreen; |
|||
}; |
|||
|
@ -1,22 +1,22 @@ |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
#include <string> |
|||
#include <vector> |
|||
#include "Settings.h" |
|||
|
|||
int main(int argc, char * argv[]){ |
|||
bool fullscreen = false; |
|||
|
|||
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc); |
|||
for(int i = 0; i < arguments.size(); ++i){ |
|||
if(arguments.at(i) == "-f"){ |
|||
fullscreen = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
Settings::instance()->setFullscreen(fullscreen); |
|||
|
|||
ofSetupOpenGL(800, 450, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
#include "ofMain.h" |
|||
#include "ofApp.h" |
|||
#include <string> |
|||
#include <vector> |
|||
#include "Settings.h" |
|||
|
|||
int main(int argc, char * argv[]){ |
|||
bool fullscreen = false; |
|||
|
|||
std::vector<std::string> arguments = std::vector<std::string>(argv, argv + argc); |
|||
for(int i = 0; i < arguments.size(); ++i){ |
|||
if(arguments.at(i) == "-f"){ |
|||
fullscreen = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
Settings::instance()->setFullscreen(fullscreen); |
|||
|
|||
ofSetupOpenGL(800, 450, OF_WINDOW); |
|||
ofRunApp(new ofApp()); |
|||
} |
|||
|
@ -1,55 +1,55 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
|
|||
// Enable or disable audio for video sources globally
|
|||
// Set this to false to save resources on the Raspberry Pi
|
|||
ofx::piMapper::VideoSource::enableAudio = true; |
|||
ofx::piMapper::VideoSource::useHDMIForAudio = false; |
|||
|
|||
// Add our CustomSource to list of fbo sources of the piMapper
|
|||
// FBO sources should be added before piMapper.setup() so the
|
|||
// piMapper is able to load the source if it is assigned to
|
|||
// a surface in XML settings.
|
|||
customSource = new CustomSource(); |
|||
piMapper.registerFboSource(customSource); |
|||
piMapper.setup(); |
|||
|
|||
// The info layer is hidden by default, press <i> to toggle
|
|||
// piMapper.showInfo();
|
|||
|
|||
ofSetFullscreen(Settings::instance()->getFullscreen()); |
|||
ofSetEscapeQuitsApp(false); |
|||
|
|||
dummyObjects.load("dummy-objects.png"); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
piMapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
dummyObjects.draw(200,200); |
|||
piMapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
piMapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
piMapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
piMapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
piMapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
piMapper.mouseDragged(x, y, button); |
|||
} |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup(){ |
|||
ofBackground(0); |
|||
|
|||
// Enable or disable audio for video sources globally
|
|||
// Set this to false to save resources on the Raspberry Pi
|
|||
ofx::piMapper::VideoSource::enableAudio = true; |
|||
ofx::piMapper::VideoSource::useHDMIForAudio = false; |
|||
|
|||
// Add our CustomSource to list of fbo sources of the piMapper
|
|||
// FBO sources should be added before piMapper.setup() so the
|
|||
// piMapper is able to load the source if it is assigned to
|
|||
// a surface in XML settings.
|
|||
customSource = new CustomSource(); |
|||
piMapper.registerFboSource(customSource); |
|||
piMapper.setup(); |
|||
|
|||
// The info layer is hidden by default, press <i> to toggle
|
|||
// piMapper.showInfo();
|
|||
|
|||
ofSetFullscreen(Settings::instance()->getFullscreen()); |
|||
ofSetEscapeQuitsApp(false); |
|||
|
|||
dummyObjects.load("dummy-objects.png"); |
|||
} |
|||
|
|||
void ofApp::update(){ |
|||
piMapper.update(); |
|||
} |
|||
|
|||
void ofApp::draw(){ |
|||
dummyObjects.draw(200,200); |
|||
piMapper.draw(); |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key){ |
|||
piMapper.keyPressed(key); |
|||
} |
|||
|
|||
void ofApp::keyReleased(int key){ |
|||
piMapper.keyReleased(key); |
|||
} |
|||
|
|||
void ofApp::mousePressed(int x, int y, int button){ |
|||
piMapper.mousePressed(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseReleased(int x, int y, int button){ |
|||
piMapper.mouseReleased(x, y, button); |
|||
} |
|||
|
|||
void ofApp::mouseDragged(int x, int y, int button){ |
|||
piMapper.mouseDragged(x, y, button); |
|||
} |
|||
|
@ -1,28 +1,28 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "Settings.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "CustomSource.h" |
|||
#include "VideoSource.h" |
|||
|
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper piMapper; |
|||
|
|||
// By using a custom source that is derived from FboSource
|
|||
// you will be able to see the source listed in sources editor
|
|||
CustomSource * customSource; |
|||
ofImage dummyObjects; |
|||
}; |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "Settings.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "CustomSource.h" |
|||
#include "VideoSource.h" |
|||
|
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
|
|||
void keyPressed(int key); |
|||
void keyReleased(int key); |
|||
|
|||
void mousePressed(int x, int y, int button); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(int x, int y, int button); |
|||
|
|||
ofxPiMapper piMapper; |
|||
|
|||
// By using a custom source that is derived from FboSource
|
|||
// you will be able to see the source listed in sources editor
|
|||
CustomSource * customSource; |
|||
ofImage dummyObjects; |
|||
}; |
|||
|
@ -1,266 +1,266 @@ |
|||
########################################################################
|
|||
# PROCESS VALID ADDONS IF AVAILABLE
|
|||
########################################################################
|
|||
|
|||
|
|||
# parses addons includes, in PARSED_ADDON_INCLUDES receives full PATHS to addons
|
|||
define parse_addons_includes |
|||
$(eval ADDONS_INCLUDES_FILTER = $(addprefix $1/, $(ADDON_INCLUDES_EXCLUDE))) \
|
|||
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
|
|||
$(eval PARSED_ADDONS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_SOURCE_INCLUDES))) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_SOURCE_INCLUDES))) \
|
|||
$(eval PARSED_ADDONS_LIBS_INCLUDES_PATHS = $(addsuffix /libs/*/include, $1)) \
|
|||
$(eval PARSED_ADDONS_LIBS_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_INCLUDES_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_INCLUDES))) \
|
|||
$(eval PARSED_ADDONS_INCLUDES = $(PARSED_ADDONS_FILTERED_INCLUDE_PATHS)) \
|
|||
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS)) \
|
|||
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS)) |
|||
endef |
|||
|
|||
# parses addons sources, in PARSED_ADDON_SOURCES receives full PATHS to addons
|
|||
define parse_addons_sources |
|||
$(eval ADDONS_SOURCES_FILTER = $(addprefix $1/, $(ADDON_SOURCES_EXCLUDE))) \
|
|||
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
|
|||
$(eval PARSED_ADDONS_OFX_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_OFX_SOURCES))) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_LIBS_SOURCES))) \
|
|||
$(eval PARSED_ADDONS_SOURCE_FILES = $(PARSED_ADDONS_FILTERED_SOURCE_PATHS)) \
|
|||
$(eval PARSED_ADDONS_SOURCE_FILES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS)) |
|||
endef |
|||
|
|||
# parses addons libraries, in PARSED_ADDON_LIBS receives full PATHS to addons and libs_exclude
|
|||
define parse_addons_libraries |
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS = $(filter-out $(ADDON_LIBS_EXCLUDE),$(addsuffix /libs/*/lib/$(ABI_LIB_SUBPATH), $1))) \
|
|||
$(eval PARSED_ALL_PLATFORM_LIBS = $(shell $(FIND) $(PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(if $(PARSED_ALL_PLATFORM_LIBS), \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.a 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.so 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dylib 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dll 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS = $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS)) \
|
|||
$(eval PARSED_ADDONS_LIBS += $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED)) \
|
|||
) |
|||
endef |
|||
|
|||
|
|||
space := |
|||
space += |
|||
|
|||
define src_to_obj |
|||
$(addsuffix .o,$(basename $(filter %.c %.cpp %.cc %.cxx %.cc %.s %.S, $(addprefix $3,$(addprefix $2,$1))))) |
|||
endef |
|||
|
|||
define rwildcard |
|||
$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d)) |
|||
endef |
|||
|
|||
# PARSE addon_config.mk FILES
|
|||
#
|
|||
# 1. read the addon_config.mk file for each adddon that has it
|
|||
# 2. read each line of the addon by converting \n to \t since makefiles treat \n as spaces
|
|||
# also convert spaces to ? so foreach works for each line instead of each word
|
|||
# 3. unscape ? to space inside the loop
|
|||
# 4. if the line matches common: or platform: set the PROCESS_NEXT flag to true
|
|||
# 5. if the line matches %: but it's not common or platform: set PROCESS_NEXT to false
|
|||
# 6: if PROCESS_NEXT eval the line to put the variable in the makefile space
|
|||
define parse_addon |
|||
$(if $(wildcard $(PROJECT_ROOT)/$1), \
|
|||
$(eval addon=$(realpath $(addprefix $(PROJECT_ROOT)/, $1))) \
|
|||
$(eval addon_obj_path=$(PROJECT_ROOT)) \
|
|||
$(eval ADDON_PATHS+= $(dir $(addon))) \
|
|||
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)addons/) \
|
|||
, \
|
|||
$(eval addon=$(realpath $(addprefix $(OF_ADDONS_PATH)/, $1))) \
|
|||
$(eval addon_obj_path=$(OF_ADDONS_PATH)) \
|
|||
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)) \
|
|||
) \
|
|||
$(eval ADDON_DEPENDENCIES= ) \
|
|||
$(eval ADDON_DATA= ) \
|
|||
$(eval ADDON_CFLAGS= ) \
|
|||
$(eval ADDON_CPPFLAGS= ) \
|
|||
$(eval ADDON_LDFLAGS= ) \
|
|||
$(eval ADDON_PKG_CONFIG_LIBRARIES= ) \
|
|||
$(eval ADDON_FRAMEWORKS= ) \
|
|||
$(eval ADDON_LIBS_EXCLUDE= ) \
|
|||
$(eval ADDON_SOURCES_EXCLUDE= ) \
|
|||
$(call parse_addons_includes, $(addon)) \
|
|||
$(eval ADDON_INCLUDES=$(PARSED_ADDONS_INCLUDES)) \
|
|||
$(call parse_addons_libraries, $(addon)) \
|
|||
$(eval ADDON_LIBS=$(PARSED_ADDONS_LIBS)) \
|
|||
$(call parse_addons_sources, $(addon)) \
|
|||
$(eval ADDON_SOURCES=$(PARSED_ADDONS_SOURCE_FILES)) \
|
|||
$(eval PROCESS_NEXT=0) \
|
|||
$(if $(wildcard $(addon)/addon_config.mk), \
|
|||
$(foreach var_line, $(shell cat $(addon)/addon_config.mk | tr '\n ' '\t?'), \
|
|||
$(eval unscaped_var_line=$(strip $(subst ?, ,$(var_line)))) \
|
|||
$(if $(filter $(PROCESS_NEXT),1), $(eval $(unscaped_var_line))) \
|
|||
$(if $(filter %:,$(unscaped_var_line)), \
|
|||
$(if $(filter common:,$(unscaped_var_line)), \
|
|||
$(eval PROCESS_NEXT=1), \
|
|||
$(if $(filter $(ABI_LIB_SUBPATH):,$(unscaped_var_line)), \
|
|||
$(eval PROCESS_NEXT=1), \
|
|||
$(eval PROCESS_NEXT=0) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(if $(strip $(ADDON_INCLUDES)), \
|
|||
$(eval ADDON_INCLUDES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_INCLUDES_EXCLUDE)),$(ADDON_INCLUDES))) \
|
|||
$(foreach addon_include, $(strip $(ADDON_INCLUDES_FILTERED)), \
|
|||
$(if $(wildcard $(addon)/$(addon_include)), \
|
|||
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon)/$(addon_include)) \
|
|||
) \
|
|||
$(if $(wildcard $(addon_include)), \
|
|||
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon_include)) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CFLAGS)) \
|
|||
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CPPFLAGS)) \
|
|||
$(if $(strip $(ADDON_LIBS)), \
|
|||
$(foreach addon_lib, $(strip $(ADDON_LIBS)), \
|
|||
$(if $(wildcard $(addon)/$(addon_lib)), \
|
|||
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon)/$(addon_lib)) \
|
|||
) \
|
|||
$(if $(wildcard $(addon_lib)), \
|
|||
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon_lib)) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(eval TMP_PROJECT_ADDONS_LDFLAGS += $(ADDON_LDFLAGS)) \
|
|||
$(eval TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES += $(ADDON_PKG_CONFIG_LIBRARIES)) \
|
|||
$(eval TMP_PROJECT_ADDONS_FRAMEWORKS += $(ADDON_FRAMEWORKS)) \
|
|||
$(eval PROJECT_AFTER += $(ADDON_AFTER)) \
|
|||
$(if $(strip $(ADDON_SOURCES)), \
|
|||
$(eval ADDON_SOURCES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_SOURCES_EXCLUDE)),$(ADDON_SOURCES))) \
|
|||
$(foreach addon_src, $(strip $(ADDON_SOURCES_FILTERED)), \
|
|||
$(if $(filter $(addon)%, $(addon_src)), \
|
|||
$(eval addon_path=$(subst %,*,$(addon_src))) \
|
|||
$(if $(findstring *,$(addon_path)), \
|
|||
$(eval addon_dir=$(dir $(addon_path))) \
|
|||
$(eval addon_rest=$(notdir $(addon_path))) \
|
|||
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
|
|||
$(foreach expanded_addon_src, $(addon_files), \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(if $(filter $(OF_ROOT)%, $(addon_src)), \
|
|||
$(eval addon_path=$(subst %,*,$(addon_src))) \
|
|||
$(if $(findstring *,$(addon_path)), \
|
|||
$(eval addon_dir=$(dir $(addon_src))) \
|
|||
$(eval addon_rest=$(notdir $(addon_src))) \
|
|||
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
|
|||
$(foreach expanded_addon_src, $(addon_files), \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(expanded_addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
,$(if $(filter-out /%, $(addon_src)), \
|
|||
$(eval addon_path=$(addon)/$(subst %,*,$(addon_src))) \
|
|||
$(if $(findstring *,$(addon_path)), \
|
|||
$(eval addon_dir=$(dir $(addon_path))) \
|
|||
$(eval addon_rest=$(notdir $(addon_path))) \
|
|||
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
|
|||
$(foreach expanded_addon_src, $(addon_files), \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_path)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_path:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
,$(error cannot find addon source file $(addon_src))) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(if $(strip $(ADDON_DATA)), \
|
|||
$(eval TMP_PROJECT_ADDONS_DATA += $(addprefix $(addon)/,$(ADDON_DATA))) \
|
|||
) \
|
|||
$(foreach addon_dep, $(strip $(ADDON_DEPENDENCIES)), \
|
|||
$(if $(filter %$(addon_dep), $(PROJECT_ADDONS)), \
|
|||
, \
|
|||
$(eval PROJECT_ADDONS += $(addon_dep)) \
|
|||
$(call parse_addon,$(addon_dep)) \
|
|||
) \
|
|||
) |
|||
endef |
|||
|
|||
|
|||
$(foreach addon_to_parse, $(PROJECT_ADDONS), \ |
|||
$(call parse_addon,$(addon_to_parse)) \
|
|||
) |
|||
|
|||
#define uniq =
|
|||
# $(eval seen :=)
|
|||
# $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
|
|||
# ${seen}
|
|||
#endef
|
|||
|
|||
|
|||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) |
|||
|
|||
|
|||
PROJECT_ADDONS_CFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_CFLAGS)) |
|||
PROJECT_ADDONS_INCLUDES = $(call uniq,$(TMP_PROJECT_ADDONS_INCLUDES)) |
|||
PROJECT_ADDONS_LIBS = $(call uniq,$(TMP_PROJECT_ADDONS_LIBS)) |
|||
PROJECT_ADDONS_LDFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_LDFLAGS)) |
|||
PROJECT_ADDONS_PKG_CONFIG_LIBRARIES = $(call uniq,$(TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES)) |
|||
PROJECT_ADDONS_FRAMEWORKS = $(call uniq,$(TMP_PROJECT_ADDONS_FRAMEWORKS)) |
|||
PROJECT_ADDONS_SOURCE_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_SOURCE_FILES)) |
|||
PROJECT_ADDONS_OBJ_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_OBJ_FILES)) |
|||
PROJECT_ADDONS_DATA = $(call uniq,$(TMP_PROJECT_ADDONS_DATA)) |
|||
VPATH += $(call uniq, $(ADDON_PATHS)) |
|||
|
|||
|
|||
OF_PROJECT_ADDONS_OBJS = $(PROJECT_ADDONS_OBJ_FILES) |
|||
OF_PROJECT_ADDONS_DEPS = $(patsubst %.o,%.d,$(PROJECT_ADDONS_OBJ_FILES)) |
|||
|
|||
########################################################################
|
|||
# DEBUGGING
|
|||
########################################################################
|
|||
# print debug information if so instructed
|
|||
ifdef MAKEFILE_DEBUG |
|||
$(info ---PROJECT_ADDONS_PATHS---) |
|||
$(foreach v, $(PROJECT_ADDONS_PATHS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_WITH_CONFIG---) |
|||
$(foreach v, $(PROJECT_ADDONS_WITH_CONFIG),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_INCLUDES---) |
|||
$(foreach v, $(PROJECT_ADDONS_INCLUDES),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_SOURCE_FILES---) |
|||
$(foreach v, $(PROJECT_ADDONS_SOURCE_FILES),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_LIBS---) |
|||
$(foreach v, $(PROJECT_ADDONS_LIBS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_OBJFILES---) |
|||
$(foreach v, $(PROJECT_ADDONS_OBJFILES),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_BASE_CFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_BASE_CFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_DEFINES_CFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_DEFINES_CFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_INCLUDES_CFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_INCLUDES_CFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_LDFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_LDFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_DATA---) |
|||
$(foreach v, $(PROJECT_ADDONS_DATA),$(info $(v))) |
|||
endif |
|||
########################################################################
|
|||
# PROCESS VALID ADDONS IF AVAILABLE
|
|||
########################################################################
|
|||
|
|||
|
|||
# parses addons includes, in PARSED_ADDON_INCLUDES receives full PATHS to addons
|
|||
define parse_addons_includes |
|||
$(eval ADDONS_INCLUDES_FILTER = $(addprefix $1/, $(ADDON_INCLUDES_EXCLUDE))) \
|
|||
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
|
|||
$(eval PARSED_ADDONS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_SOURCE_INCLUDES))) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCE_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_SOURCE_INCLUDES))) \
|
|||
$(eval PARSED_ADDONS_LIBS_INCLUDES_PATHS = $(addsuffix /libs/*/include, $1)) \
|
|||
$(eval PARSED_ADDONS_LIBS_INCLUDES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_INCLUDES_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS = $(filter-out $(ADDONS_INCLUDES_FILTER),$(PARSED_ADDONS_LIBS_INCLUDES))) \
|
|||
$(eval PARSED_ADDONS_INCLUDES = $(PARSED_ADDONS_FILTERED_INCLUDE_PATHS)) \
|
|||
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_INCLUDE_PATHS)) \
|
|||
$(eval PARSED_ADDONS_INCLUDES += $(PARSED_ADDONS_FILTERED_LIBS_INCLUDE_PATHS)) |
|||
endef |
|||
|
|||
# parses addons sources, in PARSED_ADDON_SOURCES receives full PATHS to addons
|
|||
define parse_addons_sources |
|||
$(eval ADDONS_SOURCES_FILTER = $(addprefix $1/, $(ADDON_SOURCES_EXCLUDE))) \
|
|||
$(eval PARSED_ADDONS_SOURCE_PATHS = $(addsuffix /src, $1)) \
|
|||
$(eval PARSED_ADDONS_OFX_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_OFX_SOURCES))) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCE_PATHS = $(addsuffix /libs, $1)) \
|
|||
$(eval PARSED_ADDONS_LIBS_SOURCES = $(shell $(FIND) $(PARSED_ADDONS_LIBS_SOURCE_PATHS) -type f \( -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.cxx" \) 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS = $(filter-out $(ADDONS_SOURCES_FILTER),$(PARSED_ADDONS_LIBS_SOURCES))) \
|
|||
$(eval PARSED_ADDONS_SOURCE_FILES = $(PARSED_ADDONS_FILTERED_SOURCE_PATHS)) \
|
|||
$(eval PARSED_ADDONS_SOURCE_FILES += $(PARSED_ADDONS_FILTERED_LIBS_SOURCE_PATHS)) |
|||
endef |
|||
|
|||
# parses addons libraries, in PARSED_ADDON_LIBS receives full PATHS to addons and libs_exclude
|
|||
define parse_addons_libraries |
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS = $(filter-out $(ADDON_LIBS_EXCLUDE),$(addsuffix /libs/*/lib/$(ABI_LIB_SUBPATH), $1))) \
|
|||
$(eval PARSED_ALL_PLATFORM_LIBS = $(shell $(FIND) $(PARSED_ADDONS_LIBS_PLATFORM_LIB_PATHS) -type d 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(if $(PARSED_ALL_PLATFORM_LIBS), \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.a 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED = $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.so 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dylib 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED += $(shell $(FIND) $(PARSED_ALL_PLATFORM_LIBS) -name *.dll 2> /dev/null | grep -v "/\.[^\.]" )) \
|
|||
$(eval PARSED_ADDONS_LIBS = $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_STATICS)) \
|
|||
$(eval PARSED_ADDONS_LIBS += $(PARSED_ADDONS_LIBS_PLATFORM_LIBS_SHARED)) \
|
|||
) |
|||
endef |
|||
|
|||
|
|||
space := |
|||
space += |
|||
|
|||
define src_to_obj |
|||
$(addsuffix .o,$(basename $(filter %.c %.cpp %.cc %.cxx %.cc %.s %.S, $(addprefix $3,$(addprefix $2,$1))))) |
|||
endef |
|||
|
|||
define rwildcard |
|||
$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d)) |
|||
endef |
|||
|
|||
# PARSE addon_config.mk FILES
|
|||
#
|
|||
# 1. read the addon_config.mk file for each adddon that has it
|
|||
# 2. read each line of the addon by converting \n to \t since makefiles treat \n as spaces
|
|||
# also convert spaces to ? so foreach works for each line instead of each word
|
|||
# 3. unscape ? to space inside the loop
|
|||
# 4. if the line matches common: or platform: set the PROCESS_NEXT flag to true
|
|||
# 5. if the line matches %: but it's not common or platform: set PROCESS_NEXT to false
|
|||
# 6: if PROCESS_NEXT eval the line to put the variable in the makefile space
|
|||
define parse_addon |
|||
$(if $(wildcard $(PROJECT_ROOT)/$1), \
|
|||
$(eval addon=$(realpath $(addprefix $(PROJECT_ROOT)/, $1))) \
|
|||
$(eval addon_obj_path=$(PROJECT_ROOT)) \
|
|||
$(eval ADDON_PATHS+= $(dir $(addon))) \
|
|||
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)addons/) \
|
|||
, \
|
|||
$(eval addon=$(realpath $(addprefix $(OF_ADDONS_PATH)/, $1))) \
|
|||
$(eval addon_obj_path=$(OF_ADDONS_PATH)) \
|
|||
$(eval obj_prefix=$(OF_PROJECT_OBJ_OUTPUT_PATH)) \
|
|||
) \
|
|||
$(eval ADDON_DEPENDENCIES= ) \
|
|||
$(eval ADDON_DATA= ) \
|
|||
$(eval ADDON_CFLAGS= ) \
|
|||
$(eval ADDON_CPPFLAGS= ) \
|
|||
$(eval ADDON_LDFLAGS= ) \
|
|||
$(eval ADDON_PKG_CONFIG_LIBRARIES= ) \
|
|||
$(eval ADDON_FRAMEWORKS= ) \
|
|||
$(eval ADDON_LIBS_EXCLUDE= ) \
|
|||
$(eval ADDON_SOURCES_EXCLUDE= ) \
|
|||
$(call parse_addons_includes, $(addon)) \
|
|||
$(eval ADDON_INCLUDES=$(PARSED_ADDONS_INCLUDES)) \
|
|||
$(call parse_addons_libraries, $(addon)) \
|
|||
$(eval ADDON_LIBS=$(PARSED_ADDONS_LIBS)) \
|
|||
$(call parse_addons_sources, $(addon)) \
|
|||
$(eval ADDON_SOURCES=$(PARSED_ADDONS_SOURCE_FILES)) \
|
|||
$(eval PROCESS_NEXT=0) \
|
|||
$(if $(wildcard $(addon)/addon_config.mk), \
|
|||
$(foreach var_line, $(shell cat $(addon)/addon_config.mk | tr '\n ' '\t?'), \
|
|||
$(eval unscaped_var_line=$(strip $(subst ?, ,$(var_line)))) \
|
|||
$(if $(filter $(PROCESS_NEXT),1), $(eval $(unscaped_var_line))) \
|
|||
$(if $(filter %:,$(unscaped_var_line)), \
|
|||
$(if $(filter common:,$(unscaped_var_line)), \
|
|||
$(eval PROCESS_NEXT=1), \
|
|||
$(if $(filter $(ABI_LIB_SUBPATH):,$(unscaped_var_line)), \
|
|||
$(eval PROCESS_NEXT=1), \
|
|||
$(eval PROCESS_NEXT=0) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(if $(strip $(ADDON_INCLUDES)), \
|
|||
$(eval ADDON_INCLUDES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_INCLUDES_EXCLUDE)),$(ADDON_INCLUDES))) \
|
|||
$(foreach addon_include, $(strip $(ADDON_INCLUDES_FILTERED)), \
|
|||
$(if $(wildcard $(addon)/$(addon_include)), \
|
|||
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon)/$(addon_include)) \
|
|||
) \
|
|||
$(if $(wildcard $(addon_include)), \
|
|||
$(eval TMP_PROJECT_ADDONS_INCLUDES += $(addon_include)) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CFLAGS)) \
|
|||
$(eval TMP_PROJECT_ADDONS_CFLAGS += $(ADDON_CPPFLAGS)) \
|
|||
$(if $(strip $(ADDON_LIBS)), \
|
|||
$(foreach addon_lib, $(strip $(ADDON_LIBS)), \
|
|||
$(if $(wildcard $(addon)/$(addon_lib)), \
|
|||
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon)/$(addon_lib)) \
|
|||
) \
|
|||
$(if $(wildcard $(addon_lib)), \
|
|||
$(eval TMP_PROJECT_ADDONS_LIBS += $(addon_lib)) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(eval TMP_PROJECT_ADDONS_LDFLAGS += $(ADDON_LDFLAGS)) \
|
|||
$(eval TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES += $(ADDON_PKG_CONFIG_LIBRARIES)) \
|
|||
$(eval TMP_PROJECT_ADDONS_FRAMEWORKS += $(ADDON_FRAMEWORKS)) \
|
|||
$(eval PROJECT_AFTER += $(ADDON_AFTER)) \
|
|||
$(if $(strip $(ADDON_SOURCES)), \
|
|||
$(eval ADDON_SOURCES_FILTERED = $(filter-out $(addprefix $(addon)/,$(ADDON_SOURCES_EXCLUDE)),$(ADDON_SOURCES))) \
|
|||
$(foreach addon_src, $(strip $(ADDON_SOURCES_FILTERED)), \
|
|||
$(if $(filter $(addon)%, $(addon_src)), \
|
|||
$(eval addon_path=$(subst %,*,$(addon_src))) \
|
|||
$(if $(findstring *,$(addon_path)), \
|
|||
$(eval addon_dir=$(dir $(addon_path))) \
|
|||
$(eval addon_rest=$(notdir $(addon_path))) \
|
|||
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
|
|||
$(foreach expanded_addon_src, $(addon_files), \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(if $(filter $(OF_ROOT)%, $(addon_src)), \
|
|||
$(eval addon_path=$(subst %,*,$(addon_src))) \
|
|||
$(if $(findstring *,$(addon_path)), \
|
|||
$(eval addon_dir=$(dir $(addon_src))) \
|
|||
$(eval addon_rest=$(notdir $(addon_src))) \
|
|||
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
|
|||
$(foreach expanded_addon_src, $(addon_files), \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(expanded_addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(strip $(call src_to_obj, $(addon_src:$(OF_ROOT)/%=%),,$(obj_prefix)))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
,$(if $(filter-out /%, $(addon_src)), \
|
|||
$(eval addon_path=$(addon)/$(subst %,*,$(addon_src))) \
|
|||
$(if $(findstring *,$(addon_path)), \
|
|||
$(eval addon_dir=$(dir $(addon_path))) \
|
|||
$(eval addon_rest=$(notdir $(addon_path))) \
|
|||
$(eval addon_files=$(strip $(call rwildcard,$(addon_dir),$(addon_rest)))) \
|
|||
$(foreach expanded_addon_src, $(addon_files), \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(expanded_addon_src)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(expanded_addon_src:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
, \
|
|||
$(eval TMP_PROJECT_ADDONS_SOURCE_FILES += $(addon_path)) \
|
|||
$(eval SRC_OBJ_FILE=$(addprefix $(addon_obj_path)/,$(strip $(call src_to_obj, $(addon_path:$(addon)/%=%),$(notdir $1)/,$(obj_prefix))))) \
|
|||
$(eval TMP_PROJECT_ADDONS_OBJ_FILES += $(SRC_OBJ_FILE)) \
|
|||
) \
|
|||
,$(error cannot find addon source file $(addon_src))) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
) \
|
|||
$(if $(strip $(ADDON_DATA)), \
|
|||
$(eval TMP_PROJECT_ADDONS_DATA += $(addprefix $(addon)/,$(ADDON_DATA))) \
|
|||
) \
|
|||
$(foreach addon_dep, $(strip $(ADDON_DEPENDENCIES)), \
|
|||
$(if $(filter %$(addon_dep), $(PROJECT_ADDONS)), \
|
|||
, \
|
|||
$(eval PROJECT_ADDONS += $(addon_dep)) \
|
|||
$(call parse_addon,$(addon_dep)) \
|
|||
) \
|
|||
) |
|||
endef |
|||
|
|||
|
|||
$(foreach addon_to_parse, $(PROJECT_ADDONS), \ |
|||
$(call parse_addon,$(addon_to_parse)) \
|
|||
) |
|||
|
|||
#define uniq =
|
|||
# $(eval seen :=)
|
|||
# $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
|
|||
# ${seen}
|
|||
#endef
|
|||
|
|||
|
|||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) |
|||
|
|||
|
|||
PROJECT_ADDONS_CFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_CFLAGS)) |
|||
PROJECT_ADDONS_INCLUDES = $(call uniq,$(TMP_PROJECT_ADDONS_INCLUDES)) |
|||
PROJECT_ADDONS_LIBS = $(call uniq,$(TMP_PROJECT_ADDONS_LIBS)) |
|||
PROJECT_ADDONS_LDFLAGS = $(call uniq,$(TMP_PROJECT_ADDONS_LDFLAGS)) |
|||
PROJECT_ADDONS_PKG_CONFIG_LIBRARIES = $(call uniq,$(TMP_PROJECT_ADDONS_PKG_CONFIG_LIBRARIES)) |
|||
PROJECT_ADDONS_FRAMEWORKS = $(call uniq,$(TMP_PROJECT_ADDONS_FRAMEWORKS)) |
|||
PROJECT_ADDONS_SOURCE_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_SOURCE_FILES)) |
|||
PROJECT_ADDONS_OBJ_FILES = $(call uniq,$(TMP_PROJECT_ADDONS_OBJ_FILES)) |
|||
PROJECT_ADDONS_DATA = $(call uniq,$(TMP_PROJECT_ADDONS_DATA)) |
|||
VPATH += $(call uniq, $(ADDON_PATHS)) |
|||
|
|||
|
|||
OF_PROJECT_ADDONS_OBJS = $(PROJECT_ADDONS_OBJ_FILES) |
|||
OF_PROJECT_ADDONS_DEPS = $(patsubst %.o,%.d,$(PROJECT_ADDONS_OBJ_FILES)) |
|||
|
|||
########################################################################
|
|||
# DEBUGGING
|
|||
########################################################################
|
|||
# print debug information if so instructed
|
|||
ifdef MAKEFILE_DEBUG |
|||
$(info ---PROJECT_ADDONS_PATHS---) |
|||
$(foreach v, $(PROJECT_ADDONS_PATHS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_WITH_CONFIG---) |
|||
$(foreach v, $(PROJECT_ADDONS_WITH_CONFIG),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_INCLUDES---) |
|||
$(foreach v, $(PROJECT_ADDONS_INCLUDES),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_SOURCE_FILES---) |
|||
$(foreach v, $(PROJECT_ADDONS_SOURCE_FILES),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_LIBS---) |
|||
$(foreach v, $(PROJECT_ADDONS_LIBS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_OBJFILES---) |
|||
$(foreach v, $(PROJECT_ADDONS_OBJFILES),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_BASE_CFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_BASE_CFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_DEFINES_CFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_DEFINES_CFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_INCLUDES_CFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_INCLUDES_CFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_LDFLAGS---) |
|||
$(foreach v, $(PROJECT_ADDONS_LDFLAGS),$(info $(v))) |
|||
$(info ---PROJECT_ADDONS_DATA---) |
|||
$(foreach v, $(PROJECT_ADDONS_DATA),$(info $(v))) |
|||
endif |
|||
|
@ -1,8 +1,8 @@ |
|||
#!/usr/bin/bash |
|||
|
|||
echo "This script should be run from the patches/msys2 directory" |
|||
|
|||
cp --force ./sound/ofOpenALSoundPlayer.* ../../../../libs/openFrameworks/sound/ |
|||
cp --force ./makefileCommon/config.addons.mk ../../../../libs/openFrameworksCompiled/project/makefileCommon/config.addons.mk |
|||
|
|||
echo "Patch for msys2 complete" |
|||
#!/usr/bin/bash |
|||
|
|||
echo "This script should be run from the patches/msys2 directory" |
|||
|
|||
cp --force ./sound/ofOpenALSoundPlayer.* ../../../../libs/openFrameworks/sound/ |
|||
cp --force ./makefileCommon/config.addons.mk ../../../../libs/openFrameworksCompiled/project/makefileCommon/config.addons.mk |
|||
|
|||
echo "Patch for msys2 complete" |
|||
|
File diff suppressed because it is too large
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue