diff --git a/.travis.yml b/.travis.yml index 44d8f93..4d0cc24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,59 +1,65 @@ -os: - - linux - - osx - -language: d - -sudo: false - -addons: - apt: - packages: - - libfreetype6-dev - - libgl1-mesa-dev - - libglew-dev - - libjpeg8-dev - - libopenal-dev - - libpthread-stubs0-dev - - libsndfile1-dev - - libx11-dev - - libxrandr-dev - -d: - - dmd-2.069.2 - - dmd-2.068.2 - - dmd-2.067.1 - - dmd-2.066.1 - - gdc-5.2.0 - - gdc-4.9.3 - - gdc-4.8.2 - - ldc-0.16.1 - - ldc-0.16.0 - - ldc-0.15.1 - -#GDC is not supported on OS X :( -matrix: - exclude: - - os: osx - d: gdc-5.2.0 - - os: osx - d: gdc-4.9.3 - - os: osx - d: gdc-4.8.2 - -#Build and install DSFMLC -install: - - cd $HOME - - git clone --depth=1 https://github.com/Jebbs/DSFMLC.git - - cd DSFMLC - - cmake . - - make -j2 - - export LIBRARY_PATH=${HOME}/DSFMLC/lib - - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${HOME}/DSFMLC/lib - - cd $TRAVIS_BUILD_DIR - -script: - - ${DMD} build.d - - ./build -unittest - - +os: + - linux + - osx + +language: d + +sudo: false + +addons: + apt: + packages: + - libfreetype6-dev + - libgl1-mesa-dev + - libglew-dev + - libjpeg8-dev + - libopenal-dev + - libpthread-stubs0-dev + - libsndfile1-dev + - libx11-dev + - libx11-xcb-dev + - libxrandr-dev + - libxcb-image0-dev + - libxcb-randr0-dev + - libudev-dev + - libvorbis-dev + - libflac-dev + +d: + - dmd-2.069.2 + - dmd-2.068.2 + - dmd-2.067.1 + - dmd-2.066.1 + - gdc-5.2.0 + - gdc-4.9.3 + - gdc-4.8.2 + - ldc-0.16.1 + - ldc-0.16.0 + - ldc-0.15.1 + +#GDC is not supported on OS X :( +matrix: + exclude: + - os: osx + d: gdc-5.2.0 + - os: osx + d: gdc-4.9.3 + - os: osx + d: gdc-4.8.2 + +#Build and install DSFMLC +install: + - cd $HOME + - git clone --depth=1 --branch 2.3-stringpassthrough https://github.com/aubade/DSFMLC.git + - cd DSFMLC + - cmake . + - make -j2 + - export LIBRARY_PATH=${HOME}/DSFMLC/lib + - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${HOME}/DSFMLC/lib + - cd $TRAVIS_BUILD_DIR + +script: + - ${DMD} build.d + - ./build -unittest + + diff --git a/appveyor.yml b/appveyor.yml index f3177c6..0273764 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,204 +1,204 @@ -# Build version format -version: 2.1.{build} - -os: Visual Studio 2015 - -clone_depth: 1 - -#Let's blacklist gh-pages -branches: - except: - - gh-pages - -environment: - matrix: - - DC: dmd - DVersion: 2.069.2 - arch: x86 - - DC: dmd - DVersion: 2.069.2 - arch: x64 - - DC: dmd - DVersion: 2.068.2 - arch: x86 - - DC: dmd - DVersion: 2.068.2 - arch: x64 - - DC: dmd - DVersion: 2.067.1 - arch: x86 - - DC: dmd - DVersion: 2.067.1 - arch: x64 - - DC: dmd - DVersion: 2.066.1 - arch: x86 - - DC: dmd - DVersion: 2.066.1 - arch: x64 - - DC: gdc - DVersion: 5.2.0 - arch: x86 - - DC: gdc - DVersion: 5.2.0 - arch: x64 - - DC: gdc - DVersion: 4.9.3 - arch: x86 - - DC: gdc - DVersion: 4.9.3 - arch: x64 - - DC: ldc - DVersion: 0.16.1 - arch: x64 -#0.15.1 doesn't work properly on Windows due to poor x64 support. -# - DC: ldc -# DVersion: 0.15.1 -# arch: x64 - - -#Set up our powershell functions -init: -#putting these in here for now, will export to different script to be imported later maybe? -- ps: function SetUpDCompiler - { - if($env:DC -eq "dmd"){ - if($env:arch -eq "x86"){ - $env:DConf = "m32"; - } - elseif($env:arch -eq "x64"){ - $env:DConf = "m64"; - } - $env:toolchain = "msvc"; - $version = $env:DVersion; - $WebLocation = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.zip"; - $DownloadLocation = "c:\dmd.zip"; - (new-object net.webclient).DownloadFile($WebLocation, $DownloadLocation); - pushd c:\\; - 7z x dmd.zip > $null; - popd; - } - elseif($env:DC -eq "gdc"){ - if($env:arch -eq "x86"){ - $env:DConf = "m32"; - $version = $env:DVersion; - $WebLocation = "ftp://ftp.gdcproject.org/binaries/$($version)/i686-w64-mingw32/gdc-$($version)+2.066.1.7z"; - $mingwWebLocation = "http://dsfml.com/bins/mingw/i686-5.2.0-release-posix-dwarf-rt_v4-rev0.7z"; - } - elseif($env:arch -eq "x64"){ - $env:DConf = "m64"; - $version = $env:DVersion; - $WebLocation = "ftp://ftp.gdcproject.org/binaries/$($version)/x86_64-w64-mingw32/gdc-$($version)+2.066.1.7z"; - $mingwWebLocation = "http://dsfml.com/bins/mingw/x86_64-5.2.0-release-posix-seh-rt_v4-rev0.7z"; - } - $env:toolchain = "mingw"; - $DownloadLocation = "c:\gdc.7z"; - $mingwDownloadLocation = "c:\mingw.7z"; - (new-object net.webclient).DownloadFile($WebLocation, $DownloadLocation); - (new-object net.webclient).DownloadFile($mingwWebLocation, $mingwDownloadLocation); - pushd c:\\; - 7z x gdc.7z > $null; - 7z x mingw.7z > $null; - popd; - } - elseif($env:DC -eq "ldc"){ - if($env:arch -eq "x86"){ - $env:DConf = "m32"; - } - elseif($env:arch -eq "x64"){ - $env:DConf = "m64"; - } - $env:toolchain = "msvc"; - $version = $env:DVersion; - $WebLocation = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-win64-msvc.zip"; - $DownloadLocation = "c:\ldc.zip"; - (new-object net.webclient).DownloadFile($WebLocation, $DownloadLocation); - pushd c:\\; - 7z x ldc.zip > $null; - popd; - } - } - - - -install: -#Install the D compiler -- ps: SetUpDCompiler - - -before_build: -#Set's up MSVC and MinGW -#We can't use the default PATH when using MinGW because another MinGW is on the path and it messes things up. -#We also have to set up MSVC because I couldn't get the script to work with IF statements. :( - - ps: if($env:toolchain -eq "msvc"){ - if($env:arch -eq "x86"){ - $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall"; - $env:compilersetupargs = "x86"; - } - elseif($env:arch -eq "x64"){ - $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall"; - $env:compilersetupargs = "amd64"; - } - $env:maketype = "NMake Makefiles"; - $env:makecommand = "nmake"; - } - elseif($env:toolchain -eq "mingw"){ - if($env:arch -eq "x86"){ - $env:compilerpath = "C:\mingw32\bin;"; - $env:cmakepath = "C:\Program Files (x86)\CMake\bin"; - } - elseif($env:arch -eq "x64"){ - $env:compilerpath = "C:\mingw64\bin;"; - $env:cmakepath = "C:\Program Files (x86)\CMake\bin"; - } - $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; - $env:compilersetupargs = "x86"; - $env:maketype = "MinGW Makefiles"; - $env:makecommand = "mingw32-make"; - } -#Set's up our D compiler - - ps : if($env:DC -eq "dmd"){ - $env:Dcompilerpath = "C:\dmd2\windows\bin;"; - $env:outputfile = "-ofbuild.exe"; - if($env:arch -eq "x86"){ - $env:makecommand = "nmake & implib"; - } - } - elseif($env:DC -eq "gdc"){ - $env:outputfile = "-obuild.exe"; - if($env:arch -eq "x86"){ - $env:Dcompilerpath = "C:\i686-w64-mingw32\bin;"; - } - elseif($env:arch -eq "x64"){ - $env:Dcompilerpath = "C:\x86_64-w64-mingw32\bin;"; - } - } - elseif($env:DC -eq "ldc"){ - $version = $env:DVersion; - $env:Dcompilerpath = "C:\ldc2-$($version)-win64-msvc\bin;"; - $env:outputfile = "-of=build.exe"; - $env:DC = "ldc2"; - } - - - -#Build DSFMLC and then build DSFML with it -build_script: -- echo %VCINSTALLDIR% -- '"%compilersetup%" %compilersetupargs%' -- cd .. -- git clone --depth=1 https://github.com/Jebbs/DSFMLC.git -- cd DSFMLC -- ps: if($env:toolchain -eq "mingw"){ - $env:Path = $env:compilerpath + $env:cmakepath; - } -- cmake -G"%maketype%" . -- '%makecommand%' -- cd "C:\\projects\\dsfml" -- ps : $env:Path = $env:Dcompilerpath + $env:Path -- ps: if($env:DC -eq "ldc2"){ - $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; - } -- '"%compilersetup%" %compilersetupargs%' -- '%DC% build.d %outputfile%' -- 'build.exe -%DConf% -unittest:C:\projects\DSFMLC\lib\' +# Build version format +version: 2.1.{build} + +os: Visual Studio 2015 + +clone_depth: 1 + +#Let's blacklist gh-pages +branches: + except: + - gh-pages + +environment: + matrix: + - DC: dmd + DVersion: 2.069.2 + arch: x86 + - DC: dmd + DVersion: 2.069.2 + arch: x64 + - DC: dmd + DVersion: 2.068.2 + arch: x86 + - DC: dmd + DVersion: 2.068.2 + arch: x64 + - DC: dmd + DVersion: 2.067.1 + arch: x86 + - DC: dmd + DVersion: 2.067.1 + arch: x64 + - DC: dmd + DVersion: 2.066.1 + arch: x86 + - DC: dmd + DVersion: 2.066.1 + arch: x64 + - DC: gdc + DVersion: 5.2.0 + arch: x86 + - DC: gdc + DVersion: 5.2.0 + arch: x64 + - DC: gdc + DVersion: 4.9.3 + arch: x86 + - DC: gdc + DVersion: 4.9.3 + arch: x64 + - DC: ldc + DVersion: 0.16.1 + arch: x64 +#0.15.1 doesn't work properly on Windows due to poor x64 support. +# - DC: ldc +# DVersion: 0.15.1 +# arch: x64 + + +#Set up our powershell functions +init: +#putting these in here for now, will export to different script to be imported later maybe? +- ps: function SetUpDCompiler + { + if($env:DC -eq "dmd"){ + if($env:arch -eq "x86"){ + $env:DConf = "m32"; + } + elseif($env:arch -eq "x64"){ + $env:DConf = "m64"; + } + $env:toolchain = "msvc"; + $version = $env:DVersion; + $WebLocation = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.zip"; + $DownloadLocation = "c:\dmd.zip"; + (new-object net.webclient).DownloadFile($WebLocation, $DownloadLocation); + pushd c:\\; + 7z x dmd.zip > $null; + popd; + } + elseif($env:DC -eq "gdc"){ + if($env:arch -eq "x86"){ + $env:DConf = "m32"; + $version = $env:DVersion; + $WebLocation = "ftp://ftp.gdcproject.org/binaries/$($version)/i686-w64-mingw32/gdc-$($version)+2.066.1.7z"; + $mingwWebLocation = "http://dsfml.com/bins/mingw/i686-5.2.0-release-posix-dwarf-rt_v4-rev0.7z"; + } + elseif($env:arch -eq "x64"){ + $env:DConf = "m64"; + $version = $env:DVersion; + $WebLocation = "ftp://ftp.gdcproject.org/binaries/$($version)/x86_64-w64-mingw32/gdc-$($version)+2.066.1.7z"; + $mingwWebLocation = "http://dsfml.com/bins/mingw/x86_64-5.2.0-release-posix-seh-rt_v4-rev0.7z"; + } + $env:toolchain = "mingw"; + $DownloadLocation = "c:\gdc.7z"; + $mingwDownloadLocation = "c:\mingw.7z"; + (new-object net.webclient).DownloadFile($WebLocation, $DownloadLocation); + (new-object net.webclient).DownloadFile($mingwWebLocation, $mingwDownloadLocation); + pushd c:\\; + 7z x gdc.7z > $null; + 7z x mingw.7z > $null; + popd; + } + elseif($env:DC -eq "ldc"){ + if($env:arch -eq "x86"){ + $env:DConf = "m32"; + } + elseif($env:arch -eq "x64"){ + $env:DConf = "m64"; + } + $env:toolchain = "msvc"; + $version = $env:DVersion; + $WebLocation = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-win64-msvc.zip"; + $DownloadLocation = "c:\ldc.zip"; + (new-object net.webclient).DownloadFile($WebLocation, $DownloadLocation); + pushd c:\\; + 7z x ldc.zip > $null; + popd; + } + } + + + +install: +#Install the D compiler +- ps: SetUpDCompiler + + +before_build: +#Set's up MSVC and MinGW +#We can't use the default PATH when using MinGW because another MinGW is on the path and it messes things up. +#We also have to set up MSVC because I couldn't get the script to work with IF statements. :( + - ps: if($env:toolchain -eq "msvc"){ + if($env:arch -eq "x86"){ + $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall"; + $env:compilersetupargs = "x86"; + } + elseif($env:arch -eq "x64"){ + $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall"; + $env:compilersetupargs = "amd64"; + } + $env:maketype = "NMake Makefiles"; + $env:makecommand = "nmake"; + } + elseif($env:toolchain -eq "mingw"){ + if($env:arch -eq "x86"){ + $env:compilerpath = "C:\mingw32\bin;"; + $env:cmakepath = "C:\Program Files (x86)\CMake\bin"; + } + elseif($env:arch -eq "x64"){ + $env:compilerpath = "C:\mingw64\bin;"; + $env:cmakepath = "C:\Program Files (x86)\CMake\bin"; + } + $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; + $env:compilersetupargs = "x86"; + $env:maketype = "MinGW Makefiles"; + $env:makecommand = "mingw32-make"; + } +#Set's up our D compiler + - ps : if($env:DC -eq "dmd"){ + $env:Dcompilerpath = "C:\dmd2\windows\bin;"; + $env:outputfile = "-ofbuild.exe"; + if($env:arch -eq "x86"){ + $env:makecommand = "nmake & implib"; + } + } + elseif($env:DC -eq "gdc"){ + $env:outputfile = "-obuild.exe"; + if($env:arch -eq "x86"){ + $env:Dcompilerpath = "C:\i686-w64-mingw32\bin;"; + } + elseif($env:arch -eq "x64"){ + $env:Dcompilerpath = "C:\x86_64-w64-mingw32\bin;"; + } + } + elseif($env:DC -eq "ldc"){ + $version = $env:DVersion; + $env:Dcompilerpath = "C:\ldc2-$($version)-win64-msvc\bin;"; + $env:outputfile = "-of=build.exe"; + $env:DC = "ldc2"; + } + + + +#Build DSFMLC and then build DSFML with it +build_script: +- echo %VCINSTALLDIR% +- '"%compilersetup%" %compilersetupargs%' +- cd .. +- git clone --depth=1 --branch 2.3-stringpassthrough https://github.com/aubade/DSFMLC.git +- cd DSFMLC +- ps: if($env:toolchain -eq "mingw"){ + $env:Path = $env:compilerpath + $env:cmakepath; + } +- cmake -G"%maketype%" . +- '%makecommand%' +- cd "C:\\projects\\dsfml" +- ps : $env:Path = $env:Dcompilerpath + $env:Path +- ps: if($env:DC -eq "ldc2"){ + $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; + } +- '"%compilersetup%" %compilersetupargs%' +- '%DC% build.d %outputfile%' +- 'build.exe -%DConf% -unittest:C:\projects\DSFMLC\lib\' diff --git a/build.d b/build.d index eae49c9..d37c18e 100644 --- a/build.d +++ b/build.d @@ -286,9 +286,9 @@ void initialize() //Setting up our aa with our lists of files because GDC crashes when searching for them at runtime fileList["system"] = ["clock.d", "config.d", "err.d", "inputstream.d", "lock.d", "mutex.d", "package.d", "sleep.d", "string.d", "thread.d", "vector2.d", "vector3.d"]; - fileList["audio"] = ["listener.d", "music.d", "package.d", "sound.d", "soundbuffer.d", "soundbufferrecorder.d", "soundfile.d", "soundrecorder.d", "soundsource.d", "soundstream.d"]; + fileList["audio"] = ["listener.d", "music.d", "package.d", "sound.d", "soundbuffer.d", "soundbufferrecorder.d", "inputsoundfile.d", "outputsoundfile.d", "soundrecorder.d", "soundsource.d", "soundstream.d"]; fileList["network"] = ["ftp.d", "http.d", "ipaddress.d", "package.d", "packet.d", "socket.d", "socketselector.d", "tcplistener.d", "tcpsocket.d", "udpsocket.d"]; - fileList["window"] = ["context.d", "contextsettings.d", "event.d", "joystick.d", "keyboard.d", "mouse.d", "package.d", "videomode.d", "window.d", "windowhandle.d"]; + fileList["window"] = ["context.d", "contextsettings.d", "event.d", "joystick.d", "keyboard.d", "mouse.d", "sensor.d", "touch.d", "package.d", "videomode.d", "window.d", "windowhandle.d"]; fileList["graphics"] = ["blendmode.d", "circleshape.d", "color.d", "convexshape.d", "drawable.d", "font.d", "glyph.d", "image.d", "package.d", "primitivetype.d", "rect.d", "rectangleshape.d", "renderstates.d", "rendertarget.d", "rendertexture.d", "renderwindow.d", "shader.d", "shape.d", "sprite.d", "text.d", "texture.d", "transform.d", "transformable.d", "vertex.d", "vertexarray.d", "view.d"]; diff --git a/dub.json b/dub.json index 5c5f27c..c3f066d 100644 --- a/dub.json +++ b/dub.json @@ -3,13 +3,14 @@ "description": "DSFML binding for SFML-The Simple and Fast Multimedia Library", "authors": ["Jeremy DeHaan"], "homepage": "https://github.com/Jebbs/DSFML", + "version":"2.3.0", "license": "Zlib", "dependencies": { - "dsfml:audio": "~>2.1", - "dsfml:graphics": "~>2.1", - "dsfml:window": "~>2.1", - "dsfml:network": "~>2.1", - "dsfml:system": "~>2.1" + "dsfml:audio": "~>2.3", + "dsfml:graphics": "~>2.3", + "dsfml:window": "~>2.3", + "dsfml:network": "~>2.3", + "dsfml:system": "~>2.3" }, "subPackages": [ @@ -18,9 +19,10 @@ "targetType": "library", "sourcePaths": ["src/dsfml/audio"], "libs": [ "dsfmlc-audio" ], - "dependencies": - { - "dsfml:system": "~>2.1" + "dflags":["-m32mscoff"], + "dependencies": + { + "dsfml:system": "~>2.3" } }, { @@ -28,19 +30,21 @@ "targetType": "library", "sourcePaths": ["src/dsfml/graphics"], "libs": [ "dsfmlc-graphics" ], - "dependencies": - { - "dsfml:system": "~>2.1", - "dsfml:window": "~>2.1" + "dflags":["-m32mscoff"], + "dependencies": + { + "dsfml:system": "~>2.3", + "dsfml:window": "~>2.3" } }, { "name": "window", "sourcePaths": ["src/dsfml/window"], "libs": [ "dsfmlc-window" ], - "dependencies": - { - "dsfml:system": "~>2.1" + "dflags":["-m32mscoff"], + "dependencies": + { + "dsfml:system": "~>2.3" } }, { @@ -48,9 +52,10 @@ "targetType": "library", "sourcePaths": ["src/dsfml/network"], "libs": [ "dsfmlc-network" ], - "dependencies": - { - "dsfml:system": "~>2.1" + "dflags":["-m32mscoff"], + "dependencies": + { + "dsfml:system": "~>2.3" } }, { @@ -58,6 +63,7 @@ "targetType": "library", "importPaths": ["src/"], "sourcePaths": ["src/dsfml/system"], + "dflags":["-m32mscoff"], "libs": [ "dsfmlc-system" ] } ] diff --git a/src/app.d b/src/app.d new file mode 100644 index 0000000..e7dcc27 --- /dev/null +++ b/src/app.d @@ -0,0 +1,5 @@ +import std.stdio; + +void main() { + writeln("Hello World."); +} \ No newline at end of file diff --git a/src/dsfml/audio/soundfile.d b/src/dsfml/audio/inputsoundfile.d similarity index 57% rename from src/dsfml/audio/soundfile.d rename to src/dsfml/audio/inputsoundfile.d index 42c6271..9c564fb 100644 --- a/src/dsfml/audio/soundfile.d +++ b/src/dsfml/audio/inputsoundfile.d @@ -17,7 +17,7 @@ If you use this software in a product, an acknowledgment in the product document 3. This notice may not be removed or altered from any source distribution */ -module dsfml.audio.soundfile; +module dsfml.audio.inputsoundfile; import std.string; import dsfml.system.inputstream; @@ -25,79 +25,66 @@ import dsfml.system.err; package: -struct SoundFile +struct InputSoundFile { - private sfSoundFile* m_soundFile; + private sfInputSoundFile* m_soundFile; private soundFileStream m_stream;//keeps an instance of the C++ interface stored if used void create() { - m_soundFile = sfSoundFile_create(); + m_soundFile = sfInputSoundFile_create(); } - + ~this() { - sfSoundFile_destroy(m_soundFile); + sfInputSoundFile_destroy(m_soundFile); } - bool openReadFromFile(string filename) + bool openFromFile(const(char)[] filename) { import dsfml.system.string; - bool toReturn = sfSoundFile_openReadFromFile(m_soundFile, toStringz(filename)); + bool toReturn = sfInputSoundFile_openFromFile(m_soundFile, filename.ptr, filename.length); err.write(toString(sfErr_getOutput())); return toReturn; } - bool openReadFromMemory(const(void)[] data) + bool openFromMemory(const(void)[] data) { import dsfml.system.string; - bool toReturn = sfSoundFile_openReadFromMemory(m_soundFile, data.ptr, data.length); + bool toReturn = sfInputSoundFile_openFromMemory(m_soundFile, data.ptr, data.length); err.write(toString(sfErr_getOutput())); return toReturn; } - bool openReadFromStream(InputStream stream) + bool openFromStream(InputStream stream) { import dsfml.system.string; m_stream = new soundFileStream(stream); - bool toReturn = sfSoundFile_openReadFromStream(m_soundFile, m_stream); - err.write(toString(sfErr_getOutput())); - return toReturn; - } - - bool openWrite(string filename,uint channelCount,uint sampleRate) - { - import dsfml.system.string; - bool toReturn = sfSoundFile_openWrite(m_soundFile, toStringz(filename),channelCount,sampleRate); + bool toReturn = sfInputSoundFile_openFromStream(m_soundFile, m_stream); err.write(toString(sfErr_getOutput())); return toReturn; } long read(ref short[] data) { - return sfSoundFile_read(m_soundFile,data.ptr, data.length); + return sfInputSoundFile_read(m_soundFile,data.ptr, data.length); } - void write(const(short)[] data) - { - sfSoundFile_write(m_soundFile, data.ptr, data.length); - } - void seek(long timeOffset) { import dsfml.system.string; - sfSoundFile_seek(m_soundFile, timeOffset); - + sfInputSoundFile_seek(m_soundFile, timeOffset); + //Temporary fix for a bug where attempting to write to err //throws an exception in a thread created in C++. This causes //the program to explode. Hooray. - + //This fix will skip the call to err.write if there was no error //to report. If there is an error, well, the program will still explode, - //but the user should see the error prior to the call that will make the + //but the user should see the error prior to the call that will make the //program explode. - + string temp = toString(sfErr_getOutput()); if(temp.length > 0) { @@ -107,15 +94,15 @@ struct SoundFile long getSampleCount() { - return sfSoundFile_getSampleCount(m_soundFile); + return sfInputSoundFile_getSampleCount(m_soundFile); } uint getSampleRate() { - return sfSoundFile_getSampleRate(m_soundFile); + return sfInputSoundFile_getSampleRate(m_soundFile); } uint getChannelCount() { - return sfSoundFile_getChannelCount(m_soundFile); + return sfInputSoundFile_getChannelCount(m_soundFile); } @@ -129,11 +116,11 @@ private extern(C++) interface soundInputStream { long read(void* data, long size); - + long seek(long position); - + long tell(); - + long getSize(); } @@ -141,17 +128,17 @@ extern(C++) interface soundInputStream class soundFileStream:soundInputStream { private InputStream myStream; - + this(InputStream stream) { myStream = stream; } - + extern(C++)long read(void* data, long size) { return myStream.read(data[0..cast(size_t)size]); } - + extern(C++)long seek(long position) { return myStream.seek(position); @@ -161,7 +148,7 @@ class soundFileStream:soundInputStream { return myStream.tell(); } - + extern(C++)long getSize() { return myStream.getSize(); @@ -175,32 +162,28 @@ extern(C) const(char)* sfErr_getOutput(); extern(C) { -struct sfSoundFile; - -sfSoundFile* sfSoundFile_create(); - -void sfSoundFile_destroy(sfSoundFile* file); +struct sfInputSoundFile; -long sfSoundFile_getSampleCount(const sfSoundFile* file); +sfInputSoundFile* sfInputSoundFile_create(); -uint sfSoundFile_getChannelCount( const sfSoundFile* file); +void sfInputSoundFile_destroy(sfInputSoundFile* file); -uint sfSoundFile_getSampleRate(const sfSoundFile* file); +long sfInputSoundFile_getSampleCount(const sfInputSoundFile* file); -bool sfSoundFile_openReadFromFile(sfSoundFile* file, const char* filename); +uint sfInputSoundFile_getChannelCount( const sfInputSoundFile* file); -bool sfSoundFile_openReadFromMemory(sfSoundFile* file,const(void)* data, long sizeInBytes); +uint sfInputSoundFile_getSampleRate(const sfInputSoundFile* file); -bool sfSoundFile_openReadFromStream(sfSoundFile* file, soundInputStream stream); +bool sfInputSoundFile_openFromFile(sfInputSoundFile* file, const char* filename, size_t length); -//bool sfSoundFile_openReadFromStream(sfSoundFile* file, void* stream); +bool sfInputSoundFile_openFromMemory(sfInputSoundFile* file,const(void)* data, long sizeInBytes); -bool sfSoundFile_openWrite(sfSoundFile* file, const(char)* filename,uint channelCount,uint sampleRate); +bool sfInputSoundFile_openFromStream(sfInputSoundFile* file, soundInputStream stream); -long sfSoundFile_read(sfSoundFile* file, short* data, long sampleCount); +bool sfInputSoundFile_openForWriting(sfInputSoundFile* file, const(char)* filename,uint channelCount,uint sampleRate); -void sfSoundFile_write(sfSoundFile* file, const short* data, long sampleCount); +long sfInputSoundFile_read(sfInputSoundFile* file, short* data, long sampleCount); -void sfSoundFile_seek(sfSoundFile* file, long timeOffset); +void sfInputSoundFile_seek(sfInputSoundFile* file, long timeOffset); } } diff --git a/src/dsfml/audio/listener.d b/src/dsfml/audio/listener.d index 42ee7fd..9000986 100644 --- a/src/dsfml/audio/listener.d +++ b/src/dsfml/audio/listener.d @@ -59,6 +59,28 @@ final abstract class Listener } } + /** + * The upward vector of the listener in the scene. The upward vector defines the 3D axes of the listener (left, up, front) in the scene. The upward vector doesn't have to be normalized. + * + * The default listener's upward vector is (0, 1, 0). + */ + @property + { + static void UpVector(Vector3f orientation) + { + sfListener_setUpVector(orientation.x, orientation.y, orientation.z); + } + + static Vector3f UpVector() + { + Vector3f temp; + + sfListener_getUpVector(&temp.x, &temp.y, &temp.z); + + return temp; + } + } + /** * The global volume of all the sounds and musics. The volume is a number between 0 and 100; it is combined with the individual volume of each sound / music. * @@ -141,3 +163,6 @@ void sfListener_setDirection(float x, float y, float z); void sfListener_getDirection(float* x, float* y, float* z); +void sfListener_setUpVector(float x, float y, float z); + +void sfListener_getUpVector(float* x, float* y, float* z); diff --git a/src/dsfml/audio/music.d b/src/dsfml/audio/music.d index a4119f8..8e9db47 100644 --- a/src/dsfml/audio/music.d +++ b/src/dsfml/audio/music.d @@ -43,11 +43,11 @@ import dsfml.audio.soundstream; +/ class Music : SoundStream { - import dsfml.audio.soundfile; + import dsfml.audio.inputsoundfile; private { - SoundFile m_file; + InputSoundFile m_file; Duration m_duration; short[] m_samples; Mutex m_mutex; @@ -78,7 +78,7 @@ class Music : SoundStream //stop music if already playing stop(); - if(!m_file.openReadFromFile(filename)) + if(!m_file.openFromFile(filename)) { return false; } @@ -105,7 +105,7 @@ class Music : SoundStream { stop(); - if(!m_file.openReadFromMemory(data)) + if(!m_file.openFromMemory(data)) { return false; } @@ -131,7 +131,7 @@ class Music : SoundStream { stop(); - if(!m_file.openReadFromStream(stream)) + if(!m_file.openFromStream(stream)) { return false; } diff --git a/src/dsfml/audio/outputsoundfile.d b/src/dsfml/audio/outputsoundfile.d new file mode 100644 index 0000000..f9f73ed --- /dev/null +++ b/src/dsfml/audio/outputsoundfile.d @@ -0,0 +1,78 @@ +/* +DSFML - The Simple and Fast Multimedia Library for D + +Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com) + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution +*/ + +module dsfml.audio.outputsoundfile; + +import std.string; +import dsfml.system.err; + +/** + *Provide write access to sound files. + * + *This class encodes audio samples to a sound file. + * + *It is used internally by higher-level classes such as sf::SoundBuffer, but can also be useful if you want to create audio files from + *custom data sources, like generated audio samples. + */ +struct OutputSoundFile +{ + private sfOutputSoundFile* m_soundFile; + + void create() + { + m_soundFile = sfOutputSoundFile_create(); + } + + ~this() + { + sfOutputSoundFile_destroy(m_soundFile); + } + + bool openFromFile(const(char)[] filename,uint channelCount,uint sampleRate) + { + import dsfml.system.string; + bool toReturn = sfOutputSoundFile_openFromFile(m_soundFile, filename.ptr, filename.length,channelCount,sampleRate); + err.write(toString(sfErr_getOutput())); + return toReturn; + } + + void write(const(short)[] data) + { + sfOutputSoundFile_write(m_soundFile, data.ptr, data.length); + } + +} + +extern(C) const(char)* sfErr_getOutput(); + + +private extern(C) +{ + +struct sfOutputSoundFile; + +sfOutputSoundFile* sfOutputSoundFile_create(); + +void sfOutputSoundFile_destroy(sfOutputSoundFile* file); + +bool sfOutputSoundFile_openFromFile(sfOutputSoundFile* file, const(char)* filename, size_t length, uint channelCount,uint sampleRate); + +void sfOutputSoundFile_write(sfOutputSoundFile* file, const short* data, long sampleCount); + +} diff --git a/src/dsfml/audio/soundbuffer.d b/src/dsfml/audio/soundbuffer.d index 33de772..e27f668 100644 --- a/src/dsfml/audio/soundbuffer.d +++ b/src/dsfml/audio/soundbuffer.d @@ -21,7 +21,7 @@ module dsfml.audio.soundbuffer; import core.time; -import dsfml.audio.soundfile; +import dsfml.audio.inputsoundfile; import dsfml.audio.sound; import dsfml.system.inputstream; @@ -39,17 +39,17 @@ import dsfml.system.err; /++ + Storage for audio samples defining a sound. - + + + + A sample is a 16 bits signed integer that defines the amplitude of the sound at a given time. The sound is then restituted by playing these samples at a high rate (for example, 44100 samples per second is the standard rate used for playing CDs). In short, audio samples are like texture pixels, and a SoundBuffer is similar to a Texture. - + + + + A sound buffer can be loaded from a file (see loadFromFile() for the complete list of supported formats), from memory, from a custom stream (see InputStream) or directly from an array of samples. It can also be saved back to a file. - + - + Sound buffers alone are not very useful: they hold the audio data but cannot be played. To do so, you need to use the sf::Sound class, which provides functions to play/pause/stop the sound as well as changing the way it is outputted (volume, pitch, 3D position, ...). - + + + + + Sound buffers alone are not very useful: they hold the audio data but cannot be played. To do so, you need to use the sf::Sound class, which provides functions to play/pause/stop the sound as well as changing the way it is outputted (volume, pitch, 3D position, ...). + + + This separation allows more flexibility and better performances: indeed a sf::SoundBuffer is a heavy resource, and any operation on it is slow (often too slow for real-time applications). On the other side, a sf::Sound is a lightweight object, which can use the audio data of a sound buffer and change the way it is played without actually modifying that data. Note that it is also possible to bind several Sound instances to the same SoundBuffer. - + + + + It is important to note that the Sound instance doesn't copy the buffer that it uses, it only keeps a reference to it. Thus, a SoundBuffer must not be destructed while it is used by a Sound (i.e. never write a function that uses a local SoundBuffer instance for loading a sound). - + + + + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1SoundBuffer.php#details + Authors: Laurent Gomila, Jeremy DeHaan +/ @@ -61,7 +61,7 @@ class SoundBuffer { import dsfml.system.string; sfPtr = sfSoundBuffer_construct(); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } ~this() @@ -70,15 +70,15 @@ class SoundBuffer mixin(destructorOutput); sfSoundBuffer_destroy(sfPtr); } - + //TODO: copy constructor? //So many possible properties.... - /** + /** * Get the array of audio samples stored in the buffer. - * + * * The format of the returned samples is 16 bits signed integer (sf::Int16). The total number of samples in this array is given by the getSampleCount() function. - * + * * Returns: Read-only pointer to the array of sound samples */ const(short[]) getSamples() const @@ -95,9 +95,9 @@ class SoundBuffer /** * Get the sample rate of the sound. - * + * * The sample rate is the number of samples played per second. The higher, the better the quality (for example, 44100 samples/s is CD quality). - * + * * Returns: Sample rate (number of samples per second) */ uint getSampleRate() const @@ -107,9 +107,9 @@ class SoundBuffer /** * Get the number of channels used by the sound. - * + * * If the sound is mono then the number of channels will be 1, 2 for stereo, etc. - * + * * Returns: Number of channels */ uint getChannelCount() const @@ -119,7 +119,7 @@ class SoundBuffer /** * Get the total duration of the sound. - * + * * Returns: Sound duration */ Duration getDuration() const @@ -130,36 +130,36 @@ class SoundBuffer /** * Load the sound buffer from a file. - * + * * Here is a complete list of all the supported audio formats: ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - * + * * Params: * filename = Path of the sound file to load - * + * * Returns: True if loading succeeded, false if it failed */ - bool loadFromFile(string filename) + bool loadFromFile(const(char)[] filename) { import dsfml.system.string; - if(sfSoundBuffer_loadFromFile(sfPtr, toStringz(filename))) + if(sfSoundBuffer_loadFromFile(sfPtr, filename.ptr, filename.length)) { return true; } else { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return false; } } /** * Load the sound buffer from a file in memory. - * + * * Here is a complete list of all the supported audio formats: ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - * + * * Params: * data = The array of data - * + * * Returns: True if loading succeeded, false if it failed */ bool loadFromMemory(const(void)[] data) @@ -171,23 +171,23 @@ class SoundBuffer else { import dsfml.system.string; - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return false; } } /* * Load the sound buffer from a custom stream. - * + * * Here is a complete list of all the supported audio formats: ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - * + * * Params: * stream = Source stream to read from - * + * * Returns: True if loading succeeded, false if it failed */ bool loadFromStream(InputStream stream) - { + { if(sfSoundBuffer_loadFromStream(sfPtr, new SoundBufferStream(stream))) { return true; @@ -195,21 +195,21 @@ class SoundBuffer else { import dsfml.system.string; - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return false; } } /** * Load the sound buffer from an array of audio samples. - * + * * The assumed format of the audio samples is 16 bits signed integer (short). - * + * * Params: * samples = Array of samples in memory * channelCount = Number of channels (1 = mono, 2 = stereo, ...) * sampleRate = Sample rate (number of samples to play per second) - * + * * Returns: True if loading succeeded, false if it failed */ bool loadFromSamples(const(short[]) samples, uint channelCount, uint sampleRate) @@ -221,36 +221,36 @@ class SoundBuffer else { import dsfml.system.string; - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return false; } } /** * Save the sound buffer to an audio file. - * + * * Here is a complete list of all the supported audio formats: ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - * + * * Params: * filename = Path of the sound file to write - * + * * Returns: True if saving succeeded, false if it failed */ - bool saveToFile(string filename) + bool saveToFile(const(char)[] filename) { import dsfml.system.string; - if(sfSoundBuffer_saveToFile(sfPtr, toStringz(filename))) + if(sfSoundBuffer_saveToFile(sfPtr, filename.ptr, filename.length)) { return true; } else { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return false; } } - + } @@ -288,11 +288,11 @@ unittest private extern(C++) interface sfmlInputStream { long read(void* data, long size); - + long seek(long position); - + long tell(); - + long getSize(); } @@ -315,12 +315,12 @@ private class SoundBufferStream:sfmlInputStream { return myStream.seek(position); } - + extern(C++)long tell() { return myStream.tell(); } - + extern(C++)long getSize() { return myStream.getSize(); @@ -333,7 +333,7 @@ private extern(C): sfSoundBuffer* sfSoundBuffer_construct(); -bool sfSoundBuffer_loadFromFile(sfSoundBuffer* soundBuffer, const char* filename); +bool sfSoundBuffer_loadFromFile(sfSoundBuffer* soundBuffer, const char* filename, size_t length); bool sfSoundBuffer_loadFromMemory(sfSoundBuffer* soundBuffer, const void* data, size_t sizeInBytes); @@ -345,7 +345,7 @@ sfSoundBuffer* sfSoundBuffer_copy(const sfSoundBuffer* soundBuffer); void sfSoundBuffer_destroy(sfSoundBuffer* soundBuffer); -bool sfSoundBuffer_saveToFile(const sfSoundBuffer* soundBuffer, const char* filename); +bool sfSoundBuffer_saveToFile(const sfSoundBuffer* soundBuffer, const char* filename, size_t length); const(short)* sfSoundBuffer_getSamples(const sfSoundBuffer* soundBuffer); diff --git a/src/dsfml/audio/soundrecorder.d b/src/dsfml/audio/soundrecorder.d index ee17460..9b19b53 100644 --- a/src/dsfml/audio/soundrecorder.d +++ b/src/dsfml/audio/soundrecorder.d @@ -20,29 +20,31 @@ If you use this software in a product, an acknowledgment in the product document module dsfml.audio.soundrecorder; import core.thread; +import core.time; +import dsfml.system.string; import dsfml.system.err; /++ + Abstract base class for capturing sound data. - + + + + SoundBuffer provides a simple interface to access the audio recording capabilities of the computer (the microphone). - + + + + As an abstract base class, it only cares about capturing sound samples, the task of making something useful with them is left to the derived class. Note that SFML provides a built-in specialization for saving the captured data to a sound buffer (see SoundBufferRecorder). - + + + + A derived class has only one virtual function to override: - + + + + onProcessSamples provides the new chunks of audio samples while the capture happens - + + + + Moreover, two additionnal virtual functions can be overriden as well if necessary: - + + + + onStart is called before the capture happens, to perform custom initializations + onStop is called after the capture ends, to perform custom cleanup - + + + + The audio capture feature may not be supported or activated on every platform, thus it is recommended to check its availability with the isAvailable() function. If it returns false, then any attempt to use an audio recorder will fail. - + + + + It is important to note that the audio capture happens in a separate thread, so that it doesn't block the rest of the program. In particular, the onProcessSamples and onStop virtual functions (but not onStart) will be called from this separate thread. It is important to keep this in mind, because you may have to take care of synchronization issues if you share data between threads. - + + + + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1SoundRecorder.php#details + Authors: Laurent Gomila, Jeremy DeHaan +/ @@ -58,10 +60,10 @@ class SoundRecorder callBacks = new SoundRecorderCallBacks(this); sfPtr = sfSoundRecorder_construct(callBacks); - err.write(toString(sfErr_getOutput())); - + err.write(dsfml.system.string.toString(sfErr_getOutput())); + //Fix for some strange bug that I can't seem to track down. - //This bug causes the array in SoundBufferRecorder to segfault if + //This bug causes the array in SoundBufferRecorder to segfault if //its length reaches 1024, but creating an array of this size before capturing happens //seems to fix it. This fix should allow other implementations to not segfault as well. //I will look into the cause when I have more time, but this at least renders it usable. @@ -80,7 +82,7 @@ class SoundRecorder /** * Start the capture. * The sampleRate parameter defines the number of audio samples captured per second. The higher, the better the quality (for example, 44100 samples/sec is CD quality). This function uses its own thread so that it doesn't block the rest of the program while the capture runs. Please note that only one capture can happen at the same time. - * + * * Params: * sampleRate = Desired capture rate, in number of samples per second */ @@ -89,7 +91,7 @@ class SoundRecorder import dsfml.system.string; sfSoundRecorder_start(sfPtr, theSampleRate); - err.write(toString(sfErr_getOutput())); + err.write(.toString(sfErr_getOutput())); } /// Stop the capture. @@ -100,7 +102,7 @@ class SoundRecorder /** * Get the sample rate in samples per second. - * + * * The sample rate defines the number of audio samples captured per second. The higher, the better the quality (for example, 44100 samples/sec is CD quality). */ @property @@ -111,11 +113,84 @@ class SoundRecorder } } + /** + *Get the name of the current audio capture device. + * + *Returns + * The name of the current audio capture device + */ + string getDevice() const { + return .toString(sfSoundRecorder_getDevice(sfPtr)); + } + /** + *Set the audio capture device. + * + *This function sets the audio capture device to the device with the given name. It can be called on the fly (i.e: while recording). If you do so while recording and opening the device fails, it stops the recording. + * + *Parameters + * name The name of the audio capture device + * + *Returns + * True, if it was able to set the requested device + * + *See also + * getAvailableDevices, getDefaultDevice + */ + bool setDevice (const(char)[] name) { + return sfSoundRecorder_setDevice(sfPtr, name.ptr, name.length); + } + + /** + *Get a list of the names of all available audio capture devices. + * + *This function returns an array of strings, containing the names of all available audio capture devices. + * + *Returns + * An array of strings containing the names + */ + static const(string)[] getAvailableDevices() { + static string[] availableDevices;//stores all available devices after the first call + + //if getAvailableDevices hasn't been called yet + if(availableDevices.length == 0) + { + const (char)** devices; + size_t counts; + + //returns uints instead of structs due to 64 bit bug + devices = sfSoundRecorder_getAvailableDevices(&counts); + + //calculate real length + availableDevices.length = counts; + + //populate availableDevices + for(uint i = 0; i < counts; i++) + { + availableDevices[i] = .toString(devices[i]); + } + + } + + return availableDevices; + } + + /** + *Get the name of the default audio capture device. + * + *This function returns the name of the default audio capture device. If none is available, an empty string is returned. + * + *Returns + * The name of the default audio capture device + */ + static string getDefaultDevice() { + return .toString(sfSoundRecorder_getDefaultDevice()); + } + /** * Check if the system supports audio capture. - * + * * This function should always be called before using the audio capture features. If it returns false, then any attempt to use SoundRecorder or one of its derived classes will fail. - * + * * Returns: True if audio capture is supported, false otherwise */ static bool isAvailable() @@ -125,11 +200,27 @@ class SoundRecorder protected { + /** + *Set the processing interval. + * + * The processing interval controls the period between calls to the onProcessSamples function. You may want to use a small interval if you want to process the recorded data in real time, for example. + * + * Note: this is only a hint, the actual period may vary. So don't rely on this parameter to implement precise timing. + * + * The default processing interval is 100 ms. + * + * Parameters + * interval Processing interval + */ + void setProcessingInterval (Duration interval) { + sfSoundRecorder_setProcessingInterval(sfPtr, interval.total!"usecs"); + } + /** * Start capturing audio data. - * + * * This virtual function may be overriden by a derived class if something has to be done every time a new capture starts. If not, this function can be ignored; the default implementation does nothing. - * + * * Returns: True to the start the capture, or false to abort it. */ bool onStart() @@ -139,19 +230,19 @@ class SoundRecorder /** * Process a new chunk of recorded samples. - * + * * This virtual function is called every time a new chunk of recorded data is available. The derived class can then do whatever it wants with it (storing it, playing it, sending it over the network, etc.). - * + * * Params: * samples = Array of the new chunk of recorded samples - * + * * Returns: True to continue the capture, or false to stop it */ abstract bool onProcessSamples(const(short)[] samples); /** * Stop capturing audio data. - * + * * This virtual function may be overriden by a derived class if something has to be done every time the capture ends. If not, this function can be ignored; the default implementation does nothing. */ void onStop() @@ -213,7 +304,17 @@ void sfSoundRecorder_stop(sfSoundRecorder* soundRecorder); uint sfSoundRecorder_getSampleRate(const sfSoundRecorder* soundRecorder); +bool sfSoundRecorder_setDevice(sfSoundRecorder* soundRecorder, const(char)* name, size_t length); + +const(char)* sfSoundRecorder_getDevice(const (sfSoundRecorder)* soundRecorder); + +const(char)** sfSoundRecorder_getAvailableDevices(size_t* count); + +const(char)* sfSoundRecorder_getDefaultDevice(); + bool sfSoundRecorder_isAvailable(); +void sfSoundRecorder_setProcessingInterval(sfSoundRecorder* soundRecorder, ulong time); + const(char)* sfErr_getOutput(); diff --git a/src/dsfml/audio/soundstream.d b/src/dsfml/audio/soundstream.d index 14c605e..931b4a4 100644 --- a/src/dsfml/audio/soundstream.d +++ b/src/dsfml/audio/soundstream.d @@ -32,21 +32,21 @@ import dsfml.system.err; /++ + Abstract base class for streamed audio sources. - + + + + Unlike audio buffers (see SoundBuffer), audio streams are never completely loaded in memory. - + + + + Instead, the audio data is acquired continuously while the stream is playing. This behaviour allows to play a sound with no loading delay, and keeps the memory consumption very low. - + + + + Sound sources that need to be streamed are usually big files (compressed audio musics that would eat hundreds of MB in memory) or files that would take a lot of time to be received (sounds played over the network). - + + + + SoundStream is a base class that doesn't care about the stream source, which is left to the derived class. SFML provides a built-in specialization for big files (see Music). No network stream source is provided, but you can write your own by combining this class with the network module. - + + + + A derived class has to override two virtual functions: + - onGetData fills a new chunk of audio data to be played. + - onSeek changes the current playing position in the source - + + + + It is important to note that each SoundStream is played in its own separate thread, so that the streaming loop doesn't block the rest of the program. In particular, the OnGetData and OnSeek virtual functions may sometimes be called from this separate thread. It is important to keep this in mind, because you may have to take care of synchronization issues if you share data between threads. - + + + + See_Also: http://sfml-dev.org/documentation/2.0/classsf_1_1SoundStream.php#details + Authors: Laurent Gomila, Jeremy DeHaan +/ @@ -76,7 +76,7 @@ class SoundStream:SoundSource sfSoundStream_initialize(sfPtr, channelCount, sampleRate); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } @@ -87,16 +87,16 @@ class SoundStream:SoundSource { sfSoundStream_setPitch(sfPtr, newPitch); } - + float pitch() { return sfSoundStream_getPitch(sfPtr); } } - + /** * The volume of the sound. - * + * * The volume is a vlue between 0 (mute) and 100 (full volume). The default value for the volume is 100. */ @property @@ -111,10 +111,10 @@ class SoundStream:SoundSource return sfSoundStream_getVolume(sfPtr); } } - + /** * The 3D position of the sound in the audio scene. - * + * * Only sounds with one channel (mono sounds) can be spatialized. The default position of a sound is (0, 0, 0). */ @property @@ -123,7 +123,7 @@ class SoundStream:SoundSource { sfSoundStream_setPosition(sfPtr, newPosition.x, newPosition.y, newPosition.z); } - + Vector3f position() { Vector3f temp; @@ -145,7 +145,7 @@ class SoundStream:SoundSource { sfSoundStream_setLoop(sfPtr, loop); } - + bool isLooping() { return sfSoundStream_getLoop(sfPtr); @@ -162,18 +162,18 @@ class SoundStream:SoundSource void playingOffset(Duration offset) { sfSoundStream_setPlayingOffset(sfPtr, offset.total!"usecs"); - + } - + Duration playingOffset() { return usecs(sfSoundStream_getPlayingOffset(sfPtr)); } } - + /** * Make the sound's position relative to the listener (true) or absolute (false). - * + * * Making a sound relative to the listener will ensure that it will always be played the same way regardless the position of the listener. This can be useful for non-spatialized sounds, sounds that are produced by the listener, or sounds attached to it. The default value is false (position is absolute). */ @property @@ -182,16 +182,16 @@ class SoundStream:SoundSource { sfSoundStream_setRelativeToListener(sfPtr, relative); } - + bool relativeToListener() { return sfSoundStream_isRelativeToListener(sfPtr); } } - + /** * The minimum distance of the sound. - * + * * The "minimum distance" of a sound is the maximum distance at which it is heard at its maximum volume. Further than the minimum distance, it will start to fade out according to its attenuation factor. A value of 0 ("inside the head of the listener") is an invalid value and is forbidden. The default value of the minimum distance is 1. */ @property @@ -200,18 +200,18 @@ class SoundStream:SoundSource { sfSoundStream_setMinDistance(sfPtr, distance); } - + float minDistance() { return sfSoundStream_getMinDistance(sfPtr); } } - + /** * The attenuation factor of the sound. - * - * The attenuation is a multiplicative factor which makes the sound more or less loud according to its distance from the listener. An attenuation of 0 will produce a non-attenuated sound, i.e. its volume will always be the same whether it is heard from near or from far. - * + * + * The attenuation is a multiplicative factor which makes the sound more or less loud according to its distance from the listener. An attenuation of 0 will produce a non-attenuated sound, i.e. its volume will always be the same whether it is heard from near or from far. + * * On the other hand, an attenuation value such as 100 will make the sound fade out very quickly as it gets further from the listener. The default value of the attenuation is 1. */ @property @@ -220,7 +220,7 @@ class SoundStream:SoundSource { sfSoundStream_setAttenuation(sfPtr, newAttenuation); } - + float attenuation() { return sfSoundStream_getAttenuation(sfPtr); @@ -242,7 +242,7 @@ class SoundStream:SoundSource return sfSoundStream_getChannelCount(sfPtr); } } - + /** * The stream sample rate of the stream * @@ -272,7 +272,7 @@ class SoundStream:SoundSource sfSoundStream_play(sfPtr); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } void pause() @@ -288,7 +288,7 @@ class SoundStream:SoundSource abstract bool onGetData(ref const(short)[] samples); abstract void onSeek(Duration timeOffset); - + } @@ -312,12 +312,12 @@ public: class SoundStreamCallBacks: sfmlSoundStreamCallBacks { SoundStream m_stream; - + this(SoundStream stream) { m_stream = stream; } - + extern(C++) bool onGetData(Chunk* chunk) { const(short)[] samples; @@ -330,14 +330,14 @@ class SoundStreamCallBacks: sfmlSoundStreamCallBacks return ret; } - + extern(C++) void onSeek(long time) { m_stream.onSeek(usecs(time)); } - - - + + + } private extern(C): diff --git a/src/dsfml/graphics/blendmode.d b/src/dsfml/graphics/blendmode.d index 285cbc3..39542e6 100644 --- a/src/dsfml/graphics/blendmode.d +++ b/src/dsfml/graphics/blendmode.d @@ -21,10 +21,10 @@ module dsfml.graphics.blendmode; /++ + Available blending modes for drawing. + - + See_Also: http://www.sfml-dev.org/documentation/2.0/group__graphics.php#ga80c52fe2f7050d7f7573b7ed3c995388 + + See_Also: http://www.sfml-dev.org/documentation/2.3/structsf_1_1BlendMode.php + Authors: Laurent Gomila, Jeremy DeHaan +/ -enum BlendMode +/*enum BlendMode { /// Pixel = Source * Source.a + Dest * (1 - Source.a) Alpha, @@ -34,4 +34,41 @@ enum BlendMode Multiply, /// Pixel = Source. None +}*/ + +struct BlendMode +{ + enum Alpha = BlendMode(Factor.SrcAlpha, Factor.OneMinusSrcAlpha, Equation.Add, + Factor.One, Factor.OneMinusSrcAlpha, Equation.Add); + enum Add = BlendMode(Factor.SrcAlpha, Factor.One, Equation.Add, + Factor.One, Factor.One, Equation.Add); + enum Multiply = BlendMode(Factor.DstColor, Factor.Zero, Equation.Add, Factor.DstColor, Factor.Zero, Equation.Add); + enum None = BlendMode (Factor.One, Factor.Zero, Equation.Add, Factor.One, Factor.Zero, Equation.Add); + + enum Factor + { + Zero, + One, + SrcColor, + OneMinunSrcColor, + DstColor, + OneMinusDstColor, + SrcAlpha, + OneMinusSrcAlpha, + DstAlpha, + OneMinusDstAlpha + } + + enum Equation + { + Add, + Subtract + } + + Factor colorSrcFactor = Factor.SrcAlpha; + Factor colorDstFactor = Factor.OneMinusSrcAlpha; + Equation colorEquation = Equation.Add; + Factor alphaSrcFactor = Factor.One; + Factor alphaDstFactor = Factor.OneMinusSrcAlpha; + Equation alphaEquation = Equation.Add; } \ No newline at end of file diff --git a/src/dsfml/graphics/font.d b/src/dsfml/graphics/font.d index c462d7a..98c0596 100644 --- a/src/dsfml/graphics/font.d +++ b/src/dsfml/graphics/font.d @@ -26,16 +26,16 @@ import dsfml.system.err; /++ + Class for loading and manipulating character fonts. - + + + + Fonts can be loaded from a file, from memory or from a custom stream, and supports the most common types of fonts. - + + + + See the loadFromFile function for the complete list of supported formats. - + + + + Once it is loaded, a Font instance provides three types of information about the font: + - Global metrics, such as the line spacing + - Per-glyph metrics, such as bounding box or kerning + - Pixel representation of glyphs - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://sfml-dev.org/documentation/2.0/classsf_1_1Font.php#details +/ @@ -58,7 +58,7 @@ class Font sfPtr = newFont; fontTexture = new Texture(sfFont_getTexturePtr(sfPtr)); } - + ~this() { import dsfml.system.config; @@ -68,35 +68,35 @@ class Font /** * Load the font from a file. - * + * * The supported font formats are: TrueType, Type 1, CFF, OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. Note that this function know nothing about the standard fonts installed on the user's system, thus you can't load them directly. - * + * * Params: * filename = Path of the font file to load - * + * * Returns: True if loading succeeded, false if it failed. */ - bool loadFromFile(string filename) + bool loadFromFile(const(char)[] filename) { import dsfml.system.string; - bool ret = sfFont_loadFromFile(sfPtr, toStringz(filename)); + bool ret = sfFont_loadFromFile(sfPtr, filename.ptr, filename.length); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } - + return ret; } /** * Load the font from a file in memory. - * + * * The supported font formats are: TrueType, Type 1, CFF, OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. Warning: SFML cannot preload all the font data in this function, so the buffer pointed by data has to remain valid as long as the font is used. - * + * * Params: * data = data holding the font file - * + * * Returns: True if loading succeeded, false if it failed. */ bool loadFromMemory(const(void)[] data) @@ -106,20 +106,20 @@ class Font bool ret = sfFont_loadFromMemory(sfPtr, data.ptr, data.length); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } - + return ret; } /** * Load the font from a custom stream. - * + * * The supported font formats are: TrueType, Type 1, CFF, OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. Warning: SFML cannot preload all the font data in this function, so the contents of stream have to remain valid as long as the font is used. - * + * * Params: * stream = Source stream to read from - * + * * Returns: True if loading succeeded, false if it failed. */ bool loadFromStream(InputStream stream) @@ -132,20 +132,20 @@ class Font if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } - + return ret; } /** * Retrieve a glyph of the font. - * + * * Params: * codePoint = Unicode code point of the character ot get * characterSize = Reference character size * bols = Retrieve the bold version or the regular one? - * + * * Returns: The glyph corresponding to codePoint and characterSize */ Glyph getGlyph(dchar codePoint, uint characterSize, bool bold) const @@ -159,44 +159,74 @@ class Font /** * Get the kerning offset of two glyphs. - * + * * The kerning is an extra offset (negative) to apply between two glyphs when rendering them, to make the pair look more "natural". For example, the pair "AV" have a special kerning to make them closer than other characters. Most of the glyphs pairs have a kerning offset of zero, though. - * + * * Params: * first = Unicode code point of the first character * second = Unicode code point of the second character * characterSize = Reference character size - * + * * Returns: Kerning value for first and second, in pixels */ - int getKerning (dchar first, dchar second, uint characterSize) const + float getKerning (dchar first, dchar second, uint characterSize) const { - return sfFont_getKerning(sfPtr, cast(uint)first, cast(uint)second, characterSize); + return sfFont_getKerning(sfPtr, cast(uint)first, cast(uint)second, characterSize); } /** * Get the line spacing. - * + * * The spacing is the vertical offset to apply between consecutive lines of text. - * + * * Params: * characterSize = Reference character size - * + * * Returns: Line spacing, in pixels */ - int getLineSpacing (uint characterSize) const + float getLineSpacing (uint characterSize) const + { + return sfFont_getLineSpacing(sfPtr, characterSize); + } + + /** + * Get the position of the underline. + * + * Underline position is the vertical offset to apply between the baseline and the underline. + * + * Params: + * characterSize = Reference character size + * + * Returns: Underline position, in pixels + */ + float getUnderlinePosition (uint characterSize) const { - return sfFont_getLineSpacing(sfPtr, characterSize); + return sfFont_getUnderlinePosition(sfPtr, characterSize); + } + + /** + * Get the thickness of the underline. + * + * Underline thickness is the vertical size of the underline. + * + * Params: + * characterSize = Reference character size + * + * Returns: Underline thickness, in pixels + */ + float getUnderlineThickness (uint characterSize) const + { + return sfFont_getUnderlineThickness(sfPtr, characterSize); } /** * Retrieve the texture containing the loaded glyphs of a certain size. - * + * * The contents of the returned texture changes as more glyphs are requested, thus it is not very relevant. It is mainly used internally by Text. - * + * * Params: * characterSize = Reference character size - * + * * Returns: Texture containing the glyphs of the requested size */ const(Texture) getTexture (uint characterSize) const @@ -205,11 +235,11 @@ class Font //Possible: cache last size used using sound method(mutable instance storage) import std.stdio; - + //writeln("Updating Texture"); - + sfFont_updateTexture(sfPtr, characterSize); - + //fontTexture.sfPtr = sfFont_getTexture(sfPtr, characterSize); // writeln("returning texture"); @@ -218,7 +248,7 @@ class Font /** * Performs a deep copy on the font. - * + * * Returns: The duplicated font. */ @property @@ -257,11 +287,11 @@ private: private extern(C++) interface fontInputStream { long read(void* data, long size); - + long seek(long position); - + long tell(); - + long getSize(); } @@ -269,27 +299,27 @@ private extern(C++) interface fontInputStream private class fontStream:fontInputStream { private InputStream myStream; - + this(InputStream stream) { myStream = stream; } - + extern(C++)long read(void* data, long size) { return myStream.read(data[0..cast(size_t)size]); } - + extern(C++)long seek(long position) { return myStream.seek(position); } - + extern(C++)long tell() { return myStream.tell(); } - + extern(C++)long getSize() { return myStream.getSize(); @@ -305,7 +335,7 @@ private extern(C): sfFont* sfFont_construct(); //Create a new font from a file -bool sfFont_loadFromFile(sfFont* font, const(char)* filename); +bool sfFont_loadFromFile(sfFont* font, const(char)* filename, size_t length); //Create a new image font a file in memory @@ -325,15 +355,21 @@ void sfFont_destroy(sfFont* font); //Get a glyph in a font -void sfFont_getGlyph(const(sfFont)* font, uint codePoint, int characterSize, bool bold, int* glyphAdvance, int* glyphBoundsLeft, int* glyphBoundsTop, int* glyphBoundsWidth, int* glyphBoundsHeight, int* glyphTextRectLeft, int* glyphTextRectTop, int* glyphTextRectWidth, int* glyphTextRectHeight); +void sfFont_getGlyph(const(sfFont)* font, uint codePoint, int characterSize, bool bold, float* glyphAdvance, float* glyphBoundsLeft, float* glyphBoundsTop, float* glyphBoundsWidth, float* glyphBoundsHeight, int* glyphTextRectLeft, int* glyphTextRectTop, int* glyphTextRectWidth, int* glyphTextRectHeight); //Get the kerning value corresponding to a given pair of characters in a font -int sfFont_getKerning(const(sfFont)* font, uint first, uint second, uint characterSize); +float sfFont_getKerning(const(sfFont)* font, uint first, uint second, uint characterSize); //Get the line spacing value -int sfFont_getLineSpacing(const(sfFont)* font, uint characterSize); +float sfFont_getLineSpacing(const(sfFont)* font, uint characterSize); + +//Get the position of the underline +float sfFont_getUnderlinePosition (const(sfFont)* font, uint characterSize); + +//Get the thickness of the underline +float sfFont_getUnderlineThickness (const(sfFont)* font, uint characterSize); //Get the texture pointer for a particular font diff --git a/src/dsfml/graphics/glyph.d b/src/dsfml/graphics/glyph.d index 0898a79..11cd96f 100644 --- a/src/dsfml/graphics/glyph.d +++ b/src/dsfml/graphics/glyph.d @@ -36,7 +36,7 @@ public import dsfml.graphics.rect; +/ struct Glyph { - int advance; /// Offset to move horizontally to the next character. - IntRect bounds; /// Bounding rectangle of the glyph, in coordinates relative to the baseline. + float advance; /// Offset to move horizontally to the next character. + FloatRect bounds; /// Bounding rectangle of the glyph, in coordinates relative to the baseline. IntRect textureRect; /// Texture coordinates of the glyph inside the font's texture. } \ No newline at end of file diff --git a/src/dsfml/graphics/image.d b/src/dsfml/graphics/image.d index e8e741f..05f344f 100644 --- a/src/dsfml/graphics/image.d +++ b/src/dsfml/graphics/image.d @@ -30,32 +30,32 @@ import dsfml.system.err; /++ + Class for loading, manipulating and saving images. - + + + + Image is an abstraction to manipulate images as bidimensional arrays of pixels. - + + + + The class provides functions to load, read, write and save pixels, as well as many other useful functions. - + + + + Image can handle a unique internal representation of pixels, which is RGBA 32 bits. This means that a pixel must be composed of 8 bits red, green, blue and alpha channels – just like a Color. All the functions that return an array of pixels follow this rule, and all parameters that you pass to Image functions (such as loadFromPixels) must use this representation as well. - + + + + A Image can be copied, but it is a heavy resource and if possible you should always use [const] references to pass or return them to avoid useless copies. - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1Image.php#details +/ class Image { package sfImage* sfPtr; - + this() { sfPtr = sfImage_construct(); } - + package this(sfImage* image) { sfPtr = image; } - + ~this() { import dsfml.system.config; @@ -65,29 +65,29 @@ class Image /** * Create the image and fill it with a unique color. - * + * * Params: * width = Width of the image * height = Height of the image * color = Fill color - * + * */ void create(uint width, uint height, Color color) { sfImage_createFromColor(sfPtr, width, height,color.r, color.b, color.g, color.a); } - + /** * Create the image from an array of pixels. - * + * * The pixel array is assumed to contain 32-bits RGBA pixels, and have the given width and height. If not, this is an undefined behaviour. If pixels is null, an empty image is created. - * + * * Params: * width = Width of the image * height = Height of the image * pixels = Array of pixels to copy to the image - * + * */ void create(uint width, uint height, const ref ubyte[] pixels) { @@ -96,23 +96,23 @@ class Image /** * Load the image from a file on disk. - * + * * The supported image formats are bmp, png, tga, jpg, gif, psd, hdr and pic. Some format options are not supported, like progressive jpeg. If this function fails, the image is left unchanged. - * + * * Params: * filename = Path of the image file to load - * + * * Returns: True if loading succeeded, false if it failed */ - bool loadFromFile(string fileName) + bool loadFromFile(const(char)[] fileName) { import dsfml.system.string; - bool ret = sfImage_loadFromFile(sfPtr, toStringz(fileName)); + bool ret = sfImage_loadFromFile(sfPtr, fileName.ptr, fileName.length); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; @@ -120,12 +120,12 @@ class Image /** * Load the image from a file in memory. - * + * * The supported image formats are bmp, png, tga, jpg, gif, psd, hdr and pic. Some format options are not supported, like progressive jpeg. If this function fails, the image is left unchanged. - * + * * Params: * data = Data file in memory to load - * + * * Returns: True if loading succeeded, false if it failed */ bool loadFromMemory(const(void)[] data) @@ -135,20 +135,20 @@ class Image bool ret = sfImage_loadFromMemory(sfPtr, data.ptr, data.length); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } - + return ret; } /** * Load the image from a custom stream. - * + * * The supported image formats are bmp, png, tga, jpg, gif, psd, hdr and pic. Some format options are not supported, like progressive jpeg. If this function fails, the image is left unchanged. - * + * * Params: * stream = Source stream to read from - * + * * Returns: True if loading succeeded, false if it failed */ bool loadFromStream(InputStream stream) @@ -158,7 +158,7 @@ class Image bool ret = sfImage_loadFromStream(sfPtr, new imageStream(stream)); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; @@ -166,17 +166,17 @@ class Image /** * Get the color of a pixel - * + * * This function doesn't check the validity of the pixel coordinates; using out-of-range values will result in an undefined behaviour. - * + * * Params: * x = X coordinate of the pixel to get * y = Y coordinate of the pixel to get - * + * * Returns: Color of the pixel at coordinates (x, y) */ Color getPixel(uint x, uint y) - { + { Color temp; sfImage_getPixel(sfPtr, x,y, &temp.r, &temp.b, &temp.g, &temp.a); return temp; @@ -184,16 +184,16 @@ class Image /** * Get the read-only array of pixels that make up the image. - * + * * The returned value points to an array of RGBA pixels made of 8 bits integers components. The size of the array is width * height * 4 (getSize().x * getSize().y * 4). Warning: the returned pointer may become invalid if you modify the image, so you should never store it for too long. - * + * * Returns: Read-only array of pixels that make up the image. */ const(ubyte)[] getPixelArray() { Vector2u size = getSize(); int length = size.x * size.y * 4; - + if(length!=0) { return sfImage_getPixelsPtr(sfPtr)[0..length]; @@ -207,7 +207,7 @@ class Image /** * Return the size (width and height) of the image. - * + * * Returns: Size of the image, in pixels. */ Vector2u getSize() @@ -219,9 +219,9 @@ class Image /** * Change the color of a pixel. - * + * * This function doesn't check the validity of the pixel coordinates, using out-of-range values will result in an undefined behaviour. - * + * * Params: * x = X coordinate of pixel to change * y = Y coordinate of pixel to change @@ -234,11 +234,11 @@ class Image /** * Copy pixels from another image onto this one. - * + * * This function does a slow pixel copy and should not be used intensively. It can be used to prepare a complex static image from several others, but if you need this kind of feature in real-time you'd better use RenderTexture. - * + * * If sourceRect is empty, the whole image is copied. If applyAlpha is set to true, the transparency of source pixels is applied. If it is false, the pixels are copied unchanged with their alpha value. - * + * * Params: * source = Source image to copy * destX = X coordinate of the destination position @@ -253,9 +253,9 @@ class Image /** * Create a transparency mask from a specified color-key. - * + * * This function sets the alpha value of every pixel matching the given color to alpha (0 by default) so that they become transparent. - * + * * Params: * color = Color to make transparent * alpha = Alpha value to assign to transparent pixels @@ -264,7 +264,7 @@ class Image { sfImage_createMaskFromColor(sfPtr,maskColor.r,maskColor.b, maskColor.g, maskColor.a, alpha); } - + @property Image dup() const { @@ -285,19 +285,19 @@ class Image /** * Save the image to a file on disk. - * + * * The format of the image is automatically deduced from the extension. The supported image formats are bmp, png, tga and jpg. The destination file is overwritten if it already exists. This function fails if the image is empty. - * + * * Params: * filename = Path of the file to save - * + * * Returns: True if saving was successful */ - bool saveToFile(string fileName) + bool saveToFile(const(char)[] fileName) { import dsfml.system.string; - bool toReturn = sfImage_saveToFile(sfPtr, toStringz(fileName)); - err.write(toString(sfErr_getOutput())); + bool toReturn = sfImage_saveToFile(sfPtr, fileName.ptr, fileName.length); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return toReturn; } } @@ -339,11 +339,11 @@ unittest private extern(C++) interface imageInputStream { long read(void* data, long size); - + long seek(long position); - + long tell(); - + long getSize(); } @@ -351,27 +351,27 @@ private extern(C++) interface imageInputStream private class imageStream:imageInputStream { private InputStream myStream; - + this(InputStream stream) { myStream = stream; } - + extern(C++)long read(void* data, long size) { return myStream.read(data[0..cast(size_t)size]); } - + extern(C++)long seek(long position) { return myStream.seek(position); } - + extern(C++)long tell() { return myStream.tell(); } - + extern(C++)long getSize() { return myStream.getSize(); @@ -395,7 +395,7 @@ void sfImage_createFromColor(sfImage* image, uint width, uint height, ubyte r, u void sfImage_createFromPixels(sfImage* image, uint width, uint height, const(ubyte)* pixels); /// \brief Create an image from a file on disk -bool sfImage_loadFromFile(sfImage* image, const(char)* filename); +bool sfImage_loadFromFile(sfImage* image, const(char)* filename, size_t length); /// \brief Create an image from a file in memory bool sfImage_loadFromMemory(sfImage* image, const(void)* data, size_t size); @@ -410,7 +410,7 @@ sfImage* sfImage_copy(const(sfImage)* image); void sfImage_destroy(sfImage* image); /// \brief Save an image to a file on disk -bool sfImage_saveToFile(const sfImage* image, const char* filename); +bool sfImage_saveToFile(const sfImage* image, const char* filename, size_t length); /// \brief Return the size of an image void sfImage_getSize(const sfImage* image, uint* width, uint* height); diff --git a/src/dsfml/graphics/rendertexture.d b/src/dsfml/graphics/rendertexture.d index 2634764..4053b36 100644 --- a/src/dsfml/graphics/rendertexture.d +++ b/src/dsfml/graphics/rendertexture.d @@ -40,17 +40,17 @@ import dsfml.system.err; /++ + Target for off-screen 2D rendering into a texture. - + + + + RenderTexture is the little brother of RenderWindow. - + + + + It implements the same 2D drawing and OpenGL-related functions (see their base class RenderTarget for more details), the difference is that the result is stored in an off-screen texture rather than being show in a window. - + + + + Rendering to a texture can be useful in a variety of situations: + - precomputing a complex static texture (like a level's background from multiple tiles) + - applying post-effects to the whole scene with shaders + - creating a sprite from a 3D object rendered with OpenGL + - etc. - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1RenderTexture.php#details +/ @@ -77,23 +77,23 @@ class RenderTexture : RenderTarget /** * Create the render-texture. - * - * Before calling this function, the render-texture is in an invalid state, thus it is mandatory to call it before doing anything with the render-texture. - * + * + * Before calling this function, the render-texture is in an invalid state, thus it is mandatory to call it before doing anything with the render-texture. + * * The last parameter, depthBuffer, is useful if you want to use the render-texture for 3D OpenGL rendering that requires a depth-buffer. Otherwise it is unnecessary, and you should leave this parameter to false (which is its default value). - * + * * Params: * width = Width of the render-texture * height = Height of the render-texture * depthBuffer = Do you want this render-texture to have a depth buffer? - * + * */ void create(uint width, uint height, bool depthBuffer = false) { import dsfml.system.string; sfRenderTexture_create(sfPtr, width, height, depthBuffer); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); //get view m_currentView = new View(sfRenderTexture_getView(sfPtr)); @@ -102,7 +102,7 @@ class RenderTexture : RenderTarget m_defaultView = new View(sfRenderTexture_getDefaultView(sfPtr)); } - + /** * Enable or disable texture smoothing. */ @@ -121,9 +121,9 @@ class RenderTexture : RenderTarget /** * Change the current active view. - * - * The view is like a 2D camera, it controls which part of the 2D scene is visible, and how it is viewed in the render-target. The new view will affect everything that is drawn, until another view is set. - * + * + * The view is like a 2D camera, it controls which part of the 2D scene is visible, and how it is viewed in the render-target. The new view will affect everything that is drawn, until another view is set. + * * The render target keeps its own copy of the view object, so it is not necessary to keep the original one alive after calling this function. To restore the original view of the target, you can pass the result of getDefaultView() to this function. */ @property @@ -142,9 +142,9 @@ class RenderTexture : RenderTarget /** * Get the default view of the render target. - * + * * The default view has the initial size of the render target, and never changes after the target has been created. - * + * * Returns: The default view of the render target. */ const(View) getDefaultView() const // note: if refactored, change documentation of view property above @@ -154,7 +154,7 @@ class RenderTexture : RenderTarget /** * Return the size of the rendering region of the target. - * + * * Returns: Size in pixels */ Vector2u getSize() const @@ -166,12 +166,12 @@ class RenderTexture : RenderTarget /** * Get the viewport of a view, applied to this render target. - * + * * The viewport is defined in the view as a ratio, this function simply applies this ratio to the current dimensions of the render target to calculate the pixels rectangle that the viewport actually covers in the target. - * + * * Params: * view = The view for which we want to compute the viewport - * + * * Returns: Viewport rectangle, expressed in pixels */ IntRect getViewport(const(View) view) const @@ -183,11 +183,11 @@ class RenderTexture : RenderTarget /** * Get a read-only reference to the target texture. - * + * * After drawing to the render-texture and calling Display, you can retrieve the updated texture using this function, and draw it using a sprite (for example). - * + * * The internal Texture of a render-texture is always the same instance, so that it is possible to call this function once and keep a reference to the texture even after it is modified. - * + * * Returns: Const reference to the texture. */ const(Texture) getTexture() @@ -197,11 +197,11 @@ class RenderTexture : RenderTarget /** * Activate or deactivate the render-texture for rendering. - * + * * This function makes the render-texture's context current for future OpenGL rendering operations (so you shouldn't care about it if you're not doing direct OpenGL stuff). - * + * * Only one context can be current in a thread, so if you want to draw OpenGL geometry to another render target (like a RenderWindow) don't forget to activate it again. - * + * * Params: * active = True to activate, false to deactivate */ @@ -212,9 +212,9 @@ class RenderTexture : RenderTarget /** * Clear the entire target with a single color. - * + * * This function is usually called once every frame, to clear the previous contents of the target. - * + * * Params: * color = Fill color to use to clear the render target */ @@ -225,7 +225,7 @@ class RenderTexture : RenderTarget /** * Update the contents of the target texture. - * + * * This function updates the target texture with what has been drawn so far. Like for windows, calling this function is mandatory at the end of rendering. Not calling it may leave the texture in an undefined state. */ void display() @@ -235,7 +235,7 @@ class RenderTexture : RenderTarget /** * Draw a drawable object to the render target. - * + * * Params: * drawable = Object to draw * states = Render states to use for drawing @@ -251,13 +251,13 @@ class RenderTexture : RenderTarget { states.shader = RenderStates.emptyShader; } - + drawable.draw(this, states); } /** * Draw primitives defined by an array of vertices. - * + * * Params: * vertices = Array of vertices to draw * type = Type of primitives to draw @@ -266,7 +266,7 @@ class RenderTexture : RenderTarget override void draw(const(Vertex)[] vertices, PrimitiveType type, RenderStates states = RenderStates.Default) { import std.algorithm; - + //Confirms that even a blank render states struct won't break anything during drawing if(states.texture is null) { @@ -276,18 +276,20 @@ class RenderTexture : RenderTarget { states.shader = RenderStates.emptyShader; } - - sfRenderTexture_drawPrimitives(sfPtr, vertices.ptr, cast(uint)min(uint.max, vertices.length),type,states.blendMode, states.transform.m_matrix.ptr, states.texture.sfPtr, states.shader.sfPtr); + + sfRenderTexture_drawPrimitives(sfPtr, vertices.ptr, cast(uint)min(uint.max, vertices.length),type,states.blendMode.colorSrcFactor, states.blendMode.alphaDstFactor, + states.blendMode.colorEquation, states.blendMode.alphaSrcFactor, states.blendMode.alphaDstFactor, states.blendMode.alphaEquation, + states.transform.m_matrix.ptr, states.texture.sfPtr, states.shader.sfPtr); } /** * Convert a point fom target coordinates to world coordinates, using the current view. - * + * * This function is an overload of the mapPixelToCoords function that implicitely uses the current view. - * + * * Params: * point = Pixel to convert - * + * * Returns: The converted point, in "world" coordinates. */ Vector2f mapPixelToCoords(Vector2i point) const @@ -299,19 +301,19 @@ class RenderTexture : RenderTarget /** * Convert a point from target coordinates to world coordinates. - * + * * This function finds the 2D position that matches the given pixel of the render-target. In other words, it does the inverse of what the graphics card does, to find the initial position of a rendered pixel. - * + * * Initially, both coordinate systems (world units and target pixels) match perfectly. But if you define a custom view or resize your render-target, this assertion is not true anymore, ie. a point located at (10, 50) in your render-target may map to the point (150, 75) in your 2D world – if the view is translated by (140, 25). - * + * * For render-windows, this function is typically used to find which point (or object) is located below the mouse cursor. - * + * * This version uses a custom view for calculations, see the other overload of the function if you want to use the current view of the render-target. - * + * * Params: * point = Pixel to convert * view = The view to use for converting the point - * + * * Returns: The converted point, in "world" coordinates. */ Vector2f mapPixelToCoords(Vector2i point, const(View) view) const @@ -323,46 +325,46 @@ class RenderTexture : RenderTarget /** * Convert a point from target coordinates to world coordinates, using the current view. - * + * * This function is an overload of the mapPixelToCoords function that implicitely uses the current view. - * + * * Params: * point = Point to convert - * + * * The converted point, in "world" coordinates */ Vector2i mapCoordsToPixel(Vector2f point) const { Vector2i temp; - sfRenderTexture_mapCoordsToPixel(sfPtr,point.x, point.y, &temp.x, &temp.y,null); + sfRenderTexture_mapCoordsToPixel(sfPtr,point.x, point.y, &temp.x, &temp.y,null); return temp; } /** * Convert a point from world coordinates to target coordinates. - * + * * This function finds the pixel of the render-target that matches the given 2D point. In other words, it goes through the same process as the graphics card, to compute the final position of a rendered point. - * + * * Initially, both coordinate systems (world units and target pixels) match perfectly. But if you define a custom view or resize your render-target, this assertion is not true anymore, ie. a point located at (150, 75) in your 2D world may map to the pixel (10, 50) of your render-target – if the view is translated by (140, 25). - * + * * This version uses a custom view for calculations, see the other overload of the function if you want to use the current view of the render-target. - * + * * Params: * point = Point to convert * view = The view to use for converting the point - * + * * Returns: The converted point, in target coordinates (pixels) */ Vector2i mapCoordsToPixel(Vector2f point, const(View) view) const { Vector2i temp; - sfRenderTexture_mapCoordsToPixel(sfPtr,point.x, point.y, &temp.x, &temp.y,view.sfPtr); + sfRenderTexture_mapCoordsToPixel(sfPtr,point.x, point.y, &temp.x, &temp.y,view.sfPtr); return temp; } /** * Restore the previously saved OpenGL render states and matrices. - * + * * See the description of pushGLStates to get a detailed description of these functions. */ void popGLStates() @@ -372,25 +374,25 @@ class RenderTexture : RenderTarget /** * Save the current OpenGL render states and matrices. - * + * * This function can be used when you mix SFML drawing and direct OpenGL rendering. Combined with PopGLStates, it ensures that: * - SFML's internal states are not messed up by your OpenGL code * - your OpenGL states are not modified by a call to an SFML function - * + * * More specifically, it must be used around the code that calls Draw functions. - * + * * Note that this function is quite expensive: it saves all the possible OpenGL states and matrices, even the ones you don't care about. Therefore it should be used wisely. It is provided for convenience, but the best results will be achieved if you handle OpenGL states yourself (because you know which states have really changed, and need to be saved and restored). Take a look at the ResetGLStates function if you do so. */ void pushGLStates() { import dsfml.system.string; sfRenderTexture_pushGLStates(sfPtr); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } /** * Reset the internal OpenGL states so that the target is ready for drawing. - * + * * This function can be used when you mix SFML drawing and direct OpenGL rendering, if you choose not to use pushGLStates/popGLStates. It makes sure that all OpenGL states needed by SFML are set, so that subsequent draw() calls will work as expected. */ void resetGLStates() @@ -478,7 +480,8 @@ void sfRenderTexture_mapCoordsToPixel(const sfRenderTexture* renderTexture, floa //Draw primitives defined by an array of vertices to a render texture -void sfRenderTexture_drawPrimitives(sfRenderTexture* renderTexture, const void* vertices, uint vertexCount, int type, int blendMode,const float* transform, const sfTexture* texture, const sfShader* shader); +void sfRenderTexture_drawPrimitives(sfRenderTexture* renderTexture, const void* vertices, uint vertexCount, int type, int colorSrcFactor, int colorDstFactor, int colorEquation, + int alphaSrcFactor, int alphaDstFactor, int alphaEquation, const float* transform, const sfTexture* texture, const sfShader* shader); //Save the current OpenGL render states and matrices void sfRenderTexture_pushGLStates(sfRenderTexture* renderTexture); diff --git a/src/dsfml/graphics/renderwindow.d b/src/dsfml/graphics/renderwindow.d index dec6385..48d19ee 100644 --- a/src/dsfml/graphics/renderwindow.d +++ b/src/dsfml/graphics/renderwindow.d @@ -45,17 +45,17 @@ import dsfml.system.vector2; /++ + Window that can serve as a target for 2D drawing. - + + + + RenderWindow is the main class of the Graphics package. - + + + + It defines an OS window that can be painted using the other classes of the graphics module. - + + + + RenderWindow is derived from Window, thus it inherits all its features: events, window management, OpenGL rendering, etc. See the documentation of Window for a more complete description of all these features, as well as code examples. - + + + + On top of that, RenderWindow adds more features related to 2D drawing with the graphics module (see its base class RenderTarget for more details). - + + + + Like Window, RenderWindow is still able to render direct OpenGL stuff. It is even possible to mix together OpenGL calls and regular SFML drawing commands. - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://sfml-dev.org/documentation/2.0/classsf_1_1RenderWindow.php#details +/ @@ -97,7 +97,7 @@ class RenderWindow : Window, RenderTarget /** * Change the position of the window on screen. - * + * * This property only works for top-level windows (i.e. it will be ignored for windows created from the handle of a child window/control). */ @property @@ -107,7 +107,7 @@ class RenderWindow : Window, RenderTarget sfRenderWindow_setPosition(sfPtr,newPosition.x, newPosition.y); return newPosition; } - + override Vector2i position() { Vector2i temp; @@ -136,9 +136,9 @@ class RenderWindow : Window, RenderTarget /** * Change the current active view. - * - * The view is like a 2D camera, it controls which part of the 2D scene is visible, and how it is viewed in the render-target. The new view will affect everything that is drawn, until another view is set. - * + * + * The view is like a 2D camera, it controls which part of the 2D scene is visible, and how it is viewed in the render-target. The new view will affect everything that is drawn, until another view is set. + * * The render target keeps its own copy of the view object, so it is not necessary to keep the original one alive after calling this function. To restore the original view of the target, you can pass the result of getDefaultView() to this function. */ @property @@ -157,9 +157,9 @@ class RenderWindow : Window, RenderTarget /** * Get the default view of the render target. - * + * * The default view has the initial size of the render target, and never changes after the target has been created. - * + * * Returns: The default view of the render target. */ const(View) getDefaultView() const // note: if refactored, change documentation of view property above @@ -169,9 +169,9 @@ class RenderWindow : Window, RenderTarget /** * Get the settings of the OpenGL context of the window. - * + * * Note that these settings may be different from what was passed to the constructor or the create() function, if one or more settings were not supported. In this case, SFML chose the closest match. - * + * * Returns: Structure containing the OpenGL context settings */ override ContextSettings getSettings() const @@ -184,23 +184,23 @@ class RenderWindow : Window, RenderTarget //this is a duplicate with the size property. Need to look into that.(Inherited from RenderTarget) /** * Return the size of the rendering region of the target. - * + * * Returns: Size in pixels */ Vector2u getSize() const { Vector2u temp; - + sfRenderWindow_getSize(sfPtr, &temp.x, &temp.y); - + return temp; } /** * Get the OS-specific handle of the window. - * + * * The type of the returned handle is WindowHandle, which is a typedef to the handle type defined by the OS. You shouldn't need to use this function, unless you have very specific stuff to implement that SFML doesn't support, or implement a temporary workaround until a bug is fixed. - * + * * Returns: System handle of the window */ override WindowHandle getSystemHandle() const @@ -210,48 +210,48 @@ class RenderWindow : Window, RenderTarget /** * Get the viewport of a view, applied to this render target. - * + * * The viewport is defined in the view as a ratio, this function simply applies this ratio to the current dimensions of the render target to calculate the pixels rectangle that the viewport actually covers in the target. - * + * * Params: * view = The view for which we want to compute the viewport - * + * * Returns: Viewport rectangle, expressed in pixels */ IntRect getViewport(const(View) view) const { IntRect temp; - + sfRenderWindow_getViewport(sfPtr, view.sfPtr, &temp.left, &temp.top, &temp.width, &temp.height); - + return temp; } /** * Get the viewport of a view, applied to this render target. - * + * * A window is active only on the current thread, if you want to make it active on another thread you have to deactivate it on the previous thread first if it was active. Only one window can be active on a thread at a time, thus the window previously active (if any) automatically gets deactivated. - * + * * Params: * active = True to activate, false to deactivate - * + * * Returns: True if operation was successful, false otherwise */ override bool setActive(bool active) { import dsfml.system.string; bool toReturn = sfRenderWindow_setActive(sfPtr, active); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return toReturn; } /** * Limit the framerate to a maximum fixed frequency. - * + * * If a limit is set, the window will use a small delay after each call to display() to ensure that the current frame lasted long enough to match the framerate limit. - * + * * SFML will try to match the given limit as much as it can, but since it internally uses sf::sleep, whose precision depends on the underlying OS, the results may be a little unprecise as well (for example, you can get 65 FPS when requesting 60). - * + * * Params: * limit = Framerate limit, in frames per seconds (use 0 to disable limit) */ @@ -262,11 +262,11 @@ class RenderWindow : Window, RenderTarget /** * Change the window's icon. - * + * * pixels must be an array of width x height pixels in 32-bits RGBA format. - * + * * The OS default icon is used by default. - * + * * Params: * width = Icon's width, in pixels * height = Icon's height, in pixels @@ -279,11 +279,11 @@ class RenderWindow : Window, RenderTarget /** * Change the joystick threshold. - * + * * The joystick threshold is the value below which no JoystickMoved event will be generated. - * + * * The threshold value is 0.1 by default. - * + * * Params: * threshold = New threshold, in the range [0, 100] */ @@ -294,11 +294,11 @@ class RenderWindow : Window, RenderTarget /** * Enable or disable automatic key-repeat. - * + * * If key repeat is enabled, you will receive repeated KeyPressed events while keeping a key pressed. If it is disabled, you will only get a single event when the key is pressed. - * + * * Key repeat is enabled by default. - * + * * Params: * enabled = True to enable, false to disable */ @@ -309,9 +309,9 @@ class RenderWindow : Window, RenderTarget /** * Show or hide the mouse cursor. - * + * * The mouse cursor is visible by default. - * + * * Params: * enabled = True show the mouse cursor, false to hide it */ @@ -324,45 +324,47 @@ class RenderWindow : Window, RenderTarget /** * Change the title of the window - * + * * Params: * title = New title */ - override void setTitle(string newTitle) + override void setTitle(const(char)[] newTitle) { import dsfml.system.string; - sfRenderWindow_setUnicodeTitle(sfPtr, toStringz(stringConvert!(char, dchar)(newTitle))); + auto convertedTitle = stringConvert!(char, dchar)(newTitle); + sfRenderWindow_setUnicodeTitle(sfPtr, convertedTitle.ptr, convertedTitle.length); } /** * Change the title of the window - * + * * Params: * title = New title */ - override void setTitle(wstring newTitle) + override void setTitle(const(wchar)[] newTitle) { import dsfml.system.string; - sfRenderWindow_setUnicodeTitle(sfPtr, toStringz(stringConvert!(wchar, dchar)(newTitle))); + auto convertedTitle = stringConvert!(wchar, dchar)(newTitle); + sfRenderWindow_setUnicodeTitle(sfPtr, convertedTitle.ptr, convertedTitle.length); } /** * Change the title of the window - * + * * Params: * title = New title */ - override void setTitle(dstring newTitle) + override void setTitle(const(dchar)[] newTitle) { - import dsfml.system.string; - sfRenderWindow_setUnicodeTitle(sfPtr, toStringz(newTitle)); + import dsfml.system.string; + sfRenderWindow_setUnicodeTitle(sfPtr, newTitle.ptr, newTitle.length); } /** * Enable or disable vertical synchronization. - * + * * Activating vertical synchronization will limit the number of frames displayed to the refresh rate of the monitor. This can avoid some visual artifacts, and limit the framerate to a good value (but not constant across different computers). - * + * * Vertical synchronization is disabled by default. - * + * * Params: * enabled = True to enable v-sync, false to deactivate it */ @@ -373,9 +375,9 @@ class RenderWindow : Window, RenderTarget /** * Show or hide the window. - * + * * The window is shown by default. - * + * * Params: * visible = True to show the window, false to hide it */ @@ -386,9 +388,9 @@ class RenderWindow : Window, RenderTarget /** * Clear the entire target with a single color. - * + * * This function is usually called once every frame, to clear the previous contents of the target. - * + * * Params: * color = Fill color to use to clear the render target */ @@ -399,7 +401,7 @@ class RenderWindow : Window, RenderTarget /** * Close the window and destroy all the attached resources. - * + * * After calling this function, the Window instance remains valid and you can call create() to recreate the window. All other functions such as pollEvent() or display() will still work (i.e. you don't have to test isOpen() every time), and will have no effect on closed windows. */ override void close() @@ -414,12 +416,14 @@ class RenderWindow : Window, RenderTarget ///If the window was already created, it closes it first. If style contains Style::Fullscreen, then mode must be a valid video mode. /// ///The fourth parameter is an optional structure specifying advanced OpenGL context settings such as antialiasing, depth-buffer bits, etc. - override void create(VideoMode mode, string title, Style style = Style.DefaultStyle, ref const(ContextSettings) settings = ContextSettings.Default) + override void create(VideoMode mode, const(char)[] title, Style style = Style.DefaultStyle, ref const(ContextSettings) settings = ContextSettings.Default) { import dsfml.system.string; - - sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, toStringz(stringConvert!(char,dchar)(title)), style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); - err.write(toString(sfErr_getOutput())); + + auto convertedTitle = stringConvert!(char, dchar)(title); + + sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, convertedTitle.ptr, convertedTitle.length, style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); + err.write(dsfml.system.string.toString(sfErr_getOutput())); //get view m_currentView = new View(sfRenderWindow_getView(sfPtr)); @@ -433,12 +437,13 @@ class RenderWindow : Window, RenderTarget ///If the window was already created, it closes it first. If style contains Style::Fullscreen, then mode must be a valid video mode. /// ///The fourth parameter is an optional structure specifying advanced OpenGL context settings such as antialiasing, depth-buffer bits, etc. - override void create(VideoMode mode, wstring title, Style style = Style.DefaultStyle, ref const(ContextSettings) settings = ContextSettings.Default) + override void create(VideoMode mode, const(wchar)[] title, Style style = Style.DefaultStyle, ref const(ContextSettings) settings = ContextSettings.Default) { import dsfml.system.string; - - sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, toStringz(stringConvert!(wchar,dchar)(title)), style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); - err.write(toString(sfErr_getOutput())); + auto convertedTitle = stringConvert!(wchar, dchar)(title); + + sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, convertedTitle.ptr, convertedTitle.length, style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); + err.write(dsfml.system.string.toString(sfErr_getOutput())); //get view m_currentView = new View(sfRenderWindow_getView(sfPtr)); @@ -452,12 +457,10 @@ class RenderWindow : Window, RenderTarget ///If the window was already created, it closes it first. If style contains Style::Fullscreen, then mode must be a valid video mode. /// ///The fourth parameter is an optional structure specifying advanced OpenGL context settings such as antialiasing, depth-buffer bits, etc. - override void create(VideoMode mode, dstring title, Style style = Style.DefaultStyle, ref const(ContextSettings) settings = ContextSettings.Default) + override void create(VideoMode mode, const(dchar)[] title, Style style = Style.DefaultStyle, ref const(ContextSettings) settings = ContextSettings.Default) { - import dsfml.system.string; - - sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, toStringz(title), style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); - err.write(toString(sfErr_getOutput())); + sfRenderWindow_createFromSettings(sfPtr, mode.width, mode.height, mode.bitsPerPixel, title.ptr, title.length, style, settings.depthBits, settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); + err.write(dsfml.system.string.toString(sfErr_getOutput())); //get view m_currentView = new View(sfRenderWindow_getView(sfPtr)); @@ -476,7 +479,7 @@ class RenderWindow : Window, RenderTarget { import dsfml.system.string; sfRenderWindow_createFromHandle(sfPtr, handle, settings.depthBits,settings.stencilBits, settings.antialiasingLevel, settings.majorVersion, settings.minorVersion); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); //get view m_currentView = new View(sfRenderWindow_getView(sfPtr)); @@ -486,7 +489,7 @@ class RenderWindow : Window, RenderTarget /** * Display on screen what has been rendered to the window so far. - * + * * This function is typically called after all OpenGL rendering has been done for the current frame, in order to show it on screen. */ override void display() @@ -496,7 +499,7 @@ class RenderWindow : Window, RenderTarget /** * Draw a drawable object to the render target. - * + * * Params: * drawable = Object to draw * states = Render states to use for drawing @@ -512,13 +515,13 @@ class RenderWindow : Window, RenderTarget { states.shader = RenderStates.emptyShader; } - + drawable.draw(this,states); } /** * Draw primitives defined by an array of vertices. - * + * * Params: * vertices = Array of vertices to draw * type = Type of primitives to draw @@ -536,15 +539,17 @@ class RenderWindow : Window, RenderTarget { states.shader = RenderStates.emptyShader; } - - sfRenderWindow_drawPrimitives(sfPtr, vertices.ptr, cast(uint)min(uint.max, vertices.length), type,states.blendMode, states.transform.m_matrix.ptr,states.texture.sfPtr,states.shader.sfPtr); + + sfRenderWindow_drawPrimitives(sfPtr, vertices.ptr, cast(uint)min(uint.max, vertices.length), type,states.blendMode.colorSrcFactor, states.blendMode.alphaDstFactor, + states.blendMode.colorEquation, states.blendMode.alphaSrcFactor, states.blendMode.alphaDstFactor, states.blendMode.alphaEquation, + states.transform.m_matrix.ptr,states.texture.sfPtr,states.shader.sfPtr); } /** * Tell whether or not the window is open. - * + * * This function returns whether or not the window exists. Note that a hidden window (setVisible(false)) is open (therefore this function would return true). - * + * * Returns: True if the window is open, false if it has been closed */ override bool isOpen() @@ -554,95 +559,95 @@ class RenderWindow : Window, RenderTarget /** * Convert a point fom target coordinates to world coordinates, using the current view. - * + * * This function is an overload of the mapPixelToCoords function that implicitely uses the current view. - * + * * Params: * point = Pixel to convert - * + * * Returns: The converted point, in "world" coordinates. */ Vector2f mapPixelToCoords(Vector2i point) const { Vector2f temp; - + sfRenderWindow_mapPixelToCoords(sfPtr,point.x, point.y, &temp.x, &temp.y,null); - + return temp; } /** * Convert a point from target coordinates to world coordinates. - * + * * This function finds the 2D position that matches the given pixel of the render-target. In other words, it does the inverse of what the graphics card does, to find the initial position of a rendered pixel. - * + * * Initially, both coordinate systems (world units and target pixels) match perfectly. But if you define a custom view or resize your render-target, this assertion is not true anymore, ie. a point located at (10, 50) in your render-target may map to the point (150, 75) in your 2D world – if the view is translated by (140, 25). - * + * * For render-windows, this function is typically used to find which point (or object) is located below the mouse cursor. - * + * * This version uses a custom view for calculations, see the other overload of the function if you want to use the current view of the render-target. - * + * * Params: * point = Pixel to convert * view = The view to use for converting the point - * + * * Returns: The converted point, in "world" coordinates. */ Vector2f mapPixelToCoords(Vector2i point, const(View) view) const { Vector2f temp; - + sfRenderWindow_mapPixelToCoords(sfPtr,point.x, point.y, &temp.x, &temp.y,view.sfPtr); - + return temp; } /** * Convert a point from target coordinates to world coordinates, using the current view. - * + * * This function is an overload of the mapPixelToCoords function that implicitely uses the current view. - * + * * Params: * point = Point to convert - * + * * The converted point, in "world" coordinates */ Vector2i mapCoordsToPixel(Vector2f point) const { Vector2i temp; - + sfRenderWindow_mapCoordsToPixel(sfPtr,point.x, point.y, &temp.x, &temp.y,null); - + return temp; } /** * Convert a point from world coordinates to target coordinates. - * + * * This function finds the pixel of the render-target that matches the given 2D point. In other words, it goes through the same process as the graphics card, to compute the final position of a rendered point. - * + * * Initially, both coordinate systems (world units and target pixels) match perfectly. But if you define a custom view or resize your render-target, this assertion is not true anymore, ie. a point located at (150, 75) in your 2D world may map to the pixel (10, 50) of your render-target – if the view is translated by (140, 25). - * + * * This version uses a custom view for calculations, see the other overload of the function if you want to use the current view of the render-target. - * + * * Params: * point = Point to convert * view = The view to use for converting the point - * + * * Returns: The converted point, in target coordinates (pixels) */ Vector2i mapCoordsToPixel(Vector2f point, const(View) view) const { Vector2i temp; - + sfRenderWindow_mapCoordsToPixel(sfPtr,point.x, point.y, &temp.x, &temp.y,view.sfPtr); - + return temp; } /** * Restore the previously saved OpenGL render states and matrices. - * + * * See the description of pushGLStates to get a detailed description of these functions. */ void popGLStates() @@ -652,25 +657,25 @@ class RenderWindow : Window, RenderTarget /** * Save the current OpenGL render states and matrices. - * + * * This function can be used when you mix SFML drawing and direct OpenGL rendering. Combined with PopGLStates, it ensures that: * - SFML's internal states are not messed up by your OpenGL code * - your OpenGL states are not modified by a call to an SFML function - * + * * More specifically, it must be used around the code that calls Draw functions. - * + * * Note that this function is quite expensive: it saves all the possible OpenGL states and matrices, even the ones you don't care about. Therefore it should be used wisely. It is provided for convenience, but the best results will be achieved if you handle OpenGL states yourself (because you know which states have really changed, and need to be saved and restored). Take a look at the ResetGLStates function if you do so. */ void pushGLStates() { import dsfml.system.string; sfRenderWindow_pushGLStates(sfPtr); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } /** * Reset the internal OpenGL states so that the target is ready for drawing. - * + * * This function can be used when you mix SFML drawing and direct OpenGL rendering, if you choose not to use pushGLStates/popGLStates. It makes sure that all OpenGL states needed by SFML are set, so that subsequent draw() calls will work as expected. */ void resetGLStates() @@ -680,12 +685,12 @@ class RenderWindow : Window, RenderTarget /** * Pop the event on top of the event queue, if any, and return it. - * + * * This function is not blocking: if there's no pending event then it will return false and leave event unmodified. Note that more than one event may be present in the event queue, thus you should always call this function in a loop to make sure that you process every pending event. - * + * * Params: * event = Event to be returned - * + * * Returns: True if an event was returned, or false if the event queue was empty */ override bool pollEvent(ref Event event) @@ -695,19 +700,19 @@ class RenderWindow : Window, RenderTarget /** * Wait for an event and return it. - * + * * This function is blocking: if there's no pending event then it will wait until an event is received. After this function returns (and no error occured), the event object is always valid and filled properly. This function is typically used when you have a thread that is dedicated to events handling: you want to make this thread sleep as long as no new event is received. - * + * * Params: * event = Event to be returned - * + * * Returns: False if any error occurred */ override bool waitEvent(ref Event event) { return (sfRenderWindow_waitEvent(sfPtr, &event)); } - + //TODO: Consider adding these methods. //void onCreate //void onResize @@ -736,8 +741,8 @@ class RenderWindow : Window, RenderTarget package static void* windowPointer(Window window) { scope RenderWindow temp = new RenderWindow(); - - return temp.getWindowPtr(window); + + return temp.getWindowPtr(window); } } @@ -755,43 +760,43 @@ unittest //constructor auto window = new RenderWindow(VideoMode(800,600),"Test Window"); - + //perform each window call Vector2u windowSize = window.size; - + windowSize.x = 1000; windowSize.y = 1000; - + window.size = windowSize; - + Vector2i windowPosition = window.position; - + windowPosition.x = 100; windowPosition.y = 100; - + window.position = windowPosition; - + window.setTitle("thing");//uses the first set title - + window.setTitle("素晴らしい !"d);//forces the dstring override and uses unicode - + window.setActive(true); - + window.setJoystickThreshhold(1); - + window.setVisible(true); - + window.setFramerateLimit(60); - + window.setMouseCursorVisible(true); - + window.setVerticalSyncEnabled(true); - + auto settings = window.getSettings(); - + auto image = new Image(); image.loadFromFile("res/TestImage.png"); - + window.setIcon(image.getSize().x,image.getSize().x,image.getPixelArray()); auto texture = new Texture(); @@ -816,9 +821,9 @@ unittest } window.clear(); - + window.draw(sprite); - + window.display(); } @@ -836,13 +841,13 @@ private extern(C): sfRenderWindow* sfRenderWindow_construct(); //Construct a new render window from settings -sfRenderWindow* sfRenderWindow_constructFromSettings(uint width, uint height, uint bitsPerPixel, const(dchar)* title, int style, uint depthBits, uint stencilBits, uint antialiasingLevel, uint majorVersion, uint minorVersion); +sfRenderWindow* sfRenderWindow_constructFromSettings(uint width, uint height, uint bitsPerPixel, const(dchar)* title, size_t titleLength, int style, uint depthBits, uint stencilBits, uint antialiasingLevel, uint majorVersion, uint minorVersion); //Construct a render window from an existing control sfRenderWindow* sfRenderWindow_constructFromHandle(WindowHandle handle, uint depthBits, uint stencilBits, uint antialiasingLevel, uint majorVersion, uint minorVersion); //Create(or recreate) a new render window from settings -void sfRenderWindow_createFromSettings(sfRenderWindow* renderWindow, uint width, uint height, uint bitsPerPixel, const(dchar)* title, int style, uint depthBits, uint stencilBits, uint antialiasingLevel, uint majorVersion, uint minorVersion); +void sfRenderWindow_createFromSettings(sfRenderWindow* renderWindow, uint width, uint height, uint bitsPerPixel, const(dchar)* title, size_t titleLength, int style, uint depthBits, uint stencilBits, uint antialiasingLevel, uint majorVersion, uint minorVersion); //Create(or recreate) a render window from an existing control void sfRenderWindow_createFromHandle(sfRenderWindow* renderWindow, WindowHandle handle, uint depthBits, uint stencilBits, uint antialiasingLevel, uint majorVersion, uint minorVersion); @@ -878,10 +883,10 @@ void sfRenderWindow_getSize(const sfRenderWindow* renderWindow, uint* width, uin void sfRenderWindow_setSize(sfRenderWindow* renderWindow, int width, int height); //Change the title of a render window -void sfRenderWindow_setTitle(sfRenderWindow* renderWindow, const(char)* title); +void sfRenderWindow_setTitle(sfRenderWindow* renderWindow, const(char)* title, size_t titleLength); //Change the title of a render window (with a UTF-32 string) -void sfRenderWindow_setUnicodeTitle(sfRenderWindow* renderWindow, const(dchar)* title); +void sfRenderWindow_setUnicodeTitle(sfRenderWindow* renderWindow, const(dchar)* title, size_t titleLength); //Change a render window's icon void sfRenderWindow_setIcon(sfRenderWindow* renderWindow, uint width, uint height, const ubyte* pixels); @@ -939,7 +944,8 @@ void sfRenderWindow_mapCoordsToPixel(const sfRenderWindow* renderWindow, float x //Draw primitives defined by an array of vertices to a render window -void sfRenderWindow_drawPrimitives(sfRenderWindow* renderWindow,const (void)* vertices, uint vertexCount, int type, int blendMode,const(float)* transform, const(sfTexture)* texture, const(sfShader)* shader); +void sfRenderWindow_drawPrimitives(sfRenderWindow* renderWindow,const (void)* vertices, uint vertexCount, int type, int colorSrcFactor, int colorDstFactor, int colorEquation, + int alphaSrcFactor, int alphaDstFactor, int alphaEquation, const (float)* transform, const (sfTexture)* texture, const (sfShader)* shader); //Save the current OpenGL render states and matrices void sfRenderWindow_pushGLStates(sfRenderWindow* renderWindow); diff --git a/src/dsfml/graphics/shader.d b/src/dsfml/graphics/shader.d index 06eddc1..5cb77e9 100644 --- a/src/dsfml/graphics/shader.d +++ b/src/dsfml/graphics/shader.d @@ -31,24 +31,24 @@ import dsfml.system.err; /++ + Shader class (vertex and fragment). - + + + + Shaders are programs written using a specific language, executed directly by the graphics card and allowing one to apply real-time operations to the rendered entities. - + + + + There are two kinds of shaders: + - Vertex shaders, that process vertices + - Fragment (pixel) shaders, that process pixels - + + + + A DSFML Shader can be composed of either a vertex shader alone, a fragment shader alone, or both combined (see the variants of the load functions). - + + + + Shaders are written in GLSL, which is a C-like language dedicated to OpenGL shaders. You'll probably need to learn its basics before writing your own shaders for SFML. - + + + + Like any D/C/C++ program, a shader has its own variables that you can set from your D application. DSFML's Shader handles 5 different types of variables: + - floats + - vectors (2, 3, or 4 components) + - colors + - textures + - transforms (matrices) - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1Shader.php#details +/ @@ -66,19 +66,19 @@ class Shader /// Special type/value that can be passed to setParameter, and that represents the texture of the object being drawn. struct CurrentTextureType {}; static CurrentTextureType CurrentTexture; - + this() { //creates an empty shader sfPtr=sfShader_construct(); } - + package this(sfShader* shader) { sfPtr = shader; } - + ~this() { import dsfml.system.config; @@ -88,16 +88,16 @@ class Shader /** * Load either the vertex or fragment shader from a file. - * + * * This function loads a single shader, either vertex or fragment, identified by the second argument. The source must be a text file containing a valid shader in GLSL language. GLSL is a C-like language dedicated to OpenGL shaders; you'll probably need to read a good documentation for it before writing your own shaders. - * + * * Params: * filename = Path of the vertex or fragment shader file to load * type = Type of shader (vertex or fragment) - * + * * Returns: True if loading succeeded, false if it failed. */ - bool loadFromFile(string filename, Type type) + bool loadFromFile(const(char)[] filename, Type type) { import dsfml.system.string; @@ -105,16 +105,16 @@ class Shader if(type == Type.Vertex) { - ret = sfShader_loadFromFile(sfPtr, toStringz(filename) , null); + ret = sfShader_loadFromFile(sfPtr, filename.ptr, filename.length, null, 0); } else { - ret = sfShader_loadFromFile(sfPtr, null , toStringz(filename) ); + ret = sfShader_loadFromFile(sfPtr, null, 0 , filename.ptr, filename.length); } if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; @@ -122,23 +122,24 @@ class Shader /** * Load both the vertex and fragment shaders from files. - * + * * This function loads both the vertex and the fragment shaders. If one of them fails to load, the shader is left empty (the valid shader is unloaded). The sources must be text files containing valid shaders in GLSL language. GLSL is a C-like language dedicated to OpenGL shaders; you'll probably need to read a good documentation for it before writing your own shaders. - * + * * Params: * vertexShaderFilename = Path of the vertex shader file to load * fragmentShaderFilename = Path of the fragment shader file to load - * + * * Returns: True if loading succeeded, false if it failed. */ - bool loadFromFile(string vertexShaderFilename, string fragmentShaderFilename) + bool loadFromFile(const(char)[] vertexShaderFilename, const(char)[] fragmentShaderFilename) { import dsfml.system.string; - bool ret = sfShader_loadFromFile(sfPtr, toStringz(vertexShaderFilename) , toStringz(fragmentShaderFilename)); + bool ret = sfShader_loadFromFile(sfPtr, vertexShaderFilename.ptr, vertexShaderFilename.length, + fragmentShaderFilename.ptr, fragmentShaderFilename.length); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; @@ -146,16 +147,16 @@ class Shader /** * Load either the vertex or fragment shader from a source code in memory. - * + * * This function loads a single shader, either vertex or fragment, identified by the second argument. The source code must be a valid shader in GLSL language. GLSL is a C-like language dedicated to OpenGL shaders; you'll probably need to read a good documentation for it before writing your own shaders. - * + * * Params: * shader = String containing the source code of the shader * type = Type of shader (vertex or fragment) - * + * * Returns: True if loading succeeded, false if it failed. */ - bool loadFromMemory(string shader, Type type) + bool loadFromMemory(const(char)[] shader, Type type) { import dsfml.system.string; @@ -163,52 +164,52 @@ class Shader if(type == Type.Vertex) { - ret = sfShader_loadFromMemory(sfPtr, toStringz(shader) , null); + ret = sfShader_loadFromMemory(sfPtr, shader.ptr, shader.length, null, 0); } else { - ret = sfShader_loadFromMemory(sfPtr, null , toStringz(shader) ); + ret = sfShader_loadFromMemory(sfPtr, null, 0 , shader.ptr, shader.length ); } if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; } - + /** * Load both the vertex and fragment shaders from source codes in memory. - * + * * This function loads both the vertex and the fragment shaders. If one of them fails to load, the shader is left empty (the valid shader is unloaded). The sources must be valid shaders in GLSL language. GLSL is a C-like language dedicated to OpenGL shaders; you'll probably need to read a good documentation for it before writing your own shaders. - * + * * Params: * vertexShader = String containing the source code of the vertex shader * fragmentShader = String containing the source code of the fragment shader - * + * * Returns: True if loading succeeded, false if it failed. */ - bool loadFromMemory(string vertexShader, string fragmentShader) + bool loadFromMemory(const(char)[] vertexShader, const(char)[] fragmentShader) { import dsfml.system.string; - bool ret = sfShader_loadFromMemory(sfPtr, toStringz(vertexShader) , toStringz(fragmentShader)); + bool ret = sfShader_loadFromMemory(sfPtr, vertexShader.ptr, vertexShader.length , fragmentShader.ptr, fragmentShader.length); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; } - + /** * Load either the vertex or fragment shader from a custom stream. - * + * * This function loads a single shader, either vertex or fragment, identified by the second argument. The source code must be a valid shader in GLSL language. GLSL is a C-like language dedicated to OpenGL shaders; you'll probably need to read a good documentation for it before writing your own shaders. - * + * * Params: * stream = Source stream to read from * type = Type of shader (vertex or fragment) - * + * * Returns: True if loading succeeded, false if it failed. */ bool loadFromStream(InputStream stream, Type type) @@ -227,7 +228,7 @@ class Shader } if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; @@ -235,13 +236,13 @@ class Shader /** * Load both the vertex and fragment shaders from custom streams. - * + * * This function loads a single shader, either vertex or fragment, identified by the second argument. The source code must be a valid shader in GLSL language. GLSL is a C-like language dedicated to OpenGL shaders; you'll probably need to read a good documentation for it before writing your own shaders. - * + * * Params: * vertexShaderStream = Source stream to read the vertex shader from * fragmentShaderStream = Source stream to read the fragment shader from - * + * * Returns: True if loading succeeded, false if it failed. */ bool loadFromStream(InputStream vertexShaderStream, InputStream fragmentShaderStream) @@ -251,63 +252,63 @@ class Shader bool ret = sfShader_loadFromStream(sfPtr, new shaderStream(vertexShaderStream), new shaderStream(fragmentShaderStream)); if(!ret) { - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } return ret; } /** * Change a float parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a float (float GLSL type). * x = Value to assign */ - void setParameter(string name, float x) + void setParameter(const(char)[] name, float x) { import dsfml.system.string; - sfShader_setFloatParameter(sfPtr, toStringz(name), x); + sfShader_setFloatParameter(sfPtr, name.ptr, name.length, x); } ///ditto - void opIndexAssign(float x, string name) + void opIndexAssign(float x, const(char)[] name) { import dsfml.system.string; - sfShader_setFloatParameter(sfPtr, toStringz(name), x); + sfShader_setFloatParameter(sfPtr, name.ptr, name.length, x); } /** * Change a 2-components vector parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 2x1 vector (vec2 GLSL type). * x = First component of the value to assign * y = Second component of the value to assign */ - void setParameter(string name, float x, float y) + void setParameter(const(char)[] name, float x, float y) { import dsfml.system.string; - sfShader_setFloat2Parameter(sfPtr, toStringz(name), x, y); + sfShader_setFloat2Parameter(sfPtr, name.ptr, name.length, x, y); } /** * Change a 3-components vector parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 3x1 vector (vec3 GLSL type). * x = First component of the value to assign * y = Second component of the value to assign * z = Third component of the value to assign */ - void setParameter(string name, float x, float y, float z) + void setParameter(const(char)[] name, float x, float y, float z) { import dsfml.system.string; - sfShader_setFloat3Parameter(sfPtr, toStringz(name), x,y,z); + sfShader_setFloat3Parameter(sfPtr, name.ptr, name.length, x,y,z); } /** * Change a 4-components vector parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 4x1 vector (vec4 GLSL type). * x = First component of the value to assign @@ -315,173 +316,173 @@ class Shader * z = Third component of the value to assign * w = Fourth component of the value to assign */ - void setParameter(string name, float x, float y, float z, float w) + void setParameter(const(char)[] name, float x, float y, float z, float w) { import dsfml.system.string; - sfShader_setFloat4Parameter(sfPtr, toStringz(name), x, y, z, w); + sfShader_setFloat4Parameter(sfPtr, name.ptr, name.length, x, y, z, w); } /** * Change variable length vector parameter of the shader. The length of the set of floats must be between 1 and 4. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 4x1 vector (vec4 GLSL type). * val = The set of floats to assign. */ - void opIndexAssign(float[] val, string name) + void opIndexAssign(float[] val, const(char)[] name) { import dsfml.system.string; //assert to make sure that val is of proper length at run time assert((val.length >0) && (val.length <= 4)); if(val.length == 1) - sfShader_setFloatParameter(sfPtr, toStringz(name), val[0]); + sfShader_setFloatParameter(sfPtr, name.ptr, name.length, val[0]); else if(val.length == 2) - sfShader_setFloat2Parameter(sfPtr, toStringz(name), val[0], val[1]); + sfShader_setFloat2Parameter(sfPtr, name.ptr, name.length, val[0], val[1]); else if(val.length == 3) - sfShader_setFloat3Parameter(sfPtr, toStringz(name), val[0], val[1], val[2]); + sfShader_setFloat3Parameter(sfPtr, name.ptr, name.length, val[0], val[1], val[2]); else if(val.length >= 4) - sfShader_setFloat4Parameter(sfPtr, toStringz(name), val[0], val[1], val[2], val[3]); + sfShader_setFloat4Parameter(sfPtr, name.ptr, name.length, val[0], val[1], val[2], val[3]); } /** * Change a 2-components vector parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 2x1 vector (vec2 GLSL type). * vector = Vector to assign */ - void setParameter(string name, Vector2f vector) + void setParameter(const(char)[] name, Vector2f vector) { import dsfml.system.string; - sfShader_setFloat2Parameter(sfPtr, toStringz(name), vector.x, vector.y); + sfShader_setFloat2Parameter(sfPtr, name.ptr, name.length, vector.x, vector.y); } ///ditto - void opIndexAssign(Vector2f vector, string name) + void opIndexAssign(Vector2f vector, const(char)[] name) { import dsfml.system.string; - sfShader_setFloat2Parameter(sfPtr, toStringz(name), vector.x, vector.y); + sfShader_setFloat2Parameter(sfPtr, name.ptr, name.length, vector.x, vector.y); } /** * Change a 3-components vector parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 3x1 vector (vec3 GLSL type). * vector = Vector to assign */ - void setParameter(string name, Vector3f vector) + void setParameter(const(char)[] name, Vector3f vector) { import dsfml.system.string; - sfShader_setFloat3Parameter(sfPtr, toStringz(name), vector.x, vector.y, vector.z); + sfShader_setFloat3Parameter(sfPtr, name.ptr, name.length, vector.x, vector.y, vector.z); } ///ditto - void opIndexAssign(Vector3f vector, string name) + void opIndexAssign(Vector3f vector, const(char)[] name) { import dsfml.system.string; - sfShader_setFloat3Parameter(sfPtr, toStringz(name), vector.x, vector.y, vector.z); + sfShader_setFloat3Parameter(sfPtr, name.ptr, name.length, vector.x, vector.y, vector.z); } /** * Change a color vector parameter of the shader. - * + * * It is important to note that the components of the color are normalized before being passed to the shader. Therefore, they are converted from range [0 .. 255] to range [0 .. 1]. For example, a Color(255, 125, 0, 255) will be transformed to a vec4(1.0, 0.5, 0.0, 1.0) in the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 4x1 vector (vec4 GLSL type). * color = Color to assign */ - void setParameter(string name, Color color) + void setParameter(const(char)[] name, Color color) { import dsfml.system.string; - sfShader_setColorParameter(sfPtr, toStringz(name), color.r, color.g, color.b, color.a); + sfShader_setColorParameter(sfPtr, name.ptr, name.length, color.r, color.g, color.b, color.a); } ///ditto - void opIndexAssign(Color color, string name) + void opIndexAssign(Color color, const(char)[] name) { import dsfml.system.string; - sfShader_setColorParameter(sfPtr, toStringz(name), color.r, color.g, color.b, color.a); + sfShader_setColorParameter(sfPtr, name.ptr, name.length, color.r, color.g, color.b, color.a); } /** * Change a matrix parameter of the shader. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 4x4 matrix (mat4 GLSL type). * transform = Transform to assign */ - void setParameter(string name, Transform transform) + void setParameter(const(char)[] name, Transform transform) { import dsfml.system.string; - sfShader_setTransformParameter(sfPtr, toStringz(name), transform.m_matrix.ptr); + sfShader_setTransformParameter(sfPtr, name.ptr, name.length, transform.m_matrix.ptr); } ///ditto - void opIndexAssign(Transform transform, string name) + void opIndexAssign(Transform transform, const(char)[] name) { import dsfml.system.string; - sfShader_setTransformParameter(sfPtr, toStringz(name), transform.m_matrix.ptr); + sfShader_setTransformParameter(sfPtr, name.ptr, name.length, transform.m_matrix.ptr); } /** * Change a texture parameter of the shader. - * + * * It is important to note that the texture parameter must remain alive as long as the shader uses it - no copoy is made internally. - * + * * To use the texture of the object being draw, which cannot be known in advance, you can pass the special value Shader.CurrentTexture. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 2D texture (sampler2D GLSL type). * texture = Texture to assign */ - void setParameter(string name, const(Texture) texture) + void setParameter(const(char)[] name, const(Texture) texture) { import dsfml.system.string; - sfShader_setTextureParameter(sfPtr, toStringz(name), texture.sfPtr); - err.write(toString(sfErr_getOutput())); + sfShader_setTextureParameter(sfPtr, name.ptr, name.length, texture.sfPtr); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } ///ditto - void opIndexAssign(const(Texture) texture, string name) + void opIndexAssign(const(Texture) texture, const(char)[] name) { import dsfml.system.string; - sfShader_setTextureParameter(sfPtr, toStringz(name), texture.sfPtr); - err.write(toString(sfErr_getOutput())); + sfShader_setTextureParameter(sfPtr, name.ptr, name.length, texture.sfPtr); + err.write(dsfml.system.string.toString(sfErr_getOutput())); } /** * Change a texture parameter of the shader. - * + * * This overload maps a shader texture variable to the texture of the object being drawn, which cannot be known in advance. The second argument must be Shader.CurrentTexture. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 2D texture (sampler2D GLSL type). */ - void setParameter(string name, CurrentTextureType) + void setParameter(const(char)[] name, CurrentTextureType) { import dsfml.system.string; - sfShader_setCurrentTextureParameter(sfPtr, toStringz(name)); + sfShader_setCurrentTextureParameter(sfPtr, name.ptr, name.length); } /** * Change a texture parameter of the shader. - * + * * This overload maps a shader texture variable to the texture of the object being drawn, which cannot be known in advance. The value given must be Shader.CurrentTexture. - * + * * Params: * name = The name of the variable to change in the shader. The corresponding parameter in the shader must be a 2D texture (sampler2D GLSL type). */ - void opIndexAssign(CurrentTextureType, string name) + void opIndexAssign(CurrentTextureType, const(char)[] name) { import dsfml.system.string; - sfShader_setCurrentTextureParameter(sfPtr, toStringz(name)); + sfShader_setCurrentTextureParameter(sfPtr, name.ptr, name.length); } /** * Bind a shader for rendering. - * + * * This function is not part of the graphics API, it mustn't be used when drawing SFML entities. It must be used only if you mix Shader with OpenGL code. - * + * * Params: * shader = Shader to bind. Can be null to use no shader. */ @@ -492,16 +493,16 @@ class Shader /** * Tell whether or not the system supports shaders. - * + * * This function should always be called before using the shader features. If it returns false, then any attempt to use DSFML Shader will fail. - * + * * Returns: True if shaders are supported, false otherwise */ static bool isAvailable() { import dsfml.system.string; bool toReturn = sfShader_isAvailable(); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return toReturn; } } @@ -514,11 +515,11 @@ unittest private extern(C++) interface shaderInputStream { long read(void* data, long size); - + long seek(long position); - + long tell(); - + long getSize(); } @@ -526,27 +527,27 @@ private extern(C++) interface shaderInputStream private class shaderStream:shaderInputStream { private InputStream myStream; - + this(InputStream stream) { myStream = stream; } - + extern(C++)long read(void* data, long size) { return myStream.read(data[0..cast(size_t)size]); } - + extern(C++)long seek(long position) { return myStream.seek(position); } - + extern(C++)long tell() { return myStream.tell(); } - + extern(C++)long getSize() { return myStream.getSize(); @@ -562,10 +563,10 @@ private extern(C): sfShader* sfShader_construct(); //Load both the vertex and fragment shaders from files -bool sfShader_loadFromFile(sfShader* shader, const(char)* vertexShaderFilename, const char* fragmentShaderFilename); +bool sfShader_loadFromFile(sfShader* shader, const(char)* vertexShaderFilename, size_t vertexShaderFilenameLength, const char* fragmentShaderFilename, size_t fragmentShaderFilenameLength); //Load both the vertex and fragment shaders from source codes in memory -bool sfShader_loadFromMemory(sfShader* shader, const(char)* vertexShader, const char* fragmentShader); +bool sfShader_loadFromMemory(sfShader* shader, const(char)* vertexShader, size_t vertexShaderLength, const char* fragmentShader, size_t fragmentShaderLength); //Load both the vertex and fragment shaders from custom streams bool sfShader_loadFromStream(sfShader* shader, shaderInputStream vertexShaderStream, shaderInputStream fragmentShaderStream); @@ -574,28 +575,28 @@ bool sfShader_loadFromStream(sfShader* shader, shaderInputStream vertexShaderStr void sfShader_destroy(sfShader* shader); //Change a float parameter of a shader -void sfShader_setFloatParameter(sfShader* shader, const char* name, float x); +void sfShader_setFloatParameter(sfShader* shader, const char* name, size_t length, float x); //Change a 2-components vector parameter of a shader -void sfShader_setFloat2Parameter(sfShader* shader, const char* name, float x, float y); +void sfShader_setFloat2Parameter(sfShader* shader, const char* name, size_t length, float x, float y); //Change a 3-components vector parameter of a shader -void sfShader_setFloat3Parameter(sfShader* shader, const char* name, float x, float y, float z); +void sfShader_setFloat3Parameter(sfShader* shader, const char* name, size_t length, float x, float y, float z); //Change a 4-components vector parameter of a shader -void sfShader_setFloat4Parameter(sfShader* shader, const char* name, float x, float y, float z, float w); +void sfShader_setFloat4Parameter(sfShader* shader, const char* name, size_t length, float x, float y, float z, float w); //Change a color parameter of a shader -void sfShader_setColorParameter(sfShader* shader, const char* name, ubyte r, ubyte g, ubyte b, ubyte a); +void sfShader_setColorParameter(sfShader* shader, const char* name, size_t length, ubyte r, ubyte g, ubyte b, ubyte a); //Change a matrix parameter of a shader -void sfShader_setTransformParameter(sfShader* shader, const char* name, float* transform); +void sfShader_setTransformParameter(sfShader* shader, const char* name, size_t length, float* transform); //Change a texture parameter of a shader -void sfShader_setTextureParameter(sfShader* shader, const char* name, const sfTexture* texture); +void sfShader_setTextureParameter(sfShader* shader, const char* name, size_t length, const sfTexture* texture); //Change a texture parameter of a shader -void sfShader_setCurrentTextureParameter(sfShader* shader, const char* name); +void sfShader_setCurrentTextureParameter(sfShader* shader, const char* name, size_t length); //Bind a shader for rendering (activate it) void sfShader_bind(const sfShader* shader); diff --git a/src/dsfml/graphics/sprite.d b/src/dsfml/graphics/sprite.d index 4bb7acc..ab3092d 100644 --- a/src/dsfml/graphics/sprite.d +++ b/src/dsfml/graphics/sprite.d @@ -32,20 +32,21 @@ import dsfml.graphics.renderstates; import dsfml.graphics.primitivetype; import dsfml.system.vector2; +import std.typecons:Rebindable; /++ + Drawable representation of a texture, with its own transformations, color, etc. - + + + + Sprite is a drawable class that allows to easily display a texture (or a part of it) on a render target. - + + + + It inherits all the functions from Transformable: position, rotation, scale, origin. It also adds sprite-specific properties such as the texture to use, the part of it to display, and some convenience functions to change the overall color of the sprite, or to get its bounding rectangle. - + + + + Sprite works in combination with the Texture class, which loads and provides the pixel data of a given texture. - + + + + The separation of Sprite and Texture allows more flexibility and better performances: indeed a Texture is a heavy resource, and any operation on it is slow (often too slow for real-time applications). On the other side, a Sprite is a lightweight object which can use the pixel data of a Texture and draw it with its own transformation/color/blending attributes. - + + + + It is important to note that the Sprite instance doesn't copy the texture that it uses, it only keeps a reference to it. Thus, a Texture must not be destroyed while it is used by a Sprite (i.e. never write a function that uses a local Texture instance for creating a sprite). - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://sfml-dev.org/documentation/2.0/classsf_1_1Sprite.php#details +/ @@ -66,7 +67,7 @@ class Sprite : Drawable, Transformable m_texture = null; m_textureRect = IntRect(); } - + this(const(Texture) texture) { // Constructor code @@ -82,7 +83,7 @@ class Sprite : Drawable, Transformable /** * The sub-rectangle of the texture that the sprite will display. - * + * * The texture rect is useful when you don't want to display the whole texture, but rather a part of it. By default, the texture rect covers the entire texture. */ @property @@ -105,7 +106,7 @@ class Sprite : Drawable, Transformable /** * The global color of the sprite. - * + * * This color is modulated (multiplied) with the sprite's texture. It can be used to colorize the sprite, or change its global opacity. By default, the sprite's color is opaque white. */ @property @@ -123,14 +124,14 @@ class Sprite : Drawable, Transformable { return m_vertices[0].color; } - + } /** * Get the global bounding rectangle of the entity. - * + * * The returned rectangle is in global coordinates, which means that it takes in account the transformations (translation, rotation, scale, ...) that are applied to the entity. In other words, this function returns the bounds of the sprite in the global 2D world's coordinate system. - * + * * Returns: Global bounding rectangle of the entity */ FloatRect getGlobalBounds() @@ -140,9 +141,9 @@ class Sprite : Drawable, Transformable /** * Get the local bounding rectangle of the entity. - * + * * The returned rectangle is in local coordinates, which means that it ignores the transformations (translation, rotation, scale, ...) that are applied to the entity. In other words, this function returns the bounds of the entity in the entity's coordinate system. - * + * * Returns: Local bounding rectangle of the entity */ FloatRect getLocalBounds() @@ -154,9 +155,9 @@ class Sprite : Drawable, Transformable /** * Get the source texture of the sprite. - * + * * If the sprite has no source texture, a NULL pointer is returned. The returned pointer is const, which means that you can't modify the texture when you retrieve it with this function. - * + * * Returns: The sprite's texture */ const(Texture) getTexture() @@ -166,11 +167,11 @@ class Sprite : Drawable, Transformable /** * Change the source texture of the shape. - * + * * The texture argument refers to a texture that must exist as long as the sprite uses it. Indeed, the sprite doesn't store its own copy of the texture, but rather keeps a pointer to the one that you passed to this function. If the source texture is destroyed and the sprite tries to use it, the behaviour is undefined. texture can be NULL to disable texturing. - * + * * If resetRect is true, the TextureRect property of the sprite is automatically adjusted to the size of the new texture. If it is false, the texture rect is left unchanged. - * + * * Params: * texture = New texture * resetRect = Should the texture rect be reset to the size of the new texture? @@ -181,13 +182,13 @@ class Sprite : Drawable, Transformable { textureRect(IntRect(0,0,texture.getSize().x,texture.getSize().y)); } - + m_texture = texture; } /** * Draw the sprite to a render target. - * + * * Params: * renderTarget = Target to draw to * renderStates = Current render states @@ -204,7 +205,7 @@ class Sprite : Drawable, Transformable /** * Create a new Sprite with the same data. Note that the texture is not copied, only its reference. - * + * * Returns: A new Sprite object with the same data. */ @property @@ -227,7 +228,7 @@ class Sprite : Drawable, Transformable void updatePositions() { FloatRect bounds = getLocalBounds(); - + m_vertices[0].position = Vector2f(0, 0); m_vertices[1].position = Vector2f(0, bounds.height); m_vertices[2].position = Vector2f(bounds.width, bounds.height); @@ -240,7 +241,7 @@ class Sprite : Drawable, Transformable float right = left + m_textureRect.width; float top = (m_textureRect.top); float bottom = top + m_textureRect.height; - + m_vertices[0].texCoords = Vector2f(left, top); m_vertices[1].texCoords = Vector2f(left, bottom); m_vertices[2].texCoords = Vector2f(right, bottom); diff --git a/src/dsfml/graphics/text.d b/src/dsfml/graphics/text.d index 561ea59..b72f283 100644 --- a/src/dsfml/graphics/text.d +++ b/src/dsfml/graphics/text.d @@ -34,19 +34,21 @@ import dsfml.graphics.primitivetype; import dsfml.system.vector2; +import std.typecons:Rebindable; + /++ + Graphical text that can be drawn to a render target. - + + + + Text is a drawable class that allows to easily display some text with custom style and color on a render target. - + + + + It inherits all the functions from Transformable: position, rotation, scale, origin. It also adds text-specific properties such as the font to use, the character size, the font style (bold, italic, underlined), the global color and the text to display of course. It also provides convenience functions to calculate the graphical size of the text, or to get the global position of a given character. - + + + + Text works in combination with the Font class, which loads and provides the glyphs (visual characters) of a given font. - + + + + The separation of Font and Text allows more flexibility and better performances: indeed a Font is a heavy resource, and any operation on it is slow (often too slow for real-time applications). On the other side, a Text is a lightweight object which can combine the glyphs data and metrics of a Font to display any text on a render target. - + + + + It is important to note that the Text instance doesn't copy the font that it uses, it only keeps a reference to it. Thus, a Font must not be destructed while it is used by a Text (i.e. never write a function that uses a local Font instance for creating a text). - + + + + Authors: Laurent Gomila, Jeremy DeHaan + See_Also: http://sfml-dev.org/documentation/2.0/classsf_1_1Text.php#details +/ @@ -87,7 +89,7 @@ class Text : Drawable, Transformable m_vertices = new VertexArray(PrimitiveType.Quads,0); m_bounds = FloatRect(); } - + this(T)(immutable(T)[] text, const(Font) font, uint characterSize = 30) if (is(T == dchar)||is(T == wchar)||is(T == char)) { @@ -111,7 +113,7 @@ class Text : Drawable, Transformable /** * Get the character size. - * + * * Returns: Size of the characters, in pixels. */ uint getCharacterSize() const @@ -121,7 +123,7 @@ class Text : Drawable, Transformable /** * Get the global color of the text. - * + * * Returns: Global color of the text. */ Color getColor() const @@ -131,9 +133,9 @@ class Text : Drawable, Transformable /** * Get thet text's font. - * + * * If the text has no font attached, a NULL pointer is returned. The returned reference is const, which means that you cannot modify the font when you get it from this function. - * + * * Returns: Text's font. */ const(Font) getFont() const @@ -150,9 +152,9 @@ class Text : Drawable, Transformable /** * Get the global bounding rectangle of the entity. - * + * * The returned rectangle is in global coordinates, which means that it takes in account the transformations (translation, rotation, scale, ...) that are applied to the entity. In other words, this function returns the bounds of the sprite in the global 2D world's coordinate system. - * + * * Returns: Global bounding rectangle of the entity. */ FloatRect getGlobalBounds() @@ -162,9 +164,9 @@ class Text : Drawable, Transformable /** * Get the local bounding rectangle of the entity. - * + * * The returned rectangle is in local coordinates, which means that it ignores the transformations (translation, rotation, scale, ...) that are applied to the entity. In other words, this function returns the bounds of the entity in the entity's coordinate system. - * + * * Returns: Local bounding rectangle of the entity. */ FloatRect getLocalBounds() const @@ -175,7 +177,7 @@ class Text : Drawable, Transformable //TODO: maybe a getString!dstring or getString!wstring etc template would be appropriate? /** * Get the text's string. - * + * * The returned string is a dstring, a unicode type. */ immutable(T)[] getString(T=char)() const @@ -187,7 +189,7 @@ class Text : Drawable, Transformable /** * Get the text's style. - * + * * Returns: Text's style. */ Style getStyle() const @@ -197,9 +199,9 @@ class Text : Drawable, Transformable /** * Set the character size. - * + * * The default size is 30. - * + * * Params: * size = New character size, in pixels. */ @@ -211,9 +213,9 @@ class Text : Drawable, Transformable /** * Set the global color of the text. - * + * * By default, the text's color is opaque white. - * + * * Params: * color = New color of the text. */ @@ -225,9 +227,9 @@ class Text : Drawable, Transformable /** * Set the text's font. - * + * * The font argument refers to a font that must exist as long as the text uses it. Indeed, the text doesn't store its own copy of the font, but rather keeps a pointer to the one that you passed to this function. If the font is destroyed and the text tries to use it, the behaviour is undefined. - * + * * Params: * font = New font */ @@ -239,9 +241,9 @@ class Text : Drawable, Transformable /** * Set the text's string. - * + * * A text's string is empty by default. - * + * * Params: * text = New string */ @@ -256,7 +258,7 @@ class Text : Drawable, Transformable //TODO: Does doing binary operations on Styles like the docs suggest actually work? /** * Set the text's style. - * + * * You can pass a combination of one or more styles, for example Style.Bold | Text.Italic. */ void setStyle(Style style) @@ -267,7 +269,7 @@ class Text : Drawable, Transformable /** * Draw the object to a render target. - * + * * Params: * renderTarget = Render target to draw to * renderStates = Current render states @@ -275,11 +277,11 @@ class Text : Drawable, Transformable void draw(RenderTarget renderTarget, RenderStates renderStates) { import std.stdio; - + if ((m_font !is null) && (m_characterSize>0)) { renderStates.transform *= getTransform(); - + //only call getTexture if the size has changed if(m_characterSize != lastSizeUsed) { @@ -288,18 +290,18 @@ class Text : Drawable, Transformable //grab the new texture lastTextureUsed = m_font.getTexture(m_characterSize); } - + //writeln("Update Geometry"); updateGeometry(); - + //writeln("Setting renderstates tecture"); renderStates.texture = m_font.getTexture(m_characterSize); - + if(renderStates.texture is null) { //writeln("Texture don't exist!"); } - + //writeln("Trying to draw!"); renderTarget.draw(m_vertices, renderStates); } @@ -307,12 +309,12 @@ class Text : Drawable, Transformable /** * Return the position of the index-th character. - * + * * This function computes the visual position of a character from its index in the string. The returned position is in global coordinates (translation, rotation, scale and origin are applied). If index is out of range, the position of the end of the string is returned. - * + * * Params: * index = Index of the character - * + * * Returns: Position of the character. */ Vector2f findCharacterPos(size_t index) @@ -322,7 +324,7 @@ class Text : Drawable, Transformable { return Vector2f(0,0); } - + // Adjust the index if it's out of range if(index > m_string.length) { @@ -333,17 +335,17 @@ class Text : Drawable, Transformable float hspace = cast(float)(m_font.getGlyph(' ', m_characterSize, bold).advance); float vspace = cast(float)(m_font.getLineSpacing(m_characterSize)); - + Vector2f position; dchar prevChar = 0; for (size_t i = 0; i < index; ++i) { dchar curChar = m_string[i]; - + // Apply the kerning offset position.x += cast(float)(m_font.getKerning(prevChar, curChar, m_characterSize)); prevChar = curChar; - + // Handle special characters switch (curChar) { @@ -354,14 +356,14 @@ class Text : Drawable, Transformable default: break; } - + // For regular characters, add the advance offset of the glyph position.x += cast(float)(m_font.getGlyph(curChar, m_characterSize, bold).advance); } - + // Transform the position to global coordinates position = getTransform().transformPoint(position); - + return position; } @@ -373,7 +375,7 @@ private: // Clear the previous geometry m_vertices.clear(); m_bounds = FloatRect(); - + // No font: nothing to draw if (m_font is null) return; @@ -387,13 +389,13 @@ private: float italic = (m_style & Style.Italic) ? 0.208f : 0f; // 12 degrees float underlineOffset = m_characterSize * 0.1f; float underlineThickness = m_characterSize * (bold ? 0.1f : 0.07f); - + // Precompute the variables needed by the algorithm float hspace = cast(float)(m_font.getGlyph(' ', m_characterSize, bold).advance); float vspace = cast(float)(m_font.getLineSpacing(m_characterSize)); float x = 0f; float y = cast(float)(m_characterSize); - + // Create one quad for each character float minX = m_characterSize, minY = m_characterSize, maxX = 0, maxY = 0; dchar prevChar = 0; @@ -401,7 +403,7 @@ private: { dchar curChar = m_string[i]; - + // Apply the kerning offset x += cast(float)(m_font.getKerning(prevChar, curChar, m_characterSize)); @@ -412,20 +414,20 @@ private: { float top = y + underlineOffset; float bottom = top + underlineThickness; - + m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); } - + // Handle special characters if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n') || (curChar == '\v')) { // Update the current bounds (min coordinates) minX = min(minX, x); minY = min(minY, y); - + final switch (curChar) { case ' ' : x += hspace; break; @@ -433,11 +435,11 @@ private: case '\n' : y += vspace; x = 0; break; case '\v' : y += vspace * 4; break; } - + // Update the current bounds (max coordinates) maxX = max(maxX, x); maxY = max(maxY, y); - + // Next glyph, no need to create a quad for whitespace continue; } @@ -446,17 +448,17 @@ private: // Extract the current glyph's description Glyph glyph = m_font.getGlyph(curChar, m_characterSize, bold); - - int left = glyph.bounds.left; - int top = glyph.bounds.top; - int right = glyph.bounds.left + glyph.bounds.width; - int bottom = glyph.bounds.top + glyph.bounds.height; - + + float left = glyph.bounds.left; + float top = glyph.bounds.top; + float right = glyph.bounds.left + glyph.bounds.width; + float bottom = glyph.bounds.top + glyph.bounds.height; + float u1 = cast(float)(glyph.textureRect.left); float v1 = cast(float)(glyph.textureRect.top); float u2 = cast(float)(glyph.textureRect.left + glyph.textureRect.width); float v2 = cast(float)(glyph.textureRect.top + glyph.textureRect.height); - + // Add a quad for the current character m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1))); m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1))); @@ -472,19 +474,19 @@ private: // Advance to the next character x += glyph.advance; } - + // If we're using the underlined style, add the last line if (underlined) { float top = y + underlineOffset; float bottom = top + underlineThickness; - + m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); } - + // Update the bounding rectangle m_bounds.left = minX; m_bounds.top = minY; @@ -503,7 +505,7 @@ unittest writeln("Unit test for Text"); auto renderTexture = new RenderTexture(); - + renderTexture.create(100,100); auto font = new Font(); diff --git a/src/dsfml/graphics/texture.d b/src/dsfml/graphics/texture.d index 606a768..df58533 100644 --- a/src/dsfml/graphics/texture.d +++ b/src/dsfml/graphics/texture.d @@ -1,522 +1,522 @@ -/* -DSFML - The Simple and Fast Multimedia Library for D - -Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com) - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial applications, -and to alter it and redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. -If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source distribution -*/ - -module dsfml.graphics.texture; - - -import dsfml.graphics.rect; -import dsfml.graphics.image; -import dsfml.graphics.renderwindow; - -import dsfml.window.window; - -import dsfml.system.inputstream; -import dsfml.system.vector2; -import dsfml.system.err; - -/++ - + Image living on the graphics card that can be used for drawing. - + - + Texture stores pixels that can be drawn, with a sprite for example. - + - + A texture lives in the graphics card memory, therefore it is very fast to draw a texture to a render target, or copy a render target to a texture (the graphics card can access both directly). - + - + Being stored in the graphics card memory has some drawbacks. A texture cannot be manipulated as freely as a Image, you need to prepare the pixels first and then upload them to the texture in a single operation (see Texture::update). - + - + Texture makes it easy to convert from/to Image, but keep in mind that these calls require transfers between the graphics card and the central memory, therefore they are slow operations. - + - + A texture can be loaded from an image, but also directly from a file/memory/stream. The necessary shortcuts are defined so that you don't need an image first for the most common cases. However, if you want to perform some modifications on the pixels before creating the final texture, you can load your file to a Image, do whatever you need with the pixels, and then call Texture::loadFromImage. - + - + Since they live in the graphics card memory, the pixels of a texture cannot be accessed without a slow copy first. And they cannot be accessed individually. Therefore, if you need to read the texture's pixels (like for pixel-perfect collisions), it is recommended to store the collision information separately, for example in an array of booleans. - + - + Like Image, Texture can handle a unique internal representation of pixels, which is RGBA 32 bits. This means that a pixel must be composed of 8 bits red, green, blue and alpha channels – just like a Color. - + - + Authors: Laurent Gomila, Jeremy DeHaan - + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1Texture.php#details - +/ -class Texture -{ - package sfTexture* sfPtr; - - this() - { - sfPtr = sfTexture_construct(); - } - - package this(sfTexture* texturePointer) - { - sfPtr = texturePointer; - } - - ~this() - { - import dsfml.system.config; - mixin(destructorOutput); - sfTexture_destroy( sfPtr); - } - - /** - * Load the texture from a file on disk. - * - * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. - * - * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. - * - * If this function fails, the texture is left unchanged. - * - * Params: - * filename = Path of the image file to load - * area = Area of the image to load - * - * Returns: True if loading was successful, false otherwise. - */ - bool loadFromFile(string filename, IntRect area = IntRect() ) - { - import dsfml.system.string; - - bool ret = sfTexture_loadFromFile(sfPtr, toStringz(filename) ,area.left, area.top,area.width, area.height); - if(!ret) - { - err.write(toString(sfErr_getOutput())); - } - - return ret; - } - - //TODO: Can this be done with a slice of bytes rather than a const(void)*? - /** - * Load the texture from a file in memory. - * - * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. - * - * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. - * - * If this function fails, the texture is left unchanged. - * - * Params: - * data = Image in memory - * size = Size of the data to load, in bytes. - * area = Area of the image to load - * - * Returns: True if loading was successful, false otherwise. - */ - bool loadFromMemory(const(void)[] data, IntRect area = IntRect()) - { - import dsfml.system.string; - - - bool ret = sfTexture_loadFromMemory(sfPtr, data.ptr, data.length,area.left, area.top,area.width, area.height); - if(!ret) - { - err.write(toString(sfErr_getOutput())); - } - - return ret; - } - - /** - * Load the texture from a custom stream. - * - * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. - * - * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. - * - * If this function fails, the texture is left unchanged. - * - * Params: - * stream = Source stream to read from - * area = Area of the image to load - * - * Returns: True if loading was successful, false otherwise. - */ - bool loadFromStream(InputStream stream, IntRect area = IntRect()) - { - import dsfml.system.string; - - bool ret = sfTexture_loadFromStream(sfPtr, new textureStream(stream), area.left, area.top,area.width, area.height); - if(!ret) - { - err.write(toString(sfErr_getOutput())); - } - - return ret; - } - - /** - * Load the texture from an image. - * - * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. - * - * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. - * - * If this function fails, the texture is left unchanged. - * - * Params: - * image = Image to load into the texture - * area = Area of the image to load - * - * Returns: True if loading was successful, false otherwise. - */ - bool loadFromImage(Image image, IntRect area = IntRect()) - { - import dsfml.system.string; - - bool ret = sfTexture_loadFromImage(sfPtr, image.sfPtr, area.left, area.top,area.width, area.height); - if(!ret) - { - err.write(toString(sfErr_getOutput())); - } - - return ret; - } - - /** - * Get the maximum texture size allowed. - * - * This Maximum size is defined by the graphics driver. You can expect a value of 512 pixels for low-end graphics card, and up to 8192 pixels or more for newer hardware. - * - * Returns: Maximum size allowed for textures, in pixels. - */ - static uint getMaximumSize() - { - return sfTexture_getMaximumSize(); - } - - /** - * Return the size of the texture. - * - * Returns: Size in pixels. - */ - Vector2u getSize() const - { - Vector2u temp; - sfTexture_getSize(sfPtr, &temp.x, &temp.y); - return temp; - } - - /** - * Enable or disable the smooth filter. - * - * When the filter is activated, the texture appears smoother so that pixels are less noticeable. However if you want the texture to look exactly the same as its source file, you should leave it disabled. The smooth filter is disabled by default. - * - * Params: - * smooth = True to enable smoothing, false to disable it. - */ - void setSmooth(bool smooth) - { - sfTexture_setSmooth(sfPtr, smooth);//:sfTexture_setSmooth(sfPtr, sfFalse); - } - - /** - * Enable or disable repeating. - * - * Repeating is involved when using texture coordinates outside the texture rectangle [0, 0, width, height]. In this case, if repeat mode is enabled, the whole texture will be repeated as many times as needed to reach the coordinate (for example, if the X texture coordinate is 3 * width, the texture will be repeated 3 times). - * - * If repeat mode is disabled, the "extra space" will instead be filled with border pixels. Warning: on very old graphics cards, white pixels may appear when the texture is repeated. With such cards, repeat mode can be used reliably only if the texture has power-of-two dimensions (such as 256x128). Repeating is disabled by default. - * - * Params: - * repeated = True to repeat the texture, false to disable repeating - */ - void setRepeated(bool repeated) - { - sfTexture_setRepeated(sfPtr, repeated);//:sfTexture_setRepeated(sfPtr, sfFalse); - } - - /** - * Bind a texture for rendering. - * - * This function is not part of the graphics API, it mustn't be used when drawing SFML entities. It must be used only if you mix Texture with OpenGL code. - * - * Params: - * texture = The texture to bind. Can be null to use no texture. - */ - static void bind(Texture texture) - { - (texture is null)?sfTexture_bind(null):sfTexture_bind(texture.sfPtr); - } - - /** - * Create the texture. - * - * If this function fails, the texture is left unchanged. - * - * Params: - * width = Width of the texture - * height = Height of the texture - * - * Returns: True if creation was successful, false otherwise. - */ - bool create(uint width, uint height) - { - import dsfml.system.string; - - bool ret = sfTexture_create(sfPtr, width, height); - if(!ret) - { - err.write(toString(sfErr_getOutput())); - } - - return ret; - } - - /** - * Copy the texture pixels to an image. - * - * This function performs a slow operation that downloads the texture's pixels from the graphics card and copies them to a new image, potentially applying transformations to pixels if necessary (texture may be padded or flipped). - * - * Returns: Image containing the texture's pixels. - */ - Image copyToImage() const - { - return new Image(sfTexture_copyToImage(sfPtr)); - } - - /** - * Creates a new texture from the same data (this means copying the entire set of pixels). - * - * Returns: New texture data. - */ - @property - Texture dup() const - { - return new Texture(sfTexture_copy(sfPtr)); - } - - /** - * Tell whether the texture is repeated or not. - * - * Returns: True if repeat mode is enabled, false if it is disabled. - */ - bool isRepeated() const - { - return (sfTexture_isRepeated(sfPtr));// == sfTrue)?true:false; - } - - /** - * Tell whether the smooth filter is enabled or not. - * - * Returns: True if something is enabled, false if it is disabled. - */ - bool isSmooth() const - { - return (sfTexture_isSmooth(sfPtr));// == sfTrue)?true:false; - } - - /** - * Update the texture from an image. - * - * Although the source image can be smaller than the texture, this function is usually used for updating the whole texture. The other overload, which has (x, y) additional arguments, is more convenient for updating a sub-area of the texture. - * - * No additional check is performed on the size of the image, passing an image bigger than the texture will lead to an undefined behaviour. - * - * This function does nothing if the texture was not previously created. - * - * Params: - * image = Image to copy to the texture. - */ - void updateFromImage(Image image, uint x, uint y) - { - sfTexture_updateFromImage(sfPtr, image.sfPtr, x, y); - } - - /** - * Update part of the texture from an array of pixels. - * - * The size of the pixel array must match the width and height arguments, and it must contain 32-bits RGBA pixels. - * - * No additional check is performed on the size of the pixel array or the bounds of the area to update, passing invalid arguments will lead to an undefined behaviour. - * - * This function does nothing if pixels is null or if the texture was not previously created. - * - * Params: - * pixels = Array of pixels to copy to the texture. - * width = Width of the pixel region contained in pixels - * height = Height of the pixel region contained in pixels - * x = X offset in the texture where to copy the source pixels - * y = Y offset in the texture where to copy the source pixels - */ - void updateFromPixels(const(ubyte)[] pixels, uint width, uint height, uint x, uint y) - { - sfTexture_updateFromPixels(sfPtr,pixels.ptr,width, height, x,y); - } - - //TODO: Get this working via inheritance?(so custom window classes can do it too) - /** - * Update a part of the texture from the contents of a window. - * - * No additional check is performed on the size of the window, passing an invalid combination of window size and offset will lead to an undefined behaviour. - * - * This function does nothing if either the texture or the window was not previously created. - * - * Params: - * window = Window to copy to the texture - * x = X offset in the texture where to copy the source window - * y = Y offset in the texture where to copy the source window - */ - void updateFromWindow(Window window, uint x, uint y) - { - sfTexture_updateFromWindow(sfPtr, RenderWindow.windowPointer(window), x, y); - } - - //Is this even safe? RenderWindow inherits from Window, so what happens? Is this bottom used or the top? - /** - * Update a part of the texture from the contents of a window. - * - * No additional check is performed on the size of the window, passing an invalid combination of window size and offset will lead to an undefined behaviour. - * - * This function does nothing if either the texture or the window was not previously created. - * - * Params: - * window = Window to copy to the texture - * x = X offset in the texture where to copy the source window - * y = Y offset in the texture where to copy the source window - */ - void updateFromWindow(RenderWindow window, uint x, uint y) - { - sfTexture_updateFromRenderWindow(sfPtr, window.sfPtr, x, y); - } -} - -unittest -{ - version(DSFML_Unittest_Graphics) - { - import std.stdio; - - writeln("Unit test for Texture"); - - auto texture = new Texture(); - - assert(texture.loadFromFile("res/TestImage.png")); - - //do things with the texture - - writeln(); - } -} - -private extern(C++) interface textureInputStream -{ - long read(void* data, long size); - - long seek(long position); - - long tell(); - - long getSize(); -} - - -private class textureStream:textureInputStream -{ - private InputStream myStream; - - this(InputStream stream) - { - myStream = stream; - } - - extern(C++)long read(void* data, long size) - { - return myStream.read(data[0..cast(size_t)size]); - } - - extern(C++)long seek(long position) - { - return myStream.seek(position); - } - - extern(C++)long tell() - { - return myStream.tell(); - } - - extern(C++)long getSize() - { - return myStream.getSize(); - } -} - - - -package extern(C) struct sfTexture; - -private extern(C): - -//Construct a new texture -sfTexture* sfTexture_construct(); - -//Create a new texture -bool sfTexture_create(sfTexture* texture, uint width, uint height); - -//Create a new texture from a file -bool sfTexture_loadFromFile(sfTexture* texture, const(char)* filename, int left, int top, int width, int height); - -//Create a new texture from a file in memory -bool sfTexture_loadFromMemory(sfTexture* texture, const(void)* data, size_t sizeInBytes, int left, int top, int width, int height); - -//Create a new texture from a custom stream -bool sfTexture_loadFromStream(sfTexture* texture, textureInputStream stream, int left, int top, int width, int height); - -//Create a new texture from an image -bool sfTexture_loadFromImage(sfTexture* texture, const(sfImage)* image, int left, int top, int width, int height); - -//Copy an existing texture -sfTexture* sfTexture_copy(const(sfTexture)* texture); - -//Destroy an existing texture -void sfTexture_destroy(sfTexture* texture); - -//Return the size of the texture -void sfTexture_getSize(const(sfTexture)* texture, uint* x, uint* y); - -//Copy a texture's pixels to an image -sfImage* sfTexture_copyToImage(const sfTexture* texture); - -//Update a texture from an array of pixels -void sfTexture_updateFromPixels(sfTexture* texture, const ubyte* pixels, uint width, uint height, uint x, uint y); - -//Update a texture from an image -void sfTexture_updateFromImage(sfTexture* texture, const sfImage* image, uint x, uint y); - -//Update a texture from the contents of a window -void sfTexture_updateFromWindow(sfTexture* texture, const(void)* window, uint x, uint y); - -//Update a texture from the contents of a render-window -void sfTexture_updateFromRenderWindow(sfTexture* texture, const sfRenderWindow* renderWindow, uint x, uint y); - -//Enable or disable the smooth filter on a texture -void sfTexture_setSmooth(sfTexture* texture, bool smooth); - -//Tell whether the smooth filter is enabled or not for a texture -bool sfTexture_isSmooth(const sfTexture* texture); - -//Enable or disable repeating for a texture -void sfTexture_setRepeated(sfTexture* texture, bool repeated); - -//Tell whether a texture is repeated or not -bool sfTexture_isRepeated(const sfTexture* texture); - -//Bind a texture for rendering -void sfTexture_bind(const sfTexture* texture); - -//Get the maximum texture size allowed -uint sfTexture_getMaximumSize(); - -const(char)* sfErr_getOutput(); +/* +DSFML - The Simple and Fast Multimedia Library for D + +Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com) + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution +*/ + +module dsfml.graphics.texture; + + +import dsfml.graphics.rect; +import dsfml.graphics.image; +import dsfml.graphics.renderwindow; + +import dsfml.window.window; + +import dsfml.system.inputstream; +import dsfml.system.vector2; +import dsfml.system.err; + +/++ + + Image living on the graphics card that can be used for drawing. + + + + Texture stores pixels that can be drawn, with a sprite for example. + + + + A texture lives in the graphics card memory, therefore it is very fast to draw a texture to a render target, or copy a render target to a texture (the graphics card can access both directly). + + + + Being stored in the graphics card memory has some drawbacks. A texture cannot be manipulated as freely as a Image, you need to prepare the pixels first and then upload them to the texture in a single operation (see Texture::update). + + + + Texture makes it easy to convert from/to Image, but keep in mind that these calls require transfers between the graphics card and the central memory, therefore they are slow operations. + + + + A texture can be loaded from an image, but also directly from a file/memory/stream. The necessary shortcuts are defined so that you don't need an image first for the most common cases. However, if you want to perform some modifications on the pixels before creating the final texture, you can load your file to a Image, do whatever you need with the pixels, and then call Texture::loadFromImage. + + + + Since they live in the graphics card memory, the pixels of a texture cannot be accessed without a slow copy first. And they cannot be accessed individually. Therefore, if you need to read the texture's pixels (like for pixel-perfect collisions), it is recommended to store the collision information separately, for example in an array of booleans. + + + + Like Image, Texture can handle a unique internal representation of pixels, which is RGBA 32 bits. This means that a pixel must be composed of 8 bits red, green, blue and alpha channels – just like a Color. + + + + Authors: Laurent Gomila, Jeremy DeHaan + + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1Texture.php#details + +/ +class Texture +{ + package sfTexture* sfPtr; + + this() + { + sfPtr = sfTexture_construct(); + } + + package this(sfTexture* texturePointer) + { + sfPtr = texturePointer; + } + + ~this() + { + import dsfml.system.config; + mixin(destructorOutput); + sfTexture_destroy( sfPtr); + } + + /** + * Load the texture from a file on disk. + * + * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. + * + * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. + * + * If this function fails, the texture is left unchanged. + * + * Params: + * filename = Path of the image file to load + * area = Area of the image to load + * + * Returns: True if loading was successful, false otherwise. + */ + bool loadFromFile(const(char)[] filename, IntRect area = IntRect() ) + { + import dsfml.system.string; + + bool ret = sfTexture_loadFromFile(sfPtr, filename.ptr, filename.length,area.left, area.top,area.width, area.height); + if(!ret) + { + err.write(dsfml.system.string.toString(sfErr_getOutput())); + } + + return ret; + } + + //TODO: Can this be done with a slice of bytes rather than a const(void)*? + /** + * Load the texture from a file in memory. + * + * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. + * + * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. + * + * If this function fails, the texture is left unchanged. + * + * Params: + * data = Image in memory + * size = Size of the data to load, in bytes. + * area = Area of the image to load + * + * Returns: True if loading was successful, false otherwise. + */ + bool loadFromMemory(const(void)[] data, IntRect area = IntRect()) + { + import dsfml.system.string; + + + bool ret = sfTexture_loadFromMemory(sfPtr, data.ptr, data.length,area.left, area.top,area.width, area.height); + if(!ret) + { + err.write(dsfml.system.string.toString(sfErr_getOutput())); + } + + return ret; + } + + /** + * Load the texture from a custom stream. + * + * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. + * + * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. + * + * If this function fails, the texture is left unchanged. + * + * Params: + * stream = Source stream to read from + * area = Area of the image to load + * + * Returns: True if loading was successful, false otherwise. + */ + bool loadFromStream(InputStream stream, IntRect area = IntRect()) + { + import dsfml.system.string; + + bool ret = sfTexture_loadFromStream(sfPtr, new textureStream(stream), area.left, area.top,area.width, area.height); + if(!ret) + { + err.write(dsfml.system.string.toString(sfErr_getOutput())); + } + + return ret; + } + + /** + * Load the texture from an image. + * + * The area argument can be used to load only a sub-rectangle of the whole image. If you want the entire image then leave the default value (which is an empty IntRect). If the area rectangle crosses the bounds of the image, it is adjusted to fit the image size. + * + * The maximum size for a texture depends on the graphics driver and can be retrieved with the getMaximumSize function. + * + * If this function fails, the texture is left unchanged. + * + * Params: + * image = Image to load into the texture + * area = Area of the image to load + * + * Returns: True if loading was successful, false otherwise. + */ + bool loadFromImage(Image image, IntRect area = IntRect()) + { + import dsfml.system.string; + + bool ret = sfTexture_loadFromImage(sfPtr, image.sfPtr, area.left, area.top,area.width, area.height); + if(!ret) + { + err.write(dsfml.system.string.toString(sfErr_getOutput())); + } + + return ret; + } + + /** + * Get the maximum texture size allowed. + * + * This Maximum size is defined by the graphics driver. You can expect a value of 512 pixels for low-end graphics card, and up to 8192 pixels or more for newer hardware. + * + * Returns: Maximum size allowed for textures, in pixels. + */ + static uint getMaximumSize() + { + return sfTexture_getMaximumSize(); + } + + /** + * Return the size of the texture. + * + * Returns: Size in pixels. + */ + Vector2u getSize() const + { + Vector2u temp; + sfTexture_getSize(sfPtr, &temp.x, &temp.y); + return temp; + } + + /** + * Enable or disable the smooth filter. + * + * When the filter is activated, the texture appears smoother so that pixels are less noticeable. However if you want the texture to look exactly the same as its source file, you should leave it disabled. The smooth filter is disabled by default. + * + * Params: + * smooth = True to enable smoothing, false to disable it. + */ + void setSmooth(bool smooth) + { + sfTexture_setSmooth(sfPtr, smooth);//:sfTexture_setSmooth(sfPtr, sfFalse); + } + + /** + * Enable or disable repeating. + * + * Repeating is involved when using texture coordinates outside the texture rectangle [0, 0, width, height]. In this case, if repeat mode is enabled, the whole texture will be repeated as many times as needed to reach the coordinate (for example, if the X texture coordinate is 3 * width, the texture will be repeated 3 times). + * + * If repeat mode is disabled, the "extra space" will instead be filled with border pixels. Warning: on very old graphics cards, white pixels may appear when the texture is repeated. With such cards, repeat mode can be used reliably only if the texture has power-of-two dimensions (such as 256x128). Repeating is disabled by default. + * + * Params: + * repeated = True to repeat the texture, false to disable repeating + */ + void setRepeated(bool repeated) + { + sfTexture_setRepeated(sfPtr, repeated);//:sfTexture_setRepeated(sfPtr, sfFalse); + } + + /** + * Bind a texture for rendering. + * + * This function is not part of the graphics API, it mustn't be used when drawing SFML entities. It must be used only if you mix Texture with OpenGL code. + * + * Params: + * texture = The texture to bind. Can be null to use no texture. + */ + static void bind(Texture texture) + { + (texture is null)?sfTexture_bind(null):sfTexture_bind(texture.sfPtr); + } + + /** + * Create the texture. + * + * If this function fails, the texture is left unchanged. + * + * Params: + * width = Width of the texture + * height = Height of the texture + * + * Returns: True if creation was successful, false otherwise. + */ + bool create(uint width, uint height) + { + import dsfml.system.string; + + bool ret = sfTexture_create(sfPtr, width, height); + if(!ret) + { + err.write(dsfml.system.string.toString(sfErr_getOutput())); + } + + return ret; + } + + /** + * Copy the texture pixels to an image. + * + * This function performs a slow operation that downloads the texture's pixels from the graphics card and copies them to a new image, potentially applying transformations to pixels if necessary (texture may be padded or flipped). + * + * Returns: Image containing the texture's pixels. + */ + Image copyToImage() const + { + return new Image(sfTexture_copyToImage(sfPtr)); + } + + /** + * Creates a new texture from the same data (this means copying the entire set of pixels). + * + * Returns: New texture data. + */ + @property + Texture dup() const + { + return new Texture(sfTexture_copy(sfPtr)); + } + + /** + * Tell whether the texture is repeated or not. + * + * Returns: True if repeat mode is enabled, false if it is disabled. + */ + bool isRepeated() const + { + return (sfTexture_isRepeated(sfPtr));// == sfTrue)?true:false; + } + + /** + * Tell whether the smooth filter is enabled or not. + * + * Returns: True if something is enabled, false if it is disabled. + */ + bool isSmooth() const + { + return (sfTexture_isSmooth(sfPtr));// == sfTrue)?true:false; + } + + /** + * Update the texture from an image. + * + * Although the source image can be smaller than the texture, this function is usually used for updating the whole texture. The other overload, which has (x, y) additional arguments, is more convenient for updating a sub-area of the texture. + * + * No additional check is performed on the size of the image, passing an image bigger than the texture will lead to an undefined behaviour. + * + * This function does nothing if the texture was not previously created. + * + * Params: + * image = Image to copy to the texture. + */ + void updateFromImage(Image image, uint x, uint y) + { + sfTexture_updateFromImage(sfPtr, image.sfPtr, x, y); + } + + /** + * Update part of the texture from an array of pixels. + * + * The size of the pixel array must match the width and height arguments, and it must contain 32-bits RGBA pixels. + * + * No additional check is performed on the size of the pixel array or the bounds of the area to update, passing invalid arguments will lead to an undefined behaviour. + * + * This function does nothing if pixels is null or if the texture was not previously created. + * + * Params: + * pixels = Array of pixels to copy to the texture. + * width = Width of the pixel region contained in pixels + * height = Height of the pixel region contained in pixels + * x = X offset in the texture where to copy the source pixels + * y = Y offset in the texture where to copy the source pixels + */ + void updateFromPixels(const(ubyte)[] pixels, uint width, uint height, uint x, uint y) + { + sfTexture_updateFromPixels(sfPtr,pixels.ptr,width, height, x,y); + } + + //TODO: Get this working via inheritance?(so custom window classes can do it too) + /** + * Update a part of the texture from the contents of a window. + * + * No additional check is performed on the size of the window, passing an invalid combination of window size and offset will lead to an undefined behaviour. + * + * This function does nothing if either the texture or the window was not previously created. + * + * Params: + * window = Window to copy to the texture + * x = X offset in the texture where to copy the source window + * y = Y offset in the texture where to copy the source window + */ + void updateFromWindow(Window window, uint x, uint y) + { + sfTexture_updateFromWindow(sfPtr, RenderWindow.windowPointer(window), x, y); + } + + //Is this even safe? RenderWindow inherits from Window, so what happens? Is this bottom used or the top? + /** + * Update a part of the texture from the contents of a window. + * + * No additional check is performed on the size of the window, passing an invalid combination of window size and offset will lead to an undefined behaviour. + * + * This function does nothing if either the texture or the window was not previously created. + * + * Params: + * window = Window to copy to the texture + * x = X offset in the texture where to copy the source window + * y = Y offset in the texture where to copy the source window + */ + void updateFromWindow(RenderWindow window, uint x, uint y) + { + sfTexture_updateFromRenderWindow(sfPtr, window.sfPtr, x, y); + } +} + +unittest +{ + version(DSFML_Unittest_Graphics) + { + import std.stdio; + + writeln("Unit test for Texture"); + + auto texture = new Texture(); + + assert(texture.loadFromFile("res/TestImage.png")); + + //do things with the texture + + writeln(); + } +} + +private extern(C++) interface textureInputStream +{ + long read(void* data, long size); + + long seek(long position); + + long tell(); + + long getSize(); +} + + +private class textureStream:textureInputStream +{ + private InputStream myStream; + + this(InputStream stream) + { + myStream = stream; + } + + extern(C++)long read(void* data, long size) + { + return myStream.read(data[0..cast(size_t)size]); + } + + extern(C++)long seek(long position) + { + return myStream.seek(position); + } + + extern(C++)long tell() + { + return myStream.tell(); + } + + extern(C++)long getSize() + { + return myStream.getSize(); + } +} + + + +package extern(C) struct sfTexture; + +private extern(C): + +//Construct a new texture +sfTexture* sfTexture_construct(); + +//Create a new texture +bool sfTexture_create(sfTexture* texture, uint width, uint height); + +//Create a new texture from a file +bool sfTexture_loadFromFile(sfTexture* texture, const(char)* filename, size_t length, int left, int top, int width, int height); + +//Create a new texture from a file in memory +bool sfTexture_loadFromMemory(sfTexture* texture, const(void)* data, size_t sizeInBytes, int left, int top, int width, int height); + +//Create a new texture from a custom stream +bool sfTexture_loadFromStream(sfTexture* texture, textureInputStream stream, int left, int top, int width, int height); + +//Create a new texture from an image +bool sfTexture_loadFromImage(sfTexture* texture, const(sfImage)* image, int left, int top, int width, int height); + +//Copy an existing texture +sfTexture* sfTexture_copy(const(sfTexture)* texture); + +//Destroy an existing texture +void sfTexture_destroy(sfTexture* texture); + +//Return the size of the texture +void sfTexture_getSize(const(sfTexture)* texture, uint* x, uint* y); + +//Copy a texture's pixels to an image +sfImage* sfTexture_copyToImage(const sfTexture* texture); + +//Update a texture from an array of pixels +void sfTexture_updateFromPixels(sfTexture* texture, const ubyte* pixels, uint width, uint height, uint x, uint y); + +//Update a texture from an image +void sfTexture_updateFromImage(sfTexture* texture, const sfImage* image, uint x, uint y); + +//Update a texture from the contents of a window +void sfTexture_updateFromWindow(sfTexture* texture, const(void)* window, uint x, uint y); + +//Update a texture from the contents of a render-window +void sfTexture_updateFromRenderWindow(sfTexture* texture, const sfRenderWindow* renderWindow, uint x, uint y); + +//Enable or disable the smooth filter on a texture +void sfTexture_setSmooth(sfTexture* texture, bool smooth); + +//Tell whether the smooth filter is enabled or not for a texture +bool sfTexture_isSmooth(const sfTexture* texture); + +//Enable or disable repeating for a texture +void sfTexture_setRepeated(sfTexture* texture, bool repeated); + +//Tell whether a texture is repeated or not +bool sfTexture_isRepeated(const sfTexture* texture); + +//Bind a texture for rendering +void sfTexture_bind(const sfTexture* texture); + +//Get the maximum texture size allowed +uint sfTexture_getMaximumSize(); + +const(char)* sfErr_getOutput(); diff --git a/src/dsfml/network/ftp.d b/src/dsfml/network/ftp.d index 2db5afe..aa6282e 100644 --- a/src/dsfml/network/ftp.d +++ b/src/dsfml/network/ftp.d @@ -37,16 +37,16 @@ class Ftp ///Enumeration of transfer modes. enum TransferMode { - ///Binary mode (file is transfered as a sequence of bytes) + ///Binary mode (file is transfered as a sequence of bytes) Binary, ///Text mode using ASCII encoding. Ascii, - ///Text mode using EBCDIC encoding. + ///Text mode using EBCDIC encoding. Ebcdic, } - + package sfFtp* sfPtr; - + ///Default Constructor. this() { @@ -71,26 +71,26 @@ class Ftp { return new DirectoryResponse(sfFtp_getWorkingDirectory(sfPtr)); } - + ///Get the contents of the given directory. /// ///This function retrieves the sub-directories and files contained in the given directory. It is not recursive. The directory parameter is relative to the current working directory. /// ///Returns: Server response to the request. - ListingResponse getDirectoryListing(string directory = "") + ListingResponse getDirectoryListing(const(char)[] directory = "") { import dsfml.system.string; - return new ListingResponse(sfFtp_getDirectoryListing(sfPtr, toStringz(directory))); + return new ListingResponse(sfFtp_getDirectoryListing(sfPtr, directory.ptr, directory.length)); } ///Change the current working directory. /// ///The new directory must be relative to the current one. /// ///Returns: Server response to the request. - Response changeDirectory(string directory) + Response changeDirectory(const(char)[] directory) { import dsfml.system.string; - return new Response(sfFtp_changeDirectory(sfPtr,toStringz(directory))); + return new Response(sfFtp_changeDirectory(sfPtr, directory.ptr, directory.length)); } ///Connect to the specified FTP server. @@ -106,7 +106,7 @@ class Ftp ///Returns: Server response to the request. Response connect(IpAddress address, ushort port = 21, Duration timeout = Duration.zero()) { - return new Response(sfFtp_connect(sfPtr, address.m_address.ptr, port, timeout.total!"usecs")); + return new Response(sfFtp_connect(sfPtr, address.m_address.ptr, address.m_address.length, port, timeout.total!"usecs")); } ///Connect to the specified FTP server. @@ -120,9 +120,10 @@ class Ftp /// timeout = Maximum time to wait. /// ///Returns: Server response to the request. - Response connect(string address, ushort port = 21, Duration timeout = Duration.zero()) + Response connect(const(char)[] address, ushort port = 21, Duration timeout = Duration.zero()) { - return new Response(sfFtp_connect(sfPtr, IpAddress(address).m_address.ptr, port, timeout.total!"usecs")); + auto iaddress = IpAddress(address); + return new Response(sfFtp_connect(sfPtr, iaddress.m_address.ptr, iaddress.m_address.length, port, timeout.total!"usecs")); } ///Remove an existing directory. @@ -133,10 +134,10 @@ class Ftp /// name = Name of the directory to remove. /// ///Returns: Server response to the request. - Response deleteDirectory(string name) + Response deleteDirectory(const(char)[] name) { import dsfml.system.string; - return new Response(sfFtp_deleteDirectory(sfPtr, toStringz(name))); + return new Response(sfFtp_deleteDirectory(sfPtr, name.ptr, name.length)); } ///Remove an existing file. @@ -147,10 +148,10 @@ class Ftp /// name = Name of the file to remove. /// ///Returns: Server response to the request. - Response deleteFile(string name) + Response deleteFile(const(char)[] name) { import dsfml.system.string; - return new Response(sfFtp_deleteFile(sfPtr, toStringz(name))); + return new Response(sfFtp_deleteFile(sfPtr, name.ptr, name.length)); } ///Close the connection with the server. @@ -172,10 +173,10 @@ class Ftp /// mode = Transfer mode. /// ///Returns: Server response to the request. - Response download(string remoteFile, string localPath, TransferMode mode = TransferMode.Binary) + Response download(const(char)[] remoteFile, const(char)[] localPath, TransferMode mode = TransferMode.Binary) { import dsfml.system.string; - return new Response(sfFtp_download(sfPtr, toStringz(remoteFile),toStringz(localPath),mode)); + return new Response(sfFtp_download(sfPtr, remoteFile.ptr, remoteFile.length, localPath.ptr, localPath.length ,mode)); } ///Send a null command to keep the connection alive. @@ -197,7 +198,7 @@ class Ftp { return new Response(sfFtp_loginAnonymous(sfPtr)); } - + ///Log in using a username and a password. /// ///Logging in is mandatory after connecting to the server. Users that are not logged in cannot perform any operation. @@ -207,13 +208,13 @@ class Ftp /// password = The password. /// ///Returns: Server response to the request. - Response login(string name, string password) + Response login(const(char)[] name, const(char)[] password) { import dsfml.system.string; - return new Response(sfFtp_login(sfPtr,toStringz(name), toStringz(password))); + return new Response(sfFtp_login(sfPtr, name.ptr, name.length, password.ptr, password.length)); } - ///Go to the parent directory of the current one. + ///Go to the parent directory of the current one. /// ///Returns: Server response to the request. Response parentDirectory() @@ -230,10 +231,10 @@ class Ftp /// name = Name of the directory to create. /// ///Returns: Server response to the request. - Response createDirectory(string name) + Response createDirectory(const(char)[] name) { import dsfml.system.string; - return new Response(sfFtp_createDirectory(sfPtr, toStringz(name))); + return new Response(sfFtp_createDirectory(sfPtr, name.ptr, name.length)); } ///Rename an existing file. @@ -245,10 +246,10 @@ class Ftp /// newName = New name of the file. /// ///Returns: Server response to the request. - Response renameFile(string file, string newName) + Response renameFile(const(char)[] file, const(char)[] newName) { import dsfml.system.string; - return new Response(sfFtp_renameFile(sfPtr,toStringz(file),toStringz(newName))); + return new Response(sfFtp_renameFile(sfPtr, file.ptr, file.length, newName.ptr, newName.length)); } ///Upload a file to the server. @@ -261,10 +262,24 @@ class Ftp /// mode = Transfer mode. /// ///Returns: Server response to the request. - Response upload(string localFile, string remotePath, TransferMode mode = TransferMode.Binary) + Response upload(const(char)[] localFile, const(char)[] remotePath, TransferMode mode = TransferMode.Binary) { import dsfml.system.string; - return new Response(sfFtp_upload(sfPtr,toStringz(localFile),toStringz(remotePath),mode)); + return new Response(sfFtp_upload(sfPtr, localFile.ptr, localFile.length, remotePath.ptr, remotePath.length, mode)); + } + + ///Send a command to the FTP server. + /// + ///While the most often used commands are provided as member functions in the Ftp class, this method can be used to send any FTP command to the server. If the command requires one or more parameters, they can be specified in parameter. If the server returns information, you can extract it from the response using getMessage(). + /// + ///Params: + /// command = Command to send. + /// parameter = Command parameter. + /// + ///Returns: Server response to the request. + Response sendCommand(const(char)[] command, const(char)[] parameter) { + import dsfml.system.string; + return new Response(sfFtp_sendCommand(sfPtr, command.ptr, command.length, parameter.ptr, parameter.length)); } ///Specialization of FTP response returning a directory. @@ -276,11 +291,11 @@ class Ftp package this(sfFtpDirectoryResponse* FtpDirectoryResponce) { import dsfml.system.string; - - Directory = toString(sfFtpDirectoryResponse_getDirectory(FtpDirectoryResponce)); - + + Directory = dsfml.system.string.toString(sfFtpDirectoryResponse_getDirectory(FtpDirectoryResponce)); + super(sfFtpDirectoryResponse_getStatus(FtpDirectoryResponce), sfFtpDirectoryResponse_getMessage(FtpDirectoryResponce)); - + sfFtpDirectoryResponse_destroy(FtpDirectoryResponce); } @@ -292,8 +307,8 @@ class Ftp return Directory; } } - - ///Specialization of FTP response returning a filename lisiting. + + ///Specialization of FTP response returning a filename lisiting. class ListingResponse:Response { private string[] Filenames; @@ -306,15 +321,15 @@ class Ftp Filenames.length = sfFtpListingResponse_getCount(FtpListingResponce); for(int i = 0; i < Filenames.length; i++) { - Filenames[i] = toString(sfFtpListingResponse_getName(FtpListingResponce,i)); + Filenames[i] = dsfml.system.string.toString(sfFtpListingResponse_getName(FtpListingResponce,i)); } - + super(sfFtpListingResponse_getStatus(FtpListingResponce), sfFtpListingResponse_getMessage(FtpListingResponce)); - + sfFtpListingResponse_destroy(FtpListingResponce); - + } - + ///Return the array of directory/file names. /// ///Returns: Array containing the requested listing. @@ -323,8 +338,8 @@ class Ftp return Filenames; } } - - ///Define a FTP response. + + ///Define a FTP response. class Response { ///Status codes possibly returned by a FTP response. @@ -334,7 +349,7 @@ class Ftp ServiceReadySoon = 120, DataConnectionAlreadyOpened = 125, OpeningDataConnection = 150, - + Ok = 200, PointlessCommand = 202, SystemStatus = 211, @@ -350,7 +365,7 @@ class Ftp LoggedIn = 230, FileActionOk = 250, DirectoryOk = 257, - + NeedPassword = 331, NeedAccountToLogIn = 332, NeedInformation = 350, @@ -360,7 +375,7 @@ class Ftp FileActionAborted = 450, LocalError = 451, InsufficientStorageSpace = 452, - + CommandUnknown = 500, ParametersUnknown = 501, CommandNotImplemented = 502, @@ -372,7 +387,7 @@ class Ftp PageTypeUnknown = 551, NotEnoughMemory = 552, FilenameNotAllowed = 553, - + InvalidResponse = 1000, ConnectionFailed = 1001, ConnectionClosed = 1002, @@ -394,20 +409,20 @@ class Ftp { import dsfml.system.string; FtpStatus = status; - Message = toString(message); + Message = dsfml.system.string.toString(message); } ///Get the full message contained in the response. /// - ///Returns: The response message. + ///Returns: The dsfml.system.string.toString( message. string getMessage() const { return Message; } - + ///Get the status code of the response. /// - ///Returns: Status code. + ///Returns: Status code. Status getStatus() const { return FtpStatus; @@ -570,7 +585,7 @@ void sfFtp_destroy(sfFtp* ftp); ///Connect to the specified FTP server -sfFtpResponse* sfFtp_connect(sfFtp* ftp, const(char)* serverIP, ushort port, long timeout); +sfFtpResponse* sfFtp_connect(sfFtp* ftp, const(char)* serverIP, size_t length, ushort port, long timeout); ///Log in using an anonymous account @@ -578,7 +593,7 @@ sfFtpResponse* sfFtp_loginAnonymous(sfFtp* ftp); ///Log in using a username and a password -sfFtpResponse* sfFtp_login(sfFtp* ftp, const(char)* userName, const(char)* password); +sfFtpResponse* sfFtp_login(sfFtp* ftp, const(char)* userName, size_t userNameLength, const(char)* password, size_t passwordLength); ///Close the connection with the server @@ -594,11 +609,11 @@ sfFtpDirectoryResponse* sfFtp_getWorkingDirectory(sfFtp* ftp); ///Get the contents of the given directory -sfFtpListingResponse* sfFtp_getDirectoryListing(sfFtp* ftp, const(char)* directory); +sfFtpListingResponse* sfFtp_getDirectoryListing(sfFtp* ftp, const(char)* directory, size_t length); ///Change the current working directory -sfFtpResponse* sfFtp_changeDirectory(sfFtp* ftp, const(char)* directory); +sfFtpResponse* sfFtp_changeDirectory(sfFtp* ftp, const(char)* directory, size_t length); ///Go to the parent directory of the current one @@ -606,24 +621,27 @@ sfFtpResponse* sfFtp_parentDirectory(sfFtp* ftp); ///Create a new directory -sfFtpResponse* sfFtp_createDirectory(sfFtp* ftp, const(char)* name); +sfFtpResponse* sfFtp_createDirectory(sfFtp* ftp, const(char)* name, size_t length); ///Remove an existing directory -sfFtpResponse* sfFtp_deleteDirectory(sfFtp* ftp, const(char)* name); +sfFtpResponse* sfFtp_deleteDirectory(sfFtp* ftp, const(char)* name, size_t length); ///Rename an existing file -sfFtpResponse* sfFtp_renameFile(sfFtp* ftp, const(char)* file, const(char)* newName); +sfFtpResponse* sfFtp_renameFile(sfFtp* ftp, const(char)* file, size_t fileLength, const(char)* newName, size_t newNameLength); ///Remove an existing file -sfFtpResponse* sfFtp_deleteFile(sfFtp* ftp, const(char)* name); +sfFtpResponse* sfFtp_deleteFile(sfFtp* ftp, const(char)* name, size_t length); ///Download a file from a FTP server -sfFtpResponse* sfFtp_download(sfFtp* ftp, const(char)* distantFile, const(char)* destPath, int mode); +sfFtpResponse* sfFtp_download(sfFtp* ftp, const(char)* distantFile, size_t distantFileLength, const(char)* destPath, size_t destPathLength, int mode); ///Upload a file to a FTP server -sfFtpResponse* sfFtp_upload(sfFtp* ftp, const(char)* localFile, const(char)* destPath, int mode); +sfFtpResponse* sfFtp_upload(sfFtp* ftp, const(char)* localFile, size_t localFileLength, const(char)* destPath, size_t destPathLength, int mode); + +///Send a command to a FTP server +sfFtpResponse* sfFtp_sendCommand(sfFtp* ftp, const(char)* command, size_t commandLength, const(char)* parameter, size_t parameterLength); \ No newline at end of file diff --git a/src/dsfml/network/http.d b/src/dsfml/network/http.d index 1aa43c1..88c379b 100644 --- a/src/dsfml/network/http.d +++ b/src/dsfml/network/http.d @@ -32,7 +32,7 @@ import core.time; class Http { package sfHttp* sfPtr; - + ///Default constructor this() { @@ -45,14 +45,14 @@ class Http /// ///Params: /// host = Web server to connect to. - /// port = Port to use for connection. + /// port = Port to use for connection. this(string host, ushort port = 0) { import dsfml.system.string; sfPtr = sfHttp_create(); - sfHttp_setHost(sfPtr, toStringz(host),port); + sfHttp_setHost(sfPtr, host.ptr, host.length ,port); } - + ///Destructor ~this() { @@ -60,18 +60,18 @@ class Http mixin(destructorOutput); sfHttp_destroy(sfPtr); } - + ///Set the target host. /// ///This function just stores the host address and port, it doesn't actually connect to it until you send a request. The port has a default value of 0, which means that the HTTP client will use the right port according to the protocol used (80 for HTTP, 443 for HTTPS). You should leave it like this unless you really need a port other than the standard one, or use an unknown protocol. /// ///Params: /// host = Web server to connect to. - /// port = Port to use for connection. + /// port = Port to use for connection. void setHost(string host, ushort port = 0) { import dsfml.system.string; - sfHttp_setHost(sfPtr, toStringz(host),port); + sfHttp_setHost(sfPtr, host.ptr, host.length,port); } ///Send a HTTP request and return the server's response. @@ -85,19 +85,23 @@ class Http { return new Response(sfHttp_sendRequest(sfPtr,request.sfPtrRequest,timeout.total!"usecs")); } - - ///Define a HTTP request. + + ///Define a HTTP request. static class Request { - ///Enumerate the available HTTP methods for a request. + ///Enumerate the available HTTP methods for a request. enum Method { - ///Request in get mode, standard method to retrieve a page. + ///Request in get mode, standard method to retrieve a page. Get, ///Request in post mode, usually to send data to a page. Post, - ///Request a page's header only. - Head + ///Request a page's header only. + Head, + ///Request in put mode, useful for a REST API + Put, + ///Request in delete mode, useful for a REST API + Delete } package sfHttpRequest* sfPtrRequest; @@ -112,11 +116,11 @@ class Http { import dsfml.system.string; sfPtrRequest = sfHttpRequest_create(); - sfHttpRequest_setUri(sfPtrRequest, toStringz(uri)); + sfHttpRequest_setUri(sfPtrRequest, uri.ptr, uri.length); sfHttpRequest_setMethod(sfPtrRequest, method); - sfHttpRequest_setBody(sfPtrRequest,toStringz(requestBody)); + sfHttpRequest_setBody(sfPtrRequest, requestBody.ptr, requestBody.length); } - + ///Destructor ~this() { @@ -134,7 +138,7 @@ class Http void setBody(string requestBody) { import dsfml.system.string; - sfHttpRequest_setBody(sfPtrRequest,toStringz(requestBody)); + sfHttpRequest_setBody(sfPtrRequest, requestBody.ptr, requestBody.length); } ///Set the value of a field. @@ -144,10 +148,10 @@ class Http ///Params: /// field = Name of the field to set. /// value = Value of the field. - void setField(string feild, string value) + void setField(string field, string value) { import dsfml.system.string; - sfHttpRequest_setField(sfPtrRequest,toStringz(feild),toStringz(value)); + sfHttpRequest_setField(sfPtrRequest, field.ptr, field.length , value.ptr, value.length); } ///Set the HTTP version for the request. @@ -172,7 +176,7 @@ class Http { sfHttpRequest_setMethod(sfPtrRequest,method); } - + ///Set the requested URI. /// ///The URI is the resource (usually a web page or a file) that you want to get or post. The URI is "/" (the root page) by default. @@ -182,10 +186,10 @@ class Http void setUri(string uri) { import dsfml.system.string; - sfHttpRequest_setUri(sfPtrRequest,toStringz(uri)); + sfHttpRequest_setUri(sfPtrRequest, uri.ptr, uri.length); } } - + ///Define a HTTP response. class Response { @@ -219,7 +223,7 @@ class Http InvalidResponse = 1000, ConnectionFailed = 1001 - + } package sfHttpResponse* sfPtrResponse; @@ -236,7 +240,7 @@ class Http string getBody() { import dsfml.system.string; - return toString(sfHttpResponse_getBody(sfPtrResponse)); + return dsfml.system.string.toString(sfHttpResponse_getBody(sfPtrResponse)); } ///Get the value of a field. @@ -247,10 +251,10 @@ class Http /// field = Name of the field to get. /// ///Returns: Value of the field, or empty string if not found. - string getField(string field) + string getField(const(char)[] field) { import dsfml.system.string; - return toString(sfHttpResponse_getField(sfPtrResponse,toStringz(field))); + return dsfml.system.string.toString(sfHttpResponse_getField(sfPtrResponse, field.ptr, field.length)); } ///Get the major HTTP version number of the response. @@ -260,15 +264,15 @@ class Http { return sfHttpResponse_getMajorVersion(sfPtrResponse); } - - ///Get the minor HTTP version number of the response. + + ///Get the minor HTTP version number of the response. /// ///Returns: Minor HTTP version number. uint getMinorHttpVersion() { return sfHttpResponse_getMinorVersion(sfPtrResponse); } - + ///Get the response status code. /// ///The status code should be the first thing to be checked after receiving a response, it defines whether it is a success, a failure or anything else (see the Status enumeration). @@ -286,13 +290,13 @@ unittest version(DSFML_Unittest_Network) { import std.stdio; - + writeln("Unittest for Http"); auto http = new Http(); http.setHost("http://www.sfml-dev.org"); - + // Prepare a request to get the 'features.php' page auto request = new Http.Request("learn.php"); @@ -309,7 +313,7 @@ unittest else { writeln("Error: ", status); - } + } writeln(); } } @@ -322,71 +326,71 @@ struct sfHttp; ///Create a new HTTP request sfHttpRequest* sfHttpRequest_create(); - - + + ///Destroy a HTTP request void sfHttpRequest_destroy(sfHttpRequest* httpRequest); - - + + ///Set the value of a header field of a HTTP request -void sfHttpRequest_setField(sfHttpRequest* httpRequest, const(char)* field, const(char)* value); - - +void sfHttpRequest_setField(sfHttpRequest* httpRequest, const(char)* field, size_t fieldLength, const(char)* value, size_t valueLength); + + ///Set a HTTP request method void sfHttpRequest_setMethod(sfHttpRequest* httpRequest, int method); - - + + ///Set a HTTP request URI -void sfHttpRequest_setUri(sfHttpRequest* httpRequest, const(char)* uri); - - +void sfHttpRequest_setUri(sfHttpRequest* httpRequest, const(char)* uri, size_t length); + + ///Set the HTTP version of a HTTP request void sfHttpRequest_setHttpVersion(sfHttpRequest* httpRequest,uint major, uint minor); - - + + ///Set the body of a HTTP request -void sfHttpRequest_setBody(sfHttpRequest* httpRequest, const(char)* ody); - - +void sfHttpRequest_setBody(sfHttpRequest* httpRequest, const(char)* ody, size_t length); + + //HTTP Response Functions - + ///Destroy a HTTP response void sfHttpResponse_destroy(sfHttpResponse* httpResponse); - - + + ///Get the value of a field of a HTTP response -const(char)* sfHttpResponse_getField(const sfHttpResponse* httpResponse, const(char)* field); - - +const(char)* sfHttpResponse_getField(const sfHttpResponse* httpResponse, const(char)* field, size_t length); + + ///Get the status code of a HTTP reponse Http.Response.Status sfHttpResponse_getStatus(const sfHttpResponse* httpResponse); - - + + ///Get the major HTTP version number of a HTTP response uint sfHttpResponse_getMajorVersion(const sfHttpResponse* httpResponse); - - + + ///Get the minor HTTP version number of a HTTP response uint sfHttpResponse_getMinorVersion(const sfHttpResponse* httpResponse); - - + + ///Get the body of a HTTP response const(char)* sfHttpResponse_getBody(const sfHttpResponse* httpResponse); - - + + //HTTP Functions - + ///Create a new Http object sfHttp* sfHttp_create(); - - + + ///Destroy a Http object void sfHttp_destroy(sfHttp* http); - - + + ///Set the target host of a HTTP object -void sfHttp_setHost(sfHttp* http, const(char)* host, ushort port); - - +void sfHttp_setHost(sfHttp* http, const(char)* host, size_t length, ushort port); + + ///Send a HTTP request and return the server's response. sfHttpResponse* sfHttp_sendRequest(sfHttp* http, const(sfHttpRequest)* request, long timeout); diff --git a/src/dsfml/network/ipaddress.d b/src/dsfml/network/ipaddress.d index 5c3da25..f7810ff 100644 --- a/src/dsfml/network/ipaddress.d +++ b/src/dsfml/network/ipaddress.d @@ -40,12 +40,11 @@ struct IpAddress /// ///Params: /// address = IP address or network name. - this(string address) + this(const(char)[] address) { - import dsfml.system.string; - sfIpAddress_fromString(toStringz(address) ,m_address.ptr); + sfIpAddress_fromString(address.ptr, address.length, m_address.ptr); } - + ///Construct the address from 4 bytes. /// ///Calling IpAddress(a, b, c, d) is equivalent to calling IpAddress("a.b.c.d"), but safer as it doesn't have to parse a string to get the address components. @@ -59,7 +58,7 @@ struct IpAddress { sfIpAddress_fromBytes(byte0,byte1, byte2, byte3, m_address.ptr); } - + ///Construct the address from a 32-bits integer. /// ///This constructor uses the internal representation of the address directly. It should be used only if you got that representation from IpAddress::ToInteger(). @@ -78,7 +77,7 @@ struct IpAddress ///Returns: 32-bits unsigned integer representation of the address. int toInteger() const { - return sfIpAddress_toInteger(m_address.ptr); + return sfIpAddress_toInteger(m_address.ptr, m_address.length); } ///Get a string representation of the address. @@ -86,19 +85,15 @@ struct IpAddress ///The returned string is the decimal representation of the IP address (like "192.168.1.56"), even if it was constructed from a host name. /// ///Returns: String representation of the address - string toString() const + void toString(scope void delegate(const char[]) sink) const { - import std.conv; - //TODO: possibly cache the string? Maybe with a needsUpdatingMethod? - - //Remove any null characters from the string representation int i = 0; - while((m_address[i] != 0) ) + while(( i < m_address.length && m_address[i] != 0) ) { ++i; } //and present the string. - return m_address[0..i].to!string(); + sink(m_address[0..i]); } ///Get the computer's local address. @@ -112,7 +107,7 @@ struct IpAddress sfIpAddress_getLocalAddress(temp.m_address.ptr); return temp; } - + ///Get the computer's public address. /// ///The public address is the address of the computer from the internet point of view, i.e. something like 89.54.1.169. @@ -129,12 +124,12 @@ struct IpAddress sfIpAddress_getPublicAddress(temp.m_address.ptr, timeout.total!"usecs"); return temp; } - - ///Value representing an empty/invalid address. + + ///Value representing an empty/invalid address. static immutable(IpAddress) None; - ///The "localhost" address (for connecting a computer to itself locally) + ///The "localhost" address (for connecting a computer to itself locally) static immutable(IpAddress) LocalHost; - ///The "broadcast" address (for sending UDP messages to everyone on a local network) + ///The "broadcast" address (for sending UDP messages to everyone on a local network) static immutable(IpAddress) Broadcast; static this() @@ -149,7 +144,7 @@ unittest version(DSFML_Unittest_Network) { import std.stdio; - + writeln("Unittest for IpAdress"); @@ -161,7 +156,7 @@ unittest IpAddress googleIP = IpAddress("google.com"); - writeln("Google's Ip address: ",googleIP.toString()); + writeln("Google's Ip address: ",googleIP); writeln("Your local Ip Address: ", IpAddress.getLocalAddress()); @@ -175,7 +170,7 @@ private extern(C): //Note: These functions rely on passing an existing array for the ipAddress. ///Create an address from a string -void sfIpAddress_fromString(const(char)* address, char* ipAddress); +void sfIpAddress_fromString(const(char)* address, size_t addressLength, char* ipAddress); ///Create an address from 4 bytes void sfIpAddress_fromBytes(ubyte byte0, ubyte byte1, ubyte byte2, ubyte byte3, char* ipAddress); @@ -184,7 +179,7 @@ void sfIpAddress_fromBytes(ubyte byte0, ubyte byte1, ubyte byte2, ubyte byte3, c void sfIpAddress_fromInteger(uint address, char* ipAddress); ///Get an integer representation of the address -uint sfIpAddress_toInteger(const(char)* ipAddress); +uint sfIpAddress_toInteger(const(char)* ipAddress, size_t length); ///Get the computer's local address void sfIpAddress_getLocalAddress(char* ipAddress); diff --git a/src/dsfml/network/tcplistener.d b/src/dsfml/network/tcplistener.d index c229f22..687bc11 100644 --- a/src/dsfml/network/tcplistener.d +++ b/src/dsfml/network/tcplistener.d @@ -48,7 +48,7 @@ class TcpListener:Socket { sfPtr = sfTcpListener_create(); } - + ///Destructor ~this() { @@ -67,7 +67,7 @@ class TcpListener:Socket return sfTcpListener_getLocalPort(sfPtr); } - ///Tell whether the socket is in blocking or non-blocking mode. + ///Tell whether the socket is in blocking or non-blocking mode. /// ///In blocking mode, calls will not return until they have completed their task. For example, a call to Receive in blocking mode won't return until some data was actually received. In non-blocking mode, calls will always return immediately, using the return code to signal whether there was data available or not. By default, all sockets are blocking. /// @@ -90,9 +90,9 @@ class TcpListener:Socket { import dsfml.system.string; - Status toReturn = sfTcpListener_accept(sfPtr, socket.sfPtr); - err.write(toString(sfErr_getOutput())); - return toReturn; + Status toReturn = sfTcpListener_accept(sfPtr, socket.sfPtr); + err.write(dsfml.system.string.toString(sfErr_getOutput())); + return toReturn; } ///Start listening for connections. @@ -108,7 +108,7 @@ class TcpListener:Socket import dsfml.system.string; Status toReturn = sfTcpListener_listen(sfPtr, port); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return toReturn; } @@ -134,7 +134,7 @@ unittest writeln("Unittest for Listener"); //socket connecting to server auto clientSocket = new TcpSocket(); - + //listener looking for new sockets auto listener = new TcpListener(); listener.listen(55002); @@ -147,11 +147,11 @@ unittest //socket on the server side connected to the client's socket auto serverSocket = new TcpSocket(); - + //accepts a new connection and binds it to the socket in the parameter listener.accept(serverSocket); - + clientSocket.disconnect(); writeln(); } diff --git a/src/dsfml/network/tcpsocket.d b/src/dsfml/network/tcpsocket.d index 2e8ae04..74d47db 100644 --- a/src/dsfml/network/tcpsocket.d +++ b/src/dsfml/network/tcpsocket.d @@ -49,13 +49,13 @@ import dsfml.system.err; class TcpSocket:Socket { package sfTcpSocket* sfPtr; - + ///Default constructor this() { sfPtr = sfTcpSocket_create(); } - + ///Destructor ~this() { @@ -82,9 +82,9 @@ class TcpSocket:Socket IpAddress getRemoteAddress() { IpAddress temp; - + sfTcpSocket_getRemoteAddress(sfPtr,temp.m_address.ptr); - + return temp; } @@ -125,7 +125,7 @@ class TcpSocket:Socket { return sfTcpSocket_connect(sfPtr, host.m_address.ptr,port, timeout.total!"usecs"); } - + ///Disconnect the socket from its remote peer. /// ///This function gracefully closes the connection. If the socket is not connected, this function has no effect. @@ -134,7 +134,7 @@ class TcpSocket:Socket sfTcpSocket_disconnect(sfPtr); } - ///Tell whether the socket is in blocking or non-blocking mode. + ///Tell whether the socket is in blocking or non-blocking mode. /// ///Returns: True if the socket is blocking, false otherwise. bool isBlocking() @@ -155,7 +155,7 @@ class TcpSocket:Socket import dsfml.system.string; Status toReturn = sfTcpSocket_send(sfPtr, data.ptr, data.length); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return toReturn; } @@ -236,29 +236,29 @@ unittest //socket connecting to server auto clientSocket = new TcpSocket(); - + //listener looking for new sockets auto listener = new TcpListener(); listener.listen(55003); - + //get our client socket to connect to the server clientSocket.connect(IpAddress.LocalHost, 55003); - - - + + + //packet to send data auto sendPacket = new Packet(); - - + + //Packet to receive data auto receivePacket = new Packet(); - + //socket on the server side connected to the client's socket auto serverSocket = new TcpSocket(); - + //accepts a new connection and binds it to the socket in the parameter listener.accept(serverSocket); - + string temp = "I'm sending you stuff!"; //Let's greet the server! @@ -266,7 +266,7 @@ unittest //clientSocket.send(sendPacket); clientSocket.send(temp); - + //And get the data on the server side //serverSocket.receive(receivePacket); @@ -274,17 +274,17 @@ unittest size_t received; serverSocket.receive(temp2, received); - + //What did we get from the client? writeln("Gotten from client: ", cast(string)temp2[0..received]); - + //clear the packets to send/get new information sendPacket.clear(); receivePacket.clear(); - + //Respond back to the client sendPacket.write("Hello, I'm your server."); - + serverSocket.send(sendPacket); clientSocket.receive(receivePacket); @@ -293,7 +293,7 @@ unittest string message; receivePacket.read!string(message); writeln("Gotten from server: ", message); - + clientSocket.disconnect(); writeln(); } diff --git a/src/dsfml/network/udpsocket.d b/src/dsfml/network/udpsocket.d index 1b7df3b..62c70c7 100644 --- a/src/dsfml/network/udpsocket.d +++ b/src/dsfml/network/udpsocket.d @@ -57,7 +57,7 @@ class UdpSocket:Socket { sfPtr = sfUdpSocket_create(); } - + ///Destructor ~this() { @@ -98,13 +98,13 @@ class UdpSocket:Socket Status bind(ushort port) { import dsfml.system.string; - + Status toReturn = sfUdpSocket_bind(sfPtr,port); - err.write(toString(sfErr_getOutput())); + err.write(dsfml.system.string.toString(sfErr_getOutput())); return toReturn; } - ///Tell whether the socket is in blocking or non-blocking mode. + ///Tell whether the socket is in blocking or non-blocking mode. /// ///Returns: True if the socket is blocking, false otherwise. bool isBlocking() @@ -143,10 +143,10 @@ class UdpSocket:Socket { //temporary packet to be removed on function exit scope SfPacket temp = new SfPacket(); - + //getting packet's "to send" data temp.append(packet.onSend()); - + //send the data return sfUdpSocket_sendPacket(sfPtr, temp.sfPtr,address.m_address.ptr,port); } @@ -166,13 +166,13 @@ class UdpSocket:Socket Status receive(void[] data, out size_t sizeReceived, out IpAddress address, out ushort port) { import dsfml.system.string; - + Status status; void* temp = sfUdpSocket_receive(sfPtr, data.length, &sizeReceived, address.m_address.ptr, &port, &status); - - err.write(toString(sfErr_getOutput())); - + + err.write(dsfml.system.string.toString(sfErr_getOutput())); + data[0..sizeReceived] = temp[0..sizeReceived].dup; return status; @@ -198,10 +198,10 @@ class UdpSocket:Socket //put data into the packet so that it can process it first if it wants. packet.onRecieve(temp.getData()); - + return status; } - + ///Unbind the socket from the local port to which it is bound. /// ///The port that the socket was previously using is immediately available after this function is called. If the socket is not bound to a port, this function has no effect. @@ -209,7 +209,7 @@ class UdpSocket:Socket { sfUdpSocket_unbind(sfPtr); } - + } unittest @@ -217,7 +217,7 @@ unittest version(DSFML_Unittest_Network) { import std.stdio; - + writeln("Unittest for Udp Socket"); auto clientSocket = new UdpSocket(); @@ -252,7 +252,7 @@ unittest serverSocket.receive(temp2,received, receivedFrom, receivedPort); //What did we get?! - writeln("The data received from ", receivedFrom.toString(), " at port ", receivedPort, " was: ", cast(string)temp2[0..received]); + writeln("The data received from ", receivedFrom, " at port ", receivedPort, " was: ", cast(string)temp2[0..received]); writeln(); diff --git a/src/dsfml/system/config.d b/src/dsfml/system/config.d index ebaa9c9..9cb8594 100644 --- a/src/dsfml/system/config.d +++ b/src/dsfml/system/config.d @@ -30,7 +30,7 @@ static if (__VERSION__ < 2064L) enum { DSFML_VERSION_MAJOR = 2, - DSFML_VERSION_MINOR = 1 + DSFML_VERSION_MINOR = 3 } //destructor output for mixing in. @@ -42,6 +42,6 @@ enum destructorOutput =` } else { - + }`; diff --git a/src/dsfml/system/string.d b/src/dsfml/system/string.d index 8d0e2b7..a227ae9 100644 --- a/src/dsfml/system/string.d +++ b/src/dsfml/system/string.d @@ -18,7 +18,7 @@ If you use this software in a product, an acknowledgment in the product document */ /** - *A module containing functions for interacting with strings going to and from + *A module containing functions for interacting with strings going to and from *a C/C++ library as well as converting between D's string types. This module has no dependencies *except for std.utf. */ @@ -36,53 +36,14 @@ immutable(T)[] toString(T)(in const(T)* str) pure return str[0..strlen(str)].idup; } -///Returns a pointer to a C style string created from a D string type -/// -///Params: -/// str = The D style string to convert. -/// -///Returns: the C style string pointer. -const(T)* toStringz(T)(in immutable(T)[] str) nothrow - if (is(T == dchar)||is(T == wchar)||is(T == char)) -{ - //TODO: get rid of GC usage without adding dependencies? - - //a means to store the copy after returning the address - static T[] copy; - - //if str is just "" - if(str.length == 0) - { - copy = new T[1]; - copy[0] = 0; - return copy.ptr; - } - - //Already zero terminated - if(str[$-1] == 0) - { - return str.ptr; - } - //not zero terminated - else - { - copy = new T[str.length+1]; - copy[0..str.length] = str[]; - copy[$-1] = 0; - - return copy.ptr; - - } -} - ///Returns the same string in a different utf encoding /// ///Params: /// str = The string to convert. /// ///Returns: the C style string pointer. -immutable(U)[] stringConvert(T, U)(in immutable(T)[] str) pure -if ((is(T == dchar)||is(T == wchar)||is(T == char)) && +immutable(U)[] stringConvert(T, U)(in T[] str) pure +if ((is(T == dchar)||is(T == wchar)||is(T == char)) && (is(U == dchar)||is(U == wchar)||is(U == char))) { import std.utf; @@ -123,21 +84,8 @@ unittest version(DSFML_Unittest_System) { import std.stdio; - - writeln("Unit test for string functions"); - - string str1 = "Hello, World"; - wstring str2 = "Hello, World"; - dstring str3 = "Hello, World"; - - const(char)* cstr1 = toStringz(str1); - const(wchar)* cstr2 = toStringz(str2); - const(dchar)* cstr3 = toStringz(str3); - - assert(strlen(cstr1) == 12); - assert(strlen(cstr2) == 12); - assert(strlen(cstr3) == 12); + writeln("Unit test for string functions"); } } diff --git a/src/dsfml/window/event.d b/src/dsfml/window/event.d index 94fcf28..08e5dce 100644 --- a/src/dsfml/window/event.d +++ b/src/dsfml/window/event.d @@ -22,6 +22,7 @@ module dsfml.window.event; import dsfml.window.keyboard; import dsfml.window.mouse; +import dsfml.window.sensor; /** *Defines a system event and its parameters. @@ -125,6 +126,21 @@ struct Event ///Y position of the mouse pointer, relative to the top of the owner window int y; } + + /** + *Mouse wheel scroll events parameters (MouseWheelScrolled) + */ + struct MouseWheelScrollEvent + { + ///Which wheel (for mice with multiple ones) + Mouse.Wheel wheel; + /// Wheel offset. High precision mice may use non-integral offsets. + float delta; + /// X position of the mouse pointer, relative to the left of the owner window + int x; + /// Y position of the mouse pointer, relative to the left of the owner window + int y; + } /** *Size events parameters (Resized) @@ -145,6 +161,29 @@ struct Event /// UTF-32 unicode value of the character dchar unicode; } + /** + *Sensor event parameters + */ + + struct SensorEvent + { + ///Type of the sensor + Sensor.Type type; + float x; + float y; + float z; + } + /** + *Touch Event parameters + */ + + struct TouchEvent + { + ///Index of the finger in case of multi-touch events. + uint finger; + int x; + int y; + } enum EventType { @@ -164,6 +203,8 @@ struct Event KeyReleased, ///The mouse wheel was scrolled (data in event.mouseWheel) MouseWheelMoved, + ///The mouse wheel was scrolled (data in event.mouseWheelScroll) + MouseWheelScrolled, ///A mouse button was pressed (data in event.mouseButton) MouseButtonPressed, ///A mouse button was released (data in event.mouseButton) @@ -184,6 +225,14 @@ struct Event JoystickConnected, ///A joystick was disconnected (data in event.joystickConnect) JoystickDisconnected, + ///A touch event began (data in event.touch) + TouchBegan, + ///A touch moved (data in event.touch) + TouchMoved, + ///A touch ended (data in event.touch) + TouchEnded, + ///A sensor value changed (data in event.sensor) + SensorChanged, ///Keep last -- the total number of event types Count @@ -206,12 +255,18 @@ struct Event MouseButtonEvent mouseButton; ///Mouse wheel event parameters (Event::MouseWheelMoved) MouseWheelEvent mouseWheel; + ///Mouse wheel scroll event parameters + MouseWheelScrollEvent mouseWheelScroll; ///Joystick move event parameters (Event::JoystickMoved) JoystickMoveEvent joystickMove; ///Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased) JoystickButtonEvent joystickButton; ///Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected) JoystickConnectEvent joystickConnect; + ///Touch event parameters + TouchEvent touch; + ///Sensor event Parameters + SensorEvent sensor; } } diff --git a/src/dsfml/window/joystick.d b/src/dsfml/window/joystick.d index bf0aa31..5db0ade 100644 --- a/src/dsfml/window/joystick.d +++ b/src/dsfml/window/joystick.d @@ -29,13 +29,52 @@ module dsfml.window.joystick; *by an index that is passed to the functions of this class. * *This class allows users to query the state of joysticks at any time and directly, without having to deal with - *a window and its events. Compared to the JoystickMoved, JoystickButtonPressed and JoystickButtonReleased events, - *Joystick can retrieve the state of axes and buttons of joysticks at any time (you don't need to store and update - *a boolean on your side in order to know if a button is pressed or released), and you always get the real state of + *a window and its events. Compared to the JoystickMoved, JoystickButtonPressed and JoystickButtonReleased events, + *Joystick can retrieve the state of axes and buttons of joysticks at any time (you don't need to store and update + *a boolean on your side in order to know if a button is pressed or released), and you always get the real state of *joysticks, even if they are moved, pressed or released when your window is out of focus and no event is triggered. */ final abstract class Joystick { + ///Structure holding a joystick's identification; + struct Identification { + private static dstring[immutable(uint)[2]] nameCache; + ///Index of the joystick + uint index; + ///Name of the joystick + @property dstring name() { + //In theory, each vid:pid combination should only have one name associated with it. + //slightly arcane syntax to make older GDC happy. + uint[2] tempkey; + tempkey[0] = vendorId; + tempkey[1] = productId; + immutable(uint)[2] key = tempkey; + + dstring* cachedName = (key in nameCache); + if (cachedName !is null) { + return *cachedName; + } else { + import std.exception; + + dchar[] retrievedName; + dstring retval; + + retrievedName.length = sfJoystick_getIdentificationNameLength(index); + + sfJoystick_getIdentificationName(index, retrievedName.ptr); + + nameCache[key] = retval = assumeUnique(retrievedName); + + return retval; + } + } + + ///Manufacturer identifier + uint vendorId; + ///Product identifier + uint productId; + } + //Constants related to joysticks capabilities. enum { @@ -46,7 +85,7 @@ final abstract class Joystick ///Maximum number of supported axes. JoystickAxisCount = 8 } - + ///Axes supported by SFML joysticks. enum Axis { @@ -80,7 +119,7 @@ final abstract class Joystick { return sfJoystick_getButtonCount(joystick); } - + ///Get the current position of a joystick axis. /// ///If the joystick is not connected, this function returns 0. @@ -94,7 +133,21 @@ final abstract class Joystick { return sfJoystick_getAxisPosition(joystick, axis); } - + + ///Get the joystick information + /// + ///Params: + /// joystick = Index of the joystick. + /// + ///Returns: Structure containing the joystick information. + static Identification getIdentification(uint joystick) { + Identification identification; + + sfJoystick_getIdentification(joystick, &identification.vendorId, &identification.productId); + + return identification; + } + ///Check if a joystick supports a given axis. /// ///If the joystick is not connected, this function returns false. @@ -108,7 +161,7 @@ final abstract class Joystick { return (sfJoystick_hasAxis(joystick, axis)); } - + ///Check if a joystick button is pressed. /// ///If the joystick is not connected, this function returns false. @@ -142,7 +195,7 @@ final abstract class Joystick { sfJoystick_update(); } - + } unittest @@ -151,27 +204,29 @@ unittest { import std.stdio; - + Joystick.update(); - - bool[] joysticks = [false,false,false,false,false,false,false,false]; - + + bool[] joysticks = [false,false,false,false,false,false,false,false]; + for(uint i; i < Joystick.JoystickCount; ++i) { if(Joystick.isConnected(i)) { + auto id = Joystick.getIdentification(i); joysticks[i] = true; writeln("Joystick number ",i," is connected!"); + writefln("Type: %s, ID: %x:%x", id.name, id.vendorId, id.productId); } } - + foreach(uint i,bool joystick;joysticks) { if(joystick) { //Check buttons uint buttonCounts = Joystick.getButtonCount(i); - + for(uint j = 0; j