diff --git a/extras/Demo/Builds/Android/jni/Android.mk b/extras/Demo/Builds/Android/jni/Android.mk index 6d3a4fc8b1..bf2e9e7176 100644 --- a/extras/Demo/Builds/Android/jni/Android.mk +++ b/extras/Demo/Builds/Android/jni/Android.mk @@ -36,6 +36,7 @@ LOCAL_SRC_FILES := \ ../../../Source/Demos/MultiTouch.cpp\ ../../../Source/Demos/NetworkingDemo.cpp\ ../../../Source/Demos/OpenGLDemo.cpp\ + ../../../Source/Demos/OpenGLDemo2D.cpp\ ../../../Source/Demos/PropertiesDemo.cpp\ ../../../Source/Demos/SystemInfoDemo.cpp\ ../../../Source/Demos/TimersAndEventsDemo.cpp\ diff --git a/extras/Demo/Builds/Linux/Makefile b/extras/Demo/Builds/Linux/Makefile index d9edb849c2..0be879a43a 100644 --- a/extras/Demo/Builds/Linux/Makefile +++ b/extras/Demo/Builds/Linux/Makefile @@ -79,6 +79,7 @@ OBJECTS := \ $(OBJDIR)/MultiTouch_595f3a2e.o \ $(OBJDIR)/NetworkingDemo_fbd1b19f.o \ $(OBJDIR)/OpenGLDemo_fdac55da.o \ + $(OBJDIR)/OpenGLDemo2D_48eeadec.o \ $(OBJDIR)/PropertiesDemo_8ff1a8de.o \ $(OBJDIR)/SystemInfoDemo_984acd28.o \ $(OBJDIR)/TimersAndEventsDemo_f2656547.o \ @@ -263,6 +264,11 @@ $(OBJDIR)/OpenGLDemo_fdac55da.o: ../../Source/Demos/OpenGLDemo.cpp @echo "Compiling OpenGLDemo.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/OpenGLDemo2D_48eeadec.o: ../../Source/Demos/OpenGLDemo2D.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling OpenGLDemo2D.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/PropertiesDemo_8ff1a8de.o: ../../Source/Demos/PropertiesDemo.cpp -@mkdir -p $(OBJDIR) @echo "Compiling PropertiesDemo.cpp" diff --git a/extras/Demo/Builds/MacOSX/JuceDemo.xcodeproj/project.pbxproj b/extras/Demo/Builds/MacOSX/JuceDemo.xcodeproj/project.pbxproj index 8b273de11c..dd64b9ace6 100644 --- a/extras/Demo/Builds/MacOSX/JuceDemo.xcodeproj/project.pbxproj +++ b/extras/Demo/Builds/MacOSX/JuceDemo.xcodeproj/project.pbxproj @@ -49,6 +49,7 @@ 2346D126B3690390A0925F06 = {isa = PBXBuildFile; fileRef = 24B00BED20980D12119C228F; }; C54286354BE46CB39B4C5225 = {isa = PBXBuildFile; fileRef = FD46383E356A5DDC1AD53380; }; FE559832F5E168F0FF04CB6E = {isa = PBXBuildFile; fileRef = 2DA02BCCDBFD5BF2DA2D2FA9; }; + E635FA4F49200CDAE3E4E6F0 = {isa = PBXBuildFile; fileRef = 39A06D3252DDA6F97FB09495; }; CDC1A7E9F07FBFDD5DA92031 = {isa = PBXBuildFile; fileRef = 5AB15A508A07934A89398A6B; }; 5B96583E8DAA4EA4EA1ACF18 = {isa = PBXBuildFile; fileRef = 84BAF97675BE522B63DC9A4B; }; 372B92C7E54D51285649FDD1 = {isa = PBXBuildFile; fileRef = B731664FB9EEEBC618BAB5A0; }; @@ -311,6 +312,7 @@ 38FB6ABB883ECAD52027CE19 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChildProcess.cpp"; path = "../../../../modules/juce_core/threads/juce_ChildProcess.cpp"; sourceTree = "SOURCE_ROOT"; }; 3924287A67ED97279455625B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChannelRemappingAudioSource.cpp"; path = "../../../../modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; 393A46D91FB481557E4DF792 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_mac_CoreMidi.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp"; sourceTree = "SOURCE_ROOT"; }; + 39A06D3252DDA6F97FB09495 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGLDemo2D.cpp; path = ../../Source/Demos/OpenGLDemo2D.cpp; sourceTree = "SOURCE_ROOT"; }; 39E4404D57A8B66DF520B66F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MACAddress.h"; path = "../../../../modules/juce_core/network/juce_MACAddress.h"; sourceTree = "SOURCE_ROOT"; }; 3A42694A047942A44E8216F5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../../../modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; }; 3AB9E51994CD35A10F87EFF1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringArray.h"; path = "../../../../modules/juce_core/text/juce_StringArray.h"; sourceTree = "SOURCE_ROOT"; }; @@ -931,6 +933,7 @@ E7A5AF3EBCFEEF8787F2D14F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MidiKeyboardComponent.cpp"; path = "../../../../modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; E7EA99CD84E1EC598F4984DD = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Array.h"; path = "../../../../modules/juce_core/containers/juce_Array.h"; sourceTree = "SOURCE_ROOT"; }; E80CA3836329ED0EEC74BAE6 = {isa = PBXFileReference; lastKnownFileType = file.nib; name = RecentFilesMenuTemplate.nib; path = RecentFilesMenuTemplate.nib; sourceTree = "SOURCE_ROOT"; }; + E8B785D8DD9C49BC7FF5EA75 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGL_linux.h"; path = "../../../../modules/juce_opengl/native/juce_OpenGL_linux.h"; sourceTree = "SOURCE_ROOT"; }; EA7D346CAE6A07C0B395816B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Decibels.h"; path = "../../../../modules/juce_audio_basics/effects/juce_Decibels.h"; sourceTree = "SOURCE_ROOT"; }; EACCBFA17F4D07ECE058EEBB = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; 229D2DAADACF15540C3BBD15 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuceDemo.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; @@ -939,7 +942,6 @@ E7B21011F93915ADD2CC5DD9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_GlyphArrangement.cpp"; path = "../../../../modules/juce_graphics/fonts/juce_GlyphArrangement.cpp"; sourceTree = "SOURCE_ROOT"; }; E7EE6BDC0E3A0739529AED91 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioSubsectionReader.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"; sourceTree = "SOURCE_ROOT"; }; E8128A35828C860977FEC54C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioFormatWriter.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"; sourceTree = "SOURCE_ROOT"; }; - E8B785D8DD9C49BC7FF5EA75 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGL_linux.h"; path = "../../../../modules/juce_opengl/native/juce_OpenGL_linux.h"; sourceTree = "SOURCE_ROOT"; }; E98EA1189613978EA4E78D85 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentListener.h"; path = "../../../../modules/juce_gui_basics/components/juce_ComponentListener.h"; sourceTree = "SOURCE_ROOT"; }; E9A3E96E32C301EE817059C1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SliderPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; E9B8B3FAECC80B66257B14F9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BlowFish.h"; path = "../../../../modules/juce_cryptography/encryption/juce_BlowFish.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1042,6 +1044,7 @@ 24B00BED20980D12119C228F, FD46383E356A5DDC1AD53380, 2DA02BCCDBFD5BF2DA2D2FA9, + 39A06D3252DDA6F97FB09495, 5AB15A508A07934A89398A6B, 84BAF97675BE522B63DC9A4B, B731664FB9EEEBC618BAB5A0, @@ -2288,6 +2291,7 @@ 2346D126B3690390A0925F06, C54286354BE46CB39B4C5225, FE559832F5E168F0FF04CB6E, + E635FA4F49200CDAE3E4E6F0, CDC1A7E9F07FBFDD5DA92031, 5B96583E8DAA4EA4EA1ACF18, 372B92C7E54D51285649FDD1, diff --git a/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj b/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj index 5d272f008b..d41753724a 100644 --- a/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj +++ b/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj @@ -153,6 +153,7 @@ + diff --git a/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj.filters b/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj.filters index a2cf51a888..836736c893 100644 --- a/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj.filters +++ b/extras/Demo/Builds/VisualStudio2010/JuceDemo.vcxproj.filters @@ -403,6 +403,9 @@ JuceDemo\Source\Demos + + JuceDemo\Source\Demos + JuceDemo\Source\Demos diff --git a/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj b/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj index 1f5534717e..29704ad07e 100644 --- a/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj +++ b/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj @@ -159,6 +159,7 @@ + diff --git a/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj.filters b/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj.filters index a2cf51a888..836736c893 100644 --- a/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj.filters +++ b/extras/Demo/Builds/VisualStudio2012/JuceDemo.vcxproj.filters @@ -403,6 +403,9 @@ JuceDemo\Source\Demos + + JuceDemo\Source\Demos + JuceDemo\Source\Demos diff --git a/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj b/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj index 50ed53a55a..1683e1352e 100644 --- a/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj +++ b/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj @@ -159,6 +159,7 @@ + diff --git a/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj.filters b/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj.filters index 8dd489900b..38b296356f 100644 --- a/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj.filters +++ b/extras/Demo/Builds/VisualStudio2013/JuceDemo.vcxproj.filters @@ -403,6 +403,9 @@ JuceDemo\Source\Demos + + JuceDemo\Source\Demos + JuceDemo\Source\Demos diff --git a/extras/Demo/Builds/iOS/JuceDemo.xcodeproj/project.pbxproj b/extras/Demo/Builds/iOS/JuceDemo.xcodeproj/project.pbxproj index c03c039d5b..40cd5f7211 100644 --- a/extras/Demo/Builds/iOS/JuceDemo.xcodeproj/project.pbxproj +++ b/extras/Demo/Builds/iOS/JuceDemo.xcodeproj/project.pbxproj @@ -44,6 +44,7 @@ 2346D126B3690390A0925F06 = {isa = PBXBuildFile; fileRef = 24B00BED20980D12119C228F; }; C54286354BE46CB39B4C5225 = {isa = PBXBuildFile; fileRef = FD46383E356A5DDC1AD53380; }; FE559832F5E168F0FF04CB6E = {isa = PBXBuildFile; fileRef = 2DA02BCCDBFD5BF2DA2D2FA9; }; + E635FA4F49200CDAE3E4E6F0 = {isa = PBXBuildFile; fileRef = 39A06D3252DDA6F97FB09495; }; CDC1A7E9F07FBFDD5DA92031 = {isa = PBXBuildFile; fileRef = 5AB15A508A07934A89398A6B; }; 5B96583E8DAA4EA4EA1ACF18 = {isa = PBXBuildFile; fileRef = 84BAF97675BE522B63DC9A4B; }; 372B92C7E54D51285649FDD1 = {isa = PBXBuildFile; fileRef = B731664FB9EEEBC618BAB5A0; }; @@ -305,6 +306,7 @@ 38FB6ABB883ECAD52027CE19 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChildProcess.cpp"; path = "../../../../modules/juce_core/threads/juce_ChildProcess.cpp"; sourceTree = "SOURCE_ROOT"; }; 3924287A67ED97279455625B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChannelRemappingAudioSource.cpp"; path = "../../../../modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; 393A46D91FB481557E4DF792 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_mac_CoreMidi.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp"; sourceTree = "SOURCE_ROOT"; }; + 39A06D3252DDA6F97FB09495 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGLDemo2D.cpp; path = ../../Source/Demos/OpenGLDemo2D.cpp; sourceTree = "SOURCE_ROOT"; }; 39E4404D57A8B66DF520B66F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MACAddress.h"; path = "../../../../modules/juce_core/network/juce_MACAddress.h"; sourceTree = "SOURCE_ROOT"; }; 3A42694A047942A44E8216F5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../../../modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; }; 3AB9E51994CD35A10F87EFF1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringArray.h"; path = "../../../../modules/juce_core/text/juce_StringArray.h"; sourceTree = "SOURCE_ROOT"; }; @@ -912,53 +914,52 @@ E4BD5632ADD38CF8BAD38A76 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_CallOutBox.cpp"; path = "../../../../modules/juce_gui_basics/windows/juce_CallOutBox.cpp"; sourceTree = "SOURCE_ROOT"; }; E5058DD199CEC42ECE922239 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Justification.h"; path = "../../../../modules/juce_graphics/placement/juce_Justification.h"; sourceTree = "SOURCE_ROOT"; }; E52756E1DB553ED02D829F61 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_module_info"; path = "../../../../modules/juce_cryptography/juce_module_info"; sourceTree = "SOURCE_ROOT"; }; + E5E02A3C4E942105FEDCA885 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChannelRemappingAudioSource.h"; path = "../../../../modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h"; sourceTree = "SOURCE_ROOT"; }; E6333272C33612B6A7D6073E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_AudioCDBurner.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp"; sourceTree = "SOURCE_ROOT"; }; E682A3A52BD15D5CA4933C12 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeParallelogram.h"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h"; sourceTree = "SOURCE_ROOT"; }; E6E0ADA4E3632540A8ADC7D8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ConnectedChildProcess.cpp"; path = "../../../../modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp"; sourceTree = "SOURCE_ROOT"; }; E6E0FE3CBDBE2554B527CF60 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioSourcePlayer.cpp"; path = "../../../../modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp"; sourceTree = "SOURCE_ROOT"; }; E70A283A87989F5A1CEDE6A4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ResamplingAudioSource.cpp"; path = "../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; E7113B21A18CD89165BAFD4B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Messaging.cpp"; path = "../../../../modules/juce_events/native/juce_android_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; }; - E7A5AF3EBCFEEF8787F2D14F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MidiKeyboardComponent.cpp"; path = "../../../../modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; E7B21011F93915ADD2CC5DD9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_GlyphArrangement.cpp"; path = "../../../../modules/juce_graphics/fonts/juce_GlyphArrangement.cpp"; sourceTree = "SOURCE_ROOT"; }; E7EA99CD84E1EC598F4984DD = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Array.h"; path = "../../../../modules/juce_core/containers/juce_Array.h"; sourceTree = "SOURCE_ROOT"; }; E7EE6BDC0E3A0739529AED91 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioSubsectionReader.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"; sourceTree = "SOURCE_ROOT"; }; - E8128A35828C860977FEC54C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioFormatWriter.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"; sourceTree = "SOURCE_ROOT"; }; E8B785D8DD9C49BC7FF5EA75 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGL_linux.h"; path = "../../../../modules/juce_opengl/native/juce_OpenGL_linux.h"; sourceTree = "SOURCE_ROOT"; }; E98EA1189613978EA4E78D85 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentListener.h"; path = "../../../../modules/juce_gui_basics/components/juce_ComponentListener.h"; sourceTree = "SOURCE_ROOT"; }; E9A3E96E32C301EE817059C1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SliderPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; - E9B8B3FAECC80B66257B14F9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BlowFish.h"; path = "../../../../modules/juce_cryptography/encryption/juce_BlowFish.h"; sourceTree = "SOURCE_ROOT"; }; E9BBEE1B3986E0829AA44133 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImagePreviewComponent.h"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.h"; sourceTree = "SOURCE_ROOT"; }; EA082125C757D1FD63BA38C5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentAnimator.h"; path = "../../../../modules/juce_gui_basics/layout/juce_ComponentAnimator.h"; sourceTree = "SOURCE_ROOT"; }; + EACCBFA17F4D07ECE058EEBB = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; + EB6F5F8F57F0117C10735583 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioIODevice.h"; path = "../../../../modules/juce_audio_devices/audio_io/juce_AudioIODevice.h"; sourceTree = "SOURCE_ROOT"; }; + ED3DE86815324354C48631D0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_XMLCodeTokeniser.h"; path = "../../../../modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; + ED6224ABC715AAB68661F4D4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_box2d.cpp"; path = "../../../../modules/juce_box2d/juce_box2d.cpp"; sourceTree = "SOURCE_ROOT"; }; + F1E995A1E00C6545A4C3297B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = KeyMappingsDemo.cpp; path = ../../Source/Demos/KeyMappingsDemo.cpp; sourceTree = "SOURCE_ROOT"; }; + FBCD860CD7113A3136B127C8 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; + 229D2DAADACF15540C3BBD15 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuceDemo.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; + E34DFFF51D0F7C34FB826C4C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FloatVectorOperations.h"; path = "../../../../modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h"; sourceTree = "SOURCE_ROOT"; }; + E7A5AF3EBCFEEF8787F2D14F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MidiKeyboardComponent.cpp"; path = "../../../../modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; + E8128A35828C860977FEC54C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioFormatWriter.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"; sourceTree = "SOURCE_ROOT"; }; + E9B8B3FAECC80B66257B14F9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BlowFish.h"; path = "../../../../modules/juce_cryptography/encryption/juce_BlowFish.h"; sourceTree = "SOURCE_ROOT"; }; EA3436079F0D78BB76CD15F7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInactivityDetector.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h"; sourceTree = "SOURCE_ROOT"; }; EA7D346CAE6A07C0B395816B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Decibels.h"; path = "../../../../modules/juce_audio_basics/effects/juce_Decibels.h"; sourceTree = "SOURCE_ROOT"; }; EA9FE6D1E0A072E73312916C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentDragger.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_ComponentDragger.h"; sourceTree = "SOURCE_ROOT"; }; - EACCBFA17F4D07ECE058EEBB = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; EB369EA30D31CD710A09B7FD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_ios_MessageManager.mm"; path = "../../../../modules/juce_events/native/juce_ios_MessageManager.mm"; sourceTree = "SOURCE_ROOT"; }; - EB6F5F8F57F0117C10735583 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioIODevice.h"; path = "../../../../modules/juce_audio_devices/audio_io/juce_AudioIODevice.h"; sourceTree = "SOURCE_ROOT"; }; EC8A992EA9CFA558DB9F950E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CharacterFunctions.h"; path = "../../../../modules/juce_core/text/juce_CharacterFunctions.h"; sourceTree = "SOURCE_ROOT"; }; ECAB8BD2816B0BEFCD9F6961 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AsyncUpdater.h"; path = "../../../../modules/juce_events/broadcasters/juce_AsyncUpdater.h"; sourceTree = "SOURCE_ROOT"; }; - ED3DE86815324354C48631D0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_XMLCodeTokeniser.h"; path = "../../../../modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; - ED6224ABC715AAB68661F4D4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_box2d.cpp"; path = "../../../../modules/juce_box2d/juce_box2d.cpp"; sourceTree = "SOURCE_ROOT"; }; + ED80E9909586DD64BDE03A70 = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = portmeirion.jpg; path = ../../Resources/portmeirion.jpg; sourceTree = "SOURCE_ROOT"; }; EE7001BD5206A8D8EA2D125B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RectangleList.h"; path = "../../../../modules/juce_graphics/geometry/juce_RectangleList.h"; sourceTree = "SOURCE_ROOT"; }; EEA020419EF58E90C10AAE26 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableWindow.h"; path = "../../../../modules/juce_gui_basics/windows/juce_ResizableWindow.h"; sourceTree = "SOURCE_ROOT"; }; + EEAA1BB6254EDE07A7ABAD65 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_IIRFilterAudioSource.h"; path = "../../../../modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h"; sourceTree = "SOURCE_ROOT"; }; EF8055850F3DEA173761E3B5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MessageManager.cpp"; path = "../../../../modules/juce_events/messages/juce_MessageManager.cpp"; sourceTree = "SOURCE_ROOT"; }; + EFD1BD42000EE640A17EE1ED = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioFormatReaderSource.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.cpp"; sourceTree = "SOURCE_ROOT"; }; EFD480AA79620EC53C2686EA = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Draggable3DOrientation.h"; path = "../../../../modules/juce_opengl/opengl/juce_Draggable3DOrientation.h"; sourceTree = "SOURCE_ROOT"; }; F037091D4A3012EBBA1E808F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyboardFocusTraverser.cpp"; path = "../../../../modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.cpp"; sourceTree = "SOURCE_ROOT"; }; F0ACCF70936A0BBA2A2AB289 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Value.cpp"; path = "../../../../modules/juce_data_structures/values/juce_Value.cpp"; sourceTree = "SOURCE_ROOT"; }; F1A30E40F7388D16BA35B0DB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SHA256.cpp"; path = "../../../../modules/juce_cryptography/hashing/juce_SHA256.cpp"; sourceTree = "SOURCE_ROOT"; }; - F1E995A1E00C6545A4C3297B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = KeyMappingsDemo.cpp; path = ../../Source/Demos/KeyMappingsDemo.cpp; sourceTree = "SOURCE_ROOT"; }; - F29F6395C4935C1A663A1D15 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_GZIPDecompressorInputStream.h"; path = "../../../../modules/juce_core/zip/juce_GZIPDecompressorInputStream.h"; sourceTree = "SOURCE_ROOT"; }; - F380FE12E78619086BA33CDB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_InterprocessConnection.cpp"; path = "../../../../modules/juce_events/interprocess/juce_InterprocessConnection.cpp"; sourceTree = "SOURCE_ROOT"; }; - F91A3C07D81BE2D4A191C9A2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Timer.h"; path = "../../../../modules/juce_events/timers/juce_Timer.h"; sourceTree = "SOURCE_ROOT"; }; - FBCD860CD7113A3136B127C8 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; - 229D2DAADACF15540C3BBD15 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuceDemo.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; - E34DFFF51D0F7C34FB826C4C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FloatVectorOperations.h"; path = "../../../../modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h"; sourceTree = "SOURCE_ROOT"; }; - E5E02A3C4E942105FEDCA885 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChannelRemappingAudioSource.h"; path = "../../../../modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h"; sourceTree = "SOURCE_ROOT"; }; - ED80E9909586DD64BDE03A70 = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = portmeirion.jpg; path = ../../Resources/portmeirion.jpg; sourceTree = "SOURCE_ROOT"; }; - EEAA1BB6254EDE07A7ABAD65 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_IIRFilterAudioSource.h"; path = "../../../../modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h"; sourceTree = "SOURCE_ROOT"; }; - EFD1BD42000EE640A17EE1ED = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioFormatReaderSource.cpp"; path = "../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.cpp"; sourceTree = "SOURCE_ROOT"; }; F1A9F544E889DDA995415F6D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioSourcePlayer.h"; path = "../../../../modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h"; sourceTree = "SOURCE_ROOT"; }; F26339EFC03BD8D22016EEB6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_HeapBlock.h"; path = "../../../../modules/juce_core/memory/juce_HeapBlock.h"; sourceTree = "SOURCE_ROOT"; }; + F29F6395C4935C1A663A1D15 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_GZIPDecompressorInputStream.h"; path = "../../../../modules/juce_core/zip/juce_GZIPDecompressorInputStream.h"; sourceTree = "SOURCE_ROOT"; }; + F380FE12E78619086BA33CDB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_InterprocessConnection.cpp"; path = "../../../../modules/juce_events/interprocess/juce_InterprocessConnection.cpp"; sourceTree = "SOURCE_ROOT"; }; F3A9E0AE5ED05CA1AD6F56E5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SystemAudioVolume.h"; path = "../../../../modules/juce_audio_devices/audio_io/juce_SystemAudioVolume.h"; sourceTree = "SOURCE_ROOT"; }; F3AF542BB3A9E6CC1D6E37DD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PluginListComponent.cpp"; path = "../../../../modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; F3B746DC92EFE7A9B8EA9E43 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_UndoableAction.h"; path = "../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"; sourceTree = "SOURCE_ROOT"; }; @@ -981,6 +982,7 @@ F843FC09B4C2A10C76D8D35C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PluginDirectoryScanner.cpp"; path = "../../../../modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp"; sourceTree = "SOURCE_ROOT"; }; F881704607DB79F9A3CF7491 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Audio.cpp"; path = "../../../../modules/juce_audio_devices/native/juce_android_Audio.cpp"; sourceTree = "SOURCE_ROOT"; }; F89584972F16A8EC49E5E74D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeCoordinatePositioner.h"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h"; sourceTree = "SOURCE_ROOT"; }; + F91A3C07D81BE2D4A191C9A2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Timer.h"; path = "../../../../modules/juce_events/timers/juce_Timer.h"; sourceTree = "SOURCE_ROOT"; }; F965E478C21D19EF32760A9C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FilePreviewComponent.h"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FilePreviewComponent.h"; sourceTree = "SOURCE_ROOT"; }; F97F775EDCD2D1C497625D4F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Fonts.mm"; path = "../../../../modules/juce_graphics/native/juce_mac_Fonts.mm"; sourceTree = "SOURCE_ROOT"; }; F98BEA2FEE66A3DEAD9D43B1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_mac_SystemTrayIcon.cpp"; path = "../../../../modules/juce_gui_extra/native/juce_mac_SystemTrayIcon.cpp"; sourceTree = "SOURCE_ROOT"; }; @@ -1032,6 +1034,7 @@ 24B00BED20980D12119C228F, FD46383E356A5DDC1AD53380, 2DA02BCCDBFD5BF2DA2D2FA9, + 39A06D3252DDA6F97FB09495, 5AB15A508A07934A89398A6B, 84BAF97675BE522B63DC9A4B, B731664FB9EEEBC618BAB5A0, @@ -2270,6 +2273,7 @@ 2346D126B3690390A0925F06, C54286354BE46CB39B4C5225, FE559832F5E168F0FF04CB6E, + E635FA4F49200CDAE3E4E6F0, CDC1A7E9F07FBFDD5DA92031, 5B96583E8DAA4EA4EA1ACF18, 372B92C7E54D51285649FDD1, diff --git a/extras/Demo/JuceDemo.jucer b/extras/Demo/JuceDemo.jucer index 4ee5f6203d..c15855472f 100644 --- a/extras/Demo/JuceDemo.jucer +++ b/extras/Demo/JuceDemo.jucer @@ -250,6 +250,8 @@ + demo ("20 Graphics: OpenGL"); + +#endif diff --git a/extras/Demo/Source/Demos/OpenGLDemo2D.cpp b/extras/Demo/Source/Demos/OpenGLDemo2D.cpp new file mode 100644 index 0000000000..e94c6bea4d --- /dev/null +++ b/extras/Demo/Source/Demos/OpenGLDemo2D.cpp @@ -0,0 +1,250 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-12 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#include "../JuceDemoHeader.h" + +#if JUCE_OPENGL + +//============================================================================== +class OpenGL2DShaderDemo : public Component, + private CodeDocument::Listener, + private ComboBox::Listener, + private Timer +{ +public: + OpenGL2DShaderDemo() + : fragmentEditorComp (fragmentDocument, nullptr) + { + setOpaque (true); + MainAppWindow::getMainAppWindow()->setOpenGLRenderingEngine(); + + addAndMakeVisible (statusLabel); + statusLabel.setJustificationType (Justification::topLeft); + statusLabel.setColour (Label::textColourId, Colours::black); + statusLabel.setFont (Font (14.0f)); + + Array presets (getPresets()); + StringArray presetNames; + + for (int i = 0; i < presets.size(); ++i) + presetBox.addItem (presets[i].name, i + 1); + + addAndMakeVisible (presetLabel); + presetLabel.setText ("Shader Preset:", dontSendNotification); + presetLabel.attachToComponent (&presetBox, true); + + addAndMakeVisible (presetBox); + presetBox.addListener (this); + + Colour editorBackground (Colours::white.withAlpha (0.6f)); + fragmentEditorComp.setColour (CodeEditorComponent::backgroundColourId, editorBackground); + fragmentEditorComp.setOpaque (false); + fragmentDocument.addListener (this); + addAndMakeVisible (fragmentEditorComp); + + presetBox.setSelectedItemIndex (0); + } + + ~OpenGL2DShaderDemo() + { + shader = nullptr; + } + + void paint (Graphics& g) + { + g.fillCheckerBoard (getLocalBounds(), 48, 48, Colours::lightgrey, Colours::white); + + if (shader == nullptr || shader->getFragmentShaderCode() != fragmentCode) + { + shader = nullptr; + + if (fragmentCode.isNotEmpty()) + { + shader = new OpenGLGraphicsContextCustomShader (fragmentCode); + + Result result (shader->checkCompilation (g.getInternalContext())); + + if (result.failed()) + { + statusLabel.setText (result.getErrorMessage(), dontSendNotification); + shader = nullptr; + } + } + } + + if (shader != nullptr) + { + statusLabel.setText (String::empty, dontSendNotification); + + shader->fillRect (g.getInternalContext(), getLocalBounds()); + } + } + + void resized() override + { + Rectangle area (getLocalBounds().reduced (4)); + + statusLabel.setBounds (area.removeFromTop (75)); + + area.removeFromTop (area.getHeight() / 2); + + Rectangle presets (area.removeFromTop (25)); + presets.removeFromLeft (100); + presetBox.setBounds (presets.removeFromLeft (150)); + + area.removeFromTop (4); + fragmentEditorComp.setBounds (area); + } + + void selectPreset (int preset) + { + const ShaderPreset& p = getPresets()[preset]; + fragmentDocument.replaceAllContent (p.fragmentShader); + startTimer (1); + } + + ScopedPointer shader; + + Label statusLabel, presetLabel; + ComboBox presetBox; + CodeDocument fragmentDocument; + CodeEditorComponent fragmentEditorComp; + String fragmentCode; + +private: + enum { shaderLinkDelay = 500 }; + + void codeDocumentTextInserted (const String& /*newText*/, int /*insertIndex*/) override + { + startTimer (shaderLinkDelay); + } + + void codeDocumentTextDeleted (int /*startIndex*/, int /*endIndex*/) override + { + startTimer (shaderLinkDelay); + } + + void timerCallback() override + { + stopTimer(); + fragmentCode = fragmentDocument.getAllContent(); + repaint(); + } + + void comboBoxChanged (ComboBox*) override + { + selectPreset (presetBox.getSelectedItemIndex()); + } + + struct ShaderPreset + { + const char* name; + const char* fragmentShader; + }; + + static Array getPresets() + { + #define SHADER_DEMO_HEADER \ + "/* This demo shows the use of the OpenGLGraphicsContextCustomShader,\n" \ + " which allows a 2D area to be filled using a GL shader program.\n" \ + "\n" \ + " Edit the shader program below and it will be \n" \ + " recompiled in real-time!\n" \ + "*/\n\n" + + ShaderPreset presets[] = + { + { + "Simple Gradient", + + SHADER_DEMO_HEADER + "void main()\n" + "{\n" + " " JUCE_MEDIUMP " vec4 colour1 = vec4 (1.0, 0.4, 0.6, 1.0);\n" + " " JUCE_MEDIUMP " vec4 colour2 = vec4 (0.0, 0.8, 0.6, 1.0);\n" + " " JUCE_MEDIUMP " float alpha = pixelPos.x / 1000.0;\n" + " gl_FragColor = pixelAlpha * mix (colour1, colour2, alpha);\n" + "}\n" + }, + + { + "Circular Gradient", + + SHADER_DEMO_HEADER + "void main()\n" + "{\n" + " " JUCE_MEDIUMP " vec4 colour1 = vec4 (1.0, 0.4, 0.6, 1.0);\n" + " " JUCE_MEDIUMP " vec4 colour2 = vec4 (0.3, 0.4, 0.4, 1.0);\n" + " " JUCE_MEDIUMP " float alpha = distance (pixelPos, vec2 (600.0, 500.0)) / 400.0;\n" + " gl_FragColor = pixelAlpha * mix (colour1, colour2, alpha);\n" + "}\n" + }, + + { + "Cicle", + + SHADER_DEMO_HEADER + "void main()\n" + "{\n" + " " JUCE_MEDIUMP " vec4 colour1 = vec4 (0.1, 0.1, 0.9, 1.0);\n" + " " JUCE_MEDIUMP " vec4 colour2 = vec4 (0.0, 0.8, 0.6, 1.0);\n" + " " JUCE_MEDIUMP " float distance = distance (pixelPos, vec2 (600.0, 500.0));\n" + "\n" + " " JUCE_MEDIUMP " const float innerRadius = 200.0;\n" + " " JUCE_MEDIUMP " const float outerRadius = 210.0;\n" + "\n" + " if (distance < innerRadius)\n" + " gl_FragColor = colour1;\n" + " else if (distance > outerRadius)\n" + " gl_FragColor = colour2;\n" + " else\n" + " gl_FragColor = mix (colour1, colour2, (distance - innerRadius) / (outerRadius - innerRadius));\n" + "\n" + " gl_FragColor *= pixelAlpha;\n" + "}\n" + }, + + { + "Solid Colour", + + SHADER_DEMO_HEADER + "void main()\n" + "{\n" + " gl_FragColor = vec4 (1.0, 0.6, 0.1, pixelAlpha);\n" + "}\n" + } + }; + + return Array (presets, numElementsInArray (presets)); + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGL2DShaderDemo) +}; + +//============================================================================== +// This static object will register this demo type in a global list of demos.. +static JuceDemoType demo ("20 Graphics: OpenGL 2D"); + +#endif diff --git a/extras/Demo/Source/MainWindow.cpp b/extras/Demo/Source/MainWindow.cpp index 291694587f..035a83d2f7 100644 --- a/extras/Demo/Source/MainWindow.cpp +++ b/extras/Demo/Source/MainWindow.cpp @@ -215,7 +215,14 @@ public: bool isShowingOpenGLDemo() const { - return currentDemo != nullptr && currentDemo->getName().contains ("OpenGL"); + return currentDemo != nullptr + && currentDemo->getName().contains ("OpenGL") + && ! isShowingOpenGL2DDemo(); + } + + bool isShowingOpenGL2DDemo() const + { + return currentDemo != nullptr && currentDemo->getName().contains ("OpenGL 2D"); } private: @@ -605,6 +612,11 @@ void MainAppWindow::setRenderingEngine (int index) peer->setCurrentRenderingEngine (index); } +void MainAppWindow::setOpenGLRenderingEngine() +{ + setRenderingEngine (getRenderingEngines().indexOf (openGLRendererName)); +} + int MainAppWindow::getActiveRenderingEngine() const { #if JUCE_OPENGL diff --git a/extras/Demo/Source/MainWindow.h b/extras/Demo/Source/MainWindow.h index d47509ceda..2bfe058211 100644 --- a/extras/Demo/Source/MainWindow.h +++ b/extras/Demo/Source/MainWindow.h @@ -51,6 +51,7 @@ public: StringArray getRenderingEngines() const; int getActiveRenderingEngine() const; void setRenderingEngine (int index); + void setOpenGLRenderingEngine(); // (returns the exploding JUCE logo path) static Path getJUCELogoPath(); diff --git a/modules/juce_opengl/juce_opengl.h b/modules/juce_opengl/juce_opengl.h index d805383a9b..d4f675024c 100644 --- a/modules/juce_opengl/juce_opengl.h +++ b/modules/juce_opengl/juce_opengl.h @@ -95,6 +95,7 @@ namespace juce class OpenGLTexture; class OpenGLFrameBuffer; +class OpenGLShaderProgram; #include "native/juce_MissingGLDefinitions.h" #include "opengl/juce_OpenGLHelpers.h" diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index 8c05d8c02a..ac3644ec66 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -739,9 +739,17 @@ void OpenGLContext::setAssociatedObject (const char* name, ReferenceCountedObjec if (index >= 0) { - c->associatedObjects.set (index, newObject); + if (newObject != nullptr) + { + c->associatedObjects.set (index, newObject); + } + else + { + c->associatedObjectNames.remove (index); + c->associatedObjects.remove (index); + } } - else + else if (newObject != nullptr) { c->associatedObjectNames.add (name); c->associatedObjects.add (newObject); diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index afd0e38ae2..b257841b25 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -354,12 +354,13 @@ public: " gl_Position = vec4 (scaledPos.x - 1.0, 1.0 - scaledPos.y, 0, 1.0);" "}"); - program.addFragmentShader (fragmentShader); + compiledOk = program.addFragmentShader (fragmentShader); program.link(); JUCE_CHECK_OPENGL_ERROR } OpenGLShaderProgram program; + bool compiledOk; }; struct ShaderBase : public ShaderProgramHolder @@ -1492,12 +1493,13 @@ class SavedState : public RenderingHelpers::SavedStateBase public: SavedState (GLState* const s) - : BaseClass (s->target.bounds), state (s) + : BaseClass (s->target.bounds), state (s), isUsingCustomShader (false) {} SavedState (const SavedState& other) : BaseClass (other), font (other.font), - state (other.state), transparencyLayer (other.transparencyLayer), + state (other.state), isUsingCustomShader (false), + transparencyLayer (other.transparencyLayer), previousTarget (other.previousTarget.createCopy()) {} @@ -1618,9 +1620,13 @@ public: template void fillWithSolidColour (IteratorType& iter, const PixelARGB colour, bool replaceContents) const { - state->activeTextures.disableTextures (state->shaderQuadQueue); - state->blendMode.setBlendMode (state->shaderQuadQueue, replaceContents); - state->setShader (state->currentShader.programs->solidColourProgram); + if (! isUsingCustomShader) + { + state->activeTextures.disableTextures (state->shaderQuadQueue); + state->blendMode.setBlendMode (state->shaderQuadQueue, replaceContents); + state->setShader (state->currentShader.programs->solidColourProgram); + } + state->shaderQuadQueue.add (iter, colour); } @@ -1631,16 +1637,21 @@ public: state->shaderQuadQueue.add (iter, fillType.colour.getPixelARGB()); } - void fillRectWithCustomShader (OpenGLRendering::ShaderPrograms::ShaderBase& shader, const Rectangle& area, Colour colour) + void fillRectWithCustomShader (OpenGLRendering::ShaderPrograms::ShaderBase& shader, const Rectangle& area) { state->setShader (shader); - state->shaderQuadQueue.add (area, colour.getPixelARGB()); + isUsingCustomShader = true; + + fillRect (area, true); + + isUsingCustomShader = false; state->currentShader.clearShader (state->shaderQuadQueue); } //============================================================================== Font font; GLState* state; + bool isUsingCustomShader; private: Image transparencyLayer; @@ -1659,9 +1670,9 @@ public: stack.initialise (new SavedState (&glState)); } - void fillRectWithCustomShader (ShaderPrograms::ShaderBase& shader, const Rectangle& area, Colour colour) + void fillRectWithCustomShader (ShaderPrograms::ShaderBase& shader, const Rectangle& area) { - static_cast (*stack).fillRectWithCustomShader (shader, area, colour); + static_cast (*stack).fillRectWithCustomShader (shader, area); } GLState glState; @@ -1750,39 +1761,88 @@ void clearOpenGLGlyphCache() //============================================================================== -struct OpenGLGraphicsContextCustomShader::Pimpl : public OpenGLRendering::ShaderPrograms::ShaderBase +struct CustomProgram : public ReferenceCountedObject, + public OpenGLRendering::ShaderPrograms::ShaderBase { - Pimpl (OpenGLRendering::ShaderContext& c, const String& fragmentShader) + CustomProgram (OpenGLRendering::ShaderContext& c, const String& fragmentShader) : ShaderBase (c.glState.target.context, fragmentShader.toRawUTF8()) { } - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) -}; + static CustomProgram* get (const String& hashName) + { + if (OpenGLContext* c = OpenGLContext::getCurrentContext()) + return static_cast (c->getAssociatedObject (hashName.toRawUTF8())); -OpenGLGraphicsContextCustomShader::OpenGLGraphicsContextCustomShader (Pimpl* p) : pimpl (p) {} -OpenGLGraphicsContextCustomShader::~OpenGLGraphicsContextCustomShader() {} + return nullptr; + } -OpenGLGraphicsContextCustomShader* OpenGLGraphicsContextCustomShader::create (LowLevelGraphicsContext& gc, StringRef fragmentShaderCode) -{ - if (OpenGLRendering::ShaderContext* sc = dynamic_cast (&gc)) + static CustomProgram* getOrCreate (LowLevelGraphicsContext& gc, const String& hashName, const String& code, String& errorMessage) { - ScopedPointer p (new Pimpl (*sc, String (JUCE_DECLARE_VARYING_COLOUR JUCE_DECLARE_VARYING_PIXELPOS "\n") + fragmentShaderCode)); + if (CustomProgram* c = get (hashName)) + return c; + + if (OpenGLRendering::ShaderContext* sc = dynamic_cast (&gc)) + { + ReferenceCountedObjectPtr c (new CustomProgram (*sc, code)); + + if (c->compiledOk) + { + if (OpenGLContext* context = OpenGLContext::getCurrentContext()) + { + context->setAssociatedObject (hashName.toRawUTF8(), c); + return c; + } + } - if (! p->program.isLinked()) - return nullptr; + errorMessage = c->program.getLastError(); + } - return new OpenGLGraphicsContextCustomShader (p.release()); + return nullptr; } - jassertfalse; // You've passed-in a non-GL context! + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomProgram) +}; + +OpenGLGraphicsContextCustomShader::OpenGLGraphicsContextCustomShader (const String& fragmentShaderCode) + : code (String (JUCE_DECLARE_VARYING_COLOUR + JUCE_DECLARE_VARYING_PIXELPOS + "\nfloat pixelAlpha = frontColour.a;\n") + fragmentShaderCode), + hashName (String::toHexString (fragmentShaderCode.hashCode64()) + "_shader") +{ +} + +OpenGLGraphicsContextCustomShader::~OpenGLGraphicsContextCustomShader() +{ + if (OpenGLContext* context = OpenGLContext::getCurrentContext()) + context->setAssociatedObject (hashName.toRawUTF8(), nullptr); +} + +OpenGLShaderProgram* OpenGLGraphicsContextCustomShader::getProgram (LowLevelGraphicsContext& gc) const +{ + String errorMessage; + + if (CustomProgram* c = CustomProgram::getOrCreate (gc, hashName, code, errorMessage)) + return &(c->program); + return nullptr; } -void OpenGLGraphicsContextCustomShader::fillRect (LowLevelGraphicsContext& gc, const Rectangle& area, Colour colour) const +void OpenGLGraphicsContextCustomShader::fillRect (LowLevelGraphicsContext& gc, const Rectangle& area) const { - jassert (pimpl != nullptr); + String errorMessage; if (OpenGLRendering::ShaderContext* sc = dynamic_cast (&gc)) - sc->fillRectWithCustomShader (*pimpl, area, colour); + if (CustomProgram* c = CustomProgram::getOrCreate (gc, hashName, code, errorMessage)) + sc->fillRectWithCustomShader (*c, area); +} + +Result OpenGLGraphicsContextCustomShader::checkCompilation (LowLevelGraphicsContext& gc) +{ + String errorMessage; + + if (CustomProgram::getOrCreate (gc, hashName, code, errorMessage) != nullptr) + return Result::ok(); + + return Result::fail (errorMessage); } diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h index c087d81b64..b94a80c83e 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.h @@ -47,41 +47,47 @@ LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context, //============================================================================== -/** +/** Used to create custom shaders for use with an openGL 2D rendering context. - + Given a GL-based rendering context, you can write a fragment shader that applies some kind of per-pixel effect. */ struct JUCE_API OpenGLGraphicsContextCustomShader { + /** Creates a custom shader. + + The shader code will not be compiled until actually needed, so it's OK to call this + constructor when no GL context is active. + + The code should be a normal fragment shader. As well as the usual GLSL variables, there is + also an automatically declared varying vec2 called "pixelPos", which indicates the pixel + position within the graphics context of the pixel being drawn. There is also a varying value + "pixelAlpha", which indicates the alpha by which the pixel should be multiplied, so that the + edges of any clip-region masks are anti-aliased correctly. + */ + OpenGLGraphicsContextCustomShader (const String& fragmentShaderCode); + /** Destructor. */ ~OpenGLGraphicsContextCustomShader(); - /** Attempts to compile and return a new shader object. - This must be called only when an openGL context is active. It'll return nullptr - if the code fails to compile or some other error occurs. - - The shader code should be a normal fragment shader. As well as the usual variables, there - will be some extra ones: "frontColour", which is the colour that gets passed into the fillRect - method, and "pixelPos", which is a vec2 indicating the pixel position within the graphics context - of the pixel being drawn. + /** Returns the program, if it has been linked and is active. + This can be called when you're about to use fillRect, to set up any uniforms/textures that + the program may require. */ - static OpenGLGraphicsContextCustomShader* create (LowLevelGraphicsContext&, - StringRef fragmentShaderCode); + OpenGLShaderProgram* getProgram (LowLevelGraphicsContext&) const; - /** Applies the shader to a rectangle within the graphics context. - NB: This will ignore any clip region that is active. - */ - void fillRect (LowLevelGraphicsContext&, const Rectangle& area, Colour colour) const; + /** Applies the shader to a rectangle within the graphics context. */ + void fillRect (LowLevelGraphicsContext&, const Rectangle& area) const; -private: - struct Pimpl; - friend struct Pimpl; - friend struct ContainerDeletePolicy; - ScopedPointer pimpl; + /** Attempts to compile the program if necessary, and returns an error message if it fails. */ + Result checkCompilation (LowLevelGraphicsContext&); - OpenGLGraphicsContextCustomShader (Pimpl*); + /** Returns the code that was used to create this object. */ + const String& getFragmentShaderCode() const noexcept { return code; } + +private: + String code, hashName; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLGraphicsContextCustomShader) }; diff --git a/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp b/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp index 07f33b0e81..8e53dc228a 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp @@ -23,17 +23,33 @@ */ OpenGLShaderProgram::OpenGLShaderProgram (const OpenGLContext& c) noexcept - : context (c) + : context (c), programID (0) { - // This object can only be created and used when the current thread has an active OpenGL context. +} + +OpenGLShaderProgram::~OpenGLShaderProgram() noexcept +{ + release(); +} + +GLuint OpenGLShaderProgram::getProgramID() const noexcept +{ + // This method can only be used when the current thread has an active OpenGL context. jassert (OpenGLHelpers::isContextActive()); - programID = context.extensions.glCreateProgram(); + if (programID == 0) + programID = context.extensions.glCreateProgram(); + + return programID; } -OpenGLShaderProgram::~OpenGLShaderProgram() noexcept +void OpenGLShaderProgram::release() noexcept { - context.extensions.glDeleteProgram (programID); + if (programID != 0) + { + context.extensions.glDeleteProgram (programID); + programID = 0; + } } double OpenGLShaderProgram::getLanguageVersion() @@ -83,7 +99,7 @@ bool OpenGLShaderProgram::addShader (StringRef code, GLenum type) return false; } - context.extensions.glAttachShader (programID, shaderID); + context.extensions.glAttachShader (getProgramID(), shaderID); context.extensions.glDeleteShader (shaderID); JUCE_CHECK_OPENGL_ERROR return true; @@ -94,16 +110,21 @@ bool OpenGLShaderProgram::addFragmentShader (StringRef code) { return addShader bool OpenGLShaderProgram::link() noexcept { - context.extensions.glLinkProgram (programID); + // This method can only be used when the current thread has an active OpenGL context. + jassert (OpenGLHelpers::isContextActive()); + + GLuint progID = getProgramID(); + + context.extensions.glLinkProgram (progID); GLint status = GL_FALSE; - context.extensions.glGetProgramiv (programID, GL_LINK_STATUS, &status); + context.extensions.glGetProgramiv (progID, GL_LINK_STATUS, &status); if (status == GL_FALSE) { GLchar infoLog [16384]; GLsizei infoLogLength = 0; - context.extensions.glGetProgramInfoLog (programID, sizeof (infoLog), &infoLogLength, infoLog); + context.extensions.glGetProgramInfoLog (progID, sizeof (infoLog), &infoLogLength, infoLog); errorLog = String (infoLog, (size_t) infoLogLength); #if JUCE_DEBUG && ! JUCE_DONT_ASSERT_ON_GLSL_COMPILE_ERROR @@ -124,13 +145,13 @@ void OpenGLShaderProgram::use() const noexcept } OpenGLShaderProgram::Uniform::Uniform (const OpenGLShaderProgram& program, const char* const name) - : uniformID (program.context.extensions.glGetUniformLocation (program.programID, name)), context (program.context) + : uniformID (program.context.extensions.glGetUniformLocation (program.getProgramID(), name)), context (program.context) { jassert (uniformID >= 0); } OpenGLShaderProgram::Attribute::Attribute (const OpenGLShaderProgram& program, const char* name) - : attributeID (program.context.extensions.glGetAttribLocation (program.programID, name)) + : attributeID (program.context.extensions.glGetAttribLocation (program.getProgramID(), name)) { jassert (attributeID >= 0); } diff --git a/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.h b/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.h index 17d0f258de..6a74ebf2a8 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.h +++ b/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.h @@ -82,12 +82,12 @@ public: /** Get the output for the last shader compilation or link that failed. */ const String& getLastError() const noexcept { return errorLog; } - /** Returns true if the program is linked and ready for use. */ - bool isLinked() const noexcept { return programID != 0; } - /** Selects this program into the current context. */ void use() const noexcept; + /** Deletes the program. */ + void release() noexcept; + /** Represents an openGL uniform value. After a program has been linked, you can create Uniform objects to let you set the uniforms that your shaders use. @@ -154,10 +154,11 @@ public: }; /** The ID number of the compiled program. */ - GLuint programID; + GLuint getProgramID() const noexcept; private: const OpenGLContext& context; + mutable GLuint programID; String errorLog; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLShaderProgram)